From c6a21f246263dfe1689d827af4200c64679dcc77 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 14 Oct 2013 17:51:19 +0900 Subject: regulator: mc13892: Fix checkpatch issue Fix the following checkpatch warnings. WARNING: Avoid unnecessary line continuations WARNING: line over 80 characters Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/regulator/mc13892-regulator.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 1037e07937cf..35bd53ba4a48 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -274,25 +274,25 @@ static struct mc13xxx_regulator mc13892_regulators[] = { MC13892_SW_DEFINE(SW4, SWITCHERS3, SWITCHERS3, mc13892_sw), MC13892_FIXED_DEFINE(SWBST, SWITCHERS5, mc13892_swbst), MC13892_FIXED_DEFINE(VIOHI, REGULATORMODE0, mc13892_viohi), - MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0, mc13892_vpll), - MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, mc13892_vdig), - MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1, \ + MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1, mc13892_vsd), - MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0, mc13892_vusb2), - MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1, \ + MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1, mc13892_vvideo), - MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1, \ + MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1, mc13892_vaudio), - MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, mc13892_vcam), - MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0, mc13892_vgen1), - MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0, mc13892_vgen2), - MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0, \ + MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0, mc13892_vgen3), MC13892_FIXED_DEFINE(VUSB, USB1, mc13892_vusb), MC13892_GPO_DEFINE(GPO1, POWERMISC, mc13892_gpo), @@ -476,8 +476,8 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, } mc13xxx_lock(priv->mc13xxx); - ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, mask, - reg_value); + ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, + mask, reg_value); mc13xxx_unlock(priv->mc13xxx); return ret; -- cgit v1.2.3 From afd0922e7478ce3e4ea5812835164fe4e2a12896 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 16 Oct 2013 16:45:41 +0300 Subject: ath10k: prevent starting monitor without a vdev This fixes issue with interface bridging. Linux bridging sets promiscuous mode for all interfaces that are in a bridge. This translates to configure_filter() being called in a mac80211 driver. Before the patch operational interface would be started and upped again when promiscuous mode was enabled causing all sorts of strange issues: * no HTT RX happening (i.e. no traffic) * FW crash upon driver reload/unload Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0b1cc516e778..527343de5738 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2265,8 +2265,14 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw, *total_flags &= SUPPORTED_FILTERS; ar->filter_flags = *total_flags; + /* Monitor must not be started if it wasn't created first. + * Promiscuous mode may be started on a non-monitor interface - in + * such case the monitor vdev is not created so starting the + * monitor makes no sense. Since ath10k uses no special RX filters + * (only BSS filter in STA mode) there's no need for any special + * action here. */ if ((ar->filter_flags & FIF_PROMISC_IN_BSS) && - !ar->monitor_enabled) { + !ar->monitor_enabled && ar->monitor_present) { ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d start\n", ar->monitor_vdev_id); @@ -2274,7 +2280,7 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw, if (ret) ath10k_warn("Unable to start monitor mode\n"); } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && - ar->monitor_enabled) { + ar->monitor_enabled && ar->monitor_present) { ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d stop\n", ar->monitor_vdev_id); -- cgit v1.2.3 From 0ed00eea0961db3a007cbca727e3dd54e4bfd05f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 16 Oct 2013 16:45:48 +0300 Subject: ath10k: add sanity checks for monitor management Add a few checks and warnings to make it easier to track any kind of monitor vdev mismanagement. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 527343de5738..da23c3faaf5a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -516,6 +516,11 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) lockdep_assert_held(&ar->conf_mutex); + if (!ar->monitor_present) { + ath10k_warn("mac montor stop -- monitor is not present\n"); + return -EINVAL; + } + arg.vdev_id = vdev_id; arg.channel.freq = channel->center_freq; arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1; @@ -566,6 +571,16 @@ static int ath10k_monitor_stop(struct ath10k *ar) lockdep_assert_held(&ar->conf_mutex); + if (!ar->monitor_present) { + ath10k_warn("mac montor stop -- monitor is not present\n"); + return -EINVAL; + } + + if (!ar->monitor_enabled) { + ath10k_warn("mac montor stop -- monitor is not enabled\n"); + return -EINVAL; + } + ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id); if (ret) ath10k_warn("Monitor vdev down failed: %d\n", ret); -- cgit v1.2.3 From 5c54a7bf48650a8d38f2e0b1748885f5c044f45f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 16 Oct 2013 16:45:53 +0300 Subject: ath10k: fix endianess in prints This fixes incorrect values being printed on big-endian hosts. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 77238afbed75..a796d0b9a139 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2211,7 +2211,7 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar) } ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", - __cpu_to_le32(ar->wmi.num_mem_chunks)); + ar->wmi.num_mem_chunks); cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); @@ -2224,10 +2224,10 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar) __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); ath10k_dbg(ATH10K_DBG_WMI, - "wmi chunk %d len %d requested, addr 0x%x\n", + "wmi chunk %d len %d requested, addr 0x%llx\n", i, - cmd->host_mem_chunks[i].size, - cmd->host_mem_chunks[i].ptr); + ar->wmi.mem_chunks[i].len, + (unsigned long long)ar->wmi.mem_chunks[i].paddr); } out: memcpy(&cmd->resource_config, &config, sizeof(config)); @@ -2302,7 +2302,7 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) } ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", - __cpu_to_le32(ar->wmi.num_mem_chunks)); + ar->wmi.num_mem_chunks); cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); @@ -2315,10 +2315,10 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); ath10k_dbg(ATH10K_DBG_WMI, - "wmi chunk %d len %d requested, addr 0x%x\n", + "wmi chunk %d len %d requested, addr 0x%llx\n", i, - cmd->host_mem_chunks[i].size, - cmd->host_mem_chunks[i].ptr); + ar->wmi.mem_chunks[i].len, + (unsigned long long)ar->wmi.mem_chunks[i].paddr); } out: memcpy(&cmd->resource_config, &config, sizeof(config)); -- cgit v1.2.3 From c4340c26d63550eaedcc3440f6ba78d6d4c451d4 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 16 Oct 2013 16:45:59 +0300 Subject: ath10k: fix NSS reporting in RX NSTS values reported in the VHT-SIG-A1 are 0 through 7 but they actually describe number of streams 1 through 8. 1SS frames were dropped. This patch fixes this. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 5ae373a1e294..c511f919d541 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -183,7 +183,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info, /* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2 TODO check this */ mcs = (info2 >> 4) & 0x0F; - nss = (info1 >> 10) & 0x07; + nss = ((info1 >> 10) & 0x07) + 1; bw = info1 & 3; sgi = info2 & 1; -- cgit v1.2.3 From 5e90de860bc2d82dcb73caef86c05cb49c2b5792 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 16 Oct 2013 16:46:05 +0300 Subject: ath10k: fix NULL deref upon early FW crash If firmware crashes during FW probing it would try to perform FW recovery which uses mac80211 workqueue before registering to mac80211. Using internal workqueue solves the problem. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 3 ++- drivers/net/wireless/ath/ath10k/pci.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 1129994fb105..2a360cac4cee 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -664,7 +664,8 @@ static void ath10k_core_restart(struct work_struct *work) ieee80211_restart_hw(ar->hw); break; case ATH10K_STATE_OFF: - /* this can happen if driver is being unloaded */ + /* this can happen if driver is being unloaded + * or if the crash happens during FW probing */ ath10k_warn("cannot restart a device that hasn't been started\n"); break; case ATH10K_STATE_RESTARTING: diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index f8d59c7b9082..d09f8a2861ba 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -777,7 +777,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar) reg_dump_values[i + 2], reg_dump_values[i + 3]); - ieee80211_queue_work(ar->hw, &ar->restart_work); + queue_work(ar->workqueue, &ar->restart_work); } static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, -- cgit v1.2.3 From 233eb97fc9d0f44f2ea99fe48118aa3d2dc25d64 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 16 Oct 2013 16:46:11 +0300 Subject: ath10k: implement ath10k_pci_soc_read/write32() To make it easier to access SOC registers. No functional changes. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 3 +-- drivers/net/wireless/ath/ath10k/pci.h | 10 ++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index d09f8a2861ba..5c7838398e9a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2454,8 +2454,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, return ret; } - chip_id = ath10k_pci_read32(ar, - RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS); + chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); ath10k_do_pci_sleep(ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 52fb7b973571..a304c3384902 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -318,6 +318,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) return ioread32(ar_pci->mem + offset); } +static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) +{ + return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr); +} + +static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val) +{ + ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val); +} + int ath10k_do_pci_wake(struct ath10k *ar); void ath10k_do_pci_sleep(struct ath10k *ar); -- cgit v1.2.3 From 60f85bea25d5e9915da8b0c87275143b317cec3b Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 16 Oct 2013 16:46:24 +0300 Subject: ath10k: fix FW crashes on heavy TX on 10.1.389 AP FW 10.1.389 firmware has some differences in calculation of number of outstanding HTT TX completions. This led to FW crashes of 10.1.389 while main firmware branch was unnaffected. The patch makes sure ath10k doesn't queue up more MSDUs than it should. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 11 +++++++++++ drivers/net/wireless/ath/ath10k/htt_tx.c | 11 ++++------- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index e46951b8fb92..d243f287fae7 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1050,6 +1050,17 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, u32 ctrl_addr = ath10k_ce_base_address(ce_id); int ret; + /* + * Make sure there's enough CE ringbuffer entries for HTT TX to avoid + * additional TX locking checks. + * + * For the lack of a better place do the check here. + */ + BUILD_BUG_ON(TARGET_NUM_MSDU_DESC > + (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); + BUILD_BUG_ON(TARGET_10X_NUM_MSDU_DESC > + (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); + ret = ath10k_pci_wake(ar); if (ret) return NULL; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index d9335e9d0d04..f1d36d2d2723 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -85,16 +85,13 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) int ath10k_htt_tx_attach(struct ath10k_htt *htt) { - u8 pipe; - spin_lock_init(&htt->tx_lock); init_waitqueue_head(&htt->empty_tx_wq); - /* At the beginning free queue number should hint us the maximum - * queue length */ - pipe = htt->ar->htc.endpoint[htt->eid].ul_pipe_id; - htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar, - pipe); + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features)) + htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; + else + htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC; ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", htt->max_num_pending_tx); -- cgit v1.2.3 From f3782744c9b50edf94d28e37a937ff84f267dfab Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 17 Oct 2013 11:36:15 +0300 Subject: ath10k: add error handling to ath10k_pci_wait() ath10k_pci_wait() didn't notify any errors to callers, it just printed a warning so add proper error handling. This fixes a crash Ben reported: ath10k: MSI-X interrupt handling (8 intrs) ath10k: Unable to wakeup target ath10k: target took longer 5000 us to wake up (awake count 1) ath10k: Failed to get pcie state addr: -16 ath10k: early firmware event indicated BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 IP: [] ath10k_ce_completed_send_next+0x47/0x122 [ath10k_pci] Reported-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5c7838398e9a..42d2473b56ba 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -526,15 +526,19 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar) return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON); } -static void ath10k_pci_wait(struct ath10k *ar) +static int ath10k_pci_wait(struct ath10k *ar) { int n = 100; while (n-- && !ath10k_pci_target_is_awake(ar)) msleep(10); - if (n < 0) + if (n < 0) { ath10k_warn("Unable to wakeup target\n"); + return -ETIMEDOUT; + } + + return 0; } int ath10k_do_pci_wake(struct ath10k *ar) @@ -2155,7 +2159,13 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS); - ath10k_pci_wait(ar); + ret = ath10k_pci_wait(ar); + if (ret) { + ath10k_warn("Failed to enable legacy interrupt, target did not wake up: %d\n", + ret); + free_irq(ar_pci->pdev->irq, ar); + return ret; + } /* * A potential race occurs here: The CORE_BASE write @@ -2218,6 +2228,10 @@ static int ath10k_pci_start_intr(struct ath10k *ar) } ret = ath10k_pci_start_intr_legacy(ar); + if (ret) { + ath10k_warn("Failed to start legacy interrupts: %d\n", ret); + return ret; + } exit: ar_pci->num_msi_intrs = num; @@ -2243,13 +2257,19 @@ static int ath10k_pci_reset_target(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int wait_limit = 300; /* 3 sec */ + int ret; /* Wait for Target to finish initialization before we proceed. */ iowrite32(PCIE_SOC_WAKE_V_MASK, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS); - ath10k_pci_wait(ar); + ret = ath10k_pci_wait(ar); + if (ret) { + ath10k_warn("Failed to reset target, target did not wake up: %d\n", + ret); + return ret; + } while (wait_limit-- && !(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) & -- cgit v1.2.3 From e63b33f3d059bda08ab7634a435024a6e7b82e1f Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 22 Oct 2013 14:54:14 -0700 Subject: ath10k: Initialize list-head on vif creation. If the creation fails, this keeps us from crashing later when trying to do a list_del(arvif->list). Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index da23c3faaf5a..908e90dc238c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2064,6 +2064,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->vif = vif; INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); + INIT_LIST_HEAD(&arvif->list); if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { ath10k_warn("Only one monitor interface allowed\n"); -- cgit v1.2.3 From 89c5c843110b7faee9d132826d574924c4f4c056 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 23 Oct 2013 04:02:13 -0700 Subject: ath10k: setup min channel power to a reasonable value This will be needed for proper support of (user) configurable tx power level. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 908e90dc238c..8eb84fbd2d3a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -450,7 +450,7 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif) arg.channel.mode = chan_to_phymode(&conf->chandef); - arg.channel.min_power = channel->max_power * 3; + arg.channel.min_power = 0; arg.channel.max_power = channel->max_power * 4; arg.channel.max_reg_power = channel->max_reg_power * 4; arg.channel.max_antenna_gain = channel->max_antenna_gain; @@ -529,7 +529,7 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) don't have any vifs? */ arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef); - arg.channel.min_power = channel->max_power * 3; + arg.channel.min_power = 0; arg.channel.max_power = channel->max_power * 4; arg.channel.max_reg_power = channel->max_reg_power * 4; arg.channel.max_antenna_gain = channel->max_antenna_gain; @@ -1375,7 +1375,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->passive = passive; ch->freq = channel->center_freq; - ch->min_power = channel->max_power * 3; + ch->min_power = 0; ch->max_power = channel->max_power * 4; ch->max_reg_power = channel->max_reg_power * 4; ch->max_antenna_gain = channel->max_antenna_gain; -- cgit v1.2.3 From 02256930d9b80c3c8ada90ea36fd0488a91735d0 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 23 Oct 2013 04:02:14 -0700 Subject: ath10k: use proper tx power unit It was previously thought that FW expects tx power in quarters of dBm. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 18 +++++++++--------- drivers/net/wireless/ath/ath10k/wmi.h | 3 ++- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8eb84fbd2d3a..03ef162d34d4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -451,9 +451,9 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif) arg.channel.mode = chan_to_phymode(&conf->chandef); arg.channel.min_power = 0; - arg.channel.max_power = channel->max_power * 4; - arg.channel.max_reg_power = channel->max_reg_power * 4; - arg.channel.max_antenna_gain = channel->max_antenna_gain; + arg.channel.max_power = channel->max_power * 2; + arg.channel.max_reg_power = channel->max_reg_power * 2; + arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { arg.ssid = arvif->u.ap.ssid; @@ -530,9 +530,9 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef); arg.channel.min_power = 0; - arg.channel.max_power = channel->max_power * 4; - arg.channel.max_reg_power = channel->max_reg_power * 4; - arg.channel.max_antenna_gain = channel->max_antenna_gain; + arg.channel.max_power = channel->max_power * 2; + arg.channel.max_reg_power = channel->max_reg_power * 2; + arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; ret = ath10k_wmi_vdev_start(ar, &arg); if (ret) { @@ -1376,9 +1376,9 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->freq = channel->center_freq; ch->min_power = 0; - ch->max_power = channel->max_power * 4; - ch->max_reg_power = channel->max_reg_power * 4; - ch->max_antenna_gain = channel->max_antenna_gain; + ch->max_power = channel->max_power * 2; + ch->max_reg_power = channel->max_reg_power * 2; + ch->max_antenna_gain = channel->max_antenna_gain * 2; ch->reg_class_id = 0; /* FIXME */ /* FIXME: why use only legacy modes, why not any diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 78c991aec7f9..81e33a7dbaf2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -893,6 +893,7 @@ struct wmi_channel { union { __le32 reginfo0; struct { + /* note: power unit is 0.5 dBm */ u8 min_power; u8 max_power; u8 reg_power; @@ -915,7 +916,7 @@ struct wmi_channel_arg { bool allow_ht; bool allow_vht; bool ht40plus; - /* note: power unit is 1/4th of dBm */ + /* note: power unit is 0.5 dBm */ u32 min_power; u32 max_power; u32 max_reg_power; -- cgit v1.2.3 From 5474efe802faf84b1db1ae172f1754cca390ee45 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 23 Oct 2013 04:02:15 -0700 Subject: ath10k: respect power_level values This allows txpower limits other than regulatory to be applied (e.g. user txpower limit provided via iw/nl80211). Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 03ef162d34d4..bbb0efacfaf0 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2013,6 +2013,7 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) struct ath10k *ar = hw->priv; struct ieee80211_conf *conf = &hw->conf; int ret = 0; + u32 param; mutex_lock(&ar->conf_mutex); @@ -2024,6 +2025,25 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) spin_unlock_bh(&ar->data_lock); } + if (changed & IEEE80211_CONF_CHANGE_POWER) { + ath10k_dbg(ATH10K_DBG_MAC, "mac config power %d\n", + hw->conf.power_level); + + param = ar->wmi.pdev_param->txpower_limit2g; + ret = ath10k_wmi_pdev_set_param(ar, param, + hw->conf.power_level * 2); + if (ret) + ath10k_warn("mac failed to set 2g txpower %d (%d)\n", + hw->conf.power_level, ret); + + param = ar->wmi.pdev_param->txpower_limit5g; + ret = ath10k_wmi_pdev_set_param(ar, param, + hw->conf.power_level * 2); + if (ret) + ath10k_warn("mac failed to set 5g txpower %d (%d)\n", + hw->conf.power_level, ret); + } + if (changed & IEEE80211_CONF_CHANGE_PS) ath10k_config_ps(ar); -- cgit v1.2.3 From 5fb5e41f424ad970f3bda645b8234dc71fcc8e59 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 28 Oct 2013 07:18:13 +0100 Subject: ath10k: plug memory leak in wmi mgmt tx worker sk_buff was not freed in some cases. The patch unifies the msdu freeing. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 +++- drivers/net/wireless/ath/ath10k/wmi.c | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index bbb0efacfaf0..f45eca0b7a4e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1729,8 +1729,10 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) break; ret = ath10k_wmi_mgmt_tx(ar, skb); - if (ret) + if (ret) { ath10k_warn("wmi mgmt_tx failed (%d)\n", ret); + ieee80211_free_txskb(ar->hw, skb); + } } } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index a796d0b9a139..8db9db2db946 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -674,10 +674,8 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) /* Send the management frame buffer to the target */ ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); - if (ret) { - dev_kfree_skb_any(skb); + if (ret) return ret; - } /* TODO: report tx status to mac80211 - temporary just ACK */ info->flags |= IEEE80211_TX_STAT_ACK; -- cgit v1.2.3 From e204548101732849dadd8d9f229cd1c83ae9236a Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 28 Oct 2013 07:18:14 +0100 Subject: ath10k: plug memory leak on beacon tx If beacon tx command failed the wmi command buffer was not freed. This led to OOM in the long run. This became aparent when stress testing multi-BSSID. Reported-By: Tomasz Skapski Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 8db9db2db946..f79f17ce5dc6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3092,6 +3092,7 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, { struct wmi_bcn_tx_cmd *cmd; struct sk_buff *skb; + int ret; skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len); if (!skb) @@ -3104,7 +3105,11 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); memcpy(cmd->bcn, arg->bcn, arg->bcn_len); - return ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid); + ret = ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid); + if (ret) + dev_kfree_skb(skb); + + return ret; } static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, -- cgit v1.2.3 From c77ba21d742f33dbb561cba1fe7aac669f5f0339 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Oct 2013 12:25:43 +0200 Subject: drm/i915/ns2501: Rip out the reenable hack With the change in the modeset sequence this shouldn't be required any more since the ->mode_set callback now gets called when the dvo port is fully up and running. Also limit the retry loop to 10 tries to avoid hanging the machine while holding important modeset locks. Cc: Thomas Richter Tested-by: Thomas Richter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/dvo_ns2501.c | 73 +++------------------------------------ 1 file changed, 4 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c index c4a255be6979..954acb2c7021 100644 --- a/drivers/gpu/drm/i915/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/dvo_ns2501.c @@ -87,49 +87,6 @@ struct ns2501_priv { * when switching the resolution. */ -static void enable_dvo(struct intel_dvo_device *dvo) -{ - struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); - struct i2c_adapter *adapter = dvo->i2c_bus; - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); - struct drm_i915_private *dev_priv = bus->dev_priv; - - DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__); - - ns->dvoc = I915_READ(DVO_C); - ns->pll_a = I915_READ(_DPLL_A); - ns->srcdim = I915_READ(DVOC_SRCDIM); - ns->fw_blc = I915_READ(FW_BLC); - - I915_WRITE(DVOC, 0x10004084); - I915_WRITE(_DPLL_A, 0xd0820000); - I915_WRITE(DVOC_SRCDIM, 0x400300); // 1024x768 - I915_WRITE(FW_BLC, 0x1080304); - - I915_WRITE(DVOC, 0x90004084); -} - -/* - * Restore the I915 registers modified by the above - * trigger function. - */ -static void restore_dvo(struct intel_dvo_device *dvo) -{ - struct i2c_adapter *adapter = dvo->i2c_bus; - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); - struct drm_i915_private *dev_priv = bus->dev_priv; - struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); - - I915_WRITE(DVOC, ns->dvoc); - I915_WRITE(_DPLL_A, ns->pll_a); - I915_WRITE(DVOC_SRCDIM, ns->srcdim); - I915_WRITE(FW_BLC, ns->fw_blc); -} - /* ** Read a register from the ns2501. ** Returns true if successful, false otherwise. @@ -300,7 +257,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, struct drm_display_mode *adjusted_mode) { bool ok; - bool restore = false; + int retries = 10; struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); DRM_DEBUG_KMS @@ -476,20 +433,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, ns->reg_8_shadow |= NS2501_8_BPAS; } ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow); - - if (!ok) { - if (restore) - restore_dvo(dvo); - enable_dvo(dvo); - restore = true; - } - } while (!ok); - /* - * Restore the old i915 registers before - * forcing the ns2501 on. - */ - if (restore) - restore_dvo(dvo); + } while (!ok && retries--); } /* set the NS2501 power state */ @@ -510,7 +454,7 @@ static bool ns2501_get_hw_state(struct intel_dvo_device *dvo) static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) { bool ok; - bool restore = false; + int retries = 10; struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); unsigned char ch; @@ -537,16 +481,7 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) ok &= ns2501_writeb(dvo, 0x35, enable ? 0xff : 0x00); - if (!ok) { - if (restore) - restore_dvo(dvo); - enable_dvo(dvo); - restore = true; - } - } while (!ok); - - if (restore) - restore_dvo(dvo); + } while (!ok && retries--); } } -- cgit v1.2.3 From f34191585ff30849ab80a03c2bb4294db4cfbffc Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Nov 2013 11:52:44 -0800 Subject: drm/i915: add bunit read/write routines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For modifying self-refresh exit latency. Reviewed-by: Ville Syrjälä Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_sideband.c | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b12d942ab09c..3ffe330fe026 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2400,6 +2400,8 @@ u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); +u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg); +void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f303ba995c5..0de97adc4fcb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -349,6 +349,7 @@ #define IOSF_BYTE_ENABLES_SHIFT 4 #define IOSF_BAR_SHIFT 1 #define IOSF_SB_BUSY (1<<0) +#define IOSF_PORT_BUNIT 0x3 #define IOSF_PORT_PUNIT 0x4 #define IOSF_PORT_NC 0x11 #define IOSF_PORT_DPIO 0x12 diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 9944d8135e87..d43e457b6961 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -90,6 +90,22 @@ void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) mutex_unlock(&dev_priv->dpio_lock); } +u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg) +{ + u32 val = 0; + + vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT, + PUNIT_OPCODE_REG_READ, reg, &val); + + return val; +} + +void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) +{ + vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT, + PUNIT_OPCODE_REG_WRITE, reg, &val); +} + u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) { u32 val = 0; -- cgit v1.2.3 From 85b1d7b3f475c6425707b2e064f9c0f54058019d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Nov 2013 11:52:45 -0800 Subject: drm/i915: move VLV DDR freq fetch into init_clock_gating We don't want it delayed with the RPS work. Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 09ac9e79830f..13afd54ca6e9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4064,19 +4064,6 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_CONTROL, rc6_mode); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - switch ((val >> 6) & 3) { - case 0: - case 1: - dev_priv->mem_freq = 800; - break; - case 2: - dev_priv->mem_freq = 1066; - break; - case 3: - dev_priv->mem_freq = 1333; - break; - } - DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no"); DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); @@ -5325,6 +5312,24 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) static void valleyview_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); + mutex_unlock(&dev_priv->rps.hw_lock); + switch ((val >> 6) & 3) { + case 0: + case 1: + dev_priv->mem_freq = 800; + break; + case 2: + dev_priv->mem_freq = 1066; + break; + case 3: + dev_priv->mem_freq = 1333; + break; + } + DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3 From 30a970c6a6ff734eda7cefe7e88f030157a6c939 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Nov 2013 13:48:12 -0800 Subject: drm/i915/vlv: modeset_global_* for VLV v7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On VLV/BYT, we can adjust the CDclk frequency up or down based on the max pixel clock we need to drive. Lowering it can save power, while raising it is necessary to support high resolution. Add a new callback in modeset_affected_pipes and a modeset_global_resources function to perform this adjustment as necessary. v2: use punit interface for 320 and 266 MHz CDclk adjustments (Ville) v3: reset GMBUS dividers too, since we changed CDclk (Ville) v4: jump to highest voltage when going to 400MHz CDclk (Jesse) v5: drop duplicate define (Ville) use shifts by 1 for fixed point (Ville) drop new callback (Daniel) v6: fixup adjusted_mode.clock -> adjusted_mode.crtc_clock again (Ville) document Bunit reg access better (Ville) v7: pass modeset_pipes and pipe_config to global_pipes so we get the right clock data (Ville) Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 9 ++ drivers/gpu/drm/i915/intel_display.c | 189 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_i2c.c | 4 - 3 files changed, 198 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0de97adc4fcb..86a1ad86aa7b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -360,9 +360,17 @@ #define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108) +/* See configdb bunit SB addr map */ +#define BUNIT_REG_BISOC 0x11 + #define PUNIT_OPCODE_REG_READ 6 #define PUNIT_OPCODE_REG_WRITE 7 +#define PUNIT_REG_DSPFREQ 0x36 +#define DSPFREQSTAT_SHIFT 30 +#define DSPFREQSTAT_MASK (0x3 << DSPFREQSTAT_SHIFT) +#define DSPFREQGUAR_SHIFT 14 +#define DSPFREQGUAR_MASK (0x3 << DSPFREQGUAR_SHIFT) #define PUNIT_REG_PWRGT_CTRL 0x60 #define PUNIT_REG_PWRGT_STATUS 0x61 #define PUNIT_CLK_GATE 1 @@ -425,6 +433,7 @@ #define DSI_PLL_N1_DIV_MASK (3 << 16) #define DSI_PLL_M1_DIV_SHIFT 0 #define DSI_PLL_M1_DIV_MASK (0x1ff << 0) +#define CCK_DISPLAY_CLOCK_CONTROL 0x6b /* * DPIO - a special bus for various display related registers to hide behind diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f34252d134b6..c034413a1584 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3894,6 +3894,181 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc) I915_WRITE(BCLRPAT(crtc->pipe), 0); } +static int valleyview_get_vco(struct drm_i915_private *dev_priv) +{ + int vco; + + switch (dev_priv->mem_freq) { + default: + case 800: + vco = 800; + break; + case 1066: + vco = 1600; + break; + case 1333: + vco = 2000; + break; + } + + return vco; +} + +/* Adjust CDclk dividers to allow high res or save power if possible */ +static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val, cmd; + + if (cdclk >= 320) /* jump to highest voltage for 400MHz too */ + cmd = 2; + else if (cdclk == 266) + cmd = 1; + else + cmd = 0; + + mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); + val &= ~DSPFREQGUAR_MASK; + val |= (cmd << DSPFREQGUAR_SHIFT); + vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val); + if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & + DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), + 50)) { + DRM_ERROR("timed out waiting for CDclk change\n"); + } + mutex_unlock(&dev_priv->rps.hw_lock); + + if (cdclk == 400) { + u32 divider, vco; + + vco = valleyview_get_vco(dev_priv); + divider = ((vco << 1) / cdclk) - 1; + + mutex_lock(&dev_priv->dpio_lock); + /* adjust cdclk divider */ + val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + val &= ~0xf; + val |= divider; + vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val); + mutex_unlock(&dev_priv->dpio_lock); + } + + mutex_lock(&dev_priv->dpio_lock); + /* adjust self-refresh exit latency value */ + val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC); + val &= ~0x7f; + + /* + * For high bandwidth configs, we set a higher latency in the bunit + * so that the core display fetch happens in time to avoid underruns. + */ + if (cdclk == 400) + val |= 4500 / 250; /* 4.5 usec */ + else + val |= 3000 / 250; /* 3.0 usec */ + vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val); + mutex_unlock(&dev_priv->dpio_lock); + + /* Since we changed the CDclk, we need to update the GMBUSFREQ too */ + intel_i2c_reset(dev); +} + +static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv) +{ + int cur_cdclk, vco; + int divider; + + vco = valleyview_get_vco(dev_priv); + + mutex_lock(&dev_priv->dpio_lock); + divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + mutex_unlock(&dev_priv->dpio_lock); + + divider &= 0xf; + + cur_cdclk = (vco << 1) / (divider + 1); + + return cur_cdclk; +} + +static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, + int max_pixclk) +{ + int cur_cdclk; + + cur_cdclk = valleyview_cur_cdclk(dev_priv); + + /* + * Really only a few cases to deal with, as only 4 CDclks are supported: + * 200MHz + * 267MHz + * 320MHz + * 400MHz + * So we check to see whether we're above 90% of the lower bin and + * adjust if needed. + */ + if (max_pixclk > 288000) { + return 400; + } else if (max_pixclk > 240000) { + return 320; + } else + return 266; + /* Looks like the 200MHz CDclk freq doesn't work on some configs */ +} + +static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv, + unsigned modeset_pipes, + struct intel_crtc_config *pipe_config) +{ + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *intel_crtc; + int max_pixclk = 0; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, + base.head) { + if (modeset_pipes & (1 << intel_crtc->pipe)) + max_pixclk = max(max_pixclk, + pipe_config->adjusted_mode.crtc_clock); + else if (intel_crtc->base.enabled) + max_pixclk = max(max_pixclk, + intel_crtc->config.adjusted_mode.crtc_clock); + } + + return max_pixclk; +} + +static void valleyview_modeset_global_pipes(struct drm_device *dev, + unsigned *prepare_pipes, + unsigned modeset_pipes, + struct intel_crtc_config *pipe_config) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc; + int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes, + pipe_config); + int cur_cdclk = valleyview_cur_cdclk(dev_priv); + + if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk) + return; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, + base.head) + if (intel_crtc->base.enabled) + *prepare_pipes |= (1 << intel_crtc->pipe); +} + +static void valleyview_modeset_global_resources(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int max_pixclk = intel_mode_max_pixclk(dev_priv, 0, NULL); + int cur_cdclk = valleyview_cur_cdclk(dev_priv); + int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); + + if (req_cdclk != cur_cdclk) + valleyview_set_cdclk(dev, req_cdclk); +} + static void valleyview_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -9318,6 +9493,17 @@ static int __intel_set_mode(struct drm_crtc *crtc, "[modeset]"); } + /* + * See if the config requires any additional preparation, e.g. + * to adjust global state with pipes off. We need to do this + * here so we can get the modeset_pipe updated config for the new + * mode set on this crtc. For other crtcs we need to use the + * adjusted_mode bits in the crtc directly. + */ + if (IS_VALLEYVIEW(dev)) + valleyview_modeset_global_pipes(dev, &prepare_pipes, + modeset_pipes, pipe_config); + for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) intel_crtc_disable(&intel_crtc->base); @@ -10317,6 +10503,9 @@ static void intel_init_display(struct drm_device *dev) } } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->display.modeset_global_resources = + valleyview_modeset_global_resources; } /* Default just returns -ENODEV to indicate unsupported */ diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 2ca17b14b6c1..1263409d00b3 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -87,10 +87,6 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv) BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - /* Skip setting the gmbus freq if BIOS has already programmed it */ - if (I915_READ(GMBUSFREQ_VLV) != 0xA0) - return; - /* Obtain SKU information */ mutex_lock(&dev_priv->dpio_lock); hpll_freq = -- cgit v1.2.3 From 586f49dc781314f1e6b1133f6d966d670c219a67 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Nov 2013 16:06:59 -0800 Subject: drm/i915/vlv: split CCK and DDR freq usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's possible that the CCK clock could run at a different rate than the DDR clock, so use the same method to get CCK as the GMBUS code does when calculating the new CDclk divider in the VLV display code. Reported-by: Ville Syrjälä Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 23 ++++++++--------------- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 11 +++-------- 3 files changed, 12 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c034413a1584..3c17e959a0eb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3894,24 +3894,17 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc) I915_WRITE(BCLRPAT(crtc->pipe), 0); } -static int valleyview_get_vco(struct drm_i915_private *dev_priv) +int valleyview_get_vco(struct drm_i915_private *dev_priv) { - int vco; + int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; - switch (dev_priv->mem_freq) { - default: - case 800: - vco = 800; - break; - case 1066: - vco = 1600; - break; - case 1333: - vco = 2000; - break; - } + /* Obtain SKU information */ + mutex_lock(&dev_priv->dpio_lock); + hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) & + CCK_FUSE_HPLL_FREQ_MASK; + mutex_unlock(&dev_priv->dpio_lock); - return vco; + return vco_freq[hpll_freq]; } /* Adjust CDclk dividers to allow high res or save power if possible */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9d2624fd92c2..6d701e79b611 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -693,7 +693,7 @@ void i915_disable_vga_mem(struct drm_device *dev); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); void intel_display_set_init_power(struct drm_device *dev, bool enable); - +int valleyview_get_vco(struct drm_i915_private *dev_priv); /* intel_dp.c */ void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 1263409d00b3..b1dc33f47899 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -82,16 +82,11 @@ static int get_disp_clk_div(struct drm_i915_private *dev_priv, static void gmbus_set_freq(struct drm_i915_private *dev_priv) { - int vco_freq[] = { 800, 1600, 2000, 2400 }; - int gmbus_freq = 0, cdclk_div, hpll_freq; + int vco, gmbus_freq = 0, cdclk_div; BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - /* Obtain SKU information */ - mutex_lock(&dev_priv->dpio_lock); - hpll_freq = - vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK; - mutex_unlock(&dev_priv->dpio_lock); + vco = valleyview_get_vco(dev_priv); /* Get the CDCLK divide ratio */ cdclk_div = get_disp_clk_div(dev_priv, CDCLK); @@ -102,7 +97,7 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv) * in fact 1MHz is the correct frequency. */ if (cdclk_div) - gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div; + gmbus_freq = (vco << 1) / cdclk_div; if (WARN_ON(gmbus_freq == 0)) return; -- cgit v1.2.3 From f64a28a7c5ab2fc342326de9e126acf3cc0f91d6 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Nov 2013 16:07:00 -0800 Subject: drm/i915/vlv: fixup DDR freq detection per Punit spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Either the docs were wrong or the values have changed since the old days before we had wheels. Reported-by: Ville Syrjälä Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 13afd54ca6e9..a5778e59cc15 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5319,15 +5319,22 @@ static void valleyview_init_clock_gating(struct drm_device *dev) mutex_unlock(&dev_priv->rps.hw_lock); switch ((val >> 6) & 3) { case 0: - case 1: dev_priv->mem_freq = 800; break; - case 2: + case 1: dev_priv->mem_freq = 1066; break; - case 3: + case 2: dev_priv->mem_freq = 1333; break; + case 3: + /* + * Probably a BIOS/Punit bug, or a new platform we don't + * support yet. + */ + WARN(1, "invalid DDR freq detected, assuming 800MHz\n"); + dev_priv->mem_freq = 800; + break; } DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); -- cgit v1.2.3 From 64528d03d7233800ec77f1acb9222cf090f926ca Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 30 Oct 2013 22:48:00 +0000 Subject: iio: hid-sensors: accelerometer: Add sensitivity A number of Properties that can be applied to Data Fields are per data field basis or for all data fields. Adding sensitivity field for all accelerometer fields, which is most commonly used in currently available sensor hubs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/hid-sensor-accel-3d.c | 12 ++++++++++++ include/linux/hid-sensor-ids.h | 5 +++++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index dcda17395c4e..6b8735ce8345 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -262,6 +262,18 @@ static int accel_3d_parse_report(struct platform_device *pdev, st->accel[1].index, st->accel[1].report_id, st->accel[2].index, st->accel[2].report_id); + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_ACCELERATION, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } + return ret; } diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 4f945d3ed49f..4dda3b791c82 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -23,6 +23,7 @@ /* Accel 3D (200073) */ #define HID_USAGE_SENSOR_ACCEL_3D 0x200073 +#define HID_USAGE_SENSOR_DATA_ACCELERATION 0x200452 #define HID_USAGE_SENSOR_ACCEL_X_AXIS 0x200453 #define HID_USAGE_SENSOR_ACCEL_Y_AXIS 0x200454 #define HID_USAGE_SENSOR_ACCEL_Z_AXIS 0x200455 @@ -117,4 +118,8 @@ #define HID_USAGE_SENSOR_PROP_REPORT_STATE 0x200316 #define HID_USAGE_SENSOR_PROY_POWER_STATE 0x200319 +/* Per data field properties */ +#define HID_USAGE_SENSOR_DATA_MOD_NONE 0x00 +#define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000 + #endif -- cgit v1.2.3 From 2371aebf027b86d740e40b47c813be8474500bcd Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 30 Oct 2013 22:48:00 +0000 Subject: iio: hid-sensors: gyro : Add sensitivity A number of Properties that can be applied to Data Fields are per data field basis or for all data fields. Adding sensitivity field for all gyro fields, which is most commonly used in currently available sensor hubs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/hid-sensor-gyro-3d.c | 11 +++++++++++ include/linux/hid-sensor-ids.h | 1 + 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index ea01c6bcfb56..97797dbaad34 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -262,6 +262,17 @@ static int gyro_3d_parse_report(struct platform_device *pdev, st->gyro[1].index, st->gyro[1].report_id, st->gyro[2].index, st->gyro[2].report_id); + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_ANGL_VELOCITY, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } return ret; } diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 4dda3b791c82..f3ed6b14f86c 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -34,6 +34,7 @@ /* Gyro 3D: (200076) */ #define HID_USAGE_SENSOR_GYRO_3D 0x200076 +#define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456 #define HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS 0x200457 #define HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS 0x200458 #define HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS 0x200459 -- cgit v1.2.3 From f87ee1bd888e0f6b9179c569b60d2c92c0000bc8 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 30 Oct 2013 22:48:00 +0000 Subject: iio: hid-sensors: light/als : Add sensitivity A number of Properties that can be applied to Data Fields are per data field basis or for all data fields. Adding sensitivity field for all als fields, which is most commonly used in currently available sensor hubs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/light/hid-sensor-als.c | 11 +++++++++++ include/linux/hid-sensor-ids.h | 1 + 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index fa6ae8cf89ea..0c7f115ee3b3 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -229,6 +229,17 @@ static int als_parse_report(struct platform_device *pdev, dev_dbg(&pdev->dev, "als %x:%x\n", st->als_illum.index, st->als_illum.report_id); + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_LIGHT, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } return ret; } diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index f3ed6b14f86c..8d45e0290c91 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -30,6 +30,7 @@ /* ALS (200041) */ #define HID_USAGE_SENSOR_ALS 0x200041 +#define HID_USAGE_SENSOR_DATA_LIGHT 0x2004d0 #define HID_USAGE_SENSOR_LIGHT_ILLUM 0x2004d1 /* Gyro 3D: (200076) */ -- cgit v1.2.3 From 12eb087939d11af6b5a8228807d1428535aedb3b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 30 Oct 2013 13:24:39 +0800 Subject: ath10k: fix possible memory leak in ath10k_pci_probe() memory is malloced in ath10k_pci_probe() and should be freed before leaving from the error handling cases, otherwise it will cause memory leak. Signed-off-by: Wei Yongjun Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 42d2473b56ba..25ed07b96a1e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2471,7 +2471,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ret = ath10k_do_pci_wake(ar); if (ret) { ath10k_err("Failed to get chip id: %d\n", ret); - return ret; + goto err_iomap; } chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); -- cgit v1.2.3 From c164f833cc842b427f817c3a6f30d806b1d57ef1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 Nov 2013 22:34:12 +0200 Subject: drm/i915: Sanitize prepare_pipes after valleyview_modeset_global_pipes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit valleyview_modeset_global_pipes() may add pipes that are getting fully disabled to prepare_pipes bitmask. The rest of the code doesn't expect this, so clear out any such pipes from the prepare_pipes bitmask. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c17e959a0eb..e36b3b057801 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9493,10 +9493,14 @@ static int __intel_set_mode(struct drm_crtc *crtc, * mode set on this crtc. For other crtcs we need to use the * adjusted_mode bits in the crtc directly. */ - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev)) { valleyview_modeset_global_pipes(dev, &prepare_pipes, modeset_pipes, pipe_config); + /* may have added more to prepare_pipes than we should */ + prepare_pipes &= ~disable_pipes; + } + for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) intel_crtc_disable(&intel_crtc->base); -- cgit v1.2.3 From 07ab118b393410c65146f44c17b0ae5373eb972e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 Nov 2013 22:42:28 +0200 Subject: drm/i915: Improve vlv_gpu_freq() and vlv_freq_opcode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're currently miscalculating the VLV graphics clock a little bit. This is caused by rounding the step to integer MHz, which does not match reality. Change the formula to match the GUnit HAS to give more accurate answers. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a5778e59cc15..865035beccc7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5947,57 +5947,46 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) int vlv_gpu_freq(int ddr_freq, int val) { - int mult, base; + int div; + /* 4 x czclk */ switch (ddr_freq) { case 800: - mult = 20; - base = 120; + div = 10; break; case 1066: - mult = 22; - base = 133; + div = 12; break; case 1333: - mult = 21; - base = 125; + div = 16; break; default: return -1; } - return ((val - 0xbd) * mult) + base; + return DIV_ROUND_CLOSEST(ddr_freq * (val + 6 - 0xbd), 4 * div); } int vlv_freq_opcode(int ddr_freq, int val) { - int mult, base; + int mul; + /* 4 x czclk */ switch (ddr_freq) { case 800: - mult = 20; - base = 120; + mul = 10; break; case 1066: - mult = 22; - base = 133; + mul = 12; break; case 1333: - mult = 21; - base = 125; + mul = 16; break; default: return -1; } - val /= mult; - val -= base / mult; - val += 0xbd; - - if (val > 0xea) - val = 0xea; - - return val; + return DIV_ROUND_CLOSEST(4 * mul * val, ddr_freq) + 0xbd - 6; } void intel_pm_init(struct drm_device *dev) -- cgit v1.2.3 From 2ec3815f29d1b7659ecf3f1791e7e394efdd6969 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 Nov 2013 22:42:29 +0200 Subject: drm/i915: Pass dev_priv to vlv_gpu_freq() and vlv_freq_opcode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll be looking at more than just mem_freq from dev_priv, so just pass the whole thing. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 17 +++++++---------- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_sysfs.c | 13 ++++++------- drivers/gpu/drm/i915/intel_pm.c | 38 ++++++++++++++++--------------------- 4 files changed, 31 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7008aacfc3c9..9770c2f81196 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -974,15 +974,14 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1); seq_printf(m, "max GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv->mem_freq, val)); + vlv_gpu_freq(dev_priv, val)); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM); seq_printf(m, "min GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv->mem_freq, val)); + vlv_gpu_freq(dev_priv, val)); seq_printf(m, "current GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv->mem_freq, - (freq_sts >> 8) & 0xff)); + vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); mutex_unlock(&dev_priv->rps.hw_lock); } else { seq_puts(m, "no P-state info available\n"); @@ -2725,8 +2724,7 @@ i915_max_freq_get(void *data, u64 *val) return ret; if (IS_VALLEYVIEW(dev)) - *val = vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.max_delay); + *val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay); else *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -2756,7 +2754,7 @@ i915_max_freq_set(void *data, u64 val) * Turbo will still be enabled, but won't go above the set value. */ if (IS_VALLEYVIEW(dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); dev_priv->rps.max_delay = val; gen6_set_rps(dev, val); } else { @@ -2791,8 +2789,7 @@ i915_min_freq_get(void *data, u64 *val) return ret; if (IS_VALLEYVIEW(dev)) - *val = vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.min_delay); + *val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay); else *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -2822,7 +2819,7 @@ i915_min_freq_set(void *data, u64 val) * Turbo will still be enabled, but won't go below the set value. */ if (IS_VALLEYVIEW(dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); dev_priv->rps.min_delay = val; valleyview_set_rps(dev, val); } else { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3ffe330fe026..e2d974594b2b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2411,8 +2411,8 @@ u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg, void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, enum intel_sbi_destination destination); -int vlv_gpu_freq(int ddr_freq, int val); -int vlv_freq_opcode(int ddr_freq, int val); +int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); +int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 9ff1e4d96909..2fc8d2f401be 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -257,7 +257,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, if (IS_VALLEYVIEW(dev_priv->dev)) { u32 freq; freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff); + ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff); } else { ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; } @@ -274,8 +274,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, struct drm_i915_private *dev_priv = dev->dev_private; return snprintf(buf, PAGE_SIZE, "%d\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.rpe_delay)); + vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay)); } static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) @@ -289,7 +288,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) - ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay); + ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay); else ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -316,7 +315,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); hw_max = valleyview_rps_max_freq(dev_priv); hw_min = valleyview_rps_min_freq(dev_priv); @@ -365,7 +364,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) - ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay); + ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay); else ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; mutex_unlock(&dev_priv->rps.hw_lock); @@ -392,7 +391,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) { - val = vlv_freq_opcode(dev_priv->mem_freq, val); + val = vlv_freq_opcode(dev_priv, val); hw_max = valleyview_rps_max_freq(dev_priv); hw_min = valleyview_rps_min_freq(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 865035beccc7..f5bb9b349487 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3609,9 +3609,9 @@ static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv) if (pval != dev_priv->rps.cur_delay) DRM_DEBUG_DRIVER("Punit overrode GPU freq: %d MHz (%u) requested, but got %d Mhz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), dev_priv->rps.cur_delay, - vlv_gpu_freq(dev_priv->mem_freq, pval), pval); + vlv_gpu_freq(dev_priv, pval), pval); dev_priv->rps.cur_delay = pval; } @@ -3629,10 +3629,9 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) vlv_update_rps_cur_delay(dev_priv); DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.cur_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), dev_priv->rps.cur_delay, - vlv_gpu_freq(dev_priv->mem_freq, val), val); + vlv_gpu_freq(dev_priv, val), val); if (val == dev_priv->rps.cur_delay) return; @@ -3641,7 +3640,7 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) dev_priv->rps.cur_delay = val; - trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val)); + trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val)); } static void gen6_disable_rps_interrupts(struct drm_device *dev) @@ -4070,32 +4069,27 @@ static void valleyview_enable_rps(struct drm_device *dev) dev_priv->rps.cur_delay = (val >> 8) & 0xff; DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.cur_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), dev_priv->rps.cur_delay); dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv); dev_priv->rps.hw_max = dev_priv->rps.max_delay; DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.max_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay), dev_priv->rps.max_delay); dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv); DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.rpe_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), dev_priv->rps.rpe_delay); dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv); DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.min_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay), dev_priv->rps.min_delay); DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n", - vlv_gpu_freq(dev_priv->mem_freq, - dev_priv->rps.rpe_delay), + vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), dev_priv->rps.rpe_delay); valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); @@ -5945,12 +5939,12 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) return 0; } -int vlv_gpu_freq(int ddr_freq, int val) +int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val) { int div; /* 4 x czclk */ - switch (ddr_freq) { + switch (dev_priv->mem_freq) { case 800: div = 10; break; @@ -5964,15 +5958,15 @@ int vlv_gpu_freq(int ddr_freq, int val) return -1; } - return DIV_ROUND_CLOSEST(ddr_freq * (val + 6 - 0xbd), 4 * div); + return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div); } -int vlv_freq_opcode(int ddr_freq, int val) +int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val) { int mul; /* 4 x czclk */ - switch (ddr_freq) { + switch (dev_priv->mem_freq) { case 800: mul = 10; break; @@ -5986,7 +5980,7 @@ int vlv_freq_opcode(int ddr_freq, int val) return -1; } - return DIV_ROUND_CLOSEST(4 * mul * val, ddr_freq) + 0xbd - 6; + return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6; } void intel_pm_init(struct drm_device *dev) -- cgit v1.2.3 From 8245be31391974dc756a21cf2f2e25c7f53637c5 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 6 Nov 2013 13:56:29 -0200 Subject: drm/i915: Require HW contexts (when possible) v2: Fixed the botched locking on init_hw failure in i915_reset (Ville) Call cleanup_ringbuffer on failed context create in init_hw (Ville) v3: Add dev argument ti clean_ringbuffer Reviewed-by: Kenneth Graunke Signed-off-by: Ben Widawsky Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 3 --- drivers/gpu/drm/i915/i915_drv.h | 3 +-- drivers/gpu/drm/i915/i915_gem.c | 8 +++++- drivers/gpu/drm/i915/i915_gem_context.c | 43 +++++++++++++++------------------ drivers/gpu/drm/i915/i915_sysfs.c | 6 ++--- 5 files changed, 31 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a0804fa1e306..65447572b129 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -755,12 +755,9 @@ int i915_reset(struct drm_device *dev) */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->ums.mm_suspended) { - bool hw_contexts_disabled = dev_priv->hw_contexts_disabled; dev_priv->ums.mm_suspended = 0; ret = i915_gem_init_hw(dev); - if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled) - DRM_ERROR("HW contexts didn't survive reset\n"); mutex_unlock(&dev->struct_mutex); if (ret) { DRM_ERROR("Failed hw init on reset %d\n", ret); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e2d974594b2b..efca30dc6c57 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1447,7 +1447,6 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; - bool hw_contexts_disabled; uint32_t hw_context_size; struct list_head context_list; @@ -2151,7 +2150,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj, } /* i915_gem_context.c */ -void i915_gem_context_init(struct drm_device *dev); +int __must_check i915_gem_context_init(struct drm_device *dev); void i915_gem_context_fini(struct drm_device *dev); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct intel_ring_buffer *ring, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e7b39d731db6..bc528201caca 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4463,7 +4463,13 @@ i915_gem_init_hw(struct drm_device *dev) * XXX: There was some w/a described somewhere suggesting loading * contexts before PPGTT. */ - i915_gem_context_init(dev); + ret = i915_gem_context_init(dev); + if (ret) { + i915_gem_cleanup_ringbuffer(dev); + DRM_ERROR("Context initialization failed %d\n", ret); + return ret; + } + if (dev_priv->mm.aliasing_ppgtt) { ret = dev_priv->mm.aliasing_ppgtt->enable(dev); if (ret) { diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index cc619c138777..4625670bcadb 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -244,36 +244,34 @@ err_destroy: return ret; } -void i915_gem_context_init(struct drm_device *dev) +int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + int ret; - if (!HAS_HW_CONTEXTS(dev)) { - dev_priv->hw_contexts_disabled = true; - DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n"); - return; - } + if (!HAS_HW_CONTEXTS(dev)) + return 0; /* If called from reset, or thaw... we've been here already */ - if (dev_priv->hw_contexts_disabled || - dev_priv->ring[RCS].default_context) - return; + if (dev_priv->ring[RCS].default_context) + return 0; dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); if (dev_priv->hw_context_size > (1<<20)) { - dev_priv->hw_contexts_disabled = true; DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n"); - return; + return -E2BIG; } - if (create_default_context(dev_priv)) { - dev_priv->hw_contexts_disabled = true; - DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n"); - return; + ret = create_default_context(dev_priv); + if (ret) { + DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n", + ret); + return ret; } DRM_DEBUG_DRIVER("HW context support initialized\n"); + return 0; } void i915_gem_context_fini(struct drm_device *dev) @@ -281,7 +279,7 @@ void i915_gem_context_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; - if (dev_priv->hw_contexts_disabled) + if (!HAS_HW_CONTEXTS(dev)) return; /* The only known way to stop the gpu from accessing the hw context is @@ -324,16 +322,16 @@ i915_gem_context_get_hang_stats(struct drm_device *dev, struct drm_file *file, u32 id) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; if (id == DEFAULT_CONTEXT_ID) return &file_priv->hang_stats; - ctx = NULL; - if (!dev_priv->hw_contexts_disabled) - ctx = i915_gem_context_get(file->driver_priv, id); + if (!HAS_HW_CONTEXTS(dev)) + return ERR_PTR(-ENOENT); + + ctx = i915_gem_context_get(file->driver_priv, id); if (ctx == NULL) return ERR_PTR(-ENOENT); @@ -506,7 +504,7 @@ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_i915_private *dev_priv = ring->dev->dev_private; struct i915_hw_context *to; - if (dev_priv->hw_contexts_disabled) + if (!HAS_HW_CONTEXTS(ring->dev)) return 0; WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); @@ -531,7 +529,6 @@ int i915_switch_context(struct intel_ring_buffer *ring, int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_context_create *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; @@ -540,7 +537,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; - if (dev_priv->hw_contexts_disabled) + if (!HAS_HW_CONTEXTS(dev)) return -ENODEV; ret = i915_mutex_lock_interruptible(dev); diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 2fc8d2f401be..85b98111d995 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -181,13 +181,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj, int slice = (int)(uintptr_t)attr->private; int ret; + if (!HAS_HW_CONTEXTS(drm_dev)) + return -ENXIO; + ret = l3_access_valid(drm_dev, offset); if (ret) return ret; - if (dev_priv->hw_contexts_disabled) - return -ENXIO; - ret = i915_mutex_lock_interruptible(drm_dev); if (ret) return ret; -- cgit v1.2.3 From 2325991e021fb0da21d8d08009d1eea78133745a Mon Sep 17 00:00:00 2001 From: Chon Ming Lee Date: Thu, 7 Nov 2013 15:23:26 +0800 Subject: drm/i915/vlv: Workaround a punit issue in DDR data rate for 1333. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For DDR data rate reporting by Punit in PUNIT_GPU_FREQ_STS, the actual data encoding is 00b=800, 01b=1066, 10b=1333, 11b=1333. Some premium VLV sku will get the DDR_DATA_RATE set as 11. As a result, the turbo frequency reporting will be incorrect without this workaround. Signed-off-by: Chon Ming Lee Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f5bb9b349487..38943f8ef260 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5322,12 +5322,7 @@ static void valleyview_init_clock_gating(struct drm_device *dev) dev_priv->mem_freq = 1333; break; case 3: - /* - * Probably a BIOS/Punit bug, or a new platform we don't - * support yet. - */ - WARN(1, "invalid DDR freq detected, assuming 800MHz\n"); - dev_priv->mem_freq = 800; + dev_priv->mem_freq = 1333; break; } DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); -- cgit v1.2.3 From edc08d0a40f7ddab6bf7249e59ecf692d36c7192 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2013 13:56:27 -0200 Subject: drm/i915: Fix gen3/4 vblank counter wraparound MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the hardware frame counter reads 0xffffff and we're already past vblank start, we'd return 0x1000000 as the vblank counter value. Once we'd cross into the next frame's active portion, the vblank counter would wrap to 0. So we're reporting two different vblank counter values for the same frame. Fix the problem by masking the cooked value by 0xffffff to make sure the counter wraps already after vblank start. Signed-off-by: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a228176676b2..c6176f337452 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -583,7 +583,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) * Cook up a vblank counter by also checking the pixel * counter against vblank start. */ - return ((high1 << 8) | low) + (pixel >= vbl_start); + return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; } static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) -- cgit v1.2.3 From 57e22f4add51b0f42b76a6960c4a4daa71e8f832 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2013 13:56:28 -0200 Subject: drm/i915: Use frame counter for intel_wait_for_vblank() on CTG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the same wait_for_vblank code for CTG that we use for ILK+. Also fix the name of the frame counter register while at it. Signed-off-by: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e36b3b057801..0980bd95e372 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -748,10 +748,10 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, return intel_crtc->config.cpu_transcoder; } -static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) +static void g4x_wait_for_vblank(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 frame, frame_reg = PIPEFRAME(pipe); + u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe); frame = I915_READ(frame_reg); @@ -772,8 +772,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) struct drm_i915_private *dev_priv = dev->dev_private; int pipestat_reg = PIPESTAT(pipe); - if (INTEL_INFO(dev)->gen >= 5) { - ironlake_wait_for_vblank(dev, pipe); + if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { + g4x_wait_for_vblank(dev, pipe); return; } -- cgit v1.2.3 From c5bd2bf61d487cd0125433aeaadd8bb87a11ccff Mon Sep 17 00:00:00 2001 From: Chon Ming Lee Date: Thu, 7 Nov 2013 15:23:27 +0800 Subject: drm/i915/vlv: For i915_cur_delayinfo, the max frequency reporting wrong value. The max frequency reporting is not correct. But there is already an existing valleyview_rps_max_freq and valleyview_rps_min_freq to get the frequency. Use that for i915_cur_delayinfo. Signed-off-by: Chon Ming Lee Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9770c2f81196..6889d81dc559 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -972,11 +972,11 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); - val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1); + val = valleyview_rps_max_freq(dev_priv); seq_printf(m, "max GPU freq: %d MHz\n", vlv_gpu_freq(dev_priv, val)); - val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM); + val = valleyview_rps_min_freq(dev_priv); seq_printf(m, "min GPU freq: %d MHz\n", vlv_gpu_freq(dev_priv, val)); -- cgit v1.2.3 From 6917c7b9d9083272ddf7e64f5482e8820a31fb3c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Nov 2013 13:56:26 -0200 Subject: drm/i915: Initialise min/max frequencies before updating RPS registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RPS register writing routines use the current value of min/max to set certain limits and interrupt gating. If we set those afterwards, we risk setting up the hw incorrectly and losing power management events, and worse, trigger some internal assertions. Reorder the calling sequences to be correct, and remove the then unrequired clamping from inside set_rps(). And for a bonus, fix the bug of calling gen6_set_rps() from Valleyview. Signed-off-by: Chris Wilson Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä CC: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_sysfs.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_pm.c | 19 +++++-------------- 3 files changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6889d81dc559..b5df88fa890a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2756,7 +2756,7 @@ i915_max_freq_set(void *data, u64 val) if (IS_VALLEYVIEW(dev)) { val = vlv_freq_opcode(dev_priv, val); dev_priv->rps.max_delay = val; - gen6_set_rps(dev, val); + valleyview_set_rps(dev, val); } else { do_div(val, GT_FREQUENCY_MULTIPLIER); dev_priv->rps.max_delay = val; diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 85b98111d995..fdce8824723c 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -339,15 +339,15 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, DRM_DEBUG("User requested overclocking to %d\n", val * GT_FREQUENCY_MULTIPLIER); + dev_priv->rps.max_delay = val; + if (dev_priv->rps.cur_delay > val) { - if (IS_VALLEYVIEW(dev_priv->dev)) - valleyview_set_rps(dev_priv->dev, val); + if (IS_VALLEYVIEW(dev)) + valleyview_set_rps(dev, val); else - gen6_set_rps(dev_priv->dev, val); + gen6_set_rps(dev, val); } - dev_priv->rps.max_delay = val; - mutex_unlock(&dev_priv->rps.hw_lock); return count; @@ -408,15 +408,15 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, return -EINVAL; } + dev_priv->rps.min_delay = val; + if (dev_priv->rps.cur_delay < val) { if (IS_VALLEYVIEW(dev)) valleyview_set_rps(dev, val); else - gen6_set_rps(dev_priv->dev, val); + gen6_set_rps(dev, val); } - dev_priv->rps.min_delay = val; - mutex_unlock(&dev_priv->rps.hw_lock); return count; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 38943f8ef260..e37860377285 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3414,26 +3414,19 @@ static void ironlake_disable_drps(struct drm_device *dev) * ourselves, instead of doing a rmw cycle (which might result in us clearing * all limits and the gpu stuck at whatever frequency it is at atm). */ -static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) +static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val) { u32 limits; - limits = 0; - - if (*val >= dev_priv->rps.max_delay) - *val = dev_priv->rps.max_delay; - limits |= dev_priv->rps.max_delay << 24; - /* Only set the down limit when we've reached the lowest level to avoid * getting more interrupts, otherwise leave this clear. This prevents a * race in the hw when coming out of rc6: There's a tiny window where * the hw runs at the minimal clock before selecting the desired * frequency, if the down threshold expires in that window we will not * receive a down interrupt. */ - if (*val <= dev_priv->rps.min_delay) { - *val = dev_priv->rps.min_delay; + limits = dev_priv->rps.max_delay << 24; + if (val <= dev_priv->rps.min_delay) limits |= dev_priv->rps.min_delay << 16; - } return limits; } @@ -3533,7 +3526,6 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) void gen6_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 limits = gen6_rps_limits(dev_priv, &val); WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(val > dev_priv->rps.max_delay); @@ -3556,7 +3548,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val) /* Make sure we continue to get interrupts * until we hit the minimum or maximum frequencies. */ - I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + gen6_rps_limits(dev_priv, val)); POSTING_READ(GEN6_RPNSWREQ); @@ -3620,8 +3613,6 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; - gen6_rps_limits(dev_priv, &val); - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(val > dev_priv->rps.max_delay); WARN_ON(val < dev_priv->rps.min_delay); -- cgit v1.2.3 From 4c7915616a7a09be0c1e5b76c26381df15fe671b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2013 19:57:48 +0200 Subject: drm/i915: Kill vlv_update_rps_cur_delay() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Polling to make sure the current GPU frequency matches the last requested frequency should not be necessay, and if there's some throttling involved, the two might not match anyway. Since we're still seeing this trigger occasionally, and it just introduces a rather pointless 10 ms delay, it seems like better to kill it off. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e37860377285..542b4448ccb7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3584,31 +3584,6 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->rps.hw_lock); } -/* - * Wait until the previous freq change has completed, - * or the timeout elapsed, and then update our notion - * of the current GPU frequency. - */ -static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv) -{ - u32 pval; - - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); - - if (wait_for(((pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) & GENFREQSTATUS) == 0, 10)) - DRM_DEBUG_DRIVER("timed out waiting for Punit\n"); - - pval >>= 8; - - if (pval != dev_priv->rps.cur_delay) - DRM_DEBUG_DRIVER("Punit overrode GPU freq: %d MHz (%u) requested, but got %d Mhz (%u)\n", - vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), - dev_priv->rps.cur_delay, - vlv_gpu_freq(dev_priv, pval), pval); - - dev_priv->rps.cur_delay = pval; -} - void valleyview_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3617,8 +3592,6 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) WARN_ON(val > dev_priv->rps.max_delay); WARN_ON(val < dev_priv->rps.min_delay); - vlv_update_rps_cur_delay(dev_priv); - DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n", vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), dev_priv->rps.cur_delay, -- cgit v1.2.3 From 1272e7b854e768ede5279de57b78a54cb39f5da5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2013 19:57:49 +0200 Subject: drm/i915: Use clamp_t() when limiting cur_delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the cur_delay limiting code a bit less prone to typo errors by using clamp_t(). Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c6176f337452..e14285bafbd4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -966,10 +966,8 @@ static void gen6_pm_rps_work(struct work_struct *work) /* sysfs frequency interfaces may have snuck in while servicing the * interrupt */ - if (new_delay < (int)dev_priv->rps.min_delay) - new_delay = dev_priv->rps.min_delay; - if (new_delay > (int)dev_priv->rps.max_delay) - new_delay = dev_priv->rps.max_delay; + new_delay = clamp_t(int, new_delay, + dev_priv->rps.min_delay, dev_priv->rps.max_delay); dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay; if (IS_VALLEYVIEW(dev_priv->dev)) -- cgit v1.2.3 From 6f1f56ea43223dd80e238564d31bbc31c65234dd Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 4 Nov 2013 09:18:16 -0800 Subject: ath10k: Fix un-initialized debug objects. If the 'ar' registration fails early, the debug objects were not initialized, and trouble ensued when the object was later destroyed and the un-initialized objects were accessed. Per Kalle's suggestion, move the debug_destroy to the core_unregister method. Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2a360cac4cee..7d8687694360 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -738,8 +738,6 @@ EXPORT_SYMBOL(ath10k_core_create); void ath10k_core_destroy(struct ath10k *ar) { - ath10k_debug_destroy(ar); - flush_workqueue(ar->workqueue); destroy_workqueue(ar->workqueue); @@ -986,6 +984,8 @@ void ath10k_core_unregister(struct ath10k *ar) ath10k_mac_unregister(ar); ath10k_core_free_firmware_files(ar); + + ath10k_debug_destroy(ar); } EXPORT_SYMBOL(ath10k_core_unregister); -- cgit v1.2.3 From ab3c759a0461528fcfab155b97da69edbc24b5d0 Mon Sep 17 00:00:00 2001 From: Chon Ming Lee Date: Thu, 7 Nov 2013 10:43:30 +0800 Subject: drm/i915/vlv: Rename VLV DPIO register to be more structure to match configdb document. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some VLV PHY/PLL DPIO registers have group/lane/channel access. Current DPIO register definition doesn't have a structure way to break them down. As a result it is not easy to match the PHY/PLL registers with the configdb document. Rename those registers based on the configdb for easy cross references, and without the need to check the offset in the header file. New format is as following. __DW_ For example, VLV_PCS_DW0 - Group access to PCS for lane 0 to 3 for PCS DWORD 0. VLV_PCS01_DW0_CH0 - PCS access to lane 0/1, channel 0 for PCS DWORD 0. Another example is VLV_TX_DW0 - Group access to TX lane 0 to 3 for TX DWORD 0 VLV_TX0_DW0 - Refer to TX Lane 0 access only for TX DWORD 0. There is no functional change on this patch. v2: Rebase based on previous patch change. v3: There may be configdb different version that document the start DW differently. Add a comment to clarify. Fix up some mismatch start DW for second PLL block. (Ville) Suggested-by: Ville Syrjälä Signed-off-by: Chon Ming Lee Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 40 ++++---- drivers/gpu/drm/i915/i915_reg.h | 191 +++++++++++++++++------------------ drivers/gpu/drm/i915/intel_display.c | 48 ++++----- drivers/gpu/drm/i915/intel_dp.c | 32 +++--- drivers/gpu/drm/i915/intel_hdmi.c | 54 ++++------ 5 files changed, 172 insertions(+), 193 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b5df88fa890a..1dbcc64f9ddb 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1649,28 +1649,28 @@ static int i915_dpio_info(struct seq_file *m, void *data) seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL)); - seq_printf(m, "DPIO_DIV_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_A)); - seq_printf(m, "DPIO_DIV_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B)); - - seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A)); - seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B)); - - seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_A)); - seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_B)); - - seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_A)); - seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_B)); + seq_printf(m, "DPIO PLL DW3 CH0 : 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(0))); + seq_printf(m, "DPIO PLL DW3 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(1))); + + seq_printf(m, "DPIO PLL DW5 CH0: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(0))); + seq_printf(m, "DPIO PLL DW5 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(1))); + + seq_printf(m, "DPIO PLL DW7 CH0: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(0))); + seq_printf(m, "DPIO PLL DW7 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(1))); + + seq_printf(m, "DPIO PLL DW10 CH0: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(0))); + seq_printf(m, "DPIO PLL DW10 CH1: 0x%08x\n", + vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(1))); seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE)); + vlv_dpio_read(dev_priv, PIPE_A, VLV_CMN_DW0)); mutex_unlock(&dev_priv->dpio_lock); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 86a1ad86aa7b..29265638bf56 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -452,15 +452,10 @@ #define DPIO_SFR_BYPASS (1<<1) #define DPIO_CMNRST (1<<0) -#define _DPIO_TX3_SWING_CTL4_A 0x690 -#define _DPIO_TX3_SWING_CTL4_B 0x2a90 -#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \ - _DPIO_TX3_SWING_CTL4_B) - /* * Per pipe/PLL DPIO regs */ -#define _DPIO_DIV_A 0x800c +#define _VLV_PLL_DW3_CH0 0x800c #define DPIO_POST_DIV_SHIFT (28) /* 3 bits */ #define DPIO_POST_DIV_DAC 0 #define DPIO_POST_DIV_HDMIDP 1 /* DAC 225-400M rate */ @@ -473,10 +468,10 @@ #define DPIO_ENABLE_CALIBRATION (1<<11) #define DPIO_M1DIV_SHIFT (8) /* 3 bits */ #define DPIO_M2DIV_MASK 0xff -#define _DPIO_DIV_B 0x802c -#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B) +#define _VLV_PLL_DW3_CH1 0x802c +#define VLV_PLL_DW3(ch) _PIPE(ch, _VLV_PLL_DW3_CH0, _VLV_PLL_DW3_CH1) -#define _DPIO_REFSFR_A 0x8014 +#define _VLV_PLL_DW5_CH0 0x8014 #define DPIO_REFSEL_OVERRIDE 27 #define DPIO_PLL_MODESEL_SHIFT 24 /* 3 bits */ #define DPIO_BIAS_CURRENT_CTL_SHIFT 21 /* 3 bits, always 0x7 */ @@ -484,118 +479,112 @@ #define DPIO_PLL_REFCLK_SEL_MASK 3 #define DPIO_DRIVER_CTL_SHIFT 12 /* always set to 0x8 */ #define DPIO_CLK_BIAS_CTL_SHIFT 8 /* always set to 0x5 */ -#define _DPIO_REFSFR_B 0x8034 -#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B) +#define _VLV_PLL_DW5_CH1 0x8034 +#define VLV_PLL_DW5(ch) _PIPE(ch, _VLV_PLL_DW5_CH0, _VLV_PLL_DW5_CH1) -#define _DPIO_CORE_CLK_A 0x801c -#define _DPIO_CORE_CLK_B 0x803c -#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B) +#define _VLV_PLL_DW7_CH0 0x801c +#define _VLV_PLL_DW7_CH1 0x803c +#define VLV_PLL_DW7(ch) _PIPE(ch, _VLV_PLL_DW7_CH0, _VLV_PLL_DW7_CH1) -#define _DPIO_IREF_CTL_A 0x8040 -#define _DPIO_IREF_CTL_B 0x8060 -#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B) +#define _VLV_PLL_DW8_CH0 0x8040 +#define _VLV_PLL_DW8_CH1 0x8060 +#define VLV_PLL_DW8(ch) _PIPE(ch, _VLV_PLL_DW8_CH0, _VLV_PLL_DW8_CH1) -#define DPIO_IREF_BCAST 0xc044 -#define _DPIO_IREF_A 0x8044 -#define _DPIO_IREF_B 0x8064 -#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B) +#define VLV_PLL_DW9_BCAST 0xc044 +#define _VLV_PLL_DW9_CH0 0x8044 +#define _VLV_PLL_DW9_CH1 0x8064 +#define VLV_PLL_DW9(ch) _PIPE(ch, _VLV_PLL_DW9_CH0, _VLV_PLL_DW9_CH1) -#define _DPIO_PLL_CML_A 0x804c -#define _DPIO_PLL_CML_B 0x806c -#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B) +#define _VLV_PLL_DW10_CH0 0x8048 +#define _VLV_PLL_DW10_CH1 0x8068 +#define VLV_PLL_DW10(ch) _PIPE(ch, _VLV_PLL_DW10_CH0, _VLV_PLL_DW10_CH1) -#define _DPIO_LPF_COEFF_A 0x8048 -#define _DPIO_LPF_COEFF_B 0x8068 -#define DPIO_LPF_COEFF(pipe) _PIPE(pipe, _DPIO_LPF_COEFF_A, _DPIO_LPF_COEFF_B) +#define _VLV_PLL_DW11_CH0 0x804c +#define _VLV_PLL_DW11_CH1 0x806c +#define VLV_PLL_DW11(ch) _PIPE(ch, _VLV_PLL_DW11_CH0, _VLV_PLL_DW11_CH1) -#define DPIO_CALIBRATION 0x80ac +/* Spec for ref block start counts at DW10 */ +#define VLV_REF_DW13 0x80ac -#define DPIO_FASTCLK_DISABLE 0x8100 +#define VLV_CMN_DW0 0x8100 /* * Per DDI channel DPIO regs */ -#define _DPIO_PCS_TX_0 0x8200 -#define _DPIO_PCS_TX_1 0x8400 +#define _VLV_PCS_DW0_CH0 0x8200 +#define _VLV_PCS_DW0_CH1 0x8400 #define DPIO_PCS_TX_LANE2_RESET (1<<16) #define DPIO_PCS_TX_LANE1_RESET (1<<7) -#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1) +#define VLV_PCS_DW0(ch) _PORT(ch, _VLV_PCS_DW0_CH0, _VLV_PCS_DW0_CH1) -#define _DPIO_PCS_CLK_0 0x8204 -#define _DPIO_PCS_CLK_1 0x8404 +#define _VLV_PCS_DW1_CH0 0x8204 +#define _VLV_PCS_DW1_CH1 0x8404 #define DPIO_PCS_CLK_CRI_RXEB_EIOS_EN (1<<22) #define DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21) #define DPIO_PCS_CLK_DATAWIDTH_SHIFT (6) #define DPIO_PCS_CLK_SOFT_RESET (1<<5) -#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1) - -#define _DPIO_PCS_CTL_OVR1_A 0x8224 -#define _DPIO_PCS_CTL_OVR1_B 0x8424 -#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \ - _DPIO_PCS_CTL_OVR1_B) - -#define _DPIO_PCS_STAGGER0_A 0x822c -#define _DPIO_PCS_STAGGER0_B 0x842c -#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \ - _DPIO_PCS_STAGGER0_B) - -#define _DPIO_PCS_STAGGER1_A 0x8230 -#define _DPIO_PCS_STAGGER1_B 0x8430 -#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \ - _DPIO_PCS_STAGGER1_B) - -#define _DPIO_PCS_CLOCKBUF0_A 0x8238 -#define _DPIO_PCS_CLOCKBUF0_B 0x8438 -#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \ - _DPIO_PCS_CLOCKBUF0_B) - -#define _DPIO_PCS_CLOCKBUF8_A 0x825c -#define _DPIO_PCS_CLOCKBUF8_B 0x845c -#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \ - _DPIO_PCS_CLOCKBUF8_B) - -#define _DPIO_TX_SWING_CTL2_A 0x8288 -#define _DPIO_TX_SWING_CTL2_B 0x8488 -#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \ - _DPIO_TX_SWING_CTL2_B) - -#define _DPIO_TX_SWING_CTL3_A 0x828c -#define _DPIO_TX_SWING_CTL3_B 0x848c -#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \ - _DPIO_TX_SWING_CTL3_B) - -#define _DPIO_TX_SWING_CTL4_A 0x8290 -#define _DPIO_TX_SWING_CTL4_B 0x8490 -#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \ - _DPIO_TX_SWING_CTL4_B) - -#define _DPIO_TX_OCALINIT_0 0x8294 -#define _DPIO_TX_OCALINIT_1 0x8494 +#define VLV_PCS_DW1(ch) _PORT(ch, _VLV_PCS_DW1_CH0, _VLV_PCS_DW1_CH1) + +#define _VLV_PCS_DW8_CH0 0x8220 +#define _VLV_PCS_DW8_CH1 0x8420 +#define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1) + +#define _VLV_PCS01_DW8_CH0 0x0220 +#define _VLV_PCS23_DW8_CH0 0x0420 +#define _VLV_PCS01_DW8_CH1 0x2620 +#define _VLV_PCS23_DW8_CH1 0x2820 +#define VLV_PCS01_DW8(port) _PORT(port, _VLV_PCS01_DW8_CH0, _VLV_PCS01_DW8_CH1) +#define VLV_PCS23_DW8(port) _PORT(port, _VLV_PCS23_DW8_CH0, _VLV_PCS23_DW8_CH1) + +#define _VLV_PCS_DW9_CH0 0x8224 +#define _VLV_PCS_DW9_CH1 0x8424 +#define VLV_PCS_DW9(ch) _PORT(ch, _VLV_PCS_DW9_CH0, _VLV_PCS_DW9_CH1) + +#define _VLV_PCS_DW11_CH0 0x822c +#define _VLV_PCS_DW11_CH1 0x842c +#define VLV_PCS_DW11(ch) _PORT(ch, _VLV_PCS_DW11_CH0, _VLV_PCS_DW11_CH1) + +#define _VLV_PCS_DW12_CH0 0x8230 +#define _VLV_PCS_DW12_CH1 0x8430 +#define VLV_PCS_DW12(ch) _PORT(ch, _VLV_PCS_DW12_CH0, _VLV_PCS_DW12_CH1) + +#define _VLV_PCS_DW14_CH0 0x8238 +#define _VLV_PCS_DW14_CH1 0x8438 +#define VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1) + +#define _VLV_PCS_DW23_CH0 0x825c +#define _VLV_PCS_DW23_CH1 0x845c +#define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1) + +#define _VLV_TX_DW2_CH0 0x8288 +#define _VLV_TX_DW2_CH1 0x8488 +#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1) + +#define _VLV_TX_DW3_CH0 0x828c +#define _VLV_TX_DW3_CH1 0x848c +#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1) + +#define _VLV_TX_DW4_CH0 0x8290 +#define _VLV_TX_DW4_CH1 0x8490 +#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1) + +#define _VLV_TX3_DW4_CH0 0x690 +#define _VLV_TX3_DW4_CH1 0x2a90 +#define VLV_TX3_DW4(ch) _PORT(ch, _VLV_TX3_DW4_CH0, _VLV_TX3_DW4_CH1) + +#define _VLV_TX_DW5_CH0 0x8294 +#define _VLV_TX_DW5_CH1 0x8494 #define DPIO_TX_OCALINIT_EN (1<<31) -#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \ - _DPIO_TX_OCALINIT_1) - -#define _DPIO_TX_CTL_0 0x82ac -#define _DPIO_TX_CTL_1 0x84ac -#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1) - -#define _DPIO_TX_LANE_0 0x82b8 -#define _DPIO_TX_LANE_1 0x84b8 -#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1) - -#define _DPIO_DATA_CHANNEL1 0x8220 -#define _DPIO_DATA_CHANNEL2 0x8420 -#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2) - -#define _DPIO_PORT0_PCS0 0x0220 -#define _DPIO_PORT0_PCS1 0x0420 -#define _DPIO_PORT1_PCS2 0x2620 -#define _DPIO_PORT1_PCS3 0x2820 -#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2) -#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3) -#define DPIO_DATA_CHANNEL1 0x8220 -#define DPIO_DATA_CHANNEL2 0x8420 +#define VLV_TX_DW5(ch) _PORT(ch, _VLV_TX_DW5_CH0, _VLV_TX_DW5_CH1) + +#define _VLV_TX_DW11_CH0 0x82ac +#define _VLV_TX_DW11_CH1 0x84ac +#define VLV_TX_DW11(ch) _PORT(ch, _VLV_TX_DW11_CH0, _VLV_TX_DW11_CH1) + +#define _VLV_TX_DW14_CH0 0x82b8 +#define _VLV_TX_DW14_CH1 0x84b8 +#define VLV_TX_DW14(ch) _PORT(ch, _VLV_TX_DW14_CH0, _VLV_TX_DW14_CH1) /* * Fence registers diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0980bd95e372..abf509ce5e26 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4786,24 +4786,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1)); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); reg_val &= 0xffffff00; reg_val |= 0x00000030; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); reg_val &= 0x8cffffff; reg_val = 0x8c000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1)); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); reg_val &= 0xffffff00; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); reg_val &= 0x00ffffff; reg_val |= 0xb0000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); } static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc, @@ -4872,15 +4872,15 @@ static void vlv_update_pll(struct intel_crtc *crtc) vlv_pllb_recal_opamp(dev_priv, pipe); /* Set up Tx target for periodic Rcomp update */ - vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f); /* Disable target IRef on PLL */ - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe)); + reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe)); reg_val &= 0x00ffffff; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val); /* Disable fast lock */ - vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610); + vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610); /* Set idtafcrecal before PLL is enabled */ mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); @@ -4894,48 +4894,48 @@ static void vlv_update_pll(struct intel_crtc *crtc) * Note: don't use the DAC post divider as it seems unstable. */ mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); - vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); mdiv |= DPIO_ENABLE_CALIBRATION; - vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); /* Set HBR and RBR LPF coefficients */ if (crtc->config.port_clock == 162000 || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) - vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), 0x009f0003); else - vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), 0x00d0000f); if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { /* Use SSC source */ if (!pipe) - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df40000); else - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (!pipe) - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df70000); else - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), 0x0df40000); } - coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe)); + coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) coreclk |= 0x01000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CORE_CLK(pipe), coreclk); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk); - vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000); + vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000); /* Enable DPIO clock input */ dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | @@ -5413,7 +5413,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc, int refclk = 100000; mutex_lock(&dev_priv->dpio_lock); - mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe)); + mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe)); mutex_unlock(&dev_priv->dpio_lock); clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7619eae35b25..2584eb4bbf0b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1846,16 +1846,16 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) mutex_lock(&dev_priv->dpio_lock); - val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), 0x00760018); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), 0x00400888); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); mutex_unlock(&dev_priv->dpio_lock); @@ -1881,19 +1881,19 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<dpio_lock); } @@ -2110,14 +2110,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) } mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x00000000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), demph_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), uniqtranscale_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), 0x0C782040); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x80000000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0C782040); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000); mutex_unlock(&dev_priv->dpio_lock); return 0; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 51a8336dec2e..5b9143fc9b5a 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1090,36 +1090,28 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) /* Enable clock channels for this port */ mutex_lock(&dev_priv->dpio_lock); - val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val); /* HDMI 1.0V-2dB */ - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), - 0x2b245f5f); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), - 0x5578b83a); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), - 0x0c782040); - vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port), - 0x2b247878); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), - 0x00002000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), - DPIO_TX_OCALINIT_EN); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), 0x2b245f5f); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 0x5578b83a); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0c782040); + vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), 0x2b247878); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000); + vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN); /* Program lane clock */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), - 0x00760018); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), - 0x00400888); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); mutex_unlock(&dev_priv->dpio_lock); intel_enable_hdmi(encoder); @@ -1142,24 +1134,22 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<dpio_lock); } @@ -1174,8 +1164,8 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder) /* Reset lanes to avoid HDMI flicker (VLV w/a) */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000); + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060); mutex_unlock(&dev_priv->dpio_lock); } -- cgit v1.2.3 From 00fe639a56b40930bf27eabeef9a826344d8f4c4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 Nov 2013 14:00:08 +0200 Subject: drm/i915: Make AGP support optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only depend on the intel-gtt module for GTT frobbign on older gens. The intel_agp module is optional, except for UMS and some old XvMC userland on gen3. So make AGP support optional. As before, we will fail the i915 init for UMS and gen3 KMS the same as before if intel_agp isn't around. intel-gtt.c is left with a somewhat ugly ifdef mess, but I'm going to save that for a later cleaning. At least my gen2 still works with the patch and CONFIG_AGP=n. v2: Make i915 depend on X86 and PCI, and intel-gtt depend on PCI Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/char/Makefile | 2 +- drivers/char/agp/Kconfig | 5 +++++ drivers/char/agp/Makefile | 2 +- drivers/char/agp/intel-gtt.c | 18 ++++++++++++++++++ drivers/gpu/drm/i915/Kconfig | 6 ++++-- drivers/gpu/drm/i915/i915_drv.c | 4 ++++ 6 files changed, 33 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 7ff1d0d208a7..2d68054f9795 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -50,7 +50,7 @@ obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o obj-$(CONFIG_MWAVE) += mwave/ -obj-$(CONFIG_AGP) += agp/ +obj-y += agp/ obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index d8b1b576556c..c528f96ee204 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -68,6 +68,7 @@ config AGP_AMD64 config AGP_INTEL tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support" depends on AGP && X86 + select INTEL_GTT help This option gives you AGP support for the GLX component of X on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875, @@ -155,3 +156,7 @@ config AGP_SGI_TIOCA This option gives you AGP GART support for the SGI TIO chipset for IA64 processors. +config INTEL_GTT + tristate + depends on X86 && PCI + diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile index 8eb56e273e75..604489bcdbf9 100644 --- a/drivers/char/agp/Makefile +++ b/drivers/char/agp/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_PARISC) += parisc-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o obj-$(CONFIG_AGP_INTEL) += intel-agp.o -obj-$(CONFIG_AGP_INTEL) += intel-gtt.o +obj-$(CONFIG_INTEL_GTT) += intel-gtt.o obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o obj-$(CONFIG_AGP_SIS) += sis-agp.o diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index b8e2014cb9cb..078968d8d07d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -94,6 +94,7 @@ static struct _intel_private { #define IS_IRONLAKE intel_private.driver->is_ironlake #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, struct sg_table *st) @@ -168,6 +169,7 @@ static void i8xx_destroy_pages(struct page *page) __free_pages(page, 2); atomic_dec(&agp_bridge->current_memory_agp); } +#endif #define I810_GTT_ORDER 4 static int i810_setup(void) @@ -209,6 +211,7 @@ static void i810_cleanup(void) free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER); } +#if IS_ENABLED(CONFIG_AGP_INTEL) static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -289,6 +292,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr) } kfree(curr); } +#endif static int intel_gtt_setup_scratch_page(void) { @@ -647,7 +651,9 @@ static int intel_gtt_init(void) return -ENOMEM; } +#if IS_ENABLED(CONFIG_AGP_INTEL) global_cache_flush(); /* FIXME: ? */ +#endif intel_private.stolen_size = intel_gtt_stolen_size(); @@ -671,6 +677,7 @@ static int intel_gtt_init(void) return 0; } +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_fake_agp_fetch_size(void) { int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); @@ -689,6 +696,7 @@ static int intel_fake_agp_fetch_size(void) return 0; } +#endif static void i830_cleanup(void) { @@ -801,6 +809,7 @@ static int i830_setup(void) return 0; } +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge) { agp_bridge->gatt_table_real = NULL; @@ -825,6 +834,7 @@ static int intel_fake_agp_configure(void) return 0; } +#endif static bool i830_check_flags(unsigned int flags) { @@ -863,6 +873,7 @@ void intel_gtt_insert_sg_entries(struct sg_table *st, } EXPORT_SYMBOL(intel_gtt_insert_sg_entries); +#if IS_ENABLED(CONFIG_AGP_INTEL) static void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, struct page **pages, @@ -928,6 +939,7 @@ out_err: mem->is_flushed = true; return ret; } +#endif void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) { @@ -941,6 +953,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) } EXPORT_SYMBOL(intel_gtt_clear_range); +#if IS_ENABLED(CONFIG_AGP_INTEL) static int intel_fake_agp_remove_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -982,6 +995,7 @@ static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, /* always return NULL for other allocation types for now */ return NULL; } +#endif static int intel_alloc_chipset_flush_resource(void) { @@ -1138,6 +1152,7 @@ static int i9xx_setup(void) return 0; } +#if IS_ENABLED(CONFIG_AGP_INTEL) static const struct agp_bridge_driver intel_fake_agp_driver = { .owner = THIS_MODULE, .size_type = FIXED_APER_SIZE, @@ -1159,6 +1174,7 @@ static const struct agp_bridge_driver intel_fake_agp_driver = { .agp_destroy_page = agp_generic_destroy_page, .agp_destroy_pages = agp_generic_destroy_pages, }; +#endif static const struct intel_gtt_driver i81x_gtt_driver = { .gen = 1, @@ -1376,11 +1392,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, intel_private.refcount++; +#if IS_ENABLED(CONFIG_AGP_INTEL) if (bridge) { bridge->driver = &intel_fake_agp_driver; bridge->dev_private_data = &intel_private; bridge->dev = bridge_pdev; } +#endif intel_private.bridge_dev = pci_dev_get(bridge_pdev); diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 6199d0b5b958..b0f61679c598 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -1,8 +1,10 @@ config DRM_I915 tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" depends on DRM - depends on AGP - depends on AGP_INTEL + depends on X86 && PCI + depends on (AGP || AGP=n) + select INTEL_GTT + select AGP_INTEL if AGP # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs select SHMEM diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 65447572b129..38a344694e35 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -155,7 +155,11 @@ MODULE_PARM_DESC(prefault_disable, "Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only."); static struct drm_driver driver; +#if IS_ENABLED(CONFIG_AGP_INTEL) extern int intel_agp_enabled; +#else +static int intel_agp_enabled; +#endif static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, -- cgit v1.2.3 From f227c1325948859c63678c6f9f448d72a8208d8a Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 2 Nov 2013 19:44:00 +0000 Subject: iio: Drop scan_type from viperboard adc driver the driver does not support buffering, hence scan_type is not needed Signed-off-by: Peter Meerwald Cc: Lars Poeschel Signed-off-by: Jonathan Cameron --- drivers/iio/adc/viperboard_adc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c index 09727a71e9fa..ee695e50cfa3 100644 --- a/drivers/iio/adc/viperboard_adc.c +++ b/drivers/iio/adc/viperboard_adc.c @@ -42,12 +42,6 @@ struct vprbrd_adc { .indexed = 1, \ .channel = _index, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .scan_index = _index, \ - .scan_type = { \ - .sign = 'u', \ - .realbits = 8, \ - .storagebits = 8, \ - }, \ } static struct iio_chan_spec const vprbrd_adc_iio_channels[] = { @@ -73,7 +67,7 @@ static int vprbrd_iio_read_raw(struct iio_dev *iio_dev, mutex_lock(&vb->lock); admsg->cmd = VPRBRD_ADC_CMD_GET; - admsg->chan = chan->scan_index; + admsg->chan = chan->channel; admsg->val = 0x00; ret = usb_control_msg(vb->usb_dev, -- cgit v1.2.3 From 2461fc9f3f45828eee23dd5018e7b5576aceec80 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 6 Nov 2013 00:11:00 +0000 Subject: iio: hid-sensors: magnetometer : Add sensitivity A number of Properties that can be applied to Data Fields are per data field basis or for all data fields. Adding sensitivity field for all magnetometer fields, which is most commonly used in currently available sensor hubs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/hid-sensor-magn-3d.c | 12 ++++++++++++ include/linux/hid-sensor-ids.h | 1 + 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index 2634920562fb..67fce1916d21 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -263,6 +263,18 @@ static int magn_3d_parse_report(struct platform_device *pdev, st->magn[1].index, st->magn[1].report_id, st->magn[2].index, st->magn[2].report_id); + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_ORIENTATION, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } + return ret; } diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 8d45e0290c91..4cc165887b09 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -42,6 +42,7 @@ /* ORIENTATION: Compass 3D: (200083) */ #define HID_USAGE_SENSOR_COMPASS_3D 0x200083 +#define HID_USAGE_SENSOR_DATA_ORIENTATION 0x200470 #define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING 0x200471 #define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING_X 0x200472 #define HID_USAGE_SENSOR_ORIENT_MAGN_HEADING_Y 0x200473 -- cgit v1.2.3 From 107f3198fd2c5902b9cc54c86a0c86f815c173e2 Mon Sep 17 00:00:00 2001 From: Emilio López Date: Sat, 14 Sep 2013 21:37:59 -0300 Subject: clk: composite: .determine_rate support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds .determine_rate support to the composite clock. It will use the .determine_rate callback from the rate component if available, and fall back on the mux component otherwise. This allows composite clocks to enjoy the benefits of automatic clock reparenting. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard --- drivers/clk/clk-composite.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index a33f46f20a41..753d0b784762 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -55,6 +55,30 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, return rate_ops->recalc_rate(rate_hw, parent_rate); } +static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_p) +{ + struct clk_composite *composite = to_clk_composite(hw); + const struct clk_ops *rate_ops = composite->rate_ops; + const struct clk_ops *mux_ops = composite->mux_ops; + struct clk_hw *rate_hw = composite->rate_hw; + struct clk_hw *mux_hw = composite->mux_hw; + + if (rate_hw && rate_ops && rate_ops->determine_rate) { + rate_hw->clk = hw->clk; + return rate_ops->determine_rate(rate_hw, rate, best_parent_rate, + best_parent_p); + } else if (mux_hw && mux_ops && mux_ops->determine_rate) { + mux_hw->clk = hw->clk; + return mux_ops->determine_rate(rate_hw, rate, best_parent_rate, + best_parent_p); + } else { + pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n"); + return 0; + } +} + static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { @@ -147,6 +171,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, composite->mux_ops = mux_ops; clk_composite_ops->get_parent = clk_composite_get_parent; clk_composite_ops->set_parent = clk_composite_set_parent; + if (mux_ops->determine_rate) + clk_composite_ops->determine_rate = clk_composite_determine_rate; } if (rate_hw && rate_ops) { @@ -170,6 +196,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, composite->rate_hw = rate_hw; composite->rate_ops = rate_ops; clk_composite_ops->recalc_rate = clk_composite_recalc_rate; + if (rate_ops->determine_rate) + clk_composite_ops->determine_rate = clk_composite_determine_rate; } if (gate_hw && gate_ops) { -- cgit v1.2.3 From c518e84c76e12e12a2a3404a293b2465af9be5f8 Mon Sep 17 00:00:00 2001 From: Emilio López Date: Fri, 20 Sep 2013 22:03:10 -0300 Subject: clk: sunxi: factors: fix off-by-one masks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous code would generate one bit too long masks, and was needlessly complicated. This patch replaces it by simpler code that can generate the masks correctly. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 88523f91d9b7..5687ac9bd85a 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -40,7 +40,7 @@ struct clk_factors { #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) -#define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) +#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) #define CLRMASK(len, pos) (~(SETMASK(len, pos))) #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) -- cgit v1.2.3 From 12ef06afb3959e7f6f2ae8917c4750883a3e8c14 Mon Sep 17 00:00:00 2001 From: Emilio López Date: Fri, 20 Sep 2013 22:03:11 -0300 Subject: clk: sunxi: factors: clear variables before using them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Random bits may get into our factors if we don't clear n, k, m and p. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 5687ac9bd85a..f05207a27e5f 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -88,7 +88,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - u8 n, k, m, p; + u8 n = 0, k = 0, m = 0, p = 0; u32 reg; struct clk_factors *factors = to_clk_factors(hw); struct clk_factors_config *config = factors->config; -- cgit v1.2.3 From 8e6a4c40bb6f3866548811f9f3882a627293fc2f Mon Sep 17 00:00:00 2001 From: Emilio López Date: Fri, 20 Sep 2013 22:03:12 -0300 Subject: clk: sunxi: protect core clocks from accidental shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some important clocks may get disabled as a side effect of another clock being disabled, because they have no consumers. This patch implements a mechanism so those clocks can be claimed by the driver and therefore remain enabled at all times. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sunxi.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 34ee69f4d50c..83d3eace3ebc 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -617,6 +617,31 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat } } +/** + * System clock protection + * + * By enabling these critical clocks, we prevent their accidental gating + * by the framework + */ +static void __init sunxi_clock_protect(void) +{ + struct clk *clk; + + /* memory bus clock - sun5i+ */ + clk = clk_get(NULL, "mbus"); + if (!IS_ERR(clk)) { + clk_prepare_enable(clk); + clk_put(clk); + } + + /* DDR clock - sun4i+ */ + clk = clk_get(NULL, "pll5_ddr"); + if (!IS_ERR(clk)) { + clk_prepare_enable(clk); + clk_put(clk); + } +} + void __init sunxi_init_clocks(void) { /* Register all the simple and basic clocks on DT */ @@ -633,4 +658,7 @@ void __init sunxi_init_clocks(void) /* Register gate clocks */ of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); + + /* Enable core system clocks */ + sunxi_clock_protect(); } -- cgit v1.2.3 From e71c69fc3362b88b09194d486dda6d721a8004f6 Mon Sep 17 00:00:00 2001 From: "Victor N. Ramos Mello" Date: Fri, 18 Oct 2013 20:27:51 -0300 Subject: drivers: clk: sunxi: Fix memory leakage in clk-sunxi.c Fix a possible memory leak in sun4i_osc_clk_setup(). Moved clock-frequency check to save superfluous allocation. Signed-off-by: Victor N. Ramos Mello Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sunxi.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 83d3eace3ebc..9665cb8d0238 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -38,18 +38,16 @@ static void __init sun4i_osc_clk_setup(struct device_node *node) const char *clk_name = node->name; u32 rate; + if (of_property_read_u32(node, "clock-frequency", &rate)) + return; + /* allocate fixed-rate and gate clock structs */ fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); if (!fixed) return; gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); - if (!gate) { - kfree(fixed); - return; - } - - if (of_property_read_u32(node, "clock-frequency", &rate)) - return; + if (!gate) + goto err_free_fixed; /* set up gate and fixed rate properties */ gate->reg = of_iomap(node, 0); @@ -64,10 +62,18 @@ static void __init sun4i_osc_clk_setup(struct device_node *node) &gate->hw, &clk_gate_ops, CLK_IS_ROOT); - if (!IS_ERR(clk)) { - of_clk_add_provider(node, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, clk_name, NULL); - } + if (IS_ERR(clk)) + goto err_free_gate; + + of_clk_add_provider(node, of_clk_src_simple_get, clk); + clk_register_clkdev(clk, clk_name, NULL); + + return; + +err_free_gate: + kfree(gate); +err_free_fixed: + kfree(fixed); } CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); -- cgit v1.2.3 From 547b5b2256a6d32ffb7f4f87af38f3dda207e694 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 30 Oct 2013 11:48:34 -0700 Subject: staging: ft1000: STATUS_ defines removed from ft1000_download.c Two files in the ft1000 usb driver ignore expected Linux error codes, and instead use two STATUS_SUCCESS 0, and STATUS_FAILURE 0x1001. This patch removes all remaining occurrences of these from the file ft1000_download.c. All occurrences of STATUS_SUCCESS have been replaced by 0, and occurrences of STATUS_FAILURE have been replaced by -1. One occurence of STATUS_FAILURE has been completely removed: get_handshake collects either a local #define or 0 from its helper function, check_usb_db, and immediately sets the collecting variable to STATUS_FAILURE if the #define is returned. check_usb_db has been modified to return -1 instead of the #define. Signed-off-by: Kelley Nielsen Suggested-by: Greg Kroah-Hartman Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- .../staging/ft1000/ft1000-usb/ft1000_download.c | 45 +++++++++++----------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index 68ded17c0f5c..b2643b780971 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -151,7 +151,7 @@ static int check_usb_db(struct ft1000_usb *ft1000dev) } } - return HANDSHAKE_MAG_TIMEOUT_VALUE; + return -1; } /* gets the handshake and compares it with the expected value */ @@ -172,9 +172,8 @@ static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value) ft1000dev->fcodeldr); ft1000dev->fcodeldr = 0; status = check_usb_db(ft1000dev); - if (status != STATUS_SUCCESS) { + if (status != 0) { DEBUG("get_handshake: check_usb_db failed\n"); - status = STATUS_FAILURE; break; } status = ft1000_write_register(ft1000dev, @@ -450,7 +449,7 @@ static int write_dpram32_and_check(struct ft1000_usb *ft1000dev, static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) { - int status = STATUS_SUCCESS; + int status = 0; u16 dpram; int loopcnt, i; u16 tempword; @@ -499,7 +498,7 @@ static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, } else { status = write_dpram32_and_check(ft1000dev, tempbuffer, dpram); - if (status != STATUS_SUCCESS) { + if (status != 0) { DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]); break; } @@ -523,7 +522,7 @@ static void usb_dnld_complete (struct urb *urb) static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) { - int Status = STATUS_SUCCESS; + int Status = 0; int byte_length; byte_length = word_length * 4; @@ -586,12 +585,12 @@ static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file, /*NdisMSleep (100); */ if (word_length > MAX_LENGTH) { DEBUG("FT1000:download:Download error: Max length exceeded\n"); - return STATUS_FAILURE; + return -1; } if ((word_length * 2 + (long)c_file) > (long)endpoint) { /* Error, beyond boot code range.*/ DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", (int)word_length); - return STATUS_FAILURE; + return -1; } if (word_length & 0x1) word_length++; @@ -615,7 +614,7 @@ static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file, int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, u32 FileLength) { - int status = STATUS_SUCCESS; + int status = 0; u32 state; u16 handshake; struct pseudo_hdr *pseudo_header; @@ -670,7 +669,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, loader_code_size = file_hdr->loader_code_size; correct_version = false; - while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) { + while ((status == 0) && (state != STATE_DONE_FILE)) { switch (state) { case STATE_START_DWNLD: status = scram_start_dwnld(ft1000dev, &handshake, @@ -717,7 +716,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, DEBUG ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n", request); - status = STATUS_FAILURE; + status = -1; break; } if (ft1000dev->usbboot) @@ -729,7 +728,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, } else { DEBUG ("FT1000:download:Download error: Handshake failed\n"); - status = STATUS_FAILURE; + status = -1; } break; @@ -773,7 +772,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, } else { DEBUG ("FT1000:download:Download error: Got Run address request before image offset request.\n"); - status = STATUS_FAILURE; + status = -1; break; } break; @@ -789,7 +788,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, } else { DEBUG ("FT1000:download:Download error: Got Size request before image offset request.\n"); - status = STATUS_FAILURE; + status = -1; break; } break; @@ -809,7 +808,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, if (!correct_version) { DEBUG ("FT1000:download:Download error: Got Code Segment request before image offset request.\n"); - status = STATUS_FAILURE; + status = -1; break; } @@ -948,7 +947,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, DEBUG ("FT1000:download:Download error: Bad Version Request = 0x%x.\n", (int)requested_version); - status = STATUS_FAILURE; + status = -1; break; } break; @@ -957,7 +956,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, DEBUG ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n", request); - status = STATUS_FAILURE; + status = -1; break; } if (ft1000dev->usbboot) @@ -969,7 +968,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, } else { DEBUG ("FT1000:download:Download error: Handshake failed\n"); - status = STATUS_FAILURE; + status = -1; } break; @@ -1026,14 +1025,14 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, } } else { kfree(pbuffer); - status = STATUS_FAILURE; + status = -1; } } else { - status = STATUS_FAILURE; + status = -1; } } else { /* Checksum did not compute */ - status = STATUS_FAILURE; + status = -1; } DEBUG ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n", @@ -1046,11 +1045,11 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, break; default: - status = STATUS_FAILURE; + status = -1; break; } /* End Switch */ - if (status != STATUS_SUCCESS) + if (status != 0) break; /**** -- cgit v1.2.3 From da3ab48bb8357729a780d63d5d5b8983fc91b769 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 30 Oct 2013 18:04:41 -0700 Subject: staging: ft1000: remove formal function headers from ft1000_hw.c The file ft1000_hw.c contains formal C99 style function headers that waste space and convey little to no useful information. This patch converts the headers to either one line standard /* */ style comments or shorter standard style headers with parameter lists (if the parameter list seemed helpful), or eliminates them entirely. Besides needing to be made of its own accord, this change is in preparation to eliminate the nonstandard STATUS_* #defines from the driver since they were cited in most of the headers. Signed-off-by: Kelley Nielsen Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 422 ++++---------------------- 1 file changed, 56 insertions(+), 366 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 0d4931b2c2e2..73b0c4fa59eb 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1,11 +1,9 @@ -//===================================================== -// CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. -// -// -// This file is part of Express Card USB Driver -// -// $Id: -//==================================================== +/* CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. +* +* +* This file is part of Express Card USB Driver +*/ + #include #include #include @@ -35,27 +33,17 @@ static u8 tempbuffer[1600]; #define MAX_RCV_LOOP 100 -//--------------------------------------------------------------------------- -// Function: ft1000_control -// -// Parameters: ft1000_usb - device structure -// pipe - usb control message pipe -// request - control request -// requesttype - control message request type -// value - value to be written or 0 -// index - register index -// data - data buffer to hold the read/write values -// size - data size -// timeout - control message time out value -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function sends a control message via USB interface synchronously -// -// Notes: -// -//--------------------------------------------------------------------------- +/* send a control message via USB interface synchronously +* Parameters: ft1000_usb - device structure +* pipe - usb control message pipe +* request - control request +* requesttype - control message request type +* value - value to be written or 0 +* index - register index +* data - data buffer to hold the read/write values +* size - data size +* timeout - control message time out value +*/ static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size, int timeout) @@ -76,22 +64,7 @@ static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe, return ret; } -//--------------------------------------------------------------------------- -// Function: ft1000_read_register -// -// Parameters: ft1000_usb - device structure -// Data - data buffer to hold the value read -// nRegIndex - register index -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function returns the value in a register -// -// Notes: -// -//--------------------------------------------------------------------------- - +/* returns the value in a register */ int ft1000_read_register(struct ft1000_usb *ft1000dev, u16* Data, u16 nRegIndx) { @@ -110,21 +83,7 @@ int ft1000_read_register(struct ft1000_usb *ft1000dev, u16* Data, return ret; } -//--------------------------------------------------------------------------- -// Function: ft1000_write_register -// -// Parameters: ft1000_usb - device structure -// value - value to write into a register -// nRegIndex - register index -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function writes the value in a register -// -// Notes: -// -//--------------------------------------------------------------------------- +/* writes the value in a register */ int ft1000_write_register(struct ft1000_usb *ft1000dev, u16 value, u16 nRegIndx) { @@ -143,23 +102,7 @@ int ft1000_write_register(struct ft1000_usb *ft1000dev, u16 value, return ret; } -//--------------------------------------------------------------------------- -// Function: ft1000_read_dpram32 -// -// Parameters: ft1000_usb - device structure -// indx - starting address to read -// buffer - data buffer to hold the data read -// cnt - number of byte read from DPRAM -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function read a number of bytes from DPRAM -// -// Notes: -// -//--------------------------------------------------------------------------- - +/* read a number of bytes from DPRAM */ int ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u16 cnt) { @@ -178,22 +121,7 @@ int ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, return ret; } -//--------------------------------------------------------------------------- -// Function: ft1000_write_dpram32 -// -// Parameters: ft1000_usb - device structure -// indx - starting address to write the data -// buffer - data buffer to write into DPRAM -// cnt - number of bytes to write -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function writes into DPRAM a number of bytes -// -// Notes: -// -//--------------------------------------------------------------------------- +/* writes into DPRAM a number of bytes */ int ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u16 cnt) { @@ -215,22 +143,7 @@ int ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, return ret; } -//--------------------------------------------------------------------------- -// Function: ft1000_read_dpram16 -// -// Parameters: ft1000_usb - device structure -// indx - starting address to read -// buffer - data buffer to hold the data read -// hightlow - high or low 16 bit word -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function read 16 bits from DPRAM -// -// Notes: -// -//--------------------------------------------------------------------------- +/* read 16 bits from DPRAM */ int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u8 highlow) { @@ -255,22 +168,7 @@ int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, return ret; } -//--------------------------------------------------------------------------- -// Function: ft1000_write_dpram16 -// -// Parameters: ft1000_usb - device structure -// indx - starting address to write the data -// value - 16bits value to write -// hightlow - high or low 16 bit word -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function writes into DPRAM a number of bytes -// -// Notes: -// -//--------------------------------------------------------------------------- +/* write into DPRAM a number of bytes */ int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value, u8 highlow) { int ret = STATUS_SUCCESS; @@ -294,22 +192,7 @@ int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value, u8 h return ret; } -//--------------------------------------------------------------------------- -// Function: fix_ft1000_read_dpram32 -// -// Parameters: ft1000_usb - device structure -// indx - starting address to read -// buffer - data buffer to hold the data read -// -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function read DPRAM 4 words at a time -// -// Notes: -// -//--------------------------------------------------------------------------- +/* read DPRAM 4 words at a time */ int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer) { @@ -338,22 +221,7 @@ int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, } -//--------------------------------------------------------------------------- -// Function: fix_ft1000_write_dpram32 -// -// Parameters: ft1000_usb - device structure -// indx - starting address to write -// buffer - data buffer to write -// -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function write to DPRAM 4 words at a time -// -// Notes: -// -//--------------------------------------------------------------------------- +/* Description: This function write to DPRAM 4 words at a time */ int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer) { u16 pos1; @@ -410,17 +278,7 @@ int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer) return ret; } - -//------------------------------------------------------------------------ -// -// Function: card_reset_dsp -// -// Synopsis: This function is called to reset or activate the DSP -// -// Arguments: value - reset or activate -// -// Returns: None -//----------------------------------------------------------------------- +/* reset or activate the DSP */ static void card_reset_dsp(struct ft1000_usb *ft1000dev, bool value) { u16 status = STATUS_SUCCESS; @@ -457,21 +315,11 @@ static void card_reset_dsp(struct ft1000_usb *ft1000dev, bool value) } } -//--------------------------------------------------------------------------- -// Function: card_send_command -// -// Parameters: ft1000_usb - device structure -// ptempbuffer - command buffer -// size - command buffer size -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function sends a command to ASIC -// -// Notes: -// -//--------------------------------------------------------------------------- +/* send a command to ASIC +* Parameters: ft1000_usb - device structure +* ptempbuffer - command buffer +* size - command buffer size +*/ void card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer, int size) { @@ -509,16 +357,7 @@ void card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer, } -//-------------------------------------------------------------------------- -// -// Function: dsp_reload -// -// Synopsis: This function is called to load or reload the DSP -// -// Arguments: ft1000dev - device structure -// -// Returns: None -//----------------------------------------------------------------------- +/* load or reload the DSP */ int dsp_reload(struct ft1000_usb *ft1000dev) { int status; @@ -569,17 +408,7 @@ int dsp_reload(struct ft1000_usb *ft1000dev) return 0; } -//--------------------------------------------------------------------------- -// -// Function: ft1000_reset_asic -// Description: This function will call the Card Service function to reset the -// ASIC. -// Input: -// dev - device structure -// Output: -// none -// -//--------------------------------------------------------------------------- +/* call the Card Service function to reset the ASIC. */ static void ft1000_reset_asic(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -607,18 +436,6 @@ static void ft1000_reset_asic(struct net_device *dev) DEBUG("ft1000_hw: interrupt status register = 0x%x\n", tempword); } - -//--------------------------------------------------------------------------- -// -// Function: ft1000_reset_card -// Description: This function will reset the card -// Input: -// dev - device structure -// Output: -// status - FALSE (card reset fail) -// TRUE (card reset successful) -// -//--------------------------------------------------------------------------- static int ft1000_reset_card(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -666,19 +483,7 @@ static int ft1000_reset_card(struct net_device *dev) return TRUE; } -//--------------------------------------------------------------------------- -// Function: ft1000_usb_transmit_complete -// -// Parameters: urb - transmitted usb urb -// -// -// Returns: none -// -// Description: This is the callback function when a urb is transmitted -// -// Notes: -// -//--------------------------------------------------------------------------- +/* callback function when a urb is transmitted */ static void ft1000_usb_transmit_complete(struct urb *urb) { @@ -690,21 +495,9 @@ static void ft1000_usb_transmit_complete(struct urb *urb) netif_wake_queue(ft1000dev->net); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_copy_down_pkt -// Description: This function will take an ethernet packet and convert it to -// a Flarion packet prior to sending it to the ASIC Downlink -// FIFO. -// Input: -// dev - device structure -// packet - address of ethernet packet -// len - length of IP packet -// Output: -// status - FAILURE -// SUCCESS -// -//--------------------------------------------------------------------------- +/* take an ethernet packet and convert it to a Flarion +* packet prior to sending it to the ASIC Downlink FIFO. +*/ static int ft1000_copy_down_pkt(struct net_device *netdev, u8 * packet, u16 len) { struct ft1000_info *pInfo = netdev_priv(netdev); @@ -769,20 +562,10 @@ static int ft1000_copy_down_pkt(struct net_device *netdev, u8 * packet, u16 len) return 0; } -//--------------------------------------------------------------------------- -// Function: ft1000_start_xmit -// -// Parameters: skb - socket buffer to be sent -// dev - network device -// -// -// Returns: none -// -// Description: transmit a ethernet packet -// -// Notes: -// -//--------------------------------------------------------------------------- +/* transmit an ethernet packet +* Parameters: skb - socket buffer to be sent +* dev - network device +*/ static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ft1000_info *pInfo = netdev_priv(dev); @@ -827,20 +610,7 @@ err: return NETDEV_TX_OK; } -//--------------------------------------------------------------------------- -// Function: ft1000_open -// -// Parameters: -// dev - network device -// -// -// Returns: none -// -// Description: open the network driver -// -// Notes: -// -//--------------------------------------------------------------------------- +/* open the network driver */ static int ft1000_open(struct net_device *dev) { struct ft1000_info *pInfo = netdev_priv(dev); @@ -879,21 +649,7 @@ static const struct net_device_ops ftnet_ops = .ndo_get_stats = &ft1000_netdev_stats, }; -//--------------------------------------------------------------------------- -// Function: init_ft1000_netdev -// -// Parameters: ft1000dev - device structure -// -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function initialize the network device -// -// Notes: -// -//--------------------------------------------------------------------------- - +/* initialize the network device */ static int ft1000_reset(void *dev) { ft1000_reset_card(dev); @@ -1014,20 +770,7 @@ err_net: return ret_val; } -//--------------------------------------------------------------------------- -// Function: reg_ft1000_netdev -// -// Parameters: ft1000dev - device structure -// -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function register the network driver -// -// Notes: -// -//--------------------------------------------------------------------------- +/* register the network driver */ int reg_ft1000_netdev(struct ft1000_usb *ft1000dev, struct usb_interface *intf) { @@ -1060,19 +803,9 @@ int reg_ft1000_netdev(struct ft1000_usb *ft1000dev, return 0; } -//--------------------------------------------------------------------------- -// -// Function: ft1000_copy_up_pkt -// Description: This function will take a packet from the FIFO up link and -// convert it into an ethernet packet and deliver it to the IP stack -// Input: -// urb - the receiving usb urb -// -// Output: -// status - FAILURE -// SUCCESS -// -//--------------------------------------------------------------------------- +/* take a packet from the FIFO up link and +* convert it into an ethernet packet and deliver it to the IP stack +*/ static int ft1000_copy_up_pkt(struct urb *urb) { struct ft1000_info *info = urb->context; @@ -1155,19 +888,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) } -//--------------------------------------------------------------------------- -// -// Function: ft1000_submit_rx_urb -// Description: the receiving function of the network driver -// -// Input: -// info - a private structure contains the device information -// -// Output: -// status - FAILURE -// SUCCESS -// -//--------------------------------------------------------------------------- +/* the receiving function of the network driver */ static int ft1000_submit_rx_urb(struct ft1000_info *info) { int result; @@ -1196,20 +917,7 @@ static int ft1000_submit_rx_urb(struct ft1000_info *info) return 0; } -//--------------------------------------------------------------------------- -// Function: ft1000_close -// -// Parameters: -// net - network device -// -// -// Returns: none -// -// Description: close the network driver -// -// Notes: -// -//--------------------------------------------------------------------------- +/* close the network driver */ int ft1000_close(struct net_device *net) { struct ft1000_info *pInfo = netdev_priv(net); @@ -1227,18 +935,7 @@ int ft1000_close(struct net_device *net) return 0; } -//--------------------------------------------------------------------------- -// -// Function: ft1000_chkcard -// Description: This function will check if the device is presently available on -// the system. -// Input: -// dev - device structure -// Output: -// status - FALSE (device is not present) -// TRUE (device is present) -// -//--------------------------------------------------------------------------- +/* check if the device is presently available on the system. */ static int ft1000_chkcard(struct ft1000_usb *dev) { u16 tempword; @@ -1271,19 +968,12 @@ static int ft1000_chkcard(struct ft1000_usb *dev) return TRUE; } -//--------------------------------------------------------------------------- -// -// Function: ft1000_receive_cmd -// Description: This function will read a message from the dpram area. -// Input: -// dev - network device structure -// pbuffer - caller supply address to buffer -// pnxtph - pointer to next pseudo header -// Output: -// Status = 0 (unsuccessful) -// = 1 (successful) -// -//--------------------------------------------------------------------------- +/* read a message from the dpram area. +* Input: +* dev - network device structure +* pbuffer - caller supply address to buffer +* pnxtph - pointer to next pseudo header +*/ static bool ft1000_receive_cmd(struct ft1000_usb *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) { -- cgit v1.2.3 From 46d981557b7429b2d03c56634f11cffe5cd8ed97 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 30 Oct 2013 18:05:16 -0700 Subject: staging: ft1000: STATUS defines completely removed The ft1000 driver ignores the normal Linux error codes, using its own macros, STATUS, STATUS_SUCCESS, and STATUS_FAILURE, instead. Unsigned variables (u16 and u32) are sometimes used to hold them. This patch converts all occurences of these macros to 0, 0 and -1, respectively. It also changes the last remaining status variables (mostly called status and ret) to ints, and removes the declarations of the macros. This patch does not correct the whitespace issues in the lines where the changes were made. Signed-off-by: Kelley Nielsen Suggested-by: Greg Kroah-Hartman Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 73 +++++++++++++------------- drivers/staging/ft1000/ft1000-usb/ft1000_usb.c | 4 +- drivers/staging/ft1000/ft1000-usb/ft1000_usb.h | 5 -- 3 files changed, 39 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 73b0c4fa59eb..84bdc6c647cb 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -48,7 +48,7 @@ static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size, int timeout) { - u16 ret; + int ret; if ((ft1000dev == NULL) || (ft1000dev->dev == NULL)) { DEBUG("ft1000dev or ft1000dev->dev == NULL, failure\n"); @@ -68,7 +68,7 @@ static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe, int ft1000_read_register(struct ft1000_usb *ft1000dev, u16* Data, u16 nRegIndx) { - int ret = STATUS_SUCCESS; + int ret = 0; ret = ft1000_control(ft1000dev, usb_rcvctrlpipe(ft1000dev->dev, 0), @@ -87,7 +87,7 @@ int ft1000_read_register(struct ft1000_usb *ft1000dev, u16* Data, int ft1000_write_register(struct ft1000_usb *ft1000dev, u16 value, u16 nRegIndx) { - int ret = STATUS_SUCCESS; + int ret = 0; ret = ft1000_control(ft1000dev, usb_sndctrlpipe(ft1000dev->dev, 0), @@ -106,7 +106,7 @@ int ft1000_write_register(struct ft1000_usb *ft1000dev, u16 value, int ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u16 cnt) { - int ret = STATUS_SUCCESS; + int ret = 0; ret = ft1000_control(ft1000dev, usb_rcvctrlpipe(ft1000dev->dev, 0), @@ -125,7 +125,7 @@ int ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, int ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u16 cnt) { - int ret = STATUS_SUCCESS; + int ret = 0; if (cnt % 4) cnt += cnt - (cnt % 4); @@ -147,7 +147,7 @@ int ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u8 highlow) { - int ret = STATUS_SUCCESS; + int ret = 0; u8 request; if (highlow == 0) @@ -171,7 +171,7 @@ int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, /* write into DPRAM a number of bytes */ int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value, u8 highlow) { - int ret = STATUS_SUCCESS; + int ret = 0; u8 request; if (highlow == 0) @@ -198,12 +198,12 @@ int fix_ft1000_read_dpram32(struct ft1000_usb *ft1000dev, u16 indx, { u8 buf[16]; u16 pos; - int ret = STATUS_SUCCESS; + int ret = 0; pos = (indx / 4) * 4; ret = ft1000_read_dpram32(ft1000dev, pos, buf, 16); - if (ret == STATUS_SUCCESS) { + if (ret == 0) { pos = (indx % 4) * 4; *buffer++ = buf[pos++]; *buffer++ = buf[pos++]; @@ -230,13 +230,13 @@ int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer) u8 buf[32]; u8 resultbuffer[32]; u8 *pdata; - int ret = STATUS_SUCCESS; + int ret = 0; pos1 = (indx / 4) * 4; pdata = buffer; ret = ft1000_read_dpram32(ft1000dev, pos1, buf, 16); - if (ret == STATUS_SUCCESS) { + if (ret == 0) { pos2 = (indx % 4)*4; buf[pos2++] = *buffer++; buf[pos2++] = *buffer++; @@ -250,24 +250,24 @@ int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer) ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16); - if (ret == STATUS_SUCCESS) { + if (ret == 0) { buffer = pdata; for (i = 0; i < 16; i++) { if (buf[i] != resultbuffer[i]) - ret = STATUS_FAILURE; + ret = -1; } } - if (ret == STATUS_FAILURE) { + if (ret == -1) { ret = ft1000_write_dpram32(ft1000dev, pos1, (u8 *)&tempbuffer[0], 16); ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16); - if (ret == STATUS_SUCCESS) { + if (ret == 0) { buffer = pdata; for (i = 0; i < 16; i++) { if (tempbuffer[i] != resultbuffer[i]) { - ret = STATUS_FAILURE; + ret = -1; DEBUG("%s Failed to write\n", __func__); } @@ -281,7 +281,7 @@ int fix_ft1000_write_dpram32(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer) /* reset or activate the DSP */ static void card_reset_dsp(struct ft1000_usb *ft1000dev, bool value) { - u16 status = STATUS_SUCCESS; + int status = 0; u16 tempword; status = ft1000_write_register(ft1000dev, HOST_INTF_BE, @@ -398,7 +398,7 @@ int dsp_reload(struct ft1000_usb *ft1000dev) /* call codeloader */ status = scram_dnldr(ft1000dev, pFileStart, FileLength); - if (status != STATUS_SUCCESS) + if (status != 0) return -EIO; msleep(1000); @@ -823,7 +823,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) if (ft1000dev->status & FT1000_STATUS_CLOSING) { DEBUG("network driver is closed, return\n"); - return STATUS_SUCCESS; + return 0; } // Read length len = urb->transfer_buffer_length; @@ -838,7 +838,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) if (tempword != *chksum) { info->stats.rx_errors++; ft1000_submit_rx_urb(info); - return STATUS_FAILURE; + return -1; } skb = dev_alloc_skb(len + 12 + 2); @@ -847,7 +847,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) DEBUG("ft1000_copy_up_pkt: No Network buffers available\n"); info->stats.rx_errors++; ft1000_submit_rx_urb(info); - return STATUS_FAILURE; + return -1; } pbuffer = (u8 *) skb_put(skb, len + 12); @@ -884,7 +884,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) ft1000_submit_rx_urb(info); - return SUCCESS; + return 0; } @@ -939,7 +939,7 @@ int ft1000_close(struct net_device *net) static int ft1000_chkcard(struct ft1000_usb *dev) { u16 tempword; - u16 status; + int status; if (dev->fCondResetPend) { DEBUG @@ -977,7 +977,8 @@ static int ft1000_chkcard(struct ft1000_usb *dev) static bool ft1000_receive_cmd(struct ft1000_usb *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) { - u16 size, ret; + u16 size; + int ret; u16 *ppseudohdr; int i; u16 tempword; @@ -1049,7 +1050,7 @@ static int ft1000_dsp_prov(void *arg) struct prov_record *ptr; struct pseudo_hdr *ppseudo_hdr; u16 *pmsg; - u16 status; + int status; u16 TempShortBuf[256]; DEBUG("*** DspProv Entered\n"); @@ -1071,7 +1072,7 @@ static int ft1000_dsp_prov(void *arg) i++; if (i == 10) { DEBUG("FT1000:ft1000_dsp_prov:message drop\n"); - return STATUS_FAILURE; + return -1; } ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); @@ -1125,7 +1126,7 @@ static int ft1000_dsp_prov(void *arg) dev->fProvComplete = true; info->CardReady = 1; - return STATUS_SUCCESS; + return 0; } static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) @@ -1139,7 +1140,7 @@ static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) u16 i; struct pseudo_hdr *ppseudo_hdr; u16 *pmsg; - u16 status; + int status; union { u8 byte[2]; u16 wrd; @@ -1147,7 +1148,7 @@ static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) char *cmdbuffer = kmalloc(1600, GFP_KERNEL); if (!cmdbuffer) - return STATUS_FAILURE; + return -1; status = ft1000_read_dpram32(dev, 0x200, cmdbuffer, size); @@ -1250,7 +1251,7 @@ static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) if (list_empty(&info->prov_list) == 0) { dev->fProvComplete = false; status = ft1000_dsp_prov(dev); - if (status != STATUS_SUCCESS) + if (status != 0) goto out; } else { dev->fProvComplete = true; @@ -1425,7 +1426,7 @@ static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) break; } - status = STATUS_SUCCESS; + status = 0; out: kfree(cmdbuffer); DEBUG("return from ft1000_proc_drvmsg\n"); @@ -1438,7 +1439,7 @@ int ft1000_poll(void* dev_id) struct ft1000_info *info = netdev_priv(dev->net); u16 tempword; - u16 status; + int status; u16 size; int i; u16 data; @@ -1451,7 +1452,7 @@ int ft1000_poll(void* dev_id) if (ft1000_chkcard(dev) == FALSE) { DEBUG("ft1000_poll::ft1000_chkcard: failed\n"); - return STATUS_FAILURE; + return -1; } status = ft1000_read_register (dev, &tempword, FT1000_REG_DOORBELL); @@ -1477,7 +1478,7 @@ int ft1000_poll(void* dev_id) DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n"); status = ft1000_proc_drvmsg (dev, size); - if (status != STATUS_SUCCESS ) + if (status != 0 ) return status; break; case DSPBCMSGID: @@ -1577,7 +1578,7 @@ int ft1000_poll(void* dev_id) } if (i==100) { DEBUG("Unable to reset ASIC\n"); - return STATUS_SUCCESS; + return 0; } msleep(10); // Program WMARK register @@ -1624,6 +1625,6 @@ int ft1000_poll(void* dev_id) } - return STATUS_SUCCESS; + return 0; } diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c index a8dd1e54878c..da6cc370c535 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -45,13 +45,13 @@ static int ft1000_poll_thread(void *arg) msleep(10); if (!gPollingfailed) { ret = ft1000_poll(arg); - if (ret != STATUS_SUCCESS) { + if (ret != 0) { DEBUG("ft1000_poll_thread: polling failed\n"); gPollingfailed = true; } } } - return STATUS_SUCCESS; + return 0; } static int ft1000_probe(struct usb_interface *interface, diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h index e8d00a930dc6..a6fdd524ee6f 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h @@ -11,8 +11,6 @@ #define PSEUDOSZ 16 -#define SUCCESS 0x00 - struct app_info_block { u32 nTxMsg; /* DPRAM msg sent to DSP with app_id */ u32 nRxMsg; /* DPRAM msg rcv from dsp with app_id */ @@ -31,9 +29,6 @@ struct app_info_block { #define FALSE 0 #define TRUE 1 -#define STATUS_SUCCESS 0 -#define STATUS_FAILURE 0x1001 - #define FT1000_STATUS_CLOSING 0x01 #define DSPBCMSGID 0x10 -- cgit v1.2.3 From d5ae3c482df04a74e03ed944f33209178adaf03f Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Tue, 5 Nov 2013 21:36:55 -0800 Subject: staging: ft1000: remove unused variable nxtph The function ft1000_poll, in ft1000_hw.c, is overly complex, with at least five different levels of nesting. While preparing to extract one of the cases to its own function, I discovered that the variable nxtph is not used. It is declared and assigned a value in ft1000_poll(), then passed by reference to the helper function ft1000_receive_command(), which receives it as parameter. pnxtph does not appear in the body of this function. Remove all occurrences of nxtph and pnxtph. Signed-off-by: Kelley Nielsen Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 84bdc6c647cb..e9ef27f8e19d 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -972,10 +972,9 @@ static int ft1000_chkcard(struct ft1000_usb *dev) * Input: * dev - network device structure * pbuffer - caller supply address to buffer -* pnxtph - pointer to next pseudo header */ static bool ft1000_receive_cmd(struct ft1000_usb *dev, u16 *pbuffer, - int maxsz, u16 *pnxtph) + int maxsz) { u16 size; int ret; @@ -1445,7 +1444,6 @@ int ft1000_poll(void* dev_id) u16 data; u16 modulo; u16 portid; - u16 nxtph; struct dpram_blk *pdpram_blk; struct pseudo_hdr *ppseudo_hdr; unsigned long flags; @@ -1489,10 +1487,9 @@ int ft1000_poll(void* dev_id) if ( (dev->app_info[i].DspBCMsgFlag) && (dev->app_info[i].fileobject) && (dev->app_info[i].NumOfMsg < MAX_MSG_LIMIT) ) { - nxtph = FT1000_DPRAM_RX_BASE + 2; pdpram_blk = ft1000_get_buffer (&freercvpool); if (pdpram_blk != NULL) { - if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE, &nxtph) ) { + if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE) ) { ppseudo_hdr = (struct pseudo_hdr *)pdpram_blk->pbuffer; // Put message into the appropriate application block dev->app_info[i].nRxMsg++; @@ -1520,7 +1517,7 @@ int ft1000_poll(void* dev_id) pdpram_blk = ft1000_get_buffer (&freercvpool); if (pdpram_blk != NULL) { - if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE, &nxtph) ) { + if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE) ) { ppseudo_hdr = (struct pseudo_hdr *)pdpram_blk->pbuffer; // Search for correct application block for (i=0; i Date: Tue, 5 Nov 2013 21:39:10 -0800 Subject: staging: ft1000: extract dsp_broadcast_msg_id() The function ft1000_poll, in ft1000_hw.c, is overly complex, with at least five levels of nesting. Extract the lines in switch case DSPBCMSGID into their own function, called dsp_broadcast_msg_id(). Pass one parameter, struct ft1000_usb *dev. Make a copy of struct dpram_blk *pdpram_blk local to the new function, since it is initialized at the top of each case in which it appears. Make unsigned long flags local to the new function. Remove the assignment to struct pseudo_hdr *ppseudo_hdr, which is otherwise unused in the switch case, and receives the same assignment at the top of each case in which it appears. Return an int, 0 for success and -1 for error. Correct style issues in the extracted lines. Signed-off-by: Kelley Nielsen Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 85 ++++++++++++++++----------- 1 file changed, 50 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index e9ef27f8e19d..52e6b187d0cb 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1432,6 +1432,54 @@ out: return status; } +/* Check which application has registered for dsp broadcast messages */ +static int dsp_broadcast_msg_id(struct ft1000_usb *dev) +{ + struct dpram_blk *pdpram_blk; + unsigned long flags; + int i; + + for (i = 0; i < MAX_NUM_APP; i++) { + if ((dev->app_info[i].DspBCMsgFlag) + && (dev->app_info[i].fileobject) + && (dev->app_info[i].NumOfMsg + < MAX_MSG_LIMIT)) { + pdpram_blk = ft1000_get_buffer(&freercvpool); + if (pdpram_blk != NULL) { + if (ft1000_receive_cmd(dev, + pdpram_blk->pbuffer, + MAX_CMD_SQSIZE)) { + /* Put message into the + * appropriate application block + * */ + dev->app_info[i].nRxMsg++; + spin_lock_irqsave(&free_buff_lock, + flags); + list_add_tail(&pdpram_blk->list, + &dev->app_info[i] + .app_sqlist); + dev->app_info[i].NumOfMsg++; + spin_unlock_irqrestore(&free_buff_lock, + flags); + wake_up_interruptible(&dev->app_info[i] + .wait_dpram_msg); + } else { + dev->app_info[i].nRxMsgMiss++; + ft1000_free_buffer(pdpram_blk, + &freercvpool); + DEBUG("pdpram_blk::ft1000_get_buffer NULL\n"); + return -1; + } + } else { + DEBUG("Out of memory in free receive command pool\n"); + dev->app_info[i].nRxMsgMiss++; + return -1; + } + } + } + return 0; +} + int ft1000_poll(void* dev_id) { struct ft1000_usb *dev = (struct ft1000_usb *)dev_id; @@ -1446,8 +1494,6 @@ int ft1000_poll(void* dev_id) u16 portid; struct dpram_blk *pdpram_blk; struct pseudo_hdr *ppseudo_hdr; - unsigned long flags; - if (ft1000_chkcard(dev) == FALSE) { DEBUG("ft1000_poll::ft1000_chkcard: failed\n"); return -1; @@ -1480,39 +1526,8 @@ int ft1000_poll(void* dev_id) return status; break; case DSPBCMSGID: - // This is a dsp broadcast message - // Check which application has registered for dsp broadcast messages - - for (i=0; iapp_info[i].DspBCMsgFlag) && (dev->app_info[i].fileobject) && - (dev->app_info[i].NumOfMsg < MAX_MSG_LIMIT) ) - { - pdpram_blk = ft1000_get_buffer (&freercvpool); - if (pdpram_blk != NULL) { - if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE) ) { - ppseudo_hdr = (struct pseudo_hdr *)pdpram_blk->pbuffer; - // Put message into the appropriate application block - dev->app_info[i].nRxMsg++; - spin_lock_irqsave(&free_buff_lock, flags); - list_add_tail(&pdpram_blk->list, &dev->app_info[i].app_sqlist); - dev->app_info[i].NumOfMsg++; - spin_unlock_irqrestore(&free_buff_lock, flags); - wake_up_interruptible(&dev->app_info[i].wait_dpram_msg); - } - else { - dev->app_info[i].nRxMsgMiss++; - // Put memory back to free pool - ft1000_free_buffer(pdpram_blk, &freercvpool); - DEBUG("pdpram_blk::ft1000_get_buffer NULL\n"); - } - } - else { - DEBUG("Out of memory in free receive command pool\n"); - dev->app_info[i].nRxMsgMiss++; - } - } - } - break; + status = dsp_broadcast_msg_id(dev); + break; default: pdpram_blk = ft1000_get_buffer (&freercvpool); -- cgit v1.2.3 From 8a58cad260bd37b7d20d222b083b4844d086b2d7 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 6 Nov 2013 05:08:11 -0800 Subject: staging: ft1000: extract helper handle_misc_portid() The function ft1000_poll, in ft1000_hw.c, is complex, with deep levels of nesting, unnecessary variables, and style issues. Extract the default case of the switch statement to its own function, handle_misc_portid. Make the variable struct dpram_blk *pdpram_blk local to the new function and remove it from the old. The variable struct pseudo_hdr *ppseudo_hdr is used only once, to access a member of another struct, so eliminate it and access the member directly. Return -1 in all the places where the code fails, and 0 on successful completion. Fix coding style errors. Signed-off-by: Kelley Nielsen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 92 +++++++++++++++------------ 1 file changed, 51 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 52e6b187d0cb..95ea5c4b501f 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1480,6 +1480,54 @@ static int dsp_broadcast_msg_id(struct ft1000_usb *dev) return 0; } +static int handle_misc_portid(struct ft1000_usb *dev) +{ + struct dpram_blk *pdpram_blk; + int i; + + pdpram_blk = ft1000_get_buffer(&freercvpool); + if (pdpram_blk != NULL) { + if (ft1000_receive_cmd(dev, pdpram_blk->pbuffer, + MAX_CMD_SQSIZE)) { + /* Search for correct application block */ + for (i = 0; i < MAX_NUM_APP; i++) { + if (dev->app_info[i].app_id + == ((struct pseudo_hdr *) + pdpram_blk->pbuffer) + ->portdest) + break; + return -1; + } + if (i == MAX_NUM_APP) { + DEBUG("FT1000:ft1000_parse_dpram_msg: No application matching id = %d\n", ((struct pseudo_hdr *)pdpram_blk->pbuffer)->portdest); + ft1000_free_buffer(pdpram_blk, &freercvpool); + } else { + if (dev->app_info[i].NumOfMsg > MAX_MSG_LIMIT) { + ft1000_free_buffer(pdpram_blk, + &freercvpool); + return -1; + } else { + dev->app_info[i].nRxMsg++; + /* Put message into the appropriate + * application block + * */ + list_add_tail(&pdpram_blk->list, + &dev->app_info[i] + .app_sqlist); + dev->app_info[i].NumOfMsg++; + } + } + } else { + ft1000_free_buffer(pdpram_blk, &freercvpool); + return -1; + } + } else { + DEBUG("Out of memory in free receive command pool\n"); + return -1; + } + return 0; +} + int ft1000_poll(void* dev_id) { struct ft1000_usb *dev = (struct ft1000_usb *)dev_id; @@ -1492,8 +1540,7 @@ int ft1000_poll(void* dev_id) u16 data; u16 modulo; u16 portid; - struct dpram_blk *pdpram_blk; - struct pseudo_hdr *ppseudo_hdr; + if (ft1000_chkcard(dev) == FALSE) { DEBUG("ft1000_poll::ft1000_chkcard: failed\n"); return -1; @@ -1529,45 +1576,8 @@ int ft1000_poll(void* dev_id) status = dsp_broadcast_msg_id(dev); break; default: - pdpram_blk = ft1000_get_buffer (&freercvpool); - - if (pdpram_blk != NULL) { - if ( ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE) ) { - ppseudo_hdr = (struct pseudo_hdr *)pdpram_blk->pbuffer; - // Search for correct application block - for (i=0; iapp_info[i].app_id == ppseudo_hdr->portdest) { - break; - } - } - - if (i == MAX_NUM_APP) { - DEBUG("FT1000:ft1000_parse_dpram_msg: No application matching id = %d\n", ppseudo_hdr->portdest); - // Put memory back to free pool - ft1000_free_buffer(pdpram_blk, &freercvpool); - } - else { - if (dev->app_info[i].NumOfMsg > MAX_MSG_LIMIT) { - // Put memory back to free pool - ft1000_free_buffer(pdpram_blk, &freercvpool); - } - else { - dev->app_info[i].nRxMsg++; - // Put message into the appropriate application block - list_add_tail(&pdpram_blk->list, &dev->app_info[i].app_sqlist); - dev->app_info[i].NumOfMsg++; - } - } - } - else { - // Put memory back to free pool - ft1000_free_buffer(pdpram_blk, &freercvpool); - } - } - else { - DEBUG("Out of memory in free receive command pool\n"); - } - break; + status = handle_misc_portid(dev); + break; } } else { -- cgit v1.2.3 From f3802bdb15f7bea68ca330d8d909c56ac1e15119 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 6 Nov 2013 05:08:58 -0800 Subject: staging: ft1000: flatten nesting in handle_misc_portid The newly extracted function handle_misc_portid still has several unnecessary levels of nesting, having inherited its logic from the original extracted lines. Move handling for failed memory allocation (of *pdpram_blk) to the top of the function, and return -1 from within it. This eliminates the if statement around the body of the function. Change two levels of nested if/else to an if/else-if/else. Create a label, exit_failure, at the end of the function with the cleanup code, and goto it at all points of failure. Also, goto it if the call to ft1000_receive_cmd() fails, instead of descending into an if block if it succeeds. Pull all lines from inside the former if blocks to the left, and rejoin lines to take advantage of reclaimed horizontal space. Signed-off-by: Kelley Nielsen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 61 +++++++++++---------------- 1 file changed, 25 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 95ea5c4b501f..2a23b4427ded 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1486,46 +1486,35 @@ static int handle_misc_portid(struct ft1000_usb *dev) int i; pdpram_blk = ft1000_get_buffer(&freercvpool); - if (pdpram_blk != NULL) { - if (ft1000_receive_cmd(dev, pdpram_blk->pbuffer, - MAX_CMD_SQSIZE)) { - /* Search for correct application block */ - for (i = 0; i < MAX_NUM_APP; i++) { - if (dev->app_info[i].app_id - == ((struct pseudo_hdr *) - pdpram_blk->pbuffer) - ->portdest) - break; - return -1; - } - if (i == MAX_NUM_APP) { - DEBUG("FT1000:ft1000_parse_dpram_msg: No application matching id = %d\n", ((struct pseudo_hdr *)pdpram_blk->pbuffer)->portdest); - ft1000_free_buffer(pdpram_blk, &freercvpool); - } else { - if (dev->app_info[i].NumOfMsg > MAX_MSG_LIMIT) { - ft1000_free_buffer(pdpram_blk, - &freercvpool); - return -1; - } else { - dev->app_info[i].nRxMsg++; - /* Put message into the appropriate - * application block - * */ - list_add_tail(&pdpram_blk->list, - &dev->app_info[i] - .app_sqlist); - dev->app_info[i].NumOfMsg++; - } - } - } else { - ft1000_free_buffer(pdpram_blk, &freercvpool); - return -1; - } - } else { + if (pdpram_blk == NULL) { DEBUG("Out of memory in free receive command pool\n"); return -1; } + if (!ft1000_receive_cmd(dev, pdpram_blk->pbuffer, MAX_CMD_SQSIZE)) + goto exit_failure; + + /* Search for correct application block */ + for (i = 0; i < MAX_NUM_APP; i++) { + if (dev->app_info[i].app_id == ((struct pseudo_hdr *) + pdpram_blk->pbuffer)->portdest) + break; + } + if (i == MAX_NUM_APP) { + DEBUG("FT1000:ft1000_parse_dpram_msg: No application matching id = %d\n", ((struct pseudo_hdr *)pdpram_blk->pbuffer)->portdest); + goto exit_failure; + } else if (dev->app_info[i].NumOfMsg > MAX_MSG_LIMIT) { + goto exit_failure; + } else { + dev->app_info[i].nRxMsg++; + /* Put message into the appropriate application block */ + list_add_tail(&pdpram_blk->list, &dev->app_info[i].app_sqlist); + dev->app_info[i].NumOfMsg++; + } return 0; + +exit_failure: + ft1000_free_buffer(pdpram_blk, &freercvpool); + return -1; } int ft1000_poll(void* dev_id) -- cgit v1.2.3 From 9a1261f317110e2b139a35fe7acf7fa04ca1bf97 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 6 Nov 2013 05:09:30 -0800 Subject: staging: ft1000: fix checkpatch issues in ft1000_poll() The function ft1000_poll(), in ft1000_hw.c, has many miscellaneous coding style issues, such as improper indentation, C99 comments, use of msleep(), and lines over 80 characters. Changes all spaces at the start of lines to the proper number of tabs. Convert C99 comments to standard /* */ style. Change calls to msleep(10) to usleep_range(9000, 11000). Break lines over 80 characters, unless they are user visible strings. Remove space before open paren in function calls. Fix any other issues that checkpatch finds. Signed-off-by: Kelley Nielsen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 244 +++++++++++++------------- 1 file changed, 126 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 2a23b4427ded..2f54c2a23fe7 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1517,125 +1517,133 @@ exit_failure: return -1; } -int ft1000_poll(void* dev_id) +int ft1000_poll(void *dev_id) { - struct ft1000_usb *dev = (struct ft1000_usb *)dev_id; + struct ft1000_usb *dev = (struct ft1000_usb *)dev_id; struct ft1000_info *info = netdev_priv(dev->net); + u16 tempword; + int status; + u16 size; + int i; + u16 data; + u16 modulo; + u16 portid; - u16 tempword; - int status; - u16 size; - int i; - u16 data; - u16 modulo; - u16 portid; - - if (ft1000_chkcard(dev) == FALSE) { - DEBUG("ft1000_poll::ft1000_chkcard: failed\n"); - return -1; - } - - status = ft1000_read_register (dev, &tempword, FT1000_REG_DOORBELL); - - if ( !status ) - { - - if (tempword & FT1000_DB_DPRAM_RX) { - - status = ft1000_read_dpram16(dev, 0x200, (u8 *)&data, 0); - size = ntohs(data) + 16 + 2; - if (size % 4) { - modulo = 4 - (size % 4); - size = size + modulo; - } - status = ft1000_read_dpram16(dev, 0x201, (u8 *)&portid, 1); - portid &= 0xff; - - if (size < MAX_CMD_SQSIZE) { - switch (portid) - { - case DRIVERID: - DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n"); - - status = ft1000_proc_drvmsg (dev, size); - if (status != 0 ) - return status; - break; - case DSPBCMSGID: - status = dsp_broadcast_msg_id(dev); - break; - default: - status = handle_misc_portid(dev); - break; - } - } - else { - DEBUG("FT1000:dpc:Invalid total length for SlowQ = %d\n", size); - } - status = ft1000_write_register (dev, FT1000_DB_DPRAM_RX, FT1000_REG_DOORBELL); - } - else if (tempword & FT1000_DSP_ASIC_RESET) { - - // Let's reset the ASIC from the Host side as well - status = ft1000_write_register (dev, ASIC_RESET_BIT, FT1000_REG_RESET); - status = ft1000_read_register (dev, &tempword, FT1000_REG_RESET); - i = 0; - while (tempword & ASIC_RESET_BIT) { - status = ft1000_read_register (dev, &tempword, FT1000_REG_RESET); - msleep(10); - i++; - if (i==100) - break; - } - if (i==100) { - DEBUG("Unable to reset ASIC\n"); - return 0; - } - msleep(10); - // Program WMARK register - status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK); - // clear ASIC reset doorbell - status = ft1000_write_register (dev, FT1000_DSP_ASIC_RESET, FT1000_REG_DOORBELL); - msleep(10); - } - else if (tempword & FT1000_ASIC_RESET_REQ) { - DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n"); - - // clear ASIC reset request from DSP - status = ft1000_write_register (dev, FT1000_ASIC_RESET_REQ, FT1000_REG_DOORBELL); - status = ft1000_write_register (dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); - // copy dsp session record from Adapter block - status = ft1000_write_dpram32 (dev, 0, (u8 *)&info->DSPSess.Rec[0], 1024); - // Program WMARK register - status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK); - // ring doorbell to tell DSP that ASIC is out of reset - status = ft1000_write_register (dev, FT1000_ASIC_RESET_DSP, FT1000_REG_DOORBELL); - } - else if (tempword & FT1000_DB_COND_RESET) { - DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n"); - - if (!dev->fAppMsgPend) { - // Reset ASIC and DSP - - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (u8 *)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (u8 *)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (u8 *)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (u8 *)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); - info->CardReady = 0; - info->DrvErrNum = DSP_CONDRESET_INFO; - DEBUG("ft1000_hw:DSP conditional reset requested\n"); - info->ft1000_reset(dev->net); - } - else { - dev->fProvComplete = false; - dev->fCondResetPend = true; - } - - ft1000_write_register(dev, FT1000_DB_COND_RESET, FT1000_REG_DOORBELL); - } - - } - - return 0; - + if (ft1000_chkcard(dev) == FALSE) { + DEBUG("ft1000_poll::ft1000_chkcard: failed\n"); + return -1; + } + status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL); + if (!status) { + if (tempword & FT1000_DB_DPRAM_RX) { + status = ft1000_read_dpram16(dev, + 0x200, (u8 *)&data, 0); + size = ntohs(data) + 16 + 2; + if (size % 4) { + modulo = 4 - (size % 4); + size = size + modulo; + } + status = ft1000_read_dpram16(dev, 0x201, + (u8 *)&portid, 1); + portid &= 0xff; + if (size < MAX_CMD_SQSIZE) { + switch (portid) { + case DRIVERID: + DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid DRIVERID\n"); + status = ft1000_proc_drvmsg(dev, size); + if (status != 0) + return status; + break; + case DSPBCMSGID: + status = dsp_broadcast_msg_id(dev); + break; + default: + status = handle_misc_portid(dev); + break; + } + } else + DEBUG("FT1000:dpc:Invalid total length for SlowQ = %d\n", size); + status = ft1000_write_register(dev, + FT1000_DB_DPRAM_RX, + FT1000_REG_DOORBELL); + } else if (tempword & FT1000_DSP_ASIC_RESET) { + /* Let's reset the ASIC from the Host side as well */ + status = ft1000_write_register(dev, ASIC_RESET_BIT, + FT1000_REG_RESET); + status = ft1000_read_register(dev, &tempword, + FT1000_REG_RESET); + i = 0; + while (tempword & ASIC_RESET_BIT) { + status = ft1000_read_register(dev, &tempword, + FT1000_REG_RESET); + usleep_range(9000, 11000); + i++; + if (i == 100) + break; + } + if (i == 100) { + DEBUG("Unable to reset ASIC\n"); + return 0; + } + usleep_range(9000, 11000); + /* Program WMARK register */ + status = ft1000_write_register(dev, 0x600, + FT1000_REG_MAG_WATERMARK); + /* clear ASIC reset doorbell */ + status = ft1000_write_register(dev, + FT1000_DSP_ASIC_RESET, + FT1000_REG_DOORBELL); + usleep_range(9000, 11000); + } else if (tempword & FT1000_ASIC_RESET_REQ) { + DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_ASIC_RESET_REQ\n"); + /* clear ASIC reset request from DSP */ + status = ft1000_write_register(dev, + FT1000_ASIC_RESET_REQ, + FT1000_REG_DOORBELL); + status = ft1000_write_register(dev, HOST_INTF_BE, + FT1000_REG_SUP_CTRL); + /* copy dsp session record from Adapter block */ + status = ft1000_write_dpram32(dev, 0, + (u8 *)&info->DSPSess.Rec[0], 1024); + status = ft1000_write_register(dev, 0x600, + FT1000_REG_MAG_WATERMARK); + /* ring doorbell to tell DSP that + * ASIC is out of reset + * */ + status = ft1000_write_register(dev, + FT1000_ASIC_RESET_DSP, + FT1000_REG_DOORBELL); + } else if (tempword & FT1000_DB_COND_RESET) { + DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_COND_RESET\n"); + if (!dev->fAppMsgPend) { + /* Reset ASIC and DSP */ + status = ft1000_read_dpram16(dev, + FT1000_MAG_DSP_TIMER0, + (u8 *)&(info->DSP_TIME[0]), + FT1000_MAG_DSP_TIMER0_INDX); + status = ft1000_read_dpram16(dev, + FT1000_MAG_DSP_TIMER1, + (u8 *)&(info->DSP_TIME[1]), + FT1000_MAG_DSP_TIMER1_INDX); + status = ft1000_read_dpram16(dev, + FT1000_MAG_DSP_TIMER2, + (u8 *)&(info->DSP_TIME[2]), + FT1000_MAG_DSP_TIMER2_INDX); + status = ft1000_read_dpram16(dev, + FT1000_MAG_DSP_TIMER3, + (u8 *)&(info->DSP_TIME[3]), + FT1000_MAG_DSP_TIMER3_INDX); + info->CardReady = 0; + info->DrvErrNum = DSP_CONDRESET_INFO; + DEBUG("ft1000_hw:DSP conditional reset requested\n"); + info->ft1000_reset(dev->net); + } else { + dev->fProvComplete = false; + dev->fCondResetPend = true; + } + ft1000_write_register(dev, FT1000_DB_COND_RESET, + FT1000_REG_DOORBELL); + } + } + return 0; } -- cgit v1.2.3 From a3220b89bd396ff5b83ede05d7925564d277a9ea Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 6 Nov 2013 05:09:56 -0800 Subject: staging: ft1000: flatten nesting in dsp_broadcast_msg_id() The function dsp_broadcast_msg_id() has four levels of nesting. Move the handling for failed allocation for *dpram_blk from the else block at the end to the block immediately following the test, reverse the sense of the test, and exit with an error code if the allocation fails. This eliminates descending into an if block if the allocation is successful. Move all lines inside the removed block one tab to the left, and join lines that will fall under the 80 char limit. Signed-off-by: Kelley Nielsen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 46 ++++++++++++--------------- 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 2f54c2a23fe7..c071f61d0b8f 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -1445,36 +1445,30 @@ static int dsp_broadcast_msg_id(struct ft1000_usb *dev) && (dev->app_info[i].NumOfMsg < MAX_MSG_LIMIT)) { pdpram_blk = ft1000_get_buffer(&freercvpool); - if (pdpram_blk != NULL) { - if (ft1000_receive_cmd(dev, - pdpram_blk->pbuffer, - MAX_CMD_SQSIZE)) { - /* Put message into the - * appropriate application block - * */ - dev->app_info[i].nRxMsg++; - spin_lock_irqsave(&free_buff_lock, - flags); - list_add_tail(&pdpram_blk->list, - &dev->app_info[i] - .app_sqlist); - dev->app_info[i].NumOfMsg++; - spin_unlock_irqrestore(&free_buff_lock, - flags); - wake_up_interruptible(&dev->app_info[i] - .wait_dpram_msg); - } else { - dev->app_info[i].nRxMsgMiss++; - ft1000_free_buffer(pdpram_blk, - &freercvpool); - DEBUG("pdpram_blk::ft1000_get_buffer NULL\n"); - return -1; - } - } else { + if (pdpram_blk == NULL) { DEBUG("Out of memory in free receive command pool\n"); dev->app_info[i].nRxMsgMiss++; return -1; } + if (ft1000_receive_cmd(dev, pdpram_blk->pbuffer, + MAX_CMD_SQSIZE)) { + /* Put message into the + * appropriate application block + */ + dev->app_info[i].nRxMsg++; + spin_lock_irqsave(&free_buff_lock, flags); + list_add_tail(&pdpram_blk->list, + &dev->app_info[i] .app_sqlist); + dev->app_info[i].NumOfMsg++; + spin_unlock_irqrestore(&free_buff_lock, flags); + wake_up_interruptible(&dev->app_info[i] + .wait_dpram_msg); + } else { + dev->app_info[i].nRxMsgMiss++; + ft1000_free_buffer(pdpram_blk, &freercvpool); + DEBUG("pdpram_blk::ft1000_get_buffer NULL\n"); + return -1; + } } } return 0; -- cgit v1.2.3 From 8d6c558557ee8538732188a7d2dd8c87da9000b6 Mon Sep 17 00:00:00 2001 From: Kelley Nielsen Date: Wed, 6 Nov 2013 05:10:19 -0800 Subject: staging: ft1000: fix remaining checkpatch issues in ft1000_hw.c The file ft1000_hw.c is still full of coding style problems that make it challenging to read and understand. The lines inside the switch cases in ft1000_proc_drvmsg() are indented too deeply, so remove one leading tab. Join lines that are now able to fit in the 80 character limit. This will take care of the "too many leading tabs" issue. Run checkpatch.pl on the file, and correct all other issues it reports (except lines with user visible strings over 80 chars). Signed-off-by: Kelley Nielsen Suggested-by: Waskiewicz Jr, Peter P Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 430 ++++++++++++-------------- 1 file changed, 196 insertions(+), 234 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index c071f61d0b8f..0d6c1d12170d 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -25,7 +25,9 @@ #define HARLEY_READ_OPERATION 0xc1 #define HARLEY_WRITE_OPERATION 0x41 -//#define JDEBUG +#if 0 +#define JDEBUG +#endif static int ft1000_submit_rx_urb(struct ft1000_info *info); @@ -65,7 +67,7 @@ static int ft1000_control(struct ft1000_usb *ft1000dev, unsigned int pipe, } /* returns the value in a register */ -int ft1000_read_register(struct ft1000_usb *ft1000dev, u16* Data, +int ft1000_read_register(struct ft1000_usb *ft1000dev, u16 *Data, u16 nRegIndx) { int ret = 0; @@ -169,7 +171,8 @@ int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, } /* write into DPRAM a number of bytes */ -int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value, u8 highlow) +int ft1000_write_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u16 value, + u8 highlow) { int ret = 0; u8 request; @@ -334,7 +337,7 @@ void card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer, ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); if (temp & 0x0100) - msleep(10); + usleep_range(900, 1100); /* check for odd word */ size = size + 2; @@ -344,16 +347,17 @@ void card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer, size += 4 - (size % 4); ft1000_write_dpram32(ft1000dev, 0, commandbuf, size); - msleep(1); + usleep_range(900, 1100); ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL); - msleep(1); + usleep_range(900, 1100); ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); - if ((temp & 0x0100) == 0) { - //DEBUG("card_send_command: Message sent\n"); - } +#if 0 + if ((temp & 0x0100) == 0) + DEBUG("card_send_command: Message sent\n"); +#endif } @@ -498,7 +502,7 @@ static void ft1000_usb_transmit_complete(struct urb *urb) /* take an ethernet packet and convert it to a Flarion * packet prior to sending it to the ASIC Downlink FIFO. */ -static int ft1000_copy_down_pkt(struct net_device *netdev, u8 * packet, u16 len) +static int ft1000_copy_down_pkt(struct net_device *netdev, u8 *packet, u16 len) { struct ft1000_info *pInfo = netdev_priv(netdev); struct ft1000_usb *pFt1000Dev = pInfo->priv; @@ -641,8 +645,7 @@ static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev) return &(info->stats); } -static const struct net_device_ops ftnet_ops = -{ +static const struct net_device_ops ftnet_ops = { .ndo_open = &ft1000_open, .ndo_stop = &ft1000_close, .ndo_start_xmit = &ft1000_start_xmit, @@ -687,14 +690,14 @@ int init_ft1000_netdev(struct ft1000_usb *ft1000dev) card_nr[1] = '\0'; ret_val = kstrtou8(card_nr, 10, &gCardIndex); if (ret_val) { - printk(KERN_ERR "Can't parse netdev\n"); + netdev_err(ft1000dev->net, "Can't parse netdev\n"); goto err_net; } ft1000dev->CardNumber = gCardIndex; DEBUG("card number = %d\n", ft1000dev->CardNumber); } else { - printk(KERN_ERR "ft1000: Invalid device name\n"); + netdev_err(ft1000dev->net, "ft1000: Invalid device name\n"); ret_val = -ENXIO; goto err_net; } @@ -825,7 +828,7 @@ static int ft1000_copy_up_pkt(struct urb *urb) DEBUG("network driver is closed, return\n"); return 0; } - // Read length + /* Read length */ len = urb->transfer_buffer_length; lena = urb->actual_length; @@ -942,8 +945,7 @@ static int ft1000_chkcard(struct ft1000_usb *dev) int status; if (dev->fCondResetPend) { - DEBUG - ("ft1000_hw:ft1000_chkcard:Card is being reset, return FALSE\n"); + DEBUG("ft1000_hw:ft1000_chkcard:Card is being reset, return FALSE\n"); return TRUE; } /* Mask register is used to check for device presence since it is never @@ -951,8 +953,7 @@ static int ft1000_chkcard(struct ft1000_usb *dev) */ status = ft1000_read_register(dev, &tempword, FT1000_REG_SUP_IMASK); if (tempword == 0) { - DEBUG - ("ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n"); + DEBUG("ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n"); return FALSE; } /* The system will return the value of 0xffff for the version register @@ -961,8 +962,7 @@ static int ft1000_chkcard(struct ft1000_usb *dev) status = ft1000_read_register(dev, &tempword, FT1000_REG_ASIC_ID); if (tempword != 0x1b01) { dev->status |= FT1000_STATUS_CLOSING; - DEBUG - ("ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n"); + DEBUG("ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n"); return FALSE; } return TRUE; @@ -1095,9 +1095,8 @@ static int ft1000_dsp_prov(void *arg) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } TempShortBuf[0] = 0; TempShortBuf[1] = htons(len); @@ -1115,7 +1114,7 @@ static int ft1000_dsp_prov(void *arg) kfree(ptr->pprov_data); kfree(ptr); } - msleep(10); + usleep_range(9000, 11000); } DEBUG("DSP Provisioning List Entry finished\n"); @@ -1171,154 +1170,179 @@ static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) DEBUG("ft1000_proc_drvmsg:Command message type = 0x%x\n", msgtype); switch (msgtype) { case MEDIA_STATE:{ - DEBUG - ("ft1000_proc_drvmsg:Command message type = MEDIA_STATE"); - - pmediamsg = (struct media_msg *)&cmdbuffer[0]; - if (info->ProgConStat != 0xFF) { - if (pmediamsg->state) { - DEBUG("Media is up\n"); - if (info->mediastate == 0) { - if (dev->NetDevRegDone) { - netif_wake_queue(dev-> - net); - } - info->mediastate = 1; - } - } else { - DEBUG("Media is down\n"); - if (info->mediastate == 1) { - info->mediastate = 0; - if (dev->NetDevRegDone) { - } - info->ConTm = 0; - } + DEBUG("ft1000_proc_drvmsg:Command message type = MEDIA_STATE"); + pmediamsg = (struct media_msg *)&cmdbuffer[0]; + if (info->ProgConStat != 0xFF) { + if (pmediamsg->state) { + DEBUG("Media is up\n"); + if (info->mediastate == 0) { + if (dev->NetDevRegDone) + netif_wake_queue(dev->net); + info->mediastate = 1; } } else { DEBUG("Media is down\n"); if (info->mediastate == 1) { info->mediastate = 0; - info->ConTm = 0; + if (dev->NetDevRegDone) + info->ConTm = 0; } } - break; + } else { + DEBUG("Media is down\n"); + if (info->mediastate == 1) { + info->mediastate = 0; + info->ConTm = 0; + } } + break; + } case DSP_INIT_MSG:{ - DEBUG - ("ft1000_proc_drvmsg:Command message type = DSP_INIT_MSG"); - - pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[2]; - memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ); - DEBUG("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n", - info->DspVer[0], info->DspVer[1], info->DspVer[2], - info->DspVer[3]); - memcpy(info->HwSerNum, pdspinitmsg->HwSerNum, - HWSERNUMSZ); - memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ); - memcpy(info->eui64, pdspinitmsg->eui64, EUISZ); - DEBUG("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n", - info->eui64[0], info->eui64[1], info->eui64[2], - info->eui64[3], info->eui64[4], info->eui64[5], - info->eui64[6], info->eui64[7]); - dev->net->dev_addr[0] = info->eui64[0]; - dev->net->dev_addr[1] = info->eui64[1]; - dev->net->dev_addr[2] = info->eui64[2]; - dev->net->dev_addr[3] = info->eui64[5]; - dev->net->dev_addr[4] = info->eui64[6]; - dev->net->dev_addr[5] = info->eui64[7]; - - if (ntohs(pdspinitmsg->length) == - (sizeof(struct dsp_init_msg) - 20)) { - memcpy(info->ProductMode, - pdspinitmsg->ProductMode, MODESZ); - memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, - CALVERSZ); - memcpy(info->RfCalDate, pdspinitmsg->RfCalDate, - CALDATESZ); - DEBUG("RFCalVer = 0x%2x 0x%2x\n", - info->RfCalVer[0], info->RfCalVer[1]); - } - break; + DEBUG("ft1000_proc_drvmsg:Command message type = DSP_INIT_MSG"); + pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[2]; + memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ); + DEBUG("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n", + info->DspVer[0], info->DspVer[1], info->DspVer[2], + info->DspVer[3]); + memcpy(info->HwSerNum, pdspinitmsg->HwSerNum, + HWSERNUMSZ); + memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ); + memcpy(info->eui64, pdspinitmsg->eui64, EUISZ); + DEBUG("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n", + info->eui64[0], info->eui64[1], info->eui64[2], + info->eui64[3], info->eui64[4], info->eui64[5], + info->eui64[6], info->eui64[7]); + dev->net->dev_addr[0] = info->eui64[0]; + dev->net->dev_addr[1] = info->eui64[1]; + dev->net->dev_addr[2] = info->eui64[2]; + dev->net->dev_addr[3] = info->eui64[5]; + dev->net->dev_addr[4] = info->eui64[6]; + dev->net->dev_addr[5] = info->eui64[7]; + + if (ntohs(pdspinitmsg->length) == + (sizeof(struct dsp_init_msg) - 20)) { + memcpy(info->ProductMode, pdspinitmsg->ProductMode, + MODESZ); + memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, CALVERSZ); + memcpy(info->RfCalDate, pdspinitmsg->RfCalDate, + CALDATESZ); + DEBUG("RFCalVer = 0x%2x 0x%2x\n", info->RfCalVer[0], + info->RfCalVer[1]); } + break; + } case DSP_PROVISION:{ - DEBUG - ("ft1000_proc_drvmsg:Command message type = DSP_PROVISION\n"); + DEBUG("ft1000_proc_drvmsg:Command message type = DSP_PROVISION\n"); - /* kick off dspprov routine to start provisioning - * Send provisioning data to DSP - */ - if (list_empty(&info->prov_list) == 0) { - dev->fProvComplete = false; - status = ft1000_dsp_prov(dev); - if (status != 0) - goto out; - } else { - dev->fProvComplete = true; - status = - ft1000_write_register(dev, FT1000_DB_HB, - FT1000_REG_DOORBELL); - DEBUG - ("FT1000:drivermsg:No more DSP provisioning data in dsp image\n"); - } - DEBUG("ft1000_proc_drvmsg:DSP PROVISION is done\n"); - break; + /* kick off dspprov routine to start provisioning + * Send provisioning data to DSP + */ + if (list_empty(&info->prov_list) == 0) { + dev->fProvComplete = false; + status = ft1000_dsp_prov(dev); + if (status != 0) + goto out; + } else { + dev->fProvComplete = true; + status = ft1000_write_register(dev, FT1000_DB_HB, + FT1000_REG_DOORBELL); + DEBUG("FT1000:drivermsg:No more DSP provisioning data in dsp image\n"); } + DEBUG("ft1000_proc_drvmsg:DSP PROVISION is done\n"); + break; + } case DSP_STORE_INFO:{ - DEBUG - ("ft1000_proc_drvmsg:Command message type = DSP_STORE_INFO"); - - DEBUG("FT1000:drivermsg:Got DSP_STORE_INFO\n"); - tempword = ntohs(pdrvmsg->length); - info->DSPInfoBlklen = tempword; - if (tempword < (MAX_DSP_SESS_REC - 4)) { - pmsg = (u16 *) &pdrvmsg->data[0]; - for (i = 0; i < ((tempword + 1) / 2); i++) { - DEBUG - ("FT1000:drivermsg:dsp info data = 0x%x\n", - *pmsg); - info->DSPInfoBlk[i + 10] = *pmsg++; - } - } else { - info->DSPInfoBlklen = 0; + DEBUG("ft1000_proc_drvmsg:Command message type = DSP_STORE_INFO"); + DEBUG("FT1000:drivermsg:Got DSP_STORE_INFO\n"); + tempword = ntohs(pdrvmsg->length); + info->DSPInfoBlklen = tempword; + if (tempword < (MAX_DSP_SESS_REC - 4)) { + pmsg = (u16 *) &pdrvmsg->data[0]; + for (i = 0; i < ((tempword + 1) / 2); i++) { + DEBUG("FT1000:drivermsg:dsp info data = 0x%x\n", *pmsg); + info->DSPInfoBlk[i + 10] = *pmsg++; } - break; + } else { + info->DSPInfoBlklen = 0; } + break; + } case DSP_GET_INFO:{ - DEBUG("FT1000:drivermsg:Got DSP_GET_INFO\n"); - /* copy dsp info block to dsp */ - dev->DrvMsgPend = 1; - /* allow any outstanding ioctl to finish */ + DEBUG("FT1000:drivermsg:Got DSP_GET_INFO\n"); + /* copy dsp info block to dsp */ + dev->DrvMsgPend = 1; + /* allow any outstanding ioctl to finish */ + mdelay(10); + status = ft1000_read_register(dev, &tempword, + FT1000_REG_DOORBELL); + if (tempword & FT1000_DB_DPRAM_TX) { mdelay(10); - status = - ft1000_read_register(dev, &tempword, - FT1000_REG_DOORBELL); + status = ft1000_read_register(dev, &tempword, + FT1000_REG_DOORBELL); if (tempword & FT1000_DB_DPRAM_TX) { mdelay(10); - status = - ft1000_read_register(dev, &tempword, - FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { - mdelay(10); - status = - ft1000_read_register(dev, &tempword, - FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) - break; - } + status = ft1000_read_register(dev, &tempword, + FT1000_REG_DOORBELL); + if (tempword & FT1000_DB_DPRAM_TX) + break; } - /* Put message into Slow Queue - * Form Pseudo header - */ - pmsg = (u16 *) info->DSPInfoBlk; - *pmsg++ = 0; - *pmsg++ = - htons(info->DSPInfoBlklen + 20 + - info->DSPInfoBlklen); - ppseudo_hdr = - (struct pseudo_hdr *)(u16 *) &info->DSPInfoBlk[2]; - ppseudo_hdr->length = - htons(info->DSPInfoBlklen + 4 + - info->DSPInfoBlklen); + } + /* Put message into Slow Queue Form Pseudo header */ + pmsg = (u16 *) info->DSPInfoBlk; + *pmsg++ = 0; + *pmsg++ = htons(info->DSPInfoBlklen + 20 + info->DSPInfoBlklen); + ppseudo_hdr = + (struct pseudo_hdr *)(u16 *) &info->DSPInfoBlk[2]; + ppseudo_hdr->length = htons(info->DSPInfoBlklen + 4 + + info->DSPInfoBlklen); + ppseudo_hdr->source = 0x10; + ppseudo_hdr->destination = 0x20; + ppseudo_hdr->portdest = 0; + ppseudo_hdr->portsrc = 0; + ppseudo_hdr->sh_str_id = 0; + ppseudo_hdr->control = 0; + ppseudo_hdr->rsvd1 = 0; + ppseudo_hdr->rsvd2 = 0; + ppseudo_hdr->qos_class = 0; + /* Insert slow queue sequence number */ + ppseudo_hdr->seq_num = info->squeseqnum++; + /* Insert application id */ + ppseudo_hdr->portsrc = 0; + /* Calculate new checksum */ + ppseudo_hdr->checksum = *pmsg++; + for (i = 1; i < 7; i++) + ppseudo_hdr->checksum ^= *pmsg++; + + info->DSPInfoBlk[10] = 0x7200; + info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen); + status = ft1000_write_dpram32(dev, 0, + (u8 *)&info->DSPInfoBlk[0], + (unsigned short)(info->DSPInfoBlklen + 22)); + status = ft1000_write_register(dev, FT1000_DB_DPRAM_TX, + FT1000_REG_DOORBELL); + dev->DrvMsgPend = 0; + break; + } + case GET_DRV_ERR_RPT_MSG:{ + DEBUG("FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n"); + /* copy driver error message to dsp */ + dev->DrvMsgPend = 1; + /* allow any outstanding ioctl to finish */ + mdelay(10); + status = ft1000_read_register(dev, &tempword, + FT1000_REG_DOORBELL); + if (tempword & FT1000_DB_DPRAM_TX) { + mdelay(10); + status = ft1000_read_register(dev, &tempword, + FT1000_REG_DOORBELL); + if (tempword & FT1000_DB_DPRAM_TX) + mdelay(10); + } + if ((tempword & FT1000_DB_DPRAM_TX) == 0) { + /* Put message into Slow Queue Form Pseudo header */ + pmsg = (u16 *) &tempbuffer[0]; + ppseudo_hdr = (struct pseudo_hdr *)pmsg; + ppseudo_hdr->length = htons(0x0012); ppseudo_hdr->source = 0x10; ppseudo_hdr->destination = 0x20; ppseudo_hdr->portdest = 0; @@ -1337,90 +1361,28 @@ static int ft1000_proc_drvmsg(struct ft1000_usb *dev, u16 size) for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - info->DSPInfoBlk[10] = 0x7200; - info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen); - status = - ft1000_write_dpram32(dev, 0, - (u8 *) &info->DSPInfoBlk[0], - (unsigned short)(info-> - DSPInfoBlklen - + 22)); - status = - ft1000_write_register(dev, FT1000_DB_DPRAM_TX, - FT1000_REG_DOORBELL); - dev->DrvMsgPend = 0; - - break; - } - - case GET_DRV_ERR_RPT_MSG:{ - DEBUG("FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n"); - /* copy driver error message to dsp */ - dev->DrvMsgPend = 1; - /* allow any outstanding ioctl to finish */ - mdelay(10); - status = - ft1000_read_register(dev, &tempword, - FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { - mdelay(10); - status = - ft1000_read_register(dev, &tempword, - FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) - mdelay(10); - } - - if ((tempword & FT1000_DB_DPRAM_TX) == 0) { - /* Put message into Slow Queue - * Form Pseudo header - */ - pmsg = (u16 *) &tempbuffer[0]; - ppseudo_hdr = (struct pseudo_hdr *)pmsg; - ppseudo_hdr->length = htons(0x0012); - ppseudo_hdr->source = 0x10; - ppseudo_hdr->destination = 0x20; - ppseudo_hdr->portdest = 0; - ppseudo_hdr->portsrc = 0; - ppseudo_hdr->sh_str_id = 0; - ppseudo_hdr->control = 0; - ppseudo_hdr->rsvd1 = 0; - ppseudo_hdr->rsvd2 = 0; - ppseudo_hdr->qos_class = 0; - /* Insert slow queue sequence number */ - ppseudo_hdr->seq_num = info->squeseqnum++; - /* Insert application id */ - ppseudo_hdr->portsrc = 0; - /* Calculate new checksum */ - ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) - ppseudo_hdr->checksum ^= *pmsg++; - - pmsg = (u16 *) &tempbuffer[16]; - *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); - *pmsg++ = htons(0x000e); - *pmsg++ = htons(info->DSP_TIME[0]); - *pmsg++ = htons(info->DSP_TIME[1]); - *pmsg++ = htons(info->DSP_TIME[2]); - *pmsg++ = htons(info->DSP_TIME[3]); - convert.byte[0] = info->DspVer[0]; - convert.byte[1] = info->DspVer[1]; - *pmsg++ = convert.wrd; - convert.byte[0] = info->DspVer[2]; - convert.byte[1] = info->DspVer[3]; - *pmsg++ = convert.wrd; - *pmsg++ = htons(info->DrvErrNum); - - card_send_command(dev, - (unsigned char *)&tempbuffer[0], - (u16) (0x0012 + PSEUDOSZ)); - info->DrvErrNum = 0; - } - dev->DrvMsgPend = 0; - - break; + pmsg = (u16 *) &tempbuffer[16]; + *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); + *pmsg++ = htons(0x000e); + *pmsg++ = htons(info->DSP_TIME[0]); + *pmsg++ = htons(info->DSP_TIME[1]); + *pmsg++ = htons(info->DSP_TIME[2]); + *pmsg++ = htons(info->DSP_TIME[3]); + convert.byte[0] = info->DspVer[0]; + convert.byte[1] = info->DspVer[1]; + *pmsg++ = convert.wrd; + convert.byte[0] = info->DspVer[2]; + convert.byte[1] = info->DspVer[3]; + *pmsg++ = convert.wrd; + *pmsg++ = htons(info->DrvErrNum); + + card_send_command(dev, (unsigned char *)&tempbuffer[0], + (u16)(0x0012 + PSEUDOSZ)); + info->DrvErrNum = 0; } - + dev->DrvMsgPend = 0; + break; + } default: break; } -- cgit v1.2.3 From ae6a214b3bbc8978e366b9e0eb4bdc45abdc1559 Mon Sep 17 00:00:00 2001 From: Dulshani Gunawardhana Date: Thu, 31 Oct 2013 00:19:54 +0530 Subject: staging/cxt1e1:Fixes incorrect brace placement This patch fixes the error "This open brace { should be on the above line" detected via checkpatch.pl. Signed-off-by: Dulshani Gunawardhana Reviewed-by: Zach Brown Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/comet.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/comet.c b/drivers/staging/cxt1e1/comet.c index 46a0d92173e0..6b3182aa6dc1 100644 --- a/drivers/staging/cxt1e1/comet.c +++ b/drivers/staging/cxt1e1/comet.c @@ -159,8 +159,7 @@ void init_comet(void *ci, comet_t *comet, u_int32_t port_mode, int clockmaster, /* 60: t1 ALMI cfg */ /* Configure Line Coding */ - switch (port_mode) - { + switch (port_mode) { /* 1 - T1 B8ZS */ case CFG_FRAME_SF: pci_write_32((u_int32_t *) &comet->cdrc_cfg, 0); @@ -286,8 +285,7 @@ void init_comet(void *ci, comet_t *comet, u_int32_t port_mode, int clockmaster, /* 0x30: "BRIF cfg"; 0x20 is 'CMODE', 0x03 is (bit) rate */ /* note "rate bits can only be set once after reset" */ - if (clockmaster) - { + if (clockmaster) { /* CMODE == clockMode, 0=clock master (so all 3 others should be slave) */ /* rate = 1.544 Mb/s */ if (isT1mode) @@ -302,8 +300,7 @@ void init_comet(void *ci, comet_t *comet, u_int32_t port_mode, int clockmaster, /* Master Mode i.e.FPMODE=0 (@0x20) */ pci_write_32((u_int32_t *) &comet->brif_fpcfg, 0x00); - if ((moreParams & CFG_CLK_PORT_MASK) == CFG_CLK_PORT_INTERNAL) - { + if ((moreParams & CFG_CLK_PORT_MASK) == CFG_CLK_PORT_INTERNAL) { if (cxt1e1_log_level >= LOG_SBEBUG12) pr_info(">> %s: clockmaster internal clock\n", __func__); /* internal oscillator */ @@ -422,8 +419,7 @@ WrtXmtWaveformTbl(ci_t *ci, comet_t *comet, { u_int32_t sample, unit; - for (sample = 0; sample < COMET_NUM_SAMPLES; sample++) - { + for (sample = 0; sample < COMET_NUM_SAMPLES; sample++) { for (unit = 0; unit < COMET_NUM_UNITS; unit++) WrtXmtWaveform(ci, comet, sample, unit, table[sample][unit]); } @@ -554,8 +550,7 @@ SetCometOps(comet_t *comet) { volatile u_int8_t rd_value; - if (comet == mConfig.C4Func1Base + (COMET0_OFFSET >> 2)) - { + if (comet == mConfig.C4Func1Base + (COMET0_OFFSET >> 2)) { /* read the BRIF Configuration */ rd_value = (u_int8_t) pci_read_32((u_int32_t *) &comet->brif_cfg); rd_value &= ~0x20; -- cgit v1.2.3 From 89c05d27814c77bd7b6dc86e78d2b0cfbb3e1dea Mon Sep 17 00:00:00 2001 From: Sima Baymani Date: Tue, 5 Nov 2013 21:21:38 +0100 Subject: staging: cxt1e1: comet.h - fix wrong indentation Reindent needed parts of comet.h per checkpatch warnings - whitespace changes only. This patch introduces long line warnings because of the reindentation. Those warnings are fixed by the next patch in series. Signed-off-by: Sima Baymani Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/comet.h | 582 ++++++++++++++++++++--------------------- 1 file changed, 291 insertions(+), 291 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h index 03b9bb77a809..9b2166345f55 100644 --- a/drivers/staging/cxt1e1/comet.h +++ b/drivers/staging/cxt1e1/comet.h @@ -27,298 +27,298 @@ struct s_comet_reg { - VINT32 gbl_cfg; /* 00 Global Cfg */ - VINT32 clkmon; /* 01 Clk Monitor */ - VINT32 rx_opt; /* 02 RX Options */ - VINT32 rx_line_cfg; /* 03 RX Line Interface Cfg */ - VINT32 tx_line_cfg; /* 04 TX Line Interface Cfg */ - VINT32 tx_frpass; /* 05 TX Framing & Bypass Options */ - VINT32 tx_time; /* 06 TX Timing Options */ - VINT32 intr_1; /* 07 Intr Source #1 */ - VINT32 intr_2; /* 08 Intr Source #2 */ - VINT32 intr_3; /* 09 Intr Source #3 */ - VINT32 mdiag; /* 0A Master Diagnostics */ - VINT32 mtest; /* 0B Master Test */ - VINT32 adiag; /* 0C Analog Diagnostics */ - VINT32 rev_id; /* 0D Rev/Chip Id/Global PMON Update */ + VINT32 gbl_cfg; /* 00 Global Cfg */ + VINT32 clkmon; /* 01 Clk Monitor */ + VINT32 rx_opt; /* 02 RX Options */ + VINT32 rx_line_cfg; /* 03 RX Line Interface Cfg */ + VINT32 tx_line_cfg; /* 04 TX Line Interface Cfg */ + VINT32 tx_frpass; /* 05 TX Framing & Bypass Options */ + VINT32 tx_time; /* 06 TX Timing Options */ + VINT32 intr_1; /* 07 Intr Source #1 */ + VINT32 intr_2; /* 08 Intr Source #2 */ + VINT32 intr_3; /* 09 Intr Source #3 */ + VINT32 mdiag; /* 0A Master Diagnostics */ + VINT32 mtest; /* 0B Master Test */ + VINT32 adiag; /* 0C Analog Diagnostics */ + VINT32 rev_id; /* 0D Rev/Chip Id/Global PMON Update */ #define pmon rev_id - VINT32 reset; /* 0E Reset */ - VINT32 prgd_phctl; /* 0F PRGD Positioning/Ctl & HDLC Ctl */ - VINT32 cdrc_cfg; /* 10 CDRC Cfg */ - VINT32 cdrc_ien; /* 11 CDRC Intr Enable */ - VINT32 cdrc_ists; /* 12 CDRC Intr Sts */ - VINT32 cdrc_alos; /* 13 CDRC Alternate Loss of Signal */ - - VINT32 rjat_ists; /* 14 RJAT Intr Sts */ - VINT32 rjat_n1clk; /* 15 RJAT Reference Clk Divisor (N1) Ctl */ - VINT32 rjat_n2clk; /* 16 RJAT Output Clk Divisor (N2) Ctl */ - VINT32 rjat_cfg; /* 17 RJAT Cfg */ - - VINT32 tjat_ists; /* 18 TJAT Intr Sts */ - VINT32 tjat_n1clk; /* 19 TJAT Reference Clk Divisor (N1) Ctl */ - VINT32 tjat_n2clk; /* 1A TJAT Output Clk Divisor (N2) Ctl */ - VINT32 tjat_cfg; /* 1B TJAT Cfg */ - - VINT32 rx_elst_cfg; /* 1C RX-ELST Cfg */ - VINT32 rx_elst_ists; /* 1D RX-ELST Intr Sts */ - VINT32 rx_elst_idle; /* 1E RX-ELST Idle Code */ - VINT32 _rx_elst_res1f; /* 1F RX-ELST Reserved */ - - VINT32 tx_elst_cfg; /* 20 TX-ELST Cfg */ - VINT32 tx_elst_ists; /* 21 TX-ELST Intr Sts */ - VINT32 _tx_elst_res22; /* 22 TX-ELST Reserved */ - VINT32 _tx_elst_res23; /* 23 TX-ELST Reserved */ - VINT32 __res24; /* 24 Reserved */ - VINT32 __res25; /* 25 Reserved */ - VINT32 __res26; /* 26 Reserved */ - VINT32 __res27; /* 27 Reserved */ - - VINT32 rxce1_ctl; /* 28 RXCE RX Data Link 1 Ctl */ - VINT32 rxce1_bits; /* 29 RXCE RX Data Link 1 Bit Select */ - VINT32 rxce2_ctl; /* 2A RXCE RX Data Link 2 Ctl */ - VINT32 rxce2_bits; /* 2B RXCE RX Data Link 2 Bit Select */ - VINT32 rxce3_ctl; /* 2C RXCE RX Data Link 3 Ctl */ - VINT32 rxce3_bits; /* 2D RXCE RX Data Link 3 Bit Select */ - VINT32 _rxce_res2E; /* 2E RXCE Reserved */ - VINT32 _rxce_res2F; /* 2F RXCE Reserved */ - - VINT32 brif_cfg; /* 30 BRIF RX Backplane Cfg */ - VINT32 brif_fpcfg; /* 31 BRIF RX Backplane Frame Pulse Cfg */ - VINT32 brif_pfcfg; /* 32 BRIF RX Backplane Parity/F-Bit Cfg */ - VINT32 brif_tsoff; /* 33 BRIF RX Backplane Time Slot Offset */ - VINT32 brif_boff; /* 34 BRIF RX Backplane Bit Offset */ - VINT32 _brif_res35; /* 35 BRIF RX Backplane Reserved */ - VINT32 _brif_res36; /* 36 BRIF RX Backplane Reserved */ - VINT32 _brif_res37; /* 37 BRIF RX Backplane Reserved */ - - VINT32 txci1_ctl; /* 38 TXCI TX Data Link 1 Ctl */ - VINT32 txci1_bits; /* 39 TXCI TX Data Link 2 Bit Select */ - VINT32 txci2_ctl; /* 3A TXCI TX Data Link 1 Ctl */ - VINT32 txci2_bits; /* 3B TXCI TX Data Link 2 Bit Select */ - VINT32 txci3_ctl; /* 3C TXCI TX Data Link 1 Ctl */ - VINT32 txci3_bits; /* 3D TXCI TX Data Link 2 Bit Select */ - VINT32 _txci_res3E; /* 3E TXCI Reserved */ - VINT32 _txci_res3F; /* 3F TXCI Reserved */ - - VINT32 btif_cfg; /* 40 BTIF TX Backplane Cfg */ - VINT32 btif_fpcfg; /* 41 BTIF TX Backplane Frame Pulse Cfg */ - VINT32 btif_pcfgsts; /* 42 BTIF TX Backplane Parity Cfg & Sts */ - VINT32 btif_tsoff; /* 43 BTIF TX Backplane Time Slot Offset */ - VINT32 btif_boff; /* 44 BTIF TX Backplane Bit Offset */ - VINT32 _btif_res45; /* 45 BTIF TX Backplane Reserved */ - VINT32 _btif_res46; /* 46 BTIF TX Backplane Reserved */ - VINT32 _btif_res47; /* 47 BTIF TX Backplane Reserved */ - VINT32 t1_frmr_cfg; /* 48 T1 FRMR Cfg */ - VINT32 t1_frmr_ien; /* 49 T1 FRMR Intr Enable */ - VINT32 t1_frmr_ists; /* 4A T1 FRMR Intr Sts */ - VINT32 __res_4B; /* 4B Reserved */ - VINT32 ibcd_cfg; /* 4C IBCD Cfg */ - VINT32 ibcd_ies; /* 4D IBCD Intr Enable/Sts */ - VINT32 ibcd_act; /* 4E IBCD Activate Code */ - VINT32 ibcd_deact; /* 4F IBCD Deactivate Code */ - - VINT32 sigx_cfg; /* 50 SIGX Cfg/Change of Signaling State */ - VINT32 sigx_acc_cos; /* 51 SIGX uP Access Sts/Change of Signaling State */ - VINT32 sigx_iac_cos; /* 52 SIGX Channel Indirect - * Addr/Ctl/Change of Signaling State */ - VINT32 sigx_idb_cos; /* 53 SIGX Channel Indirect Data - * Buffer/Change of Signaling State */ - - VINT32 t1_xbas_cfg; /* 54 T1 XBAS Cfg */ - VINT32 t1_xbas_altx; /* 55 T1 XBAS Alarm TX */ - VINT32 t1_xibc_ctl; /* 56 T1 XIBC Ctl */ - VINT32 t1_xibc_lbcode; /* 57 T1 XIBC Loopback Code */ - - VINT32 pmon_ies; /* 58 PMON Intr Enable/Sts */ - VINT32 pmon_fberr; /* 59 PMON Framing Bit Err Cnt */ - VINT32 pmon_feb_lsb; /* 5A PMON OFF/COFA/Far End Block Err Cnt (LSB) */ - VINT32 pmon_feb_msb; /* 5B PMON OFF/COFA/Far End Block Err Cnt (MSB) */ - VINT32 pmon_bed_lsb; /* 5C PMON Bit/Err/CRCE Cnt (LSB) */ - VINT32 pmon_bed_msb; /* 5D PMON Bit/Err/CRCE Cnt (MSB) */ - VINT32 pmon_lvc_lsb; /* 5E PMON LVC Cnt (LSB) */ - VINT32 pmon_lvc_msb; /* 5F PMON LVC Cnt (MSB) */ - - VINT32 t1_almi_cfg; /* 60 T1 ALMI Cfg */ - VINT32 t1_almi_ien; /* 61 T1 ALMI Intr Enable */ - VINT32 t1_almi_ists; /* 62 T1 ALMI Intr Sts */ - VINT32 t1_almi_detsts; /* 63 T1 ALMI Alarm Detection Sts */ - - VINT32 _t1_pdvd_res64; /* 64 T1 PDVD Reserved */ - VINT32 t1_pdvd_ies; /* 65 T1 PDVD Intr Enable/Sts */ - VINT32 _t1_xboc_res66; /* 66 T1 XBOC Reserved */ - VINT32 t1_xboc_code; /* 67 T1 XBOC Code */ - VINT32 _t1_xpde_res68; /* 68 T1 XPDE Reserved */ - VINT32 t1_xpde_ies; /* 69 T1 XPDE Intr Enable/Sts */ - - VINT32 t1_rboc_ena; /* 6A T1 RBOC Enable */ - VINT32 t1_rboc_sts; /* 6B T1 RBOC Code Sts */ - - VINT32 t1_tpsc_cfg; /* 6C TPSC Cfg */ - VINT32 t1_tpsc_sts; /* 6D TPSC uP Access Sts */ - VINT32 t1_tpsc_ciaddr; /* 6E TPSC Channel Indirect - * Addr/Ctl */ - VINT32 t1_tpsc_cidata; /* 6F TPSC Channel Indirect Data - * Buffer */ - VINT32 t1_rpsc_cfg; /* 70 RPSC Cfg */ - VINT32 t1_rpsc_sts; /* 71 RPSC uP Access Sts */ - VINT32 t1_rpsc_ciaddr; /* 72 RPSC Channel Indirect - * Addr/Ctl */ - VINT32 t1_rpsc_cidata; /* 73 RPSC Channel Indirect Data - * Buffer */ - VINT32 __res74; /* 74 Reserved */ - VINT32 __res75; /* 75 Reserved */ - VINT32 __res76; /* 76 Reserved */ - VINT32 __res77; /* 77 Reserved */ - - VINT32 t1_aprm_cfg; /* 78 T1 APRM Cfg/Ctl */ - VINT32 t1_aprm_load; /* 79 T1 APRM Manual Load */ - VINT32 t1_aprm_ists; /* 7A T1 APRM Intr Sts */ - VINT32 t1_aprm_1sec_2; /* 7B T1 APRM One Second Content Octet 2 */ - VINT32 t1_aprm_1sec_3; /* 7C T1 APRM One Second Content Octet 3 */ - VINT32 t1_aprm_1sec_4; /* 7D T1 APRM One Second Content Octet 4 */ - VINT32 t1_aprm_1sec_5; /* 7E T1 APRM One Second Content MSB (Octect 5) */ - VINT32 t1_aprm_1sec_6; /* 7F T1 APRM One Second Content MSB (Octect 6) */ - - VINT32 e1_tran_cfg; /* 80 E1 TRAN Cfg */ - VINT32 e1_tran_txalarm; /* 81 E1 TRAN TX Alarm/Diagnostic Ctl */ - VINT32 e1_tran_intctl; /* 82 E1 TRAN International Ctl */ - VINT32 e1_tran_extrab; /* 83 E1 TRAN Extra Bits Ctl */ - VINT32 e1_tran_ien; /* 84 E1 TRAN Intr Enable */ - VINT32 e1_tran_ists; /* 85 E1 TRAN Intr Sts */ - VINT32 e1_tran_nats; /* 86 E1 TRAN National Bit Codeword - * Select */ - VINT32 e1_tran_nat; /* 87 E1 TRAN National Bit Codeword */ - VINT32 __res88; /* 88 Reserved */ - VINT32 __res89; /* 89 Reserved */ - VINT32 __res8A; /* 8A Reserved */ - VINT32 __res8B; /* 8B Reserved */ - - VINT32 _t1_frmr_res8C; /* 8C T1 FRMR Reserved */ - VINT32 _t1_frmr_res8D; /* 8D T1 FRMR Reserved */ - VINT32 __res8E; /* 8E Reserved */ - VINT32 __res8F; /* 8F Reserved */ - - VINT32 e1_frmr_aopts; /* 90 E1 FRMR Frame Alignment Options */ - VINT32 e1_frmr_mopts; /* 91 E1 FRMR Maintenance Mode Options */ - VINT32 e1_frmr_ien; /* 92 E1 FRMR Framing Sts Intr Enable */ - VINT32 e1_frmr_mien; /* 93 E1 FRMR Maintenance/Alarm Sts Intr Enable */ - VINT32 e1_frmr_ists; /* 94 E1 FRMR Framing Sts Intr Indication */ - VINT32 e1_frmr_mists; /* 95 E1 FRMR Maintenance/Alarm Sts Indication Enable */ - VINT32 e1_frmr_sts; /* 96 E1 FRMR Framing Sts */ - VINT32 e1_frmr_masts; /* 97 E1 FRMR Maintenance/Alarm Sts */ - VINT32 e1_frmr_nat_bits; /* 98 E1 FRMR International/National Bits */ - VINT32 e1_frmr_crc_lsb; /* 99 E1 FRMR CRC Err Cnt - LSB */ - VINT32 e1_frmr_crc_msb; /* 9A E1 FRMR CRC Err Cnt - MSB */ - VINT32 e1_frmr_nat_ien; /* 9B E1 FRMR National Bit Codeword Intr Enables */ - VINT32 e1_frmr_nat_ists; /* 9C E1 FRMR National Bit Codeword Intr/Sts */ - VINT32 e1_frmr_nat; /* 9D E1 FRMR National Bit Codewords */ - VINT32 e1_frmr_fp_ien; /* 9E E1 FRMR Frame Pulse/Alarm Intr Enables */ - VINT32 e1_frmr_fp_ists; /* 9F E1 FRMR Frame Pulse/Alarm Intr/Sts */ - - VINT32 __resA0; /* A0 Reserved */ - VINT32 __resA1; /* A1 Reserved */ - VINT32 __resA2; /* A2 Reserved */ - VINT32 __resA3; /* A3 Reserved */ - VINT32 __resA4; /* A4 Reserved */ - VINT32 __resA5; /* A5 Reserved */ - VINT32 __resA6; /* A6 Reserved */ - VINT32 __resA7; /* A7 Reserved */ - - VINT32 tdpr1_cfg; /* A8 TDPR #1 Cfg */ - VINT32 tdpr1_utl; /* A9 TDPR #1 Upper TX Threshold */ - VINT32 tdpr1_ltl; /* AA TDPR #1 Lower TX Threshold */ - VINT32 tdpr1_ien; /* AB TDPR #1 Intr Enable */ - VINT32 tdpr1_ists; /* AC TDPR #1 Intr Sts/UDR Clear */ - VINT32 tdpr1_data; /* AD TDPR #1 TX Data */ - VINT32 __resAE; /* AE Reserved */ - VINT32 __resAF; /* AF Reserved */ - VINT32 tdpr2_cfg; /* B0 TDPR #2 Cfg */ - VINT32 tdpr2_utl; /* B1 TDPR #2 Upper TX Threshold */ - VINT32 tdpr2_ltl; /* B2 TDPR #2 Lower TX Threshold */ - VINT32 tdpr2_ien; /* B3 TDPR #2 Intr Enable */ - VINT32 tdpr2_ists; /* B4 TDPR #2 Intr Sts/UDR Clear */ - VINT32 tdpr2_data; /* B5 TDPR #2 TX Data */ - VINT32 __resB6; /* B6 Reserved */ - VINT32 __resB7; /* B7 Reserved1 */ - VINT32 tdpr3_cfg; /* B8 TDPR #3 Cfg */ - VINT32 tdpr3_utl; /* B9 TDPR #3 Upper TX Threshold */ - VINT32 tdpr3_ltl; /* BA TDPR #3 Lower TX Threshold */ - VINT32 tdpr3_ien; /* BB TDPR #3 Intr Enable */ - VINT32 tdpr3_ists; /* BC TDPR #3 Intr Sts/UDR Clear */ - VINT32 tdpr3_data; /* BD TDPR #3 TX Data */ - VINT32 __resBE; /* BE Reserved */ - VINT32 __resBF; /* BF Reserved */ - - VINT32 rdlc1_cfg; /* C0 RDLC #1 Cfg */ - VINT32 rdlc1_intctl; /* C1 RDLC #1 Intr Ctl */ - VINT32 rdlc1_sts; /* C2 RDLC #1 Sts */ - VINT32 rdlc1_data; /* C3 RDLC #1 Data */ - VINT32 rdlc1_paddr; /* C4 RDLC #1 Primary Addr Match */ - VINT32 rdlc1_saddr; /* C5 RDLC #1 Secondary Addr Match */ - VINT32 __resC6; /* C6 Reserved */ - VINT32 __resC7; /* C7 Reserved */ - VINT32 rdlc2_cfg; /* C8 RDLC #2 Cfg */ - VINT32 rdlc2_intctl; /* C9 RDLC #2 Intr Ctl */ - VINT32 rdlc2_sts; /* CA RDLC #2 Sts */ - VINT32 rdlc2_data; /* CB RDLC #2 Data */ - VINT32 rdlc2_paddr; /* CC RDLC #2 Primary Addr Match */ - VINT32 rdlc2_saddr; /* CD RDLC #2 Secondary Addr Match */ - VINT32 __resCE; /* CE Reserved */ - VINT32 __resCF; /* CF Reserved */ - VINT32 rdlc3_cfg; /* D0 RDLC #3 Cfg */ - VINT32 rdlc3_intctl; /* D1 RDLC #3 Intr Ctl */ - VINT32 rdlc3_sts; /* D2 RDLC #3 Sts */ - VINT32 rdlc3_data; /* D3 RDLC #3 Data */ - VINT32 rdlc3_paddr; /* D4 RDLC #3 Primary Addr Match */ - VINT32 rdlc3_saddr; /* D5 RDLC #3 Secondary Addr Match */ - - VINT32 csu_cfg; /* D6 CSU Cfg */ - VINT32 _csu_resD7; /* D7 CSU Reserved */ - - VINT32 rlps_idata3; /* D8 RLPS Indirect Data, 24-31 */ - VINT32 rlps_idata2; /* D9 RLPS Indirect Data, 16-23 */ - VINT32 rlps_idata1; /* DA RLPS Indirect Data, 8-15 */ - VINT32 rlps_idata0; /* DB RLPS Indirect Data, 0-7 */ - VINT32 rlps_eqvr; /* DC RLPS Equalizer Voltage Reference - * (E1 missing) */ - VINT32 _rlps_resDD; /* DD RLPS Reserved */ - VINT32 _rlps_resDE; /* DE RLPS Reserved */ - VINT32 _rlps_resDF; /* DF RLPS Reserved */ - - VINT32 prgd_ctl; /* E0 PRGD Ctl */ - VINT32 prgd_ies; /* E1 PRGD Intr Enable/Sts */ - VINT32 prgd_shift_len; /* E2 PRGD Shift Length */ - VINT32 prgd_tap; /* E3 PRGD Tap */ - VINT32 prgd_errin; /* E4 PRGD Err Insertion */ - VINT32 _prgd_resE5; /* E5 PRGD Reserved */ - VINT32 _prgd_resE6; /* E6 PRGD Reserved */ - VINT32 _prgd_resE7; /* E7 PRGD Reserved */ - VINT32 prgd_patin1; /* E8 PRGD Pattern Insertion #1 */ - VINT32 prgd_patin2; /* E9 PRGD Pattern Insertion #2 */ - VINT32 prgd_patin3; /* EA PRGD Pattern Insertion #3 */ - VINT32 prgd_patin4; /* EB PRGD Pattern Insertion #4 */ - VINT32 prgd_patdet1; /* EC PRGD Pattern Detector #1 */ - VINT32 prgd_patdet2; /* ED PRGD Pattern Detector #2 */ - VINT32 prgd_patdet3; /* EE PRGD Pattern Detector #3 */ - VINT32 prgd_patdet4; /* EF PRGD Pattern Detector #4 */ - - VINT32 xlpg_cfg; /* F0 XLPG Line Driver Cfg */ - VINT32 xlpg_ctlsts; /* F1 XLPG Ctl/Sts */ - VINT32 xlpg_pwave_addr; /* F2 XLPG Pulse Waveform Storage Write Addr */ - VINT32 xlpg_pwave_data; /* F3 XLPG Pulse Waveform Storage Data */ - VINT32 xlpg_atest_pctl; /* F4 XLPG Analog Test Positive Ctl */ - VINT32 xlpg_atest_nctl; /* F5 XLPG Analog Test Negative Ctl */ - VINT32 xlpg_fdata_sel; /* F6 XLPG Fuse Data Select */ - VINT32 _xlpg_resF7; /* F7 XLPG Reserved */ - - VINT32 rlps_cfgsts; /* F8 RLPS Cfg & Sts */ - VINT32 rlps_alos_thresh; /* F9 RLPS ALOS Detection/Clearance Threshold */ - VINT32 rlps_alos_dper; /* FA RLPS ALOS Detection Period */ - VINT32 rlps_alos_cper; /* FB RLPS ALOS Clearance Period */ - VINT32 rlps_eq_iaddr; /* FC RLPS Equalization Indirect Addr */ - VINT32 rlps_eq_rwsel; /* FD RLPS Equalization Read/WriteB Select */ - VINT32 rlps_eq_ctlsts; /* FE RLPS Equalizer Loop Sts & Ctl */ - VINT32 rlps_eq_cfg; /* FF RLPS Equalizer Cfg */ + VINT32 reset; /* 0E Reset */ + VINT32 prgd_phctl; /* 0F PRGD Positioning/Ctl & HDLC Ctl */ + VINT32 cdrc_cfg; /* 10 CDRC Cfg */ + VINT32 cdrc_ien; /* 11 CDRC Intr Enable */ + VINT32 cdrc_ists; /* 12 CDRC Intr Sts */ + VINT32 cdrc_alos; /* 13 CDRC Alternate Loss of Signal */ + + VINT32 rjat_ists; /* 14 RJAT Intr Sts */ + VINT32 rjat_n1clk; /* 15 RJAT Reference Clk Divisor (N1) Ctl */ + VINT32 rjat_n2clk; /* 16 RJAT Output Clk Divisor (N2) Ctl */ + VINT32 rjat_cfg; /* 17 RJAT Cfg */ + + VINT32 tjat_ists; /* 18 TJAT Intr Sts */ + VINT32 tjat_n1clk; /* 19 TJAT Reference Clk Divisor (N1) Ctl */ + VINT32 tjat_n2clk; /* 1A TJAT Output Clk Divisor (N2) Ctl */ + VINT32 tjat_cfg; /* 1B TJAT Cfg */ + + VINT32 rx_elst_cfg; /* 1C RX-ELST Cfg */ + VINT32 rx_elst_ists; /* 1D RX-ELST Intr Sts */ + VINT32 rx_elst_idle; /* 1E RX-ELST Idle Code */ + VINT32 _rx_elst_res1f; /* 1F RX-ELST Reserved */ + + VINT32 tx_elst_cfg; /* 20 TX-ELST Cfg */ + VINT32 tx_elst_ists; /* 21 TX-ELST Intr Sts */ + VINT32 _tx_elst_res22; /* 22 TX-ELST Reserved */ + VINT32 _tx_elst_res23; /* 23 TX-ELST Reserved */ + VINT32 __res24; /* 24 Reserved */ + VINT32 __res25; /* 25 Reserved */ + VINT32 __res26; /* 26 Reserved */ + VINT32 __res27; /* 27 Reserved */ + + VINT32 rxce1_ctl; /* 28 RXCE RX Data Link 1 Ctl */ + VINT32 rxce1_bits; /* 29 RXCE RX Data Link 1 Bit Select */ + VINT32 rxce2_ctl; /* 2A RXCE RX Data Link 2 Ctl */ + VINT32 rxce2_bits; /* 2B RXCE RX Data Link 2 Bit Select */ + VINT32 rxce3_ctl; /* 2C RXCE RX Data Link 3 Ctl */ + VINT32 rxce3_bits; /* 2D RXCE RX Data Link 3 Bit Select */ + VINT32 _rxce_res2E; /* 2E RXCE Reserved */ + VINT32 _rxce_res2F; /* 2F RXCE Reserved */ + + VINT32 brif_cfg; /* 30 BRIF RX Backplane Cfg */ + VINT32 brif_fpcfg; /* 31 BRIF RX Backplane Frame Pulse Cfg */ + VINT32 brif_pfcfg; /* 32 BRIF RX Backplane Parity/F-Bit Cfg */ + VINT32 brif_tsoff; /* 33 BRIF RX Backplane Time Slot Offset */ + VINT32 brif_boff; /* 34 BRIF RX Backplane Bit Offset */ + VINT32 _brif_res35; /* 35 BRIF RX Backplane Reserved */ + VINT32 _brif_res36; /* 36 BRIF RX Backplane Reserved */ + VINT32 _brif_res37; /* 37 BRIF RX Backplane Reserved */ + + VINT32 txci1_ctl; /* 38 TXCI TX Data Link 1 Ctl */ + VINT32 txci1_bits; /* 39 TXCI TX Data Link 2 Bit Select */ + VINT32 txci2_ctl; /* 3A TXCI TX Data Link 1 Ctl */ + VINT32 txci2_bits; /* 3B TXCI TX Data Link 2 Bit Select */ + VINT32 txci3_ctl; /* 3C TXCI TX Data Link 1 Ctl */ + VINT32 txci3_bits; /* 3D TXCI TX Data Link 2 Bit Select */ + VINT32 _txci_res3E; /* 3E TXCI Reserved */ + VINT32 _txci_res3F; /* 3F TXCI Reserved */ + + VINT32 btif_cfg; /* 40 BTIF TX Backplane Cfg */ + VINT32 btif_fpcfg; /* 41 BTIF TX Backplane Frame Pulse Cfg */ + VINT32 btif_pcfgsts; /* 42 BTIF TX Backplane Parity Cfg & Sts */ + VINT32 btif_tsoff; /* 43 BTIF TX Backplane Time Slot Offset */ + VINT32 btif_boff; /* 44 BTIF TX Backplane Bit Offset */ + VINT32 _btif_res45; /* 45 BTIF TX Backplane Reserved */ + VINT32 _btif_res46; /* 46 BTIF TX Backplane Reserved */ + VINT32 _btif_res47; /* 47 BTIF TX Backplane Reserved */ + VINT32 t1_frmr_cfg; /* 48 T1 FRMR Cfg */ + VINT32 t1_frmr_ien; /* 49 T1 FRMR Intr Enable */ + VINT32 t1_frmr_ists; /* 4A T1 FRMR Intr Sts */ + VINT32 __res_4B; /* 4B Reserved */ + VINT32 ibcd_cfg; /* 4C IBCD Cfg */ + VINT32 ibcd_ies; /* 4D IBCD Intr Enable/Sts */ + VINT32 ibcd_act; /* 4E IBCD Activate Code */ + VINT32 ibcd_deact; /* 4F IBCD Deactivate Code */ + + VINT32 sigx_cfg; /* 50 SIGX Cfg/Change of Signaling State */ + VINT32 sigx_acc_cos; /* 51 SIGX uP Access Sts/Change of Signaling State */ + VINT32 sigx_iac_cos; /* 52 SIGX Channel Indirect + * Addr/Ctl/Change of Signaling State */ + VINT32 sigx_idb_cos; /* 53 SIGX Channel Indirect Data + * Buffer/Change of Signaling State */ + + VINT32 t1_xbas_cfg; /* 54 T1 XBAS Cfg */ + VINT32 t1_xbas_altx; /* 55 T1 XBAS Alarm TX */ + VINT32 t1_xibc_ctl; /* 56 T1 XIBC Ctl */ + VINT32 t1_xibc_lbcode; /* 57 T1 XIBC Loopback Code */ + + VINT32 pmon_ies; /* 58 PMON Intr Enable/Sts */ + VINT32 pmon_fberr; /* 59 PMON Framing Bit Err Cnt */ + VINT32 pmon_feb_lsb; /* 5A PMON OFF/COFA/Far End Block Err Cnt (LSB) */ + VINT32 pmon_feb_msb; /* 5B PMON OFF/COFA/Far End Block Err Cnt (MSB) */ + VINT32 pmon_bed_lsb; /* 5C PMON Bit/Err/CRCE Cnt (LSB) */ + VINT32 pmon_bed_msb; /* 5D PMON Bit/Err/CRCE Cnt (MSB) */ + VINT32 pmon_lvc_lsb; /* 5E PMON LVC Cnt (LSB) */ + VINT32 pmon_lvc_msb; /* 5F PMON LVC Cnt (MSB) */ + + VINT32 t1_almi_cfg; /* 60 T1 ALMI Cfg */ + VINT32 t1_almi_ien; /* 61 T1 ALMI Intr Enable */ + VINT32 t1_almi_ists; /* 62 T1 ALMI Intr Sts */ + VINT32 t1_almi_detsts; /* 63 T1 ALMI Alarm Detection Sts */ + + VINT32 _t1_pdvd_res64; /* 64 T1 PDVD Reserved */ + VINT32 t1_pdvd_ies; /* 65 T1 PDVD Intr Enable/Sts */ + VINT32 _t1_xboc_res66; /* 66 T1 XBOC Reserved */ + VINT32 t1_xboc_code; /* 67 T1 XBOC Code */ + VINT32 _t1_xpde_res68; /* 68 T1 XPDE Reserved */ + VINT32 t1_xpde_ies; /* 69 T1 XPDE Intr Enable/Sts */ + + VINT32 t1_rboc_ena; /* 6A T1 RBOC Enable */ + VINT32 t1_rboc_sts; /* 6B T1 RBOC Code Sts */ + + VINT32 t1_tpsc_cfg; /* 6C TPSC Cfg */ + VINT32 t1_tpsc_sts; /* 6D TPSC uP Access Sts */ + VINT32 t1_tpsc_ciaddr; /* 6E TPSC Channel Indirect + * Addr/Ctl */ + VINT32 t1_tpsc_cidata; /* 6F TPSC Channel Indirect Data + * Buffer */ + VINT32 t1_rpsc_cfg; /* 70 RPSC Cfg */ + VINT32 t1_rpsc_sts; /* 71 RPSC uP Access Sts */ + VINT32 t1_rpsc_ciaddr; /* 72 RPSC Channel Indirect + * Addr/Ctl */ + VINT32 t1_rpsc_cidata; /* 73 RPSC Channel Indirect Data + * Buffer */ + VINT32 __res74; /* 74 Reserved */ + VINT32 __res75; /* 75 Reserved */ + VINT32 __res76; /* 76 Reserved */ + VINT32 __res77; /* 77 Reserved */ + + VINT32 t1_aprm_cfg; /* 78 T1 APRM Cfg/Ctl */ + VINT32 t1_aprm_load; /* 79 T1 APRM Manual Load */ + VINT32 t1_aprm_ists; /* 7A T1 APRM Intr Sts */ + VINT32 t1_aprm_1sec_2; /* 7B T1 APRM One Second Content Octet 2 */ + VINT32 t1_aprm_1sec_3; /* 7C T1 APRM One Second Content Octet 3 */ + VINT32 t1_aprm_1sec_4; /* 7D T1 APRM One Second Content Octet 4 */ + VINT32 t1_aprm_1sec_5; /* 7E T1 APRM One Second Content MSB (Octect 5) */ + VINT32 t1_aprm_1sec_6; /* 7F T1 APRM One Second Content MSB (Octect 6) */ + + VINT32 e1_tran_cfg; /* 80 E1 TRAN Cfg */ + VINT32 e1_tran_txalarm; /* 81 E1 TRAN TX Alarm/Diagnostic Ctl */ + VINT32 e1_tran_intctl; /* 82 E1 TRAN International Ctl */ + VINT32 e1_tran_extrab; /* 83 E1 TRAN Extra Bits Ctl */ + VINT32 e1_tran_ien; /* 84 E1 TRAN Intr Enable */ + VINT32 e1_tran_ists; /* 85 E1 TRAN Intr Sts */ + VINT32 e1_tran_nats; /* 86 E1 TRAN National Bit Codeword + * Select */ + VINT32 e1_tran_nat; /* 87 E1 TRAN National Bit Codeword */ + VINT32 __res88; /* 88 Reserved */ + VINT32 __res89; /* 89 Reserved */ + VINT32 __res8A; /* 8A Reserved */ + VINT32 __res8B; /* 8B Reserved */ + + VINT32 _t1_frmr_res8C; /* 8C T1 FRMR Reserved */ + VINT32 _t1_frmr_res8D; /* 8D T1 FRMR Reserved */ + VINT32 __res8E; /* 8E Reserved */ + VINT32 __res8F; /* 8F Reserved */ + + VINT32 e1_frmr_aopts; /* 90 E1 FRMR Frame Alignment Options */ + VINT32 e1_frmr_mopts; /* 91 E1 FRMR Maintenance Mode Options */ + VINT32 e1_frmr_ien; /* 92 E1 FRMR Framing Sts Intr Enable */ + VINT32 e1_frmr_mien; /* 93 E1 FRMR Maintenance/Alarm Sts Intr Enable */ + VINT32 e1_frmr_ists; /* 94 E1 FRMR Framing Sts Intr Indication */ + VINT32 e1_frmr_mists; /* 95 E1 FRMR Maintenance/Alarm Sts Indication Enable */ + VINT32 e1_frmr_sts; /* 96 E1 FRMR Framing Sts */ + VINT32 e1_frmr_masts; /* 97 E1 FRMR Maintenance/Alarm Sts */ + VINT32 e1_frmr_nat_bits; /* 98 E1 FRMR International/National Bits */ + VINT32 e1_frmr_crc_lsb; /* 99 E1 FRMR CRC Err Cnt - LSB */ + VINT32 e1_frmr_crc_msb; /* 9A E1 FRMR CRC Err Cnt - MSB */ + VINT32 e1_frmr_nat_ien; /* 9B E1 FRMR National Bit Codeword Intr Enables */ + VINT32 e1_frmr_nat_ists; /* 9C E1 FRMR National Bit Codeword Intr/Sts */ + VINT32 e1_frmr_nat; /* 9D E1 FRMR National Bit Codewords */ + VINT32 e1_frmr_fp_ien; /* 9E E1 FRMR Frame Pulse/Alarm Intr Enables */ + VINT32 e1_frmr_fp_ists; /* 9F E1 FRMR Frame Pulse/Alarm Intr/Sts */ + + VINT32 __resA0; /* A0 Reserved */ + VINT32 __resA1; /* A1 Reserved */ + VINT32 __resA2; /* A2 Reserved */ + VINT32 __resA3; /* A3 Reserved */ + VINT32 __resA4; /* A4 Reserved */ + VINT32 __resA5; /* A5 Reserved */ + VINT32 __resA6; /* A6 Reserved */ + VINT32 __resA7; /* A7 Reserved */ + + VINT32 tdpr1_cfg; /* A8 TDPR #1 Cfg */ + VINT32 tdpr1_utl; /* A9 TDPR #1 Upper TX Threshold */ + VINT32 tdpr1_ltl; /* AA TDPR #1 Lower TX Threshold */ + VINT32 tdpr1_ien; /* AB TDPR #1 Intr Enable */ + VINT32 tdpr1_ists; /* AC TDPR #1 Intr Sts/UDR Clear */ + VINT32 tdpr1_data; /* AD TDPR #1 TX Data */ + VINT32 __resAE; /* AE Reserved */ + VINT32 __resAF; /* AF Reserved */ + VINT32 tdpr2_cfg; /* B0 TDPR #2 Cfg */ + VINT32 tdpr2_utl; /* B1 TDPR #2 Upper TX Threshold */ + VINT32 tdpr2_ltl; /* B2 TDPR #2 Lower TX Threshold */ + VINT32 tdpr2_ien; /* B3 TDPR #2 Intr Enable */ + VINT32 tdpr2_ists; /* B4 TDPR #2 Intr Sts/UDR Clear */ + VINT32 tdpr2_data; /* B5 TDPR #2 TX Data */ + VINT32 __resB6; /* B6 Reserved */ + VINT32 __resB7; /* B7 Reserved1 */ + VINT32 tdpr3_cfg; /* B8 TDPR #3 Cfg */ + VINT32 tdpr3_utl; /* B9 TDPR #3 Upper TX Threshold */ + VINT32 tdpr3_ltl; /* BA TDPR #3 Lower TX Threshold */ + VINT32 tdpr3_ien; /* BB TDPR #3 Intr Enable */ + VINT32 tdpr3_ists; /* BC TDPR #3 Intr Sts/UDR Clear */ + VINT32 tdpr3_data; /* BD TDPR #3 TX Data */ + VINT32 __resBE; /* BE Reserved */ + VINT32 __resBF; /* BF Reserved */ + + VINT32 rdlc1_cfg; /* C0 RDLC #1 Cfg */ + VINT32 rdlc1_intctl; /* C1 RDLC #1 Intr Ctl */ + VINT32 rdlc1_sts; /* C2 RDLC #1 Sts */ + VINT32 rdlc1_data; /* C3 RDLC #1 Data */ + VINT32 rdlc1_paddr; /* C4 RDLC #1 Primary Addr Match */ + VINT32 rdlc1_saddr; /* C5 RDLC #1 Secondary Addr Match */ + VINT32 __resC6; /* C6 Reserved */ + VINT32 __resC7; /* C7 Reserved */ + VINT32 rdlc2_cfg; /* C8 RDLC #2 Cfg */ + VINT32 rdlc2_intctl; /* C9 RDLC #2 Intr Ctl */ + VINT32 rdlc2_sts; /* CA RDLC #2 Sts */ + VINT32 rdlc2_data; /* CB RDLC #2 Data */ + VINT32 rdlc2_paddr; /* CC RDLC #2 Primary Addr Match */ + VINT32 rdlc2_saddr; /* CD RDLC #2 Secondary Addr Match */ + VINT32 __resCE; /* CE Reserved */ + VINT32 __resCF; /* CF Reserved */ + VINT32 rdlc3_cfg; /* D0 RDLC #3 Cfg */ + VINT32 rdlc3_intctl; /* D1 RDLC #3 Intr Ctl */ + VINT32 rdlc3_sts; /* D2 RDLC #3 Sts */ + VINT32 rdlc3_data; /* D3 RDLC #3 Data */ + VINT32 rdlc3_paddr; /* D4 RDLC #3 Primary Addr Match */ + VINT32 rdlc3_saddr; /* D5 RDLC #3 Secondary Addr Match */ + + VINT32 csu_cfg; /* D6 CSU Cfg */ + VINT32 _csu_resD7; /* D7 CSU Reserved */ + + VINT32 rlps_idata3; /* D8 RLPS Indirect Data, 24-31 */ + VINT32 rlps_idata2; /* D9 RLPS Indirect Data, 16-23 */ + VINT32 rlps_idata1; /* DA RLPS Indirect Data, 8-15 */ + VINT32 rlps_idata0; /* DB RLPS Indirect Data, 0-7 */ + VINT32 rlps_eqvr; /* DC RLPS Equalizer Voltage Reference + * (E1 missing) */ + VINT32 _rlps_resDD; /* DD RLPS Reserved */ + VINT32 _rlps_resDE; /* DE RLPS Reserved */ + VINT32 _rlps_resDF; /* DF RLPS Reserved */ + + VINT32 prgd_ctl; /* E0 PRGD Ctl */ + VINT32 prgd_ies; /* E1 PRGD Intr Enable/Sts */ + VINT32 prgd_shift_len; /* E2 PRGD Shift Length */ + VINT32 prgd_tap; /* E3 PRGD Tap */ + VINT32 prgd_errin; /* E4 PRGD Err Insertion */ + VINT32 _prgd_resE5; /* E5 PRGD Reserved */ + VINT32 _prgd_resE6; /* E6 PRGD Reserved */ + VINT32 _prgd_resE7; /* E7 PRGD Reserved */ + VINT32 prgd_patin1; /* E8 PRGD Pattern Insertion #1 */ + VINT32 prgd_patin2; /* E9 PRGD Pattern Insertion #2 */ + VINT32 prgd_patin3; /* EA PRGD Pattern Insertion #3 */ + VINT32 prgd_patin4; /* EB PRGD Pattern Insertion #4 */ + VINT32 prgd_patdet1; /* EC PRGD Pattern Detector #1 */ + VINT32 prgd_patdet2; /* ED PRGD Pattern Detector #2 */ + VINT32 prgd_patdet3; /* EE PRGD Pattern Detector #3 */ + VINT32 prgd_patdet4; /* EF PRGD Pattern Detector #4 */ + + VINT32 xlpg_cfg; /* F0 XLPG Line Driver Cfg */ + VINT32 xlpg_ctlsts; /* F1 XLPG Ctl/Sts */ + VINT32 xlpg_pwave_addr; /* F2 XLPG Pulse Waveform Storage Write Addr */ + VINT32 xlpg_pwave_data; /* F3 XLPG Pulse Waveform Storage Data */ + VINT32 xlpg_atest_pctl; /* F4 XLPG Analog Test Positive Ctl */ + VINT32 xlpg_atest_nctl; /* F5 XLPG Analog Test Negative Ctl */ + VINT32 xlpg_fdata_sel; /* F6 XLPG Fuse Data Select */ + VINT32 _xlpg_resF7; /* F7 XLPG Reserved */ + + VINT32 rlps_cfgsts; /* F8 RLPS Cfg & Sts */ + VINT32 rlps_alos_thresh; /* F9 RLPS ALOS Detection/Clearance Threshold */ + VINT32 rlps_alos_dper; /* FA RLPS ALOS Detection Period */ + VINT32 rlps_alos_cper; /* FB RLPS ALOS Clearance Period */ + VINT32 rlps_eq_iaddr; /* FC RLPS Equalization Indirect Addr */ + VINT32 rlps_eq_rwsel; /* FD RLPS Equalization Read/WriteB Select */ + VINT32 rlps_eq_ctlsts; /* FE RLPS Equalizer Loop Sts & Ctl */ + VINT32 rlps_eq_cfg; /* FF RLPS Equalizer Cfg */ }; typedef struct s_comet_reg comet_t; -- cgit v1.2.3 From 353808bf5367c046b7ea7d8189cad2531adedbb9 Mon Sep 17 00:00:00 2001 From: Sima Baymani Date: Tue, 5 Nov 2013 21:22:12 +0100 Subject: staging: cxt1e1: comet.h - fix long lines warning Fix long lines warnings from checkpatch which were introduced in previous patch in series due to reindentation. Signed-off-by: Sima Baymani Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/comet.h | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h index 9b2166345f55..70829078e91e 100644 --- a/drivers/staging/cxt1e1/comet.h +++ b/drivers/staging/cxt1e1/comet.h @@ -118,7 +118,8 @@ struct s_comet_reg VINT32 ibcd_deact; /* 4F IBCD Deactivate Code */ VINT32 sigx_cfg; /* 50 SIGX Cfg/Change of Signaling State */ - VINT32 sigx_acc_cos; /* 51 SIGX uP Access Sts/Change of Signaling State */ + VINT32 sigx_acc_cos; /* 51 SIGX + * uP Access Sts/Change of Signaling State */ VINT32 sigx_iac_cos; /* 52 SIGX Channel Indirect * Addr/Ctl/Change of Signaling State */ VINT32 sigx_idb_cos; /* 53 SIGX Channel Indirect Data @@ -131,8 +132,10 @@ struct s_comet_reg VINT32 pmon_ies; /* 58 PMON Intr Enable/Sts */ VINT32 pmon_fberr; /* 59 PMON Framing Bit Err Cnt */ - VINT32 pmon_feb_lsb; /* 5A PMON OFF/COFA/Far End Block Err Cnt (LSB) */ - VINT32 pmon_feb_msb; /* 5B PMON OFF/COFA/Far End Block Err Cnt (MSB) */ + VINT32 pmon_feb_lsb; /* 5A PMON + * OFF/COFA/Far End Block Err Cnt (LSB) */ + VINT32 pmon_feb_msb; /* 5B PMON + * OFF/COFA/Far End Block Err Cnt (MSB) */ VINT32 pmon_bed_lsb; /* 5C PMON Bit/Err/CRCE Cnt (LSB) */ VINT32 pmon_bed_msb; /* 5D PMON Bit/Err/CRCE Cnt (MSB) */ VINT32 pmon_lvc_lsb; /* 5E PMON LVC Cnt (LSB) */ @@ -176,8 +179,10 @@ struct s_comet_reg VINT32 t1_aprm_1sec_2; /* 7B T1 APRM One Second Content Octet 2 */ VINT32 t1_aprm_1sec_3; /* 7C T1 APRM One Second Content Octet 3 */ VINT32 t1_aprm_1sec_4; /* 7D T1 APRM One Second Content Octet 4 */ - VINT32 t1_aprm_1sec_5; /* 7E T1 APRM One Second Content MSB (Octect 5) */ - VINT32 t1_aprm_1sec_6; /* 7F T1 APRM One Second Content MSB (Octect 6) */ + VINT32 t1_aprm_1sec_5; /* 7E T1 APRM + * One Second Content MSB (Octect 5) */ + VINT32 t1_aprm_1sec_6; /* 7F T1 APRM + * One Second Content MSB (Octect 6) */ VINT32 e1_tran_cfg; /* 80 E1 TRAN Cfg */ VINT32 e1_tran_txalarm; /* 81 E1 TRAN TX Alarm/Diagnostic Ctl */ @@ -201,18 +206,23 @@ struct s_comet_reg VINT32 e1_frmr_aopts; /* 90 E1 FRMR Frame Alignment Options */ VINT32 e1_frmr_mopts; /* 91 E1 FRMR Maintenance Mode Options */ VINT32 e1_frmr_ien; /* 92 E1 FRMR Framing Sts Intr Enable */ - VINT32 e1_frmr_mien; /* 93 E1 FRMR Maintenance/Alarm Sts Intr Enable */ + VINT32 e1_frmr_mien; /* 93 E1 FRMR + * Maintenance/Alarm Sts Intr Enable */ VINT32 e1_frmr_ists; /* 94 E1 FRMR Framing Sts Intr Indication */ - VINT32 e1_frmr_mists; /* 95 E1 FRMR Maintenance/Alarm Sts Indication Enable */ + VINT32 e1_frmr_mists; /* 95 E1 FRMR + * Maintenance/Alarm Sts Indication Enable */ VINT32 e1_frmr_sts; /* 96 E1 FRMR Framing Sts */ VINT32 e1_frmr_masts; /* 97 E1 FRMR Maintenance/Alarm Sts */ VINT32 e1_frmr_nat_bits; /* 98 E1 FRMR International/National Bits */ VINT32 e1_frmr_crc_lsb; /* 99 E1 FRMR CRC Err Cnt - LSB */ VINT32 e1_frmr_crc_msb; /* 9A E1 FRMR CRC Err Cnt - MSB */ - VINT32 e1_frmr_nat_ien; /* 9B E1 FRMR National Bit Codeword Intr Enables */ - VINT32 e1_frmr_nat_ists; /* 9C E1 FRMR National Bit Codeword Intr/Sts */ + VINT32 e1_frmr_nat_ien; /* 9B E1 FRMR + * National Bit Codeword Intr Enables */ + VINT32 e1_frmr_nat_ists; /* 9C E1 FRMR + * National Bit Codeword Intr/Sts */ VINT32 e1_frmr_nat; /* 9D E1 FRMR National Bit Codewords */ - VINT32 e1_frmr_fp_ien; /* 9E E1 FRMR Frame Pulse/Alarm Intr Enables */ + VINT32 e1_frmr_fp_ien; /* 9E E1 FRMR + * Frame Pulse/Alarm Intr Enables */ VINT32 e1_frmr_fp_ists; /* 9F E1 FRMR Frame Pulse/Alarm Intr/Sts */ VINT32 __resA0; /* A0 Reserved */ @@ -304,7 +314,8 @@ struct s_comet_reg VINT32 xlpg_cfg; /* F0 XLPG Line Driver Cfg */ VINT32 xlpg_ctlsts; /* F1 XLPG Ctl/Sts */ - VINT32 xlpg_pwave_addr; /* F2 XLPG Pulse Waveform Storage Write Addr */ + VINT32 xlpg_pwave_addr; /* F2 XLPG + * Pulse Waveform Storage Write Addr */ VINT32 xlpg_pwave_data; /* F3 XLPG Pulse Waveform Storage Data */ VINT32 xlpg_atest_pctl; /* F4 XLPG Analog Test Positive Ctl */ VINT32 xlpg_atest_nctl; /* F5 XLPG Analog Test Negative Ctl */ @@ -312,7 +323,8 @@ struct s_comet_reg VINT32 _xlpg_resF7; /* F7 XLPG Reserved */ VINT32 rlps_cfgsts; /* F8 RLPS Cfg & Sts */ - VINT32 rlps_alos_thresh; /* F9 RLPS ALOS Detection/Clearance Threshold */ + VINT32 rlps_alos_thresh; /* F9 RLPS + * ALOS Detection/Clearance Threshold */ VINT32 rlps_alos_dper; /* FA RLPS ALOS Detection Period */ VINT32 rlps_alos_cper; /* FB RLPS ALOS Clearance Period */ VINT32 rlps_eq_iaddr; /* FC RLPS Equalization Indirect Addr */ -- cgit v1.2.3 From af2594402d61d28bae5e784c3eb9dc80d92038eb Mon Sep 17 00:00:00 2001 From: Sima Baymani Date: Tue, 5 Nov 2013 21:22:56 +0100 Subject: staging: cxt1e1: comet,h - fix placement of braces Fix bad placement of braces per checkpatch warning. Signed-off-by: Sima Baymani Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/comet.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h index 70829078e91e..4ed78297053b 100644 --- a/drivers/staging/cxt1e1/comet.h +++ b/drivers/staging/cxt1e1/comet.h @@ -25,8 +25,7 @@ #define VINT32 volatile u_int32_t -struct s_comet_reg -{ +struct s_comet_reg { VINT32 gbl_cfg; /* 00 Global Cfg */ VINT32 clkmon; /* 01 Clk Monitor */ VINT32 rx_opt; /* 02 RX Options */ -- cgit v1.2.3 From 987e8bef1ce93299408b75ff1b08592aba7e3c5a Mon Sep 17 00:00:00 2001 From: Sima Baymani Date: Tue, 5 Nov 2013 21:49:16 +0100 Subject: staging: cxt1e1: remove typedef comet_t Remove typedef declaration per checkpatch warning. Built and loaded. Signed-off-by: Sima Baymani Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/comet.c | 18 +++++++++--------- drivers/staging/cxt1e1/comet.h | 4 +--- drivers/staging/cxt1e1/functions.c | 2 +- drivers/staging/cxt1e1/pmcc4_drv.c | 10 +++++----- drivers/staging/cxt1e1/pmcc4_private.h | 2 +- 5 files changed, 17 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/comet.c b/drivers/staging/cxt1e1/comet.c index 6b3182aa6dc1..229435ce8583 100644 --- a/drivers/staging/cxt1e1/comet.c +++ b/drivers/staging/cxt1e1/comet.c @@ -28,9 +28,9 @@ extern int cxt1e1_log_level; #define COMET_NUM_UNITS 5 /* Number of points per entry in table */ /* forward references */ -static void SetPwrLevel(comet_t *comet); -static void WrtRcvEqualizerTbl(ci_t *ci, comet_t *comet, u_int32_t *table); -static void WrtXmtWaveformTbl(ci_t *ci, comet_t *comet, u_int8_t table[COMET_NUM_SAMPLES][COMET_NUM_UNITS]); +static void SetPwrLevel(struct s_comet_reg *comet); +static void WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet, u_int32_t *table); +static void WrtXmtWaveformTbl(ci_t *ci, struct s_comet_reg *comet, u_int8_t table[COMET_NUM_SAMPLES][COMET_NUM_UNITS]); void *TWV_table[12] = { @@ -58,7 +58,7 @@ lbo_tbl_lkup(int t1, int lbo) { return lbo - 1; } -void init_comet(void *ci, comet_t *comet, u_int32_t port_mode, int clockmaster, +void init_comet(void *ci, struct s_comet_reg *comet, u_int32_t port_mode, int clockmaster, u_int8_t moreParams) { u_int8_t isT1mode; @@ -396,7 +396,7 @@ void init_comet(void *ci, comet_t *comet, u_int32_t port_mode, int clockmaster, ** Returns: Nothing */ static void -WrtXmtWaveform(ci_t *ci, comet_t *comet, u_int32_t sample, u_int32_t unit, u_int8_t data) +WrtXmtWaveform(ci_t *ci, struct s_comet_reg *comet, u_int32_t sample, u_int32_t unit, u_int8_t data) { u_int8_t WaveformAddr; @@ -414,7 +414,7 @@ WrtXmtWaveform(ci_t *ci, comet_t *comet, u_int32_t sample, u_int32_t unit, u_int ** Returns: Nothing */ static void -WrtXmtWaveformTbl(ci_t *ci, comet_t *comet, +WrtXmtWaveformTbl(ci_t *ci, struct s_comet_reg *comet, u_int8_t table[COMET_NUM_SAMPLES][COMET_NUM_UNITS]) { u_int32_t sample, unit; @@ -440,7 +440,7 @@ WrtXmtWaveformTbl(ci_t *ci, comet_t *comet, */ static void -WrtRcvEqualizerTbl(ci_t *ci, comet_t *comet, u_int32_t *table) +WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet, u_int32_t *table) { u_int32_t ramaddr; volatile u_int32_t value; @@ -504,7 +504,7 @@ WrtRcvEqualizerTbl(ci_t *ci, comet_t *comet, u_int32_t *table) */ static void -SetPwrLevel(comet_t *comet) +SetPwrLevel(struct s_comet_reg *comet) { volatile u_int32_t temp; @@ -546,7 +546,7 @@ SetPwrLevel(comet_t *comet) */ #if 0 static void -SetCometOps(comet_t *comet) +SetCometOps(struct s_comet_reg *comet) { volatile u_int8_t rd_value; diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h index 4ed78297053b..d5d286e47a4b 100644 --- a/drivers/staging/cxt1e1/comet.h +++ b/drivers/staging/cxt1e1/comet.h @@ -332,8 +332,6 @@ struct s_comet_reg { VINT32 rlps_eq_cfg; /* FF RLPS Equalizer Cfg */ }; -typedef struct s_comet_reg comet_t; - /* 00AH: MDIAG Register bit definitions */ #define COMET_MDIAG_ID5 0x40 #define COMET_MDIAG_LBMASK 0x3F @@ -349,7 +347,7 @@ typedef struct s_comet_reg comet_t; #ifdef __KERNEL__ extern void -init_comet(void *, comet_t *, u_int32_t, int, u_int8_t); +init_comet(void *, struct s_comet_reg *, u_int32_t, int, u_int8_t); #endif #endif /* _INC_COMET_H_ */ diff --git a/drivers/staging/cxt1e1/functions.c b/drivers/staging/cxt1e1/functions.c index d021b312ffa2..95218e283966 100644 --- a/drivers/staging/cxt1e1/functions.c +++ b/drivers/staging/cxt1e1/functions.c @@ -274,7 +274,7 @@ VMETRO_TRACE (void *x) void VMETRO_TRIGGER (ci_t *ci, int x) { - comet_t *comet; + struct s_comet_reg *comet; volatile u_int32_t data; comet = ci->port[0].cometbase; /* default to COMET # 0 */ diff --git a/drivers/staging/cxt1e1/pmcc4_drv.c b/drivers/staging/cxt1e1/pmcc4_drv.c index 4028ea11c442..a9d95753be20 100644 --- a/drivers/staging/cxt1e1/pmcc4_drv.c +++ b/drivers/staging/cxt1e1/pmcc4_drv.c @@ -194,7 +194,7 @@ checkPorts (ci_t *ci) * alarms conflicts with NCOMM's interrupt servicing implementation. */ - comet_t *comet; + struct s_comet_reg *comet; volatile u_int32_t value; u_int32_t copyVal, LEDval; @@ -507,7 +507,7 @@ c4_cleanup (void) int c4_get_portcfg (ci_t *ci) { - comet_t *comet; + struct s_comet_reg *comet; int portnum, mask; u_int32_t wdata, rdata; @@ -561,7 +561,7 @@ c4_init (ci_t *ci, u_char *func0, u_char *func1) for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++) { pi = &ci->port[portnum]; - pi->cometbase = (comet_t *) ((u_int32_t *) (func1 + COMET_OFFSET (portnum))); + pi->cometbase = (struct s_comet_reg *) ((u_int32_t *) (func1 + COMET_OFFSET (portnum))); pi->reg = (struct musycc_globalr *) ((u_char *) ci->reg + (portnum * 0x800)); pi->portnum = portnum; pi->p.portnum = portnum; @@ -693,7 +693,7 @@ c4_init2 (ci_t *ci) int c4_loop_port (ci_t *ci, int portnum, u_int8_t cmd) { - comet_t *comet; + struct s_comet_reg *comet; volatile u_int32_t loopValue; comet = ci->port[portnum].cometbase; @@ -752,7 +752,7 @@ c4_loop_port (ci_t *ci, int portnum, u_int8_t cmd) status_t c4_frame_rw (ci_t *ci, struct sbecom_port_param *pp) { - comet_t *comet; + struct s_comet_reg *comet; volatile u_int32_t data; if (pp->portnum >= ci->max_port)/* sanity check */ diff --git a/drivers/staging/cxt1e1/pmcc4_private.h b/drivers/staging/cxt1e1/pmcc4_private.h index b2b6e3702630..7edbd4e492e3 100644 --- a/drivers/staging/cxt1e1/pmcc4_private.h +++ b/drivers/staging/cxt1e1/pmcc4_private.h @@ -133,7 +133,7 @@ struct c4_port_info void *regram_saved; /* Original malloc value may have non-2KB * boundary. Need to save for use when * freeing. */ - comet_t *cometbase; + struct s_comet_reg *cometbase; struct sbe_card_info *up; /* -- cgit v1.2.3 From 9b38da66d0011cd7c8ba04aa92bd0d362bd6be17 Mon Sep 17 00:00:00 2001 From: Sima Baymani Date: Tue, 5 Nov 2013 21:28:56 +0100 Subject: staging: cxt1e1: fix long lines warning Break up long lines per checkpatch warnings. Signed-off-by: Sima Baymani Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/comet.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/comet.c b/drivers/staging/cxt1e1/comet.c index 229435ce8583..c4c8c0f9c959 100644 --- a/drivers/staging/cxt1e1/comet.c +++ b/drivers/staging/cxt1e1/comet.c @@ -302,13 +302,15 @@ void init_comet(void *ci, struct s_comet_reg *comet, u_int32_t port_mode, int cl pci_write_32((u_int32_t *) &comet->brif_fpcfg, 0x00); if ((moreParams & CFG_CLK_PORT_MASK) == CFG_CLK_PORT_INTERNAL) { if (cxt1e1_log_level >= LOG_SBEBUG12) - pr_info(">> %s: clockmaster internal clock\n", __func__); + pr_info(">> %s: clockmaster internal clock\n", + __func__); /* internal oscillator */ pci_write_32((u_int32_t *) &comet->tx_time, 0x0d); } else { /* external clock source */ if (cxt1e1_log_level >= LOG_SBEBUG12) - pr_info(">> %s: clockmaster external clock\n", __func__); + pr_info(">> %s: clockmaster external clock\n", + __func__); /* loop timing(external) */ pci_write_32((u_int32_t *) &comet->tx_time, 0x09); } @@ -421,11 +423,13 @@ WrtXmtWaveformTbl(ci_t *ci, struct s_comet_reg *comet, for (sample = 0; sample < COMET_NUM_SAMPLES; sample++) { for (unit = 0; unit < COMET_NUM_UNITS; unit++) - WrtXmtWaveform(ci, comet, sample, unit, table[sample][unit]); + WrtXmtWaveform(ci, comet, sample, unit, + table[sample][unit]); } /* Enable transmitter and set output amplitude */ - pci_write_32((u_int32_t *) &comet->xlpg_cfg, table[COMET_NUM_SAMPLES][0]); + pci_write_32((u_int32_t *) &comet->xlpg_cfg, + table[COMET_NUM_SAMPLES][0]); } @@ -453,7 +457,8 @@ WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet, u_int32_t *table) /* for write order preservation when Optimizing driver */ pci_flush_write(ci); /* write the addr, initiate a read */ - pci_write_32((u_int32_t *) &comet->rlps_eq_iaddr, (u_int8_t) ramaddr); + pci_write_32((u_int32_t *) &comet->rlps_eq_iaddr, + (u_int8_t) ramaddr); /* for write order preservation when Optimizing driver */ pci_flush_write(ci); /* @@ -466,9 +471,12 @@ WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet, u_int32_t *table) } value = *table++; - pci_write_32((u_int32_t *) &comet->rlps_idata3, (u_int8_t) (value >> 24)); - pci_write_32((u_int32_t *) &comet->rlps_idata2, (u_int8_t) (value >> 16)); - pci_write_32((u_int32_t *) &comet->rlps_idata1, (u_int8_t) (value >> 8)); + pci_write_32((u_int32_t *) &comet->rlps_idata3, + (u_int8_t) (value >> 24)); + pci_write_32((u_int32_t *) &comet->rlps_idata2, + (u_int8_t) (value >> 16)); + pci_write_32((u_int32_t *) &comet->rlps_idata1, + (u_int8_t) (value >> 8)); pci_write_32((u_int32_t *) &comet->rlps_idata0, (u_int8_t) value); /* for write order preservation when Optimizing driver */ pci_flush_write(ci); @@ -480,7 +488,8 @@ WrtRcvEqualizerTbl(ci_t *ci, struct s_comet_reg *comet, u_int32_t *table) /* for write order preservation when optimizing driver */ pci_flush_write(ci); /* write the addr, initiate a read */ - pci_write_32((u_int32_t *) &comet->rlps_eq_iaddr, (u_int8_t) ramaddr); + pci_write_32((u_int32_t *) &comet->rlps_eq_iaddr, + (u_int8_t) ramaddr); /* for write order preservation when optimizing driver */ pci_flush_write(ci); -- cgit v1.2.3 From 5354cb6423fbe590be8e332858a5795577919f84 Mon Sep 17 00:00:00 2001 From: Archana kumari Date: Thu, 31 Oct 2013 00:34:08 +0530 Subject: staging: imx-drm: Fix warning for static const char * array in imx-ldb.c This patch fixes the warning "static const char * array should probably be static const char * const" in imx-ldb.c. Signed-off-by: Archana kumari Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-ldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c index 654bf03e05ff..655d0c0f4ace 100644 --- a/drivers/staging/imx-drm/imx-ldb.c +++ b/drivers/staging/imx-drm/imx-ldb.c @@ -414,7 +414,7 @@ enum { LVDS_BIT_MAP_JEIDA }; -static const char *imx_ldb_bit_mappings[] = { +static const char * const imx_ldb_bit_mappings[] = { [LVDS_BIT_MAP_SPWG] = "spwg", [LVDS_BIT_MAP_JEIDA] = "jeida", }; -- cgit v1.2.3 From 49f4a9c81c1a83854ddf9510b92199368262abb2 Mon Sep 17 00:00:00 2001 From: Sima Baymani Date: Sun, 3 Nov 2013 11:18:57 +0100 Subject: staging: imx-drm: remove unnecessary braces Fix checkpatch warning by removing unnecessary braces. Compile-tested the single file. Signed-off-by: Sima Baymani Reviewed-by: Josh Triplett Reviewed-by: Archana Kumari Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-ldb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c index 655d0c0f4ace..7e593296ac47 100644 --- a/drivers/staging/imx-drm/imx-ldb.c +++ b/drivers/staging/imx-drm/imx-ldb.c @@ -167,9 +167,8 @@ static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, /* set display clock mux to LDB input clock */ ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]); - if (ret) { + if (ret) dev_err(ldb->dev, "unable to set di%d parent clock to ldb_di%d\n", mux, chno); - } } static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) -- cgit v1.2.3 From 0c4c9350c1080bf9a10fcfb73d4cd963bdce9c35 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Thu, 31 Oct 2013 09:01:41 +0530 Subject: drivers : staging :rtl8187se : r8180_core.c : remove space before semicolon This patch removes the checkpatch.pl warning space prohibited before semicolon. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/r8180_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 76a67386b927..2462ced68215 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -1855,7 +1855,7 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority, if (remain == len && !descfrag) { ownbit_flag = false; - *tail = *tail | (1<<29) ; /* fist segment of the packet */ + *tail = *tail | (1<<29); /* fist segment of the packet */ *tail = *tail | (len); } else { ownbit_flag = true; -- cgit v1.2.3 From 8e0e3aeede138c5ccc45fc1394c53c848a9f4608 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:44:38 +0530 Subject: Staging: rtl8187se: Fix C99 style commenting in dot11d.c This patch fixes the following checkpatch.pl issues in ieee80211/dot11d.c- ERROR: do not use C99 // comments Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 68 ++++++++++++++-------------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index 9d2d5c58add2..b623080247f5 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -1,11 +1,10 @@ -//----------------------------------------------------------------------------- -// File: -// Dot11d.c -// -// Description: -// Implement 802.11d. -// -//----------------------------------------------------------------------------- +/* + * File: + * Dot11d.c + * + * Description: + * Implement 802.11d + */ #include "dot11d.h" @@ -25,20 +24,20 @@ Dot11d_Init(struct ieee80211_device *ieee) printk("Dot11d_Init()\n"); } -// -// Description: -// Reset to the state as we are just entering a regulatory domain. -// +/* + * Description: + * Reset to the state as we are just entering a regulatory domain. + */ void Dot11d_Reset(struct ieee80211_device *ieee) { u32 i; PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - // Clear old channel map + /* Clear old channel map */ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - // Set new channel map + /* Set new channel map */ for (i = 1; i <= 11; i++) (pDot11dInfo->channel_map)[i] = 1; @@ -48,22 +47,20 @@ Dot11d_Reset(struct ieee80211_device *ieee) pDot11dInfo->State = DOT11D_STATE_NONE; pDot11dInfo->CountryIeLen = 0; RESET_CIE_WATCHDOG(ieee); - - //printk("Dot11d_Reset()\n"); } -// -// Description: -// Update country IE from Beacon or Probe Response -// and configure PHY for operation in the regulatory domain. -// -// TODO: -// Configure Tx power. -// -// Assumption: -// 1. IS_DOT11D_ENABLE() is TRUE. -// 2. Input IE is an valid one. -// +/* + * Description: + * Update country IE from Beacon or Probe Response and configure PHY for + * operation in the regulatory domain. + * + * TODO: + * Configure Tx power. + * + * Assumption: + * 1. IS_DOT11D_ENABLE() is TRUE. + * 2. Input IE is an valid one. + */ void Dot11d_UpdateCountryIe( struct ieee80211_device *dev, @@ -85,17 +82,23 @@ Dot11d_UpdateCountryIe( memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); MaxChnlNum = 0; - NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. + NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */ pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); for (i = 0; i < NumTriples; i++) { if (MaxChnlNum >= pTriple->FirstChnl) { - // It is not in a monotonically increasing order, so stop processing. + /* + * It is not in a monotonically increasing order, + * so stop processing. + */ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); Dot11d_Reset(dev); return; } if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) { - // It is not a valid set of channel id, so stop processing. + /* + * It is not a valid set of channel id, + * so stop processing + */ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); Dot11d_Reset(dev); return; @@ -110,7 +113,6 @@ Dot11d_UpdateCountryIe( pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3); } #if 1 - //printk("Dot11d_UpdateCountryIe(): Channel List:\n"); printk("Channel List:"); for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) if (pDot11dInfo->channel_map[i] > 0) @@ -160,7 +162,7 @@ DOT11D_ScanComplete( case DOT11D_STATE_DONE: if (GET_CIE_WATCHDOG(dev) == 0) { - // Reset country IE if previous one is gone. + /* Reset country IE if previous one is gone. */ Dot11d_Reset(dev); } break; -- cgit v1.2.3 From d58df7513d461bbec33c4d1d2410f6a441dc3b90 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:46:00 +0530 Subject: Staging: rtl8187se: Fix printk() should include KERN_ facility level This patch fixes the following checkpatch.pl issues in ieee80211/dot11d.c- WARNING: printk() should include KERN_ facility level Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index b623080247f5..c8874b80486a 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -21,7 +21,7 @@ Dot11d_Init(struct ieee80211_device *ieee) memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); RESET_CIE_WATCHDOG(ieee); - printk("Dot11d_Init()\n"); + netdev_info(ieee->dev, "Dot11d_Init()\n"); } /* @@ -74,7 +74,7 @@ Dot11d_UpdateCountryIe( PCHNL_TXPOWER_TRIPLE pTriple; if ((CoutryIeLen - 3)%3 != 0) { - printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); + netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); Dot11d_Reset(dev); return; } @@ -90,7 +90,8 @@ Dot11d_UpdateCountryIe( * It is not in a monotonically increasing order, * so stop processing. */ - printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); + netdev_info(dev->dev, + "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); Dot11d_Reset(dev); return; } @@ -99,7 +100,8 @@ Dot11d_UpdateCountryIe( * It is not a valid set of channel id, * so stop processing */ - printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); + netdev_info(dev->dev, + "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); Dot11d_Reset(dev); return; } @@ -113,11 +115,11 @@ Dot11d_UpdateCountryIe( pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3); } #if 1 - printk("Channel List:"); + netdev_info(dev->dev, "Channel List:"); for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) if (pDot11dInfo->channel_map[i] > 0) - printk(" %d", i); - printk("\n"); + netdev_info(dev->dev, " %d", i); + netdev_info(dev->dev, "\n"); #endif UPDATE_CIE_SRC(dev, pTaddr); @@ -137,7 +139,7 @@ DOT11D_GetMaxTxPwrInDbm( u8 MaxTxPwrInDbm = 255; if (MAX_CHANNEL_NUMBER < Channel) { - printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); + netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); return MaxTxPwrInDbm; } if (pDot11dInfo->channel_map[Channel]) { @@ -179,7 +181,7 @@ int IsLegalChannel( PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); if (MAX_CHANNEL_NUMBER < channel) { - printk("IsLegalChannel(): Invalid Channel\n"); + netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n"); return 0; } if (pDot11dInfo->channel_map[channel] > 0) @@ -204,7 +206,7 @@ int ToLegalChannel( } if (MAX_CHANNEL_NUMBER < channel) { - printk("IsLegalChannel(): Invalid Channel\n"); + netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n"); return default_chn; } -- cgit v1.2.3 From 3e3f837c659efc8fbb88e60cfda79b6ccfd2ac13 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:47:45 +0530 Subject: Staging: rtl8187se: Fix space prohibited before semicolon in dot11d.c This patch fixes the following checkpatch.pl issues in ieee80211/dot11d.c- WARNING: space prohibited before semicolon Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index c8874b80486a..2f5d367cd1c4 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -106,7 +106,7 @@ Dot11d_UpdateCountryIe( return; } - for (j = 0 ; j < pTriple->NumChnls; j++) { + for (j = 0; j < pTriple->NumChnls; j++) { pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; MaxChnlNum = pTriple->FirstChnl + j; -- cgit v1.2.3 From 96983a0c65775095be881ab811b3f86154bfdf6a Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:49:59 +0530 Subject: Staging: rtl8187se: Remove unnecessary braces around single statement in dot11d.c This patch fixes the following checkpatch.pl issues in ieee80211/dot11d.c- WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index 2f5d367cd1c4..eb161f28a186 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -142,9 +142,8 @@ DOT11D_GetMaxTxPwrInDbm( netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); return MaxTxPwrInDbm; } - if (pDot11dInfo->channel_map[Channel]) { + if (pDot11dInfo->channel_map[Channel]) MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; - } return MaxTxPwrInDbm; } -- cgit v1.2.3 From 10aff642fd49228bc111bce29e1b201f7dcdeca1 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:51:26 +0530 Subject: Staging: rtl8187se: Fix line over 80 characters in dot11d.c This patch fixes the following checkpatch.pl issues in ieee80211/dot11d.c- WARNING: line over 80 characters Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index eb161f28a186..0d914f25894f 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -71,6 +71,7 @@ Dot11d_UpdateCountryIe( { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); u8 i, j, NumTriples, MaxChnlNum; + u8 index, MaxTxPowerInDbm; PCHNL_TXPOWER_TRIPLE pTriple; if ((CoutryIeLen - 3)%3 != 0) { @@ -95,7 +96,8 @@ Dot11d_UpdateCountryIe( Dot11d_Reset(dev); return; } - if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) { + if (MAX_CHANNEL_NUMBER < + (pTriple->FirstChnl + pTriple->NumChnls)) { /* * It is not a valid set of channel id, * so stop processing @@ -107,8 +109,10 @@ Dot11d_UpdateCountryIe( } for (j = 0; j < pTriple->NumChnls; j++) { - pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; - pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; + index = pTriple->FirstChnl + j; + pDot11dInfo->channel_map[index] = 1; + MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm; + pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm; MaxChnlNum = pTriple->FirstChnl + j; } -- cgit v1.2.3 From 734412501b623643165424d7a839efa21471bbf7 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:53:07 +0530 Subject: Staging: rtl8187se: Remove unnecessary comments in ieee80211_crypt_ccmp.c This patch removes unnecessary comments written in ieee80211/ieee80211_crypt_ccmp.c. And hence also, removes the following checkpatch.pl issue- ERROR: do not use C99 // comments Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c index f5949e89e5c2..c74c0ccb3c6a 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c @@ -11,7 +11,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -//#include #include #include #include @@ -130,7 +129,6 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && (WLAN_FC_GET_STYPE(fc) & 0x08)); */ - // fixed by David :2006.9.6 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && (WLAN_FC_GET_STYPE(fc) & 0x80)); aad_len = 22; @@ -212,7 +210,6 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; -// mic = skb_put(skb, CCMP_MIC_LEN); i = CCMP_PN_LEN - 1; while (i >= 0) { @@ -232,7 +229,6 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = key->tx_pn[0]; hdr = (struct ieee80211_hdr_4addr *)skb->data; - //mic is moved to here by john mic = skb_put(skb, CCMP_MIC_LEN); ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); @@ -430,7 +426,6 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv) void ieee80211_ccmp_null(void) { -// printk("============>%s()\n", __func__); return; } static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { -- cgit v1.2.3 From c6a2c52f45f19998637ceab4aeee6f1cd7e1fdaf Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:54:39 +0530 Subject: Staging: rtl8187se: Fix quoted strings split across lines in ieee80211_crypt_ccmp.c This patch fixes the following checkpatch.pl issues in ieee80211/ieee80211_crypt_ccmp.c- WARNING: quoted string split across lines Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c index c74c0ccb3c6a..05d34e5453c9 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c @@ -412,9 +412,8 @@ static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) static char *ieee80211_ccmp_print_stats(char *p, void *priv) { struct ieee80211_ccmp_data *ccmp = priv; - p += sprintf(p, "key[%d] alg=CCMP key_set=%d " - "tx_pn=%pm rx_pn=%pm " - "format_errors=%d replays=%d decrypt_errors=%d\n", + p += sprintf(p, + "key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n", ccmp->key_idx, ccmp->key_set, ccmp->tx_pn, ccmp->rx_pn, ccmp->dot11RSNAStatsCCMPFormatErrors, -- cgit v1.2.3 From 1cf5ef1c46b4ab1c6a99a646648ad7ae54d23dfd Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:55:52 +0530 Subject: Staging: rtl8187se: Remove useless comments in ieee80211_crypt_tkip.c This patch removes useless comments in ieee80211/ieee80211_crypt_tkip.c. And, hence also removes the following checkpatch.pl issue- ERROR: do not use C99 // comments Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c index da24e430ca13..e5254ee0ea30 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c @@ -9,7 +9,6 @@ * more details. */ -//#include #include #include #include @@ -538,12 +537,9 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *pri michael_mic_hdr(skb, tkey->tx_hdr); - // { david, 2006.9.1 - // fix the wpa process with wmm enabled. if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; } - // } pos = skb_put(skb, 8); if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, @@ -587,12 +583,9 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, return -1; michael_mic_hdr(skb, tkey->rx_hdr); - // { david, 2006.9.1 - // fix the wpa process with wmm enabled. if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; } - // } if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) @@ -746,6 +739,5 @@ void ieee80211_crypto_tkip_exit(void) void ieee80211_tkip_null(void) { -// printk("============>%s()\n", __func__); return; } -- cgit v1.2.3 From 080b94a71350ba78973ce1e0b164bc158c787f65 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:57:07 +0530 Subject: Staging: rtl8187se: Replace "foo * bar" with "foo *bar" in ieee80211_crypt_tkip.c This patch fixes the following checkpatch.pl issues in ieee80211/ieee80211_crypt_tkip.c- ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c index e5254ee0ea30..8630504fcaac 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c @@ -64,7 +64,7 @@ struct ieee80211_tkip_data { u8 rx_hdr[16], tx_hdr[16]; }; -static void * ieee80211_tkip_init(int key_idx) +static void *ieee80211_tkip_init(int key_idx) { struct ieee80211_tkip_data *priv; @@ -466,8 +466,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return keyidx; } -static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, - u8 * data, size_t data_len, u8 * mic) +static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, + u8 *data, size_t data_len, u8 *mic) { struct hash_desc desc; struct scatterlist sg[2]; @@ -681,7 +681,7 @@ static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv) } -static char * ieee80211_tkip_print_stats(char *p, void *priv) +static char *ieee80211_tkip_print_stats(char *p, void *priv) { struct ieee80211_tkip_data *tkip = priv; p += sprintf(p, "key[%d] alg=TKIP key_set=%d " -- cgit v1.2.3 From 5befdae5b58c956bb38ae9599ef0394ef7ee0792 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 22:58:20 +0530 Subject: Staging: rtl8187se: Fix code indent should use tabs in ieee80211_crypt_tkip.c This patch fixes the following checkpatch.pl issues in ieee80211/ieee80211_crypt_tkip.c- ERROR: code indent should use tabs where possible Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- .../rtl8187se/ieee80211/ieee80211_crypt_tkip.c | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c index 8630504fcaac..fbda853d693a 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c @@ -303,8 +303,8 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; + struct ieee80211_tkip_data *tkey = priv; + struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; int len; u8 *pos; struct ieee80211_hdr_4addr *hdr; @@ -467,26 +467,26 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) } static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, - u8 *data, size_t data_len, u8 *mic) + u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; - struct scatterlist sg[2]; + struct hash_desc desc; + struct scatterlist sg[2]; - if (tfm_michael == NULL) { - printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); - return -1; - } + if (tfm_michael == NULL) { + printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); + return -1; + } sg_init_table(sg, 2); sg_set_buf(&sg[0], hdr, 16); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, 8)) - return -1; + if (crypto_hash_setkey(tfm_michael, key, 8)) + return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + desc.tfm = tfm_michael; + desc.flags = 0; + return crypto_hash_digest(&desc, sg, data_len + 16, mic); } static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) @@ -739,5 +739,5 @@ void ieee80211_crypto_tkip_exit(void) void ieee80211_tkip_null(void) { - return; + return; } -- cgit v1.2.3 From 4a0b1c4181a3af2c1c55ecf69c79fc5da635341e Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:03:43 +0530 Subject: Staging: rtl8187se: Remove unnecessary return statement in ieee80211_crypt_tkip.c This patch removes an unnecessary return statement in the function ieee80211_tkip_null() in ieee80211/ieee80211_crypt_tkip.c. Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c index fbda853d693a..9c25ffb1697c 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c @@ -739,5 +739,4 @@ void ieee80211_crypto_tkip_exit(void) void ieee80211_tkip_null(void) { - return; } -- cgit v1.2.3 From caace4b5315c3f43f19d8b16b41d5d64d00d628f Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:05:19 +0530 Subject: Staging: rtl8187se: Remove useless comments in dot11d.c This patch removes unnecessary comments in ieee80211/dot11d.c. Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index 0d914f25894f..d1395a683d5b 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -1,11 +1,3 @@ -/* - * File: - * Dot11d.c - * - * Description: - * Implement 802.11d - */ - #include "dot11d.h" void @@ -24,10 +16,7 @@ Dot11d_Init(struct ieee80211_device *ieee) netdev_info(ieee->dev, "Dot11d_Init()\n"); } -/* - * Description: - * Reset to the state as we are just entering a regulatory domain. - */ +/* Reset to the state as we are just entering a regulatory domain. */ void Dot11d_Reset(struct ieee80211_device *ieee) { -- cgit v1.2.3 From 52c5c2e0bcc4ca09f49b627a209716bc81b28145 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 3 Nov 2013 16:16:14 +0530 Subject: Staging: rtl8187se: Fix C99 style commenting in dot11d.h This patch fixes the checkpatch.pl error "do not use C99 // comments" in ieee80211/dot11d.n. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h index 029c2cab1e00..9c016fee0107 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.h +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.h @@ -3,9 +3,9 @@ #include "ieee80211.h" -//#define ENABLE_DOT11D +/* #define ENABLE_DOT11D */ -//#define DOT11D_MAX_CHNL_NUM 83 +/* #define DOT11D_MAX_CHNL_NUM 83 */ typedef struct _CHNL_TXPOWER_TRIPLE { u8 FirstChnl; @@ -20,18 +20,18 @@ typedef enum _DOT11D_STATE { }DOT11D_STATE; typedef struct _RT_DOT11D_INFO { - //DECLARE_RT_OBJECT(RT_DOT11D_INFO); + /* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */ - bool bEnabled; // dot11MultiDomainCapabilityEnabled + bool bEnabled; /* dot11MultiDomainCapabilityEnabled */ - u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. + u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */ u8 CountryIeBuf[MAX_IE_LEN]; - u8 CountryIeSrcAddr[6]; // Source AP of the country IE. + u8 CountryIeSrcAddr[6]; /* Source AP of the country IE. */ u8 CountryIeWatchdog; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) - //u8 ChnlListLen; // #Bytes valid in ChnlList[]. - //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; + u8 channel_map[MAX_CHANNEL_NUMBER+1]; /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */ + /* u8 ChnlListLen; // #Bytes valid in ChnlList[]. */ + /* u8 ChnlList[DOT11D_MAX_CHNL_NUM]; */ u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; DOT11D_STATE State; @@ -97,4 +97,4 @@ int ToLegalChannel( struct ieee80211_device * dev, u8 channel ); -#endif // #ifndef __INC_DOT11D_H +#endif /* #ifndef __INC_DOT11D_H */ -- cgit v1.2.3 From 17295913d897dc4762cae2e304032ff64a697cf6 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Wed, 6 Nov 2013 03:36:11 +0530 Subject: staging:rtl8187se: Shift open brace of function declarations to next line This patch fixes the checkpatch.pl error "open brace '{' following function declarations go on the next line" in ieee80211_softmac.c. Signed-off-by: Himangi Saraogi Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 029070603f66..1885fa47e2a6 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -106,7 +106,8 @@ void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p) } -void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) { +void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) +{ u8 *tag = *tag_p; *tag++ = MFIE_TYPE_GENERIC; //0 @@ -129,7 +130,8 @@ void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) { *tag_p = tag; } -void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { +void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) +{ u8 *tag = *tag_p; *tag++ = MFIE_TYPE_GENERIC; //0 -- cgit v1.2.3 From 5b74ff92d35e0b634d9e3ca0e698cbb568e68901 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Wed, 6 Nov 2013 11:10:24 +0530 Subject: staging:rtl8187se: Use preferred library linux/uaccess.h over asm/uaccess.h This patch fixes the checkpatch.pl warning "Use #include instead of " in ieee80211/ieee80211_softmac.c . Signed-off-by: Himangi Saraogi Reviewed-by: Lisa Nguyen Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 1885fa47e2a6..30d973bf997e 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include "dot11d.h" -- cgit v1.2.3 From 1fcd80670345c4a16c46b1e4c6c8df86727aff17 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Wed, 6 Nov 2013 16:56:33 +0530 Subject: Staging:rtl8187se: Insert spaces after commas This patch fixes the checkpatch.pl warnings space required after that ',' in ieee80211/ieee80211_softmac.c Signed-off-by: Himangi Saraogi Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 30d973bf997e..d769f168f795 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -25,12 +25,12 @@ #include "dot11d.h" u8 rsn_authen_cipher_suite[16][4] = { - {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved - {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default - {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default} - {0x00,0x0F,0xAC,0x03}, //WRAP-historical - {0x00,0x0F,0xAC,0x04}, //CCMP - {0x00,0x0F,0xAC,0x05}, //WEP-104 + {0x00, 0x0F, 0xAC, 0x00}, //Use group key, //Reserved + {0x00, 0x0F, 0xAC, 0x01}, //WEP-40 //RSNA default + {0x00, 0x0F, 0xAC, 0x02}, //TKIP //NONE //{used just as default} + {0x00, 0x0F, 0xAC, 0x03}, //WRAP-historical + {0x00, 0x0F, 0xAC, 0x04}, //CCMP + {0x00, 0x0F, 0xAC, 0x05}, //WEP-104 }; short ieee80211_is_54g(const struct ieee80211_network *net) -- cgit v1.2.3 From 2063cd41565b22e415777799660b2063ed1626ac Mon Sep 17 00:00:00 2001 From: Ana Rey Botello Date: Thu, 7 Nov 2013 09:31:21 +0100 Subject: Staging: rtl8187se: use macro IW_HANDLER to initialize r8180_wx_handlers Use IW_HANDLER to initialize iw_handler structure like in others wireless driver. Acked-by: Pablo Neira Ayuso Signed-off-by: Ana Rey Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/r8180_wx.c | 100 +++++++++++++++-------------------- 1 file changed, 42 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 4e01653e098a..92b76f4cca47 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -21,6 +21,7 @@ #include "r8180.h" #include "r8180_hw.h" +#include #include "ieee80211/dot11d.h" u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000, @@ -1156,65 +1157,48 @@ static int r8180_wx_set_gen_ie(struct net_device *dev, } -static iw_handler r8180_wx_handlers[] = { - NULL, /* SIOCSIWCOMMIT */ - r8180_wx_get_name, /* SIOCGIWNAME */ - dummy, /* SIOCSIWNWID */ - dummy, /* SIOCGIWNWID */ - r8180_wx_set_freq, /* SIOCSIWFREQ */ - r8180_wx_get_freq, /* SIOCGIWFREQ */ - r8180_wx_set_mode, /* SIOCSIWMODE */ - r8180_wx_get_mode, /* SIOCGIWMODE */ - r8180_wx_set_sens, /* SIOCSIWSENS */ - r8180_wx_get_sens, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - rtl8180_wx_get_range, /* SIOCGIWRANGE */ - NULL, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - dummy, /* SIOCSIWSPY */ - dummy, /* SIOCGIWSPY */ - NULL, /* SIOCGIWTHRSPY */ - NULL, /* SIOCWIWTHRSPY */ - r8180_wx_set_wap, /* SIOCSIWAP */ - r8180_wx_get_wap, /* SIOCGIWAP */ - r8180_wx_set_mlme, /* SIOCSIWMLME*/ - dummy, /* SIOCGIWAPLIST -- deprecated */ - r8180_wx_set_scan, /* SIOCSIWSCAN */ - r8180_wx_get_scan, /* SIOCGIWSCAN */ - r8180_wx_set_essid, /* SIOCSIWESSID */ - r8180_wx_get_essid, /* SIOCGIWESSID */ - dummy, /* SIOCSIWNICKN */ - dummy, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - r8180_wx_set_rate, /* SIOCSIWRATE */ - r8180_wx_get_rate, /* SIOCGIWRATE */ - r8180_wx_set_rts, /* SIOCSIWRTS */ - r8180_wx_get_rts, /* SIOCGIWRTS */ - r8180_wx_set_frag, /* SIOCSIWFRAG */ - r8180_wx_get_frag, /* SIOCGIWFRAG */ - dummy, /* SIOCSIWTXPOW */ - dummy, /* SIOCGIWTXPOW */ - r8180_wx_set_retry, /* SIOCSIWRETRY */ - r8180_wx_get_retry, /* SIOCGIWRETRY */ - r8180_wx_set_enc, /* SIOCSIWENCODE */ - r8180_wx_get_enc, /* SIOCGIWENCODE */ - r8180_wx_set_power, /* SIOCSIWPOWER */ - r8180_wx_get_power, /* SIOCGIWPOWER */ - NULL, /*---hole---*/ - NULL, /*---hole---*/ - r8180_wx_set_gen_ie, /* SIOCSIWGENIE */ - NULL, /* SIOCSIWGENIE */ - r8180_wx_set_auth, /* SIOCSIWAUTH */ - NULL, /* SIOCSIWAUTH */ - r8180_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ - NULL, /* SIOCSIWENCODEEXT */ - NULL, /* SIOCSIWPMKSA */ - NULL, /*---hole---*/ -}; +static const iw_handler r8180_wx_handlers[] = { + IW_HANDLER(SIOCGIWNAME, r8180_wx_get_name), + IW_HANDLER(SIOCSIWNWID, dummy), + IW_HANDLER(SIOCGIWNWID, dummy), + IW_HANDLER(SIOCSIWFREQ, r8180_wx_set_freq), + IW_HANDLER(SIOCGIWFREQ, r8180_wx_get_freq), + IW_HANDLER(SIOCSIWMODE, r8180_wx_set_mode), + IW_HANDLER(SIOCGIWMODE, r8180_wx_get_mode), + IW_HANDLER(SIOCSIWSENS, r8180_wx_set_sens), + IW_HANDLER(SIOCGIWSENS, r8180_wx_get_sens), + IW_HANDLER(SIOCGIWRANGE, rtl8180_wx_get_range), + IW_HANDLER(SIOCSIWSPY, dummy), + IW_HANDLER(SIOCGIWSPY, dummy), + IW_HANDLER(SIOCSIWAP, r8180_wx_set_wap), + IW_HANDLER(SIOCGIWAP, r8180_wx_get_wap), + IW_HANDLER(SIOCSIWMLME, r8180_wx_set_mlme), + IW_HANDLER(SIOCGIWAPLIST, dummy), /* deprecated */ + IW_HANDLER(SIOCSIWSCAN, r8180_wx_set_scan), + IW_HANDLER(SIOCGIWSCAN, r8180_wx_get_scan), + IW_HANDLER(SIOCSIWESSID, r8180_wx_set_essid), + IW_HANDLER(SIOCGIWESSID, r8180_wx_get_essid), + IW_HANDLER(SIOCSIWNICKN, dummy), + IW_HANDLER(SIOCGIWNICKN, dummy), + IW_HANDLER(SIOCSIWRATE, r8180_wx_set_rate), + IW_HANDLER(SIOCGIWRATE, r8180_wx_get_rate), + IW_HANDLER(SIOCSIWRTS, r8180_wx_set_rts), + IW_HANDLER(SIOCGIWRTS, r8180_wx_get_rts), + IW_HANDLER(SIOCSIWFRAG, r8180_wx_set_frag), + IW_HANDLER(SIOCGIWFRAG, r8180_wx_get_frag), + IW_HANDLER(SIOCSIWTXPOW, dummy), + IW_HANDLER(SIOCGIWTXPOW, dummy), + IW_HANDLER(SIOCSIWRETRY, r8180_wx_set_retry), + IW_HANDLER(SIOCGIWRETRY, r8180_wx_get_retry), + IW_HANDLER(SIOCSIWENCODE, r8180_wx_set_enc), + IW_HANDLER(SIOCGIWENCODE, r8180_wx_get_enc), + IW_HANDLER(SIOCSIWPOWER, r8180_wx_set_power), + IW_HANDLER(SIOCGIWPOWER, r8180_wx_get_power), + IW_HANDLER(SIOCSIWGENIE, r8180_wx_set_gen_ie), + IW_HANDLER(SIOCSIWAUTH, r8180_wx_set_auth), + IW_HANDLER(SIOCSIWENCODEEXT, r8180_wx_set_enc_ext), +}; static const struct iw_priv_args r8180_private_args[] = { { -- cgit v1.2.3 From 4270826c6912ff354b2ba0cb3892a6f3640a375d Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Fri, 8 Nov 2013 03:06:39 +0530 Subject: Staging:rtl8187se: Add space before open parenthesis of if condition This patch fixes the checkpatch.pl warning : space required before the open parenthesis '(' in ieee80211/ieee80211_softmac.c. Signed-off-by: Himangi Saraogi Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index d769f168f795..7864267f7980 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -119,7 +119,7 @@ void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) *tag++ = 0x00; *tag++ = 0x01; #ifdef SUPPORT_USPD - if(ieee->current_network.wmm_info & 0x80) { + if (ieee->current_network.wmm_info & 0x80) { *tag++ = 0x0f|MAX_SP_Len; } else { *tag++ = MAX_SP_Len; -- cgit v1.2.3 From 821aa20462f655f052215df8afd61c4a012056f7 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Fri, 8 Nov 2013 03:07:03 +0530 Subject: Staging:rtl8187se: Remove unnecessary braces from if-else statement This patch fixes the checkpatch.pl warning braces {} are not necessary for any arm of this statement in ieee80211/ieee80211_softmac.c. Signed-off-by: Himangi Saraogi Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 7864267f7980..a5d0e54100ca 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -119,11 +119,10 @@ void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) *tag++ = 0x00; *tag++ = 0x01; #ifdef SUPPORT_USPD - if (ieee->current_network.wmm_info & 0x80) { + if (ieee->current_network.wmm_info & 0x80) *tag++ = 0x0f|MAX_SP_Len; - } else { + else *tag++ = MAX_SP_Len; - } #else *tag++ = MAX_SP_Len; #endif -- cgit v1.2.3 From 62953c869f147f241118e3f36e58e778d86ffe25 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 10 Nov 2013 14:24:44 +0530 Subject: Staging: rtl8187se: Fix indentation errors This patch fixes the checkpatch.pl warnings "code indent should use tabs where possible" in ieee80211/ieee80211_softmac.c. Also unnecessary blanks lines are removed. Signed-off-by: Himangi Saraogi Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8187se/ieee80211/ieee80211_softmac.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index a5d0e54100ca..c281c6728e63 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -132,17 +132,15 @@ void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_GENERIC; //0 - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0xe0; - *tag++ = 0x4c; - *tag++ = 0x01;//5 - *tag++ = 0x02; - *tag++ = 0x11; + *tag++ = MFIE_TYPE_GENERIC; //0 + *tag++ = 7; + *tag++ = 0x00; + *tag++ = 0xe0; + *tag++ = 0x4c; + *tag++ = 0x01;//5 + *tag++ = 0x02; + *tag++ = 0x11; *tag++ = 0x00; - *tag_p = tag; printk(KERN_ALERT "This is enable turbo mode IE process\n"); } -- cgit v1.2.3 From fb3e170cfa4495eeef8092055dd7e84c8cf10961 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 10 Nov 2013 14:26:17 +0530 Subject: Staging: rtl8187se: Remove C99 style commenting This patch fixes the checkpatch.pl warning "do not use C99 // comments" in ieee80211/ieee80211_softmac.c. Signed-off-by: Himangi Saraogi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index c281c6728e63..7e16ccb7a645 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -132,12 +132,12 @@ void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { u8 *tag = *tag_p; - *tag++ = MFIE_TYPE_GENERIC; //0 + *tag++ = MFIE_TYPE_GENERIC; /* 0 */ *tag++ = 7; *tag++ = 0x00; *tag++ = 0xe0; *tag++ = 0x4c; - *tag++ = 0x01;//5 + *tag++ = 0x01; /* 5 */ *tag++ = 0x02; *tag++ = 0x11; *tag++ = 0x00; -- cgit v1.2.3 From 33700ac776ce60352c98c4d5fe149b48cfe790e1 Mon Sep 17 00:00:00 2001 From: Dulshani Gunawardhana Date: Thu, 31 Oct 2013 21:51:32 +0530 Subject: staging:lustre: Fix plain integer as NULL pointer warning Fix the sparse warning of 'Using plain integer as NULL pointer' in lproc_lov.c. Signed-off-by: Dulshani Gunawardhana Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lproc_lov.c | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lproc_lov.c b/drivers/staging/lustre/lustre/lov/lproc_lov.c index 15744e13a3f2..e6f22e3a3a38 100644 --- a/drivers/staging/lustre/lustre/lov/lproc_lov.c +++ b/drivers/staging/lustre/lustre/lov/lproc_lov.c @@ -260,29 +260,29 @@ LPROC_SEQ_FOPS_RO_TYPE(lov, kbytesfree); LPROC_SEQ_FOPS_RO_TYPE(lov, kbytesavail); struct lprocfs_vars lprocfs_lov_obd_vars[] = { - { "uuid", &lov_uuid_fops, 0, 0 }, - { "stripesize", &lov_stripesize_fops, 0 }, - { "stripeoffset", &lov_stripeoffset_fops, 0 }, - { "stripecount", &lov_stripecount_fops, 0 }, - { "stripetype", &lov_stripetype_fops, 0 }, - { "numobd", &lov_numobd_fops, 0, 0 }, - { "activeobd", &lov_activeobd_fops, 0, 0 }, - { "filestotal", &lov_filestotal_fops, 0, 0 }, - { "filesfree", &lov_filesfree_fops, 0, 0 }, - /*{ "filegroups", lprocfs_rd_filegroups, 0, 0 },*/ - { "blocksize", &lov_blksize_fops, 0, 0 }, - { "kbytestotal", &lov_kbytestotal_fops, 0, 0 }, - { "kbytesfree", &lov_kbytesfree_fops, 0, 0 }, - { "kbytesavail", &lov_kbytesavail_fops, 0, 0 }, - { "desc_uuid", &lov_desc_uuid_fops, 0, 0 }, - { 0 } + { "uuid", &lov_uuid_fops, NULL, 0 }, + { "stripesize", &lov_stripesize_fops, NULL }, + { "stripeoffset", &lov_stripeoffset_fops, NULL }, + { "stripecount", &lov_stripecount_fops, NULL }, + { "stripetype", &lov_stripetype_fops, NULL }, + { "numobd", &lov_numobd_fops, NULL, 0 }, + { "activeobd", &lov_activeobd_fops, NULL, 0 }, + { "filestotal", &lov_filestotal_fops, NULL, 0 }, + { "filesfree", &lov_filesfree_fops, NULL, 0 }, + /*{ "filegroups", lprocfs_rd_filegroups, NULL, 0 },*/ + { "blocksize", &lov_blksize_fops, NULL, 0 }, + { "kbytestotal", &lov_kbytestotal_fops, NULL, 0 }, + { "kbytesfree", &lov_kbytesfree_fops, NULL, 0 }, + { "kbytesavail", &lov_kbytesavail_fops, NULL, 0 }, + { "desc_uuid", &lov_desc_uuid_fops, NULL, 0 }, + { NULL } }; LPROC_SEQ_FOPS_RO_TYPE(lov, numrefs); static struct lprocfs_vars lprocfs_lov_module_vars[] = { - { "num_refs", &lov_numrefs_fops, 0, 0 }, - { 0 } + { "num_refs", &lov_numrefs_fops, NULL, 0 }, + { NULL } }; void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars) -- cgit v1.2.3 From b008e65cc236ce693017589c09ee3ac838630c35 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Tue, 5 Nov 2013 18:36:45 +0200 Subject: staging: lustre: remove space between function name and open parenthesis This fixes the following checkpatch.pl warnings: WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/nidstrings.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index 99c9e9d2493f..347579d7f560 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -60,7 +60,7 @@ static int libcfs_nidstring_idx = 0; static spinlock_t libcfs_nidstring_lock; -void libcfs_init_nidstrings (void) +void libcfs_init_nidstrings(void) { spin_lock_init(&libcfs_nidstring_lock); } @@ -69,7 +69,7 @@ void libcfs_init_nidstrings (void) # define NIDSTR_UNLOCK(f) spin_unlock_irqrestore(&libcfs_nidstring_lock, f) static char * -libcfs_next_nidstring (void) +libcfs_next_nidstring(void) { char *str; unsigned long flags; @@ -475,7 +475,7 @@ libcfs_str2nid(const char *str) sep = str + strlen(str); net = LNET_MKNET(SOCKLND, 0); nf = libcfs_lnd2netstrfns(SOCKLND); - LASSERT (nf != NULL); + LASSERT(nf != NULL); } if (!nf->nf_str2addr(str, (int)(sep - str), &addr)) -- cgit v1.2.3 From 0b2b3070f1f920ff9dae1ea26809944b6b1d46f2 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Tue, 5 Nov 2013 18:36:46 +0200 Subject: staging: lustre: place EXPORT_SYMBOL after its function This patch fixes the following type of warnings detected by checkpatch.pl: WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/nidstrings.c | 26 +++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index 347579d7f560..790c5130b74c 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -326,6 +326,7 @@ libcfs_isknown_lnd(int type) { return libcfs_lnd2netstrfns(type) != NULL; } +EXPORT_SYMBOL(libcfs_isknown_lnd); char * libcfs_lnd2modname(int lnd) @@ -334,6 +335,7 @@ libcfs_lnd2modname(int lnd) return (nf == NULL) ? NULL : nf->nf_modname; } +EXPORT_SYMBOL(libcfs_lnd2modname); char * libcfs_lnd2str(int lnd) @@ -348,6 +350,7 @@ libcfs_lnd2str(int lnd) snprintf(str, LNET_NIDSTR_SIZE, "?%u?", lnd); return str; } +EXPORT_SYMBOL(libcfs_lnd2str); int libcfs_str2lnd(const char *str) @@ -359,6 +362,7 @@ libcfs_str2lnd(const char *str) return -1; } +EXPORT_SYMBOL(libcfs_str2lnd); char * libcfs_net2str(__u32 net) @@ -377,6 +381,7 @@ libcfs_net2str(__u32 net) return str; } +EXPORT_SYMBOL(libcfs_net2str); char * libcfs_nid2str(lnet_nid_t nid) @@ -410,6 +415,7 @@ libcfs_nid2str(lnet_nid_t nid) return str; } +EXPORT_SYMBOL(libcfs_nid2str); static struct netstrfns * libcfs_str2net_internal(const char *str, __u32 *net) @@ -458,6 +464,7 @@ libcfs_str2net(const char *str) return LNET_NIDNET(LNET_NID_ANY); } +EXPORT_SYMBOL(libcfs_str2net); lnet_nid_t libcfs_str2nid(const char *str) @@ -483,6 +490,7 @@ libcfs_str2nid(const char *str) return LNET_MKNID(net, addr); } +EXPORT_SYMBOL(libcfs_str2nid); char * libcfs_id2str(lnet_process_id_t id) @@ -500,6 +508,7 @@ libcfs_id2str(lnet_process_id_t id) (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid)); return str; } +EXPORT_SYMBOL(libcfs_id2str); int libcfs_str2anynid(lnet_nid_t *nidp, const char *str) @@ -512,6 +521,7 @@ libcfs_str2anynid(lnet_nid_t *nidp, const char *str) *nidp = libcfs_str2nid(str); return *nidp != LNET_NID_ANY; } +EXPORT_SYMBOL(libcfs_str2anynid); /** * Nid range list syntax. @@ -765,6 +775,7 @@ cfs_free_nidlist(struct list_head *list) LIBCFS_FREE(nr, sizeof(struct nidrange)); } } +EXPORT_SYMBOL(cfs_free_nidlist); /** * Parses nid range list. @@ -803,6 +814,7 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) } return 1; } +EXPORT_SYMBOL(cfs_parse_nidlist); /* * Nf_match_addr method for networks using numeric addresses @@ -848,18 +860,4 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist) } return 0; } - - -EXPORT_SYMBOL(libcfs_isknown_lnd); -EXPORT_SYMBOL(libcfs_lnd2modname); -EXPORT_SYMBOL(libcfs_lnd2str); -EXPORT_SYMBOL(libcfs_str2lnd); -EXPORT_SYMBOL(libcfs_net2str); -EXPORT_SYMBOL(libcfs_nid2str); -EXPORT_SYMBOL(libcfs_str2net); -EXPORT_SYMBOL(libcfs_str2nid); -EXPORT_SYMBOL(libcfs_id2str); -EXPORT_SYMBOL(libcfs_str2anynid); -EXPORT_SYMBOL(cfs_free_nidlist); -EXPORT_SYMBOL(cfs_parse_nidlist); EXPORT_SYMBOL(cfs_match_nid); -- cgit v1.2.3 From 06fcedc8ea5df80c7a6d7940d6ec97056aff2de2 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Tue, 5 Nov 2013 18:36:47 +0200 Subject: staging: lustre: remove initialisation of static variable Fix the following checkpatch.pl error: ERROR: do not initialise statics to 0 or NULL +static int libcfs_nidstring_idx = 0; Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/nidstrings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index 790c5130b74c..732ae5540bf4 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -56,7 +56,7 @@ */ static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE]; -static int libcfs_nidstring_idx = 0; +static int libcfs_nidstring_idx; static spinlock_t libcfs_nidstring_lock; -- cgit v1.2.3 From 51d6774a91fbf1b311aa8f412d761048af7d8d53 Mon Sep 17 00:00:00 2001 From: Ebru Akagunduz Date: Sun, 10 Nov 2013 19:10:31 +0200 Subject: Staging: rtl8187se: fix printk() should include kern_ facility level Fix checkpatch.pl issues with printk() should include kern_ facility level in r8185b_init.c Signed-off-by: Ebru Akagunduz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/r8185b_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c index dc52a3e584d8..f2f0dc7d4e9a 100644 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ b/drivers/staging/rtl8187se/r8185b_init.c @@ -497,7 +497,7 @@ static void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev) */ RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1); - printk("ZEBRA_Config_85BASIC_HardCode(): (%02x)\n", + netdev_info(dev, "ZEBRA_Config_85BASIC_HardCode(): (%02x)\n", (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9); } else { @@ -1125,7 +1125,7 @@ bool MgntActSet_RF_State(struct net_device *dev, * to be stuck here. */ if (RFWaitCounter > 1000) { /* 1sec */ - printk("MgntActSet_RF_State(): Wait too long to set RF\n"); + netdev_info(dev, "MgntActSet_RF_State(): Wait too long to set RF\n"); /* TODO: Reset RF state? */ return false; } -- cgit v1.2.3 From 1e01f94317cf85bd4b0bbeaf4e00cf948d660ee0 Mon Sep 17 00:00:00 2001 From: Archana kumari Date: Fri, 1 Nov 2013 12:19:21 +0530 Subject: staging: vt6655: fixed sparse warning for static declaration in wpa2.c This patch fixes sparse warning for static declaration in wpa2.c Signed-off-by: Archana kumari Reviewed-by: Josh Triplett Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/wpa2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c index 089788dfba63..a7e33c0ceb74 100644 --- a/drivers/staging/vt6655/wpa2.c +++ b/drivers/staging/vt6655/wpa2.c @@ -42,14 +42,14 @@ static int msglevel = MSG_LEVEL_INFO; /*--------------------- Static Variables --------------------------*/ -const unsigned char abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; -const unsigned char abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; -const unsigned char abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; -const unsigned char abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; -const unsigned char abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; - -const unsigned char abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; -const unsigned char abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +static const unsigned char abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; +static const unsigned char abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +static const unsigned char abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; +static const unsigned char abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +static const unsigned char abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; + +static const unsigned char abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +static const unsigned char abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; /*--------------------- Static Functions --------------------------*/ -- cgit v1.2.3 From 3b1388518a316f1eefe0b781e0583937d5407160 Mon Sep 17 00:00:00 2001 From: Valentina Manea Date: Mon, 4 Nov 2013 10:44:02 +0200 Subject: staging: vt6656: Fix (most) sparse warnings regarding static functions/variables This fixes sparse warnings for functions and variables, e.g.: * drivers/staging/vt6656/card.c:69:11: warning: symbol 'cwRXBCNTSFOff' was not declared. Should it be static? Some warnings were false positives, such as: * drivers/staging/vt6656/dpc.c:249:5: warning: symbol 'RXbBulkInProcessData' was not declared. Should it be static? Signed-off-by: Valentina Manea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/aes_ccmp.c | 16 ++++++++-------- drivers/staging/vt6656/baseband.c | 8 ++++---- drivers/staging/vt6656/bssdb.c | 4 ++-- drivers/staging/vt6656/card.c | 4 ++-- drivers/staging/vt6656/datarate.c | 2 +- drivers/staging/vt6656/dpc.c | 2 +- drivers/staging/vt6656/rf.c | 4 ++-- drivers/staging/vt6656/rxtx.c | 6 +++--- drivers/staging/vt6656/tkip.c | 4 ++-- drivers/staging/vt6656/wcmd.c | 5 +++-- drivers/staging/vt6656/wmgr.c | 10 +++++----- drivers/staging/vt6656/wpa.c | 12 ++++++------ drivers/staging/vt6656/wpa2.c | 16 ++++++++-------- 13 files changed, 47 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/aes_ccmp.c b/drivers/staging/vt6656/aes_ccmp.c index 6c7693911cd6..61b9f7bdb858 100644 --- a/drivers/staging/vt6656/aes_ccmp.c +++ b/drivers/staging/vt6656/aes_ccmp.c @@ -37,7 +37,7 @@ * SBOX Table */ -u8 sbox_table[256] = { +static u8 sbox_table[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, @@ -56,7 +56,7 @@ u8 sbox_table[256] = { 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; -u8 dot2_table[256] = { +static u8 dot2_table[256] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, @@ -75,7 +75,7 @@ u8 dot2_table[256] = { 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 }; -u8 dot3_table[256] = { +static u8 dot3_table[256] = { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, @@ -115,7 +115,7 @@ static void xor_32(u8 *a, u8 *b, u8 *out) (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); } -void AddRoundKey(u8 *key, int round) +static void AddRoundKey(u8 *key, int round) { u8 sbox_key[4]; u8 rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; @@ -133,7 +133,7 @@ void AddRoundKey(u8 *key, int round) xor_32(&key[12], &key[8], &key[12]); } -void SubBytes(u8 *in, u8 *out) +static void SubBytes(u8 *in, u8 *out) { int i; @@ -141,7 +141,7 @@ void SubBytes(u8 *in, u8 *out) out[i] = sbox_table[in[i]]; } -void ShiftRows(u8 *in, u8 *out) +static void ShiftRows(u8 *in, u8 *out) { out[0] = in[0]; out[1] = in[5]; @@ -161,7 +161,7 @@ void ShiftRows(u8 *in, u8 *out) out[15] = in[11]; } -void MixColumns(u8 *in, u8 *out) +static void MixColumns(u8 *in, u8 *out) { out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3]; @@ -170,7 +170,7 @@ void MixColumns(u8 *in, u8 *out) out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]]; } -void AESv128(u8 *key, u8 *data, u8 *ciphertext) +static void AESv128(u8 *key, u8 *data, u8 *ciphertext) { int i; int round; diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 1e8b8412e67e..5f6480e7353d 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -48,7 +48,7 @@ static int msglevel =MSG_LEVEL_INFO; //static int msglevel =MSG_LEVEL_DEBUG; -u8 abyVT3184_AGC[] = { +static u8 abyVT3184_AGC[] = { 0x00, //0 0x00, //1 0x02, //2 @@ -115,7 +115,7 @@ u8 abyVT3184_AGC[] = { 0x3E //3F }; -u8 abyVT3184_AL2230[] = { +static u8 abyVT3184_AL2230[] = { 0x31,//00 0x00, 0x00, @@ -375,7 +375,7 @@ u8 abyVT3184_AL2230[] = { }; //{{RobertYu:20060515, new BB setting for VT3226D0 -u8 abyVT3184_VT3226D0[] = { +static u8 abyVT3184_VT3226D0[] = { 0x31,//00 0x00, 0x00, @@ -634,7 +634,7 @@ u8 abyVT3184_VT3226D0[] = { 0x00, }; -const u16 awcFrameTime[MAX_RATE] = +static const u16 awcFrameTime[MAX_RATE] = {10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216}; /* diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index dad3f8c78e21..1c3cbc54ce18 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -62,14 +62,14 @@ static int msglevel =MSG_LEVEL_INFO; //static int msglevel =MSG_LEVEL_DEBUG; -const u16 awHWRetry0[5][5] = { +static const u16 awHWRetry0[5][5] = { {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} }; -const u16 awHWRetry1[5][5] = { +static const u16 awHWRetry1[5][5] = { {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 19d3cf451b88..662cfea7527e 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -66,7 +66,7 @@ static int msglevel =MSG_LEVEL_INFO; //const u16 cwRXBCNTSFOff[MAX_RATE] = //{17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; -const u16 cwRXBCNTSFOff[MAX_RATE] = +static const u16 cwRXBCNTSFOff[MAX_RATE] = {192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3}; /* @@ -205,7 +205,7 @@ static u16 swGetOFDMControlRate(struct vnt_private *pDevice, u16 wRateIdx) * Return Value: none * */ -void +static void CARDvCalculateOFDMRParameter ( u16 wRate, u8 byBBType, diff --git a/drivers/staging/vt6656/datarate.c b/drivers/staging/vt6656/datarate.c index af9eab0c00a3..547db6f0c53f 100644 --- a/drivers/staging/vt6656/datarate.c +++ b/drivers/staging/vt6656/datarate.c @@ -45,7 +45,7 @@ /* static int msglevel = MSG_LEVEL_DEBUG; */ static int msglevel = MSG_LEVEL_INFO; -const u8 acbyIERate[MAX_RATE] = {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, +static const u8 acbyIERate[MAX_RATE] = {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; #define AUTORATE_TXOK_CNT 0x0400 diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 75dc92d64056..2bed31b741c0 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -59,7 +59,7 @@ //static int msglevel =MSG_LEVEL_DEBUG; static int msglevel =MSG_LEVEL_INFO; -const u8 acbyRxRate[MAX_RATE] = +static const u8 acbyRxRate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; static u8 s_byGetRateIdx(u8 byRate); diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index d27fa434550d..e545232f670b 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -419,7 +419,7 @@ static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = { ///}}RobertYu //{{RobertYu:20060502, TWIF 1.14, LO Current for 11b mode -const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = { +static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = { 0x0135C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz 0x0135C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz 0x0235C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz @@ -597,7 +597,7 @@ static u8 vt3342_channel_table1[CB_MAX_CHANNEL][3] = { * -*/ -const u32 al2230_power_table[AL2230_PWR_IDX_LEN] = { +static const u32 al2230_power_table[AL2230_PWR_IDX_LEN] = { 0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, 0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, 0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 35a3ddb41a6a..5601331708f3 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -64,16 +64,16 @@ static int msglevel = MSG_LEVEL_INFO; -const u16 wTimeStampOff[2][MAX_RATE] = { +static const u16 wTimeStampOff[2][MAX_RATE] = { {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble }; -const u16 wFB_Opt0[2][5] = { +static const u16 wFB_Opt0[2][5] = { {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0 {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1 }; -const u16 wFB_Opt1[2][5] = { +static const u16 wFB_Opt1[2][5] = { {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0 {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1 }; diff --git a/drivers/staging/vt6656/tkip.c b/drivers/staging/vt6656/tkip.c index 9d643e449ac3..28282f345901 100644 --- a/drivers/staging/vt6656/tkip.c +++ b/drivers/staging/vt6656/tkip.c @@ -39,7 +39,7 @@ /* The 2nd table is the same as the 1st but with the upper and lower */ /* bytes swapped. To allow an endian tolerant implementation, the byte */ /* halves have been expressed independently here. */ -const u8 TKIP_Sbox_Lower[256] = { +static const u8 TKIP_Sbox_Lower[256] = { 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, @@ -74,7 +74,7 @@ const u8 TKIP_Sbox_Lower[256] = { 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A }; -const u8 TKIP_Sbox_Upper[256] = { +static const u8 TKIP_Sbox_Upper[256] = { 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 2f8e2a875331..1031e54284f7 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -224,7 +224,7 @@ static void s_vProbeChannel(struct vnt_private *pDevice) * -*/ -struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, +static struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, struct vnt_manager *pMgmt, u8 *pScanBSSID, PWLAN_IE_SSID pSSID, PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates) { @@ -266,7 +266,8 @@ struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, return pTxPacket; } -void vCommandTimerWait(struct vnt_private *pDevice, unsigned long MSecond) +static void +vCommandTimerWait(struct vnt_private *pDevice, unsigned long MSecond) { schedule_delayed_work(&pDevice->run_command_work, msecs_to_jiffies(MSecond)); diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c index e26c41519b15..d74b0e7cb171 100644 --- a/drivers/staging/vt6656/wmgr.c +++ b/drivers/staging/vt6656/wmgr.c @@ -2961,7 +2961,7 @@ static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice, * -*/ -struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice, +static struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice, struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wCurrBeaconPeriod, u32 uCurrChannel, u16 wCurrATIMWinodw, u8 *pDstAddr, PWLAN_IE_SSID pCurrSSID, u8 *pCurrBSSID, @@ -3081,7 +3081,7 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice, * -*/ -struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice, +static struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice, struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo, u16 wListenInterval, PWLAN_IE_SSID pCurrSSID, @@ -3329,7 +3329,7 @@ struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice, * -*/ -struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice, +static struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice, struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo, u16 wListenInterval, PWLAN_IE_SSID pCurrSSID, PWLAN_IE_SUPP_RATES pCurrRates, @@ -3576,7 +3576,7 @@ struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice, * -*/ -struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice, +static struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice, struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus, u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates) @@ -3642,7 +3642,7 @@ struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice, * -*/ -struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice, +static struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice, struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus, u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates) diff --git a/drivers/staging/vt6656/wpa.c b/drivers/staging/vt6656/wpa.c index 01db4e7154da..403c295cc02c 100644 --- a/drivers/staging/vt6656/wpa.c +++ b/drivers/staging/vt6656/wpa.c @@ -43,12 +43,12 @@ static int msglevel =MSG_LEVEL_INFO; -const u8 abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 }; -const u8 abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 }; -const u8 abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 }; -const u8 abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 }; -const u8 abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 }; -const u8 abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 }; +static const u8 abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 }; +static const u8 abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 }; +static const u8 abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 }; +static const u8 abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 }; +static const u8 abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 }; +static const u8 abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 }; /*+ * diff --git a/drivers/staging/vt6656/wpa2.c b/drivers/staging/vt6656/wpa2.c index aa2216184345..df5541794e0f 100644 --- a/drivers/staging/vt6656/wpa2.c +++ b/drivers/staging/vt6656/wpa2.c @@ -37,14 +37,14 @@ static int msglevel =MSG_LEVEL_INFO; //static int msglevel =MSG_LEVEL_DEBUG; -const u8 abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; -const u8 abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; -const u8 abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; -const u8 abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; -const u8 abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; - -const u8 abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; -const u8 abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +static const u8 abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; +static const u8 abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +static const u8 abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; +static const u8 abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +static const u8 abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; + +static const u8 abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +static const u8 abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; /*+ * -- cgit v1.2.3 From ebd381d9851bba4b9565ec3b414055c726391907 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Sun, 3 Nov 2013 18:30:52 +0530 Subject: staging: vt6656: fixed whitespace related errors around operators removed prohibited spaces around operators and added required spaces around operators wherever necessary to fix checkpatch errors Signed-off-by: Nandini Hanumanthagowda Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 112 +++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 1031e54284f7..ca57fc37d609 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -55,8 +55,8 @@ #include "channel.h" #include "iowpa.h" -static int msglevel =MSG_LEVEL_INFO; -//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel = MSG_LEVEL_INFO; +//static int msglevel = MSG_LEVEL_DEBUG; static void s_vProbeChannel(struct vnt_private *); @@ -200,8 +200,8 @@ static void s_vProbeChannel(struct vnt_private *pDevice) (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG ); - if (pTxPacket != NULL ){ - for (ii = 0; ii < 1 ; ii++) { + if (pTxPacket != NULL) { + for (ii = 0; ii < 1; ii++) { if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n"); } @@ -244,9 +244,9 @@ static struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ) )); - memcpy( sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN); - memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); - memcpy( sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN); + memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN); + memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN); // Copy the SSID, pSSID->len=0 indicate broadcast SSID sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); sFrame.len += pSSID->len + WLAN_IEHDR_LEN; @@ -297,7 +297,7 @@ void vRunCommand(struct work_struct *work) spin_lock_irq(&pDevice->lock); - switch ( pDevice->eCommandState ) { + switch (pDevice->eCommandState) { case WLAN_CMD_SCAN_START: @@ -316,7 +316,7 @@ void vRunCommand(struct work_struct *work) pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; - if (pMgmt->uScanChannel == 0 ) { + if (pMgmt->uScanChannel == 0) { pMgmt->uScanChannel = pDevice->byMinChannel; } if (pMgmt->uScanChannel > pDevice->byMaxChannel) { @@ -327,7 +327,7 @@ void vRunCommand(struct work_struct *work) } else { if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n", pMgmt->uScanChannel); pMgmt->uScanChannel++; s_bCommandComplete(pDevice); spin_unlock_irq(&pDevice->lock); @@ -376,7 +376,7 @@ void vRunCommand(struct work_struct *work) pMgmt->uScanChannel++; while (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel) && - pMgmt->uScanChannel <= pDevice->byMaxChannel ){ + pMgmt->uScanChannel <= pDevice->byMaxChannel){ pMgmt->uScanChannel++; } @@ -437,7 +437,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_DISASSOCIATE_START : + case WLAN_CMD_DISASSOCIATE_START: pDevice->byReAssocCount = 0; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { @@ -461,7 +461,7 @@ void vRunCommand(struct work_struct *work) (8), &Status); pDevice->bLinkPass = false; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); // unlock command busy pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; pItemSSID->len = 0; @@ -485,7 +485,7 @@ void vRunCommand(struct work_struct *work) return; } - memcpy(pMgmt->abyAdHocSSID,pMgmt->abyDesireSSID, + memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN); pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; @@ -495,14 +495,14 @@ void vRunCommand(struct work_struct *work) if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n",pItemSSID->len); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n",pItemSSIDCurr->len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n", pItemSSID->len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n", pItemSSIDCurr->len); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" desire ssid = %s\n", pItemSSID->abySSID); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" curr ssid = %s\n", pItemSSIDCurr->abySSID); } if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || - ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)&& (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { if (pItemSSID->len == pItemSSIDCurr->len) { if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) { @@ -513,7 +513,7 @@ void vRunCommand(struct work_struct *work) } netif_stop_queue(pDevice->dev); pDevice->bLinkPass = false; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); } // set initial state pMgmt->eCurrState = WMAC_STATE_IDLE; @@ -546,11 +546,11 @@ void vRunCommand(struct work_struct *work) // if Adhoc mode else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { - if (netif_queue_stopped(pDevice->dev)){ + if (netif_queue_stopped(pDevice->dev)) { netif_wake_queue(pDevice->dev); } pDevice->bLinkPass = true; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); pMgmt->sNodeDBTable[0].bActive = true; pMgmt->sNodeDBTable[0].uInActiveCount = 0; } @@ -559,7 +559,7 @@ void vRunCommand(struct work_struct *work) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CreateOwn IBSS by CurrMode = IBSS_STA\n"); vMgrCreateOwnIBSS((void *) pDevice, &Status); - if (Status != CMD_STATUS_SUCCESS){ + if (Status != CMD_STATUS_SUCCESS) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); } @@ -575,7 +575,7 @@ void vRunCommand(struct work_struct *work) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CreateOwn IBSS by CurrMode = STANDBY\n"); vMgrCreateOwnIBSS((void *) pDevice, &Status); - if (Status != CMD_STATUS_SUCCESS){ + if (Status != CMD_STATUS_SUCCESS) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); } @@ -595,7 +595,7 @@ void vRunCommand(struct work_struct *work) // if(pDevice->bWPASuppWextEnabled == true) { union iwreq_data wrqu; - memset(&wrqu, 0, sizeof (wrqu)); + memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n"); wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); @@ -605,7 +605,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_AUTHENTICATE_WAIT : + case WLAN_AUTHENTICATE_WAIT: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); if (pMgmt->eCurrState == WMAC_STATE_AUTH) { pDevice->byLinkWaitCount = 0; @@ -621,12 +621,12 @@ void vRunCommand(struct work_struct *work) return; } } - else if(pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { + else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); } - else if(pDevice->byLinkWaitCount <= 4){ //mike add:wait another 2 sec if authenticated_frame delay! - pDevice->byLinkWaitCount ++; - printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount); + else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay! + pDevice->byLinkWaitCount++; + printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); spin_unlock_irq(&pDevice->lock); vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT/2); return; @@ -636,7 +636,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_ASSOCIATE_WAIT : + case WLAN_ASSOCIATE_WAIT: if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); if (pDevice->ePSMode != WMAC_POWER_CAM) { @@ -651,20 +651,20 @@ void vRunCommand(struct work_struct *work) pDevice->byLinkWaitCount = 0; pDevice->byReAssocCount = 0; pDevice->bLinkPass = true; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); s_bClearBSSID_SCAN(pDevice); - if (netif_queue_stopped(pDevice->dev)){ + if (netif_queue_stopped(pDevice->dev)) { netif_wake_queue(pDevice->dev); } } - else if(pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { + else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); } - else if(pDevice->byLinkWaitCount <= 4){ //mike add:wait another 2 sec if associated_frame delay! - pDevice->byLinkWaitCount ++; - printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount); + else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay! + pDevice->byLinkWaitCount++; + printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); spin_unlock_irq(&pDevice->lock); vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT/2); return; @@ -673,7 +673,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_AP_MODE_START : + case WLAN_CMD_AP_MODE_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { @@ -681,7 +681,7 @@ void vRunCommand(struct work_struct *work) pMgmt->eCurrState = WMAC_STATE_IDLE; pMgmt->eCurrMode = WMAC_MODE_STANDBY; pDevice->bLinkPass = false; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); if (pDevice->bEnableHostWEP == true) BSSvClearNodeDBTable(pDevice, 1); else @@ -698,19 +698,19 @@ void vRunCommand(struct work_struct *work) // always turn off unicast bit MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_UNICAST); pDevice->byRxMode &= ~RCR_UNICAST; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode); BSSvAddMulticastNode(pDevice); - if (netif_queue_stopped(pDevice->dev)){ + if (netif_queue_stopped(pDevice->dev)) { netif_wake_queue(pDevice->dev); } pDevice->bLinkPass = true; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); schedule_delayed_work(&pDevice->second_callback_work, HZ); } s_bCommandComplete(pDevice); break; - case WLAN_CMD_TX_PSPACKET_START : + case WLAN_CMD_TX_PSPACKET_START: // DTIM Multicast tx if (pMgmt->sNodeDBTable[0].bRxPSPoll) { while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { @@ -789,12 +789,12 @@ void vRunCommand(struct work_struct *work) 1, &byTmp); - if ( ntStatus != STATUS_SUCCESS ) { + if (ntStatus != STATUS_SUCCESS) { s_bCommandComplete(pDevice); spin_unlock_irq(&pDevice->lock); return; } - if ( (byTmp & GPIO3_DATA) == 0 ) { + if ((byTmp & GPIO3_DATA) == 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n"); // Old commands are useless. // empty command Q @@ -809,7 +809,7 @@ void vRunCommand(struct work_struct *work) pDevice->byKeyIndex = 0; pDevice->bTransmitKey = false; spin_unlock_irq(&pDevice->lock); - KeyvInitTable(pDevice,&pDevice->sKey); + KeyvInitTable(pDevice, &pDevice->sKey); spin_lock_irq(&pDevice->lock); pMgmt->byCSSPK = KEY_CTL_NONE; pMgmt->byCSSGK = KEY_CTL_NONE; @@ -828,7 +828,7 @@ void vRunCommand(struct work_struct *work) // if(pDevice->bWPASuppWextEnabled == true) { union iwreq_data wrqu; - memset(&wrqu, 0, sizeof (wrqu)); + memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); @@ -850,15 +850,15 @@ void vRunCommand(struct work_struct *work) netif_stop_queue(pDevice->dev); CARDbRadioPowerOff(pDevice); - MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_OFF); + MACvRegBitsOn(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_OFF); pDevice->bHWRadioOff = true; } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_ON........................\n"); pDevice->bHWRadioOff = false; CARDbRadioPowerOn(pDevice); - MACvRegBitsOff(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_ON); + MACvRegBitsOff(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_ON); } } @@ -894,14 +894,14 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_CHANGE_ANTENNA_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change from Antenna%d to", (int)pDevice->dwRxAntennaSel); - if ( pDevice->dwRxAntennaSel == 0) { - pDevice->dwRxAntennaSel=1; + if (pDevice->dwRxAntennaSel == 0) { + pDevice->dwRxAntennaSel = 1; if (pDevice->bTxRxAntInv == true) BBvSetAntennaMode(pDevice, ANT_RXA); else BBvSetAntennaMode(pDevice, ANT_RXB); } else { - pDevice->dwRxAntennaSel=0; + pDevice->dwRxAntennaSel = 0; if (pDevice->bTxRxAntInv == true) BBvSetAntennaMode(pDevice, ANT_RXB); else @@ -916,8 +916,8 @@ void vRunCommand(struct work_struct *work) break; case WLAN_CMD_MAC_DISPOWERSAVING_START: - ControlvReadByte (pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); - if ( (byData & PSCTL_PS) != 0 ) { + ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); + if ((byData & PSCTL_PS) != 0) { // disable power saving hw function CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_DISABLE_PS, @@ -968,7 +968,7 @@ static int s_bCommandComplete(struct vnt_private *pDevice) ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE); pDevice->cbFreeCmdQueue++; pDevice->bCmdRunning = true; - switch ( pDevice->eCommand ) { + switch (pDevice->eCommand) { case WLAN_CMD_BSSID_SCAN: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); pDevice->eCommandState = WLAN_CMD_SCAN_START; @@ -1123,7 +1123,7 @@ static int s_bClearBSSID_SCAN(struct vnt_private *pDevice) unsigned int ii; if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) { - for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii ++) { + for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) { if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN) pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE; ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE); -- cgit v1.2.3 From 383956442d7ab639777f84c3709390bc1b4daa78 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sat, 9 Nov 2013 01:00:00 +0200 Subject: staging: vt6655: replace C99 comments wtih C89 comments This patch replaces C99 comments with /* .. */ comments. Any commented code is deleted. Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 182 +++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 114 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index a23b591eeac3..9fd8baac64b9 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -64,7 +64,6 @@ /*--------------------- Static Variables --------------------------*/ static int msglevel = MSG_LEVEL_INFO; -//static int msglevel =MSG_LEVEL_DEBUG; const unsigned short awHWRetry0[5][5] = { {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, @@ -142,7 +141,7 @@ BSSpSearchBSSList( } if (pbyBSSID != NULL) { - // match BSSID first + /* match BSSID first */ for (ii = 0; ii < MAX_BSS_NUM; ii++) { pCurrBSS = &(pMgmt->sBSSList[ii]); if (pDevice->bLinkPass == false) pCurrBSS->bSelected = false; @@ -151,7 +150,7 @@ BSSpSearchBSSList( if (ether_addr_equal(pCurrBSS->abyBSSID, pbyBSSID)) { if (pSSID != NULL) { - // compare ssid + /* compare ssid */ if (!memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID, pSSID->len)) { @@ -176,26 +175,26 @@ BSSpSearchBSSList( } } } else { - // ignore BSSID + /* ignore BSSID */ for (ii = 0; ii < MAX_BSS_NUM; ii++) { pCurrBSS = &(pMgmt->sBSSList[ii]); - //2007-0721-01by MikeLiu + /* 2007-0721-01by MikeLiu */ pCurrBSS->bSelected = false; if (pCurrBSS->bActive) { if (pSSID != NULL) { - // matched SSID + /* matched SSID */ if (!!memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID, pSSID->len) || (pSSID->len != ((PWLAN_IE_SSID)pCurrBSS->abySSID)->len)) { - // SSID not match skip this BSS + /* SSID not match skip this BSS */ continue; } } if (((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) || ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) ) { - // Type not match skip this BSS + /* Type not match skip this BSS */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSS type mismatch.... Config[%d] BSS[0x%04x]\n", pMgmt->eConfigMode, pCurrBSS->wCapInfo); continue; } @@ -203,35 +202,16 @@ BSSpSearchBSSList( if (ePhyType != PHY_TYPE_AUTO) { if (((ePhyType == PHY_TYPE_11A) && (PHY_TYPE_11A != pCurrBSS->eNetworkTypeInUse)) || ((ePhyType != PHY_TYPE_11A) && (PHY_TYPE_11A == pCurrBSS->eNetworkTypeInUse))) { - // PhyType not match skip this BSS + /* PhyType not match skip this BSS */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Physical type mismatch.... ePhyType[%d] BSS[%d]\n", ePhyType, pCurrBSS->eNetworkTypeInUse); continue; } } -/* - if (pMgmt->eAuthenMode < WMAC_AUTH_WPA) { - if (pCurrBSS->bWPAValid == true) { - // WPA AP will reject connection of station without WPA enable. - continue; - } - } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || - (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) { - if (pCurrBSS->bWPAValid == false) { - // station with WPA enable can't join NonWPA AP. - continue; - } - } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || - (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { - if (pCurrBSS->bWPA2Valid == false) { - // station with WPA2 enable can't join NonWPA2 AP. - continue; - } - } -*/ + if (pSelect == NULL) { pSelect = pCurrBSS; } else { - // compare RSSI, select signal strong one + /* compare RSSI, select signal strong one */ if (pCurrBSS->uRSSI < pSelect->uRSSI) { pSelect = pCurrBSS; } @@ -240,13 +220,6 @@ BSSpSearchBSSList( } if (pSelect != NULL) { pSelect->bSelected = true; -/* - if (pDevice->bRoaming == false) { - // Einsn Add @20070907 - memset(pbyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - memcpy(pbyDesireSSID,pCurrBSS->abySSID,WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - }*/ - return pSelect; } } @@ -278,7 +251,6 @@ BSSvClearBSSList( if (pMgmt->sBSSList[ii].bActive && ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) { - // bKeepCurrBSSID = false; continue; } } @@ -385,7 +357,7 @@ BSSbInsertToBSSList( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get free KnowBSS node failed.\n"); return false; } - // save the BSS info + /* save the BSS info */ pBSSList->bActive = true; memcpy(pBSSList->abyBSSID, abyBSSIDAddr, WLAN_BSSID_LEN); HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp)); @@ -416,7 +388,7 @@ BSSbInsertToBSSList( pBSSList->sERP.byERP = psERP->byERP; pBSSList->sERP.bERPExist = psERP->bERPExist; - // Check if BSS is 802.11a/b/g + /* check if BSS is 802.11a/b/g */ if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; } else { @@ -434,7 +406,7 @@ BSSbInsertToBSSList( if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { - // assoc with BSS + /* assoc with BSS */ if (pBSSList == pMgmt->pCurrBSS) { bParsingQuiet = true; } @@ -490,7 +462,7 @@ BSSbInsertToBSSList( } if (pDevice->bUpdateBBVGA) { - // Moniter if RSSI is too strong. + /* monitor if RSSI is too strong */ pBSSList->byRSSIStatCnt = 0; RFvRSSITodBm(pDevice, (unsigned char)(pRxPacket->uRSSI), &pBSSList->ldBmMAX); pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX; @@ -507,7 +479,7 @@ BSSbInsertToBSSList( if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) { if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) && (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) { - // valid EID + /* valid EID */ if (pQuiet == NULL) { pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; CARDbSetQuiet(pMgmt->pAdapter, @@ -552,7 +524,7 @@ BSSbInsertToBSSList( * true if success. * -*/ -// TODO: input structure modify +/* TODO: input structure modify */ bool BSSbUpdateToBSSList( @@ -593,7 +565,6 @@ BSSbUpdateToBSSList( pBSSList->wCapInfo = cpu_to_le16(wCapInfo); pBSSList->uClearCount = 0; pBSSList->uChannel = byCurrChannel; -// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSbUpdateToBSSList: pBSSList->uChannel: %d\n", pBSSList->uChannel); if (pSSID->len > WLAN_SSID_MAXLEN) pSSID->len = WLAN_SSID_MAXLEN; @@ -610,7 +581,7 @@ BSSbUpdateToBSSList( pBSSList->sERP.byERP = psERP->byERP; pBSSList->sERP.bERPExist = psERP->bERPExist; - // Check if BSS is 802.11a/b/g + /* check if BSS is 802.11a/b/g */ if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; } else { @@ -629,13 +600,13 @@ BSSbUpdateToBSSList( if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { - // assoc with BSS + /* assoc with BSS */ if (pBSSList == pMgmt->pCurrBSS) { bParsingQuiet = true; } } - WPA_ClearRSN(pBSSList); //mike update + WPA_ClearRSN(pBSSList); /* mike update */ if (pRSNWPA != NULL) { unsigned int uLen = pRSNWPA->len + 2; @@ -646,7 +617,7 @@ BSSbUpdateToBSSList( } } - WPA2_ClearRSN(pBSSList); //mike update + WPA2_ClearRSN(pBSSList); /* mike update */ if (pRSN != NULL) { unsigned int uLen = pRSN->len + 2; @@ -659,7 +630,7 @@ BSSbUpdateToBSSList( if (pRxPacket->uRSSI != 0) { RFvRSSITodBm(pDevice, (unsigned char)(pRxPacket->uRSSI), &ldBm); - // Moniter if RSSI is too strong. + /* monitor if RSSI is too strong */ pBSSList->byRSSIStatCnt++; pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT; pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm; @@ -679,7 +650,7 @@ BSSbUpdateToBSSList( if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) { if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) && (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) { - // valid EID + /* valid EID */ if (pQuiet == NULL) { pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; CARDbSetQuiet(pMgmt->pAdapter, @@ -732,7 +703,7 @@ BSSDBbIsSTAInNodeDB(void *pMgmtObject, unsigned char *abyDstAddr, PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; unsigned int ii; - // Index = 0 reserved for AP Node + /* Index = 0 reserved for AP Node */ for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive) { if (ether_addr_equal(abyDstAddr, @@ -765,8 +736,10 @@ BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex) unsigned int BigestCount = 0; unsigned int SelectIndex; struct sk_buff *skb; - // Index = 0 reserved for AP Node (In STA mode) - // Index = 0 reserved for Broadcast/MultiCast (In AP mode) + /* + * Index = 0 reserved for AP Node (In STA mode) + * Index = 0 reserved for Broadcast/MultiCast (In AP mode) + */ SelectIndex = 1; for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive) { @@ -779,11 +752,11 @@ BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex) } } - // if not found replace uInActiveCount is largest one. + /* if not found replace uInActiveCount is largest one */ if (ii == (MAX_NODE_NUM + 1)) { *puNodeIndex = SelectIndex; DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Replace inactive node = %d\n", SelectIndex); - // clear ps buffer + /* clear ps buffer */ if (pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue.next != NULL) { while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue)) != NULL) dev_kfree_skb(skb); @@ -795,7 +768,7 @@ BSSvCreateOneNode(void *hDeviceContext, unsigned int *puNodeIndex) memset(&pMgmt->sNodeDBTable[*puNodeIndex], 0, sizeof(KnownNodeDB)); pMgmt->sNodeDBTable[*puNodeIndex].bActive = true; pMgmt->sNodeDBTable[*puNodeIndex].uRatePollTimeout = FALLBACK_POLL_SECOND; - // for AP mode PS queue + /* for AP mode PS queue */ skb_queue_head_init(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue); pMgmt->sNodeDBTable[*puNodeIndex].byAuthSequence = 0; pMgmt->sNodeDBTable[*puNodeIndex].wEnQueueCnt = 0; @@ -826,9 +799,9 @@ BSSvRemoveOneNode( while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue)) != NULL) dev_kfree_skb(skb); - // clear context + /* clear context */ memset(&pMgmt->sNodeDBTable[uNodeIndex], 0, sizeof(KnownNodeDB)); - // clear tx bit map + /* clear tx bit map */ pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[uNodeIndex].wAID >> 3] &= ~byMask[pMgmt->sNodeDBTable[uNodeIndex].wAID & 7]; return; @@ -885,8 +858,7 @@ BSSvUpdateAPNode( #ifdef PLICE_DEBUG printk("BSSvUpdateAPNode:MaxSuppRate is %d\n", pMgmt->sNodeDBTable[0].wMaxSuppRate); #endif - // Auto rate fallback function initiation. - // RATEbInit(pDevice); + /* auto rate fallback function initiation */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate); }; @@ -944,7 +916,7 @@ BSSvAddMulticastNode( * none. * -*/ -//2008-4-14 by chester for led issue +/* 2008-4-14 by chester for led issue */ #ifdef FOR_LED_ON_NOTEBOOK bool cc = false; unsigned int status; @@ -961,7 +933,7 @@ BSSvSecondCallBack( unsigned int uSleepySTACnt = 0; unsigned int uNonShortSlotSTACnt = 0; unsigned int uLongPreambleSTACnt = 0; - viawget_wpa_header *wpahdr; //DavidWang + viawget_wpa_header *wpahdr; /* DavidWang */ spin_lock_irq(&pDevice->lock); @@ -969,7 +941,7 @@ BSSvSecondCallBack( pDevice->byERPFlag &= ~(WLAN_SET_ERP_BARKER_MODE(1) | WLAN_SET_ERP_NONERP_PRESENT(1)); - //2008-4-14 by chester for led issue + /* 2008-4-14 by chester for led issue */ #ifdef FOR_LED_ON_NOTEBOOK MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO); if (((!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->bHWRadioOff == false)) || ((pDevice->byGPIO & GPIO0_DATA) && (pDevice->bHWRadioOff == true))) && (cc == false)) { @@ -977,7 +949,6 @@ BSSvSecondCallBack( } else if (cc == true) { if (pDevice->bHWRadioOff == true) { if (!(pDevice->byGPIO & GPIO0_DATA)) -//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) { if (status == 1) goto start; status = 1; @@ -985,12 +956,10 @@ BSSvSecondCallBack( pMgmt->sNodeDBTable[0].bActive = false; pMgmt->eCurrMode = WMAC_MODE_STANDBY; pMgmt->eCurrState = WMAC_STATE_IDLE; - //netif_stop_queue(pDevice->dev); pDevice->bLinkPass = false; } if (pDevice->byGPIO & GPIO0_DATA) -//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) { if (status == 2) goto start; status = 2; @@ -998,7 +967,6 @@ BSSvSecondCallBack( } } else { if (pDevice->byGPIO & GPIO0_DATA) -//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) { if (status == 3) goto start; status = 3; @@ -1006,12 +974,10 @@ BSSvSecondCallBack( pMgmt->sNodeDBTable[0].bActive = false; pMgmt->eCurrMode = WMAC_MODE_STANDBY; pMgmt->eCurrState = WMAC_STATE_IDLE; - //netif_stop_queue(pDevice->dev); pDevice->bLinkPass = false; } if (!(pDevice->byGPIO & GPIO0_DATA)) -//||(!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) { if (status == 4) goto start; status = 4; @@ -1025,13 +991,14 @@ start: if (pDevice->wUseProtectCntDown > 0) { pDevice->wUseProtectCntDown--; } else { - // disable protect mode + /* disable protect mode */ pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1)); } { pDevice->byReAssocCount++; - if ((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) { //10 sec timeout + /* 10 sec timeout */ + if ((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) { printk("Re-association timeout!!!\n"); pDevice->byReAssocCount = 0; #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT @@ -1053,7 +1020,7 @@ start: for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive) { - // Increase in-activity counter + /* increase in-activity counter */ pMgmt->sNodeDBTable[ii].uInActiveCount++; if (ii > 0) { @@ -1067,7 +1034,7 @@ start: if (pMgmt->sNodeDBTable[ii].eNodeState >= NODE_ASSOC) { pDevice->uAssocCount++; - // check if Non ERP exist + /* check if Non ERP exist */ if (pMgmt->sNodeDBTable[ii].uInActiveCount < ERP_RECOVER_COUNT) { if (!pMgmt->sNodeDBTable[ii].bShortPreamble) { pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1); @@ -1082,23 +1049,19 @@ start: } } - // check if any STA in PS mode + /* check if any STA in PS mode */ if (pMgmt->sNodeDBTable[ii].bPSEnable) uSleepySTACnt++; } - // Rate fallback check + /* rate fallback check */ if (!pDevice->bFixRate) { -/* - if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (ii == 0)) - RATEvTxRateFallBack(pDevice, &(pMgmt->sNodeDBTable[ii])); -*/ if (ii > 0) { - // ii = 0 for multicast node (AP & Adhoc) + /* ii = 0 for multicast node (AP & Adhoc) */ RATEvTxRateFallBack((void *)pDevice, &(pMgmt->sNodeDBTable[ii])); } else { - // ii = 0 reserved for unicast AP node (Infra STA) + /* ii = 0 reserved for unicast AP node (Infra STA) */ if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) #ifdef PLICE_DEBUG printk("SecondCallback:Before:TxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate); @@ -1112,7 +1075,7 @@ start: } - // check if pending PS queue + /* check if pending PS queue */ if (pMgmt->sNodeDBTable[ii].wEnQueueCnt != 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending \n", ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); @@ -1127,7 +1090,7 @@ start: } if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->eCurrentPHYType == PHY_TYPE_11G)) { - // on/off protect mode + /* on/off protect mode */ if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)) { if (!pDevice->bProtectMode) { MACvEnableProtectMD(pDevice->PortOffset); @@ -1139,7 +1102,7 @@ start: pDevice->bProtectMode = false; } } - // on/off short slot time + /* on/off short slot time */ if (uNonShortSlotSTACnt > 0) { if (pDevice->bShortSlotTime) { @@ -1155,7 +1118,7 @@ start: } } - // on/off barker long preamble mode + /* on/off barker long preamble mode */ if (uLongPreambleSTACnt > 0) { if (!pDevice->bBarkerPreambleMd) { @@ -1171,7 +1134,7 @@ start: } - // Check if any STA in PS mode, enable DTIM multicast deliver + /* check if any STA in PS mode, enable DTIM multicast deliver */ if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { if (uSleepySTACnt > 0) pMgmt->sNodeDBTable[0].bPSEnable = true; @@ -1184,9 +1147,9 @@ start: if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { - if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS + /* assoc with BSS */ + if (pMgmt->sNodeDBTable[0].bActive) { if (pDevice->bUpdateBBVGA) { - // s_vCheckSensitivity((void *) pDevice); s_vCheckPreEDThreshold((void *)pDevice); } @@ -1232,12 +1195,18 @@ start: if (pDevice->uAutoReConnectTime < 10) { pDevice->uAutoReConnectTime++; #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT - //network manager support need not do Roaming scan??? + /* + * network manager support need not do + * Roaming scan??? + */ if (pDevice->bWPASuppWextEnabled == true) pDevice->uAutoReConnectTime = 0; #endif } else { - //mike use old encryption status for wpa reauthen + /* + * mike use old encryption status + * for wpa reauthentication + */ if (pDevice->bWPADEVUp) pDevice->eEncryptionStatus = pDevice->eOldEncryptionStatus; @@ -1252,7 +1221,7 @@ start: } if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { - // if adhoc started which essid is NULL string, rescanning. + /* if adhoc started which essid is NULL string, rescanning */ if ((pMgmt->eCurrState == WMAC_STATE_STARTED) && (pCurrSSID->len == 0)) { if (pDevice->uAutoReConnectTime < 10) { pDevice->uAutoReConnectTime++; @@ -1266,7 +1235,6 @@ start: } if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { if (pDevice->bUpdateBBVGA) { - //s_vCheckSensitivity((void *) pDevice); s_vCheckPreEDThreshold((void *)pDevice); } if (pMgmt->sNodeDBTable[0].uInActiveCount >= ADHOC_LOST_BEACON_COUNT) { @@ -1318,10 +1286,6 @@ BSSvUpdateNodeTxCounter( unsigned short wFallBackRate = RATE_1M; unsigned char byFallBack; unsigned int ii; -// unsigned int txRetryTemp; -//PLICE_DEBUG-> - //txRetryTemp = byTxRetry; -//PLICE_DEBUG <- pTxBufHead = (PSTxBufHead) pbyBuffer; if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_0) { byFallBack = AUTO_FB_0; @@ -1330,28 +1294,24 @@ BSSvUpdateNodeTxCounter( } else { byFallBack = AUTO_FB_NONE; } - wRate = pTxBufHead->wReserved; //?wRate + wRate = pTxBufHead->wReserved; - // Only Unicast using support rates + /* Only Unicast using support rates */ if (pTxBufHead->wFIFOCtl & FIFOCTL_NEEDACK) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wRate %04X, byTsr0 %02X, byTsr1 %02X\n", wRate, byTsr0, byTsr1); if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) { pMgmt->sNodeDBTable[0].uTxAttempts += 1; if ((byTsr1 & TSR1_TERR) == 0) { - // transmit success, TxAttempts at least plus one + /* transmit success, TxAttempts at least plus one */ pMgmt->sNodeDBTable[0].uTxOk[MAX_RATE]++; if ((byFallBack == AUTO_FB_NONE) || (wRate < RATE_18M)) { wFallBackRate = wRate; } else if (byFallBack == AUTO_FB_0) { -//PLICE_DEBUG if (byTxRetry < 5) wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry]; - //wFallBackRate = awHWRetry0[wRate-RATE_12M][byTxRetry]; - //wFallBackRate = awHWRetry0[wRate-RATE_18M][txRetryTemp] +1; else wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; - //wFallBackRate = awHWRetry0[wRate-RATE_12M][4]; } else if (byFallBack == AUTO_FB_1) { if (byTxRetry < 5) wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry]; @@ -1369,17 +1329,12 @@ BSSvUpdateNodeTxCounter( (wRate < RATE_18M)) { pMgmt->sNodeDBTable[0].uTxFail[wRate] += byTxRetry; } else if (byFallBack == AUTO_FB_0) { -//PLICE_DEBUG for (ii = 0; ii < byTxRetry; ii++) - //for (ii=0;iisNodeDBTable[0].uTxFail[wFallBackRate]++; } @@ -1402,7 +1357,7 @@ BSSvUpdateNodeTxCounter( if (BSSDBbIsSTAInNodeDB((void *)pMgmt, &(pMACHeader->abyAddr1[0]), &uNodeIndex)) { pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts += 1; if ((byTsr1 & TSR1_TERR) == 0) { - // transmit success, TxAttempts at least plus one + /* transmit success, TxAttempts at least plus one */ pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++; if ((byFallBack == AUTO_FB_NONE) || (wRate < RATE_18M)) { @@ -1485,7 +1440,7 @@ BSSvClearNodeDBTable( for (ii = uStartIndex; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive) { - // check if sTxPSQueue has been initial + /* check if sTxPSQueue has been initial */ if (pMgmt->sNodeDBTable[ii].sTxPSQueue.next != NULL) { while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS skb != NULL %d\n", ii); @@ -1517,7 +1472,7 @@ void s_vCheckSensitivity( ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); if (pBSSList != NULL) { - // Updata BB Reg if RSSI is too strong. + /* Update BB Reg if RSSI is too strong */ long LocalldBmAverage = 0; long uNumofdBm = 0; for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { @@ -1580,7 +1535,7 @@ void s_uCalculateLinkQual( pDevice->scStatistic.RxOkCnt; TxOkRatio = (TxCnt < 6) ? 4000 : ((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt); RxOkRatio = (RxCnt < 6) ? 2000 : ((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); -//decide link quality + /* decide link quality */ if (pDevice->bLinkPass != true) { pDevice->scStatistic.LinkQuality = 0; pDevice->scStatistic.SignalStren = 0; @@ -1618,7 +1573,6 @@ void s_vCheckPreEDThreshold( pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); if (pBSSList != NULL) { pDevice->byBBPreEDRSSI = (unsigned char) (~(pBSSList->ldBmAverRange) + 1); - //BBvUpdatePreEDThreshold(pDevice, false); } } return; -- cgit v1.2.3 From 347a0475a627d77684b16b718230d5e5395f1cad Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sat, 9 Nov 2013 01:00:01 +0200 Subject: staging: vt6655: remove braces for single statement blocks This patch removes braces for single statement blocks, clearing these types of checkpatch.pl warnings: WARNING: braces {} are not necessary for single statement blocks WARNING: braces {} are not necessary for any arm of this statement Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 67 ++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 9fd8baac64b9..6c27be4ae9fa 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -130,14 +130,12 @@ BSSpSearchBSSList( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSpSearchBSSList BSSID[%pM]\n", pbyDesireBSSID); if ((!is_broadcast_ether_addr(pbyDesireBSSID)) && - (memcmp(pbyDesireBSSID, ZeroBSSID, 6) != 0)) { + (memcmp(pbyDesireBSSID, ZeroBSSID, 6) != 0)) pbyBSSID = pbyDesireBSSID; - } } if (pbyDesireSSID != NULL) { - if (((PWLAN_IE_SSID)pbyDesireSSID)->len != 0) { + if (((PWLAN_IE_SSID)pbyDesireSSID)->len != 0) pSSID = (PWLAN_IE_SSID) pbyDesireSSID; - } } if (pbyBSSID != NULL) { @@ -212,9 +210,8 @@ BSSpSearchBSSList( pSelect = pCurrBSS; } else { /* compare RSSI, select signal strong one */ - if (pCurrBSS->uRSSI < pSelect->uRSSI) { + if (pCurrBSS->uRSSI < pSelect->uRSSI) pSelect = pCurrBSS; - } } } } @@ -392,11 +389,10 @@ BSSbInsertToBSSList( if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; } else { - if (pBSSList->sERP.bERPExist == true) { + if (pBSSList->sERP.bERPExist == true) pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; - } else { + else pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; - } } pBSSList->byRxRate = pRxPacket->byRxRate; @@ -407,9 +403,8 @@ BSSbInsertToBSSList( if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { /* assoc with BSS */ - if (pBSSList == pMgmt->pCurrBSS) { + if (pBSSList == pMgmt->pCurrBSS) bParsingQuiet = true; - } } WPA_ClearRSN(pBSSList); @@ -573,11 +568,10 @@ BSSbUpdateToBSSList( memcpy(pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); memcpy(pBSSList->abySuppRates, pSuppRates, pSuppRates->len + WLAN_IEHDR_LEN); - if (pExtSuppRates != NULL) { + if (pExtSuppRates != NULL) memcpy(pBSSList->abyExtSuppRates, pExtSuppRates, pExtSuppRates->len + WLAN_IEHDR_LEN); - } else { + else memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); - } pBSSList->sERP.byERP = psERP->byERP; pBSSList->sERP.bERPExist = psERP->bERPExist; @@ -585,11 +579,10 @@ BSSbUpdateToBSSList( if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; } else { - if (pBSSList->sERP.bERPExist == true) { + if (pBSSList->sERP.bERPExist == true) pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; - } else { + else pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; - } } pBSSList->byRxRate = pRxPacket->byRxRate; @@ -601,9 +594,8 @@ BSSbUpdateToBSSList( if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { /* assoc with BSS */ - if (pBSSList == pMgmt->pCurrBSS) { + if (pBSSList == pMgmt->pCurrBSS) bParsingQuiet = true; - } } WPA_ClearRSN(pBSSList); /* mike update */ @@ -635,9 +627,8 @@ BSSbUpdateToBSSList( pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT; pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm; for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { - if (pBSSList->ldBmAverage[ii] != 0) { + if (pBSSList->ldBmAverage[ii] != 0) pBSSList->ldBmMAX = max(pBSSList->ldBmAverage[ii], ldBm); - } } } @@ -832,9 +823,8 @@ BSSvUpdateAPNode( memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB)); pMgmt->sNodeDBTable[0].bActive = true; - if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) uRateLen = WLAN_RATES_MAXLEN_11B; - } pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pSuppRates, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, uRateLen); @@ -1149,9 +1139,8 @@ start: (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { /* assoc with BSS */ if (pMgmt->sNodeDBTable[0].bActive) { - if (pDevice->bUpdateBBVGA) { + if (pDevice->bUpdateBBVGA) s_vCheckPreEDThreshold((void *)pDevice); - } if ((pMgmt->sNodeDBTable[0].uInActiveCount >= (LOST_BEACON_COUNT/2)) && (pDevice->byBBVGACurrent != pDevice->abyBBVGA[0])) { @@ -1234,9 +1223,8 @@ start: }; } if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { - if (pDevice->bUpdateBBVGA) { + if (pDevice->bUpdateBBVGA) s_vCheckPreEDThreshold((void *)pDevice); - } if (pMgmt->sNodeDBTable[0].uInActiveCount >= ADHOC_LOST_BEACON_COUNT) { DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost other STA beacon [%d] sec, started !\n", pMgmt->sNodeDBTable[0].uInActiveCount); pMgmt->sNodeDBTable[0].uInActiveCount = 0; @@ -1287,13 +1275,12 @@ BSSvUpdateNodeTxCounter( unsigned char byFallBack; unsigned int ii; pTxBufHead = (PSTxBufHead) pbyBuffer; - if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_0) { + if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_0) byFallBack = AUTO_FB_0; - } else if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_1) { + else if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_1) byFallBack = AUTO_FB_1; - } else { + else byFallBack = AUTO_FB_NONE; - } wRate = pTxBufHead->wReserved; /* Only Unicast using support rates */ @@ -1331,11 +1318,10 @@ BSSvUpdateNodeTxCounter( } else if (byFallBack == AUTO_FB_0) { for (ii = 0; ii < byTxRetry; ii++) { - if (ii < 5) { + if (ii < 5) wFallBackRate = awHWRetry0[wRate-RATE_18M][ii]; - } else { + else wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; - } pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; } } else if (byFallBack == AUTO_FB_1) { @@ -1511,9 +1497,8 @@ BSSvClearAnyBSSJoinRecord( PSMgmtObject pMgmt = pDevice->pMgmt; unsigned int ii; - for (ii = 0; ii < MAX_BSS_NUM; ii++) { + for (ii = 0; ii < MAX_BSS_NUM; ii++) pMgmt->sBSSList[ii].bSelected = false; - } return; } @@ -1541,13 +1526,12 @@ void s_uCalculateLinkQual( pDevice->scStatistic.SignalStren = 0; } else { RFvRSSITodBm(pDevice, (unsigned char)(pDevice->uCurrRSSI), &ldBm); - if (-ldBm < 50) { + if (-ldBm < 50) RssiRatio = 4000; - } else if (-ldBm > 90) { + else if (-ldBm > 90) RssiRatio = 0; - } else { + else RssiRatio = (40-(-ldBm-50))*4000/40; - } pDevice->scStatistic.SignalStren = RssiRatio/40; pDevice->scStatistic.LinkQuality = (RssiRatio+TxOkRatio+RxOkRatio)/100; } @@ -1571,9 +1555,8 @@ void s_vCheckPreEDThreshold( if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); - if (pBSSList != NULL) { + if (pBSSList != NULL) pDevice->byBBPreEDRSSI = (unsigned char) (~(pBSSList->ldBmAverRange) + 1); - } } return; } -- cgit v1.2.3 From b4f66ad83bcfa45247f5d587168b884435a566c4 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sat, 9 Nov 2013 01:00:02 +0200 Subject: staging: vt6655: put trailing statements on next line This patch fixes the following type of checkpatch.pl errors in drivers/staging/vt6655/bssdb.c file: ERROR: trailing statements should be on next line Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 6c27be4ae9fa..ef660cd88d45 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -142,7 +142,8 @@ BSSpSearchBSSList( /* match BSSID first */ for (ii = 0; ii < MAX_BSS_NUM; ii++) { pCurrBSS = &(pMgmt->sBSSList[ii]); - if (pDevice->bLinkPass == false) pCurrBSS->bSelected = false; + if (pDevice->bLinkPass == false) + pCurrBSS->bSelected = false; if ((pCurrBSS->bActive) && (pCurrBSS->bSelected == false)) { if (ether_addr_equal(pCurrBSS->abyBSSID, @@ -940,7 +941,8 @@ BSSvSecondCallBack( if (pDevice->bHWRadioOff == true) { if (!(pDevice->byGPIO & GPIO0_DATA)) { - if (status == 1) goto start; + if (status == 1) + goto start; status = 1; CARDbRadioPowerOff(pDevice); pMgmt->sNodeDBTable[0].bActive = false; @@ -951,14 +953,16 @@ BSSvSecondCallBack( } if (pDevice->byGPIO & GPIO0_DATA) { - if (status == 2) goto start; + if (status == 2) + goto start; status = 2; CARDbRadioPowerOn(pDevice); } } else { if (pDevice->byGPIO & GPIO0_DATA) { - if (status == 3) goto start; + if (status == 3) + goto start; status = 3; CARDbRadioPowerOff(pDevice); pMgmt->sNodeDBTable[0].bActive = false; @@ -969,7 +973,8 @@ BSSvSecondCallBack( } if (!(pDevice->byGPIO & GPIO0_DATA)) { - if (status == 4) goto start; + if (status == 4) + goto start; status = 4; CARDbRadioPowerOn(pDevice); } -- cgit v1.2.3 From 938db28b337b40faa4a5563f2f7e07ebda66ae7b Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sat, 9 Nov 2013 01:00:03 +0200 Subject: staging: vt6655: put brace on previous line Place braces on same line for code statements. Fix the following checkpatch.pl type of error for drivers/staging/vt6655/bssdb.c file: ERROR: that open brace { should be on the previous line Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index ef660cd88d45..3b39cb214418 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -939,8 +939,7 @@ BSSvSecondCallBack( cc = true; } else if (cc == true) { if (pDevice->bHWRadioOff == true) { - if (!(pDevice->byGPIO & GPIO0_DATA)) - { + if (!(pDevice->byGPIO & GPIO0_DATA)) { if (status == 1) goto start; status = 1; @@ -951,16 +950,14 @@ BSSvSecondCallBack( pDevice->bLinkPass = false; } - if (pDevice->byGPIO & GPIO0_DATA) - { + if (pDevice->byGPIO & GPIO0_DATA) { if (status == 2) goto start; status = 2; CARDbRadioPowerOn(pDevice); } } else { - if (pDevice->byGPIO & GPIO0_DATA) - { + if (pDevice->byGPIO & GPIO0_DATA) { if (status == 3) goto start; status = 3; @@ -971,8 +968,7 @@ BSSvSecondCallBack( pDevice->bLinkPass = false; } - if (!(pDevice->byGPIO & GPIO0_DATA)) - { + if (!(pDevice->byGPIO & GPIO0_DATA)) { if (status == 4) goto start; status = 4; @@ -1321,8 +1317,7 @@ BSSvUpdateNodeTxCounter( (wRate < RATE_18M)) { pMgmt->sNodeDBTable[0].uTxFail[wRate] += byTxRetry; } else if (byFallBack == AUTO_FB_0) { - for (ii = 0; ii < byTxRetry; ii++) - { + for (ii = 0; ii < byTxRetry; ii++) { if (ii < 5) wFallBackRate = awHWRetry0[wRate-RATE_18M][ii]; else -- cgit v1.2.3 From 1208f14a37fde2669b86bf1b1cd1122ad2ba3579 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sun, 10 Nov 2013 17:12:42 +0200 Subject: staging: vt6655: delete explicit comparison to bool This patch fixes the following type of coccinelle detected warnings for driver vt6655: WARNING: Comparison to bool Signed-off-by: Teodora Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 4 +- drivers/staging/vt6655/card.c | 8 +-- drivers/staging/vt6655/channel.c | 16 ++--- drivers/staging/vt6655/datarate.c | 8 +-- drivers/staging/vt6655/device_main.c | 60 +++++++++---------- drivers/staging/vt6655/dpc.c | 34 +++++------ drivers/staging/vt6655/hostap.c | 12 ++-- drivers/staging/vt6655/key.c | 44 +++++++------- drivers/staging/vt6655/mac.c | 4 +- drivers/staging/vt6655/power.c | 7 +-- drivers/staging/vt6655/rf.c | 2 +- drivers/staging/vt6655/vntwifi.c | 6 +- drivers/staging/vt6655/wcmd.c | 22 +++---- drivers/staging/vt6655/wctl.c | 6 +- drivers/staging/vt6655/wmgr.c | 109 +++++++++++++++++------------------ drivers/staging/vt6655/wpa.c | 2 +- drivers/staging/vt6655/wpa2.c | 4 +- drivers/staging/vt6655/wpactl.c | 12 ++-- 18 files changed, 176 insertions(+), 184 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 959568a1eb6a..fa14659ba43c 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1865,7 +1865,7 @@ BBvCalculateParameter( break; case RATE_5M: - if (bCCK == false) + if (!bCCK) cbBitCount++; cbUsCount = (cbBitCount * 10) / 55; cbTmp = (cbUsCount * 55) / 10; @@ -1879,7 +1879,7 @@ BBvCalculateParameter( case RATE_11M: - if (bCCK == false) + if (!bCCK) cbBitCount++; cbUsCount = cbBitCount / 11; cbTmp = cbUsCount * 11; diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index fbf18e23e78e..e95ecca549f7 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -1053,7 +1053,7 @@ CARDbAdd_PMKID_Candidate( for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) { pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii]; if (!memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) { - if ((bRSNCapExist == true) && (wRSNCap & BIT0)) { + if (bRSNCapExist && (wRSNCap & BIT0)) { pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; } else { pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); @@ -1064,7 +1064,7 @@ CARDbAdd_PMKID_Candidate( // New Candidate pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates]; - if ((bRSNCapExist == true) && (wRSNCap & BIT0)) { + if (bRSNCapExist && (wRSNCap & BIT0)) { pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; } else { pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); @@ -1190,7 +1190,7 @@ CARDbStartMeasure( } } while (pDevice->uNumOfMeasureEIDs != 0); - if (bExpired == false) { + if (!bExpired) { MACvSelectPage1(pDevice->PortOffset); VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART, LODWORD(qwStartTSF)); VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART + 4, HIDWORD(qwStartTSF)); @@ -1280,7 +1280,7 @@ CARDbSetQuiet( PSDevice pDevice = (PSDevice) pDeviceHandler; unsigned int ii = 0; - if (bResetQuiet == true) { + if (bResetQuiet) { MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); for (ii = 0; ii < MAX_QUIET_COUNT; ii++) { pDevice->sQuiet[ii].bEnable = false; diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index ba9481fa654f..3198a31e2ed7 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -441,8 +441,8 @@ void init_channel_table(void *pDeviceHandler) break; } - if ((pDevice->dwDiagRefCount != 0) || (pDevice->b11hEnable == true)) { - if (bMultiBand == true) { + if ((pDevice->dwDiagRefCount != 0) || pDevice->b11hEnable) { + if (bMultiBand) { for (ii = 0; ii < CARD_MAX_CHANNEL_TBL; ii++) { sChannelTbl[ii + 1].bValid = true; pDevice->abyRegPwr[ii + 1] = pDevice->abyOFDMDefaultPwr[ii + 1]; @@ -463,7 +463,7 @@ void init_channel_table(void *pDeviceHandler) } } } else if (pDevice->byZoneType <= CCODE_MAX) { - if (bMultiBand == true) { + if (bMultiBand) { for (ii = 0; ii < CARD_MAX_CHANNEL_TBL; ii++) { if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { sChannelTbl[ii + 1].bValid = true; @@ -531,7 +531,7 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) return bResult; } - if (sChannelTbl[uConnectionChannel].bValid == false) { + if (!sChannelTbl[uConnectionChannel].bValid) { return false; } @@ -557,7 +557,7 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) bResult &= RFbSelectChannel(pDevice->PortOffset, pDevice->byRFType, (unsigned char)uConnectionChannel); // Init Synthesizer Table - if (pDevice->bEnablePSMode == true) + if (pDevice->bEnablePSMode) RFvWriteWakeProgSyn(pDevice->PortOffset, pDevice->byRFType, uConnectionChannel); //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CARDbSetMediaChannel: %d\n", (unsigned char)uConnectionChannel); @@ -766,7 +766,7 @@ unsigned char auto_channel_select(void *pDeviceHandler, CARD_PHY_TYPE ePHYType) if (ePHYType == PHY_TYPE_11A) { for (ii = CB_MAX_CHANNEL_24G + 1; ii <= CB_MAX_CHANNEL; ii++) { - if (sChannelTbl[ii].bValid == true) { + if (sChannelTbl[ii].bValid) { if (byOptionChannel == 0) { byOptionChannel = (unsigned char) ii; } @@ -780,7 +780,7 @@ unsigned char auto_channel_select(void *pDeviceHandler, CARD_PHY_TYPE ePHYType) } else { byOptionChannel = 0; for (ii = 1; ii <= CB_MAX_CHANNEL_24G; ii++) { - if (sChannelTbl[ii].bValid == true) { + if (sChannelTbl[ii].bValid) { if (sChannelTbl[ii].byMAP == 0) { aiWeight[ii] += 100; } else if (sChannelTbl[ii].byMAP & 0x01) { @@ -807,7 +807,7 @@ unsigned char auto_channel_select(void *pDeviceHandler, CARD_PHY_TYPE ePHYType) } } for (ii = 1; ii <= CB_MAX_CHANNEL_24G; ii++) { - if ((sChannelTbl[ii].bValid == true) && + if (sChannelTbl[ii].bValid && (aiWeight[ii] > aiWeight[byOptionChannel])) { byOptionChannel = (unsigned char) ii; } diff --git a/drivers/staging/vt6655/datarate.c b/drivers/staging/vt6655/datarate.c index e7b6bc7de4ac..c9a89cd7633c 100644 --- a/drivers/staging/vt6655/datarate.c +++ b/drivers/staging/vt6655/datarate.c @@ -218,8 +218,7 @@ RATEvParseMaxRate( for (ii = 0; ii < uRateLen; ii++) { byRate = (unsigned char)(pItemRates->abyRates[ii]); - if (WLAN_MGMT_IS_BASICRATE(byRate) && - (bUpdateBasicRate == true)) { + if (WLAN_MGMT_IS_BASICRATE(byRate) && bUpdateBasicRate) { // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate)); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate)); @@ -329,7 +328,7 @@ RATEvTxRateFallBack( for (ii = 0; ii < MAX_RATE; ii++) { if (psNodeDBTable->wSuppRate & (0x0001<wTxDataRate; for (ii = psNodeDBTable->wTxDataRate; ii > 0;) { ii--; - if ((dwThroughputTbl[ii] > dwThroughput) && - (bAutoRate[ii] == true)) { + if ((dwThroughputTbl[ii] > dwThroughput) && bAutoRate[ii]) { dwThroughput = dwThroughputTbl[ii]; wIdxDownRate = (unsigned short) ii; } diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index e93fdc88d844..68cbaee29775 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -561,7 +561,7 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) pDevice->byTxAntennaMode = ANT_B; pDevice->dwTxAntennaSel = 1; pDevice->dwRxAntennaSel = 1; - if (pDevice->bTxRxAntInv == true) + if (pDevice->bTxRxAntInv) pDevice->byRxAntennaMode = ANT_A; else pDevice->byRxAntennaMode = ANT_B; @@ -578,13 +578,13 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) pDevice->dwRxAntennaSel = 0; if (byValue & EEP_ANTENNA_AUX) { pDevice->byTxAntennaMode = ANT_A; - if (pDevice->bTxRxAntInv == true) + if (pDevice->bTxRxAntInv) pDevice->byRxAntennaMode = ANT_B; else pDevice->byRxAntennaMode = ANT_A; } else { pDevice->byTxAntennaMode = ANT_B; - if (pDevice->bTxRxAntInv == true) + if (pDevice->bTxRxAntInv) pDevice->byRxAntennaMode = ANT_A; else pDevice->byRxAntennaMode = ANT_B; @@ -635,7 +635,7 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) pDevice->byRFType &= RF_MASK; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType); - if (pDevice->bZoneRegExist == false) { + if (!pDevice->bZoneRegExist) { pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType); @@ -742,7 +742,7 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) if (!(pDevice->byGPIO & GPIO0_DATA)) { pDevice->bHWRadioOff = false; } } - if ((pDevice->bRadioControlOff == true)) { + if (pDevice->bRadioControlOff) { CARDbRadioPowerOff(pDevice); } else CARDbRadioPowerOn(pDevice); #else @@ -751,7 +751,7 @@ static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) pDevice->bHWRadioOff = true; } } - if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) { + if (pDevice->bHWRadioOff || pDevice->bRadioControlOff) { CARDbRadioPowerOff(pDevice); } @@ -809,7 +809,7 @@ static bool device_release_WPADEV(PSDevice pDevice) int ii = 0; // wait_queue_head_t Set_wait; //send device close to wpa_supplicnat layer - if (pDevice->bWPADEVUp == true) { + if (pDevice->bWPADEVUp) { wpahdr = (viawget_wpa_header *)pDevice->skb->data; wpahdr->type = VIAWGET_DEVICECLOSE_MSG; wpahdr->resp_ie_len = 0; @@ -826,7 +826,7 @@ static bool device_release_WPADEV(PSDevice pDevice) //wait release WPADEV // init_waitqueue_head(&Set_wait); // wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ); //1s wait - while ((pDevice->bWPADEVUp == true)) { + while (pDevice->bWPADEVUp) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 20); //wait 50ms ii++; @@ -892,7 +892,7 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) #ifdef DEBUG printk("Before get pci_info memaddr is %x\n", pDevice->memaddr); #endif - if (device_get_pci_info(pDevice, pcid) == false) { + if (!device_get_pci_info(pDevice, pcid)) { printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n"); device_free_info(pDevice); return -ENODEV; @@ -1633,7 +1633,7 @@ static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) { bFull = true; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]); } - if (netif_queue_stopped(pDevice->dev) && (bFull == false)) { + if (netif_queue_stopped(pDevice->dev) && !bFull) { netif_wake_queue(pDevice->dev); } } @@ -1798,7 +1798,7 @@ static int device_open(struct net_device *dev) { pDevice->byReAssocCount = 0; pDevice->bWPADEVUp = false; // Patch: if WEP key already set by iwconfig but device not yet open - if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) { + if (pDevice->bEncryptionEnable && pDevice->bTransmitKey) { KeybSetDefaultKey(&(pDevice->sKey), (unsigned long)(pDevice->byKeyIndex | (1 << 31)), pDevice->uKeyLength, @@ -1895,7 +1895,7 @@ static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) { return 0; } - if (pDevice->bStopTx0Pkt == true) { + if (pDevice->bStopTx0Pkt) { dev_kfree_skb_irq(skb); spin_unlock_irq(&pDevice->lock); return 0; @@ -1924,7 +1924,7 @@ bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeI SKeyItem STempKey; // unsigned char byKeyIndex = 0; - if (pDevice->bStopTx0Pkt == true) { + if (pDevice->bStopTx0Pkt) { dev_kfree_skb_irq(skb); return false; } @@ -1993,14 +1993,14 @@ bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeI } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { byPktType = PK_TYPE_11A; } else { - if (pDevice->bProtectMode == true) { + if (pDevice->bProtectMode) { byPktType = PK_TYPE_11GB; } else { byPktType = PK_TYPE_11GA; } } - if (pDevice->bEncryptionEnable == true) + if (pDevice->bEncryptionEnable) bNeedEncryption = true; if (pDevice->bEnableHostWEP) { @@ -2076,7 +2076,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { bool bNodeExist = false; spin_lock_irq(&pDevice->lock); - if (pDevice->bLinkPass == false) { + if (!pDevice->bLinkPass) { dev_kfree_skb_irq(skb); spin_unlock_irq(&pDevice->lock); return 0; @@ -2130,7 +2130,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { } } - if (bNodeExist == false) { + if (!bNodeExist) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Unknown STA not found in node DB \n"); dev_kfree_skb_irq(skb); spin_unlock_irq(&pDevice->lock); @@ -2149,7 +2149,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { cbFrameBodySize += 8; } - if (pDevice->bEncryptionEnable == true) { + if (pDevice->bEncryptionEnable) { bNeedEncryption = true; // get Transmit key do { @@ -2196,7 +2196,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { if (pDevice->bEnableHostWEP) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "acdma0: STA index %d\n", uNodeIndex); - if (pDevice->bEncryptionEnable == true) { + if (pDevice->bEncryptionEnable) { pTransmitKey = &STempKey; pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; @@ -2286,7 +2286,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { byPktType = PK_TYPE_11A; } else { - if (pDevice->bProtectMode == true) { + if (pDevice->bProtectMode) { byPktType = PK_TYPE_11GB; } else { byPktType = PK_TYPE_11GA; @@ -2297,7 +2297,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { // printk("FIX RATE:CurrentRate is %d"); //#endif - if (bNeedEncryption == true) { + if (bNeedEncryption) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) { bNeedEncryption = false; @@ -2306,7 +2306,7 @@ static int device_xmit(struct sk_buff *skb, struct net_device *dev) { if (pTransmitKey == NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Don't Find TX KEY\n"); } else { - if (bTKIP_UseGTK == true) { + if (bTKIP_UseGTK) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "error: KEY is GTK!!~~\n"); } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); @@ -2493,7 +2493,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { MACvSelectPage0(pDevice->PortOffset); //xxxx // WCMDbFlushCommandQueue(pDevice->pMgmt, true); - if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == true) { + if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel)) { pDevice->bMeasureInProgress = true; MACvSelectPage1(pDevice->PortOffset); MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY); @@ -2544,12 +2544,12 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { if (pDevice->dwIsr & ISR_QUIETSTART) { do { ; - } while (CARDbStartQuiet(pDevice) == false); + } while (!CARDbStartQuiet(pDevice)); } } if (pDevice->dwIsr & ISR_TBTT) { - if (pDevice->bEnableFirstQuiet == true) { + if (pDevice->bEnableFirstQuiet) { pDevice->byQuietStartCount--; if (pDevice->byQuietStartCount == 0) { pDevice->bEnableFirstQuiet = false; @@ -2558,7 +2558,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { MACvSelectPage0(pDevice->PortOffset); } } - if ((pDevice->bChannelSwitch == true) && + if (pDevice->bChannelSwitch && (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) { pDevice->byChannelSwitchCount--; if (pDevice->byChannelSwitchCount == 0) { @@ -2575,7 +2575,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { if (pDevice->eOPMode == OP_MODE_ADHOC) { //pDevice->bBeaconSent = false; } else { - if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == true) && (pDevice->uCurrRSSI != 0)) { + if ((pDevice->bUpdateBBVGA) && pDevice->bLinkPass && (pDevice->uCurrRSSI != 0)) { long ldBm; RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm); @@ -2642,7 +2642,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { } pDevice->bBeaconSent = true; - if (pDevice->bChannelSwitch == true) { + if (pDevice->bChannelSwitch) { pDevice->byChannelSwitchCount--; if (pDevice->byChannelSwitchCount == 0) { pDevice->bChannelSwitch = false; @@ -3237,7 +3237,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { netif_stop_queue(pDevice->dev); #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT pMgmt->eScanType = WMAC_SCAN_ACTIVE; - if (pDevice->bWPASuppWextEnabled != true) + if (!pDevice->bWPASuppWextEnabled) #endif bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); @@ -3373,7 +3373,7 @@ viawget_resume(struct pci_dev *pcid) spin_lock_irq(&pDevice->lock); MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext); device_init_registers(pDevice, DEVICE_INIT_DXPL); - if (pMgmt->sNodeDBTable[0].bActive == true) { // Assoc with BSS + if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS pMgmt->sNodeDBTable[0].bActive = false; pDevice->bLinkPass = false; if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 0ff51cb4a207..c60f3e6dc6f8 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -379,7 +379,7 @@ device_receive_frame( pMACHeader = (PS802_11Header)((unsigned char *)(skb->data) + 8); //PLICE_DEBUG<- - if (pDevice->bMeasureInProgress == true) { + if (pDevice->bMeasureInProgress) { if ((*pbyRsr & RSR_CRCOK) != 0) { pDevice->byBasicMap |= 0x01; } @@ -436,7 +436,7 @@ device_receive_frame( } if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { - if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == true) { + if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex)) { return false; } } @@ -608,8 +608,7 @@ device_receive_frame( } } else { // discard DATA packet while not associate || BSSID error - if ((pDevice->bLinkPass == false) || - !(*pbyRsr & RSR_BSSIDOK)) { + if (!pDevice->bLinkPass || !(*pbyRsr & RSR_BSSIDOK)) { if (bDeFragRx) { if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n", @@ -658,7 +657,7 @@ device_receive_frame( // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps if (pDevice->bDiversityEnable && (FrameSize > 50) && (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && - (pDevice->bLinkPass == true)) { + pDevice->bLinkPass) { BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0); } @@ -683,7 +682,7 @@ device_receive_frame( // ----------------------------------------------- - if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == true)) { + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && pDevice->bEnable8021x) { unsigned char abyMacHdr[24]; // Only 802.1x packet incoming allowed @@ -698,7 +697,7 @@ device_receive_frame( if (wEtherType == ETH_P_PAE) { skb->dev = pDevice->apdev; - if (bIsWEP == true) { + if (bIsWEP) { // strip IV header(8) memcpy(&abyMacHdr[0], (skb->data + 4), 24); memcpy((skb->data + 4 + cbIVOffset), &abyMacHdr[0], 24); @@ -770,8 +769,9 @@ device_receive_frame( //DBG_PRN_GRP12(("LocalL: %lx, LocalR: %lx\n", dwLocalMIC_L, dwLocalMIC_R)); //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwMICKey0= %lx,dwMICKey1= %lx \n", dwMICKey0, dwMICKey1); - if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || - (pDevice->bRxMICFail == true)) { + if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || + (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || + pDevice->bRxMICFail) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MIC comparison is fail!\n"); pDevice->bRxMICFail = false; //pDevice->s802_11Counter.TKIPLocalMICFailures.QuadPart++; @@ -894,13 +894,13 @@ device_receive_frame( return false; if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { - if (s_bAPModeRxData(pDevice, + if (!s_bAPModeRxData(pDevice, skb, FrameSize, cbHeaderOffset, iSANodeIndex, iDANodeIndex -) == false) { +)) { if (bDeFragRx) { if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc more frag bufs\n", @@ -1123,7 +1123,7 @@ static bool s_bHandleRxEncryption( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pKey == NULL\n"); if (byDecMode == KEY_CTL_WEP) { // pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; - } else if (pDevice->bLinkPass == true) { + } else if (pDevice->bLinkPass) { // pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; } return false; @@ -1131,7 +1131,7 @@ static bool s_bHandleRxEncryption( if (byDecMode != pKey->byCipherSuite) { if (byDecMode == KEY_CTL_WEP) { // pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; - } else if (pDevice->bLinkPass == true) { + } else if (pDevice->bLinkPass) { // pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; } *pKeyOut = NULL; @@ -1234,7 +1234,7 @@ static bool s_bHostWepRxEncryption( if (byDecMode != pKey->byCipherSuite) { if (byDecMode == KEY_CTL_WEP) { // pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; - } else if (pDevice->bLinkPass == true) { + } else if (pDevice->bLinkPass) { // pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; } return false; @@ -1245,7 +1245,7 @@ static bool s_bHostWepRxEncryption( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "byDecMode == KEY_CTL_WEP \n"); if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true) || - (bOnFly == false)) { + !bOnFly) { // Software WEP // 1. 3253A // 2. WEP 256 @@ -1277,7 +1277,7 @@ static bool s_bHostWepRxEncryption( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "TSC0_15: %x\n", *pwRxTSC15_0); if (byDecMode == KEY_CTL_TKIP) { - if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (bOnFly == false)) { + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || !bOnFly) { // Software TKIP // 1. 3253 A // 2. NotOnFly @@ -1297,7 +1297,7 @@ static bool s_bHostWepRxEncryption( } if (byDecMode == KEY_CTL_CCMP) { - if (bOnFly == false) { + if (!bOnFly) { // Software CCMP // NotOnFly DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "soft KEY_CTL_CCMP\n"); diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c index aab0012bba92..3d30a435cabd 100644 --- a/drivers/staging/vt6655/hostap.c +++ b/drivers/staging/vt6655/hostap.c @@ -494,11 +494,11 @@ static int hostap_set_encryption(PSDevice pDevice, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg); if (param->u.crypt.alg == WPA_ALG_NONE) { - if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == true) { - if (KeybRemoveKey(&(pDevice->sKey), + if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly) { + if (!KeybRemoveKey(&(pDevice->sKey), param->sta_addr, pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex, - pDevice->PortOffset) == false) { + pDevice->PortOffset)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n"); } pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false; @@ -556,7 +556,7 @@ static int hostap_set_encryption(PSDevice pDevice, (unsigned char *)abyKey, KEY_CTL_WEP, pDevice->PortOffset, - pDevice->byLocalID) == true) { + pDevice->byLocalID)) { pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true; } else { @@ -623,7 +623,7 @@ static int hostap_set_encryption(PSDevice pDevice, (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, - pDevice->byLocalID) == true) { + pDevice->byLocalID)) { pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true; } else { @@ -635,7 +635,7 @@ static int hostap_set_encryption(PSDevice pDevice, } - if (bKeyTableFull == true) { + if (bKeyTableFull) { wKeyCtl &= 0x7F00; // clear all key control filed wKeyCtl |= (byKeyDecMode << 4); wKeyCtl |= (byKeyDecMode); diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index 04c1304d16e5..eab3b41f9e3c 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -64,13 +64,12 @@ s_vCheckKeyTableValid(PSKeyManagement pTable, unsigned long dwIoBase) int i; for (i = 0; i < MAX_KEY_TABLE; i++) { - if ((pTable->KeyTable[i].bInUse == true) && - (pTable->KeyTable[i].PairwiseKey.bKeyValid == false) && - (pTable->KeyTable[i].GroupKey[0].bKeyValid == false) && - (pTable->KeyTable[i].GroupKey[1].bKeyValid == false) && - (pTable->KeyTable[i].GroupKey[2].bKeyValid == false) && - (pTable->KeyTable[i].GroupKey[3].bKeyValid == false) -) { + if (pTable->KeyTable[i].bInUse && + !pTable->KeyTable[i].PairwiseKey.bKeyValid && + !pTable->KeyTable[i].GroupKey[0].bKeyValid && + !pTable->KeyTable[i].GroupKey[1].bKeyValid && + !pTable->KeyTable[i].GroupKey[2].bKeyValid && + !pTable->KeyTable[i].GroupKey[3].bKeyValid) { pTable->KeyTable[i].bInUse = false; pTable->KeyTable[i].wKeyCtl = 0; pTable->KeyTable[i].bSoftWEP = false; @@ -140,17 +139,17 @@ bool KeybGetKey( *pKey = NULL; for (i = 0; i < MAX_KEY_TABLE; i++) { - if ((pTable->KeyTable[i].bInUse == true) && + if (pTable->KeyTable[i].bInUse && ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { if (dwKeyIndex == 0xFFFFFFFF) { - if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) { + if (pTable->KeyTable[i].PairwiseKey.bKeyValid) { *pKey = &(pTable->KeyTable[i].PairwiseKey); return true; } else { return false; } } else if (dwKeyIndex < MAX_GROUP_KEY) { - if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == true) { + if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid) { *pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]); return true; } else { @@ -202,12 +201,11 @@ bool KeybSetKey( j = (MAX_KEY_TABLE-1); for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { - if ((pTable->KeyTable[i].bInUse == false) && - (j == (MAX_KEY_TABLE-1))) { + if (!pTable->KeyTable[i].bInUse && (j == (MAX_KEY_TABLE-1))) { // found empty table j = i; } - if ((pTable->KeyTable[i].bInUse == true) && + if (pTable->KeyTable[i].bInUse && ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { // found table already exist if ((dwKeyIndex & PAIRWISE_KEY) != 0) { @@ -384,7 +382,7 @@ bool KeybRemoveKey( } for (i = 0; i < MAX_KEY_TABLE; i++) { - if ((pTable->KeyTable[i].bInUse == true) && + if (pTable->KeyTable[i].bInUse && ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { if ((dwKeyIndex & PAIRWISE_KEY) != 0) { pTable->KeyTable[i].PairwiseKey.bKeyValid = false; @@ -428,7 +426,7 @@ bool KeybRemoveAllKey( int i, u; for (i = 0; i < MAX_KEY_TABLE; i++) { - if ((pTable->KeyTable[i].bInUse == true) && + if (pTable->KeyTable[i].bInUse && ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { pTable->KeyTable[i].PairwiseKey.bKeyValid = false; for (u = 0; u < MAX_GROUP_KEY; u++) { @@ -461,7 +459,7 @@ void KeyvRemoveWEPKey( ) { if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { - if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse == true) { + if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse) { if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) { pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false; if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) { @@ -511,10 +509,10 @@ bool KeybGetTransmitKey( *pKey = NULL; for (i = 0; i < MAX_KEY_TABLE; i++) { - if ((pTable->KeyTable[i].bInUse == true) && + if (pTable->KeyTable[i].bInUse && ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { if (dwKeyType == PAIRWISE_KEY) { - if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) { + if (pTable->KeyTable[i].PairwiseKey.bKeyValid) { *pKey = &(pTable->KeyTable[i].PairwiseKey); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:"); @@ -535,7 +533,7 @@ bool KeybGetTransmitKey( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ERROR: dwGTKeyIndex == 0 !!!\n"); return false; } - if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == true) { + if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid) { *pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybGetTransmitKey:"); @@ -583,8 +581,8 @@ bool KeybCheckPairewiseKey( *pKey = NULL; for (i = 0; i < MAX_KEY_TABLE; i++) { - if ((pTable->KeyTable[i].bInUse == true) && - (pTable->KeyTable[i].PairwiseKey.bKeyValid == true)) { + if (pTable->KeyTable[i].bInUse && + pTable->KeyTable[i].PairwiseKey.bKeyValid) { *pKey = &(pTable->KeyTable[i].PairwiseKey); return true; } @@ -657,7 +655,7 @@ bool KeybSetDefaultKey( pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000; // disable on-fly disable address match pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true; } else { - if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == false) + if (!pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP) pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000; // enable on-fly disable address match } @@ -740,7 +738,7 @@ bool KeybSetAllGroupKey( } for (i = 0; i < MAX_KEY_TABLE - 1; i++) { - if (pTable->KeyTable[i].bInUse == true) { + if (pTable->KeyTable[i].bInUse) { // found table already exist // Group key pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 001d15c0fa40..21bd8a1126d7 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -957,13 +957,13 @@ bool MACbSafeStop(unsigned long dwIoBase) { MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX); - if (MACbSafeRxOff(dwIoBase) == false) { + if (!MACbSafeRxOff(dwIoBase)) { DBG_PORT80(0xA1); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " MACbSafeRxOff == false)\n"); MACbSafeSoftwareReset(dwIoBase); return false; } - if (MACbSafeTxOff(dwIoBase) == false) { + if (!MACbSafeTxOff(dwIoBase)) { DBG_PORT80(0xA2); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " MACbSafeTxOff == false)\n"); MACbSafeSoftwareReset(dwIoBase); diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 2340d2f0399b..3da2838006e3 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -284,16 +284,15 @@ PSbSendNullPacket( PSMgmtObject pMgmt = pDevice->pMgmt; unsigned int uIdx; - if (pDevice->bLinkPass == false) { + if (!pDevice->bLinkPass) { return false; } #ifdef TxInSleep - if ((pDevice->bEnablePSMode == false) && - (pDevice->fTxDataInSleep == false)) { + if (!pDevice->bEnablePSMode && !pDevice->fTxDataInSleep) { return false; } #else - if (pDevice->bEnablePSMode == false) { + if (!pDevice->bEnablePSMode) { return false; } #endif diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index ce173cc16c19..edb1b2768b17 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -976,7 +976,7 @@ bool RFbSetPower( } bResult = RFbRawSetPower(pDevice, byPwr, uRATE); - if (bResult == true) { + if (bResult) { pDevice->byCurPwr = byPwr; } return bResult; diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c index d2bdb71fe62d..e78aedf99077 100644 --- a/drivers/staging/vt6655/vntwifi.c +++ b/drivers/staging/vt6655/vntwifi.c @@ -494,7 +494,7 @@ VNTWIFIvUpdateNodeTxCounter( } } pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts++; - if (bTxOk == true) { + if (bTxOk) { // transmit success, TxAttempts at least plus one pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++; pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wRate]++; @@ -584,7 +584,7 @@ VNTWIFIbyGetKeyCypher( { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; - if (bGroupKey == true) { + if (bGroupKey) { return pMgmt->byCSSGK; } else { return pMgmt->byCSSPK; @@ -731,7 +731,7 @@ VNTWIFIbMeasureReport( pMgmt->uLengthOfRepEIDs += (2 + pMgmt->pCurrMeasureEIDRep->len); pMgmt->pCurrMeasureEIDRep = (PWLAN_IE_MEASURE_REP) pbyCurrentEID; } - if (bEndOfReport == true) { + if (bEndOfReport) { IEEE11hbMSRRepTx(pMgmt); } //spin_unlock_irq(&pDevice->lock); diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c index 9c57eefe78fb..72caaa203ddc 100644 --- a/drivers/staging/vt6655/wcmd.c +++ b/drivers/staging/vt6655/wcmd.c @@ -317,7 +317,7 @@ vCommandTimer( if (pDevice->dwDiagRefCount != 0) return; - if (pDevice->bCmdRunning != true) + if (!pDevice->bCmdRunning) return; spin_lock_irq(&pDevice->lock); @@ -326,7 +326,7 @@ vCommandTimer( case WLAN_CMD_SCAN_START: pDevice->byReAssocCount = 0; - if (pDevice->bRadioOff == true) { + if (pDevice->bRadioOff) { s_bCommandComplete(pDevice); spin_unlock_irq(&pDevice->lock); return; @@ -393,7 +393,7 @@ vCommandTimer( vAdHocBeaconStop(pDevice); - if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel) == true) { + if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SCAN Channel: %d\n", pMgmt->uScanChannel); } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SET SCAN Channel Fail: %d\n", pMgmt->uScanChannel); @@ -408,7 +408,7 @@ vCommandTimer( } - if ((pMgmt->b11hEnable == false) || + if (!pMgmt->b11hEnable || (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) { s_vProbeChannel(pDevice); spin_unlock_irq(&pDevice->lock); @@ -498,7 +498,7 @@ vCommandTimer( case WLAN_CMD_SSID_START: pDevice->byReAssocCount = 0; - if (pDevice->bRadioOff == true) { + if (pDevice->bRadioOff) { s_bCommandComplete(pDevice); spin_unlock_irq(&pDevice->lock); return; @@ -659,7 +659,7 @@ vCommandTimer( netif_wake_queue(pDevice->dev); } #ifdef TxInSleep - if (pDevice->IsTxDataTrigger != false) { //TxDataTimer is not triggered at the first time + if (pDevice->IsTxDataTrigger) { //TxDataTimer is not triggered at the first time del_timer(&pDevice->sTimerTxData); init_timer(&pDevice->sTimerTxData); pDevice->sTimerTxData.data = (unsigned long) pDevice; @@ -694,7 +694,7 @@ vCommandTimer( pMgmt->eCurrState = WMAC_STATE_IDLE; pMgmt->eCurrMode = WMAC_MODE_STANDBY; pDevice->bLinkPass = false; - if (pDevice->bEnableHostWEP == true) + if (pDevice->bEnableHostWEP) BSSvClearNodeDBTable(pDevice, 1); else BSSvClearNodeDBTable(pDevice, 0); @@ -776,7 +776,7 @@ vCommandTimer( case WLAN_CMD_RADIO_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "eCommandState == WLAN_CMD_RADIO_START\n"); - if (pDevice->bRadioCmd == true) + if (pDevice->bRadioCmd) CARDbRadioPowerOn(pDevice); else CARDbRadioPowerOff(pDevice); @@ -948,7 +948,7 @@ bool bScheduleCommand( ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); pDevice->cbFreeCmdQueue--; - if (pDevice->bCmdRunning == false) { + if (!pDevice->bCmdRunning) { s_bCommandComplete(pDevice); } else { } @@ -1031,8 +1031,8 @@ BSSvSecondTxData( spin_lock_irq(&pDevice->lock); #if 1 - if (((pDevice->bLinkPass == true) && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking - (pDevice->fWPA_Authened == true)) { //wpa linking + if ((pDevice->bLinkPass && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking + pDevice->fWPA_Authened) { //wpa linking #else if (pDevice->bLinkPass == true) { #endif diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c index f05f9f55398b..950039f6d128 100644 --- a/drivers/staging/vt6655/wctl.c +++ b/drivers/staging/vt6655/wctl.c @@ -110,7 +110,7 @@ unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader) unsigned int ii; for (ii = 0; ii < pDevice->cbDFCB; ii++) { - if ((pDevice->sRxDFCB[ii].bInUse == true) && + if (pDevice->sRxDFCB[ii].bInUse && ether_addr_equal(pDevice->sRxDFCB[ii].abyAddr2, pMACHeader->abyAddr2)) { // @@ -141,7 +141,7 @@ unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader) if (pDevice->cbFreeDFCB == 0) return pDevice->cbDFCB; for (ii = 0; ii < pDevice->cbDFCB; ii++) { - if (pDevice->sRxDFCB[ii].bInUse == false) { + if (!pDevice->sRxDFCB[ii].bInUse) { pDevice->cbFreeDFCB--; pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime; pDevice->sRxDFCB[ii].bInUse = true; @@ -174,7 +174,7 @@ bool WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, unsigned i { unsigned int uHeaderSize; - if (bWEP == true) { + if (bWEP) { uHeaderSize = 28; if (bExtIV) // ExtIV diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index ed4b32b6d9ce..40bb9004a921 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -468,15 +468,15 @@ vMgrAssocBeginSta( // ERP Phy (802.11g) should support short preamble. if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); - if (CARDbIsShorSlotTime(pMgmt->pAdapter) == true) { + if (CARDbIsShorSlotTime(pMgmt->pAdapter)) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); } } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) { - if (CARDbIsShortPreamble(pMgmt->pAdapter) == true) { + if (CARDbIsShortPreamble(pMgmt->pAdapter)) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); } } - if (pMgmt->b11hEnable == true) + if (pMgmt->b11hEnable) pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); /* build an assocreq frame and send it */ @@ -539,15 +539,15 @@ vMgrReAssocBeginSta( // ERP Phy (802.11g) should support short preamble. if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); - if (CARDbIsShorSlotTime(pMgmt->pAdapter) == true) { + if (CARDbIsShorSlotTime(pMgmt->pAdapter)) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); } } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) { - if (CARDbIsShortPreamble(pMgmt->pAdapter) == true) { + if (CARDbIsShortPreamble(pMgmt->pAdapter)) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); } } - if (pMgmt->b11hEnable == true) + if (pMgmt->b11hEnable) pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); pTxPacket = s_MgrMakeReAssocRequest @@ -736,7 +736,7 @@ s_vMgrRxAssocRequest( pDevice->bProtectMode = true; pDevice->bNonERPPresent = true; } - if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) { + if (!pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { pDevice->bBarkerPreambleMd = true; } @@ -891,7 +891,7 @@ s_vMgrRxReAssocRequest( pDevice->bProtectMode = true; pDevice->bNonERPPresent = true; } - if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) { + if (!pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { pDevice->bBarkerPreambleMd = true; } @@ -1837,7 +1837,7 @@ s_vMgrRxBeacon( bChannelHit = true; } //2008-0730-01by MikeLiu - if (ChannelExceedZoneType(pDevice, byCurrChannel) == true) + if (ChannelExceedZoneType(pDevice, byCurrChannel)) return; if (sFrame.pERP != NULL) { @@ -1957,9 +1957,9 @@ s_vMgrRxBeacon( } } - if ((WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo) == true) && - (bIsBSSIDEqual == true) && - (bIsSSIDEqual == true) && + if (WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo) && + bIsBSSIDEqual && + bIsSSIDEqual && (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { // add state check to prevent reconnect fail since we'll receive Beacon @@ -2001,7 +2001,7 @@ s_vMgrRxBeacon( &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) ); - if (bUpdatePhyParameter == true) { + if (bUpdatePhyParameter) { CARDbSetPhyParameter(pMgmt->pAdapter, pMgmt->eCurrentPHYMode, pMgmt->wCurrCapInfo, @@ -2023,7 +2023,7 @@ s_vMgrRxBeacon( sFrame.pIE_CHSW->byCount ); - } else if (bIsChannelEqual == false) { + } else if (!bIsChannelEqual) { set_channel(pMgmt->pAdapter, pBSSList->uChannel); } } @@ -2067,12 +2067,12 @@ s_vMgrRxBeacon( } // if infra mode - if (bIsAPBeacon == true) { + if (bIsAPBeacon) { // Infra mode: Local TSF always follow AP's TSF if Difference huge. if (bTSFLargeDiff) bUpdateTSF = true; - if ((pDevice->bEnablePSMode == true) && (sFrame.pTIM != 0)) { + if (pDevice->bEnablePSMode && (sFrame.pTIM != 0)) { // deal with DTIM, analysis TIM pMgmt->bMulticastTIM = WLAN_MGMT_IS_MULTICAST_TIM(sFrame.pTIM->byBitMapCtl) ? true : false; pMgmt->byDTIMCount = sFrame.pTIM->byDTIMCount; @@ -2110,7 +2110,7 @@ s_vMgrRxBeacon( } else { pMgmt->bInTIMWake = false; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Not In TIM..\n"); - if (pDevice->bPWBitOn == false) { + if (!pDevice->bPWBitOn) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Send Null Packet\n"); if (PSbSendNullPacket(pDevice)) pDevice->bPWBitOn = true; @@ -2480,7 +2480,7 @@ vMgrCreateOwnIBSS( pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SHORTPREAMBLE(1)); } - if ((pMgmt->b11hEnable == true) && + if (pMgmt->b11hEnable && (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); } else { @@ -2530,7 +2530,7 @@ vMgrJoinBSSBegin( unsigned char byTopOFDMBasicRate = RATE_1M; for (ii = 0; ii < MAX_BSS_NUM; ii++) { - if (pMgmt->sBSSList[ii].bActive == true) + if (pMgmt->sBSSList[ii].bActive) break; } @@ -2656,7 +2656,7 @@ vMgrJoinBSSBegin( if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { bool bResult = bAdd_PMKID_Candidate((void *)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bAdd_PMKID_Candidate: 1(%d)\n", bResult); - if (bResult == false) { + if (!bResult) { vFlush_PMKID_Candidate((void *)pDevice); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vFlush_PMKID_Candidate: 4\n"); bAdd_PMKID_Candidate((void *)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj); @@ -2677,13 +2677,13 @@ vMgrJoinBSSBegin( // ad-hoc mode BSS if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { - if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) { + if (!WPA_SearchRSN(0, WPA_TKIP, pCurr)) { // encryption mode error pMgmt->eCurrState = WMAC_STATE_IDLE; return; } } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { - if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) { + if (!WPA_SearchRSN(0, WPA_AESCCMP, pCurr)) { // encryption mode error pMgmt->eCurrState = WMAC_STATE_IDLE; return; @@ -2776,10 +2776,10 @@ s_vMgrSynchBSS( *pStatus = CMD_STATUS_FAILURE; - if (s_bCipherMatch(pCurr, + if (!s_bCipherMatch(pCurr, pDevice->eEncryptionStatus, &(pMgmt->byCSSPK), - &(pMgmt->byCSSGK)) == false) { + &(pMgmt->byCSSGK))) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_bCipherMatch Fail .......\n"); return; } @@ -2869,18 +2869,17 @@ s_vMgrSynchBSS( CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_ADHOC); } - if (CARDbSetPhyParameter(pMgmt->pAdapter, + if (!CARDbSetPhyParameter(pMgmt->pAdapter, ePhyType, pCurr->wCapInfo, pCurr->sERP.byERP, pMgmt->abyCurrSuppRates, - pMgmt->abyCurrExtSuppRates - ) != true) { + pMgmt->abyCurrExtSuppRates)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Phy Mode Fail [%d]\n", ePhyType); return; } // set channel and clear NAV - if (set_channel(pMgmt->pAdapter, pCurr->uChannel) == false) { + if (!set_channel(pMgmt->pAdapter, pCurr->uChannel)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Channel [%d]\n", pCurr->uChannel); return; } @@ -2924,7 +2923,7 @@ static void Encyption_Rebuild( if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || //networkmanager 0.7.0 does not give the pairwise-key selection, (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { // so we need re-select it according to real pairwise-key info. - if (pCurr->bWPAValid == true) { //WPA-PSK + if (pCurr->bWPAValid) { //WPA-PSK pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; if (pCurr->abyPKType[0] == WPA_TKIP) { pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; //TKIP @@ -2933,7 +2932,7 @@ static void Encyption_Rebuild( pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; //AES PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-AES]\n"); } - } else if (pCurr->bWPA2Valid == true) { //WPA2-PSK + } else if (pCurr->bWPA2Valid) { //WPA2-PSK pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; if (pCurr->abyCSSPK[0] == WLAN_11i_CSS_TKIP) { pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; //TKIP @@ -3150,8 +3149,7 @@ s_MgrMakeBeacon( } } - if ((pMgmt->b11hEnable == true) && - (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { + if (pMgmt->b11hEnable && (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { // Country IE pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len); set_country_IE(pMgmt->pAdapter, pbyBuffer); @@ -3164,7 +3162,7 @@ s_MgrMakeBeacon( ((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0; pbyBuffer += (1) + WLAN_IEHDR_LEN; uLength += (1) + WLAN_IEHDR_LEN; - if (pMgmt->bSwitchChannel == true) { + if (pMgmt->bSwitchChannel) { // Channel Switch IE ((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH; ((PWLAN_IE_CH_SW) pbyBuffer)->len = 3; @@ -3193,7 +3191,7 @@ s_MgrMakeBeacon( pbyBuffer += (7) + WLAN_IEHDR_LEN; uLength += (7) + WLAN_IEHDR_LEN; for (ii = CB_MAX_CHANNEL_24G+1; ii <= CB_MAX_CHANNEL; ii++) { - if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == true) { + if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1)) { pbyBuffer += 2; uLength += 2; pIBSSDFS->len += 2; @@ -3209,11 +3207,11 @@ s_MgrMakeBeacon( sFrame.pERP->byElementID = WLAN_EID_ERP; sFrame.pERP->len = 1; sFrame.pERP->byContext = 0; - if (pDevice->bProtectMode == true) + if (pDevice->bProtectMode) sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION; - if (pDevice->bNonERPPresent == true) + if (pDevice->bNonERPPresent) sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT; - if (pDevice->bBarkerPreambleMd == true) + if (pDevice->bBarkerPreambleMd) sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE; } if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { @@ -3225,7 +3223,7 @@ s_MgrMakeBeacon( ); } // hostapd wpa/wpa2 IE - if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) { + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && pDevice->bEnableHostapd) { if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { if (pMgmt->wWPAIELen != 0) { sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); @@ -3338,16 +3336,15 @@ s_MgrMakeProbeResponse( sFrame.pERP->byElementID = WLAN_EID_ERP; sFrame.pERP->len = 1; sFrame.pERP->byContext = 0; - if (pDevice->bProtectMode == true) + if (pDevice->bProtectMode) sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION; - if (pDevice->bNonERPPresent == true) + if (pDevice->bNonERPPresent) sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT; - if (pDevice->bBarkerPreambleMd == true) + if (pDevice->bBarkerPreambleMd) sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE; } - if ((pMgmt->b11hEnable == true) && - (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { + if (pMgmt->b11hEnable && (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { // Country IE pbyBuffer = (unsigned char *)(sFrame.pBuf + sFrame.len); set_country_IE(pMgmt->pAdapter, pbyBuffer); @@ -3360,7 +3357,7 @@ s_MgrMakeProbeResponse( ((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0; pbyBuffer += (1) + WLAN_IEHDR_LEN; uLength += (1) + WLAN_IEHDR_LEN; - if (pMgmt->bSwitchChannel == true) { + if (pMgmt->bSwitchChannel) { // Channel Switch IE ((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH; ((PWLAN_IE_CH_SW) pbyBuffer)->len = 3; @@ -3389,7 +3386,7 @@ s_MgrMakeProbeResponse( pbyBuffer += (7) + WLAN_IEHDR_LEN; uLength += (7) + WLAN_IEHDR_LEN; for (ii = CB_MAX_CHANNEL_24G + 1; ii <= CB_MAX_CHANNEL; ii++) { - if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == true) { + if (get_channel_map_info(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1)) { pbyBuffer += 2; uLength += 2; pIBSSDFS->len += 2; @@ -3409,7 +3406,7 @@ s_MgrMakeProbeResponse( } // hostapd wpa/wpa2 IE - if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) { + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && pDevice->bEnableHostapd) { if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { if (pMgmt->wWPAIELen != 0) { sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); @@ -3507,7 +3504,7 @@ s_MgrMakeAssocRequest( pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN; // for 802.11h - if (pMgmt->b11hEnable == true) { + if (pMgmt->b11hEnable) { if (sFrame.pCurrPowerCap == NULL) { sFrame.pCurrPowerCap = (PWLAN_IE_PW_CAP)(sFrame.pBuf + sFrame.len); sFrame.len += (2 + WLAN_IEHDR_LEN); @@ -3650,7 +3647,7 @@ s_MgrMakeAssocRequest( sFrame.pRSN->len += 6; // RSN Capabilities - if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist) { memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); } else { sFrame.pRSN->abyRSN[16] = 0; @@ -3658,7 +3655,7 @@ s_MgrMakeAssocRequest( } sFrame.pRSN->len += 2; - if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && pDevice->bRoaming && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { // RSN PMKID pbyRSN = &sFrame.pRSN->abyRSN[18]; pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count @@ -3896,7 +3893,7 @@ s_MgrMakeReAssocRequest( sFrame.pRSN->len += 6; // RSN Capabilities - if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist) { memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); } else { sFrame.pRSN->abyRSN[16] = 0; @@ -3904,7 +3901,7 @@ s_MgrMakeReAssocRequest( } sFrame.pRSN->len += 2; - if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && pDevice->bRoaming && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { // RSN PMKID pbyRSN = &sFrame.pRSN->abyRSN[18]; pwPMKID = (unsigned short *)pbyRSN; // Point to PMKID count @@ -4141,7 +4138,7 @@ s_vMgrRxProbeResponse( } //2008-0730-01by MikeLiu - if (ChannelExceedZoneType(pDevice, byCurrChannel) == true) + if (ChannelExceedZoneType(pDevice, byCurrChannel)) return; if (sFrame.pERP != NULL) { @@ -4578,7 +4575,7 @@ bAdd_PMKID_Candidate( for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) { pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii]; if (!memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) { - if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) { + if (psRSNCapObj->bRSNCapExist && (psRSNCapObj->wRSNCap & BIT0)) { pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; } else { pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); @@ -4589,7 +4586,7 @@ bAdd_PMKID_Candidate( // New Candidate pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates]; - if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) { + if (psRSNCapObj->bRSNCapExist && (psRSNCapObj->wRSNCap & BIT0)) { pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; } else { pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); @@ -4650,7 +4647,7 @@ s_bCipherMatch( } if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && - (pBSSNode->bWPA2Valid == true) && + pBSSNode->bWPA2Valid && //20080123-01, by Einsn Liu ((EncStatus == Ndis802_11Encryption3Enabled) || (EncStatus == Ndis802_11Encryption2Enabled))) { //WPA2 @@ -4684,7 +4681,7 @@ s_bCipherMatch( } } else if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && - (pBSSNode->bWPAValid == true) && + pBSSNode->bWPAValid && ((EncStatus == Ndis802_11Encryption3Enabled) || (EncStatus == Ndis802_11Encryption2Enabled))) { //WPA // check Group Key Cipher diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c index b697fa6c3b16..990ea0f9e9fb 100644 --- a/drivers/staging/vt6655/wpa.c +++ b/drivers/staging/vt6655/wpa.c @@ -241,7 +241,7 @@ WPA_SearchRSN( int ii; unsigned char byPKType = WPA_NONE; - if (pBSSList->bWPAValid == false) + if (!pBSSList->bWPAValid) return false; switch (byCmd) { diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c index a7e33c0ceb74..2013122e92b2 100644 --- a/drivers/staging/vt6655/wpa2.c +++ b/drivers/staging/vt6655/wpa2.c @@ -192,7 +192,7 @@ WPA2vParseRSN( break; } //for - if (bUseGK == true) { + if (bUseGK) { if (j != 1) { // invalid CSS, This should be only PK CSS. return; @@ -335,7 +335,7 @@ WPA2uSetIEs( pRSNIEs->len += 2; if ((pMgmt->gsPMKIDCache.BSSIDInfoCount > 0) && - (pMgmt->bRoaming == true) && + pMgmt->bRoaming && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { // RSN PMKID pwPMKID = (unsigned short *)(&pRSNIEs->abyRSN[18]); // Point to PMKID count diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 044368a46c53..ee83704e4401 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -341,22 +341,22 @@ int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel) // If is_broadcast_ether_addr, set the key as every key entry's group key. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); - if ((KeybSetAllGroupKey(&(pDevice->sKey), + if (KeybSetAllGroupKey(&(pDevice->sKey), dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, - pDevice->byLocalID) == true) && - (KeybSetDefaultKey(&(pDevice->sKey), + pDevice->byLocalID) && + KeybSetDefaultKey(&(pDevice->sKey), dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, - pDevice->byLocalID) == true)) { + pDevice->byLocalID)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); } else { @@ -389,7 +389,7 @@ int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel) (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, - pDevice->byLocalID) == true) { + pDevice->byLocalID)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); } else { @@ -804,7 +804,7 @@ static int wpa_set_associate(PSDevice pDevice, else pDevice->bEncryptionEnable = false; if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || - ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled == true)))) //DavidWang //20080717-06, by chester//Not to initial WEP + ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && bWepEnabled))) //DavidWang //20080717-06, by chester//Not to initial WEP KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); spin_lock_irq(&pDevice->lock); pDevice->bLinkPass = false; -- cgit v1.2.3 From 0fd682f644d5773c0107838f5316db3361332a19 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sun, 10 Nov 2013 17:12:43 +0200 Subject: staging: vt6655: fix assignment of bool to 0 This patch fixes the following warnings detected using coccinelle for drivers/staging/wmgr.c file: drivers/staging/vt6655/wmgr.c:2335:1-22: WARNING: Assignment of bool to 0/1 drivers/staging/vt6655/wmgr.c:2338:1-27: WARNING: Assignment of bool to 0/1 Signed-off-by: Teodora Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/wmgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index 40bb9004a921..a1eff7e514a9 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -2332,10 +2332,10 @@ vMgrCreateOwnIBSS( } // Disable Protect Mode - pDevice->bProtectMode = 0; + pDevice->bProtectMode = false; MACvDisableProtectMD(pDevice->PortOffset); - pDevice->bBarkerPreambleMd = 0; + pDevice->bBarkerPreambleMd = false; MACvDisableBarkerPreambleMd(pDevice->PortOffset); // Kyle Test 2003.11.04 -- cgit v1.2.3 From 649520bbc51a06955b8563906b17e957e972926d Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sun, 10 Nov 2013 17:12:44 +0200 Subject: staging: vt6655: fix comparison of bool to 0/1 This patch corrects comparison of bool to 0/1 for file drivers/staging/vt6655/rxtx.c. The following type of coccinelle detected warnings are silenced: WARNING: Comparison of bool to 0/1 Signed-off-by: Teodora Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rxtx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 3a2661e2b27c..182c53ee66da 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -435,7 +435,7 @@ s_uGetDataDuration( switch (byDurType) { case DATADUR_B: //DATADUR_B - if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag + if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag if (bNeedAck) { uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); return pDevice->uSIFS + uAckTime; @@ -458,7 +458,7 @@ s_uGetDataDuration( break; case DATADUR_A: //DATADUR_A - if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag + if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag if (bNeedAck) { uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return pDevice->uSIFS + uAckTime; @@ -481,7 +481,7 @@ s_uGetDataDuration( break; case DATADUR_A_F0: //DATADUR_A_F0 - if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag + if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag if (bNeedAck) { uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return pDevice->uSIFS + uAckTime; @@ -523,7 +523,7 @@ s_uGetDataDuration( break; case DATADUR_A_F1: //DATADUR_A_F1 - if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag + if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag if (bNeedAck) { uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return pDevice->uSIFS + uAckTime; -- cgit v1.2.3 From 88cc85075d1e53731e90fec8670cd9ccafcbe9aa Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Sun, 10 Nov 2013 17:12:45 +0200 Subject: staging: vt6655: remove unneeded semicolon This patch deletes any unneeded semicolons in driver vt6655 as detected by coccinelle. Signed-off-by: Teodora Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 2 +- drivers/staging/vt6655/card.c | 2 +- drivers/staging/vt6655/dpc.c | 6 +++--- drivers/staging/vt6655/iwctl.c | 2 +- drivers/staging/vt6655/power.c | 2 +- drivers/staging/vt6655/rxtx.c | 4 ++-- drivers/staging/vt6655/wmgr.c | 12 ++++++------ 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 3b39cb214418..5995dc203c79 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -1221,7 +1221,7 @@ start: bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL); bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); pDevice->uAutoReConnectTime = 0; - }; + } } if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { if (pDevice->bUpdateBBVGA) diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index e95ecca549f7..db38ca051130 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -2013,7 +2013,7 @@ QWORD CARDqGetTSFOffset(unsigned char byRxRate, QWORD qwTSF1, QWORD qwTSF2) HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2) - 1; } else { HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2); - }; + } return qwTSFOffset; } diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index c60f3e6dc6f8..0a29c9015419 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -169,7 +169,7 @@ s_vProcessRxMACHeader(PSDevice pDevice, unsigned char *pbyRxBufferAddr, } } else { cbHeaderSize += WLAN_HDR_ADDR3_LEN; - }; + } pbyRxBuffer = (unsigned char *)(pbyRxBufferAddr + cbHeaderSize); if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) { @@ -263,7 +263,7 @@ s_vGetDASA(unsigned char *pbyRxBufferAddr, unsigned int *pcbHeaderSize, psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii]; } } - }; + } *pcbHeaderSize = cbHeaderSize; } @@ -592,7 +592,7 @@ device_receive_frame( } } else { // Control Frame - }; + } return false; } else { if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c index 4bff8aa96be7..2db4bc88e45e 100644 --- a/drivers/staging/vt6655/iwctl.c +++ b/drivers/staging/vt6655/iwctl.c @@ -1632,7 +1632,7 @@ int iwctl_giwsens(struct net_device *dev, wrq->value = ldBm; } else { wrq->value = 0; - }; + } wrq->disabled = (wrq->value == 0); wrq->fixed = 1; diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 3da2838006e3..4bd1ccb79515 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -260,7 +260,7 @@ PSvSendPSPOLL( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n"); } else { // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet success..\n"); - }; + } return; } diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 182c53ee66da..6affd6edac0d 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -2212,7 +2212,7 @@ CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { else { bNeedACK = true; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; - }; + } if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { @@ -2686,7 +2686,7 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, unsigned char *pbMPDU, un } bNeedACK = true; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; - }; + } if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c index a1eff7e514a9..5200a2a0ecca 100644 --- a/drivers/staging/vt6655/wmgr.c +++ b/drivers/staging/vt6655/wmgr.c @@ -1719,7 +1719,7 @@ s_vMgrRxDeauthentication( } /* else, ignore it. TODO: IBSS authentication service would be implemented here */ - }; + } return; } @@ -2092,10 +2092,10 @@ s_vMgrRxBeacon( pMgmt->bInTIM = sFrame.pTIM->byVirtBitMap[uLocateByteIndex] & byTIMBitOn ? true : false; } else { pMgmt->bInTIM = false; - }; + } } else { pMgmt->bInTIM = false; - }; + } if (pMgmt->bInTIM || (pMgmt->bMulticastTIM && (pMgmt->byDTIMCount == 0))) { @@ -2671,7 +2671,7 @@ vMgrJoinBSSBegin( DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "End of Join AP -- A/B/G Action\n"); } else { pMgmt->eCurrState = WMAC_STATE_IDLE; - }; + } } else { // ad-hoc mode BSS @@ -2740,8 +2740,8 @@ vMgrJoinBSSBegin( bMgrPrepareBeaconToSend((void *)pDevice, pMgmt); } else { pMgmt->eCurrState = WMAC_STATE_IDLE; - }; - }; + } + } return; } -- cgit v1.2.3 From 05323e78161b4396c31e7ed8d84670461805fb97 Mon Sep 17 00:00:00 2001 From: Archana kumari Date: Fri, 1 Nov 2013 14:05:44 +0530 Subject: staging: media: lirc: fixed sparse warnings by adding __user annotations in lirc_serial.c This patch fixes sparse warning by adding __user annotations in lirc_serial.c Signed-off-by: Archana kumari Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index af08e677b60f..23043bd70e7e 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -961,7 +961,7 @@ static void set_use_dec(void *data) spin_unlock_irqrestore(&hardware[type].lock, flags); } -static ssize_t lirc_write(struct file *file, const char *buf, +static ssize_t lirc_write(struct file *file, const char __user *buf, size_t n, loff_t *ppos) { int i, count; -- cgit v1.2.3 From 278660a44648e02c3a75b6161acd31fa120067fc Mon Sep 17 00:00:00 2001 From: Valentina Manea Date: Fri, 1 Nov 2013 15:03:08 +0200 Subject: staging: crystalhd: return true and false instead of 1 and 0 This fixes coccinelle error regarding functions that return bool and return 1 and 0 instead of true and false. Signed-off-by: Valentina Manea Reviewed-by: Lisa Nguyen Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/crystalhd/crystalhd_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c index 07a2f24d0d47..3972b52e1416 100644 --- a/drivers/staging/crystalhd/crystalhd_cmds.c +++ b/drivers/staging/crystalhd/crystalhd_cmds.c @@ -1059,7 +1059,7 @@ bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx) { if (!ctx) { BCMLOG_ERR("Invalid arg..\n"); - return 0; + return false; } return crystalhd_hw_interrupt(ctx->adp, &ctx->hw_ctx); -- cgit v1.2.3 From 585dc70d0e7b311bca74050dfca64715b1d26e4c Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 1 Nov 2013 19:19:57 +0530 Subject: Staging: keucr: Fix externs are avoided in smilmain.c This patch fixes the following checkpatch.pl warning in smilmain.c- WARNING: externs should be avoided in .c files Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smilmain.c | 90 ++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c index 2786808fde9f..ed15c3531eb9 100644 --- a/drivers/staging/keucr/smilmain.c +++ b/drivers/staging/keucr/smilmain.c @@ -4,46 +4,26 @@ #include "smcommon.h" #include "smil.h" -int Check_D_LogCHS(WORD *, BYTE *, BYTE *); -void Initialize_D_Media(void); -void PowerOff_D_Media(void); -int Check_D_MediaPower(void); -int Check_D_MediaExist(void); -int Check_D_MediaWP(void); -int Check_D_MediaFmt(struct us_data *); -int Check_D_MediaFmtForEraseAll(struct us_data *); -int Conv_D_MediaAddr(struct us_data *, DWORD); -int Inc_D_MediaAddr(struct us_data *); -int Check_D_FirstSect(void); -int Check_D_LastSect(void); -int Media_D_ReadOneSect(struct us_data *, WORD, BYTE *); -int Media_D_WriteOneSect(struct us_data *, WORD, BYTE *); -int Media_D_CopyBlockHead(struct us_data *); -int Media_D_CopyBlockTail(struct us_data *); -int Media_D_EraseOneBlock(void); -int Media_D_EraseAllBlock(void); - -int Copy_D_BlockAll(struct us_data *, DWORD); -int Copy_D_BlockHead(struct us_data *); -int Copy_D_BlockTail(struct us_data *); -int Reassign_D_BlockHead(struct us_data *); - -int Assign_D_WriteBlock(void); -int Release_D_ReadBlock(struct us_data *); -int Release_D_WriteBlock(struct us_data *); -int Release_D_CopySector(struct us_data *); - -int Copy_D_PhyOneSect(struct us_data *); -int Read_D_PhyOneSect(struct us_data *, WORD, BYTE *); -int Write_D_PhyOneSect(struct us_data *, WORD, BYTE *); -int Erase_D_PhyOneBlock(struct us_data *); - -int Set_D_PhyFmtValue(struct us_data *); -int Search_D_CIS(struct us_data *); -int Make_D_LogTable(struct us_data *); -void Check_D_BlockIsFull(void); - -int MarkFail_D_PhyOneBlock(struct us_data *); +static int Conv_D_MediaAddr(struct us_data *, DWORD); +static int Inc_D_MediaAddr(struct us_data *); +static int Media_D_ReadOneSect(struct us_data *, WORD, BYTE *); + +static int Copy_D_BlockAll(struct us_data *, DWORD); + +static int Assign_D_WriteBlock(void); +static int Release_D_ReadBlock(struct us_data *); +static int Release_D_WriteBlock(struct us_data *); +static int Release_D_CopySector(struct us_data *); + +static int Copy_D_PhyOneSect(struct us_data *); +static int Read_D_PhyOneSect(struct us_data *, WORD, BYTE *); +static int Erase_D_PhyOneBlock(struct us_data *); + +static int Set_D_PhyFmtValue(struct us_data *); +static int Search_D_CIS(struct us_data *); +static int Make_D_LogTable(struct us_data *); + +static int MarkFail_D_PhyOneBlock(struct us_data *); DWORD ErrXDCode; DWORD ErrCode; @@ -167,7 +147,7 @@ int Media_D_CopySector(struct us_data *us, DWORD start, WORD count, BYTE *buf) } /* ----- Release_D_CopySector() ------------------------------------------ */ -int Release_D_CopySector(struct us_data *us) +static int Release_D_CopySector(struct us_data *us) { Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock; Media.PhyBlock = ReadBlock; @@ -211,7 +191,7 @@ int Check_D_MediaFmt(struct us_data *us) /* SmartMedia Physical Address Control Subroutine */ /* ----- Conv_D_MediaAddr() --------------------------------------------- */ -int Conv_D_MediaAddr(struct us_data *us, DWORD addr) +static int Conv_D_MediaAddr(struct us_data *us, DWORD addr) { DWORD temp; @@ -240,7 +220,7 @@ int Conv_D_MediaAddr(struct us_data *us, DWORD addr) } /* ----- Inc_D_MediaAddr() ---------------------------------------------- */ -int Inc_D_MediaAddr(struct us_data *us) +static int Inc_D_MediaAddr(struct us_data *us) { WORD LogBlock = Media.LogBlock; @@ -290,7 +270,7 @@ int Inc_D_MediaAddr(struct us_data *us) /* SmartMedia Read/Write Subroutine with Retry */ /* ----- Media_D_ReadOneSect() ------------------------------------------ */ -int Media_D_ReadOneSect(struct us_data *us, WORD count, BYTE *buf) +static int Media_D_ReadOneSect(struct us_data *us, WORD count, BYTE *buf) { DWORD err, retry; @@ -334,7 +314,7 @@ int Media_D_ReadOneSect(struct us_data *us, WORD count, BYTE *buf) /* SmartMedia Physical Sector Data Copy Subroutine */ /* ----- Copy_D_BlockAll() ---------------------------------------------- */ -int Copy_D_BlockAll(struct us_data *us, DWORD mode) +static int Copy_D_BlockAll(struct us_data *us, DWORD mode) { BYTE sect; @@ -371,7 +351,7 @@ int Copy_D_BlockAll(struct us_data *us, DWORD mode) /* SmartMedia Physical Block Assign/Release Subroutine */ /* ----- Assign_D_WriteBlock() ------------------------------------------ */ -int Assign_D_WriteBlock(void) +static int Assign_D_WriteBlock(void) { ReadBlock = Media.PhyBlock; @@ -404,7 +384,7 @@ int Assign_D_WriteBlock(void) } /* ----- Release_D_ReadBlock() ------------------------------------------ */ -int Release_D_ReadBlock(struct us_data *us) +static int Release_D_ReadBlock(struct us_data *us) { DWORD mode; @@ -438,7 +418,7 @@ int Release_D_ReadBlock(struct us_data *us) } /* ----- Release_D_WriteBlock() ----------------------------------------- */ -int Release_D_WriteBlock(struct us_data *us) +static int Release_D_WriteBlock(struct us_data *us) { SectCopyMode = COMPLETED; Media.PhyBlock = WriteBlock; @@ -452,7 +432,7 @@ int Release_D_WriteBlock(struct us_data *us) /* SmartMedia Physical Sector Data Copy Subroutine */ /* ----- Copy_D_PhyOneSect() -------------------------------------------- */ -int Copy_D_PhyOneSect(struct us_data *us) +static int Copy_D_PhyOneSect(struct us_data *us) { int i; DWORD err, retry; @@ -529,7 +509,7 @@ int Copy_D_PhyOneSect(struct us_data *us) /* SmartMedia Physical Sector Read/Write/Erase Subroutine */ /* ----- Read_D_PhyOneSect() -------------------------------------------- */ -int Read_D_PhyOneSect(struct us_data *us, WORD count, BYTE *buf) +static int Read_D_PhyOneSect(struct us_data *us, WORD count, BYTE *buf) { int i; DWORD retry; @@ -580,7 +560,7 @@ int Read_D_PhyOneSect(struct us_data *us, WORD count, BYTE *buf) } /* ----- Erase_D_PhyOneBlock() ------------------------------------------ */ -int Erase_D_PhyOneBlock(struct us_data *us) +static int Erase_D_PhyOneBlock(struct us_data *us) { if (Ssfdc_D_EraseBlock(us)) { ErrCode = ERR_HwError; @@ -597,7 +577,7 @@ int Erase_D_PhyOneBlock(struct us_data *us) /* SmartMedia Physical Format Check Local Subroutine */ /* ----- Set_D_PhyFmtValue() -------------------------------------------- */ -int Set_D_PhyFmtValue(struct us_data *us) +static int Set_D_PhyFmtValue(struct us_data *us) { if (Set_D_SsfdcModel(us->SM_DeviceID)) return ERROR; @@ -606,7 +586,7 @@ int Set_D_PhyFmtValue(struct us_data *us) } /* ----- Search_D_CIS() ------------------------------------------------- */ -int Search_D_CIS(struct us_data *us) +static int Search_D_CIS(struct us_data *us) { Media.Zone = 0; Media.Sector = 0; @@ -660,7 +640,7 @@ int Search_D_CIS(struct us_data *us) } /* ----- Make_D_LogTable() ---------------------------------------------- */ -int Make_D_LogTable(struct us_data *us) +static int Make_D_LogTable(struct us_data *us) { WORD phyblock, logblock; @@ -761,7 +741,7 @@ int Make_D_LogTable(struct us_data *us) } /* ----- MarkFail_D_PhyOneBlock() --------------------------------------- */ -int MarkFail_D_PhyOneBlock(struct us_data *us) +static int MarkFail_D_PhyOneBlock(struct us_data *us) { BYTE sect; -- cgit v1.2.3 From 23657199840c18d605490d2d63aec2fdcf51eddc Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 1 Nov 2013 19:21:27 +0530 Subject: Staging: keucr: Fix externs are avoided in smilsub.c This patch fixes the following checkpatch.pl warning in smilsub.c- WARNING: externs should be avoided in .c files Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smilsub.c | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c index 346c5702f411..ea3c747b3a28 100644 --- a/drivers/staging/keucr/smilsub.c +++ b/drivers/staging/keucr/smilsub.c @@ -6,45 +6,13 @@ #include "smcommon.h" #include "smil.h" -void _Set_D_SsfdcRdCmd(BYTE); -void _Set_D_SsfdcRdAddr(BYTE); -void _Set_D_SsfdcRdChip(void); -void _Set_D_SsfdcRdStandby(void); -void _Start_D_SsfdcRdHwECC(void); -void _Stop_D_SsfdcRdHwECC(void); -void _Load_D_SsfdcRdHwECC(BYTE); -void _Set_D_SsfdcWrCmd(BYTE); -void _Set_D_SsfdcWrAddr(BYTE); -void _Set_D_SsfdcWrBlock(void); -void _Set_D_SsfdcWrStandby(void); -void _Start_D_SsfdcWrHwECC(void); -void _Load_D_SsfdcWrHwECC(BYTE); -int _Check_D_SsfdcBusy(WORD); -int _Check_D_SsfdcStatus(void); -void _Reset_D_SsfdcErr(void); -void _Read_D_SsfdcBuf(BYTE *); -void _Write_D_SsfdcBuf(BYTE *); -void _Read_D_SsfdcByte(BYTE *); -void _ReadRedt_D_SsfdcBuf(BYTE *); -void _WriteRedt_D_SsfdcBuf(BYTE *); -BYTE _Check_D_DevCode(BYTE); - -void _Set_D_ECCdata(BYTE, BYTE *); -void _Calc_D_ECCdata(BYTE *); - +static BYTE _Check_D_DevCode(BYTE); struct keucr_media_info Ssfdc; struct keucr_media_address Media; struct keucr_media_area CisArea; static BYTE EccBuf[6]; -extern PBYTE SMHostAddr; -extern DWORD ErrXDCode; - -extern WORD ReadBlock; -extern WORD WriteBlock; - - #define EVEN 0 /* Even Page for 256byte/page */ #define ODD 1 /* Odd Page for 256byte/page */ -- cgit v1.2.3 From afbab210f6474139f48445a9d9c7082f54da837b Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 1 Nov 2013 19:24:17 +0530 Subject: Staging: keucr: Fix externs are avoided in smscsi.c This patch fixes the following checkpatch.pl warning in smscsi.c- WARNING: externs should be avoided in .c files Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smscsi.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smscsi.c b/drivers/staging/keucr/smscsi.c index 572d6489b66b..5c03eca4dba8 100644 --- a/drivers/staging/keucr/smscsi.c +++ b/drivers/staging/keucr/smscsi.c @@ -11,16 +11,12 @@ #include "transport.h" #include "smil.h" -int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Start_Stop(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb); - -extern PBYTE SMHostAddr; -extern DWORD ErrXDCode; +static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb); /* ----- SM_SCSIIrp() -------------------------------------------------- */ int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb) @@ -57,7 +53,7 @@ int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb) } /* ----- SM_SCSI_Test_Unit_Ready() ------------------------------------- */ -int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb) +static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb) { if (us->SM_Status.Insert && us->SM_Status.Ready) return USB_STOR_TRANSPORT_GOOD; @@ -70,7 +66,7 @@ int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb) } /* ----- SM_SCSI_Inquiry() --------------------------------------------- */ -int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb) +static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb) { BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, @@ -84,7 +80,7 @@ int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb) /* ----- SM_SCSI_Mode_Sense() ------------------------------------------ */ -int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb) +static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb) { BYTE mediaNoWP[12] = {0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00}; @@ -101,7 +97,7 @@ int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb) } /* ----- SM_SCSI_Read_Capacity() --------------------------------------- */ -int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb) +static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb) { unsigned int offset = 0; struct scatterlist *sg = NULL; @@ -133,7 +129,7 @@ int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb) } /* ----- SM_SCSI_Read() -------------------------------------------------- */ -int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb) +static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb) { int result = 0; PBYTE Cdb = srb->cmnd; @@ -165,7 +161,7 @@ int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb) } /* ----- SM_SCSI_Write() -------------------------------------------------- */ -int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb) +static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb) { int result = 0; PBYTE Cdb = srb->cmnd; -- cgit v1.2.3 From ab46b7920cb1eabf2991f9f829094e53663650a0 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Fri, 1 Nov 2013 22:03:55 +0530 Subject: staging: bcm: removed prohibited space before semicolon removed prohibited space before semicolon(;) to fix checkpatch warning Signed-off-by: Nandini Hanumanthagowda Reviewed-by: Josh Triplett Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 8c811439faba..ed45b2161d49 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -1190,7 +1190,7 @@ cntrlEnd: break; case IOCTL_BCM_CAL_INIT: { - UINT uiSectorSize = 0 ; + UINT uiSectorSize = 0; if (Adapter->eNVMType == NVM_FLASH) { if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) return -EFAULT; @@ -1403,7 +1403,7 @@ cntrlEnd: case IOCTL_BCM_FLASH2X_SECTION_READ: { struct bcm_flash2x_readwrite sFlash2xRead = {0}; - PUCHAR pReadBuff = NULL ; + PUCHAR pReadBuff = NULL; UINT NOB = 0; UINT BuffSize = 0; UINT ReadBytes = 0; @@ -1438,7 +1438,7 @@ cntrlEnd: else BuffSize = NOB; - ReadOffset = sFlash2xRead.offset ; + ReadOffset = sFlash2xRead.offset; OutPutBuff = IoBuffer.OutputBuffer; pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); @@ -1483,7 +1483,7 @@ cntrlEnd: NOB = NOB - ReadBytes; if (NOB) { ReadOffset = ReadOffset + ReadBytes; - OutPutBuff = OutPutBuff + ReadBytes ; + OutPutBuff = OutPutBuff + ReadBytes; } } @@ -1538,7 +1538,7 @@ cntrlEnd: if (NOB > Adapter->uiSectorSize) BuffSize = Adapter->uiSectorSize; else - BuffSize = NOB ; + BuffSize = NOB; pWriteBuff = kmalloc(BuffSize, GFP_KERNEL); @@ -1841,10 +1841,10 @@ cntrlEnd: case IOCTL_BCM_NVM_RAW_READ: { struct bcm_nvm_readwrite stNVMRead; - INT NOB ; - INT BuffSize ; + INT NOB; + INT BuffSize; INT ReadOffset = 0; - UINT ReadBytes = 0 ; + UINT ReadBytes = 0; PUCHAR pReadBuff; void __user *OutPutBuff; -- cgit v1.2.3 From 8105705375676c11d3b7c5a4301016a1dcabb7a1 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Sat, 2 Nov 2013 00:19:31 +0530 Subject: staging: bcm: fixed space related errors around operators removed any prohibited spaces and added required spaces around operators to follow linux coding style and hence fixed the checkpatch errors Signed-off-by: Nandini Hanumanthagowda Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/DDRInit.c | 1501 ++++++++++++++++++++--------------------- 1 file changed, 749 insertions(+), 752 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c index 9f7e30f637ea..6bddf723e06a 100644 --- a/drivers/staging/bcm/DDRInit.c +++ b/drivers/staging/bcm/DDRInit.c @@ -7,527 +7,527 @@ //DDR INIT-133Mhz #define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12 //index for 0x0F007000 -static struct bcm_ddr_setting asT3_DDRSetting133MHz[]= {// # DPLL Clock Setting - {0x0F000800,0x00007212}, - {0x0f000820,0x07F13FFF}, - {0x0f000810,0x00000F95}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, +static struct bcm_ddr_setting asT3_DDRSetting133MHz[] = {// # DPLL Clock Setting + {0x0F000800, 0x00007212}, + {0x0f000820, 0x07F13FFF}, + {0x0f000810, 0x00000F95}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000840,0x0FFF1B00}, - {0x0f000870,0x00000002}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, - {0x0F00a04C,0x0000000C}, + {0x0f000840, 0x0FFF1B00}, + {0x0f000870, 0x00000002}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, + {0x0F00a04C, 0x0000000C}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 - {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x02000007}, - {0x0F007028,0x02020202}, - {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a - {0x0F007030,0x05000000}, - {0x0F007034,0x00000003}, - {0x0F007038,0x110a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 - {0x0F00703C,0x02101010},//ROB - 0x02101010,//0x02101018}, - {0x0F007040,0x45751200},//ROB - 0x45751200,//0x450f1200}, - {0x0F007044,0x110a0d00},//ROB - 0x110a0d00//0x111f0d00 - {0x0F007048,0x081b0306}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0000001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x0010246c}, - {0x0F007064,0x00000010}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00007000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020, 0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x02000007}, + {0x0F007028, 0x02020202}, + {0x0F00702c, 0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030, 0x05000000}, + {0x0F007034, 0x00000003}, + {0x0F007038, 0x110a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C, 0x02101010},//ROB - 0x02101010,//0x02101018}, + {0x0F007040, 0x45751200},//ROB - 0x45751200,//0x450f1200}, + {0x0F007044, 0x110a0d00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048, 0x081b0306}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0000001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x0010246c}, + {0x0F007064, 0x00000010}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00007000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, //# Enable BW improvement within memory controller - {0x0F007094,0x00000104}, + {0x0F007094, 0x00000104}, //# Enable 2 ports within X-bar - {0x0F00A000,0x00000016}, + {0x0F00A000, 0x00000016}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; //80Mhz #define T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 10 //index for 0x0F007000 -static struct bcm_ddr_setting asT3_DDRSetting80MHz[]= {// # DPLL Clock Setting - {0x0f000810,0x00000F95}, - {0x0f000820,0x07f1ffff}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, - {0x0F00a000,0x00000016}, - {0x0F00a04C,0x0000000C}, +static struct bcm_ddr_setting asT3_DDRSetting80MHz[] = {// # DPLL Clock Setting + {0x0f000810, 0x00000F95}, + {0x0f000820, 0x07f1ffff}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, + {0x0F00a000, 0x00000016}, + {0x0F00a04C, 0x0000000C}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01000000}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020000}, - {0x0F007020,0x04020107}, - {0x0F007024,0x00000007}, - {0x0F007028,0x02020201}, - {0x0F00702c,0x0204040a}, - {0x0F007030,0x04000000}, - {0x0F007034,0x00000002}, - {0x0F007038,0x1F060200}, - {0x0F00703C,0x1C22221F}, - {0x0F007040,0x8A006600}, - {0x0F007044,0x221a0800}, - {0x0F007048,0x02690204}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0000001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x000A15D6}, - {0x0F007064,0x0000000A}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00004000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, - {0x0F007094,0x00000104}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01000000}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020000}, + {0x0F007020, 0x04020107}, + {0x0F007024, 0x00000007}, + {0x0F007028, 0x02020201}, + {0x0F00702c, 0x0204040a}, + {0x0F007030, 0x04000000}, + {0x0F007034, 0x00000002}, + {0x0F007038, 0x1F060200}, + {0x0F00703C, 0x1C22221F}, + {0x0F007040, 0x8A006600}, + {0x0F007044, 0x221a0800}, + {0x0F007048, 0x02690204}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0000001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x000A15D6}, + {0x0F007064, 0x0000000A}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00004000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, + {0x0F007094, 0x00000104}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; //100Mhz #define T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 13 //index for 0x0F007000 -static struct bcm_ddr_setting asT3_DDRSetting100MHz[]= {// # DPLL Clock Setting - {0x0F000800,0x00007008}, - {0x0f000810,0x00000F95}, - {0x0f000820,0x07F13E3F}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, +static struct bcm_ddr_setting asT3_DDRSetting100MHz[] = {// # DPLL Clock Setting + {0x0F000800, 0x00007008}, + {0x0f000810, 0x00000F95}, + {0x0f000820, 0x07F13E3F}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL //0x0f000840,0x0FFF1800, - {0x0f000840,0x0FFF1B00}, - {0x0f000870,0x00000002}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, - {0x0F00a04C,0x0000000C}, + {0x0f000840, 0x0FFF1B00}, + {0x0f000870, 0x00000002}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, + {0x0F00a04C, 0x0000000C}, //# Enable 2 ports within X-bar - {0x0F00A000,0x00000016}, + {0x0F00A000, 0x00000016}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020001}, // POP - 0x00020000 Normal 0x01020000 - {0x0F007020,0x04020107},//Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x00000007}, - {0x0F007028,0x01020201}, - {0x0F00702c,0x0204040A}, - {0x0F007030,0x06000000}, - {0x0F007034,0x00000004}, - {0x0F007038,0x20080200}, - {0x0F00703C,0x02030320}, - {0x0F007040,0x6E7F1200}, - {0x0F007044,0x01190A00}, - {0x0F007048,0x06120305},//0x02690204 // 0x06120305 - {0x0F00704c,0x00000000}, - {0x0F007050,0x0000001C}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x00082ED6}, - {0x0F007064,0x0000000A}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00005000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020001}, // POP - 0x00020000 Normal 0x01020000 + {0x0F007020, 0x04020107},//Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x00000007}, + {0x0F007028, 0x01020201}, + {0x0F00702c, 0x0204040A}, + {0x0F007030, 0x06000000}, + {0x0F007034, 0x00000004}, + {0x0F007038, 0x20080200}, + {0x0F00703C, 0x02030320}, + {0x0F007040, 0x6E7F1200}, + {0x0F007044, 0x01190A00}, + {0x0F007048, 0x06120305},//0x02690204 // 0x06120305 + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0000001C}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x00082ED6}, + {0x0F007064, 0x0000000A}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00005000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, //# Enable BW improvement within memory controller - {0x0F007094,0x00000104}, + {0x0F007094, 0x00000104}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; //Net T3B DDR Settings //DDR INIT-133Mhz static struct bcm_ddr_setting asDPLL_266MHZ[] = { - {0x0F000800,0x00007212}, - {0x0f000820,0x07F13FFF}, - {0x0f000810,0x00000F95}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, + {0x0F000800, 0x00007212}, + {0x0f000820, 0x07F13FFF}, + {0x0f000810, 0x00000F95}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000840,0x0FFF1B00}, - {0x0f000870,0x00000002} + {0x0f000840, 0x0FFF1B00}, + {0x0f000870, 0x00000002} }; #define T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 11 //index for 0x0F007000 static struct bcm_ddr_setting asT3B_DDRSetting133MHz[] = {// # DPLL Clock Setting - {0x0f000810,0x00000F95}, - {0x0f000810,0x00000F95}, - {0x0f000810,0x00000F95}, - {0x0f000820,0x07F13652}, - {0x0f000840,0x0FFF0800}, + {0x0f000810, 0x00000F95}, + {0x0f000810, 0x00000F95}, + {0x0f000810, 0x00000F95}, + {0x0f000820, 0x07F13652}, + {0x0f000840, 0x0FFF0800}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000880,0x000003DD}, - {0x0f000860,0x00000000}, + {0x0f000880, 0x000003DD}, + {0x0f000860, 0x00000000}, // Changed source for X-bar and MIPS clock to APLL - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, //# Enable 2 ports within X-bar - {0x0F00A000,0x00000016}, + {0x0F00A000, 0x00000016}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 - {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x02000007}, - {0x0F007028,0x02020202}, - {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a - {0x0F007030,0x05000000}, - {0x0F007034,0x00000003}, - {0x0F007038,0x130a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 - {0x0F00703C,0x02101012},//ROB - 0x02101010,//0x02101018}, - {0x0F007040,0x457D1200},//ROB - 0x45751200,//0x450f1200}, - {0x0F007044,0x11130d00},//ROB - 0x110a0d00//0x111f0d00 - {0x0F007048,0x040D0306}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0000001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x0010246c}, - {0x0F007064,0x00000012}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00007000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020, 0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x02000007}, + {0x0F007028, 0x02020202}, + {0x0F00702c, 0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030, 0x05000000}, + {0x0F007034, 0x00000003}, + {0x0F007038, 0x130a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C, 0x02101012},//ROB - 0x02101010,//0x02101018}, + {0x0F007040, 0x457D1200},//ROB - 0x45751200,//0x450f1200}, + {0x0F007044, 0x11130d00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048, 0x040D0306}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0000001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x0010246c}, + {0x0F007064, 0x00000012}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00007000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, //# Enable BW improvement within memory controller - {0x0F007094,0x00000104}, + {0x0F007094, 0x00000104}, //# Enable start bit within memory controller - {0x0F007018,0x01010000}, + {0x0F007018, 0x01010000}, }; #define T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000 static struct bcm_ddr_setting asT3B_DDRSetting80MHz[] = {// # DPLL Clock Setting - {0x0f000810,0x00000F95}, - {0x0f000820,0x07F13FFF}, - {0x0f000840,0x0FFF1F00}, - {0x0f000880,0x000003DD}, - {0x0f000860,0x00000000}, + {0x0f000810, 0x00000F95}, + {0x0f000820, 0x07F13FFF}, + {0x0f000840, 0x0FFF1F00}, + {0x0f000880, 0x000003DD}, + {0x0f000860, 0x00000000}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, - {0x0F00a000,0x00000016}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, + {0x0F00a000, 0x00000016}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01000000}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020000}, - {0x0F007020,0x04020107}, - {0x0F007024,0x00000007}, - {0x0F007028,0x02020201}, - {0x0F00702c,0x0204040a}, - {0x0F007030,0x04000000}, - {0x0F007034,0x02000002}, - {0x0F007038,0x1F060202}, - {0x0F00703C,0x1C22221F}, - {0x0F007040,0x8A006600}, - {0x0F007044,0x221a0800}, - {0x0F007048,0x02690204}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0100001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x000A15D6}, - {0x0F007064,0x0000000A}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00004000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, - {0x0F007094,0x00000104}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01000000}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020000}, + {0x0F007020, 0x04020107}, + {0x0F007024, 0x00000007}, + {0x0F007028, 0x02020201}, + {0x0F00702c, 0x0204040a}, + {0x0F007030, 0x04000000}, + {0x0F007034, 0x02000002}, + {0x0F007038, 0x1F060202}, + {0x0F00703C, 0x1C22221F}, + {0x0F007040, 0x8A006600}, + {0x0F007044, 0x221a0800}, + {0x0F007048, 0x02690204}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0100001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x000A15D6}, + {0x0F007064, 0x0000000A}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00004000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, + {0x0F007094, 0x00000104}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; //100Mhz #define T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 9 //index for 0x0F007000 static struct bcm_ddr_setting asT3B_DDRSetting100MHz[] = {// # DPLL Clock Setting - {0x0f000810,0x00000F95}, - {0x0f000820,0x07F1369B}, - {0x0f000840,0x0FFF0800}, - {0x0f000880,0x000003DD}, - {0x0f000860,0x00000000}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, + {0x0f000810, 0x00000F95}, + {0x0f000820, 0x07F1369B}, + {0x0f000840, 0x0FFF0800}, + {0x0f000880, 0x000003DD}, + {0x0f000860, 0x00000000}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, //# Enable 2 ports within X-bar - {0x0F00A000,0x00000016}, + {0x0F00A000, 0x00000016}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020000}, // POP - 0x00020000 Normal 0x01020000 - {0x0F007020,0x04020107},//Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x00000007}, - {0x0F007028,0x01020201}, - {0x0F00702c,0x0204040A}, - {0x0F007030,0x06000000}, - {0x0F007034,0x02000004}, - {0x0F007038,0x20080200}, - {0x0F00703C,0x02030320}, - {0x0F007040,0x6E7F1200}, - {0x0F007044,0x01190A00}, - {0x0F007048,0x06120305},//0x02690204 // 0x06120305 - {0x0F00704c,0x00000000}, - {0x0F007050,0x0100001C}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x00082ED6}, - {0x0F007064,0x0000000A}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00005000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020000}, // POP - 0x00020000 Normal 0x01020000 + {0x0F007020, 0x04020107},//Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x00000007}, + {0x0F007028, 0x01020201}, + {0x0F00702c, 0x0204040A}, + {0x0F007030, 0x06000000}, + {0x0F007034, 0x02000004}, + {0x0F007038, 0x20080200}, + {0x0F00703C, 0x02030320}, + {0x0F007040, 0x6E7F1200}, + {0x0F007044, 0x01190A00}, + {0x0F007048, 0x06120305},//0x02690204 // 0x06120305 + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0100001C}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x00082ED6}, + {0x0F007064, 0x0000000A}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00005000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, //# Enable BW improvement within memory controller - {0x0F007094,0x00000104}, + {0x0F007094, 0x00000104}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 9 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LP_DDRSetting133MHz[]= {// # DPLL Clock Setting - {0x0f000820,0x03F1365B}, - {0x0f000810,0x00002F95}, - {0x0f000880,0x000003DD}, +static struct bcm_ddr_setting asT3LP_DDRSetting133MHz[] = {// # DPLL Clock Setting + {0x0f000820, 0x03F1365B}, + {0x0f000810, 0x00002F95}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000840,0x0FFF0000}, - {0x0f000860,0x00000000}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, - {0x0F00A000,0x00000016}, + {0x0f000840, 0x0FFF0000}, + {0x0f000860, 0x00000000}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, + {0x0F00A000, 0x00000016}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 - {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x02000007}, - {0x0F007028,0x02020200}, - {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a - {0x0F007030,0x05000000}, - {0x0F007034,0x00000003}, - {0x0F007038,0x200a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 - {0x0F00703C,0x02101020},//ROB - 0x02101010,//0x02101018, - {0x0F007040,0x45711200},//ROB - 0x45751200,//0x450f1200, - {0x0F007044,0x110D0D00},//ROB - 0x110a0d00//0x111f0d00 - {0x0F007048,0x04080306}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0100001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x0010245F}, - {0x0F007064,0x00000010}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00007000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, - {0x0F007088,0x01000001}, - {0x0F00708c,0x00000101}, - {0x0F007090,0x00000000}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020, 0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x02000007}, + {0x0F007028, 0x02020200}, + {0x0F00702c, 0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030, 0x05000000}, + {0x0F007034, 0x00000003}, + {0x0F007038, 0x200a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C, 0x02101020},//ROB - 0x02101010,//0x02101018, + {0x0F007040, 0x45711200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044, 0x110D0D00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048, 0x04080306}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0100001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x0010245F}, + {0x0F007064, 0x00000010}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00007000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, + {0x0F007088, 0x01000001}, + {0x0F00708c, 0x00000101}, + {0x0F007090, 0x00000000}, //# Enable BW improvement within memory controller - {0x0F007094,0x00040000}, - {0x0F007098,0x00000000}, - {0x0F0070c8,0x00000104}, + {0x0F007094, 0x00040000}, + {0x0F007098, 0x00000000}, + {0x0F0070c8, 0x00000104}, //# Enable 2 ports within X-bar //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 11 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LP_DDRSetting100MHz[]= {// # DPLL Clock Setting - {0x0f000810,0x00002F95}, - {0x0f000820,0x03F1369B}, - {0x0f000840,0x0fff0000}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, +static struct bcm_ddr_setting asT3LP_DDRSetting100MHz[] = {// # DPLL Clock Setting + {0x0f000810, 0x00002F95}, + {0x0f000820, 0x03F1369B}, + {0x0f000840, 0x0fff0000}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000840,0x0FFF0000}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, + {0x0f000840, 0x0FFF0000}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020000},// POP - 0x00020001 Normal 0x01020001 - {0x0F007020,0x04020107}, //Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x00000007}, - {0x0F007028,0x01020200}, - {0x0F00702c,0x0204040a},//ROB- 0x0205050a,//0x0206060a - {0x0F007030,0x06000000}, - {0x0F007034,0x00000004}, - {0x0F007038,0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 - {0x0F00703C,0x0203031F},//ROB - 0x02101010,//0x02101018, - {0x0F007040,0x6e001200},//ROB - 0x45751200,//0x450f1200, - {0x0F007044,0x011a0a00},//ROB - 0x110a0d00//0x111f0d00 - {0x0F007048,0x03000305}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0100001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x00082ED6}, - {0x0F007064,0x0000000A}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00005000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, - {0x0F007088,0x01000001}, - {0x0F00708c,0x00000101}, - {0x0F007090,0x00000000}, - {0x0F007094,0x00010000}, - {0x0F007098,0x00000000}, - {0x0F0070C8,0x00000104}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020000},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020, 0x04020107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x00000007}, + {0x0F007028, 0x01020200}, + {0x0F00702c, 0x0204040a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030, 0x06000000}, + {0x0F007034, 0x00000004}, + {0x0F007038, 0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C, 0x0203031F},//ROB - 0x02101010,//0x02101018, + {0x0F007040, 0x6e001200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044, 0x011a0a00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048, 0x03000305}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0100001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x00082ED6}, + {0x0F007064, 0x0000000A}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00005000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, + {0x0F007088, 0x01000001}, + {0x0F00708c, 0x00000101}, + {0x0F007090, 0x00000000}, + {0x0F007094, 0x00010000}, + {0x0F007098, 0x00000000}, + {0x0F0070C8, 0x00000104}, //# Enable 2 ports within X-bar - {0x0F00A000,0x00000016}, + {0x0F00A000, 0x00000016}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; #define T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting - {0x0f000820,0x07F13FFF}, - {0x0f000810,0x00002F95}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, - {0x0f000840,0x0FFF1F00}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0F00a084,0x1Cffffff}, - {0x0F00a080,0x1C000000}, - {0x0F00A000,0x00000016}, - {0x0f007000,0x00010001}, - {0x0f007004,0x01000000}, - {0x0f007008,0x01000001}, - {0x0f00700c,0x00000000}, - {0x0f007010,0x01000000}, - {0x0f007014,0x01000100}, - {0x0f007018,0x01000000}, - {0x0f00701c,0x01020000}, - {0x0f007020,0x04020107}, - {0x0f007024,0x00000007}, - {0x0f007028,0x02020200}, - {0x0f00702c,0x0204040a}, - {0x0f007030,0x04000000}, - {0x0f007034,0x00000002}, - {0x0f007038,0x1d060200}, - {0x0f00703c,0x1c22221d}, - {0x0f007040,0x8A116600}, - {0x0f007044,0x222d0800}, - {0x0f007048,0x02690204}, - {0x0f00704c,0x00000000}, - {0x0f007050,0x0100001c}, - {0x0f007054,0x00000000}, - {0x0f007058,0x00000000}, - {0x0f00705c,0x00000000}, - {0x0f007060,0x000A15D6}, - {0x0f007064,0x0000000A}, - {0x0f007068,0x00000000}, - {0x0f00706c,0x00000001}, - {0x0f007070,0x00004000}, - {0x0f007074,0x00000000}, - {0x0f007078,0x00000000}, - {0x0f00707c,0x00000000}, - {0x0f007080,0x00000000}, - {0x0f007084,0x00000000}, - {0x0f007088,0x01000001}, - {0x0f00708c,0x00000101}, - {0x0f007090,0x00000000}, - {0x0f007094,0x00010000}, - {0x0f007098,0x00000000}, - {0x0F0070C8,0x00000104}, - {0x0F007018,0x01010000} +static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[] = {// # DPLL Clock Setting + {0x0f000820, 0x07F13FFF}, + {0x0f000810, 0x00002F95}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, + {0x0f000840, 0x0FFF1F00}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0F00a084, 0x1Cffffff}, + {0x0F00a080, 0x1C000000}, + {0x0F00A000, 0x00000016}, + {0x0f007000, 0x00010001}, + {0x0f007004, 0x01000000}, + {0x0f007008, 0x01000001}, + {0x0f00700c, 0x00000000}, + {0x0f007010, 0x01000000}, + {0x0f007014, 0x01000100}, + {0x0f007018, 0x01000000}, + {0x0f00701c, 0x01020000}, + {0x0f007020, 0x04020107}, + {0x0f007024, 0x00000007}, + {0x0f007028, 0x02020200}, + {0x0f00702c, 0x0204040a}, + {0x0f007030, 0x04000000}, + {0x0f007034, 0x00000002}, + {0x0f007038, 0x1d060200}, + {0x0f00703c, 0x1c22221d}, + {0x0f007040, 0x8A116600}, + {0x0f007044, 0x222d0800}, + {0x0f007048, 0x02690204}, + {0x0f00704c, 0x00000000}, + {0x0f007050, 0x0100001c}, + {0x0f007054, 0x00000000}, + {0x0f007058, 0x00000000}, + {0x0f00705c, 0x00000000}, + {0x0f007060, 0x000A15D6}, + {0x0f007064, 0x0000000A}, + {0x0f007068, 0x00000000}, + {0x0f00706c, 0x00000001}, + {0x0f007070, 0x00004000}, + {0x0f007074, 0x00000000}, + {0x0f007078, 0x00000000}, + {0x0f00707c, 0x00000000}, + {0x0f007080, 0x00000000}, + {0x0f007084, 0x00000000}, + {0x0f007088, 0x01000001}, + {0x0f00708c, 0x00000101}, + {0x0f007090, 0x00000000}, + {0x0f007094, 0x00010000}, + {0x0f007098, 0x00000000}, + {0x0F0070C8, 0x00000104}, + {0x0F007018, 0x01010000} }; @@ -536,246 +536,245 @@ static struct bcm_ddr_setting asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting ///T3 LP-B (UMA-B) #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ 7 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LPB_DDRSetting160MHz[]= {// # DPLL Clock Setting - - {0x0f000820,0x03F137DB}, - {0x0f000810,0x01842795}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, - {0x0f000840,0x0FFF0400}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0f003050,0x00000021},//this is flash/eeprom clock divisor which set the flash clock to 20 MHz - {0x0F00a084,0x1Cffffff},//Now dump from her in internal memory - {0x0F00a080,0x1C000000}, - {0x0F00A000,0x00000016}, - {0x0f007000,0x00010001}, - {0x0f007004,0x01000001}, - {0x0f007008,0x01000101}, - {0x0f00700c,0x00000000}, - {0x0f007010,0x01000100}, - {0x0f007014,0x01000100}, - {0x0f007018,0x01000000}, - {0x0f00701c,0x01020000}, - {0x0f007020,0x04030107}, - {0x0f007024,0x02000007}, - {0x0f007028,0x02020200}, - {0x0f00702c,0x0206060a}, - {0x0f007030,0x050d0d00}, - {0x0f007034,0x00000003}, - {0x0f007038,0x170a0200}, - {0x0f00703c,0x02101012}, - {0x0f007040,0x45161200}, - {0x0f007044,0x11250c00}, - {0x0f007048,0x04da0307}, - {0x0f00704c,0x00000000}, - {0x0f007050,0x0000001c}, - {0x0f007054,0x00000000}, - {0x0f007058,0x00000000}, - {0x0f00705c,0x00000000}, - {0x0f007060,0x00142bb6}, - {0x0f007064,0x20430014}, - {0x0f007068,0x00000000}, - {0x0f00706c,0x00000001}, - {0x0f007070,0x00009000}, - {0x0f007074,0x00000000}, - {0x0f007078,0x00000000}, - {0x0f00707c,0x00000000}, - {0x0f007080,0x00000000}, - {0x0f007084,0x00000000}, - {0x0f007088,0x01000001}, - {0x0f00708c,0x00000101}, - {0x0f007090,0x00000000}, - {0x0f007094,0x00040000}, - {0x0f007098,0x00000000}, - {0x0F0070C8,0x00000104}, - {0x0F007018,0x01010000} +static struct bcm_ddr_setting asT3LPB_DDRSetting160MHz[] = {// # DPLL Clock Setting + {0x0f000820, 0x03F137DB}, + {0x0f000810, 0x01842795}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, + {0x0f000840, 0x0FFF0400}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0f003050, 0x00000021},//this is flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084, 0x1Cffffff},//Now dump from her in internal memory + {0x0F00a080, 0x1C000000}, + {0x0F00A000, 0x00000016}, + {0x0f007000, 0x00010001}, + {0x0f007004, 0x01000001}, + {0x0f007008, 0x01000101}, + {0x0f00700c, 0x00000000}, + {0x0f007010, 0x01000100}, + {0x0f007014, 0x01000100}, + {0x0f007018, 0x01000000}, + {0x0f00701c, 0x01020000}, + {0x0f007020, 0x04030107}, + {0x0f007024, 0x02000007}, + {0x0f007028, 0x02020200}, + {0x0f00702c, 0x0206060a}, + {0x0f007030, 0x050d0d00}, + {0x0f007034, 0x00000003}, + {0x0f007038, 0x170a0200}, + {0x0f00703c, 0x02101012}, + {0x0f007040, 0x45161200}, + {0x0f007044, 0x11250c00}, + {0x0f007048, 0x04da0307}, + {0x0f00704c, 0x00000000}, + {0x0f007050, 0x0000001c}, + {0x0f007054, 0x00000000}, + {0x0f007058, 0x00000000}, + {0x0f00705c, 0x00000000}, + {0x0f007060, 0x00142bb6}, + {0x0f007064, 0x20430014}, + {0x0f007068, 0x00000000}, + {0x0f00706c, 0x00000001}, + {0x0f007070, 0x00009000}, + {0x0f007074, 0x00000000}, + {0x0f007078, 0x00000000}, + {0x0f00707c, 0x00000000}, + {0x0f007080, 0x00000000}, + {0x0f007084, 0x00000000}, + {0x0f007088, 0x01000001}, + {0x0f00708c, 0x00000101}, + {0x0f007090, 0x00000000}, + {0x0f007094, 0x00040000}, + {0x0f007098, 0x00000000}, + {0x0F0070C8, 0x00000104}, + {0x0F007018, 0x01010000} }; #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 7 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LPB_DDRSetting133MHz[]= {// # DPLL Clock Setting - {0x0f000820,0x03F1365B}, - {0x0f000810,0x00002F95}, - {0x0f000880,0x000003DD}, +static struct bcm_ddr_setting asT3LPB_DDRSetting133MHz[] = {// # DPLL Clock Setting + {0x0f000820, 0x03F1365B}, + {0x0f000810, 0x00002F95}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000840,0x0FFF0000}, - {0x0f000860,0x00000000}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz - {0x0F00a084,0x1Cffffff},//dump from here in internal memory - {0x0F00a080,0x1C000000}, - {0x0F00A000,0x00000016}, + {0x0f000840, 0x0FFF0000}, + {0x0f000860, 0x00000000}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0f003050, 0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084, 0x1Cffffff},//dump from here in internal memory + {0x0F00a080, 0x1C000000}, + {0x0F00A000, 0x00000016}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 - {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x02000007}, - {0x0F007028,0x02020200}, - {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a - {0x0F007030,0x05000000}, - {0x0F007034,0x00000003}, - {0x0F007038,0x190a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 - {0x0F00703C,0x02101017},//ROB - 0x02101010,//0x02101018, - {0x0F007040,0x45171200},//ROB - 0x45751200,//0x450f1200, - {0x0F007044,0x11290D00},//ROB - 0x110a0d00//0x111f0d00 - {0x0F007048,0x04080306}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0100001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x0010245F}, - {0x0F007064,0x00000010}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00007000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, - {0x0F007088,0x01000001}, - {0x0F00708c,0x00000101}, - {0x0F007090,0x00000000}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020, 0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x02000007}, + {0x0F007028, 0x02020200}, + {0x0F00702c, 0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030, 0x05000000}, + {0x0F007034, 0x00000003}, + {0x0F007038, 0x190a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C, 0x02101017},//ROB - 0x02101010,//0x02101018, + {0x0F007040, 0x45171200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044, 0x11290D00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048, 0x04080306}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0100001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x0010245F}, + {0x0F007064, 0x00000010}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00007000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, + {0x0F007088, 0x01000001}, + {0x0F00708c, 0x00000101}, + {0x0F007090, 0x00000000}, //# Enable BW improvement within memory controller - {0x0F007094,0x00040000}, - {0x0F007098,0x00000000}, - {0x0F0070c8,0x00000104}, + {0x0F007094, 0x00040000}, + {0x0F007098, 0x00000000}, + {0x0F0070c8, 0x00000104}, //# Enable 2 ports within X-bar //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 8 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LPB_DDRSetting100MHz[]= {// # DPLL Clock Setting - {0x0f000810,0x00002F95}, - {0x0f000820,0x03F1369B}, - {0x0f000840,0x0fff0000}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, +static struct bcm_ddr_setting asT3LPB_DDRSetting100MHz[] = {// # DPLL Clock Setting + {0x0f000810, 0x00002F95}, + {0x0f000820, 0x03F1369B}, + {0x0f000840, 0x0fff0000}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, // Changed source for X-bar and MIPS clock to APLL - {0x0f000840,0x0FFF0000}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz - {0x0F00a084,0x1Cffffff}, //dump from here in internal memory - {0x0F00a080,0x1C000000}, + {0x0f000840, 0x0FFF0000}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0f003050, 0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084, 0x1Cffffff}, //dump from here in internal memory + {0x0F00a080, 0x1C000000}, //Memcontroller Default values - {0x0F007000,0x00010001}, - {0x0F007004,0x01010100}, - {0x0F007008,0x01000001}, - {0x0F00700c,0x00000000}, - {0x0F007010,0x01000000}, - {0x0F007014,0x01000100}, - {0x0F007018,0x01000000}, - {0x0F00701c,0x01020000},// POP - 0x00020001 Normal 0x01020001 - {0x0F007020,0x04020107}, //Normal - 0x04030107 POP - 0x05030107 - {0x0F007024,0x00000007}, - {0x0F007028,0x01020200}, - {0x0F00702c,0x0204040a},//ROB- 0x0205050a,//0x0206060a - {0x0F007030,0x06000000}, - {0x0F007034,0x00000004}, - {0x0F007038,0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 - {0x0F00703C,0x0203031F},//ROB - 0x02101010,//0x02101018, - {0x0F007040,0x6e001200},//ROB - 0x45751200,//0x450f1200, - {0x0F007044,0x011a0a00},//ROB - 0x110a0d00//0x111f0d00 - {0x0F007048,0x03000305}, - {0x0F00704c,0x00000000}, - {0x0F007050,0x0100001c}, - {0x0F007054,0x00000000}, - {0x0F007058,0x00000000}, - {0x0F00705c,0x00000000}, - {0x0F007060,0x00082ED6}, - {0x0F007064,0x0000000A}, - {0x0F007068,0x00000000}, - {0x0F00706c,0x00000001}, - {0x0F007070,0x00005000}, - {0x0F007074,0x00000000}, - {0x0F007078,0x00000000}, - {0x0F00707C,0x00000000}, - {0x0F007080,0x00000000}, - {0x0F007084,0x00000000}, - {0x0F007088,0x01000001}, - {0x0F00708c,0x00000101}, - {0x0F007090,0x00000000}, - {0x0F007094,0x00010000}, - {0x0F007098,0x00000000}, - {0x0F0070C8,0x00000104}, + {0x0F007000, 0x00010001}, + {0x0F007004, 0x01010100}, + {0x0F007008, 0x01000001}, + {0x0F00700c, 0x00000000}, + {0x0F007010, 0x01000000}, + {0x0F007014, 0x01000100}, + {0x0F007018, 0x01000000}, + {0x0F00701c, 0x01020000},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020, 0x04020107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024, 0x00000007}, + {0x0F007028, 0x01020200}, + {0x0F00702c, 0x0204040a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030, 0x06000000}, + {0x0F007034, 0x00000004}, + {0x0F007038, 0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C, 0x0203031F},//ROB - 0x02101010,//0x02101018, + {0x0F007040, 0x6e001200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044, 0x011a0a00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048, 0x03000305}, + {0x0F00704c, 0x00000000}, + {0x0F007050, 0x0100001c}, + {0x0F007054, 0x00000000}, + {0x0F007058, 0x00000000}, + {0x0F00705c, 0x00000000}, + {0x0F007060, 0x00082ED6}, + {0x0F007064, 0x0000000A}, + {0x0F007068, 0x00000000}, + {0x0F00706c, 0x00000001}, + {0x0F007070, 0x00005000}, + {0x0F007074, 0x00000000}, + {0x0F007078, 0x00000000}, + {0x0F00707C, 0x00000000}, + {0x0F007080, 0x00000000}, + {0x0F007084, 0x00000000}, + {0x0F007088, 0x01000001}, + {0x0F00708c, 0x00000101}, + {0x0F007090, 0x00000000}, + {0x0F007094, 0x00010000}, + {0x0F007098, 0x00000000}, + {0x0F0070C8, 0x00000104}, //# Enable 2 ports within X-bar - {0x0F00A000,0x00000016}, + {0x0F00A000, 0x00000016}, //# Enable start bit within memory controller - {0x0F007018,0x01010000} + {0x0F007018, 0x01010000} }; #define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 7 //index for 0x0F007000 -static struct bcm_ddr_setting asT3LPB_DDRSetting80MHz[]= {// # DPLL Clock Setting - {0x0f000820,0x07F13FFF}, - {0x0f000810,0x00002F95}, - {0x0f000860,0x00000000}, - {0x0f000880,0x000003DD}, - {0x0f000840,0x0FFF1F00}, - {0x0F00a044,0x1fffffff}, - {0x0F00a040,0x1f000000}, - {0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz - {0x0F00a084,0x1Cffffff},// dump from here in internal memory - {0x0F00a080,0x1C000000}, - {0x0F00A000,0x00000016}, - {0x0f007000,0x00010001}, - {0x0f007004,0x01000000}, - {0x0f007008,0x01000001}, - {0x0f00700c,0x00000000}, - {0x0f007010,0x01000000}, - {0x0f007014,0x01000100}, - {0x0f007018,0x01000000}, - {0x0f00701c,0x01020000}, - {0x0f007020,0x04020107}, - {0x0f007024,0x00000007}, - {0x0f007028,0x02020200}, - {0x0f00702c,0x0204040a}, - {0x0f007030,0x04000000}, - {0x0f007034,0x00000002}, - {0x0f007038,0x1d060200}, - {0x0f00703c,0x1c22221d}, - {0x0f007040,0x8A116600}, - {0x0f007044,0x222d0800}, - {0x0f007048,0x02690204}, - {0x0f00704c,0x00000000}, - {0x0f007050,0x0100001c}, - {0x0f007054,0x00000000}, - {0x0f007058,0x00000000}, - {0x0f00705c,0x00000000}, - {0x0f007060,0x000A15D6}, - {0x0f007064,0x0000000A}, - {0x0f007068,0x00000000}, - {0x0f00706c,0x00000001}, - {0x0f007070,0x00004000}, - {0x0f007074,0x00000000}, - {0x0f007078,0x00000000}, - {0x0f00707c,0x00000000}, - {0x0f007080,0x00000000}, - {0x0f007084,0x00000000}, - {0x0f007088,0x01000001}, - {0x0f00708c,0x00000101}, - {0x0f007090,0x00000000}, - {0x0f007094,0x00010000}, - {0x0f007098,0x00000000}, - {0x0F0070C8,0x00000104}, - {0x0F007018,0x01010000} +static struct bcm_ddr_setting asT3LPB_DDRSetting80MHz[] = {// # DPLL Clock Setting + {0x0f000820, 0x07F13FFF}, + {0x0f000810, 0x00002F95}, + {0x0f000860, 0x00000000}, + {0x0f000880, 0x000003DD}, + {0x0f000840, 0x0FFF1F00}, + {0x0F00a044, 0x1fffffff}, + {0x0F00a040, 0x1f000000}, + {0x0f003050, 0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084, 0x1Cffffff},// dump from here in internal memory + {0x0F00a080, 0x1C000000}, + {0x0F00A000, 0x00000016}, + {0x0f007000, 0x00010001}, + {0x0f007004, 0x01000000}, + {0x0f007008, 0x01000001}, + {0x0f00700c, 0x00000000}, + {0x0f007010, 0x01000000}, + {0x0f007014, 0x01000100}, + {0x0f007018, 0x01000000}, + {0x0f00701c, 0x01020000}, + {0x0f007020, 0x04020107}, + {0x0f007024, 0x00000007}, + {0x0f007028, 0x02020200}, + {0x0f00702c, 0x0204040a}, + {0x0f007030, 0x04000000}, + {0x0f007034, 0x00000002}, + {0x0f007038, 0x1d060200}, + {0x0f00703c, 0x1c22221d}, + {0x0f007040, 0x8A116600}, + {0x0f007044, 0x222d0800}, + {0x0f007048, 0x02690204}, + {0x0f00704c, 0x00000000}, + {0x0f007050, 0x0100001c}, + {0x0f007054, 0x00000000}, + {0x0f007058, 0x00000000}, + {0x0f00705c, 0x00000000}, + {0x0f007060, 0x000A15D6}, + {0x0f007064, 0x0000000A}, + {0x0f007068, 0x00000000}, + {0x0f00706c, 0x00000001}, + {0x0f007070, 0x00004000}, + {0x0f007074, 0x00000000}, + {0x0f007078, 0x00000000}, + {0x0f00707c, 0x00000000}, + {0x0f007080, 0x00000000}, + {0x0f007084, 0x00000000}, + {0x0f007088, 0x01000001}, + {0x0f00708c, 0x00000101}, + {0x0f007090, 0x00000000}, + {0x0f007094, 0x00010000}, + {0x0f007098, 0x00000000}, + {0x0F0070C8, 0x00000104}, + {0x0F007018, 0x01010000} }; int ddr_init(struct bcm_mini_adapter *Adapter) { - struct bcm_ddr_setting *psDDRSetting=NULL; - ULONG RegCount=0; + struct bcm_ddr_setting *psDDRSetting = NULL; + ULONG RegCount = 0; UINT value = 0; UINT uiResetValue = 0; UINT uiClockSetting = 0; @@ -787,20 +786,20 @@ int ddr_init(struct bcm_mini_adapter *Adapter) switch (Adapter->DDRSetting) { case DDR_80_MHZ: - psDDRSetting=asT3LP_DDRSetting80MHz; - RegCount=(sizeof(asT3LP_DDRSetting80MHz)/ + psDDRSetting = asT3LP_DDRSetting80MHz; + RegCount = (sizeof(asT3LP_DDRSetting80MHz)/ sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: - psDDRSetting=asT3LP_DDRSetting100MHz; - RegCount=(sizeof(asT3LP_DDRSetting100MHz)/ + psDDRSetting = asT3LP_DDRSetting100MHz; + RegCount = (sizeof(asT3LP_DDRSetting100MHz)/ sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: - psDDRSetting=asT3LP_DDRSetting133MHz; - RegCount=(sizeof(asT3LP_DDRSetting133MHz)/ + psDDRSetting = asT3LP_DDRSetting133MHz; + RegCount = (sizeof(asT3LP_DDRSetting133MHz)/ sizeof(struct bcm_ddr_setting)); - if(Adapter->bMipsConfig == MIPS_200_MHZ) + if (Adapter->bMipsConfig == MIPS_200_MHZ) { uiClockSetting = 0x03F13652; } @@ -818,47 +817,47 @@ int ddr_init(struct bcm_mini_adapter *Adapter) case BCS220_2: case BCS220_2BC: case BCS250_BC: - case BCS220_3 : + case BCS220_3: /* Set bit 2 and bit 6 to 1 for BBIC 2mA drive * (please check current value and additionally set these bits) */ - if( (Adapter->chip_id != BCS220_2) && + if ((Adapter->chip_id != BCS220_2) && (Adapter->chip_id != BCS220_2BC) && - (Adapter->chip_id != BCS220_3) ) + (Adapter->chip_id != BCS220_3)) { - retval= rdmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + retval = rdmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue)); + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue |= 0x44; retval = wrmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } } - switch(Adapter->DDRSetting) + switch (Adapter->DDRSetting) { case DDR_80_MHZ: psDDRSetting = asT3LPB_DDRSetting80MHz; - RegCount=(sizeof(asT3B_DDRSetting80MHz)/ + RegCount = (sizeof(asT3B_DDRSetting80MHz)/ sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: - psDDRSetting=asT3LPB_DDRSetting100MHz; - RegCount=(sizeof(asT3B_DDRSetting100MHz)/ + psDDRSetting = asT3LPB_DDRSetting100MHz; + RegCount = (sizeof(asT3B_DDRSetting100MHz)/ sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: psDDRSetting = asT3LPB_DDRSetting133MHz; - RegCount=(sizeof(asT3B_DDRSetting133MHz)/ + RegCount = (sizeof(asT3B_DDRSetting133MHz)/ sizeof(struct bcm_ddr_setting)); - if(Adapter->bMipsConfig == MIPS_200_MHZ) + if (Adapter->bMipsConfig == MIPS_200_MHZ) { uiClockSetting = 0x03F13652; } @@ -872,7 +871,7 @@ int ddr_init(struct bcm_mini_adapter *Adapter) psDDRSetting = asT3LPB_DDRSetting160MHz; RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(struct bcm_ddr_setting); - if(Adapter->bMipsConfig == MIPS_200_MHZ) + if (Adapter->bMipsConfig == MIPS_200_MHZ) { uiClockSetting = 0x03F137D2; } @@ -915,30 +914,30 @@ int ddr_init(struct bcm_mini_adapter *Adapter) { case DDR_80_MHZ: psDDRSetting = asT3B_DDRSetting80MHz; - RegCount=(sizeof(asT3B_DDRSetting80MHz)/ + RegCount = (sizeof(asT3B_DDRSetting80MHz)/ sizeof(struct bcm_ddr_setting)); break; case DDR_100_MHZ: - psDDRSetting=asT3B_DDRSetting100MHz; - RegCount=(sizeof(asT3B_DDRSetting100MHz)/ + psDDRSetting = asT3B_DDRSetting100MHz; + RegCount = (sizeof(asT3B_DDRSetting100MHz)/ sizeof(struct bcm_ddr_setting)); break; case DDR_133_MHZ: - if(Adapter->bDPLLConfig == PLL_266_MHZ)//266Mhz PLL selected. + if (Adapter->bDPLLConfig == PLL_266_MHZ)//266Mhz PLL selected. { memcpy(asT3B_DDRSetting133MHz, asDPLL_266MHZ, sizeof(asDPLL_266MHZ)); psDDRSetting = asT3B_DDRSetting133MHz; - RegCount=(sizeof(asT3B_DDRSetting133MHz)/ + RegCount = (sizeof(asT3B_DDRSetting133MHz)/ sizeof(struct bcm_ddr_setting)); } else { psDDRSetting = asT3B_DDRSetting133MHz; - RegCount=(sizeof(asT3B_DDRSetting133MHz)/ + RegCount = (sizeof(asT3B_DDRSetting133MHz)/ sizeof(struct bcm_ddr_setting)); - if(Adapter->bMipsConfig == MIPS_200_MHZ) + if (Adapter->bMipsConfig == MIPS_200_MHZ) { uiClockSetting = 0x07F13652; } @@ -958,11 +957,11 @@ int ddr_init(struct bcm_mini_adapter *Adapter) return -EINVAL; } - value=0; + value = 0; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register Count is =%lu\n", RegCount); - while(RegCount && !retval) + while (RegCount && !retval) { - if(uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG) + if (uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG) { value = uiClockSetting; } @@ -971,7 +970,7 @@ int ddr_init(struct bcm_mini_adapter *Adapter) value = psDDRSetting->ulRegValue; } retval = wrmalt(Adapter, psDDRSetting->ulRegAddress, &value, sizeof(value)); - if(STATUS_SUCCESS != retval) { + if (STATUS_SUCCESS != retval) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__); break; } @@ -980,36 +979,36 @@ int ddr_init(struct bcm_mini_adapter *Adapter) psDDRSetting++; } - if(Adapter->chip_id >= 0xbece3300 ) + if (Adapter->chip_id >= 0xbece3300) { mdelay(3); - if( (Adapter->chip_id != BCS220_2)&& - (Adapter->chip_id != BCS220_2BC)&& + if ((Adapter->chip_id != BCS220_2) && + (Adapter->chip_id != BCS220_2BC) && (Adapter->chip_id != BCS220_3)) { /* drive MDDR to half in case of UMA-B: */ uiResetValue = 0x01010001; retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x00040020; retval = wrmalt(Adapter, (UINT)0x0F007094, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x01020101; retval = wrmalt(Adapter, (UINT)0x0F00701c, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x01010000; retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } @@ -1022,73 +1021,73 @@ int ddr_init(struct bcm_mini_adapter *Adapter) * and since we dont have internal PMU lets do it under UMA-B chip id. * we will change this when we will have internal PMU. */ - if(Adapter->PmuMode == HYBRID_MODE_7C) + if (Adapter->PmuMode == HYBRID_MODE_7C) { retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x1322a8; retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x132296; retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } } - else if(Adapter->PmuMode == HYBRID_MODE_6 ) + else if (Adapter->PmuMode == HYBRID_MODE_6) { retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x6003229a; retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } uiResetValue = 0x1322a8; retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue)); - if(retval < 0) { + if (retval < 0) { BCM_DEBUG_PRINT(Adapter, CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __func__, __LINE__); return retval; } @@ -1101,8 +1100,8 @@ int ddr_init(struct bcm_mini_adapter *Adapter) int download_ddr_settings(struct bcm_mini_adapter *Adapter) { - struct bcm_ddr_setting *psDDRSetting=NULL; - ULONG RegCount=0; + struct bcm_ddr_setting *psDDRSetting = NULL; + ULONG RegCount = 0; unsigned long ul_ddr_setting_load_addr = DDR_DUMP_INTERNAL_DEVICE_MEMORY; UINT value = 0; int retval = STATUS_SUCCESS; @@ -1116,20 +1115,20 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) case DDR_80_MHZ: psDDRSetting = asT3LP_DDRSetting80MHz; RegCount = ARRAY_SIZE(asT3LP_DDRSetting80MHz); - RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; break; case DDR_100_MHZ: psDDRSetting = asT3LP_DDRSetting100MHz; RegCount = ARRAY_SIZE(asT3LP_DDRSetting100MHz); - RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; break; case DDR_133_MHZ: bOverrideSelfRefresh = TRUE; psDDRSetting = asT3LP_DDRSetting133MHz; RegCount = ARRAY_SIZE(asT3LP_DDRSetting133MHz); - RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; break; default: @@ -1141,26 +1140,26 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) case BCS220_2: case BCS220_2BC: case BCS250_BC: - case BCS220_3 : + case BCS220_3: switch (Adapter->DDRSetting) { case DDR_80_MHZ: psDDRSetting = asT3LPB_DDRSetting80MHz; - RegCount=ARRAY_SIZE(asT3LPB_DDRSetting80MHz); - RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + RegCount = ARRAY_SIZE(asT3LPB_DDRSetting80MHz); + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; break; case DDR_100_MHZ: psDDRSetting = asT3LPB_DDRSetting100MHz; RegCount = ARRAY_SIZE(asT3LPB_DDRSetting100MHz); - RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; break; case DDR_133_MHZ: bOverrideSelfRefresh = TRUE; psDDRSetting = asT3LPB_DDRSetting133MHz; RegCount = ARRAY_SIZE(asT3LPB_DDRSetting133MHz); - RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; break; @@ -1182,20 +1181,20 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) case DDR_80_MHZ: psDDRSetting = asT3_DDRSetting80MHz; RegCount = ARRAY_SIZE(asT3_DDRSetting80MHz); - RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + RegCount -= T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; break; case DDR_100_MHZ: psDDRSetting = asT3_DDRSetting100MHz; RegCount = ARRAY_SIZE(asT3_DDRSetting100MHz); - RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + RegCount -= T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; break; case DDR_133_MHZ: psDDRSetting = asT3_DDRSetting133MHz; RegCount = ARRAY_SIZE(asT3_DDRSetting133MHz); - RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; - psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + RegCount -= T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; + psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; break; default: return -EINVAL; @@ -1208,20 +1207,20 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) case DDR_80_MHZ: psDDRSetting = asT3B_DDRSetting80MHz; RegCount = ARRAY_SIZE(asT3B_DDRSetting80MHz); - RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; break; case DDR_100_MHZ: psDDRSetting = asT3B_DDRSetting100MHz; RegCount = ARRAY_SIZE(asT3B_DDRSetting100MHz); - RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; break; case DDR_133_MHZ: bOverrideSelfRefresh = TRUE; psDDRSetting = asT3B_DDRSetting133MHz; RegCount = ARRAY_SIZE(asT3B_DDRSetting133MHz); - RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; break; } @@ -1231,9 +1230,9 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) return -EINVAL; } //total number of Register that has to be dumped - value =RegCount ; + value = RegCount; retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); - if(retval) + if (retval) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__); @@ -1241,29 +1240,29 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) } ul_ddr_setting_load_addr += sizeof(ULONG); /*signature */ - value =(0x1d1e0dd0); + value = (0x1d1e0dd0); retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); - if(retval) + if (retval) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__); return retval; } ul_ddr_setting_load_addr += sizeof(ULONG); - RegCount*=(sizeof(struct bcm_ddr_setting)/sizeof(ULONG)); + RegCount *= (sizeof(struct bcm_ddr_setting)/sizeof(ULONG)); - while(RegCount && !retval) + while (RegCount && !retval) { - value = psDDRSetting->ulRegAddress ; - retval = wrmalt( Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); + value = psDDRSetting->ulRegAddress; + retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); ul_ddr_setting_load_addr += sizeof(ULONG); - if(!retval) + if (!retval) { - if(bOverrideSelfRefresh && (psDDRSetting->ulRegAddress == 0x0F007018)) + if (bOverrideSelfRefresh && (psDDRSetting->ulRegAddress == 0x0F007018)) { value = (psDDRSetting->ulRegValue |(1<<8)); - if(STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr, - &value, sizeof(value))){ + if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr, + &value, sizeof(value))) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__); break; } @@ -1272,8 +1271,8 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) { value = psDDRSetting->ulRegValue; - if(STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr , - &value, sizeof(value))){ + if (STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr , + &value, sizeof(value))) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "%s:%d\n", __func__, __LINE__); break; } @@ -1285,5 +1284,3 @@ int download_ddr_settings(struct bcm_mini_adapter *Adapter) } return retval; } - - -- cgit v1.2.3 From 7fae8b0a0b09b59539e8056f943b3cf0c60b738f Mon Sep 17 00:00:00 2001 From: Ingrid Cheung Date: Sat, 9 Nov 2013 20:53:21 -0500 Subject: Staging: bcm: Fix checkpatch warning for long line. Fixed a line that was over 80 characters in Bcmchar.c. Signed-off-by: Ingrid Cheung Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index ed45b2161d49..2cf64df22938 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -160,7 +160,9 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) struct bcm_ioctl_buffer IoBuffer; int bytes; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, + "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", + cmd, arg); if (_IOC_TYPE(cmd) != BCM_IOCTL) return -EFAULT; -- cgit v1.2.3 From 5570de180d4a69f582564db82e89b08bfa09a151 Mon Sep 17 00:00:00 2001 From: Ingrid Cheung Date: Sat, 9 Nov 2013 23:02:50 -0500 Subject: Staging: bcm: Fix checkpatch warnings for long lines. Fixes multiple checkpatch warnings for long lines in Bcmchar.c. Signed-off-by: Ingrid Cheung Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 116 ++++++++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 2cf64df22938..6385b57572fa 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -268,7 +268,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (uiTempVar == EEPROM_REJECT_REG_3) || (uiTempVar == EEPROM_REJECT_REG_4))) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "EEPROM Access Denied, not in VSG Mode\n"); return -EFAULT; } @@ -276,9 +277,11 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (PUINT)sWrmBuffer.Data, sizeof(ULONG)); if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, "WRM Done\n"); } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, "WRM Failed\n"); Status = -EFAULT; } break; @@ -293,7 +296,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "Device in Idle Mode, Blocking Rdms\n"); return -EACCES; } @@ -319,7 +323,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || ((ULONG)sRdmBuffer.Register & 0x3)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "RDM Done On invalid Address : %x Access Denied.\n", (int)sRdmBuffer.Register); kfree(temp_buff); @@ -327,7 +332,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; - bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength); + bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, + (PUINT)temp_buff, IoBuffer.OutputLength); if (bytes > 0) { Status = STATUS_SUCCESS; @@ -351,7 +357,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "Device in Idle Mode, Blocking Wrms\n"); return -EACCES; } @@ -369,7 +376,9 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || ((ULONG)sWrmBuffer.Register & 0x3)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "WRM Done On invalid Address : %x Access Denied.\n", + (int)sWrmBuffer.Register); return -EINVAL; } @@ -381,17 +390,21 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (uiTempVar == EEPROM_REJECT_REG_4)) && (cmd == IOCTL_BCM_REGISTER_WRITE)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "EEPROM Access Denied, not in VSG Mode\n"); return -EFAULT; } Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, - (PUINT)sWrmBuffer.Data, sWrmBuffer.Length); + (PUINT)sWrmBuffer.Data, + sWrmBuffer.Length); if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, + DBG_LVL_ALL, "WRM Done\n"); } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, "WRM Failed\n"); Status = -EFAULT; } break; @@ -407,7 +420,9 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, + "GPIO Can't be set/clear in Low power Mode"); return -EACCES; } @@ -425,7 +440,10 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) value = (1< is not correspond to LED !!!", value); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, + "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!", + value); Status = -EINVAL; break; } @@ -433,27 +451,42 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) /* Set - setting 1 */ if (uiOperation) { /* Set the gpio output register */ - Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, (PUINT)(&value), sizeof(UINT)); + Status = wrmaltWithLock(Adapter, + BCM_GPIO_OUTPUT_SET_REG, + (PUINT)(&value), sizeof(UINT)); if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, + OSAL_DBG, DBG_LVL_ALL, + "Set the GPIO bit\n"); } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to set the %dth GPIO\n", uiBit); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, + OSAL_DBG, DBG_LVL_ALL, + "Failed to set the %dth GPIO\n", + uiBit); break; } } else { /* Set the gpio output register */ - Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)(&value), sizeof(UINT)); + Status = wrmaltWithLock(Adapter, + BCM_GPIO_OUTPUT_CLR_REG, + (PUINT)(&value), sizeof(UINT)); if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, + OSAL_DBG, DBG_LVL_ALL, + "Set the GPIO bit\n"); } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to clear the %dth GPIO\n", uiBit); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, + OSAL_DBG, DBG_LVL_ALL, + "Failed to clear the %dth GPIO\n", + uiBit); break; } } - bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); + bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, + (PUINT)ucResetValue, sizeof(UINT)); if (bytes < 0) { Status = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, @@ -469,9 +502,13 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (PUINT)ucResetValue, sizeof(UINT)); if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO to output Mode\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, + "Set the GPIO to output Mode\n"); } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, + "Failed to put GPIO in Output Mode\n"); break; } } @@ -479,13 +516,16 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case BCM_LED_THREAD_STATE_CHANGE_REQ: { struct bcm_user_thread_req threadReq = {0}; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, + "User made LED thread InActive"); if ((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus == TRUE) || (Adapter->bPreparingForLowPowerMode == TRUE)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, + "GPIO Can't be set/clear in Low power Mode"); Status = -EACCES; break; } @@ -502,10 +542,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) /* if LED thread is running(Actively or Inactively) set it state to make inactive */ if (Adapter->LEDInfo.led_thread_running) { if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Activating thread req"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, + OSAL_DBG, DBG_LVL_ALL, + "Activating thread req"); Adapter->DriverState = LED_THREAD_ACTIVE; } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DeActivating Thread req....."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, + OSAL_DBG, DBG_LVL_ALL, + "DeActivating Thread req....."); Adapter->DriverState = LED_THREAD_INACTIVE; } @@ -542,7 +586,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (bytes < 0) { Status = bytes; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "RDM Failed\n"); return Status; } else { Status = STATUS_SUCCESS; @@ -572,9 +617,11 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) return -EFAULT; if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == false) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, + DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!", - pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap); + pgpio_multi_info[WIMAX_IDX].uiGPIOMask, + Adapter->gpioBitMap); Status = -EINVAL; break; } @@ -592,7 +639,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (PUINT)ucResetValue, sizeof(ULONG)); if (Status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); return Status; } @@ -605,7 +653,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG)); if (Status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed."); return Status; } } @@ -615,7 +664,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (bytes < 0) { Status = bytes; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "RDM to GPIO_PIN_STATE_REGISTER Failed."); return Status; } else { Status = STATUS_SUCCESS; -- cgit v1.2.3 From 8bf961c8c2e3a5c8f0148a49cccda866f166e060 Mon Sep 17 00:00:00 2001 From: Ebru Akagunduz Date: Fri, 1 Nov 2013 19:00:38 +0200 Subject: Staging: media: fix space prohibited before semicolon Fix checkpatch.pl issues with space prohibited before semicolon in dm365_ipipe.c Signed-off-by: Ebru Akagunduz Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/davinci_vpfe/dm365_ipipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 766a071b0a22..b7044a380fe3 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -1009,7 +1009,7 @@ static int ipipe_validate_yee_params(struct vpfe_ipipe_yee *yee) yee->es_ofst_grad > YEE_THR_MASK) return -EINVAL; - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_YEE_LUT ; i++) + for (i = 0; i < VPFE_IPIPE_MAX_SIZE_YEE_LUT; i++) if (yee->table[i] > YEE_ENTRY_MASK) return -EINVAL; -- cgit v1.2.3 From 5c72afd8f49b0b7c1a8fce7930c94e9ba7eef855 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 17:50:56 +0530 Subject: staging:media:go7007:go7007-fw.c: move trailing statement to next line This patch removes the checkpatch.pl error "trailing statements should be on next line" in go7007-fw.c. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/go7007/go7007-fw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/staging/media/go7007/go7007-fw.c index c2d0e58afc34..479953b2d983 100644 --- a/drivers/staging/media/go7007/go7007-fw.c +++ b/drivers/staging/media/go7007/go7007-fw.c @@ -722,7 +722,8 @@ static int vti_bitlen(struct go7007 *go) { unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale; - for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i); + for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i) + ; return i + 1; } -- cgit v1.2.3 From 432b29c4175b7e3895760a7180ec13a687cca839 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 22:42:22 +0530 Subject: staging:media:go7007:saa7134-go7007.c: Remove space before tabs This patch removes the checkpatch.pl warning "please, no space before tabs" in saa7134-go7007.c by converting space followed by tab to tab followed by tab. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/go7007/saa7134-go7007.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/go7007/saa7134-go7007.c b/drivers/staging/media/go7007/saa7134-go7007.c index d80b235d72ee..6e2ca338cdd9 100644 --- a/drivers/staging/media/go7007/saa7134-go7007.c +++ b/drivers/staging/media/go7007/saa7134-go7007.c @@ -86,7 +86,7 @@ static const struct go7007_board_info board_voyager = { .audio_main_div = 2, .hpi_buffer_cap = 7, .num_inputs = 1, - .inputs = { + .inputs = { { .name = "SAA7134", }, -- cgit v1.2.3 From 430dfd55eea22bff4b3a6b0f5de933af4a2a011d Mon Sep 17 00:00:00 2001 From: Archana kumari Date: Sun, 3 Nov 2013 11:51:31 +0530 Subject: staging: media: davinci_vpfe:Removed space before semicolon in dm365_ipipe_hw.c This patch fixes "space prohibted before semicolon" warning in dm365_ipipe_hw.cdetected via checkpatch.pl Signed-off-by: Archana kumari Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c index e027b92b54ef..2d36b60bdbf1 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c @@ -791,7 +791,7 @@ ipipe_set_3d_lut_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, /* valied table */ tbl = lut_3d->table; - for (i = 0 ; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) { + for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) { /* Each entry has 0-9 (B), 10-19 (G) and 20-29 R values */ val = tbl[i].b & D3_LUT_ENTRY_MASK; @@ -899,7 +899,7 @@ ipipe_set_gbce_regs(void *__iomem base_addr, void *__iomem isp5_base_addr, if (!gbce->table) return; - for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT ; count += 2) + for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2) w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) << GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask), ((count/2) << 2) + GBCE_TB_START_ADDR); -- cgit v1.2.3 From bb1da756e03c7929bf8b101788588a88aaadb523 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 18:02:38 +0530 Subject: staging:wlan-ng:cfg80211.c: Shorten lines to 80 characters This patch removes checkpatch.pl warnings "line over 80 characters" in cfg80211.c. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index a4fd5c4717a8..a7d24c95191d 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -73,7 +73,8 @@ static int prism2_result2err(int prism2_result) static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; - p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + p80211item_uint32_t *mibitem = + (p80211item_uint32_t *) &msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; @@ -86,7 +87,8 @@ static int prism2_domibset_pstr32(wlandevice_t *wlandev, u32 did, u8 len, u8 *data) { struct p80211msg_dot11req_mibset msg; - p80211item_pstr32_t *mibitem = (p80211item_pstr32_t *) &msg.mibattribute.data; + p80211item_pstr32_t *mibitem = + (p80211item_pstr32_t *) &msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; @@ -182,7 +184,8 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, goto exit; } - result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key); + result = prism2_domibset_pstr32(wlandev, did, + params->key_len, params->key); if (result) goto exit; break; @@ -328,7 +331,8 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, return result; } -static int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +static int prism2_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) { struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); @@ -380,7 +384,8 @@ static int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *reques (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels); i++) msg1.channellist.data.data[i] = - ieee80211_frequency_to_channel(request->channels[i]->center_freq); + ieee80211_frequency_to_channel( + request->channels[i]->center_freq); msg1.channellist.data.len = request->n_channels; msg1.maxchanneltime.data = 250; @@ -410,7 +415,8 @@ static int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *reques ie_len = ie_buf[1] + 2; memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); bss = cfg80211_inform_bss(wiphy, - ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)), + ieee80211_get_channel(wiphy, + ieee80211_dsss_chan_to_freq(msg2.dschannel.data)), (const u8 *) &(msg2.bssid.data.data), msg2.timestamp.data, msg2.capinfo.data, msg2.beaconperiod.data, -- cgit v1.2.3 From b21199116a0ed9a27326b0cb85b1cdcc3997b879 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 18:11:44 +0530 Subject: staging:wlan-ng:hfa384x.h: remove typedef struct hfa384x_bytestr __packed hfa384x_bytestr_t This patch removes the checkpatch.pl warning "do not add new typedefs" and changes all source files that use that typedef. Also lines were shortened to 80 characters to do away with the checkpatch.pl warning "line over 80 characters" generated due to replacement of the hfa384x_bytestr_t by struct hfa384x_bytestr in prism2mgmt.c, prism2mgmt.h, prism2mib.c, prism2sta.c. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 4 ++-- drivers/staging/wlan-ng/prism2mgmt.c | 4 ++-- drivers/staging/wlan-ng/prism2mgmt.h | 6 ++++-- drivers/staging/wlan-ng/prism2mib.c | 6 ++++-- drivers/staging/wlan-ng/prism2sta.c | 6 +++--- 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 3dfa85ccc504..333a2f693e49 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -350,10 +350,10 @@ PD Record codes /*-------------------------------------------------------------*/ /* Commonly used basic types */ -typedef struct hfa384x_bytestr { +struct hfa384x_bytestr { u16 len; u8 data[0]; -} __packed hfa384x_bytestr_t; +} __packed; typedef struct hfa384x_bytestr32 { u16 len; diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index d22db43e8031..a9909f6b0001 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -525,7 +525,7 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) p80211pstrd_t *pstr; u8 bytebuf[80]; - hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; + struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf; u16 word; wlandev->macmode = WLAN_MACMODE_NONE; @@ -1019,7 +1019,7 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) struct p80211msg_lnxreq_autojoin *msg = msgp; p80211pstrd_t *pstr; u8 bytebuf[256]; - hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; + struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf; wlandev->macmode = WLAN_MACMODE_NONE; diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index 07eecebeb6cc..190d390c8490 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -92,8 +92,10 @@ void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr); void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len); /* byte string conversion functions*/ -void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); -void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); +void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, + p80211pstrd_t *pstr); +void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, + p80211pstrd_t *pstr); /* functions to convert Group Addresses */ void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t *pstr, hfa384x_t *priv); diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index d3a06fa0b4f6..9b5f3b72d3ca 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -763,7 +763,8 @@ static int prism2mib_priv(struct mibrec *mib, * ----------------------------------------------------------------*/ -void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) +void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, + p80211pstrd_t *pstr) { bytestr->len = cpu_to_le16((u16) (pstr->len)); memcpy(bytestr->data, pstr->data, pstr->len); @@ -804,7 +805,8 @@ void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr) * ----------------------------------------------------------------*/ -void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) +void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, + p80211pstrd_t *pstr) { pstr->len = (u8) (le16_to_cpu((u16) (bytestr->len))); memcpy(pstr->data, bytestr->data, pstr->len); diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 76374b220228..46f9491d10d3 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1279,7 +1279,7 @@ void prism2sta_processing_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid, + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, (p80211pstrd_t *) & wlandev->ssid); @@ -1361,7 +1361,7 @@ void prism2sta_processing_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid, + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, (p80211pstrd_t *) &wlandev->ssid); hw->link_status = HFA384x_LINK_CONNECTED; @@ -2037,7 +2037,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid, + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, (p80211pstrd_t *) &wlandev->ssid); /* Reschedule timer */ -- cgit v1.2.3 From 5fb4471ef3363bb512ad1a97292e9a321c065eac Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 17:31:22 +0530 Subject: staging:usbip:stub_rx.c: Remove warning quoted string split across lines This patch removes the checkpatch.pl warnings "quoted string split across lines" in stub_rx.c by merging the quoted strings and the ensuring that the lines are not more than 80 characters long. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub_rx.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index db48a789d308..5d1d4a183300 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -102,11 +102,13 @@ static int tweak_clear_halt_cmd(struct urb *urb) ret = usb_clear_halt(urb->dev, target_pipe); if (ret < 0) - dev_err(&urb->dev->dev, "usb_clear_halt error: devnum %d endp " - "%d ret %d\n", urb->dev->devnum, target_endp, ret); + dev_err(&urb->dev->dev, + "usb_clear_halt error: devnum %d endp %d ret %d\n", + urb->dev->devnum, target_endp, ret); else - dev_info(&urb->dev->dev, "usb_clear_halt done: devnum %d endp " - "%d\n", urb->dev->devnum, target_endp); + dev_info(&urb->dev->dev, + "usb_clear_halt done: devnum %d endp %d\n", + urb->dev->devnum, target_endp); return ret; } @@ -127,11 +129,13 @@ static int tweak_set_interface_cmd(struct urb *urb) ret = usb_set_interface(urb->dev, interface, alternate); if (ret < 0) - dev_err(&urb->dev->dev, "usb_set_interface error: inf %u alt " - "%u ret %d\n", interface, alternate, ret); + dev_err(&urb->dev->dev, + "usb_set_interface error: inf %u alt %u ret %d\n", + interface, alternate, ret); else - dev_info(&urb->dev->dev, "usb_set_interface done: inf %u alt " - "%u\n", interface, alternate); + dev_info(&urb->dev->dev, + "usb_set_interface done: inf %u alt %u\n", + interface, alternate); return ret; } -- cgit v1.2.3 From b482da2b98a3a716d823995b0678405ff398c0c3 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 17:38:10 +0530 Subject: staging:usbip:usbip_common.c: Join quoted string split accross lines This patch removes the checkpatch.pl warnings "quoted string split accross lines" in usbip_common.c. Signed-off-by: Himangi Saraogi Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/usbip_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index e3fc749c1e7e..4470cd321d65 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -155,8 +155,9 @@ static void usbip_dump_usb_device(struct usb_device *udev) dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus); - dev_dbg(dev, "descriptor %p, config %p, actconfig %p, " - "rawdescriptors %p\n", &udev->descriptor, udev->config, + dev_dbg(dev, + "descriptor %p, config %p, actconfig %p, rawdescriptors %p\n", + &udev->descriptor, udev->config, udev->actconfig, udev->rawdescriptors); dev_dbg(dev, "have_langid %d, string_langid %d\n", -- cgit v1.2.3 From d0306a514da25976fde942d21f85b12384dd4c1f Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 4 Nov 2013 13:12:12 +0200 Subject: staging: usbip: fix sparse warnings regarding endianness The wHubCharacteristics field in usb_hub_descriptor structure is __le16 so there is no need for cast. The cpu_to_le16 returns a __le16 type for a u16 type. Used cpu_to_le16 to silence last sparse error. drivers/staging/usbip/vhci_hcd.c:223:35: warning: incorrect type in assignment (different base types) drivers/staging/usbip/vhci_hcd.c:223:35: expected restricted __le16 [usertype] wHubCharacteristics drivers/staging/usbip/vhci_hcd.c:223:35: got unsigned short [unsigned] [usertype] drivers/staging/usbip/vhci_hcd.c:351:34: warning: incorrect type in assignment (different base types) drivers/staging/usbip/vhci_hcd.c:351:34: expected unsigned short [unsigned] [short] [usertype] drivers/staging/usbip/vhci_hcd.c:351:34: got restricted __le16 [usertype] drivers/staging/usbip/vhci_hcd.c:352:34: warning: incorrect type in assignment (different base types) drivers/staging/usbip/vhci_hcd.c:352:34: expected unsigned short [unsigned] [short] [usertype] drivers/staging/usbip/vhci_hcd.c:352:34: got restricted __le16 [usertype] drivers/staging/usbip/vhci_hcd.c:540:36: warning: restricted __le16 degrades to integer Signed-off-by: Teodora Baluta Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_hcd.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index e810ad53e2ac..e37c6c1a9931 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -220,8 +220,7 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc) memset(desc, 0, sizeof(*desc)); desc->bDescriptorType = 0x29; desc->bDescLength = 9; - desc->wHubCharacteristics = (__force __u16) - (__constant_cpu_to_le16(0x0001)); + desc->wHubCharacteristics = (__constant_cpu_to_le16(0x0001)); desc->bNbrPorts = VHCI_NPORTS; desc->u.hs.DeviceRemovable[0] = 0xff; desc->u.hs.DeviceRemovable[1] = 0xff; @@ -348,8 +347,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, USB_PORT_STAT_ENABLE; } } - ((u16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]); - ((u16 *) buf)[1] = cpu_to_le16(dum->port_status[rhport] >> 16); + ((__le16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]); + ((__le16 *) buf)[1] = cpu_to_le16(dum->port_status[rhport] >> 16); usbip_dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0], ((u16 *)buf)[1]); @@ -537,7 +536,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, goto no_need_xmit; case USB_REQ_GET_DESCRIPTOR: - if (ctrlreq->wValue == (USB_DT_DEVICE << 8)) + if (ctrlreq->wValue == cpu_to_le16(USB_DT_DEVICE << 8)) usbip_dbg_vhci_hc("Not yet?: " "Get_Descriptor to device 0 " "(get max pipe size)\n"); -- cgit v1.2.3 From 1f5a0d0cd43f2a02af16a1c23fba8ae14f707d49 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:34:44 +0530 Subject: Staging: rtl8192e: Fix incorrect type in assignment in rtllib_rx.c This patch fixes the following Sparse warning in rtllib_rx.c- drivers/staging/rtl8192e/rtllib_rx.c:493:37: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_rx.c:493:37: expected unsigned short [unsigned] [usertype] len drivers/staging/rtl8192e/rtllib_rx.c:493:37: got restricted __be16 [usertype] drivers/staging/rtl8192e/rtllib_rx.c:1227:37: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_rx.c:1227:37: expected unsigned short [unsigned] [usertype] len drivers/staging/rtl8192e/rtllib_rx.c:1227:37: got restricted __be16 [usertype] drivers/staging/rtl8192e/rtllib_rx.c:1635:40: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_rx.c:1635:40: expected restricted __le16 drivers/staging/rtl8192e/rtllib_rx.c:1635:40: got int drivers/staging/rtl8192e/rtllib_rx.c:1637:40: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_rx.c:1637:40: expected restricted __le16 drivers/staging/rtl8192e/rtllib_rx.c:1637:40: got int drivers/staging/rtl8192e/rtllib_rx.c:1641:45: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_rx.c:1641:45: expected restricted __le16 drivers/staging/rtl8192e/rtllib_rx.c:1641:45: got unsigned short [unsigned] [usertype] Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 1a011b9b9da6..6aa837e1c512 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -490,7 +490,7 @@ void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb **prx } else { u16 len; /* Leave Ethernet header part of hdr and full payload */ - len = htons(sub_skb->len); + len = sub_skb->len; memcpy(skb_push(sub_skb, 2), &len, 2); memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); @@ -1224,7 +1224,7 @@ static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee, } else { u16 len; /* Leave Ethernet header part of hdr and full payload */ - len = htons(sub_skb->len); + len = sub_skb->len; memcpy(skb_push(sub_skb, 2), &len, 2); memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); @@ -1632,13 +1632,13 @@ static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci]; - qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F; + qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F); - qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4; + qos_param->cw_max[aci] = cpu_to_le16((ac_params->ecw_min_max & 0xF0) >> 4); qos_param->flag[aci] = (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00; - qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit); + qos_param->tx_op_limit[aci] = ac_params->tx_op_limit; } return rc; } -- cgit v1.2.3 From 26a6b074971cfb8568e2bf1f972c6f7c10c2c749 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:36:12 +0530 Subject: Staging: rtl8192e: Fix Sparse warning of restricted __le16 degrades to integer in rtllib_rx.c This patch fixes the following sparse warning in rtllib_rx.c- warning: restricted __le16 degrades to integer Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 58 ++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 6aa837e1c512..6b46af596b35 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -2528,29 +2528,30 @@ static inline void rtllib_process_probe_response( "'%s' ( %pM ): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", escape_essid(info_element->data, info_element->len), beacon->header.addr3, - (beacon->capability & (1<<0xf)) ? '1' : '0', - (beacon->capability & (1<<0xe)) ? '1' : '0', - (beacon->capability & (1<<0xd)) ? '1' : '0', - (beacon->capability & (1<<0xc)) ? '1' : '0', - (beacon->capability & (1<<0xb)) ? '1' : '0', - (beacon->capability & (1<<0xa)) ? '1' : '0', - (beacon->capability & (1<<0x9)) ? '1' : '0', - (beacon->capability & (1<<0x8)) ? '1' : '0', - (beacon->capability & (1<<0x7)) ? '1' : '0', - (beacon->capability & (1<<0x6)) ? '1' : '0', - (beacon->capability & (1<<0x5)) ? '1' : '0', - (beacon->capability & (1<<0x4)) ? '1' : '0', - (beacon->capability & (1<<0x3)) ? '1' : '0', - (beacon->capability & (1<<0x2)) ? '1' : '0', - (beacon->capability & (1<<0x1)) ? '1' : '0', - (beacon->capability & (1<<0x0)) ? '1' : '0'); + (le16_to_cpu(beacon->capability) & (1<<0xf)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0xe)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0xd)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0xc)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0xb)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0xa)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x9)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x8)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x7)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x6)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x5)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x4)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x3)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x2)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x1)) ? '1' : '0', + (le16_to_cpu(beacon->capability) & (1<<0x0)) ? '1' : '0'); if (rtllib_network_init(ieee, beacon, network, stats)) { RTLLIB_DEBUG_SCAN("Dropped '%s' ( %pM) via %s.\n", escape_essid(info_element->data, info_element->len), beacon->header.addr3, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + WLAN_FC_GET_STYPE( + le16_to_cpu(beacon->header.frame_ctl)) == RTLLIB_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); goto free_network; @@ -2560,7 +2561,7 @@ static inline void rtllib_process_probe_response( if (!rtllib_legal_channel(ieee, network->channel)) goto free_network; - if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) == RTLLIB_STYPE_PROBE_RESP) { if (IsPassiveChannel(ieee, network->channel)) { printk(KERN_INFO "GetScanInfo(): For Global Domain, " @@ -2629,7 +2630,8 @@ static inline void rtllib_process_probe_response( RTLLIB_DEBUG_SCAN("Adding '%s' ( %pM) via %s.\n", escape_essid(network->ssid, network->ssid_len), network->bssid, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + WLAN_FC_GET_STYPE( + le16_to_cpu(beacon->header.frame_ctl)) == RTLLIB_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); memcpy(target, network, sizeof(*target)); @@ -2640,7 +2642,8 @@ static inline void rtllib_process_probe_response( RTLLIB_DEBUG_SCAN("Updating '%s' ( %pM) via %s.\n", escape_essid(target->ssid, target->ssid_len), target->bssid, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + WLAN_FC_GET_STYPE( + le16_to_cpu(beacon->header.frame_ctl)) == RTLLIB_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); @@ -2682,15 +2685,17 @@ void rtllib_rx_mgt(struct rtllib_device *ieee, { struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data ; - if (WLAN_FC_GET_STYPE(header->frame_ctl) != RTLLIB_STYPE_PROBE_RESP && - WLAN_FC_GET_STYPE(header->frame_ctl) != RTLLIB_STYPE_BEACON) + if ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) != + RTLLIB_STYPE_PROBE_RESP) && + (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) != + RTLLIB_STYPE_BEACON)) ieee->last_rx_ps_time = jiffies; - switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) { case RTLLIB_STYPE_BEACON: RTLLIB_DEBUG_MGMT("received BEACON (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); + WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))); RTLLIB_DEBUG_SCAN("Beacon\n"); rtllib_process_probe_response( ieee, (struct rtllib_probe_response *)header, @@ -2705,14 +2710,15 @@ void rtllib_rx_mgt(struct rtllib_device *ieee, case RTLLIB_STYPE_PROBE_RESP: RTLLIB_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); + WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))); RTLLIB_DEBUG_SCAN("Probe response\n"); rtllib_process_probe_response(ieee, (struct rtllib_probe_response *)header, stats); break; case RTLLIB_STYPE_PROBE_REQ: RTLLIB_DEBUG_MGMT("received PROBE RESQUEST (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); + WLAN_FC_GET_STYPE( + le16_to_cpu(header->frame_ctl))); RTLLIB_DEBUG_SCAN("Probe request\n"); if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && ((ieee->iw_mode == IW_MODE_ADHOC || -- cgit v1.2.3 From e0b1ca6055d454d7f4c1fa9c7db5bf5da5a8a885 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:37:04 +0530 Subject: Staging: rtl8192e: Fix incorrect casting in rtllib_rx.c This patch fixes the following sparse warning in rtllib_rx.c- drivers/staging/rtl8192e/rtllib_rx.c:2267:34: warning: cast to restricted __le32 drivers/staging/rtl8192e/rtllib_rx.c:2268:34: warning: cast to restricted __le32 drivers/staging/rtl8192e/rtllib_rx.c:2269:36: warning: cast to restricted __le32 drivers/staging/rtl8192e/rtllib_rx.c:2269:36: warning: cast from restricted __le16 Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 6b46af596b35..1fab69d313ba 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -2260,9 +2260,9 @@ static inline int rtllib_network_init( memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); network->capability = le16_to_cpu(beacon->capability); network->last_scanned = jiffies; - network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); - network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); - network->beacon_interval = le32_to_cpu(beacon->beacon_interval); + network->time_stamp[0] = beacon->time_stamp[0]; + network->time_stamp[1] = beacon->time_stamp[1]; + network->beacon_interval = le16_to_cpu(beacon->beacon_interval); /* Where to pull this? beacon->listen_interval;*/ network->listen_interval = 0x0A; network->rates_len = network->rates_ex_len = 0; -- cgit v1.2.3 From cf8ab8cf9952ac26e8401eced227b6f988703480 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:38:00 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning for Static Declarations in rtllib_module.c This patch fixes the following sparse warning in rtllib_module.c- drivers/staging/rtl8192e/rtllib_module.c:240:12: warning: symbol 'rtllib_init' was not declared. Should it be static? drivers/staging/rtl8192e/rtllib_module.c:260:13: warning: symbol 'rtllib_exit' was not declared. Should it be static? Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index 51d46e04d3f5..136909eff6d5 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -237,7 +237,7 @@ static const struct file_operations fops = { .release = single_release, }; -int __init rtllib_init(void) +static int __init rtllib_init(void) { struct proc_dir_entry *e; @@ -257,7 +257,7 @@ int __init rtllib_init(void) return 0; } -void __exit rtllib_exit(void) +static void __exit rtllib_exit(void) { if (rtllib_proc) { remove_proc_entry("debug_level", rtllib_proc); -- cgit v1.2.3 From 198e0d17c2f8081a8a1bb75d6047c7c89326fc66 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:39:22 +0530 Subject: Staging: rtl8192e: Fix incorrect type in assignment in rtllib_tx.c This patch fixes the following sparse warning in rtllib_tx.c- drivers/staging/rtl8192e/rtllib_tx.c:234:24: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_tx.c:234:24: expected restricted __le16 [usertype] frag_size drivers/staging/rtl8192e/rtllib_tx.c:234:24: got int [signed] txb_size drivers/staging/rtl8192e/rtllib_tx.c:613:43: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_tx.c:613:43: expected restricted __le16 [usertype] payload_size drivers/staging/rtl8192e/rtllib_tx.c:613:43: got unsigned int [unsigned] len drivers/staging/rtl8192e/rtllib_tx.c:767:35: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_tx.c:767:35: expected restricted __le16 [usertype] payload_size drivers/staging/rtl8192e/rtllib_tx.c:767:35: got int [signed] [assigned] bytes drivers/staging/rtl8192e/rtllib_tx.c:814:51: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_tx.c:814:51: expected restricted __le16 [usertype] seq_ctl drivers/staging/rtl8192e/rtllib_tx.c:814:51: got unsigned short drivers/staging/rtl8192e/rtllib_tx.c:174:36: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_tx.c:174:36: expected unsigned short [unsigned] [short] [usertype] drivers/staging/rtl8192e/rtllib_tx.c:174:36: got restricted __be16 [usertype] drivers/staging/rtl8192e/rtllib_tx.c:873:35: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_tx.c:873:35: expected restricted __le16 [usertype] payload_size drivers/staging/rtl8192e/rtllib_tx.c:873:35: got unsigned int [unsigned] len Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_tx.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 3183627823fb..8ff03f8675e8 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -171,7 +171,7 @@ inline int rtllib_put_snap(u8 *data, u16 h_proto) snap->oui[1] = oui[1]; snap->oui[2] = oui[2]; - *(u16 *)(data + SNAP_SIZE) = htons(h_proto); + *(u16 *)(data + SNAP_SIZE) = h_proto; return SNAP_SIZE + sizeof(u16); } @@ -231,7 +231,7 @@ static struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size, memset(txb, 0, sizeof(struct rtllib_txb)); txb->nr_frags = nr_frags; - txb->frag_size = txb_size; + txb->frag_size = cpu_to_le16(txb_size); for (i = 0; i < nr_frags; i++) { txb->fragments[i] = dev_alloc_skb(txb_size); @@ -610,7 +610,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) } txb->encrypted = 0; - txb->payload_size = skb->len; + txb->payload_size = cpu_to_le16(skb->len); memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len); @@ -764,7 +764,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) goto failed; } txb->encrypted = encrypt; - txb->payload_size = bytes; + txb->payload_size = cpu_to_le16(bytes); if (qos_actived) txb->queue_index = UP2AC(skb->priority); @@ -812,8 +812,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) } if ((qos_actived) && (!bIsMulticast)) { frag_hdr->seq_ctl = - rtllib_query_seqnum(ieee, skb_frag, - header.addr1); + cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag, + header.addr1)); frag_hdr->seq_ctl = cpu_to_le16(frag_hdr->seq_ctl<<4 | i); } else { @@ -870,7 +870,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) } txb->encrypted = 0; - txb->payload_size = skb->len; + txb->payload_size = cpu_to_le16(skb->len); memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len); } -- cgit v1.2.3 From 86005e169b35b3d276ff094c6142528acc1f0437 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 2 Nov 2013 23:40:15 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning of restricted __le16 degrades to integer in rtllib_tx.c This patch fixes the following sparse warning in rtllib_tx.c- warning: restricted __le16 degrades to integer Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 8ff03f8675e8..77964885b3f2 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -815,7 +815,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag, header.addr1)); frag_hdr->seq_ctl = - cpu_to_le16(frag_hdr->seq_ctl<<4 | i); + cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctl)<<4 | i); } else { frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); -- cgit v1.2.3 From f7df1918b5f4fe140baf1eda68ff0853774bbcd6 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 18:56:28 +0530 Subject: Staging: rtl8192e: Fix Sparse warning of restricted __le16 degrades to integer in rtllib_softmac.c This patch fixes the following Sparse warning in rtllib_softmac.c- drivers/staging/rtl8192e/rtllib_softmac.c:230:19: warning: restricted __le16 degrades to integer Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 933bd6deaca1..0ad159f52d4c 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -227,7 +227,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) /* called with 2nd param 0, no mgmt lock required */ rtllib_sta_wakeup(ieee, 0); - if (header->frame_ctl == RTLLIB_STYPE_BEACON) + if (le16_to_cpu(header->frame_ctl) == RTLLIB_STYPE_BEACON) tcb_desc->queue_index = BEACON_QUEUE; else tcb_desc->queue_index = MGNT_QUEUE; -- cgit v1.2.3 From 7fe30a7d4af6a0cce07b6ca9dd2a624eead661d2 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 18:57:37 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning of invalid assignment '|=' in rtllib_softmac.c This patch fixes the following Sparse warning in rtllib_softmac.c- drivers/staging/rtl8192e/rtllib_softmac.c:812:40: warning: invalid assignment: |= drivers/staging/rtl8192e/rtllib_softmac.c:812:40: left side has type restricted __le16 drivers/staging/rtl8192e/rtllib_softmac.c:812:40: right side has type int drivers/staging/rtl8192e/rtllib_softmac.c:924:17: warning: invalid assignment: |= drivers/staging/rtl8192e/rtllib_softmac.c:924:17: left side has type restricted __le16 drivers/staging/rtl8192e/rtllib_softmac.c:924:17: right side has type int drivers/staging/rtl8192e/rtllib_softmac.c:924:17: error: cast from unknown type Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 0ad159f52d4c..721ee254b820 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -809,7 +809,7 @@ inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, auth->header.frame_ctl = RTLLIB_STYPE_AUTH; if (challengelen) - auth->header.frame_ctl |= RTLLIB_FCTL_WEP; + auth->header.frame_ctl |= cpu_to_le16(RTLLIB_FCTL_WEP); auth->header.duration_id = 0x013a; memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); @@ -921,8 +921,8 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest) if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) - cpu_to_le16((beacon_buf->capability |= - WLAN_CAPABILITY_SHORT_SLOT_TIME)); + beacon_buf->capability |= + cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; if (encrypt) -- cgit v1.2.3 From 1830a6d840d7bcc9fa3e4ad07b405e3432cc5282 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 18:58:57 +0530 Subject: Staging: rtl8192e: Fix incorrect type in assignment in rtllib_softmac.c This patch fixes the following Sparse warning in rtllib_softmac.c- drivers/staging/rtl8192e/rtllib_softmac.c:298:12: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:298:12: expected unsigned short [unsigned] [usertype] fc drivers/staging/rtl8192e/rtllib_softmac.c:298:12: got restricted __le16 [usertype] frame_ctl drivers/staging/rtl8192e/rtllib_softmac.c:810:32: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:810:32: expected restricted __le16 [usertype] frame_ctl drivers/staging/rtl8192e/rtllib_softmac.c:810:32: got int drivers/staging/rtl8192e/rtllib_softmac.c:814:34: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:814:34: expected restricted __le16 [usertype] duration_id drivers/staging/rtl8192e/rtllib_softmac.c:814:34: got int drivers/staging/rtl8192e/rtllib_softmac.c:821:33: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:821:33: expected restricted __le16 [usertype] algorithm drivers/staging/rtl8192e/rtllib_softmac.c:821:33: got int drivers/staging/rtl8192e/rtllib_softmac.c:955:24: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:955:24: expected unsigned short [unsigned] [usertype] val16 drivers/staging/rtl8192e/rtllib_softmac.c:955:24: got restricted __le16 [usertype] drivers/staging/rtl8192e/rtllib_softmac.c:1263:33: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:1263:33: expected restricted __le16 [usertype] duration_id drivers/staging/rtl8192e/rtllib_softmac.c:1263:33: got int drivers/staging/rtl8192e/rtllib_softmac.c:1282:30: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtllib_softmac.c:1282:30: expected restricted __le16 [usertype] listen_interval drivers/staging/rtl8192e/rtllib_softmac.c:1282:30: got unsigned short [unsigned] [usertype] listen_interval Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 721ee254b820..31cb858d978e 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -295,7 +295,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, u16 fc, type, stype; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8); - fc = header->frame_ctl; + fc = le16_to_cpu(header->frame_ctl); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); @@ -807,18 +807,18 @@ inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, auth = (struct rtllib_authentication *) skb_put(skb, sizeof(struct rtllib_authentication)); - auth->header.frame_ctl = RTLLIB_STYPE_AUTH; + auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH); if (challengelen) auth->header.frame_ctl |= cpu_to_le16(RTLLIB_FCTL_WEP); - auth->header.duration_id = 0x013a; + auth->header.duration_id = cpu_to_le16(0x013a); memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); if (ieee->auth_mode == 0) auth->algorithm = WLAN_AUTH_OPEN; else if (ieee->auth_mode == 1) - auth->algorithm = WLAN_AUTH_SHARED_KEY; + auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY); else if (ieee->auth_mode == 2) auth->algorithm = WLAN_AUTH_OPEN; auth->transaction = cpu_to_le16(ieee->associate_seq); @@ -952,7 +952,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest) u16 val16; *(tag++) = MFIE_TYPE_IBSS_SET; *(tag++) = 2; - val16 = cpu_to_le16(ieee->current_network.atim_window); + val16 = ieee->current_network.atim_window; memcpy((u8 *)tag, (u8 *)&val16, 2); tag += 2; } @@ -1260,7 +1260,7 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon, hdr->header.frame_ctl = RTLLIB_STYPE_ASSOC_REQ; - hdr->header.duration_id = 37; + hdr->header.duration_id = cpu_to_le16(37); memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); @@ -1279,7 +1279,7 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon, hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); - hdr->listen_interval = beacon->listen_interval; + hdr->listen_interval = cpu_to_le16(beacon->listen_interval); hdr->info_element[0].id = MFIE_TYPE_SSID; -- cgit v1.2.3 From c5654c0bf9718816535e3df661777d697c7b926e Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:05:09 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning for Static Declarations in rtllib_softmac.c This patch fixes the following Sparse warnings in rtllib_softmac.c- drivers/staging/rtl8192e/rtllib_softmac.c:3636:12: warning: symbol 'rtllib_MgntDisconnectIBSS' was not declared. Should it be static? drivers/staging/rtl8192e/rtllib_softmac.c:3661:13: warning: symbol 'rtllib_MlmeDisassociateRequest' was not declared. Should it be static? drivers/staging/rtl8192e/rtllib_softmac.c:3687:13: warning: symbol 'rtllib_MgntDisconnectAP' was not declared. Should it be static? Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 31cb858d978e..eeec19cde229 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -3633,7 +3633,7 @@ out: } EXPORT_SYMBOL(rtllib_wpa_supplicant_ioctl); -void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib) +static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib) { u8 OpMode; u8 i; @@ -3658,7 +3658,7 @@ void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib) } -void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, u8 *asSta, +static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, u8 *asSta, u8 asRsn) { u8 i; @@ -3684,7 +3684,7 @@ void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, u8 *asSta, } -void +static void rtllib_MgntDisconnectAP( struct rtllib_device *rtllib, u8 asRsn -- cgit v1.2.3 From 450246465a76abc89c1d75882669fb63d5398c21 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 8 Nov 2013 18:26:20 +0530 Subject: Staging: rtl8192e: Fix incorrect type in assignment in rtl819x_BAProc.c This patch fixes the following Sparse warnings in rtl819x_BAProc.c- drivers/staging/rtl8192e/rtl819x_BAProc.c:118:21: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl819x_BAProc.c:118:21: expected unsigned short [unsigned] [usertype] tmp drivers/staging/rtl8192e/rtl819x_BAProc.c:118:21: got restricted __le16 [usertype] drivers/staging/rtl8192e/rtl819x_BAProc.c:122:13: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl819x_BAProc.c:122:13: expected unsigned short [unsigned] [addressable] [usertype] tmp drivers/staging/rtl8192e/rtl819x_BAProc.c:122:13: got restricted __le16 [usertype] drivers/staging/rtl8192e/rtl819x_BAProc.c:125:13: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl819x_BAProc.c:125:13: expected unsigned short [unsigned] [addressable] [usertype] tmp drivers/staging/rtl8192e/rtl819x_BAProc.c:125:13: got restricted __le16 [usertype] drivers/staging/rtl8192e/rtl819x_BAProc.c:181:13: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl819x_BAProc.c:181:13: expected unsigned short [unsigned] [usertype] tmp drivers/staging/rtl8192e/rtl819x_BAProc.c:181:13: got restricted __le16 [usertype] drivers/staging/rtl8192e/rtl819x_BAProc.c:184:13: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl819x_BAProc.c:184:13: expected unsigned short [unsigned] [addressable] [usertype] tmp drivers/staging/rtl8192e/rtl819x_BAProc.c:184:13: got restricted __le16 [usertype] Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl819x_BAProc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c index 32fbbc9d0d92..adc6cc7ca3d6 100644 --- a/drivers/staging/rtl8192e/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c @@ -115,14 +115,14 @@ static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst, if (ACT_ADDBARSP == type) { RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n"); - tmp = cpu_to_le16(StatusCode); + tmp = StatusCode; memcpy(tag, (u8 *)&tmp, 2); tag += 2; } - tmp = cpu_to_le16(pBA->BaParamSet.shortData); + tmp = pBA->BaParamSet.shortData; memcpy(tag, (u8 *)&tmp, 2); tag += 2; - tmp = cpu_to_le16(pBA->BaTimeoutValue); + tmp = pBA->BaTimeoutValue; memcpy(tag, (u8 *)&tmp, 2); tag += 2; @@ -178,10 +178,10 @@ static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst, *tag ++= ACT_CAT_BA; *tag ++= ACT_DELBA; - tmp = cpu_to_le16(DelbaParamSet.shortData); + tmp = DelbaParamSet.shortData; memcpy(tag, (u8 *)&tmp, 2); tag += 2; - tmp = cpu_to_le16(ReasonCode); + tmp = ReasonCode; memcpy(tag, (u8 *)&tmp, 2); tag += 2; -- cgit v1.2.3 From 327ca222aeed7cda0ba1e378088e1aa4f239ca0f Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:07:50 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning for Static Declarations in rtllib_crypt_ccmp.c This patch fixes the following Sparse warnings in rtllib_crypt_ccmp.c- drivers/staging/rtl8192e/rtllib_crypt_ccmp.c:446:12: warning: symbol 'rtllib_crypto_ccmp_init' was not declared. Should it be static? drivers/staging/rtl8192e/rtllib_crypt_ccmp.c:452:13: warning: symbol 'rtllib_crypto_ccmp_exit' was not declared. Should it be static? Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_ccmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index e51cb49ce10e..5e5c76bcdbd0 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -443,13 +443,13 @@ static struct lib80211_crypto_ops rtllib_crypt_ccmp = { }; -int __init rtllib_crypto_ccmp_init(void) +static int __init rtllib_crypto_ccmp_init(void) { return lib80211_register_crypto_ops(&rtllib_crypt_ccmp); } -void __exit rtllib_crypto_ccmp_exit(void) +static void __exit rtllib_crypto_ccmp_exit(void) { lib80211_unregister_crypto_ops(&rtllib_crypt_ccmp); } -- cgit v1.2.3 From 99277c1f99627af12499b2c63b0b6666bebc1701 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:09:25 +0530 Subject: Staging: rtl8192e: Fix Sparse warning of cast to restricted __le16 in rtllib_crypt_tkip.c This patch fixes the following Sparse warnings in rtllib_crypt_tkip.c- drivers/staging/rtl8192e/rtllib_crypt_tkip.c:176:16: warning: cast to restricted __le16 Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_tkip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index 5cfd73baf1cc..d85802ee528b 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -173,7 +173,7 @@ static inline u16 Mk16(u8 hi, u8 lo) static inline u16 Mk16_le(u16 *v) { - return le16_to_cpu(*v); + return *v; } -- cgit v1.2.3 From 316de3cabb5472225195a86f2dc150cf90698682 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:10:18 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning for Static Declarations in rtllib_crypt_tkip.c This patch fixes the following Sparse warnings in rtllib_crypt_tkip.c- drivers/staging/rtl8192e/rtllib_crypt_tkip.c:755:12: warning: symbol 'rtllib_crypto_tkip_init' was not declared. Should it be static? drivers/staging/rtl8192e/rtllib_crypt_tkip.c:761:13: warning: symbol 'rtllib_crypto_tkip_exit' was not declared. Should it be static? Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_tkip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index d85802ee528b..d2768986c53e 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -752,13 +752,13 @@ static struct lib80211_crypto_ops rtllib_crypt_tkip = { }; -int __init rtllib_crypto_tkip_init(void) +static int __init rtllib_crypto_tkip_init(void) { return lib80211_register_crypto_ops(&rtllib_crypt_tkip); } -void __exit rtllib_crypto_tkip_exit(void) +static void __exit rtllib_crypto_tkip_exit(void) { lib80211_unregister_crypto_ops(&rtllib_crypt_tkip); } -- cgit v1.2.3 From 20fc5afc32a642104d23efc2d00141fe3d1a2661 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:11:31 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning for Static Declarations in rtllib_crypt_wep.c This patch fixes the following Sparse warnings in rtllib_crypt_wep.c- drivers/staging/rtl8192e/rtllib_crypt_wep.c:273:12: warning: symbol 'rtllib_crypto_wep_init' was not declared. Should it be static? drivers/staging/rtl8192e/rtllib_crypt_wep.c:279:13: warning: symbol 'rtllib_crypto_wep_exit' was not declared. Should it be static? Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_wep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c index c4df6e01ef74..b0e5f1ff07ee 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c @@ -270,13 +270,13 @@ static struct lib80211_crypto_ops rtllib_crypt_wep = { }; -int __init rtllib_crypto_wep_init(void) +static int __init rtllib_crypto_wep_init(void) { return lib80211_register_crypto_ops(&rtllib_crypt_wep); } -void __exit rtllib_crypto_wep_exit(void) +static void __exit rtllib_crypto_wep_exit(void) { lib80211_unregister_crypto_ops(&rtllib_crypt_wep); } -- cgit v1.2.3 From d95cb1c7748d1021ae26499561aa3953d9b263a9 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:12:28 +0530 Subject: Staging: rtl8192e: Fix Sparse warning of cast from restricted __le16 in r8192E_dev.c This patch fixes the following Sparse warning in rtl8192e/r8192E_dev.c- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:196:34: warning: cast from restricted __le16 drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:198:33: warning: cast from restricted __le16 drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:200:33: warning: cast from restricted __le16 Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 2cace9a4525a..dc9d7d616a49 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -193,11 +193,12 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) dm_init_edca_turbo(dev); - u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[pAcParam])) << + u4bAcParam = (((le16_to_cpu( + qos_parameters->tx_op_limit[pAcParam])) << AC_PARAM_TXOP_LIMIT_OFFSET) | - (((u32)(qos_parameters->cw_max[pAcParam])) << + ((le16_to_cpu(qos_parameters->cw_max[pAcParam])) << AC_PARAM_ECW_MAX_OFFSET) | - (((u32)(qos_parameters->cw_min[pAcParam])) << + ((le16_to_cpu(qos_parameters->cw_min[pAcParam])) << AC_PARAM_ECW_MIN_OFFSET) | (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET)); -- cgit v1.2.3 From 285cce0560fe9882373b26f16221ec0e2726c6af Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:13:49 +0530 Subject: Staging: rtl8192e: Fix incorrect type in assignment in r8192E_dev.c This patch fixes the following sparse warning in rtl8192e/r8192E_dev.c- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:1275:27: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:1275:27: expected unsigned int [unsigned] [usertype] TxBuffAddr drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:1275:27: got restricted __le32 [usertype] drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:1305:27: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:1305:27: expected unsigned int [unsigned] [usertype] TxBuffAddr drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c:1305:27: got restricted __le32 [usertype] Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index dc9d7d616a49..175c7a16695b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -1272,7 +1272,7 @@ void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, pdesc->LastSeg = 1; pdesc->TxBufferSize = skb->len; - pdesc->TxBuffAddr = cpu_to_le32(mapping); + pdesc->TxBuffAddr = mapping; } void rtl8192_tx_fill_cmd_desc(struct net_device *dev, @@ -1302,7 +1302,7 @@ void rtl8192_tx_fill_cmd_desc(struct net_device *dev, entry_tmp->RATid = (u8)DESC_PACKET_TYPE_INIT; } entry->TxBufferSize = skb->len; - entry->TxBuffAddr = cpu_to_le32(mapping); + entry->TxBuffAddr = mapping; entry->OWN = 1; } -- cgit v1.2.3 From fa63c9ce864012ac2ff26991f08f139d6a0debba Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:14:56 +0530 Subject: Staging: rtl8192e: Fix Sparse Warning for Static Declarations in rtl_core.c This patch fixes the following sparse warning in rtl8192e/rtl_core.c- drivers/staging/rtl8192e/rtl8192e/rtl_core.c:58:5: warning: symbol 'hwwep' was not declared. Should it be static? drivers/staging/rtl8192e/rtl8192e/rtl_core.c:588:5: warning: symbol 'WDCAPARA_ADD' was not declared. Should it be static? drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2695:13: warning: symbol 'rtl8192_interrupt' was not declared. Should it be static? Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 2 +- drivers/staging/rtl8192e/rtl8192e/rtl_cam.c | 1 - drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 4 +--- drivers/staging/rtl8192e/rtl8192e/rtl_core.h | 2 ++ 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 175c7a16695b..4a35f9b5602d 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -30,7 +30,7 @@ #include "rtl_dm.h" #include "rtl_wx.h" -extern int WDCAPARA_ADD[]; +static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO}; void rtl8192e_start_beacon(struct net_device *dev) { diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index fa5603a562c3..c46c65c5542f 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -28,7 +28,6 @@ #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */ #include "r8192E_cmdpkt.h" -extern int hwwep; void CamResetAllEntry(struct net_device *dev) { u32 ulcommand = 0; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index d93caca9657d..ceb29c8032f3 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -585,8 +585,6 @@ static void rtl8192_update_beacon(void *data) rtl8192_update_cap(dev, net->capability); } -int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO}; - static void rtl8192_qos_activate(void *data) { struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, @@ -2692,7 +2690,7 @@ out: } -irqreturn_t rtl8192_interrupt(int irq, void *netdev) +static irqreturn_t rtl8192_interrupt(int irq, void *netdev) { struct net_device *dev = (struct net_device *) netdev; struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index b015bf61cf05..ce239be8f2f6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -188,6 +188,8 @@ #define MAX_RX_COUNT 64 #define MAX_TX_QUEUE_COUNT 9 +extern int hwwep; + enum RTL819x_PHY_PARAM { RTL819X_PHY_MACPHY_REG = 0, RTL819X_PHY_MACPHY_REG_PG = 1, -- cgit v1.2.3 From 34e987e6ff615b97fbf8d3bb273ff343fa2ed8b6 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:15:48 +0530 Subject: Staging: rtl8192e: Fix incorrect type in assignment in rtl_core.c This patch fixes the following sparse warning in rtl8192e/rtl_core.c- drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:10: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:10: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:10: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:13: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:13: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:13: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:16: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:16: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:16: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:19: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:19: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:565:19: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:10: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:10: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:10: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:13: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:13: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:13: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:16: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:16: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:16: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:19: warning: incorrect type in initializer (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:19: expected restricted __le16 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:566:19: got int drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2012:12: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2012:12: expected unsigned short [unsigned] [usertype] fc drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2012:12: got restricted __le16 [usertype] frame_ctl drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2102:46: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2102:46: expected unsigned int [unsigned] [usertype] BufferAddress drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2102:46: got restricted __le32 [usertype] drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2137:41: warning: incorrect type in assignment (different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2137:41: expected unsigned int [unsigned] [usertype] NextDescAddress drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2137:41: got restricted __le32 [usertype] drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2401:38: warning: incorrect type in assignment rtllib_softmac.c(different base types) drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2401:38: expected unsigned int [unsigned] [usertype] BufferAddress drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2401:38: got restricted __le32 [usertype] Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index ceb29c8032f3..d36d6bb91342 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -562,8 +562,8 @@ void rtl8192_update_cap(struct net_device *dev, u16 cap) } static struct rtllib_qos_parameters def_qos_parameters = { - {3, 3, 3, 3}, - {7, 7, 7, 7}, + {cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3)}, + {cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7)}, {2, 2, 2, 2}, {0, 0, 0, 0}, {0, 0, 0, 0} @@ -2009,7 +2009,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) fwinfo_size = sizeof(struct tx_fwinfo_8190pci); header = (struct rtllib_hdr_1addr *)(((u8 *)skb->data) + fwinfo_size); - fc = header->frame_ctl; + fc = le16_to_cpu(header->frame_ctl); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); pda_addr = header->addr1; @@ -2099,7 +2099,7 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev) dev_kfree_skb_any(skb); return -1; } - entry->BufferAddress = cpu_to_le32(*mapping); + entry->BufferAddress = *mapping; entry->Length = priv->rxbuffersize; entry->OWN = 1; @@ -2135,8 +2135,8 @@ static int rtl8192_alloc_tx_desc_ring(struct net_device *dev, for (i = 0; i < entries; i++) ring[i].NextDescAddress = - cpu_to_le32((u32)dma + ((i + 1) % entries) * - sizeof(*ring)); + (u32)dma + ((i + 1) % entries) * + sizeof(*ring); return 0; } @@ -2398,7 +2398,7 @@ static void rtl8192_rx_normal(struct net_device *dev) } } done: - pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); + pdesc->BufferAddress = *((dma_addr_t *)skb->cb); pdesc->OWN = 1; pdesc->Length = priv->rxbuffersize; if (priv->rx_idx[rx_queue_idx] == priv->rxringcount-1) -- cgit v1.2.3 From 466bc7f2307e47ad53c0b520c56b0a4c45b6d0a2 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 19:16:36 +0530 Subject: Staging: rtl8192e: Fix Sparse warning of cast to restricted __le32 in rtl_core.c This patch fixes the following sparse warnings in rtl8192e/rtl_core.c- drivers/staging/rtl8192e/rtl8192e/rtl_core.c:1846:46: warning: cast to restricted __le32 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:1951:46: warning: cast to restricted __le32 drivers/staging/rtl8192e/rtl8192e/rtl_core.c:2199:50: warning: cast to restricted __le32 Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index d36d6bb91342..c01abc23213e 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -1843,7 +1843,7 @@ static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio) struct tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr), + pci_unmap_single(priv->pdev, entry->TxBuffAddr, skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; @@ -1948,7 +1948,7 @@ static void rtl8192_tx_isr(struct net_device *dev, int prio) } skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr), + pci_unmap_single(priv->pdev, entry->TxBuffAddr, skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); @@ -2196,7 +2196,7 @@ void rtl8192_pci_resetdescring(struct net_device *dev) __skb_dequeue(&ring->queue); pci_unmap_single(priv->pdev, - le32_to_cpu(entry->TxBuffAddr), + entry->TxBuffAddr, skb->len, PCI_DMA_TODEVICE); kfree_skb(skb); ring->idx = (ring->idx + 1) % ring->entries; -- cgit v1.2.3 From 1f9d82d29345b0bf6a4ce4eec13e63236b739272 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Fri, 8 Nov 2013 00:13:46 +0200 Subject: staging: rtl8188eu: correct code alignment This patch fixes incorrect code alignment due to mixed indenting with spaces and tabs. This patch was detected using coccinelle and silences the following warnings: drivers/staging/rtl8188eu/core/rtw_io.c:297:2-29: code aligned with following code on line 299 drivers/staging/rtl8188eu/core/rtw_mlme_ext.c:4420:2-29: code aligned with following code on line 4422 drivers/staging/rtl8188eu/os_dep/osdep_service.c:54:2-17: code aligned with following code on line 55 drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:7229:2-17: code aligned with following code on line 7231 Signed-off-by: Teodora Baluta Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_io.c | 2 +- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 2 +- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 34 ++++++++++++------------ drivers/staging/rtl8188eu/os_dep/osdep_service.c | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_io.c b/drivers/staging/rtl8188eu/core/rtw_io.c index 10c9c6560b20..c47990a62b7c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_io.c +++ b/drivers/staging/rtl8188eu/core/rtw_io.c @@ -296,7 +296,7 @@ u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt, u8 *pme if (ret == _SUCCESS) ret = rtw_sctx_wait(&sctx); - return ret; + return ret; } void _rtw_write_port_cancel(struct adapter *adapter) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 7ab5ff039c88..6519a7b3f833 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4419,7 +4419,7 @@ s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntfr if (ret == _SUCCESS) ret = rtw_sctx_wait(&sctx); - return ret; + return ret; } s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe) diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index ae5458770234..a002d2e75e9f 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -7228,25 +7228,25 @@ static int rtw_mp_thermal(struct net_device *dev, if (copy_from_user(extra, wrqu->pointer, wrqu->length)) return -EFAULT; - bwrite = strncmp(extra, "write", 6); /* strncmp true is 0 */ + bwrite = strncmp(extra, "write", 6); /* strncmp true is 0 */ - Hal_GetThermalMeter(padapter, &val); + Hal_GetThermalMeter(padapter, &val); - if (bwrite == 0) { - EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); - if (2 > max_available_size) { - DBG_88E("no available efuse!\n"); - return -EFAULT; - } - if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) { - DBG_88E("rtw_efuse_map_write error\n"); - return -EFAULT; - } else { - sprintf(extra, " efuse write ok :%d", val); - } - } else { - sprintf(extra, "%d", val); - } + if (bwrite == 0) { + EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false); + if (2 > max_available_size) { + DBG_88E("no available efuse!\n"); + return -EFAULT; + } + if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) { + DBG_88E("rtw_efuse_map_write error\n"); + return -EFAULT; + } else { + sprintf(extra, " efuse write ok :%d", val); + } + } else { + sprintf(extra, "%d", val); + } wrqu->length = strlen(extra); return 0; diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 5a9e9e4558aa..7b3fb35dd5ce 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -52,7 +52,7 @@ u32 rtw_atoi(u8 *s) } if (flag == 1) num = num * -1; - return num; + return num; } inline u8 *_rtw_vmalloc(u32 sz) -- cgit v1.2.3 From 74772fcf61bbbb71a8f1b3eaf70d67d00b7bc752 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Fri, 8 Nov 2013 00:13:47 +0200 Subject: staging: rtl8188eu: remove unneeded semicolon This patch fixes the following issues detected by coccinelle: drivers/staging/rtl8188eu/core/rtw_xmit.c:688:75-76: Unneeded semicolon drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c:2307:64-65: Unneeded semicolon drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c:89:66-67: Unneeded semicolon Signed-off-by: Teodora Baluta Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_xmit.c | 2 +- drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c | 2 +- drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index a594e51d2e1c..01662f78e53d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -685,7 +685,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr _func_enter_; - hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);; + hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); if (pattrib->encrypt == _TKIP_) {/* if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_PRIVACY_) */ /* encode mic code */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 52b3fba0fae1..a291d7ae6f42 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -2304,7 +2304,7 @@ void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool if (registry_par->antdiv_cfg == 2) { /* 2:By EFUSE */ pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E]&0x18)>>3; if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) - pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION&0x18)>>3;; + pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION&0x18)>>3; } else { pHalData->AntDivCfg = registry_par->antdiv_cfg; /* 0:OFF , 1:ON, 2:By EFUSE */ } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 05e2475cfd61..511f61cbb9e0 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -86,7 +86,7 @@ void update_recvframe_attrib_88e(union recv_frame *precvframe, struct recv_stat pattrib = &precvframe->u.hdr.attrib; _rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib)); - pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);;/* u8)prxreport->crc32; */ + pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);/* u8)prxreport->crc32; */ /* update rx report to recv_frame attribute */ pattrib->pkt_rpt_type = (u8)((le32_to_cpu(report.rxdw3) >> 14) & 0x3);/* prxreport->rpt_sel; */ -- cgit v1.2.3 From fa7b3d028852e4a3ebecfcd7b642cb3d2c86f8b9 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 10 Nov 2013 03:04:54 +0530 Subject: staging:rtl8192e: Rewrite macro definition as static inline function. This patch removes the checkpatch.pl error Macros "with complex values should be enclosed in parenthesis" in dot11d.h by rewriting it as a static inline function. Signed-off-by: Himangi Saraogi Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/dot11d.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h index fb7683fa5ffd..eeea50260f1d 100644 --- a/drivers/staging/rtl8192e/dot11d.h +++ b/drivers/staging/rtl8192e/dot11d.h @@ -87,7 +87,10 @@ static inline void cpMacAddr(unsigned char *des, unsigned char *src) #define CIE_WATCHDOG_TH 1 #define GET_CIE_WATCHDOG(__pIeeeDev) \ (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog) -#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 +static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev) +{ + GET_CIE_WATCHDOG(__pIeeeDev) = 0; +} #define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev)) #define IS_DOT11D_STATE_DONE(__pIeeeDev) \ -- cgit v1.2.3 From f249da27e3615da41f2d072691503f358c220732 Mon Sep 17 00:00:00 2001 From: Archana kumari Date: Mon, 11 Nov 2013 00:04:04 +0530 Subject: staging: rtl8192e: Fixed space prohibited warning in dot11d.c This patch fixes space prohibited before semicolon warning in dot11d.c Signed-off-by: Archana kumari Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/dot11d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index 1260f10944ef..eb33c517fcc8 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -144,7 +144,7 @@ void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, return; } - for (j = 0 ; j < pTriple->NumChnls; j++) { + for (j = 0; j < pTriple->NumChnls; j++) { pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; -- cgit v1.2.3 From c37da1c638685487d03f703c41e9740140939869 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 18:56:40 +0530 Subject: Staging: tidspbridge: Fix foo ** bar should be foo **bar in cmm.c This patch fixes the following checkpatch.pl warning in pmgr/cmm.c- ERROR: "foo ** bar" should be "foo **bar" Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/cmm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/cmm.c b/drivers/staging/tidspbridge/pmgr/cmm.c index 4a800dadd703..011145e46e0a 100644 --- a/drivers/staging/tidspbridge/pmgr/cmm.c +++ b/drivers/staging/tidspbridge/pmgr/cmm.c @@ -359,7 +359,7 @@ int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa, u32 ul_seg_id) * Return the communication memory manager object for this device. * This is typically called from the client process. */ -int cmm_get_handle(void *hprocessor, struct cmm_object ** ph_cmm_mgr) +int cmm_get_handle(void *hprocessor, struct cmm_object **ph_cmm_mgr) { int status = 0; struct dev_object *hdev_obj; @@ -828,7 +828,7 @@ int cmm_xlator_free_buf(struct cmm_xlatorobject *xlator, void *buf_va) * Purpose: * Set/Get translator info. */ -int cmm_xlator_info(struct cmm_xlatorobject *xlator, u8 ** paddr, +int cmm_xlator_info(struct cmm_xlatorobject *xlator, u8 **paddr, u32 ul_size, u32 segm_id, bool set_info) { struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator; -- cgit v1.2.3 From a5fdf083f2eeb0ecc24bd0816bb7e3d86a351029 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 18:57:21 +0530 Subject: Staging: tidspbridge: Fix quoted string split across lines in cmm.c This patch fixes the following checkpatch.pl warning in pmgr/cmm.c- WARNING: quoted string split across lines Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/cmm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/cmm.c b/drivers/staging/tidspbridge/pmgr/cmm.c index 011145e46e0a..f961e0ec9da8 100644 --- a/drivers/staging/tidspbridge/pmgr/cmm.c +++ b/drivers/staging/tidspbridge/pmgr/cmm.c @@ -449,8 +449,7 @@ int cmm_register_gppsm_seg(struct cmm_object *hcmm_mgr, struct cmm_mnode *new_node; s32 slot_seg; - dev_dbg(bridge, "%s: dw_gpp_base_pa %x ul_size %x dsp_addr_offset %x " - "dw_dsp_base %x ul_dsp_size %x gpp_base_va %x\n", + dev_dbg(bridge, "%s: dw_gpp_base_pa %x ul_size %x dsp_addr_offset %x dw_dsp_base %x ul_dsp_size %x gpp_base_va %x\n", __func__, dw_gpp_base_pa, ul_size, dsp_addr_offset, dw_dsp_base, ul_dsp_size, gpp_base_va); -- cgit v1.2.3 From 50e8f001847ce75ee4fe5210ba7d26be2ef68348 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 18:58:09 +0530 Subject: Staging: tidspbridge: Fix quoted string split across line in dbll.c This patch fixes the following checkpatch.pl warning in pmgr/dbll.c- WARNING: quoted string split across lines Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dbll.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c index 41e88abe47af..941961e44020 100644 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ b/drivers/staging/tidspbridge/pmgr/dbll.c @@ -378,8 +378,8 @@ int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr, opened_doff = false; } - dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, " - "status 0x%x\n", __func__, lib, name, paddr, psize, status); + dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, status 0x%x\n", + __func__, lib, name, paddr, psize, status); return status; } @@ -705,8 +705,8 @@ func_cont: opened_doff = false; } - dev_dbg(bridge, "%s: lib: %p name: %s buf: %p size: 0x%x, " - "status 0x%x\n", __func__, lib, name, buf, size, status); + dev_dbg(bridge, "%s: lib: %p name: %s buf: %p size: 0x%x, status 0x%x\n", + __func__, lib, name, buf, size, status); return status; } @@ -1172,8 +1172,7 @@ func_cont: if (!run_addr_flag) info->run_addr = info->load_addr; info->context = (u32) rmm_addr_obj.segid; - dev_dbg(bridge, "%s: %s base = 0x%x len = 0x%x, " - "info->run_addr 0x%x, info->load_addr 0x%x\n", + dev_dbg(bridge, "%s: %s base = 0x%x len = 0x%x, info->run_addr 0x%x, info->load_addr 0x%x\n", __func__, info->name, info->load_addr / DSPWORDSIZE, info->size / DSPWORDSIZE, info->run_addr, info->load_addr); -- cgit v1.2.3 From ae510a6a22300cc0e457bf2663ecd0f0ba352f83 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 18:58:44 +0530 Subject: Staging: tidspbridge: Fix no space before tabs in dbll.c This patch fixes the following checkpatch.pl warning in pmgr/dbll.c- WARNING: please, no space before tabs Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dbll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c index 941961e44020..c7d816e466c9 100644 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ b/drivers/staging/tidspbridge/pmgr/dbll.c @@ -1398,7 +1398,7 @@ void find_symbol_callback(void *elem, void *user_data) * @sym_addr_output: Symbol Output address * @name_output: String with the dsp symbol * - * This function retrieves the dsp symbol from the dsp binary. + * This function retrieves the dsp symbol from the dsp binary. */ bool dbll_find_dsp_symbol(struct dbll_library_obj *zl_lib, u32 address, u32 offset_range, u32 *sym_addr_output, -- cgit v1.2.3 From b5f45d8eb6abe3e34fc43c119a2c12fc10b46d9b Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 18:59:17 +0530 Subject: Staging: tidspbridge: Fix no space at the start of the line in dbll.c This patch fixes the following checkpatch.pl warning in pmgr/dbll.c- WARNING: please, no space at the start of the line Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dbll.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c index c7d816e466c9..996a02d27d34 100644 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ b/drivers/staging/tidspbridge/pmgr/dbll.c @@ -915,10 +915,10 @@ static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, status = dbll_get_addr((struct dbll_library_obj *)lib, (char *)name, &dbll_sym); if (!status) { - status = - dbll_get_c_addr((struct dbll_library_obj *) - lib, (char *)name, - &dbll_sym); + status = dbll_get_c_addr( + (struct dbll_library_obj *) + lib, (char *)name, + &dbll_sym); } } } -- cgit v1.2.3 From 09ebd191f16a834f85ae8f8e9e7ae36c758589ff Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 18:59:51 +0530 Subject: Staging: tidspbridge: Fix foo * bar should be foo *bar in dev.c This patch fixes the following checkpatch.pl warning in pmgr/dev.c- ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c index 6234ffb5e8a3..e23e6a23daa2 100644 --- a/drivers/staging/tidspbridge/pmgr/dev.c +++ b/drivers/staging/tidspbridge/pmgr/dev.c @@ -606,7 +606,7 @@ int dev_get_node_manager(struct dev_object *hdev_obj, * ======== dev_get_symbol ======== */ int dev_get_symbol(struct dev_object *hdev_obj, - const char *str_sym, u32 * pul_value) + const char *str_sym, u32 *pul_value) { int status = 0; struct cod_manager *cod_mgr; -- cgit v1.2.3 From bf40d51a1c9490740e68815c28d449ab8d17af62 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 19:00:22 +0530 Subject: Staging: tidspbridge: Fix no space at the start of the line in dev.c This patch fixes the following checkpatch.pl warning in pmgr/dev.c- WARNING: please, no spaces at the start of a line Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c index e23e6a23daa2..616dc1f63070 100644 --- a/drivers/staging/tidspbridge/pmgr/dev.c +++ b/drivers/staging/tidspbridge/pmgr/dev.c @@ -916,8 +916,8 @@ static void store_interface_fxns(struct bridge_drv_interface *drv_fxns, /* Local helper macro: */ #define STORE_FXN(cast, pfn) \ - (intf_fxns->pfn = ((drv_fxns->pfn != NULL) ? drv_fxns->pfn : \ - (cast)fxn_not_implemented)) + (intf_fxns->pfn = ((drv_fxns->pfn != NULL) ? drv_fxns->pfn : \ + (cast)fxn_not_implemented)) bridge_version = MAKEVERSION(drv_fxns->brd_api_major_version, drv_fxns->brd_api_minor_version); -- cgit v1.2.3 From e2a6d03f9c8099a726aea105d4da8d92309e7f3f Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 19:00:54 +0530 Subject: Staging: tidspbridge: Fix quoted string split across line in dmm.c This patch fixes the following checkpatch.pl warning in pmgr/dmm.c- WARNING: quoted string split across lines Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dmm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c index 7c9f83916068..01734196264b 100644 --- a/drivers/staging/tidspbridge/pmgr/dmm.c +++ b/drivers/staging/tidspbridge/pmgr/dmm.c @@ -217,8 +217,8 @@ int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 size) status = -ENOENT; spin_unlock(&dmm_obj->dmm_lock); - dev_dbg(bridge, "%s dmm_mgr %p, addr %x, size %x\n\tstatus %x, " - "chunk %p", __func__, dmm_mgr, addr, size, status, chunk); + dev_dbg(bridge, "%s dmm_mgr %p, addr %x, size %x\n\tstatus %x, chunk %p", + __func__, dmm_mgr, addr, size, status, chunk); return status; } @@ -268,9 +268,9 @@ int dmm_reserve_memory(struct dmm_object *dmm_mgr, u32 size, spin_unlock(&dmm_obj->dmm_lock); - dev_dbg(bridge, "%s dmm_mgr %p, size %x, prsv_addr %p\n\tstatus %x, " - "rsv_addr %x, rsv_size %x\n", __func__, dmm_mgr, size, - prsv_addr, status, rsv_addr, rsv_size); + dev_dbg(bridge, "%s dmm_mgr %p, size %x, prsv_addr %p\n\tstatus %x, rsv_addr %x, rsv_size %x\n", + __func__, dmm_mgr, size, + prsv_addr, status, rsv_addr, rsv_size); return status; } @@ -299,8 +299,8 @@ int dmm_un_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 *psize) } spin_unlock(&dmm_obj->dmm_lock); - dev_dbg(bridge, "%s: dmm_mgr %p, addr %x, psize %p\n\tstatus %x, " - "chunk %p\n", __func__, dmm_mgr, addr, psize, status, chunk); + dev_dbg(bridge, "%s: dmm_mgr %p, addr %x, psize %p\n\tstatus %x, chunk %p\n", + __func__, dmm_mgr, addr, psize, status, chunk); return status; } -- cgit v1.2.3 From 0431aa1b4e15d79a03a11cd229da35c888e1b590 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 19:01:26 +0530 Subject: Staging: tidspbridge: Remove unnecessary white space before a quoted newline in dmm.c This patch fixes the following checkpatch.pl warning in pmgr/dmm.c- WARNING: unnecessary whitespace before a quoted newline Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dmm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c index 01734196264b..e192823611f2 100644 --- a/drivers/staging/tidspbridge/pmgr/dmm.c +++ b/drivers/staging/tidspbridge/pmgr/dmm.c @@ -477,9 +477,9 @@ u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr) spin_unlock(&dmm_mgr->dmm_lock); printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n", freemem / (1024 * 1024)); - printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n", + printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes\n", (((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024)); - printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n", + printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes\n\n", (bigsize * PG_SIZE4K / (1024 * 1024))); return 0; -- cgit v1.2.3 From 6467f5c15e7f17b921bd57bccd662b1b3030927a Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 19:02:24 +0530 Subject: Staging: tidspbridge: Prefer dev_info() then printk() in dmm.c This patch fixes the following checkpatch.pl warning in pmgr/dmm.c- WARNING: Prefer netdev_info(netdev, ... then dev_info(dev, ... then pr_info(... to printk(KERN_INFO ... Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dmm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c index e192823611f2..04a6b0669fa9 100644 --- a/drivers/staging/tidspbridge/pmgr/dmm.c +++ b/drivers/staging/tidspbridge/pmgr/dmm.c @@ -475,11 +475,11 @@ u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr) } } spin_unlock(&dmm_mgr->dmm_lock); - printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n", + dev_info(bridge, "Total DSP VA FREE memory = %d Mbytes\n", freemem / (1024 * 1024)); - printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes\n", + dev_info(bridge, "Total DSP VA USED memory= %d Mbytes\n", (((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024)); - printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes\n\n", + dev_info(bridge, "DSP VA - Biggest FREE block = %d Mbytes\n\n", (bigsize * PG_SIZE4K / (1024 * 1024))); return 0; -- cgit v1.2.3 From 9279e0c6ed247ae467d0a369ac1390bca8f28519 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 10 Nov 2013 19:02:54 +0530 Subject: Staging: tidspbridge: Fix foo * bar should be foo *bar in dspapi.c This patch fixes the following checkpatch.pl warning in pmgr/dspapi.c- ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dspapi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dspapi.c b/drivers/staging/tidspbridge/pmgr/dspapi.c index 70db4ff99ec6..b7d5c8cbb2a1 100644 --- a/drivers/staging/tidspbridge/pmgr/dspapi.c +++ b/drivers/staging/tidspbridge/pmgr/dspapi.c @@ -162,7 +162,7 @@ static u8 size_cmd[] = { ARRAY_SIZE(cmm_cmd), }; -static inline void _cp_fm_usr(void *to, const void __user * from, +static inline void _cp_fm_usr(void *to, const void __user *from, int *err, unsigned long bytes) { if (*err) @@ -507,7 +507,7 @@ u32 mgrwrap_wait_for_bridge_events(union trapped_args *args, void *pr_ctxt) /* * ======== MGRWRAP_GetProcessResourceInfo ======== */ -u32 __deprecated mgrwrap_get_process_resources_info(union trapped_args * args, +u32 __deprecated mgrwrap_get_process_resources_info(union trapped_args *args, void *pr_ctxt) { pr_err("%s: deprecated dspbridge ioctl\n", __func__); @@ -581,7 +581,7 @@ func_end: /* * ======== procwrap_detach ======== */ -u32 __deprecated procwrap_detach(union trapped_args * args, void *pr_ctxt) +u32 __deprecated procwrap_detach(union trapped_args *args, void *pr_ctxt) { /* proc_detach called at bridge_release only */ pr_err("%s: deprecated dspbridge ioctl\n", __func__); @@ -1564,7 +1564,7 @@ u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt) /* * ======== strmwrap_get_event_handle ======== */ -u32 __deprecated strmwrap_get_event_handle(union trapped_args * args, +u32 __deprecated strmwrap_get_event_handle(union trapped_args *args, void *pr_ctxt) { pr_err("%s: deprecated dspbridge ioctl\n", __func__); @@ -1793,7 +1793,7 @@ u32 strmwrap_select(union trapped_args *args, void *pr_ctxt) /* * ======== cmmwrap_calloc_buf ======== */ -u32 __deprecated cmmwrap_calloc_buf(union trapped_args * args, void *pr_ctxt) +u32 __deprecated cmmwrap_calloc_buf(union trapped_args *args, void *pr_ctxt) { /* This operation is done in kernel */ pr_err("%s: deprecated dspbridge ioctl\n", __func__); @@ -1803,7 +1803,7 @@ u32 __deprecated cmmwrap_calloc_buf(union trapped_args * args, void *pr_ctxt) /* * ======== cmmwrap_free_buf ======== */ -u32 __deprecated cmmwrap_free_buf(union trapped_args * args, void *pr_ctxt) +u32 __deprecated cmmwrap_free_buf(union trapped_args *args, void *pr_ctxt) { /* This operation is done in kernel */ pr_err("%s: deprecated dspbridge ioctl\n", __func__); -- cgit v1.2.3 From 4b5c08e85d5dbbe6c22e47b5cf4401be2639e9e5 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 4 Nov 2013 20:13:11 +0200 Subject: staging: comedi: remove unneeded semicolon There is no need for ';' after '}'. This minor fix was suggested by coccinelle. Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 9e4d7e860509..8b5e9c097349 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -753,7 +753,7 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev, } else { devpriv->ai_mode = INT_TYPE_AI3_DMA; outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */ - }; + } } /* -- cgit v1.2.3 From 42a5a418b2e572ae7056a6381d4d8428008a18b3 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 4 Nov 2013 20:13:10 +0200 Subject: staging: comedi: change bool assignment to true This is a minor fix that was suggested by coccinelle. When defined as a bool, a variable should use true/false rather than 1/0. Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 2e4bf284d52c..9c9559ffc643 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -513,7 +513,7 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev, int event = 0; spin_lock_irqsave(&subpriv->spinlock, flags); - subpriv->active = 1; + subpriv->active = true; /* Set up end of acquisition. */ switch (cmd->stop_src) { -- cgit v1.2.3 From f635bbd1376bcb82dabea4c88ddd90faea7e3d25 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 5 Nov 2013 23:51:18 +0530 Subject: staging: ctxt1e1: Fixed sparse warning related to static declaration Fixed below thrown sparse warning by making the local variable declaration static: drivers/staging/cxt1e1/musycc.c:1:14: warning: symbol 'max_intcnt' was not declared. Should it be static? drivers/staging/cxt1e1/musycc.c:2:14: warning: symbol 'max_bh' was not declared. Should it be static? Signed-off-by: Nandini Hanumanthagowda Reviewed-by: Lisa Nguyen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/musycc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c index 0ba8c3ae673b..7a3a30cd0f7f 100644 --- a/drivers/staging/cxt1e1/musycc.c +++ b/drivers/staging/cxt1e1/musycc.c @@ -1,5 +1,5 @@ -unsigned int max_intcnt = 0; -unsigned int max_bh = 0; +static unsigned int max_intcnt = 0; +static unsigned int max_bh = 0; /*----------------------------------------------------------------------------- * musycc.c - -- cgit v1.2.3 From 4ed7eeceb576e3534e61a36c85a0c9d33ad829d9 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 20:27:43 +0530 Subject: Staging: gdm724x: Remove confusing macro gdm_lte_rcv_with_cb in gdm_lte.c This patch removes confusing macro gdm_lte_rcv_with_cb as stated in TODO list in file gdm_lte.c. It then fixes the place where the macro is used. Signed-off-by: Rashika Kheria Reviewed-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index c57a6ba5d010..d061cd553053 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -53,9 +53,6 @@ #define gdm_lte_sdu_send(n, d, l, c, b, i, t) (\ n->phy_dev->send_sdu_func(n->phy_dev->priv_dev, d, l, n->pdn_table.dft_eps_id, 0, c, b, i, t)) -#define gdm_lte_rcv_with_cb(n, c, b, e) (\ - n->rcv_func(n->priv_dev, c, b, e)) - #define IP_VERSION_4 4 #define IP_VERSION_6 6 @@ -762,7 +759,7 @@ void start_rx_proc(struct phy_dev *phy_dev) int i; for (i = 0; i < MAX_RX_SUBMIT_COUNT; i++) - gdm_lte_rcv_with_cb(phy_dev, rx_complete, phy_dev, USB_COMPLETE); + phy_dev->rcv_func(phy_dev->priv_dev, rx_complete, phy_dev, USB_COMPLETE); } static struct net_device_ops gdm_netdev_ops = { -- cgit v1.2.3 From 04db9c6a2db7427e6046300413967bf6d6fd4b6b Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 20:28:40 +0530 Subject: Staging: gdm724x: Remove confusing macro gdm_dev_endian in gdm_lte.c This patch removes confusing macro gdm_dev_endian as stated in TODO list in file gdm_lte.c. It then fixes the place where the macro is used. Signed-off-by: Rashika Kheria Reviewed-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index d061cd553053..5cf0f6f7f8d3 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -44,9 +44,6 @@ */ #define DEFAULT_MTU_SIZE 1500 -#define gdm_dev_endian(n) (\ - n->phy_dev->get_endian(n->phy_dev->priv_dev)) - #define gdm_lte_hci_send(n, d, l) (\ n->phy_dev->send_hci_func(n->phy_dev->priv_dev, d, l, NULL, NULL)) @@ -500,7 +497,10 @@ static int gdm_lte_event_send(struct net_device *dev, char *buf, int len) sscanf(dev->name, "lte%d", &idx); return netlink_send(lte_event.sock, idx, 0, buf, - gdm_dev16_to_cpu(gdm_dev_endian(nic), hci->len) + HCI_HEADER_SIZE); + gdm_dev16_to_cpu( + nic->phy_dev->get_endian( + nic->phy_dev->priv_dev), hci->len) + + HCI_HEADER_SIZE); } static void gdm_lte_event_rcv(struct net_device *dev, u16 type, void *msg, int len) @@ -685,8 +685,14 @@ static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len) if (pdn_table->activate) { nic->pdn_table.activate = pdn_table->activate; - nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->dft_eps_id); - nic->pdn_table.nic_type = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->nic_type); + nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu( + nic->phy_dev->get_endian( + nic->phy_dev->priv_dev), + pdn_table->dft_eps_id); + nic->pdn_table.nic_type = gdm_dev32_to_cpu( + nic->phy_dev->get_endian( + nic->phy_dev->priv_dev), + pdn_table->nic_type); netdev_info(dev, "pdn activated, nic_type=0x%x\n", nic->pdn_table.nic_type); -- cgit v1.2.3 From abb40c11c44d93d7d9d6fe42088c5cad9a852c2a Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Thu, 7 Nov 2013 20:29:23 +0530 Subject: Staging: gdm724x: Remove confusing macro gdm_lte_hci_send in gdm_lte.c This patch removes confusing macro gdm_lte_hci_send as stated in TODO list in file gdm_lte.c. It then fixes the place where the macro is used. Signed-off-by: Rashika Kheria Reviewed-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 5cf0f6f7f8d3..723cc270deb9 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -44,9 +44,6 @@ */ #define DEFAULT_MTU_SIZE 1500 -#define gdm_lte_hci_send(n, d, l) (\ - n->phy_dev->send_hci_func(n->phy_dev->priv_dev, d, l, NULL, NULL)) - #define gdm_lte_sdu_send(n, d, l, c, b, i, t) (\ n->phy_dev->send_sdu_func(n->phy_dev->priv_dev, d, l, n->pdn_table.dft_eps_id, 0, c, b, i, t)) @@ -507,7 +504,8 @@ static void gdm_lte_event_rcv(struct net_device *dev, u16 type, void *msg, int l { struct nic *nic = netdev_priv(dev); - gdm_lte_hci_send(nic, msg, len); + nic->phy_dev->send_hci_func(nic->phy_dev->priv_dev, msg, len, NULL, + NULL); } int gdm_lte_event_init(void) -- cgit v1.2.3 From 29ef8a53542ab4a6e0151978459d03996750d54b Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Fri, 8 Nov 2013 18:09:44 +0530 Subject: Staging: gdm724x: Use ALIGN() macro for dummy_cnt in gdm_mux.c As suggested in TODO list, this patch uses ALIGN() macro for variable dummy_cnt in functions up_to_host() and gdm_mux_send() in file gdm_mux.c. The macro has already been defined in include/linux/kernel.h, hence is not defined again. Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_mux.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 62163673976c..2fa3a5a6580f 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -158,7 +158,6 @@ static int up_to_host(struct mux_rx *r) unsigned int start_flag; unsigned int payload_size; unsigned short packet_type; - int remain; int dummy_cnt; u32 packet_size_sum = r->offset; int index; @@ -176,8 +175,7 @@ static int up_to_host(struct mux_rx *r) break; } - remain = (MUX_HEADER_SIZE + payload_size) % 4; - dummy_cnt = remain ? (4-remain) : 0; + dummy_cnt = ALIGN(MUX_HEADER_SIZE + payload_size, 4); if (len - packet_size_sum < MUX_HEADER_SIZE + payload_size + dummy_cnt) { @@ -361,7 +359,6 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, struct mux_pkt_header *mux_header; struct mux_tx *t = NULL; static u32 seq_num = 1; - int remain; int dummy_cnt; int total_len; int ret; @@ -375,8 +372,7 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, spin_lock_irqsave(&mux_dev->write_lock, flags); - remain = (MUX_HEADER_SIZE + len) % 4; - dummy_cnt = remain ? (4 - remain) : 0; + dummy_cnt = ALIGN(MUX_HEADER_SIZE + len, 4); total_len = len + MUX_HEADER_SIZE + dummy_cnt; -- cgit v1.2.3 From 95ee28ec64c9d16f5bcf7e7749ff30f652177659 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Fri, 8 Nov 2013 04:12:41 +0530 Subject: staging:wlags49_h2: Fix sparse warnings in sta_h25.c This patch fixes sparse warnings "Using plain integer as NULL pointer" in sta_h25.c Signed-off-by: Himangi Saraogi Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlags49_h2/sta_h25.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlags49_h2/sta_h25.c b/drivers/staging/wlags49_h2/sta_h25.c index 5b6f670d8ef2..eccd780ef135 100644 --- a/drivers/staging/wlags49_h2/sta_h25.c +++ b/drivers/staging/wlags49_h2/sta_h25.c @@ -5211,7 +5211,7 @@ static const CFG_PROG_STRCT fw_image_code[] = { 0000, 0x000F429B, // Start execution address }, - { 0000, 0000, 0000, 0000, 00000000, 0000, 00000000} + { 0000, 0000, 0000, 0000, 00000000, 0000, NULL} }; static const CFG_RANGE20_STRCT fw_image_infocompat[] = { @@ -5247,8 +5247,8 @@ memimage fw_image = { "FUPU7D37dhfwci\001C", //signature, , C/Bin type (CFG_PROG_STRCT *) fw_image_code, 0x000F429B, - 00000000, //(dummy) pdaplug - 00000000, //(dummy) priplug + NULL, //(dummy) pdaplug + NULL, //(dummy) priplug (CFG_RANGE20_STRCT *) fw_image_infocompat, (CFG_IDENTITY_STRCT *) fw_image_infoidentity, }; -- cgit v1.2.3 From e4607fcfb1cd5d869425e190a85f841fc910c4ca Mon Sep 17 00:00:00 2001 From: Chon Ming Lee Date: Wed, 6 Nov 2013 14:36:35 +0800 Subject: drm/i915/vlv: Make the vlv_dpio_read/vlv_dpio_write more PHY centric MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vlv_dpio_read/write should be describe more in PHY centric instead of display controller centric. Create a enum dpio_channel for channel index and enum dpio_phy for PHY index. This should better to gather for upcoming platform. v2: Rebase the code based on drm/i915/vlv: Fix typo in the DPIO register define. v3: Rename vlv_phy to dpio_phy_iosf_port and define additional macro DPIO_PHY, and remove unrelated change. (Ville) Suggested-by: Ville Syrjälä Signed-off-by: Chon Ming Lee Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 13 +++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 16 ++++++++++++---- drivers/gpu/drm/i915/intel_dp.c | 8 ++++---- drivers/gpu/drm/i915/intel_drv.h | 7 ++++--- drivers/gpu/drm/i915/intel_hdmi.c | 8 ++++---- drivers/gpu/drm/i915/intel_sideband.c | 13 ++----------- 7 files changed, 42 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index efca30dc6c57..c546316ac649 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -88,6 +88,18 @@ enum port { }; #define port_name(p) ((p) + 'A') +#define I915_NUM_PHYS_VLV 1 + +enum dpio_channel { + DPIO_CH0, + DPIO_CH1 +}; + +enum dpio_phy { + DPIO_PHY0, + DPIO_PHY1 +}; + enum intel_display_power_domain { POWER_DOMAIN_PIPE_A, POWER_DOMAIN_PIPE_B, @@ -1403,6 +1415,7 @@ typedef struct drm_i915_private { int num_shared_dpll; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; struct intel_ddi_plls ddi_plls; + int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; /* Reclocking support */ bool render_reclock_avail; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 29265638bf56..a8a5bcb521c7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -452,6 +452,9 @@ #define DPIO_SFR_BYPASS (1<<1) #define DPIO_CMNRST (1<<0) +#define DPIO_PHY(pipe) ((pipe) >> 1) +#define DPIO_PHY_IOSF_PORT(phy) (dev_priv->dpio_phy_iosf_port[phy]) + /* * Per pipe/PLL DPIO regs */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index abf509ce5e26..752d83019f36 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1361,6 +1361,7 @@ static void intel_init_dpio(struct drm_device *dev) if (!IS_VALLEYVIEW(dev)) return; + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; /* * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - * 6. De-assert cmn_reset/side_reset. Same as VLV X0. @@ -1494,18 +1495,25 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) POSTING_READ(DPLL(pipe)); } -void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) +void vlv_wait_port_ready(struct drm_i915_private *dev_priv, + struct intel_digital_port *dport) { u32 port_mask; - if (!port) + switch (dport->port) { + case PORT_B: port_mask = DPLL_PORTB_READY_MASK; - else + break; + case PORT_C: port_mask = DPLL_PORTC_READY_MASK; + break; + default: + BUG(); + } if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) WARN(1, "timed out waiting for port %c ready: 0x%08x\n", - 'B' + port, I915_READ(DPLL(0))); + 'B' + dport->port, I915_READ(DPLL(0))); } /** diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2584eb4bbf0b..34d605762a60 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1839,7 +1839,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; struct edp_power_seq power_seq; u32 val; @@ -1866,7 +1866,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) intel_enable_dp(encoder); - vlv_wait_port_ready(dev_priv, port); + vlv_wait_port_ready(dev_priv, dport); } static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) @@ -1876,7 +1876,7 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; /* Program Tx lane resets to default */ @@ -2033,7 +2033,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) unsigned long demph_reg_value, preemph_reg_value, uniqtranscale_reg_value; uint8_t train_set = intel_dp->train_set[0]; - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6d701e79b611..9134a5464dd5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -490,9 +490,9 @@ vlv_dport_to_channel(struct intel_digital_port *dport) { switch (dport->port) { case PORT_B: - return 0; + return DPIO_CH0; case PORT_C: - return 1; + return DPIO_CH1; default: BUG(); } @@ -637,7 +637,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, void intel_wait_for_vblank(struct drm_device *dev, int pipe); void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); -void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port); +void vlv_wait_port_ready(struct drm_i915_private *dev_priv, + struct intel_digital_port *dport); bool intel_get_load_detect_pipe(struct drm_connector *connector, struct drm_display_mode *mode, struct intel_load_detect_pipe *old); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 5b9143fc9b5a..61cff670ff3f 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1081,7 +1081,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; u32 val; @@ -1116,7 +1116,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) intel_enable_hdmi(encoder); - vlv_wait_port_ready(dev_priv, port); + vlv_wait_port_ready(dev_priv, dport); } static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) @@ -1126,7 +1126,7 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; if (!IS_VALLEYVIEW(dev)) @@ -1159,7 +1159,7 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int port = vlv_dport_to_channel(dport); + enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; /* Reset lanes to avoid HDMI flicker (VLV w/a) */ diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index d43e457b6961..cc6fbcde7d3d 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -176,27 +176,18 @@ void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) PUNIT_OPCODE_REG_WRITE, reg, &val); } -static u32 vlv_get_phy_port(enum pipe pipe) -{ - u32 port = IOSF_PORT_DPIO; - - WARN_ON ((pipe != PIPE_A) && (pipe != PIPE_B)); - - return port; -} - u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe), + vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)), DPIO_OPCODE_REG_READ, reg, &val); return val; } void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val) { - vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe), + vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)), DPIO_OPCODE_REG_WRITE, reg, &val); } -- cgit v1.2.3 From f2d91a2c556479713abbefec237cad4bc1d54b0d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 7 Nov 2013 09:48:57 +0100 Subject: drm/i915: tune reset dmesg output a bit We don't want any ERROR for simulated gpu hangs, otoh printing the error code when the reset failed for real should be interesting. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71333 lu hua Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 38a344694e35..c3e9485f38fe 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -731,14 +731,14 @@ int i915_reset(struct drm_device *dev) DRM_INFO("Simulated gpu hang, resetting stop_rings\n"); dev_priv->gpu_error.stop_rings = 0; if (ret == -ENODEV) { - DRM_ERROR("Reset not implemented, but ignoring " - "error for simulated gpu hangs\n"); + DRM_INFO("Reset not implemented, but ignoring " + "error for simulated gpu hangs\n"); ret = 0; } } if (ret) { - DRM_ERROR("Failed to reset chip.\n"); + DRM_ERROR("Failed to reset chip: %i\n", ret); mutex_unlock(&dev->struct_mutex); return ret; } -- cgit v1.2.3 From b596f52209ae6206dc01cd659008d26a5244d092 Mon Sep 17 00:00:00 2001 From: Ebru Akagunduz Date: Sun, 10 Nov 2013 23:16:58 +0200 Subject: Staging: rtl8187se: Fix Sparse Warnings This patch fixes the Sparse Warnings "symbol was not declared. Should it be static?" so it removes some extern expressions to r8180.h and it defines some extern expressions in ieee80211.h Signed-off-by: Ebru Akagunduz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211.h | 3 +++ drivers/staging/rtl8187se/r8180.h | 10 ++++++++++ drivers/staging/rtl8187se/r8180_core.c | 10 ---------- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h index 7f015499cfae..ce8dcf79185c 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -90,6 +90,9 @@ #define IEEE_CRYPT_ALG_NAME_LEN 16 +extern int ieee80211_crypto_tkip_init(void); +extern void ieee80211_crypto_tkip_exit(void); + //by amy for ps typedef struct ieee_param { u32 cmd; diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h index d052f4a9a839..84957be01b4f 100644 --- a/drivers/staging/rtl8187se/r8180.h +++ b/drivers/staging/rtl8187se/r8180.h @@ -687,3 +687,13 @@ void rtl8180_rate_adapter(struct work_struct * work); bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u32 ChangeSource); #endif + +/* fun with the built-in ieee80211 stack... */ +extern int ieee80211_crypto_init(void); +extern void ieee80211_crypto_deinit(void); +extern int ieee80211_crypto_tkip_init(void); +extern void ieee80211_crypto_tkip_exit(void); +extern int ieee80211_crypto_ccmp_init(void); +extern void ieee80211_crypto_ccmp_exit(void); +extern int ieee80211_crypto_wep_init(void); +extern void ieee80211_crypto_wep_exit(void); diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 2462ced68215..d4ba717ff0df 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -3310,16 +3310,6 @@ static void rtl8180_pci_remove(struct pci_dev *pdev) DMESG("wlan driver removed\n"); } -/* fun with the built-in ieee80211 stack... */ -extern int ieee80211_crypto_init(void); -extern void ieee80211_crypto_deinit(void); -extern int ieee80211_crypto_tkip_init(void); -extern void ieee80211_crypto_tkip_exit(void); -extern int ieee80211_crypto_ccmp_init(void); -extern void ieee80211_crypto_ccmp_exit(void); -extern int ieee80211_crypto_wep_init(void); -extern void ieee80211_crypto_wep_exit(void); - static int __init rtl8180_pci_module_init(void) { int ret; -- cgit v1.2.3 From 52fdda40f65422d6e88df599169607f442c36267 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 20:38:20 +0530 Subject: Staging: keucr: Move the declaration of variable ErrXDCode in smilsub.c This patch moves the declaration of variable ErrXDCode to file smilsub.c since this is the only file which uses it. Hence, it also removes extern declaration from the header file smil.h and unnecessary declaration in smilmain.c Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smil.h | 1 - drivers/staging/keucr/smilmain.c | 1 - drivers/staging/keucr/smilsub.c | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smil.h b/drivers/staging/keucr/smil.h index 1538d7bd600f..fe1d5dc7d530 100644 --- a/drivers/staging/keucr/smil.h +++ b/drivers/staging/keucr/smil.h @@ -193,7 +193,6 @@ struct keucr_media_area { extern BYTE IsSSFDCCompliance; extern BYTE IsXDCompliance; -extern DWORD ErrXDCode; extern DWORD ErrCode; extern WORD ReadBlock; extern WORD WriteBlock; diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c index ed15c3531eb9..4e81c7adf74c 100644 --- a/drivers/staging/keucr/smilmain.c +++ b/drivers/staging/keucr/smilmain.c @@ -25,7 +25,6 @@ static int Make_D_LogTable(struct us_data *); static int MarkFail_D_PhyOneBlock(struct us_data *); -DWORD ErrXDCode; DWORD ErrCode; static BYTE WorkBuf[SECTSIZE]; static BYTE Redundant[REDTSIZE]; diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c index ea3c747b3a28..a58c6c557a19 100644 --- a/drivers/staging/keucr/smilsub.c +++ b/drivers/staging/keucr/smilsub.c @@ -7,6 +7,7 @@ #include "smil.h" static BYTE _Check_D_DevCode(BYTE); +static DWORD ErrXDCode; struct keucr_media_info Ssfdc; struct keucr_media_address Media; -- cgit v1.2.3 From 665fba0e1d28df9f2f4659991063e90040d62917 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 20:39:34 +0530 Subject: Staging: keucr: Move the declaration of variable ErrCode in smilmain.c This patch moves the declaration of variable ErrCode to file smilmain.c since this is the only file which uses it. Hence, it also removes extern declaration from the header file smil.h. Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smil.h | 1 - drivers/staging/keucr/smilmain.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smil.h b/drivers/staging/keucr/smil.h index fe1d5dc7d530..420529e884c6 100644 --- a/drivers/staging/keucr/smil.h +++ b/drivers/staging/keucr/smil.h @@ -193,7 +193,6 @@ struct keucr_media_area { extern BYTE IsSSFDCCompliance; extern BYTE IsXDCompliance; -extern DWORD ErrCode; extern WORD ReadBlock; extern WORD WriteBlock; extern DWORD MediaChange; diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c index 4e81c7adf74c..02f73bfcd286 100644 --- a/drivers/staging/keucr/smilmain.c +++ b/drivers/staging/keucr/smilmain.c @@ -25,7 +25,7 @@ static int Make_D_LogTable(struct us_data *); static int MarkFail_D_PhyOneBlock(struct us_data *); -DWORD ErrCode; +static DWORD ErrCode; static BYTE WorkBuf[SECTSIZE]; static BYTE Redundant[REDTSIZE]; static BYTE WorkRedund[REDTSIZE]; -- cgit v1.2.3 From 91c954dde335ff48e95074e57e40321f09851d96 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 20:41:04 +0530 Subject: Staging: keucr: Move the declaration of variable IsSSFDCCompliance in smilsub.c This patch moves the declaration of variable IsSSFDCCompliance to file smilsub.c since this is the only file which uses it. Hence, it also removes extern declaration from the header file smil.h and unnecessary declaration in smilmain.c Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smil.h | 2 -- drivers/staging/keucr/smilmain.c | 1 - drivers/staging/keucr/smilsub.c | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smil.h b/drivers/staging/keucr/smil.h index 420529e884c6..b8851661c8f1 100644 --- a/drivers/staging/keucr/smil.h +++ b/drivers/staging/keucr/smil.h @@ -189,8 +189,6 @@ struct keucr_media_area { WORD PhyBlock; /* Physical Block Number on Zone 0 */ }; - -extern BYTE IsSSFDCCompliance; extern BYTE IsXDCompliance; extern WORD ReadBlock; diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c index 02f73bfcd286..a2691f59391d 100644 --- a/drivers/staging/keucr/smilmain.c +++ b/drivers/staging/keucr/smilmain.c @@ -44,7 +44,6 @@ static BYTE BitData[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; #define Clr_D_Bit(a, b) (a[(BYTE)((b) / 8)] &= ~BitData[(b) % 8]) #define Chk_D_Bit(a, b) (a[(BYTE)((b) / 8)] & BitData[(b) % 8]) -BYTE IsSSFDCCompliance; BYTE IsXDCompliance; diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c index a58c6c557a19..2f36e06c2718 100644 --- a/drivers/staging/keucr/smilsub.c +++ b/drivers/staging/keucr/smilsub.c @@ -8,6 +8,7 @@ static BYTE _Check_D_DevCode(BYTE); static DWORD ErrXDCode; +static BYTE IsSSFDCCompliance; struct keucr_media_info Ssfdc; struct keucr_media_address Media; -- cgit v1.2.3 From f6daf9e6880da85beaf38718ac264e8922988750 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 20:42:35 +0530 Subject: Staging: keucr: Move the declaration of variable IsXDCompliance in smilsub.c This patch moves the declaration of variable IsXDCompliance to file smilsub.c since this is the only file which uses it. Hence, it also removes extern declaration from the header file smil.h and unnecessary declaration in smilmain.c Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smil.h | 2 -- drivers/staging/keucr/smilmain.c | 3 --- drivers/staging/keucr/smilsub.c | 1 + 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/keucr/smil.h b/drivers/staging/keucr/smil.h index b8851661c8f1..fff6c9e6164a 100644 --- a/drivers/staging/keucr/smil.h +++ b/drivers/staging/keucr/smil.h @@ -189,8 +189,6 @@ struct keucr_media_area { WORD PhyBlock; /* Physical Block Number on Zone 0 */ }; -extern BYTE IsXDCompliance; - extern WORD ReadBlock; extern WORD WriteBlock; extern DWORD MediaChange; diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c index a2691f59391d..9434cda885ca 100644 --- a/drivers/staging/keucr/smilmain.c +++ b/drivers/staging/keucr/smilmain.c @@ -44,9 +44,6 @@ static BYTE BitData[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; #define Clr_D_Bit(a, b) (a[(BYTE)((b) / 8)] &= ~BitData[(b) % 8]) #define Chk_D_Bit(a, b) (a[(BYTE)((b) / 8)] & BitData[(b) % 8]) -BYTE IsXDCompliance; - - /* ----- SM_FreeMem() ------------------------------------------------- */ int SM_FreeMem(void) { diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c index 2f36e06c2718..16da9a9b4033 100644 --- a/drivers/staging/keucr/smilsub.c +++ b/drivers/staging/keucr/smilsub.c @@ -9,6 +9,7 @@ static BYTE _Check_D_DevCode(BYTE); static DWORD ErrXDCode; static BYTE IsSSFDCCompliance; +static BYTE IsXDCompliance; struct keucr_media_info Ssfdc; struct keucr_media_address Media; -- cgit v1.2.3 From 18278771f42ed5ab2fbf730947790f1f433ef8f1 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 11 Nov 2013 19:27:05 +0200 Subject: staging: vt6655: use netdev_* instead of printk Checkpatch.pl gave the following warnings WARNING: printk() should include KERN_ facility level After fixing these with KERN_INFO facility level, it was suggested to use netdev_ instead of printk() with KERN_INFO facility. Used netdev_dbg for the statements inside of PLICE_DEBUG #ifdef, as debugging shouldn't rely on compile options and netdev_info for one printk which wasn't inside any #ifdef PLICE_DEBUG. Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Suggested-by: Greg Kroah-Hartman Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 5995dc203c79..8214e4ba2b43 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -846,9 +846,8 @@ BSSvUpdateAPNode( pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxSuppRate; pMgmt->sNodeDBTable[0].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*pwCapInfo); pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND; -#ifdef PLICE_DEBUG - printk("BSSvUpdateAPNode:MaxSuppRate is %d\n", pMgmt->sNodeDBTable[0].wMaxSuppRate); -#endif + netdev_dbg(pDevice->dev, "BSSvUpdateAPNode:MaxSuppRate is %d\n", + pMgmt->sNodeDBTable[0].wMaxSuppRate); /* auto rate fallback function initiation */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate); }; @@ -889,9 +888,9 @@ BSSvAddMulticastNode( &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) ); pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxBasicRate; -#ifdef PLICE_DEBUG - printk("BSSvAddMultiCastNode:pMgmt->sNodeDBTable[0].wTxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate); -#endif + netdev_dbg(pDevice->dev, + "BSSvAddMultiCastNode:pMgmt->sNodeDBTable[0].wTxDataRate is %d\n", + pMgmt->sNodeDBTable[0].wTxDataRate); pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND; }; @@ -990,7 +989,7 @@ start: pDevice->byReAssocCount++; /* 10 sec timeout */ if ((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) { - printk("Re-association timeout!!!\n"); + netdev_info(pDevice->dev, "Re-association timeout!!!\n"); pDevice->byReAssocCount = 0; #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT { @@ -1054,13 +1053,13 @@ start: } else { /* ii = 0 reserved for unicast AP node (Infra STA) */ if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) -#ifdef PLICE_DEBUG - printk("SecondCallback:Before:TxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate); -#endif + netdev_dbg(pDevice->dev, + "SecondCallback:Before:TxDataRate is %d\n", + pMgmt->sNodeDBTable[0].wTxDataRate); RATEvTxRateFallBack((void *)pDevice, &(pMgmt->sNodeDBTable[ii])); -#ifdef PLICE_DEBUG - printk("SecondCallback:After:TxDataRate is %d\n", pMgmt->sNodeDBTable[0].wTxDataRate); -#endif + netdev_dbg(pDevice->dev, + "SecondCallback:After:TxDataRate is %d\n", + pMgmt->sNodeDBTable[0].wTxDataRate); } -- cgit v1.2.3 From a777289800a3b767cec3f5974b784e0e0a61c68e Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 11 Nov 2013 19:27:06 +0200 Subject: staging: vt6655: delete unnecessary whitespace before a quoted newline This patch silences the following type of warnings: WARNING: unnecessary whitespace before a quoted newline Signed-off-by: Teodora Baluta Reviewed-by: Lisa Nguyen Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 8214e4ba2b43..3c0a062cd098 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -849,7 +849,7 @@ BSSvUpdateAPNode( netdev_dbg(pDevice->dev, "BSSvUpdateAPNode:MaxSuppRate is %d\n", pMgmt->sNodeDBTable[0].wMaxSuppRate); /* auto rate fallback function initiation */ - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->sNodeDBTable[0].wTxDataRate = %d\n", pMgmt->sNodeDBTable[0].wTxDataRate); }; /*+ @@ -1067,11 +1067,11 @@ start: /* check if pending PS queue */ if (pMgmt->sNodeDBTable[ii].wEnQueueCnt != 0) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending \n", + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending\n", ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); if ((ii > 0) && (pMgmt->sNodeDBTable[ii].wEnQueueCnt > 15)) { BSSvRemoveOneNode(pDevice, ii); - DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Pending many queues PS STA Index = %d remove \n", ii); + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Pending many queues PS STA Index = %d remove\n", ii); continue; } } -- cgit v1.2.3 From 2b0c2a48b62d57213fee4e780c28f06d066f1f71 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 11 Nov 2013 19:27:07 +0200 Subject: staging: vt6655: delete explicit comparison to bool This patch fixes all bool tests by deleting the comparison. Most of these were detected using coccinelle and silence the following type of coccinelle warnings for drivers/staging/vt6655/bssdb.c file: WARNING: Comparison to bool Signed-off-by: Teodora Baluta Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/bssdb.c | 50 ++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c index 3c0a062cd098..d7efd0173a9a 100644 --- a/drivers/staging/vt6655/bssdb.c +++ b/drivers/staging/vt6655/bssdb.c @@ -142,10 +142,10 @@ BSSpSearchBSSList( /* match BSSID first */ for (ii = 0; ii < MAX_BSS_NUM; ii++) { pCurrBSS = &(pMgmt->sBSSList[ii]); - if (pDevice->bLinkPass == false) + if (!pDevice->bLinkPass) pCurrBSS->bSelected = false; if ((pCurrBSS->bActive) && - (pCurrBSS->bSelected == false)) { + (!pCurrBSS->bSelected)) { if (ether_addr_equal(pCurrBSS->abyBSSID, pbyBSSID)) { if (pSSID != NULL) { @@ -390,7 +390,7 @@ BSSbInsertToBSSList( if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; } else { - if (pBSSList->sERP.bERPExist == true) + if (pBSSList->sERP.bERPExist) pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; else pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; @@ -431,7 +431,7 @@ BSSbInsertToBSSList( } } - if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pBSSList->bWPA2Valid == true)) { + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || pBSSList->bWPA2Valid) { PSKeyItem pTransmitKey = NULL; bool bIs802_1x = false; @@ -441,13 +441,13 @@ BSSbInsertToBSSList( break; } } - if ((bIs802_1x == true) && (pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len) && + if (bIs802_1x && (pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len) && (!memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID, pSSID->len))) { bAdd_PMKID_Candidate((void *)pDevice, pBSSList->abyBSSID, &pBSSList->sRSNCapObj); - if ((pDevice->bLinkPass == true) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { - if ((KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, PAIRWISE_KEY, &pTransmitKey) == true) || - (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, GROUP_KEY, &pTransmitKey) == true)) { + if (pDevice->bLinkPass && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + if (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, PAIRWISE_KEY, &pTransmitKey) || + KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, GROUP_KEY, &pTransmitKey)) { pDevice->gsPMKIDCandidate.StatusType = Ndis802_11StatusType_PMKID_CandidateList; pDevice->gsPMKIDCandidate.Version = 1; @@ -466,13 +466,12 @@ BSSbInsertToBSSList( pBSSList->ldBmAverage[ii] = 0; } - if ((pIE_Country != NULL) && - (pMgmt->b11hEnable == true)) { + if ((pIE_Country != NULL) && pMgmt->b11hEnable) { set_country_info(pMgmt->pAdapter, pBSSList->eNetworkTypeInUse, pIE_Country); } - if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) { + if (bParsingQuiet && (pIE_Quiet != NULL)) { if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) && (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) { /* valid EID */ @@ -498,8 +497,7 @@ BSSbInsertToBSSList( } } - if ((bParsingQuiet == true) && - (pQuiet != NULL)) { + if (bParsingQuiet && (pQuiet != NULL)) { CARDbStartQuiet(pMgmt->pAdapter); } @@ -580,7 +578,7 @@ BSSbUpdateToBSSList( if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; } else { - if (pBSSList->sERP.bERPExist == true) + if (pBSSList->sERP.bERPExist) pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; else pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; @@ -633,13 +631,12 @@ BSSbUpdateToBSSList( } } - if ((pIE_Country != NULL) && - (pMgmt->b11hEnable == true)) { + if ((pIE_Country != NULL) && pMgmt->b11hEnable) { set_country_info(pMgmt->pAdapter, pBSSList->eNetworkTypeInUse, pIE_Country); } - if ((bParsingQuiet == true) && (pIE_Quiet != NULL)) { + if (bParsingQuiet && (pIE_Quiet != NULL)) { if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) && (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) { /* valid EID */ @@ -665,8 +662,7 @@ BSSbUpdateToBSSList( } } - if ((bParsingQuiet == true) && - (pQuiet != NULL)) { + if (bParsingQuiet && (pQuiet != NULL)) { CARDbStartQuiet(pMgmt->pAdapter); } @@ -934,10 +930,12 @@ BSSvSecondCallBack( /* 2008-4-14 by chester for led issue */ #ifdef FOR_LED_ON_NOTEBOOK MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO); - if (((!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->bHWRadioOff == false)) || ((pDevice->byGPIO & GPIO0_DATA) && (pDevice->bHWRadioOff == true))) && (cc == false)) { + if (((!(pDevice->byGPIO & GPIO0_DATA) && (!pDevice->bHWRadioOff)) || + ((pDevice->byGPIO & GPIO0_DATA) && pDevice->bHWRadioOff)) && + (!cc)) { cc = true; - } else if (cc == true) { - if (pDevice->bHWRadioOff == true) { + } else if (cc) { + if (pDevice->bHWRadioOff) { if (!(pDevice->byGPIO & GPIO0_DATA)) { if (status == 1) goto start; @@ -988,7 +986,7 @@ start: { pDevice->byReAssocCount++; /* 10 sec timeout */ - if ((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) { + if ((pDevice->byReAssocCount > 10) && (!pDevice->bLinkPass)) { netdev_info(pDevice->dev, "Re-association timeout!!!\n"); pDevice->byReAssocCount = 0; #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT @@ -1000,7 +998,7 @@ start: wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); } #endif - } else if (pDevice->bLinkPass == true) + } else if (pDevice->bLinkPass) pDevice->byReAssocCount = 0; } @@ -1188,7 +1186,7 @@ start: * network manager support need not do * Roaming scan??? */ - if (pDevice->bWPASuppWextEnabled == true) + if (pDevice->bWPASuppWextEnabled) pDevice->uAutoReConnectTime = 0; #endif } else { @@ -1520,7 +1518,7 @@ void s_uCalculateLinkQual( TxOkRatio = (TxCnt < 6) ? 4000 : ((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt); RxOkRatio = (RxCnt < 6) ? 2000 : ((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); /* decide link quality */ - if (pDevice->bLinkPass != true) { + if (!pDevice->bLinkPass) { pDevice->scStatistic.LinkQuality = 0; pDevice->scStatistic.SignalStren = 0; } else { -- cgit v1.2.3 From 2dce674891c1d2708715fecaad222362db53f815 Mon Sep 17 00:00:00 2001 From: Matina Maria Trompouki Date: Mon, 11 Nov 2013 00:22:51 +0000 Subject: Staging: ozwpan: fixed whitespace before semicolon This patch removes the following warning reported by checkpatch.pl WARNING: space prohibited before semicolon drivers/staging/ozwpan/ozproto.c Signed-off-by: Matina Maria Trompouki Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozproto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 88714ec85705..9f2dffe6e131 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -337,7 +337,7 @@ static void oz_rx_frame(struct sk_buff *skb) oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); mac_hdr = skb_mac_header(skb); - src_addr = &mac_hdr[ETH_ALEN] ; + src_addr = &mac_hdr[ETH_ALEN]; length = skb->len; /* Check the version field */ -- cgit v1.2.3 From 70a51d284be020a310d9f5ec989cfe2bbce5ecd6 Mon Sep 17 00:00:00 2001 From: Matina Maria Trompouki Date: Mon, 11 Nov 2013 01:11:22 +0000 Subject: Staging: lirc: fix quoted string split across lines This patch removes the following warning reported by checkpatch.pl WARNING: quoted string split across lines drivers/staging/media/lirc/lirc_igorplugusb.c drivers/staging/media/lirc/lirc_imon.c drivers/staging/media/lirc/lirc_serial.c drivers/staging/media/lirc/lirc_zilog.c Signed-off-by: Matina Maria Trompouki Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_igorplugusb.c | 4 ++-- drivers/staging/media/lirc/lirc_imon.c | 8 ++++---- drivers/staging/media/lirc/lirc_serial.c | 4 ++-- drivers/staging/media/lirc/lirc_zilog.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c index 28c8b0bcf5b2..f2dcc4a292da 100644 --- a/drivers/staging/media/lirc/lirc_igorplugusb.c +++ b/drivers/staging/media/lirc/lirc_igorplugusb.c @@ -363,8 +363,8 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf) /*dummy*/ir->buf_in, /*dummy*/ir->len_in, /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); if (ret < 0) - printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: " - "error %d\n", ir->devnum, ret); + printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", + ir->devnum, ret); return 0; } else if (ret < 0) printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n", diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index ab2ae115b524..663c963b16df 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -878,8 +878,8 @@ static int imon_probe(struct usb_interface *interface, alloc_status = 7; goto unlock; } else - dev_info(dev, "Registered iMON driver " - "(lirc minor: %d)\n", lirc_minor); + dev_info(dev, "Registered iMON driver (lirc minor: %d)\n", + lirc_minor); /* Needed while unregistering! */ driver->minor = lirc_minor; @@ -923,8 +923,8 @@ static int imon_probe(struct usb_interface *interface, if (usb_register_dev(interface, &imon_class)) { /* Not a fatal error, so ignore */ - dev_info(dev, "%s: could not get a minor number for " - "display\n", __func__); + dev_info(dev, "%s: could not get a minor number for display\n", + __func__); } } diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index 23043bd70e7e..c1f965d42ab0 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -428,8 +428,8 @@ static int init_timing_params(unsigned int new_duty_cycle, period = 256 * 1000000L / freq; pulse_width = period * duty_cycle / 100; space_width = period - pulse_width; - dprintk("in init_timing_params, freq=%d pulse=%ld, " - "space=%ld\n", freq, pulse_width, space_width); + dprintk("in init_timing_params, freq=%d pulse=%ld, space=%ld\n", + freq, pulse_width, space_width); return 0; } #endif /* USE_RDTSC */ diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 11d5338b4f2f..5c255ffcb877 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -764,8 +764,8 @@ static int fw_load(struct IR_tx *tx) /* Request codeset data file */ ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); if (ret != 0) { - zilog_error("firmware haup-ir-blaster.bin not available " - "(%d)\n", ret); + zilog_error("firmware haup-ir-blaster.bin not available (%d)\n", + ret); ret = ret < 0 ? ret : -EFAULT; goto out; } -- cgit v1.2.3 From c79bfed605337be42860398336523769aad19a13 Mon Sep 17 00:00:00 2001 From: Matina Maria Trompouki Date: Mon, 11 Nov 2013 00:29:12 +0000 Subject: Staging: lirc: fix line over 80 characters This patch removes the following warning reported by checkpatch.pl WARNING: line over 80 characters drivers/staging/media/lirc/lirc_imon.c Signed-off-by: Matina Maria Trompouki Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_imon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index 663c963b16df..c7d6667e7d14 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -808,7 +808,8 @@ static int imon_probe(struct usb_interface *interface, /* Input endpoint is mandatory */ if (!ir_ep_found) { - dev_err(dev, "%s: no valid input (IR) endpoint found.\n", __func__); + dev_err(dev, "%s: no valid input (IR) endpoint found.\n", + __func__); retval = -ENODEV; alloc_status = 2; goto alloc_status_switch; -- cgit v1.2.3 From b73db54750482cf3910046c82a84ce8c1684dfbe Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 11:52:31 +0530 Subject: Staging: dgrp: Refactor the function dgrp_receive() in drrp_net_ops.c The function dgrp_receive() in dgrp_net_ops.c is too long and can be refactored. It uses various switch statements and goto labels. I have removed a label called data and tried to extract a new function out of it called as handle_data_in_packet(). This helps to make the code more modularize and simple to read and understand. Signed-off-by: Rashika Kheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgrp/dgrp_net_ops.c | 330 +++++++++++++++++++----------------- 1 file changed, 175 insertions(+), 155 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c index 33ac7fb88cbd..1f61b89eca44 100644 --- a/drivers/staging/dgrp/dgrp_net_ops.c +++ b/drivers/staging/dgrp/dgrp_net_ops.c @@ -2232,6 +2232,177 @@ done: return rtn; } +/* + * Common Packet Handling code + */ + +static void handle_data_in_packet(struct nd_struct *nd, struct ch_struct *ch, + long dlen, long plen, int n1, u8 *dbuf) +{ + char *error; + long n; + long remain; + u8 *buf; + u8 *b; + + remain = nd->nd_remain; + nd->nd_tx_work = 1; + + /* + * Otherwise data should appear only when we are + * in the CS_READY state. + */ + + if (ch->ch_state < CS_READY) { + error = "Data received before RWIN established"; + nd->nd_remain = 0; + nd->nd_state = NS_SEND_ERROR; + nd->nd_error = error; + } + + /* + * Assure that the data received is within the + * allowable window. + */ + + n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff; + + if (dlen > n) { + error = "Receive data overrun"; + nd->nd_remain = 0; + nd->nd_state = NS_SEND_ERROR; + nd->nd_error = error; + } + + /* + * If we received 3 or less characters, + * assume it is a human typing, and set RTIME + * to 10 milliseconds. + * + * If we receive 10 or more characters, + * assume its not a human typing, and set RTIME + * to 100 milliseconds. + */ + + if (ch->ch_edelay != DGRP_RTIME) { + if (ch->ch_rtime != ch->ch_edelay) { + ch->ch_rtime = ch->ch_edelay; + ch->ch_flag |= CH_PARAM; + } + } else if (dlen <= 3) { + if (ch->ch_rtime != 10) { + ch->ch_rtime = 10; + ch->ch_flag |= CH_PARAM; + } + } else { + if (ch->ch_rtime != DGRP_RTIME) { + ch->ch_rtime = DGRP_RTIME; + ch->ch_flag |= CH_PARAM; + } + } + + /* + * If a portion of the packet is outside the + * buffer, shorten the effective length of the + * data packet to be the amount of data received. + */ + + if (remain < plen) + dlen -= plen - remain; + + /* + * Detect if receive flush is now complete. + */ + + if ((ch->ch_flag & CH_RX_FLUSH) != 0 && + ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >= + ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) { + ch->ch_flag &= ~CH_RX_FLUSH; + } + + /* + * If we are ready to receive, move the data into + * the receive buffer. + */ + + ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff; + + if (ch->ch_state == CS_READY && + (ch->ch_tun.un_open_count != 0) && + (ch->ch_tun.un_flag & UN_CLOSING) == 0 && + (ch->ch_cflag & CF_CREAD) != 0 && + (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 && + (ch->ch_send & RR_RX_FLUSH) == 0) { + + if (ch->ch_rin + dlen >= RBUF_MAX) { + n = RBUF_MAX - ch->ch_rin; + + memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n); + + ch->ch_rin = 0; + dbuf += n; + dlen -= n; + } + + memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen); + + ch->ch_rin += dlen; + + + /* + * If we are not in fastcook mode, or + * if there is a fastcook thread + * waiting for data, send the data to + * the line discipline. + */ + + if ((ch->ch_flag & CH_FAST_READ) == 0 || + ch->ch_inwait != 0) { + dgrp_input(ch); + } + + /* + * If there is a read thread waiting + * in select, and we are in fastcook + * mode, wake him up. + */ + + if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) && + (ch->ch_flag & CH_FAST_READ) != 0) + wake_up_interruptible(&ch->ch_tun.un_tty->read_wait); + + /* + * Wake any thread waiting in the + * fastcook loop. + */ + + if ((ch->ch_flag & CH_INPUT) != 0) { + ch->ch_flag &= ~CH_INPUT; + wake_up_interruptible(&ch->ch_flag_wait); + } + } + + /* + * Fabricate and insert a data packet header to + * preced the remaining data when it comes in. + */ + + if (remain < plen) { + dlen = plen - remain; + b = buf; + + b[0] = 0x90 + n1; + put_unaligned_be16(dlen, b + 1); + + remain = 3; + if (remain > 0 && b != buf) + memcpy(buf, b, remain); + + nd->nd_remain = remain; + return; + } +} + /** * dgrp_receive() -- decode data packets received from the remote PortServer. * @nd: pointer to a node structure @@ -2306,7 +2477,8 @@ static void dgrp_receive(struct nd_struct *nd) plen = dlen + 1; dbuf = b + 1; - goto data; + handle_data_in_packet(nd, ch, dlen, plen, n1, dbuf); + break; /* * Process 2-byte header data packet. @@ -2320,7 +2492,8 @@ static void dgrp_receive(struct nd_struct *nd) plen = dlen + 2; dbuf = b + 2; - goto data; + handle_data_in_packet(nd, ch, dlen, plen, n1, dbuf); + break; /* * Process 3-byte header data packet. @@ -2335,159 +2508,6 @@ static void dgrp_receive(struct nd_struct *nd) dbuf = b + 3; - /* - * Common packet handling code. - */ - -data: - nd->nd_tx_work = 1; - - /* - * Otherwise data should appear only when we are - * in the CS_READY state. - */ - - if (ch->ch_state < CS_READY) { - error = "Data received before RWIN established"; - goto prot_error; - } - - /* - * Assure that the data received is within the - * allowable window. - */ - - n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff; - - if (dlen > n) { - error = "Receive data overrun"; - goto prot_error; - } - - /* - * If we received 3 or less characters, - * assume it is a human typing, and set RTIME - * to 10 milliseconds. - * - * If we receive 10 or more characters, - * assume its not a human typing, and set RTIME - * to 100 milliseconds. - */ - - if (ch->ch_edelay != DGRP_RTIME) { - if (ch->ch_rtime != ch->ch_edelay) { - ch->ch_rtime = ch->ch_edelay; - ch->ch_flag |= CH_PARAM; - } - } else if (dlen <= 3) { - if (ch->ch_rtime != 10) { - ch->ch_rtime = 10; - ch->ch_flag |= CH_PARAM; - } - } else { - if (ch->ch_rtime != DGRP_RTIME) { - ch->ch_rtime = DGRP_RTIME; - ch->ch_flag |= CH_PARAM; - } - } - - /* - * If a portion of the packet is outside the - * buffer, shorten the effective length of the - * data packet to be the amount of data received. - */ - - if (remain < plen) - dlen -= plen - remain; - - /* - * Detect if receive flush is now complete. - */ - - if ((ch->ch_flag & CH_RX_FLUSH) != 0 && - ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >= - ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) { - ch->ch_flag &= ~CH_RX_FLUSH; - } - - /* - * If we are ready to receive, move the data into - * the receive buffer. - */ - - ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff; - - if (ch->ch_state == CS_READY && - (ch->ch_tun.un_open_count != 0) && - (ch->ch_tun.un_flag & UN_CLOSING) == 0 && - (ch->ch_cflag & CF_CREAD) != 0 && - (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 && - (ch->ch_send & RR_RX_FLUSH) == 0) { - - if (ch->ch_rin + dlen >= RBUF_MAX) { - n = RBUF_MAX - ch->ch_rin; - - memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n); - - ch->ch_rin = 0; - dbuf += n; - dlen -= n; - } - - memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen); - - ch->ch_rin += dlen; - - - /* - * If we are not in fastcook mode, or - * if there is a fastcook thread - * waiting for data, send the data to - * the line discipline. - */ - - if ((ch->ch_flag & CH_FAST_READ) == 0 || - ch->ch_inwait != 0) { - dgrp_input(ch); - } - - /* - * If there is a read thread waiting - * in select, and we are in fastcook - * mode, wake him up. - */ - - if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) && - (ch->ch_flag & CH_FAST_READ) != 0) - wake_up_interruptible(&ch->ch_tun.un_tty->read_wait); - - /* - * Wake any thread waiting in the - * fastcook loop. - */ - - if ((ch->ch_flag & CH_INPUT) != 0) { - ch->ch_flag &= ~CH_INPUT; - - wake_up_interruptible(&ch->ch_flag_wait); - } - } - - /* - * Fabricate and insert a data packet header to - * preced the remaining data when it comes in. - */ - - if (remain < plen) { - dlen = plen - remain; - b = buf; - - b[0] = 0x90 + n1; - put_unaligned_be16(dlen, b + 1); - - remain = 3; - goto done; - } break; /* -- cgit v1.2.3 From a23bb460aa28063a83c9e2b923218044e3fb4aab Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 12:09:58 +0530 Subject: Staging: gdm724x: Remove confusing macro gdm_lte_sdu_send in gdm_lte.c This patch removes confusing macro gdm_lte_sdu_send as stated in TODO list in file gdm_lte.c. It then fixes the place where the macro is used. Signed-off-by: Rashika Kheria Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 723cc270deb9..74a03608b2dd 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -44,9 +44,6 @@ */ #define DEFAULT_MTU_SIZE 1500 -#define gdm_lte_sdu_send(n, d, l, c, b, i, t) (\ - n->phy_dev->send_sdu_func(n->phy_dev->priv_dev, d, l, n->pdn_table.dft_eps_id, 0, c, b, i, t)) - #define IP_VERSION_4 4 #define IP_VERSION_6 6 @@ -449,13 +446,11 @@ static int gdm_lte_tx(struct sk_buff *skb, struct net_device *dev) sscanf(dev->name, "lte%d", &idx); - ret = gdm_lte_sdu_send(nic, - data_buf, - data_len, - tx_complete, - nic, - idx, - nic_type); + ret = nic->phy_dev->send_sdu_func(nic->phy_dev->priv_dev, + data_buf, data_len, + nic->pdn_table.dft_eps_id, 0, + tx_complete, nic, idx, + nic_type); if (ret == TX_NO_BUFFER || ret == TX_NO_SPC) { netif_stop_queue(dev); -- cgit v1.2.3 From 1fb35c297663e80aeee863997aa775ca285bf1c2 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Mon, 11 Nov 2013 12:35:12 +0530 Subject: Staging: tidspbridge: Remove unnecessary newline character in dmm.c This patch removes an extra newline character in pmgr/dmm.c. Signed-off-by: Rashika Kheria Suggested-by: Greg KH Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/pmgr/dmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c index 04a6b0669fa9..fcf564aa566d 100644 --- a/drivers/staging/tidspbridge/pmgr/dmm.c +++ b/drivers/staging/tidspbridge/pmgr/dmm.c @@ -479,7 +479,7 @@ u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr) freemem / (1024 * 1024)); dev_info(bridge, "Total DSP VA USED memory= %d Mbytes\n", (((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024)); - dev_info(bridge, "DSP VA - Biggest FREE block = %d Mbytes\n\n", + dev_info(bridge, "DSP VA - Biggest FREE block = %d Mbytes\n", (bigsize * PG_SIZE4K / (1024 * 1024))); return 0; -- cgit v1.2.3 From b047a8dc30a84d272d230b76b41ca2d0730f0d97 Mon Sep 17 00:00:00 2001 From: Dulshani Gunawardhana Date: Mon, 11 Nov 2013 15:47:17 +0530 Subject: staging: lustre: Fix incorrect type in assignment Fix the following sparse warings in local_storage.c. drivers/staging/lustre/lustre/obdclass/local_storage.c:269:16:warning:incorrect type in assignment (different base types) Signed-off-by: Dulshani Gunawardhana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/local_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.c b/drivers/staging/lustre/lustre/obdclass/local_storage.c index cc19fbab0207..51ab7f413004 100644 --- a/drivers/staging/lustre/lustre/obdclass/local_storage.c +++ b/drivers/staging/lustre/lustre/obdclass/local_storage.c @@ -246,7 +246,7 @@ int local_object_create(const struct lu_env *env, struct dt_object_format *dof, struct thandle *th) { struct dt_thread_info *dti = dt_info(env); - obd_id lastid; + __le64 lastid; int rc; rc = dt_create(env, o, attr, NULL, dof, th); -- cgit v1.2.3 From 20a6264abf8bd77bbfcbfc9e7a279203f1630410 Mon Sep 17 00:00:00 2001 From: Dulshani Gunawardhana Date: Mon, 11 Nov 2013 15:30:44 +0530 Subject: staging:lustre: Fix variable type declaration Fix the following sparse warnings generated by AND-ing FMODE_* constant with a normal integer. drivers/staging/lustre/lustre/llite/file.c:102:32: warning: restricted fmode_t degrades to integer Signed-off-by: Dulshani Gunawardhana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 5e11107d4c66..b6fd03e45bb7 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -85,7 +85,7 @@ struct obd_client_handle { struct lu_fid och_fid; struct md_open_data *och_mod; __u32 och_magic; - int och_flags; + fmode_t och_flags; }; #define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed -- cgit v1.2.3 From 5fb0a2fa24441a71275e1c42eac1590938a1ec9f Mon Sep 17 00:00:00 2001 From: Dulshani Gunawardhana Date: Mon, 11 Nov 2013 21:47:56 +0530 Subject: staging: lustre: Fix sparse warning for one-bit signed bitfield Fix the following sparse warning: drivers/staging/lustre/lustre/llite/llite_internal.h:461:49: error:dubious one-bit signed bitfield Signed-off-by: Dulshani Gunawardhana Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 47e443d90fe1..fb7cbb5fa124 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -458,7 +458,7 @@ struct ll_sb_info { struct lu_fid ll_root_fid; /* root object fid */ int ll_flags; - int ll_umounting:1; + unsigned int ll_umounting:1; struct list_head ll_conn_chain; /* per-conn chain of SBs */ struct lustre_client_ocd ll_lco; -- cgit v1.2.3 From c265be0121154709a0b16f13c87ff58245ba81bc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:22 +0000 Subject: staging: comedi: remove unused command callback support The 'kcomedilib' module used to provide functions to allow asynchronous comedi commands to be set up from another kernel module, but now commands can only be set up by ioctls from user space via the core comedi module. Since support for commands initiated from kernel space has been dropped, the `cb_func` and `cb_arg` members of `struct comedi_async` are never set (although the `cb_mask` member is still used to mask comedi events). The `SRF_USER` bit of the comedi subdevice runflags is no longer needed to distinguish commands from user and kernel space since they only come from user space. Don't bother setting or testing the `SRF_USER` flag, and get rid of it, along with the `cb_func` and `cb_arg` members. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 21 +++++++-------------- drivers/staging/comedi/comedidev.h | 4 ---- 2 files changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index f3d59e2a1152..0d8565428abb 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1469,8 +1469,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & TRIG_WAKE_EOS) async->cb_mask |= COMEDI_CB_EOS; - comedi_set_subdevice_runflags(s, SRF_USER | SRF_ERROR | SRF_RUNNING, - SRF_USER | SRF_RUNNING); + comedi_set_subdevice_runflags(s, SRF_ERROR | SRF_RUNNING, SRF_RUNNING); /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with * comedi_read() or comedi_write() */ @@ -1700,8 +1699,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, return -EBUSY; ret = do_cancel(dev, s); - if (comedi_get_subdevice_runflags(s) & SRF_USER) - wake_up_interruptible(&s->async->wait_head); + wake_up_interruptible(&s->async->wait_head); return ret; } @@ -2368,16 +2366,11 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) } if (async->cb_mask & s->async->events) { - if (comedi_get_subdevice_runflags(s) & SRF_USER) { - wake_up_interruptible(&async->wait_head); - if (s->subdev_flags & SDF_CMD_READ) - kill_fasync(&dev->async_queue, SIGIO, POLL_IN); - if (s->subdev_flags & SDF_CMD_WRITE) - kill_fasync(&dev->async_queue, SIGIO, POLL_OUT); - } else { - if (async->cb_func) - async->cb_func(s->async->events, async->cb_arg); - } + wake_up_interruptible(&async->wait_head); + if (s->subdev_flags & SDF_CMD_READ) + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + if (s->subdev_flags & SDF_CMD_WRITE) + kill_fasync(&dev->async_queue, SIGIO, POLL_OUT); } s->async->events = 0; } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 143be8076a2e..38a4eebcd818 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -141,10 +141,7 @@ struct comedi_async { wait_queue_head_t wait_head; - /* callback stuff */ unsigned int cb_mask; - int (*cb_func) (unsigned int flags, void *); - void *cb_arg; int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x); @@ -240,7 +237,6 @@ void stop_polling(struct comedi_device *); /* subdevice runflags */ enum subdevice_runflags { - SRF_USER = 0x00000001, SRF_RT = 0x00000002, /* indicates an COMEDI_CB_ERROR event has occurred since the last * command was started */ -- cgit v1.2.3 From ab3cb2e30ec8223777f6ea4696ba24191ffc5c72 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:23 +0000 Subject: staging: comedi: add a couple of #includes to comedidev.h Two structures defined in "comedidev.h" have an element of type `spinlock_t`, so add `#include ` to declare it. One structure has an element of type `struct mutex` so add `#include ` to declare it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 38a4eebcd818..e2432471c390 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -20,6 +20,8 @@ #define _COMEDIDEV_H #include +#include +#include #include "comedi.h" -- cgit v1.2.3 From 2f3fdcd7ce935f6f2899ceab57dc8fe5286db3e1 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:24 +0000 Subject: staging: comedi: add rw_semaphore to protect against device detachment The 'read' and 'write' file operations on comedi devices do not use the main mutex in the `struct comedi_device` to avoid contention with ioctls that may take a while to complete. However, it is necessary to protect against the device being detached while the operation is in progress. Add member `struct rw_semaphore attach_lock` to `struct comedi_device` for this purpose and initialize it on creation. The actual locking and unlocking will be implemented by subsequent patches. Tasks that are attaching or detaching comedi devices will write-acquire the new semaphore whilst also holding the main mutex in the `struct comedi_device`. Tasks that wish to protect against the comedi device being detached need to acquire either the main mutex, or read-acquire the new semaphore, or both in that order. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 1 + drivers/staging/comedi/comedidev.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 0d8565428abb..a1705ed0b844 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -91,6 +91,7 @@ static void comedi_device_init(struct comedi_device *dev) { spin_lock_init(&dev->spinlock); mutex_init(&dev->mutex); + init_rwsem(&dev->attach_lock); dev->minor = -1; } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index e2432471c390..70de3558c74e 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "comedi.h" @@ -184,6 +185,7 @@ struct comedi_device { bool ioenabled:1; spinlock_t spinlock; struct mutex mutex; + struct rw_semaphore attach_lock; int n_subdevices; struct comedi_subdevice *subdevices; -- cgit v1.2.3 From bf11c134246e8f3cfa2582a3d2af84ed7dfd59b6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:25 +0000 Subject: staging: comedi: use attach_lock semaphore during attach and detach Acquire the `attach_lock` semaphore in the `struct comedi_device` while modifying the `attached` flag. This is a "write" acquire. Note that the main mutex in the `struct comedi_device` is also held at this time. Tasks wishing to check the device is attached will need to either acquire the main mutex, or "read" acquire the `attach_lock` semaphore, or both in that order. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 8f02bf66e20b..c398422e073d 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -133,10 +133,12 @@ static void cleanup_device(struct comedi_device *dev) void comedi_device_detach(struct comedi_device *dev) { + down_write(&dev->attach_lock); dev->attached = false; if (dev->driver) dev->driver->detach(dev); cleanup_device(dev); + up_write(&dev->attach_lock); } static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s) @@ -355,8 +357,9 @@ static int comedi_device_postconfig(struct comedi_device *dev) ret = __comedi_device_postconfig(dev); if (ret < 0) return ret; - smp_wmb(); + down_write(&dev->attach_lock); dev->attached = true; + up_write(&dev->attach_lock); return 0; } -- cgit v1.2.3 From 3867e20db4823c733710f11b65606a9ed7d297c2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:26 +0000 Subject: staging: comedi: cleanup_device() -> comedi_device_detach_cleanup() Rename the local function `cleanup_device()` to `comedi_device_detach_cleanup()`. It is only called from the `comedi_device_detach()` function and that is called from `comedi_device_cleanup()` and other places. The more specific function name seems less confusing. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index c398422e073d..1f44f2939f6a 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -95,7 +95,7 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) } EXPORT_SYMBOL_GPL(comedi_alloc_subdevices); -static void cleanup_device(struct comedi_device *dev) +static void comedi_device_detach_cleanup(struct comedi_device *dev) { int i; struct comedi_subdevice *s; @@ -137,7 +137,7 @@ void comedi_device_detach(struct comedi_device *dev) dev->attached = false; if (dev->driver) dev->driver->detach(dev); - cleanup_device(dev); + comedi_device_detach_cleanup(dev); up_write(&dev->attach_lock); } -- cgit v1.2.3 From 8da8c86f52e5487adfa2e3bae4d539e46f2714dd Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:27 +0000 Subject: staging: comedi: wake up async waiters when become non-busy Wake up all waiters on the comedi subdevice's async wait queue whenever the subdevice is marked "non-busy". This happens when an asynchronous command is cancelled or when a command is terminated and all data has been read or written. Note: use `wake_up_interruptible_all()` as we only use interruptible waits. Remove the call to `wake_up_interruptible()` from `do_cancel_ioctl()` as it will call `wake_up_interruptible_all()` indirectly via `do_cancel()` and `do_become_nonbusy()`. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index a1705ed0b844..9c85f01e847b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -563,12 +563,13 @@ static void do_become_nonbusy(struct comedi_device *dev, async->inttrig = NULL; kfree(async->cmd.chanlist); async->cmd.chanlist = NULL; + s->busy = NULL; + wake_up_interruptible_all(&s->async->wait_head); } else { dev_err(dev->class_dev, "BUG: (?) do_become_nonbusy called with async=NULL\n"); + s->busy = NULL; } - - s->busy = NULL; } static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) @@ -1700,7 +1701,6 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, return -EBUSY; ret = do_cancel(dev, s); - wake_up_interruptible(&s->async->wait_head); return ret; } -- cgit v1.2.3 From d19db51a0eeb659cd924a9d08b20a2ed4ee46b15 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:28 +0000 Subject: staging: comedi: cancel commands before detaching device The comedi core module's handling of the `COMEDI_DEVCONFIG` ioctl will not allow a device to be detached if it is busy. However, comedi devices can also be auto-detached due to a removal of a hardware device. One of the things we should do in that case is cancel any asynchronous commands that are running. Add a new function `comedi_device_cancel_all()` to do that and call it from `comedi_device_detach()`. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 15 +++++++++++++++ drivers/staging/comedi/comedi_internal.h | 1 + drivers/staging/comedi/drivers.c | 1 + 3 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 9c85f01e847b..eafa18efdeea 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -584,6 +584,21 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } +void comedi_device_cancel_all(struct comedi_device *dev) +{ + struct comedi_subdevice *s; + int i; + + if (!dev->attached) + return; + + for (i = 0; i < dev->n_subdevices; i++) { + s = &dev->subdevices[i]; + if (s->async) + do_cancel(dev, s); + } +} + static int is_device_busy(struct comedi_device *dev) { struct comedi_subdevice *s; diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index fda1a7ba0e16..151693b11383 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -17,6 +17,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); void comedi_buf_reset(struct comedi_async *async); unsigned int comedi_buf_write_n_allocated(struct comedi_async *async); +void comedi_device_cancel_all(struct comedi_device *dev); extern unsigned int comedi_default_buf_size_kb; extern unsigned int comedi_default_buf_maxsize_kb; diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 1f44f2939f6a..4f727731a72d 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -133,6 +133,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) void comedi_device_detach(struct comedi_device *dev) { + comedi_device_cancel_all(dev); down_write(&dev->attach_lock); dev->attached = false; if (dev->driver) -- cgit v1.2.3 From ef77c0b2570623f1d72527cb1c6c3f3d3c59793e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:29 +0000 Subject: staging: comedi: add detachment counter for validity checks Add a member `detach_count` to `struct comedi_device` that is incremented every time the device gets detached. This will be used in some validity checks in the 'read' and 'write' file operations to make sure the attachment remains valid. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 1 + drivers/staging/comedi/drivers.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 70de3558c74e..05cc8dbcd515 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -173,6 +173,7 @@ struct comedi_device { struct device *class_dev; int minor; + unsigned int detach_count; /* hw_dev is passed to dma_alloc_coherent when allocating async buffers * for subdevices that have async_dma_dir set to something other than * DMA_NONE */ diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 4f727731a72d..15b1ab885e77 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -136,6 +136,7 @@ void comedi_device_detach(struct comedi_device *dev) comedi_device_cancel_all(dev); down_write(&dev->attach_lock); dev->attached = false; + dev->detach_count++; if (dev->driver) dev->driver->detach(dev); comedi_device_detach_cleanup(dev); -- cgit v1.2.3 From 9329f13956bb8e43c254e7137386dce0b35f24b6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:30 +0000 Subject: staging: comedi: protect against detach during write operation The 'write' file operation for comedi devices does not use the main mutex in the `struct comedi_device` to avoid contention with some ioctls that may take a while to complete. Use the `attach_lock` semaphore to protect against detachment while the 'write' operation is in progress. This is a `struct rw_semaphore` and we read-lock it to protect against device detachment. Note that `comedi_device_cancel_all()` is called during device detachment, which cancels any ongoing asynchronous commands. This will wake up any blocked writers which will then release the `attach_lock` semaphore and complete the 'write' operation early. The only time the 'write' file operation does use the main mutex is at the end of the command when it has to call `do_become_nonbusy()` to mark the subdevice as no longer busy handling an asynchronous command. To avoid deadlock, it has to remove the task from the wait queue and release the `attach_lock` semaphore before acquiring the main mutex. It then needs to confirm that the device is still attached. Unfortunately, we do not yet protect against a dynamically allocated `struct comedi_device` being deleted during the operation. This will be addressed by a later patch. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 61 ++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index eafa18efdeea..1ae2bdf08646 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2023,38 +2023,77 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file_inode(file)); struct comedi_device *dev = comedi_dev_from_minor(minor); + bool on_wait_queue = false; + bool attach_locked; + unsigned int old_detach_count; if (!dev) return -ENODEV; + /* Protect against device detachment during operation. */ + down_read(&dev->attach_lock); + attach_locked = true; + old_detach_count = dev->detach_count; + if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); - return -ENODEV; + retval = -ENODEV; + goto out; } s = comedi_write_subdevice(dev, minor); - if (!s || !s->async) - return -EIO; + if (!s || !s->async) { + retval = -EIO; + goto out; + } async = s->async; if (!s->busy || !nbytes) - return 0; - if (s->busy != file) - return -EACCES; + goto out; + if (s->busy != file) { + retval = -EACCES; + goto out; + } add_wait_queue(&async->wait_head, &wait); + on_wait_queue = true; while (nbytes > 0 && !retval) { set_current_state(TASK_INTERRUPTIBLE); if (!comedi_is_subdevice_running(s)) { if (count == 0) { - mutex_lock(&dev->mutex); + struct comedi_subdevice *new_s; + if (comedi_is_subdevice_in_error(s)) retval = -EPIPE; else retval = 0; - do_become_nonbusy(dev, s); + /* + * To avoid deadlock, cannot acquire dev->mutex + * while dev->attach_lock is held. Need to + * remove task from the async wait queue before + * releasing dev->attach_lock, as it might not + * be valid afterwards. + */ + remove_wait_queue(&async->wait_head, &wait); + on_wait_queue = false; + up_read(&dev->attach_lock); + attach_locked = false; + mutex_lock(&dev->mutex); + /* + * Become non-busy unless things have changed + * behind our back. Checking dev->detach_count + * is unchanged ought to be sufficient (unless + * there have been 2**32 detaches in the + * meantime!), but check the subdevice pointer + * as well just in case. + */ + new_s = comedi_write_subdevice(dev, minor); + if (dev->attached && + old_detach_count == dev->detach_count && + s == new_s && new_s->async == async) + do_become_nonbusy(dev, s); mutex_unlock(&dev->mutex); } break; @@ -2104,8 +2143,12 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, buf += n; break; /* makes device work like a pipe */ } +out: + if (on_wait_queue) + remove_wait_queue(&async->wait_head, &wait); set_current_state(TASK_RUNNING); - remove_wait_queue(&async->wait_head, &wait); + if (attach_locked) + up_read(&dev->attach_lock); return count ? count : retval; } -- cgit v1.2.3 From 45c2bc557ca333a2115bb9f812b026b482cca5fa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:31 +0000 Subject: staging: comedi: protect against detach during read operation The 'read' file operation for comedi devices does not use the main mutex in the `struct comedi_device` to avoid contention with some ioctls that may take a while to complete. Use the `attach_lock` semaphore to protect against detachment while the 'read' operation is in progress. This is a `struct rw_semaphore` and we read-lock it to protect against device detachment. Note that `comedi_device_cancel_all()` is called during device detachment, which cancels any ongoing asynchronous commands. This will wake up any blocked readers which will then release the `attach_lock` semaphore and complete the 'read' operation early. The only time the 'read' file operation does use the main mutex is at the end of the command when it has to call `do_become_nonbusy()` to mark the subdevice as no longer busy handling an asynchronous command. To avoid deadlock, it has to remove the task from the wait queue and release the `attach_lock` semaphore before acquiring the main mutex. It then needs to confirm the device is still attached. Unfortunately, we do not yet protect against a dynamically allocated `struct comedi_device` being deleted during the operation. This will be addressed by a later patch. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 62 ++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 1ae2bdf08646..fa8da20df753 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2162,24 +2162,37 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file_inode(file)); struct comedi_device *dev = comedi_dev_from_minor(minor); + unsigned int old_detach_count; + bool become_nonbusy = false; + bool attach_locked; if (!dev) return -ENODEV; + /* Protect against device detachment during operation. */ + down_read(&dev->attach_lock); + attach_locked = true; + old_detach_count = dev->detach_count; + if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); - return -ENODEV; + retval = -ENODEV; + goto out; } s = comedi_read_subdevice(dev, minor); - if (!s || !s->async) - return -EIO; + if (!s || !s->async) { + retval = -EIO; + goto out; + } async = s->async; if (!s->busy || !nbytes) - return 0; - if (s->busy != file) - return -EACCES; + goto out; + if (s->busy != file) { + retval = -EACCES; + goto out; + } add_wait_queue(&async->wait_head, &wait); while (nbytes > 0 && !retval) { @@ -2197,13 +2210,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, if (n == 0) { if (!comedi_is_subdevice_running(s)) { - mutex_lock(&dev->mutex); - do_become_nonbusy(dev, s); if (comedi_is_subdevice_in_error(s)) retval = -EPIPE; else retval = 0; - mutex_unlock(&dev->mutex); + become_nonbusy = true; break; } if (file->f_flags & O_NONBLOCK) { @@ -2241,14 +2252,37 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, buf += n; break; /* makes device work like a pipe */ } - if (comedi_is_subdevice_idle(s)) { + remove_wait_queue(&async->wait_head, &wait); + set_current_state(TASK_RUNNING); + if (become_nonbusy || comedi_is_subdevice_idle(s)) { + struct comedi_subdevice *new_s; + + /* + * To avoid deadlock, cannot acquire dev->mutex + * while dev->attach_lock is held. + */ + up_read(&dev->attach_lock); + attach_locked = false; mutex_lock(&dev->mutex); - if (async->buf_read_count - async->buf_write_count == 0) - do_become_nonbusy(dev, s); + /* + * Check device hasn't become detached behind our back. + * Checking dev->detach_count is unchanged ought to be + * sufficient (unless there have been 2**32 detaches in the + * meantime!), but check the subdevice pointer as well just in + * case. + */ + new_s = comedi_read_subdevice(dev, minor); + if (dev->attached && old_detach_count == dev->detach_count && + s == new_s && new_s->async == async) { + if (become_nonbusy || + async->buf_read_count - async->buf_write_count == 0) + do_become_nonbusy(dev, s); + } mutex_unlock(&dev->mutex); } - set_current_state(TASK_RUNNING); - remove_wait_queue(&async->wait_head, &wait); +out: + if (attach_locked) + up_read(&dev->attach_lock); return count ? count : retval; } -- cgit v1.2.3 From 5b13ed94a7d24fdc8abbac81e7e4d30ab22c6540 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:32 +0000 Subject: staging: comedi: add a kref to comedi device Add a `struct kref refcount` member to `struct comedi_device` to allow safe destruction of the comedi device. Only free the comedi device via the 'release' callback `kref_put()`. Currently, nothing calls `kref_put()`, so the safe destruction is ineffective, but this will be addressed by later patches. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 22 +++++++++++++++++++--- drivers/staging/comedi/comedidev.h | 2 ++ 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index fa8da20df753..403324c895b1 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -89,12 +89,29 @@ static struct cdev comedi_cdev; static void comedi_device_init(struct comedi_device *dev) { + kref_init(&dev->refcount); spin_lock_init(&dev->spinlock); mutex_init(&dev->mutex); init_rwsem(&dev->attach_lock); dev->minor = -1; } +static void comedi_dev_kref_release(struct kref *kref) +{ + struct comedi_device *dev = + container_of(kref, struct comedi_device, refcount); + + mutex_destroy(&dev->mutex); + kfree(dev); +} + +int comedi_dev_put(struct comedi_device *dev) +{ + if (dev) + return kref_put(&dev->refcount, comedi_dev_kref_release); + return 1; +} + static void comedi_device_cleanup(struct comedi_device *dev) { struct module *driver_module = NULL; @@ -112,7 +129,6 @@ static void comedi_device_cleanup(struct comedi_device *dev) dev->use_count--; } mutex_unlock(&dev->mutex); - mutex_destroy(&dev->mutex); } static bool comedi_clear_board_dev(struct comedi_device *dev) @@ -148,7 +164,7 @@ static void comedi_free_board_dev(struct comedi_device *dev) MKDEV(COMEDI_MAJOR, dev->minor)); } comedi_device_cleanup(dev); - kfree(dev); + comedi_dev_put(dev); } } @@ -2494,7 +2510,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) if (i == COMEDI_NUM_BOARD_MINORS) { mutex_unlock(&dev->mutex); comedi_device_cleanup(dev); - kfree(dev); + comedi_dev_put(dev); pr_err("comedi: error: ran out of minor numbers for board device files.\n"); return ERR_PTR(-EBUSY); } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 05cc8dbcd515..08652dfa8c03 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "comedi.h" @@ -187,6 +188,7 @@ struct comedi_device { spinlock_t spinlock; struct mutex mutex; struct rw_semaphore attach_lock; + struct kref refcount; int n_subdevices; struct comedi_subdevice *subdevices; -- cgit v1.2.3 From b449c1cad7e3acf80834d4bdb1b6241d5d8dd249 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:33 +0000 Subject: staging: comedi: add comedi_dev_get_from_minor() Add function `struct comedi_device *comedi_dev_get_from_minor(unsigned minor)`. This behaves like the existing `comedi_dev_from_minor()` except that it also increments the `struct kref refcount` member (via new helper function `comedi_dev_get()`) to prevent it being freed. If it returns a valid pointer, the caller is responsible for calling `comedi_dev_put()` to decrement the reference count. Export `comedi_dev_get_from_minor()` and `comedi_dev_put()` as they will be used by the "kcomedilib" module in addition to the "comedi" module itself. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 42 ++++++++++++++++++++++++++++++++++++ drivers/staging/comedi/comedidev.h | 2 ++ 2 files changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 403324c895b1..5e5ddbdbad0b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -111,6 +111,14 @@ int comedi_dev_put(struct comedi_device *dev) return kref_put(&dev->refcount, comedi_dev_kref_release); return 1; } +EXPORT_SYMBOL_GPL(comedi_dev_put); + +static struct comedi_device *comedi_dev_get(struct comedi_device *dev) +{ + if (dev) + kref_get(&dev->refcount); + return dev; +} static void comedi_device_cleanup(struct comedi_device *dev) { @@ -209,6 +217,40 @@ struct comedi_device *comedi_dev_from_minor(unsigned minor) } EXPORT_SYMBOL_GPL(comedi_dev_from_minor); +static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) +{ + struct comedi_device *dev; + + BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + mutex_lock(&comedi_board_minor_table_lock); + dev = comedi_dev_get(comedi_board_minor_table[minor]); + mutex_unlock(&comedi_board_minor_table_lock); + return dev; +} + +static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) +{ + struct comedi_device *dev; + struct comedi_subdevice *s; + unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; + + BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); + mutex_lock(&comedi_subdevice_minor_table_lock); + s = comedi_subdevice_minor_table[i]; + dev = comedi_dev_get(s ? s->device : NULL); + mutex_unlock(&comedi_subdevice_minor_table_lock); + return dev; +} + +struct comedi_device *comedi_dev_get_from_minor(unsigned minor) +{ + if (minor < COMEDI_NUM_BOARD_MINORS) + return comedi_dev_get_from_board_minor(minor); + else + return comedi_dev_get_from_subdevice_minor(minor); +} +EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor); + static struct comedi_subdevice * comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor) { diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 08652dfa8c03..a9b1468aa17c 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -236,6 +236,8 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; struct comedi_device *comedi_dev_from_minor(unsigned minor); +struct comedi_device *comedi_dev_get_from_minor(unsigned minor); +int comedi_dev_put(struct comedi_device *dev); void init_polling(void); void cleanup_polling(void); -- cgit v1.2.3 From fc406986d4115dfbd5e2ea8a0e96920e97162689 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:34 +0000 Subject: staging: comedi: increment reference while file open In the 'open' file operation handler `comedi_open()` in "comedi_fops.c", call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()` to get the pointer to the `struct comedi_device`. This increments the reference to prevent it being freed. Call `comedi_dev_put()` to decrement the reference on failure, and also call it from the 'release' file operation handler `comedi_close()`. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 5e5ddbdbad0b..0ff69133c212 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2348,7 +2348,8 @@ out: static int comedi_open(struct inode *inode, struct file *file) { const unsigned minor = iminor(inode); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = comedi_dev_get_from_minor(minor); + int rc; if (!dev) { DPRINTK("invalid minor number\n"); @@ -2373,8 +2374,8 @@ static int comedi_open(struct inode *inode, struct file *file) goto ok; if (!capable(CAP_NET_ADMIN) && dev->in_request_module) { DPRINTK("in request module\n"); - mutex_unlock(&dev->mutex); - return -ENODEV; + rc = -ENODEV; + goto out; } if (capable(CAP_NET_ADMIN) && dev->in_request_module) goto ok; @@ -2391,8 +2392,8 @@ static int comedi_open(struct inode *inode, struct file *file) if (!dev->attached && !capable(CAP_NET_ADMIN)) { DPRINTK("not attached and not CAP_NET_ADMIN\n"); - mutex_unlock(&dev->mutex); - return -ENODEV; + rc = -ENODEV; + goto out; } ok: __module_get(THIS_MODULE); @@ -2400,26 +2401,28 @@ ok: if (dev->attached) { if (!try_module_get(dev->driver->module)) { module_put(THIS_MODULE); - mutex_unlock(&dev->mutex); - return -ENOSYS; + rc = -ENOSYS; + goto out; } } if (dev->attached && dev->use_count == 0 && dev->open) { - int rc = dev->open(dev); + rc = dev->open(dev); if (rc < 0) { module_put(dev->driver->module); module_put(THIS_MODULE); - mutex_unlock(&dev->mutex); - return rc; + goto out; } } dev->use_count++; + rc = 0; +out: mutex_unlock(&dev->mutex); - - return 0; + if (rc) + comedi_dev_put(dev); + return rc; } static int comedi_fasync(int fd, struct file *file, int on) @@ -2465,6 +2468,7 @@ static int comedi_close(struct inode *inode, struct file *file) dev->use_count--; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return 0; } -- cgit v1.2.3 From a200fadca97abb337dcc28e737c1a2e11f56b714 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:35 +0000 Subject: staging: comedi: use refcount in comedi_driver_unregister() Change `comedi_driver_unregister()` to call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()` when finding devices using the driver. This increments the reference count to prevent the device being removed while it is being checked to see if it is attached to the driver. Call `comedi_dev_put()` to decrement the reference afterwards. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 15b1ab885e77..a5d03b9c3717 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -662,7 +662,7 @@ void comedi_driver_unregister(struct comedi_driver *driver) /* check for devices using this driver */ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { - struct comedi_device *dev = comedi_dev_from_minor(i); + struct comedi_device *dev = comedi_dev_get_from_minor(i); if (!dev) continue; @@ -676,6 +676,7 @@ void comedi_driver_unregister(struct comedi_driver *driver) comedi_device_detach(dev); } mutex_unlock(&dev->mutex); + comedi_dev_put(dev); } } EXPORT_SYMBOL_GPL(comedi_driver_unregister); -- cgit v1.2.3 From 616a3548e816553c31d57cc211a86d327a192e12 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:36 +0000 Subject: staging: comedi: use refcount while reading /proc/comedi In the seq_file 'show' handler for "/proc/comedi" - `comedi_read()` in "comedi/proc.c", call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()` to increment the reference counter for the `struct comedi_device` while it is being examined. Call `comedi_dev_put()` to decrement the reference afterwards. Also acquire the `attach_lock` rwsem while checking whether the device is attached. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/proc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c index ade00035d3bb..da6bc5855ebc 100644 --- a/drivers/staging/comedi/proc.c +++ b/drivers/staging/comedi/proc.c @@ -41,16 +41,20 @@ static int comedi_read(struct seq_file *m, void *v) "driver_name, board_name, n_subdevices"); for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { - struct comedi_device *dev = comedi_dev_from_minor(i); + struct comedi_device *dev = comedi_dev_get_from_minor(i); + if (!dev) continue; + down_read(&dev->attach_lock); if (dev->attached) { devices_q = 1; seq_printf(m, "%2d: %-20s %-20s %4d\n", i, dev->driver->driver_name, dev->board_name, dev->n_subdevices); } + up_read(&dev->attach_lock); + comedi_dev_put(dev); } if (!devices_q) seq_puts(m, "no devices\n"); -- cgit v1.2.3 From be535c9a058b73600666d5431cfb442f39989a33 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:37 +0000 Subject: staging: comedi: use refcount in sysfs attribute handlers Call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()` in the sysfs attribute handler functions to increment the reference of the `struct comedi_device` during the operation. Call `comedi_dev_put()` to decrement the reference afterwards. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 0ff69133c212..37400e85c417 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -328,7 +328,7 @@ static ssize_t max_read_buffer_kb_show(struct device *csdev, struct comedi_subdevice *s; unsigned int size = 0; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -338,6 +338,7 @@ static ssize_t max_read_buffer_kb_show(struct device *csdev, size = s->async->max_bufsize / 1024; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return snprintf(buf, PAGE_SIZE, "%i\n", size); } @@ -358,7 +359,7 @@ static ssize_t max_read_buffer_kb_store(struct device *csdev, return -EINVAL; size *= 1024; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -370,6 +371,7 @@ static ssize_t max_read_buffer_kb_store(struct device *csdev, err = -EINVAL; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return err ? err : count; } static DEVICE_ATTR_RW(max_read_buffer_kb); @@ -382,7 +384,7 @@ static ssize_t read_buffer_kb_show(struct device *csdev, struct comedi_subdevice *s; unsigned int size = 0; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -392,6 +394,7 @@ static ssize_t read_buffer_kb_show(struct device *csdev, size = s->async->prealloc_bufsz / 1024; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return snprintf(buf, PAGE_SIZE, "%i\n", size); } @@ -412,7 +415,7 @@ static ssize_t read_buffer_kb_store(struct device *csdev, return -EINVAL; size *= 1024; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -424,6 +427,7 @@ static ssize_t read_buffer_kb_store(struct device *csdev, err = -EINVAL; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return err ? err : count; } static DEVICE_ATTR_RW(read_buffer_kb); @@ -437,7 +441,7 @@ static ssize_t max_write_buffer_kb_show(struct device *csdev, struct comedi_subdevice *s; unsigned int size = 0; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -447,6 +451,7 @@ static ssize_t max_write_buffer_kb_show(struct device *csdev, size = s->async->max_bufsize / 1024; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return snprintf(buf, PAGE_SIZE, "%i\n", size); } @@ -467,7 +472,7 @@ static ssize_t max_write_buffer_kb_store(struct device *csdev, return -EINVAL; size *= 1024; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -479,6 +484,7 @@ static ssize_t max_write_buffer_kb_store(struct device *csdev, err = -EINVAL; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return err ? err : count; } static DEVICE_ATTR_RW(max_write_buffer_kb); @@ -491,7 +497,7 @@ static ssize_t write_buffer_kb_show(struct device *csdev, struct comedi_subdevice *s; unsigned int size = 0; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -501,6 +507,7 @@ static ssize_t write_buffer_kb_show(struct device *csdev, size = s->async->prealloc_bufsz / 1024; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return snprintf(buf, PAGE_SIZE, "%i\n", size); } @@ -521,7 +528,7 @@ static ssize_t write_buffer_kb_store(struct device *csdev, return -EINVAL; size *= 1024; - dev = comedi_dev_from_minor(minor); + dev = comedi_dev_get_from_minor(minor); if (!dev) return -ENODEV; @@ -533,6 +540,7 @@ static ssize_t write_buffer_kb_store(struct device *csdev, err = -EINVAL; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return err ? err : count; } static DEVICE_ATTR_RW(write_buffer_kb); -- cgit v1.2.3 From 799a66ba36cb51330c53c024dffc6ddb68545c9c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:38 +0000 Subject: staging: comedi: kcomedilib: increment reference while device in use Low-level comedi drivers that use the "kcomedilib" module (currently only the "comedi_bond" driver) call `comedi_open()` to "open" another comedi device (not as a file) and `comedi_close()` to "close" it. (Note: these are the functions exported by the "kcomedilib" module, not the identically named, statically linked functions in the core "comedi" module.) In `comedi_open()`, call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()` to get the pointer to the `struct comedi_device` being "opened". This increments its reference count to prevent it being freed. Call `comedi_dev_put()` if `comedi_open()` returns `NULL`, and also call it from `comedi_close()`. This decrements the reference count. Note that although we now protect against the `struct comedi_device` being freed, we do not yet protect against it being "detached" while it is being used. This will be addressed by a later patch. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index cd60677a3ed2..b3a06f2dbad6 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -35,7 +35,7 @@ MODULE_LICENSE("GPL"); struct comedi_device *comedi_open(const char *filename) { - struct comedi_device *dev; + struct comedi_device *dev, *retval = NULL; unsigned int minor; if (strncmp(filename, "/dev/comedi", 11) != 0) @@ -46,15 +46,19 @@ struct comedi_device *comedi_open(const char *filename) if (minor >= COMEDI_NUM_BOARD_MINORS) return NULL; - dev = comedi_dev_from_minor(minor); - - if (!dev || !dev->attached) + dev = comedi_dev_get_from_minor(minor); + if (!dev) return NULL; - if (!try_module_get(dev->driver->module)) - return NULL; + if (dev->attached && try_module_get(dev->driver->module)) + retval = dev; + else + retval = NULL; + + if (retval == NULL) + comedi_dev_put(dev); - return dev; + return retval; } EXPORT_SYMBOL_GPL(comedi_open); @@ -63,6 +67,7 @@ int comedi_close(struct comedi_device *d) struct comedi_device *dev = (struct comedi_device *)d; module_put(dev->driver->module); + comedi_dev_put(dev); return 0; } -- cgit v1.2.3 From 69e2387f3bfd408c7fb6c0d14b83d792f67ed638 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:39 +0000 Subject: staging: comedi: kcomedilib: protect against device detachment The functions in "kcomedilib" need to prevent the comedi device being detached during their operation. This can be done by acquiring either the main mutex or the "attach lock" semaphore in the `struct comedi_device`. Use the attach lock when merely checking whether the device is attached. Use the mutex when processing a comedi instruction. Also, don't bother trying to manipulate the module use count of low-level comedi driver in `comedi_open()` and `comedi_close()`. If the device gets detached while it is "open", we wouldn't be able to decrement the module use count anyway. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../staging/comedi/kcomedilib/kcomedilib_main.c | 57 +++++++++++++--------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index b3a06f2dbad6..7dc5a18e69d4 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -50,10 +50,12 @@ struct comedi_device *comedi_open(const char *filename) if (!dev) return NULL; - if (dev->attached && try_module_get(dev->driver->module)) + down_read(&dev->attach_lock); + if (dev->attached) retval = dev; else retval = NULL; + up_read(&dev->attach_lock); if (retval == NULL) comedi_dev_put(dev); @@ -62,13 +64,9 @@ struct comedi_device *comedi_open(const char *filename) } EXPORT_SYMBOL_GPL(comedi_open); -int comedi_close(struct comedi_device *d) +int comedi_close(struct comedi_device *dev) { - struct comedi_device *dev = (struct comedi_device *)d; - - module_put(dev->driver->module); comedi_dev_put(dev); - return 0; } EXPORT_SYMBOL_GPL(comedi_close); @@ -78,7 +76,14 @@ static int comedi_do_insn(struct comedi_device *dev, unsigned int *data) { struct comedi_subdevice *s; - int ret = 0; + int ret; + + mutex_lock(&dev->mutex); + + if (!dev->attached) { + ret = -EINVAL; + goto error; + } /* a subdevice instruction */ if (insn->subdev >= dev->n_subdevices) { @@ -125,6 +130,7 @@ static int comedi_do_insn(struct comedi_device *dev, s->busy = NULL; error: + mutex_unlock(&dev->mutex); return ret; } @@ -174,9 +180,6 @@ int comedi_dio_bitfield2(struct comedi_device *dev, unsigned int subdev, unsigned int shift; int ret; - if (subdev >= dev->n_subdevices) - return -EINVAL; - base_channel = CR_CHAN(base_channel); n_chan = comedi_get_n_channels(dev, subdev); if (base_channel >= n_chan) @@ -216,23 +219,33 @@ int comedi_find_subdevice_by_type(struct comedi_device *dev, int type, unsigned int subd) { struct comedi_subdevice *s; - - if (subd > dev->n_subdevices) - return -ENODEV; - - for (; subd < dev->n_subdevices; subd++) { - s = &dev->subdevices[subd]; - if (s->type == type) - return subd; - } - return -1; + int ret = -ENODEV; + + down_read(&dev->attach_lock); + if (dev->attached) + for (; subd < dev->n_subdevices; subd++) { + s = &dev->subdevices[subd]; + if (s->type == type) { + ret = subd; + break; + } + } + up_read(&dev->attach_lock); + return ret; } EXPORT_SYMBOL_GPL(comedi_find_subdevice_by_type); int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice) { - struct comedi_subdevice *s = &dev->subdevices[subdevice]; + int n; + + down_read(&dev->attach_lock); + if (!dev->attached || subdevice >= dev->n_subdevices) + n = 0; + else + n = dev->subdevices[subdevice].n_chan; + up_read(&dev->attach_lock); - return s->n_chan; + return n; } EXPORT_SYMBOL_GPL(comedi_get_n_channels); -- cgit v1.2.3 From e5d670dcb7b336fb0c2fcff29ce87892e492e6b3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:40 +0000 Subject: staging: comedi: use file->private_data in file operations Since the `struct comedi_device` should now be protected from being freed while an open file object is using it, use the `private_data` member of the `struct file` to point to it. Set it in `comedi_open()` and use it in the other file operation handlers instead of calling `comedi_dev_from_minor()` and checking the result. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 38 ++++++++---------------------------- 1 file changed, 8 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 37400e85c417..08aa93a1c87c 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1828,12 +1828,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { const unsigned minor = iminor(file_inode(file)); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = file->private_data; int rc; - if (!dev) - return -ENODEV; - mutex_lock(&dev->mutex); /* Device config is special, because it must work on @@ -1964,7 +1961,7 @@ static struct vm_operations_struct comedi_vm_ops = { static int comedi_mmap(struct file *file, struct vm_area_struct *vma) { const unsigned minor = iminor(file_inode(file)); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = file->private_data; struct comedi_subdevice *s; struct comedi_async *async; unsigned long start = vma->vm_start; @@ -1973,9 +1970,6 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) int i; int retval; - if (!dev) - return -ENODEV; - mutex_lock(&dev->mutex); if (!dev->attached) { @@ -2043,12 +2037,9 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; const unsigned minor = iminor(file_inode(file)); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = file->private_data; struct comedi_subdevice *s; - if (!dev) - return -ENODEV; - mutex_lock(&dev->mutex); if (!dev->attached) { @@ -2088,14 +2079,11 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file_inode(file)); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = file->private_data; bool on_wait_queue = false; bool attach_locked; unsigned int old_detach_count; - if (!dev) - return -ENODEV; - /* Protect against device detachment during operation. */ down_read(&dev->attach_lock); attach_locked = true; @@ -2227,14 +2215,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file_inode(file)); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = file->private_data; unsigned int old_detach_count; bool become_nonbusy = false; bool attach_locked; - if (!dev) - return -ENODEV; - /* Protect against device detachment during operation. */ down_read(&dev->attach_lock); attach_locked = true; @@ -2424,6 +2409,7 @@ ok: } dev->use_count++; + file->private_data = dev; rc = 0; out: @@ -2435,25 +2421,17 @@ out: static int comedi_fasync(int fd, struct file *file, int on) { - const unsigned minor = iminor(file_inode(file)); - struct comedi_device *dev = comedi_dev_from_minor(minor); - - if (!dev) - return -ENODEV; + struct comedi_device *dev = file->private_data; return fasync_helper(fd, file, on, &dev->async_queue); } static int comedi_close(struct inode *inode, struct file *file) { - const unsigned minor = iminor(inode); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = file->private_data; struct comedi_subdevice *s = NULL; int i; - if (!dev) - return -ENODEV; - mutex_lock(&dev->mutex); if (dev->subdevices) { -- cgit v1.2.3 From 49445b9117a6e9ca9a741251784432a1da2f9919 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:41 +0000 Subject: staging: comedi: remove comedi_dev_from_minor() The `comedi_dev_from_minor()` function is no longer used, so remove it. Calls to it have either been replaced by calls to `comedi_dev_get_from_minor()` or by using the `private_data` member of the open file object. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 28 ---------------------------- drivers/staging/comedi/comedidev.h | 1 - 2 files changed, 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 08aa93a1c87c..d569484f315b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -189,34 +189,6 @@ static struct comedi_subdevice return s; } -static struct comedi_device *comedi_dev_from_board_minor(unsigned minor) -{ - struct comedi_device *dev; - - BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); - mutex_lock(&comedi_board_minor_table_lock); - dev = comedi_board_minor_table[minor]; - mutex_unlock(&comedi_board_minor_table_lock); - return dev; -} - -static struct comedi_device *comedi_dev_from_subdevice_minor(unsigned minor) -{ - struct comedi_subdevice *s; - - s = comedi_subdevice_from_minor(minor); - return s ? s->device : NULL; -} - -struct comedi_device *comedi_dev_from_minor(unsigned minor) -{ - if (minor < COMEDI_NUM_BOARD_MINORS) - return comedi_dev_from_board_minor(minor); - else - return comedi_dev_from_subdevice_minor(minor); -} -EXPORT_SYMBOL_GPL(comedi_dev_from_minor); - static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) { struct comedi_device *dev; diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index a9b1468aa17c..4e7cd1443be6 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -235,7 +235,6 @@ enum comedi_minor_bits { static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; -struct comedi_device *comedi_dev_from_minor(unsigned minor); struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -- cgit v1.2.3 From 63ab039511509739f881acfb99aef76b772e35a2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:42 +0000 Subject: staging: comedi: make determination of read or write subdevice safer `comedi_read_subdevice()` and `comedi_write_subdevice()` respectively determine the read and write subdevice to use for a comedi device, depending on a minor device number passed in. The comedi device has a main "board" minor device number and may also have dynamically assigned, subdevice-specific minor device numbers, in a range of numbers shared by all comedi devices. If the minor device number is within the range of subdevice-specific minor device numbers, both functions call `comedi_subdevice_from_minor()` to determine what subdevice is associated with the minor device number (if any) and then check the subdevice belongs to the comedi device. Since the subdevice might belong to a different comedi device, the check is not protected against the subdevice being freed. Perform the check in `comedi_subdevice_from_minor()` instead, where it is protected against the subdevice being freed. Make it return `NULL` if the subdevice does not belong to the device. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index d569484f315b..8cb9d956e8f2 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -177,7 +177,7 @@ static void comedi_free_board_dev(struct comedi_device *dev) } static struct comedi_subdevice -*comedi_subdevice_from_minor(unsigned minor) +*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned minor) { struct comedi_subdevice *s; unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; @@ -185,6 +185,8 @@ static struct comedi_subdevice BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); mutex_lock(&comedi_subdevice_minor_table_lock); s = comedi_subdevice_minor_table[i]; + if (s && s->device != dev) + s = NULL; mutex_unlock(&comedi_subdevice_minor_table_lock); return s; } @@ -229,10 +231,8 @@ comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor) struct comedi_subdevice *s; if (minor >= COMEDI_NUM_BOARD_MINORS) { - s = comedi_subdevice_from_minor(minor); - if (!s || s->device != dev) - return NULL; - if (s->subdev_flags & SDF_CMD_READ) + s = comedi_subdevice_from_minor(dev, minor); + if (s == NULL || (s->subdev_flags & SDF_CMD_READ)) return s; } return dev->read_subdev; @@ -244,10 +244,8 @@ comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor) struct comedi_subdevice *s; if (minor >= COMEDI_NUM_BOARD_MINORS) { - s = comedi_subdevice_from_minor(minor); - if (!s || s->device != dev) - return NULL; - if (s->subdev_flags & SDF_CMD_WRITE) + s = comedi_subdevice_from_minor(dev, minor); + if (s == NULL || (s->subdev_flags & SDF_CMD_WRITE)) return s; } return dev->write_subdev; -- cgit v1.2.3 From af93da31634d6d55c9d313b5c49af8b272f7cb79 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:43 +0000 Subject: staging: comedi: protect buffer from being freed while mmapped If a comedi device is automatically detached by `comedi_auto_unconfig()` any data buffers associated with subdevices that support asynchronous commands will be freed. If the buffer is mmapped at the time, bad things are likely to happen! Prevent this by moving some of the buffer details from `struct comedi_async` into a new, dynamically allocated, and kref-counted `struct comedi_buf_map`. This holds a list of pages, a reference count, and enough information to free the pages. The new member `buf_map` of `struct comedi_async` points to a `struct comedi_buf_map` when the buffer size is non-zero. Provide a new helper function `comedi_buf_is_mapped()` to check whether an a buffer is mmapped. If it is mmapped, the buffer is not allowed to be resized and the device is not allowed to be manually detached by the `COMEDI_DEVCONFIG` ioctl. Provide helper functions `comedi_buf_map_get()` and `comedi_buf_map_put()` to manipulate the reference count of the `struct comedi_buf_map`, which will be freed along with its contents via the 'release' callback of the `kref_put()` call. The reference count is manipulated by the vma operations and the mmap file operation. Now, when the comedi device is automatically detached, the buffer will be effectively freed by calling `comedi_buf_alloc()` with a new buffer size of 0. That calls local function `__comedi_buf_free()` which calls `comedi_buf_map_put()` on the `buf_map` member to free it. It won't actually be freed until the final 'put'. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_buf.c | 99 ++++++++++++++++++++++---------- drivers/staging/comedi/comedi_fops.c | 38 ++++++------ drivers/staging/comedi/comedi_internal.h | 3 + drivers/staging/comedi/comedidev.h | 14 +++-- drivers/staging/comedi/drivers/mite.c | 2 +- 5 files changed, 99 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 4e26bd7fc84f..924fce977985 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -16,6 +16,7 @@ */ #include +#include #include "comedidev.h" #include "comedi_internal.h" @@ -26,31 +27,21 @@ #define COMEDI_PAGE_PROTECTION PAGE_KERNEL #endif -static void __comedi_buf_free(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned n_pages) +static void comedi_buf_map_kref_release(struct kref *kref) { - struct comedi_async *async = s->async; + struct comedi_buf_map *bm = + container_of(kref, struct comedi_buf_map, refcount); struct comedi_buf_page *buf; - unsigned i; - - if (async->prealloc_buf) { - vunmap(async->prealloc_buf); - async->prealloc_buf = NULL; - async->prealloc_bufsz = 0; - } + unsigned int i; - if (!async->buf_page_list) - return; - - for (i = 0; i < n_pages; ++i) { - buf = &async->buf_page_list[i]; - if (buf->virt_addr) { + if (bm->page_list) { + for (i = 0; i < bm->n_pages; i++) { + buf = &bm->page_list[i]; clear_bit(PG_reserved, &(virt_to_page(buf->virt_addr)->flags)); - if (s->async_dma_dir != DMA_NONE) { + if (bm->dma_dir != DMA_NONE) { #ifdef CONFIG_HAS_DMA - dma_free_coherent(dev->hw_dev, + dma_free_coherent(bm->dma_hw_dev, PAGE_SIZE, buf->virt_addr, buf->dma_addr); @@ -59,10 +50,26 @@ static void __comedi_buf_free(struct comedi_device *dev, free_page((unsigned long)buf->virt_addr); } } + vfree(bm->page_list); } - vfree(async->buf_page_list); - async->buf_page_list = NULL; - async->n_buf_pages = 0; + if (bm->dma_dir != DMA_NONE) + put_device(bm->dma_hw_dev); + kfree(bm); +} + +static void __comedi_buf_free(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct comedi_async *async = s->async; + + if (async->prealloc_buf) { + vunmap(async->prealloc_buf); + async->prealloc_buf = NULL; + async->prealloc_bufsz = 0; + } + + comedi_buf_map_put(async->buf_map); + async->buf_map = NULL; } static void __comedi_buf_alloc(struct comedi_device *dev, @@ -71,6 +78,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, { struct comedi_async *async = s->async; struct page **pages = NULL; + struct comedi_buf_map *bm; struct comedi_buf_page *buf; unsigned i; @@ -80,18 +88,29 @@ static void __comedi_buf_alloc(struct comedi_device *dev, return; } - async->buf_page_list = vzalloc(sizeof(*buf) * n_pages); - if (async->buf_page_list) + bm = kzalloc(sizeof(*async->buf_map), GFP_KERNEL); + if (!bm) + return; + + async->buf_map = bm; + kref_init(&bm->refcount); + bm->dma_dir = s->async_dma_dir; + if (bm->dma_dir != DMA_NONE) + /* Need ref to hardware device to free buffer later. */ + bm->dma_hw_dev = get_device(dev->hw_dev); + + bm->page_list = vzalloc(sizeof(*buf) * n_pages); + if (bm->page_list) pages = vmalloc(sizeof(struct page *) * n_pages); if (!pages) return; for (i = 0; i < n_pages; i++) { - buf = &async->buf_page_list[i]; - if (s->async_dma_dir != DMA_NONE) + buf = &bm->page_list[i]; + if (bm->dma_dir != DMA_NONE) #ifdef CONFIG_HAS_DMA - buf->virt_addr = dma_alloc_coherent(dev->hw_dev, + buf->virt_addr = dma_alloc_coherent(bm->dma_hw_dev, PAGE_SIZE, &buf->dma_addr, GFP_KERNEL | @@ -108,6 +127,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, pages[i] = virt_to_page(buf->virt_addr); } + bm->n_pages = i; /* vmap the prealloc_buf if all the pages were allocated */ if (i == n_pages) @@ -117,6 +137,26 @@ static void __comedi_buf_alloc(struct comedi_device *dev, vfree(pages); } +void comedi_buf_map_get(struct comedi_buf_map *bm) +{ + if (bm) + kref_get(&bm->refcount); +} + +int comedi_buf_map_put(struct comedi_buf_map *bm) +{ + if (bm) + return kref_put(&bm->refcount, comedi_buf_map_kref_release); + return 1; +} + +bool comedi_buf_is_mmapped(struct comedi_async *async) +{ + struct comedi_buf_map *bm = async->buf_map; + + return bm && (atomic_read(&bm->refcount.refcount) > 1); +} + int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size) { @@ -130,7 +170,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, return 0; /* deallocate old buffer */ - __comedi_buf_free(dev, s, async->n_buf_pages); + __comedi_buf_free(dev, s); /* allocate new buffer */ if (new_size) { @@ -140,10 +180,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, if (!async->prealloc_buf) { /* allocation failed */ - __comedi_buf_free(dev, s, n_pages); + __comedi_buf_free(dev, s); return -ENOMEM; } - async->n_buf_pages = n_pages; } async->prealloc_bufsz = new_size; diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 8cb9d956e8f2..58f2b27144ca 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -264,7 +264,7 @@ static int resize_async_buffer(struct comedi_device *dev, DPRINTK("subdevice is busy, cannot resize buffer\n"); return -EBUSY; } - if (async->mmap_count) { + if (comedi_buf_is_mmapped(async)) { DPRINTK("subdevice is mmapped, cannot resize buffer\n"); return -EBUSY; } @@ -647,7 +647,7 @@ static int is_device_busy(struct comedi_device *dev) s = &dev->subdevices[i]; if (s->busy) return 1; - if (s->async && s->async->mmap_count) + if (s->async && comedi_buf_is_mmapped(s->async)) return 1; } @@ -1899,28 +1899,18 @@ done: static void comedi_vm_open(struct vm_area_struct *area) { - struct comedi_async *async; - struct comedi_device *dev; + struct comedi_buf_map *bm; - async = area->vm_private_data; - dev = async->subdevice->device; - - mutex_lock(&dev->mutex); - async->mmap_count++; - mutex_unlock(&dev->mutex); + bm = area->vm_private_data; + comedi_buf_map_get(bm); } static void comedi_vm_close(struct vm_area_struct *area) { - struct comedi_async *async; - struct comedi_device *dev; + struct comedi_buf_map *bm; - async = area->vm_private_data; - dev = async->subdevice->device; - - mutex_lock(&dev->mutex); - async->mmap_count--; - mutex_unlock(&dev->mutex); + bm = area->vm_private_data; + comedi_buf_map_put(bm); } static struct vm_operations_struct comedi_vm_ops = { @@ -1934,6 +1924,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) struct comedi_device *dev = file->private_data; struct comedi_subdevice *s; struct comedi_async *async; + struct comedi_buf_map *bm; unsigned long start = vma->vm_start; unsigned long size; int n_pages; @@ -1980,8 +1971,13 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) } n_pages = size >> PAGE_SHIFT; + bm = async->buf_map; + if (!bm || n_pages > bm->n_pages) { + retval = -EINVAL; + goto done; + } for (i = 0; i < n_pages; ++i) { - struct comedi_buf_page *buf = &async->buf_page_list[i]; + struct comedi_buf_page *buf = &bm->page_list[i]; if (remap_pfn_range(vma, start, page_to_pfn(virt_to_page(buf->virt_addr)), @@ -1993,9 +1989,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) } vma->vm_ops = &comedi_vm_ops; - vma->vm_private_data = async; + vma->vm_private_data = bm; - async->mmap_count++; + vma->vm_ops->open(vma); retval = 0; done: diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index 151693b11383..9a746570f161 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -16,6 +16,9 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s); int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); void comedi_buf_reset(struct comedi_async *async); +bool comedi_buf_is_mmapped(struct comedi_async *async); +void comedi_buf_map_get(struct comedi_buf_map *bm); +int comedi_buf_map_put(struct comedi_buf_map *bm); unsigned int comedi_buf_write_n_allocated(struct comedi_async *async); void comedi_device_cancel_all(struct comedi_device *dev); diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 4e7cd1443be6..a7b8937aa4a3 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -104,18 +104,22 @@ struct comedi_buf_page { dma_addr_t dma_addr; }; +struct comedi_buf_map { + struct device *dma_hw_dev; + struct comedi_buf_page *page_list; + unsigned int n_pages; + enum dma_data_direction dma_dir; + struct kref refcount; +}; + struct comedi_async { struct comedi_subdevice *subdevice; void *prealloc_buf; /* pre-allocated buffer */ unsigned int prealloc_bufsz; /* buffer size, in bytes */ - /* virtual and dma address of each page */ - struct comedi_buf_page *buf_page_list; - unsigned n_buf_pages; /* num elements in buf_page_list */ + struct comedi_buf_map *buf_map; /* map of buffer pages */ unsigned int max_bufsize; /* maximum buffer size, bytes */ - /* current number of mmaps of prealloc_buf */ - unsigned int mmap_count; /* byte count for writer (write completed) */ unsigned int buf_write_count; diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 35cb4ace7970..1a2191699351 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -345,7 +345,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, for (i = 0; i < n_links; i++) { ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE); ring->descriptors[i].addr = - cpu_to_le32(async->buf_page_list[i].dma_addr); + cpu_to_le32(async->buf_map->page_list[i].dma_addr); ring->descriptors[i].next = cpu_to_le32(ring->descriptors_dma_addr + (i + 1) * -- cgit v1.2.3 From 95bcc666e9437ac33f639e6d971b0b6e9dc86607 Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Wed, 6 Nov 2013 15:55:31 +0800 Subject: lustre/fld: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO This patch fixes coccinelle error regarding usage of IS_ERR and PTR_ERR instead of PTR_ERR_OR_ZERO. Signed-off-by: Duan Jiong Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/fld_request.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index e47fd50b2a2e..3191a398675d 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -504,10 +504,7 @@ static int __init fld_mod_init(void) fld_type_proc_dir = lprocfs_register(LUSTRE_FLD_NAME, proc_lustre_root, NULL, NULL); - if (IS_ERR(fld_type_proc_dir)) - return PTR_ERR(fld_type_proc_dir); - - return 0; + return PTR_ERR_OR_ZERO(fld_type_proc_dir); } static void __exit fld_mod_exit(void) -- cgit v1.2.3 From 5e6dc548e453c68d79bd44a1a4a6fca43898009d Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Thu, 31 Oct 2013 15:27:37 +0800 Subject: drivers: staging: speakup: serialio: only use platform specific SERIAL_PORT_DFNS. If SERIAL_PORT_DFNS isn't present by platform, it need be defined to "nothing", like the 8250 serial driver does it. All related macros also need be removed: IRQF_SHARED is defined in "linux/interrupt.h", others will be defined when related architecture has SERIAL_PORT_DFNS. Or it will cause issue (for arc, with allmodconfig): CC [M] drivers/staging/speakup/serialio.o drivers/staging/speakup/serialio.c:12:2: error: initializer element is not constant SERIAL_PORT_DFNS ^ drivers/staging/speakup/serialio.c:12:2: error: (near initialization for 'rs_table[0].baud_base') drivers/staging/speakup/serialio.c:12:2: error: initializer element is not constant drivers/staging/speakup/serialio.c:12:2: error: (near initialization for 'rs_table[1].baud_base') drivers/staging/speakup/serialio.c:12:2: error: initializer element is not constant drivers/staging/speakup/serialio.c:12:2: error: (near initialization for 'rs_table[2].baud_base') drivers/staging/speakup/serialio.c:12:2: error: initializer element is not constant drivers/staging/speakup/serialio.c:12:2: error: (near initialization for 'rs_table[3].baud_base') Signed-off-by: Chen Gang Acked-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/serialio.c | 4 ++++ drivers/staging/speakup/serialio.h | 26 -------------------------- 2 files changed, 4 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c index 135428856d47..4e18fb405344 100644 --- a/drivers/staging/speakup/serialio.c +++ b/drivers/staging/speakup/serialio.c @@ -6,6 +6,10 @@ #include "spk_priv.h" #include "serialio.h" +#ifndef SERIAL_PORT_DFNS +#define SERIAL_PORT_DFNS +#endif + static void start_serial_interrupt(int irq); static const struct old_serial_port rs_table[] = { diff --git a/drivers/staging/speakup/serialio.h b/drivers/staging/speakup/serialio.h index 55d68b5ad165..0a937732a190 100644 --- a/drivers/staging/speakup/serialio.h +++ b/drivers/staging/speakup/serialio.h @@ -36,30 +36,4 @@ struct old_serial_port { #define spk_serial_tx_busy() ((inb(speakup_info.port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) -/* 2.6.22 doesn't have them any more, hardcode it for now (these values should - * be fine for 99% cases) */ -#ifndef BASE_BAUD -#define BASE_BAUD (1843200 / 16) -#endif -#ifndef STD_COM_FLAGS -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF -#endif -#endif -#ifndef SERIAL_PORT_DFNS -#define SERIAL_PORT_DFNS \ - /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ - { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ - { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ -#endif -#ifndef IRQF_SHARED -#define IRQF_SHARED SA_SHIRQ -#endif - #endif -- cgit v1.2.3 From 4e20effa23b1cbfc15fcdd6774937334775c5361 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 31 Oct 2013 14:20:25 +0900 Subject: staging: android: Fix typo in android/sync.h Correct spelling typo in android/sync.h Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.h | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 38ea986dc70f..62e2255b1c1e 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -28,7 +28,7 @@ struct sync_fence; /** * struct sync_timeline_ops - sync object implementation ops - * @driver_name: name of the implentation + * @driver_name: name of the implementation * @dup: duplicate a sync_pt * @has_signaled: returns: * 1 if pt has signaled @@ -37,12 +37,12 @@ struct sync_fence; * @compare: returns: * 1 if b will signal before a * 0 if a and b will signal at the same time - * -1 if a will signabl before b + * -1 if a will signal before b * @free_pt: called before sync_pt is freed * @release_obj: called before sync_timeline is freed * @print_obj: deprecated * @print_pt: deprecated - * @fill_driver_data: write implmentation specific driver data to data. + * @fill_driver_data: write implementation specific driver data to data. * should return an error if there is not enough room * as specified by size. This information is returned * to userspace by SYNC_IOC_FENCE_INFO. @@ -88,9 +88,9 @@ struct sync_timeline_ops { /** * struct sync_timeline - sync object * @kref: reference count on fence. - * @ops: ops that define the implementaiton of the sync_timeline + * @ops: ops that define the implementation of the sync_timeline * @name: name of the sync_timeline. Useful for debugging - * @destoryed: set when sync_timeline is destroyed + * @destroyed: set when sync_timeline is destroyed * @child_list_head: list of children sync_pts for this sync_timeline * @child_list_lock: lock protecting @child_list_head, destroyed, and * sync_pt.status @@ -119,12 +119,12 @@ struct sync_timeline { * @parent: sync_timeline to which this sync_pt belongs * @child_list: membership in sync_timeline.child_list_head * @active_list: membership in sync_timeline.active_list_head - * @signaled_list: membership in temorary signaled_list on stack + * @signaled_list: membership in temporary signaled_list on stack * @fence: sync_fence to which the sync_pt belongs * @pt_list: membership in sync_fence.pt_list_head * @status: 1: signaled, 0:active, <0: error * @timestamp: time which sync_pt status transitioned from active to - * singaled or error. + * signaled or error. */ struct sync_pt { struct sync_timeline *parent; @@ -145,9 +145,9 @@ struct sync_pt { /** * struct sync_fence - sync fence * @file: file representing this fence - * @kref: referenace count on fence. + * @kref: reference count on fence. * @name: name of sync_fence. Useful for debugging - * @pt_list_head: list of sync_pts in ths fence. immutable once fence + * @pt_list_head: list of sync_pts in the fence. immutable once fence * is created * @waiter_list_head: list of asynchronous waiters on this fence * @waiter_list_lock: lock protecting @waiter_list_head and @status @@ -201,23 +201,23 @@ static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, /** * sync_timeline_create() - creates a sync object - * @ops: specifies the implemention ops for the object + * @ops: specifies the implementation ops for the object * @size: size to allocate for this obj * @name: sync_timeline name * - * Creates a new sync_timeline which will use the implemetation specified by - * @ops. @size bytes will be allocated allowing for implemntation specific - * data to be kept after the generic sync_timeline stuct. + * Creates a new sync_timeline which will use the implementation specified by + * @ops. @size bytes will be allocated allowing for implementation specific + * data to be kept after the generic sync_timeline struct. */ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, int size, const char *name); /** - * sync_timeline_destory() - destorys a sync object + * sync_timeline_destroy() - destroys a sync object * @obj: sync_timeline to destroy * - * A sync implemntation should call this when the @obj is going away - * (i.e. module unload.) @obj won't actually be freed until all its childern + * A sync implementation should call this when the @obj is going away + * (i.e. module unload.) @obj won't actually be freed until all its children * sync_pts are freed. */ void sync_timeline_destroy(struct sync_timeline *obj); @@ -226,7 +226,7 @@ void sync_timeline_destroy(struct sync_timeline *obj); * sync_timeline_signal() - signal a status change on a sync_timeline * @obj: sync_timeline to signal * - * A sync implemntation should call this any time one of it's sync_pts + * A sync implementation should call this any time one of it's sync_pts * has signaled or has an error condition. */ void sync_timeline_signal(struct sync_timeline *obj); @@ -236,8 +236,8 @@ void sync_timeline_signal(struct sync_timeline *obj); * @parent: sync_pt's parent sync_timeline * @size: size to allocate for this pt * - * Creates a new sync_pt as a chiled of @parent. @size bytes will be - * allocated allowing for implemntation specific data to be kept after + * Creates a new sync_pt as a child of @parent. @size bytes will be + * allocated allowing for implementation specific data to be kept after * the generic sync_timeline struct. */ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); @@ -287,7 +287,7 @@ struct sync_fence *sync_fence_merge(const char *name, struct sync_fence *sync_fence_fdget(int fd); /** - * sync_fence_put() - puts a refernnce of a sync fence + * sync_fence_put() - puts a reference of a sync fence * @fence: fence to put * * Puts a reference on @fence. If this is the last reference, the fence and @@ -297,7 +297,7 @@ void sync_fence_put(struct sync_fence *fence); /** * sync_fence_install() - installs a fence into a file descriptor - * @fence: fence to instal + * @fence: fence to install * @fd: file descriptor in which to install the fence * * Installs @fence into @fd. @fd's should be acquired through get_unused_fd(). @@ -359,10 +359,10 @@ struct sync_merge_data { * struct sync_pt_info - detailed sync_pt information * @len: length of sync_pt_info including any driver_data * @obj_name: name of parent sync_timeline - * @driver_name: name of driver implmenting the parent + * @driver_name: name of driver implementing the parent * @status: status of the sync_pt 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds - * @driver_data: any driver dependant data + * @driver_data: any driver dependent data */ struct sync_pt_info { __u32 len; @@ -377,7 +377,7 @@ struct sync_pt_info { /** * struct sync_fence_info_data - data returned from fence info ioctl * @len: ioctl caller writes the size of the buffer its passing in. - * ioctl returns length of sync_fence_data reutnred to userspace + * ioctl returns length of sync_fence_data returned to userspace * including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error @@ -418,7 +418,7 @@ struct sync_fence_info_data { * pt_info. * * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. - * To itterate over the sync_pt_infos, use the sync_pt_info.len field. + * To iterate over the sync_pt_infos, use the sync_pt_info.len field. */ #define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\ struct sync_fence_info_data) -- cgit v1.2.3 From c766d23b969d6915965893d718a3d56290777ff0 Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Mon, 4 Nov 2013 14:15:22 +0200 Subject: Staging: ft1000: boot.h: fixed a few styling issues Fixed the following styling issues: Line 30: Removed space before open square bracket '[' Lines 31 to 155: Moved the commas that were in the start of the lines, to the end of the lines. Inserted spaces after the commas. Inserted a one tab indentation to each line. Signed-off-by: Aldo Iljazi Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-pcmcia/boot.h | 252 ++++++++++++++-------------- 1 file changed, 126 insertions(+), 126 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-pcmcia/boot.h b/drivers/staging/ft1000/ft1000-pcmcia/boot.h index 9dce54eae1cf..915165e38704 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/boot.h +++ b/drivers/staging/ft1000/ft1000-pcmcia/boot.h @@ -27,132 +27,132 @@ #define _BOOTH_ // Official bootloader -static unsigned char bootimage [] = { -0x00,0x00,0x01,0x5E,0x00,0x00 -,0x00,0x00,0x00,0x00,0x02,0xD7 -,0x00,0x00,0x01,0x5E,0x46,0xB3 -,0xE6,0x02,0x00,0x98,0xE6,0x8C -,0x00,0x98,0xFB,0x92,0xFF,0xFF -,0x98,0xFB,0x94,0xFF,0xFF,0x98 -,0xFB,0x06,0x08,0x00,0x98,0xFB -,0x96,0x84,0x00,0x98,0xFB,0x08 -,0x1C,0x00,0x98,0xFB,0x51,0x25 -,0x10,0x1C,0x00,0xE6,0x51,0x01 -,0x07,0xFD,0x4C,0xFF,0x20,0xF5 -,0x51,0x02,0x20,0x08,0x00,0x4C -,0xFF,0x20,0x3C,0x00,0xC0,0x64 -,0x98,0xC0,0x66,0x98,0xC0,0x68 -,0x98,0xC0,0x6A,0x98,0xC0,0x6C -,0x98,0x90,0x08,0x90,0x09,0x90 -,0x0A,0x90,0x0B,0x90,0x0C,0x90 -,0x0D,0x90,0x0E,0x90,0x0F,0x90 -,0x04,0x90,0x06,0xFB,0x51,0x22 -,0x16,0x08,0x03,0xFB,0x51,0x52 -,0x16,0x08,0x04,0xFB,0x51,0x24 -,0x2B,0x08,0x06,0xFB,0x51,0x54 -,0x2B,0x08,0x07,0xFB,0x51,0x24 -,0x2B,0x08,0x09,0xFB,0x51,0x54 -,0x2B,0x08,0x0A,0xFB,0x51,0x12 -,0x16,0x08,0x0C,0xFB,0x51,0x52 -,0x16,0x08,0x0D,0x78,0x00,0x00 -,0x00,0x16,0x00,0x00,0xEC,0x31 -,0xAE,0x00,0x00,0x81,0x4C,0x0F -,0xE6,0x43,0xFF,0xEC,0x31,0x4E -,0x00,0x00,0x91,0xEC,0x31,0xAE -,0x00,0x00,0x91,0x4C,0x0F,0xE6 -,0x43,0xFF,0xEC,0x31,0x5E,0x00 -,0x00,0xA1,0xEB,0x31,0x08,0x00 -,0x00,0xA6,0xEB,0x31,0x08,0x00 -,0x00,0xAC,0x3C,0x00,0xEB,0x31 -,0x08,0x00,0x00,0xA8,0x76,0xFE -,0xFE,0x08,0xEB,0x31,0x08,0x20 -,0x00,0x00,0x76,0xFF,0xFF,0x18 -,0xED,0x31,0x08,0x20,0x00,0x00 -,0x26,0x10,0x04,0x10,0xF5,0x3C -,0x01,0x3C,0x00,0x08,0x01,0x12 -,0x3C,0x11,0x3C,0x00,0x08,0x01 -,0x0B,0x08,0x00,0x6D,0xEC,0x31 -,0xAE,0x20,0x00,0x06,0xED,0x4D -,0x08,0x00,0x00,0x67,0x80,0x6F -,0x00,0x01,0x0B,0x6F,0x00,0x02 -,0x2E,0x76,0xEE,0x01,0x48,0x06 -,0x01,0x39,0xED,0x4D,0x18,0x00 -,0x02,0xED,0x4D,0x08,0x00,0x04 -,0x14,0x06,0xA4,0xED,0x31,0x22 -,0x00,0x00,0xAC,0x76,0xEE,0x07 -,0x48,0x6D,0x22,0x01,0x1E,0x08 -,0x01,0x58,0xEB,0x31,0x08,0x00 -,0x00,0xAC,0x06,0xFF,0xBA,0x3C -,0x00,0xEB,0x31,0x08,0x20,0x00 -,0x04,0x3C,0x30,0xEB,0x31,0x08 -,0x20,0x00,0x02,0x3C,0x10,0xEB -,0x31,0x08,0x20,0x00,0x00,0xED -,0x31,0x08,0x20,0x00,0x00,0x04 -,0x10,0xF7,0xED,0x31,0x08,0x00 -,0x00,0xA2,0x91,0x00,0x9C,0x3C -,0x80,0xEB,0x31,0x08,0x20,0x00 -,0x04,0x3C,0x20,0xEB,0x31,0x08 -,0x20,0x00,0x02,0x3C,0x10,0xEB -,0x31,0x08,0x20,0x00,0x00,0xED -,0x31,0x08,0x20,0x00,0x00,0x04 -,0x10,0xF7,0xED,0x31,0x08,0x20 -,0x00,0x04,0x42,0x10,0x90,0x08 -,0xEC,0x31,0xAE,0x20,0x00,0x06 -,0xA4,0x41,0x08,0x00,0xB6,0xED -,0x41,0x28,0x7D,0xFF,0xFF,0x22 -,0xB3,0x40,0x98,0x2A,0x32,0xEB -,0x41,0x28,0xB4,0x43,0xFC,0x05 -,0xFF,0xE6,0xA0,0x31,0x20,0x00 -,0x06,0xEB,0x31,0x08,0x20,0x00 -,0x04,0x3C,0x20,0xEB,0x31,0x08 -,0x20,0x00,0x02,0x3C,0x10,0xEB -,0x31,0x08,0x20,0x00,0x00,0xED -,0x31,0x08,0x20,0x00,0x00,0x04 -,0x10,0xF7,0xED,0x31,0x08,0x20 -,0x00,0x04,0x42,0x10,0x90,0x08 -,0xEC,0x31,0xAE,0x20,0x00,0x06 -,0xA4,0x41,0x08,0x00,0x68,0xED -,0x41,0x28,0x7D,0xFF,0xFF,0x22 -,0xB3,0x40,0x98,0x2A,0x32,0xEB -,0x41,0x28,0xB4,0x43,0xFC,0x05 -,0xFF,0xE6,0x48,0x04,0xEB,0x31 -,0x08,0x20,0x00,0x04,0xEB,0x31 -,0x18,0x20,0x00,0x02,0x3C,0x11 -,0xEB,0x31,0x18,0x20,0x00,0x00 -,0xED,0x31,0x08,0x20,0x00,0x00 -,0x04,0x10,0xF7,0xED,0x31,0x08 -,0x20,0x00,0x02,0x66,0x00,0x6F -,0x00,0x01,0x16,0x76,0xEE,0x06 -,0x48,0x4A,0x1E,0x48,0x04,0xED -,0x31,0x08,0x20,0x00,0x04,0xEB -,0x31,0x08,0x00,0x00,0xA4,0x48 -,0x04,0xED,0x31,0x08,0x20,0x00 -,0x04,0xEB,0x31,0x08,0x00,0x00 -,0xA2,0x48,0x04,0x20,0x20,0x4A -,0x7C,0x46,0x82,0x50,0x05,0x50 -,0x15,0xB5,0x1E,0x98,0xED,0x31 -,0x08,0x00,0x00,0xA8,0x10,0x47 -,0x3B,0x2C,0x01,0xDB,0x40,0x11 -,0x98,0xC1,0x1E,0x98,0x10,0x07 -,0x30,0xF9,0x40,0x07,0x18,0x98 -,0x2A,0x10,0xEB,0x31,0x08,0x00 -,0x00,0xA8,0xA4,0x1E,0x98,0xBB -,0x1E,0x98,0x50,0x14,0x50,0x04 -,0x46,0x83,0x48,0x04,0x02,0x01 -,0x00,0x50,0x05,0x50,0x15,0x10 -,0x87,0x3F,0x90,0x2B,0x18,0x01 -,0x00,0xC0,0x31,0x00,0x00,0xAE -,0xDF,0x41,0x00,0x08,0x00,0x1A -,0x42,0x11,0x67,0x01,0xDF,0x41 -,0x02,0x08,0x00,0x10,0x42,0x11 -,0x62,0x01,0xB4,0x43,0x4A,0x68 -,0x50,0x14,0x50,0x04,0x24,0x10 -,0x48,0x04,0xF2,0x31,0x00,0x01 -,0x00,0x00,0xAE,0xF6,0x31,0x00 -,0x01,0x00,0x00,0xAE,0x62,0xE4 -,0xE5,0x61,0x04,0x48,0x04,0xE5 -,0x63,0x05,0x48,0x04,0x20,0x20 -,0x00,0x00,0x00,0x00 +static unsigned char bootimage[] = { + 0x00, 0x00, 0x01, 0x5E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xD7, + 0x00, 0x00, 0x01, 0x5E, 0x46, 0xB3, + 0xE6, 0x02, 0x00, 0x98, 0xE6, 0x8C, + 0x00, 0x98, 0xFB, 0x92, 0xFF, 0xFF, + 0x98, 0xFB, 0x94, 0xFF, 0xFF, 0x98, + 0xFB, 0x06, 0x08, 0x00, 0x98, 0xFB, + 0x96, 0x84, 0x00, 0x98, 0xFB, 0x08, + 0x1C, 0x00, 0x98, 0xFB, 0x51, 0x25, + 0x10, 0x1C, 0x00, 0xE6, 0x51, 0x01, + 0x07, 0xFD, 0x4C, 0xFF, 0x20, 0xF5, + 0x51, 0x02, 0x20, 0x08, 0x00, 0x4C, + 0xFF, 0x20, 0x3C, 0x00, 0xC0, 0x64, + 0x98, 0xC0, 0x66, 0x98, 0xC0, 0x68, + 0x98, 0xC0, 0x6A, 0x98, 0xC0, 0x6C, + 0x98, 0x90, 0x08, 0x90, 0x09, 0x90, + 0x0A, 0x90, 0x0B, 0x90, 0x0C, 0x90, + 0x0D, 0x90, 0x0E, 0x90, 0x0F, 0x90, + 0x04, 0x90, 0x06, 0xFB, 0x51, 0x22, + 0x16, 0x08, 0x03, 0xFB, 0x51, 0x52, + 0x16, 0x08, 0x04, 0xFB, 0x51, 0x24, + 0x2B, 0x08, 0x06, 0xFB, 0x51, 0x54, + 0x2B, 0x08, 0x07, 0xFB, 0x51, 0x24, + 0x2B, 0x08, 0x09, 0xFB, 0x51, 0x54, + 0x2B, 0x08, 0x0A, 0xFB, 0x51, 0x12, + 0x16, 0x08, 0x0C, 0xFB, 0x51, 0x52, + 0x16, 0x08, 0x0D, 0x78, 0x00, 0x00, + 0x00, 0x16, 0x00, 0x00, 0xEC, 0x31, + 0xAE, 0x00, 0x00, 0x81, 0x4C, 0x0F, + 0xE6, 0x43, 0xFF, 0xEC, 0x31, 0x4E, + 0x00, 0x00, 0x91, 0xEC, 0x31, 0xAE, + 0x00, 0x00, 0x91, 0x4C, 0x0F, 0xE6, + 0x43, 0xFF, 0xEC, 0x31, 0x5E, 0x00, + 0x00, 0xA1, 0xEB, 0x31, 0x08, 0x00, + 0x00, 0xA6, 0xEB, 0x31, 0x08, 0x00, + 0x00, 0xAC, 0x3C, 0x00, 0xEB, 0x31, + 0x08, 0x00, 0x00, 0xA8, 0x76, 0xFE, + 0xFE, 0x08, 0xEB, 0x31, 0x08, 0x20, + 0x00, 0x00, 0x76, 0xFF, 0xFF, 0x18, + 0xED, 0x31, 0x08, 0x20, 0x00, 0x00, + 0x26, 0x10, 0x04, 0x10, 0xF5, 0x3C, + 0x01, 0x3C, 0x00, 0x08, 0x01, 0x12, + 0x3C, 0x11, 0x3C, 0x00, 0x08, 0x01, + 0x0B, 0x08, 0x00, 0x6D, 0xEC, 0x31, + 0xAE, 0x20, 0x00, 0x06, 0xED, 0x4D, + 0x08, 0x00, 0x00, 0x67, 0x80, 0x6F, + 0x00, 0x01, 0x0B, 0x6F, 0x00, 0x02, + 0x2E, 0x76, 0xEE, 0x01, 0x48, 0x06, + 0x01, 0x39, 0xED, 0x4D, 0x18, 0x00, + 0x02, 0xED, 0x4D, 0x08, 0x00, 0x04, + 0x14, 0x06, 0xA4, 0xED, 0x31, 0x22, + 0x00, 0x00, 0xAC, 0x76, 0xEE, 0x07, + 0x48, 0x6D, 0x22, 0x01, 0x1E, 0x08, + 0x01, 0x58, 0xEB, 0x31, 0x08, 0x00, + 0x00, 0xAC, 0x06, 0xFF, 0xBA, 0x3C, + 0x00, 0xEB, 0x31, 0x08, 0x20, 0x00, + 0x04, 0x3C, 0x30, 0xEB, 0x31, 0x08, + 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB, + 0x31, 0x08, 0x20, 0x00, 0x00, 0xED, + 0x31, 0x08, 0x20, 0x00, 0x00, 0x04, + 0x10, 0xF7, 0xED, 0x31, 0x08, 0x00, + 0x00, 0xA2, 0x91, 0x00, 0x9C, 0x3C, + 0x80, 0xEB, 0x31, 0x08, 0x20, 0x00, + 0x04, 0x3C, 0x20, 0xEB, 0x31, 0x08, + 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB, + 0x31, 0x08, 0x20, 0x00, 0x00, 0xED, + 0x31, 0x08, 0x20, 0x00, 0x00, 0x04, + 0x10, 0xF7, 0xED, 0x31, 0x08, 0x20, + 0x00, 0x04, 0x42, 0x10, 0x90, 0x08, + 0xEC, 0x31, 0xAE, 0x20, 0x00, 0x06, + 0xA4, 0x41, 0x08, 0x00, 0xB6, 0xED, + 0x41, 0x28, 0x7D, 0xFF, 0xFF, 0x22, + 0xB3, 0x40, 0x98, 0x2A, 0x32, 0xEB, + 0x41, 0x28, 0xB4, 0x43, 0xFC, 0x05, + 0xFF, 0xE6, 0xA0, 0x31, 0x20, 0x00, + 0x06, 0xEB, 0x31, 0x08, 0x20, 0x00, + 0x04, 0x3C, 0x20, 0xEB, 0x31, 0x08, + 0x20, 0x00, 0x02, 0x3C, 0x10, 0xEB, + 0x31, 0x08, 0x20, 0x00, 0x00, 0xED, + 0x31, 0x08, 0x20, 0x00, 0x00, 0x04, + 0x10, 0xF7, 0xED, 0x31, 0x08, 0x20, + 0x00, 0x04, 0x42, 0x10, 0x90, 0x08, + 0xEC, 0x31, 0xAE, 0x20, 0x00, 0x06, + 0xA4, 0x41, 0x08, 0x00, 0x68, 0xED, + 0x41, 0x28, 0x7D, 0xFF, 0xFF, 0x22, + 0xB3, 0x40, 0x98, 0x2A, 0x32, 0xEB, + 0x41, 0x28, 0xB4, 0x43, 0xFC, 0x05, + 0xFF, 0xE6, 0x48, 0x04, 0xEB, 0x31, + 0x08, 0x20, 0x00, 0x04, 0xEB, 0x31, + 0x18, 0x20, 0x00, 0x02, 0x3C, 0x11, + 0xEB, 0x31, 0x18, 0x20, 0x00, 0x00, + 0xED, 0x31, 0x08, 0x20, 0x00, 0x00, + 0x04, 0x10, 0xF7, 0xED, 0x31, 0x08, + 0x20, 0x00, 0x02, 0x66, 0x00, 0x6F, + 0x00, 0x01, 0x16, 0x76, 0xEE, 0x06, + 0x48, 0x4A, 0x1E, 0x48, 0x04, 0xED, + 0x31, 0x08, 0x20, 0x00, 0x04, 0xEB, + 0x31, 0x08, 0x00, 0x00, 0xA4, 0x48, + 0x04, 0xED, 0x31, 0x08, 0x20, 0x00, + 0x04, 0xEB, 0x31, 0x08, 0x00, 0x00, + 0xA2, 0x48, 0x04, 0x20, 0x20, 0x4A, + 0x7C, 0x46, 0x82, 0x50, 0x05, 0x50, + 0x15, 0xB5, 0x1E, 0x98, 0xED, 0x31, + 0x08, 0x00, 0x00, 0xA8, 0x10, 0x47, + 0x3B, 0x2C, 0x01, 0xDB, 0x40, 0x11, + 0x98, 0xC1, 0x1E, 0x98, 0x10, 0x07, + 0x30, 0xF9, 0x40, 0x07, 0x18, 0x98, + 0x2A, 0x10, 0xEB, 0x31, 0x08, 0x00, + 0x00, 0xA8, 0xA4, 0x1E, 0x98, 0xBB, + 0x1E, 0x98, 0x50, 0x14, 0x50, 0x04, + 0x46, 0x83, 0x48, 0x04, 0x02, 0x01, + 0x00, 0x50, 0x05, 0x50, 0x15, 0x10, + 0x87, 0x3F, 0x90, 0x2B, 0x18, 0x01, + 0x00, 0xC0, 0x31, 0x00, 0x00, 0xAE, + 0xDF, 0x41, 0x00, 0x08, 0x00, 0x1A, + 0x42, 0x11, 0x67, 0x01, 0xDF, 0x41, + 0x02, 0x08, 0x00, 0x10, 0x42, 0x11, + 0x62, 0x01, 0xB4, 0x43, 0x4A, 0x68, + 0x50, 0x14, 0x50, 0x04, 0x24, 0x10, + 0x48, 0x04, 0xF2, 0x31, 0x00, 0x01, + 0x00, 0x00, 0xAE, 0xF6, 0x31, 0x00, + 0x01, 0x00, 0x00, 0xAE, 0x62, 0xE4, + 0xE5, 0x61, 0x04, 0x48, 0x04, 0xE5, + 0x63, 0x05, 0x48, 0x04, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00 }; #endif -- cgit v1.2.3 From c4df2822cd54118ad8a7a672ea9dcaa2d77fc776 Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Sun, 10 Nov 2013 15:44:20 +0200 Subject: Staging: ft1000: ft1000_download: fixed coding style issues Fixed the following coding style issues: Lines 84-91,99-106,275,514: Replaced spaces at the start of the lines with tabs. Lines 205,271: Inserted spaces after the commas. Lines 275,1060,1065: Indented the code with tabs instead of spaces. Line 275: Inserted spaces around '=' and '<', also moved the trailing statement on the next line. Line 512: Removed space between function name and open parenthesis. Line 839: Removed space after '&'. Line 853: Removed space after '&'. Signed-off-by: Aldo Iljazi Signed-off-by: Greg Kroah-Hartman --- .../staging/ft1000/ft1000-usb/ft1000_download.c | 57 +++++++++++----------- 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index b2643b780971..3c2b085e7990 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -81,29 +81,29 @@ #define DWNLD_MAG1_PS_HDR_LOC 0x03 struct dsp_file_hdr { - long version_id; // Version ID of this image format. - long package_id; // Package ID of code release. - long build_date; // Date/time stamp when file was built. - long commands_offset; // Offset to attached commands in Pseudo Hdr format. - long loader_offset; // Offset to bootloader code. - long loader_code_address; // Start address of bootloader. - long loader_code_end; // Where bootloader code ends. - long loader_code_size; - long version_data_offset; // Offset were scrambled version data begins. - long version_data_size; // Size, in words, of scrambled version data. - long nDspImages; // Number of DSP images in file. + long version_id; // Version ID of this image format. + long package_id; // Package ID of code release. + long build_date; // Date/time stamp when file was built. + long commands_offset; // Offset to attached commands in Pseudo Hdr format. + long loader_offset; // Offset to bootloader code. + long loader_code_address; // Start address of bootloader. + long loader_code_end; // Where bootloader code ends. + long loader_code_size; + long version_data_offset; // Offset were scrambled version data begins. + long version_data_size; // Size, in words, of scrambled version data. + long nDspImages; // Number of DSP images in file. }; #pragma pack(1) struct dsp_image_info { - long coff_date; // Date/time when DSP Coff image was built. - long begin_offset; // Offset in file where image begins. - long end_offset; // Offset in file where image begins. - long run_address; // On chip Start address of DSP code. - long image_size; // Size of image. - long version; // Embedded version # of DSP code. - unsigned short checksum; // DSP File checksum - unsigned short pad1; + long coff_date; // Date/time when DSP Coff image was built. + long begin_offset; // Offset in file where image begins. + long end_offset; // Offset in file where image begins. + long run_address; // On chip Start address of DSP code. + long image_size; // Size of image. + long version; // Embedded version # of DSP code. + unsigned short checksum; // DSP File checksum + unsigned short pad1; }; @@ -201,7 +201,7 @@ static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value) } /* write the handshake value to the handshake location */ -static void put_handshake(struct ft1000_usb *ft1000dev,u16 handshake_value) +static void put_handshake(struct ft1000_usb *ft1000dev, u16 handshake_value) { u32 tempx; u16 tempword; @@ -267,11 +267,12 @@ static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value) return HANDSHAKE_TIMEOUT_VALUE; } -static void put_handshake_usb(struct ft1000_usb *ft1000dev,u16 handshake_value) +static void put_handshake_usb(struct ft1000_usb *ft1000dev, u16 handshake_value) { int i; - for (i=0; i<1000; i++); + for (i = 0; i < 1000; i++) + ; } static u16 get_request_type(struct ft1000_usb *ft1000dev) @@ -508,9 +509,9 @@ static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, return status; } -static void usb_dnld_complete (struct urb *urb) +static void usb_dnld_complete(struct urb *urb) { - //DEBUG("****** usb_dnld_complete\n"); + //DEBUG("****** usb_dnld_complete\n"); } /* writes a block of DSP image to DPRAM @@ -835,7 +836,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, * Position ASIC DPRAM auto-increment pointer. */ - data = (u16 *) & mailbox_data->data[0]; + data = (u16 *) &mailbox_data->data[0]; dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; @@ -849,7 +850,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, - (u8 *) & templong); + (u8 *) &templong); } break; @@ -1056,12 +1057,12 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, // Check if Card is present status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK); if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) { - break; + break; } status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID); if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) { - break; + break; } ****/ -- cgit v1.2.3 From 9961d59d3fe7b8bd135f4a8506bd7e5f4d919dbe Mon Sep 17 00:00:00 2001 From: Jie Liu Date: Fri, 1 Nov 2013 22:22:08 +0800 Subject: staging: ozwpan: remove unneeded __GFP_ZERO to kzalloc() at oz_elt_stream_create() Get rid of the needless __GFP_ZERO flag for kzalloc() at oz_elt_stream_create(). Signed-off-by: Jie Liu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozeltbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c index 9b86486c6b11..02d541247819 100644 --- a/drivers/staging/ozwpan/ozeltbuf.c +++ b/drivers/staging/ozwpan/ozeltbuf.c @@ -138,7 +138,7 @@ int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count) oz_dbg(ON, "%s: (0x%x)\n", __func__, id); - st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC | __GFP_ZERO); + st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC); if (st == NULL) return -ENOMEM; atomic_set(&st->ref_count, 1); -- cgit v1.2.3 From fc0524b0986f994693f06a00c8de1c0469fd7086 Mon Sep 17 00:00:00 2001 From: Gu Zheng Date: Thu, 31 Oct 2013 18:33:01 +0800 Subject: staging/olpc_docn: reorder the lock sequence to avoid potential dead lock The lock sequence of dcon_blank_fb(fb_info->lock ---> console_lock) is against with the one of console_callback(console_lock ---> fb_info->lock), it'll lead to a potential dead lock, so reorder the lock sequence of dcon_blank_fb to avoid the potential dead lock. Signed-off-by: Gu Zheng Signed-off-by: Greg Kroah-Hartman --- drivers/staging/olpc_dcon/olpc_dcon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 92b02891704d..26b4ec56fd30 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -255,17 +255,19 @@ static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank) { int err; + console_lock(); if (!lock_fb_info(dcon->fbinfo)) { + console_unlock(); dev_err(&dcon->client->dev, "unable to lock framebuffer\n"); return false; } - console_lock(); + dcon->ignore_fb_events = true; err = fb_blank(dcon->fbinfo, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); dcon->ignore_fb_events = false; - console_unlock(); unlock_fb_info(dcon->fbinfo); + console_unlock(); if (err) { dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n", -- cgit v1.2.3 From a72f8beeedc97b776799a1a80c04eb5312980c9b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 3 Nov 2013 14:31:09 +0100 Subject: drm/imx: directly call drm_put_dev in ->remove Again no apparent user of the driver data field. Signed-off-by: Daniel Vetter Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-drm-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 4483d47f7395..65396b2468e5 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -443,6 +443,8 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) if (!imx_drm_device_get()) ret = -EINVAL; + platform_set_drvdata(drm->platformdev, drm); + ret = 0; err_init: @@ -822,7 +824,7 @@ static int imx_drm_platform_probe(struct platform_device *pdev) static int imx_drm_platform_remove(struct platform_device *pdev) { - drm_platform_exit(&imx_drm_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } -- cgit v1.2.3 From 302433daf47aeb7d21d66e55fb84d6a8fffd4aed Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 3 Nov 2013 17:40:51 +0000 Subject: staging: vt6656: device.h Remove typedef enum __device_init_type. Since typedef enum __device_init_type is only ever called in one state. Remove the typedef from main_usb.c:device_init_registers and replace with macro values. The other values may be needed later. Apply cold value to sInitCmd.byInitClass. Remove if braces and correct formatting within. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 8 +- drivers/staging/vt6656/main_usb.c | 274 +++++++++++++++++++------------------- 2 files changed, 143 insertions(+), 139 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 62b7de19b371..ef2b9228180c 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -149,11 +149,9 @@ typedef enum __device_msg_level { MSG_LEVEL_DEBUG = 4 /* Only for debug purpose. */ } DEVICE_MSG_LEVEL, *PDEVICE_MSG_LEVEL; -typedef enum __device_init_type { - DEVICE_INIT_COLD = 0, /* cold init */ - DEVICE_INIT_RESET, /* reset init or Dx to D0 power remain */ - DEVICE_INIT_DXPL /* Dx to D0 power lost init */ -} DEVICE_INIT_TYPE, *PDEVICE_INIT_TYPE; +#define DEVICE_INIT_COLD 0x0 /* cold init */ +#define DEVICE_INIT_RESET 0x1 /* reset init or Dx to D0 power remain */ +#define DEVICE_INIT_DXPL 0x2 /* Dx to D0 power lost init */ /* USB */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index aae228c533ef..297dd109631c 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -215,8 +215,7 @@ static void device_set_multi(struct net_device *dev); static int device_close(struct net_device *dev); static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int device_init_registers(struct vnt_private *pDevice, - DEVICE_INIT_TYPE InitType); +static int device_init_registers(struct vnt_private *pDevice); static bool device_init_defrag_cb(struct vnt_private *pDevice); static void device_init_diversity_timer(struct vnt_private *pDevice); static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev); @@ -297,8 +296,7 @@ static void device_init_diversity_timer(struct vnt_private *pDevice) * initialization of MAC & BBP registers */ -static int device_init_registers(struct vnt_private *pDevice, - DEVICE_INIT_TYPE InitType) +static int device_init_registers(struct vnt_private *pDevice) { struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -313,12 +311,14 @@ static int device_init_registers(struct vnt_private *pDevice, u8 byTmp; u8 byCalibTXIQ = 0, byCalibTXDC = 0, byCalibRXIQ = 0; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---->INIbInitAdapter. [%d][%d]\n", InitType, pDevice->byPacketType); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---->INIbInitAdapter. [%d][%d]\n", + DEVICE_INIT_COLD, pDevice->byPacketType); + spin_lock_irq(&pDevice->lock); - if (InitType == DEVICE_INIT_COLD) { - memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN); - memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN); - memcpy(pDevice->abySNAP_Bridgetunnel, + + memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN); + memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN); + memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN); @@ -342,9 +342,8 @@ static int device_init_registers(struct vnt_private *pDevice, spin_unlock_irq(&pDevice->lock); return false; } - } - sInitCmd.byInitClass = (u8)InitType; + sInitCmd.byInitClass = DEVICE_INIT_COLD; sInitCmd.bExistSWNetAddr = (u8) pDevice->bExistSWNetAddr; for (ii = 0; ii < 6; ii++) sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii]; @@ -364,138 +363,145 @@ static int device_init_registers(struct vnt_private *pDevice, spin_unlock_irq(&pDevice->lock); return false; } - if (InitType == DEVICE_INIT_COLD) { - ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp)); - - if (ntStatus != STATUS_SUCCESS) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n"); - spin_unlock_irq(&pDevice->lock); - return false; - } + ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_INIT_RSP, 0, 0, + sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp)); + if (ntStatus != STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Cardinit request in status fail!\n"); + spin_unlock_irq(&pDevice->lock); + return false; + } /* local ID for AES functions */ - ntStatus = CONTROLnsRequestIn(pDevice, - MESSAGE_TYPE_READ, - MAC_REG_LOCALID, - MESSAGE_REQUEST_MACREG, - 1, - &pDevice->byLocalID); - - if ( ntStatus != STATUS_SUCCESS ) { - spin_unlock_irq(&pDevice->lock); - return false; - } + ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, + MAC_REG_LOCALID, MESSAGE_REQUEST_MACREG, 1, + &pDevice->byLocalID); + if (ntStatus != STATUS_SUCCESS) { + spin_unlock_irq(&pDevice->lock); + return false; + } /* do MACbSoftwareReset in MACvInitialize */ /* force CCK */ - pDevice->bCCK = true; + pDevice->bCCK = true; pDevice->bProtectMode = false; /* only used in 11g type, sync with ERP IE */ - pDevice->bNonERPPresent = false; - pDevice->bBarkerPreambleMd = false; - if ( pDevice->bFixRate ) { - pDevice->wCurrentRate = (u16) pDevice->uConnectionRate; - } else { - if ( pDevice->byBBType == BB_TYPE_11B ) - pDevice->wCurrentRate = RATE_11M; - else - pDevice->wCurrentRate = RATE_54M; - } + pDevice->bNonERPPresent = false; + pDevice->bBarkerPreambleMd = false; + if (pDevice->bFixRate) { + pDevice->wCurrentRate = (u16)pDevice->uConnectionRate; + } else { + if (pDevice->byBBType == BB_TYPE_11B) + pDevice->wCurrentRate = RATE_11M; + else + pDevice->wCurrentRate = RATE_54M; + } - CHvInitChannelTable(pDevice); + CHvInitChannelTable(pDevice); - pDevice->byTopOFDMBasicRate = RATE_24M; - pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_24M; + pDevice->byTopCCKBasicRate = RATE_1M; pDevice->byRevId = 0; /* target to IF pin while programming to RF chip */ - pDevice->byCurPwr = 0xFF; + pDevice->byCurPwr = 0xFF; - pDevice->byCCKPwr = pDevice->abyEEPROM[EEP_OFS_PWR_CCK]; - pDevice->byOFDMPwrG = pDevice->abyEEPROM[EEP_OFS_PWR_OFDMG]; + pDevice->byCCKPwr = pDevice->abyEEPROM[EEP_OFS_PWR_CCK]; + pDevice->byOFDMPwrG = pDevice->abyEEPROM[EEP_OFS_PWR_OFDMG]; /* load power table */ for (ii = 0; ii < 14; ii++) { - pDevice->abyCCKPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_CCK_PWR_TBL]; - if (pDevice->abyCCKPwrTbl[ii] == 0) - pDevice->abyCCKPwrTbl[ii] = pDevice->byCCKPwr; - pDevice->abyOFDMPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_OFDM_PWR_TBL]; - if (pDevice->abyOFDMPwrTbl[ii] == 0) - pDevice->abyOFDMPwrTbl[ii] = pDevice->byOFDMPwrG; - } + pDevice->abyCCKPwrTbl[ii] = + pDevice->abyEEPROM[ii + EEP_OFS_CCK_PWR_TBL]; + + if (pDevice->abyCCKPwrTbl[ii] == 0) + pDevice->abyCCKPwrTbl[ii] = pDevice->byCCKPwr; + pDevice->abyOFDMPwrTbl[ii] = + pDevice->abyEEPROM[ii + EEP_OFS_OFDM_PWR_TBL]; + if (pDevice->abyOFDMPwrTbl[ii] == 0) + pDevice->abyOFDMPwrTbl[ii] = pDevice->byOFDMPwrG; + } /* * original zonetype is USA, but custom zonetype is Europe, * then need to recover 12, 13, 14 channels with 11 channel */ - if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) || - (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&& - (pDevice->byOriginalZonetype == ZoneType_USA)) { + if (((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) || + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe)) && + (pDevice->byOriginalZonetype == ZoneType_USA)) { for (ii = 11; ii < 14; ii++) { pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; } - } + } - pDevice->byOFDMPwrA = 0x34; /* same as RFbMA2829SelectChannel */ + pDevice->byOFDMPwrA = 0x34; /* same as RFbMA2829SelectChannel */ - /* load OFDM A power table */ - for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { - pDevice->abyOFDMAPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_OFDMA_PWR_TBL]; - if (pDevice->abyOFDMAPwrTbl[ii] == 0) - pDevice->abyOFDMAPwrTbl[ii] = pDevice->byOFDMPwrA; - } + /* load OFDM A power table */ + for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { + pDevice->abyOFDMAPwrTbl[ii] = + pDevice->abyEEPROM[ii + EEP_OFS_OFDMA_PWR_TBL]; - byAntenna = pDevice->abyEEPROM[EEP_OFS_ANTENNA]; - if (byAntenna & EEP_ANTINV) - pDevice->bTxRxAntInv = true; - else - pDevice->bTxRxAntInv = false; + if (pDevice->abyOFDMAPwrTbl[ii] == 0) + pDevice->abyOFDMAPwrTbl[ii] = pDevice->byOFDMPwrA; + } - byAntenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + byAntenna = pDevice->abyEEPROM[EEP_OFS_ANTENNA]; + + if (byAntenna & EEP_ANTINV) + pDevice->bTxRxAntInv = true; + else + pDevice->bTxRxAntInv = false; + + byAntenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); if (byAntenna == 0) /* if not set default is both */ - byAntenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - - if (byAntenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { - pDevice->byAntennaCount = 2; - pDevice->byTxAntennaMode = ANT_B; - pDevice->dwTxAntennaSel = 1; - pDevice->dwRxAntennaSel = 1; - if (pDevice->bTxRxAntInv == true) - pDevice->byRxAntennaMode = ANT_A; - else - pDevice->byRxAntennaMode = ANT_B; - - if (pDevice->bDiversityRegCtlON) - pDevice->bDiversityEnable = true; - else - pDevice->bDiversityEnable = false; - } else { - pDevice->bDiversityEnable = false; - pDevice->byAntennaCount = 1; - pDevice->dwTxAntennaSel = 0; - pDevice->dwRxAntennaSel = 0; - if (byAntenna & EEP_ANTENNA_AUX) { - pDevice->byTxAntennaMode = ANT_A; - if (pDevice->bTxRxAntInv == true) - pDevice->byRxAntennaMode = ANT_B; - else - pDevice->byRxAntennaMode = ANT_A; - } else { - pDevice->byTxAntennaMode = ANT_B; - if (pDevice->bTxRxAntInv == true) - pDevice->byRxAntennaMode = ANT_A; - else - pDevice->byRxAntennaMode = ANT_B; - } - } - pDevice->ulDiversityNValue = 100*255; - pDevice->ulDiversityMValue = 100*16; - pDevice->byTMax = 1; - pDevice->byTMax2 = 4; - pDevice->ulSQ3TH = 0; - pDevice->byTMax3 = 64; + byAntenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + + if (byAntenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { + pDevice->byAntennaCount = 2; + pDevice->byTxAntennaMode = ANT_B; + pDevice->dwTxAntennaSel = 1; + pDevice->dwRxAntennaSel = 1; + + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + + if (pDevice->bDiversityRegCtlON) + pDevice->bDiversityEnable = true; + else + pDevice->bDiversityEnable = false; + } else { + pDevice->bDiversityEnable = false; + pDevice->byAntennaCount = 1; + pDevice->dwTxAntennaSel = 0; + pDevice->dwRxAntennaSel = 0; + + if (byAntenna & EEP_ANTENNA_AUX) { + pDevice->byTxAntennaMode = ANT_A; + + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_B; + else + pDevice->byRxAntennaMode = ANT_A; + } else { + pDevice->byTxAntennaMode = ANT_B; + + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + } + } + + pDevice->ulDiversityNValue = 100 * 255; + pDevice->ulDiversityMValue = 100 * 16; + pDevice->byTMax = 1; + pDevice->byTMax2 = 4; + pDevice->ulSQ3TH = 0; + pDevice->byTMax3 = 64; /* get Auto Fall Back type */ pDevice->byAutoFBCtrl = AUTO_FB_0; @@ -524,49 +530,50 @@ static int device_init_registers(struct vnt_private *pDevice, } /* load vt3266 calibration parameters in EEPROM */ - if (pDevice->byRFType == RF_VT3226D0) { - if((pDevice->abyEEPROM[EEP_OFS_MAJOR_VER] == 0x1) && - (pDevice->abyEEPROM[EEP_OFS_MINOR_VER] >= 0x4)) { - byCalibTXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_IQ]; - byCalibTXDC = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_DC]; - byCalibRXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_RX_IQ]; - if( (byCalibTXIQ || byCalibTXDC || byCalibRXIQ) ) { + if (pDevice->byRFType == RF_VT3226D0) { + if ((pDevice->abyEEPROM[EEP_OFS_MAJOR_VER] == 0x1) && + (pDevice->abyEEPROM[EEP_OFS_MINOR_VER] >= 0x4)) { + + byCalibTXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_IQ]; + byCalibTXDC = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_DC]; + byCalibRXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_RX_IQ]; + if (byCalibTXIQ || byCalibTXDC || byCalibRXIQ) { /* CR255, enable TX/RX IQ and DC compensation mode */ - ControlvWriteByte(pDevice, + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xFF, 0x03); /* CR251, TX I/Q Imbalance Calibration */ - ControlvWriteByte(pDevice, + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xFB, byCalibTXIQ); /* CR252, TX DC-Offset Calibration */ - ControlvWriteByte(pDevice, + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xFC, byCalibTXDC); /* CR253, RX I/Q Imbalance Calibration */ - ControlvWriteByte(pDevice, + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xFD, byCalibRXIQ); - } else { + } else { /* CR255, turn off BB Calibration compensation */ - ControlvWriteByte(pDevice, + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xFF, 0x0); - } - } - } + } + } + } pMgmt->eScanType = WMAC_SCAN_PASSIVE; pMgmt->uCurrChannel = pDevice->uChannel; pMgmt->uIBSSChannel = pDevice->uChannel; CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); /* get permanent network address */ - memcpy(pDevice->abyPermanentNetAddr,&(sInitRsp.byNetAddr[0]),6); + memcpy(pDevice->abyPermanentNetAddr, &sInitRsp.byNetAddr[0], 6); memcpy(pDevice->abyCurrentNetAddr, pDevice->abyPermanentNetAddr, ETH_ALEN); @@ -574,7 +581,6 @@ static int device_init_registers(struct vnt_private *pDevice, /* if exist SW network address, use it */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n", pDevice->abyCurrentNetAddr); - } /* * set BB and packet type at the same time @@ -962,10 +968,10 @@ static int device_open(struct net_device *dev) /* read config file */ Read_config_file(pDevice); - if (device_init_registers(pDevice, DEVICE_INIT_COLD) == false) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " init register fail\n"); - goto free_all; - } + if (device_init_registers(pDevice) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " init register fail\n"); + goto free_all; + } device_set_multi(pDevice->dev); -- cgit v1.2.3 From 3d47a6fb2bd842206924214f7ec820cdfb92cf02 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 3 Nov 2013 17:43:23 +0000 Subject: staging: vt6656: Replace typedef struct _CMD_CARD_INIT Replace with struct vnt_cmd_card_init init_cmd in device_init_registers. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 27 ++++++++++++--------------- drivers/staging/vt6656/rndis.h | 14 +++++++------- 2 files changed, 19 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 297dd109631c..fd8dfe971054 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -299,13 +299,13 @@ static void device_init_diversity_timer(struct vnt_private *pDevice) static int device_init_registers(struct vnt_private *pDevice) { struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_cmd_card_init init_cmd; u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 abySNAP_RFC1042[ETH_ALEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; u8 abySNAP_Bridgetunnel[ETH_ALEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; u8 byAntenna; int ii; - CMD_CARD_INIT sInitCmd; int ntStatus = STATUS_SUCCESS; RSP_CARD_INIT sInitRsp; u8 byTmp; @@ -343,20 +343,17 @@ static int device_init_registers(struct vnt_private *pDevice) return false; } - sInitCmd.byInitClass = DEVICE_INIT_COLD; - sInitCmd.bExistSWNetAddr = (u8) pDevice->bExistSWNetAddr; - for (ii = 0; ii < 6; ii++) - sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii]; - sInitCmd.byShortRetryLimit = pDevice->byShortRetryLimit; - sInitCmd.byLongRetryLimit = pDevice->byLongRetryLimit; - - /* issue card_init command to device */ - ntStatus = CONTROLnsRequestOut(pDevice, - MESSAGE_TYPE_CARDINIT, - 0, - 0, - sizeof(CMD_CARD_INIT), - (u8 *) &(sInitCmd)); + init_cmd.init_class = DEVICE_INIT_COLD; + init_cmd.exist_sw_net_addr = (u8) pDevice->bExistSWNetAddr; + for (ii = 0; ii < 6; ii++) + init_cmd.sw_net_addr[ii] = pDevice->abyCurrentNetAddr[ii]; + init_cmd.short_retry_limit = pDevice->byShortRetryLimit; + init_cmd.long_retry_limit = pDevice->byLongRetryLimit; + + /* issue card_init command to device */ + ntStatus = CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_CARDINIT, 0, 0, + sizeof(struct vnt_cmd_card_init), (u8 *)&init_cmd); if ( ntStatus != STATUS_SUCCESS ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n"); diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h index 5e073062017a..5dcc4b4007a3 100644 --- a/drivers/staging/vt6656/rndis.h +++ b/drivers/staging/vt6656/rndis.h @@ -77,14 +77,14 @@ typedef struct _CMD_WRITE_MASK u8 byMask; } CMD_WRITE_MASK, *PCMD_WRITE_MASK; -typedef struct _CMD_CARD_INIT +struct vnt_cmd_card_init { - u8 byInitClass; - u8 bExistSWNetAddr; - u8 bySWNetAddr[6]; - u8 byShortRetryLimit; - u8 byLongRetryLimit; -} CMD_CARD_INIT, *PCMD_CARD_INIT; + u8 init_class; + u8 exist_sw_net_addr; + u8 sw_net_addr[6]; + u8 short_retry_limit; + u8 long_retry_limit; +}; typedef struct _RSP_CARD_INIT { -- cgit v1.2.3 From ae1e1fe6e57b1640a3bed1d90f63bb59e8a4a3dc Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 3 Nov 2013 17:45:06 +0000 Subject: staging: vt6656: Replace typedef struct _RSP_CARD_INIT. Replace with struct vnt_rsp_card_rsp init_rsp in device_init_registers. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 8 ++++---- drivers/staging/vt6656/rndis.h | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index fd8dfe971054..d1f923c047e8 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -300,6 +300,7 @@ static int device_init_registers(struct vnt_private *pDevice) { struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; struct vnt_cmd_card_init init_cmd; + struct vnt_rsp_card_init init_rsp; u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 abySNAP_RFC1042[ETH_ALEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; u8 abySNAP_Bridgetunnel[ETH_ALEN] @@ -307,7 +308,6 @@ static int device_init_registers(struct vnt_private *pDevice) u8 byAntenna; int ii; int ntStatus = STATUS_SUCCESS; - RSP_CARD_INIT sInitRsp; u8 byTmp; u8 byCalibTXIQ = 0, byCalibTXDC = 0, byCalibRXIQ = 0; @@ -362,7 +362,7 @@ static int device_init_registers(struct vnt_private *pDevice) } ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_INIT_RSP, 0, 0, - sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp)); + sizeof(struct vnt_rsp_card_init), (u8 *)&init_rsp); if (ntStatus != STATUS_SUCCESS) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n"); @@ -519,7 +519,7 @@ static int device_init_registers(struct vnt_private *pDevice) pDevice->byMaxChannel = CB_MAX_CHANNEL; /* get RFType */ - pDevice->byRFType = sInitRsp.byRFType; + pDevice->byRFType = init_rsp.rf_type; if ((pDevice->byRFType & RF_EMU) != 0) { /* force change RevID for VT3253 emu */ @@ -570,7 +570,7 @@ static int device_init_registers(struct vnt_private *pDevice) CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); /* get permanent network address */ - memcpy(pDevice->abyPermanentNetAddr, &sInitRsp.byNetAddr[0], 6); + memcpy(pDevice->abyPermanentNetAddr, &init_rsp.net_addr[0], 6); memcpy(pDevice->abyCurrentNetAddr, pDevice->abyPermanentNetAddr, ETH_ALEN); diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h index 5dcc4b4007a3..08321ad48920 100644 --- a/drivers/staging/vt6656/rndis.h +++ b/drivers/staging/vt6656/rndis.h @@ -86,14 +86,14 @@ struct vnt_cmd_card_init u8 long_retry_limit; }; -typedef struct _RSP_CARD_INIT +struct vnt_rsp_card_init { - u8 byStatus; - u8 byNetAddr[6]; - u8 byRFType; - u8 byMinChannel; - u8 byMaxChannel; -} RSP_CARD_INIT, *PRSP_CARD_INIT; + u8 status; + u8 net_addr[6]; + u8 rf_type; + u8 min_channel; + u8 max_channel; +}; typedef struct _CMD_SET_KEY { -- cgit v1.2.3 From 748bf69c155607b6413206fcbce4d90097bac723 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 3 Nov 2013 17:49:32 +0000 Subject: staging; vt6656: device_init_registers Change vnt_cmd_card_int and vnt_rsp_card_int to off stack Move structures to vnt_private and convert to pointers in device_init_registers. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 3 +++ drivers/staging/vt6656/main_usb.c | 23 +++++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index ef2b9228180c..739cda41b5a7 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -75,6 +75,7 @@ #include "desc.h" #include "key.h" #include "card.h" +#include "rndis.h" #define VNT_USB_VENDOR_ID 0x160a #define VNT_USB_PRODUCT_ID 0x3184 @@ -465,6 +466,8 @@ struct vnt_private { u8 byOriginalZonetype; int bLinkPass; /* link status: OK or fail */ + struct vnt_cmd_card_init init_command; + struct vnt_rsp_card_init init_response; u8 abyCurrentNetAddr[ETH_ALEN]; u8 abyPermanentNetAddr[ETH_ALEN]; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index d1f923c047e8..ba39aaa44220 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -67,7 +67,6 @@ #include "datarate.h" #include "rf.h" #include "firmware.h" -#include "rndis.h" #include "control.h" #include "channel.h" #include "int.h" @@ -299,8 +298,8 @@ static void device_init_diversity_timer(struct vnt_private *pDevice) static int device_init_registers(struct vnt_private *pDevice) { struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; - struct vnt_cmd_card_init init_cmd; - struct vnt_rsp_card_init init_rsp; + struct vnt_cmd_card_init *init_cmd = &pDevice->init_command; + struct vnt_rsp_card_init *init_rsp = &pDevice->init_response; u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 abySNAP_RFC1042[ETH_ALEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; u8 abySNAP_Bridgetunnel[ETH_ALEN] @@ -343,17 +342,17 @@ static int device_init_registers(struct vnt_private *pDevice) return false; } - init_cmd.init_class = DEVICE_INIT_COLD; - init_cmd.exist_sw_net_addr = (u8) pDevice->bExistSWNetAddr; + init_cmd->init_class = DEVICE_INIT_COLD; + init_cmd->exist_sw_net_addr = (u8) pDevice->bExistSWNetAddr; for (ii = 0; ii < 6; ii++) - init_cmd.sw_net_addr[ii] = pDevice->abyCurrentNetAddr[ii]; - init_cmd.short_retry_limit = pDevice->byShortRetryLimit; - init_cmd.long_retry_limit = pDevice->byLongRetryLimit; + init_cmd->sw_net_addr[ii] = pDevice->abyCurrentNetAddr[ii]; + init_cmd->short_retry_limit = pDevice->byShortRetryLimit; + init_cmd->long_retry_limit = pDevice->byLongRetryLimit; /* issue card_init command to device */ ntStatus = CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_CARDINIT, 0, 0, - sizeof(struct vnt_cmd_card_init), (u8 *)&init_cmd); + sizeof(struct vnt_cmd_card_init), (u8 *)init_cmd); if ( ntStatus != STATUS_SUCCESS ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n"); @@ -362,7 +361,7 @@ static int device_init_registers(struct vnt_private *pDevice) } ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_INIT_RSP, 0, 0, - sizeof(struct vnt_rsp_card_init), (u8 *)&init_rsp); + sizeof(struct vnt_rsp_card_init), (u8 *)init_rsp); if (ntStatus != STATUS_SUCCESS) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n"); @@ -519,7 +518,7 @@ static int device_init_registers(struct vnt_private *pDevice) pDevice->byMaxChannel = CB_MAX_CHANNEL; /* get RFType */ - pDevice->byRFType = init_rsp.rf_type; + pDevice->byRFType = init_rsp->rf_type; if ((pDevice->byRFType & RF_EMU) != 0) { /* force change RevID for VT3253 emu */ @@ -570,7 +569,7 @@ static int device_init_registers(struct vnt_private *pDevice) CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); /* get permanent network address */ - memcpy(pDevice->abyPermanentNetAddr, &init_rsp.net_addr[0], 6); + memcpy(pDevice->abyPermanentNetAddr, init_rsp->net_addr, 6); memcpy(pDevice->abyCurrentNetAddr, pDevice->abyPermanentNetAddr, ETH_ALEN); -- cgit v1.2.3 From cbc06fb10c7295855c28c3a4b84b96b48e1dd844 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 3 Nov 2013 17:52:15 +0000 Subject: staging: vt6656: cleanup device_init_registers White space and formatting clean up. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 227 +++++++++++++++++++------------------- 1 file changed, 116 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ba39aaa44220..21805c650319 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -294,7 +294,6 @@ static void device_init_diversity_timer(struct vnt_private *pDevice) /* * initialization of MAC & BBP registers */ - static int device_init_registers(struct vnt_private *pDevice) { struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; @@ -317,30 +316,29 @@ static int device_init_registers(struct vnt_private *pDevice) memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN); memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN); - memcpy(pDevice->abySNAP_Bridgetunnel, - abySNAP_Bridgetunnel, - ETH_ALEN); - - if ( !FIRMWAREbCheckVersion(pDevice) ) { - if (FIRMWAREbDownload(pDevice) == true) { - if (FIRMWAREbBrach2Sram(pDevice) == false) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" FIRMWAREbBrach2Sram fail \n"); - spin_unlock_irq(&pDevice->lock); - return false; - } - } else { - - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" FIRMWAREbDownload fail \n"); - spin_unlock_irq(&pDevice->lock); - return false; - } - } + memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN); + + if (!FIRMWAREbCheckVersion(pDevice)) { + if (FIRMWAREbDownload(pDevice) == true) { + if (FIRMWAREbBrach2Sram(pDevice) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + " FIRMWAREbBrach2Sram fail\n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + " FIRMWAREbDownload fail\n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + } - if ( !BBbVT3184Init(pDevice) ) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" BBbVT3184Init fail \n"); - spin_unlock_irq(&pDevice->lock); - return false; - } + if (!BBbVT3184Init(pDevice)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" BBbVT3184Init fail\n"); + spin_unlock_irq(&pDevice->lock); + return false; + } init_cmd->init_class = DEVICE_INIT_COLD; init_cmd->exist_sw_net_addr = (u8) pDevice->bExistSWNetAddr; @@ -353,12 +351,11 @@ static int device_init_registers(struct vnt_private *pDevice) ntStatus = CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_CARDINIT, 0, 0, sizeof(struct vnt_cmd_card_init), (u8 *)init_cmd); - - if ( ntStatus != STATUS_SUCCESS ) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n"); - spin_unlock_irq(&pDevice->lock); - return false; - } + if (ntStatus != STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail\n"); + spin_unlock_irq(&pDevice->lock); + return false; + } ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_INIT_RSP, 0, 0, sizeof(struct vnt_rsp_card_init), (u8 *)init_rsp); @@ -500,30 +497,30 @@ static int device_init_registers(struct vnt_private *pDevice) pDevice->byTMax3 = 64; /* get Auto Fall Back type */ - pDevice->byAutoFBCtrl = AUTO_FB_0; + pDevice->byAutoFBCtrl = AUTO_FB_0; /* set SCAN Time */ - pDevice->uScanTime = WLAN_SCAN_MINITIME; + pDevice->uScanTime = WLAN_SCAN_MINITIME; /* default Auto Mode */ /* pDevice->NetworkType = Ndis802_11Automode; */ - pDevice->eConfigPHYMode = PHY_TYPE_AUTO; - pDevice->byBBType = BB_TYPE_11G; + pDevice->eConfigPHYMode = PHY_TYPE_AUTO; + pDevice->byBBType = BB_TYPE_11G; /* initialize BBP registers */ - pDevice->ulTxPower = 25; + pDevice->ulTxPower = 25; /* get channel range */ - pDevice->byMinChannel = 1; - pDevice->byMaxChannel = CB_MAX_CHANNEL; + pDevice->byMinChannel = 1; + pDevice->byMaxChannel = CB_MAX_CHANNEL; /* get RFType */ pDevice->byRFType = init_rsp->rf_type; - if ((pDevice->byRFType & RF_EMU) != 0) { + if ((pDevice->byRFType & RF_EMU) != 0) { /* force change RevID for VT3253 emu */ pDevice->byRevId = 0x80; - } + } /* load vt3266 calibration parameters in EEPROM */ if (pDevice->byRFType == RF_VT3226D0) { @@ -536,105 +533,113 @@ static int device_init_registers(struct vnt_private *pDevice) if (byCalibTXIQ || byCalibTXDC || byCalibRXIQ) { /* CR255, enable TX/RX IQ and DC compensation mode */ ControlvWriteByte(pDevice, - MESSAGE_REQUEST_BBREG, - 0xFF, - 0x03); + MESSAGE_REQUEST_BBREG, + 0xff, + 0x03); /* CR251, TX I/Q Imbalance Calibration */ ControlvWriteByte(pDevice, - MESSAGE_REQUEST_BBREG, - 0xFB, - byCalibTXIQ); + MESSAGE_REQUEST_BBREG, + 0xfb, + byCalibTXIQ); /* CR252, TX DC-Offset Calibration */ ControlvWriteByte(pDevice, - MESSAGE_REQUEST_BBREG, - 0xFC, - byCalibTXDC); + MESSAGE_REQUEST_BBREG, + 0xfC, + byCalibTXDC); /* CR253, RX I/Q Imbalance Calibration */ ControlvWriteByte(pDevice, - MESSAGE_REQUEST_BBREG, - 0xFD, - byCalibRXIQ); + MESSAGE_REQUEST_BBREG, + 0xfd, + byCalibRXIQ); } else { /* CR255, turn off BB Calibration compensation */ ControlvWriteByte(pDevice, - MESSAGE_REQUEST_BBREG, - 0xFF, - 0x0); + MESSAGE_REQUEST_BBREG, + 0xff, + 0x0); } } } - pMgmt->eScanType = WMAC_SCAN_PASSIVE; - pMgmt->uCurrChannel = pDevice->uChannel; - pMgmt->uIBSSChannel = pDevice->uChannel; - CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); + + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + pMgmt->uCurrChannel = pDevice->uChannel; + pMgmt->uIBSSChannel = pDevice->uChannel; + CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); /* get permanent network address */ memcpy(pDevice->abyPermanentNetAddr, init_rsp->net_addr, 6); memcpy(pDevice->abyCurrentNetAddr, - pDevice->abyPermanentNetAddr, - ETH_ALEN); + pDevice->abyPermanentNetAddr, ETH_ALEN); /* if exist SW network address, use it */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n", pDevice->abyCurrentNetAddr); - /* - * set BB and packet type at the same time - * set Short Slot Time, xIFS, and RSPINF - */ - if (pDevice->byBBType == BB_TYPE_11A) { - CARDbAddBasicRate(pDevice, RATE_6M); - pDevice->bShortSlotTime = true; - } else { - CARDbAddBasicRate(pDevice, RATE_1M); - pDevice->bShortSlotTime = false; - } - BBvSetShortSlotTime(pDevice); - CARDvSetBSSMode(pDevice); + /* + * set BB and packet type at the same time + * set Short Slot Time, xIFS, and RSPINF + */ + if (pDevice->byBBType == BB_TYPE_11A) { + CARDbAddBasicRate(pDevice, RATE_6M); + pDevice->bShortSlotTime = true; + } else { + CARDbAddBasicRate(pDevice, RATE_1M); + pDevice->bShortSlotTime = false; + } - if (pDevice->bUpdateBBVGA) { - pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; - pDevice->byBBVGANew = pDevice->byBBVGACurrent; - BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); - } + BBvSetShortSlotTime(pDevice); + CARDvSetBSSMode(pDevice); - pDevice->byRadioCtl = pDevice->abyEEPROM[EEP_OFS_RADIOCTL]; - pDevice->bHWRadioOff = false; - if ( (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) != 0 ) { - ntStatus = CONTROLnsRequestIn(pDevice, - MESSAGE_TYPE_READ, - MAC_REG_GPIOCTL1, - MESSAGE_REQUEST_MACREG, - 1, - &byTmp); - - if ( ntStatus != STATUS_SUCCESS ) { - spin_unlock_irq(&pDevice->lock); - return false; - } - if ( (byTmp & GPIO3_DATA) == 0 ) { - pDevice->bHWRadioOff = true; - MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); - } else { - MACvRegBitsOff(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); - pDevice->bHWRadioOff = false; - } + if (pDevice->bUpdateBBVGA) { + pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + pDevice->byBBVGANew = pDevice->byBBVGACurrent; - } + BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); + } - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_TMLEN,0x38); - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); - MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL0,0x01); + pDevice->byRadioCtl = pDevice->abyEEPROM[EEP_OFS_RADIOCTL]; + pDevice->bHWRadioOff = false; - if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) { - CARDbRadioPowerOff(pDevice); - } else { - CARDbRadioPowerOn(pDevice); - } + if ((pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) != 0) { + ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, + MAC_REG_GPIOCTL1, MESSAGE_REQUEST_MACREG, 1, &byTmp); - spin_unlock_irq(&pDevice->lock); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----INIbInitAdapter Exit\n"); - return true; + if (ntStatus != STATUS_SUCCESS) { + spin_unlock_irq(&pDevice->lock); + return false; + } + + if ((byTmp & GPIO3_DATA) == 0) { + pDevice->bHWRadioOff = true; + MACvRegBitsOn(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); + } else { + MACvRegBitsOff(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); + pDevice->bHWRadioOff = false; + } + + } + + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, + MAC_REG_PAPEDELAY, LEDSTS_TMLEN, 0x38); + + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, + MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); + + MACvRegBitsOn(pDevice, MAC_REG_GPIOCTL0, 0x01); + + if ((pDevice->bHWRadioOff == true) || + (pDevice->bRadioControlOff == true)) { + CARDbRadioPowerOff(pDevice); + } else { + CARDbRadioPowerOn(pDevice); + } + + + spin_unlock_irq(&pDevice->lock); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----INIbInitAdapter Exit\n"); + + return true; } #ifdef CONFIG_PM /* Minimal support for suspend and resume */ -- cgit v1.2.3 From f0fde117c12692f76887e09944f4d923a5470bdd Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 3 Nov 2013 19:02:41 +0000 Subject: staging: vt6656: main_usb.c ether_crc use kernel code use ether_crc already in kernel and remove local version. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 1 + drivers/staging/vt6656/main_usb.c | 16 ---------------- 2 files changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 739cda41b5a7..b7a6e14e4d9f 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef SIOCETHTOOL #define DEVICE_ETHTOOL_IOCTL_SUPPORT diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 21805c650319..4cb7aa737a99 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1194,22 +1194,6 @@ out: return NETDEV_TX_OK; } -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc(int length, unsigned char *data) -{ - int crc = -1; - - while(--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ - ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - } - return crc; -} - /* find out the start position of str2 from str1 */ static unsigned char *kstrstr(const unsigned char *str1, const unsigned char *str2) { -- cgit v1.2.3 From a82c40cba28266186eff04bde6e368083eefa687 Mon Sep 17 00:00:00 2001 From: Rupert Muchembled Date: Fri, 8 Nov 2013 06:01:48 +0000 Subject: Staging: silicom: Remove unnecessary variable from do_cmd() Remove unnecessary variable ioctl from do_cmd(). As a consequence, this patch removes an assignment to ioctl in an if condition, reported by checkpatch.pl. Signed-off-by: Rupert Muchembled Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bypasslib/bypass.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/silicom/bypasslib/bypass.c b/drivers/staging/silicom/bypasslib/bypass.c index ba0d23a1cfbe..7d2cb54ad6c0 100644 --- a/drivers/staging/silicom/bypasslib/bypass.c +++ b/drivers/staging/silicom/bypasslib/bypass.c @@ -47,13 +47,13 @@ static int do_cmd(struct net_device *dev, struct ifreq *ifr, int cmd, int *data) { int ret = -1; struct if_bypass *bypass_cb; - static int (*ioctl) (struct net_device *, struct ifreq *, int); bypass_cb = (struct if_bypass *)ifr; bypass_cb->cmd = cmd; bypass_cb->data = *data; - if ((dev->netdev_ops) && (ioctl = dev->netdev_ops->ndo_do_ioctl)) { - ret = ioctl(dev, ifr, SIOCGIFBYPASS); + + if (dev->netdev_ops && dev->netdev_ops->ndo_do_ioctl) { + ret = dev->netdev_ops->ndo_do_ioctl(dev, ifr, SIOCGIFBYPASS); *data = bypass_cb->data; } -- cgit v1.2.3 From 473b1716256d2b01bfd105e6af96ccc34b951fe3 Mon Sep 17 00:00:00 2001 From: Rupert Muchembled Date: Fri, 8 Nov 2013 06:01:49 +0000 Subject: Staging: silicom: Remove unnecessary variable from get_bypass_info() Remove unnecessary variable ioctl from get_bypass_info(). As a consequence, this patch removes an assignment to ioctl in an if condition, reported by checkpatch.pl. Signed-off-by: Rupert Muchembled Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bypasslib/bypass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/silicom/bypasslib/bypass.c b/drivers/staging/silicom/bypasslib/bypass.c index 7d2cb54ad6c0..dda1b2a6b84b 100644 --- a/drivers/staging/silicom/bypasslib/bypass.c +++ b/drivers/staging/silicom/bypasslib/bypass.c @@ -480,7 +480,6 @@ static int get_bypass_info(int if_index, struct bp_info *bp_info) SET_BPLIB_INT_FN2(get_bypass_info, int, if_index, struct bp_info *, bp_info, ret); } else { - static int (*ioctl) (struct net_device *, struct ifreq *, int); struct net_device *dev; struct net_device *n; @@ -493,9 +492,10 @@ static int get_bypass_info(int if_index, struct bp_info *bp_info) bypass_cb = (struct if_bypass_info *)𝔦 bypass_cb->cmd = GET_BYPASS_INFO; - if ((dev->netdev_ops) && - (ioctl = dev->netdev_ops->ndo_do_ioctl)) { - ret = ioctl(dev, &ifr, SIOCGIFBYPASS); + if (dev->netdev_ops && + dev->netdev_ops->ndo_do_ioctl) { + ret = dev->netdev_ops->ndo_do_ioctl(dev, + &ifr, SIOCGIFBYPASS); } else -- cgit v1.2.3 From 6c7b4ac9363488a5d19ea26f864f0a8866ea5b49 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 8 Nov 2013 18:41:42 -0500 Subject: mm/staging: remove unnecessary inclusion of bootmem.h Clean-up to remove depedency with bootmem headers. Cc: Yinghai Lu Cc: Tejun Heo Cc: Andrew Morton Cc: William Hubbs Cc: Chris Brannon Cc: Kirk Reiser Cc: Greg Kroah-Hartman Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 47502fa5f3f6..ef5933b93590 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -37,8 +37,6 @@ #include #include -#include /* for alloc_bootmem */ - /* speakup_*_selection */ #include #include -- cgit v1.2.3 From 91f9765d377385863950f31d43aba5a888faa413 Mon Sep 17 00:00:00 2001 From: Joachim Adi Schuetz Date: Sun, 10 Nov 2013 15:15:06 +0100 Subject: staging: ced401: ced_ioc: fix a blank/tab codingstyle issue. Fixed a coding style issue - removed a blank before a tab. Signed-off-by: Joachim Adolf Schuetz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ced1401/ced_ioc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c index 62efd74b8c04..043a93230e82 100644 --- a/drivers/staging/ced1401/ced_ioc.c +++ b/drivers/staging/ced1401/ced_ioc.c @@ -630,7 +630,7 @@ int ClearArea(DEVICE_EXTENSION *pdx, int nArea) } spin_unlock_irq(&pdx->stagedLock); - if (pPages) { /* if we decided to release the memory */ + if (pPages) { /* if we decided to release the memory */ /* Now we must undo the pinning down of the pages. We will assume the worst and mark */ /* all the pages as dirty. Don't be tempted to move this up above as you must not be */ /* holding a spin lock to do this stuff as it is not atomic. */ -- cgit v1.2.3 From 0d100bfc4bedbcd297afa77714b9dbea8e9452db Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:34:57 +0200 Subject: staging: lustre: ptlrpc: pack_generic: clean up whitespace around parentheses Fix the following types of checkpatch errors and warnings in pack_generic.c to comply with coding style: ERROR: space required before the open parenthesis '(' ERROR: space prohibited before that close parenthesis ')' WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Kristina Martsenko Reviewed-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 362 ++++++++++----------- 1 file changed, 181 insertions(+), 181 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index cd2611a3b53d..94abb51cf642 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -274,8 +274,8 @@ do { \ spin_unlock(&ptlrpc_rs_debug_lock); \ } while (0) #else -# define PTLRPC_RS_DEBUG_LRU_ADD(rs) do {} while(0) -# define PTLRPC_RS_DEBUG_LRU_DEL(rs) do {} while(0) +# define PTLRPC_RS_DEBUG_LRU_ADD(rs) do {} while (0) +# define PTLRPC_RS_DEBUG_LRU_DEL(rs) do {} while (0) #endif struct ptlrpc_reply_state * @@ -507,14 +507,14 @@ void lustre_free_reply_state(struct ptlrpc_reply_state *rs) { PTLRPC_RS_DEBUG_LRU_DEL(rs); - LASSERT (atomic_read(&rs->rs_refcount) == 0); - LASSERT (!rs->rs_difficult || rs->rs_handled); - LASSERT (!rs->rs_on_net); - LASSERT (!rs->rs_scheduled); - LASSERT (rs->rs_export == NULL); - LASSERT (rs->rs_nlocks == 0); - LASSERT (list_empty(&rs->rs_exp_list)); - LASSERT (list_empty(&rs->rs_obd_list)); + LASSERT(atomic_read(&rs->rs_refcount) == 0); + LASSERT(!rs->rs_difficult || rs->rs_handled); + LASSERT(!rs->rs_on_net); + LASSERT(!rs->rs_scheduled); + LASSERT(rs->rs_export == NULL); + LASSERT(rs->rs_nlocks == 0); + LASSERT(list_empty(&rs->rs_exp_list)); + LASSERT(list_empty(&rs->rs_obd_list)); sptlrpc_svc_free_rs(rs); } @@ -548,8 +548,8 @@ static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len) required_len = lustre_msg_hdr_size_v2(m->lm_bufcount); if (len < required_len) { /* didn't receive all the buffer lengths */ - CERROR ("message length %d too small for %d buflens\n", - len, m->lm_bufcount); + CERROR("message length %d too small for %d buflens\n", + len, m->lm_bufcount); return -EINVAL; } @@ -749,7 +749,7 @@ char *lustre_msg_string(struct lustre_msg *m, int index, int max_len) } if (str == NULL) { - CERROR ("can't unpack string in msg %p buffer[%d]\n", m, index); + CERROR("can't unpack string in msg %p buffer[%d]\n", m, index); return NULL; } @@ -1653,25 +1653,25 @@ EXPORT_SYMBOL(do_set_info_async); */ void lustre_swab_ptlrpc_body(struct ptlrpc_body *b) { - __swab32s (&b->pb_type); - __swab32s (&b->pb_version); - __swab32s (&b->pb_opc); - __swab32s (&b->pb_status); - __swab64s (&b->pb_last_xid); - __swab64s (&b->pb_last_seen); - __swab64s (&b->pb_last_committed); - __swab64s (&b->pb_transno); - __swab32s (&b->pb_flags); - __swab32s (&b->pb_op_flags); - __swab32s (&b->pb_conn_cnt); - __swab32s (&b->pb_timeout); - __swab32s (&b->pb_service_time); - __swab32s (&b->pb_limit); - __swab64s (&b->pb_slv); - __swab64s (&b->pb_pre_versions[0]); - __swab64s (&b->pb_pre_versions[1]); - __swab64s (&b->pb_pre_versions[2]); - __swab64s (&b->pb_pre_versions[3]); + __swab32s(&b->pb_type); + __swab32s(&b->pb_version); + __swab32s(&b->pb_opc); + __swab32s(&b->pb_status); + __swab64s(&b->pb_last_xid); + __swab64s(&b->pb_last_seen); + __swab64s(&b->pb_last_committed); + __swab64s(&b->pb_transno); + __swab32s(&b->pb_flags); + __swab32s(&b->pb_op_flags); + __swab32s(&b->pb_conn_cnt); + __swab32s(&b->pb_timeout); + __swab32s(&b->pb_service_time); + __swab32s(&b->pb_limit); + __swab64s(&b->pb_slv); + __swab64s(&b->pb_pre_versions[0]); + __swab64s(&b->pb_pre_versions[1]); + __swab64s(&b->pb_pre_versions[2]); + __swab64s(&b->pb_pre_versions[3]); CLASSERT(offsetof(typeof(*b), pb_padding) != 0); /* While we need to maintain compatibility between * clients and servers without ptlrpc_body_v2 (< 2.3) @@ -1723,33 +1723,33 @@ void lustre_swab_connect(struct obd_connect_data *ocd) CLASSERT(offsetof(typeof(*ocd), paddingF) != 0); } -void lustre_swab_obdo (struct obdo *o) +void lustre_swab_obdo(struct obdo *o) { - __swab64s (&o->o_valid); + __swab64s(&o->o_valid); lustre_swab_ost_id(&o->o_oi); - __swab64s (&o->o_parent_seq); - __swab64s (&o->o_size); - __swab64s (&o->o_mtime); - __swab64s (&o->o_atime); - __swab64s (&o->o_ctime); - __swab64s (&o->o_blocks); - __swab64s (&o->o_grant); - __swab32s (&o->o_blksize); - __swab32s (&o->o_mode); - __swab32s (&o->o_uid); - __swab32s (&o->o_gid); - __swab32s (&o->o_flags); - __swab32s (&o->o_nlink); - __swab32s (&o->o_parent_oid); - __swab32s (&o->o_misc); - __swab64s (&o->o_ioepoch); - __swab32s (&o->o_stripe_idx); - __swab32s (&o->o_parent_ver); + __swab64s(&o->o_parent_seq); + __swab64s(&o->o_size); + __swab64s(&o->o_mtime); + __swab64s(&o->o_atime); + __swab64s(&o->o_ctime); + __swab64s(&o->o_blocks); + __swab64s(&o->o_grant); + __swab32s(&o->o_blksize); + __swab32s(&o->o_mode); + __swab32s(&o->o_uid); + __swab32s(&o->o_gid); + __swab32s(&o->o_flags); + __swab32s(&o->o_nlink); + __swab32s(&o->o_parent_oid); + __swab32s(&o->o_misc); + __swab64s(&o->o_ioepoch); + __swab32s(&o->o_stripe_idx); + __swab32s(&o->o_parent_ver); /* o_handle is opaque */ /* o_lcookie is swabbed elsewhere */ - __swab32s (&o->o_uid_h); - __swab32s (&o->o_gid_h); - __swab64s (&o->o_data_version); + __swab32s(&o->o_uid_h); + __swab32s(&o->o_gid_h); + __swab64s(&o->o_data_version); CLASSERT(offsetof(typeof(*o), o_padding_4) != 0); CLASSERT(offsetof(typeof(*o), o_padding_5) != 0); CLASSERT(offsetof(typeof(*o), o_padding_6) != 0); @@ -1757,19 +1757,19 @@ void lustre_swab_obdo (struct obdo *o) } EXPORT_SYMBOL(lustre_swab_obdo); -void lustre_swab_obd_statfs (struct obd_statfs *os) +void lustre_swab_obd_statfs(struct obd_statfs *os) { - __swab64s (&os->os_type); - __swab64s (&os->os_blocks); - __swab64s (&os->os_bfree); - __swab64s (&os->os_bavail); - __swab64s (&os->os_files); - __swab64s (&os->os_ffree); + __swab64s(&os->os_type); + __swab64s(&os->os_blocks); + __swab64s(&os->os_bfree); + __swab64s(&os->os_bavail); + __swab64s(&os->os_files); + __swab64s(&os->os_ffree); /* no need to swab os_fsid */ - __swab32s (&os->os_bsize); - __swab32s (&os->os_namelen); - __swab64s (&os->os_maxbytes); - __swab32s (&os->os_state); + __swab32s(&os->os_bsize); + __swab32s(&os->os_namelen); + __swab64s(&os->os_maxbytes); + __swab32s(&os->os_state); CLASSERT(offsetof(typeof(*os), os_fprecreated) != 0); CLASSERT(offsetof(typeof(*os), os_spare2) != 0); CLASSERT(offsetof(typeof(*os), os_spare3) != 0); @@ -1790,17 +1790,17 @@ void lustre_swab_obd_ioobj(struct obd_ioobj *ioo) } EXPORT_SYMBOL(lustre_swab_obd_ioobj); -void lustre_swab_niobuf_remote (struct niobuf_remote *nbr) +void lustre_swab_niobuf_remote(struct niobuf_remote *nbr) { - __swab64s (&nbr->offset); - __swab32s (&nbr->len); - __swab32s (&nbr->flags); + __swab64s(&nbr->offset); + __swab32s(&nbr->len); + __swab32s(&nbr->flags); } EXPORT_SYMBOL(lustre_swab_niobuf_remote); -void lustre_swab_ost_body (struct ost_body *b) +void lustre_swab_ost_body(struct ost_body *b) { - lustre_swab_obdo (&b->oa); + lustre_swab_obdo(&b->oa); } EXPORT_SYMBOL(lustre_swab_ost_body); @@ -1861,45 +1861,45 @@ void lustre_swab_lquota_lvb(struct lquota_lvb *lvb) } EXPORT_SYMBOL(lustre_swab_lquota_lvb); -void lustre_swab_mdt_body (struct mdt_body *b) +void lustre_swab_mdt_body(struct mdt_body *b) { - lustre_swab_lu_fid (&b->fid1); - lustre_swab_lu_fid (&b->fid2); + lustre_swab_lu_fid(&b->fid1); + lustre_swab_lu_fid(&b->fid2); /* handle is opaque */ - __swab64s (&b->valid); - __swab64s (&b->size); - __swab64s (&b->mtime); - __swab64s (&b->atime); - __swab64s (&b->ctime); - __swab64s (&b->blocks); - __swab64s (&b->ioepoch); + __swab64s(&b->valid); + __swab64s(&b->size); + __swab64s(&b->mtime); + __swab64s(&b->atime); + __swab64s(&b->ctime); + __swab64s(&b->blocks); + __swab64s(&b->ioepoch); CLASSERT(offsetof(typeof(*b), unused1) != 0); - __swab32s (&b->fsuid); - __swab32s (&b->fsgid); - __swab32s (&b->capability); - __swab32s (&b->mode); - __swab32s (&b->uid); - __swab32s (&b->gid); - __swab32s (&b->flags); - __swab32s (&b->rdev); - __swab32s (&b->nlink); + __swab32s(&b->fsuid); + __swab32s(&b->fsgid); + __swab32s(&b->capability); + __swab32s(&b->mode); + __swab32s(&b->uid); + __swab32s(&b->gid); + __swab32s(&b->flags); + __swab32s(&b->rdev); + __swab32s(&b->nlink); CLASSERT(offsetof(typeof(*b), unused2) != 0); - __swab32s (&b->suppgid); - __swab32s (&b->eadatasize); - __swab32s (&b->aclsize); - __swab32s (&b->max_mdsize); - __swab32s (&b->max_cookiesize); - __swab32s (&b->uid_h); - __swab32s (&b->gid_h); + __swab32s(&b->suppgid); + __swab32s(&b->eadatasize); + __swab32s(&b->aclsize); + __swab32s(&b->max_mdsize); + __swab32s(&b->max_cookiesize); + __swab32s(&b->uid_h); + __swab32s(&b->gid_h); CLASSERT(offsetof(typeof(*b), padding_5) != 0); } EXPORT_SYMBOL(lustre_swab_mdt_body); -void lustre_swab_mdt_ioepoch (struct mdt_ioepoch *b) +void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b) { /* handle is opaque */ - __swab64s (&b->ioepoch); - __swab32s (&b->flags); + __swab64s(&b->ioepoch); + __swab32s(&b->flags); CLASSERT(offsetof(typeof(*b), padding) != 0); } EXPORT_SYMBOL(lustre_swab_mdt_ioepoch); @@ -1957,49 +1957,49 @@ void lustre_swab_mgs_config_res(struct mgs_config_res *body) } EXPORT_SYMBOL(lustre_swab_mgs_config_res); -static void lustre_swab_obd_dqinfo (struct obd_dqinfo *i) +static void lustre_swab_obd_dqinfo(struct obd_dqinfo *i) { - __swab64s (&i->dqi_bgrace); - __swab64s (&i->dqi_igrace); - __swab32s (&i->dqi_flags); - __swab32s (&i->dqi_valid); + __swab64s(&i->dqi_bgrace); + __swab64s(&i->dqi_igrace); + __swab32s(&i->dqi_flags); + __swab32s(&i->dqi_valid); } -static void lustre_swab_obd_dqblk (struct obd_dqblk *b) +static void lustre_swab_obd_dqblk(struct obd_dqblk *b) { - __swab64s (&b->dqb_ihardlimit); - __swab64s (&b->dqb_isoftlimit); - __swab64s (&b->dqb_curinodes); - __swab64s (&b->dqb_bhardlimit); - __swab64s (&b->dqb_bsoftlimit); - __swab64s (&b->dqb_curspace); - __swab64s (&b->dqb_btime); - __swab64s (&b->dqb_itime); - __swab32s (&b->dqb_valid); + __swab64s(&b->dqb_ihardlimit); + __swab64s(&b->dqb_isoftlimit); + __swab64s(&b->dqb_curinodes); + __swab64s(&b->dqb_bhardlimit); + __swab64s(&b->dqb_bsoftlimit); + __swab64s(&b->dqb_curspace); + __swab64s(&b->dqb_btime); + __swab64s(&b->dqb_itime); + __swab32s(&b->dqb_valid); CLASSERT(offsetof(typeof(*b), dqb_padding) != 0); } -void lustre_swab_obd_quotactl (struct obd_quotactl *q) +void lustre_swab_obd_quotactl(struct obd_quotactl *q) { - __swab32s (&q->qc_cmd); - __swab32s (&q->qc_type); - __swab32s (&q->qc_id); - __swab32s (&q->qc_stat); - lustre_swab_obd_dqinfo (&q->qc_dqinfo); - lustre_swab_obd_dqblk (&q->qc_dqblk); + __swab32s(&q->qc_cmd); + __swab32s(&q->qc_type); + __swab32s(&q->qc_id); + __swab32s(&q->qc_stat); + lustre_swab_obd_dqinfo(&q->qc_dqinfo); + lustre_swab_obd_dqblk(&q->qc_dqblk); } EXPORT_SYMBOL(lustre_swab_obd_quotactl); -void lustre_swab_mdt_remote_perm (struct mdt_remote_perm *p) +void lustre_swab_mdt_remote_perm(struct mdt_remote_perm *p) { - __swab32s (&p->rp_uid); - __swab32s (&p->rp_gid); - __swab32s (&p->rp_fsuid); - __swab32s (&p->rp_fsuid_h); - __swab32s (&p->rp_fsgid); - __swab32s (&p->rp_fsgid_h); - __swab32s (&p->rp_access_perm); - __swab32s (&p->rp_padding); + __swab32s(&p->rp_uid); + __swab32s(&p->rp_gid); + __swab32s(&p->rp_fsuid); + __swab32s(&p->rp_fsuid_h); + __swab32s(&p->rp_fsgid); + __swab32s(&p->rp_fsgid_h); + __swab32s(&p->rp_access_perm); + __swab32s(&p->rp_padding); }; EXPORT_SYMBOL(lustre_swab_mdt_remote_perm); @@ -2089,31 +2089,31 @@ void lustre_swab_mdt_rec_reint (struct mdt_rec_reint *rr) }; EXPORT_SYMBOL(lustre_swab_mdt_rec_reint); -void lustre_swab_lov_desc (struct lov_desc *ld) +void lustre_swab_lov_desc(struct lov_desc *ld) { - __swab32s (&ld->ld_tgt_count); - __swab32s (&ld->ld_active_tgt_count); - __swab32s (&ld->ld_default_stripe_count); - __swab32s (&ld->ld_pattern); - __swab64s (&ld->ld_default_stripe_size); - __swab64s (&ld->ld_default_stripe_offset); - __swab32s (&ld->ld_qos_maxage); + __swab32s(&ld->ld_tgt_count); + __swab32s(&ld->ld_active_tgt_count); + __swab32s(&ld->ld_default_stripe_count); + __swab32s(&ld->ld_pattern); + __swab64s(&ld->ld_default_stripe_size); + __swab64s(&ld->ld_default_stripe_offset); + __swab32s(&ld->ld_qos_maxage); /* uuid endian insensitive */ } EXPORT_SYMBOL(lustre_swab_lov_desc); -void lustre_swab_lmv_desc (struct lmv_desc *ld) +void lustre_swab_lmv_desc(struct lmv_desc *ld) { - __swab32s (&ld->ld_tgt_count); - __swab32s (&ld->ld_active_tgt_count); - __swab32s (&ld->ld_default_stripe_count); - __swab32s (&ld->ld_pattern); - __swab64s (&ld->ld_default_hash_size); - __swab32s (&ld->ld_qos_maxage); + __swab32s(&ld->ld_tgt_count); + __swab32s(&ld->ld_active_tgt_count); + __swab32s(&ld->ld_default_stripe_count); + __swab32s(&ld->ld_pattern); + __swab64s(&ld->ld_default_hash_size); + __swab32s(&ld->ld_qos_maxage); /* uuid endian insensitive */ } -void lustre_swab_lmv_stripe_md (struct lmv_stripe_md *mea) +void lustre_swab_lmv_stripe_md(struct lmv_stripe_md *mea) { __swab32s(&mea->mea_magic); __swab32s(&mea->mea_count); @@ -2142,7 +2142,7 @@ void lustre_swab_lmv_user_md(struct lmv_user_md *lum) } EXPORT_SYMBOL(lustre_swab_lmv_user_md); -static void print_lum (struct lov_user_md *lum) +static void print_lum(struct lov_user_md *lum) { CDEBUG(D_OTHER, "lov_user_md %p:\n", lum); CDEBUG(D_OTHER, "\tlmm_magic: %#x\n", lum->lmm_magic); @@ -2212,16 +2212,16 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, } EXPORT_SYMBOL(lustre_swab_lov_user_md_objects); -void lustre_swab_ldlm_res_id (struct ldlm_res_id *id) +void lustre_swab_ldlm_res_id(struct ldlm_res_id *id) { int i; for (i = 0; i < RES_NAME_SIZE; i++) - __swab64s (&id->name[i]); + __swab64s(&id->name[i]); } EXPORT_SYMBOL(lustre_swab_ldlm_res_id); -void lustre_swab_ldlm_policy_data (ldlm_wire_policy_data_t *d) +void lustre_swab_ldlm_policy_data(ldlm_wire_policy_data_t *d) { /* the lock data is a union and the first two fields are always an * extent so it's ok to process an LDLM_EXTENT and LDLM_FLOCK lock @@ -2234,46 +2234,46 @@ void lustre_swab_ldlm_policy_data (ldlm_wire_policy_data_t *d) } EXPORT_SYMBOL(lustre_swab_ldlm_policy_data); -void lustre_swab_ldlm_intent (struct ldlm_intent *i) +void lustre_swab_ldlm_intent(struct ldlm_intent *i) { - __swab64s (&i->opc); + __swab64s(&i->opc); } EXPORT_SYMBOL(lustre_swab_ldlm_intent); -void lustre_swab_ldlm_resource_desc (struct ldlm_resource_desc *r) +void lustre_swab_ldlm_resource_desc(struct ldlm_resource_desc *r) { - __swab32s (&r->lr_type); + __swab32s(&r->lr_type); CLASSERT(offsetof(typeof(*r), lr_padding) != 0); - lustre_swab_ldlm_res_id (&r->lr_name); + lustre_swab_ldlm_res_id(&r->lr_name); } EXPORT_SYMBOL(lustre_swab_ldlm_resource_desc); -void lustre_swab_ldlm_lock_desc (struct ldlm_lock_desc *l) +void lustre_swab_ldlm_lock_desc(struct ldlm_lock_desc *l) { - lustre_swab_ldlm_resource_desc (&l->l_resource); - __swab32s (&l->l_req_mode); - __swab32s (&l->l_granted_mode); - lustre_swab_ldlm_policy_data (&l->l_policy_data); + lustre_swab_ldlm_resource_desc(&l->l_resource); + __swab32s(&l->l_req_mode); + __swab32s(&l->l_granted_mode); + lustre_swab_ldlm_policy_data(&l->l_policy_data); } EXPORT_SYMBOL(lustre_swab_ldlm_lock_desc); -void lustre_swab_ldlm_request (struct ldlm_request *rq) +void lustre_swab_ldlm_request(struct ldlm_request *rq) { - __swab32s (&rq->lock_flags); - lustre_swab_ldlm_lock_desc (&rq->lock_desc); - __swab32s (&rq->lock_count); + __swab32s(&rq->lock_flags); + lustre_swab_ldlm_lock_desc(&rq->lock_desc); + __swab32s(&rq->lock_count); /* lock_handle[] opaque */ } EXPORT_SYMBOL(lustre_swab_ldlm_request); -void lustre_swab_ldlm_reply (struct ldlm_reply *r) +void lustre_swab_ldlm_reply(struct ldlm_reply *r) { - __swab32s (&r->lock_flags); + __swab32s(&r->lock_flags); CLASSERT(offsetof(typeof(*r), lock_padding) != 0); - lustre_swab_ldlm_lock_desc (&r->lock_desc); + lustre_swab_ldlm_lock_desc(&r->lock_desc); /* lock_handle opaque */ - __swab64s (&r->lock_policy_res1); - __swab64s (&r->lock_policy_res2); + __swab64s(&r->lock_policy_res1); + __swab64s(&r->lock_policy_res2); } EXPORT_SYMBOL(lustre_swab_ldlm_reply); @@ -2409,7 +2409,7 @@ static inline int rep_ptlrpc_body_swabbed(struct ptlrpc_request *req) void _debug_req(struct ptlrpc_request *req, struct libcfs_debug_msg_data *msgdata, - const char *fmt, ... ) + const char *fmt, ...) { int req_ok = req->rq_reqmsg != NULL; int rep_ok = req->rq_repmsg != NULL; @@ -2457,20 +2457,20 @@ EXPORT_SYMBOL(_debug_req); void lustre_swab_lustre_capa(struct lustre_capa *c) { lustre_swab_lu_fid(&c->lc_fid); - __swab64s (&c->lc_opc); - __swab64s (&c->lc_uid); - __swab64s (&c->lc_gid); - __swab32s (&c->lc_flags); - __swab32s (&c->lc_keyid); - __swab32s (&c->lc_timeout); - __swab32s (&c->lc_expiry); + __swab64s(&c->lc_opc); + __swab64s(&c->lc_uid); + __swab64s(&c->lc_gid); + __swab32s(&c->lc_flags); + __swab32s(&c->lc_keyid); + __swab32s(&c->lc_timeout); + __swab32s(&c->lc_expiry); } EXPORT_SYMBOL(lustre_swab_lustre_capa); void lustre_swab_lustre_capa_key(struct lustre_capa_key *k) { - __swab64s (&k->lk_seq); - __swab32s (&k->lk_keyid); + __swab64s(&k->lk_seq); + __swab32s(&k->lk_keyid); CLASSERT(offsetof(typeof(*k), lk_padding) != 0); } EXPORT_SYMBOL(lustre_swab_lustre_capa_key); -- cgit v1.2.3 From 3949015e4dc169e738bb6f04ef5cbd26253b1cf9 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:34:58 +0200 Subject: staging: lustre: ptlrpc: clean up whitespace around parentheses Fix the following types of checkpatch errors and warnings to comply with coding style: ERROR: space required before the open parenthesis '(' ERROR: space prohibited after that open parenthesis '(' ERROR: space prohibited before that close parenthesis ')' WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Kristina Martsenko Reviewed-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 16 ++--- drivers/staging/lustre/lustre/ptlrpc/events.c | 75 +++++++++++----------- .../staging/lustre/lustre/ptlrpc/gss/gss_keyring.c | 2 +- .../lustre/lustre/ptlrpc/gss/gss_krb5_mech.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c | 6 +- drivers/staging/lustre/lustre/ptlrpc/import.c | 12 ++-- drivers/staging/lustre/lustre/ptlrpc/layout.c | 4 +- drivers/staging/lustre/lustre/ptlrpc/llog_client.c | 6 +- .../staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 70 ++++++++++---------- .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h | 10 +-- .../staging/lustre/lustre/ptlrpc/ptlrpc_module.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/service.c | 28 ++++---- 13 files changed, 117 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index c2ab0c8c4d42..07d34b4a074e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -459,7 +459,7 @@ ptlrpc_init_rq_pool(int num_rq, int msgsize, { struct ptlrpc_request_pool *pool; - OBD_ALLOC(pool, sizeof (struct ptlrpc_request_pool)); + OBD_ALLOC(pool, sizeof(struct ptlrpc_request_pool)); if (!pool) return NULL; @@ -475,7 +475,7 @@ ptlrpc_init_rq_pool(int num_rq, int msgsize, if (list_empty(&pool->prp_req_list)) { /* have not allocated a single request for the pool */ - OBD_FREE(pool, sizeof (struct ptlrpc_request_pool)); + OBD_FREE(pool, sizeof(struct ptlrpc_request_pool)); pool = NULL; } return pool; @@ -881,7 +881,7 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set) /* Requests on the set should either all be completed, or all be new */ expected_phase = (atomic_read(&set->set_remaining) == 0) ? RQ_PHASE_COMPLETE : RQ_PHASE_NEW; - list_for_each (tmp, &set->set_requests) { + list_for_each(tmp, &set->set_requests) { struct ptlrpc_request *req = list_entry(tmp, struct ptlrpc_request, rq_set_chain); @@ -912,7 +912,7 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set) req->rq_invalid_rqset = 0; spin_unlock(&req->rq_lock); - ptlrpc_req_finished (req); + ptlrpc_req_finished(req); } LASSERT(atomic_read(&set->set_remaining) == 0); @@ -1020,7 +1020,7 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, { int delay = 0; - LASSERT (status != NULL); + LASSERT(status != NULL); *status = 0; if (req->rq_ctx_init || req->rq_ctx_fini) { @@ -1907,7 +1907,7 @@ int ptlrpc_expired_set(void *data) /* * A timeout expired. See which reqs it applies to... */ - list_for_each (tmp, &set->set_requests) { + list_for_each(tmp, &set->set_requests) { struct ptlrpc_request *req = list_entry(tmp, struct ptlrpc_request, rq_set_chain); @@ -2688,7 +2688,7 @@ int ptlrpc_replay_req(struct ptlrpc_request *req) LASSERT(req->rq_import->imp_state == LUSTRE_IMP_REPLAY); - LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args)); + LASSERT(sizeof(*aa) <= sizeof(req->rq_async_args)); aa = ptlrpc_req_async_args(req); memset(aa, 0, sizeof(*aa)); @@ -2962,7 +2962,7 @@ void *ptlrpcd_alloc_work(struct obd_import *imp, init_waitqueue_head(&req->rq_set_waitq); atomic_set(&req->rq_refcount, 1); - CLASSERT (sizeof(*args) <= sizeof(req->rq_async_args)); + CLASSERT(sizeof(*args) <= sizeof(req->rq_async_args)); args = ptlrpc_req_async_args(req); args->magic = PTLRPC_WORK_MAGIC; args->cb = cb; diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 58d089c3fef4..f66cfea87acf 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -56,9 +56,9 @@ void request_out_callback(lnet_event_t *ev) struct ptlrpc_cb_id *cbid = ev->md.user_ptr; struct ptlrpc_request *req = cbid->cbid_arg; - LASSERT (ev->type == LNET_EVENT_SEND || - ev->type == LNET_EVENT_UNLINK); - LASSERT (ev->unlinked); + LASSERT(ev->type == LNET_EVENT_SEND || + ev->type == LNET_EVENT_UNLINK); + LASSERT(ev->unlinked); DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status); @@ -90,9 +90,9 @@ void reply_in_callback(lnet_event_t *ev) DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status); - LASSERT (ev->type == LNET_EVENT_PUT || ev->type == LNET_EVENT_UNLINK); - LASSERT (ev->md.start == req->rq_repbuf); - LASSERT (ev->offset + ev->mlength <= req->rq_repbuf_len); + LASSERT(ev->type == LNET_EVENT_PUT || ev->type == LNET_EVENT_UNLINK); + LASSERT(ev->md.start == req->rq_repbuf); + LASSERT(ev->offset + ev->mlength <= req->rq_repbuf_len); /* We've set LNET_MD_MANAGE_REMOTE for all outgoing requests for adaptive timeouts' early reply. */ LASSERT((ev->md.options & LNET_MD_MANAGE_REMOTE) != 0); @@ -113,7 +113,7 @@ void reply_in_callback(lnet_event_t *ev) goto out_wake; } - if (ev->mlength < ev->rlength ) { + if (ev->mlength < ev->rlength) { CDEBUG(D_RPCTRACE, "truncate req %p rpc %d - %d+%d\n", req, req->rq_replen, ev->rlength, ev->offset); req->rq_reply_truncate = 1; @@ -167,18 +167,18 @@ out_wake: /* * Client's bulk has been written/read */ -void client_bulk_callback (lnet_event_t *ev) +void client_bulk_callback(lnet_event_t *ev) { struct ptlrpc_cb_id *cbid = ev->md.user_ptr; struct ptlrpc_bulk_desc *desc = cbid->cbid_arg; struct ptlrpc_request *req; - LASSERT ((desc->bd_type == BULK_PUT_SINK && - ev->type == LNET_EVENT_PUT) || - (desc->bd_type == BULK_GET_SOURCE && - ev->type == LNET_EVENT_GET) || - ev->type == LNET_EVENT_UNLINK); - LASSERT (ev->unlinked); + LASSERT((desc->bd_type == BULK_PUT_SINK && + ev->type == LNET_EVENT_PUT) || + (desc->bd_type == BULK_GET_SOURCE && + ev->type == LNET_EVENT_GET) || + ev->type == LNET_EVENT_UNLINK); + LASSERT(ev->unlinked); if (CFS_FAIL_CHECK_ORSET(OBD_FAIL_PTLRPC_CLIENT_BULK_CB, CFS_FAIL_ONCE)) ev->status = -EIO; @@ -283,11 +283,11 @@ void request_in_callback(lnet_event_t *ev) struct ptlrpc_service *service = svcpt->scp_service; struct ptlrpc_request *req; - LASSERT (ev->type == LNET_EVENT_PUT || - ev->type == LNET_EVENT_UNLINK); - LASSERT ((char *)ev->md.start >= rqbd->rqbd_buffer); - LASSERT ((char *)ev->md.start + ev->offset + ev->mlength <= - rqbd->rqbd_buffer + service->srv_buf_size); + LASSERT(ev->type == LNET_EVENT_PUT || + ev->type == LNET_EVENT_UNLINK); + LASSERT((char *)ev->md.start >= rqbd->rqbd_buffer); + LASSERT((char *)ev->md.start + ev->offset + ev->mlength <= + rqbd->rqbd_buffer + service->srv_buf_size); CDEBUG((ev->status == 0) ? D_NET : D_ERROR, "event type %d, status %d, service %s\n", @@ -300,9 +300,9 @@ void request_in_callback(lnet_event_t *ev) * we'd have to re-post the rqbd, which we can't do in this * context. */ req = &rqbd->rqbd_req; - memset(req, 0, sizeof (*req)); + memset(req, 0, sizeof(*req)); } else { - LASSERT (ev->type == LNET_EVENT_PUT); + LASSERT(ev->type == LNET_EVENT_PUT); if (ev->status != 0) { /* We moaned above already... */ return; @@ -381,19 +381,19 @@ void reply_out_callback(lnet_event_t *ev) struct ptlrpc_reply_state *rs = cbid->cbid_arg; struct ptlrpc_service_part *svcpt = rs->rs_svcpt; - LASSERT (ev->type == LNET_EVENT_SEND || - ev->type == LNET_EVENT_ACK || - ev->type == LNET_EVENT_UNLINK); + LASSERT(ev->type == LNET_EVENT_SEND || + ev->type == LNET_EVENT_ACK || + ev->type == LNET_EVENT_UNLINK); if (!rs->rs_difficult) { /* 'Easy' replies have no further processing so I drop the * net's ref on 'rs' */ - LASSERT (ev->unlinked); + LASSERT(ev->unlinked); ptlrpc_rs_decref(rs); return; } - LASSERT (rs->rs_on_net); + LASSERT(rs->rs_on_net); if (ev->unlinked) { /* Last network callback. The net's ref on 'rs' stays put @@ -419,18 +419,17 @@ static void ptlrpc_master_callback(lnet_event_t *ev) void (*callback)(lnet_event_t *ev) = cbid->cbid_fn; /* Honestly, it's best to find out early. */ - LASSERT (cbid->cbid_arg != LP_POISON); - LASSERT (callback == request_out_callback || - callback == reply_in_callback || - callback == client_bulk_callback || - callback == request_in_callback || - callback == reply_out_callback - ); - - callback (ev); + LASSERT(cbid->cbid_arg != LP_POISON); + LASSERT(callback == request_out_callback || + callback == reply_in_callback || + callback == client_bulk_callback || + callback == request_in_callback || + callback == reply_out_callback); + + callback(ev); } -int ptlrpc_uuid_to_peer (struct obd_uuid *uuid, +int ptlrpc_uuid_to_peer(struct obd_uuid *uuid, lnet_process_id_t *peer, lnet_nid_t *self) { int best_dist = 0; @@ -538,7 +537,7 @@ int ptlrpc_ni_init(void) /* We're not passing any limits yet... */ rc = LNetNIInit(pid); if (rc < 0) { - CDEBUG (D_NET, "Can't init network interface: %d\n", rc); + CDEBUG(D_NET, "Can't init network interface: %d\n", rc); return (-ENOENT); } @@ -552,7 +551,7 @@ int ptlrpc_ni_init(void) if (rc == 0) return 0; - CERROR ("Failed to allocate event queue: %d\n", rc); + CERROR("Failed to allocate event queue: %d\n", rc); LNetNIFini(); return (-ENOMEM); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c index 188dbbfbd2f4..d43a13c69669 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c @@ -165,7 +165,7 @@ void ctx_start_timer_kr(struct ptlrpc_cli_ctx *ctx, long timeout) init_timer(timer); timer->expires = timeout; - timer->data = (unsigned long ) ctx; + timer->data = (unsigned long) ctx; timer->function = ctx_upcall_timeout_kr; add_timer(timer); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c index c106a9e049a7..b9fa3b4a40db 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c @@ -1276,7 +1276,7 @@ arc4_out_tfm: arc4_out_key: rawobj_free(&arc4_keye); arc4_out: - do {} while(0); /* just to avoid compile warning */ + do {} while (0); /* just to avoid compile warning */ } else { rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0, 3, data_desc, &cipher, 1); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c index b42ddda9ee25..92543f81eacf 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c @@ -483,7 +483,7 @@ int gss_do_check_seq(unsigned long *window, __u32 win_size, __u32 *max_seq, memset(window, 0, win_size / 8); *max_seq = seq_num; } else { - while(*max_seq < seq_num) { + while (*max_seq < seq_num) { (*max_seq)++; __clear_bit((*max_seq) % win_size, window); } @@ -2369,7 +2369,7 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) if (swabbed) gss_header_swabber(ghdr); - switch(ghdr->gh_proc) { + switch (ghdr->gh_proc) { case PTLRPC_GSS_PROC_INIT: case PTLRPC_GSS_PROC_CONTINUE_INIT: rc = gss_svc_handle_init(req, gw); @@ -2388,7 +2388,7 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) switch (rc) { case SECSVC_OK: - LASSERT (grctx->src_ctx); + LASSERT(grctx->src_ctx); req->rq_auth_gss = 1; req->rq_auth_remote = grctx->src_ctx->gsc_remote; diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 7b96a0e88cdb..ac8813e4ce2d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -81,14 +81,14 @@ do { \ ptlrpc_import_state_name(state)); \ __import_set_state(imp, state); \ } \ -} while(0) +} while (0) #define IMPORT_SET_STATE(imp, state) \ do { \ spin_lock(&imp->imp_lock); \ IMPORT_SET_STATE_NOLOCK(imp, state); \ spin_unlock(&imp->imp_lock); \ -} while(0) +} while (0) static int ptlrpc_connect_interpret(const struct lu_env *env, @@ -680,7 +680,7 @@ int ptlrpc_connect_import(struct obd_import *imp) ptlrpc_request_set_replen(request); request->rq_interpret_reply = ptlrpc_connect_interpret; - CLASSERT(sizeof (*aa) <= sizeof (request->rq_async_args)); + CLASSERT(sizeof(*aa) <= sizeof(request->rq_async_args)); aa = ptlrpc_req_async_args(request); memset(aa, 0, sizeof(*aa)); @@ -859,7 +859,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, if (MSG_CONNECT_RECONNECT & msg_flags) { memset(&old_hdl, 0, sizeof(old_hdl)); if (!memcmp(&old_hdl, lustre_msg_get_handle(request->rq_repmsg), - sizeof (old_hdl))) { + sizeof(old_hdl))) { LCONSOLE_WARN("Reconnect to %s (at @%s) failed due " "bad handle "LPX64"\n", obd2cli_tgt(imp->imp_obd), @@ -1507,7 +1507,7 @@ int at_measured(struct adaptive_timeout *at, unsigned int val) at->at_worst_time = now; at->at_hist[0] = val; at->at_binstart = now; - } else if (now - at->at_binstart < binlimit ) { + } else if (now - at->at_binstart < binlimit) { /* in bin 0 */ at->at_hist[0] = max(val, at->at_hist[0]); at->at_current = max(val, at->at_current); @@ -1517,7 +1517,7 @@ int at_measured(struct adaptive_timeout *at, unsigned int val) /* move bins over */ shift = (now - at->at_binstart) / binlimit; LASSERT(shift > 0); - for(i = AT_BINS - 1; i >= 0; i--) { + for (i = AT_BINS - 1; i >= 0; i--) { if (i >= shift) { at->at_hist[i] = at->at_hist[i - shift]; maxv = max(maxv, at->at_hist[i]); diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index d0a6e5689227..504682d2eefa 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -1808,7 +1808,7 @@ swabber_dumper_helper(struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc, int offset, - void *value, int len, int dump, void (*swabber)( void *)) + void *value, int len, int dump, void (*swabber)(void *)) { void *p; int i; @@ -1883,7 +1883,7 @@ swabber_dumper_helper(struct req_capsule *pill, static void *__req_capsule_get(struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc, - void (*swabber)( void *), + void (*swabber)(void *), int dump) { const struct req_format *fmt; diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c index 379e59477ea2..ab084541fddb 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c @@ -63,7 +63,7 @@ return (-EINVAL); \ } \ mutex_unlock(&ctxt->loc_mutex); \ -} while(0) +} while (0) #define LLOG_CLIENT_EXIT(ctxt, imp) do { \ mutex_lock(&ctxt->loc_mutex); \ @@ -72,7 +72,7 @@ ctxt->loc_imp, imp); \ class_import_put(imp); \ mutex_unlock(&ctxt->loc_mutex); \ -} while(0) +} while (0) /* This is a callback from the llog_* functions. * Assumes caller has already pushed us into the kernel context. */ @@ -302,7 +302,7 @@ static int llog_client_read_header(const struct lu_env *env, if (hdr == NULL) GOTO(out, rc =-EFAULT); - memcpy(handle->lgh_hdr, hdr, sizeof (*hdr)); + memcpy(handle->lgh_hdr, hdr, sizeof(*hdr)); handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index; /* sanity checks */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index bea44a3d4a2f..09d832b59f97 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -221,7 +221,7 @@ void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, for (i = 0; i < EXTRA_LAST_OPC; i++) { char *units; - switch(i) { + switch (i) { case BRW_WRITE_BYTES: case BRW_READ_BYTES: units = "bytes"; diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index a0e009717a5a..6eb06ed8b5ad 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -47,17 +47,17 @@ * over \a conn connection to portal \a portal. * Returns 0 on success or error code. */ -static int ptl_send_buf (lnet_handle_md_t *mdh, void *base, int len, - lnet_ack_req_t ack, struct ptlrpc_cb_id *cbid, - struct ptlrpc_connection *conn, int portal, __u64 xid, - unsigned int offset) +static int ptl_send_buf(lnet_handle_md_t *mdh, void *base, int len, + lnet_ack_req_t ack, struct ptlrpc_cb_id *cbid, + struct ptlrpc_connection *conn, int portal, __u64 xid, + unsigned int offset) { int rc; lnet_md_t md; - LASSERT (portal != 0); - LASSERT (conn != NULL); - CDEBUG (D_INFO, "conn=%p id %s\n", conn, libcfs_id2str(conn->c_peer)); + LASSERT(portal != 0); + LASSERT(conn != NULL); + CDEBUG(D_INFO, "conn=%p id %s\n", conn, libcfs_id2str(conn->c_peer)); md.start = base; md.length = len; md.threshold = (ack == LNET_ACK_REQ) ? 2 : 1; @@ -71,18 +71,18 @@ static int ptl_send_buf (lnet_handle_md_t *mdh, void *base, int len, ack = LNET_NOACK_REQ; } - rc = LNetMDBind (md, LNET_UNLINK, mdh); + rc = LNetMDBind(md, LNET_UNLINK, mdh); if (unlikely(rc != 0)) { - CERROR ("LNetMDBind failed: %d\n", rc); - LASSERT (rc == -ENOMEM); + CERROR("LNetMDBind failed: %d\n", rc); + LASSERT(rc == -ENOMEM); return -ENOMEM; } CDEBUG(D_NET, "Sending %d bytes to portal %d, xid "LPD64", offset %u\n", len, portal, xid, offset); - rc = LNetPut (conn->c_self, *mdh, ack, - conn->c_peer, portal, xid, offset, 0); + rc = LNetPut(conn->c_self, *mdh, ack, + conn->c_peer, portal, xid, offset, 0); if (unlikely(rc != 0)) { int rc2; /* We're going to get an UNLINK event when I unlink below, @@ -363,14 +363,14 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags) * request, or a saved copy if this is a req saved in * target_queue_final_reply(). */ - LASSERT (req->rq_no_reply == 0); - LASSERT (req->rq_reqbuf != NULL); - LASSERT (rs != NULL); - LASSERT ((flags & PTLRPC_REPLY_MAYBE_DIFFICULT) || !rs->rs_difficult); - LASSERT (req->rq_repmsg != NULL); - LASSERT (req->rq_repmsg == rs->rs_msg); - LASSERT (rs->rs_cb_id.cbid_fn == reply_out_callback); - LASSERT (rs->rs_cb_id.cbid_arg == rs); + LASSERT(req->rq_no_reply == 0); + LASSERT(req->rq_reqbuf != NULL); + LASSERT(rs != NULL); + LASSERT((flags & PTLRPC_REPLY_MAYBE_DIFFICULT) || !rs->rs_difficult); + LASSERT(req->rq_repmsg != NULL); + LASSERT(req->rq_repmsg == rs->rs_msg); + LASSERT(rs->rs_cb_id.cbid_fn == reply_out_callback); + LASSERT(rs->rs_cb_id.cbid_arg == rs); /* There may be no rq_export during failover */ @@ -423,12 +423,12 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags) req->rq_sent = cfs_time_current_sec(); - rc = ptl_send_buf (&rs->rs_md_h, rs->rs_repbuf, rs->rs_repdata_len, - (rs->rs_difficult && !rs->rs_no_ack) ? - LNET_ACK_REQ : LNET_NOACK_REQ, - &rs->rs_cb_id, conn, - ptlrpc_req2svc(req)->srv_rep_portal, - req->rq_xid, req->rq_reply_off); + rc = ptl_send_buf(&rs->rs_md_h, rs->rs_repbuf, rs->rs_repdata_len, + (rs->rs_difficult && !rs->rs_no_ack) ? + LNET_ACK_REQ : LNET_NOACK_REQ, + &rs->rs_cb_id, conn, + ptlrpc_req2svc(req)->srv_rep_portal, + req->rq_xid, req->rq_reply_off); out: if (unlikely(rc != 0)) ptlrpc_req_drop_rs(req); @@ -437,7 +437,7 @@ out: } EXPORT_SYMBOL(ptlrpc_send_reply); -int ptlrpc_reply (struct ptlrpc_request *req) +int ptlrpc_reply(struct ptlrpc_request *req) { if (req->rq_no_reply) return 0; @@ -537,13 +537,13 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) /* bulk register should be done after wrap_request() */ if (request->rq_bulk != NULL) { - rc = ptlrpc_register_bulk (request); + rc = ptlrpc_register_bulk(request); if (rc != 0) GOTO(out, rc); } if (!noreply) { - LASSERT (request->rq_replen != 0); + LASSERT(request->rq_replen != 0); if (request->rq_repbuf == NULL) { LASSERT(request->rq_repdata == NULL); LASSERT(request->rq_repmsg == NULL); @@ -566,7 +566,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) LNET_UNLINK, LNET_INS_AFTER, &reply_me_h); if (rc != 0) { CERROR("LNetMEAttach failed: %d\n", rc); - LASSERT (rc == -ENOMEM); + LASSERT(rc == -ENOMEM); GOTO(cleanup_bulk, rc = -ENOMEM); } } @@ -604,7 +604,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) &request->rq_reply_md_h); if (rc != 0) { CERROR("LNetMDAttach failed: %d\n", rc); - LASSERT (rc == -ENOMEM); + LASSERT(rc == -ENOMEM); spin_lock(&request->rq_lock); /* ...but the MD attach didn't succeed... */ request->rq_receiving_reply = 0; @@ -655,7 +655,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) * nobody apart from the PUT's target has the right nid+XID to * access the reply buffer. */ rc2 = LNetMEUnlink(reply_me_h); - LASSERT (rc2 == 0); + LASSERT(rc2 == 0); /* UNLINKED callback called synchronously */ LASSERT(!request->rq_receiving_reply); @@ -715,9 +715,9 @@ int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd) return (0); CERROR("LNetMDAttach failed: %d; \n", rc); - LASSERT (rc == -ENOMEM); - rc = LNetMEUnlink (me_h); - LASSERT (rc == 0); + LASSERT(rc == -ENOMEM); + rc = LNetMEUnlink(me_h); + LASSERT(rc == 0); rqbd->rqbd_refcount = 0; return (-ENOMEM); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index ab363477151d..9bd3f84b33b7 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -77,13 +77,13 @@ void ptlrpc_lprocfs_register_service(struct proc_dir_entry *proc_entry, struct ptlrpc_service *svc); void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc); void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount); -void ptlrpc_lprocfs_do_request_stat (struct ptlrpc_request *req, +void ptlrpc_lprocfs_do_request_stat(struct ptlrpc_request *req, long q_usec, long work_usec); #else -#define ptlrpc_lprocfs_register_service(params...) do{}while(0) -#define ptlrpc_lprocfs_unregister_service(params...) do{}while(0) -#define ptlrpc_lprocfs_rpc_sent(params...) do{}while(0) -#define ptlrpc_lprocfs_do_request_stat(params...) do{}while(0) +#define ptlrpc_lprocfs_register_service(params...) do{}while (0) +#define ptlrpc_lprocfs_unregister_service(params...) do{}while (0) +#define ptlrpc_lprocfs_rpc_sent(params...) do{}while (0) +#define ptlrpc_lprocfs_do_request_stat(params...) do{}while (0) #endif /* LPROCFS */ /* NRS */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c index 419e634854df..0efd35887a15 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c @@ -112,7 +112,7 @@ __init int ptlrpc_init(void) return 0; cleanup: - switch(cleanup_phase) { + switch (cleanup_phase) { case 8: ptlrpc_nrs_fini(); case 7: diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 21de868da522..b21ea83e75cd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -386,7 +386,7 @@ ptlrpc_schedule_difficult_reply(struct ptlrpc_reply_state *rs) { LASSERT(spin_is_locked(&rs->rs_svcpt->scp_rep_lock)); LASSERT(spin_is_locked(&rs->rs_lock)); - LASSERT (rs->rs_difficult); + LASSERT(rs->rs_difficult); rs->rs_scheduled_ever = 1; /* flag any notification attempt */ if (rs->rs_scheduled) { /* being set up or already notified */ @@ -412,7 +412,7 @@ void ptlrpc_commit_replies(struct obd_export *exp) spin_lock(&exp->exp_uncommitted_replies_lock); list_for_each_entry_safe(rs, nxt, &exp->exp_uncommitted_replies, rs_obd_list) { - LASSERT (rs->rs_difficult); + LASSERT(rs->rs_difficult); /* VBR: per-export last_committed */ LASSERT(rs->rs_export); if (rs->rs_transno <= exp->exp_last_committed) { @@ -796,7 +796,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf, LASSERT(rc == 0); mutex_lock(&ptlrpc_all_services_mutex); - list_add (&service->srv_list, &ptlrpc_all_services); + list_add(&service->srv_list, &ptlrpc_all_services); mutex_unlock(&ptlrpc_all_services_mutex); if (proc_entry != NULL) @@ -1777,9 +1777,9 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt, rc = lustre_unpack_req_ptlrpc_body(req, MSG_PTLRPC_BODY_OFF); if (rc) { - CERROR ("error unpacking ptlrpc body: ptl %d from %s x" - LPU64"\n", svc->srv_req_portal, - libcfs_id2str(req->rq_peer), req->rq_xid); + CERROR("error unpacking ptlrpc body: ptl %d from %s x" + LPU64"\n", svc->srv_req_portal, + libcfs_id2str(req->rq_peer), req->rq_xid); goto err_req; } @@ -1798,7 +1798,7 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt, goto err_req; } - switch(lustre_msg_get_opc(req->rq_reqmsg)) { + switch (lustre_msg_get_opc(req->rq_reqmsg)) { case MDS_WRITEPAGE: case OST_WRITE: req->rq_bulk_write = 1; @@ -1895,7 +1895,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt, ptlrpc_rqphase_move(request, RQ_PHASE_INTERPRET); - if(OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DUMP_LOG)) + if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DUMP_LOG)) libcfs_debug_dumplog(); do_gettimeofday(&work_start); @@ -2037,13 +2037,13 @@ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs) exp = rs->rs_export; - LASSERT (rs->rs_difficult); - LASSERT (rs->rs_scheduled); - LASSERT (list_empty(&rs->rs_list)); + LASSERT(rs->rs_difficult); + LASSERT(rs->rs_scheduled); + LASSERT(list_empty(&rs->rs_list)); spin_lock(&exp->exp_lock); /* Noop if removed already */ - list_del_init (&rs->rs_exp_list); + list_del_init(&rs->rs_exp_list); spin_unlock(&exp->exp_lock); /* The disk commit callback holds exp_uncommitted_replies_lock while it @@ -2113,9 +2113,9 @@ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs) /* Off the net */ spin_unlock(&rs->rs_lock); - class_export_put (exp); + class_export_put(exp); rs->rs_export = NULL; - ptlrpc_rs_decref (rs); + ptlrpc_rs_decref(rs); if (atomic_dec_and_test(&svcpt->scp_nreps_difficult) && svc->srv_is_stopping) wake_up_all(&svcpt->scp_waitq); -- cgit v1.2.3 From cb68dd2d0df552fe6c18da86eceda461ec0cc7c8 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:34:59 +0200 Subject: staging: lustre: ptlrpc: clean up whitespace around braces Fix the following types of checkpatch errors to comply with coding style: ERROR: space required after that close brace '}' ERROR: space required before the open brace '{' Also change "if (x == 0)" into "if (!x)" on one line, to avoid introducing new checkpatch issues. Signed-off-by: Kristina Martsenko Reviewed-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 3 ++- drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c | 8 +++++--- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 3 ++- drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h | 8 ++++---- drivers/staging/lustre/lustre/ptlrpc/service.c | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 07d34b4a074e..a5b5caabf2e8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1596,7 +1596,8 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) continue; spin_lock(&imp->imp_lock); - if (ptlrpc_import_delay_req(imp, req, &status)){ + if (ptlrpc_import_delay_req(imp, req, + &status)) { /* put on delay list - only if we wait * recovery finished - before send */ list_del_init(&req->rq_list); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c index 92543f81eacf..8ce6271a5daa 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c @@ -804,7 +804,8 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx, case PTLRPC_GSS_PROC_DATA: pack_bulk = ghdr->gh_flags & LUSTRE_GSS_PACK_BULK; - if (!req->rq_early && !equi(req->rq_pack_bulk == 1, pack_bulk)){ + if (!req->rq_early && + !equi(req->rq_pack_bulk == 1, pack_bulk)) { CERROR("%s bulk flag in reply\n", req->rq_pack_bulk ? "missing" : "unexpected"); return -EPROTO; @@ -1009,7 +1010,8 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx, case PTLRPC_GSS_PROC_DATA: pack_bulk = ghdr->gh_flags & LUSTRE_GSS_PACK_BULK; - if (!req->rq_early && !equi(req->rq_pack_bulk == 1, pack_bulk)){ + if (!req->rq_early && + !equi(req->rq_pack_bulk == 1, pack_bulk)) { CERROR("%s bulk flag in reply\n", req->rq_pack_bulk ? "missing" : "unexpected"); return -EPROTO; @@ -1979,7 +1981,7 @@ int gss_svc_handle_init(struct ptlrpc_request *req, return SECSVC_DROP; } - if (reqbuf->lm_bufcount < 3 || reqbuf->lm_bufcount > 4){ + if (reqbuf->lm_bufcount < 3 || reqbuf->lm_bufcount > 4) { CERROR("Invalid bufcount %d\n", reqbuf->lm_bufcount); return SECSVC_DROP; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 6eb06ed8b5ad..9b18b68ba1fe 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -66,7 +66,8 @@ static int ptl_send_buf(lnet_handle_md_t *mdh, void *base, int len, md.eq_handle = ptlrpc_eq_h; if (unlikely(ack == LNET_ACK_REQ && - OBD_FAIL_CHECK_ORSET(OBD_FAIL_PTLRPC_ACK, OBD_FAIL_ONCE))){ + OBD_FAIL_CHECK_ORSET(OBD_FAIL_PTLRPC_ACK, + OBD_FAIL_ONCE))) { /* don't ask for the ack to simulate failing client */ ack = LNET_NOACK_REQ; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index 9bd3f84b33b7..5d0749cc4b0f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -80,10 +80,10 @@ void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount); void ptlrpc_lprocfs_do_request_stat(struct ptlrpc_request *req, long q_usec, long work_usec); #else -#define ptlrpc_lprocfs_register_service(params...) do{}while (0) -#define ptlrpc_lprocfs_unregister_service(params...) do{}while (0) -#define ptlrpc_lprocfs_rpc_sent(params...) do{}while (0) -#define ptlrpc_lprocfs_do_request_stat(params...) do{}while (0) +#define ptlrpc_lprocfs_register_service(params...) do {} while (0) +#define ptlrpc_lprocfs_unregister_service(params...) do {} while (0) +#define ptlrpc_lprocfs_rpc_sent(params...) do {} while (0) +#define ptlrpc_lprocfs_do_request_stat(params...) do {} while (0) #endif /* LPROCFS */ /* NRS */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index b21ea83e75cd..544a030a2a2e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1268,7 +1268,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) return -ETIMEDOUT; } - if ((lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT) == 0){ + if (!(lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT)) { DEBUG_REQ(D_INFO, req, "Wanted to ask client for more time, " "but no AT support"); return -ENOSYS; -- cgit v1.2.3 From 7b8633dea27a5b4197d17e01e37ec07ed7837dc8 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:35:00 +0200 Subject: staging: lustre: ptlrpc: remove an unnecessary semicolon Remove an unnecessary semicolon and remove a space before another one to comply with coding style. Fix the following type of checkpatch warning: WARNING: space prohibited before semicolon Signed-off-by: Kristina Martsenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index a5b5caabf2e8..777f9314d6c4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -200,7 +200,7 @@ void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin) class_import_put(desc->bd_import); if (unpin) { - for (i = 0; i < desc->bd_iov_count ; i++) + for (i = 0; i < desc->bd_iov_count; i++) page_cache_release(desc->bd_iov[i].kiov_page); } @@ -1039,7 +1039,7 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, *status = -EIO; } else if (req->rq_send_state == LUSTRE_IMP_CONNECTING && imp->imp_state == LUSTRE_IMP_CONNECTING) { - /* allow CONNECT even if import is invalid */ ; + /* allow CONNECT even if import is invalid */ if (atomic_read(&imp->imp_inval_count) != 0) { DEBUG_REQ(D_ERROR, req, "invalidate in flight"); *status = -EIO; -- cgit v1.2.3 From 2a763282df786aa8470a1e52c653dc3dcc574ed7 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:35:01 +0200 Subject: staging: lustre: ptlrpc: convert spaces to tabs Fix the following type of checkpatch warning to comply with coding style: WARNING: please, no spaces at the start of a line Signed-off-by: Kristina Martsenko Reviewed-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h | 6 +++--- drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h | 10 +++++----- drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h index c70eb00796f9..bdfd83880422 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h @@ -64,9 +64,9 @@ #define G_REFLECT (-2045022961L) #define G_WRONG_TOKID (-2045022960L) -#define g_OID_equal(o1,o2) \ - (((o1)->len == (o2)->len) && \ - (memcmp((o1)->data,(o2)->data,(int) (o1)->len) == 0)) +#define g_OID_equal(o1, o2) \ + (((o1)->len == (o2)->len) && \ + (memcmp((o1)->data, (o2)->data, (int) (o1)->len) == 0)) __u32 g_verify_token_header(rawobj_t *mech, int *body_size, diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h index 13425796fa33..37ec101e14e5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h @@ -106,14 +106,14 @@ typedef unsigned int OM_uint32; * evaluates its argument only once. */ #define GSS_CALLING_ERROR(x) \ - ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) + ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) #define GSS_ROUTINE_ERROR(x) \ - ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) + ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) #define GSS_SUPPLEMENTARY_INFO(x) \ - ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) + ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) #define GSS_ERROR(x) \ - ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ - (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) /* * Now the actual status code definitions diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 09d832b59f97..65451f77e782 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -46,8 +46,8 @@ struct ll_rpc_opcode { - __u32 opcode; - const char *opname; + __u32 opcode; + const char *opname; } ll_rpc_opcode_table[LUSTRE_MAX_OPCODES] = { { OST_REPLY, "ost_reply" }, { OST_GETATTR, "ost_getattr" }, @@ -137,8 +137,8 @@ struct ll_rpc_opcode { }; struct ll_eopcode { - __u32 opcode; - const char *opname; + __u32 opcode; + const char *opname; } ll_eopcode_table[EXTRA_LAST_OPC] = { { LDLM_GLIMPSE_ENQUEUE, "ldlm_glimpse_enqueue" }, { LDLM_PLAIN_ENQUEUE, "ldlm_plain_enqueue" }, -- cgit v1.2.3 From 998d2766fe2027be201d1571524e235672157bc2 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:35:02 +0200 Subject: staging: lustre: ptlrpc: remove whitespace before a newline Fix the following type of checkpatch warning: WARNING: unnecessary whitespace before a quoted newline Signed-off-by: Kristina Martsenko Reviewed-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 9b18b68ba1fe..5f2aa7aa17ea 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -715,7 +715,7 @@ int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd) if (rc == 0) return (0); - CERROR("LNetMDAttach failed: %d; \n", rc); + CERROR("LNetMDAttach failed: %d;\n", rc); LASSERT(rc == -ENOMEM); rc = LNetMEUnlink(me_h); LASSERT(rc == 0); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index 5dec771d70ee..a084eb1b1aca 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -576,7 +576,7 @@ int ptlrpc_del_timeout_client(struct list_head *obd_list, break; } } - LASSERTF(ti != NULL, "ti is NULL ! \n"); + LASSERTF(ti != NULL, "ti is NULL !\n"); if (list_empty(&ti->ti_obd_list)) { list_del(&ti->ti_chain); OBD_FREE_PTR(ti); -- cgit v1.2.3 From 532118c080368bd15dcafd1e6054f4b5a343941d Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:35:03 +0200 Subject: staging: lustre: ptlrpc: fix indentation Fix the following type of checkpatch warning to comply with coding style: WARNING: suspect code indent for conditional statements Also join a debug string split across lines, as it was on the same lines as the other changes anyway. And reformat some comments in the kernel coding style for the same reason. Signed-off-by: Kristina Martsenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/import.c | 26 ++++++++++++---------- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 4 ++-- drivers/staging/lustre/lustre/ptlrpc/service.c | 21 +++++++++-------- 3 files changed, 28 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index ac8813e4ce2d..283173a2fe23 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -72,15 +72,15 @@ static void __import_set_state(struct obd_import *imp, } /* A CLOSED import should remain so. */ -#define IMPORT_SET_STATE_NOLOCK(imp, state) \ -do { \ - if (imp->imp_state != LUSTRE_IMP_CLOSED) { \ - CDEBUG(D_HA, "%p %s: changing import state from %s to %s\n", \ - imp, obd2cli_tgt(imp->imp_obd), \ - ptlrpc_import_state_name(imp->imp_state), \ - ptlrpc_import_state_name(state)); \ - __import_set_state(imp, state); \ - } \ +#define IMPORT_SET_STATE_NOLOCK(imp, state) \ +do { \ + if (imp->imp_state != LUSTRE_IMP_CLOSED) { \ + CDEBUG(D_HA, "%p %s: changing import state from %s to %s\n", \ + imp, obd2cli_tgt(imp->imp_obd), \ + ptlrpc_import_state_name(imp->imp_state), \ + ptlrpc_import_state_name(state)); \ + __import_set_state(imp, state); \ + } \ } while (0) #define IMPORT_SET_STATE(imp, state) \ @@ -1135,9 +1135,11 @@ out: if (ocd && (ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && (ocd->ocd_version != LUSTRE_VERSION_CODE)) { - /* Actually servers are only supposed to refuse - connection from liblustre clients, so we should - never see this from VFS context */ + /* + * Actually servers are only supposed to refuse + * connection from liblustre clients, so we + * should never see this from VFS context + */ LCONSOLE_ERROR_MSG(0x16a, "Server %s version " "(%d.%d.%d.%d)" " refused connection from this client " diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 94abb51cf642..4659314a1865 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -636,8 +636,8 @@ static inline int lustre_unpack_ptlrpc_body_v2(struct ptlrpc_request *req, } if ((pb->pb_version & ~LUSTRE_VERSION_MASK) != PTLRPC_MSG_VERSION) { - CERROR("wrong lustre_msg version %08x\n", pb->pb_version); - return -EINVAL; + CERROR("wrong lustre_msg version %08x\n", pb->pb_version); + return -EINVAL; } if (!inout) diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 544a030a2a2e..2b10d6dea2d9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1115,8 +1115,10 @@ static int ptlrpc_check_req(struct ptlrpc_request *req) } if (unlikely(req->rq_export->exp_obd && req->rq_export->exp_obd->obd_fail)) { - /* Failing over, don't handle any more reqs, send - error response instead. */ + /* + * Failing over, don't handle any more reqs, send + * error response instead. + */ CDEBUG(D_RPCTRACE, "Dropping req %p for failed obd %s\n", req, req->rq_export->exp_obd->obd_name); rc = -ENODEV; @@ -1967,13 +1969,14 @@ put_conn: lu_context_fini(&request->rq_session); if (unlikely(cfs_time_current_sec() > request->rq_deadline)) { - DEBUG_REQ(D_WARNING, request, "Request took longer " - "than estimated ("CFS_DURATION_T":"CFS_DURATION_T"s);" - " client may timeout.", - cfs_time_sub(request->rq_deadline, - request->rq_arrival_time.tv_sec), - cfs_time_sub(cfs_time_current_sec(), - request->rq_deadline)); + DEBUG_REQ(D_WARNING, request, + "Request took longer than estimated (" + CFS_DURATION_T":"CFS_DURATION_T + "s); client may timeout.", + cfs_time_sub(request->rq_deadline, + request->rq_arrival_time.tv_sec), + cfs_time_sub(cfs_time_current_sec(), + request->rq_deadline)); } do_gettimeofday(&work_end); -- cgit v1.2.3 From 7f1d15a819f01c0abc5763c522d537b9e3ef40fe Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 21:35:04 +0200 Subject: staging: lustre: ptlrpc: fix label indentation Fix the following type of checkpatch warning to comply with coding style: WARNING: labels should not be indented Signed-off-by: Kristina Martsenko Reviewed-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 777f9314d6c4..d90efe408414 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1753,7 +1753,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) ptlrpc_rqphase_move(req, RQ_PHASE_INTERPRET); - interpret: +interpret: LASSERT(req->rq_phase == RQ_PHASE_INTERPRET); /* This moves to "unregistering" phase we need to wait for -- cgit v1.2.3 From e630a6bcf18079b2ab6b03d55c9757e8ef6656b6 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Mon, 11 Nov 2013 22:42:32 +0200 Subject: staging: lustre: fix checkpatch issue regarding pointer coding style Fix the following checkpatch error: ERROR: "(foo*)" should be "(foo *)" Signed-off-by: Kristina Martsenko Reviewed-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdecho/echo_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 1fb0ac4e920d..9b2dea292363 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1106,7 +1106,7 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, /* coverity[overrun-buffer-val] */ obj = cl_object_find(env, echo_dev2cl(d), fid, &conf->eoc_cl); if (IS_ERR(obj)) - GOTO(out, eco = (void*)obj); + GOTO(out, eco = (void *)obj); eco = cl2echo_obj(obj); if (eco->eo_deleted) { -- cgit v1.2.3 From 2ac0f45099d2d3b8918d63e1bac698b5cb272aa1 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 12 Nov 2013 14:44:19 +0200 Subject: drm/i915: add i915_reset_count reset_counter will be incremented twice per successful reset. Odd values mean reset is in progress and even values mean that reset has completed. Reset status ioctl introduced in following commit needs to deliver global reset count to userspace so use reset_counter to derive the actual reset count for the gpu Note that reset in progress is enough to increment the counter. v2: wedged equals reset in progress (Daniel Vetter) v3: Fixed stale comments (Damien Lespiau) Signed-off-by: Mika Kuoppala Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 43 +++++++++++++++++++++-------------------- drivers/gpu/drm/i915/i915_irq.c | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c546316ac649..4c0f751d1c88 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1069,34 +1069,30 @@ struct i915_gpu_error { unsigned long missed_irq_rings; /** - * State variable and reset counter controlling the reset flow + * State variable controlling the reset flow and count * - * Upper bits are for the reset counter. This counter is used by the - * wait_seqno code to race-free noticed that a reset event happened and - * that it needs to restart the entire ioctl (since most likely the - * seqno it waited for won't ever signal anytime soon). + * This is a counter which gets incremented when reset is triggered, + * and again when reset has been handled. So odd values (lowest bit set) + * means that reset is in progress and even values that + * (reset_counter >> 1):th reset was successfully completed. + * + * If reset is not completed succesfully, the I915_WEDGE bit is + * set meaning that hardware is terminally sour and there is no + * recovery. All waiters on the reset_queue will be woken when + * that happens. + * + * This counter is used by the wait_seqno code to notice that reset + * event happened and it needs to restart the entire ioctl (since most + * likely the seqno it waited for won't ever signal anytime soon). * * This is important for lock-free wait paths, where no contended lock * naturally enforces the correct ordering between the bail-out of the * waiter and the gpu reset work code. - * - * Lowest bit controls the reset state machine: Set means a reset is in - * progress. This state will (presuming we don't have any bugs) decay - * into either unset (successful reset) or the special WEDGED value (hw - * terminally sour). All waiters on the reset_queue will be woken when - * that happens. */ atomic_t reset_counter; - /** - * Special values/flags for reset_counter - * - * Note that the code relies on - * I915_WEDGED & I915_RESET_IN_PROGRESS_FLAG - * being true. - */ #define I915_RESET_IN_PROGRESS_FLAG 1 -#define I915_WEDGED 0xffffffff +#define I915_WEDGED (1 << 31) /** * Waitqueue to signal when the reset has completed. Used by clients @@ -2046,12 +2042,17 @@ int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, static inline bool i915_reset_in_progress(struct i915_gpu_error *error) { return unlikely(atomic_read(&error->reset_counter) - & I915_RESET_IN_PROGRESS_FLAG); + & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED)); } static inline bool i915_terminally_wedged(struct i915_gpu_error *error) { - return atomic_read(&error->reset_counter) == I915_WEDGED; + return atomic_read(&error->reset_counter) & I915_WEDGED; +} + +static inline u32 i915_reset_count(struct i915_gpu_error *error) +{ + return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2; } void i915_gem_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e14285bafbd4..19949e8b36c5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1781,7 +1781,7 @@ static void i915_error_work_func(struct work_struct *work) kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); } else { - atomic_set(&error->reset_counter, I915_WEDGED); + atomic_set_mask(I915_WEDGED, &error->reset_counter); } /* -- cgit v1.2.3 From b6359918b885da7c7b58c050674278dbd06020ab Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 30 Oct 2013 15:44:16 +0200 Subject: drm/i915: add i915_get_reset_stats_ioctl This ioctl returns reset stats for specified context. The struct returned contains context loss counters. reset_count: all resets across all contexts batch_active: active batches lost on resets batch_pending: pending batches lost on resets v2: get rid of state tracking completely and deliver only counts. Idea from Chris Wilson. v3: fix commit message v4: default context handled inside i915_gem_context_get_hang_stats v5: reset_count only for priviledged process v6: ctx=0 needs CAP_SYS_ADMIN for batch_* counters (Chris Wilson) v7: context hang stats never returns NULL v8: rebased on top of reworked context hang stats DRM_RENDER_ALLOW for ioctl v9: use DEFAULT_CONTEXT_ID. Improve comments for ioctl struct members Signed-off-by: Mika Kuoppala Cc: Ian Romanick Cc: Chris Wilson Cc: Daniel Vetter Reviewed-by: Damien Lespiau Reviewed-by: Ian Romanick Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_uncore.c | 34 ++++++++++++++++++++++++++++++++++ include/uapi/drm/i915_drm.h | 19 +++++++++++++++++++ 4 files changed, 56 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d045135..00d74f816a72 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1908,6 +1908,7 @@ const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4c0f751d1c88..6d2a9a1c8379 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2382,6 +2382,8 @@ extern int intel_enable_rc6(const struct drm_device *dev); extern bool i915_semaphore_is_enabled(struct drm_device *dev); int i915_reg_read_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); /* overlay */ extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index f6fae35c568e..21cf9519be78 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -633,6 +633,40 @@ int i915_reg_read_ioctl(struct drm_device *dev, return 0; } +int i915_get_reset_stats_ioctl(struct drm_device *dev, + void *data, struct drm_file *file) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_reset_stats *args = data; + struct i915_ctx_hang_stats *hs; + int ret; + + if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id); + if (IS_ERR(hs)) { + mutex_unlock(&dev->struct_mutex); + return PTR_ERR(hs); + } + + if (capable(CAP_SYS_ADMIN)) + args->reset_count = i915_reset_count(&dev_priv->gpu_error); + else + args->reset_count = 0; + + args->batch_active = hs->batch_active; + args->batch_pending = hs->batch_pending; + + mutex_unlock(&dev->struct_mutex); + + return 0; +} + static int i965_reset_complete(struct drm_device *dev) { u8 gdrst; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 3a4e97bd8607..52aed893710a 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -222,6 +222,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_SET_CACHING 0x2f #define DRM_I915_GEM_GET_CACHING 0x30 #define DRM_I915_REG_READ 0x31 +#define DRM_I915_GET_RESET_STATS 0x32 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -271,6 +272,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) #define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read) +#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -1030,4 +1032,21 @@ struct drm_i915_reg_read { __u64 offset; __u64 val; /* Return value */ }; + +struct drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + + /* All resets since boot/module reload, for all contexts */ + __u32 reset_count; + + /* Number of batches lost when active in GPU, for this context */ + __u32 batch_active; + + /* Number of batches lost pending for execution, for this context */ + __u32 batch_pending; + + __u32 pad; +}; + #endif /* _UAPI_I915_DRM_H_ */ -- cgit v1.2.3 From 479398b07048342c7fdca89fd3a6cdb739e48a86 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 4 Nov 2013 09:19:34 -0800 Subject: ath10k: add logging to better determine some VIF/STA creation failures Not all errors were properly notified, fix that. kvalo: use ath10k_warn() for all messages, cosmetic changes to some of the messages Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index f45eca0b7a4e..56f030ed357a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -322,12 +322,16 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr) lockdep_assert_held(&ar->conf_mutex); ret = ath10k_wmi_peer_create(ar, vdev_id, addr); - if (ret) + if (ret) { + ath10k_warn("Failed to create wmi peer: %i\n", ret); return ret; + } ret = ath10k_wait_for_peer_created(ar, vdev_id, addr); - if (ret) + if (ret) { + ath10k_warn("Failed to wait for created wmi peer: %i\n", ret); return ret; + } return 0; } @@ -2404,8 +2408,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ret = ath10k_peer_create(ar, arvif->vdev_id, info->bssid); if (ret) - ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", - info->bssid, arvif->vdev_id); + ath10k_warn("Failed to add peer %pM for vdev %d when changin bssid: %i\n", + info->bssid, arvif->vdev_id, ret); if (vif->type == NL80211_IFTYPE_STATION) { /* @@ -2687,8 +2691,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); if (ret) - ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", - sta->addr, arvif->vdev_id); + ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n", + sta->addr, arvif->vdev_id, ret); } else if ((old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST)) { /* -- cgit v1.2.3 From fad6ed7867f41b2a9a7fc6cd01db37f33a29da1e Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:23 +0100 Subject: ath10k: remove ar_pci->ce_count It wasn't really useful to have it to begin with. This makes it a little simpler to re-arrange PCI init code as some function depended on ar_pci->ce_count being set. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 9 +++------ drivers/net/wireless/ath/ath10k/pci.c | 18 ++++++++---------- drivers/net/wireless/ath/ath10k/pci.h | 3 --- 3 files changed, 11 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index d243f287fae7..2b99bd41dde3 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -731,7 +731,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) void ath10k_ce_per_engine_service_any(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ce_id, ret; u32 intr_summary; @@ -741,7 +740,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) intr_summary = CE_INTERRUPT_SUMMARY(ar); - for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) { + for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) { if (intr_summary & (1 << ce_id)) intr_summary &= ~(1 << ce_id); else @@ -785,16 +784,14 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, void ath10k_ce_disable_interrupts(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ce_id, ret; ret = ath10k_pci_wake(ar); if (ret) return; - for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) { - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; - u32 ctrl_addr = ce_state->ctrl_addr; + for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { + u32 ctrl_addr = ath10k_ce_base_address(ce_id); ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); } diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 25ed07b96a1e..f054d4c30245 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -831,7 +831,7 @@ static int ath10k_pci_start_ce(struct ath10k *ar) spin_lock_init(&ar_pci->compl_lock); INIT_LIST_HEAD(&ar_pci->compl_process); - for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { pipe_info = &ar_pci->pipe_info[pipe_num]; spin_lock_init(&pipe_info->pipe_lock); @@ -924,7 +924,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar) spin_unlock_bh(&ar_pci->compl_lock); /* Free unused completions for each pipe. */ - for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { pipe_info = &ar_pci->pipe_info[pipe_num]; spin_lock_bh(&pipe_info->pipe_lock); @@ -1166,7 +1166,7 @@ static int ath10k_pci_post_rx(struct ath10k *ar) const struct ce_attr *attr; int pipe_num, ret = 0; - for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { pipe_info = &ar_pci->pipe_info[pipe_num]; attr = &host_ce_config_wlan[pipe_num]; @@ -1295,7 +1295,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int pipe_num; - for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { struct ath10k_pci_pipe *pipe_info; pipe_info = &ar_pci->pipe_info[pipe_num]; @@ -1310,7 +1310,7 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar) struct ath10k_pci_pipe *pipe_info; int pipe_num; - for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { pipe_info = &ar_pci->pipe_info[pipe_num]; if (pipe_info->ce_hdl) { ath10k_ce_deinit(pipe_info->ce_hdl); @@ -1755,7 +1755,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar) const struct ce_attr *attr; int pipe_num; - for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { pipe_info = &ar_pci->pipe_info[pipe_num]; pipe_info->pipe_num = pipe_num; pipe_info->hif_ce_state = ar; @@ -1772,13 +1772,12 @@ static int ath10k_pci_ce_init(struct ath10k *ar) return -1; } - if (pipe_num == ar_pci->ce_count - 1) { + if (pipe_num == CE_COUNT - 1) { /* * Reserve the ultimate CE for * diagnostic Window support */ - ar_pci->ce_diag = - ar_pci->pipe_info[ar_pci->ce_count - 1].ce_hdl; + ar_pci->ce_diag = pipe_info->ce_hdl; continue; } @@ -2235,7 +2234,6 @@ static int ath10k_pci_start_intr(struct ath10k *ar) exit: ar_pci->num_msi_intrs = num; - ar_pci->ce_count = CE_COUNT; return ret; } diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index a304c3384902..73a3d4ee6ebf 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -199,9 +199,6 @@ struct ath10k_pci { struct tasklet_struct intr_tq; struct tasklet_struct msi_fw_err; - /* Number of Copy Engines supported */ - unsigned int ce_count; - int started; atomic_t keep_awake_count; -- cgit v1.2.3 From 103d4f5ed68b2667c134189749fb48cb7c96aa80 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:24 +0100 Subject: ath10k: don't forget to kill fw error tasklet It was possible for FW error tasklet to be executed during teardown. This could lead to system crashes and/or memory corruption. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index f054d4c30245..31cdde05562e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -888,6 +888,7 @@ static void ath10k_pci_stop_ce(struct ath10k *ar) /* Cancel the pending tasklet */ tasklet_kill(&ar_pci->intr_tq); + tasklet_kill(&ar_pci->msi_fw_err); for (i = 0; i < CE_COUNT; i++) tasklet_kill(&ar_pci->pipe_info[i].intr); -- cgit v1.2.3 From 96a9d0dc296b9ee63383549efb683dbf0ae2f0f8 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:25 +0100 Subject: ath10k: split tasklet killing function The function will soon be called from more than 1 place. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 31cdde05562e..a001ff250d3a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -877,21 +877,26 @@ static int ath10k_pci_start_ce(struct ath10k *ar) return 0; } -static void ath10k_pci_stop_ce(struct ath10k *ar) +static void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_pci_compl *compl; - struct sk_buff *skb; int i; - ath10k_ce_disable_interrupts(ar); - - /* Cancel the pending tasklet */ tasklet_kill(&ar_pci->intr_tq); tasklet_kill(&ar_pci->msi_fw_err); for (i = 0; i < CE_COUNT; i++) tasklet_kill(&ar_pci->pipe_info[i].intr); +} + +static void ath10k_pci_stop_ce(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_compl *compl; + struct sk_buff *skb; + + ath10k_ce_disable_interrupts(ar); + ath10k_pci_kill_tasklet(ar); /* Mark pending completions as aborted, so that upper layers free up * their associated resources */ -- cgit v1.2.3 From d7fb47f52ef5538b4eb32856bd8cb580623dd87f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:26 +0100 Subject: ath10k: rename ath10k_pci_reset_target() What the function does is to actually wait for the firmware indication bit to be set. Prerequisite for this is having interrupts registered. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index a001ff250d3a..4aa7992f1a35 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -53,7 +53,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); static void ath10k_pci_stop_ce(struct ath10k *ar); static void ath10k_pci_device_reset(struct ath10k *ar); -static int ath10k_pci_reset_target(struct ath10k *ar); +static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_start_intr(struct ath10k *ar); static void ath10k_pci_stop_intr(struct ath10k *ar); @@ -1857,7 +1857,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) */ ath10k_pci_device_reset(ar); - ret = ath10k_pci_reset_target(ar); + ret = ath10k_pci_wait_for_target_init(ar); if (ret) goto err_irq; @@ -2257,7 +2257,7 @@ static void ath10k_pci_stop_intr(struct ath10k *ar) pci_disable_msi(ar_pci->pdev); } -static int ath10k_pci_reset_target(struct ath10k *ar) +static int ath10k_pci_wait_for_target_init(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int wait_limit = 300; /* 3 sec */ -- cgit v1.2.3 From 93e0daa0ee3ef53a45293e60b2eaf770d7bb1d53 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:27 +0100 Subject: ath10k: make sure to mask all CE irqs CE error interrupts were not disabled. This could lead to invalid memory accesses / memory corruption. Also make sure CE watermark interrupts are also disabled. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 2b99bd41dde3..7a49cde9c616 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -243,6 +243,16 @@ static inline void ath10k_ce_error_intr_enable(struct ath10k *ar, misc_ie_addr | CE_ERROR_MASK); } +static inline void ath10k_ce_error_intr_disable(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + u32 misc_ie_addr = ath10k_pci_read32(ar, + ce_ctrl_addr + MISC_IE_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, + misc_ie_addr & ~CE_ERROR_MASK); +} + static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int mask) @@ -794,6 +804,8 @@ void ath10k_ce_disable_interrupts(struct ath10k *ar) u32 ctrl_addr = ath10k_ce_base_address(ce_id); ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); + ath10k_ce_error_intr_disable(ar, ctrl_addr); + ath10k_ce_watermark_intr_disable(ar, ctrl_addr); } ath10k_pci_sleep(ar); } -- cgit v1.2.3 From 1d34902192bf31741729184dd459eccdba5dbc83 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:28 +0100 Subject: ath10k: fix ath10k_ce_init() failpath Make sure to put target back to sleep. This was a minor issue as it didn't really matter if we put target back to sleep at this point. It just looked wrong. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 7a49cde9c616..657e8f2ee982 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1077,7 +1077,7 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ce_state = ath10k_ce_init_state(ar, ce_id, attr); if (!ce_state) { ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id); - return NULL; + goto out; } if (attr->src_nentries) { @@ -1086,7 +1086,8 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n", ce_id, ret); ath10k_ce_deinit(ce_state); - return NULL; + ce_state = NULL; + goto out; } } @@ -1096,15 +1097,16 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n", ce_id, ret); ath10k_ce_deinit(ce_state); - return NULL; + ce_state = NULL; + goto out; } } /* Enable CE error interrupts */ ath10k_ce_error_intr_enable(ar, ctrl_addr); +out: ath10k_pci_sleep(ar); - return ce_state; } -- cgit v1.2.3 From 8630e3ad92e76c1b9e4cbd90eaf2eb6d58f1dd31 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:29 +0100 Subject: ath10k: remove meaningless check The check doesn't make much sense. If the address were to be 0x0000 the check would fail. In this case a 0 address isn't wrong. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4aa7992f1a35..62df0ddd3238 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2307,9 +2307,6 @@ static void ath10k_pci_device_reset(struct ath10k *ar) int i; u32 val; - if (!SOC_GLOBAL_RESET_ADDRESS) - return; - ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { -- cgit v1.2.3 From 5b2589fcfff1def576314f9e89d61eeb23bac5ac Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:30 +0100 Subject: ath10k: use ath10k_do_pci_wake/sleep This removes some remaining direct use of the wake register which could interfere with power state tracking of the target device. This will allow initialization code reordering. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 84 +++++++++++------------------------ 1 file changed, 26 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 62df0ddd3238..2b4f7d3969e1 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -52,7 +52,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, int num); static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); static void ath10k_pci_stop_ce(struct ath10k *ar); -static void ath10k_pci_device_reset(struct ath10k *ar); +static int ath10k_pci_device_reset(struct ath10k *ar); static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_start_intr(struct ath10k *ar); static void ath10k_pci_stop_intr(struct ath10k *ar); @@ -526,21 +526,6 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar) return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON); } -static int ath10k_pci_wait(struct ath10k *ar) -{ - int n = 100; - - while (n-- && !ath10k_pci_target_is_awake(ar)) - msleep(10); - - if (n < 0) { - ath10k_warn("Unable to wakeup target\n"); - return -ETIMEDOUT; - } - - return 0; -} - int ath10k_do_pci_wake(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1855,7 +1840,11 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) * is in an unexpected state. We try to catch that here in order to * reset the Target and retry the probe. */ - ath10k_pci_device_reset(ar); + ret = ath10k_pci_device_reset(ar); + if (ret) { + ath10k_err("failed to reset target: %d\n", ret); + goto err_irq; + } ret = ath10k_pci_wait_for_target_init(ar); if (ret) @@ -2156,19 +2145,10 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) if (ret < 0) return ret; - /* - * Make sure to wake the Target before enabling Legacy - * Interrupt. - */ - iowrite32(PCIE_SOC_WAKE_V_MASK, - ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + - PCIE_SOC_WAKE_ADDRESS); - - ret = ath10k_pci_wait(ar); + ret = ath10k_do_pci_wake(ar); if (ret) { - ath10k_warn("Failed to enable legacy interrupt, target did not wake up: %d\n", - ret); free_irq(ar_pci->pdev->irq, ar); + ath10k_err("failed to wake up target: %d\n", ret); return ret; } @@ -2184,10 +2164,8 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) PCIE_INTR_CE_MASK_ALL, ar_pci->mem + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); - iowrite32(PCIE_SOC_WAKE_RESET, - ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + - PCIE_SOC_WAKE_ADDRESS); + ath10k_do_pci_sleep(ar); ath10k_info("legacy interrupt handling\n"); return 0; } @@ -2263,15 +2241,9 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) int wait_limit = 300; /* 3 sec */ int ret; - /* Wait for Target to finish initialization before we proceed. */ - iowrite32(PCIE_SOC_WAKE_V_MASK, - ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + - PCIE_SOC_WAKE_ADDRESS); - - ret = ath10k_pci_wait(ar); + ret = ath10k_do_pci_wake(ar); if (ret) { - ath10k_warn("Failed to reset target, target did not wake up: %d\n", - ret); + ath10k_err("failed to wake up target: %d\n", ret); return ret; } @@ -2288,31 +2260,26 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) } if (wait_limit < 0) { - ath10k_err("Target stalled\n"); - iowrite32(PCIE_SOC_WAKE_RESET, - ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + - PCIE_SOC_WAKE_ADDRESS); - return -EIO; + ath10k_err("target stalled\n"); + ret = -EIO; + goto out; } - iowrite32(PCIE_SOC_WAKE_RESET, - ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + - PCIE_SOC_WAKE_ADDRESS); - - return 0; +out: + ath10k_do_pci_sleep(ar); + return ret; } -static void ath10k_pci_device_reset(struct ath10k *ar) +static int ath10k_pci_device_reset(struct ath10k *ar) { - int i; + int i, ret; u32 val; - ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, - PCIE_SOC_WAKE_V_MASK); - for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { - if (ath10k_pci_target_is_awake(ar)) - break; - msleep(1); + ret = ath10k_do_pci_wake(ar); + if (ret) { + ath10k_err("failed to wake up target: %d\n", + ret); + return ret; } /* Put Target, including PCIe, into RESET. */ @@ -2338,7 +2305,8 @@ static void ath10k_pci_device_reset(struct ath10k *ar) msleep(1); } - ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + ath10k_do_pci_sleep(ar); + return 0; } static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci) -- cgit v1.2.3 From 28642f428100fa602d08714d0005b6a5a4e47e9b Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:31 +0100 Subject: ath10k: propagate ath10k_ce_disable_interrupts() errors This shouldn't be silenced. This will be necessary for PCI init code reordering. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 7 +++++-- drivers/net/wireless/ath/ath10k/ce.h | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 6 +++++- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 657e8f2ee982..ab22d14f4569 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -792,13 +792,13 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, ath10k_pci_sleep(ar); } -void ath10k_ce_disable_interrupts(struct ath10k *ar) +int ath10k_ce_disable_interrupts(struct ath10k *ar) { int ce_id, ret; ret = ath10k_pci_wake(ar); if (ret) - return; + return ret; for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { u32 ctrl_addr = ath10k_ce_base_address(ce_id); @@ -807,7 +807,10 @@ void ath10k_ce_disable_interrupts(struct ath10k *ar) ath10k_ce_error_intr_disable(ar, ctrl_addr); ath10k_ce_watermark_intr_disable(ar, ctrl_addr); } + ath10k_pci_sleep(ar); + + return 0; } void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 15d45b5b7615..67dbde6a5c74 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -234,7 +234,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state); /*==================CE Interrupt Handlers====================*/ void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); -void ath10k_ce_disable_interrupts(struct ath10k *ar); +int ath10k_ce_disable_interrupts(struct ath10k *ar); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 2b4f7d3969e1..e41665f7eb85 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -879,8 +879,12 @@ static void ath10k_pci_stop_ce(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_compl *compl; struct sk_buff *skb; + int ret; + + ret = ath10k_ce_disable_interrupts(ar); + if (ret) + ath10k_warn("failed to disable CE interrupts: %d\n", ret); - ath10k_ce_disable_interrupts(ar); ath10k_pci_kill_tasklet(ar); /* Mark pending completions as aborted, so that upper layers free up -- cgit v1.2.3 From 2415fc16391af204170f5478072fb1a2c66b87f3 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:32 +0100 Subject: ath10k: guard against CE corruption from firmware In case firmware crashes it may report CE completions for entries that were never submitted/filled with meaningful data. This in turn led to NULL dereferences. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htc.c | 5 +++++ drivers/net/wireless/ath/ath10k/pci.c | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 3118d7506734..6d7a72eb11a5 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -191,6 +191,11 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar, struct ath10k_htc *htc = &ar->htc; struct ath10k_htc_ep *ep = &htc->endpoint[eid]; + if (!skb) { + ath10k_warn("invalid sk_buff completion - NULL pointer. firmware crashed?\n"); + return 0; + } + ath10k_htc_notify_tx_completion(ep, skb); /* the skb now belongs to the completion handler */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index e41665f7eb85..0b897269f129 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1270,6 +1270,13 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) * Indicate the completion to higer layer to free * the buffer */ + + if (!netbuf) { + ath10k_warn("invalid sk_buff on CE %d - NULL pointer. firmware crashed?\n", + ce_hdl->id); + continue; + } + ATH10K_SKB_CB(netbuf)->is_aborted = true; ar_pci->msg_callbacks_current.tx_completion(ar, netbuf, -- cgit v1.2.3 From 98563d5aafa45498f8c2f6885b2bd03eab648f19 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:33 +0100 Subject: ath10k: re-arrange PCI init code This patch moves irq registering after necessary structures have been allocated and initialized. This should prevent interrupts from causing tasklet access invalid memory pointers. Reported-By: Ben Greear Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 19 ++++++-- drivers/net/wireless/ath/ath10k/ce.h | 1 + drivers/net/wireless/ath/ath10k/pci.c | 87 ++++++++++++++++++++++------------- 3 files changed, 71 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index ab22d14f4569..476928f2dadc 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -792,6 +792,21 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, ath10k_pci_sleep(ar); } +int ath10k_ce_enable_err_irq(struct ath10k *ar) +{ + int i, ret; + + ret = ath10k_pci_wake(ar); + if (ret) + return ret; + + for (i = 0; i < CE_COUNT; i++) + ath10k_ce_error_intr_enable(ar, ath10k_ce_base_address(i)); + + ath10k_pci_sleep(ar); + return 0; +} + int ath10k_ce_disable_interrupts(struct ath10k *ar) { int ce_id, ret; @@ -1059,7 +1074,6 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, const struct ce_attr *attr) { struct ath10k_ce_pipe *ce_state; - u32 ctrl_addr = ath10k_ce_base_address(ce_id); int ret; /* @@ -1105,9 +1119,6 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, } } - /* Enable CE error interrupts */ - ath10k_ce_error_intr_enable(ar, ctrl_addr); - out: ath10k_pci_sleep(ar); return ce_state; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 67dbde6a5c74..8a58bac958a1 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -235,6 +235,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state); void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_disable_interrupts(struct ath10k *ar); +int ath10k_ce_enable_err_irq(struct ath10k *ar); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0b897269f129..e552770a9e6d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1786,18 +1786,6 @@ static int ath10k_pci_ce_init(struct ath10k *ar) pipe_info->buf_sz = (size_t) (attr->src_sz_max); } - /* - * Initially, establish CE completion handlers for use with BMI. - * These are overwritten with generic handlers after we exit BMI phase. - */ - pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; - ath10k_ce_send_cb_register(pipe_info->ce_hdl, - ath10k_pci_bmi_send_done, 0); - - pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST]; - ath10k_ce_recv_cb_register(pipe_info->ce_hdl, - ath10k_pci_bmi_recv_data); - return 0; } @@ -1830,17 +1818,27 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar) ath10k_pci_sleep(ar); } +static void ath10k_pci_start_bmi(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_pipe *pipe; + + /* + * Initially, establish CE completion handlers for use with BMI. + * These are overwritten with generic handlers after we exit BMI phase. + */ + pipe = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; + ath10k_ce_send_cb_register(pipe->ce_hdl, ath10k_pci_bmi_send_done, 0); + + pipe = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST]; + ath10k_ce_recv_cb_register(pipe->ce_hdl, ath10k_pci_bmi_recv_data); +} + static int ath10k_pci_hif_power_up(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - ret = ath10k_pci_start_intr(ar); - if (ret) { - ath10k_err("could not start interrupt handling (%d)\n", ret); - goto err; - } - /* * Bring the target up cleanly. * @@ -1854,13 +1852,9 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ret = ath10k_pci_device_reset(ar); if (ret) { ath10k_err("failed to reset target: %d\n", ret); - goto err_irq; + goto err; } - ret = ath10k_pci_wait_for_target_init(ar); - if (ret) - goto err_irq; - if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) /* Force AWAKE forever */ ath10k_do_pci_wake(ar); @@ -1869,25 +1863,54 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) if (ret) goto err_ps; - ret = ath10k_pci_init_config(ar); - if (ret) + ret = ath10k_ce_disable_interrupts(ar); + if (ret) { + ath10k_err("failed to disable CE interrupts: %d\n", ret); + goto err_ce; + } + + ret = ath10k_pci_start_intr(ar); + if (ret) { + ath10k_err("failed to start interrupt handling: %d\n", ret); goto err_ce; + } + + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) { + ath10k_err("failed to wait for target to init: %d\n", ret); + goto err_irq; + } + + ret = ath10k_ce_enable_err_irq(ar); + if (ret) { + ath10k_err("failed to enable CE error irq: %d\n", ret); + goto err_irq; + } + + ret = ath10k_pci_init_config(ar); + if (ret) { + ath10k_err("failed to setup init config: %d\n", ret); + goto err_irq; + } ret = ath10k_pci_wake_target_cpu(ar); if (ret) { ath10k_err("could not wake up target CPU (%d)\n", ret); - goto err_ce; + goto err_irq; } + ath10k_pci_start_bmi(ar); return 0; +err_irq: + ath10k_ce_disable_interrupts(ar); + ath10k_pci_stop_intr(ar); + ath10k_pci_kill_tasklet(ar); err_ce: ath10k_pci_ce_deinit(ar); err_ps: if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) ath10k_do_pci_sleep(ar); -err_irq: - ath10k_pci_stop_intr(ar); err: return ret; } @@ -2156,7 +2179,7 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) if (ret < 0) return ret; - ret = ath10k_do_pci_wake(ar); + ret = ath10k_pci_wake(ar); if (ret) { free_irq(ar_pci->pdev->irq, ar); ath10k_err("failed to wake up target: %d\n", ret); @@ -2176,7 +2199,7 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) ar_pci->mem + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); - ath10k_do_pci_sleep(ar); + ath10k_pci_sleep(ar); ath10k_info("legacy interrupt handling\n"); return 0; } @@ -2252,7 +2275,7 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) int wait_limit = 300; /* 3 sec */ int ret; - ret = ath10k_do_pci_wake(ar); + ret = ath10k_pci_wake(ar); if (ret) { ath10k_err("failed to wake up target: %d\n", ret); return ret; @@ -2277,7 +2300,7 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) } out: - ath10k_do_pci_sleep(ar); + ath10k_pci_sleep(ar); return ret; } -- cgit v1.2.3 From 1d2b48d6174efb216012ec7cae7ddc653871543f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:34 +0100 Subject: ath10k: add and fix some PCI prints Add missing error reporting and adjust other prints to make everything more consistent. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 69 ++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index e552770a9e6d..eaa99561dab3 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -712,7 +712,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id, flags); if (ret) - ath10k_warn("CE send failed: %p\n", nbuf); + ath10k_warn("failed to send sk_buff to CE: %p\n", nbuf); return ret; } @@ -739,9 +739,10 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar) ar->fw_version_build); host_addr = host_interest_item_address(HI_ITEM(hi_failure_state)); - if (ath10k_pci_diag_read_mem(ar, host_addr, - ®_dump_area, sizeof(u32)) != 0) { - ath10k_warn("could not read hi_failure_state\n"); + ret = ath10k_pci_diag_read_mem(ar, host_addr, + ®_dump_area, sizeof(u32)); + if (ret) { + ath10k_err("failed to read FW dump area address: %d\n", ret); return; } @@ -751,7 +752,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar) ®_dump_values[0], REG_DUMP_COUNT_QCA988X * sizeof(u32)); if (ret != 0) { - ath10k_err("could not dump FW Dump Area\n"); + ath10k_err("failed to read FW dump area: %d\n", ret); return; } @@ -973,8 +974,8 @@ static void ath10k_pci_process_ce(struct ath10k *ar) case ATH10K_PCI_COMPL_RECV: ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1); if (ret) { - ath10k_warn("Unable to post recv buffer for pipe: %d\n", - compl->pipe_info->pipe_num); + ath10k_warn("failed to post RX buffer for pipe %d: %d\n", + compl->pipe_info->pipe_num, ret); break; } @@ -1113,7 +1114,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, for (i = 0; i < num; i++) { skb = dev_alloc_skb(pipe_info->buf_sz); if (!skb) { - ath10k_warn("could not allocate skbuff for pipe %d\n", + ath10k_warn("failed to allocate skbuff for pipe %d\n", num); ret = -ENOMEM; goto err; @@ -1126,7 +1127,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(ar->dev, ce_data))) { - ath10k_warn("could not dma map skbuff\n"); + ath10k_warn("failed to DMA map sk_buff\n"); dev_kfree_skb_any(skb); ret = -EIO; goto err; @@ -1141,7 +1142,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, ret = ath10k_ce_recv_buf_enqueue(ce_state, (void *)skb, ce_data); if (ret) { - ath10k_warn("could not enqueue to pipe %d (%d)\n", + ath10k_warn("failed to enqueue to pipe %d: %d\n", num, ret); goto err; } @@ -1171,8 +1172,8 @@ static int ath10k_pci_post_rx(struct ath10k *ar) ret = ath10k_pci_post_rx_pipe(pipe_info, attr->dest_nentries - 1); if (ret) { - ath10k_warn("Unable to replenish recv buffers for pipe: %d\n", - pipe_num); + ath10k_warn("failed to post RX buffer for pipe %d: %d\n", + pipe_num, ret); for (; pipe_num >= 0; pipe_num--) { pipe_info = &ar_pci->pipe_info[pipe_num]; @@ -1192,14 +1193,15 @@ static int ath10k_pci_hif_start(struct ath10k *ar) ret = ath10k_pci_start_ce(ar); if (ret) { - ath10k_warn("could not start CE (%d)\n", ret); + ath10k_warn("failed to start CE: %d\n", ret); return ret; } /* Post buffers once to start things off. */ ret = ath10k_pci_post_rx(ar); if (ret) { - ath10k_warn("could not post rx pipes (%d)\n", ret); + ath10k_warn("failed to post RX buffers for all pipes: %d\n", + ret); return ret; } @@ -1593,7 +1595,7 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar) CORE_CTRL_ADDRESS, &core_ctrl); if (ret) { - ath10k_warn("Unable to read core ctrl\n"); + ath10k_warn("failed to read core_ctrl: %d\n", ret); return ret; } @@ -1603,10 +1605,13 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar) ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS, core_ctrl); - if (ret) - ath10k_warn("Unable to set interrupt mask\n"); + if (ret) { + ath10k_warn("failed to set target CPU interrupt mask: %d\n", + ret); + return ret; + } - return ret; + return 0; } static int ath10k_pci_init_config(struct ath10k *ar) @@ -1765,7 +1770,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar) pipe_info->ce_hdl = ath10k_ce_init(ar, pipe_num, attr); if (pipe_info->ce_hdl == NULL) { - ath10k_err("Unable to initialize CE for pipe: %d\n", + ath10k_err("failed to initialize CE for pipe: %d\n", pipe_num); /* It is safe to call it here. It checks if ce_hdl is @@ -1832,6 +1837,8 @@ static void ath10k_pci_start_bmi(struct ath10k *ar) pipe = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST]; ath10k_ce_recv_cb_register(pipe->ce_hdl, ath10k_pci_bmi_recv_data); + + ath10k_dbg(ATH10K_DBG_BOOT, "boot start bmi\n"); } static int ath10k_pci_hif_power_up(struct ath10k *ar) @@ -1860,8 +1867,10 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ath10k_do_pci_wake(ar); ret = ath10k_pci_ce_init(ar); - if (ret) + if (ret) { + ath10k_err("failed to initialize CE: %d\n", ret); goto err_ps; + } ret = ath10k_ce_disable_interrupts(ar); if (ret) { @@ -1895,7 +1904,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ret = ath10k_pci_wake_target_cpu(ar); if (ret) { - ath10k_err("could not wake up target CPU (%d)\n", ret); + ath10k_err("could not wake up target CPU: %d\n", ret); goto err_irq; } @@ -2397,7 +2406,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops); if (!ar) { - ath10k_err("ath10k_core_create failed!\n"); + ath10k_err("failed to create driver core\n"); ret = -EINVAL; goto err_ar_pci; } @@ -2416,20 +2425,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev, */ ret = pci_assign_resource(pdev, BAR_NUM); if (ret) { - ath10k_err("cannot assign PCI space: %d\n", ret); + ath10k_err("failed to assign PCI space: %d\n", ret); goto err_ar; } ret = pci_enable_device(pdev); if (ret) { - ath10k_err("cannot enable PCI device: %d\n", ret); + ath10k_err("failed to enable PCI device: %d\n", ret); goto err_ar; } /* Request MMIO resources */ ret = pci_request_region(pdev, BAR_NUM, "ath"); if (ret) { - ath10k_err("PCI MMIO reservation error: %d\n", ret); + ath10k_err("failed to request MMIO region: %d\n", ret); goto err_device; } @@ -2439,13 +2448,13 @@ static int ath10k_pci_probe(struct pci_dev *pdev, */ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret) { - ath10k_err("32-bit DMA not available: %d\n", ret); + ath10k_err("failed to set DMA mask to 32-bit: %d\n", ret); goto err_region; } ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret) { - ath10k_err("cannot enable 32-bit consistent DMA\n"); + ath10k_err("failed to set consistent DMA mask to 32-bit\n"); goto err_region; } @@ -2462,7 +2471,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, /* Arrange for access to Target SoC registers. */ mem = pci_iomap(pdev, BAR_NUM, 0); if (!mem) { - ath10k_err("PCI iomap error\n"); + ath10k_err("failed to perform IOMAP for BAR%d\n", BAR_NUM); ret = -EIO; goto err_master; } @@ -2485,7 +2494,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ret = ath10k_core_register(ar, chip_id); if (ret) { - ath10k_err("could not register driver core (%d)\n", ret); + ath10k_err("failed to register driver core: %d\n", ret); goto err_iomap; } @@ -2551,7 +2560,7 @@ static int __init ath10k_pci_init(void) ret = pci_register_driver(&ath10k_pci_driver); if (ret) - ath10k_err("pci_register_driver failed [%d]\n", ret); + ath10k_err("failed to register PCI driver: %d\n", ret); return ret; } -- cgit v1.2.3 From 6a42a47e23acdcbc97aac925b5a14d1b187606cf Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:01:35 +0100 Subject: ath10k: reset device upon stopping/power down This should make sure the device won't issue any interrupts nor access any memory after the driver is stopped/freed thus avoid memory corruption in some cases. Reported-By: Ben Greear Reported-By: Janusz Dziedzic Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index eaa99561dab3..46c94ce58f97 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1353,6 +1353,13 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_pci_cleanup_ce(ar); ath10k_pci_buffer_cleanup(ar); + /* Make the sure the device won't access any structures on the host by + * resetting it. The device was fed with PCI CE ringbuffer + * configuration during init. If ringbuffers are freed and the device + * were to access them this could lead to memory corruption on the + * host. */ + ath10k_pci_device_reset(ar); + ar_pci->started = 0; } @@ -1915,6 +1922,7 @@ err_irq: ath10k_ce_disable_interrupts(ar); ath10k_pci_stop_intr(ar); ath10k_pci_kill_tasklet(ar); + ath10k_pci_device_reset(ar); err_ce: ath10k_pci_ce_deinit(ar); err_ps: @@ -1929,6 +1937,7 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); ath10k_pci_stop_intr(ar); + ath10k_pci_device_reset(ar); ath10k_pci_ce_deinit(ar); if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) -- cgit v1.2.3 From 67e3c63fef6041f41e22335852de9d3924cff7a1 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Nov 2013 08:05:18 +0100 Subject: ath10k: fix core init failpath HIF was not stopped properly in ath10k_core_start() upon failure. This could cause memory leaks of CE completions entries and possibly other issues as well. Move the HIF start/stop out of ath10k_htc_wait_target(). The ctl_resp completion is already prepared in ath10k_htc_init. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 16 +++++++++++++--- drivers/net/wireless/ath/ath10k/htc.c | 26 +++++--------------------- 2 files changed, 18 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7d8687694360..be5b17e89902 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -785,14 +785,22 @@ int ath10k_core_start(struct ath10k *ar) goto err; } - status = ath10k_htc_wait_target(&ar->htc); - if (status) + status = ath10k_hif_start(ar); + if (status) { + ath10k_err("could not start HIF: %d\n", status); goto err_wmi_detach; + } + + status = ath10k_htc_wait_target(&ar->htc); + if (status) { + ath10k_err("failed to connect to HTC: %d\n", status); + goto err_hif_stop; + } status = ath10k_htt_attach(ar); if (status) { ath10k_err("could not attach htt (%d)\n", status); - goto err_wmi_detach; + goto err_hif_stop; } status = ath10k_init_connect_htc(ar); @@ -831,6 +839,8 @@ err_disconnect_htc: ath10k_htc_stop(&ar->htc); err_htt_detach: ath10k_htt_detach(&ar->htt); +err_hif_stop: + ath10k_hif_stop(ar); err_wmi_detach: ath10k_wmi_detach(ar); err: diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 6d7a72eb11a5..b068ae04cf6b 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -539,14 +539,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) u16 credit_count; u16 credit_size; - INIT_COMPLETION(htc->ctl_resp); - - status = ath10k_hif_start(htc->ar); - if (status) { - ath10k_err("could not start HIF (%d)\n", status); - goto err_start; - } - status = wait_for_completion_timeout(&htc->ctl_resp, ATH10K_HTC_WAIT_TIMEOUT_HZ); if (status <= 0) { @@ -554,15 +546,13 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) status = -ETIMEDOUT; ath10k_err("ctl_resp never came in (%d)\n", status); - goto err_target; + return status; } if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) { ath10k_err("Invalid HTC ready msg len:%d\n", htc->control_resp_len); - - status = -ECOMM; - goto err_target; + return -ECOMM; } msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; @@ -572,8 +562,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) if (message_id != ATH10K_HTC_MSG_READY_ID) { ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id); - status = -ECOMM; - goto err_target; + return -ECOMM; } htc->total_transmit_credits = credit_count; @@ -586,9 +575,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) if ((htc->total_transmit_credits == 0) || (htc->target_credit_size == 0)) { - status = -ECOMM; ath10k_err("Invalid credit size received\n"); - goto err_target; + return -ECOMM; } ath10k_htc_setup_target_buffer_assignments(htc); @@ -605,14 +593,10 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp); if (status) { ath10k_err("could not connect to htc service (%d)\n", status); - goto err_target; + return status; } return 0; -err_target: - ath10k_hif_stop(htc->ar); -err_start: - return status; } int ath10k_htc_connect_service(struct ath10k_htc *htc, -- cgit v1.2.3 From db31af1d4e815e141295b0bdf8da3e77885001d5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:53 +0200 Subject: drm/i915: clean up backlight conditional build I've always felt the backlight device conditional build has been all backwards. Make it feel right. Gently move things towards connector based stuff while at it. There should be no functional changes. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 9 +++-- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_panel.c | 65 ++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3cddd508d110..9cb36a42783e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11070,12 +11070,11 @@ void intel_modeset_cleanup(struct drm_device *dev) /* flush any delayed tasks or pending work */ flush_scheduled_work(); - /* destroy backlight, if any, before the connectors */ - intel_panel_destroy_backlight(dev); - - /* destroy the sysfs files before encoders/connectors */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) + /* destroy the backlight and sysfs files before encoders/connectors */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + intel_panel_destroy_backlight(connector); drm_sysfs_connector_remove(connector); + } drm_mode_config_cleanup(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1e49aa8f5377..5548180e5558 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -808,7 +808,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, int intel_panel_setup_backlight(struct drm_connector *connector); void intel_panel_enable_backlight(struct intel_connector *connector); void intel_panel_disable_backlight(struct intel_connector *connector); -void intel_panel_destroy_backlight(struct drm_device *dev); +void intel_panel_destroy_backlight(struct drm_connector *connector); enum drm_connector_status intel_panel_detect(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac02c4f6..a0d13d3173ee 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -709,16 +709,6 @@ static void intel_panel_init_backlight_regs(struct drm_device *dev) } } -static void intel_panel_init_backlight(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - intel_panel_init_backlight_regs(dev); - - dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); - dev_priv->backlight.enabled = dev_priv->backlight.level != 0; -} - enum drm_connector_status intel_panel_detect(struct drm_device *dev) { @@ -742,7 +732,7 @@ intel_panel_detect(struct drm_device *dev) } #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) -static int intel_panel_update_status(struct backlight_device *bd) +static int intel_backlight_device_update_status(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; @@ -756,7 +746,7 @@ static int intel_panel_update_status(struct backlight_device *bd) return 0; } -static int intel_panel_get_brightness(struct backlight_device *bd) +static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; @@ -771,20 +761,18 @@ static int intel_panel_get_brightness(struct backlight_device *bd) return intel_panel_get_backlight(connector->base.dev, pipe); } -static const struct backlight_ops intel_panel_bl_ops = { - .update_status = intel_panel_update_status, - .get_brightness = intel_panel_get_brightness, +static const struct backlight_ops intel_backlight_device_ops = { + .update_status = intel_backlight_device_update_status, + .get_brightness = intel_backlight_device_get_brightness, }; -int intel_panel_setup_backlight(struct drm_connector *connector) +static int intel_backlight_device_register(struct intel_connector *connector) { - struct drm_device *dev = connector->dev; + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct backlight_properties props; unsigned long flags; - intel_panel_init_backlight(dev); - if (WARN_ON(dev_priv->backlight.device)) return -ENODEV; @@ -802,9 +790,9 @@ int intel_panel_setup_backlight(struct drm_connector *connector) } dev_priv->backlight.device = backlight_device_register("intel_backlight", - connector->kdev, - to_intel_connector(connector), - &intel_panel_bl_ops, &props); + connector->base.kdev, + connector, + &intel_backlight_device_ops, &props); if (IS_ERR(dev_priv->backlight.device)) { DRM_ERROR("Failed to register backlight: %ld\n", @@ -815,26 +803,47 @@ int intel_panel_setup_backlight(struct drm_connector *connector) return 0; } -void intel_panel_destroy_backlight(struct drm_device *dev) +static void intel_backlight_device_unregister(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->backlight.device) { backlight_device_unregister(dev_priv->backlight.device); dev_priv->backlight.device = NULL; } } -#else +#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ +static int intel_backlight_device_register(struct intel_connector *connector) +{ + return 0; +} +static void intel_backlight_device_unregister(struct intel_connector *connector) +{ +} +#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ + int intel_panel_setup_backlight(struct drm_connector *connector) { - intel_panel_init_backlight(connector->dev); + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_connector *intel_connector = to_intel_connector(connector); + + intel_panel_init_backlight_regs(dev); + + dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); + dev_priv->backlight.enabled = dev_priv->backlight.level != 0; + + intel_backlight_device_register(intel_connector); + return 0; } -void intel_panel_destroy_backlight(struct drm_device *dev) +void intel_panel_destroy_backlight(struct drm_connector *connector) { - return; + struct intel_connector *intel_connector = to_intel_connector(connector); + + intel_backlight_device_unregister(intel_connector); } -#endif int intel_panel_init(struct intel_panel *panel, struct drm_display_mode *fixed_mode) -- cgit v1.2.3 From 58c68779e48fa6d60b97fadc3dcac61a6c318c4c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:54 +0200 Subject: drm/i915: make backlight info per-connector Move from dev_priv to connector->panel. We still don't allow multiple sysfs interfaces, though. There should be no functional changes, except for a slight reordering of connector backlight and sysfs destroy calls. (This change happens now that the backlight device is actually per-connector, even though the destroy calls became per-connector earlier.) Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 9 +--- drivers/gpu/drm/i915/i915_suspend.c | 8 ++-- drivers/gpu/drm/i915/intel_drv.h | 7 +++ drivers/gpu/drm/i915/intel_panel.c | 85 ++++++++++++++++++++----------------- 5 files changed, 61 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d045135..9a2a17507df4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1486,7 +1486,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); - spin_lock_init(&dev_priv->backlight.lock); + spin_lock_init(&dev_priv->backlight_lock); spin_lock_init(&dev_priv->uncore.lock); spin_lock_init(&dev_priv->mm.object_stat_lock); mutex_init(&dev_priv->dpio_lock); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8600c315b4c4..a2009bff2f36 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1368,13 +1368,8 @@ typedef struct drm_i915_private { struct intel_overlay *overlay; unsigned int sprite_scaling_enabled; - /* backlight */ - struct { - int level; - bool enabled; - spinlock_t lock; /* bl registers and the above bl fields */ - struct backlight_device *device; - } backlight; + /* backlight registers and fields in struct intel_panel */ + spinlock_t backlight_lock; /* LVDS info */ bool no_aux_handshake; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 98790c7cccb1..eadf8e19d2c4 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -203,7 +203,7 @@ static void i915_save_display(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_save_display_reg(dev); - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); /* LVDS state */ if (HAS_PCH_SPLIT(dev)) { @@ -241,7 +241,7 @@ static void i915_save_display(struct drm_device *dev) dev_priv->regfile.saveLVDS = I915_READ(LVDS); } - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev)) dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL); @@ -287,7 +287,7 @@ static void i915_restore_display(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_restore_display_reg(dev); - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); /* LVDS state */ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) @@ -341,7 +341,7 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL); } - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); /* only restore FBC info on the platform that supports FBC*/ intel_disable_fbc(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5548180e5558..9460e54cf140 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -156,6 +156,13 @@ struct intel_encoder { struct intel_panel { struct drm_display_mode *fixed_mode; int fitting_mode; + + /* backlight */ + struct { + u32 level; + bool enabled; + struct backlight_device *device; + } backlight; }; struct intel_connector { diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a0d13d3173ee..0a4aeaf96865 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -346,7 +346,7 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) struct drm_i915_private *dev_priv = dev->dev_private; u32 val; - WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock)); + WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock)); /* Restore the CTL value if it lost, e.g. GPU reset */ @@ -449,7 +449,7 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, unsigned long flags; int reg; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); if (HAS_PCH_SPLIT(dev)) { val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; @@ -473,7 +473,7 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, val = intel_panel_compute_brightness(dev, pipe, val); - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); return val; @@ -530,6 +530,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 freq; unsigned long flags; @@ -537,7 +538,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, if (pipe == INVALID_PIPE) return; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); freq = intel_panel_get_max_backlight(dev, pipe); if (!freq) { @@ -551,20 +552,21 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, else level = freq / max * level; - dev_priv->backlight.level = level; - if (dev_priv->backlight.device) - dev_priv->backlight.device->props.brightness = level; + panel->backlight.level = level; + if (panel->backlight.device) + panel->backlight.device->props.brightness = level; - if (dev_priv->backlight.enabled) + if (panel->backlight.enabled) intel_panel_actually_set_backlight(dev, pipe, level); out: - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); unsigned long flags; @@ -582,9 +584,9 @@ void intel_panel_disable_backlight(struct intel_connector *connector) return; } - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); - dev_priv->backlight.enabled = false; + panel->backlight.enabled = false; intel_panel_actually_set_backlight(dev, pipe, 0); if (INTEL_INFO(dev)->gen >= 4) { @@ -606,13 +608,14 @@ void intel_panel_disable_backlight(struct intel_connector *connector) } } - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } void intel_panel_enable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); @@ -623,14 +626,14 @@ void intel_panel_enable_backlight(struct intel_connector *connector) DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); - if (dev_priv->backlight.level == 0) { - dev_priv->backlight.level = intel_panel_get_max_backlight(dev, - pipe); - if (dev_priv->backlight.device) - dev_priv->backlight.device->props.brightness = - dev_priv->backlight.level; + if (panel->backlight.level == 0) { + panel->backlight.level = intel_panel_get_max_backlight(dev, + pipe); + if (panel->backlight.device) + panel->backlight.device->props.brightness = + panel->backlight.level; } if (INTEL_INFO(dev)->gen >= 4) { @@ -680,11 +683,11 @@ set_level: * BLC_PWM_CPU_CTL may be cleared to zero automatically when these * registers are set. */ - dev_priv->backlight.enabled = true; + panel->backlight.enabled = true; intel_panel_actually_set_backlight(dev, pipe, - dev_priv->backlight.level); + panel->backlight.level); - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } /* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */ @@ -770,34 +773,40 @@ static int intel_backlight_device_register(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; struct backlight_properties props; unsigned long flags; - if (WARN_ON(dev_priv->backlight.device)) + if (WARN_ON(panel->backlight.device)) return -ENODEV; memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; - props.brightness = dev_priv->backlight.level; + props.brightness = panel->backlight.level; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); + spin_lock_irqsave(&dev_priv->backlight_lock, flags); props.max_brightness = intel_panel_get_max_backlight(dev, 0); - spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); if (props.max_brightness == 0) { DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); return -ENODEV; } - dev_priv->backlight.device = + + /* + * Note: using the same name independent of the connector prevents + * registration of multiple backlight devices in the driver. + */ + panel->backlight.device = backlight_device_register("intel_backlight", connector->base.kdev, connector, &intel_backlight_device_ops, &props); - if (IS_ERR(dev_priv->backlight.device)) { + if (IS_ERR(panel->backlight.device)) { DRM_ERROR("Failed to register backlight: %ld\n", - PTR_ERR(dev_priv->backlight.device)); - dev_priv->backlight.device = NULL; + PTR_ERR(panel->backlight.device)); + panel->backlight.device = NULL; return -ENODEV; } return 0; @@ -805,11 +814,11 @@ static int intel_backlight_device_register(struct intel_connector *connector) static void intel_backlight_device_unregister(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->backlight.device) { - backlight_device_unregister(dev_priv->backlight.device); - dev_priv->backlight.device = NULL; + struct intel_panel *panel = &connector->panel; + + if (panel->backlight.device) { + backlight_device_unregister(panel->backlight.device); + panel->backlight.device = NULL; } } #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ @@ -825,13 +834,13 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) int intel_panel_setup_backlight(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_panel *panel = &intel_connector->panel; intel_panel_init_backlight_regs(dev); - dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); - dev_priv->backlight.enabled = dev_priv->backlight.level != 0; + panel->backlight.level = intel_panel_get_backlight(dev, 0); + panel->backlight.enabled = panel->backlight.level != 0; intel_backlight_device_register(intel_connector); -- cgit v1.2.3 From c91c9f32843a1b433de5a1ead4789a6bc8d3d914 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:55 +0200 Subject: drm/i915: make asle notifications update backlight on all connectors ALthough usually there's only one connector that supports backlight, this also finds the correct connector. Before, we only updated the connector on pipe A, which might not be the one with backlight. (This only made a difference on BYT.) Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_opregion.c | 43 +++++++++++------------------------ drivers/gpu/drm/i915/intel_panel.c | 4 ++++ 3 files changed, 18 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9460e54cf140..bcb47b83787d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -159,6 +159,7 @@ struct intel_panel { /* backlight */ struct { + bool present; u32 level; bool enabled; struct backlight_device *device; diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 91b68dca0641..a0b5a99204a8 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -396,13 +396,10 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_encoder *encoder; struct drm_connector *connector; - struct intel_connector *intel_connector = NULL; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; + struct intel_connector *intel_connector; + struct intel_panel *panel; struct opregion_asle __iomem *asle = dev_priv->opregion.asle; - u32 ret = 0; - bool found = false; DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); @@ -414,38 +411,24 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) return ASLC_BACKLIGHT_FAILED; mutex_lock(&dev->mode_config.mutex); + /* - * Could match the OpRegion connector here instead, but we'd also need - * to verify the connector could handle a backlight call. + * Update backlight on all connectors that support backlight (usually + * only one). */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->crtc == crtc) { - found = true; - break; - } - - if (!found) { - ret = ASLC_BACKLIGHT_FAILED; - goto out; - } - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - if (connector->encoder == encoder) - intel_connector = to_intel_connector(connector); - - if (!intel_connector) { - ret = ASLC_BACKLIGHT_FAILED; - goto out; - } - DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); - intel_panel_set_backlight(intel_connector, bclp, 255); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + intel_connector = to_intel_connector(connector); + panel = &intel_connector->panel; + if (panel->backlight.present) + intel_panel_set_backlight(intel_connector, bclp, 255); + } iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv); -out: mutex_unlock(&dev->mode_config.mutex); - return ret; + + return 0; } static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 0a4aeaf96865..c80bffc21b5b 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -844,13 +844,17 @@ int intel_panel_setup_backlight(struct drm_connector *connector) intel_backlight_device_register(intel_connector); + panel->backlight.present = true; + return 0; } void intel_panel_destroy_backlight(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_panel *panel = &intel_connector->panel; + panel->backlight.present = false; intel_backlight_device_unregister(intel_connector); } -- cgit v1.2.3 From 7bd688cd66db93f6430f6e2b3145ee5686daa315 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:56 +0200 Subject: drm/i915: handle backlight through chip specific functions The backlight code has grown rather hairy, not least because the hardware registers and bits have repeatedly been shuffled around. And this isn't expected to get any easier with new hardware. Make things easier for our (read: my) poor brains, and split the code up into chip specific functions. There should be no functional changes. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 9 + drivers/gpu/drm/i915/intel_display.c | 2 + drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_panel.c | 642 +++++++++++++++++++++++------------ 4 files changed, 447 insertions(+), 208 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a2009bff2f36..c243b8e954a0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -351,6 +351,7 @@ struct drm_i915_error_state { enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS]; }; +struct intel_connector; struct intel_crtc_config; struct intel_crtc; struct intel_limit; @@ -413,6 +414,14 @@ struct drm_i915_display_funcs { /* render clock increase/decrease */ /* display clock increase/decrease */ /* pll clock increase/decrease */ + + int (*setup_backlight)(struct intel_connector *connector); + uint32_t (*get_max_backlight)(struct intel_connector *connector); + uint32_t (*get_backlight)(struct intel_connector *connector); + void (*set_backlight)(struct intel_connector *connector, + uint32_t level); + void (*disable_backlight)(struct intel_connector *connector); + void (*enable_backlight)(struct intel_connector *connector); }; struct intel_uncore_funcs { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9cb36a42783e..25ef080d1bc2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10418,6 +10418,8 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.queue_flip = intel_gen7_queue_flip; break; } + + intel_panel_init_backlight_funcs(dev); } /* diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bcb47b83787d..819d0d2f0142 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -161,6 +161,7 @@ struct intel_panel { struct { bool present; u32 level; + u32 max; bool enabled; struct backlight_device *device; } backlight; @@ -817,6 +818,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector); void intel_panel_enable_backlight(struct intel_connector *connector); void intel_panel_disable_backlight(struct intel_connector *connector); void intel_panel_destroy_backlight(struct drm_connector *connector); +void intel_panel_init_backlight_funcs(struct drm_device *dev); enum drm_connector_status intel_panel_detect(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index c80bffc21b5b..a821949a9c7a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -338,79 +338,117 @@ static int is_backlight_combination_mode(struct drm_device *dev) return 0; } -/* XXX: query mode clock or hardware clock and program max PWM appropriately - * when it's 0. - */ -static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) +static u32 pch_get_max_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val; - WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock)); + val = I915_READ(BLC_PWM_PCH_CTL2); + if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { + dev_priv->regfile.saveBLC_PWM_CTL2 = val; + } else if (val == 0) { + val = dev_priv->regfile.saveBLC_PWM_CTL2; + I915_WRITE(BLC_PWM_PCH_CTL2, val); + } - /* Restore the CTL value if it lost, e.g. GPU reset */ + val >>= 16; - if (HAS_PCH_SPLIT(dev_priv->dev)) { - val = I915_READ(BLC_PWM_PCH_CTL2); - if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { - dev_priv->regfile.saveBLC_PWM_CTL2 = val; - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL2; - I915_WRITE(BLC_PWM_PCH_CTL2, val); - } - } else if (IS_VALLEYVIEW(dev)) { - val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(pipe)); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), - dev_priv->regfile.saveBLC_PWM_CTL2); - } + return val; +} - if (!val) - val = 0x0f42ffff; - } else { - val = I915_READ(BLC_PWM_CTL); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - if (INTEL_INFO(dev)->gen >= 4) - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(BLC_PWM_CTL2); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(BLC_PWM_CTL, val); - if (INTEL_INFO(dev)->gen >= 4) - I915_WRITE(BLC_PWM_CTL2, - dev_priv->regfile.saveBLC_PWM_CTL2); - } +static u32 i9xx_get_max_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + val = I915_READ(BLC_PWM_CTL); + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { + dev_priv->regfile.saveBLC_PWM_CTL = val; + } else if (val == 0) { + val = dev_priv->regfile.saveBLC_PWM_CTL; + I915_WRITE(BLC_PWM_CTL, val); } + val >>= 17; + + if (is_backlight_combination_mode(dev)) + val *= 0xff; + return val; } -static u32 intel_panel_get_max_backlight(struct drm_device *dev, - enum pipe pipe) +static u32 i965_get_max_backlight(struct intel_connector *connector) { - u32 max; + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + val = I915_READ(BLC_PWM_CTL); + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { + dev_priv->regfile.saveBLC_PWM_CTL = val; + dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); + } else if (val == 0) { + val = dev_priv->regfile.saveBLC_PWM_CTL; + I915_WRITE(BLC_PWM_CTL, val); + I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); + } - max = i915_read_blc_pwm_ctl(dev, pipe); + val >>= 16; - if (HAS_PCH_SPLIT(dev)) { - max >>= 16; - } else { - if (INTEL_INFO(dev)->gen < 4) - max >>= 17; - else - max >>= 16; + if (is_backlight_combination_mode(dev)) + val *= 0xff; + + return val; +} + +static u32 _vlv_get_max_backlight(struct drm_device *dev, enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; - if (is_backlight_combination_mode(dev)) - max *= 0xff; + val = I915_READ(VLV_BLC_PWM_CTL(pipe)); + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { + dev_priv->regfile.saveBLC_PWM_CTL = val; + dev_priv->regfile.saveBLC_PWM_CTL2 = + I915_READ(VLV_BLC_PWM_CTL2(pipe)); + } else if (val == 0) { + val = dev_priv->regfile.saveBLC_PWM_CTL; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), + dev_priv->regfile.saveBLC_PWM_CTL2); } + if (!val) + val = 0x0f42ffff; + + val >>= 16; + + return val; +} + +static u32 vlv_get_max_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + enum pipe pipe = intel_get_pipe_from_connector(connector); + + return _vlv_get_max_backlight(dev, pipe); +} + +/* XXX: query mode clock or hardware clock and program max PWM appropriately + * when it's 0. + */ +static u32 intel_panel_get_max_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 max; + + WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock)); + + max = dev_priv->display.get_max_backlight(connector); + DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); return max; @@ -423,9 +461,10 @@ MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "to dri-devel@lists.freedesktop.org, if your machine needs it. " "It will then be included in an upcoming module version."); module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); -static u32 intel_panel_compute_brightness(struct drm_device *dev, - enum pipe pipe, u32 val) +static u32 intel_panel_compute_brightness(struct intel_connector *connector, + u32 val) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; if (i915_panel_invert_brightness < 0) @@ -433,7 +472,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, if (i915_panel_invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { - u32 max = intel_panel_get_max_backlight(dev, pipe); + u32 max = intel_panel_get_max_backlight(connector); if (max) return max - val; } @@ -441,37 +480,60 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, return val; } -static u32 intel_panel_get_backlight(struct drm_device *dev, - enum pipe pipe) +static u32 pch_get_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - unsigned long flags; - int reg; - spin_lock_irqsave(&dev_priv->backlight_lock, flags); + return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; +} - if (HAS_PCH_SPLIT(dev)) { - val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - } else { - if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL(pipe); - else - reg = BLC_PWM_CTL; +static u32 i9xx_get_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; - val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK; - if (INTEL_INFO(dev)->gen < 4) - val >>= 1; + val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + if (INTEL_INFO(dev)->gen < 4) + val >>= 1; - if (is_backlight_combination_mode(dev)) { - u8 lbpc; + if (is_backlight_combination_mode(dev)) { + u8 lbpc; - pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); - val *= lbpc; - } + pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); + val *= lbpc; } - val = intel_panel_compute_brightness(dev, pipe, val); + return val; +} + +static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; +} + +static u32 vlv_get_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + enum pipe pipe = intel_get_pipe_from_connector(connector); + + return _vlv_get_backlight(dev, pipe); +} + +static u32 intel_panel_get_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->backlight_lock, flags); + + val = dev_priv->display.get_backlight(connector); + val = intel_panel_compute_brightness(connector, val); spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); @@ -479,28 +541,24 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, return val; } -static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) +static void pch_set_backlight(struct intel_connector *connector, u32 level) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(BLC_PWM_CPU_CTL, val | level); + u32 tmp; + + tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); } -static void intel_panel_actually_set_backlight(struct drm_device *dev, - enum pipe pipe, u32 level) +static void i9xx_set_backlight(struct intel_connector *connector, u32 level) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp; - int reg; - - DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); - level = intel_panel_compute_brightness(dev, pipe, level); - - if (HAS_PCH_SPLIT(dev)) - return intel_pch_panel_set_backlight(dev, level); if (is_backlight_combination_mode(dev)) { - u32 max = intel_panel_get_max_backlight(dev, pipe); + u32 max = intel_panel_get_max_backlight(connector); u8 lbpc; /* we're screwed, but keep behaviour backwards compatible */ @@ -512,16 +570,34 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); } - if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL(pipe); - else - reg = BLC_PWM_CTL; - - tmp = I915_READ(reg); if (INTEL_INFO(dev)->gen < 4) level <<= 1; - tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(reg, tmp | level); + + tmp = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_CTL, tmp | level); +} + +static void vlv_set_backlight(struct intel_connector *connector, u32 level) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 tmp; + + tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); +} + +static void +intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); + + level = intel_panel_compute_brightness(connector, level); + dev_priv->display.set_backlight(connector, level); } /* set backlight brightness to level in range [0..max] */ @@ -540,7 +616,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, spin_lock_irqsave(&dev_priv->backlight_lock, flags); - freq = intel_panel_get_max_backlight(dev, pipe); + freq = intel_panel_get_max_backlight(connector); if (!freq) { /* we are screwed, bail out */ goto out; @@ -557,11 +633,45 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, panel->backlight.device->props.brightness = level; if (panel->backlight.enabled) - intel_panel_actually_set_backlight(dev, pipe, level); + intel_panel_actually_set_backlight(connector, level); out: spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } +static void pch_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; + + tmp = I915_READ(BLC_PWM_CPU_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); + + tmp = I915_READ(BLC_PWM_PCH_CTL1); + I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); +} + +static void i965_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; + + tmp = I915_READ(BLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); +} + +static void vlv_disable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 tmp; + + tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); +} + void intel_panel_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; @@ -587,28 +697,100 @@ void intel_panel_disable_backlight(struct intel_connector *connector) spin_lock_irqsave(&dev_priv->backlight_lock, flags); panel->backlight.enabled = false; - intel_panel_actually_set_backlight(dev, pipe, 0); + intel_panel_actually_set_backlight(connector, 0); - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg, tmp; + if (dev_priv->display.disable_backlight) + dev_priv->display.disable_backlight(connector); - if (HAS_PCH_SPLIT(dev)) - reg = BLC_PWM_CPU_CTL2; - else if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL2(pipe); - else - reg = BLC_PWM_CTL2; + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); +} - I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); +static void pch_enable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + enum transcoder cpu_transcoder = + intel_pipe_to_cpu_transcoder(dev_priv, pipe); + u32 tmp; - if (HAS_PCH_SPLIT(dev)) { - tmp = I915_READ(BLC_PWM_PCH_CTL1); - tmp &= ~BLM_PCH_PWM_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); - } + tmp = I915_READ(BLC_PWM_CPU_CTL2); + + /* Note that this can also get called through dpms changes. And + * we don't track the backlight dpms state, hence check whether + * we have to do anything first. */ + if (tmp & BLM_PWM_ENABLE) + return; + + if (INTEL_INFO(dev)->num_pipes == 3) + tmp &= ~BLM_PIPE_SELECT_IVB; + else + tmp &= ~BLM_PIPE_SELECT; + + if (cpu_transcoder == TRANSCODER_EDP) + tmp |= BLM_TRANSCODER_EDP; + else + tmp |= BLM_PIPE(cpu_transcoder); + tmp &= ~BLM_PWM_ENABLE; + + I915_WRITE(BLC_PWM_CPU_CTL2, tmp); + POSTING_READ(BLC_PWM_CPU_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL2, tmp | BLM_PWM_ENABLE); + + if (!(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { + tmp = I915_READ(BLC_PWM_PCH_CTL1); + tmp |= BLM_PCH_PWM_ENABLE; + tmp &= ~BLM_PCH_OVERRIDE_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, tmp); } +} - spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); +static void i965_enable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 tmp; + + tmp = I915_READ(BLC_PWM_CTL2); + + /* Note that this can also get called through dpms changes. And + * we don't track the backlight dpms state, hence check whether + * we have to do anything first. */ + if (tmp & BLM_PWM_ENABLE) + return; + + tmp &= ~BLM_PIPE_SELECT; + tmp |= BLM_PIPE(pipe); + tmp &= ~BLM_PWM_ENABLE; + + I915_WRITE(BLC_PWM_CTL2, tmp); + POSTING_READ(BLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL2, tmp | BLM_PWM_ENABLE); +} + +static void vlv_enable_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 tmp; + + tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + + /* Note that this can also get called through dpms changes. And + * we don't track the backlight dpms state, hence check whether + * we have to do anything first. */ + if (tmp & BLM_PWM_ENABLE) + return; + + tmp &= ~BLM_PIPE_SELECT; + tmp |= BLM_PIPE(pipe); + tmp &= ~BLM_PWM_ENABLE; + + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp); + POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp | BLM_PWM_ENABLE); } void intel_panel_enable_backlight(struct intel_connector *connector) @@ -617,8 +799,6 @@ void intel_panel_enable_backlight(struct intel_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); - enum transcoder cpu_transcoder = - intel_pipe_to_cpu_transcoder(dev_priv, pipe); unsigned long flags; if (pipe == INVALID_PIPE) @@ -629,89 +809,25 @@ void intel_panel_enable_backlight(struct intel_connector *connector) spin_lock_irqsave(&dev_priv->backlight_lock, flags); if (panel->backlight.level == 0) { - panel->backlight.level = intel_panel_get_max_backlight(dev, - pipe); + panel->backlight.level = intel_panel_get_max_backlight(connector); if (panel->backlight.device) panel->backlight.device->props.brightness = panel->backlight.level; } - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg, tmp; - - if (HAS_PCH_SPLIT(dev)) - reg = BLC_PWM_CPU_CTL2; - else if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL2(pipe); - else - reg = BLC_PWM_CTL2; - - tmp = I915_READ(reg); - - /* Note that this can also get called through dpms changes. And - * we don't track the backlight dpms state, hence check whether - * we have to do anything first. */ - if (tmp & BLM_PWM_ENABLE) - goto set_level; - - if (INTEL_INFO(dev)->num_pipes == 3) - tmp &= ~BLM_PIPE_SELECT_IVB; - else - tmp &= ~BLM_PIPE_SELECT; - - if (cpu_transcoder == TRANSCODER_EDP) - tmp |= BLM_TRANSCODER_EDP; - else - tmp |= BLM_PIPE(cpu_transcoder); - tmp &= ~BLM_PWM_ENABLE; - - I915_WRITE(reg, tmp); - POSTING_READ(reg); - I915_WRITE(reg, tmp | BLM_PWM_ENABLE); - - if (HAS_PCH_SPLIT(dev) && - !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { - tmp = I915_READ(BLC_PWM_PCH_CTL1); - tmp |= BLM_PCH_PWM_ENABLE; - tmp &= ~BLM_PCH_OVERRIDE_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); - } - } + if (dev_priv->display.enable_backlight) + dev_priv->display.enable_backlight(connector); -set_level: /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. * BLC_PWM_CPU_CTL may be cleared to zero automatically when these * registers are set. */ panel->backlight.enabled = true; - intel_panel_actually_set_backlight(dev, pipe, - panel->backlight.level); + intel_panel_actually_set_backlight(connector, panel->backlight.level); spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } -/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */ -static void intel_panel_init_backlight_regs(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (IS_VALLEYVIEW(dev)) { - enum pipe pipe; - - for_each_pipe(pipe) { - u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - - /* Skip if the modulation freq is already set */ - if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) - continue; - - cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | - cur_val); - } - } -} - enum drm_connector_status intel_panel_detect(struct drm_device *dev) { @@ -753,15 +869,13 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; - enum pipe pipe; + int ret; mutex_lock(&dev->mode_config.mutex); - pipe = intel_get_pipe_from_connector(connector); + ret = intel_panel_get_backlight(connector); mutex_unlock(&dev->mode_config.mutex); - if (pipe == INVALID_PIPE) - return 0; - return intel_panel_get_backlight(connector->base.dev, pipe); + return ret; } static const struct backlight_ops intel_backlight_device_ops = { @@ -771,27 +885,18 @@ static const struct backlight_ops intel_backlight_device_ops = { static int intel_backlight_device_register(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; struct backlight_properties props; - unsigned long flags; if (WARN_ON(panel->backlight.device)) return -ENODEV; + BUG_ON(panel->backlight.max == 0); + memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.brightness = panel->backlight.level; - - spin_lock_irqsave(&dev_priv->backlight_lock, flags); - props.max_brightness = intel_panel_get_max_backlight(dev, 0); - spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); - - if (props.max_brightness == 0) { - DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); - return -ENODEV; - } + props.max_brightness = panel->backlight.max; /* * Note: using the same name independent of the connector prevents @@ -831,15 +936,102 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) } #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ +/* Note: The setup hooks can't assume pipe is set! */ +static int pch_setup_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + u32 val; + + panel->backlight.max = pch_get_max_backlight(connector); + if (!panel->backlight.max) + return -ENODEV; + + val = pch_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + return 0; +} + +static int i9xx_setup_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + u32 val; + + panel->backlight.max = i9xx_get_max_backlight(connector); + if (!panel->backlight.max) + return -ENODEV; + + val = i9xx_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + return 0; +} + +static int i965_setup_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + u32 val; + + panel->backlight.max = i965_get_max_backlight(connector); + if (!panel->backlight.max) + return -ENODEV; + + val = i9xx_get_backlight(connector); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + return 0; +} + +static int vlv_setup_backlight(struct intel_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + enum pipe pipe; + u32 val; + + for_each_pipe(pipe) { + u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); + + /* Skip if the modulation freq is already set */ + if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) + continue; + + cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | + cur_val); + } + + panel->backlight.max = _vlv_get_max_backlight(dev, PIPE_A); + if (!panel->backlight.max) + return -ENODEV; + + val = _vlv_get_backlight(dev, PIPE_A); + panel->backlight.level = intel_panel_compute_brightness(connector, val); + + return 0; +} + int intel_panel_setup_backlight(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_panel *panel = &intel_connector->panel; + unsigned long flags; + int ret; - intel_panel_init_backlight_regs(dev); + /* set level and max in panel struct */ + spin_lock_irqsave(&dev_priv->backlight_lock, flags); + ret = dev_priv->display.setup_backlight(intel_connector); + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); + + if (ret) { + DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", + drm_get_connector_name(connector)); + return ret; + } - panel->backlight.level = intel_panel_get_backlight(dev, 0); panel->backlight.enabled = panel->backlight.level != 0; intel_backlight_device_register(intel_connector); @@ -858,6 +1050,40 @@ void intel_panel_destroy_backlight(struct drm_connector *connector) intel_backlight_device_unregister(intel_connector); } +/* Set up chip specific backlight functions */ +void intel_panel_init_backlight_funcs(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (HAS_PCH_SPLIT(dev)) { + dev_priv->display.setup_backlight = pch_setup_backlight; + dev_priv->display.enable_backlight = pch_enable_backlight; + dev_priv->display.disable_backlight = pch_disable_backlight; + dev_priv->display.set_backlight = pch_set_backlight; + dev_priv->display.get_backlight = pch_get_backlight; + dev_priv->display.get_max_backlight = pch_get_max_backlight; + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->display.setup_backlight = vlv_setup_backlight; + dev_priv->display.enable_backlight = vlv_enable_backlight; + dev_priv->display.disable_backlight = vlv_disable_backlight; + dev_priv->display.set_backlight = vlv_set_backlight; + dev_priv->display.get_backlight = vlv_get_backlight; + dev_priv->display.get_max_backlight = vlv_get_max_backlight; + } else if (IS_GEN4(dev)) { + dev_priv->display.setup_backlight = i965_setup_backlight; + dev_priv->display.enable_backlight = i965_enable_backlight; + dev_priv->display.disable_backlight = i965_disable_backlight; + dev_priv->display.set_backlight = i9xx_set_backlight; + dev_priv->display.get_backlight = i9xx_get_backlight; + dev_priv->display.get_max_backlight = i965_get_max_backlight; + } else { + dev_priv->display.setup_backlight = i9xx_setup_backlight; + dev_priv->display.set_backlight = i9xx_set_backlight; + dev_priv->display.get_backlight = i9xx_get_backlight; + dev_priv->display.get_max_backlight = i9xx_get_max_backlight; + } +} + int intel_panel_init(struct intel_panel *panel, struct drm_display_mode *fixed_mode) { -- cgit v1.2.3 From b53c8c3577150a70e94b10090f68cfe3a4b601a5 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 12 Nov 2013 14:53:08 -0800 Subject: drm/i915: drop duplicate ggtt vma list add in setup_global_gtt Preallocated objects will already have been added to the vma_list when creating their ggtt vma entry, and coincidentally also marked as holding a ggtt mapping. Repeating the vma_list manipulation when setting up the ggtt after preallocation is a recipe for an unhappy kernel. Signed-off-by: Jesse Barnes Reviewed-by: Chris Wilson [danvet: Use the improve commit message suggest by Chris.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c4c42e7cbd7b..2b4c530d74a3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -759,7 +759,6 @@ void i915_gem_setup_global_gtt(struct drm_device *dev, if (ret) DRM_DEBUG_KMS("Reservation failed\n"); obj->has_global_gtt_mapping = 1; - list_add(&vma->vma_link, &obj->vma_list); } dev_priv->gtt.base.start = start; -- cgit v1.2.3 From b329b32854eca71853ce1e3e06b573c25b262d5f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:57 +0200 Subject: drm/i915: fix gen2-gen3 backlight set Citing Jani's response to Imre's question in the review discussion: > According to the gen2/3 bspec I have, the correct mask is > BACKLIGHT_DUTY_CYCLE_MASK_PNV only in case of IS_PINEVIEW(dev), for > everything else it's BACKLIGHT_DUTY_CYCLE_MASK. What you say is correct, but we've treated all gen2/3 similar to PNV since commit ca88479c1c3b7b1a9f94320745f5331e1de77f80 Author: Keith Packard Date: Fri Nov 18 11:09:24 2011 -0800 drm/i915: Treat pre-gen4 backlight duty cycle value consistently i.e. we only use the high 15 bits for all gen2/3. For non-PNV this just means the lowest bit is always zero. For PNV the lowest bit has a different meaning in both the PWM freq and duty cycle fields. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak [danvet: Make the commit message less empty.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a821949a9c7a..e82b2dd93eef 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -555,7 +555,7 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 tmp; + u32 tmp, mask; if (is_backlight_combination_mode(dev)) { u32 max = intel_panel_get_max_backlight(connector); @@ -570,10 +570,14 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level) pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); } - if (INTEL_INFO(dev)->gen < 4) + if (IS_GEN4(dev)) { + mask = BACKLIGHT_DUTY_CYCLE_MASK; + } else { level <<= 1; + mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; + } - tmp = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + tmp = I915_READ(BLC_PWM_CTL) & ~mask; I915_WRITE(BLC_PWM_CTL, tmp | level); } -- cgit v1.2.3 From ab51c86a88ba09ec657b1e02aa7824938afb7bd3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:58 +0200 Subject: drm/i915: vlv does not have pipe field in backlight registers It has per pipe registers. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e82b2dd93eef..5bd64db9a9bf 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -788,8 +788,6 @@ static void vlv_enable_backlight(struct intel_connector *connector) if (tmp & BLM_PWM_ENABLE) return; - tmp &= ~BLM_PIPE_SELECT; - tmp |= BLM_PIPE(pipe); tmp &= ~BLM_PWM_ENABLE; I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp); -- cgit v1.2.3 From 3bd712e545996658f4bc6c61ff99d7bae2a8cfcf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:48:59 +0200 Subject: drm/i915: move backlight level setting in enable/disable to hooks This allows more flexibility in the ordering of the register writes, and lets us drop level setting altogether as necessary on a per platform basis. For gen2-gen3, this is the only thing that happens in enable/disable. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 48 ++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 5bd64db9a9bf..ed6b1eccb7dd 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -648,6 +648,8 @@ static void pch_disable_backlight(struct intel_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp; + intel_panel_actually_set_backlight(connector, 0); + tmp = I915_READ(BLC_PWM_CPU_CTL2); I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); @@ -655,12 +657,19 @@ static void pch_disable_backlight(struct intel_connector *connector) I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); } +static void i9xx_disable_backlight(struct intel_connector *connector) +{ + intel_panel_actually_set_backlight(connector, 0); +} + static void i965_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp; + intel_panel_actually_set_backlight(connector, 0); + tmp = I915_READ(BLC_PWM_CTL2); I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); } @@ -672,6 +681,8 @@ static void vlv_disable_backlight(struct intel_connector *connector) enum pipe pipe = intel_get_pipe_from_connector(connector); u32 tmp; + intel_panel_actually_set_backlight(connector, 0); + tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); } @@ -701,10 +712,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector) spin_lock_irqsave(&dev_priv->backlight_lock, flags); panel->backlight.enabled = false; - intel_panel_actually_set_backlight(connector, 0); - - if (dev_priv->display.disable_backlight) - dev_priv->display.disable_backlight(connector); + dev_priv->display.disable_backlight(connector); spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } @@ -713,6 +721,7 @@ static void pch_enable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); @@ -747,12 +756,27 @@ static void pch_enable_backlight(struct intel_connector *connector) tmp &= ~BLM_PCH_OVERRIDE_ENABLE; I915_WRITE(BLC_PWM_PCH_CTL1, tmp); } + + /* + * Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. + * BLC_PWM_CPU_CTL may be cleared to zero automatically when these + * registers are set. + */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); +} + +static void i9xx_enable_backlight(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + + intel_panel_actually_set_backlight(connector, panel->backlight.level); } static void i965_enable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 tmp; @@ -771,12 +795,15 @@ static void i965_enable_backlight(struct intel_connector *connector) I915_WRITE(BLC_PWM_CTL2, tmp); POSTING_READ(BLC_PWM_CTL2); I915_WRITE(BLC_PWM_CTL2, tmp | BLM_PWM_ENABLE); + + intel_panel_actually_set_backlight(connector, panel->backlight.level); } static void vlv_enable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 tmp; @@ -793,6 +820,8 @@ static void vlv_enable_backlight(struct intel_connector *connector) I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp); POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp | BLM_PWM_ENABLE); + + intel_panel_actually_set_backlight(connector, panel->backlight.level); } void intel_panel_enable_backlight(struct intel_connector *connector) @@ -817,15 +846,8 @@ void intel_panel_enable_backlight(struct intel_connector *connector) panel->backlight.level; } - if (dev_priv->display.enable_backlight) - dev_priv->display.enable_backlight(connector); - - /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. - * BLC_PWM_CPU_CTL may be cleared to zero automatically when these - * registers are set. - */ + dev_priv->display.enable_backlight(connector); panel->backlight.enabled = true; - intel_panel_actually_set_backlight(connector, panel->backlight.level); spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } @@ -1080,6 +1102,8 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.get_max_backlight = i965_get_max_backlight; } else { dev_priv->display.setup_backlight = i9xx_setup_backlight; + dev_priv->display.enable_backlight = i9xx_enable_backlight; + dev_priv->display.disable_backlight = i9xx_disable_backlight; dev_priv->display.set_backlight = i9xx_set_backlight; dev_priv->display.get_backlight = i9xx_get_backlight; dev_priv->display.get_max_backlight = i9xx_get_max_backlight; -- cgit v1.2.3 From f91c15e0808e612abacdb0fbca557b23fe2aa4d1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:49:00 +0200 Subject: drm/i915: use the initialized backlight max value instead of reading it We now have the max backlight value cached. Use it. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 45 ++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index ed6b1eccb7dd..9a55b36370b3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -436,9 +436,6 @@ static u32 vlv_get_max_backlight(struct intel_connector *connector) return _vlv_get_max_backlight(dev, pipe); } -/* XXX: query mode clock or hardware clock and program max PWM appropriately - * when it's 0. - */ static u32 intel_panel_get_max_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; @@ -466,15 +463,16 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector, { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; + + WARN_ON(panel->backlight.max == 0); if (i915_panel_invert_brightness < 0) return val; if (i915_panel_invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { - u32 max = intel_panel_get_max_backlight(connector); - if (max) - return max - val; + return panel->backlight.max - val; } return val; @@ -555,17 +553,15 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; u32 tmp, mask; + WARN_ON(panel->backlight.max == 0); + if (is_backlight_combination_mode(dev)) { - u32 max = intel_panel_get_max_backlight(connector); u8 lbpc; - /* we're screwed, but keep behaviour backwards compatible */ - if (!max) - max = 1; - - lbpc = level * 0xfe / max + 1; + lbpc = level * 0xfe / panel->backlight.max + 1; level /= lbpc; pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); } @@ -620,13 +616,10 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, spin_lock_irqsave(&dev_priv->backlight_lock, flags); - freq = intel_panel_get_max_backlight(connector); - if (!freq) { - /* we are screwed, bail out */ - goto out; - } + WARN_ON(panel->backlight.max == 0); - /* scale to hardware, but be careful to not overflow */ + /* scale to hardware max, but be careful to not overflow */ + freq = panel->backlight.max; if (freq < max) level = level * freq / max; else @@ -638,7 +631,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, if (panel->backlight.enabled) intel_panel_actually_set_backlight(connector, level); -out: + spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); } @@ -839,8 +832,13 @@ void intel_panel_enable_backlight(struct intel_connector *connector) spin_lock_irqsave(&dev_priv->backlight_lock, flags); + /* XXX: transitional, call to make sure freq is set */ + intel_panel_get_max_backlight(connector); + + WARN_ON(panel->backlight.max == 0); + if (panel->backlight.level == 0) { - panel->backlight.level = intel_panel_get_max_backlight(connector); + panel->backlight.level = panel->backlight.max; if (panel->backlight.device) panel->backlight.device->props.brightness = panel->backlight.level; @@ -960,7 +958,12 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) } #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ -/* Note: The setup hooks can't assume pipe is set! */ +/* + * Note: The setup hooks can't assume pipe is set! + * + * XXX: Query mode clock or hardware clock and program PWM modulation frequency + * appropriately when it's 0. Use VBT and/or sane defaults. + */ static int pch_setup_backlight(struct intel_connector *connector) { struct intel_panel *panel = &connector->panel; -- cgit v1.2.3 From c445b3b1e02a40666b7e4bea58bce0c4723eba4f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:49:01 +0200 Subject: drm/i915: debug print on backlight register Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 9a55b36370b3..3dd9f57da69c 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1065,6 +1065,12 @@ int intel_panel_setup_backlight(struct drm_connector *connector) panel->backlight.present = true; + DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, " + "sysfs interface %sregistered\n", + panel->backlight.enabled ? "enabled" : "disabled", + panel->backlight.level, panel->backlight.max, + panel->backlight.device ? "" : "not "); + return 0; } -- cgit v1.2.3 From 661df0415e6f6bfaade501fb94cc324fa44f29b4 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 12 Nov 2013 19:49:35 +0200 Subject: drm/i915: check i915_get_reset_stats_ioctl args Insist that flags and pad fields are zero, so that we can safely extend the interface in future. Testcase: igt/gem_reset_stats/params Suggested-by: Daniel Vetter Signed-off-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 21cf9519be78..a881906969eb 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -641,6 +641,9 @@ int i915_get_reset_stats_ioctl(struct drm_device *dev, struct i915_ctx_hang_stats *hs; int ret; + if (args->flags || args->pad) + return -EINVAL; + if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN)) return -EPERM; -- cgit v1.2.3 From 56dde80a1a62b1f84f9ba7d2aee267dc9476ee58 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Nov 2013 14:52:26 +0800 Subject: regulator: lp3971: Convert to devm_regulator_register Both num_regulators and **rdev are no longer required after this conversion, thus remove them from struct lp3971. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 43 ++++++------------------------------------- 1 file changed, 6 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 947c05ffe0ab..3b1102b75071 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -25,8 +25,6 @@ struct lp3971 { struct device *dev; struct mutex io_lock; struct i2c_client *i2c; - int num_regulators; - struct regulator_dev **rdev; }; static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg); @@ -383,42 +381,27 @@ static int setup_regulators(struct lp3971 *lp3971, { int i, err; - lp3971->num_regulators = pdata->num_regulators; - lp3971->rdev = kcalloc(pdata->num_regulators, - sizeof(struct regulator_dev *), GFP_KERNEL); - if (!lp3971->rdev) { - err = -ENOMEM; - goto err_nomem; - } - /* Instantiate the regulators */ for (i = 0; i < pdata->num_regulators; i++) { struct regulator_config config = { }; struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; + struct regulator_dev *rdev; config.dev = lp3971->dev; config.init_data = reg->initdata; config.driver_data = lp3971; - lp3971->rdev[i] = regulator_register(®ulators[reg->id], - &config); - if (IS_ERR(lp3971->rdev[i])) { - err = PTR_ERR(lp3971->rdev[i]); + rdev = devm_regulator_register(lp3971->dev, + ®ulators[reg->id], &config); + if (IS_ERR(rdev)) { + err = PTR_ERR(rdev); dev_err(lp3971->dev, "regulator init failed: %d\n", err); - goto error; + return err; } } return 0; - -error: - while (--i >= 0) - regulator_unregister(lp3971->rdev[i]); - kfree(lp3971->rdev); - lp3971->rdev = NULL; -err_nomem: - return err; } static int lp3971_i2c_probe(struct i2c_client *i2c, @@ -460,19 +443,6 @@ static int lp3971_i2c_probe(struct i2c_client *i2c, return 0; } -static int lp3971_i2c_remove(struct i2c_client *i2c) -{ - struct lp3971 *lp3971 = i2c_get_clientdata(i2c); - int i; - - for (i = 0; i < lp3971->num_regulators; i++) - regulator_unregister(lp3971->rdev[i]); - - kfree(lp3971->rdev); - - return 0; -} - static const struct i2c_device_id lp3971_i2c_id[] = { { "lp3971", 0 }, { } @@ -485,7 +455,6 @@ static struct i2c_driver lp3971_i2c_driver = { .owner = THIS_MODULE, }, .probe = lp3971_i2c_probe, - .remove = lp3971_i2c_remove, .id_table = lp3971_i2c_id, }; -- cgit v1.2.3 From ea8eea73ac62fab878912a74df7fb586586238e7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Nov 2013 09:35:17 +0100 Subject: drm/i915: Make AGP=n work even on gen3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most platforms din't hit this condition, but if we want to allow building without agp we should also make this allowed on gen3. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c3e9485f38fe..a19940f5ef06 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -158,7 +158,7 @@ static struct drm_driver driver; #if IS_ENABLED(CONFIG_AGP_INTEL) extern int intel_agp_enabled; #else -static int intel_agp_enabled; +static int intel_agp_enabled = 1; #endif static const struct intel_device_info intel_i830_info = { -- cgit v1.2.3 From 3bb6ce66866310f50d461b9eff949c1ce95560ce Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 13 Nov 2013 22:14:16 +0100 Subject: drm/i915: Kill legeacy AGP for gen3 kms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thus far we've tried to carefully work around the fact that old userspace relied on the AGP-backed legacy buffer mapping ioctls for a bit too long. But it's really horribly, and now some new users for it started to show up again: http://www.mail-archive.com/mesa-dev@lists.freedesktop.org/msg45547.html This uses drmAgpSize to figure out the GTT size, which is both the wrong thing to inquire and also might force us to keep this crap around for another few years. So I want to stop this particular zombie from raising ever again. Now it's only been 4 years since XvMC was fixed for gen3, so a bit early by the usual rules. But since Linus explicitly said that an ABI breakage only counts if someone actually observes it I want to tempt fate an accelarate the demise of AGP. We probably need to wait 2-3 kernel releases with this shipping until we go on a killing spree code-wise. v2: Remove intel_agp_enabled since it's unused (Ville). Cc: Ville Syrjälä Cc: Dave Airlie Acked-by: Dave Airlie Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-agp.c | 5 ----- drivers/gpu/drm/i915/i915_drv.c | 17 +---------------- 2 files changed, 1 insertion(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a426ee1f57a6..9ef0a48a5b28 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -14,9 +14,6 @@ #include "intel-agp.h" #include -int intel_agp_enabled; -EXPORT_SYMBOL(intel_agp_enabled); - static int intel_fetch_size(void) { int i; @@ -814,8 +811,6 @@ static int agp_intel_probe(struct pci_dev *pdev, found_gmch: pci_set_drvdata(pdev, bridge); err = agp_add_bridge(bridge); - if (!err) - intel_agp_enabled = 1; return err; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a19940f5ef06..b16a6eca795f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -155,11 +155,6 @@ MODULE_PARM_DESC(prefault_disable, "Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only."); static struct drm_driver driver; -#if IS_ENABLED(CONFIG_AGP_INTEL) -extern int intel_agp_enabled; -#else -static int intel_agp_enabled = 1; -#endif static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, @@ -797,17 +792,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (PCI_FUNC(pdev->devfn)) return -ENODEV; - /* We've managed to ship a kms-enabled ddx that shipped with an XvMC - * implementation for gen3 (and only gen3) that used legacy drm maps - * (gasp!) to share buffers between X and the client. Hence we need to - * keep around the fake agp stuff for gen3, even when kms is enabled. */ - if (intel_info->gen != 3) { - driver.driver_features &= - ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP); - } else if (!intel_agp_enabled) { - DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); - return -ENODEV; - } + driver.driver_features &= ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP); return drm_get_pci_dev(pdev, ent, &driver); } -- cgit v1.2.3 From b30324adaf8d2e5950a602bde63030d15a61826f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 13 Nov 2013 22:11:25 +0100 Subject: drm/i915: Deprecated UMS support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's been 5 years since kms support was merged and roughly 4 years since UMS support was ripped out from userspace drivers. Thus far it's not been a big burden to keep the ums paths alive, and we've made some good progress in better separating it from the kms code by sprinkling DRIVER_MODESET checks all over the place. But now that the drm demidlayering is within reach this changes. I want to make the driver loading code more robust using devres.c and other cool tricks. But that doesn't work with ums due to the shadow-attach trick. Which means we either a) need to split out a complete ums codebase like radeon has b) kill it for good. The 2nd option is obviously much less work than the first, so I think it's time to test the waters and see how many people out there still use ums. I've decided that silently failing to initialize the driver (and not e.g. failing to load the module) is the right thing. That way we should only get reports from users that actually care about some ums features (like accelerated gl or support for secondary outputs). Everyone else will just fall back to the vesa X driver. For developers there's a small info level dmesg output. The plan is to drop this Kconfig option after 3.16 (so gives us 2 full releases) and then start killing code for real 2-3 releases afterwards. That should be more than enough time for users to pipe up. Of course if anyone does we need to revisit this plan and maybe go with option a) above. Also enable the KMS support by default in Kconfig and polish the help texts a bit. v2: Add the missing hunk of actual code changes. Oops. (Ville) Cc: Ville Syrjälä Cc: Dave Airlie Acked-by: Dave Airlie Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/Kconfig | 24 +++++++++++++++++++----- drivers/gpu/drm/i915/i915_drv.c | 7 ++++++- 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index b0f61679c598..b0fa4c4055ee 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -37,12 +37,11 @@ config DRM_I915 config DRM_I915_KMS bool "Enable modesetting on intel by default" depends on DRM_I915 + default y help - Choose this option if you want kernel modesetting enabled by default, - and you have a new enough userspace to support this. Running old - userspaces with this enabled will cause pain. Note that this causes - the driver to bind to PCI devices, which precludes loading things - like intelfb. + Choose this option if you want kernel modesetting enabled by default. + + If in doubt, say "Y". config DRM_I915_FBDEV bool "Enable legacy fbdev support for the modesettting intel driver" @@ -57,9 +56,12 @@ config DRM_I915_FBDEV support. Note that this support also provide the linux console support on top of the intel modesetting driver. + If in doubt, say "Y". + config DRM_I915_PRELIMINARY_HW_SUPPORT bool "Enable preliminary support for prerelease Intel hardware by default" depends on DRM_I915 + default n help Choose this option if you have prerelease Intel hardware and want the i915 driver to support it by default. You can enable such support at @@ -67,3 +69,15 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT option changes the default for that module option. If in doubt, say "N". + +config DRM_I915_UMS + bool "Enable userspace modesetting on Intel hardware (DEPRECATED)" + depends on DRM_I915 + default n + help + Choose this option if you still need userspace modesetting. + + Userspace modesetting is deprecated for quite some time now, so + enable this only if you have ancient versions of the DDX drivers. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b16a6eca795f..92ad319164d7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -975,8 +975,13 @@ static int __init i915_init(void) driver.driver_features &= ~DRIVER_MODESET; #endif - if (!(driver.driver_features & DRIVER_MODESET)) + if (!(driver.driver_features & DRIVER_MODESET)) { driver.get_vblank_timestamp = NULL; +#ifndef CONFIG_DRM_I915_UMS + /* Silently fail loading to not upset userspace. */ + return 0; +#endif + } return drm_pci_init(&driver, &i915_pci_driver); } -- cgit v1.2.3 From 636baebfa62fa31b204bc5a816700bd2fd135e57 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:49:02 +0200 Subject: drm/i915: gather backlight information at setup Prepare for being able to use the information at enable. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_panel.c | 68 +++++++++++++++++++++++++++++++------- 2 files changed, 58 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 819d0d2f0142..4fbd073810ef 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -163,6 +163,8 @@ struct intel_panel { u32 level; u32 max; bool enabled; + bool combination_mode; /* gen 2/4 only */ + bool active_low_pwm; struct backlight_device *device; } backlight; }; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 3dd9f57da69c..0e8f0a3d3bf6 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -490,13 +490,14 @@ static u32 i9xx_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; u32 val; val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; if (INTEL_INFO(dev)->gen < 4) val >>= 1; - if (is_backlight_combination_mode(dev)) { + if (panel->backlight.combination_mode) { u8 lbpc; pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); @@ -558,7 +559,7 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level) WARN_ON(panel->backlight.max == 0); - if (is_backlight_combination_mode(dev)) { + if (panel->backlight.combination_mode) { u8 lbpc; lbpc = level * 0xfe / panel->backlight.max + 1; @@ -966,46 +967,84 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) */ static int pch_setup_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; - u32 val; + u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; - panel->backlight.max = pch_get_max_backlight(connector); + pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); + panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; + + pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); + panel->backlight.max = pch_ctl2 >> 16; if (!panel->backlight.max) return -ENODEV; val = pch_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); + cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); + panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && + (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; + return 0; } static int i9xx_setup_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; - u32 val; + u32 ctl, val; + + ctl = I915_READ(BLC_PWM_CTL); + + if (IS_GEN2(dev)) + panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; + + if (IS_PINEVIEW(dev)) + panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; + + panel->backlight.max = ctl >> 17; + if (panel->backlight.combination_mode) + panel->backlight.max *= 0xff; - panel->backlight.max = i9xx_get_max_backlight(connector); if (!panel->backlight.max) return -ENODEV; val = i9xx_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); + panel->backlight.enabled = panel->backlight.level != 0; + return 0; } static int i965_setup_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; - u32 val; + u32 ctl, ctl2, val; + + ctl2 = I915_READ(BLC_PWM_CTL2); + panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; + panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; + + ctl = I915_READ(BLC_PWM_CTL); + panel->backlight.max = ctl >> 16; + if (panel->backlight.combination_mode) + panel->backlight.max *= 0xff; - panel->backlight.max = i965_get_max_backlight(connector); if (!panel->backlight.max) return -ENODEV; val = i9xx_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); + panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && + panel->backlight.level != 0; + return 0; } @@ -1015,7 +1054,7 @@ static int vlv_setup_backlight(struct intel_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; enum pipe pipe; - u32 val; + u32 ctl, ctl2, val; for_each_pipe(pipe) { u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); @@ -1029,13 +1068,20 @@ static int vlv_setup_backlight(struct intel_connector *connector) cur_val); } - panel->backlight.max = _vlv_get_max_backlight(dev, PIPE_A); + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); + panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; + + ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); + panel->backlight.max = ctl >> 16; if (!panel->backlight.max) return -ENODEV; val = _vlv_get_backlight(dev, PIPE_A); panel->backlight.level = intel_panel_compute_brightness(connector, val); + panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && + panel->backlight.level != 0; + return 0; } @@ -1059,8 +1105,6 @@ int intel_panel_setup_backlight(struct drm_connector *connector) return ret; } - panel->backlight.enabled = panel->backlight.level != 0; - intel_backlight_device_register(intel_connector); panel->backlight.present = true; -- cgit v1.2.3 From 5dd8c4c3f18b2ebf3f5303c7c273396441db6c6c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 8 Nov 2013 10:20:06 -0800 Subject: drm/i915/bdw: Add BDW to ULT macro For what we care about ULT and ULX are interchangeable. We know of 3 types of pciids for these cases. I am not sure if at some point we will need to distinguish ULT and ULX. Cc: Paulo Zanoni Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8600c315b4c4..51951ef7e71d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1755,8 +1755,13 @@ struct drm_i915_file_private { #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0C00) -#define IS_ULT(dev) (IS_HASWELL(dev) && \ +#define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ + (((dev)->pdev->device & 0xf) == 0x2 || \ + ((dev)->pdev->device & 0xf) == 0x6 || \ + ((dev)->pdev->device & 0xf) == 0xe)) +#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0A00) +#define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0x00F0) == 0x0020) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) -- cgit v1.2.3 From f8e100621b072384ec1180563d933e86e2f7e2d5 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 11 Nov 2013 11:12:57 +0200 Subject: drm/i915/bdw: GEN8 backlight support Prior to Haswell the CPU control register for backlight (BLC_PWM_CPU_CTL) toggled the PCH baclight pin for us. This made some sense as there was no pin on the CPU. With Haswell came the introduction of a CPU backlight pin, but the interface was still controlled by software with the same mechnism. Behind the scenes, hardware did all the dirty work for us. Broadwell no longer provides this for free. If we want to use the PCH backlight pin [1] then we have to set the override bit BLC_PWM_PCH_CTL1 and program BLC_PWM_PCH_CTL2 for the PWM values. This patch implements that. This patch is compile tested only, and given that I rarely if ever touch this code, careful review is welcome. [1] According to Art, we know of no devices that exist which use the CPU pin (and remember it has existed already on HSW). If such a device does exist, we'll have to handle it properly - this is left as TODO until then. v2: Drop the abstraction prep patch, as a bigger backlight overhaul is in the works, and do just the mimimal bdw enabling now. (by Jani) CC: Art Runyan Signed-off-by: Ben Widawsky Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac02c4f6..e6f782d1c669 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -451,7 +451,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, spin_lock_irqsave(&dev_priv->backlight.lock, flags); - if (HAS_PCH_SPLIT(dev)) { + if (IS_BROADWELL(dev)) { + val = I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; + } else if (HAS_PCH_SPLIT(dev)) { val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { if (IS_VALLEYVIEW(dev)) @@ -479,6 +481,13 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, return val; } +static void intel_bdw_panel_set_backlight(struct drm_device *dev, u32 level) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_PCH_CTL2, val | level); +} + static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -496,7 +505,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); level = intel_panel_compute_brightness(dev, pipe, level); - if (HAS_PCH_SPLIT(dev)) + if (IS_BROADWELL(dev)) + return intel_bdw_panel_set_backlight(dev, level); + else if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); if (is_backlight_combination_mode(dev)) { @@ -666,7 +677,16 @@ void intel_panel_enable_backlight(struct intel_connector *connector) POSTING_READ(reg); I915_WRITE(reg, tmp | BLM_PWM_ENABLE); - if (HAS_PCH_SPLIT(dev) && + if (IS_BROADWELL(dev)) { + /* + * Broadwell requires PCH override to drive the PCH + * backlight pin. The above will configure the CPU + * backlight pin, which we don't plan to use. + */ + tmp = I915_READ(BLC_PWM_PCH_CTL1); + tmp |= BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, tmp); + } else if (HAS_PCH_SPLIT(dev) && !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { tmp = I915_READ(BLC_PWM_PCH_CTL1); tmp |= BLM_PCH_PWM_ENABLE; -- cgit v1.2.3 From 935e8de97564a1ea22c3bb30ca2b20b12af7cbfb Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:47 -0800 Subject: drm/i915/bdw: Do gen6 style reset for gen8 This patch existed before, but was lost over time. Note that reset is still somewhat problematic in my limited testing (ie. module_reload will not pass) but it can be disabled with a module parameter, and support should be considered preliminary anyway. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index f9883ceff946..6a4f9b615de1 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -782,6 +782,7 @@ static int gen6_do_reset(struct drm_device *dev) int intel_gpu_reset(struct drm_device *dev) { switch (INTEL_INFO(dev)->gen) { + case 8: case 7: case 6: return gen6_do_reset(dev); case 5: return ironlake_do_reset(dev); -- cgit v1.2.3 From 230f955f73074ec5b1b4389f3f26152eebf54404 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:48 -0800 Subject: drm/i915/bdw: Free correct number of ppgtt pages I am unclear how this got messed up in the shuffle, but it did. Cc: Imre Deak Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 3620a1b0a73c..5a3cc3189f1f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -335,8 +335,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) kfree(ppgtt->gen8_pt_dma_addr[i]); } - __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT); - __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT); + __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT)); + __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT)); } /** -- cgit v1.2.3 From eb0d4b75d506050cb369df467b93b92360f5acaf Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:50 -0800 Subject: drm/i915/bdw: Add comment about gen8 HWS PGA This confused me some many times that I think it is appropriate to add a small comment to instruct the reader of the code that it is indeed doing what it is supposed to do. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b620337e6d67..c2f09d456300 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -965,6 +965,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); } else { + /* XXX: gen8 returns to sanity */ mmio = RING_HWS_PGA(ring->mmio_base); } -- cgit v1.2.3 From 3a2ffb65eec6dbda2fd8151894f51c18b42c8d41 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:51 -0800 Subject: drm/i915/bdw: Limit GTT to 2GB Because of the way in which we're allocating the pages for the Aliasing PPGTT, we cannot actually successfully alloc enough space for anything greater than 2GB. Instead of a quick hack to fix this, we should defer until we have the real solution in place (allocating much less contiguous space). This wasn't found sooner because we didn't not have any systems supporting more than a 2GB GTT. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 5a3cc3189f1f..f69bdc741b80 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1239,6 +1239,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; if (bdw_gmch_ctl) bdw_gmch_ctl = 1 << bdw_gmch_ctl; + if (bdw_gmch_ctl > 4) { + WARN_ON(!i915_preliminary_hw_support); + return 4<<20; + } + return bdw_gmch_ctl << 20; } -- cgit v1.2.3 From 596cc11e7a4a89bf6c45f955402d0bd0c7d51f13 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 11 Nov 2013 14:46:28 -0800 Subject: drm/i915/bdw: PIPE_[BC] I[ME]R moved to powerwell The pipe B and pipe C interrupt mask and enable registers are now part of the pipe, so disabling the pipe power wells will lost the contests of the registers. Art totally debugged this one! v2: Use the irq_lock to clarify code, and prevent future bugs (Daniel) Cc: Art Runyan Cc: Paulo Zanoni Signed-off-by: Ben Widawsky [danvet: Make sparse happy.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a07d7c9cafc..33a8dbe64039 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5684,6 +5684,7 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; bool is_enabled, enable_requested; + unsigned long irqflags; uint32_t tmp; tmp = I915_READ(HSW_PWR_WELL_DRIVER); @@ -5701,9 +5702,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) HSW_PWR_WELL_STATE_ENABLED), 20)) DRM_ERROR("Timeout enabling power well\n"); } + + if (IS_BROADWELL(dev)) { + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), + dev_priv->de_irq_mask[PIPE_B]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), + ~dev_priv->de_irq_mask[PIPE_B] | + GEN8_PIPE_VBLANK); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), + dev_priv->de_irq_mask[PIPE_C]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), + ~dev_priv->de_irq_mask[PIPE_C] | + GEN8_PIPE_VBLANK); + POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + } } else { if (enable_requested) { - unsigned long irqflags; enum pipe p; I915_WRITE(HSW_PWR_WELL_DRIVER, 0); -- cgit v1.2.3 From b35684b8fa94e04f55fd38bf672b737741d2f9e2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 14 Nov 2013 12:13:41 +0200 Subject: drm/i915: do full backlight setup at enable time We should now have all the information we need to do a full initialization of the backlight registers. v2: Keep QUIRK_NO_PCH_PWM_ENABLE for now (Imre). Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 149 +++++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 0e8f0a3d3bf6..0986472d4254 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -719,50 +719,75 @@ static void pch_enable_backlight(struct intel_connector *connector) enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); - u32 tmp; - - tmp = I915_READ(BLC_PWM_CPU_CTL2); + u32 cpu_ctl2, pch_ctl1, pch_ctl2; - /* Note that this can also get called through dpms changes. And - * we don't track the backlight dpms state, hence check whether - * we have to do anything first. */ - if (tmp & BLM_PWM_ENABLE) - return; + cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); + if (cpu_ctl2 & BLM_PWM_ENABLE) { + WARN(1, "cpu backlight already enabled\n"); + cpu_ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); + } - if (INTEL_INFO(dev)->num_pipes == 3) - tmp &= ~BLM_PIPE_SELECT_IVB; - else - tmp &= ~BLM_PIPE_SELECT; + pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); + if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { + DRM_DEBUG_KMS("pch backlight already enabled\n"); + pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); + } if (cpu_transcoder == TRANSCODER_EDP) - tmp |= BLM_TRANSCODER_EDP; + cpu_ctl2 = BLM_TRANSCODER_EDP; else - tmp |= BLM_PIPE(cpu_transcoder); - tmp &= ~BLM_PWM_ENABLE; - - I915_WRITE(BLC_PWM_CPU_CTL2, tmp); + cpu_ctl2 = BLM_PIPE(cpu_transcoder); + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); POSTING_READ(BLC_PWM_CPU_CTL2); - I915_WRITE(BLC_PWM_CPU_CTL2, tmp | BLM_PWM_ENABLE); - - if (!(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { - tmp = I915_READ(BLC_PWM_PCH_CTL1); - tmp |= BLM_PCH_PWM_ENABLE; - tmp &= ~BLM_PCH_OVERRIDE_ENABLE; - I915_WRITE(BLC_PWM_PCH_CTL1, tmp); - } + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); - /* - * Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. - * BLC_PWM_CPU_CTL may be cleared to zero automatically when these - * registers are set. - */ + /* This won't stick until the above enable. */ intel_panel_actually_set_backlight(connector, panel->backlight.level); + + pch_ctl2 = panel->backlight.max << 16; + I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); + + /* XXX: transitional */ + if (dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE) + return; + + pch_ctl1 = 0; + if (panel->backlight.active_low_pwm) + pch_ctl1 |= BLM_PCH_POLARITY; + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); + POSTING_READ(BLC_PWM_PCH_CTL1); + I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); } static void i9xx_enable_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; + u32 ctl, freq; + + ctl = I915_READ(BLC_PWM_CTL); + if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { + WARN(1, "backlight already enabled\n"); + I915_WRITE(BLC_PWM_CTL, 0); + } + freq = panel->backlight.max; + if (panel->backlight.combination_mode) + freq /= 0xff; + + ctl = freq << 17; + if (IS_GEN2(dev) && panel->backlight.combination_mode) + ctl |= BLM_LEGACY_MODE; + if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) + ctl |= BLM_POLARITY_PNV; + + I915_WRITE(BLC_PWM_CTL, ctl); + POSTING_READ(BLC_PWM_CTL); + + /* XXX: combine this into above write? */ intel_panel_actually_set_backlight(connector, panel->backlight.level); } @@ -772,25 +797,33 @@ static void i965_enable_backlight(struct intel_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); - u32 tmp; + u32 ctl, ctl2, freq; - tmp = I915_READ(BLC_PWM_CTL2); + ctl2 = I915_READ(BLC_PWM_CTL2); + if (ctl2 & BLM_PWM_ENABLE) { + WARN(1, "backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CTL2, ctl2); + } - /* Note that this can also get called through dpms changes. And - * we don't track the backlight dpms state, hence check whether - * we have to do anything first. */ - if (tmp & BLM_PWM_ENABLE) - return; + freq = panel->backlight.max; + if (panel->backlight.combination_mode) + freq /= 0xff; - tmp &= ~BLM_PIPE_SELECT; - tmp |= BLM_PIPE(pipe); - tmp &= ~BLM_PWM_ENABLE; - - I915_WRITE(BLC_PWM_CTL2, tmp); - POSTING_READ(BLC_PWM_CTL2); - I915_WRITE(BLC_PWM_CTL2, tmp | BLM_PWM_ENABLE); + ctl = freq << 16; + I915_WRITE(BLC_PWM_CTL, ctl); + /* XXX: combine this into above write? */ intel_panel_actually_set_backlight(connector, panel->backlight.level); + + ctl2 = BLM_PIPE(pipe); + if (panel->backlight.combination_mode) + ctl2 |= BLM_COMBINATION_MODE; + if (panel->backlight.active_low_pwm) + ctl2 |= BLM_POLARITY_I965; + I915_WRITE(BLC_PWM_CTL2, ctl2); + POSTING_READ(BLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); } static void vlv_enable_backlight(struct intel_connector *connector) @@ -799,23 +832,27 @@ static void vlv_enable_backlight(struct intel_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); - u32 tmp; + u32 ctl, ctl2; - tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + if (ctl2 & BLM_PWM_ENABLE) { + WARN(1, "backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); + } - /* Note that this can also get called through dpms changes. And - * we don't track the backlight dpms state, hence check whether - * we have to do anything first. */ - if (tmp & BLM_PWM_ENABLE) - return; + ctl = panel->backlight.max << 16; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); - tmp &= ~BLM_PWM_ENABLE; + /* XXX: combine this into above write? */ + intel_panel_actually_set_backlight(connector, panel->backlight.level); - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp); + ctl2 = 0; + if (panel->backlight.active_low_pwm) + ctl2 |= BLM_POLARITY_I965; + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp | BLM_PWM_ENABLE); - - intel_panel_actually_set_backlight(connector, panel->backlight.level); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } void intel_panel_enable_backlight(struct intel_connector *connector) -- cgit v1.2.3 From bc0bb9fd1c7810407ab810d204bbaecb255fddde Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 14 Nov 2013 12:14:29 +0200 Subject: drm/i915: remove QUIRK_NO_PCH_PWM_ENABLE The quirk was added as what I'd say was a stopgap measure in commit e85843bec6c2ea7c10ec61238396891cc2b753a9 Author: Kamal Mostafa Date: Fri Jul 19 15:02:01 2013 -0700 drm/i915: quirk no PCH_PWM_ENABLE for Dell XPS13 backlight without really digging into what was going on. Also, as mentioned in the related bug [1], having the quirk regressed some of the machines it was supposed to fix to begin with, and there were patches posted to disable the quirk on such machines [2]! The fact is, we do need the BLM_PCH_PWM_ENABLE bit set to have backlight. With the quirk, we've relied on BIOS to have set it, and our save/restore code to retain it. With the full backlight setup at enable, we have no place for things that rely on previous state. With the per platform hooks, we've also made a change in the PCH platform enable order: setting the backlight duty cycle between CPU and PCH PWM enable. Some experimenting and commit 770c12312ad617172b1a65b911d3e6564fc5aca8 Author: Takashi Iwai Date: Sat Aug 11 08:56:42 2012 +0200 drm/i915: Fix blank panel at reopening lid indicate that we can't set the backlight before enabling CPU PWM; the value just won't stick. But AFAICT we should do it before enabling the PCH PWM. Finally, any fallout we should fix properly, preferrably without quirks, and absolutely without quirks that rely on existing state. With the per platform hooks have much more flexibility to adjust the sequence as required by platforms. [1] https://bugzilla.kernel.org/show_bug.cgi?id=47941 [2] http://lkml.kernel.org/r/1378229848-29113-1-git-send-email-kamal@canonical.com Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_display.c | 16 ---------------- drivers/gpu/drm/i915/intel_panel.c | 4 ---- 3 files changed, 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c243b8e954a0..e726ab985100 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -717,7 +717,6 @@ enum intel_sbi_destination { #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) -#define QUIRK_NO_PCH_PWM_ENABLE (1<<3) struct intel_fbdev; struct intel_fbc_work; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 25ef080d1bc2..b9f763c637ec 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10456,17 +10456,6 @@ static void quirk_invert_brightness(struct drm_device *dev) DRM_INFO("applying inverted panel brightness quirk\n"); } -/* - * Some machines (Dell XPS13) suffer broken backlight controls if - * BLM_PCH_PWM_ENABLE is set. - */ -static void quirk_no_pcm_pwm_enable(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; - DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); -} - struct intel_quirk { int device; int subsystem_vendor; @@ -10526,11 +10515,6 @@ static struct intel_quirk intel_quirks[] = { * seem to use inverted backlight PWM. */ { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness }, - - /* Dell XPS13 HD Sandy Bridge */ - { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, - /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */ - { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable }, }; static void intel_init_quirks(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 0986472d4254..da088e33dd19 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -749,10 +749,6 @@ static void pch_enable_backlight(struct intel_connector *connector) pch_ctl2 = panel->backlight.max << 16; I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); - /* XXX: transitional */ - if (dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE) - return; - pch_ctl1 = 0; if (panel->backlight.active_low_pwm) pch_ctl1 |= BLM_PCH_POLARITY; -- cgit v1.2.3 From 58cad0768ca204599561bdb5509fb4ffc92603cb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 16:49:04 +0200 Subject: drm/i915: nuke get max backlight functions No longer needed. We now have fully cached max backlight values. Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_panel.c | 133 ------------------------------------- 2 files changed, 134 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e726ab985100..247e922942dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -416,7 +416,6 @@ struct drm_i915_display_funcs { /* pll clock increase/decrease */ int (*setup_backlight)(struct intel_connector *connector); - uint32_t (*get_max_backlight)(struct intel_connector *connector); uint32_t (*get_backlight)(struct intel_connector *connector); void (*set_backlight)(struct intel_connector *connector, uint32_t level); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index da088e33dd19..eadfe338dbeb 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -325,132 +325,6 @@ out: pipe_config->gmch_pfit.lvds_border_bits = border; } -static int is_backlight_combination_mode(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (IS_GEN4(dev)) - return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; - - if (IS_GEN2(dev)) - return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; - - return 0; -} - -static u32 pch_get_max_backlight(struct intel_connector *connector) -{ - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - val = I915_READ(BLC_PWM_PCH_CTL2); - if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { - dev_priv->regfile.saveBLC_PWM_CTL2 = val; - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL2; - I915_WRITE(BLC_PWM_PCH_CTL2, val); - } - - val >>= 16; - - return val; -} - -static u32 i9xx_get_max_backlight(struct intel_connector *connector) -{ - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - val = I915_READ(BLC_PWM_CTL); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(BLC_PWM_CTL, val); - } - - val >>= 17; - - if (is_backlight_combination_mode(dev)) - val *= 0xff; - - return val; -} - -static u32 i965_get_max_backlight(struct intel_connector *connector) -{ - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - val = I915_READ(BLC_PWM_CTL); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(BLC_PWM_CTL, val); - I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); - } - - val >>= 16; - - if (is_backlight_combination_mode(dev)) - val *= 0xff; - - return val; -} - -static u32 _vlv_get_max_backlight(struct drm_device *dev, enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(pipe)); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), - dev_priv->regfile.saveBLC_PWM_CTL2); - } - - if (!val) - val = 0x0f42ffff; - - val >>= 16; - - return val; -} - -static u32 vlv_get_max_backlight(struct intel_connector *connector) -{ - struct drm_device *dev = connector->base.dev; - enum pipe pipe = intel_get_pipe_from_connector(connector); - - return _vlv_get_max_backlight(dev, pipe); -} - -static u32 intel_panel_get_max_backlight(struct intel_connector *connector) -{ - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 max; - - WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight_lock)); - - max = dev_priv->display.get_max_backlight(connector); - - DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); - - return max; -} - static int i915_panel_invert_brightness; MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "(-1 force normal, 0 machine defaults, 1 force inversion), please " @@ -866,9 +740,6 @@ void intel_panel_enable_backlight(struct intel_connector *connector) spin_lock_irqsave(&dev_priv->backlight_lock, flags); - /* XXX: transitional, call to make sure freq is set */ - intel_panel_get_max_backlight(connector); - WARN_ON(panel->backlight.max == 0); if (panel->backlight.level == 0) { @@ -1171,28 +1042,24 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = pch_disable_backlight; dev_priv->display.set_backlight = pch_set_backlight; dev_priv->display.get_backlight = pch_get_backlight; - dev_priv->display.get_max_backlight = pch_get_max_backlight; } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.setup_backlight = vlv_setup_backlight; dev_priv->display.enable_backlight = vlv_enable_backlight; dev_priv->display.disable_backlight = vlv_disable_backlight; dev_priv->display.set_backlight = vlv_set_backlight; dev_priv->display.get_backlight = vlv_get_backlight; - dev_priv->display.get_max_backlight = vlv_get_max_backlight; } else if (IS_GEN4(dev)) { dev_priv->display.setup_backlight = i965_setup_backlight; dev_priv->display.enable_backlight = i965_enable_backlight; dev_priv->display.disable_backlight = i965_disable_backlight; dev_priv->display.set_backlight = i9xx_set_backlight; dev_priv->display.get_backlight = i9xx_get_backlight; - dev_priv->display.get_max_backlight = i965_get_max_backlight; } else { dev_priv->display.setup_backlight = i9xx_setup_backlight; dev_priv->display.enable_backlight = i9xx_enable_backlight; dev_priv->display.disable_backlight = i9xx_disable_backlight; dev_priv->display.set_backlight = i9xx_set_backlight; dev_priv->display.get_backlight = i9xx_get_backlight; - dev_priv->display.get_max_backlight = i9xx_get_max_backlight; } } -- cgit v1.2.3 From 565ee3897f0cb1e9b09905747b3784e6605767e8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 13 Nov 2013 12:56:29 +0200 Subject: drm/i915: do not save/restore backlight registers in KMS The backlight enable code now has the smarts to do the right thing. Only do backlight register save/restore in UMS. Some VLV specific code gets dropped as UMS is not supported on VLV. v2: Move save/restore to UMS instead of removing completely (Daniel). Signed-off-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_suspend.c | 45 ------------------------------------- drivers/gpu/drm/i915/i915_ums.c | 27 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 247e922942dd..d069f6ba4286 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -768,8 +768,6 @@ struct i915_suspend_saved_registers { u32 saveBLC_PWM_CTL; u32 saveBLC_PWM_CTL2; u32 saveBLC_HIST_CTL_B; - u32 saveBLC_PWM_CTL_B; - u32 saveBLC_PWM_CTL2_B; u32 saveBLC_CPU_PWM_CTL; u32 saveBLC_CPU_PWM_CTL2; u32 saveFPB0; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index eadf8e19d2c4..6b8fef7fb3bb 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -192,7 +192,6 @@ static void i915_restore_vga(struct drm_device *dev) static void i915_save_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long flags; /* Display arbitration control */ if (INTEL_INFO(dev)->gen <= 4) @@ -203,46 +202,27 @@ static void i915_save_display(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_save_display_reg(dev); - spin_lock_irqsave(&dev_priv->backlight_lock, flags); - /* LVDS state */ if (HAS_PCH_SPLIT(dev)) { dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL); - dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); - dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); - dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL); - dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS); } else if (IS_VALLEYVIEW(dev)) { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->regfile.saveBLC_PWM_CTL = - I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(VLV_BLC_HIST_CTL(PIPE_A)); - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); - dev_priv->regfile.saveBLC_PWM_CTL_B = - I915_READ(VLV_BLC_PWM_CTL(PIPE_B)); dev_priv->regfile.saveBLC_HIST_CTL_B = I915_READ(VLV_BLC_HIST_CTL(PIPE_B)); - dev_priv->regfile.saveBLC_PWM_CTL2_B = - I915_READ(VLV_BLC_PWM_CTL2(PIPE_B)); } else { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); - if (INTEL_INFO(dev)->gen >= 4) - dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); if (IS_MOBILE(dev) && !IS_I830(dev)) dev_priv->regfile.saveLVDS = I915_READ(LVDS); } - spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); - if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev)) dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL); @@ -278,7 +258,6 @@ static void i915_restore_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 mask = 0xffffffff; - unsigned long flags; /* Display arbitration */ if (INTEL_INFO(dev)->gen <= 4) @@ -287,12 +266,6 @@ static void i915_restore_display(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_restore_display_reg(dev); - spin_lock_irqsave(&dev_priv->backlight_lock, flags); - - /* LVDS state */ - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); - if (drm_core_check_feature(dev, DRIVER_MODESET)) mask = ~LVDS_PORT_EN; @@ -305,13 +278,6 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL); if (HAS_PCH_SPLIT(dev)) { - I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL); - I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); - /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2; - * otherwise we get blank eDP screen after S3 on some machines - */ - I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2); - I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL); I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); @@ -319,21 +285,12 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(RSTDBYCTL, dev_priv->regfile.saveMCHBAR_RENDER_STANDBY); } else if (IS_VALLEYVIEW(dev)) { - I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A), - dev_priv->regfile.saveBLC_PWM_CTL); I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A), dev_priv->regfile.saveBLC_HIST_CTL); - I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A), - dev_priv->regfile.saveBLC_PWM_CTL2); - I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B), - dev_priv->regfile.saveBLC_PWM_CTL); I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B), dev_priv->regfile.saveBLC_HIST_CTL); - I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B), - dev_priv->regfile.saveBLC_PWM_CTL2); } else { I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS); - I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL); I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL); I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); @@ -341,8 +298,6 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL); } - spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); - /* only restore FBC info on the platform that supports FBC*/ intel_disable_fbc(dev); if (I915_HAS_FBC(dev)) { diff --git a/drivers/gpu/drm/i915/i915_ums.c b/drivers/gpu/drm/i915/i915_ums.c index 967da4772c44..caa18e855815 100644 --- a/drivers/gpu/drm/i915/i915_ums.c +++ b/drivers/gpu/drm/i915/i915_ums.c @@ -270,6 +270,18 @@ void i915_save_display_reg(struct drm_device *dev) } /* FIXME: regfile.save TV & SDVO state */ + /* Backlight */ + if (HAS_PCH_SPLIT(dev)) { + dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); + dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); + dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL); + dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); + } else { + dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + if (INTEL_INFO(dev)->gen >= 4) + dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); + } + return; } @@ -280,6 +292,21 @@ void i915_restore_display_reg(struct drm_device *dev) int dpll_b_reg, fpb0_reg, fpb1_reg; int i; + /* Backlight */ + if (HAS_PCH_SPLIT(dev)) { + I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL); + I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); + /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2; + * otherwise we get blank eDP screen after S3 on some machines + */ + I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL); + } else { + if (INTEL_INFO(dev)->gen >= 4) + I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL); + } + /* Display port ratios (must be done before clock is set) */ if (SUPPORTS_INTEGRATED_DP(dev)) { I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M); -- cgit v1.2.3 From b378360e8fa4a2f21960747f194c1c7c1f3ae7f9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 14 Nov 2013 11:30:42 +0100 Subject: drm/i915: Use for_each_pipe in intel_display_crc_init We have a nice macro, so use it. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1dbcc64f9ddb..8362dc154af4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3014,10 +3014,10 @@ static struct i915_debugfs_files { void intel_display_crc_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int i; + enum pipe pipe; - for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; + for_each_pipe(pipe) { + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; pipe_crc->opened = false; spin_lock_init(&pipe_crc->lock); -- cgit v1.2.3 From 7eb1c496f7ac0f386552c0cd9144f6965fc61da5 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 14 Nov 2013 11:30:43 +0100 Subject: drm/i915: Reject opening of pipe crc files for invalid pipes We don't init the lock nor set up all the other state. And it doesn't make sense anyway. This appeases lockdep when running the igt/drv_debugfs_reader test. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8362dc154af4..506f8efeb519 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1771,6 +1771,9 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep) struct drm_i915_private *dev_priv = info->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; + if (info->pipe >= INTEL_INFO(info->dev)->num_pipes) + return -ENODEV; + spin_lock_irq(&pipe_crc->lock); if (pipe_crc->opened) { -- cgit v1.2.3 From 89580e3792ee74b4873efbfdd5e2df1c3ae01d67 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 15 Nov 2013 00:13:03 +0800 Subject: staging/lustre/llite: restore ll_fiemap It was removed by coan by mistake when first porting the code. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index fb85a58db058..c5b721c9cffd 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2628,6 +2628,38 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) return ll_getattr_it(mnt, de, &it, stat); } +int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + __u64 start, __u64 len) +{ + int rc; + size_t num_bytes; + struct ll_user_fiemap *fiemap; + unsigned int extent_count = fieinfo->fi_extents_max; + + num_bytes = sizeof(*fiemap) + (extent_count * + sizeof(struct ll_fiemap_extent)); + OBD_ALLOC_LARGE(fiemap, num_bytes); + + if (fiemap == NULL) + return -ENOMEM; + + fiemap->fm_flags = fieinfo->fi_flags; + fiemap->fm_extent_count = fieinfo->fi_extents_max; + fiemap->fm_start = start; + fiemap->fm_length = len; + memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start, + sizeof(struct ll_fiemap_extent)); + + rc = ll_do_fiemap(inode, fiemap, num_bytes); + + fieinfo->fi_flags = fiemap->fm_flags; + fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents; + memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0], + fiemap->fm_mapped_extents * sizeof(struct ll_fiemap_extent)); + + OBD_FREE_LARGE(fiemap, num_bytes); + return rc; +} struct posix_acl * ll_get_acl(struct inode *inode, int type) { @@ -2740,6 +2772,7 @@ struct inode_operations ll_file_inode_operations = { .getxattr = ll_getxattr, .listxattr = ll_listxattr, .removexattr = ll_removexattr, + .fiemap = ll_fiemap, .get_acl = ll_get_acl, }; -- cgit v1.2.3 From c8d6036ae972c7ccfa7cc24e0601f38ccef1bc0b Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 15 Nov 2013 00:13:04 +0800 Subject: staging/lustre: remove lu_target.h It is only needed by server code. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lu_target.h | 91 ----------------------- 1 file changed, 91 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/include/lu_target.h (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lu_target.h b/drivers/staging/lustre/lustre/include/lu_target.h deleted file mode 100644 index 8d48cf4e27ee..000000000000 --- a/drivers/staging/lustre/lustre/include/lu_target.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LUSTRE_LU_TARGET_H -#define _LUSTRE_LU_TARGET_H - -#include -#include - -struct lu_target { - struct obd_device *lut_obd; - struct dt_device *lut_bottom; - /** last_rcvd file */ - struct dt_object *lut_last_rcvd; - /* transaction callbacks */ - struct dt_txn_callback lut_txn_cb; - /** server data in last_rcvd file */ - struct lr_server_data lut_lsd; - /** Server last transaction number */ - __u64 lut_last_transno; - /** Lock protecting last transaction number */ - spinlock_t lut_translock; - /** Lock protecting client bitmap */ - spinlock_t lut_client_bitmap_lock; - /** Bitmap of known clients */ - unsigned long *lut_client_bitmap; -}; - -typedef void (*tgt_cb_t)(struct lu_target *lut, __u64 transno, - void *data, int err); -struct tgt_commit_cb { - tgt_cb_t tgt_cb_func; - void *tgt_cb_data; -}; - -void tgt_boot_epoch_update(struct lu_target *lut); -int tgt_last_commit_cb_add(struct thandle *th, struct lu_target *lut, - struct obd_export *exp, __u64 transno); -int tgt_new_client_cb_add(struct thandle *th, struct obd_export *exp); -int tgt_init(const struct lu_env *env, struct lu_target *lut, - struct obd_device *obd, struct dt_device *dt); -void tgt_fini(const struct lu_env *env, struct lu_target *lut); -int tgt_client_alloc(struct obd_export *exp); -void tgt_client_free(struct obd_export *exp); -int tgt_client_del(const struct lu_env *env, struct obd_export *exp); -int tgt_client_add(const struct lu_env *env, struct obd_export *exp, int); -int tgt_client_new(const struct lu_env *env, struct obd_export *exp); -int tgt_client_data_read(const struct lu_env *env, struct lu_target *tg, - struct lsd_client_data *lcd, loff_t *off, int index); -int tgt_client_data_write(const struct lu_env *env, struct lu_target *tg, - struct lsd_client_data *lcd, loff_t *off, struct thandle *th); -int tgt_server_data_read(const struct lu_env *env, struct lu_target *tg); -int tgt_server_data_write(const struct lu_env *env, struct lu_target *tg, - struct thandle *th); -int tgt_server_data_update(const struct lu_env *env, struct lu_target *tg, int sync); -int tgt_truncate_last_rcvd(const struct lu_env *env, struct lu_target *tg, loff_t off); - -#endif /* __LUSTRE_LU_TARGET_H */ -- cgit v1.2.3 From 28706a78d8fbbce3a2bb0c187063d6540a7e4a88 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 15 Nov 2013 00:13:05 +0800 Subject: staging/lustre: remove llog_server.c It is only used by server. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_net.h | 9 - drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 39 -- drivers/staging/lustre/lustre/ptlrpc/Makefile | 2 +- drivers/staging/lustre/lustre/ptlrpc/llog_server.c | 450 --------------------- 4 files changed, 1 insertion(+), 499 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/ptlrpc/llog_server.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 72edf01b58a2..91f28e363be2 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -3470,15 +3470,6 @@ static inline void ptlrpc_lprocfs_brw(struct ptlrpc_request *req, int bytes) {} #endif /** @} */ -/* ptlrpc/llog_server.c */ -int llog_origin_handle_open(struct ptlrpc_request *req); -int llog_origin_handle_destroy(struct ptlrpc_request *req); -int llog_origin_handle_prev_block(struct ptlrpc_request *req); -int llog_origin_handle_next_block(struct ptlrpc_request *req); -int llog_origin_handle_read_header(struct ptlrpc_request *req); -int llog_origin_handle_close(struct ptlrpc_request *req); -int llog_origin_handle_cancel(struct ptlrpc_request *req); - /* ptlrpc/llog_client.c */ extern struct llog_operations llog_client_ops; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index fde9bcd1d48d..40c58b7ae2ff 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -597,45 +597,6 @@ static int ldlm_callback_handler(struct ptlrpc_request *req) rc = ldlm_handle_setinfo(req); ldlm_callback_reply(req, rc); return 0; - case OBD_LOG_CANCEL: /* remove this eventually - for 1.4.0 compat */ - CERROR("shouldn't be handling OBD_LOG_CANCEL on DLM thread\n"); - req_capsule_set(&req->rq_pill, &RQF_LOG_CANCEL); - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOG_CANCEL_NET)) - return 0; - rc = llog_origin_handle_cancel(req); - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOG_CANCEL_REP)) - return 0; - ldlm_callback_reply(req, rc); - return 0; - case LLOG_ORIGIN_HANDLE_CREATE: - req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE); - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET)) - return 0; - rc = llog_origin_handle_open(req); - ldlm_callback_reply(req, rc); - return 0; - case LLOG_ORIGIN_HANDLE_NEXT_BLOCK: - req_capsule_set(&req->rq_pill, - &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK); - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET)) - return 0; - rc = llog_origin_handle_next_block(req); - ldlm_callback_reply(req, rc); - return 0; - case LLOG_ORIGIN_HANDLE_READ_HEADER: - req_capsule_set(&req->rq_pill, - &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER); - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET)) - return 0; - rc = llog_origin_handle_read_header(req); - ldlm_callback_reply(req, rc); - return 0; - case LLOG_ORIGIN_HANDLE_CLOSE: - if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET)) - return 0; - rc = llog_origin_handle_close(req); - ldlm_callback_reply(req, rc); - return 0; case OBD_QC_CALLBACK: req_capsule_set(&req->rq_pill, &RQF_QC_CALLBACK); if (OBD_FAIL_CHECK(OBD_FAIL_OBD_QC_CALLBACK_NET)) diff --git a/drivers/staging/lustre/lustre/ptlrpc/Makefile b/drivers/staging/lustre/lustre/ptlrpc/Makefile index 6d78b80487f2..2ec0c24ff38b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/Makefile +++ b/drivers/staging/lustre/lustre/ptlrpc/Makefile @@ -10,7 +10,7 @@ ldlm_objs += $(LDLM)ldlm_pool.o ldlm_objs += $(LDLM)interval_tree.o ptlrpc_objs := client.o recover.o connection.o niobuf.o pack_generic.o ptlrpc_objs += events.o ptlrpc_module.o service.o pinger.o -ptlrpc_objs += llog_net.o llog_client.o llog_server.o import.o ptlrpcd.o +ptlrpc_objs += llog_net.o llog_client.o import.o ptlrpcd.o ptlrpc_objs += pers.o lproc_ptlrpc.o wiretest.o layout.o ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o sec_lproc.o ptlrpc_objs += sec_null.o sec_plain.o nrs.o nrs_fifo.o diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c deleted file mode 100644 index af9d2ac391ef..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/ptlrpc/llog_server.c - * - * remote api for llog - server side - * - * Author: Andreas Dilger - */ - -#define DEBUG_SUBSYSTEM S_LOG - - -#include -#include -#include -#include - -#if defined(LUSTRE_LOG_SERVER) -static int llog_origin_close(const struct lu_env *env, struct llog_handle *lgh) -{ - if (lgh->lgh_hdr != NULL && lgh->lgh_hdr->llh_flags & LLOG_F_IS_CAT) - return llog_cat_close(env, lgh); - else - return llog_close(env, lgh); -} - -/* Only open is supported, no new llog can be created remotely */ -int llog_origin_handle_open(struct ptlrpc_request *req) -{ - struct obd_export *exp = req->rq_export; - struct obd_device *obd = exp->exp_obd; - struct obd_device *disk_obd; - struct lvfs_run_ctxt saved; - struct llog_handle *loghandle; - struct llogd_body *body; - struct llog_logid *logid = NULL; - struct llog_ctxt *ctxt; - char *name = NULL; - int rc; - - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); - if (body == NULL) - return -EFAULT; - - if (ostid_id(&body->lgd_logid.lgl_oi) > 0) - logid = &body->lgd_logid; - - if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) { - name = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - if (name == NULL) - return -EFAULT; - CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name); - } - - ctxt = llog_get_context(obd, body->lgd_ctxt_idx); - if (ctxt == NULL) { - CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n", - obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name); - return -ENODEV; - } - disk_obd = ctxt->loc_exp->exp_obd; - push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - - rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle, logid, - name, LLOG_OPEN_EXISTS); - if (rc) - GOTO(out_pop, rc); - - rc = req_capsule_server_pack(&req->rq_pill); - if (rc) - GOTO(out_close, rc = -ENOMEM); - - body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); - body->lgd_logid = loghandle->lgh_id; - -out_close: - llog_origin_close(req->rq_svc_thread->t_env, loghandle); -out_pop: - pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - llog_ctxt_put(ctxt); - return rc; -} -EXPORT_SYMBOL(llog_origin_handle_open); - -int llog_origin_handle_destroy(struct ptlrpc_request *req) -{ - struct obd_device *disk_obd; - struct lvfs_run_ctxt saved; - struct llogd_body *body; - struct llog_logid *logid = NULL; - struct llog_ctxt *ctxt; - int rc; - - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); - if (body == NULL) - return -EFAULT; - - if (ostid_id(&body->lgd_logid.lgl_oi) > 0) - logid = &body->lgd_logid; - - if (!(body->lgd_llh_flags & LLOG_F_IS_PLAIN)) - CERROR("%s: wrong llog flags %x\n", - req->rq_export->exp_obd->obd_name, body->lgd_llh_flags); - - ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx); - if (ctxt == NULL) - return -ENODEV; - - disk_obd = ctxt->loc_exp->exp_obd; - push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - - rc = req_capsule_server_pack(&req->rq_pill); - /* erase only if no error and logid is valid */ - if (rc == 0) - rc = llog_erase(req->rq_svc_thread->t_env, ctxt, logid, NULL); - pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - llog_ctxt_put(ctxt); - return rc; -} -EXPORT_SYMBOL(llog_origin_handle_destroy); - -int llog_origin_handle_next_block(struct ptlrpc_request *req) -{ - struct obd_device *disk_obd; - struct llog_handle *loghandle; - struct llogd_body *body; - struct llogd_body *repbody; - struct lvfs_run_ctxt saved; - struct llog_ctxt *ctxt; - __u32 flags; - void *ptr; - int rc; - - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); - if (body == NULL) - return -EFAULT; - - ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx); - if (ctxt == NULL) - return -ENODEV; - - disk_obd = ctxt->loc_exp->exp_obd; - push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - - rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle, - &body->lgd_logid, NULL, LLOG_OPEN_EXISTS); - if (rc) - GOTO(out_pop, rc); - - flags = body->lgd_llh_flags; - rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags, - NULL); - if (rc) - GOTO(out_close, rc); - - req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, - LLOG_CHUNK_SIZE); - rc = req_capsule_server_pack(&req->rq_pill); - if (rc) - GOTO(out_close, rc = -ENOMEM); - - repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); - *repbody = *body; - - ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA); - rc = llog_next_block(req->rq_svc_thread->t_env, loghandle, - &repbody->lgd_saved_index, repbody->lgd_index, - &repbody->lgd_cur_offset, ptr, LLOG_CHUNK_SIZE); - if (rc) - GOTO(out_close, rc); -out_close: - llog_origin_close(req->rq_svc_thread->t_env, loghandle); -out_pop: - pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - llog_ctxt_put(ctxt); - return rc; -} -EXPORT_SYMBOL(llog_origin_handle_next_block); - -int llog_origin_handle_prev_block(struct ptlrpc_request *req) -{ - struct llog_handle *loghandle; - struct llogd_body *body; - struct llogd_body *repbody; - struct obd_device *disk_obd; - struct lvfs_run_ctxt saved; - struct llog_ctxt *ctxt; - __u32 flags; - void *ptr; - int rc; - - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); - if (body == NULL) - return -EFAULT; - - ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx); - if (ctxt == NULL) - return -ENODEV; - - disk_obd = ctxt->loc_exp->exp_obd; - push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - - rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle, - &body->lgd_logid, NULL, LLOG_OPEN_EXISTS); - if (rc) - GOTO(out_pop, rc); - - flags = body->lgd_llh_flags; - rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags, - NULL); - if (rc) - GOTO(out_close, rc); - - req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, - LLOG_CHUNK_SIZE); - rc = req_capsule_server_pack(&req->rq_pill); - if (rc) - GOTO(out_close, rc = -ENOMEM); - - repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); - *repbody = *body; - - ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA); - rc = llog_prev_block(req->rq_svc_thread->t_env, loghandle, - body->lgd_index, ptr, LLOG_CHUNK_SIZE); - if (rc) - GOTO(out_close, rc); - -out_close: - llog_origin_close(req->rq_svc_thread->t_env, loghandle); -out_pop: - pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - llog_ctxt_put(ctxt); - return rc; -} -EXPORT_SYMBOL(llog_origin_handle_prev_block); - -int llog_origin_handle_read_header(struct ptlrpc_request *req) -{ - struct obd_device *disk_obd; - struct llog_handle *loghandle; - struct llogd_body *body; - struct llog_log_hdr *hdr; - struct lvfs_run_ctxt saved; - struct llog_ctxt *ctxt; - __u32 flags; - int rc; - - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); - if (body == NULL) - return -EFAULT; - - ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx); - if (ctxt == NULL) - return -ENODEV; - - disk_obd = ctxt->loc_exp->exp_obd; - push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - - rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle, - &body->lgd_logid, NULL, LLOG_OPEN_EXISTS); - if (rc) - GOTO(out_pop, rc); - - /* - * llog_init_handle() reads the llog header - */ - flags = body->lgd_llh_flags; - rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags, - NULL); - if (rc) - GOTO(out_close, rc); - flags = loghandle->lgh_hdr->llh_flags; - - rc = req_capsule_server_pack(&req->rq_pill); - if (rc) - GOTO(out_close, rc = -ENOMEM); - - hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR); - *hdr = *loghandle->lgh_hdr; -out_close: - llog_origin_close(req->rq_svc_thread->t_env, loghandle); -out_pop: - pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - llog_ctxt_put(ctxt); - return rc; -} -EXPORT_SYMBOL(llog_origin_handle_read_header); - -int llog_origin_handle_close(struct ptlrpc_request *req) -{ - /* Nothing to do */ - return 0; -} -EXPORT_SYMBOL(llog_origin_handle_close); - -int llog_origin_handle_cancel(struct ptlrpc_request *req) -{ - int num_cookies, rc = 0, err, i, failed = 0; - struct obd_device *disk_obd; - struct llog_cookie *logcookies; - struct llog_ctxt *ctxt = NULL; - struct lvfs_run_ctxt saved; - struct llog_handle *cathandle; - struct inode *inode; - void *handle; - - logcookies = req_capsule_client_get(&req->rq_pill, &RMF_LOGCOOKIES); - num_cookies = req_capsule_get_size(&req->rq_pill, &RMF_LOGCOOKIES, - RCL_CLIENT) / sizeof(*logcookies); - if (logcookies == NULL || num_cookies == 0) { - DEBUG_REQ(D_HA, req, "No llog cookies sent"); - return -EFAULT; - } - - ctxt = llog_get_context(req->rq_export->exp_obd, - logcookies->lgc_subsys); - if (ctxt == NULL) - return -ENODEV; - - disk_obd = ctxt->loc_exp->exp_obd; - push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - for (i = 0; i < num_cookies; i++, logcookies++) { - cathandle = ctxt->loc_handle; - LASSERT(cathandle != NULL); - inode = cathandle->lgh_file->f_dentry->d_inode; - - handle = fsfilt_start_log(disk_obd, inode, - FSFILT_OP_CANCEL_UNLINK, NULL, 1); - if (IS_ERR(handle)) { - CERROR("fsfilt_start_log() failed: %ld\n", - PTR_ERR(handle)); - GOTO(pop_ctxt, rc = PTR_ERR(handle)); - } - - rc = llog_cat_cancel_records(req->rq_svc_thread->t_env, - cathandle, 1, logcookies); - - /* - * Do not raise -ENOENT errors for resent rpcs. This rec already - * might be killed. - */ - if (rc == -ENOENT && - (lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT)) { - /* - * Do not change this message, reply-single.sh test_59b - * expects to find this in log. - */ - CDEBUG(D_RPCTRACE, "RESENT cancel req %p - ignored\n", - req); - rc = 0; - } else if (rc == 0) { - CDEBUG(D_RPCTRACE, "Canceled %d llog-records\n", - num_cookies); - } - - err = fsfilt_commit(disk_obd, inode, handle, 0); - if (err) { - CERROR("Error committing transaction: %d\n", err); - if (!rc) - rc = err; - failed++; - GOTO(pop_ctxt, rc); - } else if (rc) - failed++; - } - GOTO(pop_ctxt, rc); -pop_ctxt: - pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); - if (rc) - CERROR("Cancel %d of %d llog-records failed: %d\n", - failed, num_cookies, rc); - - llog_ctxt_put(ctxt); - return rc; -} -EXPORT_SYMBOL(llog_origin_handle_cancel); - -#else /* !__KERNEL__ */ -int llog_origin_handle_open(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} - -int llog_origin_handle_destroy(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} - -int llog_origin_handle_next_block(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} -int llog_origin_handle_prev_block(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} -int llog_origin_handle_read_header(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} -int llog_origin_handle_close(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} -int llog_origin_handle_cancel(struct ptlrpc_request *req) -{ - LBUG(); - return 0; -} -#endif -- cgit v1.2.3 From ea1db0814cbcf5e68ec948723d519f6a04e5e3f3 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Fri, 15 Nov 2013 00:13:08 +0800 Subject: staging/lustre/llite: use correct FID in ll_och_fill() When ll_intent_file_open() is called on a file with a stale dentry, ll_och_fill() may incorrectly use the FID from the struct ll_inode_info rather than the FID from the response body (which is the correct FID for the close). Fix this, remove the ll_inode_info parameter from ll_och_fill(), and move the call to ll_ioepoch_open() from ll_och_fill() to ll_local_open(). Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3233 Lustre-change: http://review.whamcloud.com/6695 Signed-off-by: John L. Hammond Reviewed-by: Fan Yong Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c5b721c9cffd..bfa6b0e97fff 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -431,22 +431,17 @@ void ll_ioepoch_open(struct ll_inode_info *lli, __u64 ioepoch) } } -static int ll_och_fill(struct obd_export *md_exp, struct ll_inode_info *lli, - struct lookup_intent *it, struct obd_client_handle *och) +static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it, + struct obd_client_handle *och) { struct ptlrpc_request *req = it->d.lustre.it_data; struct mdt_body *body; - LASSERT(och); - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - LASSERT(body != NULL); /* reply already checked out */ - - memcpy(&och->och_fh, &body->handle, sizeof(body->handle)); + och->och_fh = body->handle; + och->och_fid = body->fid1; och->och_magic = OBD_CLIENT_HANDLE_MAGIC; - och->och_fid = lli->lli_fid; och->och_flags = it->it_flags; - ll_ioepoch_open(lli, body->ioepoch); return md_set_open_replay_data(md_exp, och, req); } @@ -466,15 +461,12 @@ int ll_local_open(struct file *file, struct lookup_intent *it, struct mdt_body *body; int rc; - rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, lli, it, och); - if (rc) + rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och); + if (rc != 0) return rc; body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if ((it->it_flags & FMODE_WRITE) && - (body->valid & OBD_MD_FLSIZE)) - CDEBUG(D_INODE, "Epoch "LPU64" opened on "DFID"\n", - lli->lli_ioepoch, PFID(&lli->lli_fid)); + ll_ioepoch_open(lli, body->ioepoch); } LUSTRE_FPRIVATE(file) = fd; @@ -1482,8 +1474,7 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it) if (!och) GOTO(out, rc = -ENOMEM); - ll_och_fill(ll_i2sbi(inode)->ll_md_exp, - ll_i2info(inode), it, och); + ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och); rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och); -- cgit v1.2.3 From aa363d6a1c2c3e8260d9ec3f88bbecebcf276b2c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 15 Nov 2013 00:13:15 +0800 Subject: staging/lustre/autoconf: remove vectored fops tests file_operations.readv/writev have been removed since v2.6.19 We can remove the test and the dead code. Lustre-change: http://review.whamcloud.com/5343 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2800 Signed-off-by: Jeff Mahoney Signed-off-by: James Simmons Reviewed-by: Bob Glossman Reviewed-by: Christopher J. Morrone Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index bfa6b0e97fff..17064b4f6176 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2699,17 +2699,12 @@ int ll_inode_permission(struct inode *inode, int mask) return rc; } -#define READ_METHOD aio_read -#define READ_FUNCTION ll_file_aio_read -#define WRITE_METHOD aio_write -#define WRITE_FUNCTION ll_file_aio_write - /* -o localflock - only provides locally consistent flock locks */ struct file_operations ll_file_operations = { .read = ll_file_read, - .READ_METHOD = READ_FUNCTION, + .aio_read = ll_file_aio_read, .write = ll_file_write, - .WRITE_METHOD = WRITE_FUNCTION, + .aio_write = ll_file_aio_write, .unlocked_ioctl = ll_file_ioctl, .open = ll_file_open, .release = ll_file_release, @@ -2722,9 +2717,9 @@ struct file_operations ll_file_operations = { struct file_operations ll_file_operations_flock = { .read = ll_file_read, - .READ_METHOD = READ_FUNCTION, + .aio_read = ll_file_aio_read, .write = ll_file_write, - .WRITE_METHOD = WRITE_FUNCTION, + .aio_write = ll_file_aio_write, .unlocked_ioctl = ll_file_ioctl, .open = ll_file_open, .release = ll_file_release, @@ -2740,9 +2735,9 @@ struct file_operations ll_file_operations_flock = { /* These are for -o noflock - to return ENOSYS on flock calls */ struct file_operations ll_file_operations_noflock = { .read = ll_file_read, - .READ_METHOD = READ_FUNCTION, + .aio_read = ll_file_aio_read, .write = ll_file_write, - .WRITE_METHOD = WRITE_FUNCTION, + .aio_write = ll_file_aio_write, .unlocked_ioctl = ll_file_ioctl, .open = ll_file_open, .release = ll_file_release, -- cgit v1.2.3 From c7c99012dd68feaebd7f6e0df9251bb62e184e9a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 15 Nov 2013 00:13:16 +0800 Subject: staging/lustre/autoconf: remove LIBCFS_HAVE_IS_COMPAT_TASK test is_compat_task has been defined on all arches since v2.6.29. We can remove the test and dead code. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2800 Lustre-change: http://review.whamcloud.com/5393 Signed-off-by: Jeff Mahoney Signed-off-by: James Simmons Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/curproc.h | 1 - drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c | 13 ------------- drivers/staging/lustre/lustre/llite/llite_internal.h | 3 ++- 3 files changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/curproc.h b/drivers/staging/lustre/include/linux/libcfs/curproc.h index de8e35b796ab..507d16b9213c 100644 --- a/drivers/staging/lustre/include/linux/libcfs/curproc.h +++ b/drivers/staging/lustre/include/linux/libcfs/curproc.h @@ -61,7 +61,6 @@ int cfs_curproc_groups_nr(void); */ /* check if task is running in compat mode.*/ -int current_is_32bit(void); #define current_pid() (current->pid) #define current_comm() (current->comm) int cfs_get_environ(const char *key, char *value, int *val_len); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c index 0bf8e5d87f1a..a2ef64c3403d 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c @@ -140,18 +140,6 @@ int cfs_capable(cfs_cap_t cap) return capable(cfs_cap_unpack(cap)); } -/* Check if task is running in 32-bit API mode, for the purpose of - * userspace binary interfaces. On 32-bit Linux this is (unfortunately) - * always true, even if the application is using LARGEFILE64 and 64-bit - * APIs, because Linux provides no way for the filesystem to know if it - * is called via 32-bit or 64-bit APIs. Other clients may vary. On - * 64-bit systems, this will only be true if the binary is calling a - * 32-bit system call. */ -int current_is_32bit(void) -{ - return is_compat_task(); -} - static int cfs_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) { @@ -311,7 +299,6 @@ EXPORT_SYMBOL(cfs_cap_raised); EXPORT_SYMBOL(cfs_curproc_cap_pack); EXPORT_SYMBOL(cfs_curproc_cap_unpack); EXPORT_SYMBOL(cfs_capable); -EXPORT_SYMBOL(current_is_32bit); /* * Local variables: diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index fb7cbb5fa124..d37c183109ba 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -46,6 +46,7 @@ #include #include #include +#include #ifndef FMODE_EXEC #define FMODE_EXEC 0 @@ -643,7 +644,7 @@ static inline int ll_need_32bit_api(struct ll_sb_info *sbi) #if BITS_PER_LONG == 32 return 1; #else - return unlikely(current_is_32bit() || (sbi->ll_flags & LL_SBI_32BIT_API)); + return unlikely(is_compat_task() || (sbi->ll_flags & LL_SBI_32BIT_API)); #endif } -- cgit v1.2.3 From 2a0f0eacd7d75e8fa79d642aa85bcf7c681187a7 Mon Sep 17 00:00:00 2001 From: Li Xi Date: Fri, 15 Nov 2013 00:13:17 +0800 Subject: staging/lustre/llog: fix return value of llog_alloc_handle llog_open() calls llog_alloc_handle() taking NULL as the error return value. But llog_alloc_handle() returns ERR_PTR(-ENOMEM) instead when error. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3470 Lustre-change: http://review.whamcloud.com/6644 Signed-off-by: Li Xi Reviewed-by: Mike Pershin Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/llog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 0cb44287502b..b4dad344b72a 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -62,7 +62,7 @@ struct llog_handle *llog_alloc_handle(void) OBD_ALLOC_PTR(loghandle); if (loghandle == NULL) - return ERR_PTR(-ENOMEM); + return NULL; init_rwsem(&loghandle->lgh_lock); spin_lock_init(&loghandle->lgh_hdr_lock); -- cgit v1.2.3 From f3b2734f4bcc0093f1e7b49d658ae8353c86d32d Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Fri, 15 Nov 2013 00:13:18 +0800 Subject: staging/lustre/lov: convert magic to host-endian in lov_dump_lmm() In lov_dump_lmm(), convert the lmm_magic from little-endian to host-endian byte order before the switch statement, as the other lov_dump_xxx() and lov_verify_xxx() functions already do. Remove the unused macro LMM_ASSERT(). Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3297 Lustre-change: http://review.whamcloud.com/6290 Signed-off-by: John L. Hammond Reviewed-by: Li Wei Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_pack.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index ec6f6e0572ae..27ed27e6fa6a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -105,24 +105,22 @@ void lov_dump_lmm(int level, void *lmm) { int magic; - magic = ((struct lov_mds_md_v1 *)(lmm))->lmm_magic; + magic = le32_to_cpu(((struct lov_mds_md *)lmm)->lmm_magic); switch (magic) { case LOV_MAGIC_V1: - return lov_dump_lmm_v1(level, (struct lov_mds_md_v1 *)(lmm)); + lov_dump_lmm_v1(level, (struct lov_mds_md_v1 *)lmm); + break; case LOV_MAGIC_V3: - return lov_dump_lmm_v3(level, (struct lov_mds_md_v3 *)(lmm)); + lov_dump_lmm_v3(level, (struct lov_mds_md_v3 *)lmm); + break; default: - CERROR("Cannot recognize lmm_magic %x", magic); + CDEBUG(level, "unrecognized lmm_magic %x, assuming %x\n", + magic, LOV_MAGIC_V1); + lov_dump_lmm_common(level, lmm); + break; } - return; } -#define LMM_ASSERT(test) \ -do { \ - if (!(test)) lov_dump_lmm(D_ERROR, lmm); \ - LASSERT(test); /* so we know what assertion failed */ \ -} while (0) - /* Pack LOV object metadata for disk storage. It is packed in LE byte * order and is opaque to the networking layer. * -- cgit v1.2.3 From 86c17c0b5eed0bb4e1e61d5889a80f56bf59c93f Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sat, 2 Nov 2013 10:05:30 +0530 Subject: staging:dwc2:hcd_queue.c : cleanups to the microframe scheduler code This patch takes up the task mentioned in the TODO file of dwc2 to cleanup the microframe scheduler code. The while(!done) loops have been replaced with appropriate for loops and unnecessary variables like done and ret have been removed. Signed-off-by: Himangi Saraogi Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_queue.c | 90 ++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c index f200f1f6e1c6..2f68fbc08827 100644 --- a/drivers/staging/dwc2/hcd_queue.c +++ b/drivers/staging/dwc2/hcd_queue.c @@ -344,25 +344,17 @@ void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg) static int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { unsigned short utime = qh->usecs; - int done = 0; - int i = 0; - int ret = -1; + int i; - while (!done) { + for (i = 0; i < 8; i++) { /* At the start hsotg->frame_usecs[i] = max_uframe_usecs[i] */ if (utime <= hsotg->frame_usecs[i]) { hsotg->frame_usecs[i] -= utime; qh->frame_usecs[i] += utime; - ret = i; - done = 1; - } else { - i++; - if (i == 8) - done = 1; + return i; } } - - return ret; + return -1; } /* @@ -372,21 +364,14 @@ static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { unsigned short utime = qh->usecs; unsigned short xtime; - int t_left = utime; - int done = 0; - int i = 0; + int t_left; + int i; int j; - int ret = -1; - - while (!done) { - if (hsotg->frame_usecs[i] <= 0) { - i++; - if (i == 8) { - ret = -1; - done = 1; - } + int k; + + for (i = 0; i < 8; i++) { + if (hsotg->frame_usecs[i] <= 0) continue; - } /* * we need n consecutive slots so use j as a start slot @@ -400,50 +385,35 @@ static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) */ if (xtime + hsotg->frame_usecs[j] < utime) { if (hsotg->frame_usecs[j] < - max_uframe_usecs[j]) { - ret = -1; - break; - } + max_uframe_usecs[j]) + continue; } if (xtime >= utime) { - ret = i; - break; + t_left = utime; + for (k = i; k < 8; k++) { + t_left -= hsotg->frame_usecs[k]; + if (t_left <= 0) { + qh->frame_usecs[k] += + hsotg->frame_usecs[k] + + t_left; + hsotg->frame_usecs[k] = -t_left; + return i; + } else { + qh->frame_usecs[k] += + hsotg->frame_usecs[k]; + hsotg->frame_usecs[k] = 0; + } + } } /* add the frame time to x time */ xtime += hsotg->frame_usecs[j]; /* we must have a fully available next frame or break */ if (xtime < utime && - hsotg->frame_usecs[j] == max_uframe_usecs[j]) { - ret = -1; - break; - } - } - if (ret >= 0) { - t_left = utime; - for (j = i; t_left > 0 && j < 8; j++) { - t_left -= hsotg->frame_usecs[j]; - if (t_left <= 0) { - qh->frame_usecs[j] += - hsotg->frame_usecs[j] + t_left; - hsotg->frame_usecs[j] = -t_left; - ret = i; - done = 1; - } else { - qh->frame_usecs[j] += - hsotg->frame_usecs[j]; - hsotg->frame_usecs[j] = 0; - } - } - } else { - i++; - if (i == 8) { - ret = -1; - done = 1; - } + hsotg->frame_usecs[j] == max_uframe_usecs[j]) + continue; } } - - return ret; + return -1; } static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) -- cgit v1.2.3 From c4dd0d01da8979bd5c7f4367661115617bc389ea Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 13 Nov 2013 11:05:10 +0100 Subject: ath10k: allow dynamic bandwidth in hw rate control Frames were never retransmitted with different/lower bandwidths, e.g. only 80MHz bandwidth was used when dealing with a VHT80 peer. Allow HW rate control to try out different bandwidths when retransmitting. This increases robustness. Also, document the parameter properly. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 56f030ed357a..db819429134a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1964,7 +1964,7 @@ static int ath10k_start(struct ieee80211_hw *hw) ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", ret); - ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 0); + ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1); if (ret) ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 81e33a7dbaf2..8b824f9c2f1e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -2234,7 +2234,12 @@ enum wmi_pdev_param { * 0: no protection 1:use CTS-to-self 2: use RTS/CTS */ WMI_PDEV_PARAM_PROTECTION_MODE, - /* Dynamic bandwidth 0: disable 1: enable */ + /* + * Dynamic bandwidth - 0: disable, 1: enable + * + * When enabled HW rate control tries different bandwidths when + * retransmitting frames. + */ WMI_PDEV_PARAM_DYNAMIC_BW, /* Non aggregrate/ 11g sw retry threshold.0-disable */ WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, -- cgit v1.2.3 From 652de35e86da3e206fbfa40bca254b028b6403b6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Nov 2013 15:23:30 +0200 Subject: ath10k: remove htt rx amsdu clear retry bit hack With commit 0cfcefef1 ("mac80211: support reporting A-MSDU subframes individually") there's no need to have the hack to clear the retry bit in ath10k_htt_rx_amsdu(), mac80211 can handle this properly now. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 1 + drivers/net/wireless/ath/ath10k/htt_rx.c | 20 +++----------------- drivers/net/wireless/ath/ath10k/txrx.c | 3 +++ 3 files changed, 7 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 1a337e93b7e9..7fc7919ea5f5 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1182,6 +1182,7 @@ struct htt_rx_info { u32 info2; } rate; bool fcs_err; + bool amsdu_more; }; struct ath10k_htt { diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 90d4f74c28d7..0335218ad579 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -659,23 +659,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, memcpy(hdr_buf, hdr, hdr_len); hdr = (struct ieee80211_hdr *)hdr_buf; - /* FIXME: Hopefully this is a temporary measure. - * - * Reporting individual A-MSDU subframes means each reported frame - * shares the same sequence number. - * - * mac80211 drops frames it recognizes as duplicates, i.e. - * retransmission flag is set and sequence number matches sequence - * number from a previous frame (as per IEEE 802.11-2012: 9.3.2.10 - * "Duplicate detection and recovery") - * - * To avoid frames being dropped clear retransmission flag for all - * received A-MSDUs. - * - * Worst case: actual duplicate frames will be reported but this should - * still be handled gracefully by other OSI/ISO layers. */ - hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_RETRY); - first = skb; while (skb) { void *decap_hdr; @@ -746,6 +729,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, skb = skb->next; info->skb->next = NULL; + if (skb) + info->amsdu_more = true; + ath10k_process_rx(htt->ar, info); } diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index c511f919d541..df279a31e189 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -236,6 +236,9 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) if (info->fcs_err) status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (info->amsdu_more) + status->flag |= RX_FLAG_AMSDU_MORE; + status->signal = info->signal; spin_lock_bh(&ar->data_lock); -- cgit v1.2.3 From 71098615730f01cd5e70c7777b691572ee2bafb0 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Thu, 14 Nov 2013 09:01:15 +0100 Subject: ath10k: expand the wmi mgmt queue limit to 128 It was obseverd many times the short queue limit can be easily exceeded in case of AP multiple BSSID scenarios. "ath10k: wmi mgmt_tx queue limit reached." This was leading to TX packets drops. This patch expands the queue limit to 128. After many stress experiments (high traffic and lot of management frames in the air) the new value seems to fix the problem on platforms with limited resources. Reported-By: Tomasz Skapski Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 0934f7633de3..be35df2902c4 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -43,7 +43,7 @@ /* Antenna noise floor */ #define ATH10K_DEFAULT_NOISE_FLOOR -95 -#define ATH10K_MAX_NUM_MGMT_PENDING 16 +#define ATH10K_MAX_NUM_MGMT_PENDING 128 struct ath10k; -- cgit v1.2.3 From 5d04e4120a6ef2eac3a3a80bda6a16bb90f2da2c Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 14 Nov 2013 10:34:18 +0100 Subject: ath10k: clear tx status before submitting to mac80211 Garbage was reported in ieee80211_tx_info. This led to a WARN_ON in cfg80211_calculate_bitrate(). This also fixes some random tx bitrate values reported through `iw` command. Reported-By: Kalle Valo Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/txrx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index df279a31e189..d476b2cc9d78 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -75,6 +75,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ath10k_report_offchan_tx(htt->ar, msdu); info = IEEE80211_SKB_CB(msdu); + memset(info, 0, sizeof(*info)); if (tx_done->discard) { ieee80211_free_txskb(htt->ar->hw, msdu); -- cgit v1.2.3 From 4aeebd7443e36b0a40032e518a9338f48bd27efc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 31 Oct 2013 09:53:36 +0100 Subject: drm/i915: dp aux irq support for g4x/vlv Now we have this everywhere. Next up would be to wire up the DP hotplug pin to speed up panel power sequencing for eDP panels ... I've decided to leave the has_aux_irq logic in the code, it should come handy for hw bringup. For testing/fail-safety the dp aux code already has a timeout when waiting for interrupts to signal completion and screams rather loud if they don't arrive in time. Given that we need a real piece of hw to talk to anyway this is probably as good as it gets. v2: Don't check the dp aux channel bits on i965 machines, they have a different meaning there. Yay for reusing bits at will! Spotted by Jani. Cc: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 7 +++++++ drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_dp.c | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 931ee5d8cdb1..271560080ad5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1472,6 +1472,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915); + if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) + dp_aux_irq_handler(dev); + I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_READ(PORT_HOTPLUG_STAT); } @@ -3653,6 +3656,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) intel_hpd_irq_handler(dev, hotplug_trigger, IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915); + if (IS_G4X(dev) && + (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)) + dp_aux_irq_handler(dev); + I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_READ(PORT_HOTPLUG_STAT); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 849e595ed19d..04d46b23d97c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2131,6 +2131,10 @@ #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +#define DP_AUX_CHANNEL_D_INT_STATUS_G4X (1 << 6) +#define DP_AUX_CHANNEL_C_INT_STATUS_G4X (1 << 5) +#define DP_AUX_CHANNEL_B_INT_STATUS_G4X (1 << 4) +#define DP_AUX_CHANNEL_MASK_INT_STATUS_G4X (1 << 4) /* SDVO is different across gen3/4 */ #define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) #define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dbe4840d6fb8..3b22e726585e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, int i, ret, recv_bytes; uint32_t status; int try, precharge, clock = 0; - bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev); + bool has_aux_irq = true; uint32_t timeout; /* dp aux is extremely sensitive to irq latency, hence request the -- cgit v1.2.3 From 6e555e2752ea284bda55b0ee477a512e1525b84a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 1 Nov 2013 11:26:43 +0200 Subject: OMAPDSS: fix omap2 dss fck handling The driver considers OMAP2 DSS's functional clock as a fixed clock. However, it can be changed, but the possible dividers are not continuous which is why it was just handled as a fixed clock. As a partial fix, this patch changes the code to handle the continous part of the dividers, from 1 to 6. This let's us handle the OMAP2 fck the same way as fcks on other OMAPs. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index bd01608e67e2..e59577a2c41c 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -484,11 +484,6 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) unsigned m; if (dss.dpll4_m4_ck == NULL) { - /* - * TODO: dss1_fclk can be changed on OMAP2, but the available - * dividers are not continuous. We just use the pre-set rate for - * now. - */ fck = clk_get_rate(dss.dss_clk); fckd = 1; return func(fckd, fck, data); @@ -761,9 +756,13 @@ void dss_debug_dump_clocks(struct seq_file *s) #endif static const struct dss_features omap24xx_dss_feats __initconst = { - .fck_div_max = 16, + /* + * fck div max is really 16, but the divider range has gaps. The range + * from 1 to 6 has no gaps, so let's use that as a max. + */ + .fck_div_max = 6, .dss_fck_multiplier = 2, - .clk_name = NULL, + .clk_name = "dss1_fck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; -- cgit v1.2.3 From d0f58bd3bba3877fb1af4664c4e33273d36f00e4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 31 Oct 2013 14:44:23 +0200 Subject: OMAPDSS: remove struct dss_clock_info Remove struct dss_clock_info, as it is not usable in a case where DSS fclk comes from a dedicated PLL. Instead, just use the fclk rate in place of dss_clock_info, as that is all that's needed. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dpi.c | 13 +++++----- drivers/video/omap2/dss/dss.c | 59 ++++++++++--------------------------------- drivers/video/omap2/dss/dss.h | 13 ++-------- drivers/video/omap2/dss/sdi.c | 19 +++++++------- 4 files changed, 30 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index bd48cde53561..16acdddc94e3 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -117,7 +117,7 @@ struct dpi_clk_calc_ctx { /* outputs */ struct dsi_clock_info dsi_cinfo; - struct dss_clock_info dss_cinfo; + unsigned long long fck; struct dispc_clock_info dispc_cinfo; }; @@ -184,12 +184,11 @@ static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint, dpi_calc_hsdiv_cb, ctx); } -static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) +static bool dpi_calc_dss_cb(unsigned long fck, void *data) { struct dpi_clk_calc_ctx *ctx = data; - ctx->dss_cinfo.fck = fck; - ctx->dss_cinfo.fck_div = fckd; + ctx->fck = fck; return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, dpi_calc_dispc_cb, ctx); @@ -286,13 +285,13 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, if (!ok) return -EINVAL; - r = dss_set_clock_div(&ctx.dss_cinfo); + r = dss_set_fck_rate(ctx.fck); if (r) return r; dpi.mgr_config.clock_info = ctx.dispc_cinfo; - *fck = ctx.dss_cinfo.fck; + *fck = ctx.fck; *lck_div = ctx.dispc_cinfo.lck_div; *pck_div = ctx.dispc_cinfo.pck_div; @@ -495,7 +494,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev, if (!ok) return -EINVAL; - fck = ctx.dss_cinfo.fck; + fck = ctx.fck; } lck_div = ctx.dispc_cinfo.lck_div; diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index e59577a2c41c..c37d934e1a57 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -81,7 +81,6 @@ static struct { unsigned long cache_req_pck; unsigned long cache_prate; - struct dss_clock_info cache_dss_cinfo; struct dispc_clock_info cache_dispc_cinfo; enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; @@ -451,29 +450,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) } } -/* calculate clock rates using dividers in cinfo */ -int dss_calc_clock_rates(struct dss_clock_info *cinfo) -{ - if (dss.dpll4_m4_ck) { - unsigned long prate; - - if (cinfo->fck_div > dss.feat->fck_div_max || - cinfo->fck_div == 0) - return -EINVAL; - - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - - cinfo->fck = prate / cinfo->fck_div * - dss.feat->dss_fck_multiplier; - } else { - if (cinfo->fck_div != 0) - return -EINVAL; - cinfo->fck = clk_get_rate(dss.dss_clk); - } - - return 0; -} - bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) { int fckd, fckd_start, fckd_stop; @@ -485,8 +461,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) if (dss.dpll4_m4_ck == NULL) { fck = clk_get_rate(dss.dss_clk); - fckd = 1; - return func(fckd, fck, data); + return func(fck, data); } fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); @@ -503,38 +478,35 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { fck = prate / fckd * m; - if (func(fckd, fck, data)) + if (func(fck, data)) return true; } return false; } -int dss_set_clock_div(struct dss_clock_info *cinfo) +int dss_set_fck_rate(unsigned long rate) { + DSSDBG("set fck to %lu\n", rate); + if (dss.dpll4_m4_ck) { unsigned long prate; + unsigned m; int r; prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - DSSDBG("dpll4_m4 = %ld\n", prate); + m = dss.feat->dss_fck_multiplier; - r = clk_set_rate(dss.dpll4_m4_ck, - DIV_ROUND_UP(prate, cinfo->fck_div)); + r = clk_set_rate(dss.dpll4_m4_ck, rate * m); if (r) return r; - } else { - if (cinfo->fck_div != 0) - return -EINVAL; } dss.dss_clk_rate = clk_get_rate(dss.dss_clk); - WARN_ONCE(dss.dss_clk_rate != cinfo->fck, + WARN_ONCE(dss.dss_clk_rate != rate, "clk rate mismatch: %lu != %lu", dss.dss_clk_rate, - cinfo->fck); - - DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); + rate); return 0; } @@ -555,8 +527,8 @@ unsigned long dss_get_dispc_clk_rate(void) static int dss_setup_default_clock(void) { unsigned long max_dss_fck, prate; + unsigned long fck; unsigned fck_div; - struct dss_clock_info dss_cinfo = { 0 }; int r; if (dss.dpll4_m4_ck == NULL) @@ -568,14 +540,9 @@ static int dss_setup_default_clock(void) fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier, max_dss_fck); + fck = prate / fck_div * dss.feat->dss_fck_multiplier; - dss_cinfo.fck_div = fck_div; - - r = dss_calc_clock_rates(&dss_cinfo); - if (r) - return r; - - r = dss_set_clock_div(&dss_cinfo); + r = dss_set_fck_rate(fck); if (r) return r; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index e172531d196b..ead1960ad9d8 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -100,14 +100,6 @@ enum dss_writeback_channel { DSS_WB_LCD3_MGR = 7, }; -struct dss_clock_info { - /* rates that we get with dividers below */ - unsigned long fck; - - /* dividers */ - u16 fck_div; -}; - struct dispc_clock_info { /* rates that we get with dividers below */ unsigned long lck; @@ -251,10 +243,9 @@ void dss_set_venc_output(enum omap_dss_venc_type type); void dss_set_dac_pwrdn_bgz(bool enable); unsigned long dss_get_dpll4_rate(void); -int dss_calc_clock_rates(struct dss_clock_info *cinfo); -int dss_set_clock_div(struct dss_clock_info *cinfo); +int dss_set_fck_rate(unsigned long rate); -typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data); +typedef bool (*dss_div_calc_func)(unsigned long fck, void *data); bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data); /* SDI */ diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index ccc569ae7cca..221fd34c42ff 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -46,7 +46,7 @@ static struct { struct sdi_clk_calc_ctx { unsigned long pck_min, pck_max; - struct dss_clock_info dss_cinfo; + unsigned long long fck; struct dispc_clock_info dispc_cinfo; }; @@ -63,19 +63,18 @@ static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, return true; } -static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) +static bool dpi_calc_dss_cb(unsigned long fck, void *data) { struct sdi_clk_calc_ctx *ctx = data; - ctx->dss_cinfo.fck = fck; - ctx->dss_cinfo.fck_div = fckd; + ctx->fck = fck; return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, dpi_calc_dispc_cb, ctx); } static int sdi_calc_clock_div(unsigned long pclk, - struct dss_clock_info *dss_cinfo, + unsigned long *fck, struct dispc_clock_info *dispc_cinfo) { int i; @@ -100,7 +99,7 @@ static int sdi_calc_clock_div(unsigned long pclk, ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx); if (ok) { - *dss_cinfo = ctx.dss_cinfo; + *fck = ctx.fck; *dispc_cinfo = ctx.dispc_cinfo; return 0; } @@ -128,7 +127,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_device *out = &sdi.output; struct omap_video_timings *t = &sdi.timings; - struct dss_clock_info dss_cinfo; + unsigned long fck; struct dispc_clock_info dispc_cinfo; unsigned long pck; int r; @@ -150,13 +149,13 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); + r = sdi_calc_clock_div(t->pixel_clock * 1000, &fck, &dispc_cinfo); if (r) goto err_calc_clock_div; sdi.mgr_config.clock_info = dispc_cinfo; - pck = dss_cinfo.fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000; + pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000; if (pck != t->pixel_clock) { DSSWARN("Could not find exact pixel clock. Requested %d kHz, " @@ -169,7 +168,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev) dss_mgr_set_timings(out->manager, t); - r = dss_set_clock_div(&dss_cinfo); + r = dss_set_fck_rate(fck); if (r) goto err_set_dss_clock_div; -- cgit v1.2.3 From 9c15d76200dbd9c0ae5b1c6bfa17cbfdfaa2e2ae Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 1 Nov 2013 11:36:10 +0200 Subject: OMAPDSS: simplify dss clk dump Simplify dss_dump_clocks() so that it doesn't make any presumptions about the DSS fclks nature. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index c37d934e1a57..3dea532daf4c 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -264,8 +264,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) void dss_dump_clocks(struct seq_file *s) { - unsigned long dpll4_ck_rate; - unsigned long dpll4_m4_ck_rate; const char *fclk_name, *fclk_real_name; unsigned long fclk_rate; @@ -278,21 +276,9 @@ void dss_dump_clocks(struct seq_file *s) fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); fclk_rate = clk_get_rate(dss.dss_clk); - if (dss.dpll4_m4_ck) { - dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); - - seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); - - seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n", - fclk_name, fclk_real_name, dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - dss.feat->dss_fck_multiplier, fclk_rate); - } else { - seq_printf(s, "%s (%s) = %lu\n", - fclk_name, fclk_real_name, - fclk_rate); - } + seq_printf(s, "%s (%s) = %lu\n", + fclk_name, fclk_real_name, + fclk_rate); dss_runtime_put(); } -- cgit v1.2.3 From 64ad846ffd9fe2d29ac9d2f68a4866f67ad9e3f1 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 1 Nov 2013 11:38:04 +0200 Subject: OMAPDSS: rename parent clk variables Rename the variables related to DSS fclk's parent: "clk_name" and "dpll4_m4_ck", to "parent_clk_name" and "parent_clk", which much better tell what they mean. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 3dea532daf4c..d510ba333e7d 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -67,7 +67,7 @@ static void dss_runtime_put(void); struct dss_features { u8 fck_div_max; u8 dss_fck_multiplier; - const char *clk_name; + const char *parent_clk_name; int (*dpi_select_source)(enum omap_channel channel); }; @@ -75,7 +75,7 @@ static struct { struct platform_device *pdev; void __iomem *base; - struct clk *dpll4_m4_ck; + struct clk *parent_clk; struct clk *dss_clk; unsigned long dss_clk_rate; @@ -445,7 +445,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) unsigned long prate; unsigned m; - if (dss.dpll4_m4_ck == NULL) { + if (dss.parent_clk == NULL) { fck = clk_get_rate(dss.dss_clk); return func(fck, data); } @@ -475,15 +475,15 @@ int dss_set_fck_rate(unsigned long rate) { DSSDBG("set fck to %lu\n", rate); - if (dss.dpll4_m4_ck) { + if (dss.parent_clk) { unsigned long prate; unsigned m; int r; - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + prate = clk_get_rate(clk_get_parent(dss.parent_clk)); m = dss.feat->dss_fck_multiplier; - r = clk_set_rate(dss.dpll4_m4_ck, rate * m); + r = clk_set_rate(dss.parent_clk, rate * m); if (r) return r; } @@ -499,8 +499,8 @@ int dss_set_fck_rate(unsigned long rate) unsigned long dss_get_dpll4_rate(void) { - if (dss.dpll4_m4_ck) - return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + if (dss.parent_clk) + return clk_get_rate(clk_get_parent(dss.parent_clk)); else return 0; } @@ -517,7 +517,7 @@ static int dss_setup_default_clock(void) unsigned fck_div; int r; - if (dss.dpll4_m4_ck == NULL) + if (dss.parent_clk == NULL) return 0; max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); @@ -654,25 +654,25 @@ static int dss_get_clocks(void) dss.dss_clk = clk; - if (dss.feat->clk_name) { - clk = clk_get(NULL, dss.feat->clk_name); + if (dss.feat->parent_clk_name) { + clk = clk_get(NULL, dss.feat->parent_clk_name); if (IS_ERR(clk)) { - DSSERR("Failed to get %s\n", dss.feat->clk_name); + DSSERR("Failed to get %s\n", dss.feat->parent_clk_name); return PTR_ERR(clk); } } else { clk = NULL; } - dss.dpll4_m4_ck = clk; + dss.parent_clk = clk; return 0; } static void dss_put_clocks(void) { - if (dss.dpll4_m4_ck) - clk_put(dss.dpll4_m4_ck); + if (dss.parent_clk) + clk_put(dss.parent_clk); } static int dss_runtime_get(void) @@ -715,35 +715,35 @@ static const struct dss_features omap24xx_dss_feats __initconst = { */ .fck_div_max = 6, .dss_fck_multiplier = 2, - .clk_name = "dss1_fck", + .parent_clk_name = "dss1_fck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap34xx_dss_feats __initconst = { .fck_div_max = 16, .dss_fck_multiplier = 2, - .clk_name = "dpll4_m4_ck", + .parent_clk_name = "dpll4_m4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap3630_dss_feats __initconst = { .fck_div_max = 32, .dss_fck_multiplier = 1, - .clk_name = "dpll4_m4_ck", + .parent_clk_name = "dpll4_m4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap44xx_dss_feats __initconst = { .fck_div_max = 32, .dss_fck_multiplier = 1, - .clk_name = "dpll_per_m5x2_ck", + .parent_clk_name = "dpll_per_m5x2_ck", .dpi_select_source = &dss_dpi_select_source_omap4, }; static const struct dss_features omap54xx_dss_feats __initconst = { .fck_div_max = 64, .dss_fck_multiplier = 1, - .clk_name = "dpll_per_h12x2_ck", + .parent_clk_name = "dpll_per_h12x2_ck", .dpi_select_source = &dss_dpi_select_source_omap5, }; -- cgit v1.2.3 From ada9443ff407f83a96abc15ea44a106250dd23f2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 31 Oct 2013 16:06:38 +0200 Subject: OMAPDSS: cleanup fck parent handling The dss parent_clk_name currently points to a clock node which we use to change the fclk rate. Now that we have CLK_SET_RATE_PARENT properly set, we can set the rate directly to the fclk node. However, we still need to calculate the possible clock rates. For this, we need the rate of the parent of the current parent_clk. To simplify the code, this patch changes the parent_clk_name to point to the above mentioned parent, so that we can get the rate directly. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 39 ++++++++++++--------------------------- drivers/video/omap2/dss/dss.h | 1 - 2 files changed, 12 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index d510ba333e7d..7af97199c905 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -454,7 +454,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) fckd_hw_max = dss.feat->fck_div_max; m = dss.feat->dss_fck_multiplier; - prate = dss_get_dpll4_rate(); + prate = clk_get_rate(dss.parent_clk); fck_min = fck_min ? fck_min : 1; @@ -473,20 +473,13 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) int dss_set_fck_rate(unsigned long rate) { - DSSDBG("set fck to %lu\n", rate); - - if (dss.parent_clk) { - unsigned long prate; - unsigned m; - int r; + int r; - prate = clk_get_rate(clk_get_parent(dss.parent_clk)); - m = dss.feat->dss_fck_multiplier; + DSSDBG("set fck to %lu\n", rate); - r = clk_set_rate(dss.parent_clk, rate * m); - if (r) - return r; - } + r = clk_set_rate(dss.dss_clk, rate); + if (r) + return r; dss.dss_clk_rate = clk_get_rate(dss.dss_clk); @@ -497,14 +490,6 @@ int dss_set_fck_rate(unsigned long rate) return 0; } -unsigned long dss_get_dpll4_rate(void) -{ - if (dss.parent_clk) - return clk_get_rate(clk_get_parent(dss.parent_clk)); - else - return 0; -} - unsigned long dss_get_dispc_clk_rate(void) { return dss.dss_clk_rate; @@ -522,7 +507,7 @@ static int dss_setup_default_clock(void) max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); - prate = dss_get_dpll4_rate(); + prate = clk_get_rate(dss.parent_clk); fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier, max_dss_fck); @@ -715,35 +700,35 @@ static const struct dss_features omap24xx_dss_feats __initconst = { */ .fck_div_max = 6, .dss_fck_multiplier = 2, - .parent_clk_name = "dss1_fck", + .parent_clk_name = "core_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap34xx_dss_feats __initconst = { .fck_div_max = 16, .dss_fck_multiplier = 2, - .parent_clk_name = "dpll4_m4_ck", + .parent_clk_name = "dpll4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap3630_dss_feats __initconst = { .fck_div_max = 32, .dss_fck_multiplier = 1, - .parent_clk_name = "dpll4_m4_ck", + .parent_clk_name = "dpll4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap44xx_dss_feats __initconst = { .fck_div_max = 32, .dss_fck_multiplier = 1, - .parent_clk_name = "dpll_per_m5x2_ck", + .parent_clk_name = "dpll_per_x2_ck", .dpi_select_source = &dss_dpi_select_source_omap4, }; static const struct dss_features omap54xx_dss_feats __initconst = { .fck_div_max = 64, .dss_fck_multiplier = 1, - .parent_clk_name = "dpll_per_h12x2_ck", + .parent_clk_name = "dpll_per_x2_ck", .dpi_select_source = &dss_dpi_select_source_omap5, }; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index ead1960ad9d8..6fc786fddbcb 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -242,7 +242,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); void dss_set_venc_output(enum omap_dss_venc_type type); void dss_set_dac_pwrdn_bgz(bool enable); -unsigned long dss_get_dpll4_rate(void); int dss_set_fck_rate(unsigned long rate); typedef bool (*dss_div_calc_func)(unsigned long fck, void *data); -- cgit v1.2.3 From 688af02d22c11a077532d6437e4afc7bdc972f82 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 31 Oct 2013 16:41:57 +0200 Subject: OMAPDSS: pass pck to dss fck clock calc We need the required pixel clock rate when calculating the dss fclk on SoCs that have a dedicated DSS PLL. This patch changes the code to pass the pck to the calc functions. The pck rate is taken into use in the next patch. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dpi.c | 2 +- drivers/video/omap2/dss/dss.c | 3 ++- drivers/video/omap2/dss/dss.h | 3 ++- drivers/video/omap2/dss/sdi.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 16acdddc94e3..ae1c8b9d39ca 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -236,7 +236,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) ctx->pck_min = 0; ctx->pck_max = pck + 1000 * i * i * i; - ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx); + ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx); if (ok) return ok; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 7af97199c905..08c58ebe219c 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -436,7 +436,8 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) } } -bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) +bool dss_div_calc(unsigned long pck, unsigned long fck_min, + dss_div_calc_func func, void *data) { int fckd, fckd_start, fckd_stop; unsigned long fck; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 6fc786fddbcb..2acc6615b984 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -245,7 +245,8 @@ void dss_set_dac_pwrdn_bgz(bool enable); int dss_set_fck_rate(unsigned long rate); typedef bool (*dss_div_calc_func)(unsigned long fck, void *data); -bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data); +bool dss_div_calc(unsigned long pck, unsigned long fck_min, + dss_div_calc_func func, void *data); /* SDI */ int sdi_init_platform_driver(void) __init; diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 221fd34c42ff..3bf47c92aedf 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -97,7 +97,7 @@ static int sdi_calc_clock_div(unsigned long pclk, ctx.pck_min = 0; ctx.pck_max = pclk + 1000 * i * i * i; - ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx); + ok = dss_div_calc(pclk, ctx.pck_min, dpi_calc_dss_cb, &ctx); if (ok) { *fck = ctx.fck; *dispc_cinfo = ctx.dispc_cinfo; -- cgit v1.2.3 From fc1fe6e794cc85fcdb63daa9c7a977940ff49e4f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 31 Oct 2013 16:42:13 +0200 Subject: OMAPDSS: add dedicated fck PLL support This patch adds support for SoCs that have a dedicated DSS PLL used for DSS function clock. If there is no dss parent clock defined, it is presumed that the functionl clock rate can be set (almost) freely. The code calculates the highest allowed fck rate, which when divided with some integer gives the required pck. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 08c58ebe219c..9a145da35ad3 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -446,12 +446,20 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, unsigned long prate; unsigned m; + fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + if (dss.parent_clk == NULL) { - fck = clk_get_rate(dss.dss_clk); + unsigned pckd; + + pckd = fck_hw_max / pck; + + fck = pck * pckd; + + fck = clk_round_rate(dss.dss_clk, fck); + return func(fck, data); } - fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); fckd_hw_max = dss.feat->fck_div_max; m = dss.feat->dss_fck_multiplier; @@ -503,16 +511,17 @@ static int dss_setup_default_clock(void) unsigned fck_div; int r; - if (dss.parent_clk == NULL) - return 0; - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); - prate = clk_get_rate(dss.parent_clk); + if (dss.parent_clk == NULL) { + fck = clk_round_rate(dss.dss_clk, max_dss_fck); + } else { + prate = clk_get_rate(dss.parent_clk); - fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier, - max_dss_fck); - fck = prate / fck_div * dss.feat->dss_fck_multiplier; + fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier, + max_dss_fck); + fck = prate / fck_div * dss.feat->dss_fck_multiplier; + } r = dss_set_fck_rate(fck); if (r) -- cgit v1.2.3 From 0694001b27efe5878ba5bd273e39b384821d865e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 30 Oct 2013 18:27:43 -0200 Subject: drm/i915: reuse WRPLL when possible It seems we do have machines with 3 HDMI/DVI outputs, so sharing WRPLLs is the only way to get 3 pipes working. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68485 Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1591576a6101..e5eecfd5e47c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -713,8 +713,6 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) uint32_t reg, val; int clock = intel_crtc->config.port_clock; - /* TODO: reuse PLLs when possible (compare values) */ - intel_ddi_put_crtc_pll(crtc); if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { @@ -742,31 +740,40 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) } else if (type == INTEL_OUTPUT_HDMI) { unsigned p, n2, r2; - if (plls->wrpll1_refcount == 0) { + intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); + + val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | + WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | + WRPLL_DIVIDER_POST(p); + + if (val == I915_READ(WRPLL_CTL1)) { + DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n", + pipe_name(pipe)); + reg = WRPLL_CTL1; + } else if (val == I915_READ(WRPLL_CTL2)) { + DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n", + pipe_name(pipe)); + reg = WRPLL_CTL2; + } else if (plls->wrpll1_refcount == 0) { DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n", pipe_name(pipe)); - plls->wrpll1_refcount++; reg = WRPLL_CTL1; - intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; } else if (plls->wrpll2_refcount == 0) { DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n", pipe_name(pipe)); - plls->wrpll2_refcount++; reg = WRPLL_CTL2; - intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; } else { DRM_ERROR("No WRPLLs available!\n"); return false; } - WARN(I915_READ(reg) & WRPLL_PLL_ENABLE, - "WRPLL already enabled\n"); - - intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); - - val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | - WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | - WRPLL_DIVIDER_POST(p); + if (reg == WRPLL_CTL1) { + plls->wrpll1_refcount++; + intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; + } else { + plls->wrpll2_refcount++; + intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; + } } else if (type == INTEL_OUTPUT_ANALOG) { if (plls->spll_refcount == 0) { -- cgit v1.2.3 From f671d117bc0338b67b0a7485882d332fe6c4b570 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 16 Nov 2013 16:02:04 +0100 Subject: drm/i915: remove intel_uncore_clear_errors This was forgotten in commit 9d1cb9147dbe45f6e94dc796518ecf67cb64b359 Author: Paulo Zanoni Date: Fri Nov 1 13:32:08 2013 -0200 drm/i915: avoid unclaimed registers when capturing the error state Cc: Paulo Zanoni Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_uncore.c | 9 --------- 2 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6b96e91c6f1a..18ff544670d8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1920,7 +1920,6 @@ extern void intel_pm_init(struct drm_device *dev); extern void intel_uncore_sanitize(struct drm_device *dev); extern void intel_uncore_early_sanitize(struct drm_device *dev); extern void intel_uncore_init(struct drm_device *dev); -extern void intel_uncore_clear_errors(struct drm_device *dev); extern void intel_uncore_check_errors(struct drm_device *dev); extern void intel_uncore_fini(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 5103d80fc3ae..07c0ad0e1583 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -828,15 +828,6 @@ int intel_gpu_reset(struct drm_device *dev) } } -void intel_uncore_clear_errors(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - /* XXX needs spinlock around caller's grouping */ - if (HAS_FPGA_DBG_UNCLAIMED(dev)) - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); -} - void intel_uncore_check_errors(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; -- cgit v1.2.3 From b80d5ccca3a012e91ca64a2a0b13049163a6a698 Mon Sep 17 00:00:00 2001 From: Haiyan Hu Date: Tue, 10 Sep 2013 11:25:37 +0800 Subject: NVMe: Avoid shift operation when writing cq head doorbell Changes the type of dev->db_stride to unsigned and changes the value stored there to be 1 << the current value. Then there is less calculation to be done at completion time. Signed-off-by: Haiyan Hu Signed-off-by: Matthew Wilcox --- drivers/block/nvme-core.c | 10 +++++----- include/linux/nvme.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 26d03fa0bf26..073aec913c78 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -775,7 +775,7 @@ static int nvme_process_cq(struct nvme_queue *nvmeq) if (head == nvmeq->cq_head && phase == nvmeq->cq_phase) return 0; - writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride)); + writel(head, nvmeq->q_db + nvmeq->dev->db_stride); nvmeq->cq_head = head; nvmeq->cq_phase = phase; @@ -1113,7 +1113,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, init_waitqueue_head(&nvmeq->sq_full); init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread); bio_list_init(&nvmeq->sq_cong); - nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)]; + nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride]; nvmeq->q_depth = depth; nvmeq->cq_vector = vector; nvmeq->q_suspended = 1; @@ -1149,7 +1149,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid) nvmeq->sq_tail = 0; nvmeq->cq_head = 0; nvmeq->cq_phase = 1; - nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)]; + nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride]; memset(nvmeq->cmdid_data, 0, extra); memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq->q_depth)); nvme_cancel_ios(nvmeq, false); @@ -1741,7 +1741,7 @@ static int set_queue_count(struct nvme_dev *dev, int count) static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues) { - return 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3)); + return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride); } static int nvme_setup_io_queues(struct nvme_dev *dev) @@ -1958,7 +1958,7 @@ static int nvme_dev_map(struct nvme_dev *dev) if (!dev->bar) goto disable; - dev->db_stride = NVME_CAP_STRIDE(readq(&dev->bar->cap)); + dev->db_stride = 1 << NVME_CAP_STRIDE(readq(&dev->bar->cap)); dev->dbs = ((void __iomem *)dev->bar) + 4096; return 0; diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 26ebcf41c213..8119a476cb29 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -80,7 +80,7 @@ struct nvme_dev { struct dma_pool *prp_small_pool; int instance; int queue_count; - int db_stride; + u32 db_stride; u32 ctrl_config; struct msix_entry *entry; struct nvme_bar __iomem *bar; -- cgit v1.2.3 From 481e5bad84239b01415b888df2040c1860ae3cfd Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Sat, 12 Oct 2013 06:23:29 +0200 Subject: NVMe: remove deprecated IRQF_DISABLED This patch proposes to remove the use of the IRQF_DISABLED flag It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Signed-off-by: Matthew Wilcox --- drivers/block/nvme-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 073aec913c78..df3daeb6227f 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -1134,11 +1134,10 @@ static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq, { if (use_threaded_interrupts) return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector, - nvme_irq_check, nvme_irq, - IRQF_DISABLED | IRQF_SHARED, + nvme_irq_check, nvme_irq, IRQF_SHARED, name, nvmeq); return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq, - IRQF_DISABLED | IRQF_SHARED, name, nvmeq); + IRQF_SHARED, name, nvmeq); } static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid) -- cgit v1.2.3 From 9fee8240cfd37081c88e2d84852c497ba18baeac Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sun, 17 Nov 2013 13:51:23 -0800 Subject: HID: usbkbd: fix inconsistent debugging output It looks like this typo was introduced by a mistake in a copy-and-paste in commit ddbe32491951. Signed-off-by: Adam Cozzette Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/usbkbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index 796086980f4a..9a332e683db7 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -146,7 +146,7 @@ static void usb_kbd_irq(struct urb *urb) input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); else hid_info(urb->dev, - "Unknown key (scancode %#x) released.\n", + "Unknown key (scancode %#x) pressed.\n", kbd->new[i]); } } -- cgit v1.2.3 From d3a8a4e2d5e42e80625d734bb2bc5f71ecd9ffc1 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 19 Nov 2013 21:23:41 +0800 Subject: staging/lustre/hsm: Implementation of exclusive open Proposed way to do exclusive open: 0. First of all, we have to perform most of the work in kernel space; 1. Client exclusively opens the file with IT_RELEASE_OPEN. 1.1 exclusive open means the open will fail if the file is being opened by somebody else; 2. the MDT will handle IT_RELEASE as follows: 2.1 Revoke OPEN_LOCK on this file, just request EX mode of MDS_INODELOCK_OPEN lock and release it; 2.2 Acquire a rwsem, say open_rwsem, with write mode before trying to the file; for the normal open, it should acquire read mode of open_rwsem; 2.3 Check if the file is already being opened by others, if not return with -EBUSY; 2.4 Check if the file can be released; 2.5 Set a special flag in struct mdt_file_data to mark this open is exclusive; 2.5 Release open rwsem. >From now on, if the file is opened by others, it will mark mdt_file_data that the exclusive open is broken. 3. Client: if IT_RELEASE_OPEN is finished successfully, and do followings: 3.1 Acquire full PW or EX extent lock to flush dirty cache; 3.2 Pack the handle of layout lock, data version and other attars; 3.3 Close the file with IT_RELEASE_CLOSE. 4. Back to MDT to handle IT_RELEASE CLOSE: 4.1 Grab the open_rwsem 4.2 Check if the exclusive open has ever been broken, in that case, the RELEASE process will fail; 4.3 Verify the data version matches archive; 4.4 Grab EX layout lock 4.5 Swap the layout 4.6 Release EX layout lock 4.7 Close the exclusive open Basically we avoid granting EX layout lock back to client and introduce exclusive open so that we know it if the file has ever being accessed. I hope this can simplify things a little bit. Also, exclusive open can be used to implement file lease. In this patch, a framework of lease is implemented. However, only exclusive lease is supported right now. To apply a lease, MDS_OPEN_LEASE must be set to open the file, EX mode open lock is returned to the client side to hold a lease. From that time on, if this file is opened again by other processes, the open lock will be revoked so the client who holds the lease will know the lease is already broken by checking that open lock. To release a lease, normal close is used. The client will revoke the open lock before sending CLOSE request. Lease can be applied in two ways. ll_lease_open()/close() can be called directly if the lease holder is in kernel space; or if the lease holder lives in user space, it has to open the file first and then use ioctl() with command LL_IOC_SET_LEASE to apply a lease. The lease holder has to poll the lease status itself. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2919 Lustre-change: http://review.whamcloud.com/6730 Signed-off-by: Jinshan Xiong Signed-off-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/linux/lustre_intent.h | 2 +- .../lustre/lustre/include/lustre/lustre_idl.h | 5 + .../lustre/lustre/include/lustre/lustre_user.h | 3 + .../lustre/lustre/include/lustre_dlm_flags.h | 12 +- drivers/staging/lustre/lustre/include/lustre_lib.h | 11 +- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 5 + drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 4 +- drivers/staging/lustre/lustre/llite/file.c | 297 ++++++++++++++++++++- .../staging/lustre/lustre/llite/llite_internal.h | 11 +- drivers/staging/lustre/lustre/mdc/mdc_internal.h | 2 +- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 7 +- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 40 ++- 12 files changed, 370 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_intent.h b/drivers/staging/lustre/lustre/include/linux/lustre_intent.h index b10ddfa7df29..c491d52d86a2 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_intent.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_intent.h @@ -52,8 +52,8 @@ struct lustre_intent_data { struct lookup_intent { int it_op; - int it_flags; int it_create_mode; + __u64 it_flags; union { struct lustre_intent_data lustre; } d; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 5ca18d016014..e592a0e0f794 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2120,6 +2120,7 @@ extern void lustre_swab_generic_32s (__u32 *val); #define DISP_ENQ_OPEN_REF 0x00800000 #define DISP_ENQ_CREATE_REF 0x01000000 #define DISP_OPEN_LOCK 0x02000000 +#define DISP_OPEN_LEASE 0x04000000 /* INODE LOCK PARTS */ #define MDS_INODELOCK_LOOKUP 0x000001 /* dentry, mode, owner, group */ @@ -2373,6 +2374,10 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa); * hsm restore) */ #define MDS_OPEN_VOLATILE 0400000000000ULL /* File is volatile = created unlinked */ +#define MDS_OPEN_LEASE 01000000000000ULL /* Open the file and grant lease + * delegation, succeed if it's not + * being opened with conflict mode. + */ /* permission for create non-directory file */ #define MAY_CREATE (1 << 7) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index c7bd4473a1d0..9fd1d3ba2a63 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -245,6 +245,9 @@ struct ost_id { #define LL_IOC_LMV_GETSTRIPE _IOWR('f', 241, struct lmv_user_md) #define LL_IOC_REMOVE_ENTRY _IOWR('f', 242, __u64) +#define LL_IOC_SET_LEASE _IOWR('f', 243, long) +#define LL_IOC_GET_LEASE _IO('f', 244) + #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 #define LL_STATFS_NODELAY 4 diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h index 8c34d9d4d258..f8b4ba749683 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h @@ -35,7 +35,7 @@ #ifndef LDLM_ALL_FLAGS_MASK /** l_flags bits marked as "all_flags" bits */ -#define LDLM_FL_ALL_FLAGS_MASK 0x007FFFFFC08F132FULL +#define LDLM_FL_ALL_FLAGS_MASK 0x00FFFFFFC08F132FULL /** l_flags bits marked as "ast" bits */ #define LDLM_FL_AST_MASK 0x0000000080000000ULL @@ -53,7 +53,7 @@ #define LDLM_FL_INHERIT_MASK 0x0000000000800000ULL /** l_flags bits marked as "local_only" bits */ -#define LDLM_FL_LOCAL_ONLY_MASK 0x007FFFFF00000000ULL +#define LDLM_FL_LOCAL_ONLY_MASK 0x00FFFFFF00000000ULL /** l_flags bits marked as "on_wire" bits */ #define LDLM_FL_ON_WIRE_MASK 0x00000000C08F132FULL @@ -358,6 +358,12 @@ #define ldlm_set_ns_srv(_l) LDLM_SET_FLAG(( _l), 1ULL << 54) #define ldlm_clear_ns_srv(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 54) +/** Flag whether this lock can be reused. Used by exclusive open. */ +#define LDLM_FL_EXCL 0x0080000000000000ULL /* bit 55 */ +#define ldlm_is_excl(_l) LDLM_TEST_FLAG((_l), 1ULL << 55) +#define ldlm_set_excl(_l) LDLM_SET_FLAG((_l), 1ULL << 55) +#define ldlm_clear_excl(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 55) + /** test for ldlm_lock flag bit set */ #define LDLM_TEST_FLAG(_l, _b) (((_l)->l_flags & (_b)) != 0) @@ -414,6 +420,7 @@ static int hf_lustre_ldlm_fl_server_lock = -1; static int hf_lustre_ldlm_fl_res_locked = -1; static int hf_lustre_ldlm_fl_waited = -1; static int hf_lustre_ldlm_fl_ns_srv = -1; +static int hf_lustre_ldlm_fl_excl = -1; const value_string lustre_ldlm_flags_vals[] = { {LDLM_FL_LOCK_CHANGED, "LDLM_FL_LOCK_CHANGED"}, @@ -454,6 +461,7 @@ const value_string lustre_ldlm_flags_vals[] = { {LDLM_FL_RES_LOCKED, "LDLM_FL_RES_LOCKED"}, {LDLM_FL_WAITED, "LDLM_FL_WAITED"}, {LDLM_FL_NS_SRV, "LDLM_FL_NS_SRV"}, + {LDLM_FL_EXCL, "LDLM_FL_EXCL"}, { 0, NULL } }; #endif /* WIRESHARK_COMPILE */ diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index b6fd03e45bb7..609a090484a6 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -81,11 +81,12 @@ struct client_obd *client_conn2cli(struct lustre_handle *conn); struct md_open_data; struct obd_client_handle { - struct lustre_handle och_fh; - struct lu_fid och_fid; - struct md_open_data *och_mod; - __u32 och_magic; - fmode_t och_flags; + struct lustre_handle och_fh; + struct lu_fid och_fid; + struct md_open_data *och_mod; + struct lustre_handle och_lease_handle; /* open lock for lease */ + __u32 och_magic; + fmode_t och_flags; }; #define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 3900a69742fc..ef826e90df03 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1129,6 +1129,11 @@ static struct ldlm_lock *search_queue(struct list_head *queue, if (lock == old_lock) break; + /* Check if this lock can be matched. + * Used by LU-2919(exclusive open) for open lease lock */ + if (ldlm_is_excl(lock)) + continue; + /* llite sometimes wants to match locks that will be * canceled when their users drop, but we allow it to match * if it passes in CBPENDING and the lock still has users. diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index dcc278403136..1e2c0dd67569 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -910,7 +910,7 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, lock->l_conn_export = exp; lock->l_export = NULL; lock->l_blocking_ast = einfo->ei_cb_bl; - lock->l_flags |= (*flags & LDLM_FL_NO_LRU); + lock->l_flags |= (*flags & (LDLM_FL_NO_LRU | LDLM_FL_EXCL)); /* lock not sent to server yet */ @@ -1333,7 +1333,7 @@ int ldlm_cli_cancel(struct lustre_handle *lockh, } rc = ldlm_cli_cancel_local(lock); - if (rc == LDLM_FL_LOCAL_ONLY) { + if (rc == LDLM_FL_LOCAL_ONLY || cancel_flags & LCF_LOCAL) { LDLM_LOCK_RELEASE(lock); return 0; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 17064b4f6176..971409ed52e7 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -241,6 +241,24 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode, if (unlikely(fd->fd_flags & LL_FILE_GROUP_LOCKED)) ll_put_grouplock(inode, file, fd->fd_grouplock.cg_gid); + if (fd->fd_lease_och != NULL) { + bool lease_broken; + + /* Usually the lease is not released when the + * application crashed, we need to release here. */ + rc = ll_lease_close(fd->fd_lease_och, inode, &lease_broken); + CDEBUG(rc ? D_ERROR : D_INODE, "Clean up lease "DFID" %d/%d\n", + PFID(&lli->lli_fid), rc, lease_broken); + + fd->fd_lease_och = NULL; + } + + if (fd->fd_och != NULL) { + rc = ll_close_inode_openhandle(md_exp, inode, fd->fd_och); + fd->fd_och = NULL; + GOTO(out, rc); + } + /* Let's see if we have good enough OPEN lock on the file and if we can skip talking to MDS */ if (file->f_dentry->d_inode) { /* Can this ever be false? */ @@ -277,6 +295,7 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode, file, file->f_dentry, file->f_dentry->d_name.name); } +out: LUSTRE_FPRIVATE(file) = NULL; ll_file_data_put(fd); ll_capa_close(inode); @@ -440,6 +459,7 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); och->och_fh = body->handle; och->och_fid = body->fid1; + och->och_lease_handle.cookie = it->d.lustre.it_lock_handle; och->och_magic = OBD_CLIENT_HANDLE_MAGIC; och->och_flags = it->it_flags; @@ -471,7 +491,7 @@ int ll_local_open(struct file *file, struct lookup_intent *it, LUSTRE_FPRIVATE(file) = fd; ll_readahead_init(inode, &fd->fd_ras); - fd->fd_omode = it->it_flags; + fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); return 0; } @@ -673,6 +693,196 @@ out_openerr: return rc; } +static int ll_md_blocking_lease_ast(struct ldlm_lock *lock, + struct ldlm_lock_desc *desc, void *data, int flag) +{ + int rc; + struct lustre_handle lockh; + + switch (flag) { + case LDLM_CB_BLOCKING: + ldlm_lock2handle(lock, &lockh); + rc = ldlm_cli_cancel(&lockh, LCF_ASYNC); + if (rc < 0) { + CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc); + return rc; + } + break; + case LDLM_CB_CANCELING: + /* do nothing */ + break; + } + return 0; +} + +/** + * Acquire a lease and open the file. + */ +struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file, + fmode_t fmode) +{ + struct lookup_intent it = { .it_op = IT_OPEN }; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct md_op_data *op_data; + struct ptlrpc_request *req; + struct lustre_handle old_handle = { 0 }; + struct obd_client_handle *och = NULL; + int rc; + int rc2; + + if (fmode != FMODE_WRITE && fmode != FMODE_READ) + return ERR_PTR(-EINVAL); + + if (file != NULL) { + struct ll_inode_info *lli = ll_i2info(inode); + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct obd_client_handle **och_p; + __u64 *och_usecount; + + if (!(fmode & file->f_mode) || (file->f_mode & FMODE_EXEC)) + return ERR_PTR(-EPERM); + + /* Get the openhandle of the file */ + rc = -EBUSY; + mutex_lock(&lli->lli_och_mutex); + if (fd->fd_lease_och != NULL) { + mutex_unlock(&lli->lli_och_mutex); + return ERR_PTR(rc); + } + + if (fd->fd_och == NULL) { + if (file->f_mode & FMODE_WRITE) { + LASSERT(lli->lli_mds_write_och != NULL); + och_p = &lli->lli_mds_write_och; + och_usecount = &lli->lli_open_fd_write_count; + } else { + LASSERT(lli->lli_mds_read_och != NULL); + och_p = &lli->lli_mds_read_och; + och_usecount = &lli->lli_open_fd_read_count; + } + if (*och_usecount == 1) { + fd->fd_och = *och_p; + *och_p = NULL; + *och_usecount = 0; + rc = 0; + } + } + mutex_unlock(&lli->lli_och_mutex); + if (rc < 0) /* more than 1 opener */ + return ERR_PTR(rc); + + LASSERT(fd->fd_och != NULL); + old_handle = fd->fd_och->och_fh; + } + + OBD_ALLOC_PTR(och); + if (och == NULL) + return ERR_PTR(-ENOMEM); + + op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + GOTO(out, rc = PTR_ERR(op_data)); + + /* To tell the MDT this openhandle is from the same owner */ + op_data->op_handle = old_handle; + + it.it_flags = fmode | MDS_OPEN_LOCK | MDS_OPEN_BY_FID | MDS_OPEN_LEASE; + rc = md_intent_lock(sbi->ll_md_exp, op_data, NULL, 0, &it, 0, &req, + ll_md_blocking_lease_ast, + /* LDLM_FL_NO_LRU: To not put the lease lock into LRU list, otherwise + * it can be cancelled which may mislead applications that the lease is + * broken; + * LDLM_FL_EXCL: Set this flag so that it won't be matched by normal + * open in ll_md_blocking_ast(). Otherwise as ll_md_blocking_lease_ast + * doesn't deal with openhandle, so normal openhandle will be leaked. */ + LDLM_FL_NO_LRU | LDLM_FL_EXCL); + ll_finish_md_op_data(op_data); + if (req != NULL) { + ptlrpc_req_finished(req); + it_clear_disposition(&it, DISP_ENQ_COMPLETE); + } + if (rc < 0) + GOTO(out_release_it, rc); + + if (it_disposition(&it, DISP_LOOKUP_NEG)) + GOTO(out_release_it, rc = -ENOENT); + + rc = it_open_error(DISP_OPEN_OPEN, &it); + if (rc) + GOTO(out_release_it, rc); + + LASSERT(it_disposition(&it, DISP_ENQ_OPEN_REF)); + ll_och_fill(sbi->ll_md_exp, &it, och); + + if (!it_disposition(&it, DISP_OPEN_LEASE)) /* old server? */ + GOTO(out_close, rc = -EOPNOTSUPP); + + /* already get lease, handle lease lock */ + ll_set_lock_data(sbi->ll_md_exp, inode, &it, NULL); + if (it.d.lustre.it_lock_mode == 0 || + it.d.lustre.it_lock_bits != MDS_INODELOCK_OPEN) { + /* open lock must return for lease */ + CERROR(DFID "lease granted but no open lock, %d/%llu.\n", + PFID(ll_inode2fid(inode)), it.d.lustre.it_lock_mode, + it.d.lustre.it_lock_bits); + GOTO(out_close, rc = -EPROTO); + } + + ll_intent_release(&it); + return och; + +out_close: + rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, inode, och); + if (rc2) + CERROR("Close openhandle returned %d\n", rc2); + + /* cancel open lock */ + if (it.d.lustre.it_lock_mode != 0) { + ldlm_lock_decref_and_cancel(&och->och_lease_handle, + it.d.lustre.it_lock_mode); + it.d.lustre.it_lock_mode = 0; + } +out_release_it: + ll_intent_release(&it); +out: + OBD_FREE_PTR(och); + return ERR_PTR(rc); +} +EXPORT_SYMBOL(ll_lease_open); + +/** + * Release lease and close the file. + * It will check if the lease has ever broken. + */ +int ll_lease_close(struct obd_client_handle *och, struct inode *inode, + bool *lease_broken) +{ + struct ldlm_lock *lock; + bool cancelled = true; + int rc; + + lock = ldlm_handle2lock(&och->och_lease_handle); + if (lock != NULL) { + lock_res_and_lock(lock); + cancelled = ldlm_is_cancel(lock); + unlock_res_and_lock(lock); + ldlm_lock_put(lock); + } + + CDEBUG(D_INODE, "lease for "DFID" broken? %d\n", + PFID(&ll_i2info(inode)->lli_fid), cancelled); + + if (!cancelled) + ldlm_cli_cancel(&och->och_lease_handle, 0); + if (lease_broken != NULL) + *lease_broken = cancelled; + + rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och); + return rc; +} +EXPORT_SYMBOL(ll_lease_close); + /* Fills the obdo with the attributes for the lsm */ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, struct obd_capa *capa, struct obdo *obdo, @@ -2066,6 +2276,91 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) OBD_FREE_PTR(hca); return rc; } + case LL_IOC_SET_LEASE: { + struct ll_inode_info *lli = ll_i2info(inode); + struct obd_client_handle *och = NULL; + bool lease_broken; + fmode_t mode = 0; + + switch (arg) { + case F_WRLCK: + if (!(file->f_mode & FMODE_WRITE)) + return -EPERM; + mode = FMODE_WRITE; + break; + case F_RDLCK: + if (!(file->f_mode & FMODE_READ)) + return -EPERM; + mode = FMODE_READ; + break; + case F_UNLCK: + mutex_lock(&lli->lli_och_mutex); + if (fd->fd_lease_och != NULL) { + och = fd->fd_lease_och; + fd->fd_lease_och = NULL; + } + mutex_unlock(&lli->lli_och_mutex); + + if (och != NULL) { + mode = och->och_flags & + (FMODE_READ|FMODE_WRITE); + rc = ll_lease_close(och, inode, &lease_broken); + if (rc == 0 && lease_broken) + mode = 0; + } else { + rc = -ENOLCK; + } + + /* return the type of lease or error */ + return rc < 0 ? rc : (int)mode; + default: + return -EINVAL; + } + + CDEBUG(D_INODE, "Set lease with mode %d\n", mode); + + /* apply for lease */ + och = ll_lease_open(inode, file, mode); + if (IS_ERR(och)) + return PTR_ERR(och); + + rc = 0; + mutex_lock(&lli->lli_och_mutex); + if (fd->fd_lease_och == NULL) { + fd->fd_lease_och = och; + och = NULL; + } + mutex_unlock(&lli->lli_och_mutex); + if (och != NULL) { + /* impossible now that only excl is supported for now */ + ll_lease_close(och, inode, &lease_broken); + rc = -EBUSY; + } + return rc; + } + case LL_IOC_GET_LEASE: { + struct ll_inode_info *lli = ll_i2info(inode); + struct ldlm_lock *lock = NULL; + + rc = 0; + mutex_lock(&lli->lli_och_mutex); + if (fd->fd_lease_och != NULL) { + struct obd_client_handle *och = fd->fd_lease_och; + + lock = ldlm_handle2lock(&och->och_lease_handle); + if (lock != NULL) { + lock_res_and_lock(lock); + if (!ldlm_is_cancel(lock)) + rc = och->och_flags & + (FMODE_READ | FMODE_WRITE); + unlock_res_and_lock(lock); + ldlm_lock_put(lock); + } + } + mutex_unlock(&lli->lli_och_mutex); + + return rc; + } default: { int err; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index d37c183109ba..1a13330ac966 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -608,10 +608,14 @@ extern struct kmem_cache *ll_file_data_slab; struct lustre_handle; struct ll_file_data { struct ll_readahead_state fd_ras; - int fd_omode; struct ccc_grouplock fd_grouplock; __u64 lfd_pos; __u32 fd_flags; + fmode_t fd_omode; + /* openhandle if lease exists for this file. + * Borrow lli->lli_och_mutex to protect assignment */ + struct obd_client_handle *fd_lease_och; + struct obd_client_handle *fd_och; struct file *fd_file; /* Indicate whether need to report failure when close. * true: failure is known, not report again. @@ -777,6 +781,11 @@ int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg); int ll_fid2path(struct inode *inode, void *arg); int ll_data_version(struct inode *inode, __u64 *data_version, int extent_lock); +struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file, + fmode_t mode); +int ll_lease_close(struct obd_client_handle *och, struct inode *inode, + bool *lease_broken); + /* llite/dcache.c */ int ll_dops_init(struct dentry *de, int block, int init_sa); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 2aeff0ecec34..b995af6a2782 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -69,7 +69,7 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, const void *data, int datalen, __u32 mode, __u32 uid, __u32 gid, cfs_cap_t capability, __u64 rdev); void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - __u32 mode, __u64 rdev, __u32 flags, const void *data, + __u32 mode, __u64 rdev, __u64 flags, const void *data, int datalen); void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index b2de47803679..3e7702075bf9 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -174,12 +174,12 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, } } -static __u64 mds_pack_open_flags(__u32 flags, __u32 mode) +static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) { __u64 cr_flags = (flags & (FMODE_READ | FMODE_WRITE | MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | - MDS_OPEN_BY_FID)); + MDS_OPEN_BY_FID | MDS_OPEN_LEASE)); if (flags & O_CREAT) cr_flags |= MDS_OPEN_CREAT; if (flags & O_EXCL) @@ -207,7 +207,7 @@ static __u64 mds_pack_open_flags(__u32 flags, __u32 mode) /* packing of MDS records */ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - __u32 mode, __u64 rdev, __u32 flags, const void *lmm, + __u32 mode, __u64 rdev, __u64 flags, const void *lmm, int lmmlen) { struct mdt_rec_create *rec; @@ -234,6 +234,7 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_suppgid2 = op_data->op_suppgids[1]; rec->cr_bias = op_data->op_bias; rec->cr_umask = current_umask(); + rec->cr_old_handle = op_data->op_handle; mdc_pack_capa(req, &RMF_CAPA1, op_data->op_capa1); /* the next buffer is child capa, which is used for replay, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index fb5a9959bf7a..eccbab7561fe 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -75,6 +75,12 @@ EXPORT_SYMBOL(it_clear_disposition); int it_open_error(int phase, struct lookup_intent *it) { + if (it_disposition(it, DISP_OPEN_LEASE)) { + if (phase >= DISP_OPEN_LEASE) + return it->d.lustre.it_status; + else + return 0; + } if (it_disposition(it, DISP_OPEN_OPEN)) { if (phase >= DISP_OPEN_OPEN) return it->d.lustre.it_status; @@ -281,14 +287,21 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, /* XXX: openlock is not cancelled for cross-refs. */ /* If inode is known, cancel conflicting OPEN locks. */ if (fid_is_sane(&op_data->op_fid2)) { - if (it->it_flags & (FMODE_WRITE|MDS_OPEN_TRUNC)) - mode = LCK_CW; + if (it->it_flags & MDS_OPEN_LEASE) { /* try to get lease */ + if (it->it_flags & FMODE_WRITE) + mode = LCK_EX; + else + mode = LCK_PR; + } else { + if (it->it_flags & (FMODE_WRITE|MDS_OPEN_TRUNC)) + mode = LCK_CW; #ifdef FMODE_EXEC - else if (it->it_flags & FMODE_EXEC) - mode = LCK_PR; + else if (it->it_flags & FMODE_EXEC) + mode = LCK_PR; #endif - else - mode = LCK_CR; + else + mode = LCK_CR; + } count = mdc_resource_get_unused(exp, &op_data->op_fid2, &cancels, mode, MDS_INODELOCK_OPEN); @@ -1065,10 +1078,10 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, LASSERT(it); CDEBUG(D_DLMTRACE, "(name: %.*s,"DFID") in obj "DFID - ", intent: %s flags %#o\n", op_data->op_namelen, - op_data->op_name, PFID(&op_data->op_fid2), - PFID(&op_data->op_fid1), ldlm_it2str(it->it_op), - it->it_flags); + ", intent: %s flags %#Lo\n", op_data->op_namelen, + op_data->op_name, PFID(&op_data->op_fid2), + PFID(&op_data->op_fid1), ldlm_it2str(it->it_op), + it->it_flags); lockh.cookie = 0; if (fid_is_sane(&op_data->op_fid2) && @@ -1194,9 +1207,10 @@ int mdc_intent_getattr_async(struct obd_export *exp, int rc = 0; __u64 flags = LDLM_FL_HAS_INTENT; - CDEBUG(D_DLMTRACE,"name: %.*s in inode "DFID", intent: %s flags %#o\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - ldlm_it2str(it->it_op), it->it_flags); + CDEBUG(D_DLMTRACE, + "name: %.*s in inode "DFID", intent: %s flags %#Lo\n", + op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), + ldlm_it2str(it->it_op), it->it_flags); fid_build_reg_res_name(&op_data->op_fid1, &res_id); req = mdc_intent_getattr_pack(exp, it, op_data); -- cgit v1.2.3 From d298b5377d415f001bcba914610417e3396d6d6c Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 21:23:42 +0800 Subject: drivers/staging/lustre: indent lustre_ldlm_flags_vals To follow kernel's "no spaces at the start of a line" rule. Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_dlm_flags.h | 80 +++++++++++----------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h index f8b4ba749683..75716f17f64b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h @@ -423,46 +423,46 @@ static int hf_lustre_ldlm_fl_ns_srv = -1; static int hf_lustre_ldlm_fl_excl = -1; const value_string lustre_ldlm_flags_vals[] = { - {LDLM_FL_LOCK_CHANGED, "LDLM_FL_LOCK_CHANGED"}, - {LDLM_FL_BLOCK_GRANTED, "LDLM_FL_BLOCK_GRANTED"}, - {LDLM_FL_BLOCK_CONV, "LDLM_FL_BLOCK_CONV"}, - {LDLM_FL_BLOCK_WAIT, "LDLM_FL_BLOCK_WAIT"}, - {LDLM_FL_AST_SENT, "LDLM_FL_AST_SENT"}, - {LDLM_FL_REPLAY, "LDLM_FL_REPLAY"}, - {LDLM_FL_INTENT_ONLY, "LDLM_FL_INTENT_ONLY"}, - {LDLM_FL_HAS_INTENT, "LDLM_FL_HAS_INTENT"}, - {LDLM_FL_DISCARD_DATA, "LDLM_FL_DISCARD_DATA"}, - {LDLM_FL_NO_TIMEOUT, "LDLM_FL_NO_TIMEOUT"}, - {LDLM_FL_BLOCK_NOWAIT, "LDLM_FL_BLOCK_NOWAIT"}, - {LDLM_FL_TEST_LOCK, "LDLM_FL_TEST_LOCK"}, - {LDLM_FL_CANCEL_ON_BLOCK, "LDLM_FL_CANCEL_ON_BLOCK"}, - {LDLM_FL_DENY_ON_CONTENTION, "LDLM_FL_DENY_ON_CONTENTION"}, - {LDLM_FL_AST_DISCARD_DATA, "LDLM_FL_AST_DISCARD_DATA"}, - {LDLM_FL_FAIL_LOC, "LDLM_FL_FAIL_LOC"}, - {LDLM_FL_SKIPPED, "LDLM_FL_SKIPPED"}, - {LDLM_FL_CBPENDING, "LDLM_FL_CBPENDING"}, - {LDLM_FL_WAIT_NOREPROC, "LDLM_FL_WAIT_NOREPROC"}, - {LDLM_FL_CANCEL, "LDLM_FL_CANCEL"}, - {LDLM_FL_LOCAL_ONLY, "LDLM_FL_LOCAL_ONLY"}, - {LDLM_FL_FAILED, "LDLM_FL_FAILED"}, - {LDLM_FL_CANCELING, "LDLM_FL_CANCELING"}, - {LDLM_FL_LOCAL, "LDLM_FL_LOCAL"}, - {LDLM_FL_LVB_READY, "LDLM_FL_LVB_READY"}, - {LDLM_FL_KMS_IGNORE, "LDLM_FL_KMS_IGNORE"}, - {LDLM_FL_CP_REQD, "LDLM_FL_CP_REQD"}, - {LDLM_FL_CLEANED, "LDLM_FL_CLEANED"}, - {LDLM_FL_ATOMIC_CB, "LDLM_FL_ATOMIC_CB"}, - {LDLM_FL_BL_AST, "LDLM_FL_BL_AST"}, - {LDLM_FL_BL_DONE, "LDLM_FL_BL_DONE"}, - {LDLM_FL_NO_LRU, "LDLM_FL_NO_LRU"}, - {LDLM_FL_FAIL_NOTIFIED, "LDLM_FL_FAIL_NOTIFIED"}, - {LDLM_FL_DESTROYED, "LDLM_FL_DESTROYED"}, - {LDLM_FL_SERVER_LOCK, "LDLM_FL_SERVER_LOCK"}, - {LDLM_FL_RES_LOCKED, "LDLM_FL_RES_LOCKED"}, - {LDLM_FL_WAITED, "LDLM_FL_WAITED"}, - {LDLM_FL_NS_SRV, "LDLM_FL_NS_SRV"}, - {LDLM_FL_EXCL, "LDLM_FL_EXCL"}, - { 0, NULL } + {LDLM_FL_LOCK_CHANGED, "LDLM_FL_LOCK_CHANGED"}, + {LDLM_FL_BLOCK_GRANTED, "LDLM_FL_BLOCK_GRANTED"}, + {LDLM_FL_BLOCK_CONV, "LDLM_FL_BLOCK_CONV"}, + {LDLM_FL_BLOCK_WAIT, "LDLM_FL_BLOCK_WAIT"}, + {LDLM_FL_AST_SENT, "LDLM_FL_AST_SENT"}, + {LDLM_FL_REPLAY, "LDLM_FL_REPLAY"}, + {LDLM_FL_INTENT_ONLY, "LDLM_FL_INTENT_ONLY"}, + {LDLM_FL_HAS_INTENT, "LDLM_FL_HAS_INTENT"}, + {LDLM_FL_DISCARD_DATA, "LDLM_FL_DISCARD_DATA"}, + {LDLM_FL_NO_TIMEOUT, "LDLM_FL_NO_TIMEOUT"}, + {LDLM_FL_BLOCK_NOWAIT, "LDLM_FL_BLOCK_NOWAIT"}, + {LDLM_FL_TEST_LOCK, "LDLM_FL_TEST_LOCK"}, + {LDLM_FL_CANCEL_ON_BLOCK, "LDLM_FL_CANCEL_ON_BLOCK"}, + {LDLM_FL_DENY_ON_CONTENTION, "LDLM_FL_DENY_ON_CONTENTION"}, + {LDLM_FL_AST_DISCARD_DATA, "LDLM_FL_AST_DISCARD_DATA"}, + {LDLM_FL_FAIL_LOC, "LDLM_FL_FAIL_LOC"}, + {LDLM_FL_SKIPPED, "LDLM_FL_SKIPPED"}, + {LDLM_FL_CBPENDING, "LDLM_FL_CBPENDING"}, + {LDLM_FL_WAIT_NOREPROC, "LDLM_FL_WAIT_NOREPROC"}, + {LDLM_FL_CANCEL, "LDLM_FL_CANCEL"}, + {LDLM_FL_LOCAL_ONLY, "LDLM_FL_LOCAL_ONLY"}, + {LDLM_FL_FAILED, "LDLM_FL_FAILED"}, + {LDLM_FL_CANCELING, "LDLM_FL_CANCELING"}, + {LDLM_FL_LOCAL, "LDLM_FL_LOCAL"}, + {LDLM_FL_LVB_READY, "LDLM_FL_LVB_READY"}, + {LDLM_FL_KMS_IGNORE, "LDLM_FL_KMS_IGNORE"}, + {LDLM_FL_CP_REQD, "LDLM_FL_CP_REQD"}, + {LDLM_FL_CLEANED, "LDLM_FL_CLEANED"}, + {LDLM_FL_ATOMIC_CB, "LDLM_FL_ATOMIC_CB"}, + {LDLM_FL_BL_AST, "LDLM_FL_BL_AST"}, + {LDLM_FL_BL_DONE, "LDLM_FL_BL_DONE"}, + {LDLM_FL_NO_LRU, "LDLM_FL_NO_LRU"}, + {LDLM_FL_FAIL_NOTIFIED, "LDLM_FL_FAIL_NOTIFIED"}, + {LDLM_FL_DESTROYED, "LDLM_FL_DESTROYED"}, + {LDLM_FL_SERVER_LOCK, "LDLM_FL_SERVER_LOCK"}, + {LDLM_FL_RES_LOCKED, "LDLM_FL_RES_LOCKED"}, + {LDLM_FL_WAITED, "LDLM_FL_WAITED"}, + {LDLM_FL_NS_SRV, "LDLM_FL_NS_SRV"}, + {LDLM_FL_EXCL, "LDLM_FL_EXCL"}, + { 0, NULL } }; #endif /* WIRESHARK_COMPILE */ #endif /* LDLM_ALL_FLAGS_MASK */ -- cgit v1.2.3 From d75e265bd87a34174198fe8ebf15030919e6ad5e Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Tue, 19 Nov 2013 21:23:44 +0800 Subject: staging/lustre/lnet: coding style fix for lst_test_add_ioctl To make the function a bit easier to read. This is coding style fix part of original Lustre commit in external tree. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3093 Lustre-change: http://review.whamcloud.com/6092 Signed-off-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conctl.c | 56 +++++++++++++-------------- 1 file changed, 27 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index bce3d3bde6b2..cbc416de7008 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -723,12 +723,12 @@ lst_stat_query_ioctl(lstio_stat_args_t *args) int lst_test_add_ioctl(lstio_test_args_t *args) { - char *name; - char *srcgrp = NULL; - char *dstgrp = NULL; - void *param = NULL; - int ret = 0; - int rc = -ENOMEM; + char *batch_name; + char *src_name = NULL; + char *dst_name = NULL; + void *param = NULL; + int ret = 0; + int rc = -ENOMEM; if (args->lstio_tes_resultp == NULL || args->lstio_tes_retp == NULL || @@ -755,16 +755,16 @@ int lst_test_add_ioctl(lstio_test_args_t *args) args->lstio_tes_param_len > PAGE_CACHE_SIZE - sizeof(lstcon_test_t))) return -EINVAL; - LIBCFS_ALLOC(name, args->lstio_tes_bat_nmlen + 1); - if (name == NULL) + LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1); + if (batch_name == NULL) return rc; - LIBCFS_ALLOC(srcgrp, args->lstio_tes_sgrp_nmlen + 1); - if (srcgrp == NULL) + LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1); + if (src_name == NULL) goto out; - LIBCFS_ALLOC(dstgrp, args->lstio_tes_dgrp_nmlen + 1); - if (dstgrp == NULL) + LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1); + if (dst_name == NULL) goto out; if (args->lstio_tes_param != NULL) { @@ -774,39 +774,37 @@ int lst_test_add_ioctl(lstio_test_args_t *args) } rc = -EFAULT; - if (copy_from_user(name, - args->lstio_tes_bat_name, - args->lstio_tes_bat_nmlen) || - copy_from_user(srcgrp, - args->lstio_tes_sgrp_name, - args->lstio_tes_sgrp_nmlen) || - copy_from_user(dstgrp, - args->lstio_tes_dgrp_name, - args->lstio_tes_dgrp_nmlen) || + if (copy_from_user(batch_name, args->lstio_tes_bat_name, + args->lstio_tes_bat_nmlen) || + copy_from_user(src_name, args->lstio_tes_sgrp_name, + args->lstio_tes_sgrp_nmlen) || + copy_from_user(dst_name, args->lstio_tes_dgrp_name, + args->lstio_tes_dgrp_nmlen) || copy_from_user(param, args->lstio_tes_param, args->lstio_tes_param_len)) goto out; - rc = lstcon_test_add(name, + rc = lstcon_test_add(batch_name, args->lstio_tes_type, args->lstio_tes_loop, args->lstio_tes_concur, args->lstio_tes_dist, args->lstio_tes_span, - srcgrp, dstgrp, param, args->lstio_tes_param_len, + src_name, dst_name, param, + args->lstio_tes_param_len, &ret, args->lstio_tes_resultp); if (ret != 0) rc = (copy_to_user(args->lstio_tes_retp, &ret, sizeof(ret))) ? -EFAULT : 0; out: - if (name != NULL) - LIBCFS_FREE(name, args->lstio_tes_bat_nmlen + 1); + if (batch_name != NULL) + LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1); - if (srcgrp != NULL) - LIBCFS_FREE(srcgrp, args->lstio_tes_sgrp_nmlen + 1); + if (src_name != NULL) + LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1); - if (dstgrp != NULL) - LIBCFS_FREE(dstgrp, args->lstio_tes_dgrp_nmlen + 1); + if (dst_name != NULL) + LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1); if (param != NULL) LIBCFS_FREE(param, args->lstio_tes_param_len); -- cgit v1.2.3 From f02e015688079350cb507c45cdf9790cfc772384 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Tue, 19 Nov 2013 21:23:45 +0800 Subject: staging/lustre/lnet: remove extra space in lstcon_rpc_trans_abort This is coding style fix part of original Lustre commit in external tree. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3093 Lustre-change: http://review.whamcloud.com/6092 Signed-off-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/conrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 9a52f25b72e9..53d58924737b 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -311,7 +311,7 @@ lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) sfw_abort_rpc(rpc); - if (error != ETIMEDOUT) + if (error != ETIMEDOUT) continue; nd = crpc->crp_node; -- cgit v1.2.3 From 75f1c090c2d01b2e91f30d3502967d6c14e22aea Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Tue, 19 Nov 2013 21:23:46 +0800 Subject: staging/lustre/lnet: constify name argument of lstcon_group_find/lstcon_batch_find This is part of original Lustre commit in external tree. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3093 Lustre-change: http://review.whamcloud.com/6092 Signed-off-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/console.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index f1152e4fbcc4..e78281d86639 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -265,7 +265,7 @@ lstcon_group_decref(lstcon_group_t *grp) } static int -lstcon_group_find(char *name, lstcon_group_t **grpp) +lstcon_group_find(const char *name, lstcon_group_t **grpp) { lstcon_group_t *grp; @@ -831,7 +831,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, } int -lstcon_batch_find(char *name, lstcon_batch_t **batpp) +lstcon_batch_find(const char *name, lstcon_batch_t **batpp) { lstcon_batch_t *bat; -- cgit v1.2.3 From 6a5b7a6dbfc70cd59ea7144d62fbec92b28d8a37 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Tue, 19 Nov 2013 21:23:47 +0800 Subject: staging/lustre/lnet: coding style fix for lstcon_test_add To make the function a bit easier to read. This is coding style fix part of original Lustre commit in external tree. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3093 Lustre-change: http://review.whamcloud.com/6092 Signed-off-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/console.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index e78281d86639..067a8b535f7c 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1284,18 +1284,18 @@ lstcon_test_add(char *name, int type, int loop, int concur, } memset(test, 0, offsetof(lstcon_test_t, tes_param[paramlen])); - test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id; - test->tes_batch = batch; - test->tes_type = type; - test->tes_oneside = 0; /* TODO */ - test->tes_loop = loop; + test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id; + test->tes_batch = batch; + test->tes_type = type; + test->tes_oneside = 0; /* TODO */ + test->tes_loop = loop; test->tes_concur = concur; - test->tes_stop_onerr = 1; /* TODO */ - test->tes_span = span; - test->tes_dist = dist; + test->tes_stop_onerr = 1; /* TODO */ + test->tes_span = span; + test->tes_dist = dist; test->tes_cliidx = 0; /* just used for creating RPC */ - test->tes_src_grp = src_grp; - test->tes_dst_grp = dst_grp; + test->tes_src_grp = src_grp; + test->tes_dst_grp = dst_grp; INIT_LIST_HEAD(&test->tes_trans_list); if (param != NULL) { -- cgit v1.2.3 From de55446b8e3e81ffcc1bfefb4b2d20209af45536 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:35 +0800 Subject: staging/lustre/libcfs: remove HAVE_MM_INLINE Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index c204b677796f..9b30b4d92cc9 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -63,9 +63,7 @@ #include #include #include -#ifdef HAVE_MM_INLINE -# include -#endif +#include #include #include #include -- cgit v1.2.3 From 76766b46105b5b1d944bfc2fb12c98823de8e650 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:36 +0800 Subject: staging/lustre: remove liblustreapi.h It is only used by user space. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/liblustreapi.h | 43 ---------------------- 1 file changed, 43 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/include/lustre/liblustreapi.h (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/liblustreapi.h b/drivers/staging/lustre/lustre/include/lustre/liblustreapi.h deleted file mode 100644 index 707eb74fdf68..000000000000 --- a/drivers/staging/lustre/lustre/include/lustre/liblustreapi.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -/* - * NOTE: This file is DEPRECATED! Please include lustreapi.h directly - * instead of this file. This file will be removed from a future version - * of lustre! - */ - -#ifndef _LIBLUSTREAPI_H_ -#define _LIBLUSTREAPI_H_ - -#include -#warning "Including liblustreapi.h is deprecated. Include lustreapi.h directly." - -#endif -- cgit v1.2.3 From e964cb969e493725a1c911b8d620117722bd2db6 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:37 +0800 Subject: staging/lustre: remove lustreapi.h It is only used by user space. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustreapi.h | 310 --------------------- 1 file changed, 310 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/include/lustre/lustreapi.h (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustreapi.h b/drivers/staging/lustre/lustre/include/lustre/lustreapi.h deleted file mode 100644 index 63da66506639..000000000000 --- a/drivers/staging/lustre/lustre/include/lustre/lustreapi.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Whamcloud, Inc. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LUSTREAPI_H_ -#define _LUSTREAPI_H_ - -/** \defgroup llapi llapi - * - * @{ - */ - -#include - -typedef void (*llapi_cb_t)(char *obd_type_name, char *obd_name, char *obd_uuid, void *args); - -/* lustreapi message severity level */ -enum llapi_message_level { - LLAPI_MSG_OFF = 0, - LLAPI_MSG_FATAL = 1, - LLAPI_MSG_ERROR = 2, - LLAPI_MSG_WARN = 3, - LLAPI_MSG_NORMAL = 4, - LLAPI_MSG_INFO = 5, - LLAPI_MSG_DEBUG = 6, - LLAPI_MSG_MAX -}; - -/* the bottom three bits reserved for llapi_message_level */ -#define LLAPI_MSG_MASK 0x00000007 -#define LLAPI_MSG_NO_ERRNO 0x00000010 - -extern void llapi_msg_set_level(int level); -extern void llapi_error(int level, int rc, char *fmt, ...); -#define llapi_err_noerrno(level, fmt, a...) \ - llapi_error((level) | LLAPI_MSG_NO_ERRNO, 0, fmt, ## a) -extern void llapi_printf(int level, char *fmt, ...); -extern int llapi_file_create(const char *name, unsigned long long stripe_size, - int stripe_offset, int stripe_count, - int stripe_pattern); -extern int llapi_file_open(const char *name, int flags, int mode, - unsigned long long stripe_size, int stripe_offset, - int stripe_count, int stripe_pattern); -extern int llapi_file_create_pool(const char *name, - unsigned long long stripe_size, - int stripe_offset, int stripe_count, - int stripe_pattern, char *pool_name); -extern int llapi_file_open_pool(const char *name, int flags, int mode, - unsigned long long stripe_size, - int stripe_offset, int stripe_count, - int stripe_pattern, char *pool_name); -extern int llapi_poollist(const char *name); -extern int llapi_get_poollist(const char *name, char **poollist, int list_size, - char *buffer, int buffer_size); -extern int llapi_get_poolmembers(const char *poolname, char **members, - int list_size, char *buffer, int buffer_size); -extern int llapi_file_get_stripe(const char *path, struct lov_user_md *lum); -#define HAVE_LLAPI_FILE_LOOKUP -extern int llapi_file_lookup(int dirfd, const char *name); - -#define VERBOSE_COUNT 0x1 -#define VERBOSE_SIZE 0x2 -#define VERBOSE_OFFSET 0x4 -#define VERBOSE_POOL 0x8 -#define VERBOSE_DETAIL 0x10 -#define VERBOSE_OBJID 0x20 -#define VERBOSE_GENERATION 0x40 -#define VERBOSE_MDTINDEX 0x80 -#define VERBOSE_ALL (VERBOSE_COUNT | VERBOSE_SIZE | VERBOSE_OFFSET | \ - VERBOSE_POOL | VERBOSE_OBJID | VERBOSE_GENERATION) - -struct find_param { - unsigned int maxdepth; - time_t atime; - time_t mtime; - time_t ctime; - int asign; /* cannot be bitfields due to using pointers to */ - int csign; /* access them during argument parsing. */ - int msign; - int type; - int size_sign:2, /* these need to be signed values */ - stripesize_sign:2, - stripecount_sign:2; - unsigned long long size; - unsigned long long size_units; - uid_t uid; - gid_t gid; - - unsigned long zeroend:1, - recursive:1, - exclude_pattern:1, - exclude_type:1, - exclude_obd:1, - exclude_mdt:1, - exclude_gid:1, - exclude_uid:1, - check_gid:1, /* group ID */ - check_uid:1, /* user ID */ - check_pool:1, /* LOV pool name */ - check_size:1, /* file size */ - exclude_pool:1, - exclude_size:1, - exclude_atime:1, - exclude_mtime:1, - exclude_ctime:1, - get_lmv:1, /* get MDT list from LMV */ - raw:1, /* do not fill in defaults */ - check_stripesize:1, /* LOV stripe size */ - exclude_stripesize:1, - check_stripecount:1, /* LOV stripe count */ - exclude_stripecount:1; - - int verbose; - int quiet; - - /* regular expression */ - char *pattern; - - char *print_fmt; - - struct obd_uuid *obduuid; - int num_obds; - int num_alloc_obds; - int obdindex; - int *obdindexes; - - struct obd_uuid *mdtuuid; - int num_mdts; - int num_alloc_mdts; - int mdtindex; - int *mdtindexes; - int file_mdtindex; - - int lumlen; - struct lov_user_mds_data *lmd; - - char poolname[LOV_MAXPOOLNAME + 1]; - - int fp_lmv_count; - struct lmv_user_md *fp_lmv_md; - - unsigned long long stripesize; - unsigned long long stripesize_units; - unsigned long long stripecount; - - /* In-process parameters. */ - unsigned long got_uuids:1, - obds_printed:1, - have_fileinfo:1; /* file attrs and LOV xattr */ - unsigned int depth; - dev_t st_dev; -}; - -extern int llapi_ostlist(char *path, struct find_param *param); -extern int llapi_uuid_match(char *real_uuid, char *search_uuid); -extern int llapi_getstripe(char *path, struct find_param *param); -extern int llapi_find(char *path, struct find_param *param); - -extern int llapi_file_fget_mdtidx(int fd, int *mdtidx); -extern int llapi_dir_create_pool(const char *name, int flags, int stripe_offset, - int stripe_count, int stripe_pattern, - char *poolname); -int llapi_direntry_remove(char *dname); -extern int llapi_obd_statfs(char *path, __u32 type, __u32 index, - struct obd_statfs *stat_buf, - struct obd_uuid *uuid_buf); -extern int llapi_ping(char *obd_type, char *obd_name); -extern int llapi_target_check(int num_types, char **obd_types, char *dir); -extern int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid); -extern int llapi_file_get_lmv_uuid(const char *path, struct obd_uuid *lmv_uuid); -extern int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_uuid); -extern int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count); -extern int llapi_lmv_get_uuids(int fd, struct obd_uuid *uuidp, int *mdt_count); -extern int llapi_is_lustre_mnttype(const char *type); -extern int llapi_search_ost(char *fsname, char *poolname, char *ostname); -extern int llapi_get_obd_count(char *mnt, int *count, int is_mdt); -extern int parse_size(char *optarg, unsigned long long *size, - unsigned long long *size_units, int bytes_spec); -extern int llapi_search_mounts(const char *pathname, int index, - char *mntdir, char *fsname); -extern int llapi_search_fsname(const char *pathname, char *fsname); -extern int llapi_getname(const char *path, char *buf, size_t size); - -extern void llapi_ping_target(char *obd_type, char *obd_name, - char *obd_uuid, void *args); - -extern int llapi_search_rootpath(char *pathname, const char *fsname); - -struct mntent; -#define HAVE_LLAPI_IS_LUSTRE_MNT -extern int llapi_is_lustre_mnt(struct mntent *mnt); -extern int llapi_quotachown(char *path, int flag); -extern int llapi_quotacheck(char *mnt, int check_type); -extern int llapi_poll_quotacheck(char *mnt, struct if_quotacheck *qchk); -extern int llapi_quotactl(char *mnt, struct if_quotactl *qctl); -extern int llapi_target_iterate(int type_num, char **obd_type, void *args, - llapi_cb_t cb); -extern int llapi_get_connect_flags(const char *mnt, __u64 *flags); -extern int llapi_lsetfacl(int argc, char *argv[]); -extern int llapi_lgetfacl(int argc, char *argv[]); -extern int llapi_rsetfacl(int argc, char *argv[]); -extern int llapi_rgetfacl(int argc, char *argv[]); -extern int llapi_cp(int argc, char *argv[]); -extern int llapi_ls(int argc, char *argv[]); -extern int llapi_fid2path(const char *device, const char *fidstr, char *path, - int pathlen, long long *recno, int *linkno); -extern int llapi_path2fid(const char *path, lustre_fid *fid); -extern int llapi_fd2fid(const int fd, lustre_fid *fid); - -extern int llapi_get_version(char *buffer, int buffer_size, char **version); -extern int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags); -extern int llapi_hsm_state_get(const char *path, struct hsm_user_state *hus); -extern int llapi_hsm_state_set(const char *path, __u64 setmask, __u64 clearmask, - __u32 archive_id); - -extern int llapi_create_volatile_idx(char *directory, int idx, int mode); -static inline int llapi_create_volatile(char *directory, int mode) -{ - return llapi_create_volatile_idx(directory, -1, mode); -} - - -extern int llapi_fswap_layouts(const int fd1, const int fd2, - __u64 dv1, __u64 dv2, __u64 flags); -extern int llapi_swap_layouts(const char *path1, const char *path2, - __u64 dv1, __u64 dv2, __u64 flags); - -/* Changelog interface. priv is private state, managed internally - by these functions */ -#define CHANGELOG_FLAG_FOLLOW 0x01 /* Not yet implemented */ -#define CHANGELOG_FLAG_BLOCK 0x02 /* Blocking IO makes sense in case of - slow user parsing of the records, but it also prevents us from cleaning - up if the records are not consumed. */ - -/* Records received are in extentded format now, though most of them are still - * written in disk in changelog_rec format (to save space and time), it's - * converted to extented format in the lustre api to ease changelog analysis. */ -#define HAVE_CHANGELOG_EXTEND_REC 1 - -extern int llapi_changelog_start(void **priv, int flags, const char *mdtname, - long long startrec); -extern int llapi_changelog_fini(void **priv); -extern int llapi_changelog_recv(void *priv, struct changelog_ext_rec **rech); -extern int llapi_changelog_free(struct changelog_ext_rec **rech); -/* Allow records up to endrec to be destroyed; requires registered id. */ -extern int llapi_changelog_clear(const char *mdtname, const char *idstr, - long long endrec); - -/* HSM copytool interface. - * priv is private state, managed internally by these functions - */ -struct hsm_copytool_private; -extern int llapi_hsm_copytool_start(struct hsm_copytool_private **priv, - char *fsname, int flags, - int archive_count, int *archives); -extern int llapi_hsm_copytool_fini(struct hsm_copytool_private **priv); -extern int llapi_hsm_copytool_recv(struct hsm_copytool_private *priv, - struct hsm_action_list **hal, int *msgsize); -extern int llapi_hsm_copytool_free(struct hsm_action_list **hal); -extern int llapi_hsm_copy_start(char *mnt, struct hsm_copy *copy, - const struct hsm_action_item *hai); -extern int llapi_hsm_copy_end(char *mnt, struct hsm_copy *copy, - const struct hsm_progress *hp); -extern int llapi_hsm_progress(char *mnt, struct hsm_progress *hp); -extern int llapi_hsm_import(const char *dst, int archive, struct stat *st, - unsigned long long stripe_size, int stripe_offset, - int stripe_count, int stripe_pattern, - char *pool_name, lustre_fid *newfid); - -/* HSM user interface */ -extern struct hsm_user_request *llapi_hsm_user_request_alloc(int itemcount, - int data_len); -extern int llapi_hsm_request(char *mnt, struct hsm_user_request *request); -extern int llapi_hsm_current_action(const char *path, - struct hsm_current_action *hca); -/** @} llapi */ - -#endif -- cgit v1.2.3 From bda211d5c166a836c14f8f76268228550d3baf67 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:38 +0800 Subject: staging/lustre: remove fsfilt_ext3.c It is only used by server. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c | 760 ----------------------- 1 file changed, 760 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c b/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c deleted file mode 100644 index ee75994003e1..000000000000 --- a/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/lvfs/fsfilt_ext3.c - * - * Author: Andreas Dilger - */ - -#define DEBUG_SUBSYSTEM S_FILTER - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#ifdef HAVE_EXT_PBLOCK /* Name changed to ext4_ext_pblock for kernel 2.6.35 */ -#define ext3_ext_pblock(ex) ext_pblock((ex)) -#endif - -/* for kernels 2.6.18 and later */ -#define FSFILT_SINGLEDATA_TRANS_BLOCKS(sb) EXT3_SINGLEDATA_TRANS_BLOCKS(sb) - -#define fsfilt_ext3_ext_insert_extent(handle, inode, path, newext, flag) \ - ext3_ext_insert_extent(handle, inode, path, newext, flag) - -#define ext3_mb_discard_inode_preallocations(inode) \ - ext3_discard_preallocations(inode) - -#define fsfilt_log_start_commit(journal, tid) jbd2_log_start_commit(journal, tid) -#define fsfilt_log_wait_commit(journal, tid) jbd2_log_wait_commit(journal, tid) - -static struct kmem_cache *fcb_cache; - -struct fsfilt_cb_data { - struct ext4_journal_cb_entry cb_jcb; /* private data - MUST BE FIRST */ - fsfilt_cb_t cb_func; /* MDS/OBD completion function */ - struct obd_device *cb_obd; /* MDS/OBD completion device */ - __u64 cb_last_rcvd; /* MDS/OST last committed operation */ - void *cb_data; /* MDS/OST completion function data */ -}; - -static char *fsfilt_ext3_get_label(struct super_block *sb) -{ - return EXT3_SB(sb)->s_es->s_volume_name; -} - -/* kernel has ext4_blocks_for_truncate since linux-3.1.1 */ -# include - -/* - * We don't currently need any additional blocks for rmdir and - * unlink transactions because we are storing the OST oa_id inside - * the inode (which we will be changing anyways as part of this - * transaction). - */ -static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private, - int logs) -{ - /* For updates to the last received file */ - int nblocks = FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb); - journal_t *journal; - void *handle; - - if (current->journal_info) { - CDEBUG(D_INODE, "increasing refcount on %p\n", - current->journal_info); - goto journal_start; - } - - switch(op) { - case FSFILT_OP_UNLINK: - /* delete one file + create/update logs for each stripe */ - nblocks += EXT3_DELETE_TRANS_BLOCKS(inode->i_sb); - nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS + - FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb)) * logs; - break; - case FSFILT_OP_CANCEL_UNLINK: - LASSERT(logs == 1); - - /* blocks for log header bitmap update OR - * blocks for catalog header bitmap update + unlink of logs + - * blocks for delete the inode (include blocks truncating). */ - nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) + - EXT3_DELETE_TRANS_BLOCKS(inode->i_sb) + - ext4_blocks_for_truncate(inode) + 3; - break; - default: CERROR("unknown transaction start op %d\n", op); - LBUG(); - } - - LASSERT(current->journal_info == desc_private); - journal = EXT3_SB(inode->i_sb)->s_journal; - if (nblocks > journal->j_max_transaction_buffers) { - CWARN("too many credits %d for op %ux%u using %d instead\n", - nblocks, op, logs, journal->j_max_transaction_buffers); - nblocks = journal->j_max_transaction_buffers; - } - - journal_start: - LASSERTF(nblocks > 0, "can't start %d credit transaction\n", nblocks); - handle = ext3_journal_start(inode, nblocks); - - if (!IS_ERR(handle)) - LASSERT(current->journal_info == handle); - else - CERROR("error starting handle for op %u (%u credits): rc %ld\n", - op, nblocks, PTR_ERR(handle)); - return handle; -} - -static int fsfilt_ext3_commit(struct inode *inode, void *h, int force_sync) -{ - int rc; - handle_t *handle = h; - - LASSERT(current->journal_info == handle); - if (force_sync) - handle->h_sync = 1; /* recovery likes this */ - - rc = ext3_journal_stop(handle); - - return rc; -} - -#ifndef EXT3_EXTENTS_FL -#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ -#endif - -#ifndef EXT_ASSERT -#define EXT_ASSERT(cond) BUG_ON(!(cond)) -#endif - -#define EXT_GENERATION(inode) (EXT4_I(inode)->i_ext_generation) -#define ext3_ext_base inode -#define ext3_ext_base2inode(inode) (inode) -#define EXT_DEPTH(inode) ext_depth(inode) -#define fsfilt_ext3_ext_walk_space(inode, block, num, cb, cbdata) \ - ext3_ext_walk_space(inode, block, num, cb, cbdata); - -struct bpointers { - unsigned long *blocks; - unsigned long start; - int num; - int init_num; - int create; -}; - -static long ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path, - unsigned long block, int *aflags) -{ - struct ext3_inode_info *ei = EXT3_I(inode); - unsigned long bg_start; - unsigned long colour; - int depth; - - if (path) { - struct ext3_extent *ex; - depth = path->p_depth; - - /* try to predict block placement */ - if ((ex = path[depth].p_ext)) - return ext4_ext_pblock(ex) + (block - le32_to_cpu(ex->ee_block)); - - /* it looks index is empty - * try to find starting from index itself */ - if (path[depth].p_bh) - return path[depth].p_bh->b_blocknr; - } - - /* OK. use inode's group */ - bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + - le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); - colour = (current->pid % 16) * - (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); - return bg_start + colour + block; -} - -#define ll_unmap_underlying_metadata(sb, blocknr) \ - unmap_underlying_metadata((sb)->s_bdev, blocknr) - -#ifndef EXT3_MB_HINT_GROUP_ALLOC -static unsigned long new_blocks(handle_t *handle, struct ext3_ext_base *base, - struct ext3_ext_path *path, unsigned long block, - unsigned long *count, int *err) -{ - unsigned long pblock, goal; - int aflags = 0; - struct inode *inode = ext3_ext_base2inode(base); - - goal = ext3_ext_find_goal(inode, path, block, &aflags); - aflags |= 2; /* block have been already reserved */ - pblock = ext3_mb_new_blocks(handle, inode, goal, count, aflags, err); - return pblock; - -} -#else -static unsigned long new_blocks(handle_t *handle, struct ext3_ext_base *base, - struct ext3_ext_path *path, unsigned long block, - unsigned long *count, int *err) -{ - struct inode *inode = ext3_ext_base2inode(base); - struct ext3_allocation_request ar; - unsigned long pblock; - int aflags; - - /* find neighbour allocated blocks */ - ar.lleft = block; - *err = ext3_ext_search_left(base, path, &ar.lleft, &ar.pleft); - if (*err) - return 0; - ar.lright = block; - *err = ext3_ext_search_right(base, path, &ar.lright, &ar.pright); - if (*err) - return 0; - - /* allocate new block */ - ar.goal = ext3_ext_find_goal(inode, path, block, &aflags); - ar.inode = inode; - ar.logical = block; - ar.len = *count; - ar.flags = EXT3_MB_HINT_DATA; - pblock = ext3_mb_new_blocks(handle, &ar, err); - *count = ar.len; - return pblock; -} -#endif - -static int ext3_ext_new_extent_cb(struct ext3_ext_base *base, - struct ext3_ext_path *path, - struct ext3_ext_cache *cex, -#ifdef HAVE_EXT_PREPARE_CB_EXTENT - struct ext3_extent *ex, -#endif - void *cbdata) -{ - struct bpointers *bp = cbdata; - struct inode *inode = ext3_ext_base2inode(base); - struct ext3_extent nex; - unsigned long pblock; - unsigned long tgen; - int err, i; - unsigned long count; - handle_t *handle; - -#ifdef EXT3_EXT_CACHE_EXTENT - if (cex->ec_type == EXT3_EXT_CACHE_EXTENT) -#else - if ((cex->ec_len != 0) && (cex->ec_start != 0)) -#endif - { - err = EXT_CONTINUE; - goto map; - } - - if (bp->create == 0) { - i = 0; - if (cex->ec_block < bp->start) - i = bp->start - cex->ec_block; - if (i >= cex->ec_len) - CERROR("nothing to do?! i = %d, e_num = %u\n", - i, cex->ec_len); - for (; i < cex->ec_len && bp->num; i++) { - *(bp->blocks) = 0; - bp->blocks++; - bp->num--; - bp->start++; - } - - return EXT_CONTINUE; - } - - tgen = EXT_GENERATION(base); - count = ext3_ext_calc_credits_for_insert(base, path); - - handle = ext3_journal_start(inode, count+EXT3_ALLOC_NEEDED+1); - if (IS_ERR(handle)) { - return PTR_ERR(handle); - } - - if (tgen != EXT_GENERATION(base)) { - /* the tree has changed. so path can be invalid at moment */ - ext3_journal_stop(handle); - return EXT_REPEAT; - } - - /* In 2.6.32 kernel, ext4_ext_walk_space()'s callback func is not - * protected by i_data_sem as whole. so we patch it to store - * generation to path and now verify the tree hasn't changed */ - down_write((&EXT4_I(inode)->i_data_sem)); - - /* validate extent, make sure the extent tree does not changed */ - if (EXT_GENERATION(base) != path[0].p_generation) { - /* cex is invalid, try again */ - up_write(&EXT4_I(inode)->i_data_sem); - ext3_journal_stop(handle); - return EXT_REPEAT; - } - - count = cex->ec_len; - pblock = new_blocks(handle, base, path, cex->ec_block, &count, &err); - if (!pblock) - goto out; - EXT_ASSERT(count <= cex->ec_len); - - /* insert new extent */ - nex.ee_block = cpu_to_le32(cex->ec_block); - ext3_ext_store_pblock(&nex, pblock); - nex.ee_len = cpu_to_le16(count); - err = fsfilt_ext3_ext_insert_extent(handle, base, path, &nex, 0); - if (err) { - /* free data blocks we just allocated */ - /* not a good idea to call discard here directly, - * but otherwise we'd need to call it every free() */ -#ifdef EXT3_MB_HINT_GROUP_ALLOC - ext3_mb_discard_inode_preallocations(inode); -#endif -#ifdef HAVE_EXT_FREE_BLOCK_WITH_BUFFER_HEAD /* Introduced in 2.6.32-rc7 */ - ext3_free_blocks(handle, inode, NULL, ext4_ext_pblock(&nex), - cpu_to_le16(nex.ee_len), 0); -#else - ext3_free_blocks(handle, inode, ext4_ext_pblock(&nex), - cpu_to_le16(nex.ee_len), 0); -#endif - goto out; - } - - /* - * Putting len of the actual extent we just inserted, - * we are asking ext3_ext_walk_space() to continue - * scaning after that block - */ - cex->ec_len = le16_to_cpu(nex.ee_len); - cex->ec_start = ext4_ext_pblock(&nex); - BUG_ON(le16_to_cpu(nex.ee_len) == 0); - BUG_ON(le32_to_cpu(nex.ee_block) != cex->ec_block); - -out: - up_write((&EXT4_I(inode)->i_data_sem)); - ext3_journal_stop(handle); -map: - if (err >= 0) { - /* map blocks */ - if (bp->num == 0) { - CERROR("hmm. why do we find this extent?\n"); - CERROR("initial space: %lu:%u\n", - bp->start, bp->init_num); -#ifdef EXT3_EXT_CACHE_EXTENT - CERROR("current extent: %u/%u/%llu %d\n", - cex->ec_block, cex->ec_len, - (unsigned long long)cex->ec_start, - cex->ec_type); -#else - CERROR("current extent: %u/%u/%llu\n", - cex->ec_block, cex->ec_len, - (unsigned long long)cex->ec_start); -#endif - } - i = 0; - if (cex->ec_block < bp->start) - i = bp->start - cex->ec_block; - if (i >= cex->ec_len) - CERROR("nothing to do?! i = %d, e_num = %u\n", - i, cex->ec_len); - for (; i < cex->ec_len && bp->num; i++) { - *(bp->blocks) = cex->ec_start + i; -#ifdef EXT3_EXT_CACHE_EXTENT - if (cex->ec_type != EXT3_EXT_CACHE_EXTENT) -#else - if ((cex->ec_len == 0) || (cex->ec_start == 0)) -#endif - { - /* unmap any possible underlying metadata from - * the block device mapping. bug 6998. */ - ll_unmap_underlying_metadata(inode->i_sb, - *(bp->blocks)); - } - bp->blocks++; - bp->num--; - bp->start++; - } - } - return err; -} - -int fsfilt_map_nblocks(struct inode *inode, unsigned long block, - unsigned long num, unsigned long *blocks, - int create) -{ - struct ext3_ext_base *base = inode; - struct bpointers bp; - int err; - - CDEBUG(D_OTHER, "blocks %lu-%lu requested for inode %u\n", - block, block + num - 1, (unsigned) inode->i_ino); - - bp.blocks = blocks; - bp.start = block; - bp.init_num = bp.num = num; - bp.create = create; - - err = fsfilt_ext3_ext_walk_space(base, block, num, - ext3_ext_new_extent_cb, &bp); - ext3_ext_invalidate_cache(base); - - return err; -} - -int fsfilt_ext3_map_ext_inode_pages(struct inode *inode, struct page **page, - int pages, unsigned long *blocks, - int create) -{ - int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits; - int rc = 0, i = 0; - struct page *fp = NULL; - int clen = 0; - - CDEBUG(D_OTHER, "inode %lu: map %d pages from %lu\n", - inode->i_ino, pages, (*page)->index); - - /* pages are sorted already. so, we just have to find - * contig. space and process them properly */ - while (i < pages) { - if (fp == NULL) { - /* start new extent */ - fp = *page++; - clen = 1; - i++; - continue; - } else if (fp->index + clen == (*page)->index) { - /* continue the extent */ - page++; - clen++; - i++; - continue; - } - - /* process found extent */ - rc = fsfilt_map_nblocks(inode, fp->index * blocks_per_page, - clen * blocks_per_page, blocks, - create); - if (rc) - GOTO(cleanup, rc); - - /* look for next extent */ - fp = NULL; - blocks += blocks_per_page * clen; - } - - if (fp) - rc = fsfilt_map_nblocks(inode, fp->index * blocks_per_page, - clen * blocks_per_page, blocks, - create); -cleanup: - return rc; -} - -int fsfilt_ext3_map_bm_inode_pages(struct inode *inode, struct page **page, - int pages, unsigned long *blocks, - int create) -{ - int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits; - unsigned long *b; - int rc = 0, i; - - for (i = 0, b = blocks; i < pages; i++, page++) { - rc = ext3_map_inode_page(inode, *page, b, create); - if (rc) { - CERROR("ino %lu, blk %lu create %d: rc %d\n", - inode->i_ino, *b, create, rc); - break; - } - - b += blocks_per_page; - } - return rc; -} - -int fsfilt_ext3_map_inode_pages(struct inode *inode, struct page **page, - int pages, unsigned long *blocks, - int create, struct mutex *optional_mutex) -{ - int rc; - - if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) { - rc = fsfilt_ext3_map_ext_inode_pages(inode, page, pages, - blocks, create); - return rc; - } - if (optional_mutex != NULL) - mutex_lock(optional_mutex); - rc = fsfilt_ext3_map_bm_inode_pages(inode, page, pages, blocks, create); - if (optional_mutex != NULL) - mutex_unlock(optional_mutex); - - return rc; -} - -int fsfilt_ext3_read(struct inode *inode, void *buf, int size, loff_t *offs) -{ - unsigned long block; - struct buffer_head *bh; - int err, blocksize, csize, boffs, osize = size; - - /* prevent reading after eof */ - spin_lock(&inode->i_lock); - if (i_size_read(inode) < *offs + size) { - size = i_size_read(inode) - *offs; - spin_unlock(&inode->i_lock); - if (size < 0) { - CDEBUG(D_EXT2, "size %llu is too short for read @%llu\n", - i_size_read(inode), *offs); - return -EBADR; - } else if (size == 0) { - return 0; - } - } else { - spin_unlock(&inode->i_lock); - } - - blocksize = 1 << inode->i_blkbits; - - while (size > 0) { - block = *offs >> inode->i_blkbits; - boffs = *offs & (blocksize - 1); - csize = min(blocksize - boffs, size); - bh = ext3_bread(NULL, inode, block, 0, &err); - if (!bh) { - CERROR("can't read block: %d\n", err); - return err; - } - - memcpy(buf, bh->b_data + boffs, csize); - brelse(bh); - - *offs += csize; - buf += csize; - size -= csize; - } - return osize; -} -EXPORT_SYMBOL(fsfilt_ext3_read); - -static int fsfilt_ext3_read_record(struct file * file, void *buf, - int size, loff_t *offs) -{ - int rc; - rc = fsfilt_ext3_read(file->f_dentry->d_inode, buf, size, offs); - if (rc > 0) - rc = 0; - return rc; -} - -int fsfilt_ext3_write_handle(struct inode *inode, void *buf, int bufsize, - loff_t *offs, handle_t *handle) -{ - struct buffer_head *bh = NULL; - loff_t old_size = i_size_read(inode), offset = *offs; - loff_t new_size = i_size_read(inode); - unsigned long block; - int err = 0, blocksize = 1 << inode->i_blkbits, size, boffs; - - while (bufsize > 0) { - if (bh != NULL) - brelse(bh); - - block = offset >> inode->i_blkbits; - boffs = offset & (blocksize - 1); - size = min(blocksize - boffs, bufsize); - bh = ext3_bread(handle, inode, block, 1, &err); - if (!bh) { - CERROR("can't read/create block: %d\n", err); - break; - } - - err = ext3_journal_get_write_access(handle, bh); - if (err) { - CERROR("journal_get_write_access() returned error %d\n", - err); - break; - } - LASSERT(bh->b_data + boffs + size <= bh->b_data + bh->b_size); - memcpy(bh->b_data + boffs, buf, size); - err = ext3_journal_dirty_metadata(handle, bh); - if (err) { - CERROR("journal_dirty_metadata() returned error %d\n", - err); - break; - } - if (offset + size > new_size) - new_size = offset + size; - offset += size; - bufsize -= size; - buf += size; - } - if (bh) - brelse(bh); - - /* correct in-core and on-disk sizes */ - if (new_size > i_size_read(inode)) { - spin_lock(&inode->i_lock); - if (new_size > i_size_read(inode)) - i_size_write(inode, new_size); - if (i_size_read(inode) > EXT3_I(inode)->i_disksize) - EXT3_I(inode)->i_disksize = i_size_read(inode); - if (i_size_read(inode) > old_size) { - spin_unlock(&inode->i_lock); - mark_inode_dirty(inode); - } else { - spin_unlock(&inode->i_lock); - } - } - - if (err == 0) - *offs = offset; - return err; -} -EXPORT_SYMBOL(fsfilt_ext3_write_handle); - -static int fsfilt_ext3_write_record(struct file *file, void *buf, int bufsize, - loff_t *offs, int force_sync) -{ - struct inode *inode = file->f_dentry->d_inode; - handle_t *handle; - int err, block_count = 0, blocksize; - - /* Determine how many transaction credits are needed */ - blocksize = 1 << inode->i_blkbits; - block_count = (*offs & (blocksize - 1)) + bufsize; - block_count = (block_count + blocksize - 1) >> inode->i_blkbits; - - handle = ext3_journal_start(inode, - block_count * EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + 2); - if (IS_ERR(handle)) { - CERROR("can't start transaction for %d blocks (%d bytes)\n", - block_count * EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + 2, - bufsize); - return PTR_ERR(handle); - } - - err = fsfilt_ext3_write_handle(inode, buf, bufsize, offs, handle); - - if (!err && force_sync) - handle->h_sync = 1; /* recovery likes this */ - - ext3_journal_stop(handle); - - return err; -} - -static int fsfilt_ext3_setup(struct super_block *sb) -{ - if (!EXT3_HAS_COMPAT_FEATURE(sb, - EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { - CERROR("ext3 mounted without journal\n"); - return -EINVAL; - } - -#ifdef S_PDIROPS - CWARN("Enabling PDIROPS\n"); - set_opt(EXT3_SB(sb)->s_mount_opt, PDIROPS); - sb->s_flags |= S_PDIROPS; -#endif - if (!EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) - CWARN("filesystem doesn't have dir_index feature enabled\n"); - return 0; -} -static struct fsfilt_operations fsfilt_ext3_ops = { - .fs_type = "ext3", - .fs_owner = THIS_MODULE, - .fs_getlabel = fsfilt_ext3_get_label, - .fs_start = fsfilt_ext3_start, - .fs_commit = fsfilt_ext3_commit, - .fs_map_inode_pages = fsfilt_ext3_map_inode_pages, - .fs_write_record = fsfilt_ext3_write_record, - .fs_read_record = fsfilt_ext3_read_record, - .fs_setup = fsfilt_ext3_setup, -}; - -static int __init fsfilt_ext3_init(void) -{ - int rc; - - fcb_cache = kmem_cache_create("fsfilt_ext3_fcb", - sizeof(struct fsfilt_cb_data), 0, 0); - if (!fcb_cache) { - CERROR("error allocating fsfilt journal callback cache\n"); - GOTO(out, rc = -ENOMEM); - } - - rc = fsfilt_register_ops(&fsfilt_ext3_ops); - - if (rc) { - int err = kmem_cache_destroy(fcb_cache); - LASSERTF(err == 0, "error destroying new cache: rc %d\n", err); - } -out: - return rc; -} - -static void __exit fsfilt_ext3_exit(void) -{ - int rc; - - fsfilt_unregister_ops(&fsfilt_ext3_ops); - rc = kmem_cache_destroy(fcb_cache); - LASSERTF(rc == 0, "couldn't destroy fcb_cache slab\n"); -} - -module_init(fsfilt_ext3_init); -module_exit(fsfilt_ext3_exit); - -MODULE_AUTHOR("Sun Microsystems, Inc. "); -MODULE_DESCRIPTION("Lustre ext3 Filesystem Helper v0.1"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6f0737c9c817545af6774a23722a6bc99b9dbb44 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:39 +0800 Subject: staging/lustre/o2iblnd: remove kib_sysctl we have #define CFS_SYSFS_MODULE_PARM 1 so it is indeed dead code. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 1 - .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h | 3 - .../lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c | 262 --------------------- 3 files changed, 266 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 86397f96b033..644a0000130a 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -3230,7 +3230,6 @@ void __exit kiblnd_module_fini (void) { lnet_unregister_lnd(&the_o2iblnd); - kiblnd_tunables_fini(); } int __init diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 938df0cf8c64..3f83ce4871cf 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -106,9 +106,6 @@ typedef struct int *kib_fmr_pool_size; /* # FMRs in pool */ int *kib_fmr_flush_trigger; /* When to trigger FMR flush */ int *kib_fmr_cache; /* enable FMR pool cache? */ -#if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM - ctl_table_header_t *kib_sysctl; /* sysctl interface */ -#endif int *kib_require_priv_port;/* accept only privileged ports */ int *kib_use_priv_port; /* use privileged port for active connect */ /* # threads on each CPT */ diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c index 92dc5672e2dd..cc291d00dba0 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c @@ -176,261 +176,6 @@ kib_tunables_t kiblnd_tunables = { .kib_nscheds = &nscheds }; -#if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM - -static char ipif_basename_space[32]; - - -enum { - O2IBLND_SERVICE = 1, - O2IBLND_CKSUM, - O2IBLND_TIMEOUT, - O2IBLND_NTX, - O2IBLND_CREDITS, - O2IBLND_PEER_TXCREDITS, - O2IBLND_PEER_CREDITS_HIW, - O2IBLND_PEER_RTRCREDITS, - O2IBLND_PEER_TIMEOUT, - O2IBLND_IPIF_BASENAME, - O2IBLND_RETRY_COUNT, - O2IBLND_RNR_RETRY_COUNT, - O2IBLND_KEEPALIVE, - O2IBLND_CONCURRENT_SENDS, - O2IBLND_IB_MTU, - O2IBLND_MAP_ON_DEMAND, - O2IBLND_FMR_POOL_SIZE, - O2IBLND_FMR_FLUSH_TRIGGER, - O2IBLND_FMR_CACHE, - O2IBLND_PMR_POOL_SIZE, - O2IBLND_DEV_FAILOVER -}; - -static ctl_table_t kiblnd_ctl_table[] = { - { - .ctl_name = O2IBLND_SERVICE, - .procname = "service", - .data = &service, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_CKSUM, - .procname = "cksum", - .data = &cksum, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_TIMEOUT, - .procname = "timeout", - .data = &timeout, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_NTX, - .procname = "ntx", - .data = &ntx, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_CREDITS, - .procname = "credits", - .data = &credits, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_PEER_TXCREDITS, - .procname = "peer_credits", - .data = &peer_credits, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_PEER_CREDITS_HIW, - .procname = "peer_credits_hiw", - .data = &peer_credits_hiw, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_PEER_RTRCREDITS, - .procname = "peer_buffer_credits", - .data = &peer_buffer_credits, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_PEER_TIMEOUT, - .procname = "peer_timeout", - .data = &peer_timeout, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_IPIF_BASENAME, - .procname = "ipif_name", - .data = ipif_basename_space, - .maxlen = sizeof(ipif_basename_space), - .mode = 0444, - .proc_handler = &proc_dostring - }, - { - .ctl_name = O2IBLND_RETRY_COUNT, - .procname = "retry_count", - .data = &retry_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_RNR_RETRY_COUNT, - .procname = "rnr_retry_count", - .data = &rnr_retry_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_KEEPALIVE, - .procname = "keepalive", - .data = &keepalive, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_CONCURRENT_SENDS, - .procname = "concurrent_sends", - .data = &concurrent_sends, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_IB_MTU, - .procname = "ib_mtu", - .data = &ib_mtu, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_MAP_ON_DEMAND, - .procname = "map_on_demand", - .data = &map_on_demand, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - - { - .ctl_name = O2IBLND_FMR_POOL_SIZE, - .procname = "fmr_pool_size", - .data = &fmr_pool_size, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_FMR_FLUSH_TRIGGER, - .procname = "fmr_flush_trigger", - .data = &fmr_flush_trigger, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_FMR_CACHE, - .procname = "fmr_cache", - .data = &fmr_cache, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_PMR_POOL_SIZE, - .procname = "pmr_pool_size", - .data = &pmr_pool_size, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = O2IBLND_DEV_FAILOVER, - .procname = "dev_failover", - .data = &dev_failover, - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec - }, - {0} -}; - -static ctl_table_t kiblnd_top_ctl_table[] = { - { - .ctl_name = CTL_O2IBLND, - .procname = "o2iblnd", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = kiblnd_ctl_table - }, - {0} -}; - -void -kiblnd_initstrtunable(char *space, char *str, int size) -{ - strncpy(space, str, size); - space[size-1] = 0; -} - -void -kiblnd_sysctl_init (void) -{ - kiblnd_initstrtunable(ipif_basename_space, ipif_name, - sizeof(ipif_basename_space)); - - kiblnd_tunables.kib_sysctl = - register_sysctl_table(kiblnd_top_ctl_table); - - if (kiblnd_tunables.kib_sysctl == NULL) - CWARN("Can't setup /proc tunables\n"); -} - -void -kiblnd_sysctl_fini (void) -{ - if (kiblnd_tunables.kib_sysctl != NULL) - unregister_sysctl_table(kiblnd_tunables.kib_sysctl); -} - -#else - -void -kiblnd_sysctl_init (void) -{ -} - -void -kiblnd_sysctl_fini (void) -{ -} - -#endif - int kiblnd_tunables_init (void) { @@ -482,12 +227,5 @@ kiblnd_tunables_init (void) *kiblnd_tunables.kib_concurrent_sends, *kiblnd_tunables.kib_peertxcredits); } - kiblnd_sysctl_init(); return 0; } - -void -kiblnd_tunables_fini (void) -{ - kiblnd_sysctl_fini(); -} -- cgit v1.2.3 From a05a2e4d19ec3be7a8a70e831b5f5c8dcea2efe4 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:40 +0800 Subject: staging/lustre/socklnd: remove ksnd_sysctl It is dead code because we defined CFS_SYSFS_MODULE_PARM. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/klnds/socklnd/socklnd.c | 1 - .../staging/lustre/lnet/klnds/socklnd/socklnd.h | 6 - .../lustre/lnet/klnds/socklnd/socklnd_lib-linux.c | 307 --------------------- .../lustre/lnet/klnds/socklnd/socklnd_modparams.c | 12 +- 4 files changed, 1 insertion(+), 325 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 2ddc3aadb8d6..8f74d0be32f1 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -2866,7 +2866,6 @@ void __exit ksocknal_module_fini (void) { lnet_unregister_lnd(&the_ksocklnd); - ksocknal_tunables_fini(); } int __init diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index b483e0c3a69a..df2be7a7f46e 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -124,9 +124,6 @@ typedef struct unsigned int *ksnd_zc_min_payload; /* minimum zero copy payload size */ int *ksnd_zc_recv; /* enable ZC receive (for Chelsio TOE) */ int *ksnd_zc_recv_min_nfrags; /* minimum # of fragments to enable ZC receive */ -#if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM - ctl_table_header_t *ksnd_sysctl; /* sysctl interface */ -#endif } ksock_tunables_t; typedef struct @@ -592,9 +589,6 @@ extern int ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle); extern int ksocknal_tunables_init(void); -extern void ksocknal_tunables_fini(void); -extern int ksocknal_lib_tunables_init(void); -extern void ksocknal_lib_tunables_fini(void); extern void ksocknal_lib_csum_tx(ksock_tx_t *tx); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c index a1c6a519bf5b..80141aa32c21 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c @@ -36,313 +36,6 @@ #include "socklnd.h" -# if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM - - -enum { - SOCKLND_TIMEOUT = 1, - SOCKLND_CREDITS, - SOCKLND_PEER_TXCREDITS, - SOCKLND_PEER_RTRCREDITS, - SOCKLND_PEER_TIMEOUT, - SOCKLND_NCONNDS, - SOCKLND_RECONNECTS_MIN, - SOCKLND_RECONNECTS_MAX, - SOCKLND_EAGER_ACK, - SOCKLND_ZERO_COPY, - SOCKLND_TYPED, - SOCKLND_BULK_MIN, - SOCKLND_RX_BUFFER_SIZE, - SOCKLND_TX_BUFFER_SIZE, - SOCKLND_NAGLE, - SOCKLND_IRQ_AFFINITY, - SOCKLND_ROUND_ROBIN, - SOCKLND_KEEPALIVE, - SOCKLND_KEEPALIVE_IDLE, - SOCKLND_KEEPALIVE_COUNT, - SOCKLND_KEEPALIVE_INTVL, - SOCKLND_BACKOFF_INIT, - SOCKLND_BACKOFF_MAX, - SOCKLND_PROTOCOL, - SOCKLND_ZERO_COPY_RECV, - SOCKLND_ZERO_COPY_RECV_MIN_NFRAGS -}; - -static ctl_table_t ksocknal_ctl_table[] = { - { - .ctl_name = SOCKLND_TIMEOUT, - .procname = "timeout", - .data = &ksocknal_tunables.ksnd_timeout, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_CREDITS, - .procname = "credits", - .data = &ksocknal_tunables.ksnd_credits, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_PEER_TXCREDITS, - .procname = "peer_credits", - .data = &ksocknal_tunables.ksnd_peertxcredits, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_PEER_RTRCREDITS, - .procname = "peer_buffer_credits", - .data = &ksocknal_tunables.ksnd_peerrtrcredits, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_PEER_TIMEOUT, - .procname = "peer_timeout", - .data = &ksocknal_tunables.ksnd_peertimeout, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_NCONNDS, - .procname = "nconnds", - .data = &ksocknal_tunables.ksnd_nconnds, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_RECONNECTS_MIN, - .procname = "min_reconnectms", - .data = &ksocknal_tunables.ksnd_min_reconnectms, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_RECONNECTS_MAX, - .procname = "max_reconnectms", - .data = &ksocknal_tunables.ksnd_max_reconnectms, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_EAGER_ACK, - .procname = "eager_ack", - .data = &ksocknal_tunables.ksnd_eager_ack, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_ZERO_COPY, - .procname = "zero_copy", - .data = &ksocknal_tunables.ksnd_zc_min_payload, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_ZERO_COPY_RECV, - .procname = "zero_copy_recv", - .data = &ksocknal_tunables.ksnd_zc_recv, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - - { - .ctl_name = SOCKLND_ZERO_COPY_RECV_MIN_NFRAGS, - .procname = "zero_copy_recv", - .data = &ksocknal_tunables.ksnd_zc_recv_min_nfrags, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_TYPED, - .procname = "typed", - .data = &ksocknal_tunables.ksnd_typed_conns, - .maxlen = sizeof (int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_BULK_MIN, - .procname = "min_bulk", - .data = &ksocknal_tunables.ksnd_min_bulk, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_RX_BUFFER_SIZE, - .procname = "rx_buffer_size", - .data = &ksocknal_tunables.ksnd_rx_buffer_size, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_TX_BUFFER_SIZE, - .procname = "tx_buffer_size", - .data = &ksocknal_tunables.ksnd_tx_buffer_size, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_NAGLE, - .procname = "nagle", - .data = &ksocknal_tunables.ksnd_nagle, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_ROUND_ROBIN, - .procname = "round_robin", - .data = &ksocknal_tunables.ksnd_round_robin, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_KEEPALIVE, - .procname = "keepalive", - .data = &ksocknal_tunables.ksnd_keepalive, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_KEEPALIVE_IDLE, - .procname = "keepalive_idle", - .data = &ksocknal_tunables.ksnd_keepalive_idle, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_KEEPALIVE_COUNT, - .procname = "keepalive_count", - .data = &ksocknal_tunables.ksnd_keepalive_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, - { - .ctl_name = SOCKLND_KEEPALIVE_INTVL, - .procname = "keepalive_intvl", - .data = &ksocknal_tunables.ksnd_keepalive_intvl, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, -#if SOCKNAL_VERSION_DEBUG - { - .ctl_name = SOCKLND_PROTOCOL, - .procname = "protocol", - .data = &ksocknal_tunables.ksnd_protocol, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - }, -#endif - {0} -}; - - -ctl_table_t ksocknal_top_ctl_table[] = { - { - .ctl_name = CTL_SOCKLND, - .procname = "socknal", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = ksocknal_ctl_table - }, - { 0 } -}; - -int -ksocknal_lib_tunables_init () -{ - if (!*ksocknal_tunables.ksnd_typed_conns) { - int rc = -EINVAL; -#if SOCKNAL_VERSION_DEBUG - if (*ksocknal_tunables.ksnd_protocol < 3) - rc = 0; -#endif - if (rc != 0) { - CERROR("Protocol V3.x MUST have typed connections\n"); - return rc; - } - } - - if (*ksocknal_tunables.ksnd_zc_recv_min_nfrags < 2) - *ksocknal_tunables.ksnd_zc_recv_min_nfrags = 2; - if (*ksocknal_tunables.ksnd_zc_recv_min_nfrags > LNET_MAX_IOV) - *ksocknal_tunables.ksnd_zc_recv_min_nfrags = LNET_MAX_IOV; - - ksocknal_tunables.ksnd_sysctl = - register_sysctl_table(ksocknal_top_ctl_table); - - if (ksocknal_tunables.ksnd_sysctl == NULL) - CWARN("Can't setup /proc tunables\n"); - - return 0; -} - -void -ksocknal_lib_tunables_fini(void) -{ - if (ksocknal_tunables.ksnd_sysctl != NULL) - unregister_sysctl_table(ksocknal_tunables.ksnd_sysctl); -} -#else -int -ksocknal_lib_tunables_init(void) -{ - return 0; -} - -void -ksocknal_lib_tunables_fini(void) -{ -} -#endif /* # if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM */ - int ksocknal_lib_get_conn_addrs (ksock_conn_t *conn) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c index 8a474f64abbe..9f4c64e51b0b 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c @@ -181,18 +181,8 @@ int ksocknal_tunables_init(void) ksocknal_tunables.ksnd_protocol = &protocol; #endif -#if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM - ksocknal_tunables.ksnd_sysctl = NULL; -#endif - if (*ksocknal_tunables.ksnd_zc_min_payload < (2 << 10)) *ksocknal_tunables.ksnd_zc_min_payload = (2 << 10); - /* initialize platform-sepcific tunables */ - return ksocknal_lib_tunables_init(); + return 0; }; - -void ksocknal_tunables_fini(void) -{ - ksocknal_lib_tunables_fini(); -} -- cgit v1.2.3 From 81ddefb0040f9bf4722d99b4a1938c771e036530 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:41 +0800 Subject: staging/lustre: remove CFS_SYSFS_MODULE_PARM No more references to it. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 9b30b4d92cc9..d4c671651dea 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -77,8 +77,6 @@ module_param(name, type, perm);\ MODULE_PARM_DESC(name, desc) -#define CFS_SYSFS_MODULE_PARM 1 /* module parameters accessible via sysfs */ - /******************************************************************************/ /* Light-weight trace * Support for temporary event tracing with minimal Heisenberg effect. */ -- cgit v1.2.3 From 6be96847b3233ed7f659ca3c1cf70f5ac4cc0a6b Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:42 +0800 Subject: staging/lustre/libcfs: remove IOCTL_LIBCFS_TYPE Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_ioctl.h | 66 +++++++++++----------- .../lustre/include/linux/libcfs/linux/kp30.h | 2 - 2 files changed, 33 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 5be367973508..315743ec92e3 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -110,41 +110,41 @@ struct libcfs_ioctl_handler { #define IOC_LIBCFS_TYPE 'e' #define IOC_LIBCFS_MIN_NR 30 /* libcfs ioctls */ -#define IOC_LIBCFS_PANIC _IOWR('e', 30, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_LWT_CONTROL _IOWR('e', 33, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_LWT_SNAPSHOT _IOWR('e', 34, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_LWT_LOOKUP_STRING _IOWR('e', 35, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_MEMHOG _IOWR('e', 36, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_PING_TEST _IOWR('e', 37, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_PANIC _IOWR('e', 30, long) +#define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, long) +#define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, long) +#define IOC_LIBCFS_LWT_CONTROL _IOWR('e', 33, long) +#define IOC_LIBCFS_LWT_SNAPSHOT _IOWR('e', 34, long) +#define IOC_LIBCFS_LWT_LOOKUP_STRING _IOWR('e', 35, long) +#define IOC_LIBCFS_MEMHOG _IOWR('e', 36, long) +#define IOC_LIBCFS_PING_TEST _IOWR('e', 37, long) /* lnet ioctls */ -#define IOC_LIBCFS_GET_NI _IOWR('e', 50, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_FAIL_NID _IOWR('e', 51, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_ADD_ROUTE _IOWR('e', 52, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_DEL_ROUTE _IOWR('e', 53, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_GET_ROUTE _IOWR('e', 54, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_NOTIFY_ROUTER _IOWR('e', 55, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_UNCONFIGURE _IOWR('e', 56, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_LNET_DIST _IOWR('e', 58, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_PING _IOWR('e', 61, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_LNETST _IOWR('e', 63, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_GET_NI _IOWR('e', 50, long) +#define IOC_LIBCFS_FAIL_NID _IOWR('e', 51, long) +#define IOC_LIBCFS_ADD_ROUTE _IOWR('e', 52, long) +#define IOC_LIBCFS_DEL_ROUTE _IOWR('e', 53, long) +#define IOC_LIBCFS_GET_ROUTE _IOWR('e', 54, long) +#define IOC_LIBCFS_NOTIFY_ROUTER _IOWR('e', 55, long) +#define IOC_LIBCFS_UNCONFIGURE _IOWR('e', 56, long) +#define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, long) +#define IOC_LIBCFS_LNET_DIST _IOWR('e', 58, long) +#define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, long) +#define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, long) +#define IOC_LIBCFS_PING _IOWR('e', 61, long) +#define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, long) +#define IOC_LIBCFS_LNETST _IOWR('e', 63, long) /* lnd ioctls */ -#define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_CLOSE_CONNECTION _IOWR('e', 71, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_PUSH_CONNECTION _IOWR('e', 72, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_GET_CONN _IOWR('e', 73, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_DEL_PEER _IOWR('e', 74, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_ADD_PEER _IOWR('e', 75, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_GET_PEER _IOWR('e', 76, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_GET_TXDESC _IOWR('e', 77, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_ADD_INTERFACE _IOWR('e', 78, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_DEL_INTERFACE _IOWR('e', 79, IOCTL_LIBCFS_TYPE) -#define IOC_LIBCFS_GET_INTERFACE _IOWR('e', 80, IOCTL_LIBCFS_TYPE) +#define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, long) +#define IOC_LIBCFS_CLOSE_CONNECTION _IOWR('e', 71, long) +#define IOC_LIBCFS_PUSH_CONNECTION _IOWR('e', 72, long) +#define IOC_LIBCFS_GET_CONN _IOWR('e', 73, long) +#define IOC_LIBCFS_DEL_PEER _IOWR('e', 74, long) +#define IOC_LIBCFS_ADD_PEER _IOWR('e', 75, long) +#define IOC_LIBCFS_GET_PEER _IOWR('e', 76, long) +#define IOC_LIBCFS_GET_TXDESC _IOWR('e', 77, long) +#define IOC_LIBCFS_ADD_INTERFACE _IOWR('e', 78, long) +#define IOC_LIBCFS_DEL_INTERFACE _IOWR('e', 79, long) +#define IOC_LIBCFS_GET_INTERFACE _IOWR('e', 80, long) #define IOC_LIBCFS_MAX_NR 80 diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index d4c671651dea..69eefd5179bd 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -175,8 +175,6 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, /* ------------------------------------------------------------------ */ -#define IOCTL_LIBCFS_TYPE long - #ifdef __CYGWIN__ # ifndef BITS_PER_LONG # define BITS_PER_LONG 64 -- cgit v1.2.3 From 414b1419c5ef5962ba82d3b29bbe722568a82556 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:43 +0800 Subject: staging/lustre: remove __CYGWIN__ Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 6 ------ drivers/staging/lustre/include/linux/lnet/types.h | 11 ----------- drivers/staging/lustre/lustre/osc/osc_request.c | 4 ---- 3 files changed, 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 69eefd5179bd..fedf086e7ccf 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -175,12 +175,6 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, /* ------------------------------------------------------------------ */ -#ifdef __CYGWIN__ -# ifndef BITS_PER_LONG -# define BITS_PER_LONG 64 -# endif -#endif - # define LI_POISON 0x5a5a5a5a #if BITS_PER_LONG > 32 # define LL_POISON 0x5a5a5a5a5a5a5a5aL diff --git a/drivers/staging/lustre/include/linux/lnet/types.h b/drivers/staging/lustre/include/linux/lnet/types.h index 4f63b7acb9d7..c833ce8544d3 100644 --- a/drivers/staging/lustre/include/linux/lnet/types.h +++ b/drivers/staging/lustre/include/linux/lnet/types.h @@ -383,14 +383,6 @@ typedef enum { typedef unsigned LNET_SEQ_BASETYPE lnet_seq_t; #define LNET_SEQ_GT(a,b) (((signed LNET_SEQ_BASETYPE)((a) - (b))) > 0) -/* XXX - * cygwin need the pragma line, not clear if it's needed in other places. - * checking!!! - */ -#ifdef __CYGWIN__ -#pragma pack(push, 4) -#endif - /** * Information about an event on a MD. */ @@ -462,9 +454,6 @@ typedef struct { */ volatile lnet_seq_t sequence; } lnet_event_t; -#ifdef __CYGWIN__ -#pragma pop -#endif /** * Event queue handler function type. diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index cb197782d9a3..c837a0d71e0f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -46,10 +46,6 @@ #include #include -#ifdef __CYGWIN__ -# include -#endif - #include #include #include -- cgit v1.2.3 From bace1077ff38c5258c3c10f26e7e08db2abd32ed Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:44 +0800 Subject: staging/lustre: remove _LWORDSIZE Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index fedf086e7ccf..44f490ca782e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -185,8 +185,6 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, /* this is a bit chunky */ -#define _LWORDSIZE BITS_PER_LONG - # define LPU64 "%llu" # define LPD64 "%lld" # define LPX64 "%#llx" @@ -206,9 +204,6 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, */ # define LPPID "%d" - -#undef _LWORDSIZE - /* compat macroses */ -- cgit v1.2.3 From 9f773620f1c14e4b0e8e2e17792d559f2e39fb44 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:45 +0800 Subject: staging/lustre: get_cpu is always defined Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 44f490ca782e..e6f03c7ae006 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -206,18 +206,6 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, /* compat macroses */ - -#ifndef get_cpu -# ifdef CONFIG_PREEMPT -# define get_cpu() ({ preempt_disable(); smp_processor_id(); }) -# define put_cpu() preempt_enable() -# else -# define get_cpu() smp_processor_id() -# define put_cpu() -# endif -#else -#endif /* get_cpu & put_cpu */ - #define INIT_CTL_NAME(a) #define INIT_STRATEGY(a) -- cgit v1.2.3 From 7fb3d1c5276b1e31f5cc736730231cf72d2d5a05 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:46 +0800 Subject: staging/lustre: remove INIT_CTL_NAME legacy code used to support kernel where struct ctl_table has ctl_name member. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/linux/kp30.h | 1 - drivers/staging/lustre/lnet/lnet/router_proc.c | 10 --------- .../lustre/lustre/libcfs/linux/linux-proc.c | 25 +--------------------- .../lustre/lustre/obdclass/linux/linux-sysctl.c | 23 ++------------------ 4 files changed, 3 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index e6f03c7ae006..ba7854159d7d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -206,7 +206,6 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, /* compat macroses */ -#define INIT_CTL_NAME(a) #define INIT_STRATEGY(a) #endif diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 5e47de36c184..daaa043ad118 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -855,55 +855,46 @@ static ctl_table_t lnet_table[] = { * to go via /proc for portability. */ { - INIT_CTL_NAME(PSDEV_LNET_STATS) .procname = "stats", .mode = 0644, .proc_handler = &proc_lnet_stats, }, { - INIT_CTL_NAME(PSDEV_LNET_ROUTES) .procname = "routes", .mode = 0444, .proc_handler = &proc_lnet_routes, }, { - INIT_CTL_NAME(PSDEV_LNET_ROUTERS) .procname = "routers", .mode = 0444, .proc_handler = &proc_lnet_routers, }, { - INIT_CTL_NAME(PSDEV_LNET_PEERS) .procname = "peers", .mode = 0444, .proc_handler = &proc_lnet_peers, }, { - INIT_CTL_NAME(PSDEV_LNET_PEERS) .procname = "buffers", .mode = 0444, .proc_handler = &proc_lnet_buffers, }, { - INIT_CTL_NAME(PSDEV_LNET_NIS) .procname = "nis", .mode = 0444, .proc_handler = &proc_lnet_nis, }, { - INIT_CTL_NAME(PSDEV_LNET_PTL_ROTOR) .procname = "portal_rotor", .mode = 0644, .proc_handler = &proc_lnet_portal_rotor, }, { - INIT_CTL_NAME(0) } }; static ctl_table_t top_table[] = { { - INIT_CTL_NAME(CTL_LNET) .procname = "lnet", .mode = 0555, .data = NULL, @@ -911,7 +902,6 @@ static ctl_table_t top_table[] = { .child = lnet_table, }, { - INIT_CTL_NAME(0) } }; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c index fc6c97749487..f2bb8672a4ff 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c @@ -371,7 +371,6 @@ static ctl_table_t lnet_table[] = { * to go via /proc for portability. */ { - INIT_CTL_NAME(PSDEV_DEBUG) .procname = "debug", .data = &libcfs_debug, .maxlen = sizeof(int), @@ -379,7 +378,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dobitmasks, }, { - INIT_CTL_NAME(PSDEV_SUBSYSTEM_DEBUG) .procname = "subsystem_debug", .data = &libcfs_subsystem_debug, .maxlen = sizeof(int), @@ -387,7 +385,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dobitmasks, }, { - INIT_CTL_NAME(PSDEV_PRINTK) .procname = "printk", .data = &libcfs_printk, .maxlen = sizeof(int), @@ -395,7 +392,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dobitmasks, }, { - INIT_CTL_NAME(PSDEV_CONSOLE_RATELIMIT) .procname = "console_ratelimit", .data = &libcfs_console_ratelimit, .maxlen = sizeof(int), @@ -403,21 +399,18 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dointvec }, { - INIT_CTL_NAME(PSDEV_CONSOLE_MAX_DELAY_CS) .procname = "console_max_delay_centisecs", .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_console_max_delay_cs }, { - INIT_CTL_NAME(PSDEV_CONSOLE_MIN_DELAY_CS) .procname = "console_min_delay_centisecs", .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_console_min_delay_cs }, { - INIT_CTL_NAME(PSDEV_CONSOLE_BACKOFF) .procname = "console_backoff", .maxlen = sizeof(int), .mode = 0644, @@ -425,7 +418,6 @@ static ctl_table_t lnet_table[] = { }, { - INIT_CTL_NAME(PSDEV_DEBUG_PATH) .procname = "debug_path", .data = libcfs_debug_file_path_arr, .maxlen = sizeof(libcfs_debug_file_path_arr), @@ -434,7 +426,6 @@ static ctl_table_t lnet_table[] = { }, { - INIT_CTL_NAME(PSDEV_CPT_TABLE) .procname = "cpu_partition_table", .maxlen = 128, .mode = 0444, @@ -442,7 +433,6 @@ static ctl_table_t lnet_table[] = { }, { - INIT_CTL_NAME(PSDEV_LNET_UPCALL) .procname = "upcall", .data = lnet_upcall, .maxlen = sizeof(lnet_upcall), @@ -450,7 +440,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dostring, }, { - INIT_CTL_NAME(PSDEV_LNET_DEBUG_LOG_UPCALL) .procname = "debug_log_upcall", .data = lnet_debug_log_upcall, .maxlen = sizeof(lnet_debug_log_upcall), @@ -458,7 +447,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dostring, }, { - INIT_CTL_NAME(PSDEV_LNET_MEMUSED) .procname = "lnet_memused", .data = (int *)&libcfs_kmemory.counter, .maxlen = sizeof(int), @@ -467,7 +455,6 @@ static ctl_table_t lnet_table[] = { INIT_STRATEGY(&sysctl_intvec) }, { - INIT_CTL_NAME(PSDEV_LNET_CATASTROPHE) .procname = "catastrophe", .data = &libcfs_catastrophe, .maxlen = sizeof(int), @@ -476,7 +463,6 @@ static ctl_table_t lnet_table[] = { INIT_STRATEGY(&sysctl_intvec) }, { - INIT_CTL_NAME(PSDEV_LNET_PANIC_ON_LBUG) .procname = "panic_on_lbug", .data = &libcfs_panic_on_lbug, .maxlen = sizeof(int), @@ -485,27 +471,23 @@ static ctl_table_t lnet_table[] = { INIT_STRATEGY(&sysctl_intvec) }, { - INIT_CTL_NAME(PSDEV_LNET_DUMP_KERNEL) .procname = "dump_kernel", .maxlen = 256, .mode = 0200, .proc_handler = &proc_dump_kernel, }, { - INIT_CTL_NAME(PSDEV_LNET_DAEMON_FILE) .procname = "daemon_file", .mode = 0644, .maxlen = 256, .proc_handler = &proc_daemon_file, }, { - INIT_CTL_NAME(PSDEV_LNET_DEBUG_MB) .procname = "debug_mb", .mode = 0644, .proc_handler = &proc_debug_mb, }, { - INIT_CTL_NAME(PSDEV_LNET_WATCHDOG_RATELIMIT) .procname = "watchdog_ratelimit", .data = &libcfs_watchdog_ratelimit, .maxlen = sizeof(int), @@ -514,7 +496,7 @@ static ctl_table_t lnet_table[] = { .extra1 = &min_watchdog_ratelimit, .extra2 = &max_watchdog_ratelimit, }, - { INIT_CTL_NAME(PSDEV_LNET_FORCE_LBUG) + { .procname = "force_lbug", .data = NULL, .maxlen = 0, @@ -522,7 +504,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &libcfs_force_lbug }, { - INIT_CTL_NAME(PSDEV_LNET_FAIL_LOC) .procname = "fail_loc", .data = &cfs_fail_loc, .maxlen = sizeof(cfs_fail_loc), @@ -530,7 +511,6 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_fail_loc }, { - INIT_CTL_NAME(PSDEV_LNET_FAIL_VAL) .procname = "fail_val", .data = &cfs_fail_val, .maxlen = sizeof(int), @@ -538,14 +518,12 @@ static ctl_table_t lnet_table[] = { .proc_handler = &proc_dointvec }, { - INIT_CTL_NAME(0) } }; #ifdef CONFIG_SYSCTL static ctl_table_t top_table[] = { { - INIT_CTL_NAME(CTL_LNET) .procname = "lnet", .mode = 0555, .data = NULL, @@ -553,7 +531,6 @@ static ctl_table_t top_table[] = { .child = lnet_table, }, { - INIT_CTL_NAME(0) } }; #endif diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index acd2619227df..d66be020983d 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -282,7 +282,6 @@ int LL_PROC_PROTO(proc_at_history) #ifdef CONFIG_SYSCTL static ctl_table_t obd_table[] = { { - INIT_CTL_NAME(OBD_TIMEOUT) .procname = "timeout", .data = &obd_timeout, .maxlen = sizeof(int), @@ -290,7 +289,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_set_timeout }, { - INIT_CTL_NAME(OBD_DEBUG_PEER_ON_TIMEOUT) .procname = "debug_peer_on_timeout", .data = &obd_debug_peer_on_timeout, .maxlen = sizeof(int), @@ -298,7 +296,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_dointvec }, { - INIT_CTL_NAME(OBD_DUMP_ON_TIMEOUT) .procname = "dump_on_timeout", .data = &obd_dump_on_timeout, .maxlen = sizeof(int), @@ -306,7 +303,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_dointvec }, { - INIT_CTL_NAME(OBD_DUMP_ON_EVICTION) .procname = "dump_on_eviction", .data = &obd_dump_on_eviction, .maxlen = sizeof(int), @@ -314,7 +310,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_dointvec }, { - INIT_CTL_NAME(OBD_MEMUSED) .procname = "memused", .data = NULL, .maxlen = 0, @@ -322,7 +317,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_memory_alloc }, { - INIT_CTL_NAME(OBD_PAGESUSED) .procname = "pagesused", .data = NULL, .maxlen = 0, @@ -330,7 +324,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_pages_alloc }, { - INIT_CTL_NAME(OBD_MAXMEMUSED) .procname = "memused_max", .data = NULL, .maxlen = 0, @@ -338,7 +331,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_mem_max }, { - INIT_CTL_NAME(OBD_MAXPAGESUSED) .procname = "pagesused_max", .data = NULL, .maxlen = 0, @@ -346,7 +338,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_pages_max }, { - INIT_CTL_NAME(OBD_LDLM_TIMEOUT) .procname = "ldlm_timeout", .data = &ldlm_timeout, .maxlen = sizeof(int), @@ -354,7 +345,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_set_timeout }, { - INIT_CTL_NAME(OBD_ALLOC_FAIL_RATE) .procname = "alloc_fail_rate", .data = &obd_alloc_fail_rate, .maxlen = sizeof(int), @@ -362,7 +352,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_alloc_fail_rate }, { - INIT_CTL_NAME(OBD_MAX_DIRTY_PAGES) .procname = "max_dirty_mb", .data = &obd_max_dirty_pages, .maxlen = sizeof(int), @@ -370,7 +359,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_max_dirty_pages_in_mb }, { - INIT_CTL_NAME(OBD_AT_MIN) .procname = "at_min", .data = &at_min, .maxlen = sizeof(int), @@ -378,7 +366,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_at_min }, { - INIT_CTL_NAME(OBD_AT_MAX) .procname = "at_max", .data = &at_max, .maxlen = sizeof(int), @@ -386,7 +373,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_at_max }, { - INIT_CTL_NAME(OBD_AT_EXTRA) .procname = "at_extra", .data = &at_extra, .maxlen = sizeof(int), @@ -394,7 +380,6 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_at_extra }, { - INIT_CTL_NAME(OBD_AT_EARLY_MARGIN) .procname = "at_early_margin", .data = &at_early_margin, .maxlen = sizeof(int), @@ -402,26 +387,22 @@ static ctl_table_t obd_table[] = { .proc_handler = &proc_at_early_margin }, { - INIT_CTL_NAME(OBD_AT_HISTORY) .procname = "at_history", .data = &at_history, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_at_history - }, - { INIT_CTL_NAME(0) } + } }; static ctl_table_t parent_table[] = { { - INIT_CTL_NAME(OBD_SYSCTL) .procname = "lustre", .data = NULL, .maxlen = 0, .mode = 0555, .child = obd_table - }, - { INIT_CTL_NAME(0) } + } }; #endif -- cgit v1.2.3 From 843cff5abd3d6668f5d4862e05eabc8c07bbe3f9 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 19 Nov 2013 22:38:47 +0800 Subject: staging/lustre: remove INIT_STRATEGY legacy code used to support kernel where struct ctl_table has strategy member. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 4 ---- drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c | 3 --- 2 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index ba7854159d7d..3a883f82e64f 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -204,8 +204,4 @@ extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, */ # define LPPID "%d" -/* compat macroses */ - -#define INIT_STRATEGY(a) - #endif diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c index f2bb8672a4ff..ef0ab106496f 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c @@ -452,7 +452,6 @@ static ctl_table_t lnet_table[] = { .maxlen = sizeof(int), .mode = 0444, .proc_handler = &proc_dointvec, - INIT_STRATEGY(&sysctl_intvec) }, { .procname = "catastrophe", @@ -460,7 +459,6 @@ static ctl_table_t lnet_table[] = { .maxlen = sizeof(int), .mode = 0444, .proc_handler = &proc_dointvec, - INIT_STRATEGY(&sysctl_intvec) }, { .procname = "panic_on_lbug", @@ -468,7 +466,6 @@ static ctl_table_t lnet_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, - INIT_STRATEGY(&sysctl_intvec) }, { .procname = "dump_kernel", -- cgit v1.2.3 From 433dc9b3d123e72a0f5988c1f0d1c9319a735276 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 14 Nov 2013 01:26:21 +0000 Subject: sfc: Implement the SIOCGHWTSTAMP ioctl Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 4 +++- drivers/net/ethernet/sfc/nic.h | 3 ++- drivers/net/ethernet/sfc/ptp.c | 11 ++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 07c9bc4c61bc..22ca5cd3f722 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1857,7 +1857,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) struct mii_ioctl_data *data = if_mii(ifr); if (cmd == SIOCSHWTSTAMP) - return efx_ptp_ioctl(efx, ifr, cmd); + return efx_ptp_set_ts_config(efx, ifr); + if (cmd == SIOCGHWTSTAMP) + return efx_ptp_get_ts_config(efx, ifr); /* Convert phy_id from older PRTAD/DEVAD format */ if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 11b6112d9249..33852e824f12 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -555,7 +555,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, struct ethtool_ts_info; void efx_ptp_probe(struct efx_nic *efx); -int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd); +int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); +int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 03acf57df045..afd4d3a50460 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1231,7 +1231,7 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); } -int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) +int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr) { struct hwtstamp_config config; int rc; @@ -1251,6 +1251,15 @@ int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) ? -EFAULT : 0; } +int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr) +{ + if (!efx->ptp_data) + return -EOPNOTSUPP; + + return copy_to_user(ifr->ifr_data, &efx->ptp_data->config, + sizeof(efx->ptp_data->config)) ? -EFAULT : 0; +} + static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len) { struct efx_ptp_data *ptp = efx->ptp_data; -- cgit v1.2.3 From 1c126bc6a248ee0ce2f1df09ac99eedc22bc4520 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:19 +0100 Subject: staging: Remove superfluous name casts device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/platform.c | 2 +- drivers/staging/usbip/vhci_hcd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/platform.c b/drivers/staging/dwc2/platform.c index 76ae6e210f55..8f0489efdf40 100644 --- a/drivers/staging/dwc2/platform.c +++ b/drivers/staging/dwc2/platform.c @@ -134,7 +134,7 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table); static struct platform_driver dwc2_platform_driver = { .driver = { - .name = (char *)dwc2_driver_name, + .name = dwc2_driver_name, .of_match_table = dwc2_of_match_table, }, .probe = dwc2_driver_probe, diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index e37c6c1a9931..64cace681cee 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -1107,7 +1107,7 @@ static struct platform_driver vhci_driver = { .suspend = vhci_hcd_suspend, .resume = vhci_hcd_resume, .driver = { - .name = (char *) driver_name, + .name = driver_name, .owner = THIS_MODULE, }, }; -- cgit v1.2.3 From 782872bf7a86d17a1fade8353479151b3b2fcf15 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:20 +0100 Subject: staging: r8188eu: Remove superfluous name cast usb_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 7d14779310d3..b21b1566424b 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -71,7 +71,7 @@ struct rtw_usb_drv { }; static struct rtw_usb_drv rtl8188e_usb_drv = { - .usbdrv.name = (char *)"r8188eu", + .usbdrv.name = "r8188eu", .usbdrv.probe = rtw_drv_init, .usbdrv.disconnect = rtw_dev_remove, .usbdrv.id_table = rtw_usb_id_tbl, -- cgit v1.2.3 From 6fafecb90c9ed2cca8ed450fed693095c0160dc2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:21 +0100 Subject: staging: usbip: Remove superfluous name cast platform_device.name is "const char *" Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 64cace681cee..aa22c631191c 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -1124,7 +1124,7 @@ static void the_pdev_release(struct device *dev) static struct platform_device the_pdev = { /* should be the same name as driver_name */ - .name = (char *) driver_name, + .name = driver_name, .id = -1, .dev = { .release = the_pdev_release, -- cgit v1.2.3 From e8e8f87e24261916e8f11f82c11cbefe1c54df3b Mon Sep 17 00:00:00 2001 From: Eddie Kovsky Date: Mon, 18 Nov 2013 20:57:45 -0700 Subject: staging: Clean up whitespace warnings in staging/winbond Reduced checkpatch.pl warnings from 46 to 17 Long strings on lines over 80 characters remain untouched Signed-off-by: Eddie Kovsky Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/mds.c | 101 +++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c index cac7720bef2b..aef0855f4c68 100644 --- a/drivers/staging/winbond/mds.c +++ b/drivers/staging/winbond/mds.c @@ -56,7 +56,8 @@ static void Mds_DurationSet(struct wbsoft_priv *adapter, RTS_on = true; /* Using RTS */ else { if (pT01->T01_modulation_type) { /* Is using OFDM */ - if (CURRENT_PROTECT_MECHANISM) /* Is using protect */ + /* Is using protect */ + if (CURRENT_PROTECT_MECHANISM) CTS_on = true; /* Using CTS */ } } @@ -69,9 +70,9 @@ static void Mds_DurationSet(struct wbsoft_priv *adapter, * ACK Rate : 24 Mega bps * ACK frame length = 14 bytes */ Duration = 2*DEFAULT_SIFSTIME + - 2*PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION + - ((BodyLen*8 + 22 + Rate*4 - 1)/(Rate*4))*Tsym + - ((112 + 22 + 95)/96)*Tsym; + 2*PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION + + ((BodyLen*8 + 22 + Rate*4 - 1)/(Rate*4))*Tsym + + ((112 + 22 + 95)/96)*Tsym; } else { /* DSSS */ /* CTS duration * 2 SIFS + DATA transmit time + 1 ACK @@ -92,13 +93,15 @@ static void Mds_DurationSet(struct wbsoft_priv *adapter, * CTS Rate : 24 Mega bps * CTS frame length = 14 bytes */ Duration += (DEFAULT_SIFSTIME + - PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION + - ((112 + 22 + 95)/96)*Tsym); + PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION + + ((112 + 22 + 95)/96)*Tsym); } else { /* CTS + 1 SIFS + CTS duration * CTS Rate : ?? Mega bps - * CTS frame length = 14 bytes */ - if (pT01->T01_plcp_header_length) /* long preamble */ + * CTS frame length = 14 bytes + */ + /* long preamble */ + if (pT01->T01_plcp_header_length) Duration += LONG_PREAMBLE_PLUS_PLCPHEADER_TIME; else Duration += SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME; @@ -149,8 +152,8 @@ static void Mds_DurationSet(struct wbsoft_priv *adapter, + Rate-1) / Rate + DEFAULT_SIFSTIME*3); } - - ((u16 *)buffer)[5] = cpu_to_le16(Duration); /* 4 USHOR for skip 8B USB, 2USHORT=FC + Duration */ + /* 4 USHOR for skip 8B USB, 2USHORT=FC + Duration */ + ((u16 *)buffer)[5] = cpu_to_le16(Duration); /* ----20061009 add by anson's endian */ pNextT00->value = cpu_to_le32(pNextT00->value); @@ -159,7 +162,8 @@ static void Mds_DurationSet(struct wbsoft_priv *adapter, buffer += OffsetSize; pT01 = (struct T01_descriptor *)(buffer+4); - if (i != 1) /* The last fragment will not have the next fragment */ + /* The last fragment will not have the next fragment */ + if (i != 1) pNextT00 = (struct T00_descriptor *)(buffer+OffsetSize); } @@ -189,7 +193,8 @@ static void Mds_DurationSet(struct wbsoft_priv *adapter, } } - ((u16 *)buffer)[5] = cpu_to_le16(Duration); /* 4 USHOR for skip 8B USB, 2USHORT=FC + Duration */ + /* 4 USHOR for skip 8B USB, 2USHORT=FC + Duration */ + ((u16 *)buffer)[5] = cpu_to_le16(Duration); pT00->value = cpu_to_le32(pT00->value); pT01->value = cpu_to_le32(pT01->value); /* --end 20061009 add */ @@ -221,9 +226,10 @@ static u16 Mds_BodyCopy(struct wbsoft_priv *adapter, CopySize = SizeLeft; if (SizeLeft > pDes->FragmentThreshold) { CopySize = pDes->FragmentThreshold; - pT00->T00_frame_length = 24 + CopySize; /* Set USB length */ - } else - pT00->T00_frame_length = 24 + SizeLeft; /* Set USB length */ + /* Set USB length */ + pT00->T00_frame_length = 24 + CopySize; + } else /* Set USB length */ + pT00->T00_frame_length = 24 + SizeLeft; SizeLeft -= CopySize; @@ -267,21 +273,27 @@ static u16 Mds_BodyCopy(struct wbsoft_priv *adapter, /* 931130.5.n */ if (pMds->MicAdd) { if (!SizeLeft) { - pMds->MicWriteAddress[pMds->MicWriteIndex] = buffer - pMds->MicAdd; - pMds->MicWriteSize[pMds->MicWriteIndex] = pMds->MicAdd; + pMds->MicWriteAddress[pMds->MicWriteIndex] = + buffer - pMds->MicAdd; + pMds->MicWriteSize[pMds->MicWriteIndex] = + pMds->MicAdd; pMds->MicAdd = 0; } else if (SizeLeft < 8) { /* 931130.5.p */ pMds->MicAdd = SizeLeft; - pMds->MicWriteAddress[pMds->MicWriteIndex] = buffer - (8 - SizeLeft); - pMds->MicWriteSize[pMds->MicWriteIndex] = 8 - SizeLeft; + pMds->MicWriteAddress[pMds->MicWriteIndex] = + buffer - (8 - SizeLeft); + pMds->MicWriteSize[pMds->MicWriteIndex] = + 8 - SizeLeft; pMds->MicWriteIndex++; } } /* Does it need to generate the new header for next mpdu? */ if (SizeLeft) { - buffer = TargetBuffer + Size; /* Get the next 4n start address */ - memcpy(buffer, TargetBuffer, 32); /* Copy 8B USB +24B 802.11 */ + /* Get the next 4n start address */ + buffer = TargetBuffer + Size; + /* Copy 8B USB +24B 802.11 */ + memcpy(buffer, TargetBuffer, 32); pT00 = (struct T00_descriptor *)buffer; pT00->T00_first_mpdu = 0; } @@ -293,7 +305,8 @@ static u16 Mds_BodyCopy(struct wbsoft_priv *adapter, pT00->T00_IsLastMpdu = 1; buffer = (u8 *)pT00 + 8; /* +8 for USB hdr */ buffer[1] &= ~0x04; /* Clear more frag bit of 802.11 frame control */ - pDes->FragmentCount = FragmentCount; /* Update the correct fragment number */ + /* Update the correct fragment number */ + pDes->FragmentCount = FragmentCount; return Size; } @@ -330,7 +343,8 @@ static void Mds_HeaderCopy(struct wbsoft_priv *adapter, FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; /* Do not fragment */ /* Copy full data, the 1'st buffer contain all the data 931130.5.j */ - memcpy(TargetBuffer, src_buffer, DOT_11_MAC_HEADER_SIZE); /* Copy header */ + /* Copy header */ + memcpy(TargetBuffer, src_buffer, DOT_11_MAC_HEADER_SIZE); pDes->buffer_address[0] = src_buffer + DOT_11_MAC_HEADER_SIZE; pDes->buffer_total_size -= DOT_11_MAC_HEADER_SIZE; pDes->buffer_size[0] = pDes->buffer_total_size; @@ -358,8 +372,8 @@ static void Mds_HeaderCopy(struct wbsoft_priv *adapter, for (i = 0; i < 2; i++) { if (i == 1) ctmp1 = ctmpf; - - pMds->TxRate[pDes->Descriptor_ID][i] = ctmp1; /* backup the ta rate and fall back rate */ + /* backup the ta rate and fall back rate */ + pMds->TxRate[pDes->Descriptor_ID][i] = ctmp1; if (ctmp1 == 108) ctmp2 = 7; @@ -395,7 +409,8 @@ static void Mds_HeaderCopy(struct wbsoft_priv *adapter, /* * Set preamble type */ - if ((pT01->T01_modulation_type == 0) && (pT01->T01_transmit_rate == 0)) /* RATE_1M */ + /* RATE_1M */ + if ((pT01->T01_modulation_type == 0) && (pT01->T01_transmit_rate == 0)) pDes->PreambleMode = WLAN_PREAMBLE_TYPE_LONG; else pDes->PreambleMode = CURRENT_PREAMBLE_MODE; @@ -468,12 +483,14 @@ Mds_Tx(struct wbsoft_priv *adapter) /* Start to fill the data */ do { FillIndex = pMds->TxFillIndex; - if (pMds->TxOwner[FillIndex]) { /* Is owned by software 0:Yes 1:No */ + /* Is owned by software 0:Yes 1:No */ + if (pMds->TxOwner[FillIndex]) { pr_debug("[Mds_Tx] Tx Owner is H/W.\n"); break; } - XmitBufAddress = pMds->pTxBuffer + (MAX_USB_TX_BUFFER * FillIndex); /* Get buffer */ + /* Get buffer */ + XmitBufAddress = pMds->pTxBuffer + (MAX_USB_TX_BUFFER * FillIndex); XmitBufSize = 0; FillCount = 0; do { @@ -485,7 +502,8 @@ Mds_Tx(struct wbsoft_priv *adapter) FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD; /* 931130.5.b */ FragmentCount = PacketSize/FragmentThreshold + 1; - stmp = PacketSize + FragmentCount*32 + 8; /* 931130.5.c 8:MIC */ + /* 931130.5.c 8:MIC */ + stmp = PacketSize + FragmentCount*32 + 8; if ((XmitBufSize + stmp) >= MAX_USB_TX_BUFFER) break; /* buffer is not enough */ @@ -499,18 +517,23 @@ Mds_Tx(struct wbsoft_priv *adapter) TxDesIndex = pMds->TxDesIndex; /* Get the current ID */ pTxDes->Descriptor_ID = TxDesIndex; - pMds->TxDesFrom[TxDesIndex] = 2; /* Storing the information of source coming from */ + /* Storing the information of source coming from */ + pMds->TxDesFrom[TxDesIndex] = 2; pMds->TxDesIndex++; pMds->TxDesIndex %= MAX_USB_TX_DESCRIPTOR; MLME_GetNextPacket(adapter, pTxDes); - /* Copy header. 8byte USB + 24byte 802.11Hdr. Set TxRate, Preamble type */ + /* + * Copy header. 8byte USB + 24byte 802.11Hdr. + * Set TxRate, Preamble type + */ Mds_HeaderCopy(adapter, pTxDes, XmitBufAddress); /* For speed up Key setting */ if (pTxDes->EapFix) { - pr_debug("35: EPA 4th frame detected. Size = %d\n", PacketSize); + pr_debug("35: EPA 4th frame detected. Size = %d\n", + PacketSize); pHwData->IsKeyPreSet = 1; } @@ -524,7 +547,9 @@ Mds_Tx(struct wbsoft_priv *adapter) XmitBufSize += CurrentSize; XmitBufAddress += CurrentSize; - /* Get packet to transmit completed, 1:TESTSTA 2:MLME 3: Ndis data */ + /* Get packet to transmit completed, + * 1:TESTSTA 2:MLME 3: Ndis data + */ MLME_SendComplete(adapter, 0, true); /* Software TSC count 20060214 */ @@ -533,7 +558,12 @@ Mds_Tx(struct wbsoft_priv *adapter) pMds->TxTsc_2++; FillCount++; /* 20060928 */ - } while (HAL_USB_MODE_BURST(pHwData)); /* End of multiple MSDU copy loop. false = single true = multiple sending */ + /* + * End of multiple MSDU copy loop. + * false = single + * true = multiple sending + */ + } while (HAL_USB_MODE_BURST(pHwData)); /* Move to the next one, if necessary */ if (BufferFilled) { @@ -594,7 +624,8 @@ Mds_SendComplete(struct wbsoft_priv *adapter, struct T02_descriptor *pT02) pHwData->tx_retry_count[RetryCount] += RetryCount; else pHwData->tx_retry_count[7] += RetryCount; - pr_debug("dto_tx_retry_count =%d\n", pHwData->dto_tx_retry_count); + pr_debug("dto_tx_retry_count =%d\n", + pHwData->dto_tx_retry_count); MTO_SetTxCount(adapter, TxRate, RetryCount); } pHwData->dto_tx_frag_count += (RetryCount+1); -- cgit v1.2.3 From 6eaf842a24bae6c4d8159a26f428919d114fc667 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Thu, 14 Nov 2013 21:15:10 +0900 Subject: staging: alarm-dev: Remove unnecessary parenthesis Signed-off-by: SeongJae Park Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/alarm-dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 647694f43dcf..ccf74eef5364 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -68,8 +68,8 @@ static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; */ static int is_wakeup(enum android_alarm_type type) { - return (type == ANDROID_ALARM_RTC_WAKEUP || - type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP); + return type == ANDROID_ALARM_RTC_WAKEUP || + type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP; } -- cgit v1.2.3 From 027c440971f9b3dccc05da5bf626cb129f8daf58 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Thu, 14 Nov 2013 21:15:11 +0900 Subject: staging: alarm-dev: Remove unnecessary blank lines Signed-off-by: SeongJae Park Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/alarm-dev.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index ccf74eef5364..a3b467be7f8f 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -72,7 +72,6 @@ static int is_wakeup(enum android_alarm_type type) type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP; } - static void devalarm_start(struct devalarm *alrm, ktime_t exp) { if (is_wakeup(alrm->type)) @@ -111,7 +110,6 @@ static void alarm_clear(enum android_alarm_type alarm_type) } alarm_enabled &= ~alarm_type_mask; spin_unlock_irqrestore(&alarm_slock, flags); - } static void alarm_set(enum android_alarm_type alarm_type, @@ -371,7 +369,6 @@ static void devalarm_triggered(struct devalarm *alarm) spin_unlock_irqrestore(&alarm_slock, flags); } - static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) { struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); -- cgit v1.2.3 From 5230a5f585244b300586d1f4cd578d9e604b8771 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Thu, 14 Nov 2013 21:15:12 +0900 Subject: staging: alarm-dev: Seperate functions with one blank line Signed-off-by: SeongJae Park Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/alarm-dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index a3b467be7f8f..2fc7cdd4c4e3 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -278,6 +278,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } + #ifdef CONFIG_COMPAT static long alarm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -- cgit v1.2.3 From ffae31f625d881b162a7979229d12c047d3c21f1 Mon Sep 17 00:00:00 2001 From: Eric Skoglund Date: Tue, 12 Nov 2013 10:42:21 +0100 Subject: Drivers: Staging: cxt1e1: sbeid: Fixed coding style issue - space -> tabs This patch converts spaces to tabs to conform to the coding style standards. Signed-off-by: Eric Skoglund Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/sbeid.c | 318 ++++++++++++++++++++--------------------- 1 file changed, 159 insertions(+), 159 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/sbeid.c b/drivers/staging/cxt1e1/sbeid.c index 6ec51bccceb1..75efbc3a62ff 100644 --- a/drivers/staging/cxt1e1/sbeid.c +++ b/drivers/staging/cxt1e1/sbeid.c @@ -22,44 +22,44 @@ char * sbeid_get_bdname (ci_t *ci) { - char *np = NULL; + char *np = NULL; - switch (ci->brd_id) - { - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): - np = "wanPTMC-256T3 "; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): - np = "wanPTMC-256T3 "; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): - np = "wanPMC-C4T1E1"; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): - np = "wanPMC-C2T1E1"; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): - np = "wanPMC-C1T1E1"; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): - np = "wanPCI-C4T1E1"; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): - np = "wanPCI-C2T1E1"; - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): - np = "wanPCI-C1T1E1"; - break; - default: - /*** np = ""; ***/ - np = "wanPCI-CxT1E1"; - break; - } + switch (ci->brd_id) + { + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): + np = "wanPTMC-256T3 "; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): + np = "wanPTMC-256T3 "; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): + np = "wanPMC-C4T1E1"; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): + np = "wanPMC-C2T1E1"; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): + np = "wanPMC-C1T1E1"; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): + np = "wanPCI-C4T1E1"; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): + np = "wanPCI-C2T1E1"; + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): + np = "wanPCI-C1T1E1"; + break; + default: + /*** np = ""; ***/ + np = "wanPCI-CxT1E1"; + break; + } - return np; + return np; } @@ -68,96 +68,96 @@ sbeid_get_bdname (ci_t *ci) void sbeid_set_hdwbid (ci_t *ci) { - /* - * set SBE's unique hardware identification (for legacy boards might not - * have this register implemented) - */ + /* + * set SBE's unique hardware identification (for legacy boards might not + * have this register implemented) + */ - switch (ci->brd_id) - { + switch (ci->brd_id) + { case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): - ci->hdw_bid = SBE_BID_256T3_E1; /* 0x46 - SBE wanPTMC-256T3 (E1 - * Version) */ - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): - ci->hdw_bid = SBE_BID_256T3_T1; /* 0x42 - SBE wanPTMC-256T3 (T1 - * Version) */ - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): - /* - * This Board ID is a generic identification. Use the found number - * of ports to further define this hardware. - */ - switch (ci->max_port) - { - default: /* shouldn't need a default, but have one - * anyway */ - case 4: - ci->hdw_bid = SBE_BID_PMC_C4T1E1; /* 0xC4 - SBE wanPMC-C4T1E1 */ - break; - case 2: - ci->hdw_bid = SBE_BID_PMC_C2T1E1; /* 0xC2 - SBE wanPMC-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); - break; - case 1: - ci->hdw_bid = SBE_BID_PMC_C1T1E1; /* 0xC1 - SBE wanPMC-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); - break; - } - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): - ci->hdw_bid = SBE_BID_PMC_C2T1E1; /* 0xC2 - SBE wanPMC-C2T1E1 */ - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): - ci->hdw_bid = SBE_BID_PMC_C1T1E1; /* 0xC1 - SBE wanPMC-C1T1E1 */ - break; + ci->hdw_bid = SBE_BID_256T3_E1; /* 0x46 - SBE wanPTMC-256T3 (E1 + * Version) */ + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): + ci->hdw_bid = SBE_BID_256T3_T1; /* 0x42 - SBE wanPTMC-256T3 (T1 + * Version) */ + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): + /* + * This Board ID is a generic identification. Use the found number + * of ports to further define this hardware. + */ + switch (ci->max_port) + { + default: /* shouldn't need a default, but have one + * anyway */ + case 4: + ci->hdw_bid = SBE_BID_PMC_C4T1E1; /* 0xC4 - SBE wanPMC-C4T1E1 */ + break; + case 2: + ci->hdw_bid = SBE_BID_PMC_C2T1E1; /* 0xC2 - SBE wanPMC-C2T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); + break; + case 1: + ci->hdw_bid = SBE_BID_PMC_C1T1E1; /* 0xC1 - SBE wanPMC-C1T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); + break; + } + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): + ci->hdw_bid = SBE_BID_PMC_C2T1E1; /* 0xC2 - SBE wanPMC-C2T1E1 */ + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): + ci->hdw_bid = SBE_BID_PMC_C1T1E1; /* 0xC1 - SBE wanPMC-C1T1E1 */ + break; #ifdef SBE_PMCC4_ENABLE - /* - * This case is entered as a result of the inability to obtain the - * from the board's EEPROM. Assume a PCI board and set - * according to the number ofr found ports. - */ - case 0: - /* start by assuming 4-port for ZERO casing */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); - /* drop thru to set hdw_bid and alternate PCI CxT1E1 settings */ + /* + * This case is entered as a result of the inability to obtain the + * from the board's EEPROM. Assume a PCI board and set + * according to the number ofr found ports. + */ + case 0: + /* start by assuming 4-port for ZERO casing */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); + /* drop thru to set hdw_bid and alternate PCI CxT1E1 settings */ #endif - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): - /* - * This Board ID is a generic identification. Use the number of - * found ports to further define this hardware. - */ - switch (ci->max_port) - { - default: /* shouldn't need a default, but have one - * anyway */ - case 4: - ci->hdw_bid = SBE_BID_PCI_C4T1E1; /* 0x04 - SBE wanPCI-C4T1E1 */ - break; - case 2: - ci->hdw_bid = SBE_BID_PCI_C2T1E1; /* 0x02 - SBE wanPCI-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); - break; - case 1: - ci->hdw_bid = SBE_BID_PCI_C1T1E1; /* 0x01 - SBE wanPCI-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); - break; - } - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): - ci->hdw_bid = SBE_BID_PCI_C2T1E1; /* 0x02 - SBE wanPCI-C2T1E1 */ - break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): - ci->hdw_bid = SBE_BID_PCI_C1T1E1; /* 0x01 - SBE wanPCI-C1T1E1 */ - break; - default: - /*** bid = ""; ***/ - ci->hdw_bid = SBE_BID_PMC_C4T1E1; /* 0x41 - SBE wanPTMC-C4T1E1 */ - break; - } + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): + /* + * This Board ID is a generic identification. Use the number of + * found ports to further define this hardware. + */ + switch (ci->max_port) + { + default: /* shouldn't need a default, but have one + * anyway */ + case 4: + ci->hdw_bid = SBE_BID_PCI_C4T1E1; /* 0x04 - SBE wanPCI-C4T1E1 */ + break; + case 2: + ci->hdw_bid = SBE_BID_PCI_C2T1E1; /* 0x02 - SBE wanPCI-C2T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); + break; + case 1: + ci->hdw_bid = SBE_BID_PCI_C1T1E1; /* 0x01 - SBE wanPCI-C1T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); + break; + } + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): + ci->hdw_bid = SBE_BID_PCI_C2T1E1; /* 0x02 - SBE wanPCI-C2T1E1 */ + break; + case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): + ci->hdw_bid = SBE_BID_PCI_C1T1E1; /* 0x01 - SBE wanPCI-C1T1E1 */ + break; + default: + /*** bid = ""; ***/ + ci->hdw_bid = SBE_BID_PMC_C4T1E1; /* 0x41 - SBE wanPTMC-C4T1E1 */ + break; + } } /* given the presetting of hdw_bid, set the corresponding brd_id */ @@ -165,45 +165,45 @@ sbeid_set_hdwbid (ci_t *ci) void sbeid_set_bdtype (ci_t *ci) { - /* set SBE's unique PCI VENDOR/DEVID */ - switch (ci->hdw_bid) - { + /* set SBE's unique PCI VENDOR/DEVID */ + switch (ci->hdw_bid) + { case SBE_BID_C1T3: /* SBE wanPMC-C1T3 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3); - break; - case SBE_BID_C24TE1: /* SBE wanPTMC-C24TE1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1); - break; - case SBE_BID_256T3_E1: /* SBE wanPTMC-256T3 E1 Version */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1); - break; - case SBE_BID_256T3_T1: /* SBE wanPTMC-256T3 T1 Version */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1); - break; - case SBE_BID_PMC_C4T1E1: /* 0xC4 - SBE wanPMC-C4T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1); - break; - case SBE_BID_PMC_C2T1E1: /* 0xC2 - SBE wanPMC-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); - break; - case SBE_BID_PMC_C1T1E1: /* 0xC1 - SBE wanPMC-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); - break; - case SBE_BID_PCI_C4T1E1: /* 0x04 - SBE wanPCI-C4T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); - break; - case SBE_BID_PCI_C2T1E1: /* 0x02 - SBE wanPCI-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); - break; - case SBE_BID_PCI_C1T1E1: /* 0x01 - SBE wanPCI-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); - break; + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3); + break; + case SBE_BID_C24TE1: /* SBE wanPTMC-C24TE1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1); + break; + case SBE_BID_256T3_E1: /* SBE wanPTMC-256T3 E1 Version */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1); + break; + case SBE_BID_256T3_T1: /* SBE wanPTMC-256T3 T1 Version */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1); + break; + case SBE_BID_PMC_C4T1E1: /* 0xC4 - SBE wanPMC-C4T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1); + break; + case SBE_BID_PMC_C2T1E1: /* 0xC2 - SBE wanPMC-C2T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); + break; + case SBE_BID_PMC_C1T1E1: /* 0xC1 - SBE wanPMC-C1T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); + break; + case SBE_BID_PCI_C4T1E1: /* 0x04 - SBE wanPCI-C4T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); + break; + case SBE_BID_PCI_C2T1E1: /* 0x02 - SBE wanPCI-C2T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); + break; + case SBE_BID_PCI_C1T1E1: /* 0x01 - SBE wanPCI-C1T1E1 */ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); + break; - default: - /*** hdw_bid = ""; ***/ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); - break; - } + default: + /*** hdw_bid = ""; ***/ + ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); + break; + } } -- cgit v1.2.3 From e585e3df37cc5db728a3945987c256e71c92c446 Mon Sep 17 00:00:00 2001 From: Eric Skoglund Date: Tue, 12 Nov 2013 10:42:22 +0100 Subject: Drivers: Staging: cxt1e1: sbeid: Fixed braces coding style issue This patch fixes a brace coding style issue. Signed-off-by: Eric Skoglund Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/sbeid.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/sbeid.c b/drivers/staging/cxt1e1/sbeid.c index 75efbc3a62ff..bf6c94375205 100644 --- a/drivers/staging/cxt1e1/sbeid.c +++ b/drivers/staging/cxt1e1/sbeid.c @@ -24,8 +24,7 @@ sbeid_get_bdname (ci_t *ci) { char *np = NULL; - switch (ci->brd_id) - { + switch (ci->brd_id) { case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): np = "wanPTMC-256T3 "; break; @@ -73,8 +72,7 @@ sbeid_set_hdwbid (ci_t *ci) * have this register implemented) */ - switch (ci->brd_id) - { + switch (ci->brd_id) { case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): ci->hdw_bid = SBE_BID_256T3_E1; /* 0x46 - SBE wanPTMC-256T3 (E1 * Version) */ @@ -89,8 +87,7 @@ sbeid_set_hdwbid (ci_t *ci) * This Board ID is a generic identification. Use the found number * of ports to further define this hardware. */ - switch (ci->max_port) - { + switch (ci->max_port) { default: /* shouldn't need a default, but have one * anyway */ case 4: @@ -130,8 +127,7 @@ sbeid_set_hdwbid (ci_t *ci) * This Board ID is a generic identification. Use the number of * found ports to further define this hardware. */ - switch (ci->max_port) - { + switch (ci->max_port) { default: /* shouldn't need a default, but have one * anyway */ case 4: @@ -166,8 +162,7 @@ void sbeid_set_bdtype (ci_t *ci) { /* set SBE's unique PCI VENDOR/DEVID */ - switch (ci->hdw_bid) - { + switch (ci->hdw_bid) { case SBE_BID_C1T3: /* SBE wanPMC-C1T3 */ ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3); break; -- cgit v1.2.3 From 5ee86a38058deb464afdbfbb487825b4278d85ca Mon Sep 17 00:00:00 2001 From: Eric Skoglund Date: Tue, 12 Nov 2013 10:42:23 +0100 Subject: Drivers: Staging: cxt1e1: stbeid: Fixed whitespace between function and parameters This patch fixes whitespace coding style errors: func () --> func() Signed-of-by: Eric Skoglund Signed-off-by: Greg Kroah-Hartman --- drivers/staging/cxt1e1/sbeid.c | 84 +++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cxt1e1/sbeid.c b/drivers/staging/cxt1e1/sbeid.c index bf6c94375205..97c5c6e7e299 100644 --- a/drivers/staging/cxt1e1/sbeid.c +++ b/drivers/staging/cxt1e1/sbeid.c @@ -20,36 +20,36 @@ #include "sbe_bid.h" char * -sbeid_get_bdname (ci_t *ci) +sbeid_get_bdname(ci_t *ci) { char *np = NULL; switch (ci->brd_id) { - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): np = "wanPTMC-256T3 "; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): np = "wanPTMC-256T3 "; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): np = "wanPMC-C4T1E1"; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): np = "wanPMC-C2T1E1"; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): np = "wanPMC-C1T1E1"; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): np = "wanPCI-C4T1E1"; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): np = "wanPCI-C2T1E1"; break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): np = "wanPCI-C1T1E1"; break; default: @@ -65,7 +65,7 @@ sbeid_get_bdname (ci_t *ci) /* given the presetting of brd_id, set the corresponding hdw_id */ void -sbeid_set_hdwbid (ci_t *ci) +sbeid_set_hdwbid(ci_t *ci) { /* * set SBE's unique hardware identification (for legacy boards might not @@ -73,16 +73,16 @@ sbeid_set_hdwbid (ci_t *ci) */ switch (ci->brd_id) { - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): ci->hdw_bid = SBE_BID_256T3_E1; /* 0x46 - SBE wanPTMC-256T3 (E1 * Version) */ break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): ci->hdw_bid = SBE_BID_256T3_T1; /* 0x42 - SBE wanPTMC-256T3 (T1 * Version) */ break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): /* * This Board ID is a generic identification. Use the found number * of ports to further define this hardware. @@ -95,20 +95,20 @@ sbeid_set_hdwbid (ci_t *ci) break; case 2: ci->hdw_bid = SBE_BID_PMC_C2T1E1; /* 0xC2 - SBE wanPMC-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); break; case 1: ci->hdw_bid = SBE_BID_PMC_C1T1E1; /* 0xC1 - SBE wanPMC-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); break; } break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): ci->hdw_bid = SBE_BID_PMC_C2T1E1; /* 0xC2 - SBE wanPMC-C2T1E1 */ break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): ci->hdw_bid = SBE_BID_PMC_C1T1E1; /* 0xC1 - SBE wanPMC-C1T1E1 */ break; #ifdef SBE_PMCC4_ENABLE @@ -119,10 +119,10 @@ sbeid_set_hdwbid (ci_t *ci) */ case 0: /* start by assuming 4-port for ZERO casing */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); /* drop thru to set hdw_bid and alternate PCI CxT1E1 settings */ #endif - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): /* * This Board ID is a generic identification. Use the number of * found ports to further define this hardware. @@ -135,18 +135,18 @@ sbeid_set_hdwbid (ci_t *ci) break; case 2: ci->hdw_bid = SBE_BID_PCI_C2T1E1; /* 0x02 - SBE wanPCI-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); break; case 1: ci->hdw_bid = SBE_BID_PCI_C1T1E1; /* 0x01 - SBE wanPCI-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); break; } break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): ci->hdw_bid = SBE_BID_PCI_C2T1E1; /* 0x02 - SBE wanPCI-C2T1E1 */ break; - case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): + case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): ci->hdw_bid = SBE_BID_PCI_C1T1E1; /* 0x01 - SBE wanPCI-C1T1E1 */ break; default: @@ -159,44 +159,44 @@ sbeid_set_hdwbid (ci_t *ci) /* given the presetting of hdw_bid, set the corresponding brd_id */ void -sbeid_set_bdtype (ci_t *ci) +sbeid_set_bdtype(ci_t *ci) { /* set SBE's unique PCI VENDOR/DEVID */ switch (ci->hdw_bid) { - case SBE_BID_C1T3: /* SBE wanPMC-C1T3 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3); + case SBE_BID_C1T3: /* SBE wanPMC-C1T3 */ + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3); break; case SBE_BID_C24TE1: /* SBE wanPTMC-C24TE1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1); break; case SBE_BID_256T3_E1: /* SBE wanPTMC-256T3 E1 Version */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1); break; case SBE_BID_256T3_T1: /* SBE wanPTMC-256T3 T1 Version */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1); break; case SBE_BID_PMC_C4T1E1: /* 0xC4 - SBE wanPMC-C4T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1); break; case SBE_BID_PMC_C2T1E1: /* 0xC2 - SBE wanPMC-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1); break; case SBE_BID_PMC_C1T1E1: /* 0xC1 - SBE wanPMC-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1); break; case SBE_BID_PCI_C4T1E1: /* 0x04 - SBE wanPCI-C4T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); break; case SBE_BID_PCI_C2T1E1: /* 0x02 - SBE wanPCI-C2T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1); break; case SBE_BID_PCI_C1T1E1: /* 0x01 - SBE wanPCI-C1T1E1 */ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1); break; default: /*** hdw_bid = ""; ***/ - ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); + ci->brd_id = SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1); break; } } -- cgit v1.2.3 From 5cfa1b2598f3b0610ac597082aa997f7a94a7b3d Mon Sep 17 00:00:00 2001 From: Ana Rey Date: Tue, 12 Nov 2013 15:22:50 +0100 Subject: staging: rtl8187se: fix coding style in function declarations Removed innecessary spaces and indentation errors in function definition (including some curly braces wrongly placed and broke up at 80-chars per line). I still see some errors if I run the checkpatch.pl script, but those are not my fault. I'll address them in follow up patches. Signed-off-by: Ana Rey Acked-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/dot11d.c | 36 ++---- drivers/staging/rtl8187se/ieee80211/dot11d.h | 46 ++------ drivers/staging/rtl8187se/ieee80211/ieee80211.h | 122 +++++++++++---------- .../staging/rtl8187se/ieee80211/ieee80211_crypt.c | 3 +- .../rtl8187se/ieee80211/ieee80211_crypt_ccmp.c | 2 +- .../rtl8187se/ieee80211/ieee80211_crypt_tkip.c | 9 +- drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c | 39 +++---- .../rtl8187se/ieee80211/ieee80211_softmac.c | 91 ++++++++------- .../rtl8187se/ieee80211/ieee80211_softmac_wx.c | 64 ++++++----- drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c | 13 +-- drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c | 8 +- drivers/staging/rtl8187se/r8180.h | 22 ++-- drivers/staging/rtl8187se/r8180_core.c | 17 ++- drivers/staging/rtl8187se/r8180_dm.h | 2 +- drivers/staging/rtl8187se/r8180_rtl8225.h | 3 +- drivers/staging/rtl8187se/r8180_wx.c | 102 ++++++++--------- drivers/staging/rtl8187se/r8185b_init.c | 13 ++- 17 files changed, 281 insertions(+), 311 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index d1395a683d5b..4483c2c0307c 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -1,7 +1,6 @@ #include "dot11d.h" -void -Dot11d_Init(struct ieee80211_device *ieee) +void Dot11d_Init(struct ieee80211_device *ieee) { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); @@ -17,8 +16,7 @@ Dot11d_Init(struct ieee80211_device *ieee) } /* Reset to the state as we are just entering a regulatory domain. */ -void -Dot11d_Reset(struct ieee80211_device *ieee) +void Dot11d_Reset(struct ieee80211_device *ieee) { u32 i; PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); @@ -50,13 +48,8 @@ Dot11d_Reset(struct ieee80211_device *ieee) * 1. IS_DOT11D_ENABLE() is TRUE. * 2. Input IE is an valid one. */ -void -Dot11d_UpdateCountryIe( - struct ieee80211_device *dev, - u8 *pTaddr, - u16 CoutryIeLen, - u8 *pCoutryIe - ) +void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr, + u16 CoutryIeLen, u8 *pCoutryIe) { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); u8 i, j, NumTriples, MaxChnlNum; @@ -122,11 +115,7 @@ Dot11d_UpdateCountryIe( pDot11dInfo->State = DOT11D_STATE_LEARNED; } -u8 -DOT11D_GetMaxTxPwrInDbm( - struct ieee80211_device *dev, - u8 Channel - ) +u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel) { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); u8 MaxTxPwrInDbm = 255; @@ -142,10 +131,7 @@ DOT11D_GetMaxTxPwrInDbm( } -void -DOT11D_ScanComplete( - struct ieee80211_device *dev - ) +void DOT11D_ScanComplete(struct ieee80211_device *dev) { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); @@ -165,10 +151,7 @@ DOT11D_ScanComplete( } } -int IsLegalChannel( - struct ieee80211_device *dev, - u8 channel -) +int IsLegalChannel(struct ieee80211_device *dev, u8 channel) { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); @@ -181,10 +164,7 @@ int IsLegalChannel( return 0; } -int ToLegalChannel( - struct ieee80211_device *dev, - u8 channel -) +int ToLegalChannel(struct ieee80211_device *dev, u8 channel) { PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); u8 default_chn = 0; diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h index 9c016fee0107..63f4f3c72f10 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.h +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.h @@ -58,43 +58,13 @@ typedef struct _RT_DOT11D_INFO { #define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) +void Dot11d_Init(struct ieee80211_device *dev); +void Dot11d_Reset(struct ieee80211_device *dev); +void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr, + u16 CoutryIeLen, u8 *pCoutryIe); +u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel); +void DOT11D_ScanComplete(struct ieee80211_device *dev); +int IsLegalChannel(struct ieee80211_device *dev, u8 channel); +int ToLegalChannel(struct ieee80211_device *dev, u8 channel); -void -Dot11d_Init( - struct ieee80211_device *dev - ); - -void -Dot11d_Reset( - struct ieee80211_device *dev - ); - -void -Dot11d_UpdateCountryIe( - struct ieee80211_device *dev, - u8 * pTaddr, - u16 CoutryIeLen, - u8 * pCoutryIe - ); - -u8 -DOT11D_GetMaxTxPwrInDbm( - struct ieee80211_device *dev, - u8 Channel - ); - -void -DOT11D_ScanComplete( - struct ieee80211_device * dev - ); - -int IsLegalChannel( - struct ieee80211_device * dev, - u8 channel -); - -int ToLegalChannel( - struct ieee80211_device * dev, - u8 channel -); #endif /* #ifndef __INC_DOT11D_H */ diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h index ce8dcf79185c..09ffd9bc8991 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -1240,7 +1240,8 @@ static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) return 1; } -static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) +static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, + int mode) { /* * It is possible for both access points and our device to support @@ -1303,19 +1304,16 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee); /* ieee80211_tx.c */ -extern int ieee80211_encrypt_fragment( - struct ieee80211_device *ieee, - struct sk_buff *frag, - int hdr_len); +extern int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, + struct sk_buff *frag, int hdr_len); -extern int ieee80211_rtl_xmit(struct sk_buff *skb, - struct net_device *dev); +extern int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev); extern void ieee80211_txb_free(struct ieee80211_txb *); /* ieee80211_rx.c */ extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats); + struct ieee80211_rx_stats *rx_stats); extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *header, struct ieee80211_rx_stats *stats); @@ -1331,25 +1329,28 @@ extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *key); extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data* wrqu, char *extra); + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); int ieee80211_wx_set_auth(struct ieee80211_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra); + struct iw_request_info *info, + struct iw_param *data, char *extra); int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); /* ieee80211_softmac.c */ extern short ieee80211_is_54g(const struct ieee80211_network *net); extern short ieee80211_is_shortslot(const struct ieee80211_network *net); -extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, u16 type, - u16 stype); -extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net); - -extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee); +extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, + struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, + u16 type, u16 stype); +extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, + struct ieee80211_network *net); + +extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, + struct ieee80211_device *ieee); extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee); extern void ieee80211_start_bss(struct ieee80211_device *ieee); extern void ieee80211_start_master_bss(struct ieee80211_device *ieee); @@ -1371,16 +1372,17 @@ extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); -extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p); +extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, + struct iw_point *p); extern void notify_wx_assoc_event(struct ieee80211_device *ieee); extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); -extern void SendDisassociation(struct ieee80211_device *ieee,u8* asSta,u8 asRsn); +extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, + u8 asRsn); extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee); //Add for RF power on power off by lizhaoming 080512 -extern void SendDisassociation(struct ieee80211_device *ieee, - u8* asSta, - u8 asRsn); +extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, + u8 asRsn); /* ieee80211_crypt_ccmp&tkip&wep.c */ extern void ieee80211_tkip_null(void); @@ -1389,64 +1391,72 @@ extern void ieee80211_ccmp_null(void); /* ieee80211_softmac_wx.c */ extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *ext); + struct iw_request_info *info, + union iwreq_data *wrqu, char *ext); extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra); + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra); -extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b); +extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b); extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); -extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); +extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b); -extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); +extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b); extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra); + struct iw_request_info *a, + union iwreq_data *wrqu, char *extra); -extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); +extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b); -extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); +extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b); -extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); +extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b); extern void ieee80211_wx_sync_scan_wq(struct work_struct *work); extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); extern int ieee80211_wx_get_name(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + extern int ieee80211_wx_get_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); extern void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee); -extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr); +extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, + short pwr); extern const long ieee80211_wlan_frequencies[]; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c index 694eae3d4fda..a0340ee9d8b7 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c @@ -39,8 +39,7 @@ struct ieee80211_crypto { static struct ieee80211_crypto *hcrypt; -void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, - int force) +void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) { struct list_head *ptr, *n; struct ieee80211_crypt_data *entry; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c index 05d34e5453c9..0e8392acdeac 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c @@ -60,7 +60,7 @@ struct ieee80211_ccmp_data { }; void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) + const u8 pt[16], u8 ct[16]) { crypto_cipher_encrypt_one((void *)tfm, ct, pt); } diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c index 9c25ffb1697c..34a10d1868b4 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c @@ -520,7 +520,8 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) } -static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) +static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, + void *priv) { struct ieee80211_tkip_data *tkey = priv; u8 *pos; @@ -550,8 +551,8 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *pri } static void ieee80211_michael_mic_failure(struct net_device *dev, - struct ieee80211_hdr_4addr *hdr, - int keyidx) + struct ieee80211_hdr_4addr *hdr, + int keyidx) { union iwreq_data wrqu; struct iw_michaelmicfailure ev; @@ -571,7 +572,7 @@ static void ieee80211_michael_mic_failure(struct net_device *dev, } static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, - int hdr_len, void *priv) + int hdr_len, void *priv) { struct ieee80211_tkip_data *tkey = priv; u8 mic[8]; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c index 304579096562..b522b57a2691 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c @@ -337,8 +337,9 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, /* Called only as a tasklet (software IRQ), by ieee80211_rx */ static inline int -ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *skb, - int keyidx, struct ieee80211_crypt_data *crypt) +ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, + struct sk_buff *skb, int keyidx, + struct ieee80211_crypt_data *crypt) { struct ieee80211_hdr_4addr *hdr; int res, hdrlen; @@ -366,7 +367,7 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s /* this function is stolen from ipw2200 driver*/ #define IEEE_PACKET_RETRY_TIME (5*HZ) static int is_duplicate_packet(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header) + struct ieee80211_hdr_4addr *header) { u16 fc = le16_to_cpu(header->frame_ctl); u16 sc = le16_to_cpu(header->seq_ctl); @@ -467,7 +468,7 @@ drop: * IEEE 802.11 format, i.e., in the format it was sent over air. * This function is called only as a tasklet (software IRQ). */ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats) + struct ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); @@ -794,9 +795,7 @@ static inline int ieee80211_is_ofdm_rate(u8 rate) return 0; } -static inline int ieee80211_SignalStrengthTranslate( - int CurrSS - ) +static inline int ieee80211_SignalStrengthTranslate(int CurrSS) { int RetSS; @@ -831,12 +830,10 @@ static inline int ieee80211_SignalStrengthTranslate( return RetSS; } -static inline void ieee80211_extract_country_ie( - struct ieee80211_device *ieee, - struct ieee80211_info_element *info_element, - struct ieee80211_network *network, - u8 *addr2 -) +static inline void +ieee80211_extract_country_ie(struct ieee80211_device *ieee, + struct ieee80211_info_element *info_element, + struct ieee80211_network *network, u8 *addr2) { if (IS_DOT11D_ENABLE(ieee)) { if (info_element->len != 0) { @@ -858,10 +855,8 @@ static inline void ieee80211_extract_country_ie( } -static int -ieee80211_TranslateToDbm( - unsigned char SignalStrengthIndex // 0-100 index. - ) +/* SignalStrengthIndex is 0-100 */ +static int ieee80211_TranslateToDbm(unsigned char SignalStrengthIndex) { unsigned char SignalPower; // in dBm. @@ -1197,7 +1192,7 @@ static inline int is_same_network(struct ieee80211_network *src, } inline void update_network(struct ieee80211_network *dst, - struct ieee80211_network *src) + struct ieee80211_network *src) { unsigned char quality = src->stats.signalstrength; unsigned char signal = 0; @@ -1281,10 +1276,10 @@ inline void update_network(struct ieee80211_network *dst, } -inline void ieee80211_process_probe_response( - struct ieee80211_device *ieee, - struct ieee80211_probe_response *beacon, - struct ieee80211_rx_stats *stats) +inline void +ieee80211_process_probe_response(struct ieee80211_device *ieee, + struct ieee80211_probe_response *beacon, + struct ieee80211_rx_stats *stats) { struct ieee80211_network network; struct ieee80211_network *target; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 7e16ccb7a645..3af1bf965981 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -186,7 +186,8 @@ void init_mgmt_queue(struct ieee80211_device *ieee) void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl); -inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) +inline void softmac_mgmt_xmit(struct sk_buff *skb, + struct ieee80211_device *ieee) { unsigned long flags; short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; @@ -237,7 +238,8 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee } -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) +inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, + struct ieee80211_device *ieee) { short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; @@ -275,10 +277,9 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i // dev_kfree_skb_any(skb);//edit by thomas } //by amy for power save -inline struct sk_buff *ieee80211_disassociate_skb( - struct ieee80211_network *beacon, - struct ieee80211_device *ieee, - u8 asRsn) +inline struct sk_buff * +ieee80211_disassociate_skb(struct ieee80211_network *beacon, + struct ieee80211_device *ieee, u8 asRsn) { struct sk_buff *skb; struct ieee80211_disassoc_frame *disass; @@ -298,12 +299,7 @@ inline struct sk_buff *ieee80211_disassociate_skb( disass->reasoncode = asRsn; return skb; } -void -SendDisassociation( - struct ieee80211_device *ieee, - u8* asSta, - u8 asRsn -) +void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn) { struct ieee80211_network *beacon = &ieee->current_network; struct sk_buff *skb; @@ -734,8 +730,9 @@ void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) } -inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, int challengelen) +inline struct sk_buff * +ieee80211_authentication_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee, int challengelen) { struct sk_buff *skb; struct ieee80211_authentication *auth; @@ -767,7 +764,8 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be } -static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest) +static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, + u8 *dest) { u8 *tag; int beacon_size; @@ -968,7 +966,7 @@ static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee, } -struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) +struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee, short pwr) { struct sk_buff *skb; struct ieee80211_hdr_3addr* hdr; @@ -994,7 +992,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) } -void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest) +void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest) { struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest); @@ -1005,7 +1003,7 @@ void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest) } -void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest) +void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8 *dest) { struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest); @@ -1028,7 +1026,9 @@ void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) } -inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee) +inline struct sk_buff * +ieee80211_association_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee) { struct sk_buff *skb; //unsigned long flags; @@ -1199,7 +1199,8 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee) } } -void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) +void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, + int chlen) { u8 *c; struct sk_buff *skb; @@ -1309,7 +1310,8 @@ void ieee80211_associate_procedure_wq(struct work_struct *work) up(&ieee->wx_sem); } -inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net) +inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, + struct ieee80211_network *net) { u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; int tmp_ssid_len = 0; @@ -1422,7 +1424,7 @@ void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee) } -static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen) +static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen) { struct ieee80211_authentication *a; u8 *t; @@ -1448,7 +1450,7 @@ static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen) } -int auth_rq_parse(struct sk_buff *skb,u8* dest) +int auth_rq_parse(struct sk_buff *skb, u8 *dest) { struct ieee80211_authentication *a; @@ -1466,7 +1468,8 @@ int auth_rq_parse(struct sk_buff *skb,u8* dest) return WLAN_STATUS_SUCCESS; } -static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src) +static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, + u8 *src) { u8 *tag; u8 *skbend; @@ -1504,7 +1507,7 @@ static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, } -int assoc_rq_parse(struct sk_buff *skb,u8* dest) +int assoc_rq_parse(struct sk_buff *skb, u8 *dest) { struct ieee80211_assoc_request_frame *a; @@ -1535,8 +1538,8 @@ static inline u16 assoc_parse(struct sk_buff *skb, int *aid) return le16_to_cpu(a->status); } -static inline void -ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb) +static inline void ieee80211_rx_probe_rq(struct ieee80211_device *ieee, + struct sk_buff *skb) { u8 dest[ETH_ALEN]; @@ -1550,8 +1553,8 @@ ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb) } } -inline void -ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb) +inline void ieee80211_rx_auth_rq(struct ieee80211_device *ieee, + struct sk_buff *skb) { u8 dest[ETH_ALEN]; int status; @@ -1594,7 +1597,8 @@ void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr) } -short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l) +short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, + u32 *time_l) { int timeout = 0; @@ -1769,10 +1773,10 @@ void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success) spin_unlock_irqrestore(&ieee->lock, flags); } -inline int -ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, u16 type, - u16 stype) +inline int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, + struct sk_buff *skb, + struct ieee80211_rx_stats *rx_stats, + u16 type, u16 stype) { struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data; u16 errcode; @@ -1975,7 +1979,8 @@ associate_complete: * to the driver later, when it wakes the queue. */ -void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee) +void ieee80211_softmac_xmit(struct ieee80211_txb *txb, + struct ieee80211_device *ieee) { @@ -2618,7 +2623,8 @@ static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value) } -void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len) +void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, + int wpa_ie_len) { /* make sure WPA is enabled */ ieee80211_wpa_enable(ieee, 1); @@ -2627,7 +2633,8 @@ void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int } -static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason) +static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, + int reason) { int ret = 0; @@ -2651,7 +2658,7 @@ static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int re static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee, - struct ieee_param *param, int plen) + struct ieee_param *param, int plen) { u8 *buf; @@ -2705,7 +2712,8 @@ static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value) return ret; } -static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value) +static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, + u32 value) { int ret=0; unsigned long flags; @@ -2783,7 +2791,7 @@ static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 v /* implementation borrowed from hostap driver */ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, - struct ieee_param *param, int param_len) + struct ieee_param *param, int param_len) { int ret = 0; @@ -2930,7 +2938,8 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, return ret; } -int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p) +int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, + struct iw_point *p) { struct ieee_param *param; int ret=0; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c index e5282068e3de..46f35644126c 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c @@ -28,8 +28,9 @@ const long ieee80211_wlan_frequencies[] = { }; -int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) +int ieee80211_wx_set_freq(struct ieee80211_device *ieee, + struct iw_request_info *a, union iwreq_data *wrqu, + char *b) { int ret; struct iw_freq *fwrq = &wrqu->freq; @@ -82,8 +83,8 @@ out: int ieee80211_wx_get_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) + struct iw_request_info *a, union iwreq_data *wrqu, + char *b) { struct iw_freq *fwrq = &wrqu->freq; @@ -97,8 +98,8 @@ int ieee80211_wx_get_freq(struct ieee80211_device *ieee, } int ieee80211_wx_get_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { unsigned long flags; @@ -126,8 +127,7 @@ int ieee80211_wx_get_wap(struct ieee80211_device *ieee, int ieee80211_wx_set_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *awrq, + struct iw_request_info *info, union iwreq_data *awrq, char *extra) { @@ -174,8 +174,9 @@ out: return ret; } -int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) +int ieee80211_wx_get_essid(struct ieee80211_device *ieee, + struct iw_request_info *a, union iwreq_data *wrqu, + char *b) { int len, ret = 0; unsigned long flags; @@ -211,8 +212,8 @@ out: } int ieee80211_wx_set_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { u32 target_rate = wrqu->bitrate.value; @@ -230,8 +231,8 @@ int ieee80211_wx_set_rate(struct ieee80211_device *ieee, int ieee80211_wx_get_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { wrqu->bitrate.value = ieee->rate * 100000; @@ -239,8 +240,9 @@ int ieee80211_wx_get_rate(struct ieee80211_device *ieee, return 0; } -int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) +int ieee80211_wx_set_mode(struct ieee80211_device *ieee, + struct iw_request_info *a, union iwreq_data *wrqu, + char *b) { ieee->sync_scan_hurryup = 1; @@ -305,8 +307,9 @@ void ieee80211_wx_sync_scan_wq(struct work_struct *work) } -int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) +int ieee80211_wx_set_scan(struct ieee80211_device *ieee, + struct iw_request_info *a, union iwreq_data *wrqu, + char *b) { int ret = 0; @@ -333,8 +336,8 @@ out: } int ieee80211_wx_set_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *a, union iwreq_data *wrqu, + char *extra) { int ret = 0, len; @@ -395,8 +398,9 @@ out: return ret; } -int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) +int ieee80211_wx_get_mode(struct ieee80211_device *ieee, + struct iw_request_info *a, union iwreq_data *wrqu, + char *b) { wrqu->mode = ieee->iw_mode; @@ -404,8 +408,8 @@ int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info } int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { int *parms = (int *)extra; @@ -440,8 +444,8 @@ int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, } int ieee80211_wx_get_name(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { strlcpy(wrqu->name, "802.11", IFNAMSIZ); if (ieee->modulation & IEEE80211_CCK_MODULATION) { @@ -464,8 +468,8 @@ int ieee80211_wx_get_name(struct ieee80211_device *ieee, /* this is mostly stolen from hostap */ int ieee80211_wx_set_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { int ret = 0; @@ -525,8 +529,8 @@ exit: /* this is stolen from hostap */ int ieee80211_wx_get_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, + char *extra) { int ret = 0; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c index f5a5219fe14d..0dc5ae414270 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c @@ -177,10 +177,8 @@ static inline int ieee80211_put_snap(u8 *data, u16 h_proto) return SNAP_SIZE + sizeof(u16); } -int ieee80211_encrypt_fragment( - struct ieee80211_device *ieee, - struct sk_buff *frag, - int hdr_len) +int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, + struct sk_buff *frag, int hdr_len) { struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx]; int res; @@ -279,8 +277,8 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, * Classify the to-be send data packet * Need to acquire the sent queue index. */ -static int -ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) +static int ieee80211_classify(struct sk_buff *skb, + struct ieee80211_network *network) { struct ether_header *eh = (struct ether_header *)skb->data; unsigned int wme_UP = 0; @@ -310,8 +308,7 @@ ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) } /* SKBs are added to the ieee->tx_queue. */ -int ieee80211_rtl_xmit(struct sk_buff *skb, - struct net_device *dev) +int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); struct ieee80211_txb *txb = NULL; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c index 24d39ccc1337..3b7955f0ff98 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c @@ -633,8 +633,8 @@ done: return ret; } int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct iw_mlme *mlme = (struct iw_mlme *) extra; // printk("\ndkgadfslkdjgalskdf===============>%s(), cmd:%x\n", __func__, mlme->cmd); @@ -653,8 +653,8 @@ int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, } int ieee80211_wx_set_auth(struct ieee80211_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra) + struct iw_request_info *info, + struct iw_param *data, char *extra) { /* struct ieee80211_security sec = { diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h index 84957be01b4f..e9602f67cac8 100644 --- a/drivers/staging/rtl8187se/r8180.h +++ b/drivers/staging/rtl8187se/r8180.h @@ -639,20 +639,20 @@ typedef struct r8180_priv ((_ac) == WME_AC_BK) ? BK_PRIORITY : \ BE_PRIORITY) -short rtl8180_tx(struct net_device *dev,u8* skbuf, int len,int priority, - short morefrag,short fragdesc,int rate); +short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority, + short morefrag, short fragdesc, int rate); u8 read_nic_byte(struct net_device *dev, int x); u32 read_nic_dword(struct net_device *dev, int x); u16 read_nic_word(struct net_device *dev, int x) ; -void write_nic_byte(struct net_device *dev, int x,u8 y); -void write_nic_word(struct net_device *dev, int x,u16 y); -void write_nic_dword(struct net_device *dev, int x,u32 y); +void write_nic_byte(struct net_device *dev, int x, u8 y); +void write_nic_word(struct net_device *dev, int x, u16 y); +void write_nic_dword(struct net_device *dev, int x, u32 y); void force_pci_posting(struct net_device *dev); void rtl8180_rtx_disable(struct net_device *); -void rtl8180_set_anaparam(struct net_device *dev,u32 a); -void rtl8185_set_anaparam2(struct net_device *dev,u32 a); +void rtl8180_set_anaparam(struct net_device *dev, u32 a); +void rtl8185_set_anaparam2(struct net_device *dev, u32 a); void rtl8180_set_hw_wep(struct net_device *dev); void rtl8180_no_hw_wep(struct net_device *dev); void rtl8180_update_msr(struct net_device *dev); @@ -661,7 +661,7 @@ void rtl8180_beacon_rx_disable(struct net_device *dev); int rtl8180_down(struct net_device *dev); int rtl8180_up(struct net_device *dev); void rtl8180_commit(struct net_device *dev); -void rtl8180_set_chan(struct net_device *dev,short ch); +void rtl8180_set_chan(struct net_device *dev, short ch); void write_phy(struct net_device *dev, u8 adr, u8 data); void write_phy_cck(struct net_device *dev, u8 adr, u32 data); void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data); @@ -671,7 +671,8 @@ void IPSEnter(struct net_device *dev); void IPSLeave(struct net_device *dev); int get_curr_tx_free_desc(struct net_device *dev, int priority); void UpdateInitialGain(struct net_device *dev); -bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt, bool bAntDiversity); +bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt, + bool bAntDiversity); //#ifdef CONFIG_RTL8185B void rtl8185b_adapter_start(struct net_device *dev); @@ -684,7 +685,8 @@ void fix_tx_fifo(struct net_device *dev); void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch); void rtl8180_rate_adapter(struct work_struct * work); //#endif -bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u32 ChangeSource); +bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, + u32 ChangeSource); #endif diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index d4ba717ff0df..297136b3c57d 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -79,7 +79,7 @@ module_param(hwwep, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards"); static int rtl8180_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); + const struct pci_device_id *id); static void rtl8180_pci_remove(struct pci_dev *pdev); @@ -387,7 +387,8 @@ static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma, return 0; } -void buffer_free(struct net_device *dev, struct buffer **buffer, int len, short consistent) +void buffer_free(struct net_device *dev, struct buffer **buffer, int len, + short consistent) { struct buffer *tmp, *next; @@ -2238,7 +2239,8 @@ static CHANNEL_LIST ChannelPlan[] = { {{1,2,3,4,5,6,7,8,9,10,11,12,13},13} /* world wide 13: ch1~ch11 active scan, ch12~13 passive //lzm add 080826 */ }; -static void rtl8180_set_channel_map(u8 channel_plan, struct ieee80211_device *ieee) +static void rtl8180_set_channel_map(u8 channel_plan, + struct ieee80211_device *ieee) { int i; @@ -2830,11 +2832,8 @@ static struct net_device_stats *rtl8180_stats(struct net_device *dev) /* * Change current and default preamble mode. */ -bool -MgntActSet_802_11_PowerSaveMode( - struct r8180_priv *priv, - RT_PS_MODE rtPsMode -) +bool MgntActSet_802_11_PowerSaveMode(struct r8180_priv *priv, + RT_PS_MODE rtPsMode) { /* Currently, we do not change power save mode on IBSS mode. */ if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) @@ -3161,7 +3160,7 @@ static const struct net_device_ops rtl8180_netdev_ops = { }; static int rtl8180_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) + const struct pci_device_id *id) { unsigned long ioaddr = 0; struct net_device *dev = NULL; diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h index 732c06ac1026..cb4046f346ef 100644 --- a/drivers/staging/rtl8187se/r8180_dm.h +++ b/drivers/staging/rtl8187se/r8180_dm.h @@ -5,7 +5,7 @@ /* #include "r8180_hw.h" */ /* #include "r8180_93cx6.h" */ void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength); -bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex); +bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex); bool SwitchAntenna(struct net_device *dev); void SwAntennaDiversity(struct net_device *dev); void SwAntennaDiversityTimerCallback(struct net_device *dev); diff --git a/drivers/staging/rtl8187se/r8180_rtl8225.h b/drivers/staging/rtl8187se/r8180_rtl8225.h index c94ca0794a5d..de084f07a071 100644 --- a/drivers/staging/rtl8187se/r8180_rtl8225.h +++ b/drivers/staging/rtl8187se/r8180_rtl8225.h @@ -28,7 +28,8 @@ u16 RF_ReadReg(struct net_device *dev, u8 offset); void rtl8180_set_mode(struct net_device *dev, int mode); void rtl8180_set_mode(struct net_device *dev, int mode); -bool SetZebraRFPowerState8185(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState); +bool SetZebraRFPowerState8185(struct net_device *dev, + RT_RF_POWER_STATE eRFPowerState); void rtl8225z4_rf_sleep(struct net_device *dev); void rtl8225z4_rf_wakeup(struct net_device *dev); diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 92b76f4cca47..bae68759bd6a 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -75,8 +75,9 @@ static int r8180_wx_set_key(struct net_device *dev, } -static int r8180_wx_set_beaconinterval(struct net_device *dev, struct iw_request_info *aa, - union iwreq_data *wrqu, char *b) +static int r8180_wx_set_beaconinterval(struct net_device *dev, + struct iw_request_info *aa, + union iwreq_data *wrqu, char *b) { int *parms = (int *)b; int bi = parms[0]; @@ -474,9 +475,8 @@ static int r8180_wx_get_frag(struct net_device *dev, static int r8180_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra) + struct iw_request_info *info, + union iwreq_data *awrq, char *extra) { int ret; struct r8180_priv *priv = ieee80211_priv(dev); @@ -538,8 +538,10 @@ static int r8180_wx_get_enc(struct net_device *dev, } -static int r8180_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union - iwreq_data *wrqu, char *p) { +static int r8180_wx_set_scan_type(struct net_device *dev, + struct iw_request_info *aa, + union iwreq_data *wrqu, char *p) +{ struct r8180_priv *priv = ieee80211_priv(dev); int *parms = (int*)p; @@ -554,8 +556,8 @@ static int r8180_wx_set_scan_type(struct net_device *dev, struct iw_request_info } static int r8180_wx_set_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); int err = 0; @@ -602,8 +604,8 @@ exit: } static int r8180_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -626,8 +628,8 @@ static int r8180_wx_get_retry(struct net_device *dev, } static int r8180_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); if (priv->rf_set_sens == NULL) @@ -638,8 +640,8 @@ static int r8180_wx_get_sens(struct net_device *dev, static int r8180_wx_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -667,8 +669,8 @@ exit: static int r8180_wx_set_rawtx(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); int ret; @@ -687,8 +689,8 @@ static int r8180_wx_set_rawtx(struct net_device *dev, } static int r8180_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { int ret; struct r8180_priv *priv = ieee80211_priv(dev); @@ -703,8 +705,8 @@ static int r8180_wx_get_power(struct net_device *dev, } static int r8180_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { int ret; struct r8180_priv *priv = ieee80211_priv(dev); @@ -729,8 +731,8 @@ static int r8180_wx_set_power(struct net_device *dev, } static int r8180_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -751,8 +753,8 @@ static int r8180_wx_set_rts(struct net_device *dev, return 0; } static int r8180_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -842,8 +844,8 @@ static int r8180_wx_set_iwmode(struct net_device *dev, return ret; } static int r8180_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -859,8 +861,8 @@ static int r8180_wx_get_preamble(struct net_device *dev, return 0; } static int r8180_wx_set_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); int ret = 0; @@ -882,8 +884,8 @@ static int r8180_wx_set_preamble(struct net_device *dev, return ret; } static int r8180_wx_get_siglevel(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); int ret = 0; @@ -901,8 +903,8 @@ static int r8180_wx_get_siglevel(struct net_device *dev, return ret; } static int r8180_wx_get_sigqual(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); int ret = 0; @@ -960,8 +962,8 @@ static int r8180_wx_reset_stats(struct net_device *dev, } static int r8180_wx_radio_on(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -979,8 +981,8 @@ static int r8180_wx_radio_on(struct net_device *dev, } static int r8180_wx_radio_off(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -997,8 +999,8 @@ static int r8180_wx_radio_off(struct net_device *dev, } static int r8180_wx_get_channelplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -1014,8 +1016,8 @@ static int r8180_wx_get_channelplan(struct net_device *dev, return 0; } static int r8180_wx_set_channelplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); int *val = (int *)extra; @@ -1044,8 +1046,8 @@ static int r8180_wx_set_channelplan(struct net_device *dev, } static int r8180_wx_get_version(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); /* struct ieee80211_device *ieee; */ @@ -1060,8 +1062,8 @@ static int r8180_wx_get_version(struct net_device *dev, /* added by amy 080818 */ /*receive datarate from user typing valid rate is from 2 to 108 (1 - 54M), if input 0, return to normal rate adaptive. */ static int r8180_wx_set_forcerate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); u8 forcerate = *extra; @@ -1085,8 +1087,8 @@ static int r8180_wx_set_forcerate(struct net_device *dev, } static int r8180_wx_set_enc_ext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct r8180_priv *priv = ieee80211_priv(dev); @@ -1119,8 +1121,8 @@ static int r8180_wx_set_auth(struct net_device *dev, } static int r8180_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { int ret = 0; struct r8180_priv *priv = ieee80211_priv(dev); @@ -1334,7 +1336,7 @@ static iw_handler r8180_private_handler[] = { }; static inline int is_same_network(struct ieee80211_network *src, - struct ieee80211_network *dst, + struct ieee80211_network *dst, struct ieee80211_device *ieee) { /* A network is only a duplicate if the channel, BSSID, ESSID diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c index f2f0dc7d4e9a..c8b9baff1dbc 100644 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ b/drivers/staging/rtl8187se/r8185b_init.c @@ -870,9 +870,10 @@ static u8 GetSupportedWirelessMode8185(struct net_device *dev) return WIRELESS_MODE_B | WIRELESS_MODE_G; } -static void ActUpdateChannelAccessSetting(struct net_device *dev, - WIRELESS_MODE WirelessMode, - PCHANNEL_ACCESS_SETTING ChnlAccessSetting) +static void +ActUpdateChannelAccessSetting(struct net_device *dev, + WIRELESS_MODE WirelessMode, + PCHANNEL_ACCESS_SETTING ChnlAccessSetting) { AC_CODING eACI; @@ -1084,7 +1085,7 @@ static bool MgntDisconnect(struct net_device *dev, u8 asRsn) * PASSIVE LEVEL. */ static bool SetRFPowerState(struct net_device *dev, - RT_RF_POWER_STATE eRFPowerState) + RT_RF_POWER_STATE eRFPowerState) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); bool bResult = false; @@ -1097,8 +1098,8 @@ static bool SetRFPowerState(struct net_device *dev, return bResult; } -bool MgntActSet_RF_State(struct net_device *dev, - RT_RF_POWER_STATE StateToSet, u32 ChangeSource) +bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, + u32 ChangeSource) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); bool bActionAllowed = false; -- cgit v1.2.3 From 566597a37647c34600d971e5898d5816dddd7afd Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:30 +0530 Subject: staging: vt6656: removed unnecessary braces around if-else statements removed unnecessary braces around if-else statement whenever the if-else construct was followed by just single line of code to comply with linux coding style Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 53 ++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index ca57fc37d609..5f0a00295ef4 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -108,9 +108,7 @@ static void vAdHocBeaconStop(struct vnt_private *pDevice) bStop = true; } if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G) - { bStop = true; - } } if (bStop) @@ -182,13 +180,13 @@ static void s_vProbeChannel(struct vnt_private *pDevice) u8 *pbyRate; int ii; - if (pDevice->byBBType == BB_TYPE_11A) { - pbyRate = &abyCurrSuppRatesA[0]; - } else if (pDevice->byBBType == BB_TYPE_11B) { - pbyRate = &abyCurrSuppRatesB[0]; - } else { - pbyRate = &abyCurrSuppRatesG[0]; - } + if (pDevice->byBBType == BB_TYPE_11A) + pbyRate = &abyCurrSuppRatesA[0]; + else if (pDevice->byBBType == BB_TYPE_11B) + pbyRate = &abyCurrSuppRatesB[0]; + else + pbyRate = &abyCurrSuppRatesG[0]; + // build an assocreq frame and send it pTxPacket = s_MgrMakeProbeRequest ( @@ -204,10 +202,9 @@ static void s_vProbeChannel(struct vnt_private *pDevice) for (ii = 0; ii < 1; ii++) { if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n"); - } - else { + } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n"); - } + } } } @@ -316,9 +313,8 @@ void vRunCommand(struct work_struct *work) pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; - if (pMgmt->uScanChannel == 0) { + if (pMgmt->uScanChannel == 0) pMgmt->uScanChannel = pDevice->byMinChannel; - } if (pMgmt->uScanChannel > pDevice->byMaxChannel) { pDevice->eCommandState = WLAN_CMD_SCAN_END; s_bCommandComplete(pDevice); @@ -546,9 +542,8 @@ void vRunCommand(struct work_struct *work) // if Adhoc mode else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { - if (netif_queue_stopped(pDevice->dev)) { + if (netif_queue_stopped(pDevice->dev)) netif_wake_queue(pDevice->dev); - } pDevice->bLinkPass = true; ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); pMgmt->sNodeDBTable[0].bActive = true; @@ -654,9 +649,8 @@ void vRunCommand(struct work_struct *work) ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); s_bClearBSSID_SCAN(pDevice); - if (netif_queue_stopped(pDevice->dev)) { + if (netif_queue_stopped(pDevice->dev)) netif_wake_queue(pDevice->dev); - } } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { @@ -700,9 +694,8 @@ void vRunCommand(struct work_struct *work) pDevice->byRxMode &= ~RCR_UNICAST; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode); BSSvAddMulticastNode(pDevice); - if (netif_queue_stopped(pDevice->dev)) { + if (netif_queue_stopped(pDevice->dev)) netif_wake_queue(pDevice->dev); - } pDevice->bLinkPass = true; ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); schedule_delayed_work(&pDevice->second_callback_work, HZ); @@ -722,9 +715,8 @@ void vRunCommand(struct work_struct *work) pDevice->bMoreData = true; } - if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) { + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n"); - } pMgmt->sNodeDBTable[0].wEnQueueCnt--; } @@ -747,9 +739,8 @@ void vRunCommand(struct work_struct *work) pDevice->bMoreData = true; } - if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) { + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n"); - } pMgmt->sNodeDBTable[ii].wEnQueueCnt--; // check if sta ps enable, wait next pspoll @@ -973,11 +964,10 @@ static int s_bCommandComplete(struct vnt_private *pDevice) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); pDevice->eCommandState = WLAN_CMD_SCAN_START; pMgmt->uScanChannel = 0; - if (pSSID->len != 0) { + if (pSSID->len != 0) memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - } else { + else memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - } /* if ((bForceSCAN == false) && (pDevice->bLinkPass == true)) { if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) && @@ -1054,9 +1044,8 @@ int bScheduleCommand(struct vnt_private *pDevice, CMD_CODE eCommand, u8 *pbyItem0) { - if (pDevice->cbFreeCmdQueue == 0) { + if (pDevice->cbFreeCmdQueue == 0) return (false); - } pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand; pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true; memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); @@ -1094,11 +1083,9 @@ int bScheduleCommand(struct vnt_private *pDevice, ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); pDevice->cbFreeCmdQueue--; - if (pDevice->bCmdRunning == false) { + if (pDevice->bCmdRunning == false) s_bCommandComplete(pDevice); - } - else { - } + return (true); } -- cgit v1.2.3 From c3f007f5b6bcaeaf554014e3ec471c2308843c6e Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:31 +0530 Subject: staging: vt6656: fixed open brace placement related error fixed the following checkpatch error: ERROR: that open brace { should be on the previous line Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 5f0a00295ef4..cf234829806b 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -100,19 +100,16 @@ static void vAdHocBeaconStop(struct vnt_private *pDevice) */ bStop = false; if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && - (pMgmt->eCurrState >= WMAC_STATE_STARTED)) - { + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) && - (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) - { + (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { bStop = true; } if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G) bStop = true; } - if (bStop) - { + if (bStop) { //PMESG(("STOP_BEACON: IBSSChannel = %u, ScanChannel = %u\n", // pMgmt->uIBSSChannel, pMgmt->uScanChannel)); MACvRegBitsOff(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); @@ -144,8 +141,7 @@ static void vAdHocBeaconRestart(struct vnt_private *pDevice) * (2) VT3253 is programmed as automatic Beacon Transmitting */ if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && - (pMgmt->eCurrState >= WMAC_STATE_STARTED)) - { + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { //PMESG(("RESTART_BEACON\n")); MACvRegBitsOn(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); } -- cgit v1.2.3 From bfce700fb107bb0d3dcb29726629535892267dd2 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:32 +0530 Subject: staging: vt6656: fixed checkpatch errors related to close brace fixed following checkpatch error: ERROR: else should follow close brace '}' Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index cf234829806b..a6681a2f7146 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -350,8 +350,7 @@ void vRunCommand(struct work_struct *work) if ((pDevice->byBBType != BB_TYPE_11A) && (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { pDevice->byBBType = BB_TYPE_11A; CARDvSetBSSMode(pDevice); - } - else if ((pDevice->byBBType == BB_TYPE_11A) && (pMgmt->uScanChannel <= CB_MAX_CHANNEL_24G)) { + } else if ((pDevice->byBBType == BB_TYPE_11A) && (pMgmt->uScanChannel <= CB_MAX_CHANNEL_24G)) { pDevice->byBBType = BB_TYPE_11G; CARDvSetBSSMode(pDevice); } @@ -544,8 +543,7 @@ void vRunCommand(struct work_struct *work) ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); pMgmt->sNodeDBTable[0].bActive = true; pMgmt->sNodeDBTable[0].uInActiveCount = 0; - } - else { + } else { // start own IBSS DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CreateOwn IBSS by CurrMode = IBSS_STA\n"); @@ -580,8 +578,7 @@ void vRunCommand(struct work_struct *work) } s_bClearBSSID_SCAN(pDevice); */ - } - else { + } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n"); // if(pDevice->bWPASuppWextEnabled == true) { @@ -611,11 +608,9 @@ void vRunCommand(struct work_struct *work) spin_unlock_irq(&pDevice->lock); return; } - } - else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { + } else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); - } - else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay! + } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay! pDevice->byLinkWaitCount++; printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); spin_unlock_irq(&pDevice->lock); @@ -648,11 +643,9 @@ void vRunCommand(struct work_struct *work) if (netif_queue_stopped(pDevice->dev)) netif_wake_queue(pDevice->dev); - } - else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { + } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); - } - else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay! + } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay! pDevice->byLinkWaitCount++; printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); spin_unlock_irq(&pDevice->lock); @@ -706,8 +699,7 @@ void vRunCommand(struct work_struct *work) if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) { pMgmt->abyPSTxMap[0] &= ~byMask[0]; pDevice->bMoreData = false; - } - else { + } else { pDevice->bMoreData = true; } @@ -730,8 +722,7 @@ void vRunCommand(struct work_struct *work) pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; pDevice->bMoreData = false; - } - else { + } else { pDevice->bMoreData = true; } @@ -946,8 +937,7 @@ static int s_bCommandComplete(struct vnt_private *pDevice) //Command Queue Empty pDevice->bCmdRunning = false; return true; - } - else { + } else { pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd; pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID; bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd; -- cgit v1.2.3 From 015bdc262bfe21042af4d554459647c8d1f9b571 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:33 +0530 Subject: staging: vt6656: fixed unnecessary whitespace warning removed the "unnecessary whitespace before quoted new line" warning reported by checkpatch script Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index a6681a2f7146..5f8175368c4f 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -197,9 +197,9 @@ static void s_vProbeChannel(struct vnt_private *pDevice) if (pTxPacket != NULL) { for (ii = 0; ii < 1; ii++) { if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail..\n"); } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending..\n"); } } } @@ -319,7 +319,7 @@ void vRunCommand(struct work_struct *work) } else { if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n", pMgmt->uScanChannel); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d\n", pMgmt->uScanChannel); pMgmt->uScanChannel++; s_bCommandComplete(pDevice); spin_unlock_irq(&pDevice->lock); @@ -704,7 +704,7 @@ void vRunCommand(struct work_struct *work) } if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail\n"); pMgmt->sNodeDBTable[0].wEnQueueCnt--; } @@ -727,7 +727,7 @@ void vRunCommand(struct work_struct *work) } if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail\n"); pMgmt->sNodeDBTable[ii].wEnQueueCnt--; // check if sta ps enable, wait next pspoll @@ -739,7 +739,7 @@ void vRunCommand(struct work_struct *work) // clear tx map pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear \n", ii); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear\n", ii); } pMgmt->sNodeDBTable[ii].bRxPSPoll = false; } -- cgit v1.2.3 From faaf9c195e162ec6c0d8c2247e06da4277dad80b Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:34 +0530 Subject: staging: vt6656: fixed the switch case indentation level error aligned the case statements of 'switch' so that the switch and case are on same indentation level to fix the following error. ERROR: switch and case should be at the same indent Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 78 +++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 5f8175368c4f..c07737769e3b 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -292,7 +292,7 @@ void vRunCommand(struct work_struct *work) switch (pDevice->eCommandState) { - case WLAN_CMD_SCAN_START: + case WLAN_CMD_SCAN_START: pDevice->byReAssocCount = 0; if (pDevice->bRadioOff == true) { @@ -392,7 +392,7 @@ void vRunCommand(struct work_struct *work) break; - case WLAN_CMD_SCAN_END: + case WLAN_CMD_SCAN_END: // Set Baseband's sensitivity back. if (pDevice->byBBType != pDevice->byScanBBType) { @@ -428,7 +428,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_DISASSOCIATE_START: + case WLAN_CMD_DISASSOCIATE_START: pDevice->byReAssocCount = 0; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { @@ -467,7 +467,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_SSID_START: + case WLAN_CMD_SSID_START: pDevice->byReAssocCount = 0; if (pDevice->bRadioOff == true) { @@ -593,7 +593,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_AUTHENTICATE_WAIT: + case WLAN_AUTHENTICATE_WAIT: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); if (pMgmt->eCurrState == WMAC_STATE_AUTH) { pDevice->byLinkWaitCount = 0; @@ -622,7 +622,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_ASSOCIATE_WAIT: + case WLAN_ASSOCIATE_WAIT: if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); if (pDevice->ePSMode != WMAC_POWER_CAM) { @@ -656,7 +656,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_AP_MODE_START: + case WLAN_CMD_AP_MODE_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { @@ -692,7 +692,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_TX_PSPACKET_START: + case WLAN_CMD_TX_PSPACKET_START: // DTIM Multicast tx if (pMgmt->sNodeDBTable[0].bRxPSPoll) { while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { @@ -748,7 +748,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_RADIO_START: + case WLAN_CMD_RADIO_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n"); // if (pDevice->bRadioCmd == true) @@ -843,7 +843,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_CHANGE_BBSENSITIVITY_START: + case WLAN_CMD_CHANGE_BBSENSITIVITY_START: pDevice->bStopDataPkt = true; pDevice->byBBVGACurrent = pDevice->byBBVGANew; @@ -853,24 +853,24 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_TBTT_WAKEUP_START: + case WLAN_CMD_TBTT_WAKEUP_START: PSbIsNextTBTTWakeUp(pDevice); s_bCommandComplete(pDevice); break; - case WLAN_CMD_BECON_SEND_START: + case WLAN_CMD_BECON_SEND_START: bMgrPrepareBeaconToSend(pDevice, pMgmt); s_bCommandComplete(pDevice); break; - case WLAN_CMD_SETPOWER_START: + case WLAN_CMD_SETPOWER_START: RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel); s_bCommandComplete(pDevice); break; - case WLAN_CMD_CHANGE_ANTENNA_START: + case WLAN_CMD_CHANGE_ANTENNA_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change from Antenna%d to", (int)pDevice->dwRxAntennaSel); if (pDevice->dwRxAntennaSel == 0) { pDevice->dwRxAntennaSel = 1; @@ -888,12 +888,12 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_REMOVE_ALLKEY_START: + case WLAN_CMD_REMOVE_ALLKEY_START: KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); s_bCommandComplete(pDevice); break; - case WLAN_CMD_MAC_DISPOWERSAVING_START: + case WLAN_CMD_MAC_DISPOWERSAVING_START: ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); if ((byData & PSCTL_PS) != 0) { // disable power saving hw function @@ -908,7 +908,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_11H_CHSW_START: + case WLAN_CMD_11H_CHSW_START: CARDbSetMediaChannel(pDevice, pDevice->byNewChannel); pDevice->bChannelSwitch = false; pMgmt->uCurrChannel = pDevice->byNewChannel; @@ -916,7 +916,7 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - default: + default: s_bCommandComplete(pDevice); break; } //switch @@ -946,7 +946,7 @@ static int s_bCommandComplete(struct vnt_private *pDevice) pDevice->cbFreeCmdQueue++; pDevice->bCmdRunning = true; switch (pDevice->eCommand) { - case WLAN_CMD_BSSID_SCAN: + case WLAN_CMD_BSSID_SCAN: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); pDevice->eCommandState = WLAN_CMD_SCAN_START; pMgmt->uScanChannel = 0; @@ -963,7 +963,7 @@ static int s_bCommandComplete(struct vnt_private *pDevice) } */ break; - case WLAN_CMD_SSID: + case WLAN_CMD_SSID: pDevice->eCommandState = WLAN_CMD_SSID_START; if (pSSID->len > WLAN_SSID_MAXLEN) pSSID->len = WLAN_SSID_MAXLEN; @@ -971,52 +971,52 @@ static int s_bCommandComplete(struct vnt_private *pDevice) memcpy(pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SSID_START\n"); break; - case WLAN_CMD_DISASSOCIATE: + case WLAN_CMD_DISASSOCIATE: pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START; break; - case WLAN_CMD_RX_PSPOLL: + case WLAN_CMD_RX_PSPOLL: pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START; break; - case WLAN_CMD_RUN_AP: + case WLAN_CMD_RUN_AP: pDevice->eCommandState = WLAN_CMD_AP_MODE_START; break; - case WLAN_CMD_RADIO: + case WLAN_CMD_RADIO: pDevice->eCommandState = WLAN_CMD_RADIO_START; pDevice->bRadioCmd = bRadioCmd; break; - case WLAN_CMD_CHANGE_BBSENSITIVITY: + case WLAN_CMD_CHANGE_BBSENSITIVITY: pDevice->eCommandState = WLAN_CMD_CHANGE_BBSENSITIVITY_START; break; - case WLAN_CMD_TBTT_WAKEUP: + case WLAN_CMD_TBTT_WAKEUP: pDevice->eCommandState = WLAN_CMD_TBTT_WAKEUP_START; break; - case WLAN_CMD_BECON_SEND: + case WLAN_CMD_BECON_SEND: pDevice->eCommandState = WLAN_CMD_BECON_SEND_START; break; - case WLAN_CMD_SETPOWER: + case WLAN_CMD_SETPOWER: pDevice->eCommandState = WLAN_CMD_SETPOWER_START; break; - case WLAN_CMD_CHANGE_ANTENNA: + case WLAN_CMD_CHANGE_ANTENNA: pDevice->eCommandState = WLAN_CMD_CHANGE_ANTENNA_START; break; - case WLAN_CMD_REMOVE_ALLKEY: + case WLAN_CMD_REMOVE_ALLKEY: pDevice->eCommandState = WLAN_CMD_REMOVE_ALLKEY_START; break; - case WLAN_CMD_MAC_DISPOWERSAVING: + case WLAN_CMD_MAC_DISPOWERSAVING: pDevice->eCommandState = WLAN_CMD_MAC_DISPOWERSAVING_START; break; - case WLAN_CMD_11H_CHSW: + case WLAN_CMD_11H_CHSW: pDevice->eCommandState = WLAN_CMD_11H_CHSW_START; break; - default: + default: break; } @@ -1037,31 +1037,31 @@ int bScheduleCommand(struct vnt_private *pDevice, memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); if (pbyItem0 != NULL) { switch (eCommand) { - case WLAN_CMD_BSSID_SCAN: + case WLAN_CMD_BSSID_SCAN: pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false; memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); break; - case WLAN_CMD_SSID: + case WLAN_CMD_SSID: memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); break; - case WLAN_CMD_DISASSOCIATE: + case WLAN_CMD_DISASSOCIATE: pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0); break; /* - case WLAN_CMD_DEAUTH: + case WLAN_CMD_DEAUTH: pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((u16 *)pbyItem0); break; */ - case WLAN_CMD_RADIO: + case WLAN_CMD_RADIO: pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0); break; - default: + default: break; } } -- cgit v1.2.3 From cab086d37a8e024717fcd1d666999a05e0430588 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:35 +0530 Subject: staging: vt6656: indented all if-else statement blocks indented all if-else statement blocks to remove checkpatch warnings and errors like indent code wherever possible and no spaces at the start of line Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 1274 ++++++++++++++++++++--------------------- 1 file changed, 633 insertions(+), 641 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index c07737769e3b..a53a15a60b4e 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -99,21 +99,21 @@ static void vAdHocBeaconStop(struct vnt_private *pDevice) * (3.2) AdHoc channel is in A mode */ bStop = false; - if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && - (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { - if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) && - (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { - bStop = true; - } - if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G) - bStop = true; - } - - if (bStop) { - //PMESG(("STOP_BEACON: IBSSChannel = %u, ScanChannel = %u\n", - // pMgmt->uIBSSChannel, pMgmt->uScanChannel)); - MACvRegBitsOff(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); - } + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { + if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) && + (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { + bStop = true; + } + if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G) + bStop = true; + } + + if (bStop) { + //PMESG(("STOP_BEACON: IBSSChannel = %u, ScanChannel = %u\n", + // pMgmt->uIBSSChannel, pMgmt->uScanChannel)); + MACvRegBitsOff(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); + } } /* vAdHocBeaconStop */ @@ -140,11 +140,11 @@ static void vAdHocBeaconRestart(struct vnt_private *pDevice) * (1) STA is in AdHoc mode * (2) VT3253 is programmed as automatic Beacon Transmitting */ - if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && - (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { - //PMESG(("RESTART_BEACON\n")); - MACvRegBitsOn(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); - } + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { + //PMESG(("RESTART_BEACON\n")); + MACvRegBitsOn(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); + } } @@ -194,15 +194,15 @@ static void s_vProbeChannel(struct vnt_private *pDevice) (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG ); - if (pTxPacket != NULL) { - for (ii = 0; ii < 1; ii++) { - if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail..\n"); - } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending..\n"); - } - } - } + if (pTxPacket != NULL) { + for (ii = 0; ii < 1; ii++) { + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail..\n"); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending..\n"); + } + } + } } @@ -248,11 +248,11 @@ static struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); // Copy the extension rate set - if (pDevice->byBBType == BB_TYPE_11G) { - sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); - sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; - memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); - } + if (pDevice->byBBType == BB_TYPE_11G) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } pTxPacket->cbMPDULen = sFrame.len; pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; @@ -283,10 +283,10 @@ void vRunCommand(struct work_struct *work) if (pDevice->Flags & fMP_DISCONNECTED) return; - if (pDevice->dwDiagRefCount != 0) - return; - if (pDevice->bCmdRunning != true) - return; + if (pDevice->dwDiagRefCount != 0) + return; + if (pDevice->bCmdRunning != true) + return; spin_lock_irq(&pDevice->lock); @@ -295,126 +295,123 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_SCAN_START: pDevice->byReAssocCount = 0; - if (pDevice->bRadioOff == true) { - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } - - if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } + if (pDevice->bRadioOff == true) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; - if (pMgmt->uScanChannel == 0) - pMgmt->uScanChannel = pDevice->byMinChannel; - if (pMgmt->uScanChannel > pDevice->byMaxChannel) { - pDevice->eCommandState = WLAN_CMD_SCAN_END; - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - - } else { - if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d\n", pMgmt->uScanChannel); + if (pMgmt->uScanChannel == 0) + pMgmt->uScanChannel = pDevice->byMinChannel; + if (pMgmt->uScanChannel > pDevice->byMaxChannel) { + pDevice->eCommandState = WLAN_CMD_SCAN_END; + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } else { + if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d\n", pMgmt->uScanChannel); + pMgmt->uScanChannel++; + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + if (pMgmt->uScanChannel == pDevice->byMinChannel) { + // pMgmt->eScanType = WMAC_SCAN_ACTIVE; //mike mark + pMgmt->abyScanBSSID[0] = 0xFF; + pMgmt->abyScanBSSID[1] = 0xFF; + pMgmt->abyScanBSSID[2] = 0xFF; + pMgmt->abyScanBSSID[3] = 0xFF; + pMgmt->abyScanBSSID[4] = 0xFF; + pMgmt->abyScanBSSID[5] = 0xFF; + pItemSSID->byElementID = WLAN_EID_SSID; + // clear bssid list + /* BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass); */ + pMgmt->eScanState = WMAC_IS_SCANNING; + pDevice->byScanBBType = pDevice->byBBType; //lucas + pDevice->bStopDataPkt = true; + // Turn off RCR_BSSID filter every time + MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode &= ~RCR_BSSID; + } + //lucas + vAdHocBeaconStop(pDevice); + if ((pDevice->byBBType != BB_TYPE_11A) && + (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { + pDevice->byBBType = BB_TYPE_11A; + CARDvSetBSSMode(pDevice); + } else if ((pDevice->byBBType == BB_TYPE_11A) && + (pMgmt->uScanChannel <= CB_MAX_CHANNEL_24G)) { + pDevice->byBBType = BB_TYPE_11G; + CARDvSetBSSMode(pDevice); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning.... channel: [%d]\n", pMgmt->uScanChannel); + // Set channel + CARDbSetMediaChannel(pDevice, pMgmt->uScanChannel); + // Set Baseband to be more sensitive. + + if (pDevice->bUpdateBBVGA) { + BBvSetShortSlotTime(pDevice); + BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); + BBvUpdatePreEDThreshold(pDevice, true); + } pMgmt->uScanChannel++; - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } - if (pMgmt->uScanChannel == pDevice->byMinChannel) { - // pMgmt->eScanType = WMAC_SCAN_ACTIVE; //mike mark - pMgmt->abyScanBSSID[0] = 0xFF; - pMgmt->abyScanBSSID[1] = 0xFF; - pMgmt->abyScanBSSID[2] = 0xFF; - pMgmt->abyScanBSSID[3] = 0xFF; - pMgmt->abyScanBSSID[4] = 0xFF; - pMgmt->abyScanBSSID[5] = 0xFF; - pItemSSID->byElementID = WLAN_EID_SSID; - // clear bssid list - /* BSSvClearBSSList((void *) pDevice, - pDevice->bLinkPass); */ - pMgmt->eScanState = WMAC_IS_SCANNING; - pDevice->byScanBBType = pDevice->byBBType; //lucas - pDevice->bStopDataPkt = true; - // Turn off RCR_BSSID filter every time - MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_BSSID); - pDevice->byRxMode &= ~RCR_BSSID; - - } - //lucas - vAdHocBeaconStop(pDevice); - if ((pDevice->byBBType != BB_TYPE_11A) && (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { - pDevice->byBBType = BB_TYPE_11A; - CARDvSetBSSMode(pDevice); - } else if ((pDevice->byBBType == BB_TYPE_11A) && (pMgmt->uScanChannel <= CB_MAX_CHANNEL_24G)) { - pDevice->byBBType = BB_TYPE_11G; - CARDvSetBSSMode(pDevice); - } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning.... channel: [%d]\n", pMgmt->uScanChannel); - // Set channel - CARDbSetMediaChannel(pDevice, pMgmt->uScanChannel); - // Set Baseband to be more sensitive. - - if (pDevice->bUpdateBBVGA) { - BBvSetShortSlotTime(pDevice); - BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); - BBvUpdatePreEDThreshold(pDevice, true); - } - pMgmt->uScanChannel++; - - while (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel) && - pMgmt->uScanChannel <= pDevice->byMaxChannel){ - pMgmt->uScanChannel++; - } - - if (pMgmt->uScanChannel > pDevice->byMaxChannel) { - // Set Baseband to be not sensitive and rescan - pDevice->eCommandState = WLAN_CMD_SCAN_END; - - } - if ((pMgmt->b11hEnable == false) || - (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) { - s_vProbeChannel(pDevice); - spin_unlock_irq(&pDevice->lock); - vCommandTimerWait((void *) pDevice, 100); - return; - } else { - spin_unlock_irq(&pDevice->lock); - vCommandTimerWait((void *) pDevice, WCMD_PASSIVE_SCAN_TIME); - return; - } - - } + + while (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel) && + pMgmt->uScanChannel <= pDevice->byMaxChannel){ + pMgmt->uScanChannel++; + } + + if (pMgmt->uScanChannel > pDevice->byMaxChannel) { + // Set Baseband to be not sensitive and rescan + pDevice->eCommandState = WLAN_CMD_SCAN_END; + } + if ((pMgmt->b11hEnable == false) || + (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) { + s_vProbeChannel(pDevice); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, 100); + return; + } else { + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, WCMD_PASSIVE_SCAN_TIME); + return; + } + } break; case WLAN_CMD_SCAN_END: // Set Baseband's sensitivity back. - if (pDevice->byBBType != pDevice->byScanBBType) { - pDevice->byBBType = pDevice->byScanBBType; - CARDvSetBSSMode(pDevice); - } + if (pDevice->byBBType != pDevice->byScanBBType) { + pDevice->byBBType = pDevice->byScanBBType; + CARDvSetBSSMode(pDevice); + } - if (pDevice->bUpdateBBVGA) { - BBvSetShortSlotTime(pDevice); - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); - BBvUpdatePreEDThreshold(pDevice, false); - } + if (pDevice->bUpdateBBVGA) { + BBvSetShortSlotTime(pDevice); + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + BBvUpdatePreEDThreshold(pDevice, false); + } // Set channel back vAdHocBeaconRestart(pDevice); // Set channel back CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); // Set Filter - if (pMgmt->bCurrBSSIDFilterOn) { - MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); - pDevice->byRxMode |= RCR_BSSID; - } + if (pMgmt->bCurrBSSIDFilterOn) { + MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode |= RCR_BSSID; + } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel); pMgmt->uScanChannel = 0; pMgmt->eScanState = WMAC_NO_SCANNING; @@ -430,37 +427,36 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_DISASSOCIATE_START: pDevice->byReAssocCount = 0; - if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && - (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } else { - - pDevice->bwextstep0 = false; - pDevice->bwextstep1 = false; - pDevice->bwextstep2 = false; - pDevice->bwextstep3 = false; - pDevice->bWPASuppWextEnabled = false; - pDevice->fWPA_Authened = false; - - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send Disassociation Packet..\n"); - // reason = 8 : disassoc because sta has left - vMgrDisassocBeginSta((void *) pDevice, - pMgmt, - pMgmt->abyCurrBSSID, - (8), - &Status); - pDevice->bLinkPass = false; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); - // unlock command busy - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; - pItemSSID->len = 0; - memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); - pMgmt->eCurrState = WMAC_STATE_IDLE; - pMgmt->sNodeDBTable[0].bActive = false; -// pDevice->bBeaconBufReady = false; - } + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } else { + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = false; + pDevice->fWPA_Authened = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send Disassociation Packet..\n"); + // reason = 8 : disassoc because sta has left + vMgrDisassocBeginSta((void *) pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + (8), + &Status); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); + // unlock command busy + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->sNodeDBTable[0].bActive = false; +// pDevice->bBeaconBufReady = false; + } netif_stop_queue(pDevice->dev); if (pDevice->bNeedRadioOFF == true) CARDbRadioPowerOff(pDevice); @@ -470,11 +466,11 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_SSID_START: pDevice->byReAssocCount = 0; - if (pDevice->bRadioOff == true) { - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } + if (pDevice->bRadioOff == true) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN); @@ -484,28 +480,27 @@ void vRunCommand(struct work_struct *work) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: desire ssid = %s\n", pItemSSID->abySSID); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID); - if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n", pItemSSID->len); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n", pItemSSIDCurr->len); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" desire ssid = %s\n", pItemSSID->abySSID); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" curr ssid = %s\n", pItemSSIDCurr->abySSID); - } - - if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || - ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { - - if (pItemSSID->len == pItemSSIDCurr->len) { - if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) { - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } - } - netif_stop_queue(pDevice->dev); - pDevice->bLinkPass = false; - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); - } + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n", pItemSSID->len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n", pItemSSIDCurr->len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" desire ssid = %s\n", pItemSSID->abySSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" curr ssid = %s\n", pItemSSIDCurr->abySSID); + } + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + if (pItemSSID->len == pItemSSIDCurr->len) { + if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + } + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); + } // set initial state pMgmt->eCurrState = WMAC_STATE_IDLE; pMgmt->eCurrMode = WMAC_MODE_STANDBY; @@ -513,145 +508,144 @@ void vRunCommand(struct work_struct *work) BSSvClearNodeDBTable(pDevice, 0); vMgrJoinBSSBegin((void *) pDevice, &Status); // if Infra mode - if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { - // Call mgr to begin the deauthentication - // reason = (3) because sta has left ESS - if (pMgmt->eCurrState >= WMAC_STATE_AUTH) { - vMgrDeAuthenBeginSta((void *)pDevice, - pMgmt, - pMgmt->abyCurrBSSID, - (3), - &Status); - } - // Call mgr to begin the authentication - vMgrAuthenBeginSta((void *) pDevice, pMgmt, &Status); - if (Status == CMD_STATUS_SUCCESS) { - pDevice->byLinkWaitCount = 0; - pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT; - vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT); - spin_unlock_irq(&pDevice->lock); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n"); - return; - } - } - // if Adhoc mode - else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { - if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { - if (netif_queue_stopped(pDevice->dev)) - netif_wake_queue(pDevice->dev); - pDevice->bLinkPass = true; - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); - pMgmt->sNodeDBTable[0].bActive = true; - pMgmt->sNodeDBTable[0].uInActiveCount = 0; - } else { - // start own IBSS - DBG_PRT(MSG_LEVEL_DEBUG, - KERN_INFO "CreateOwn IBSS by CurrMode = IBSS_STA\n"); - vMgrCreateOwnIBSS((void *) pDevice, &Status); - if (Status != CMD_STATUS_SUCCESS) { - DBG_PRT(MSG_LEVEL_DEBUG, - KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); - } - BSSvAddMulticastNode(pDevice); - } - s_bClearBSSID_SCAN(pDevice); - } - // if SSID not found - else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) { - if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA || - pMgmt->eConfigMode == WMAC_CONFIG_AUTO) { - // start own IBSS - DBG_PRT(MSG_LEVEL_DEBUG, - KERN_INFO "CreateOwn IBSS by CurrMode = STANDBY\n"); - vMgrCreateOwnIBSS((void *) pDevice, &Status); - if (Status != CMD_STATUS_SUCCESS) { - DBG_PRT(MSG_LEVEL_DEBUG, - KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); - } - BSSvAddMulticastNode(pDevice); - s_bClearBSSID_SCAN(pDevice); + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { + // Call mgr to begin the deauthentication + // reason = (3) because sta has left ESS + if (pMgmt->eCurrState >= WMAC_STATE_AUTH) { + vMgrDeAuthenBeginSta((void *)pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + (3), + &Status); + } + // Call mgr to begin the authentication + vMgrAuthenBeginSta((void *) pDevice, pMgmt, &Status); + if (Status == CMD_STATUS_SUCCESS) { + pDevice->byLinkWaitCount = 0; + pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT; + vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT); + spin_unlock_irq(&pDevice->lock); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n"); + return; + } + } + // if Adhoc mode + else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { + if (netif_queue_stopped(pDevice->dev)) + netif_wake_queue(pDevice->dev); + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); + pMgmt->sNodeDBTable[0].bActive = true; + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + } else { + // start own IBSS + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "CreateOwn IBSS by CurrMode = IBSS_STA\n"); + vMgrCreateOwnIBSS((void *) pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); + } + BSSvAddMulticastNode(pDevice); + } + s_bClearBSSID_SCAN(pDevice); + } + // if SSID not found + else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) { + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA || + pMgmt->eConfigMode == WMAC_CONFIG_AUTO) { + // start own IBSS + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "CreateOwn IBSS by CurrMode = STANDBY\n"); + vMgrCreateOwnIBSS((void *) pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); + } + BSSvAddMulticastNode(pDevice); + s_bClearBSSID_SCAN(pDevice); /* - pDevice->bLinkPass = true; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); - if (netif_queue_stopped(pDevice->dev)){ - netif_wake_queue(pDevice->dev); - } - s_bClearBSSID_SCAN(pDevice); + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + s_bClearBSSID_SCAN(pDevice); */ - } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n"); - // if(pDevice->bWPASuppWextEnabled == true) - { - union iwreq_data wrqu; - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n"); - wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); - } - } - } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n"); + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + } s_bCommandComplete(pDevice); break; case WLAN_AUTHENTICATE_WAIT: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); - if (pMgmt->eCurrState == WMAC_STATE_AUTH) { - pDevice->byLinkWaitCount = 0; - // Call mgr to begin the association - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_AUTH\n"); - vMgrAssocBeginSta((void *) pDevice, pMgmt, &Status); - if (Status == CMD_STATUS_SUCCESS) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState = WLAN_ASSOCIATE_WAIT\n"); - pDevice->byLinkWaitCount = 0; - pDevice->eCommandState = WLAN_ASSOCIATE_WAIT; - vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT); - spin_unlock_irq(&pDevice->lock); - return; - } - } else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { - printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); - } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay! - pDevice->byLinkWaitCount++; - printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); - spin_unlock_irq(&pDevice->lock); - vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT/2); - return; - } + if (pMgmt->eCurrState == WMAC_STATE_AUTH) { + pDevice->byLinkWaitCount = 0; + // Call mgr to begin the association + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_AUTH\n"); + vMgrAssocBeginSta((void *) pDevice, pMgmt, &Status); + if (Status == CMD_STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState = WLAN_ASSOCIATE_WAIT\n"); + pDevice->byLinkWaitCount = 0; + pDevice->eCommandState = WLAN_ASSOCIATE_WAIT; + vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT); + spin_unlock_irq(&pDevice->lock); + return; + } + } else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { + printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); + } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay! + pDevice->byLinkWaitCount++; + printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT/2); + return; + } pDevice->byLinkWaitCount = 0; s_bCommandComplete(pDevice); break; case WLAN_ASSOCIATE_WAIT: - if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); - if (pDevice->ePSMode != WMAC_POWER_CAM) { - PSvEnablePowerSaving((void *) pDevice, - pMgmt->wListenInterval); - } + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); + if (pDevice->ePSMode != WMAC_POWER_CAM) { + PSvEnablePowerSaving((void *) pDevice, + pMgmt->wListenInterval); + } /* - if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) { - KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); - } + if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) { + KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); + } */ - pDevice->byLinkWaitCount = 0; - pDevice->byReAssocCount = 0; - pDevice->bLinkPass = true; - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); - s_bClearBSSID_SCAN(pDevice); - - if (netif_queue_stopped(pDevice->dev)) - netif_wake_queue(pDevice->dev); - - } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { - printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); - } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay! - pDevice->byLinkWaitCount++; - printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); - spin_unlock_irq(&pDevice->lock); - vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT/2); - return; - } + pDevice->byLinkWaitCount = 0; + pDevice->byReAssocCount = 0; + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); + s_bClearBSSID_SCAN(pDevice); + + if (netif_queue_stopped(pDevice->dev)) + netif_wake_queue(pDevice->dev); + + } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { + printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); + } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay! + pDevice->byLinkWaitCount++; + printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT/2); + return; + } s_bCommandComplete(pDevice); break; @@ -659,91 +653,91 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_AP_MODE_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); - if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { - cancel_delayed_work_sync(&pDevice->second_callback_work); - pMgmt->eCurrState = WMAC_STATE_IDLE; - pMgmt->eCurrMode = WMAC_MODE_STANDBY; - pDevice->bLinkPass = false; - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); - if (pDevice->bEnableHostWEP == true) - BSSvClearNodeDBTable(pDevice, 1); - else - BSSvClearNodeDBTable(pDevice, 0); - pDevice->uAssocCount = 0; - pMgmt->eCurrState = WMAC_STATE_IDLE; - pDevice->bFixRate = false; - - vMgrCreateOwnIBSS((void *) pDevice, &Status); - if (Status != CMD_STATUS_SUCCESS) { - DBG_PRT(MSG_LEVEL_DEBUG, - KERN_INFO "vMgrCreateOwnIBSS fail!\n"); - } - // always turn off unicast bit - MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_UNICAST); - pDevice->byRxMode &= ~RCR_UNICAST; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode); - BSSvAddMulticastNode(pDevice); - if (netif_queue_stopped(pDevice->dev)) - netif_wake_queue(pDevice->dev); - pDevice->bLinkPass = true; - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); - schedule_delayed_work(&pDevice->second_callback_work, HZ); - } + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + cancel_delayed_work_sync(&pDevice->second_callback_work); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); + if (pDevice->bEnableHostWEP == true) + BSSvClearNodeDBTable(pDevice, 1); + else + BSSvClearNodeDBTable(pDevice, 0); + pDevice->uAssocCount = 0; + pMgmt->eCurrState = WMAC_STATE_IDLE; + pDevice->bFixRate = false; + + vMgrCreateOwnIBSS((void *) pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "vMgrCreateOwnIBSS fail!\n"); + } + // always turn off unicast bit + MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_UNICAST); + pDevice->byRxMode &= ~RCR_UNICAST; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode); + BSSvAddMulticastNode(pDevice); + if (netif_queue_stopped(pDevice->dev)) + netif_wake_queue(pDevice->dev); + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); + schedule_delayed_work(&pDevice->second_callback_work, HZ); + } s_bCommandComplete(pDevice); break; case WLAN_CMD_TX_PSPACKET_START: // DTIM Multicast tx - if (pMgmt->sNodeDBTable[0].bRxPSPoll) { - while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { - if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) { - pMgmt->abyPSTxMap[0] &= ~byMask[0]; - pDevice->bMoreData = false; - } else { - pDevice->bMoreData = true; - } - - if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail\n"); - - pMgmt->sNodeDBTable[0].wEnQueueCnt--; - } - } + if (pMgmt->sNodeDBTable[0].bRxPSPoll) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { + if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) { + pMgmt->abyPSTxMap[0] &= ~byMask[0]; + pDevice->bMoreData = false; + } else { + pDevice->bMoreData = true; + } + + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail\n"); + + pMgmt->sNodeDBTable[0].wEnQueueCnt--; + } + } // PS nodes tx - for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { - if (pMgmt->sNodeDBTable[ii].bActive && - pMgmt->sNodeDBTable[ii].bRxPSPoll) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n", - ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); - while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) { - if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { - // clear tx map - pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= - ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; - pDevice->bMoreData = false; - } else { - pDevice->bMoreData = true; - } - - if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail\n"); - - pMgmt->sNodeDBTable[ii].wEnQueueCnt--; - // check if sta ps enable, wait next pspoll - // if sta ps disable, send all pending buffers. - if (pMgmt->sNodeDBTable[ii].bPSEnable) - break; - } - if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { - // clear tx map - pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= - ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear\n", ii); - } - pMgmt->sNodeDBTable[ii].bRxPSPoll = false; - } - } + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive && + pMgmt->sNodeDBTable[ii].bRxPSPoll) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n", + ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) { + if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { + // clear tx map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= + ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; + pDevice->bMoreData = false; + } else { + pDevice->bMoreData = true; + } + + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail\n"); + + pMgmt->sNodeDBTable[ii].wEnQueueCnt--; + // check if sta ps enable, wait next pspoll + // if sta ps disable, send all pending buffers. + if (pMgmt->sNodeDBTable[ii].bPSEnable) + break; + } + if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { + // clear tx map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= + ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear\n", ii); + } + pMgmt->sNodeDBTable[ii].bRxPSPoll = false; + } + } s_bCommandComplete(pDevice); break; @@ -751,94 +745,93 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_RADIO_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n"); - // if (pDevice->bRadioCmd == true) - // CARDbRadioPowerOn(pDevice); - // else - // CARDbRadioPowerOff(pDevice); - - { - int ntStatus = STATUS_SUCCESS; - u8 byTmp; - - ntStatus = CONTROLnsRequestIn(pDevice, - MESSAGE_TYPE_READ, - MAC_REG_GPIOCTL1, - MESSAGE_REQUEST_MACREG, - 1, - &byTmp); - - if (ntStatus != STATUS_SUCCESS) { - s_bCommandComplete(pDevice); - spin_unlock_irq(&pDevice->lock); - return; - } - if ((byTmp & GPIO3_DATA) == 0) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n"); - // Old commands are useless. - // empty command Q - pDevice->cbFreeCmdQueue = CMD_Q_SIZE; - pDevice->uCmdDequeueIdx = 0; - pDevice->uCmdEnqueueIdx = 0; - //0415pDevice->bCmdRunning = false; - pDevice->bCmdClear = true; - pDevice->bStopTx0Pkt = false; - pDevice->bStopDataPkt = true; - - pDevice->byKeyIndex = 0; - pDevice->bTransmitKey = false; - spin_unlock_irq(&pDevice->lock); - KeyvInitTable(pDevice, &pDevice->sKey); - spin_lock_irq(&pDevice->lock); - pMgmt->byCSSPK = KEY_CTL_NONE; - pMgmt->byCSSGK = KEY_CTL_NONE; - - if (pDevice->bLinkPass == true) { - // reason = 8 : disassoc because sta has left - vMgrDisassocBeginSta((void *) pDevice, - pMgmt, - pMgmt->abyCurrBSSID, - (8), - &Status); - pDevice->bLinkPass = false; - // unlock command busy - pMgmt->eCurrState = WMAC_STATE_IDLE; - pMgmt->sNodeDBTable[0].bActive = false; - // if(pDevice->bWPASuppWextEnabled == true) - { - union iwreq_data wrqu; - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); - wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); - } - } - pDevice->bwextstep0 = false; - pDevice->bwextstep1 = false; - pDevice->bwextstep2 = false; - pDevice->bwextstep3 = false; - pDevice->bWPASuppWextEnabled = false; - //clear current SSID - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; - pItemSSID->len = 0; - memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); - //clear desired SSID - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; - pItemSSID->len = 0; - memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); - - netif_stop_queue(pDevice->dev); - CARDbRadioPowerOff(pDevice); - MACvRegBitsOn(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_OFF); - pDevice->bHWRadioOff = true; - } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_ON........................\n"); - pDevice->bHWRadioOff = false; - CARDbRadioPowerOn(pDevice); - MACvRegBitsOff(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); - ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_ON); - } - } +// if (pDevice->bRadioCmd == true) +// CARDbRadioPowerOn(pDevice); +// else +// CARDbRadioPowerOff(pDevice); + { + int ntStatus = STATUS_SUCCESS; + u8 byTmp; + + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + MAC_REG_GPIOCTL1, + MESSAGE_REQUEST_MACREG, + 1, + &byTmp); + + if (ntStatus != STATUS_SUCCESS) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + if ((byTmp & GPIO3_DATA) == 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n"); + // Old commands are useless. + // empty command Q + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + //0415pDevice->bCmdRunning = false; + pDevice->bCmdClear = true; + pDevice->bStopTx0Pkt = false; + pDevice->bStopDataPkt = true; + + pDevice->byKeyIndex = 0; + pDevice->bTransmitKey = false; + spin_unlock_irq(&pDevice->lock); + KeyvInitTable(pDevice, &pDevice->sKey); + spin_lock_irq(&pDevice->lock); + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_NONE; + + if (pDevice->bLinkPass == true) { + // reason = 8 : disassoc because sta has left + vMgrDisassocBeginSta((void *) pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + (8), + &Status); + pDevice->bLinkPass = false; + // unlock command busy + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->sNodeDBTable[0].bActive = false; + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = false; + //clear current SSID + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + //clear desired SSID + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + + netif_stop_queue(pDevice->dev); + CARDbRadioPowerOff(pDevice); + MACvRegBitsOn(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_OFF); + pDevice->bHWRadioOff = true; + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_ON........................\n"); + pDevice->bHWRadioOff = false; + CARDbRadioPowerOn(pDevice); + MACvRegBitsOff(pDevice, MAC_REG_GPIOCTL1, GPIO3_INTMD); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_ON); + } + } s_bCommandComplete(pDevice); break; @@ -872,19 +865,19 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_CHANGE_ANTENNA_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change from Antenna%d to", (int)pDevice->dwRxAntennaSel); - if (pDevice->dwRxAntennaSel == 0) { - pDevice->dwRxAntennaSel = 1; - if (pDevice->bTxRxAntInv == true) - BBvSetAntennaMode(pDevice, ANT_RXA); - else - BBvSetAntennaMode(pDevice, ANT_RXB); - } else { - pDevice->dwRxAntennaSel = 0; - if (pDevice->bTxRxAntInv == true) - BBvSetAntennaMode(pDevice, ANT_RXB); - else - BBvSetAntennaMode(pDevice, ANT_RXA); - } + if (pDevice->dwRxAntennaSel == 0) { + pDevice->dwRxAntennaSel = 1; + if (pDevice->bTxRxAntInv == true) + BBvSetAntennaMode(pDevice, ANT_RXA); + else + BBvSetAntennaMode(pDevice, ANT_RXB); + } else { + pDevice->dwRxAntennaSel = 0; + if (pDevice->bTxRxAntInv == true) + BBvSetAntennaMode(pDevice, ANT_RXB); + else + BBvSetAntennaMode(pDevice, ANT_RXA); + } s_bCommandComplete(pDevice); break; @@ -895,16 +888,16 @@ void vRunCommand(struct work_struct *work) case WLAN_CMD_MAC_DISPOWERSAVING_START: ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); - if ((byData & PSCTL_PS) != 0) { - // disable power saving hw function - CONTROLnsRequestOut(pDevice, - MESSAGE_TYPE_DISABLE_PS, - 0, - 0, - 0, - NULL - ); - } + if ((byData & PSCTL_PS) != 0) { + // disable power saving hw function + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_DISABLE_PS, + 0, + 0, + 0, + NULL + ); + } s_bCommandComplete(pDevice); break; @@ -933,95 +926,94 @@ static int s_bCommandComplete(struct vnt_private *pDevice) int bForceSCAN = true; pDevice->eCommandState = WLAN_CMD_IDLE; - if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) { - //Command Queue Empty - pDevice->bCmdRunning = false; - return true; - } else { - pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd; - pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID; - bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd; - bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN; - ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE); - pDevice->cbFreeCmdQueue++; - pDevice->bCmdRunning = true; - switch (pDevice->eCommand) { - case WLAN_CMD_BSSID_SCAN: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); - pDevice->eCommandState = WLAN_CMD_SCAN_START; - pMgmt->uScanChannel = 0; - if (pSSID->len != 0) - memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - else - memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) { + //Command Queue Empty + pDevice->bCmdRunning = false; + return true; + } else { + pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd; + pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID; + bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd; + bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN; + ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE); + pDevice->cbFreeCmdQueue++; + pDevice->bCmdRunning = true; + switch (pDevice->eCommand) { + case WLAN_CMD_BSSID_SCAN: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); + pDevice->eCommandState = WLAN_CMD_SCAN_START; + pMgmt->uScanChannel = 0; + if (pSSID->len != 0) + memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + else + memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); /* - if ((bForceSCAN == false) && (pDevice->bLinkPass == true)) { - if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) && - ( !memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, pSSID->len))) { - pDevice->eCommandState = WLAN_CMD_IDLE; - } - } + if ((bForceSCAN == false) && (pDevice->bLinkPass == true)) { + if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) && + ( !memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, pSSID->len))) { + pDevice->eCommandState = WLAN_CMD_IDLE; + } + } */ - break; - case WLAN_CMD_SSID: - pDevice->eCommandState = WLAN_CMD_SSID_START; - if (pSSID->len > WLAN_SSID_MAXLEN) - pSSID->len = WLAN_SSID_MAXLEN; - if (pSSID->len != 0) - memcpy(pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SSID_START\n"); - break; - case WLAN_CMD_DISASSOCIATE: - pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START; - break; - case WLAN_CMD_RX_PSPOLL: - pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START; - break; - case WLAN_CMD_RUN_AP: - pDevice->eCommandState = WLAN_CMD_AP_MODE_START; - break; - case WLAN_CMD_RADIO: - pDevice->eCommandState = WLAN_CMD_RADIO_START; - pDevice->bRadioCmd = bRadioCmd; - break; - case WLAN_CMD_CHANGE_BBSENSITIVITY: - pDevice->eCommandState = WLAN_CMD_CHANGE_BBSENSITIVITY_START; - break; - - case WLAN_CMD_TBTT_WAKEUP: - pDevice->eCommandState = WLAN_CMD_TBTT_WAKEUP_START; - break; - - case WLAN_CMD_BECON_SEND: - pDevice->eCommandState = WLAN_CMD_BECON_SEND_START; - break; - - case WLAN_CMD_SETPOWER: - pDevice->eCommandState = WLAN_CMD_SETPOWER_START; - break; - - case WLAN_CMD_CHANGE_ANTENNA: - pDevice->eCommandState = WLAN_CMD_CHANGE_ANTENNA_START; - break; - - case WLAN_CMD_REMOVE_ALLKEY: - pDevice->eCommandState = WLAN_CMD_REMOVE_ALLKEY_START; - break; - - case WLAN_CMD_MAC_DISPOWERSAVING: - pDevice->eCommandState = WLAN_CMD_MAC_DISPOWERSAVING_START; - break; - - case WLAN_CMD_11H_CHSW: - pDevice->eCommandState = WLAN_CMD_11H_CHSW_START; - break; - - default: - break; - - } - vCommandTimerWait(pDevice, 0); - } + break; + case WLAN_CMD_SSID: + pDevice->eCommandState = WLAN_CMD_SSID_START; + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + if (pSSID->len != 0) + memcpy(pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SSID_START\n"); + break; + case WLAN_CMD_DISASSOCIATE: + pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START; + break; + case WLAN_CMD_RX_PSPOLL: + pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START; + break; + case WLAN_CMD_RUN_AP: + pDevice->eCommandState = WLAN_CMD_AP_MODE_START; + break; + case WLAN_CMD_RADIO: + pDevice->eCommandState = WLAN_CMD_RADIO_START; + pDevice->bRadioCmd = bRadioCmd; + break; + case WLAN_CMD_CHANGE_BBSENSITIVITY: + pDevice->eCommandState = WLAN_CMD_CHANGE_BBSENSITIVITY_START; + break; + + case WLAN_CMD_TBTT_WAKEUP: + pDevice->eCommandState = WLAN_CMD_TBTT_WAKEUP_START; + break; + + case WLAN_CMD_BECON_SEND: + pDevice->eCommandState = WLAN_CMD_BECON_SEND_START; + break; + + case WLAN_CMD_SETPOWER: + pDevice->eCommandState = WLAN_CMD_SETPOWER_START; + break; + + case WLAN_CMD_CHANGE_ANTENNA: + pDevice->eCommandState = WLAN_CMD_CHANGE_ANTENNA_START; + break; + + case WLAN_CMD_REMOVE_ALLKEY: + pDevice->eCommandState = WLAN_CMD_REMOVE_ALLKEY_START; + break; + + case WLAN_CMD_MAC_DISPOWERSAVING: + pDevice->eCommandState = WLAN_CMD_MAC_DISPOWERSAVING_START; + break; + + case WLAN_CMD_11H_CHSW: + pDevice->eCommandState = WLAN_CMD_11H_CHSW_START; + break; + + default: + break; + } + vCommandTimerWait(pDevice, 0); + } return true; } @@ -1030,47 +1022,47 @@ int bScheduleCommand(struct vnt_private *pDevice, CMD_CODE eCommand, u8 *pbyItem0) { - if (pDevice->cbFreeCmdQueue == 0) - return (false); - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand; - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true; - memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - if (pbyItem0 != NULL) { - switch (eCommand) { - case WLAN_CMD_BSSID_SCAN: - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false; - memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, - pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - break; - - case WLAN_CMD_SSID: - memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, - pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - break; - - case WLAN_CMD_DISASSOCIATE: - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0); - break; + if (pDevice->cbFreeCmdQueue == 0) + return (false); + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand; + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true; + memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + if (pbyItem0 != NULL) { + switch (eCommand) { + case WLAN_CMD_BSSID_SCAN: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false; + memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, + pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + break; + + case WLAN_CMD_SSID: + memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, + pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + break; + + case WLAN_CMD_DISASSOCIATE: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0); + break; /* - case WLAN_CMD_DEAUTH: - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((u16 *)pbyItem0); - break; + case WLAN_CMD_DEAUTH: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((u16 *)pbyItem0); + break; */ - case WLAN_CMD_RADIO: - pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0); - break; + case WLAN_CMD_RADIO: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0); + break; - default: - break; - } - } + default: + break; + } + } ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); pDevice->cbFreeCmdQueue--; - if (pDevice->bCmdRunning == false) - s_bCommandComplete(pDevice); + if (pDevice->bCmdRunning == false) + s_bCommandComplete(pDevice); return (true); @@ -1095,15 +1087,15 @@ static int s_bClearBSSID_SCAN(struct vnt_private *pDevice) unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx; unsigned int ii; - if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) { - for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) { - if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN) - pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE; - ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE); - if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx) - break; - } - } + if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) { + for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) { + if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN) + pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE; + ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE); + if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx) + break; + } + } return true; } -- cgit v1.2.3 From 97d59f87433d1a4eb6eafcd8b1896e239bf34569 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:36 +0530 Subject: staging: vt6656: indented the code under all function blocks indented the code under all functions to remove unnecessary space at start of a line and indent code wherver possible errors thrown from checkpatch script Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 302 +++++++++++++++++++++--------------------- 1 file changed, 151 insertions(+), 151 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index a53a15a60b4e..fa6234bbca11 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -87,18 +87,18 @@ static void vAdHocBeaconStop(struct vnt_private *pDevice) struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; int bStop; - /* - * temporarily stop Beacon packet for AdHoc Server - * if all of the following coditions are met: - * (1) STA is in AdHoc mode - * (2) VT3253 is programmed as automatic Beacon Transmitting - * (3) One of the following conditions is met - * (3.1) AdHoc channel is in B/G band and the - * current scan channel is in A band - * or - * (3.2) AdHoc channel is in A mode - */ - bStop = false; + /* + * temporarily stop Beacon packet for AdHoc Server + * if all of the following coditions are met: + * (1) STA is in AdHoc mode + * (2) VT3253 is programmed as automatic Beacon Transmitting + * (3) One of the following conditions is met + * (3.1) AdHoc channel is in B/G band and the + * current scan channel is in A band + * or + * (3.2) AdHoc channel is in A mode + */ + bStop = false; if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState >= WMAC_STATE_STARTED)) { if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) && @@ -183,16 +183,16 @@ static void s_vProbeChannel(struct vnt_private *pDevice) else pbyRate = &abyCurrSuppRatesG[0]; - // build an assocreq frame and send it - pTxPacket = s_MgrMakeProbeRequest - ( - pDevice, - pMgmt, - pMgmt->abyScanBSSID, - (PWLAN_IE_SSID)pMgmt->abyScanSSID, - (PWLAN_IE_SUPP_RATES)pbyRate, - (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG - ); + // build an assocreq frame and send it + pTxPacket = s_MgrMakeProbeRequest + ( + pDevice, + pMgmt, + pMgmt->abyScanBSSID, + (PWLAN_IE_SSID)pMgmt->abyScanSSID, + (PWLAN_IE_SUPP_RATES)pbyRate, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG + ); if (pTxPacket != NULL) { for (ii = 0; ii < 1; ii++) { @@ -229,34 +229,34 @@ static struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, + WLAN_PROBEREQ_FR_MAXLEN); pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + sizeof(struct vnt_tx_mgmt)); - sFrame.pBuf = (u8 *)pTxPacket->p80211Header; - sFrame.len = WLAN_PROBEREQ_FR_MAXLEN; - vMgrEncodeProbeRequest(&sFrame); - sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( - ( - WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | - WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ) - )); - memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN); - memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); - memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN); - // Copy the SSID, pSSID->len=0 indicate broadcast SSID - sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); - sFrame.len += pSSID->len + WLAN_IEHDR_LEN; - memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); - sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); - sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; - memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); - // Copy the extension rate set + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_PROBEREQ_FR_MAXLEN; + vMgrEncodeProbeRequest(&sFrame); + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ) + )); + memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN); + memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN); + // Copy the SSID, pSSID->len=0 indicate broadcast SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + // Copy the extension rate set if (pDevice->byBBType == BB_TYPE_11G) { sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); } - pTxPacket->cbMPDULen = sFrame.len; - pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; - return pTxPacket; + return pTxPacket; } static void @@ -288,11 +288,11 @@ void vRunCommand(struct work_struct *work) if (pDevice->bCmdRunning != true) return; - spin_lock_irq(&pDevice->lock); + spin_lock_irq(&pDevice->lock); - switch (pDevice->eCommandState) { + switch (pDevice->eCommandState) { - case WLAN_CMD_SCAN_START: + case WLAN_CMD_SCAN_START: pDevice->byReAssocCount = 0; if (pDevice->bRadioOff == true) { @@ -307,7 +307,7 @@ void vRunCommand(struct work_struct *work) return; } - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; if (pMgmt->uScanChannel == 0) pMgmt->uScanChannel = pDevice->byMinChannel; @@ -387,11 +387,11 @@ void vRunCommand(struct work_struct *work) } } - break; + break; - case WLAN_CMD_SCAN_END: + case WLAN_CMD_SCAN_END: - // Set Baseband's sensitivity back. + // Set Baseband's sensitivity back. if (pDevice->byBBType != pDevice->byScanBBType) { pDevice->byBBType = pDevice->byScanBBType; CARDvSetBSSMode(pDevice); @@ -403,29 +403,29 @@ void vRunCommand(struct work_struct *work) BBvUpdatePreEDThreshold(pDevice, false); } - // Set channel back - vAdHocBeaconRestart(pDevice); - // Set channel back - CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); - // Set Filter + // Set channel back + vAdHocBeaconRestart(pDevice); + // Set channel back + CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); + // Set Filter if (pMgmt->bCurrBSSIDFilterOn) { MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); pDevice->byRxMode |= RCR_BSSID; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel); pMgmt->uScanChannel = 0; - pMgmt->eScanState = WMAC_NO_SCANNING; - pDevice->bStopDataPkt = false; + pMgmt->eScanState = WMAC_NO_SCANNING; + pDevice->bStopDataPkt = false; /*send scan event to wpa_Supplicant*/ PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n"); memset(&wrqu, 0, sizeof(wrqu)); wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL); - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_DISASSOCIATE_START: + case WLAN_CMD_DISASSOCIATE_START: pDevice->byReAssocCount = 0; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { @@ -457,13 +457,13 @@ void vRunCommand(struct work_struct *work) pMgmt->sNodeDBTable[0].bActive = false; // pDevice->bBeaconBufReady = false; } - netif_stop_queue(pDevice->dev); - if (pDevice->bNeedRadioOFF == true) - CARDbRadioPowerOff(pDevice); - s_bCommandComplete(pDevice); - break; + netif_stop_queue(pDevice->dev); + if (pDevice->bNeedRadioOFF == true) + CARDbRadioPowerOff(pDevice); + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_SSID_START: + case WLAN_CMD_SSID_START: pDevice->byReAssocCount = 0; if (pDevice->bRadioOff == true) { @@ -472,13 +472,13 @@ void vRunCommand(struct work_struct *work) return; } - memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID, - ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN); + memcpy(pMgmt->abyAdHocSSID, pMgmt->abyDesireSSID, + ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN); - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; - pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: desire ssid = %s\n", pItemSSID->abySSID); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: desire ssid = %s\n", pItemSSID->abySSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID); if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n"); @@ -501,13 +501,13 @@ void vRunCommand(struct work_struct *work) pDevice->bLinkPass = false; ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); } - // set initial state - pMgmt->eCurrState = WMAC_STATE_IDLE; - pMgmt->eCurrMode = WMAC_MODE_STANDBY; - PSvDisablePowerSaving((void *) pDevice); - BSSvClearNodeDBTable(pDevice, 0); - vMgrJoinBSSBegin((void *) pDevice, &Status); - // if Infra mode + // set initial state + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + PSvDisablePowerSaving((void *) pDevice); + BSSvClearNodeDBTable(pDevice, 0); + vMgrJoinBSSBegin((void *) pDevice, &Status); + // if Infra mode if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { // Call mgr to begin the deauthentication // reason = (3) because sta has left ESS @@ -584,11 +584,11 @@ void vRunCommand(struct work_struct *work) } } } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_AUTHENTICATE_WAIT: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); + case WLAN_AUTHENTICATE_WAIT: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); if (pMgmt->eCurrState == WMAC_STATE_AUTH) { pDevice->byLinkWaitCount = 0; // Call mgr to begin the association @@ -611,12 +611,12 @@ void vRunCommand(struct work_struct *work) vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT/2); return; } - pDevice->byLinkWaitCount = 0; + pDevice->byLinkWaitCount = 0; - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_ASSOCIATE_WAIT: + case WLAN_ASSOCIATE_WAIT: if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); if (pDevice->ePSMode != WMAC_POWER_CAM) { @@ -647,10 +647,10 @@ void vRunCommand(struct work_struct *work) return; } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_AP_MODE_START: + case WLAN_CMD_AP_MODE_START: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { @@ -686,8 +686,8 @@ void vRunCommand(struct work_struct *work) s_bCommandComplete(pDevice); break; - case WLAN_CMD_TX_PSPACKET_START: - // DTIM Multicast tx + case WLAN_CMD_TX_PSPACKET_START: + // DTIM Multicast tx if (pMgmt->sNodeDBTable[0].bRxPSPoll) { while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) { @@ -739,12 +739,12 @@ void vRunCommand(struct work_struct *work) } } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_RADIO_START: + case WLAN_CMD_RADIO_START: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n"); // if (pDevice->bRadioCmd == true) // CARDbRadioPowerOn(pDevice); // else @@ -833,38 +833,38 @@ void vRunCommand(struct work_struct *work) } } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_CHANGE_BBSENSITIVITY_START: + case WLAN_CMD_CHANGE_BBSENSITIVITY_START: - pDevice->bStopDataPkt = true; - pDevice->byBBVGACurrent = pDevice->byBBVGANew; - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change sensitivity pDevice->byBBVGACurrent = %x\n", pDevice->byBBVGACurrent); - pDevice->bStopDataPkt = false; - s_bCommandComplete(pDevice); - break; + pDevice->bStopDataPkt = true; + pDevice->byBBVGACurrent = pDevice->byBBVGANew; + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change sensitivity pDevice->byBBVGACurrent = %x\n", pDevice->byBBVGACurrent); + pDevice->bStopDataPkt = false; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_TBTT_WAKEUP_START: - PSbIsNextTBTTWakeUp(pDevice); - s_bCommandComplete(pDevice); - break; + case WLAN_CMD_TBTT_WAKEUP_START: + PSbIsNextTBTTWakeUp(pDevice); + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_BECON_SEND_START: - bMgrPrepareBeaconToSend(pDevice, pMgmt); - s_bCommandComplete(pDevice); - break; + case WLAN_CMD_BECON_SEND_START: + bMgrPrepareBeaconToSend(pDevice, pMgmt); + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_SETPOWER_START: + case WLAN_CMD_SETPOWER_START: - RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel); + RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel); - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_CHANGE_ANTENNA_START: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change from Antenna%d to", (int)pDevice->dwRxAntennaSel); + case WLAN_CMD_CHANGE_ANTENNA_START: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change from Antenna%d to", (int)pDevice->dwRxAntennaSel); if (pDevice->dwRxAntennaSel == 0) { pDevice->dwRxAntennaSel = 1; if (pDevice->bTxRxAntInv == true) @@ -878,16 +878,16 @@ void vRunCommand(struct work_struct *work) else BBvSetAntennaMode(pDevice, ANT_RXA); } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_REMOVE_ALLKEY_START: - KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); - s_bCommandComplete(pDevice); - break; + case WLAN_CMD_REMOVE_ALLKEY_START: + KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_MAC_DISPOWERSAVING_START: - ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); + case WLAN_CMD_MAC_DISPOWERSAVING_START: + ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); if ((byData & PSCTL_PS) != 0) { // disable power saving hw function CONTROLnsRequestOut(pDevice, @@ -898,24 +898,24 @@ void vRunCommand(struct work_struct *work) NULL ); } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; - case WLAN_CMD_11H_CHSW_START: - CARDbSetMediaChannel(pDevice, pDevice->byNewChannel); - pDevice->bChannelSwitch = false; - pMgmt->uCurrChannel = pDevice->byNewChannel; - pDevice->bStopDataPkt = false; - s_bCommandComplete(pDevice); - break; + case WLAN_CMD_11H_CHSW_START: + CARDbSetMediaChannel(pDevice, pDevice->byNewChannel); + pDevice->bChannelSwitch = false; + pMgmt->uCurrChannel = pDevice->byNewChannel; + pDevice->bStopDataPkt = false; + s_bCommandComplete(pDevice); + break; - default: - s_bCommandComplete(pDevice); - break; - } //switch + default: + s_bCommandComplete(pDevice); + break; + } //switch - spin_unlock_irq(&pDevice->lock); - return; + spin_unlock_irq(&pDevice->lock); + return; } static int s_bCommandComplete(struct vnt_private *pDevice) @@ -925,7 +925,7 @@ static int s_bCommandComplete(struct vnt_private *pDevice) int bRadioCmd = false; int bForceSCAN = true; - pDevice->eCommandState = WLAN_CMD_IDLE; + pDevice->eCommandState = WLAN_CMD_IDLE; if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) { //Command Queue Empty pDevice->bCmdRunning = false; @@ -1015,7 +1015,7 @@ static int s_bCommandComplete(struct vnt_private *pDevice) vCommandTimerWait(pDevice, 0); } - return true; + return true; } int bScheduleCommand(struct vnt_private *pDevice, @@ -1058,13 +1058,13 @@ int bScheduleCommand(struct vnt_private *pDevice, } } - ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); - pDevice->cbFreeCmdQueue--; + ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); + pDevice->cbFreeCmdQueue--; if (pDevice->bCmdRunning == false) s_bCommandComplete(pDevice); - return (true); + return (true); } @@ -1096,7 +1096,7 @@ static int s_bClearBSSID_SCAN(struct vnt_private *pDevice) break; } } - return true; + return true; } //mike add:reset command timer -- cgit v1.2.3 From 820c9b12153d83319fdfbba2783ff1c07a1ad817 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:37 +0530 Subject: staging: vt6656: removed parenthesis from return statement parenthesis is not required in return statement since its not a fucntion, hence remove parentheses to comply with linux coding style Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index fa6234bbca11..246a266556a3 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -1023,7 +1023,7 @@ int bScheduleCommand(struct vnt_private *pDevice, { if (pDevice->cbFreeCmdQueue == 0) - return (false); + return false; pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand; pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true; memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); @@ -1064,7 +1064,7 @@ int bScheduleCommand(struct vnt_private *pDevice, if (pDevice->bCmdRunning == false) s_bCommandComplete(pDevice); - return (true); + return true; } -- cgit v1.2.3 From 2eca4ead3819b375ec169bb9f38eba82bd0e1dca Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:38 +0530 Subject: staging: vt6656: removed all whitespace errors removed all whitespace errors from the code like no space at the start of line and indent the code wherever possible Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 246a266556a3..640813e722a8 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -651,7 +651,7 @@ void vRunCommand(struct work_struct *work) break; case WLAN_CMD_AP_MODE_START: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { cancel_delayed_work_sync(&pDevice->second_callback_work); @@ -683,8 +683,8 @@ void vRunCommand(struct work_struct *work) ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_INTER); schedule_delayed_work(&pDevice->second_callback_work, HZ); } - s_bCommandComplete(pDevice); - break; + s_bCommandComplete(pDevice); + break; case WLAN_CMD_TX_PSPACKET_START: // DTIM Multicast tx @@ -704,7 +704,7 @@ void vRunCommand(struct work_struct *work) } } - // PS nodes tx + // PS nodes tx for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { if (pMgmt->sNodeDBTable[ii].bActive && pMgmt->sNodeDBTable[ii].bRxPSPoll) { -- cgit v1.2.3 From 819b920b7d66195c5e118e844239721b92ff8180 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:39 +0530 Subject: staging: vt6656: added space after coma operator in funtion call as per coding style a space is required after ',' operator in function calls, hence added the missing space after ',' operator in a function call Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 640813e722a8..9646d72dc9b2 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -448,7 +448,7 @@ void vRunCommand(struct work_struct *work) (8), &Status); pDevice->bLinkPass = false; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); // unlock command busy pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; pItemSSID->len = 0; -- cgit v1.2.3 From df6b85138faa297c643542047d09081877c24026 Mon Sep 17 00:00:00 2001 From: Nandini Hanumanthagowda Date: Tue, 12 Nov 2013 23:05:40 +0530 Subject: staging: vt6656: removed the trailing statement should be on next line error as per linux coding style trailing statments should not be there at the end of line, instead it should be placed in next line. hence removed that error by moving trailing statement to next line Signed-off-by: Nandini Hanumanthagowda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 9646d72dc9b2..2d05ccb58a7a 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -604,7 +604,8 @@ void vRunCommand(struct work_struct *work) } } else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); - } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay! + } else if (pDevice->byLinkWaitCount <= 4) { + //mike add:wait another 2 sec if authenticated_frame delay! pDevice->byLinkWaitCount++; printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); spin_unlock_irq(&pDevice->lock); @@ -639,7 +640,8 @@ void vRunCommand(struct work_struct *work) } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); - } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay! + } else if (pDevice->byLinkWaitCount <= 4) { + //mike add:wait another 2 sec if associated_frame delay! pDevice->byLinkWaitCount++; printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount); spin_unlock_irq(&pDevice->lock); -- cgit v1.2.3 From 28397dc9a6de41eafbd76a799883ace8f0570bd0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 18 Nov 2013 14:33:05 +0100 Subject: mfd: staging: Constify struct mfd_cell where possible As of commit 03e361b25ee8dfb1fd9b890072c23c4aae01c6c7 ("mfd: Stop setting refcounting pointers in original mfd_cell arrays"), the "cell" parameter of mfd_add_devices() is "const" again. Hence make all cell data passed to mfd_add_devices() const where possible. Signed-off-by: Geert Uytterhoeven Cc: Greg Kroah-Hartman Cc: devel@driverdev.osuosl.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 3066ee2e753b..27d74134f187 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -83,7 +83,7 @@ enum nvec_sleep_subcmds { static struct nvec_chip *nvec_power_handle; -static struct mfd_cell nvec_devices[] = { +static const struct mfd_cell nvec_devices[] = { { .name = "nvec-kbd", .id = 1, -- cgit v1.2.3 From e1970ee78c16adf39cb4d240f7745109909ff26a Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Sat, 16 Nov 2013 16:17:55 +0200 Subject: Drivers: staging: ft1000-usb: ft1000_proc.c: fixed a few styling issues. Fixed a few styling issues, particularly: Lines 36,42: Inserted a space before the open paranthesis. Line 50: Removed space between function name and open parenthesis. Lines 56,57: Removed trailing whitespace. lines: 130, 133: Replaced spaces with tabs for identation. Signed-off-by: Aldo Iljazi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_proc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c index 5ead942be680..2575d0d6bff3 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c @@ -33,13 +33,13 @@ #define seq_putx(m, message, size, var) \ seq_printf(m, message); \ - for(i = 0; i < (size - 1); i++) \ + for (i = 0; i < (size - 1); i++) \ seq_printf(m, "%02x:", var[i]); \ seq_printf(m, "%02x\n", var[i]) #define seq_putd(m, message, size, var) \ seq_printf(m, message); \ - for(i = 0; i < (size - 1); i++) \ + for (i = 0; i < (size - 1); i++) \ seq_printf(m, "%d.", var[i]); \ seq_printf(m, "%d\n", var[i]) @@ -47,14 +47,14 @@ #define FTNET_PROC init_net.proc_net -int ft1000_read_dpram16 (struct ft1000_usb *ft1000dev, u16 indx, +int ft1000_read_dpram16(struct ft1000_usb *ft1000dev, u16 indx, u8 *buffer, u8 highlow); static int ft1000ReadProc(struct seq_file *m, void *v) { - static const char *status[] = { - "Idle (Disconnect)", + static const char *status[] = { + "Idle (Disconnect)", "Searching", "Active (Connected)", "Waiting for L2", @@ -127,10 +127,10 @@ static int ft1000ReadProc(struct seq_file *m, void *v) } seq_printf(m, "Connection Time: %02ld:%02ld:%02ld\n", - ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60)); + ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60)); seq_printf(m, "Connection Time[s]: %ld\n", delta); seq_printf(m, "Asic ID: %s\n", - (info->AsicID) == ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC"); + (info->AsicID) == ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC"); seq_putx(m, "SKU: ", SKUSZ, info->Sku); seq_putx(m, "EUI64: ", EUISZ, info->eui64); seq_putd(m, "DSP version number: ", DSPVERSZ, info->DspVer); -- cgit v1.2.3 From 9702c686081240bff1f05150c78335152d37ac8d Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Wed, 20 Nov 2013 09:59:41 +0200 Subject: ath10k: add phyerr/dfs handling Handle phyerr, dfs event, radar_report and fft_report. Add also debugfs dfs_simulate_radar and dfs_stats files. Use ath dfs pattern detector. Signed-off-by: Janusz Dziedzic Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 13 ++ drivers/net/wireless/ath/ath10k/debug.c | 90 ++++++++++++ drivers/net/wireless/ath/ath10k/debug.h | 6 + drivers/net/wireless/ath/ath10k/mac.c | 24 ++++ drivers/net/wireless/ath/ath10k/wmi.c | 244 +++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.h | 85 +++++++++++ 6 files changed, 461 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index be35df2902c4..afbc7449b137 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -30,6 +30,7 @@ #include "wmi.h" #include "../ath.h" #include "../regd.h" +#include "../dfs_pattern_detector.h" #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) @@ -192,6 +193,14 @@ struct ath10k_target_stats { }; +struct ath10k_dfs_stats { + u32 phy_errors; + u32 pulses_total; + u32 pulses_detected; + u32 pulses_discarded; + u32 radar_detected; +}; + #define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */ struct ath10k_peer { @@ -261,6 +270,8 @@ struct ath10k_debug { unsigned long htt_stats_mask; struct delayed_work htt_stats_dwork; + struct ath10k_dfs_stats dfs_stats; + struct ath_dfs_pool_stats dfs_pool_stats; }; enum ath10k_state { @@ -428,6 +439,8 @@ struct ath10k { u32 survey_last_cycle_count; struct survey_info survey[ATH10K_NUM_CHANS]; + struct dfs_pattern_detector *dfs_detector; + #ifdef CONFIG_ATH10K_DEBUGFS struct ath10k_debug debug; #endif diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 760ff2289e3c..13705d41795e 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -639,6 +639,86 @@ void ath10k_debug_stop(struct ath10k *ar) cancel_delayed_work(&ar->debug.htt_stats_dwork); } +static ssize_t ath10k_write_simulate_radar(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + + ieee80211_radar_detected(ar->hw); + + return count; +} + +static const struct file_operations fops_simulate_radar = { + .write = ath10k_write_simulate_radar, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +#define ATH10K_DFS_STAT(s, p) (\ + len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \ + ar->debug.dfs_stats.p)) + +#define ATH10K_DFS_POOL_STAT(s, p) (\ + len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \ + ar->debug.dfs_pool_stats.p)) + +static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + int retval = 0, len = 0; + const int size = 8000; + struct ath10k *ar = file->private_data; + char *buf; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + if (!ar->dfs_detector) { + len += scnprintf(buf + len, size - len, "DFS not enabled\n"); + goto exit; + } + + ar->debug.dfs_pool_stats = + ar->dfs_detector->get_stats(ar->dfs_detector); + + len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n"); + + ATH10K_DFS_STAT("reported phy errors", phy_errors); + ATH10K_DFS_STAT("pulse events reported", pulses_total); + ATH10K_DFS_STAT("DFS pulses detected", pulses_detected); + ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded); + ATH10K_DFS_STAT("Radars detected", radar_detected); + + len += scnprintf(buf + len, size - len, "Global Pool statistics:\n"); + ATH10K_DFS_POOL_STAT("Pool references", pool_reference); + ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated); + ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error); + ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used); + ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated); + ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error); + ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used); + +exit: + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + +static const struct file_operations fops_dfs_stats = { + .read = ath10k_read_dfs_stats, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath10k_debug_create(struct ath10k *ar) { ar->debug.debugfs_phy = debugfs_create_dir("ath10k", @@ -667,6 +747,16 @@ int ath10k_debug_create(struct ath10k *ar) debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_htt_stats_mask); + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { + debugfs_create_file("dfs_simulate_radar", S_IWUSR, + ar->debug.debugfs_phy, ar, + &fops_simulate_radar); + + debugfs_create_file("dfs_stats", S_IRUSR, + ar->debug.debugfs_phy, ar, + &fops_dfs_stats); + } + return 0; } diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 46e640a6968d..92f1a5e1aa71 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -33,6 +33,7 @@ enum ath10k_debug_mask { ATH10K_DBG_MGMT = 0x00000100, ATH10K_DBG_DATA = 0x00000200, ATH10K_DBG_BMI = 0x00000400, + ATH10K_DBG_REGULATORY = 0x00000800, ATH10K_DBG_ANY = 0xffffffff, }; @@ -53,6 +54,8 @@ void ath10k_debug_read_service_map(struct ath10k *ar, void ath10k_debug_read_target_stats(struct ath10k *ar, struct wmi_stats_event *ev); +#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) + #else static inline int ath10k_debug_start(struct ath10k *ar) { @@ -82,6 +85,9 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar, struct wmi_stats_event *ev) { } + +#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) + #endif /* CONFIG_ATH10K_DEBUGFS */ #ifdef CONFIG_ATH10K_DEBUG diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index db819429134a..c95a3985209d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1442,9 +1442,20 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ath10k *ar = hw->priv; + bool result; ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory); + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) { + ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs region 0x%x\n", + request->dfs_region); + result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector, + request->dfs_region); + if (!result) + ath10k_warn("dfs region 0x%X not supported, will trigger radar for every pulse\n", + request->dfs_region); + } + mutex_lock(&ar->conf_mutex); if (ar->state == ATH10K_STATE_ON) ath10k_regd_update(ar); @@ -3531,6 +3542,16 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->netdev_features = NETIF_F_HW_CSUM; + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { + /* Init ath dfs pattern detector */ + ar->ath_common.debug_mask = ATH_DBG_DFS; + ar->dfs_detector = dfs_pattern_detector_init(&ar->ath_common, + NL80211_DFS_UNSET); + + if (!ar->dfs_detector) + ath10k_warn("dfs pattern detector init failed\n"); + } + ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, ath10k_reg_notifier); if (ret) { @@ -3566,6 +3587,9 @@ void ath10k_mac_unregister(struct ath10k *ar) { ieee80211_unregister_hw(ar->hw); + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) + ar->dfs_detector->exit(ar->dfs_detector); + kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index f79f17ce5dc6..f0bc94abbc74 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1381,9 +1381,251 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n"); } +static void ath10k_dfs_radar_report(struct ath10k *ar, + struct wmi_single_phyerr_rx_event *event, + struct phyerr_radar_report *rr, + u64 tsf) +{ + u32 reg0, reg1, tsf32l; + struct pulse_event pe; + u64 tsf64; + u8 rssi, width; + + reg0 = __le32_to_cpu(rr->reg0); + reg1 = __le32_to_cpu(rr->reg1); + + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi phyerr radar report chirp %d max_width %d agc_total_gain %d pulse_delta_diff %d\n", + MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP), + MS(reg0, RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH), + MS(reg0, RADAR_REPORT_REG0_AGC_TOTAL_GAIN), + MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_DIFF)); + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi phyerr radar report pulse_delta_pean %d pulse_sidx %d fft_valid %d agc_mb_gain %d subchan_mask %d\n", + MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_PEAK), + MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX), + MS(reg1, RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID), + MS(reg1, RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN), + MS(reg1, RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK)); + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi phyerr radar report pulse_tsf_offset 0x%X pulse_dur: %d\n", + MS(reg1, RADAR_REPORT_REG1_PULSE_TSF_OFFSET), + MS(reg1, RADAR_REPORT_REG1_PULSE_DUR)); + + if (!ar->dfs_detector) + return; + + /* report event to DFS pattern detector */ + tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp); + tsf64 = tsf & (~0xFFFFFFFFULL); + tsf64 |= tsf32l; + + width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); + rssi = event->hdr.rssi_combined; + + /* hardware store this as 8 bit signed value, + * set to zero if negative number + */ + if (rssi & 0x80) + rssi = 0; + + pe.ts = tsf64; + pe.freq = ar->hw->conf.chandef.chan->center_freq; + pe.width = width; + pe.rssi = rssi; + + ath10k_dbg(ATH10K_DBG_REGULATORY, + "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n", + pe.freq, pe.width, pe.rssi, pe.ts); + + ATH10K_DFS_STAT_INC(ar, pulses_detected); + + if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) { + ath10k_dbg(ATH10K_DBG_REGULATORY, + "dfs no pulse pattern detected, yet\n"); + return; + } + + ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs radar detected\n"); + ATH10K_DFS_STAT_INC(ar, radar_detected); + ieee80211_radar_detected(ar->hw); +} + +static int ath10k_dfs_fft_report(struct ath10k *ar, + struct wmi_single_phyerr_rx_event *event, + struct phyerr_fft_report *fftr, + u64 tsf) +{ + u32 reg0, reg1; + u8 rssi, peak_mag; + + reg0 = __le32_to_cpu(fftr->reg0); + reg1 = __le32_to_cpu(fftr->reg1); + rssi = event->hdr.rssi_combined; + + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n", + MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB), + MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB), + MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX), + MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX)); + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi phyerr fft report rel_pwr_db %d avgpwr_db %d peak_mag %d num_store_bin %d\n", + MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB), + MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB), + MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG), + MS(reg1, SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB)); + + peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG); + + /* false event detection */ + if (rssi == DFS_RSSI_POSSIBLY_FALSE && + peak_mag < 2 * DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE) { + ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs false pulse detected\n"); + ATH10K_DFS_STAT_INC(ar, pulses_discarded); + return -EINVAL; + } + + return 0; +} + +static void ath10k_wmi_event_dfs(struct ath10k *ar, + struct wmi_single_phyerr_rx_event *event, + u64 tsf) +{ + int buf_len, tlv_len, res, i = 0; + struct phyerr_tlv *tlv; + struct phyerr_radar_report *rr; + struct phyerr_fft_report *fftr; + u8 *tlv_buf; + + buf_len = __le32_to_cpu(event->hdr.buf_len); + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n", + event->hdr.phy_err_code, event->hdr.rssi_combined, + __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len); + + /* Skip event if DFS disabled */ + if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) + return; + + ATH10K_DFS_STAT_INC(ar, pulses_total); + + while (i < buf_len) { + if (i + sizeof(*tlv) > buf_len) { + ath10k_warn("too short buf for tlv header (%d)\n", i); + return; + } + + tlv = (struct phyerr_tlv *)&event->bufp[i]; + tlv_len = __le16_to_cpu(tlv->len); + tlv_buf = &event->bufp[i + sizeof(*tlv)]; + ath10k_dbg(ATH10K_DBG_REGULATORY, + "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", + tlv_len, tlv->tag, tlv->sig); + + switch (tlv->tag) { + case PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY: + if (i + sizeof(*tlv) + sizeof(*rr) > buf_len) { + ath10k_warn("too short radar pulse summary (%d)\n", + i); + return; + } + + rr = (struct phyerr_radar_report *)tlv_buf; + ath10k_dfs_radar_report(ar, event, rr, tsf); + break; + case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: + if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { + ath10k_warn("too short fft report (%d)\n", i); + return; + } + + fftr = (struct phyerr_fft_report *)tlv_buf; + res = ath10k_dfs_fft_report(ar, event, fftr, tsf); + if (res) + return; + break; + } + + i += sizeof(*tlv) + tlv_len; + } +} + +static void ath10k_wmi_event_spectral_scan(struct ath10k *ar, + struct wmi_single_phyerr_rx_event *event, + u64 tsf) +{ + ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n"); +} + static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) { - ath10k_dbg(ATH10K_DBG_WMI, "WMI_PHYERR_EVENTID\n"); + struct wmi_comb_phyerr_rx_event *comb_event; + struct wmi_single_phyerr_rx_event *event; + u32 count, i, buf_len, phy_err_code; + u64 tsf; + int left_len = skb->len; + + ATH10K_DFS_STAT_INC(ar, phy_errors); + + /* Check if combined event available */ + if (left_len < sizeof(*comb_event)) { + ath10k_warn("wmi phyerr combined event wrong len\n"); + return; + } + + left_len -= sizeof(*comb_event); + + /* Check number of included events */ + comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data; + count = __le32_to_cpu(comb_event->hdr.num_phyerr_events); + + tsf = __le32_to_cpu(comb_event->hdr.tsf_u32); + tsf <<= 32; + tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi event phyerr count %d tsf64 0x%llX\n", + count, tsf); + + event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp; + for (i = 0; i < count; i++) { + /* Check if we can read event header */ + if (left_len < sizeof(*event)) { + ath10k_warn("single event (%d) wrong head len\n", i); + return; + } + + left_len -= sizeof(*event); + + buf_len = __le32_to_cpu(event->hdr.buf_len); + phy_err_code = event->hdr.phy_err_code; + + if (left_len < buf_len) { + ath10k_warn("single event (%d) wrong buf len\n", i); + return; + } + + left_len -= buf_len; + + switch (phy_err_code) { + case PHY_ERROR_RADAR: + ath10k_wmi_event_dfs(ar, event, tsf); + break; + case PHY_ERROR_SPECTRAL_SCAN: + ath10k_wmi_event_spectral_scan(ar, event, tsf); + break; + case PHY_ERROR_FALSE_RADAR_EXT: + ath10k_wmi_event_dfs(ar, event, tsf); + ath10k_wmi_event_spectral_scan(ar, event, tsf); + break; + default: + break; + } + + event += sizeof(*event) + buf_len; + } } static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 8b824f9c2f1e..e71273e65c5d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1978,6 +1978,10 @@ struct wmi_mgmt_rx_event_v2 { #define WMI_RX_STATUS_ERR_MIC 0x10 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20 +#define PHY_ERROR_SPECTRAL_SCAN 0x26 +#define PHY_ERROR_FALSE_RADAR_EXT 0x24 +#define PHY_ERROR_RADAR 0x05 + struct wmi_single_phyerr_rx_hdr { /* TSF timestamp */ __le32 tsf_timestamp; @@ -2069,6 +2073,87 @@ struct wmi_comb_phyerr_rx_event { u8 bufp[0]; } __packed; +#define PHYERR_TLV_SIG 0xBB +#define PHYERR_TLV_TAG_SEARCH_FFT_REPORT 0xFB +#define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY 0xF8 + +struct phyerr_radar_report { + __le32 reg0; /* RADAR_REPORT_REG0_* */ + __le32 reg1; /* REDAR_REPORT_REG1_* */ +} __packed; + +#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_MASK 0x80000000 +#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_LSB 31 + +#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_MASK 0x40000000 +#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_LSB 30 + +#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_MASK 0x3FF00000 +#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_LSB 20 + +#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_MASK 0x000F0000 +#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_LSB 16 + +#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_MASK 0x0000FC00 +#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_LSB 10 + +#define RADAR_REPORT_REG0_PULSE_SIDX_MASK 0x000003FF +#define RADAR_REPORT_REG0_PULSE_SIDX_LSB 0 + +#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_MASK 0x80000000 +#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_LSB 31 + +#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_MASK 0x7F000000 +#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_LSB 24 + +#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_MASK 0x00FF0000 +#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_LSB 16 + +#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_MASK 0x0000FF00 +#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_LSB 8 + +#define RADAR_REPORT_REG1_PULSE_DUR_MASK 0x000000FF +#define RADAR_REPORT_REG1_PULSE_DUR_LSB 0 + +struct phyerr_fft_report { + __le32 reg0; /* SEARCH_FFT_REPORT_REG0_ * */ + __le32 reg1; /* SEARCH_FFT_REPORT_REG1_ * */ +} __packed; + +#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_MASK 0xFF800000 +#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_LSB 23 + +#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_MASK 0x007FC000 +#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_LSB 14 + +#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_MASK 0x00003000 +#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_LSB 12 + +#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_MASK 0x00000FFF +#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_LSB 0 + +#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_MASK 0xFC000000 +#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_LSB 26 + +#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_MASK 0x03FC0000 +#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_LSB 18 + +#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_MASK 0x0003FF00 +#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_LSB 8 + +#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK 0x000000FF +#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB 0 + + +struct phyerr_tlv { + __le16 len; + u8 tag; + u8 sig; +} __packed; + +#define DFS_RSSI_POSSIBLY_FALSE 50 +#define DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE 40 + struct wmi_mgmt_tx_hdr { __le32 vdev_id; struct wmi_mac_addr peer_macaddr; -- cgit v1.2.3 From e8a50f8ba44b6933b2a39b6a65528b9a4e8ba5f3 Mon Sep 17 00:00:00 2001 From: Marek Puzyniak Date: Wed, 20 Nov 2013 09:59:47 +0200 Subject: ath10k: introduce DFS implementation Configure interface combination for AP running on channels where radar detection is required. It allows only one type of interface - AP on DFS channel and limits number of AP interfaces to 8. Setup WMI channel flags accordingly to mac channel configuration. CAC based on additional monitor vdev is started if required for current channel. kvalo: dropped ATH10K_DFS_CERTIFIED config option as this the DFS still depends on few mac80211 and cfg80211 patches which are on mac80211-next.git right now. The config option will be added later once all dependencies are available. Signed-off-by: Marek Puzyniak Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 6 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 5 + drivers/net/wireless/ath/ath10k/mac.c | 160 +++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/wmi.c | 23 ++++- drivers/net/wireless/ath/ath10k/wmi.h | 1 + 5 files changed, 182 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index afbc7449b137..0b88d554f95f 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -310,6 +310,11 @@ enum ath10k_fw_features { ATH10K_FW_FEATURE_COUNT, }; +enum ath10k_dev_flags { + /* Indicates that ath10k device is during CAC phase of DFS */ + ATH10K_CAC_RUNNING, +}; + struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; @@ -403,6 +408,7 @@ struct ath10k { bool monitor_enabled; bool monitor_present; unsigned int filter_flags; + unsigned long dev_flags; struct wmi_pdev_set_wmm_params_arg wmm_params; struct completion install_key_done; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 0335218ad579..fcb534f2f28f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -945,6 +945,11 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, continue; } + if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { + ath10k_htt_rx_free_msdu_chain(msdu_head); + continue; + } + /* FIXME: we do not support chaining yet. * this needs investigation */ if (msdu_chaining) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c95a3985209d..b70a3b2f9f46 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -463,6 +463,10 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif) arg.ssid = arvif->u.ap.ssid; arg.ssid_len = arvif->u.ap.ssid_len; arg.hidden_ssid = arvif->u.ap.hidden_ssid; + + /* For now allow DFS for AP mode */ + arg.channel.chan_radar = + !!(channel->flags & IEEE80211_CHAN_RADAR); } else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { arg.ssid = arvif->vif->bss_conf.ssid; arg.ssid_len = arvif->vif->bss_conf.ssid_len; @@ -532,6 +536,8 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) /* TODO setup this dynamically, what in case we don't have any vifs? */ arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef); + arg.channel.chan_radar = + !!(channel->flags & IEEE80211_CHAN_RADAR); arg.channel.min_power = 0; arg.channel.max_power = channel->max_power * 2; @@ -666,6 +672,107 @@ static int ath10k_monitor_destroy(struct ath10k *ar) return ret; } +static int ath10k_start_cac(struct ath10k *ar) +{ + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); + + ret = ath10k_monitor_create(ar); + if (ret) { + clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); + return ret; + } + + ret = ath10k_monitor_start(ar, ar->monitor_vdev_id); + if (ret) { + clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); + ath10k_monitor_destroy(ar); + return ret; + } + + ath10k_dbg(ATH10K_DBG_MAC, "mac cac start monitor vdev %d\n", + ar->monitor_vdev_id); + + return 0; +} + +static int ath10k_stop_cac(struct ath10k *ar) +{ + lockdep_assert_held(&ar->conf_mutex); + + /* CAC is not running - do nothing */ + if (!test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) + return 0; + + ath10k_monitor_stop(ar); + ath10k_monitor_destroy(ar); + clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); + + ath10k_dbg(ATH10K_DBG_MAC, "mac cac finished\n"); + + return 0; +} + +static const char *ath10k_dfs_state(enum nl80211_dfs_state dfs_state) +{ + switch (dfs_state) { + case NL80211_DFS_USABLE: + return "USABLE"; + case NL80211_DFS_UNAVAILABLE: + return "UNAVAILABLE"; + case NL80211_DFS_AVAILABLE: + return "AVAILABLE"; + default: + WARN_ON(1); + return "bug"; + } +} + +static void ath10k_config_radar_detection(struct ath10k *ar) +{ + struct ieee80211_channel *chan = ar->hw->conf.chandef.chan; + bool radar = ar->hw->conf.radar_enabled; + bool chan_radar = !!(chan->flags & IEEE80211_CHAN_RADAR); + enum nl80211_dfs_state dfs_state = chan->dfs_state; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ath10k_dbg(ATH10K_DBG_MAC, + "mac radar config update: chan %dMHz radar %d chan radar %d chan state %s\n", + chan->center_freq, radar, chan_radar, + ath10k_dfs_state(dfs_state)); + + /* + * It's safe to call it even if CAC is not started. + * This call here guarantees changing channel, etc. will stop CAC. + */ + ath10k_stop_cac(ar); + + if (!radar) + return; + + if (!chan_radar) + return; + + if (dfs_state != NL80211_DFS_USABLE) + return; + + ret = ath10k_start_cac(ar); + if (ret) { + /* + * Not possible to start CAC on current channel so starting + * radiation is not allowed, make this channel DFS_UNAVAILABLE + * by indicating that radar was detected. + */ + ath10k_warn("failed to start CAC (%d)\n", ret); + ieee80211_radar_detected(ar->hw); + } +} + static void ath10k_control_beaconing(struct ath10k_vif *arvif, struct ieee80211_bss_conf *info) { @@ -1375,6 +1482,9 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->ht40plus = !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS); + ch->chan_radar = + !!(channel->flags & IEEE80211_CHAN_RADAR); + passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN; ch->passive = passive; @@ -1921,6 +2031,7 @@ void ath10k_halt(struct ath10k *ar) { lockdep_assert_held(&ar->conf_mutex); + ath10k_stop_cac(ar); del_timer_sync(&ar->scan.timeout); ath10k_offchan_tx_purge(ar); ath10k_mgmt_over_wmi_tx_purge(ar); @@ -2035,11 +2146,16 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&ar->conf_mutex); if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ath10k_dbg(ATH10K_DBG_MAC, "mac config channel %d mhz\n", - conf->chandef.chan->center_freq); + ath10k_dbg(ATH10K_DBG_MAC, + "mac config channel %d mhz flags 0x%x\n", + conf->chandef.chan->center_freq, + conf->chandef.chan->flags); + spin_lock_bh(&ar->data_lock); ar->rx_channel = conf->chandef.chan; spin_unlock_bh(&ar->data_lock); + + ath10k_config_radar_detection(ar); } if (changed & IEEE80211_CONF_CHANGE_POWER) { @@ -3308,12 +3424,36 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = { }, }; -static const struct ieee80211_iface_combination ath10k_if_comb = { - .limits = ath10k_if_limits, - .n_limits = ARRAY_SIZE(ath10k_if_limits), - .max_interfaces = 8, - .num_different_channels = 1, - .beacon_int_infra_match = true, +#ifdef CONFIG_ATH10K_DFS_CERTIFIED +static const struct ieee80211_iface_limit ath10k_if_dfs_limits[] = { + { + .max = 8, + .types = BIT(NL80211_IFTYPE_AP) + }, +}; +#endif + +static const struct ieee80211_iface_combination ath10k_if_comb[] = { + { + .limits = ath10k_if_limits, + .n_limits = ARRAY_SIZE(ath10k_if_limits), + .max_interfaces = 8, + .num_different_channels = 1, + .beacon_int_infra_match = true, + }, +#ifdef CONFIG_ATH10K_DFS_CERTIFIED + { + .limits = ath10k_if_dfs_limits, + .n_limits = ARRAY_SIZE(ath10k_if_dfs_limits), + .max_interfaces = 8, + .num_different_channels = 1, + .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), + } +#endif }; static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) @@ -3537,8 +3677,8 @@ int ath10k_mac_register(struct ath10k *ar) */ ar->hw->queues = 4; - ar->hw->wiphy->iface_combinations = &ath10k_if_comb; - ar->hw->wiphy->n_iface_combinations = 1; + ar->hw->wiphy->iface_combinations = ath10k_if_comb; + ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ath10k_if_comb); ar->hw->netdev_features = NETIF_F_HW_CSUM; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index f0bc94abbc74..aea81d944d86 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -907,6 +907,11 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ATH10K_DBG_MGMT, "event mgmt rx status %08x\n", rx_status); + if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) { + dev_kfree_skb(skb); + return 0; + } + if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) { dev_kfree_skb(skb); return 0; @@ -2302,6 +2307,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar, { struct wmi_set_channel_cmd *cmd; struct sk_buff *skb; + u32 ch_flags = 0; if (arg->passive) return -EINVAL; @@ -2310,10 +2316,14 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar, if (!skb) return -ENOMEM; + if (arg->chan_radar) + ch_flags |= WMI_CHAN_FLAG_DFS; + cmd = (struct wmi_set_channel_cmd *)skb->data; cmd->chan.mhz = __cpu_to_le32(arg->freq); cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq); cmd->chan.mode = arg->mode; + cmd->chan.flags |= __cpu_to_le32(ch_flags); cmd->chan.min_power = arg->min_power; cmd->chan.max_power = arg->max_power; cmd->chan.reg_power = arg->max_reg_power; @@ -2862,6 +2872,7 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, struct sk_buff *skb; const char *cmdname; u32 flags = 0; + u32 ch_flags = 0; if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) @@ -2888,6 +2899,8 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, flags |= WMI_VDEV_START_HIDDEN_SSID; if (arg->pmf_enabled) flags |= WMI_VDEV_START_PMF_ENABLED; + if (arg->channel.chan_radar) + ch_flags |= WMI_CHAN_FLAG_DFS; cmd = (struct wmi_vdev_start_request_cmd *)skb->data; cmd->vdev_id = __cpu_to_le32(arg->vdev_id); @@ -2909,6 +2922,7 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, __cpu_to_le32(arg->channel.band_center_freq1); cmd->chan.mode = arg->channel.mode; + cmd->chan.flags |= __cpu_to_le32(ch_flags); cmd->chan.min_power = arg->channel.min_power; cmd->chan.max_power = arg->channel.max_power; cmd->chan.reg_power = arg->channel.max_reg_power; @@ -2916,9 +2930,10 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, cmd->chan.antenna_max = arg->channel.max_antenna_gain; ath10k_dbg(ATH10K_DBG_WMI, - "wmi vdev %s id 0x%x freq %d, mode %d, ch_flags: 0x%0X," - "max_power: %d\n", cmdname, arg->vdev_id, arg->channel.freq, - arg->channel.mode, flags, arg->channel.max_power); + "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, " + "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id, + flags, arg->channel.freq, arg->channel.mode, + cmd->chan.flags, arg->channel.max_power); return ath10k_wmi_cmd_send(ar, skb, cmd_id); } @@ -3252,6 +3267,8 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, flags |= WMI_CHAN_FLAG_ALLOW_VHT; if (ch->ht40plus) flags |= WMI_CHAN_FLAG_HT40_PLUS; + if (ch->chan_radar) + flags |= WMI_CHAN_FLAG_DFS; ci->mhz = __cpu_to_le32(ch->freq); ci->band_center_freq1 = __cpu_to_le32(ch->freq); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index e71273e65c5d..0087d699b85b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -916,6 +916,7 @@ struct wmi_channel_arg { bool allow_ht; bool allow_vht; bool ht40plus; + bool chan_radar; /* note: power unit is 0.5 dBm */ u32 min_power; u32 max_power; -- cgit v1.2.3 From 7d9b40b4618a1f6fcd69db7056903d5cba835c2e Mon Sep 17 00:00:00 2001 From: Marek Puzyniak Date: Wed, 20 Nov 2013 10:00:28 +0200 Subject: ath10k: add debugfs file to control radar events blocking Sometimes for DFS testing is required to stay on current channel even after radar detected. This patch allows to enable/disable radar detected event to be passed to mac80211. By default radar detected event in not blocked. To block it: echo 1 > /sys/kernel/debug/ieee80211/phyX/ath10k/dfs_block_radar_events To unblock again: echo 0 > /sys/kernel/debug/ieee80211/phyX/ath10k/dfs_block_radar_events Inform about blocking radar detected event even when logs are disabled for throughput/performance reasons. Signed-off-by: Marek Puzyniak Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 4 ++++ drivers/net/wireless/ath/ath10k/wmi.c | 8 ++++++++ 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 0b88d554f95f..7721e3b2dd5f 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -409,6 +409,7 @@ struct ath10k { bool monitor_present; unsigned int filter_flags; unsigned long dev_flags; + u32 dfs_block_radar_events; struct wmi_pdev_set_wmm_params_arg wmm_params; struct completion install_key_done; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 13705d41795e..6bdfad3144af 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -752,6 +752,10 @@ int ath10k_debug_create(struct ath10k *ar) ar->debug.debugfs_phy, ar, &fops_simulate_radar); + debugfs_create_bool("dfs_block_radar_events", S_IWUSR, + ar->debug.debugfs_phy, + &ar->dfs_block_radar_events); + debugfs_create_file("dfs_stats", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_dfs_stats); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index aea81d944d86..c654137c0cf2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1453,6 +1453,14 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs radar detected\n"); ATH10K_DFS_STAT_INC(ar, radar_detected); + + /* Control radar events reporting in debugfs file + dfs_block_radar_events */ + if (ar->dfs_block_radar_events) { + ath10k_info("DFS Radar detected, but ignored as requested\n"); + return; + } + ieee80211_radar_detected(ar->hw); } -- cgit v1.2.3 From 95cbb6a8f1baa4118912a7d38cf4eca7583c868a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Nov 2013 10:00:35 +0200 Subject: ath10k: don't show MSI registration warnings Convert the MSI failure warnings to a debug message to make them less spammy. Also convert the irq mode printout to a single print to make it easier to show it only once. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 46c94ce58f97..a3cdd72f3148 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1851,6 +1851,7 @@ static void ath10k_pci_start_bmi(struct ath10k *ar) static int ath10k_pci_hif_power_up(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + const char *irq_mode; int ret; /* @@ -1916,6 +1917,16 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) } ath10k_pci_start_bmi(ar); + + if (ar_pci->num_msi_intrs > 1) + irq_mode = "MSI-X"; + else if (ar_pci->num_msi_intrs == 1) + irq_mode = "MSI"; + else + irq_mode = "legacy"; + + ath10k_info("pci irq %s\n", irq_mode); + return 0; err_irq: @@ -2161,7 +2172,8 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num) } } - ath10k_info("MSI-X interrupt handling (%d intrs)\n", num); + ath10k_dbg(ATH10K_DBG_BOOT, + "MSI-X interrupt handling (%d intrs)\n", num); return 0; } @@ -2182,7 +2194,7 @@ static int ath10k_pci_start_intr_msi(struct ath10k *ar) return ret; } - ath10k_info("MSI interrupt handling\n"); + ath10k_dbg(ATH10K_DBG_BOOT, "MSI interrupt handling\n"); return 0; } @@ -2218,7 +2230,7 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) PCIE_INTR_ENABLE_ADDRESS)); ath10k_pci_sleep(ar); - ath10k_info("legacy interrupt handling\n"); + ath10k_dbg(ATH10K_DBG_BOOT, "legacy interrupt handling\n"); return 0; } @@ -2248,7 +2260,8 @@ static int ath10k_pci_start_intr(struct ath10k *ar) if (ret == 0) goto exit; - ath10k_warn("MSI-X didn't succeed (%d), trying MSI\n", ret); + ath10k_dbg(ATH10K_DBG_BOOT, + "MSI-X didn't succeed (%d), trying MSI\n", ret); num = 1; } @@ -2257,8 +2270,9 @@ static int ath10k_pci_start_intr(struct ath10k *ar) if (ret == 0) goto exit; - ath10k_warn("MSI didn't succeed (%d), trying legacy INTR\n", - ret); + ath10k_dbg(ATH10K_DBG_BOOT, + "MSI didn't succeed (%d), trying legacy INTR\n", + ret); num = 0; } -- cgit v1.2.3 From c8c39afee20124b29b69a35b78e5081dccb97a9b Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Nov 2013 10:00:41 +0200 Subject: ath10k: make core boot messages more compact We can show the same amount of information in one line. And then it's easier to show this information only during first firmware boot (see next patch). For UART printouts there's already a message when they are enabled so no need to have a print when they are disabled, that's the default anyway. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 16 ++++++++++------ drivers/net/wireless/ath/ath10k/htt.c | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index be5b17e89902..e6c468b3ea56 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -597,10 +597,8 @@ static int ath10k_init_uart(struct ath10k *ar) return ret; } - if (!uart_print) { - ath10k_info("UART prints disabled\n"); + if (!uart_print) return 0; - } ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7); if (ret) { @@ -645,8 +643,8 @@ static int ath10k_init_hw_params(struct ath10k *ar) ar->hw_params = *hw_params; - ath10k_info("Hardware name %s version 0x%x\n", - ar->hw_params.name, ar->target_version); + ath10k_dbg(ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n", + ar->hw_params.name, ar->target_version); return 0; } @@ -807,7 +805,8 @@ int ath10k_core_start(struct ath10k *ar) if (status) goto err_htt_detach; - ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); + ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n", + ar->hw->wiphy->fw_version); status = ath10k_wmi_cmd_init(ar); if (status) { @@ -833,6 +832,11 @@ int ath10k_core_start(struct ath10k *ar) ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; INIT_LIST_HEAD(&ar->arvifs); + ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n", + ar->hw_params.name, ar->target_version, + ar->hw->wiphy->fw_version, ar->fw_api, + ar->htt.target_version_major, ar->htt.target_version_minor); + return 0; err_disconnect_htc: diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 5f7eeebc5432..69697af59ce0 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -104,8 +104,8 @@ err_htc_attach: static int ath10k_htt_verify_version(struct ath10k_htt *htt) { - ath10k_info("htt target version %d.%d\n", - htt->target_version_major, htt->target_version_minor); + ath10k_dbg(ATH10K_DBG_BOOT, "htt target version %d.%d\n", + htt->target_version_major, htt->target_version_minor); if (htt->target_version_major != 2 && htt->target_version_major != 3) { -- cgit v1.2.3 From 650b91fb09c035a99f2aaeb5de9bfc5215301816 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Nov 2013 10:00:49 +0200 Subject: ath10k: show hardware and firmware info prints only once This makes ath10k a lot less spammy by default. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 12 ++++++++---- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/pci.c | 4 +++- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index e6c468b3ea56..3b59af3bddf4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -832,10 +832,14 @@ int ath10k_core_start(struct ath10k *ar) ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; INIT_LIST_HEAD(&ar->arvifs); - ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n", - ar->hw_params.name, ar->target_version, - ar->hw->wiphy->fw_version, ar->fw_api, - ar->htt.target_version_major, ar->htt.target_version_minor); + if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) + ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n", + ar->hw_params.name, ar->target_version, + ar->hw->wiphy->fw_version, ar->fw_api, + ar->htt.target_version_major, + ar->htt.target_version_minor); + + __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags); return 0; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7721e3b2dd5f..79726e0fe2f0 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -313,6 +313,7 @@ enum ath10k_fw_features { enum ath10k_dev_flags { /* Indicates that ath10k device is during CAC phase of DFS */ ATH10K_CAC_RUNNING, + ATH10K_FLAG_FIRST_BOOT_DONE, }; struct ath10k { diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index a3cdd72f3148..2457c8ba9017 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "core.h" #include "debug.h" @@ -1925,7 +1926,8 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) else irq_mode = "legacy"; - ath10k_info("pci irq %s\n", irq_mode); + if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) + ath10k_info("pci irq %s\n", irq_mode); return 0; -- cgit v1.2.3 From 92b5c411ab3a3441ccbf2053bc4b00eca6cc8c96 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:28 +0100 Subject: HID: sony: Rename rumble_* functions/variables to state_* The commands used to modify the rumble motor state also modifies the LEDs at the same time. The functionality used to modify this state in the driver has to be shared between the rumble and LED part. It is therefore better to replace the "rumble" part of the names with "state". Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 098af2f84b8c..28b847ad5458 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -226,7 +226,7 @@ struct sony_sc { unsigned long quirks; #ifdef CONFIG_SONY_FF - struct work_struct rumble_worker; + struct work_struct state_worker; struct hid_device *hdev; __u8 left; __u8 right; @@ -622,9 +622,9 @@ static void buzz_remove(struct hid_device *hdev) } #ifdef CONFIG_SONY_FF -static void sony_rumble_worker(struct work_struct *work) +static void sony_state_worker(struct work_struct *work) { - struct sony_sc *sc = container_of(work, struct sony_sc, rumble_worker); + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); unsigned char buf[] = { 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, @@ -655,7 +655,7 @@ static int sony_play_effect(struct input_dev *dev, void *data, sc->left = effect->u.rumble.strong_magnitude / 256; sc->right = effect->u.rumble.weak_magnitude ? 1 : 0; - schedule_work(&sc->rumble_worker); + schedule_work(&sc->state_worker); return 0; } @@ -667,7 +667,7 @@ static int sony_init_ff(struct hid_device *hdev) struct sony_sc *sc = hid_get_drvdata(hdev); sc->hdev = hdev; - INIT_WORK(&sc->rumble_worker, sony_rumble_worker); + INIT_WORK(&sc->state_worker, sony_state_worker); input_set_capability(input_dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(input_dev, NULL, sony_play_effect); @@ -677,7 +677,7 @@ static void sony_destroy_ff(struct hid_device *hdev) { struct sony_sc *sc = hid_get_drvdata(hdev); - cancel_work_sync(&sc->rumble_worker); + cancel_work_sync(&sc->state_worker); } #else -- cgit v1.2.3 From f1c458caa11430d30b3beae72d8ec9dfdce9c3ac Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:29 +0100 Subject: HID: sony: Use BIT(x) macro to define quirks constants Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 28b847ad5458..067729290012 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -33,11 +33,11 @@ #include "hid-ids.h" -#define VAIO_RDESC_CONSTANT (1 << 0) -#define SIXAXIS_CONTROLLER_USB (1 << 1) -#define SIXAXIS_CONTROLLER_BT (1 << 2) -#define BUZZ_CONTROLLER (1 << 3) -#define PS3REMOTE (1 << 4) +#define VAIO_RDESC_CONSTANT BIT(0) +#define SIXAXIS_CONTROLLER_USB BIT(1) +#define SIXAXIS_CONTROLLER_BT BIT(2) +#define BUZZ_CONTROLLER BIT(3) +#define PS3REMOTE BIT(4) static const u8 sixaxis_rdesc_fixup[] = { 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, -- cgit v1.2.3 From c53825190ac58d44d6ade6c6e6c8ad22f77ff954 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:30 +0100 Subject: HID: sony: Rename buzz_* functions to sony_led_* More controllers managed by the hid-sony module have 4 LEDs. These can share most of the functionality provided by the buzz functions. Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 067729290012..cdb24192db96 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -466,7 +466,7 @@ static void buzz_set_leds(struct hid_device *hdev, int leds) hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } -static void buzz_led_set_brightness(struct led_classdev *led, +static void sony_led_set_brightness(struct led_classdev *led, enum led_brightness value) { struct device *dev = led->dev->parent; @@ -498,7 +498,7 @@ static void buzz_led_set_brightness(struct led_classdev *led, } } -static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) +static enum led_brightness sony_led_get_brightness(struct led_classdev *led) { struct device *dev = led->dev->parent; struct hid_device *hdev = container_of(dev, struct hid_device, dev); @@ -525,7 +525,7 @@ static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) return on ? LED_FULL : LED_OFF; } -static int buzz_init(struct hid_device *hdev) +static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; struct buzz_extra *buzz; @@ -567,8 +567,8 @@ static int buzz_init(struct hid_device *hdev) led->name = name; led->brightness = 0; led->max_brightness = 1; - led->brightness_get = buzz_led_get_brightness; - led->brightness_set = buzz_led_set_brightness; + led->brightness_get = sony_led_get_brightness; + led->brightness_set = sony_led_set_brightness; if (led_classdev_register(&hdev->dev, led)) { hid_err(hdev, "Failed to register LED %d\n", n); @@ -596,7 +596,7 @@ error_leds: return ret; } -static void buzz_remove(struct hid_device *hdev) +static void sony_leds_remove(struct hid_device *hdev) { struct sony_sc *drv_data; struct buzz_extra *buzz; @@ -733,7 +733,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ret = sixaxis_set_operational_bt(hdev); else if (sc->quirks & BUZZ_CONTROLLER) - ret = buzz_init(hdev); + ret = sony_leds_init(hdev); else ret = 0; @@ -755,7 +755,7 @@ static void sony_remove(struct hid_device *hdev) struct sony_sc *sc = hid_get_drvdata(hdev); if (sc->quirks & BUZZ_CONTROLLER) - buzz_remove(hdev); + sony_leds_remove(hdev); sony_destroy_ff(hdev); -- cgit v1.2.3 From 2251b85f3dfd7be140e2d6a1f9d1e78287367a4f Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:31 +0100 Subject: HID: sony: Move LED data to the main structure It is not necessary to keep the LED information in an extra struct which is only used by the Buzz device. It can also be used by other devices. Signed-off-by: Sven Eckelmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 58 +++++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index cdb24192db96..2f93aab11056 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -223,6 +223,7 @@ static const unsigned int buzz_keymap[] = { }; struct sony_sc { + struct led_classdev *leds[4]; unsigned long quirks; #ifdef CONFIG_SONY_FF @@ -232,12 +233,7 @@ struct sony_sc { __u8 right; #endif - void *extra; -}; - -struct buzz_extra { - int led_state; - struct led_classdev *leds[4]; + __u8 led_state; }; static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, @@ -472,26 +468,24 @@ static void sony_led_set_brightness(struct led_classdev *led, struct device *dev = led->dev->parent; struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct sony_sc *drv_data; - struct buzz_extra *buzz; int n; drv_data = hid_get_drvdata(hdev); - if (!drv_data || !drv_data->extra) { + if (!drv_data) { hid_err(hdev, "No device data\n"); return; } - buzz = drv_data->extra; for (n = 0; n < 4; n++) { - if (led == buzz->leds[n]) { - int on = !! (buzz->led_state & (1 << n)); + if (led == drv_data->leds[n]) { + int on = !!(drv_data->led_state & (1 << n)); if (value == LED_OFF && on) { - buzz->led_state &= ~(1 << n); - buzz_set_leds(hdev, buzz->led_state); + drv_data->led_state &= ~(1 << n); + buzz_set_leds(hdev, drv_data->led_state); } else if (value != LED_OFF && !on) { - buzz->led_state |= (1 << n); - buzz_set_leds(hdev, buzz->led_state); + drv_data->led_state |= (1 << n); + buzz_set_leds(hdev, drv_data->led_state); } break; } @@ -503,21 +497,19 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) struct device *dev = led->dev->parent; struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct sony_sc *drv_data; - struct buzz_extra *buzz; int n; int on = 0; drv_data = hid_get_drvdata(hdev); - if (!drv_data || !drv_data->extra) { + if (!drv_data) { hid_err(hdev, "No device data\n"); return LED_OFF; } - buzz = drv_data->extra; for (n = 0; n < 4; n++) { - if (led == buzz->leds[n]) { - on = !! (buzz->led_state & (1 << n)); + if (led == drv_data->leds[n]) { + on = !!(drv_data->led_state & (1 << n)); break; } } @@ -528,7 +520,6 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; - struct buzz_extra *buzz; int n, ret = 0; struct led_classdev *led; size_t name_sz; @@ -541,13 +532,6 @@ static int sony_leds_init(struct hid_device *hdev) if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) return -ENODEV; - buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); - if (!buzz) { - hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); - return -ENOMEM; - } - drv_data->extra = buzz; - /* Clear LEDs as we have no way of reading their initial state. This is * only relevant if the driver is loaded after somebody actively set the * LEDs to on */ @@ -576,49 +560,41 @@ static int sony_leds_init(struct hid_device *hdev) goto error_leds; } - buzz->leds[n] = led; + drv_data->leds[n] = led; } return ret; error_leds: for (n = 0; n < 4; n++) { - led = buzz->leds[n]; - buzz->leds[n] = NULL; + led = drv_data->leds[n]; + drv_data->leds[n] = NULL; if (!led) continue; led_classdev_unregister(led); kfree(led); } - kfree(drv_data->extra); - drv_data->extra = NULL; return ret; } static void sony_leds_remove(struct hid_device *hdev) { struct sony_sc *drv_data; - struct buzz_extra *buzz; struct led_classdev *led; int n; drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); - buzz = drv_data->extra; - for (n = 0; n < 4; n++) { - led = buzz->leds[n]; - buzz->leds[n] = NULL; + led = drv_data->leds[n]; + drv_data->leds[n] = NULL; if (!led) continue; led_classdev_unregister(led); kfree(led); } - - kfree(drv_data->extra); - drv_data->extra = NULL; } #ifdef CONFIG_SONY_FF -- cgit v1.2.3 From 0a286ef278529f2bc4f4bb27c4cf99c05999c818 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 19 Nov 2013 20:26:32 +0100 Subject: HID: sony: Add LED support for Sixaxis/Dualshock3 USB The PS3 Sixaxis controller has 4 LEDs which can be controlled using the same command as the rumble functionality. It seems not to be possible to only change the LED without modifying the rumble motor state. Thus both have to be stored on the host and retransmitted when either the LED or rumble state is changed. Third party controllers may not support to disable all LEDs at once. These controllers automatically switch to blinking of all LEDs when no LED is active anymore. Signed-off-by: Sven Eckelmann Tested-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 120 +++++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 2f93aab11056..b60bc38903db 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -39,6 +39,8 @@ #define BUZZ_CONTROLLER BIT(3) #define PS3REMOTE BIT(4) +#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER) + static const u8 sixaxis_rdesc_fixup[] = { 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, @@ -223,12 +225,12 @@ static const unsigned int buzz_keymap[] = { }; struct sony_sc { + struct hid_device *hdev; struct led_classdev *leds[4]; unsigned long quirks; + struct work_struct state_worker; #ifdef CONFIG_SONY_FF - struct work_struct state_worker; - struct hid_device *hdev; __u8 left; __u8 right; #endif @@ -462,6 +464,18 @@ static void buzz_set_leds(struct hid_device *hdev, int leds) hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } +static void sony_set_leds(struct hid_device *hdev, __u8 leds) +{ + struct sony_sc *drv_data = hid_get_drvdata(hdev); + + if (drv_data->quirks & BUZZ_CONTROLLER) { + buzz_set_leds(hdev, leds); + } else if (drv_data->quirks & SIXAXIS_CONTROLLER_USB) { + drv_data->led_state = leds; + schedule_work(&drv_data->state_worker); + } +} + static void sony_led_set_brightness(struct led_classdev *led, enum led_brightness value) { @@ -482,10 +496,10 @@ static void sony_led_set_brightness(struct led_classdev *led, int on = !!(drv_data->led_state & (1 << n)); if (value == LED_OFF && on) { drv_data->led_state &= ~(1 << n); - buzz_set_leds(hdev, drv_data->led_state); + sony_set_leds(hdev, drv_data->led_state); } else if (value != LED_OFF && !on) { drv_data->led_state |= (1 << n); - buzz_set_leds(hdev, drv_data->led_state); + sony_set_leds(hdev, drv_data->led_state); } break; } @@ -517,6 +531,25 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) return on ? LED_FULL : LED_OFF; } +static void sony_leds_remove(struct hid_device *hdev) +{ + struct sony_sc *drv_data; + struct led_classdev *led; + int n; + + drv_data = hid_get_drvdata(hdev); + BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); + + for (n = 0; n < 4; n++) { + led = drv_data->leds[n]; + drv_data->leds[n] = NULL; + if (!led) + continue; + led_classdev_unregister(led); + kfree(led); + } +} + static int sony_leds_init(struct hid_device *hdev) { struct sony_sc *drv_data; @@ -524,20 +557,29 @@ static int sony_leds_init(struct hid_device *hdev) struct led_classdev *led; size_t name_sz; char *name; + size_t name_len; + const char *name_fmt; drv_data = hid_get_drvdata(hdev); - BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); - - /* Validate expected report characteristics. */ - if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) - return -ENODEV; + BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); + + if (drv_data->quirks & BUZZ_CONTROLLER) { + name_len = strlen("::buzz#"); + name_fmt = "%s::buzz%d"; + /* Validate expected report characteristics. */ + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; + } else { + name_len = strlen("::sony#"); + name_fmt = "%s::sony%d"; + } /* Clear LEDs as we have no way of reading their initial state. This is * only relevant if the driver is loaded after somebody actively set the * LEDs to on */ - buzz_set_leds(hdev, 0x00); + sony_set_leds(hdev, 0x00); - name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; + name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; for (n = 0; n < 4; n++) { led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); @@ -547,7 +589,7 @@ static int sony_leds_init(struct hid_device *hdev) } name = (void *)(&led[1]); - snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); + snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); led->name = name; led->brightness = 0; led->max_brightness = 1; @@ -566,45 +608,18 @@ static int sony_leds_init(struct hid_device *hdev) return ret; error_leds: - for (n = 0; n < 4; n++) { - led = drv_data->leds[n]; - drv_data->leds[n] = NULL; - if (!led) - continue; - led_classdev_unregister(led); - kfree(led); - } + sony_leds_remove(hdev); return ret; } -static void sony_leds_remove(struct hid_device *hdev) -{ - struct sony_sc *drv_data; - struct led_classdev *led; - int n; - - drv_data = hid_get_drvdata(hdev); - BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); - - for (n = 0; n < 4; n++) { - led = drv_data->leds[n]; - drv_data->leds[n] = NULL; - if (!led) - continue; - led_classdev_unregister(led); - kfree(led); - } -} - -#ifdef CONFIG_SONY_FF static void sony_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); unsigned char buf[] = { 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, @@ -612,13 +627,18 @@ static void sony_state_worker(struct work_struct *work) 0x00, 0x00, 0x00, 0x00, 0x00 }; +#ifdef CONFIG_SONY_FF buf[3] = sc->right; buf[5] = sc->left; +#endif + + buf[10] |= (sc->led_state & 0xf) << 1; sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT); } +#ifdef CONFIG_SONY_FF static int sony_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { @@ -640,10 +660,6 @@ static int sony_init_ff(struct hid_device *hdev) struct hid_input *hidinput = list_entry(hdev->inputs.next, struct hid_input, list); struct input_dev *input_dev = hidinput->input; - struct sony_sc *sc = hid_get_drvdata(hdev); - - sc->hdev = hdev; - INIT_WORK(&sc->state_worker, sony_state_worker); input_set_capability(input_dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(input_dev, NULL, sony_play_effect); @@ -682,6 +698,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) sc->quirks = quirks; hid_set_drvdata(hdev, sc); + sc->hdev = hdev; ret = hid_parse(hdev); if (ret) { @@ -705,23 +722,30 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) if (sc->quirks & SIXAXIS_CONTROLLER_USB) { hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; ret = sixaxis_set_operational_usb(hdev); + INIT_WORK(&sc->state_worker, sony_state_worker); } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ret = sixaxis_set_operational_bt(hdev); - else if (sc->quirks & BUZZ_CONTROLLER) - ret = sony_leds_init(hdev); else ret = 0; if (ret < 0) goto err_stop; + if (sc->quirks & SONY_LED_SUPPORT) { + ret = sony_leds_init(hdev); + if (ret < 0) + goto err_stop; + } + ret = sony_init_ff(hdev); if (ret < 0) goto err_stop; return 0; err_stop: + if (sc->quirks & SONY_LED_SUPPORT) + sony_leds_remove(hdev); hid_hw_stop(hdev); return ret; } @@ -730,7 +754,7 @@ static void sony_remove(struct hid_device *hdev) { struct sony_sc *sc = hid_get_drvdata(hdev); - if (sc->quirks & BUZZ_CONTROLLER) + if (sc->quirks & SONY_LED_SUPPORT) sony_leds_remove(hdev); sony_destroy_ff(hdev); -- cgit v1.2.3 From 9688ecadd268770834cca72ac81c9aec8fb8cf2f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2013 23:02:19 +0200 Subject: drm/i915: Limit FBC flush to post batch flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't issue the FBC nuke/cache clean command when invalidate_domains!=0. That would indicate that we're not being called for the post-batch flush. Signed-off-by: Ville Syrjälä Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index c2f09d456300..e26e18a1d916 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -354,7 +354,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, 0); intel_ring_advance(ring); - if (flush_domains) + if (!invalidate_domains && flush_domains) return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); return 0; @@ -1838,7 +1838,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, } intel_ring_advance(ring); - if (IS_GEN7(dev) && flush) + if (IS_GEN7(dev) && !invalidate && flush) return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); return 0; -- cgit v1.2.3 From 37c1d94fa83482c308f14ec671910278e8647934 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2013 23:02:20 +0200 Subject: drm/i915: Emit SRM after the MSG_FBC_REND_STATE LRI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec tells us that we need to emit an SRM after the LRI to MSG_FBC_REND_STATE. Signed-off-by: Ville Syrjälä Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 04d46b23d97c..1777bebc664b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -235,6 +235,7 @@ */ #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1) +#define MI_SRM_LRM_GLOBAL_GTT (1<<22) #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ #define MI_FLUSH_DW_STORE_INDEX (1<<21) #define MI_INVALIDATE_TLB (1<<18) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e26e18a1d916..b65f4d77e3ed 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -285,14 +285,16 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) if (!ring->fbc_dirty) return 0; - ret = intel_ring_begin(ring, 4); + ret = intel_ring_begin(ring, 6); if (ret) return ret; - intel_ring_emit(ring, MI_NOOP); /* WaFbcNukeOn3DBlt:ivb/hsw */ intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, MSG_FBC_REND_STATE); intel_ring_emit(ring, value); + intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT); + intel_ring_emit(ring, MSG_FBC_REND_STATE); + intel_ring_emit(ring, ring->scratch.gtt_offset + 256); intel_ring_advance(ring); ring->fbc_dirty = false; -- cgit v1.2.3 From cbaef0f173c7c8bb14976f3928e5876efec444e2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2013 23:02:24 +0200 Subject: drm/i915: Set has_fbc=true for all SNB+, except VLV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At least since SNB (perhaps even earlier) even the desktop parts should have FBC. Signed-off-by: Ville Syrjälä Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c2e00ed23195..583adcbef5e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -264,6 +264,7 @@ static const struct intel_device_info intel_ironlake_m_info = { static const struct intel_device_info intel_sandybridge_d_info = { .gen = 6, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, + .has_fbc = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING, .has_llc = 1, }; @@ -279,6 +280,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { #define GEN7_FEATURES \ .gen = 7, .num_pipes = 3, \ .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1 @@ -291,7 +293,6 @@ static const struct intel_device_info intel_ivybridge_m_info = { GEN7_FEATURES, .is_ivybridge = 1, .is_mobile = 1, - .has_fbc = 1, }; static const struct intel_device_info intel_ivybridge_q_info = { @@ -306,6 +307,7 @@ static const struct intel_device_info intel_valleyview_m_info = { .num_pipes = 2, .is_valleyview = 1, .display_mmio_offset = VLV_DISPLAY_BASE, + .has_fbc = 0, /* legal, last one wins */ .has_llc = 0, /* legal, last one wins */ }; @@ -314,6 +316,7 @@ static const struct intel_device_info intel_valleyview_d_info = { .num_pipes = 2, .is_valleyview = 1, .display_mmio_offset = VLV_DISPLAY_BASE, + .has_fbc = 0, /* legal, last one wins */ .has_llc = 0, /* legal, last one wins */ }; @@ -331,7 +334,6 @@ static const struct intel_device_info intel_haswell_m_info = { .is_mobile = 1, .has_ddi = 1, .has_fpga_dbg = 1, - .has_fbc = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, }; -- cgit v1.2.3 From b19870ee67ad8b552db0e7456a8d1d33f96421c0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2013 23:02:25 +0200 Subject: drm/i915: Use plane_name() in gen7_enable_fbc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the other .enable_fbc() funcs use plane_name(). Make gen7_enable_fbc() do the same. Signed-off-by: Ville Syrjälä Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 172efa0bfb86..0fcd591b0a4b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -295,7 +295,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) sandybridge_blit_fbc_update(dev); - DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); } bool intel_fbc_enabled(struct drm_device *dev) -- cgit v1.2.3 From 4ea67bc700c0c085e0428b6cb75071ec8c858f7b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2013 18:32:38 -0800 Subject: drm/i915: Enable pipe gamma for sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We send the primary and cursor plane data through the gamma unit. In order to get matching output from sprites, also send the sprite data through the gamma unit. In the future we should add some properties to control this explicitly, and also add properties for the per-sprite gamma ramps what have you, but for now this seems like a reasonable thing to do. Signed-off-by: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1777bebc664b..f2104f5e3af7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3793,7 +3793,7 @@ #define _SPACNTR (VLV_DISPLAY_BASE + 0x72180) #define SP_ENABLE (1<<31) -#define SP_GEAMMA_ENABLE (1<<30) +#define SP_GAMMA_ENABLE (1<<30) #define SP_PIXFORMAT_MASK (0xf<<26) #define SP_FORMAT_YUV422 (0<<26) #define SP_FORMAT_BGR565 (5<<26) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b9fabf826f7d..90a3f6db8288 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -104,6 +104,12 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, break; } + /* + * Enable gamma to match primary/cursor plane behaviour. + * FIXME should be user controllable via propertiesa. + */ + sprctl |= SP_GAMMA_ENABLE; + if (obj->tiling_mode != I915_TILING_NONE) sprctl |= SP_TILED; @@ -257,6 +263,12 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, BUG(); } + /* + * Enable gamma to match primary/cursor plane behaviour. + * FIXME should be user controllable via propertiesa. + */ + sprctl |= SPRITE_GAMMA_ENABLE; + if (obj->tiling_mode != I915_TILING_NONE) sprctl |= SPRITE_TILED; @@ -453,6 +465,12 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, BUG(); } + /* + * Enable gamma to match primary/cursor plane behaviour. + * FIXME should be user controllable via propertiesa. + */ + dvscntr |= DVS_GAMMA_ENABLE; + if (obj->tiling_mode != I915_TILING_NONE) dvscntr |= DVS_TILED; -- cgit v1.2.3 From 3458122e27fd381411e0cd4c45c28816fcffbe20 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Nov 2013 18:32:36 -0800 Subject: drm/i915: Hold pc8 lock around toggling pc8.gpu_idle We need to hold the pc8 lock around toggling the value of gpu_idle. Signed-off-by: Chris Wilson Cc: Paulo Zanoni Reviewed-by: Paulo Zanoni Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3b7f1c4eb48e..54e7fa6d9628 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6761,18 +6761,22 @@ done: static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv) { + mutex_lock(&dev_priv->pc8.lock); if (!dev_priv->pc8.gpu_idle) { dev_priv->pc8.gpu_idle = true; - hsw_enable_package_c8(dev_priv); + __hsw_enable_package_c8(dev_priv); } + mutex_unlock(&dev_priv->pc8.lock); } static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv) { + mutex_lock(&dev_priv->pc8.lock); if (dev_priv->pc8.gpu_idle) { dev_priv->pc8.gpu_idle = false; - hsw_disable_package_c8(dev_priv); + __hsw_disable_package_c8(dev_priv); } + mutex_unlock(&dev_priv->pc8.lock); } #define for_each_power_domain(domain, mask) \ -- cgit v1.2.3 From c50aa44db3f803d3c3b79c926e76862454e77c48 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 19 Nov 2013 16:04:00 +0000 Subject: mfd: wm5110: Make DSP memories readable Expose the memory regions used by the DSP cores on WM5110 as readable and volatile. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 69 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 3113e39b318e..4430404471c0 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -14,6 +14,7 @@ #include #include +#include #include "arizona.h" @@ -1336,6 +1337,64 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00001404, 0x0000 }, /* R5124 - DSP4 Status 1 */ }; +static bool wm5110_is_rev_b_adsp_memory(unsigned int reg) +{ + if ((reg >= 0x100000 && reg < 0x103000) || + (reg >= 0x180000 && reg < 0x181000) || + (reg >= 0x190000 && reg < 0x192000) || + (reg >= 0x1a8000 && reg < 0x1a9000) || + (reg >= 0x200000 && reg < 0x209000) || + (reg >= 0x280000 && reg < 0x281000) || + (reg >= 0x290000 && reg < 0x29a000) || + (reg >= 0x2a8000 && reg < 0x2aa000) || + (reg >= 0x300000 && reg < 0x30f000) || + (reg >= 0x380000 && reg < 0x382000) || + (reg >= 0x390000 && reg < 0x39e000) || + (reg >= 0x3a8000 && reg < 0x3b6000) || + (reg >= 0x400000 && reg < 0x403000) || + (reg >= 0x480000 && reg < 0x481000) || + (reg >= 0x490000 && reg < 0x492000) || + (reg >= 0x4a8000 && reg < 0x4a9000)) + return true; + else + return false; +} + +static bool wm5110_is_rev_d_adsp_memory(unsigned int reg) +{ + if ((reg >= 0x100000 && reg < 0x106000) || + (reg >= 0x180000 && reg < 0x182000) || + (reg >= 0x190000 && reg < 0x198000) || + (reg >= 0x1a8000 && reg < 0x1aa000) || + (reg >= 0x200000 && reg < 0x20f000) || + (reg >= 0x280000 && reg < 0x282000) || + (reg >= 0x290000 && reg < 0x29c000) || + (reg >= 0x2a6000 && reg < 0x2b4000) || + (reg >= 0x300000 && reg < 0x30f000) || + (reg >= 0x380000 && reg < 0x382000) || + (reg >= 0x390000 && reg < 0x3a2000) || + (reg >= 0x3a6000 && reg < 0x3b4000) || + (reg >= 0x400000 && reg < 0x406000) || + (reg >= 0x480000 && reg < 0x482000) || + (reg >= 0x490000 && reg < 0x498000) || + (reg >= 0x4a8000 && reg < 0x4aa000)) + return true; + else + return false; +} + +static bool wm5110_is_adsp_memory(struct device *dev, unsigned int reg) +{ + struct arizona *arizona = dev_get_drvdata(dev); + + switch (arizona->rev) { + case 0 ... 2: + return wm5110_is_rev_b_adsp_memory(reg); + default: + return wm5110_is_rev_d_adsp_memory(reg); + } +} + static bool wm5110_readable_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -2308,7 +2367,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_DSP4_STATUS_3: return true; default: - return false; + return wm5110_is_adsp_memory(dev, reg); } } @@ -2368,16 +2427,18 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_DSP4_STATUS_3: return true; default: - return false; + return wm5110_is_adsp_memory(dev, reg); } } +#define WM5110_MAX_REGISTER 0x4a9fff + const struct regmap_config wm5110_spi_regmap = { .reg_bits = 32, .pad_bits = 16, .val_bits = 16, - .max_register = ARIZONA_DSP1_STATUS_2, + .max_register = WM5110_MAX_REGISTER, .readable_reg = wm5110_readable_register, .volatile_reg = wm5110_volatile_register, @@ -2391,7 +2452,7 @@ const struct regmap_config wm5110_i2c_regmap = { .reg_bits = 32, .val_bits = 16, - .max_register = ARIZONA_DSP1_STATUS_2, + .max_register = WM5110_MAX_REGISTER, .readable_reg = wm5110_readable_register, .volatile_reg = wm5110_volatile_register, -- cgit v1.2.3 From 254dc326dbfd23c2678fafad1b84fc0e42ac4374 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 19 Nov 2013 16:04:03 +0000 Subject: ASoC: wm5110: Expose input high pass filter controls Acked-by: Mark Brown Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 4 ++++ include/linux/mfd/arizona/registers.h | 37 +++++++++++++++++++++++++++++++++++ sound/soc/codecs/arizona.c | 10 ++++++++++ sound/soc/codecs/arizona.h | 1 + sound/soc/codecs/wm5110.c | 19 ++++++++++++++++++ 5 files changed, 71 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 4430404471c0..3b079f6b021e 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -518,6 +518,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000300, 0x0000 }, /* R768 - Input Enables */ { 0x00000308, 0x0000 }, /* R776 - Input Rate */ { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */ + { 0x0000030C, 0x0002 }, /* R780 - HPF Control */ { 0x00000310, 0x2080 }, /* R784 - IN1L Control */ { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */ { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */ @@ -539,6 +540,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000328, 0x2000 }, /* R808 - IN4L Control */ { 0x00000329, 0x0180 }, /* R809 - ADC Digital Volume 4L */ { 0x0000032A, 0x0000 }, /* R810 - DMIC4L Control */ + { 0x0000032C, 0x0000 }, /* R812 - IN4R Control */ { 0x0000032D, 0x0180 }, /* R813 - ADC Digital Volume 4R */ { 0x0000032E, 0x0000 }, /* R814 - DMIC4R Control */ { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ @@ -1512,6 +1514,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_INPUT_ENABLES_STATUS: case ARIZONA_INPUT_RATE: case ARIZONA_INPUT_VOLUME_RAMP: + case ARIZONA_HPF_CONTROL: case ARIZONA_IN1L_CONTROL: case ARIZONA_ADC_DIGITAL_VOLUME_1L: case ARIZONA_DMIC1L_CONTROL: @@ -1533,6 +1536,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_IN4L_CONTROL: case ARIZONA_ADC_DIGITAL_VOLUME_4L: case ARIZONA_DMIC4L_CONTROL: + case ARIZONA_IN4R_CONTROL: case ARIZONA_ADC_DIGITAL_VOLUME_4R: case ARIZONA_DMIC4R_CONTROL: case ARIZONA_OUTPUT_ENABLES_1: diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index 4706d3d46e56..cdf1f5acbe53 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -139,6 +139,7 @@ #define ARIZONA_INPUT_ENABLES_STATUS 0x301 #define ARIZONA_INPUT_RATE 0x308 #define ARIZONA_INPUT_VOLUME_RAMP 0x309 +#define ARIZONA_HPF_CONTROL 0x30C #define ARIZONA_IN1L_CONTROL 0x310 #define ARIZONA_ADC_DIGITAL_VOLUME_1L 0x311 #define ARIZONA_DMIC1L_CONTROL 0x312 @@ -160,6 +161,7 @@ #define ARIZONA_IN4L_CONTROL 0x328 #define ARIZONA_ADC_DIGITAL_VOLUME_4L 0x329 #define ARIZONA_DMIC4L_CONTROL 0x32A +#define ARIZONA_IN4R_CONTROL 0x32C #define ARIZONA_ADC_DIGITAL_VOLUME_4R 0x32D #define ARIZONA_DMIC4R_CONTROL 0x32E #define ARIZONA_OUTPUT_ENABLES_1 0x400 @@ -2292,9 +2294,19 @@ #define ARIZONA_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */ #define ARIZONA_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */ +/* + * R780 (0x30C) - HPF Control + */ +#define ARIZONA_IN_HPF_CUT_MASK 0x0007 /* IN_HPF_CUT [2:0] */ +#define ARIZONA_IN_HPF_CUT_SHIFT 0 /* IN_HPF_CUT [2:0] */ +#define ARIZONA_IN_HPF_CUT_WIDTH 3 /* IN_HPF_CUT [2:0] */ + /* * R784 (0x310) - IN1L Control */ +#define ARIZONA_IN1L_HPF_MASK 0x8000 /* IN1L_HPF - [15] */ +#define ARIZONA_IN1L_HPF_SHIFT 15 /* IN1L_HPF - [15] */ +#define ARIZONA_IN1L_HPF_WIDTH 1 /* IN1L_HPF - [15] */ #define ARIZONA_IN1_OSR_MASK 0x6000 /* IN1_OSR - [14:13] */ #define ARIZONA_IN1_OSR_SHIFT 13 /* IN1_OSR - [14:13] */ #define ARIZONA_IN1_OSR_WIDTH 2 /* IN1_OSR - [14:13] */ @@ -2333,6 +2345,9 @@ /* * R788 (0x314) - IN1R Control */ +#define ARIZONA_IN1R_HPF_MASK 0x8000 /* IN1R_HPF - [15] */ +#define ARIZONA_IN1R_HPF_SHIFT 15 /* IN1R_HPF - [15] */ +#define ARIZONA_IN1R_HPF_WIDTH 1 /* IN1R_HPF - [15] */ #define ARIZONA_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */ #define ARIZONA_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */ #define ARIZONA_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */ @@ -2362,6 +2377,9 @@ /* * R792 (0x318) - IN2L Control */ +#define ARIZONA_IN2L_HPF_MASK 0x8000 /* IN2L_HPF - [15] */ +#define ARIZONA_IN2L_HPF_SHIFT 15 /* IN2L_HPF - [15] */ +#define ARIZONA_IN2L_HPF_WIDTH 1 /* IN2L_HPF - [15] */ #define ARIZONA_IN2_OSR_MASK 0x6000 /* IN2_OSR - [14:13] */ #define ARIZONA_IN2_OSR_SHIFT 13 /* IN2_OSR - [14:13] */ #define ARIZONA_IN2_OSR_WIDTH 2 /* IN2_OSR - [14:13] */ @@ -2400,6 +2418,9 @@ /* * R796 (0x31C) - IN2R Control */ +#define ARIZONA_IN2R_HPF_MASK 0x8000 /* IN2R_HPF - [15] */ +#define ARIZONA_IN2R_HPF_SHIFT 15 /* IN2R_HPF - [15] */ +#define ARIZONA_IN2R_HPF_WIDTH 1 /* IN2R_HPF - [15] */ #define ARIZONA_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */ #define ARIZONA_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */ #define ARIZONA_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */ @@ -2429,6 +2450,9 @@ /* * R800 (0x320) - IN3L Control */ +#define ARIZONA_IN3L_HPF_MASK 0x8000 /* IN3L_HPF - [15] */ +#define ARIZONA_IN3L_HPF_SHIFT 15 /* IN3L_HPF - [15] */ +#define ARIZONA_IN3L_HPF_WIDTH 1 /* IN3L_HPF - [15] */ #define ARIZONA_IN3_OSR_MASK 0x6000 /* IN3_OSR - [14:13] */ #define ARIZONA_IN3_OSR_SHIFT 13 /* IN3_OSR - [14:13] */ #define ARIZONA_IN3_OSR_WIDTH 2 /* IN3_OSR - [14:13] */ @@ -2467,6 +2491,9 @@ /* * R804 (0x324) - IN3R Control */ +#define ARIZONA_IN3R_HPF_MASK 0x8000 /* IN3R_HPF - [15] */ +#define ARIZONA_IN3R_HPF_SHIFT 15 /* IN3R_HPF - [15] */ +#define ARIZONA_IN3R_HPF_WIDTH 1 /* IN3R_HPF - [15] */ #define ARIZONA_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */ #define ARIZONA_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */ #define ARIZONA_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */ @@ -2496,6 +2523,9 @@ /* * R808 (0x328) - IN4 Control */ +#define ARIZONA_IN4L_HPF_MASK 0x8000 /* IN4L_HPF - [15] */ +#define ARIZONA_IN4L_HPF_SHIFT 15 /* IN4L_HPF - [15] */ +#define ARIZONA_IN4L_HPF_WIDTH 1 /* IN4L_HPF - [15] */ #define ARIZONA_IN4_OSR_MASK 0x6000 /* IN4_OSR - [14:13] */ #define ARIZONA_IN4_OSR_SHIFT 13 /* IN4_OSR - [14:13] */ #define ARIZONA_IN4_OSR_WIDTH 2 /* IN4_OSR - [14:13] */ @@ -2525,6 +2555,13 @@ #define ARIZONA_IN4L_DMIC_DLY_SHIFT 0 /* IN4L_DMIC_DLY - [5:0] */ #define ARIZONA_IN4L_DMIC_DLY_WIDTH 6 /* IN4L_DMIC_DLY - [5:0] */ +/* + * R812 (0x32C) - IN4R Control + */ +#define ARIZONA_IN4R_HPF_MASK 0x8000 /* IN4R_HPF - [15] */ +#define ARIZONA_IN4R_HPF_SHIFT 15 /* IN4R_HPF - [15] */ +#define ARIZONA_IN4R_HPF_WIDTH 1 /* IN4R_HPF - [15] */ + /* * R813 (0x32D) - ADC Digital Volume 4R */ diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 657808ba1418..708326265a37 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -560,6 +560,16 @@ const struct soc_enum arizona_ng_hold = 4, arizona_ng_hold_text); EXPORT_SYMBOL_GPL(arizona_ng_hold); +static const char * const arizona_in_hpf_cut_text[] = { + "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" +}; + +const struct soc_enum arizona_in_hpf_cut_enum = + SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, + ARRAY_SIZE(arizona_in_hpf_cut_text), + arizona_in_hpf_cut_text); +EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); + static const char * const arizona_in_dmic_osr_text[] = { "1.536MHz", "3.072MHz", "6.144MHz", }; diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 9e81b6392692..f8e63865a1c5 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -199,6 +199,7 @@ extern const struct soc_enum arizona_lhpf3_mode; extern const struct soc_enum arizona_lhpf4_mode; extern const struct soc_enum arizona_ng_hold; +extern const struct soc_enum arizona_in_hpf_cut_enum; extern const struct soc_enum arizona_in_dmic_osr[]; extern int arizona_in_ev(struct snd_soc_dapm_widget *w, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index bbd64384ca1c..ea18e88e0a07 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -76,6 +76,25 @@ SOC_SINGLE_RANGE_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL, SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL, ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), +SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum), + +SOC_SINGLE("IN1L HPF Switch", ARIZONA_IN1L_CONTROL, + ARIZONA_IN1L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN1R HPF Switch", ARIZONA_IN1R_CONTROL, + ARIZONA_IN1R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2L HPF Switch", ARIZONA_IN2L_CONTROL, + ARIZONA_IN2L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN2R HPF Switch", ARIZONA_IN2R_CONTROL, + ARIZONA_IN2R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3L HPF Switch", ARIZONA_IN3L_CONTROL, + ARIZONA_IN3L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN3R HPF Switch", ARIZONA_IN3R_CONTROL, + ARIZONA_IN3R_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4L HPF Switch", ARIZONA_IN4L_CONTROL, + ARIZONA_IN4L_HPF_SHIFT, 1, 0), +SOC_SINGLE("IN4R HPF Switch", ARIZONA_IN4R_CONTROL, + ARIZONA_IN4R_HPF_SHIFT, 1, 0), + SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv), SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R, -- cgit v1.2.3 From 5ea17d6cb9a72fbb7e5ab75868369bade2c5f2bc Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Thu, 21 Nov 2013 22:24:48 +0800 Subject: staging/lustre/llite: Access to released file triggers a restore When a client accesses data in a released file, or truncate it, client must trig a restore request. During this restore, the client must not glimpse and must use size from MDT. To bring the "restore is running" information on the client we add a new t_state bit field to mdt_info which will be used to carry transient file state. To memorise this information in the inode we add a new flag LLIF_FILE_RESTORING. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3432 Lustre-change: http://review.whamcloud.com/6537 Signed-off-by: JC Lafoucriere Reviewed-by: Oleg Drokin Tested-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/cl_object.h | 6 ++- .../lustre/lustre/include/lustre/lustre_idl.h | 14 ++++-- drivers/staging/lustre/lustre/lclient/lcommon_cl.c | 6 +++ drivers/staging/lustre/lustre/llite/file.c | 39 +++++++++++++++- .../staging/lustre/lustre/llite/llite_internal.h | 3 ++ drivers/staging/lustre/lustre/llite/llite_lib.c | 36 +++++++++++++++ drivers/staging/lustre/lustre/llite/vvp_io.c | 54 ++++++++++++++++++++-- drivers/staging/lustre/lustre/lov/lov_io.c | 15 ++++-- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 18 +++++--- 10 files changed, 169 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index c485206fc6c2..4d692dcd96cf 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -2388,7 +2388,11 @@ struct cl_io { * Right now, only two opertaions need to verify layout: glimpse * and setattr. */ - ci_verify_layout:1; + ci_verify_layout:1, + /** + * file is released, restore has to to be triggered by vvp layer + */ + ci_restore_needed:1; /** * Number of pages owned by this IO. For invariant checking. */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index e592a0e0f794..4d8d8c34cd67 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1725,10 +1725,7 @@ static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic) #define OBD_MD_MDS (0x0000000100000000ULL) /* where an inode lives on */ #define OBD_MD_REINT (0x0000000200000000ULL) /* reintegrate oa */ #define OBD_MD_MEA (0x0000000400000000ULL) /* CMD split EA */ - -/* OBD_MD_MDTIDX is used to get MDT index, but it is never been used overwire, - * and it is already obsolete since 2.3 */ -/* #define OBD_MD_MDTIDX (0x0000000800000000ULL) */ +#define OBD_MD_TSTATE (0x0000000800000000ULL) /* transient state field */ #define OBD_MD_FLXATTR (0x0000001000000000ULL) /* xattr */ #define OBD_MD_FLXATTRLS (0x0000002000000000ULL) /* xattr list */ @@ -2208,6 +2205,11 @@ static inline int ll_inode_to_ext_flags(int iflags) ((iflags & S_IMMUTABLE) ? LUSTRE_IMMUTABLE_FL : 0)); } +/* 64 possible states */ +enum md_transient_state { + MS_RESTORE = (1 << 0), /* restore is running */ +}; + struct mdt_body { struct lu_fid fid1; struct lu_fid fid2; @@ -2219,7 +2221,9 @@ struct mdt_body { obd_time ctime; __u64 blocks; /* XID, in the case of MDS_READPAGE */ __u64 ioepoch; - __u64 unused1; /* was "ino" until 2.4.0 */ + __u64 t_state; /* transient file state defined in + * enum md_transient_state + * was "ino" until 2.4.0 */ __u32 fsuid; __u32 fsgid; __u32 capability; diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index e60c04d5393a..1c628e325750 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -1006,6 +1006,12 @@ again: cl_io_fini(env, io); if (unlikely(io->ci_need_restart)) goto again; + /* HSM import case: file is released, cannot be restored + * no need to fail except if restore registration failed + * with -ENODATA */ + if (result == -ENODATA && io->ci_restore_needed && + io->ci_result != -ENODATA) + result = 0; cl_env_put(env, &refcheck); return result; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 971409ed52e7..82248e9f6bff 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1107,7 +1107,7 @@ out: cl_io_fini(env, io); /* If any bit been read/written (result != 0), we just return * short read/write instead of restart io. */ - if (result == 0 && io->ci_need_restart) { + if ((result == 0 || result == -ENODATA) && io->ci_need_restart) { CDEBUG(D_VFSTRACE, "Restart %s on %s from %lld, count:%zd\n", iot == CIT_READ ? "read" : "write", file->f_dentry->d_name.name, *ppos, count); @@ -2867,7 +2867,15 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it, LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_lvb.lvb_mtime; LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_lvb.lvb_ctime; } else { - rc = ll_glimpse_size(inode); + /* In case of restore, the MDT has the right size and has + * already send it back without granting the layout lock, + * inode is up-to-date so glimpse is useless. + * Also to glimpse we need the layout, in case of a running + * restore the MDT holds the layout lock so the glimpse will + * block up to the end of restore (getattr will block) + */ + if (!(ll_i2info(inode)->lli_flags & LLIF_FILE_RESTORING)) + rc = ll_glimpse_size(inode); } return rc; } @@ -3464,3 +3472,30 @@ again: return rc; } + +/** + * This function send a restore request to the MDT + */ +int ll_layout_restore(struct inode *inode) +{ + struct hsm_user_request *hur; + int len, rc; + + len = sizeof(struct hsm_user_request) + + sizeof(struct hsm_user_item); + OBD_ALLOC(hur, len); + if (hur == NULL) + return -ENOMEM; + + hur->hur_request.hr_action = HUA_RESTORE; + hur->hur_request.hr_archive_id = 0; + hur->hur_request.hr_flags = 0; + memcpy(&hur->hur_user_item[0].hui_fid, &ll_i2info(inode)->lli_fid, + sizeof(hur->hur_user_item[0].hui_fid)); + hur->hur_user_item[0].hui_extent.length = -1; + hur->hur_request.hr_itemcount = 1; + rc = obd_iocontrol(LL_IOC_HSM_REQUEST, cl_i2sbi(inode)->ll_md_exp, + len, hur, NULL); + OBD_FREE(hur, len); + return rc; +} diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1a13330ac966..c326ff24410c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -125,6 +125,8 @@ enum lli_flags { LLIF_SRVLOCK = (1 << 5), /* File data is modified. */ LLIF_DATA_MODIFIED = (1 << 6), + /* File is being restored */ + LLIF_FILE_RESTORING = (1 << 7), }; struct ll_inode_info { @@ -1588,5 +1590,6 @@ enum { int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf); int ll_layout_refresh(struct inode *inode, __u32 *gen); +int ll_layout_restore(struct inode *inode); #endif /* LLITE_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index fd584ff7e2df..facc39158447 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1353,6 +1353,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; + bool file_is_released = false; int rc = 0, rc1 = 0; CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, " @@ -1436,10 +1437,40 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) op_data->op_flags = MF_EPOCH_OPEN; + /* truncate on a released file must failed with -ENODATA, + * so size must not be set on MDS for released file + * but other attributes must be set + */ + if (S_ISREG(inode->i_mode)) { + struct lov_stripe_md *lsm; + __u32 gen; + + ll_layout_refresh(inode, &gen); + lsm = ccc_inode_lsm_get(inode); + if (lsm && lsm->lsm_pattern & LOV_PATTERN_F_RELEASED) + file_is_released = true; + ccc_inode_lsm_put(inode, lsm); + } + + /* clear size attr for released file + * we clear the attribute send to MDT in op_data, not the original + * received from caller in attr which is used later to + * decide return code */ + if (file_is_released && (attr->ia_valid & ATTR_SIZE)) + op_data->op_attr.ia_valid &= ~ATTR_SIZE; + rc = ll_md_setattr(dentry, op_data, &mod); if (rc) GOTO(out, rc); + /* truncate failed, others succeed */ + if (file_is_released) { + if (attr->ia_valid & ATTR_SIZE) + GOTO(out, rc = -ENODATA); + else + GOTO(out, rc = 0); + } + /* RPC to MDT is sent, cancel data modification flag */ if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) { spin_lock(&lli->lli_lock); @@ -1761,6 +1792,11 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT(md->oss_capa); ll_add_capa(inode, md->oss_capa); } + + if (body->valid & OBD_MD_TSTATE) { + if (body->t_state & MS_RESTORE) + lli->lli_flags |= LLIF_FILE_RESTORING; + } } void ll_read_inode2(struct inode *inode, void *opaque) diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 3ff664ce7503..f69e3aa98022 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -121,8 +121,38 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) CLOBINVRNT(env, obj, ccc_object_invariant(obj)); - CDEBUG(D_VFSTRACE, "ignore/verify layout %d/%d, layout version %d.\n", - io->ci_ignore_layout, io->ci_verify_layout, cio->cui_layout_gen); + CDEBUG(D_VFSTRACE, DFID + " ignore/verify layout %d/%d, layout version %d restore needed %d\n", + PFID(lu_object_fid(&obj->co_lu)), + io->ci_ignore_layout, io->ci_verify_layout, + cio->cui_layout_gen, io->ci_restore_needed); + + if (io->ci_restore_needed == 1) { + int rc; + + /* file was detected release, we need to restore it + * before finishing the io + */ + rc = ll_layout_restore(ccc_object_inode(obj)); + /* if restore registration failed, no restart, + * we will return -ENODATA */ + /* The layout will change after restore, so we need to + * block on layout lock hold by the MDT + * as MDT will not send new layout in lvb (see LU-3124) + * we have to explicitly fetch it, all this will be done + * by ll_layout_refresh() + */ + if (rc == 0) { + io->ci_restore_needed = 0; + io->ci_need_restart = 1; + io->ci_verify_layout = 1; + } else { + io->ci_restore_needed = 1; + io->ci_need_restart = 0; + io->ci_verify_layout = 0; + io->ci_result = rc; + } + } if (!io->ci_ignore_layout && io->ci_verify_layout) { __u32 gen = 0; @@ -130,9 +160,17 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) /* check layout version */ ll_layout_refresh(ccc_object_inode(obj), &gen); io->ci_need_restart = cio->cui_layout_gen != gen; - if (io->ci_need_restart) - CDEBUG(D_VFSTRACE, "layout changed from %d to %d.\n", - cio->cui_layout_gen, gen); + if (io->ci_need_restart) { + CDEBUG(D_VFSTRACE, + DFID" layout changed from %d to %d.\n", + PFID(lu_object_fid(&obj->co_lu)), + cio->cui_layout_gen, gen); + /* today successful restore is the only possible + * case */ + /* restore was done, clear restoring state */ + ll_i2info(ccc_object_inode(obj))->lli_flags &= + ~LLIF_FILE_RESTORING; + } } } @@ -1111,6 +1149,12 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, CLOBINVRNT(env, obj, ccc_object_invariant(obj)); + CDEBUG(D_VFSTRACE, DFID + " ignore/verify layout %d/%d, layout version %d restore needed %d\n", + PFID(lu_object_fid(&obj->co_lu)), + io->ci_ignore_layout, io->ci_verify_layout, + cio->cui_layout_gen, io->ci_restore_needed); + CL_IO_SLICE_CLEAN(cio, cui_cl); cl_io_slice_add(io, &cio->cui_cl, obj, &vvp_io_ops); vio->cui_ra_window_set = 0; diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 2792fa5c4be2..5a6ab70ed0a1 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -947,14 +947,23 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, LASSERTF(0, "invalid type %d\n", io->ci_type); case CIT_MISC: case CIT_FSYNC: - result = +1; + result = 1; break; case CIT_SETATTR: + /* the truncate to 0 is managed by MDT: + * - in open, for open O_TRUNC + * - in setattr, for truncate + */ + /* the truncate is for size > 0 so triggers a restore */ + if (cl_io_is_trunc(io)) + io->ci_restore_needed = 1; + result = -ENODATA; + break; case CIT_READ: case CIT_WRITE: case CIT_FAULT: - /* TODO: need to restore the file. */ - result = -EBADF; + io->ci_restore_needed = 1; + result = -ENODATA; break; } if (result == 0) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 4659314a1865..d831bd7e8e08 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1873,7 +1873,7 @@ void lustre_swab_mdt_body(struct mdt_body *b) __swab64s(&b->ctime); __swab64s(&b->blocks); __swab64s(&b->ioepoch); - CLASSERT(offsetof(typeof(*b), unused1) != 0); + __swab64s(&b->t_state); __swab32s(&b->fsuid); __swab32s(&b->fsgid); __swab32s(&b->capability); diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 9890bd9cfb93..e3f02c77f3b9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -49,9 +49,10 @@ void lustre_assert_wire_constants(void) { /* Wire protocol assertions generated by 'wirecheck' * (make -C lustre/utils newwiretest) - * running on Linux deva 2.6.32.279.lustre #5 SMP Tue Apr 9 22:52:17 CST 2013 x86_64 x86_64 x - * with gcc version 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC) */ - + * running on Linux centos6-bis 2.6.32-358.0.1.el6-head + * #3 SMP Wed Apr 17 17:37:43 CEST 2013 + * with gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) + */ /* Constants... */ LASSERTF(PTL_RPC_MSG_REQUEST == 4711, "found %lld\n", @@ -1335,6 +1336,8 @@ void lustre_assert_wire_constants(void) OBD_MD_REINT); LASSERTF(OBD_MD_MEA == (0x0000000400000000ULL), "found 0x%.16llxULL\n", OBD_MD_MEA); + LASSERTF(OBD_MD_TSTATE == (0x0000000800000000ULL), + "found 0x%.16llxULL\n", OBD_MD_TSTATE); LASSERTF(OBD_MD_FLXATTR == (0x0000001000000000ULL), "found 0x%.16llxULL\n", OBD_MD_FLXATTR); LASSERTF(OBD_MD_FLXATTRLS == (0x0000002000000000ULL), "found 0x%.16llxULL\n", @@ -1918,10 +1921,11 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct mdt_body, blocks)); LASSERTF((int)sizeof(((struct mdt_body *)0)->blocks) == 8, "found %lld\n", (long long)(int)sizeof(((struct mdt_body *)0)->blocks)); - LASSERTF((int)offsetof(struct mdt_body, unused1) == 96, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, unused1)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->unused1) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->unused1)); + LASSERTF((int)offsetof(struct mdt_body, t_state) == 96, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, t_state)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->t_state) == 8, + "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->t_state)); LASSERTF((int)offsetof(struct mdt_body, fsuid) == 104, "found %lld\n", (long long)(int)offsetof(struct mdt_body, fsuid)); LASSERTF((int)sizeof(((struct mdt_body *)0)->fsuid) == 4, "found %lld\n", -- cgit v1.2.3 From 6d95e0481be819417a5ecef4e0effdb59133a68a Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Thu, 21 Nov 2013 22:24:49 +0800 Subject: staging/lustre/ldlm: fix resource/fid check, use DLDLMRES In ll_md_blocking_ast() the FID/resource comparison is incorrectly checking for fid_ver() stored in res_id.name[2] instead of name[1] changed since http://review.whamcloud.com/2271 (commit 4f91d5161d00) landed. This does not impact current clients, since name[2] and fid_ver() are always zero, but it could cause problems in the future. In ldlm_cli_enqueue_fini() use ldlm_res_eq() instead of comparing each of the resource fields separately. Use DLDLMRES/PLDLMRES when printing resource names everywhere. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2901 Lustre-change: http://review.whamcloud.com/6592 Signed-off-by: Lai Siyao Reviewed-by: Johann Lombardi Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 32 ++++++++-------------- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 19 ++++--------- drivers/staging/lustre/lustre/llite/namei.c | 5 +--- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 9 ++---- drivers/staging/lustre/lustre/mgc/mgc_request.c | 4 +-- 5 files changed, 21 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 1e2c0dd67569..1ddcca34bb79 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -610,18 +610,12 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, lock->l_req_mode = newmode; } - if (memcmp(reply->lock_desc.l_resource.lr_name.name, - lock->l_resource->lr_name.name, - sizeof(struct ldlm_res_id))) { - CDEBUG(D_INFO, "remote intent success, locking " - "(%ld,%ld,%ld) instead of " - "(%ld,%ld,%ld)\n", - (long)reply->lock_desc.l_resource.lr_name.name[0], - (long)reply->lock_desc.l_resource.lr_name.name[1], - (long)reply->lock_desc.l_resource.lr_name.name[2], - (long)lock->l_resource->lr_name.name[0], - (long)lock->l_resource->lr_name.name[1], - (long)lock->l_resource->lr_name.name[2]); + if (!ldlm_res_eq(&reply->lock_desc.l_resource.lr_name, + &lock->l_resource->lr_name)) { + CDEBUG(D_INFO, "remote intent success, locking "DLDLMRES + " instead of "DLDLMRES"\n", + PLDLMRES(&reply->lock_desc.l_resource), + PLDLMRES(lock->l_resource)); rc = ldlm_lock_change_resource(ns, lock, &reply->lock_desc.l_resource.lr_name); @@ -1912,7 +1906,8 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, 0, flags | LCF_BL_AST, opaque); rc = ldlm_cli_cancel_list(&cancels, count, NULL, flags); if (rc != ELDLM_OK) - CERROR("ldlm_cli_cancel_unused_resource: %d\n", rc); + CERROR("canceling unused lock "DLDLMRES": rc = %d\n", + PLDLMRES(res), rc); LDLM_RESOURCE_DELREF(res); ldlm_resource_putref(res); @@ -1930,15 +1925,10 @@ static int ldlm_cli_hash_cancel_unused(struct cfs_hash *hs, struct cfs_hash_bd * { struct ldlm_resource *res = cfs_hash_object(hs, hnode); struct ldlm_cli_cancel_arg *lc = arg; - int rc; - rc = ldlm_cli_cancel_unused_resource(ldlm_res_to_ns(res), &res->lr_name, - NULL, LCK_MINMODE, - lc->lc_flags, lc->lc_opaque); - if (rc != 0) { - CERROR("ldlm_cli_cancel_unused ("LPU64"): %d\n", - res->lr_name.name[0], rc); - } + ldlm_cli_cancel_unused_resource(ldlm_res_to_ns(res), &res->lr_name, + NULL, LCK_MINMODE, + lc->lc_flags, lc->lc_opaque); /* must return 0 for hash iteration */ return 0; } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 77e022bf8bcc..25e14e1b3659 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -762,16 +762,9 @@ static int ldlm_resource_complain(struct cfs_hash *hs, struct cfs_hash_bd *bd, struct ldlm_resource *res = cfs_hash_object(hs, hnode); lock_res(res); - CERROR("Namespace %s resource refcount nonzero " - "(%d) after lock cleanup; forcing " - "cleanup.\n", - ldlm_ns_name(ldlm_res_to_ns(res)), - atomic_read(&res->lr_refcount) - 1); - - CERROR("Resource: %p ("LPU64"/"LPU64"/"LPU64"/" - LPU64") (rc: %d)\n", res, - res->lr_name.name[0], res->lr_name.name[1], - res->lr_name.name[2], res->lr_name.name[3], + CERROR("%s: namespace resource "DLDLMRES + " (%p) refcount nonzero (%d) after lock cleanup; forcing cleanup.\n", + ldlm_ns_name(ldlm_res_to_ns(res)), PLDLMRES(res), res, atomic_read(&res->lr_refcount) - 1); ldlm_resource_dump(D_ERROR, res); @@ -1403,10 +1396,8 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res) if (!((libcfs_debug | D_ERROR) & level)) return; - CDEBUG(level, "--- Resource: %p ("LPU64"/"LPU64"/"LPU64"/"LPU64 - ") (rc: %d)\n", res, res->lr_name.name[0], res->lr_name.name[1], - res->lr_name.name[2], res->lr_name.name[3], - atomic_read(&res->lr_refcount)); + CDEBUG(level, "--- Resource: "DLDLMRES" (%p) refcount = %d\n", + PLDLMRES(res), res, atomic_read(&res->lr_refcount)); if (!list_empty(&res->lr_granted)) { CDEBUG(level, "Granted locks (in reverse order):\n"); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 34815b550e71..83774684734c 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -233,12 +233,9 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, ll_have_md_lock(inode, &bits, mode); fid = ll_inode2fid(inode); - if (lock->l_resource->lr_name.name[0] != fid_seq(fid) || - lock->l_resource->lr_name.name[1] != fid_oid(fid) || - lock->l_resource->lr_name.name[2] != fid_ver(fid)) { + if (!fid_res_name_eq(fid, &lock->l_resource->lr_name)) LDLM_ERROR(lock, "data mismatch with object " DFID" (%p)", PFID(fid), inode); - } if (bits & MDS_INODELOCK_OPEN) { int flags = 0; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index eccbab7561fe..09dee1120ed2 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -971,13 +971,8 @@ static int mdc_finish_intent_lock(struct obd_export *exp, LASSERTF(fid_res_name_eq(&mdt_body->fid1, &lock->l_resource->lr_name), - "Lock res_id: %lu/%lu/%lu, fid: %lu/%lu/%lu.\n", - (unsigned long)lock->l_resource->lr_name.name[0], - (unsigned long)lock->l_resource->lr_name.name[1], - (unsigned long)lock->l_resource->lr_name.name[2], - (unsigned long)fid_seq(&mdt_body->fid1), - (unsigned long)fid_oid(&mdt_body->fid1), - (unsigned long)fid_ver(&mdt_body->fid1)); + "Lock res_id: "DLDLMRES", fid: "DFID"\n", + PLDLMRES(lock->l_resource), PFID(&mdt_body->fid1)); LDLM_LOCK_PUT(lock); memcpy(&old_lock, lockh, sizeof(*lockh)); diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 12a9ede21a85..93b601d1ff38 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -788,8 +788,8 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, /* We've given up the lock, prepare ourselves to update. */ LDLM_DEBUG(lock, "MGC cancel CB"); - CDEBUG(D_MGC, "Lock res "LPX64" (%.8s)\n", - lock->l_resource->lr_name.name[0], + CDEBUG(D_MGC, "Lock res "DLDLMRES" (%.8s)\n", + PLDLMRES(lock->l_resource), (char *)&lock->l_resource->lr_name.name[0]); if (!cld) { -- cgit v1.2.3 From 4f317748f2660cb62bcf43aac368aa42dbeb2b78 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Thu, 21 Nov 2013 22:24:50 +0800 Subject: staging/lustre/lnet: Fix assert on empty group in selftest module The core of the issue is that the selftest module doesn't sanitize its own API, but it depends on lst utility to do such checks. As a result this issue manifests itself in this particular LU through an assert on an empty group. If the NID is misspelled then an empty group is added. An error output is provided, but if that's never checked in a batch script, as is the case with this issue, then the script will try to add an empty group to a test to run in a batch, and that will cause an assert The fix is two fold. Ensure that lst utility checks that a group is added with at least one node. If not the group is subsequently deleted. And the add_test command would fail, since the group no longer exists. The second fix is to ensure that the kernel module itself sanitizes its own API in this particular case, so that if a different utility is used other than lst to communicate with the selftest kernel module then this error would be caught. This fix looks up the batch and the groups, src and dst, in the ioctl handle and sanitizes that input at this point. If the group looked up either doesn't exist or doesn't have at least one ACTIVE node, then the command fails. NOTE:there are many other cases in the code where the selftest kernel module doesn't check for sanity of the input, but depends totally on the lst module to do such checks. Particularly around length of strings passed in. Thus it is possible to crash the selftest module if someone tries to create another userspace app to communicate with the selftest kernel module without ensuring sanity of the params sent to the kernel module. In effect, it's always assumed that lst is the front end for selftest and no other front end is to be used. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3093 Lustre-change: http://review.whamcloud.com/6092 Signed-off-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Liang Zhen Reviewed-by: Oleg Drokin [coding style fix of the original patch is splitted into a new one -- PengTao] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/console.c | 79 +++++++++++++++++++------- drivers/staging/lustre/lnet/selftest/console.h | 6 +- 2 files changed, 61 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 067a8b535f7c..9556bc0412d6 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1237,41 +1237,77 @@ again: goto again; } -int -lstcon_test_add(char *name, int type, int loop, int concur, - int dist, int span, char *src_name, char * dst_name, - void *param, int paramlen, int *retp, - struct list_head *result_up) +static int +lstcon_verify_batch(const char *name, lstcon_batch_t **batch) { - lstcon_group_t *src_grp = NULL; - lstcon_group_t *dst_grp = NULL; - lstcon_test_t *test = NULL; - lstcon_batch_t *batch; - int rc; + int rc; - rc = lstcon_batch_find(name, &batch); + rc = lstcon_batch_find(name, batch); if (rc != 0) { CDEBUG(D_NET, "Can't find batch %s\n", name); return rc; } - if (batch->bat_state != LST_BATCH_IDLE) { + if ((*batch)->bat_state != LST_BATCH_IDLE) { CDEBUG(D_NET, "Can't change running batch %s\n", name); - return rc; + return -EINVAL; } - rc = lstcon_group_find(src_name, &src_grp); + return 0; +} + +static int +lstcon_verify_group(const char *name, lstcon_group_t **grp) +{ + int rc; + lstcon_ndlink_t *ndl; + + rc = lstcon_group_find(name, grp); if (rc != 0) { - CDEBUG(D_NET, "Can't find group %s\n", src_name); - goto out; + CDEBUG(D_NET, "can't find group %s\n", name); + return rc; } - rc = lstcon_group_find(dst_name, &dst_grp); - if (rc != 0) { - CDEBUG(D_NET, "Can't find group %s\n", dst_name); - goto out; + list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) { + if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE) + return 0; } + CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name); + + return -EINVAL; +} + +int +lstcon_test_add(char *batch_name, int type, int loop, + int concur, int dist, int span, + char *src_name, char *dst_name, + void *param, int paramlen, int *retp, + struct list_head *result_up) +{ + lstcon_test_t *test = NULL; + int rc; + lstcon_group_t *src_grp = NULL; + lstcon_group_t *dst_grp = NULL; + lstcon_batch_t *batch = NULL; + + /* + * verify that a batch of the given name exists, and the groups + * that will be part of the batch exist and have at least one + * active node + */ + rc = lstcon_verify_batch(batch_name, &batch); + if (rc != 0) + goto out; + + rc = lstcon_verify_group(src_name, &src_grp); + if (rc != 0) + goto out; + + rc = lstcon_verify_group(dst_name, &dst_grp); + if (rc != 0) + goto out; + if (dst_grp->grp_userland) *retp = 1; @@ -1310,7 +1346,8 @@ lstcon_test_add(char *name, int type, int loop, int concur, if (lstcon_trans_stat()->trs_rpc_errno != 0 || lstcon_trans_stat()->trs_fwk_errno != 0) - CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type, name); + CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type, + batch_name); /* add to test list anyway, so user can check what's going on */ list_add_tail(&test->tes_link, &batch->bat_test_list); diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index e61b26687dbb..b57dbd80478a 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -224,9 +224,9 @@ extern int lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up); extern int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, int timeout, struct list_head *result_up); -extern int lstcon_test_add(char *name, int type, int loop, int concur, - int dist, int span, char *src_name, char * dst_name, +extern int lstcon_test_add(char *batch_name, int type, int loop, + int concur, int dist, int span, + char *src_name, char *dst_name, void *param, int paramlen, int *retp, struct list_head *result_up); - #endif -- cgit v1.2.3 From 7575c917cf29824b71c4dff8274fe39fc32bc173 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 22:54:03 +0000 Subject: bfin_mac: Implement the SIOCGHWTSTAMP ioctl Compile-tested only (thanks to the kbuild test robot). Signed-off-by: Ben Hutchings --- drivers/net/ethernet/adi/bfin_mac.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index 75fb1d20d6fd..0d4f29579879 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -667,8 +667,8 @@ static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result) return 1000000000UL / ppn; } -static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) +static int bfin_mac_hwtstamp_set(struct net_device *netdev, + struct ifreq *ifr) { struct hwtstamp_config config; struct bfin_mac_local *lp = netdev_priv(netdev); @@ -824,6 +824,16 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, -EFAULT : 0; } +static int bfin_mac_hwtstamp_get(struct net_device *netdev, + struct ifreq *ifr) +{ + struct bfin_mac_local *lp = netdev_priv(netdev); + + return copy_to_user(ifr->ifr_data, &lp->stamp_cfg, + sizeof(lp->stamp_cfg)) ? + -EFAULT : 0; +} + static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); @@ -1062,7 +1072,8 @@ static void bfin_phc_release(struct bfin_mac_local *lp) #else # define bfin_mac_hwtstamp_is_none(cfg) 0 # define bfin_mac_hwtstamp_init(dev) -# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP) +# define bfin_mac_hwtstamp_set(dev, ifr) (-EOPNOTSUPP) +# define bfin_mac_hwtstamp_get(dev, ifr) (-EOPNOTSUPP) # define bfin_rx_hwtstamp(dev, skb) # define bfin_tx_hwtstamp(dev, skb) # define bfin_phc_init(netdev, dev) 0 @@ -1496,7 +1507,9 @@ static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCSHWTSTAMP: - return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd); + return bfin_mac_hwtstamp_set(netdev, ifr); + case SIOCGHWTSTAMP: + return bfin_mac_hwtstamp_get(netdev, ifr); default: if (lp->phydev) return phy_mii_ioctl(lp->phydev, ifr, cmd); -- cgit v1.2.3 From 7260899bde50cbe84bdf0a15b5642e2c3b03db32 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 22:59:43 +0000 Subject: tg3: Implement the SIOCGHWTSTAMP ioctl While we're doing this, fix the error code for SIOCSHWTSTAMP ioctl on non-timestamping hardware. Compile-tested only. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/broadcom/tg3.c | 71 ++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a9e068423ba0..539c6ace1706 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -13603,14 +13603,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, } -static int tg3_hwtstamp_ioctl(struct net_device *dev, - struct ifreq *ifr, int cmd) +static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) { struct tg3 *tp = netdev_priv(dev); struct hwtstamp_config stmpconf; if (!tg3_flag(tp, PTP_CAPABLE)) - return -EINVAL; + return -EOPNOTSUPP; if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) return -EFAULT; @@ -13691,6 +13690,67 @@ static int tg3_hwtstamp_ioctl(struct net_device *dev, -EFAULT : 0; } +static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) +{ + struct tg3 *tp = netdev_priv(dev); + struct hwtstamp_config stmpconf; + + if (!tg3_flag(tp, PTP_CAPABLE)) + return -EOPNOTSUPP; + + stmpconf.flags = 0; + stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ? + HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF); + + switch (tp->rxptpctl) { + case 0: + stmpconf.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; + break; + default: + WARN_ON_ONCE(1); + return -ERANGE; + } + + return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? + -EFAULT : 0; +} + static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); @@ -13744,7 +13804,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; case SIOCSHWTSTAMP: - return tg3_hwtstamp_ioctl(dev, ifr, cmd); + return tg3_hwtstamp_set(dev, ifr); + + case SIOCGHWTSTAMP: + return tg3_hwtstamp_get(dev, ifr); default: /* do nothing */ -- cgit v1.2.3 From 1d5244d0e43b70565d3988a52c6461ee42d3927c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:02:44 +0000 Subject: fec: Implement the SIOCGHWTSTAMP ioctl This is untested. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/freescale/fec.h | 3 ++- drivers/net/ethernet/freescale/fec_main.c | 8 ++++++-- drivers/net/ethernet/freescale/fec_ptp.c | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 0120217a16dd..3b8d6d19ff05 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -339,7 +339,8 @@ struct fec_enet_private { void fec_ptp_init(struct platform_device *pdev); void fec_ptp_start_cyclecounter(struct net_device *ndev); -int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); +int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); +int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); /****************************************************************************/ #endif /* FEC_H */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 4cbebf3d80eb..40e953e81eb5 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1684,8 +1684,12 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) if (!phydev) return -ENODEV; - if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex) - return fec_ptp_ioctl(ndev, rq, cmd); + if (fep->bufdesc_ex) { + if (cmd == SIOCSHWTSTAMP) + return fec_ptp_set(ndev, rq); + if (cmd == SIOCGHWTSTAMP) + return fec_ptp_get(ndev, rq); + } return phy_mii_ioctl(phydev, rq, cmd); } diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 5007e4f9fff9..3a74ea48fd40 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -274,7 +274,7 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, * @ifreq: ioctl data * @cmd: particular ioctl requested */ -int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) { struct fec_enet_private *fep = netdev_priv(ndev); @@ -321,6 +321,20 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) -EFAULT : 0; } +int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + struct hwtstamp_config config; + + config.flags = 0; + config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + config.rx_filter = (fep->hwts_rx_en ? + HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + /** * fec_time_keep - call timecounter_read every second to avoid timer overrun * because ENET just support 32bit counter, will timeout in 4s -- cgit v1.2.3 From ca0c88c2897581fa70227d408c43fb4efb7b7631 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:05:27 +0000 Subject: gianfar: Implement the SIOCGHWTSTAMP ioctl This is untested. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/freescale/gianfar.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index b14d7904a075..365342d293e8 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -795,8 +795,7 @@ err_grp_init: return err; } -static int gfar_hwtstamp_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) +static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) { struct hwtstamp_config config; struct gfar_private *priv = netdev_priv(netdev); @@ -845,7 +844,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev, -EFAULT : 0; } -/* Ioctl MII Interface */ +static int gfar_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) +{ + struct hwtstamp_config config; + struct gfar_private *priv = netdev_priv(netdev); + + config.flags = 0; + config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + config.rx_filter = (priv->hwts_rx_en ? + HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct gfar_private *priv = netdev_priv(dev); @@ -854,7 +866,9 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EINVAL; if (cmd == SIOCSHWTSTAMP) - return gfar_hwtstamp_ioctl(dev, rq, cmd); + return gfar_hwtstamp_set(dev, rq); + if (cmd == SIOCGHWTSTAMP) + return gfar_hwtstamp_get(dev, rq); if (!priv->phydev) return -ENODEV; -- cgit v1.2.3 From 4e8cff6480932f3ebe865614a1f2274e1983d08c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:07:16 +0000 Subject: e1000e: Implement the SIOCGHWTSTAMP ioctl Compile-tested only. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/intel/e1000e/netdev.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index f02816575369..03e6af736de4 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5790,7 +5790,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, * specified. Matching the kind of event packet is not supported, with the * exception of "all V2 events regardless of level 2 or 4". **/ -static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) +static int e1000e_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) { struct e1000_adapter *adapter = netdev_priv(netdev); struct hwtstamp_config config; @@ -5825,6 +5825,14 @@ static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) sizeof(config)) ? -EFAULT : 0; } +static int e1000e_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + return copy_to_user(ifr->ifr_data, &adapter->hwtstamp_config, + sizeof(adapter->hwtstamp_config)) ? -EFAULT : 0; +} + static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { @@ -5833,7 +5841,9 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case SIOCSMIIREG: return e1000_mii_ioctl(netdev, ifr, cmd); case SIOCSHWTSTAMP: - return e1000e_hwtstamp_ioctl(netdev, ifr); + return e1000e_hwtstamp_set(netdev, ifr); + case SIOCGHWTSTAMP: + return e1000e_hwtstamp_get(netdev, ifr); default: return -EOPNOTSUPP; } -- cgit v1.2.3 From 100dbda8e40bf4b537332d909660ddf9945196ff Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:13:31 +0000 Subject: mlx4_en: Implement the SIOCGHWTSTAMP ioctl Compile-tested only. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index e72d8a112a6b..709e5ec5ce14 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2025,7 +2025,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) +static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -2084,11 +2084,21 @@ static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) sizeof(config)) ? -EFAULT : 0; } +static int mlx4_en_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + + return copy_to_user(ifr->ifr_data, &priv->hwtstamp_config, + sizeof(priv->hwtstamp_config)) ? -EFAULT : 0; +} + static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { switch (cmd) { case SIOCSHWTSTAMP: - return mlx4_en_hwtstamp_ioctl(dev, ifr); + return mlx4_en_hwtstamp_set(dev, ifr); + case SIOCGHWTSTAMP: + return mlx4_en_hwtstamp_get(dev, ifr); default: return -EOPNOTSUPP; } -- cgit v1.2.3 From 450e55e996e714250baee79e334e879ee659bd11 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:16:23 +0000 Subject: vxge: Implement the SIOCGHWTSTAMP ioctl Compile-tested only. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/neterion/vxge/vxge-main.c | 27 ++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 8614eeb7de81..33f98eca5dc3 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -3185,7 +3185,7 @@ static enum vxge_hw_status vxge_timestamp_config(struct __vxge_hw_device *devh) return status; } -static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) +static int vxge_hwtstamp_set(struct vxgedev *vdev, void __user *data) { struct hwtstamp_config config; int i; @@ -3246,6 +3246,21 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) return 0; } +static int vxge_hwtstamp_get(struct vxgedev *vdev, void __user *data) +{ + struct hwtstamp_config config; + + config.flags = 0; + config.tx_type = HWTSTAMP_TX_OFF; + config.rx_filter = (vdev->rx_hwts ? + HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); + + if (copy_to_user(data, &config, sizeof(config))) + return -EFAULT; + + return 0; +} + /** * vxge_ioctl * @dev: Device pointer. @@ -3259,19 +3274,15 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data) static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct vxgedev *vdev = netdev_priv(dev); - int ret; switch (cmd) { case SIOCSHWTSTAMP: - ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data); - if (ret) - return ret; - break; + return vxge_hwtstamp_set(vdev, rq->ifr_data); + case SIOCGHWTSTAMP: + return vxge_hwtstamp_get(vdev, rq->ifr_data); default: return -EOPNOTSUPP; } - - return 0; } /** -- cgit v1.2.3 From a5b4145ba937b76dd698ad6fe5c5f37e0edbac43 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:23:40 +0000 Subject: ti_cpsw: Implement the SIOCGHWTSTAMP ioctl This is untested. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/ti/cpsw.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 7536a4c01293..bc0cb154fc53 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1322,7 +1322,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv) __raw_writel(ETH_P_1588, &priv->regs->ts_ltype); } -static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) +static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) { struct cpsw_priv *priv = netdev_priv(dev); struct cpts *cpts = priv->cpts; @@ -1383,6 +1383,24 @@ static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; } +static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) +{ + struct cpsw_priv *priv = netdev_priv(dev); + struct cpts *cpts = priv->cpts; + struct hwtstamp_config cfg; + + if (priv->version != CPSW_VERSION_1 && + priv->version != CPSW_VERSION_2) + return -EOPNOTSUPP; + + cfg.flags = 0; + cfg.tx_type = cpts->tx_enable ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + cfg.rx_filter = (cpts->rx_enable ? + HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE); + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; +} + #endif /*CONFIG_TI_CPTS*/ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) @@ -1397,7 +1415,9 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) switch (cmd) { #ifdef CONFIG_TI_CPTS case SIOCSHWTSTAMP: - return cpsw_hwtstamp_ioctl(dev, req); + return cpsw_hwtstamp_set(dev, req); + case SIOCGHWTSTAMP: + return cpsw_hwtstamp_get(dev, req); #endif case SIOCGMIIPHY: data->phy_id = priv->slaves[slave_no].phy->addr; -- cgit v1.2.3 From 6ab96d1e06ba1452d583f3e45d6a3a45bb36b1c3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:25:20 +0000 Subject: tile_net: Implement the SIOCGHWTSTAMP ioctl Compile-tested only (thanks to the kbuild test robot). Signed-off-by: Ben Hutchings --- drivers/net/ethernet/tile/tilegx.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 628b736e5ae7..858f9a786b8c 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -481,8 +481,7 @@ static void tile_tx_timestamp(struct sk_buff *skb, int instance) } /* Use ioctl() to enable or disable TX or RX timestamping. */ -static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, - int cmd) +static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq) { #ifdef CONFIG_PTP_1588_CLOCK_TILEGX struct hwtstamp_config config; @@ -535,6 +534,21 @@ static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, #endif } +static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq) +{ +#ifdef CONFIG_PTP_1588_CLOCK_TILEGX + struct tile_net_priv *priv = netdev_priv(dev); + + if (copy_to_user(rq->ifr_data, &priv->stamp_cfg, + sizeof(priv->stamp_cfg))) + return -EFAULT; + + return 0; +#else + return -EOPNOTSUPP; +#endif +} + static inline bool filter_packet(struct net_device *dev, void *buf) { /* Filter packets received before we're up. */ @@ -2098,7 +2112,9 @@ static void tile_net_tx_timeout(struct net_device *dev) static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { if (cmd == SIOCSHWTSTAMP) - return tile_hwtstamp_ioctl(dev, rq, cmd); + return tile_hwtstamp_set(dev, rq); + if (cmd == SIOCGHWTSTAMP) + return tile_hwtstamp_get(dev, rq); return -EOPNOTSUPP; } -- cgit v1.2.3 From 81fc347a0f0ab460276e3800147aaf2e8b32b466 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 18 Nov 2013 23:28:30 +0000 Subject: ixp4xx_eth: Implement the SIOCGHWTSTAMP ioctl This is untested. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/xscale/ixp4xx_eth.c | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index bcc224a83734..25283f17d82f 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -373,7 +373,7 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); } -static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) { struct hwtstamp_config cfg; struct ixp46x_ts_regs *regs; @@ -417,6 +417,32 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; } +static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) +{ + struct hwtstamp_config cfg; + struct port *port = netdev_priv(netdev); + + cfg.flags = 0; + cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + + switch (port->hwts_rx_en) { + case 0: + cfg.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case PTP_SLAVE_MODE: + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + break; + case PTP_MASTER_MODE: + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + break; + default: + WARN_ON_ONCE(1); + return -ERANGE; + } + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; +} + static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, int write, u16 cmd) { @@ -959,8 +985,12 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) if (!netif_running(dev)) return -EINVAL; - if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP) - return hwtstamp_ioctl(dev, req, cmd); + if (cpu_is_ixp46x()) { + if (cmd == SIOCSHWTSTAMP) + return hwtstamp_set(dev, req); + if (cmd == SIOCGHWTSTAMP) + return hwtstamp_get(dev, req); + } return phy_mii_ioctl(port->phydev, req, cmd); } -- cgit v1.2.3 From 432f3342e0fc4d5601b2168fe251f9219bdc97d3 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 21 Nov 2013 16:49:46 +0100 Subject: i915, debugfs: Fix uninitialized warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc complains that: drivers/gpu/drm/i915/i915_debugfs.c: In function ‘display_crc_ctl_write’: drivers/gpu/drm/i915/i915_debugfs.c:2393:2: warning: ‘val’ may be used uninitialized in this function [-Wuninitialized] drivers/gpu/drm/i915/i915_debugfs.c:2350:6: note: ‘val’ was declared here but it can't see that we're going to use val only in the success case. So shut it up. Cc: Daniel Vetter Cc: David Airlie Cc: intel-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Borislav Petkov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d1491f8e0f39..97c304ea4760 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2349,7 +2349,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - u32 val; + u32 val = 0; /* shut up gcc */ int ret; if (pipe_crc->source == source) -- cgit v1.2.3 From 6605782f79ccb3b840e302079770d24f2c1be96e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 21 Nov 2013 15:29:55 +0100 Subject: i915, fbdev: Fix Kconfig typo Too many t's. Cc: Daniel Vetter Cc: intel-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Borislav Petkov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index b0fa4c4055ee..73ed59eff139 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -44,7 +44,7 @@ config DRM_I915_KMS If in doubt, say "Y". config DRM_I915_FBDEV - bool "Enable legacy fbdev support for the modesettting intel driver" + bool "Enable legacy fbdev support for the modesetting intel driver" depends on DRM_I915 select DRM_KMS_FB_HELPER select FB_CFB_FILLRECT -- cgit v1.2.3 From 8f1ae77f466660b6da2455cccecc07ae631fa66d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 24 Sep 2013 11:07:43 +0300 Subject: reset: Add Allwinner SoCs Reset Controller Driver The Allwinner A31 and most of the other Allwinner SoCs have an IP maintaining a few other IPs in the SoC in reset by default. Among these IPs are the A31's High Speed Timers, hence why we can't use the regular driver construct in every cases, and need to call the registering function directly during machine initialisation. Apart from this, the implementation is fairly straightforward, and could easily be moved to a generic MMIO-based reset controller driver if the need ever arise. Signed-off-by: Maxime Ripard Acked-by: Philipp Zabel --- drivers/reset/Makefile | 1 + drivers/reset/reset-sunxi.c | 175 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 drivers/reset/reset-sunxi.c (limited to 'drivers') diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 1e2d83f2b995..cc29832c9638 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o +obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c new file mode 100644 index 000000000000..695bd3496eba --- /dev/null +++ b/drivers/reset/reset-sunxi.c @@ -0,0 +1,175 @@ +/* + * Allwinner SoCs Reset Controller driver + * + * Copyright 2013 Maxime Ripard + * + * Maxime Ripard + * + * 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 + +struct sunxi_reset_data { + spinlock_t lock; + void __iomem *membase; + struct reset_controller_dev rcdev; +}; + +static int sunxi_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct sunxi_reset_data *data = container_of(rcdev, + struct sunxi_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * 4)); + writel(reg & ~BIT(offset), data->membase + (bank * 4)); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int sunxi_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct sunxi_reset_data *data = container_of(rcdev, + struct sunxi_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * 4)); + writel(reg | BIT(offset), data->membase + (bank * 4)); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static struct reset_control_ops sunxi_reset_ops = { + .assert = sunxi_reset_assert, + .deassert = sunxi_reset_deassert, +}; + +static int sunxi_reset_init(struct device_node *np) +{ + struct sunxi_reset_data *data; + struct resource res; + resource_size_t size; + int ret; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + goto err_alloc; + + size = resource_size(&res); + if (!request_mem_region(res.start, size, np->name)) { + ret = -EBUSY; + goto err_alloc; + } + + data->membase = ioremap(res.start, size); + if (!data->membase) { + ret = -ENOMEM; + goto err_alloc; + } + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = size * 32; + data->rcdev.ops = &sunxi_reset_ops; + data->rcdev.of_node = np; + reset_controller_register(&data->rcdev); + + return 0; + +err_alloc: + kfree(data); + return ret; +}; + +/* + * These are the reset controller we need to initialize early on in + * our system, before we can even think of using a regular device + * driver for it. + */ +static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = { + { .compatible = "allwinner,sun6i-a31-ahb1-reset", }, + { /* sentinel */ }, +}; + +void __init sun6i_reset_init(void) +{ + struct device_node *np; + + for_each_matching_node(np, sunxi_early_reset_dt_ids) + sunxi_reset_init(np); +} + +/* + * And these are the controllers we can register through the regular + * device model. + */ +static const struct of_device_id sunxi_reset_dt_ids[] = { + { .compatible = "allwinner,sun6i-a31-clock-reset", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, sunxi_reset_dt_ids); + +static int sunxi_reset_probe(struct platform_device *pdev) +{ + return sunxi_reset_init(pdev->dev.of_node); +} + +static int sunxi_reset_remove(struct platform_device *pdev) +{ + struct sunxi_reset_data *data = platform_get_drvdata(pdev); + + reset_controller_unregister(&data->rcdev); + iounmap(data->membase); + kfree(data); + + return 0; +} + +static struct platform_driver sunxi_reset_driver = { + .probe = sunxi_reset_probe, + .remove = sunxi_reset_remove, + .driver = { + .name = "sunxi-reset", + .owner = THIS_MODULE, + .of_match_table = sunxi_reset_dt_ids, + }, +}; +module_platform_driver(sunxi_reset_driver); + +MODULE_AUTHOR("Maxime Ripard Date: Fri, 22 Nov 2013 21:52:12 +0100 Subject: ACPI / scan: Define non-empty device removal handler If an ACPI namespace node is removed (usually, as a result of a table unload), and there is a data object attached to that node, acpi_ns_delete_node() executes the removal handler submitted to acpi_attach_data() for that object. That handler is currently empty for struct acpi_device objects, so it is necessary to detach those objects from the corresponding ACPI namespace nodes in advance every time a table unload may happen. That is cumbersome and inefficient and leads to some design constraints that turn out to be quite inconvenient (in particular, struct acpi_device objects cannot be registered for namespace nodes representing devices that are not reported as present or functional by _STA). For this reason, introduce a non-empty removal handler for ACPI device objects that will unregister them when their ACPI namespace nodes go away. This code modification alone should not change functionality except for the ordering of the ACPI hotplug workqueue which should not matter (without subsequent code changes). Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/internal.h | 2 + drivers/acpi/osl.c | 6 ++- drivers/acpi/scan.c | 114 +++++++++++++++++++++++++++++++++++++++--------- include/acpi/acpi_bus.h | 1 + 4 files changed, 102 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a29739c0ba79..d8606498bf6f 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -73,6 +73,8 @@ void acpi_lpss_init(void); static inline void acpi_lpss_init(void) {} #endif +bool acpi_queue_hotplug_work(struct work_struct *work); + /* -------------------------------------------------------------------------- Device Node Initialization / Removal -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 54a20ff4b864..5b9a785e2155 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1215,6 +1215,10 @@ acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src) return AE_OK; } +bool acpi_queue_hotplug_work(struct work_struct *work) +{ + return queue_work(kacpi_hotplug_wq, work); +} acpi_status acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) @@ -1794,7 +1798,7 @@ acpi_status __init acpi_os_initialize1(void) { kacpid_wq = alloc_workqueue("kacpid", 0, 1); kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); - kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1); + kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); BUG_ON(!kacpid_wq); BUG_ON(!kacpi_notify_wq); BUG_ON(!kacpi_hotplug_wq); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fd39459926b1..ad2522015e5e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -14,6 +14,8 @@ #include +#include + #include "internal.h" #define _COMPONENT ACPI_BUS_COMPONENT @@ -27,6 +29,8 @@ extern struct acpi_device *acpi_root; #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) +#define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) + /* * If set, devices will be hot-removed even if they cannot be put offline * gracefully (from the kernel's standpoint). @@ -907,9 +911,91 @@ struct bus_type acpi_bus_type = { .uevent = acpi_device_uevent, }; -static void acpi_bus_data_handler(acpi_handle handle, void *context) +static void acpi_device_del(struct acpi_device *device) +{ + mutex_lock(&acpi_device_lock); + if (device->parent) + list_del(&device->node); + + list_del(&device->wakeup_list); + mutex_unlock(&acpi_device_lock); + + acpi_power_add_remove_device(device, false); + acpi_device_remove_files(device); + if (device->remove) + device->remove(device); + + device_del(&device->dev); +} + +static LIST_HEAD(acpi_device_del_list); +static DEFINE_MUTEX(acpi_device_del_lock); + +static void acpi_device_del_work_fn(struct work_struct *work_not_used) +{ + for (;;) { + struct acpi_device *adev; + + mutex_lock(&acpi_device_del_lock); + + if (list_empty(&acpi_device_del_list)) { + mutex_unlock(&acpi_device_del_lock); + break; + } + adev = list_first_entry(&acpi_device_del_list, + struct acpi_device, del_list); + list_del(&adev->del_list); + + mutex_unlock(&acpi_device_del_lock); + + acpi_device_del(adev); + /* + * Drop references to all power resources that might have been + * used by the device. + */ + acpi_power_transition(adev, ACPI_STATE_D3_COLD); + put_device(&adev->dev); + } +} + +/** + * acpi_scan_drop_device - Drop an ACPI device object. + * @handle: Handle of an ACPI namespace node, not used. + * @context: Address of the ACPI device object to drop. + * + * This is invoked by acpi_ns_delete_node() during the removal of the ACPI + * namespace node the device object pointed to by @context is attached to. + * + * The unregistration is carried out asynchronously to avoid running + * acpi_device_del() under the ACPICA's namespace mutex and the list is used to + * ensure the correct ordering (the device objects must be unregistered in the + * same order in which the corresponding namespace nodes are deleted). + */ +static void acpi_scan_drop_device(acpi_handle handle, void *context) { - /* Intentionally empty. */ + static DECLARE_WORK(work, acpi_device_del_work_fn); + struct acpi_device *adev = context; + + mutex_lock(&acpi_device_del_lock); + + /* + * Use the ACPI hotplug workqueue which is ordered, so this work item + * won't run after any hotplug work items submitted subsequently. That + * prevents attempts to register device objects identical to those being + * deleted from happening concurrently (such attempts result from + * hotplug events handled via the ACPI hotplug workqueue). It also will + * run after all of the work items submitted previosuly, which helps + * those work items to ensure that they are not accessing stale device + * objects. + */ + if (list_empty(&acpi_device_del_list)) + acpi_queue_hotplug_work(&work); + + list_add_tail(&adev->del_list, &acpi_device_del_list); + /* Make acpi_ns_validate_handle() return NULL for this handle. */ + adev->handle = INVALID_ACPI_HANDLE; + + mutex_unlock(&acpi_device_del_lock); } int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) @@ -919,7 +1005,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) if (!device) return -EINVAL; - status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); + status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); if (ACPI_FAILURE(status) || !*device) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", handle)); @@ -939,7 +1025,7 @@ int acpi_device_add(struct acpi_device *device, if (device->handle) { acpi_status status; - status = acpi_attach_data(device->handle, acpi_bus_data_handler, + status = acpi_attach_data(device->handle, acpi_scan_drop_device, device); if (ACPI_FAILURE(status)) { acpi_handle_err(device->handle, @@ -957,6 +1043,7 @@ int acpi_device_add(struct acpi_device *device, INIT_LIST_HEAD(&device->node); INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); + INIT_LIST_HEAD(&device->del_list); mutex_init(&device->physical_node_lock); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); @@ -1020,27 +1107,14 @@ int acpi_device_add(struct acpi_device *device, mutex_unlock(&acpi_device_lock); err_detach: - acpi_detach_data(device->handle, acpi_bus_data_handler); + acpi_detach_data(device->handle, acpi_scan_drop_device); return result; } static void acpi_device_unregister(struct acpi_device *device) { - mutex_lock(&acpi_device_lock); - if (device->parent) - list_del(&device->node); - - list_del(&device->wakeup_list); - mutex_unlock(&acpi_device_lock); - - acpi_detach_data(device->handle, acpi_bus_data_handler); - - acpi_power_add_remove_device(device, false); - acpi_device_remove_files(device); - if (device->remove) - device->remove(device); - - device_del(&device->dev); + acpi_detach_data(device->handle, acpi_scan_drop_device); + acpi_device_del(device); /* * Transition the device to D3cold to drop the reference counts of all * power resources the device depends on and turn off the ones that have diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c602c7718421..9fe5f63155ed 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -299,6 +299,7 @@ struct acpi_device { struct list_head children; struct list_head node; struct list_head wakeup_list; + struct list_head del_list; struct acpi_device_status status; struct acpi_device_flags flags; struct acpi_device_pnp pnp; -- cgit v1.2.3 From 202317a573b20d77a9abb7c16a3fd5b40cef3d9d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:54:37 +0100 Subject: ACPI / scan: Add acpi_device objects for all device nodes in the namespace Modify the ACPI namespace scanning code to register a struct acpi_device object for every namespace node representing a device, processor and so on, even if the device represented by that namespace node is reported to be not present and not functional by _STA. There are multiple reasons to do that. First of all, it avoids quite a lot of overhead when struct acpi_device objects are deleted every time acpi_bus_trim() is run and then added again by a subsequent acpi_bus_scan() for the same scope, although the namespace objects they correspond to stay in memory all the time (which always is the case on a vast majority of systems). Second, it will allow user space to see that there are namespace nodes representing devices that are not present at the moment and may be added to the system. It will also allow user space to evaluate _SUN for those nodes to check what physical slots the "missing" devices may be put into and it will make sense to add a sysfs attribute for _STA evaluation after this change (that will be useful for thermal management on some systems). Next, it will help to consolidate the ACPI hotplug handling among subsystems by making it possible to store hotplug-related information in struct acpi_device objects in a standard common way. Finally, it will help to avoid a race condition related to the deletion of ACPI namespace nodes. Namely, namespace nodes may be deleted as a result of a table unload triggered by _EJ0 or _DCK. If a hotplug notification for one of those nodes is triggered right before the deletion and it executes a hotplug callback via acpi_hotplug_execute(), the ACPI handle passed to that callback may be stale when the callback actually runs. One way to work around that is to always pass struct acpi_device pointers to hotplug callbacks after doing a get_device() on the objects in question which eliminates the use-after-free possibility (the ACPI handles in those objects are invalidated by acpi_scan_drop_device(), so they will trigger ACPICA errors on attempts to use them). Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- Documentation/acpi/namespace.txt | 9 +--- drivers/acpi/device_pm.c | 22 ++++++-- drivers/acpi/dock.c | 9 ++-- drivers/acpi/internal.h | 3 ++ drivers/acpi/pci_root.c | 5 +- drivers/acpi/scan.c | 107 ++++++++++++++++++------------------- drivers/pci/hotplug/acpiphp_glue.c | 2 +- drivers/xen/xen-acpi-cpuhotplug.c | 8 +-- drivers/xen/xen-acpi-memhotplug.c | 7 +-- include/acpi/acpi_bus.h | 9 +++- 10 files changed, 97 insertions(+), 84 deletions(-) (limited to 'drivers') diff --git a/Documentation/acpi/namespace.txt b/Documentation/acpi/namespace.txt index 260f6a3661fa..1860cb3865c6 100644 --- a/Documentation/acpi/namespace.txt +++ b/Documentation/acpi/namespace.txt @@ -235,10 +235,6 @@ Wysocki . named object's type in the second column). In that case the object's directory in sysfs will contain the 'path' attribute whose value is the full path to the node from the namespace root. - struct acpi_device objects are created for the ACPI namespace nodes - whose _STA control methods return PRESENT or FUNCTIONING. The power - resource nodes or nodes without _STA are assumed to be both PRESENT - and FUNCTIONING. F: The struct acpi_device object is created for a fixed hardware feature (as indicated by the fixed feature flag's name in the second @@ -340,7 +336,7 @@ Wysocki . | +-------------+-------+----------------+ | | | | +- - - - - - - +- - - - - - +- - - - - - - -+ - | +-| * PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: | + | +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: | | | +- - - - - - - +- - - - - - +- - - - - - - -+ | | | | +------------+------------+-----------------------+ @@ -390,6 +386,3 @@ Wysocki . attribute (as described earlier in this document). NOTE: N/A indicates the device object does not have the 'path' or the 'modalias' attribute. - NOTE: The PNP0C0D device listed above is highlighted (marked by "*") - to indicate it will be created only when its _STA methods return - PRESENT or FUNCTIONING. diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index b3480cf7db1a..d49f1e464703 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -256,6 +256,8 @@ int acpi_bus_init_power(struct acpi_device *device) return -EINVAL; device->power.state = ACPI_STATE_UNKNOWN; + if (!acpi_device_is_present(device)) + return 0; result = acpi_device_get_power(device, &state); if (result) @@ -302,15 +304,18 @@ int acpi_device_fix_up_power(struct acpi_device *device) return ret; } -int acpi_bus_update_power(acpi_handle handle, int *state_p) +int acpi_device_update_power(struct acpi_device *device, int *state_p) { - struct acpi_device *device; int state; int result; - result = acpi_bus_get_device(handle, &device); - if (result) + if (device->power.state == ACPI_STATE_UNKNOWN) { + result = acpi_bus_init_power(device); + if (!result && state_p) + *state_p = device->power.state; + return result; + } result = acpi_device_get_power(device, &state); if (result) @@ -338,6 +343,15 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p) return 0; } + +int acpi_bus_update_power(acpi_handle handle, int *state_p) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + return result ? result : acpi_device_update_power(device, state_p); +} EXPORT_SYMBOL_GPL(acpi_bus_update_power); bool acpi_bus_power_manageable(acpi_handle handle) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index dcd73ccb514c..de032010da3c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -323,14 +323,11 @@ static int dock_present(struct dock_station *ds) */ static void dock_create_acpi_device(acpi_handle handle) { - struct acpi_device *device; + struct acpi_device *device = NULL; int ret; - if (acpi_bus_get_device(handle, &device)) { - /* - * no device created for this object, - * so we should create one. - */ + acpi_bus_get_device(handle, &device); + if (!acpi_device_enumerated(device)) { ret = acpi_bus_scan(handle); if (ret) pr_debug("error adding bus, %x\n", -ret); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index d8606498bf6f..809b8082c134 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -90,6 +90,7 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); void acpi_bus_device_eject(void *data, u32 ost_src); +bool acpi_device_is_present(struct acpi_device *adev); /* -------------------------------------------------------------------------- Power Resource @@ -107,6 +108,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state); int acpi_power_on_resources(struct acpi_device *device, int state); int acpi_power_transition(struct acpi_device *device, int state); +int acpi_device_update_power(struct acpi_device *device, int *state_p); + int acpi_wakeup_device_init(void); void acpi_early_processor_set_pdc(void); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 20360e480bd8..4076491c6ded 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -634,9 +634,10 @@ void __init acpi_pci_root_init(void) static void handle_root_bridge_insertion(acpi_handle handle) { - struct acpi_device *device; + struct acpi_device *device = NULL; - if (!acpi_bus_get_device(handle, &device)) { + acpi_bus_get_device(handle, &device); + if (acpi_device_enumerated(device)) { dev_printk(KERN_DEBUG, &device->dev, "acpi device already exists; ignoring notify\n"); return; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ad2522015e5e..bc52192785f1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -259,7 +259,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_bus_trim(device); - /* Device node has been unregistered. */ put_device(&device->dev); device = NULL; @@ -328,7 +327,7 @@ void acpi_bus_device_eject(void *data, u32 ost_src) static void acpi_scan_bus_device_check(void *data, u32 ost_source) { acpi_handle handle = data; - struct acpi_device *device = NULL; + struct acpi_device *device; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; @@ -336,8 +335,9 @@ static void acpi_scan_bus_device_check(void *data, u32 ost_source) mutex_lock(&acpi_scan_lock); if (ost_source != ACPI_NOTIFY_BUS_CHECK) { + device = NULL; acpi_bus_get_device(handle, &device); - if (device) { + if (acpi_device_enumerated(device)) { dev_warn(&device->dev, "Attempt to re-insert\n"); goto out; } @@ -347,9 +347,10 @@ static void acpi_scan_bus_device_check(void *data, u32 ost_source) acpi_handle_warn(handle, "Namespace scan failure\n"); goto out; } - error = acpi_bus_get_device(handle, &device); - if (error) { - acpi_handle_warn(handle, "Missing device node object\n"); + device = NULL; + acpi_bus_get_device(handle, &device); + if (!acpi_device_enumerated(device)) { + acpi_handle_warn(handle, "Device not enumerated\n"); goto out; } ost_code = ACPI_OST_SC_SUCCESS; @@ -1111,20 +1112,6 @@ int acpi_device_add(struct acpi_device *device, return result; } -static void acpi_device_unregister(struct acpi_device *device) -{ - acpi_detach_data(device->handle, acpi_scan_drop_device); - acpi_device_del(device); - /* - * Transition the device to D3cold to drop the reference counts of all - * power resources the device depends on and turn off the ones that have - * no more references. - */ - acpi_device_set_power(device, ACPI_STATE_D3_COLD); - device->handle = NULL; - put_device(&device->dev); -} - /* -------------------------------------------------------------------------- Driver Management -------------------------------------------------------------------------- */ @@ -1703,6 +1690,8 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, acpi_set_pnp_ids(handle, &device->pnp, type); acpi_bus_get_flags(device); device->flags.match_driver = false; + device->flags.initialized = true; + device->flags.visited = false; device_initialize(&device->dev); dev_set_uevent_suppress(&device->dev, true); } @@ -1787,6 +1776,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, return 0; } +bool acpi_device_is_present(struct acpi_device *adev) +{ + if (adev->status.present || adev->status.functional) + return true; + + adev->flags.initialized = false; + return false; +} + static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, char *idstr, const struct acpi_device_id **matchid) @@ -1880,18 +1878,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, acpi_scan_init_hotplug(handle, type); - if (!(sta & ACPI_STA_DEVICE_PRESENT) && - !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { - struct acpi_device_wakeup wakeup; - - if (acpi_has_method(handle, "_PRW")) { - acpi_bus_extract_wakeup_device_power_package(handle, - &wakeup); - acpi_power_resources_list_free(&wakeup.resources); - } - return AE_CTRL_DEPTH; - } - acpi_add_single_object(&device, handle, type, sta); if (!device) return AE_CTRL_DEPTH; @@ -1930,32 +1916,50 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, void *not_used, void **ret_not_used) { struct acpi_device *device; - unsigned long long sta_not_used; + unsigned long long sta; int ret; /* * Ignore errors ignored by acpi_bus_check_add() to avoid terminating * namespace walks prematurely. */ - if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) + if (acpi_bus_type_and_status(handle, &ret, &sta)) return AE_OK; if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; + STRUCT_TO_INT(device->status) = sta; + /* Skip devices that are not present. */ + if (!acpi_device_is_present(device)) + goto err; + if (device->handler) return AE_OK; + if (!device->flags.initialized) { + acpi_bus_update_power(device, NULL); + device->flags.initialized = true; + } ret = acpi_scan_attach_handler(device); if (ret < 0) - return AE_CTRL_DEPTH; + goto err; device->flags.match_driver = true; if (ret > 0) - return AE_OK; + goto ok; ret = device_attach(&device->dev); - return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; + if (ret < 0) + goto err; + + ok: + device->flags.visited = true; + return AE_OK; + + err: + device->flags.visited = false; + return AE_CTRL_DEPTH; } /** @@ -2007,21 +2011,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, } else { device_release_driver(&device->dev); } + /* + * Most likely, the device is going away, so put it into D3cold + * before that. + */ + acpi_device_set_power(device, ACPI_STATE_D3_COLD); + device->flags.initialized = false; + device->flags.visited = false; } return AE_OK; } -static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_not_used) -{ - struct acpi_device *device = NULL; - - if (!acpi_bus_get_device(handle, &device)) - acpi_device_unregister(device); - - return AE_OK; -} - /** * acpi_bus_trim - Remove ACPI device node and all of its descendants * @start: Root of the ACPI device nodes subtree to remove. @@ -2037,13 +2037,6 @@ void acpi_bus_trim(struct acpi_device *start) acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, acpi_bus_device_detach, NULL, NULL); acpi_bus_device_detach(start->handle, 0, NULL, NULL); - /* - * Execute acpi_bus_remove() as a post-order callback to remove device - * nodes in the given namespace scope. - */ - acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, - acpi_bus_remove, NULL, NULL); - acpi_bus_remove(start->handle, 0, NULL, NULL); } EXPORT_SYMBOL_GPL(acpi_bus_trim); @@ -2121,7 +2114,9 @@ int __init acpi_scan_init(void) result = acpi_bus_scan_fixed(); if (result) { - acpi_device_unregister(acpi_root); + acpi_detach_data(acpi_root->handle, acpi_scan_drop_device); + acpi_device_del(acpi_root); + put_device(&acpi_root->dev); goto out; } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1cf605f67673..67be6bab7535 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -489,7 +489,7 @@ static void acpiphp_bus_add(acpi_handle handle) acpi_bus_scan(handle); acpi_bus_get_device(handle, &adev); - if (adev) + if (acpi_device_enumerated(adev)) acpi_device_set_power(adev, ACPI_STATE_D0); } diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c index 8dae6c13063a..73496c3d18ae 100644 --- a/drivers/xen/xen-acpi-cpuhotplug.c +++ b/drivers/xen/xen-acpi-cpuhotplug.c @@ -269,7 +269,8 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!is_processor_present(handle)) break; - if (!acpi_bus_get_device(handle, &device)) + acpi_bus_get_device(handle, &device); + if (acpi_device_enumerated(device)) break; result = acpi_bus_scan(handle); @@ -277,8 +278,9 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, pr_err(PREFIX "Unable to add the device\n"); break; } - result = acpi_bus_get_device(handle, &device); - if (result) { + device = NULL; + acpi_bus_get_device(handle, &device); + if (!acpi_device_enumerated(device)) { pr_err(PREFIX "Missing device object\n"); break; } diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c index 9083f1e474f8..9b056f06691f 100644 --- a/drivers/xen/xen-acpi-memhotplug.c +++ b/drivers/xen/xen-acpi-memhotplug.c @@ -169,7 +169,7 @@ static int acpi_memory_get_device(acpi_handle handle, acpi_scan_lock_acquire(); acpi_bus_get_device(handle, &device); - if (device) + if (acpi_device_enumerated(device)) goto end; /* @@ -182,8 +182,9 @@ static int acpi_memory_get_device(acpi_handle handle, result = -EINVAL; goto out; } - result = acpi_bus_get_device(handle, &device); - if (result) { + device = NULL; + acpi_bus_get_device(handle, &device); + if (!acpi_device_enumerated(device)) { pr_warn(PREFIX "Missing device object\n"); result = -EINVAL; goto out; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 9fe5f63155ed..e748dbfca9d5 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -169,7 +169,9 @@ struct acpi_device_flags { u32 ejectable:1; u32 power_manageable:1; u32 match_driver:1; - u32 reserved:27; + u32 initialized:1; + u32 visited:1; + u32 reserved:25; }; /* File System */ @@ -386,6 +388,11 @@ int acpi_match_device_ids(struct acpi_device *device, int acpi_create_dir(struct acpi_device *); void acpi_remove_dir(struct acpi_device *); +static inline bool acpi_device_enumerated(struct acpi_device *adev) +{ + return adev && adev->flags.initialized && adev->flags.visited; +} + typedef void (*acpi_hp_callback)(void *data, u32 src); acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); -- cgit v1.2.3 From 1ceaba05b4afb4bd7b4b4801f2718c13f59321eb Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:54:52 +0100 Subject: ACPI / hotplug: Do not fail bus and device checks for disabled hotplug If the scan handler for the given device has hotplug.enabled unset, it doesn't really make sense to fail bus check and device check notifications. First, bus check may not have anything to do with the device it is signaled for, but it may concern another device on the bus below this one. For this reason, bus check notifications should not be failed if hotplug is disabled for the target device. Second, device check notifications are signaled only after a device has already appeared (or disappeared), so failing it can only prevent scan handlers and drivers from attaching to that (already existing) device, which is not very useful. Consequently, if device hotplug is disabled through the device's scan handler, fail eject request notifications only. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/scan.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bc52192785f1..4fa416f94f52 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -363,43 +363,13 @@ static void acpi_scan_bus_device_check(void *data, u32 ost_source) unlock_device_hotplug(); } -static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) -{ - u32 ost_status; - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - acpi_handle_debug(handle, - "ACPI_NOTIFY_BUS_CHECK event: unsupported\n"); - ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; - break; - case ACPI_NOTIFY_DEVICE_CHECK: - acpi_handle_debug(handle, - "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n"); - ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; - break; - case ACPI_NOTIFY_EJECT_REQUEST: - acpi_handle_debug(handle, - "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n"); - ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - break; - default: - /* non-hotplug event; possibly handled by other handler */ - return; - } - - acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); -} - static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) { + u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; struct acpi_scan_handler *handler = data; struct acpi_device *adev; acpi_status status; - if (!handler->hotplug.enabled) - return acpi_hotplug_unsupported(handle, type); - switch (type) { case ACPI_NOTIFY_BUS_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); @@ -409,6 +379,11 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); + if (!handler->hotplug.enabled) { + acpi_handle_err(handle, "Eject disabled\n"); + ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; + goto err_out; + } if (acpi_bus_get_device(handle, &adev)) goto err_out; @@ -428,8 +403,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) return; err_out: - acpi_evaluate_hotplug_ost(handle, type, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); + acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); } static ssize_t real_power_state_show(struct device *dev, -- cgit v1.2.3 From c27b2c33b6215eeb3d5c290ac889ab6d543f6207 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:55:07 +0100 Subject: ACPI / hotplug: Introduce common hotplug function acpi_device_hotplug() Modify the common ACPI device hotplug code to always queue up the same function, acpi_device_hotplug(), using acpi_hotplug_execute() and make the PCI host bridge hotplug code use that function too for device hot removal. This allows some code duplication to be reduced and a race condition where the relevant ACPI handle may become invalid between the notification handler and the function queued up by it via acpi_hotplug_execute() to be avoided. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/internal.h | 2 +- drivers/acpi/pci_root.c | 4 +- drivers/acpi/scan.c | 141 ++++++++++++++++++++++-------------------------- 3 files changed, 68 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 809b8082c134..a0d42cf5b0c5 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -89,7 +89,7 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); -void acpi_bus_device_eject(void *data, u32 ost_src); +void acpi_device_hotplug(void *data, u32 ost_src); bool acpi_device_is_present(struct acpi_device *adev); /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 4076491c6ded..ca05064f3ff7 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -683,11 +683,13 @@ static void hotplug_event_root(void *data, u32 type) if (!root) break; + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, + ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); get_device(&root->device->dev); acpi_scan_lock_release(); - acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); + acpi_device_hotplug(root->device, ACPI_NOTIFY_EJECT_REQUEST); return; default: acpi_handle_warn(handle, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4fa416f94f52..dd0ff9de9277 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -206,12 +206,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_status status; unsigned long long sta; - /* If there is no handle, the device node has been unregistered. */ - if (!handle) { - dev_dbg(&device->dev, "ACPI handle missing\n"); - put_device(&device->dev); - return -EINVAL; - } + if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); /* * Carry out two passes here and ignore errors in the first pass, @@ -230,7 +226,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) dev_warn(errdev, "Offline disabled.\n"); acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_online, NULL, NULL, NULL); - put_device(&device->dev); return -EPERM; } acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); @@ -249,7 +244,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_online, NULL, NULL, NULL); - put_device(&device->dev); return -EBUSY; } } @@ -259,9 +253,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_bus_trim(device); - put_device(&device->dev); - device = NULL; - acpi_evaluate_lck(handle, 0); /* * TBD: _EJD support. @@ -288,77 +279,74 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -void acpi_bus_device_eject(void *data, u32 ost_src) +static int acpi_scan_device_check(struct acpi_device *adev) { - struct acpi_device *device = data; - acpi_handle handle = device->handle; - u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; int error; - lock_device_hotplug(); - mutex_lock(&acpi_scan_lock); - - if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) - acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - - if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) - kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - - error = acpi_scan_hot_remove(device); - if (error == -EPERM) { - goto err_support; - } else if (error) { - goto err_out; + /* + * This function is only called for device objects for which matching + * scan handlers exist. The only situation in which the scan handler is + * not attached to this device object yet is when the device has just + * appeared (either it wasn't present at all before or it was removed + * and then added again). + */ + if (adev->handler) { + dev_warn(&adev->dev, "Already enumerated\n"); + return -EBUSY; } - - out: - mutex_unlock(&acpi_scan_lock); - unlock_device_hotplug(); - return; - - err_support: - ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - err_out: - acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); - goto out; + error = acpi_bus_scan(adev->handle); + if (error) { + dev_warn(&adev->dev, "Namespace scan failure\n"); + return error; + } + if (adev->handler) { + if (adev->handler->hotplug.mode == AHM_CONTAINER) + kobject_uevent(&adev->dev.kobj, KOBJ_ONLINE); + } else { + dev_warn(&adev->dev, "Enumeration failure\n"); + return -ENODEV; + } + return 0; } -static void acpi_scan_bus_device_check(void *data, u32 ost_source) +void acpi_device_hotplug(void *data, u32 src) { - acpi_handle handle = data; - struct acpi_device *device; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; + struct acpi_device *adev = data; int error; lock_device_hotplug(); mutex_lock(&acpi_scan_lock); - if (ost_source != ACPI_NOTIFY_BUS_CHECK) { - device = NULL; - acpi_bus_get_device(handle, &device); - if (acpi_device_enumerated(device)) { - dev_warn(&device->dev, "Attempt to re-insert\n"); - goto out; - } - } - error = acpi_bus_scan(handle); - if (error) { - acpi_handle_warn(handle, "Namespace scan failure\n"); - goto out; - } - device = NULL; - acpi_bus_get_device(handle, &device); - if (!acpi_device_enumerated(device)) { - acpi_handle_warn(handle, "Device not enumerated\n"); + /* + * The device object's ACPI handle cannot become invalid as long as we + * are holding acpi_scan_lock, but it may have become invalid before + * that lock was acquired. + */ + if (adev->handle == INVALID_ACPI_HANDLE) goto out; + + switch (src) { + case ACPI_NOTIFY_BUS_CHECK: + error = acpi_bus_scan(adev->handle); + break; + case ACPI_NOTIFY_DEVICE_CHECK: + error = acpi_scan_device_check(adev); + break; + case ACPI_NOTIFY_EJECT_REQUEST: + case ACPI_OST_EC_OSPM_EJECT: + error = acpi_scan_hot_remove(adev); + break; + default: + error = -EINVAL; + break; } - ost_code = ACPI_OST_SC_SUCCESS; - if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) - kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); + if (!error) + ost_code = ACPI_OST_SC_SUCCESS; out: - acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); + acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); + put_device(&adev->dev); mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); } @@ -370,6 +358,9 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) struct acpi_device *adev; acpi_status status; + if (acpi_bus_get_device(handle, &adev)) + goto err_out; + switch (type) { case ACPI_NOTIFY_BUS_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); @@ -384,24 +375,20 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; goto err_out; } - if (acpi_bus_get_device(handle, &adev)) - goto err_out; - - get_device(&adev->dev); - status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); - if (ACPI_SUCCESS(status)) - return; - - put_device(&adev->dev); - goto err_out; + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, + ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); + break; default: /* non-hotplug event; possibly handled by other handler */ return; } - status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); + get_device(&adev->dev); + status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); if (ACPI_SUCCESS(status)) return; + put_device(&adev->dev); + err_out: acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); } @@ -454,7 +441,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); get_device(&acpi_device->dev); - status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, + status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, ACPI_OST_EC_OSPM_EJECT); if (ACPI_SUCCESS(status)) return count; -- cgit v1.2.3 From 3338db0057ed9f554050bd06863731c515d79672 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:55:20 +0100 Subject: ACPI / hotplug: Make ACPI PCI root hotplug use common hotplug code Rework the common ACPI device hotplug code so that it is suitable for PCI host bridge hotplug and switch the PCI host bridge scan handler to using the common hotplug code. This allows quite a few lines of code that are not necessary any more to be dropped from the PCI host bridge scan handler and removes arbitrary differences in behavior between PCI host bridge hotplug and ACPI-based hotplug of other components, like CPUs and memory. Also acpi_device_hotplug() can be static now. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/internal.h | 2 - drivers/acpi/pci_root.c | 125 +++++------------------------------------------- drivers/acpi/scan.c | 42 +++++++++------- include/acpi/acpi_bus.h | 2 +- 4 files changed, 37 insertions(+), 134 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a0d42cf5b0c5..f4aa467c407e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -28,7 +28,6 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); void acpi_pci_root_init(void); void acpi_pci_link_init(void); -void acpi_pci_root_hp_init(void); void acpi_processor_init(void); void acpi_platform_init(void); int acpi_sysfs_init(void); @@ -89,7 +88,6 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); int acpi_bind_one(struct device *dev, acpi_handle handle); int acpi_unbind_one(struct device *dev); -void acpi_device_hotplug(void *data, u32 ost_src); bool acpi_device_is_present(struct acpi_device *adev); /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ca05064f3ff7..2dd11e0bac24 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -51,6 +51,12 @@ static int acpi_pci_root_add(struct acpi_device *device, const struct acpi_device_id *not_used); static void acpi_pci_root_remove(struct acpi_device *device); +static int acpi_pci_root_scan_dependent(struct acpi_device *adev) +{ + acpiphp_check_host_bridge(adev->handle); + return 0; +} + #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ | OSC_PCI_ASPM_SUPPORT \ | OSC_PCI_CLOCK_PM_SUPPORT \ @@ -66,7 +72,8 @@ static struct acpi_scan_handler pci_root_handler = { .attach = acpi_pci_root_add, .detach = acpi_pci_root_remove, .hotplug = { - .ignore = true, + .enabled = true, + .scan_dependent = acpi_pci_root_scan_dependent, }, }; @@ -624,119 +631,9 @@ static void acpi_pci_root_remove(struct acpi_device *device) void __init acpi_pci_root_init(void) { acpi_hest_init(); - - if (!acpi_pci_disabled) { - pci_acpi_crs_quirks(); - acpi_scan_add_handler(&pci_root_handler); - } -} -/* Support root bridge hotplug */ - -static void handle_root_bridge_insertion(acpi_handle handle) -{ - struct acpi_device *device = NULL; - - acpi_bus_get_device(handle, &device); - if (acpi_device_enumerated(device)) { - dev_printk(KERN_DEBUG, &device->dev, - "acpi device already exists; ignoring notify\n"); - return; - } - - if (acpi_bus_scan(handle)) - acpi_handle_err(handle, "cannot add bridge to acpi list\n"); -} - -static void hotplug_event_root(void *data, u32 type) -{ - acpi_handle handle = data; - struct acpi_pci_root *root; - - acpi_scan_lock_acquire(); - - root = acpi_pci_find_root(handle); - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - /* bus enumerate */ - acpi_handle_printk(KERN_DEBUG, handle, - "Bus check notify on %s\n", __func__); - if (root) - acpiphp_check_host_bridge(handle); - else - handle_root_bridge_insertion(handle); - - break; - - case ACPI_NOTIFY_DEVICE_CHECK: - /* device check */ - acpi_handle_printk(KERN_DEBUG, handle, - "Device check notify on %s\n", __func__); - if (!root) - handle_root_bridge_insertion(handle); - break; - - case ACPI_NOTIFY_EJECT_REQUEST: - /* request device eject */ - acpi_handle_printk(KERN_DEBUG, handle, - "Device eject notify on %s\n", __func__); - if (!root) - break; - - acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); - get_device(&root->device->dev); - - acpi_scan_lock_release(); - - acpi_device_hotplug(root->device, ACPI_NOTIFY_EJECT_REQUEST); + if (acpi_pci_disabled) return; - default: - acpi_handle_warn(handle, - "notify_handler: unknown event type 0x%x\n", - type); - break; - } - - acpi_scan_lock_release(); -} - -static void handle_hotplug_event_root(acpi_handle handle, u32 type, - void *context) -{ - acpi_hotplug_execute(hotplug_event_root, handle, type); -} - -static acpi_status __init -find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - int *count = (int *)context; - - if (!acpi_is_root_bridge(handle)) - return AE_OK; - - (*count)++; - - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_root, NULL); - if (ACPI_FAILURE(status)) - acpi_handle_printk(KERN_DEBUG, handle, - "notify handler is not installed, exit status: %u\n", - (unsigned int)status); - else - acpi_handle_printk(KERN_DEBUG, handle, - "notify handler is installed\n"); - - return AE_OK; -} - -void __init acpi_pci_root_hp_init(void) -{ - int num = 0; - - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); - printk(KERN_DEBUG "Found %d acpi root devices\n", num); + pci_acpi_crs_quirks(); + acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root"); } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index dd0ff9de9277..18865c86c463 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -283,17 +283,6 @@ static int acpi_scan_device_check(struct acpi_device *adev) { int error; - /* - * This function is only called for device objects for which matching - * scan handlers exist. The only situation in which the scan handler is - * not attached to this device object yet is when the device has just - * appeared (either it wasn't present at all before or it was removed - * and then added again). - */ - if (adev->handler) { - dev_warn(&adev->dev, "Already enumerated\n"); - return -EBUSY; - } error = acpi_bus_scan(adev->handle); if (error) { dev_warn(&adev->dev, "Namespace scan failure\n"); @@ -309,10 +298,11 @@ static int acpi_scan_device_check(struct acpi_device *adev) return 0; } -void acpi_device_hotplug(void *data, u32 src) +static void acpi_device_hotplug(void *data, u32 src) { u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; struct acpi_device *adev = data; + struct acpi_scan_handler *handler; int error; lock_device_hotplug(); @@ -326,12 +316,32 @@ void acpi_device_hotplug(void *data, u32 src) if (adev->handle == INVALID_ACPI_HANDLE) goto out; + handler = adev->handler; + switch (src) { case ACPI_NOTIFY_BUS_CHECK: - error = acpi_bus_scan(adev->handle); + if (handler) { + error = handler->hotplug.scan_dependent ? + handler->hotplug.scan_dependent(adev) : + acpi_bus_scan(adev->handle); + } else { + error = acpi_scan_device_check(adev); + } break; case ACPI_NOTIFY_DEVICE_CHECK: - error = acpi_scan_device_check(adev); + /* + * This code is only run for device objects for which matching + * scan handlers exist. The only situation in which the scan + * handler is not attached to this device object yet is when the + * device has just appeared (either it wasn't present at all + * before or it was removed and then added again). + */ + if (adev->handler) { + dev_warn(&adev->dev, "Already enumerated\n"); + error = -EBUSY; + } else { + error = acpi_scan_device_check(adev); + } break; case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_OST_EC_OSPM_EJECT: @@ -1805,7 +1815,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) */ list_for_each_entry(hwid, &pnp.ids, list) { handler = acpi_scan_match_handler(hwid->id, NULL); - if (handler && !handler->hotplug.ignore) { + if (handler) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_hotplug_notify_cb, handler); break; @@ -2083,8 +2093,6 @@ int __init acpi_scan_init(void) acpi_update_all_gpes(); - acpi_pci_root_hp_init(); - out: mutex_unlock(&acpi_scan_lock); return result; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e748dbfca9d5..2359c69f1680 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -100,8 +100,8 @@ enum acpi_hotplug_mode { struct acpi_hotplug_profile { struct kobject kobj; bool enabled:1; - bool ignore:1; enum acpi_hotplug_mode mode; + int (*scan_dependent)(struct acpi_device *adev); }; static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( -- cgit v1.2.3 From 46394fd017c0615982a3d29d45ced14bea9c526d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:55:32 +0100 Subject: ACPI / hotplug: Move container-specific code out of the core Move container-specific uevents from the core hotplug code to the container scan handler's .attach() and .detach() callbacks. This way the core will not have to special-case containers and the uevents will be guaranteed to happen every time a container is either scanned or trimmed as appropriate. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/container.c | 11 ++++++++--- drivers/acpi/scan.c | 8 +------- include/acpi/acpi_bus.h | 7 ------- 3 files changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index e23151667655..83d232c10f13 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -44,19 +44,24 @@ static const struct acpi_device_id container_device_ids[] = { {"", 0}, }; -static int container_device_attach(struct acpi_device *device, +static int container_device_attach(struct acpi_device *adev, const struct acpi_device_id *not_used) { - /* This is necessary for container hotplug to work. */ + kobject_uevent(&adev->dev.kobj, KOBJ_ONLINE); return 1; } +static void container_device_detach(struct acpi_device *adev) +{ + kobject_uevent(&adev->dev.kobj, KOBJ_OFFLINE); +} + static struct acpi_scan_handler container_handler = { .ids = container_device_ids, .attach = container_device_attach, + .detach = container_device_detach, .hotplug = { .enabled = true, - .mode = AHM_CONTAINER, }, }; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 18865c86c463..b1b8f4304597 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -206,9 +206,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_status status; unsigned long long sta; - if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) - kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - /* * Carry out two passes here and ignore errors in the first pass, * because if the devices in question are memory blocks and @@ -288,10 +285,7 @@ static int acpi_scan_device_check(struct acpi_device *adev) dev_warn(&adev->dev, "Namespace scan failure\n"); return error; } - if (adev->handler) { - if (adev->handler->hotplug.mode == AHM_CONTAINER) - kobject_uevent(&adev->dev.kobj, KOBJ_ONLINE); - } else { + if (!adev->handler) { dev_warn(&adev->dev, "Enumeration failure\n"); return -ENODEV; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 2359c69f1680..3e4150b6d71a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -91,16 +91,9 @@ struct acpi_device; * ----------------- */ -enum acpi_hotplug_mode { - AHM_GENERIC = 0, - AHM_CONTAINER, - AHM_COUNT -}; - struct acpi_hotplug_profile { struct kobject kobj; bool enabled:1; - enum acpi_hotplug_mode mode; int (*scan_dependent)(struct acpi_device *adev); }; -- cgit v1.2.3 From 443fc8202272190c4693209b772edba46cd7fe61 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:55:43 +0100 Subject: ACPI / hotplug: Rework generic code to handle suprise removals The generic ACPI hotplug code used for several types of device doesn't handle surprise removals, mostly because those devices currently cannot be removed by surprise in the majority of systems. However, surprise removals should be handled by that code as well as surprise additions of devices, so make it do that. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/scan.c | 85 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b1b8f4304597..06db2c036085 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -276,18 +276,72 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } +static int acpi_scan_device_not_present(struct acpi_device *adev) +{ + if (!acpi_device_enumerated(adev)) { + dev_warn(&adev->dev, "Still not present\n"); + return -EALREADY; + } + acpi_bus_trim(adev); + return 0; +} + static int acpi_scan_device_check(struct acpi_device *adev) { int error; + acpi_bus_get_status(adev); + if (adev->status.present || adev->status.functional) { + /* + * This function is only called for device objects for which + * matching scan handlers exist. The only situation in which + * the scan handler is not attached to this device object yet + * is when the device has just appeared (either it wasn't + * present at all before or it was removed and then added + * again). + */ + if (adev->handler) { + dev_warn(&adev->dev, "Already enumerated\n"); + return -EALREADY; + } + error = acpi_bus_scan(adev->handle); + if (error) { + dev_warn(&adev->dev, "Namespace scan failure\n"); + return error; + } + if (!adev->handler) { + dev_warn(&adev->dev, "Enumeration failure\n"); + error = -ENODEV; + } + } else { + error = acpi_scan_device_not_present(adev); + } + return error; +} + +static int acpi_scan_bus_check(struct acpi_device *adev) +{ + struct acpi_scan_handler *handler = adev->handler; + struct acpi_device *child; + int error; + + acpi_bus_get_status(adev); + if (!(adev->status.present || adev->status.functional)) { + acpi_scan_device_not_present(adev); + return 0; + } + if (handler && handler->hotplug.scan_dependent) + return handler->hotplug.scan_dependent(adev); + error = acpi_bus_scan(adev->handle); if (error) { dev_warn(&adev->dev, "Namespace scan failure\n"); return error; } - if (!adev->handler) { - dev_warn(&adev->dev, "Enumeration failure\n"); - return -ENODEV; + list_for_each_entry(child, &adev->children, node) { + error = acpi_scan_bus_check(child); + if (error) + return error; } return 0; } @@ -296,7 +350,6 @@ static void acpi_device_hotplug(void *data, u32 src) { u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; struct acpi_device *adev = data; - struct acpi_scan_handler *handler; int error; lock_device_hotplug(); @@ -310,32 +363,12 @@ static void acpi_device_hotplug(void *data, u32 src) if (adev->handle == INVALID_ACPI_HANDLE) goto out; - handler = adev->handler; - switch (src) { case ACPI_NOTIFY_BUS_CHECK: - if (handler) { - error = handler->hotplug.scan_dependent ? - handler->hotplug.scan_dependent(adev) : - acpi_bus_scan(adev->handle); - } else { - error = acpi_scan_device_check(adev); - } + error = acpi_scan_bus_check(adev); break; case ACPI_NOTIFY_DEVICE_CHECK: - /* - * This code is only run for device objects for which matching - * scan handlers exist. The only situation in which the scan - * handler is not attached to this device object yet is when the - * device has just appeared (either it wasn't present at all - * before or it was removed and then added again). - */ - if (adev->handler) { - dev_warn(&adev->dev, "Already enumerated\n"); - error = -EBUSY; - } else { - error = acpi_scan_device_check(adev); - } + error = acpi_scan_device_check(adev); break; case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_OST_EC_OSPM_EJECT: -- cgit v1.2.3 From f4b734c35e98c343cd99824153de09e48867b97e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:55:55 +0100 Subject: ACPI / hotplug: Drop unfinished global notification handling routines There are two global hotplug notification handling routines in bus.c, acpi_bus_check_device() and acpi_bus_check_scope(), that have never been finished and don't do anything useful, so drop them. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 64 ++---------------------------------------------------- 1 file changed, 2 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index bba9b72e25f8..8b09a75f6579 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -329,58 +329,6 @@ static void acpi_bus_osc_support(void) Notification Handling -------------------------------------------------------------------------- */ -static void acpi_bus_check_device(acpi_handle handle) -{ - struct acpi_device *device; - acpi_status status; - struct acpi_device_status old_status; - - if (acpi_bus_get_device(handle, &device)) - return; - if (!device) - return; - - old_status = device->status; - - /* - * Make sure this device's parent is present before we go about - * messing with the device. - */ - if (device->parent && !device->parent->status.present) { - device->status = device->parent->status; - return; - } - - status = acpi_bus_get_status(device); - if (ACPI_FAILURE(status)) - return; - - if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) - return; - - /* - * Device Insertion/Removal - */ - if ((device->status.present) && !(old_status.present)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); - /* TBD: Handle device insertion */ - } else if (!(device->status.present) && (old_status.present)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); - /* TBD: Handle device removal */ - } -} - -static void acpi_bus_check_scope(acpi_handle handle) -{ - /* Status Change? */ - acpi_bus_check_device(handle); - - /* - * TBD: Enumerate child devices within this device's scope and - * run acpi_bus_check_device()'s on them. - */ -} - /** * acpi_bus_notify * --------------- @@ -397,19 +345,11 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) switch (type) { case ACPI_NOTIFY_BUS_CHECK: - acpi_bus_check_scope(handle); - /* - * TBD: We'll need to outsource certain events to non-ACPI - * drivers via the device manager (device.c). - */ + /* TBD */ break; case ACPI_NOTIFY_DEVICE_CHECK: - acpi_bus_check_device(handle); - /* - * TBD: We'll need to outsource certain events to non-ACPI - * drivers via the device manager (device.c). - */ + /* TBD */ break; case ACPI_NOTIFY_DEVICE_WAKE: -- cgit v1.2.3 From 25db115b0bf72acfdf8a339fa8e37d8b895214d6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 22 Nov 2013 21:56:06 +0100 Subject: ACPI: Introduce acpi_set_device_status() Introduce a static inline function for setting the status field of struct acpi_device on the basis of a supplied u32 number, acpi_set_device_status(), and use it instead of the horrible horrible STRUCT_TO_INT() macro wherever applicable. Having done that, drop STRUCT_TO_INT() (and pretend that it has never existed). Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/acpi/bus.c | 11 +++-------- drivers/acpi/scan.c | 5 ++--- include/acpi/acpi_bus.h | 5 +++++ 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 8b09a75f6579..f509019ee2c7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -52,9 +52,6 @@ struct acpi_device *acpi_root; struct proc_dir_entry *acpi_root_dir; EXPORT_SYMBOL(acpi_root_dir); -#define STRUCT_TO_INT(s) (*((int*)&s)) - - #ifdef CONFIG_X86 static int set_copy_dsdt(const struct dmi_system_id *id) { @@ -115,18 +112,16 @@ int acpi_bus_get_status(struct acpi_device *device) if (ACPI_FAILURE(status)) return -ENODEV; - STRUCT_TO_INT(device->status) = (int) sta; + acpi_set_device_status(device, sta); if (device->status.functional && !device->status.present) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: " "functional but not present;\n", - device->pnp.bus_id, - (u32) STRUCT_TO_INT(device->status))); + device->pnp.bus_id, (u32)sta)); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", - device->pnp.bus_id, - (u32) STRUCT_TO_INT(device->status))); + device->pnp.bus_id, (u32)sta)); return 0; } EXPORT_SYMBOL(acpi_bus_get_status); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 06db2c036085..cf773c918102 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -20,7 +20,6 @@ #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("scan"); -#define STRUCT_TO_INT(s) (*((int*)&s)) extern struct acpi_device *acpi_root; #define ACPI_BUS_CLASS "system_bus" @@ -1683,7 +1682,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - STRUCT_TO_INT(device->status) = sta; + acpi_set_device_status(device, sta); acpi_device_get_busid(device); acpi_set_pnp_ids(handle, &device->pnp, type); acpi_bus_get_flags(device); @@ -1927,7 +1926,7 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - STRUCT_TO_INT(device->status) = sta; + acpi_set_device_status(device, sta); /* Skip devices that are not present. */ if (!acpi_device_is_present(device)) goto err; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3e4150b6d71a..95831e7b70be 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -320,6 +320,11 @@ static inline void *acpi_driver_data(struct acpi_device *d) #define to_acpi_device(d) container_of(d, struct acpi_device, dev) #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) +static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) +{ + *((u32 *)&adev->status) = sta; +} + /* acpi_device.dev.bus == &acpi_bus_type */ extern struct bus_type acpi_bus_type; -- cgit v1.2.3 From 045cc22e53a1a0caaa9a0b6b64246d2690049906 Mon Sep 17 00:00:00 2001 From: "ethan.zhao" Date: Wed, 6 Nov 2013 22:49:13 +0800 Subject: PCI: Clear NumVFs when disabling SR-IOV in sriov_init() When SR-IOV is disabled (VF Enable is cleared), NumVFs is not very useful, so this patch clears it out to prevent confusing lspci output like that below. We already clear NumVFs in sriov_disable(), and this does the same when we disable SR-IOV as part of parsing the SR-IOV capability. $ lspci -vvv -s 13:00.0 13:00.0 Ethernet controller: Intel Corporation 82599EB 10-Gigabit SFI/SFP+ Network Connection (rev 01) Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV) IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy+ Initial VFs: 64, Total VFs: 64, Number of VFs: 64, ... [bhelgaas: changelog] Signed-off-by: ethan.zhao Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 1fe2d6fb19d5..68311ec849ee 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -441,6 +441,7 @@ static int sriov_init(struct pci_dev *dev, int pos) found: pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); + pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, 0); pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset); pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride); if (!offset || (total > 1 && !stride)) -- cgit v1.2.3 From 462098b090897fbcf00088b225eb7a3adc407e98 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 29 Oct 2013 20:01:46 +0100 Subject: ata: libata-eh: Remove unnecessary snprintf arithmetic Remove an unnecessary arithmetic operation from a call to snprintf, because the size parameter of snprintf includes the trailing null space. Also, initialize the buffer on definition instead of a memset call. Signed-off-by: Levente Kurusa Signed-off-by: Tejun Heo --- drivers/ata/libata-eh.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 92d7797223be..6d8757008318 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2402,7 +2402,7 @@ static void ata_eh_link_report(struct ata_link *link) struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &link->eh_context; const char *frozen, *desc; - char tries_buf[6]; + char tries_buf[6] = ""; int tag, nr_failed = 0; if (ehc->i.flags & ATA_EHI_QUIET) @@ -2433,9 +2433,8 @@ static void ata_eh_link_report(struct ata_link *link) if (ap->pflags & ATA_PFLAG_FROZEN) frozen = " frozen"; - memset(tries_buf, 0, sizeof(tries_buf)); if (ap->eh_tries < ATA_EH_MAX_TRIES) - snprintf(tries_buf, sizeof(tries_buf) - 1, " t%d", + snprintf(tries_buf, sizeof(tries_buf), " t%d", ap->eh_tries); if (ehc->i.dev) { -- cgit v1.2.3 From cb85696d7277592ddbd2897db9a29f3ec6e9fe11 Mon Sep 17 00:00:00 2001 From: James Laird Date: Tue, 19 Nov 2013 11:06:38 +1100 Subject: ahci: mcp89: enter AHCI mode under Apple BIOS emulation Apple's BIOS emulation forcibly disables MCP89 AHCI, eg. on Macbook7,1. We can re-enable it, replacing the previous workaround of using ata_generic. tj: whitespace adjustments, dropped inline from is_mcp89_apple() Signed-off-by: James Laird Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 60 ++++++++++++++++++++++++++++++++++++++++------- drivers/ata/ata_generic.c | 7 ------ 2 files changed, 51 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e2903d03180e..c55e00562527 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -83,6 +83,8 @@ enum board_ids { static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); +static void ahci_mcp89_apple_enable(struct pci_dev *pdev); +static bool is_mcp89_apple(struct pci_dev *pdev); static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); #ifdef CONFIG_PM @@ -659,6 +661,10 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) if (rc) return rc; + /* Apple BIOS helpfully mangles the registers on resume */ + if (is_mcp89_apple(pdev)) + ahci_mcp89_apple_enable(pdev); + if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { rc = ahci_pci_reset_controller(host); if (rc) @@ -775,6 +781,48 @@ static void ahci_p5wdh_workaround(struct ata_host *host) } } +/* + * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when + * booting in BIOS compatibility mode. We restore the registers but not ID. + */ +static void ahci_mcp89_apple_enable(struct pci_dev *pdev) +{ + u32 val; + + printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); + + pci_read_config_dword(pdev, 0xf8, &val); + val |= 1 << 0x1b; + /* the following changes the device ID, but appears not to affect function */ + /* val = (val & ~0xf0000000) | 0x80000000; */ + pci_write_config_dword(pdev, 0xf8, val); + + pci_read_config_dword(pdev, 0x54c, &val); + val |= 1 << 0xc; + pci_write_config_dword(pdev, 0x54c, val); + + pci_read_config_dword(pdev, 0x4a4, &val); + val &= 0xff; + val |= 0x01060100; + pci_write_config_dword(pdev, 0x4a4, val); + + pci_read_config_dword(pdev, 0x54c, &val); + val &= ~(1 << 0xc); + pci_write_config_dword(pdev, 0x54c, val); + + pci_read_config_dword(pdev, 0xf8, &val); + val &= ~(1 << 0x1b); + pci_write_config_dword(pdev, 0xf8, val); +} + +static bool is_mcp89_apple(struct pci_dev *pdev) +{ + return pdev->vendor == PCI_VENDOR_ID_NVIDIA && + pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && + pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && + pdev->subsystem_device == 0xcb89; +} + /* only some SB600 ahci controllers can do 64bit DMA */ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) { @@ -1207,15 +1255,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) return -ENODEV; - /* - * For some reason, MCP89 on MacBook 7,1 doesn't work with - * ahci, use ata_generic instead. - */ - if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && - pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && - pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && - pdev->subsystem_device == 0xcb89) - return -ENODEV; + /* Apple BIOS on MCP89 prevents us using AHCI */ + if (is_mcp89_apple(pdev)) + ahci_mcp89_apple_enable(pdev); /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. * At the moment, we can only use the AHCI mode. Let the users know diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index f8f38a08abc5..7d196656adb5 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -221,13 +221,6 @@ static struct pci_device_id ata_generic[] = { { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), }, { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), .driver_data = ATA_GEN_FORCE_DMA }, - /* - * For some reason, MCP89 on MacBook 7,1 doesn't work with - * ahci, use ata_generic instead. - */ - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA, - PCI_VENDOR_ID_APPLE, 0xcb89, - .driver_data = ATA_GEN_FORCE_DMA }, #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE) { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, -- cgit v1.2.3 From 3ca08509ac49c12c48d694e3ac849642fa7b0d4f Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 7 Nov 2013 16:59:33 +0800 Subject: clk: mvebu: staticize of_cpu_clk_setup This symbol is used only in this file. The patch fix the following sparse warning: warning: symbol 'of_cpu_clk_setup' was not declared. Should it be static? Signed-off-by: Jisheng Zhang Acked-by: Jason Cooper Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- drivers/clk/mvebu/clk-cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index 1466865b0743..8ebf757d29e2 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c @@ -101,7 +101,7 @@ static const struct clk_ops cpu_ops = { .set_rate = clk_cpu_set_rate, }; -void __init of_cpu_clk_setup(struct device_node *node) +static void __init of_cpu_clk_setup(struct device_node *node) { struct cpu_clk *cpuclk; void __iomem *clock_complex_base = of_iomap(node, 0); -- cgit v1.2.3 From 33879d4512c021ae65be9706608dacb36b4687b1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 23 Nov 2013 22:33:32 -0800 Subject: block: submit_bio_wait() conversions It was being open coded in a few places. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Joern Engel Cc: Prasad Joshi Cc: Neil Brown Cc: Chris Mason Acked-by: NeilBrown --- block/blk-flush.c | 19 +------------------ drivers/md/md.c | 14 +------------- fs/btrfs/check-integrity.c | 32 +++++++++++++------------------- fs/btrfs/check-integrity.h | 2 ++ fs/btrfs/extent_io.c | 12 +----------- fs/btrfs/scrub.c | 33 ++++----------------------------- fs/hfsplus/wrapper.c | 17 +---------------- fs/logfs/dev_bdev.c | 13 +------------ 8 files changed, 24 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/block/blk-flush.c b/block/blk-flush.c index 331e627301ea..fb6f3c0ffa49 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -502,15 +502,6 @@ void blk_abort_flushes(struct request_queue *q) } } -static void bio_end_flush(struct bio *bio, int err) -{ - if (err) - clear_bit(BIO_UPTODATE, &bio->bi_flags); - if (bio->bi_private) - complete(bio->bi_private); - bio_put(bio); -} - /** * blkdev_issue_flush - queue a flush * @bdev: blockdev to issue flush for @@ -526,7 +517,6 @@ static void bio_end_flush(struct bio *bio, int err) int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, sector_t *error_sector) { - DECLARE_COMPLETION_ONSTACK(wait); struct request_queue *q; struct bio *bio; int ret = 0; @@ -548,13 +538,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, return -ENXIO; bio = bio_alloc(gfp_mask, 0); - bio->bi_end_io = bio_end_flush; bio->bi_bdev = bdev; - bio->bi_private = &wait; - bio_get(bio); - submit_bio(WRITE_FLUSH, bio); - wait_for_completion_io(&wait); + ret = submit_bio_wait(WRITE_FLUSH, bio); /* * The driver must store the error location in ->bi_sector, if @@ -564,9 +550,6 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, if (error_sector) *error_sector = bio->bi_sector; - if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - bio_put(bio); return ret; } diff --git a/drivers/md/md.c b/drivers/md/md.c index b6b7a2866c9e..739b1ec54e28 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -776,20 +776,12 @@ void md_super_wait(struct mddev *mddev) finish_wait(&mddev->sb_wait, &wq); } -static void bi_complete(struct bio *bio, int error) -{ - complete((struct completion*)bio->bi_private); -} - int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, struct page *page, int rw, bool metadata_op) { struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev); - struct completion event; int ret; - rw |= REQ_SYNC; - bio->bi_bdev = (metadata_op && rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; if (metadata_op) @@ -801,11 +793,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, else bio->bi_sector = sector + rdev->data_offset; bio_add_page(bio, page, size, 0); - init_completion(&event); - bio->bi_private = &event; - bio->bi_end_io = bi_complete; - submit_bio(rw, bio); - wait_for_completion(&event); + submit_bio_wait(rw, bio); ret = test_bit(BIO_UPTODATE, &bio->bi_flags); bio_put(bio); diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index b50764bef141..131d82800b3a 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -333,7 +333,6 @@ static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx); static int btrfsic_read_block(struct btrfsic_state *state, struct btrfsic_block_data_ctx *block_ctx); static void btrfsic_dump_database(struct btrfsic_state *state); -static void btrfsic_complete_bio_end_io(struct bio *bio, int err); static int btrfsic_test_for_metadata(struct btrfsic_state *state, char **datav, unsigned int num_pages); static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, @@ -1687,7 +1686,6 @@ static int btrfsic_read_block(struct btrfsic_state *state, for (i = 0; i < num_pages;) { struct bio *bio; unsigned int j; - DECLARE_COMPLETION_ONSTACK(complete); bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i); if (!bio) { @@ -1698,8 +1696,6 @@ static int btrfsic_read_block(struct btrfsic_state *state, } bio->bi_bdev = block_ctx->dev->bdev; bio->bi_sector = dev_bytenr >> 9; - bio->bi_end_io = btrfsic_complete_bio_end_io; - bio->bi_private = &complete; for (j = i; j < num_pages; j++) { ret = bio_add_page(bio, block_ctx->pagev[j], @@ -1712,12 +1708,7 @@ static int btrfsic_read_block(struct btrfsic_state *state, "btrfsic: error, failed to add a single page!\n"); return -1; } - submit_bio(READ, bio); - - /* this will also unplug the queue */ - wait_for_completion(&complete); - - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { + if (submit_bio_wait(READ, bio)) { printk(KERN_INFO "btrfsic: read error at logical %llu dev %s!\n", block_ctx->start, block_ctx->dev->name); @@ -1740,11 +1731,6 @@ static int btrfsic_read_block(struct btrfsic_state *state, return block_ctx->len; } -static void btrfsic_complete_bio_end_io(struct bio *bio, int err) -{ - complete((struct completion *)bio->bi_private); -} - static void btrfsic_dump_database(struct btrfsic_state *state) { struct list_head *elem_all; @@ -3008,14 +2994,12 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) return submit_bh(rw, bh); } -void btrfsic_submit_bio(int rw, struct bio *bio) +static void __btrfsic_submit_bio(int rw, struct bio *bio) { struct btrfsic_dev_state *dev_state; - if (!btrfsic_is_initialized) { - submit_bio(rw, bio); + if (!btrfsic_is_initialized) return; - } mutex_lock(&btrfsic_mutex); /* since btrfsic_submit_bio() is also called before @@ -3106,10 +3090,20 @@ void btrfsic_submit_bio(int rw, struct bio *bio) } leave: mutex_unlock(&btrfsic_mutex); +} +void btrfsic_submit_bio(int rw, struct bio *bio) +{ + __btrfsic_submit_bio(rw, bio); submit_bio(rw, bio); } +int btrfsic_submit_bio_wait(int rw, struct bio *bio) +{ + __btrfsic_submit_bio(rw, bio); + return submit_bio_wait(rw, bio); +} + int btrfsic_mount(struct btrfs_root *root, struct btrfs_fs_devices *fs_devices, int including_extent_data, u32 print_mask) diff --git a/fs/btrfs/check-integrity.h b/fs/btrfs/check-integrity.h index 8b59175cc502..13b8566c97ab 100644 --- a/fs/btrfs/check-integrity.h +++ b/fs/btrfs/check-integrity.h @@ -22,9 +22,11 @@ #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY int btrfsic_submit_bh(int rw, struct buffer_head *bh); void btrfsic_submit_bio(int rw, struct bio *bio); +int btrfsic_submit_bio_wait(int rw, struct bio *bio); #else #define btrfsic_submit_bh submit_bh #define btrfsic_submit_bio submit_bio +#define btrfsic_submit_bio_wait submit_bio_wait #endif int btrfsic_mount(struct btrfs_root *root, diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8e457fca0a0b..ff43802a7c88 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1952,11 +1952,6 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec, return err; } -static void repair_io_failure_callback(struct bio *bio, int err) -{ - complete(bio->bi_private); -} - /* * this bypasses the standard btrfs submit functions deliberately, as * the standard behavior is to write all copies in a raid setup. here we only @@ -1973,7 +1968,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start, { struct bio *bio; struct btrfs_device *dev; - DECLARE_COMPLETION_ONSTACK(compl); u64 map_length = 0; u64 sector; struct btrfs_bio *bbio = NULL; @@ -1990,8 +1984,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start, bio = btrfs_io_bio_alloc(GFP_NOFS, 1); if (!bio) return -EIO; - bio->bi_private = &compl; - bio->bi_end_io = repair_io_failure_callback; bio->bi_size = 0; map_length = length; @@ -2012,10 +2004,8 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start, } bio->bi_bdev = dev->bdev; bio_add_page(bio, page, length, start - page_offset(page)); - btrfsic_submit_bio(WRITE_SYNC, bio); - wait_for_completion(&compl); - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { + if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) { /* try to remap that extent elsewhere? */ bio_put(bio); btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS); diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 561e2f16ba3e..1fd3f33c330a 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -208,7 +208,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info, int is_metadata, int have_csum, const u8 *csum, u64 generation, u16 csum_size); -static void scrub_complete_bio_end_io(struct bio *bio, int err); static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad, struct scrub_block *sblock_good, int force_write); @@ -1294,7 +1293,6 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info, for (page_num = 0; page_num < sblock->page_count; page_num++) { struct bio *bio; struct scrub_page *page = sblock->pagev[page_num]; - DECLARE_COMPLETION_ONSTACK(complete); if (page->dev->bdev == NULL) { page->io_error = 1; @@ -1311,18 +1309,11 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info, } bio->bi_bdev = page->dev->bdev; bio->bi_sector = page->physical >> 9; - bio->bi_end_io = scrub_complete_bio_end_io; - bio->bi_private = &complete; bio_add_page(bio, page->page, PAGE_SIZE, 0); - btrfsic_submit_bio(READ, bio); - - /* this will also unplug the queue */ - wait_for_completion(&complete); - - page->io_error = !test_bit(BIO_UPTODATE, &bio->bi_flags); - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + if (btrfsic_submit_bio_wait(READ, bio)) sblock->no_io_error_seen = 0; + bio_put(bio); } @@ -1391,11 +1382,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info, sblock->checksum_error = 1; } -static void scrub_complete_bio_end_io(struct bio *bio, int err) -{ - complete((struct completion *)bio->bi_private); -} - static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad, struct scrub_block *sblock_good, int force_write) @@ -1430,7 +1416,6 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, sblock_bad->checksum_error || page_bad->io_error) { struct bio *bio; int ret; - DECLARE_COMPLETION_ONSTACK(complete); if (!page_bad->dev->bdev) { printk_ratelimited(KERN_WARNING @@ -1443,19 +1428,14 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, return -EIO; bio->bi_bdev = page_bad->dev->bdev; bio->bi_sector = page_bad->physical >> 9; - bio->bi_end_io = scrub_complete_bio_end_io; - bio->bi_private = &complete; ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0); if (PAGE_SIZE != ret) { bio_put(bio); return -EIO; } - btrfsic_submit_bio(WRITE, bio); - /* this will also unplug the queue */ - wait_for_completion(&complete); - if (!bio_flagged(bio, BIO_UPTODATE)) { + if (btrfsic_submit_bio_wait(WRITE, bio)) { btrfs_dev_stat_inc_and_print(page_bad->dev, BTRFS_DEV_STAT_WRITE_ERRS); btrfs_dev_replace_stats_inc( @@ -3375,7 +3355,6 @@ static int write_page_nocow(struct scrub_ctx *sctx, struct bio *bio; struct btrfs_device *dev; int ret; - DECLARE_COMPLETION_ONSTACK(compl); dev = sctx->wr_ctx.tgtdev; if (!dev) @@ -3392,8 +3371,6 @@ static int write_page_nocow(struct scrub_ctx *sctx, spin_unlock(&sctx->stat_lock); return -ENOMEM; } - bio->bi_private = &compl; - bio->bi_end_io = scrub_complete_bio_end_io; bio->bi_size = 0; bio->bi_sector = physical_for_dev_replace >> 9; bio->bi_bdev = dev->bdev; @@ -3404,10 +3381,8 @@ leave_with_eio: btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS); return -EIO; } - btrfsic_submit_bio(WRITE_SYNC, bio); - wait_for_completion(&compl); - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) goto leave_with_eio; bio_put(bio); diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index b51a6079108d..e9a97a0d4314 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -24,13 +24,6 @@ struct hfsplus_wd { u16 embed_count; }; -static void hfsplus_end_io_sync(struct bio *bio, int err) -{ - if (err) - clear_bit(BIO_UPTODATE, &bio->bi_flags); - complete(bio->bi_private); -} - /* * hfsplus_submit_bio - Perfrom block I/O * @sb: super block of volume for I/O @@ -53,7 +46,6 @@ static void hfsplus_end_io_sync(struct bio *bio, int err) int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf, void **data, int rw) { - DECLARE_COMPLETION_ONSTACK(wait); struct bio *bio; int ret = 0; u64 io_size; @@ -73,8 +65,6 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, bio = bio_alloc(GFP_NOIO, 1); bio->bi_sector = sector; bio->bi_bdev = sb->s_bdev; - bio->bi_end_io = hfsplus_end_io_sync; - bio->bi_private = &wait; if (!(rw & WRITE) && data) *data = (u8 *)buf + offset; @@ -93,12 +83,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, buf = (u8 *)buf + len; } - submit_bio(rw, bio); - wait_for_completion(&wait); - - if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - + ret = submit_bio_wait(rw, bio); out: bio_put(bio); return ret < 0 ? ret : 0; diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 550475ca6a0e..0f95f0d0b313 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -14,16 +14,10 @@ #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) -static void request_complete(struct bio *bio, int err) -{ - complete((struct completion *)bio->bi_private); -} - static int sync_request(struct page *page, struct block_device *bdev, int rw) { struct bio bio; struct bio_vec bio_vec; - struct completion complete; bio_init(&bio); bio.bi_max_vecs = 1; @@ -35,13 +29,8 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) bio.bi_size = PAGE_SIZE; bio.bi_bdev = bdev; bio.bi_sector = page->index * (PAGE_SIZE >> 9); - init_completion(&complete); - bio.bi_private = &complete; - bio.bi_end_io = request_complete; - submit_bio(rw, &bio); - wait_for_completion(&complete); - return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO; + return submit_bio_wait(rw, &bio); } static int bdev_readpage(void *_sb, struct page *page) -- cgit v1.2.3 From ed9c47bebeeea4a468b07cfd745c690190f8014c Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 22 Nov 2013 19:37:48 -0800 Subject: bcache: Kill unaligned bvec hack Bcache has a hack to avoid cloning the biovec if it's all full pages - but with immutable biovecs coming this won't be necessary anymore. For now, we remove the special case and always clone the bvec array so that the immutable biovec patches are simpler. Signed-off-by: Kent Overstreet --- drivers/md/bcache/bcache.h | 1 - drivers/md/bcache/request.c | 37 +++++++------------------------------ drivers/md/bcache/super.c | 4 ---- 3 files changed, 7 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 4beb55a0ff30..6b6fe935be73 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -279,7 +279,6 @@ struct bcache_device { unsigned long sectors_dirty_last; long sectors_dirty_derivative; - mempool_t *unaligned_bvec; struct bio_set *bio_split; unsigned data_csum:1; diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index fbcc851ed5a5..78bab4154e97 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -606,7 +606,6 @@ struct search { unsigned insert_bio_sectors; unsigned recoverable:1; - unsigned unaligned_bvec:1; unsigned write:1; unsigned read_dirty_data:1; @@ -614,6 +613,7 @@ struct search { struct btree_op op; struct data_insert_op iop; + struct bio_vec bv[BIO_MAX_PAGES]; }; static void bch_cache_read_endio(struct bio *bio, int error) @@ -759,10 +759,14 @@ static void bio_complete(struct search *s) static void do_bio_hook(struct search *s) { struct bio *bio = &s->bio.bio; - memcpy(bio, s->orig_bio, sizeof(struct bio)); + bio_init(bio); + bio->bi_io_vec = s->bv; + bio->bi_max_vecs = BIO_MAX_PAGES; + __bio_clone(bio, s->orig_bio); bio->bi_end_io = request_endio; bio->bi_private = &s->cl; + atomic_set(&bio->bi_cnt, 3); } @@ -774,9 +778,6 @@ static void search_free(struct closure *cl) if (s->iop.bio) bio_put(s->iop.bio); - if (s->unaligned_bvec) - mempool_free(s->bio.bio.bi_io_vec, s->d->unaligned_bvec); - closure_debug_destroy(cl); mempool_free(s, s->d->c->search); } @@ -784,7 +785,6 @@ static void search_free(struct closure *cl) static struct search *search_alloc(struct bio *bio, struct bcache_device *d) { struct search *s; - struct bio_vec *bv; s = mempool_alloc(d->c->search, GFP_NOIO); memset(s, 0, offsetof(struct search, iop.insert_keys)); @@ -803,15 +803,6 @@ static struct search *search_alloc(struct bio *bio, struct bcache_device *d) s->start_time = jiffies; do_bio_hook(s); - if (bio->bi_size != bio_segments(bio) * PAGE_SIZE) { - bv = mempool_alloc(d->unaligned_bvec, GFP_NOIO); - memcpy(bv, bio_iovec(bio), - sizeof(struct bio_vec) * bio_segments(bio)); - - s->bio.bio.bi_io_vec = bv; - s->unaligned_bvec = 1; - } - return s; } @@ -850,26 +841,13 @@ static void cached_dev_read_error(struct closure *cl) { struct search *s = container_of(cl, struct search, cl); struct bio *bio = &s->bio.bio; - struct bio_vec *bv; - int i; if (s->recoverable) { /* Retry from the backing device: */ trace_bcache_read_retry(s->orig_bio); s->iop.error = 0; - bv = s->bio.bio.bi_io_vec; do_bio_hook(s); - s->bio.bio.bi_io_vec = bv; - - if (!s->unaligned_bvec) - bio_for_each_segment(bv, s->orig_bio, i) - bv->bv_offset = 0, bv->bv_len = PAGE_SIZE; - else - memcpy(s->bio.bio.bi_io_vec, - bio_iovec(s->orig_bio), - sizeof(struct bio_vec) * - bio_segments(s->orig_bio)); /* XXX: invalidate cache */ @@ -905,8 +883,7 @@ static void cached_dev_read_done(struct closure *cl) s->cache_miss = NULL; } - if (verify(dc, &s->bio.bio) && s->recoverable && - !s->unaligned_bvec && !s->read_dirty_data) + if (verify(dc, &s->bio.bio) && s->recoverable && !s->read_dirty_data) bch_data_verify(dc, s->orig_bio); bio_complete(s); diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index dec15cd2d797..1d9ee67d14ec 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -739,8 +739,6 @@ static void bcache_device_free(struct bcache_device *d) } bio_split_pool_free(&d->bio_split_hook); - if (d->unaligned_bvec) - mempool_destroy(d->unaligned_bvec); if (d->bio_split) bioset_free(d->bio_split); if (is_vmalloc_addr(d->full_dirty_stripes)) @@ -793,8 +791,6 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size, return minor; if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) || - !(d->unaligned_bvec = mempool_create_kmalloc_pool(1, - sizeof(struct bio_vec) * BIO_MAX_PAGES)) || bio_split_pool_init(&d->bio_split_hook) || !(d->disk = alloc_disk(1))) { ida_simple_remove(&bcache_minor, minor); -- cgit v1.2.3 From 4f024f3797c43cb4b73cd2c50cec728842d0e49e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 11 Oct 2013 15:44:27 -0700 Subject: block: Abstract out bvec iterator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Immutable biovecs are going to require an explicit iterator. To implement immutable bvecs, a later patch is going to add a bi_bvec_done member to this struct; for now, this patch effectively just renames things. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Geert Uytterhoeven Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: "Ed L. Cashin" Cc: Nick Piggin Cc: Lars Ellenberg Cc: Jiri Kosina Cc: Matthew Wilcox Cc: Geoff Levand Cc: Yehuda Sadeh Cc: Sage Weil Cc: Alex Elder Cc: ceph-devel@vger.kernel.org Cc: Joshua Morris Cc: Philip Kelleher Cc: Rusty Russell Cc: "Michael S. Tsirkin" Cc: Konrad Rzeszutek Wilk Cc: Jeremy Fitzhardinge Cc: Neil Brown Cc: Alasdair Kergon Cc: Mike Snitzer Cc: dm-devel@redhat.com Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: Boaz Harrosh Cc: Benny Halevy Cc: "James E.J. Bottomley" Cc: Greg Kroah-Hartman Cc: "Nicholas A. Bellinger" Cc: Alexander Viro Cc: Chris Mason Cc: "Theodore Ts'o" Cc: Andreas Dilger Cc: Jaegeuk Kim Cc: Steven Whitehouse Cc: Dave Kleikamp Cc: Joern Engel Cc: Prasad Joshi Cc: Trond Myklebust Cc: KONISHI Ryusuke Cc: Mark Fasheh Cc: Joel Becker Cc: Ben Myers Cc: xfs@oss.sgi.com Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Len Brown Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Herton Ronaldo Krzesinski Cc: Ben Hutchings Cc: Andrew Morton Cc: Guo Chao Cc: Tejun Heo Cc: Asai Thambi S P Cc: Selvan Mani Cc: Sam Bradshaw Cc: Wei Yongjun Cc: "Roger Pau Monné" Cc: Jan Beulich Cc: Stefano Stabellini Cc: Ian Campbell Cc: Sebastian Ott Cc: Christian Borntraeger Cc: Minchan Kim Cc: Jiang Liu Cc: Nitin Gupta Cc: Jerome Marchand Cc: Joe Perches Cc: Peng Tao Cc: Andy Adamson Cc: fanchaoting Cc: Jie Liu Cc: Sunil Mushran Cc: "Martin K. Petersen" Cc: Namjae Jeon Cc: Pankaj Kumar Cc: Dan Magenheimer Cc: Mel Gorman 6 --- Documentation/block/biodoc.txt | 7 +-- arch/m68k/emu/nfblock.c | 2 +- arch/powerpc/sysdev/axonram.c | 3 +- block/blk-core.c | 36 ++++++------ block/blk-flush.c | 2 +- block/blk-lib.c | 12 ++-- block/blk-map.c | 6 +- block/blk-merge.c | 4 +- block/blk-mq.c | 2 +- block/blk-throttle.c | 14 ++--- block/elevator.c | 2 +- drivers/block/aoe/aoecmd.c | 6 +- drivers/block/brd.c | 4 +- drivers/block/drbd/drbd_actlog.c | 2 +- drivers/block/drbd/drbd_bitmap.c | 2 +- drivers/block/drbd/drbd_receiver.c | 6 +- drivers/block/drbd/drbd_req.c | 6 +- drivers/block/drbd/drbd_req.h | 2 +- drivers/block/floppy.c | 4 +- drivers/block/loop.c | 4 +- drivers/block/mtip32xx/mtip32xx.c | 7 ++- drivers/block/nvme-core.c | 25 ++++---- drivers/block/pktcdvd.c | 54 +++++++++-------- drivers/block/ps3disk.c | 2 +- drivers/block/ps3vram.c | 2 +- drivers/block/rbd.c | 21 +++---- drivers/block/rsxx/dev.c | 6 +- drivers/block/rsxx/dma.c | 4 +- drivers/block/umem.c | 9 +-- drivers/block/xen-blkback/blkback.c | 2 +- drivers/block/xen-blkfront.c | 2 +- drivers/md/bcache/btree.c | 4 +- drivers/md/bcache/debug.c | 2 +- drivers/md/bcache/io.c | 26 ++++----- drivers/md/bcache/journal.c | 12 ++-- drivers/md/bcache/movinggc.c | 4 +- drivers/md/bcache/request.c | 58 +++++++++--------- drivers/md/bcache/super.c | 16 ++--- drivers/md/bcache/util.c | 4 +- drivers/md/bcache/writeback.c | 6 +- drivers/md/bcache/writeback.h | 2 +- drivers/md/dm-bio-record.h | 12 ++-- drivers/md/dm-bufio.c | 2 +- drivers/md/dm-cache-policy-mq.c | 4 +- drivers/md/dm-cache-target.c | 22 +++---- drivers/md/dm-crypt.c | 19 +++--- drivers/md/dm-delay.c | 7 ++- drivers/md/dm-flakey.c | 7 ++- drivers/md/dm-io.c | 6 +- drivers/md/dm-linear.c | 3 +- drivers/md/dm-raid1.c | 16 ++--- drivers/md/dm-region-hash.c | 3 +- drivers/md/dm-snap.c | 18 +++--- drivers/md/dm-stripe.c | 13 +++-- drivers/md/dm-switch.c | 4 +- drivers/md/dm-thin.c | 22 +++---- drivers/md/dm-verity.c | 8 +-- drivers/md/dm.c | 25 ++++---- drivers/md/faulty.c | 19 +++--- drivers/md/linear.c | 12 ++-- drivers/md/md.c | 10 ++-- drivers/md/multipath.c | 13 +++-- drivers/md/raid0.c | 16 ++--- drivers/md/raid1.c | 75 ++++++++++++------------ drivers/md/raid10.c | 91 ++++++++++++++++------------- drivers/md/raid5.c | 72 ++++++++++++----------- drivers/s390/block/dcssblk.c | 5 +- drivers/s390/block/xpram.c | 9 +-- drivers/scsi/osd/osd_initiator.c | 2 +- drivers/staging/lustre/lustre/llite/lloop.c | 12 ++-- drivers/staging/zram/zram_drv.c | 14 +++-- drivers/target/target_core_iblock.c | 2 +- fs/bio-integrity.c | 8 +-- fs/bio.c | 56 +++++++++--------- fs/btrfs/check-integrity.c | 8 +-- fs/btrfs/compression.c | 17 +++--- fs/btrfs/extent_io.c | 14 ++--- fs/btrfs/file-item.c | 19 +++--- fs/btrfs/inode.c | 22 +++---- fs/btrfs/raid56.c | 22 +++---- fs/btrfs/scrub.c | 12 ++-- fs/btrfs/volumes.c | 12 ++-- fs/buffer.c | 12 ++-- fs/direct-io.c | 4 +- fs/ext4/page-io.c | 4 +- fs/f2fs/data.c | 2 +- fs/f2fs/segment.c | 2 +- fs/gfs2/lops.c | 2 +- fs/gfs2/ops_fstype.c | 2 +- fs/hfsplus/wrapper.c | 2 +- fs/jfs/jfs_logmgr.c | 12 ++-- fs/jfs/jfs_metapage.c | 9 +-- fs/logfs/dev_bdev.c | 20 +++---- fs/mpage.c | 2 +- fs/nfs/blocklayout/blocklayout.c | 9 +-- fs/nilfs2/segbuf.c | 3 +- fs/ocfs2/cluster/heartbeat.c | 2 +- fs/xfs/xfs_aops.c | 2 +- fs/xfs/xfs_buf.c | 4 +- include/linux/bio.h | 16 ++--- include/linux/blk_types.h | 19 +++--- include/trace/events/bcache.h | 26 ++++----- include/trace/events/block.h | 26 ++++----- include/trace/events/f2fs.h | 4 +- kernel/power/block_io.c | 2 +- kernel/trace/blktrace.c | 15 ++--- mm/page_io.c | 10 ++-- 107 files changed, 700 insertions(+), 638 deletions(-) (limited to 'drivers') diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 8df5e8e6dceb..2101e718670d 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -447,14 +447,13 @@ struct bio_vec { * main unit of I/O for the block layer and lower layers (ie drivers) */ struct bio { - sector_t bi_sector; struct bio *bi_next; /* request queue link */ struct block_device *bi_bdev; /* target device */ unsigned long bi_flags; /* status, command, etc */ unsigned long bi_rw; /* low bits: r/w, high: priority */ unsigned int bi_vcnt; /* how may bio_vec's */ - unsigned int bi_idx; /* current index into bio_vec array */ + struct bvec_iter bi_iter; /* current index into bio_vec array */ unsigned int bi_size; /* total size in bytes */ unsigned short bi_phys_segments; /* segments after physaddr coalesce*/ @@ -480,7 +479,7 @@ With this multipage bio design: - Code that traverses the req list can find all the segments of a bio by using rq_for_each_segment. This handles the fact that a request has multiple bios, each of which can have multiple segments. -- Drivers which can't process a large bio in one shot can use the bi_idx +- Drivers which can't process a large bio in one shot can use the bi_iter field to keep track of the next bio_vec entry to process. (e.g a 1MB bio_vec needs to be handled in max 128kB chunks for IDE) [TBD: Should preferably also have a bi_voffset and bi_vlen to avoid modifying @@ -589,7 +588,7 @@ driver should not modify these values. The block layer sets up the nr_sectors and current_nr_sectors fields (based on the corresponding hard_xxx values and the number of bytes transferred) and updates it on every transfer that invokes end_that_request_first. It does the same for the -buffer, bio, bio->bi_idx fields too. +buffer, bio, bio->bi_iter fields too. The buffer field is just a virtual address mapping of the current segment of the i/o buffer in cases where the buffer resides in low-memory. For high diff --git a/arch/m68k/emu/nfblock.c b/arch/m68k/emu/nfblock.c index 0721858fbd1e..0a9d0b3c794b 100644 --- a/arch/m68k/emu/nfblock.c +++ b/arch/m68k/emu/nfblock.c @@ -64,7 +64,7 @@ static void nfhd_make_request(struct request_queue *queue, struct bio *bio) struct nfhd_device *dev = queue->queuedata; struct bio_vec *bvec; int i, dir, len, shift; - sector_t sec = bio->bi_sector; + sector_t sec = bio->bi_iter.bi_sector; dir = bio_data_dir(bio); shift = dev->bshift; diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index 1c16141c031c..f33bcbaa6a07 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -113,7 +113,8 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio) unsigned int transfered; unsigned short idx; - phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT); + phys_mem = bank->io_addr + (bio->bi_iter.bi_sector << + AXON_RAM_SECTOR_SHIFT); phys_end = bank->io_addr + bank->size; transfered = 0; bio_for_each_segment(vec, bio, idx) { diff --git a/block/blk-core.c b/block/blk-core.c index 8bdd0121212a..5c2ab2c74066 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -130,7 +130,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio, bio_advance(bio, nbytes); /* don't actually finish bio if it's part of flush sequence */ - if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) + if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) bio_endio(bio, error); } @@ -1326,7 +1326,7 @@ void blk_add_request_payload(struct request *rq, struct page *page, bio->bi_io_vec->bv_offset = 0; bio->bi_io_vec->bv_len = len; - bio->bi_size = len; + bio->bi_iter.bi_size = len; bio->bi_vcnt = 1; bio->bi_phys_segments = 1; @@ -1351,7 +1351,7 @@ bool bio_attempt_back_merge(struct request_queue *q, struct request *req, req->biotail->bi_next = bio; req->biotail = bio; - req->__data_len += bio->bi_size; + req->__data_len += bio->bi_iter.bi_size; req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); blk_account_io_start(req, false); @@ -1380,8 +1380,8 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req, * not touch req->buffer either... */ req->buffer = bio_data(bio); - req->__sector = bio->bi_sector; - req->__data_len += bio->bi_size; + req->__sector = bio->bi_iter.bi_sector; + req->__data_len += bio->bi_iter.bi_size; req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); blk_account_io_start(req, false); @@ -1459,7 +1459,7 @@ void init_request_from_bio(struct request *req, struct bio *bio) req->cmd_flags |= REQ_FAILFAST_MASK; req->errors = 0; - req->__sector = bio->bi_sector; + req->__sector = bio->bi_iter.bi_sector; req->ioprio = bio_prio(bio); blk_rq_bio_prep(req->q, req, bio); } @@ -1583,12 +1583,12 @@ static inline void blk_partition_remap(struct bio *bio) if (bio_sectors(bio) && bdev != bdev->bd_contains) { struct hd_struct *p = bdev->bd_part; - bio->bi_sector += p->start_sect; + bio->bi_iter.bi_sector += p->start_sect; bio->bi_bdev = bdev->bd_contains; trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), bio, bdev->bd_dev, - bio->bi_sector - p->start_sect); + bio->bi_iter.bi_sector - p->start_sect); } } @@ -1654,7 +1654,7 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors) /* Test device or partition size, when known. */ maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9; if (maxsector) { - sector_t sector = bio->bi_sector; + sector_t sector = bio->bi_iter.bi_sector; if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { /* @@ -1690,7 +1690,7 @@ generic_make_request_checks(struct bio *bio) "generic_make_request: Trying to access " "nonexistent block-device %s (%Lu)\n", bdevname(bio->bi_bdev, b), - (long long) bio->bi_sector); + (long long) bio->bi_iter.bi_sector); goto end_io; } @@ -1704,9 +1704,9 @@ generic_make_request_checks(struct bio *bio) } part = bio->bi_bdev->bd_part; - if (should_fail_request(part, bio->bi_size) || + if (should_fail_request(part, bio->bi_iter.bi_size) || should_fail_request(&part_to_disk(part)->part0, - bio->bi_size)) + bio->bi_iter.bi_size)) goto end_io; /* @@ -1865,7 +1865,7 @@ void submit_bio(int rw, struct bio *bio) if (rw & WRITE) { count_vm_events(PGPGOUT, count); } else { - task_io_account_read(bio->bi_size); + task_io_account_read(bio->bi_iter.bi_size); count_vm_events(PGPGIN, count); } @@ -1874,7 +1874,7 @@ void submit_bio(int rw, struct bio *bio) printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n", current->comm, task_pid_nr(current), (rw & WRITE) ? "WRITE" : "READ", - (unsigned long long)bio->bi_sector, + (unsigned long long)bio->bi_iter.bi_sector, bdevname(bio->bi_bdev, b), count); } @@ -2007,7 +2007,7 @@ unsigned int blk_rq_err_bytes(const struct request *rq) for (bio = rq->bio; bio; bio = bio->bi_next) { if ((bio->bi_rw & ff) != ff) break; - bytes += bio->bi_size; + bytes += bio->bi_iter.bi_size; } /* this could lead to infinite loop */ @@ -2378,9 +2378,9 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) total_bytes = 0; while (req->bio) { struct bio *bio = req->bio; - unsigned bio_bytes = min(bio->bi_size, nr_bytes); + unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes); - if (bio_bytes == bio->bi_size) + if (bio_bytes == bio->bi_iter.bi_size) req->bio = bio->bi_next; req_bio_endio(req, bio, bio_bytes, error); @@ -2728,7 +2728,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->nr_phys_segments = bio_phys_segments(q, bio); rq->buffer = bio_data(bio); } - rq->__data_len = bio->bi_size; + rq->__data_len = bio->bi_iter.bi_size; rq->bio = rq->biotail = bio; if (bio->bi_bdev) diff --git a/block/blk-flush.c b/block/blk-flush.c index fb6f3c0ffa49..9288aaf35c21 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -548,7 +548,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, * copied from blk_rq_pos(rq). */ if (error_sector) - *error_sector = bio->bi_sector; + *error_sector = bio->bi_iter.bi_sector; bio_put(bio); return ret; diff --git a/block/blk-lib.c b/block/blk-lib.c index 9b5b561cb928..2da76c999ef3 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -108,12 +108,12 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, req_sects = end_sect - sector; } - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_end_io = bio_batch_end_io; bio->bi_bdev = bdev; bio->bi_private = &bb; - bio->bi_size = req_sects << 9; + bio->bi_iter.bi_size = req_sects << 9; nr_sects -= req_sects; sector = end_sect; @@ -174,7 +174,7 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, break; } - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_end_io = bio_batch_end_io; bio->bi_bdev = bdev; bio->bi_private = &bb; @@ -184,11 +184,11 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev); if (nr_sects > max_write_same_sectors) { - bio->bi_size = max_write_same_sectors << 9; + bio->bi_iter.bi_size = max_write_same_sectors << 9; nr_sects -= max_write_same_sectors; sector += max_write_same_sectors; } else { - bio->bi_size = nr_sects << 9; + bio->bi_iter.bi_size = nr_sects << 9; nr_sects = 0; } @@ -240,7 +240,7 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, break; } - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; bio->bi_end_io = bio_batch_end_io; bio->bi_private = &bb; diff --git a/block/blk-map.c b/block/blk-map.c index 623e1cd4cffe..ae4ae1047fd9 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -20,7 +20,7 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq, rq->biotail->bi_next = bio; rq->biotail = bio; - rq->__data_len += bio->bi_size; + rq->__data_len += bio->bi_iter.bi_size; } return 0; } @@ -76,7 +76,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, ret = blk_rq_append_bio(q, rq, bio); if (!ret) - return bio->bi_size; + return bio->bi_iter.bi_size; /* if it was boucned we must call the end io function */ bio_endio(bio, 0); @@ -220,7 +220,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, if (IS_ERR(bio)) return PTR_ERR(bio); - if (bio->bi_size != len) { + if (bio->bi_iter.bi_size != len) { /* * Grab an extra reference to this bio, as bio_unmap_user() * expects to be able to drop it twice as it happens on the diff --git a/block/blk-merge.c b/block/blk-merge.c index 1ffc58977835..03bc083c28cf 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -543,9 +543,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) int blk_try_merge(struct request *rq, struct bio *bio) { - if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_sector) + if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector) return ELEVATOR_BACK_MERGE; - else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_sector) + else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector) return ELEVATOR_FRONT_MERGE; return ELEVATOR_NO_MERGE; } diff --git a/block/blk-mq.c b/block/blk-mq.c index cdc629cf075b..e4fbcc3fd2db 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -301,7 +301,7 @@ void blk_mq_complete_request(struct request *rq, int error) struct bio *next = bio->bi_next; bio->bi_next = NULL; - bytes += bio->bi_size; + bytes += bio->bi_iter.bi_size; blk_mq_bio_endio(rq, bio, error); bio = next; } diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 06534049afba..20f820037775 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -877,14 +877,14 @@ static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio, do_div(tmp, HZ); bytes_allowed = tmp; - if (tg->bytes_disp[rw] + bio->bi_size <= bytes_allowed) { + if (tg->bytes_disp[rw] + bio->bi_iter.bi_size <= bytes_allowed) { if (wait) *wait = 0; return 1; } /* Calc approx time to dispatch */ - extra_bytes = tg->bytes_disp[rw] + bio->bi_size - bytes_allowed; + extra_bytes = tg->bytes_disp[rw] + bio->bi_iter.bi_size - bytes_allowed; jiffy_wait = div64_u64(extra_bytes * HZ, tg->bps[rw]); if (!jiffy_wait) @@ -987,7 +987,7 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) bool rw = bio_data_dir(bio); /* Charge the bio to the group */ - tg->bytes_disp[rw] += bio->bi_size; + tg->bytes_disp[rw] += bio->bi_iter.bi_size; tg->io_disp[rw]++; /* @@ -1003,8 +1003,8 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) */ if (!(bio->bi_rw & REQ_THROTTLED)) { bio->bi_rw |= REQ_THROTTLED; - throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, - bio->bi_rw); + throtl_update_dispatch_stats(tg_to_blkg(tg), + bio->bi_iter.bi_size, bio->bi_rw); } } @@ -1508,7 +1508,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) if (tg) { if (!tg->has_rules[rw]) { throtl_update_dispatch_stats(tg_to_blkg(tg), - bio->bi_size, bio->bi_rw); + bio->bi_iter.bi_size, bio->bi_rw); goto out_unlock_rcu; } } @@ -1564,7 +1564,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) /* out-of-limit, queue to @tg */ throtl_log(sq, "[%c] bio. bdisp=%llu sz=%u bps=%llu iodisp=%u iops=%u queued=%d/%d", rw == READ ? 'R' : 'W', - tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], + tg->bytes_disp[rw], bio->bi_iter.bi_size, tg->bps[rw], tg->io_disp[rw], tg->iops[rw], sq->nr_queued[READ], sq->nr_queued[WRITE]); diff --git a/block/elevator.c b/block/elevator.c index b7ff2861b6bd..42c45a7d6714 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -440,7 +440,7 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) /* * See if our hash lookup can find a potential backmerge. */ - __rq = elv_rqhash_find(q, bio->bi_sector); + __rq = elv_rqhash_find(q, bio->bi_iter.bi_sector); if (__rq && elv_rq_merge_ok(__rq, bio)) { *req = __rq; return ELEVATOR_BACK_MERGE; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index d2515435e23f..877ba119b3f8 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -929,8 +929,8 @@ bufinit(struct buf *buf, struct request *rq, struct bio *bio) memset(buf, 0, sizeof(*buf)); buf->rq = rq; buf->bio = bio; - buf->resid = bio->bi_size; - buf->sector = bio->bi_sector; + buf->resid = bio->bi_iter.bi_size; + buf->sector = bio->bi_iter.bi_sector; bio_pageinc(bio); buf->bv = bio_iovec(bio); buf->bv_resid = buf->bv->bv_len; @@ -1152,7 +1152,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) do { bio = rq->bio; bok = !fastfail && test_bit(BIO_UPTODATE, &bio->bi_flags); - } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_size)); + } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_iter.bi_size)); /* cf. http://lkml.org/lkml/2006/10/31/28 */ if (!fastfail) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index d91f1a56e861..66f5aaae15a2 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -333,13 +333,13 @@ static void brd_make_request(struct request_queue *q, struct bio *bio) int i; int err = -EIO; - sector = bio->bi_sector; + sector = bio->bi_iter.bi_sector; if (bio_end_sector(bio) > get_capacity(bdev->bd_disk)) goto out; if (unlikely(bio->bi_rw & REQ_DISCARD)) { err = 0; - discard_from_brd(brd, sector, bio->bi_size); + discard_from_brd(brd, sector, bio->bi_iter.bi_size); goto out; } diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 28c73ca320a8..a9b13f2cc420 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -159,7 +159,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, bio = bio_alloc_drbd(GFP_NOIO); bio->bi_bdev = bdev->md_bdev; - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; err = -EIO; if (bio_add_page(bio, page, size, 0) != size) goto out; diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index b12c11ec4bd2..597f111df67b 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -1028,7 +1028,7 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must } else page = b->bm_pages[page_nr]; bio->bi_bdev = mdev->ldev->md_bdev; - bio->bi_sector = on_disk_sector; + bio->bi_iter.bi_sector = on_disk_sector; /* bio_add_page of a single page to an empty bio will always succeed, * according to api. Do we want to assert that? */ bio_add_page(bio, page, len, 0); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 6fa6673b36b3..5326c22cdb9d 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1333,7 +1333,7 @@ next_bio: goto fail; } /* > peer_req->i.sector, unless this is the first bio */ - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_bdev = mdev->ldev->backing_bdev; bio->bi_rw = rw; bio->bi_private = peer_req; @@ -1353,7 +1353,7 @@ next_bio: dev_err(DEV, "bio_add_page failed for len=%u, " "bi_vcnt=0 (bi_sector=%llu)\n", - len, (unsigned long long)bio->bi_sector); + len, (uint64_t)bio->bi_iter.bi_sector); err = -ENOSPC; goto fail; } @@ -1615,7 +1615,7 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req, mdev->recv_cnt += data_size>>9; bio = req->master_bio; - D_ASSERT(sector == bio->bi_sector); + D_ASSERT(sector == bio->bi_iter.bi_sector); bio_for_each_segment(bvec, bio, i) { void *mapped = kmap(bvec->bv_page) + bvec->bv_offset; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index fec7bef44994..104a040f24de 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -77,8 +77,8 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev, req->epoch = 0; drbd_clear_interval(&req->i); - req->i.sector = bio_src->bi_sector; - req->i.size = bio_src->bi_size; + req->i.sector = bio_src->bi_iter.bi_sector; + req->i.size = bio_src->bi_iter.bi_size; req->i.local = true; req->i.waiting = false; @@ -1280,7 +1280,7 @@ void drbd_make_request(struct request_queue *q, struct bio *bio) /* * what we "blindly" assume: */ - D_ASSERT(IS_ALIGNED(bio->bi_size, 512)); + D_ASSERT(IS_ALIGNED(bio->bi_iter.bi_size, 512)); inc_ap_bio(mdev); __drbd_make_request(mdev, bio, start_time); diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 978cb1addc98..28e15d91197a 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -269,7 +269,7 @@ static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bi /* Short lived temporary struct on the stack. * We could squirrel the error to be returned into - * bio->bi_size, or similar. But that would be too ugly. */ + * bio->bi_iter.bi_size, or similar. But that would be too ugly. */ struct bio_and_error { struct bio *bio; int error; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 000abe2f105c..6a86fe7b730f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3775,9 +3775,9 @@ static int __floppy_read_block_0(struct block_device *bdev) bio_vec.bv_len = size; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; - bio.bi_size = size; + bio.bi_iter.bi_size = size; bio.bi_bdev = bdev; - bio.bi_sector = 0; + bio.bi_iter.bi_sector = 0; bio.bi_flags = (1 << BIO_QUIET); init_completion(&complete); bio.bi_private = &complete; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index c8dac7305244..f5e39989adde 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -415,7 +415,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) loff_t pos; int ret; - pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; + pos = ((loff_t) bio->bi_iter.bi_sector << 9) + lo->lo_offset; if (bio_rw(bio) == WRITE) { struct file *file = lo->lo_backing_file; @@ -444,7 +444,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) goto out; } ret = file->f_op->fallocate(file, mode, pos, - bio->bi_size); + bio->bi_iter.bi_size); if (unlikely(ret && ret != -EINVAL && ret != -EOPNOTSUPP)) ret = -EIO; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 050c71267f14..69e9eb5a6b34 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -3993,7 +3993,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) } if (unlikely(bio->bi_rw & REQ_DISCARD)) { - bio_endio(bio, mtip_send_trim(dd, bio->bi_sector, + bio_endio(bio, mtip_send_trim(dd, bio->bi_iter.bi_sector, bio_sectors(bio))); return; } @@ -4006,7 +4006,8 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) if (bio_data_dir(bio) == WRITE && bio_sectors(bio) <= 64 && dd->unal_qdepth) { - if (bio->bi_sector % 8 != 0) /* Unaligned on 4k boundaries */ + if (bio->bi_iter.bi_sector % 8 != 0) + /* Unaligned on 4k boundaries */ unaligned = 1; else if (bio_sectors(bio) % 8 != 0) /* Aligned but not 4k/8k */ unaligned = 1; @@ -4035,7 +4036,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) /* Issue the read/write. */ mtip_hw_submit_io(dd, - bio->bi_sector, + bio->bi_iter.bi_sector, bio_sectors(bio), nents, tag, diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 26d03fa0bf26..53d217381873 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -468,7 +468,7 @@ static struct nvme_bio_pair *nvme_bio_split(struct bio *bio, int idx, { struct nvme_bio_pair *bp; - BUG_ON(len > bio->bi_size); + BUG_ON(len > bio->bi_iter.bi_size); BUG_ON(idx > bio->bi_vcnt); bp = kmalloc(sizeof(*bp), GFP_ATOMIC); @@ -479,11 +479,11 @@ static struct nvme_bio_pair *nvme_bio_split(struct bio *bio, int idx, bp->b1 = *bio; bp->b2 = *bio; - bp->b1.bi_size = len; - bp->b2.bi_size -= len; + bp->b1.bi_iter.bi_size = len; + bp->b2.bi_iter.bi_size -= len; bp->b1.bi_vcnt = idx; - bp->b2.bi_idx = idx; - bp->b2.bi_sector += len >> 9; + bp->b2.bi_iter.bi_idx = idx; + bp->b2.bi_iter.bi_sector += len >> 9; if (offset) { bp->bv1 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec), @@ -552,11 +552,12 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, { struct bio_vec *bvec, *bvprv = NULL; struct scatterlist *sg = NULL; - int i, length = 0, nsegs = 0, split_len = bio->bi_size; + int i, length = 0, nsegs = 0, split_len = bio->bi_iter.bi_size; if (nvmeq->dev->stripe_size) split_len = nvmeq->dev->stripe_size - - ((bio->bi_sector << 9) & (nvmeq->dev->stripe_size - 1)); + ((bio->bi_iter.bi_sector << 9) & + (nvmeq->dev->stripe_size - 1)); sg_init_table(iod->sg, psegs); bio_for_each_segment(bvec, bio, i) { @@ -584,7 +585,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, if (dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir) == 0) return -ENOMEM; - BUG_ON(length != bio->bi_size); + BUG_ON(length != bio->bi_iter.bi_size); return length; } @@ -608,8 +609,8 @@ static int nvme_submit_discard(struct nvme_queue *nvmeq, struct nvme_ns *ns, iod->npages = 0; range->cattr = cpu_to_le32(0); - range->nlb = cpu_to_le32(bio->bi_size >> ns->lba_shift); - range->slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_sector)); + range->nlb = cpu_to_le32(bio->bi_iter.bi_size >> ns->lba_shift); + range->slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_iter.bi_sector)); memset(cmnd, 0, sizeof(*cmnd)); cmnd->dsm.opcode = nvme_cmd_dsm; @@ -674,7 +675,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, } result = -ENOMEM; - iod = nvme_alloc_iod(psegs, bio->bi_size, GFP_ATOMIC); + iod = nvme_alloc_iod(psegs, bio->bi_iter.bi_size, GFP_ATOMIC); if (!iod) goto nomem; iod->private = bio; @@ -723,7 +724,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, cmnd->rw.nsid = cpu_to_le32(ns->ns_id); length = nvme_setup_prps(nvmeq->dev, &cmnd->common, iod, length, GFP_ATOMIC); - cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_sector)); + cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_iter.bi_sector)); cmnd->rw.length = cpu_to_le16((length >> ns->lba_shift) - 1); cmnd->rw.control = cpu_to_le16(control); cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index ff8668c5efb1..ce986bacf7b7 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -651,7 +651,7 @@ static struct pkt_rb_node *pkt_rbtree_find(struct pktcdvd_device *pd, sector_t s for (;;) { tmp = rb_entry(n, struct pkt_rb_node, rb_node); - if (s <= tmp->bio->bi_sector) + if (s <= tmp->bio->bi_iter.bi_sector) next = n->rb_left; else next = n->rb_right; @@ -660,12 +660,12 @@ static struct pkt_rb_node *pkt_rbtree_find(struct pktcdvd_device *pd, sector_t s n = next; } - if (s > tmp->bio->bi_sector) { + if (s > tmp->bio->bi_iter.bi_sector) { tmp = pkt_rbtree_next(tmp); if (!tmp) return NULL; } - BUG_ON(s > tmp->bio->bi_sector); + BUG_ON(s > tmp->bio->bi_iter.bi_sector); return tmp; } @@ -676,13 +676,13 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod { struct rb_node **p = &pd->bio_queue.rb_node; struct rb_node *parent = NULL; - sector_t s = node->bio->bi_sector; + sector_t s = node->bio->bi_iter.bi_sector; struct pkt_rb_node *tmp; while (*p) { parent = *p; tmp = rb_entry(parent, struct pkt_rb_node, rb_node); - if (s < tmp->bio->bi_sector) + if (s < tmp->bio->bi_iter.bi_sector) p = &(*p)->rb_left; else p = &(*p)->rb_right; @@ -857,7 +857,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) spin_lock(&pd->iosched.lock); bio = bio_list_peek(&pd->iosched.write_queue); spin_unlock(&pd->iosched.lock); - if (bio && (bio->bi_sector == pd->iosched.last_write)) + if (bio && (bio->bi_iter.bi_sector == + pd->iosched.last_write)) need_write_seek = 0; if (need_write_seek && reads_queued) { if (atomic_read(&pd->cdrw.pending_bios) > 0) { @@ -888,7 +889,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) continue; if (bio_data_dir(bio) == READ) - pd->iosched.successive_reads += bio->bi_size >> 10; + pd->iosched.successive_reads += + bio->bi_iter.bi_size >> 10; else { pd->iosched.successive_reads = 0; pd->iosched.last_write = bio_end_sector(bio); @@ -978,7 +980,7 @@ static void pkt_end_io_read(struct bio *bio, int err) pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n", bio, (unsigned long long)pkt->sector, - (unsigned long long)bio->bi_sector, err); + (unsigned long long)bio->bi_iter.bi_sector, err); if (err) atomic_inc(&pkt->io_errors); @@ -1026,8 +1028,9 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) memset(written, 0, sizeof(written)); spin_lock(&pkt->lock); bio_list_for_each(bio, &pkt->orig_bios) { - int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); - int num_frames = bio->bi_size / CD_FRAMESIZE; + int first_frame = (bio->bi_iter.bi_sector - pkt->sector) / + (CD_FRAMESIZE >> 9); + int num_frames = bio->bi_iter.bi_size / CD_FRAMESIZE; pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9); BUG_ON(first_frame < 0); BUG_ON(first_frame + num_frames > pkt->frames); @@ -1053,7 +1056,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) bio = pkt->r_bios[f]; bio_reset(bio); - bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9); + bio->bi_iter.bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9); bio->bi_bdev = pd->bdev; bio->bi_end_io = pkt_end_io_read; bio->bi_private = pkt; @@ -1150,8 +1153,8 @@ static int pkt_start_recovery(struct packet_data *pkt) bio_reset(pkt->bio); pkt->bio->bi_bdev = pd->bdev; pkt->bio->bi_rw = REQ_WRITE; - pkt->bio->bi_sector = new_sector; - pkt->bio->bi_size = pkt->frames * CD_FRAMESIZE; + pkt->bio->bi_iter.bi_sector = new_sector; + pkt->bio->bi_iter.bi_size = pkt->frames * CD_FRAMESIZE; pkt->bio->bi_vcnt = pkt->frames; pkt->bio->bi_end_io = pkt_end_io_packet_write; @@ -1213,7 +1216,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) node = first_node; while (node) { bio = node->bio; - zone = get_zone(bio->bi_sector, pd); + zone = get_zone(bio->bi_iter.bi_sector, pd); list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) { if (p->sector == zone) { bio = NULL; @@ -1252,14 +1255,14 @@ try_next_bio: pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone); while ((node = pkt_rbtree_find(pd, zone)) != NULL) { bio = node->bio; - pkt_dbg(2, pd, "found zone=%llx\n", - (unsigned long long)get_zone(bio->bi_sector, pd)); - if (get_zone(bio->bi_sector, pd) != zone) + pkt_dbg(2, pd, "found zone=%llx\n", (unsigned long long) + get_zone(bio->bi_iter.bi_sector, pd)); + if (get_zone(bio->bi_iter.bi_sector, pd) != zone) break; pkt_rbtree_erase(pd, node); spin_lock(&pkt->lock); bio_list_add(&pkt->orig_bios, bio); - pkt->write_size += bio->bi_size / CD_FRAMESIZE; + pkt->write_size += bio->bi_iter.bi_size / CD_FRAMESIZE; spin_unlock(&pkt->lock); } /* check write congestion marks, and if bio_queue_size is @@ -1293,7 +1296,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) struct bio_vec *bvec = pkt->w_bio->bi_io_vec; bio_reset(pkt->w_bio); - pkt->w_bio->bi_sector = pkt->sector; + pkt->w_bio->bi_iter.bi_sector = pkt->sector; pkt->w_bio->bi_bdev = pd->bdev; pkt->w_bio->bi_end_io = pkt_end_io_packet_write; pkt->w_bio->bi_private = pkt; @@ -2370,20 +2373,20 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) if (!test_bit(PACKET_WRITABLE, &pd->flags)) { pkt_notice(pd, "WRITE for ro device (%llu)\n", - (unsigned long long)bio->bi_sector); + (unsigned long long)bio->bi_iter.bi_sector); goto end_io; } - if (!bio->bi_size || (bio->bi_size % CD_FRAMESIZE)) { + if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { pkt_err(pd, "wrong bio size\n"); goto end_io; } blk_queue_bounce(q, &bio); - zone = get_zone(bio->bi_sector, pd); + zone = get_zone(bio->bi_iter.bi_sector, pd); pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", - (unsigned long long)bio->bi_sector, + (unsigned long long)bio->bi_iter.bi_sector, (unsigned long long)bio_end_sector(bio)); /* Check if we have to split the bio */ @@ -2395,7 +2398,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) last_zone = get_zone(bio_end_sector(bio) - 1, pd); if (last_zone != zone) { BUG_ON(last_zone != zone + pd->settings.size); - first_sectors = last_zone - bio->bi_sector; + first_sectors = last_zone - bio->bi_iter.bi_sector; bp = bio_split(bio, first_sectors); BUG_ON(!bp); pkt_make_request(q, &bp->bio1); @@ -2417,7 +2420,8 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) if ((pkt->state == PACKET_WAITING_STATE) || (pkt->state == PACKET_READ_WAIT_STATE)) { bio_list_add(&pkt->orig_bios, bio); - pkt->write_size += bio->bi_size / CD_FRAMESIZE; + pkt->write_size += + bio->bi_iter.bi_size / CD_FRAMESIZE; if ((pkt->write_size >= pkt->frames) && (pkt->state == PACKET_WAITING_STATE)) { atomic_inc(&pkt->run_sm); diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index d754a88d7585..464be78a0836 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -104,7 +104,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u segs %u sectors from %lu\n", __func__, __LINE__, i, bio_segments(iter.bio), - bio_sectors(iter.bio), iter.bio->bi_sector); + bio_sectors(iter.bio), iter.bio->bi_iter.bi_sector); size = bvec->bv_len; buf = bvec_kmap_irq(bvec, &flags); diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index 06a2e53e5f37..320bbfc9b902 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c @@ -553,7 +553,7 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev, struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev); int write = bio_data_dir(bio) == WRITE; const char *op = write ? "write" : "read"; - loff_t offset = bio->bi_sector << 9; + loff_t offset = bio->bi_iter.bi_sector << 9; int error = 0; struct bio_vec *bvec; unsigned int i; diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index cb1db2979d3d..a8f4fe2d4d1b 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1183,14 +1183,14 @@ static struct bio *bio_clone_range(struct bio *bio_src, /* Handle the easy case for the caller */ - if (!offset && len == bio_src->bi_size) + if (!offset && len == bio_src->bi_iter.bi_size) return bio_clone(bio_src, gfpmask); if (WARN_ON_ONCE(!len)) return NULL; - if (WARN_ON_ONCE(len > bio_src->bi_size)) + if (WARN_ON_ONCE(len > bio_src->bi_iter.bi_size)) return NULL; - if (WARN_ON_ONCE(offset > bio_src->bi_size - len)) + if (WARN_ON_ONCE(offset > bio_src->bi_iter.bi_size - len)) return NULL; /* Find first affected segment... */ @@ -1220,7 +1220,8 @@ static struct bio *bio_clone_range(struct bio *bio_src, return NULL; /* ENOMEM */ bio->bi_bdev = bio_src->bi_bdev; - bio->bi_sector = bio_src->bi_sector + (offset >> SECTOR_SHIFT); + bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector + + (offset >> SECTOR_SHIFT); bio->bi_rw = bio_src->bi_rw; bio->bi_flags |= 1 << BIO_CLONED; @@ -1239,8 +1240,7 @@ static struct bio *bio_clone_range(struct bio *bio_src, } bio->bi_vcnt = vcnt; - bio->bi_size = len; - bio->bi_idx = 0; + bio->bi_iter.bi_size = len; return bio; } @@ -1271,7 +1271,7 @@ static struct bio *bio_chain_clone_range(struct bio **bio_src, /* Build up a chain of clone bios up to the limit */ - if (!bi || off >= bi->bi_size || !len) + if (!bi || off >= bi->bi_iter.bi_size || !len) return NULL; /* Nothing to clone */ end = &chain; @@ -1283,7 +1283,7 @@ static struct bio *bio_chain_clone_range(struct bio **bio_src, rbd_warn(NULL, "bio_chain exhausted with %u left", len); goto out_err; /* EINVAL; ran out of bio's */ } - bi_size = min_t(unsigned int, bi->bi_size - off, len); + bi_size = min_t(unsigned int, bi->bi_iter.bi_size - off, len); bio = bio_clone_range(bi, off, bi_size, gfpmask); if (!bio) goto out_err; /* ENOMEM */ @@ -1292,7 +1292,7 @@ static struct bio *bio_chain_clone_range(struct bio **bio_src, end = &bio->bi_next; off += bi_size; - if (off == bi->bi_size) { + if (off == bi->bi_iter.bi_size) { bi = bi->bi_next; off = 0; } @@ -2186,7 +2186,8 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request, if (type == OBJ_REQUEST_BIO) { bio_list = data_desc; - rbd_assert(img_offset == bio_list->bi_sector << SECTOR_SHIFT); + rbd_assert(img_offset == + bio_list->bi_iter.bi_sector << SECTOR_SHIFT); } else { rbd_assert(type == OBJ_REQUEST_PAGES); pages = data_desc; diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c index 2284f5d3a54a..2839d37e5af7 100644 --- a/drivers/block/rsxx/dev.c +++ b/drivers/block/rsxx/dev.c @@ -174,7 +174,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio) if (!card) goto req_err; - if (bio->bi_sector + (bio->bi_size >> 9) > get_capacity(card->gendisk)) + if (bio_end_sector(bio) > get_capacity(card->gendisk)) goto req_err; if (unlikely(card->halt)) { @@ -187,7 +187,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio) goto req_err; } - if (bio->bi_size == 0) { + if (bio->bi_iter.bi_size == 0) { dev_err(CARD_TO_DEV(card), "size zero BIO!\n"); goto req_err; } @@ -208,7 +208,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio) dev_dbg(CARD_TO_DEV(card), "BIO[%c]: meta: %p addr8: x%llx size: %d\n", bio_data_dir(bio) ? 'W' : 'R', bio_meta, - (u64)bio->bi_sector << 9, bio->bi_size); + (u64)bio->bi_iter.bi_sector << 9, bio->bi_iter.bi_size); st = rsxx_dma_queue_bio(card, bio, &bio_meta->pending_dmas, bio_dma_done_cb, bio_meta); diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c index fc88ba3e1bd2..3716633be3c2 100644 --- a/drivers/block/rsxx/dma.c +++ b/drivers/block/rsxx/dma.c @@ -696,7 +696,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, int st; int i; - addr8 = bio->bi_sector << 9; /* sectors are 512 bytes */ + addr8 = bio->bi_iter.bi_sector << 9; /* sectors are 512 bytes */ atomic_set(n_dmas, 0); for (i = 0; i < card->n_targets; i++) { @@ -705,7 +705,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, } if (bio->bi_rw & REQ_DISCARD) { - bv_len = bio->bi_size; + bv_len = bio->bi_iter.bi_size; while (bv_len > 0) { tgt = rsxx_get_dma_tgt(card, addr8); diff --git a/drivers/block/umem.c b/drivers/block/umem.c index ad70868f8a96..dab4f1afeae9 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -352,8 +352,8 @@ static int add_bio(struct cardinfo *card) bio = card->currentbio; if (!bio && card->bio) { card->currentbio = card->bio; - card->current_idx = card->bio->bi_idx; - card->current_sector = card->bio->bi_sector; + card->current_idx = card->bio->bi_iter.bi_idx; + card->current_sector = card->bio->bi_iter.bi_sector; card->bio = card->bio->bi_next; if (card->bio == NULL) card->biotail = &card->bio; @@ -451,7 +451,7 @@ static void process_page(unsigned long data) if (page->idx >= bio->bi_vcnt) { page->bio = bio->bi_next; if (page->bio) - page->idx = page->bio->bi_idx; + page->idx = page->bio->bi_iter.bi_idx; } pci_unmap_page(card->dev, desc->data_dma_handle, @@ -532,7 +532,8 @@ static void mm_make_request(struct request_queue *q, struct bio *bio) { struct cardinfo *card = q->queuedata; pr_debug("mm_make_request %llu %u\n", - (unsigned long long)bio->bi_sector, bio->bi_size); + (unsigned long long)bio->bi_iter.bi_sector, + bio->bi_iter.bi_size); spin_lock_irq(&card->lock); *card->biotail = bio; diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 6620b73d0490..4b97b86da926 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -1257,7 +1257,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, bio->bi_bdev = preq.bdev; bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; - bio->bi_sector = preq.sector_number; + bio->bi_iter.bi_sector = preq.sector_number; } preq.sector_number += seg[i].nsec; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 432db1b59b00..80e86307dd4b 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1547,7 +1547,7 @@ static int blkif_recover(struct blkfront_info *info) for (i = 0; i < pending; i++) { offset = (i * segs * PAGE_SIZE) >> 9; size = min((unsigned int)(segs * PAGE_SIZE) >> 9, - (unsigned int)(bio->bi_size >> 9) - offset); + (unsigned int)bio_sectors(bio) - offset); cloned_bio = bio_clone(bio, GFP_NOIO); BUG_ON(cloned_bio == NULL); bio_trim(cloned_bio, offset, size); diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 5e2765aadce1..038a6d2aced3 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -299,7 +299,7 @@ void bch_btree_node_read(struct btree *b) bio = bch_bbio_alloc(b->c); bio->bi_rw = REQ_META|READ_SYNC; - bio->bi_size = KEY_SIZE(&b->key) << 9; + bio->bi_iter.bi_size = KEY_SIZE(&b->key) << 9; bio->bi_end_io = btree_node_read_endio; bio->bi_private = &cl; @@ -395,7 +395,7 @@ static void do_btree_node_write(struct btree *b) b->bio->bi_end_io = btree_node_write_endio; b->bio->bi_private = cl; b->bio->bi_rw = REQ_META|WRITE_SYNC|REQ_FUA; - b->bio->bi_size = set_blocks(i, b->c) * block_bytes(b->c); + b->bio->bi_iter.bi_size = set_blocks(i, b->c) * block_bytes(b->c); bch_bio_map(b->bio, i); /* diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c index 264fcfbd6290..92b3fd468a03 100644 --- a/drivers/md/bcache/debug.c +++ b/drivers/md/bcache/debug.c @@ -195,7 +195,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) dc->disk.c, "verify failed at dev %s sector %llu", bdevname(dc->bdev, name), - (uint64_t) bio->bi_sector); + (uint64_t) bio->bi_iter.bi_sector); kunmap_atomic(p1); } diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 9056632995b1..cc4ba2da5fb6 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -21,18 +21,18 @@ static void bch_bi_idx_hack_endio(struct bio *bio, int error) static void bch_generic_make_request_hack(struct bio *bio) { - if (bio->bi_idx) { + if (bio->bi_iter.bi_idx) { struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio)); memcpy(clone->bi_io_vec, bio_iovec(bio), bio_segments(bio) * sizeof(struct bio_vec)); - clone->bi_sector = bio->bi_sector; + clone->bi_iter.bi_sector = bio->bi_iter.bi_sector; clone->bi_bdev = bio->bi_bdev; clone->bi_rw = bio->bi_rw; clone->bi_vcnt = bio_segments(bio); - clone->bi_size = bio->bi_size; + clone->bi_iter.bi_size = bio->bi_iter.bi_size; clone->bi_private = bio; clone->bi_end_io = bch_bi_idx_hack_endio; @@ -72,7 +72,7 @@ static void bch_generic_make_request_hack(struct bio *bio) struct bio *bch_bio_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs) { - unsigned idx = bio->bi_idx, vcnt = 0, nbytes = sectors << 9; + unsigned idx = bio->bi_iter.bi_idx, vcnt = 0, nbytes = sectors << 9; struct bio_vec *bv; struct bio *ret = NULL; @@ -90,7 +90,7 @@ struct bio *bch_bio_split(struct bio *bio, int sectors, } bio_for_each_segment(bv, bio, idx) { - vcnt = idx - bio->bi_idx; + vcnt = idx - bio->bi_iter.bi_idx; if (!nbytes) { ret = bio_alloc_bioset(gfp, vcnt, bs); @@ -119,15 +119,15 @@ struct bio *bch_bio_split(struct bio *bio, int sectors, } out: ret->bi_bdev = bio->bi_bdev; - ret->bi_sector = bio->bi_sector; - ret->bi_size = sectors << 9; + ret->bi_iter.bi_sector = bio->bi_iter.bi_sector; + ret->bi_iter.bi_size = sectors << 9; ret->bi_rw = bio->bi_rw; ret->bi_vcnt = vcnt; ret->bi_max_vecs = vcnt; - bio->bi_sector += sectors; - bio->bi_size -= sectors << 9; - bio->bi_idx = idx; + bio->bi_iter.bi_sector += sectors; + bio->bi_iter.bi_size -= sectors << 9; + bio->bi_iter.bi_idx = idx; if (bio_integrity(bio)) { if (bio_integrity_clone(ret, bio, gfp)) { @@ -162,7 +162,7 @@ static unsigned bch_bio_max_sectors(struct bio *bio) bio_for_each_segment(bv, bio, i) { struct bvec_merge_data bvm = { .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_sector, + .bi_sector = bio->bi_iter.bi_sector, .bi_size = ret << 9, .bi_rw = bio->bi_rw, }; @@ -272,8 +272,8 @@ void __bch_submit_bbio(struct bio *bio, struct cache_set *c) { struct bbio *b = container_of(bio, struct bbio, bio); - bio->bi_sector = PTR_OFFSET(&b->key, 0); - bio->bi_bdev = PTR_CACHE(c, &b->key, 0)->bdev; + bio->bi_iter.bi_sector = PTR_OFFSET(&b->key, 0); + bio->bi_bdev = PTR_CACHE(c, &b->key, 0)->bdev; b->submit_time_us = local_clock_us(); closure_bio_submit(bio, bio->bi_private, PTR_CACHE(c, &b->key, 0)); diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index ecdaa671bd50..7eafdf09a0ae 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -51,10 +51,10 @@ reread: left = ca->sb.bucket_size - offset; len = min_t(unsigned, left, PAGE_SECTORS * 8); bio_reset(bio); - bio->bi_sector = bucket + offset; + bio->bi_iter.bi_sector = bucket + offset; bio->bi_bdev = ca->bdev; bio->bi_rw = READ; - bio->bi_size = len << 9; + bio->bi_iter.bi_size = len << 9; bio->bi_end_io = journal_read_endio; bio->bi_private = &cl; @@ -437,13 +437,13 @@ static void do_journal_discard(struct cache *ca) atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT); bio_init(bio); - bio->bi_sector = bucket_to_sector(ca->set, + bio->bi_iter.bi_sector = bucket_to_sector(ca->set, ca->sb.d[ja->discard_idx]); bio->bi_bdev = ca->bdev; bio->bi_rw = REQ_WRITE|REQ_DISCARD; bio->bi_max_vecs = 1; bio->bi_io_vec = bio->bi_inline_vecs; - bio->bi_size = bucket_bytes(ca); + bio->bi_iter.bi_size = bucket_bytes(ca); bio->bi_end_io = journal_discard_endio; closure_get(&ca->set->cl); @@ -608,10 +608,10 @@ static void journal_write_unlocked(struct closure *cl) atomic_long_add(sectors, &ca->meta_sectors_written); bio_reset(bio); - bio->bi_sector = PTR_OFFSET(k, i); + bio->bi_iter.bi_sector = PTR_OFFSET(k, i); bio->bi_bdev = ca->bdev; bio->bi_rw = REQ_WRITE|REQ_SYNC|REQ_META|REQ_FLUSH|REQ_FUA; - bio->bi_size = sectors << 9; + bio->bi_iter.bi_size = sectors << 9; bio->bi_end_io = journal_write_endio; bio->bi_private = w; diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c index 7c1275e66025..581f95df8265 100644 --- a/drivers/md/bcache/movinggc.c +++ b/drivers/md/bcache/movinggc.c @@ -82,7 +82,7 @@ static void moving_init(struct moving_io *io) bio_get(bio); bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); - bio->bi_size = KEY_SIZE(&io->w->key) << 9; + bio->bi_iter.bi_size = KEY_SIZE(&io->w->key) << 9; bio->bi_max_vecs = DIV_ROUND_UP(KEY_SIZE(&io->w->key), PAGE_SECTORS); bio->bi_private = &io->cl; @@ -98,7 +98,7 @@ static void write_moving(struct closure *cl) if (!op->error) { moving_init(io); - io->bio.bio.bi_sector = KEY_START(&io->w->key); + io->bio.bio.bi_iter.bi_sector = KEY_START(&io->w->key); op->write_prio = 1; op->bio = &io->bio.bio; diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 78bab4154e97..47a9bbc75124 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -261,7 +261,7 @@ static void bch_data_invalidate(struct closure *cl) struct bio *bio = op->bio; pr_debug("invalidating %i sectors from %llu", - bio_sectors(bio), (uint64_t) bio->bi_sector); + bio_sectors(bio), (uint64_t) bio->bi_iter.bi_sector); while (bio_sectors(bio)) { unsigned sectors = min(bio_sectors(bio), @@ -270,11 +270,11 @@ static void bch_data_invalidate(struct closure *cl) if (bch_keylist_realloc(&op->insert_keys, 0, op->c)) goto out; - bio->bi_sector += sectors; - bio->bi_size -= sectors << 9; + bio->bi_iter.bi_sector += sectors; + bio->bi_iter.bi_size -= sectors << 9; bch_keylist_add(&op->insert_keys, - &KEY(op->inode, bio->bi_sector, sectors)); + &KEY(op->inode, bio->bi_iter.bi_sector, sectors)); } op->insert_data_done = true; @@ -364,7 +364,7 @@ static void bch_data_insert_start(struct closure *cl) k = op->insert_keys.top; bkey_init(k); SET_KEY_INODE(k, op->inode); - SET_KEY_OFFSET(k, bio->bi_sector); + SET_KEY_OFFSET(k, bio->bi_iter.bi_sector); if (!bch_alloc_sectors(op->c, k, bio_sectors(bio), op->write_point, op->write_prio, @@ -522,7 +522,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) (bio->bi_rw & REQ_WRITE))) goto skip; - if (bio->bi_sector & (c->sb.block_size - 1) || + if (bio->bi_iter.bi_sector & (c->sb.block_size - 1) || bio_sectors(bio) & (c->sb.block_size - 1)) { pr_debug("skipping unaligned io"); goto skip; @@ -546,8 +546,8 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) spin_lock(&dc->io_lock); - hlist_for_each_entry(i, iohash(dc, bio->bi_sector), hash) - if (i->last == bio->bi_sector && + hlist_for_each_entry(i, iohash(dc, bio->bi_iter.bi_sector), hash) + if (i->last == bio->bi_iter.bi_sector && time_before(jiffies, i->jiffies)) goto found; @@ -556,8 +556,8 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) add_sequential(task); i->sequential = 0; found: - if (i->sequential + bio->bi_size > i->sequential) - i->sequential += bio->bi_size; + if (i->sequential + bio->bi_iter.bi_size > i->sequential) + i->sequential += bio->bi_iter.bi_size; i->last = bio_end_sector(bio); i->jiffies = jiffies + msecs_to_jiffies(5000); @@ -650,15 +650,15 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k) struct bkey *bio_key; unsigned ptr; - if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_sector, 0)) <= 0) + if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0)) <= 0) return MAP_CONTINUE; if (KEY_INODE(k) != s->iop.inode || - KEY_START(k) > bio->bi_sector) { + KEY_START(k) > bio->bi_iter.bi_sector) { unsigned bio_sectors = bio_sectors(bio); unsigned sectors = KEY_INODE(k) == s->iop.inode ? min_t(uint64_t, INT_MAX, - KEY_START(k) - bio->bi_sector) + KEY_START(k) - bio->bi_iter.bi_sector) : INT_MAX; int ret = s->d->cache_miss(b, s, bio, sectors); @@ -681,13 +681,13 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k) s->read_dirty_data = true; n = bch_bio_split(bio, min_t(uint64_t, INT_MAX, - KEY_OFFSET(k) - bio->bi_sector), + KEY_OFFSET(k) - bio->bi_iter.bi_sector), GFP_NOIO, s->d->bio_split); bio_key = &container_of(n, struct bbio, bio)->key; bch_bkey_copy_single_ptr(bio_key, k, ptr); - bch_cut_front(&KEY(s->iop.inode, n->bi_sector, 0), bio_key); + bch_cut_front(&KEY(s->iop.inode, n->bi_iter.bi_sector, 0), bio_key); bch_cut_back(&KEY(s->iop.inode, bio_end_sector(n), 0), bio_key); n->bi_end_io = bch_cache_read_endio; @@ -714,7 +714,7 @@ static void cache_lookup(struct closure *cl) struct bio *bio = &s->bio.bio; int ret = bch_btree_map_keys(&s->op, s->iop.c, - &KEY(s->iop.inode, bio->bi_sector, 0), + &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0), cache_lookup_fn, MAP_END_KEY); if (ret == -EAGAIN) continue_at(cl, cache_lookup, bcache_wq); @@ -872,9 +872,9 @@ static void cached_dev_read_done(struct closure *cl) if (s->iop.bio) { bio_reset(s->iop.bio); - s->iop.bio->bi_sector = s->cache_miss->bi_sector; + s->iop.bio->bi_iter.bi_sector = s->cache_miss->bi_iter.bi_sector; s->iop.bio->bi_bdev = s->cache_miss->bi_bdev; - s->iop.bio->bi_size = s->insert_bio_sectors << 9; + s->iop.bio->bi_iter.bi_size = s->insert_bio_sectors << 9; bch_bio_map(s->iop.bio, NULL); bio_copy_data(s->cache_miss, s->iop.bio); @@ -937,7 +937,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s, s->insert_bio_sectors = min(sectors, bio_sectors(bio) + reada); s->iop.replace_key = KEY(s->iop.inode, - bio->bi_sector + s->insert_bio_sectors, + bio->bi_iter.bi_sector + s->insert_bio_sectors, s->insert_bio_sectors); ret = bch_btree_insert_check_key(b, &s->op, &s->iop.replace_key); @@ -957,9 +957,9 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s, if (!cache_bio) goto out_submit; - cache_bio->bi_sector = miss->bi_sector; - cache_bio->bi_bdev = miss->bi_bdev; - cache_bio->bi_size = s->insert_bio_sectors << 9; + cache_bio->bi_iter.bi_sector = miss->bi_iter.bi_sector; + cache_bio->bi_bdev = miss->bi_bdev; + cache_bio->bi_iter.bi_size = s->insert_bio_sectors << 9; cache_bio->bi_end_io = request_endio; cache_bio->bi_private = &s->cl; @@ -1009,7 +1009,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) { struct closure *cl = &s->cl; struct bio *bio = &s->bio.bio; - struct bkey start = KEY(dc->disk.id, bio->bi_sector, 0); + struct bkey start = KEY(dc->disk.id, bio->bi_iter.bi_sector, 0); struct bkey end = KEY(dc->disk.id, bio_end_sector(bio), 0); bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys, &start, &end); @@ -1104,13 +1104,13 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio) part_stat_unlock(); bio->bi_bdev = dc->bdev; - bio->bi_sector += dc->sb.data_offset; + bio->bi_iter.bi_sector += dc->sb.data_offset; if (cached_dev_get(dc)) { s = search_alloc(bio, d); trace_bcache_request_start(s->d, bio); - if (!bio->bi_size) { + if (!bio->bi_iter.bi_size) { /* * can't call bch_journal_meta from under * generic_make_request @@ -1197,9 +1197,9 @@ static int flash_dev_cache_miss(struct btree *b, struct search *s, sectors -= j; } - bio_advance(bio, min(sectors << 9, bio->bi_size)); + bio_advance(bio, min(sectors << 9, bio->bi_iter.bi_size)); - if (!bio->bi_size) + if (!bio->bi_iter.bi_size) return MAP_DONE; return MAP_CONTINUE; @@ -1233,7 +1233,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio) trace_bcache_request_start(s->d, bio); - if (!bio->bi_size) { + if (!bio->bi_iter.bi_size) { /* * can't call bch_journal_meta from under * generic_make_request @@ -1243,7 +1243,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio) bcache_wq); } else if (rw) { bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys, - &KEY(d->id, bio->bi_sector, 0), + &KEY(d->id, bio->bi_iter.bi_sector, 0), &KEY(d->id, bio_end_sector(bio), 0)); s->iop.bypass = (bio->bi_rw & REQ_DISCARD) != 0; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 1d9ee67d14ec..60fb6044b953 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -233,9 +233,9 @@ static void __write_super(struct cache_sb *sb, struct bio *bio) struct cache_sb *out = page_address(bio->bi_io_vec[0].bv_page); unsigned i; - bio->bi_sector = SB_SECTOR; - bio->bi_rw = REQ_SYNC|REQ_META; - bio->bi_size = SB_SIZE; + bio->bi_iter.bi_sector = SB_SECTOR; + bio->bi_rw = REQ_SYNC|REQ_META; + bio->bi_iter.bi_size = SB_SIZE; bch_bio_map(bio, NULL); out->offset = cpu_to_le64(sb->offset); @@ -347,7 +347,7 @@ static void uuid_io(struct cache_set *c, unsigned long rw, struct bio *bio = bch_bbio_alloc(c); bio->bi_rw = REQ_SYNC|REQ_META|rw; - bio->bi_size = KEY_SIZE(k) << 9; + bio->bi_iter.bi_size = KEY_SIZE(k) << 9; bio->bi_end_io = uuid_endio; bio->bi_private = cl; @@ -503,10 +503,10 @@ static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw) closure_init_stack(cl); - bio->bi_sector = bucket * ca->sb.bucket_size; - bio->bi_bdev = ca->bdev; - bio->bi_rw = REQ_SYNC|REQ_META|rw; - bio->bi_size = bucket_bytes(ca); + bio->bi_iter.bi_sector = bucket * ca->sb.bucket_size; + bio->bi_bdev = ca->bdev; + bio->bi_rw = REQ_SYNC|REQ_META|rw; + bio->bi_iter.bi_size = bucket_bytes(ca); bio->bi_end_io = prio_endio; bio->bi_private = ca; diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c index 462214eeacbe..c57621e49dc0 100644 --- a/drivers/md/bcache/util.c +++ b/drivers/md/bcache/util.c @@ -218,10 +218,10 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done) void bch_bio_map(struct bio *bio, void *base) { - size_t size = bio->bi_size; + size_t size = bio->bi_iter.bi_size; struct bio_vec *bv = bio->bi_io_vec; - BUG_ON(!bio->bi_size); + BUG_ON(!bio->bi_iter.bi_size); BUG_ON(bio->bi_vcnt); bv->bv_offset = base ? ((unsigned long) base) % PAGE_SIZE : 0; diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 99053b1251be..04657e93f4fd 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -113,7 +113,7 @@ static void dirty_init(struct keybuf_key *w) if (!io->dc->writeback_percent) bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); - bio->bi_size = KEY_SIZE(&w->key) << 9; + bio->bi_iter.bi_size = KEY_SIZE(&w->key) << 9; bio->bi_max_vecs = DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS); bio->bi_private = w; bio->bi_io_vec = bio->bi_inline_vecs; @@ -186,7 +186,7 @@ static void write_dirty(struct closure *cl) dirty_init(w); io->bio.bi_rw = WRITE; - io->bio.bi_sector = KEY_START(&w->key); + io->bio.bi_iter.bi_sector = KEY_START(&w->key); io->bio.bi_bdev = io->dc->bdev; io->bio.bi_end_io = dirty_endio; @@ -255,7 +255,7 @@ static void read_dirty(struct cached_dev *dc) io->dc = dc; dirty_init(w); - io->bio.bi_sector = PTR_OFFSET(&w->key, 0); + io->bio.bi_iter.bi_sector = PTR_OFFSET(&w->key, 0); io->bio.bi_bdev = PTR_CACHE(dc->disk.c, &w->key, 0)->bdev; io->bio.bi_rw = READ; diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h index c9ddcf4614b9..e2f8598937ac 100644 --- a/drivers/md/bcache/writeback.h +++ b/drivers/md/bcache/writeback.h @@ -50,7 +50,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio, return false; if (dc->partial_stripes_expensive && - bcache_dev_stripe_dirty(dc, bio->bi_sector, + bcache_dev_stripe_dirty(dc, bio->bi_iter.bi_sector, bio_sectors(bio))) return true; diff --git a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h index 3a8cfa2645c7..5ace48ee9f58 100644 --- a/drivers/md/dm-bio-record.h +++ b/drivers/md/dm-bio-record.h @@ -40,10 +40,10 @@ static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio) { unsigned i; - bd->bi_sector = bio->bi_sector; + bd->bi_sector = bio->bi_iter.bi_sector; bd->bi_bdev = bio->bi_bdev; - bd->bi_size = bio->bi_size; - bd->bi_idx = bio->bi_idx; + bd->bi_size = bio->bi_iter.bi_size; + bd->bi_idx = bio->bi_iter.bi_idx; bd->bi_flags = bio->bi_flags; for (i = 0; i < bio->bi_vcnt; i++) { @@ -56,10 +56,10 @@ static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio) { unsigned i; - bio->bi_sector = bd->bi_sector; + bio->bi_iter.bi_sector = bd->bi_sector; bio->bi_bdev = bd->bi_bdev; - bio->bi_size = bd->bi_size; - bio->bi_idx = bd->bi_idx; + bio->bi_iter.bi_size = bd->bi_size; + bio->bi_iter.bi_idx = bd->bi_idx; bio->bi_flags = bd->bi_flags; for (i = 0; i < bio->bi_vcnt; i++) { diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 173cbb20d104..4113b6044b80 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -538,7 +538,7 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, bio_init(&b->bio); b->bio.bi_io_vec = b->bio_vec; b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS; - b->bio.bi_sector = block << b->c->sectors_per_block_bits; + b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits; b->bio.bi_bdev = b->c->bdev; b->bio.bi_end_io = end_io; diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c index 416b7b752a6e..bfba97dcde2d 100644 --- a/drivers/md/dm-cache-policy-mq.c +++ b/drivers/md/dm-cache-policy-mq.c @@ -72,7 +72,7 @@ static enum io_pattern iot_pattern(struct io_tracker *t) static void iot_update_stats(struct io_tracker *t, struct bio *bio) { - if (bio->bi_sector == from_oblock(t->last_end_oblock) + 1) + if (bio->bi_iter.bi_sector == from_oblock(t->last_end_oblock) + 1) t->nr_seq_samples++; else { /* @@ -87,7 +87,7 @@ static void iot_update_stats(struct io_tracker *t, struct bio *bio) t->nr_rand_samples++; } - t->last_end_oblock = to_oblock(bio->bi_sector + bio_sectors(bio) - 1); + t->last_end_oblock = to_oblock(bio_end_sector(bio) - 1); } static void iot_check_for_pattern_switch(struct io_tracker *t) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 9efcf1059b99..86f9c83eb30c 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -664,15 +664,17 @@ static void remap_to_origin(struct cache *cache, struct bio *bio) static void remap_to_cache(struct cache *cache, struct bio *bio, dm_cblock_t cblock) { - sector_t bi_sector = bio->bi_sector; + sector_t bi_sector = bio->bi_iter.bi_sector; bio->bi_bdev = cache->cache_dev->bdev; if (!block_size_is_power_of_two(cache)) - bio->bi_sector = (from_cblock(cblock) * cache->sectors_per_block) + - sector_div(bi_sector, cache->sectors_per_block); + bio->bi_iter.bi_sector = + (from_cblock(cblock) * cache->sectors_per_block) + + sector_div(bi_sector, cache->sectors_per_block); else - bio->bi_sector = (from_cblock(cblock) << cache->sectors_per_block_shift) | - (bi_sector & (cache->sectors_per_block - 1)); + bio->bi_iter.bi_sector = + (from_cblock(cblock) << cache->sectors_per_block_shift) | + (bi_sector & (cache->sectors_per_block - 1)); } static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio) @@ -712,7 +714,7 @@ static void remap_to_cache_dirty(struct cache *cache, struct bio *bio, static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio) { - sector_t block_nr = bio->bi_sector; + sector_t block_nr = bio->bi_iter.bi_sector; if (!block_size_is_power_of_two(cache)) (void) sector_div(block_nr, cache->sectors_per_block); @@ -1027,7 +1029,7 @@ static void issue_overwrite(struct dm_cache_migration *mg, struct bio *bio) static bool bio_writes_complete_block(struct cache *cache, struct bio *bio) { return (bio_data_dir(bio) == WRITE) && - (bio->bi_size == (cache->sectors_per_block << SECTOR_SHIFT)); + (bio->bi_iter.bi_size == (cache->sectors_per_block << SECTOR_SHIFT)); } static void avoid_copy(struct dm_cache_migration *mg) @@ -1252,7 +1254,7 @@ static void process_flush_bio(struct cache *cache, struct bio *bio) size_t pb_data_size = get_per_bio_data_size(cache); struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size); - BUG_ON(bio->bi_size); + BUG_ON(bio->bi_iter.bi_size); if (!pb->req_nr) remap_to_origin(cache, bio); else @@ -1275,9 +1277,9 @@ static void process_flush_bio(struct cache *cache, struct bio *bio) */ static void process_discard_bio(struct cache *cache, struct bio *bio) { - dm_block_t start_block = dm_sector_div_up(bio->bi_sector, + dm_block_t start_block = dm_sector_div_up(bio->bi_iter.bi_sector, cache->discard_block_size); - dm_block_t end_block = bio->bi_sector + bio_sectors(bio); + dm_block_t end_block = bio_end_sector(bio); dm_block_t b; end_block = block_div(end_block, cache->discard_block_size); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 81b0fa660452..1e2e5465d28e 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -828,8 +828,8 @@ static void crypt_convert_init(struct crypt_config *cc, ctx->bio_out = bio_out; ctx->offset_in = 0; ctx->offset_out = 0; - ctx->idx_in = bio_in ? bio_in->bi_idx : 0; - ctx->idx_out = bio_out ? bio_out->bi_idx : 0; + ctx->idx_in = bio_in ? bio_in->bi_iter.bi_idx : 0; + ctx->idx_out = bio_out ? bio_out->bi_iter.bi_idx : 0; ctx->cc_sector = sector + cc->iv_offset; init_completion(&ctx->restart); } @@ -1021,7 +1021,7 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size, size -= len; } - if (!clone->bi_size) { + if (!clone->bi_iter.bi_size) { bio_put(clone); return NULL; } @@ -1161,7 +1161,7 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) crypt_inc_pending(io); clone_init(io, clone); - clone->bi_sector = cc->start + io->sector; + clone->bi_iter.bi_sector = cc->start + io->sector; generic_make_request(clone); return 0; @@ -1209,7 +1209,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) /* crypt_convert should have filled the clone bio */ BUG_ON(io->ctx.idx_out < clone->bi_vcnt); - clone->bi_sector = cc->start + io->sector; + clone->bi_iter.bi_sector = cc->start + io->sector; if (async) kcryptd_queue_io(io); @@ -1224,7 +1224,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) struct dm_crypt_io *new_io; int crypt_finished; unsigned out_of_pages = 0; - unsigned remaining = io->base_bio->bi_size; + unsigned remaining = io->base_bio->bi_iter.bi_size; sector_t sector = io->sector; int r; @@ -1248,7 +1248,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) io->ctx.bio_out = clone; io->ctx.idx_out = 0; - remaining -= clone->bi_size; + remaining -= clone->bi_iter.bi_size; sector += bio_sectors(clone); crypt_inc_pending(io); @@ -1869,11 +1869,12 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) { bio->bi_bdev = cc->dev->bdev; if (bio_sectors(bio)) - bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector); + bio->bi_iter.bi_sector = cc->start + + dm_target_offset(ti, bio->bi_iter.bi_sector); return DM_MAPIO_REMAPPED; } - io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_sector)); + io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); if (bio_data_dir(io->base_bio) == READ) { if (kcryptd_io_read(io, GFP_NOWAIT)) diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 496d5f3646a5..84c860191a2e 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -281,14 +281,15 @@ static int delay_map(struct dm_target *ti, struct bio *bio) if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) { bio->bi_bdev = dc->dev_write->bdev; if (bio_sectors(bio)) - bio->bi_sector = dc->start_write + - dm_target_offset(ti, bio->bi_sector); + bio->bi_iter.bi_sector = dc->start_write + + dm_target_offset(ti, bio->bi_iter.bi_sector); return delay_bio(dc, dc->write_delay, bio); } bio->bi_bdev = dc->dev_read->bdev; - bio->bi_sector = dc->start_read + dm_target_offset(ti, bio->bi_sector); + bio->bi_iter.bi_sector = dc->start_read + + dm_target_offset(ti, bio->bi_iter.bi_sector); return delay_bio(dc, dc->read_delay, bio); } diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index c80a0ec5f126..b257e46876d3 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -248,7 +248,8 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio) bio->bi_bdev = fc->dev->bdev; if (bio_sectors(bio)) - bio->bi_sector = flakey_map_sector(ti, bio->bi_sector); + bio->bi_iter.bi_sector = + flakey_map_sector(ti, bio->bi_iter.bi_sector); } static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) @@ -265,8 +266,8 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) DMDEBUG("Corrupting data bio=%p by writing %u to byte %u " "(rw=%c bi_rw=%lu bi_sector=%llu cur_bytes=%u)\n", bio, fc->corrupt_bio_value, fc->corrupt_bio_byte, - (bio_data_dir(bio) == WRITE) ? 'w' : 'r', - bio->bi_rw, (unsigned long long)bio->bi_sector, bio_bytes); + (bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_rw, + (unsigned long long)bio->bi_iter.bi_sector, bio_bytes); } } diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 2a20986a2fec..01558b093307 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -304,14 +304,14 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT))); bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); - bio->bi_sector = where->sector + (where->count - remaining); + bio->bi_iter.bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; store_io_and_region_in_bio(bio, io, region); if (rw & REQ_DISCARD) { num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); - bio->bi_size = num_sectors << SECTOR_SHIFT; + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; remaining -= num_sectors; } else if (rw & REQ_WRITE_SAME) { /* @@ -320,7 +320,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, dp->get_page(dp, &page, &len, &offset); bio_add_page(bio, page, logical_block_size, offset); num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining); - bio->bi_size = num_sectors << SECTOR_SHIFT; + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; offset = 0; remaining -= num_sectors; diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 4f99d267340c..53e848c10939 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -85,7 +85,8 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio) bio->bi_bdev = lc->dev->bdev; if (bio_sectors(bio)) - bio->bi_sector = linear_map_sector(ti, bio->bi_sector); + bio->bi_iter.bi_sector = + linear_map_sector(ti, bio->bi_iter.bi_sector); } static int linear_map(struct dm_target *ti, struct bio *bio) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 9584443c5614..9f6d8e6baa7d 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -432,7 +432,7 @@ static int mirror_available(struct mirror_set *ms, struct bio *bio) region_t region = dm_rh_bio_to_region(ms->rh, bio); if (log->type->in_sync(log, region, 0)) - return choose_mirror(ms, bio->bi_sector) ? 1 : 0; + return choose_mirror(ms, bio->bi_iter.bi_sector) ? 1 : 0; return 0; } @@ -442,15 +442,15 @@ static int mirror_available(struct mirror_set *ms, struct bio *bio) */ static sector_t map_sector(struct mirror *m, struct bio *bio) { - if (unlikely(!bio->bi_size)) + if (unlikely(!bio->bi_iter.bi_size)) return 0; - return m->offset + dm_target_offset(m->ms->ti, bio->bi_sector); + return m->offset + dm_target_offset(m->ms->ti, bio->bi_iter.bi_sector); } static void map_bio(struct mirror *m, struct bio *bio) { bio->bi_bdev = m->dev->bdev; - bio->bi_sector = map_sector(m, bio); + bio->bi_iter.bi_sector = map_sector(m, bio); } static void map_region(struct dm_io_region *io, struct mirror *m, @@ -527,7 +527,7 @@ static void read_async_bio(struct mirror *m, struct bio *bio) struct dm_io_request io_req = { .bi_rw = READ, .mem.type = DM_IO_BVEC, - .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx, + .mem.ptr.bvec = bio->bi_io_vec + bio->bi_iter.bi_idx, .notify.fn = read_callback, .notify.context = bio, .client = m->ms->io_client, @@ -559,7 +559,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads) * We can only read balance if the region is in sync. */ if (likely(region_in_sync(ms, region, 1))) - m = choose_mirror(ms, bio->bi_sector); + m = choose_mirror(ms, bio->bi_iter.bi_sector); else if (m && atomic_read(&m->error_count)) m = NULL; @@ -630,7 +630,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio) struct dm_io_request io_req = { .bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA), .mem.type = DM_IO_BVEC, - .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx, + .mem.ptr.bvec = bio->bi_io_vec + bio->bi_iter.bi_idx, .notify.fn = write_callback, .notify.context = bio, .client = ms->io_client, @@ -1181,7 +1181,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio) * The region is in-sync and we can perform reads directly. * Store enough information so we can retry if it fails. */ - m = choose_mirror(ms, bio->bi_sector); + m = choose_mirror(ms, bio->bi_iter.bi_sector); if (unlikely(!m)) return -EIO; diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 69732e03eb34..b929fd5f4984 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -126,7 +126,8 @@ EXPORT_SYMBOL_GPL(dm_rh_region_to_sector); region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio) { - return dm_rh_sector_to_region(rh, bio->bi_sector - rh->target_begin); + return dm_rh_sector_to_region(rh, bio->bi_iter.bi_sector - + rh->target_begin); } EXPORT_SYMBOL_GPL(dm_rh_bio_to_region); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index aec57d76db5d..3ded8c729dfb 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1562,11 +1562,10 @@ static void remap_exception(struct dm_snapshot *s, struct dm_exception *e, struct bio *bio, chunk_t chunk) { bio->bi_bdev = s->cow->bdev; - bio->bi_sector = chunk_to_sector(s->store, - dm_chunk_number(e->new_chunk) + - (chunk - e->old_chunk)) + - (bio->bi_sector & - s->store->chunk_mask); + bio->bi_iter.bi_sector = + chunk_to_sector(s->store, dm_chunk_number(e->new_chunk) + + (chunk - e->old_chunk)) + + (bio->bi_iter.bi_sector & s->store->chunk_mask); } static int snapshot_map(struct dm_target *ti, struct bio *bio) @@ -1584,7 +1583,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_REMAPPED; } - chunk = sector_to_chunk(s->store, bio->bi_sector); + chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector); /* Full snapshots are not usable */ /* To get here the table must be live so s->active is always set. */ @@ -1645,7 +1644,8 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio) r = DM_MAPIO_SUBMITTED; if (!pe->started && - bio->bi_size == (s->store->chunk_size << SECTOR_SHIFT)) { + bio->bi_iter.bi_size == + (s->store->chunk_size << SECTOR_SHIFT)) { pe->started = 1; up_write(&s->lock); start_full_bio(pe, bio); @@ -1701,7 +1701,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_REMAPPED; } - chunk = sector_to_chunk(s->store, bio->bi_sector); + chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector); down_write(&s->lock); @@ -2038,7 +2038,7 @@ static int do_origin(struct dm_dev *origin, struct bio *bio) down_read(&_origins_lock); o = __lookup_origin(origin->bdev); if (o) - r = __origin_write(&o->snapshots, bio->bi_sector, bio); + r = __origin_write(&o->snapshots, bio->bi_iter.bi_sector, bio); up_read(&_origins_lock); return r; diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 73c1712dad96..d1600d2aa2e2 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -259,13 +259,15 @@ static int stripe_map_range(struct stripe_c *sc, struct bio *bio, { sector_t begin, end; - stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin); + stripe_map_range_sector(sc, bio->bi_iter.bi_sector, + target_stripe, &begin); stripe_map_range_sector(sc, bio_end_sector(bio), target_stripe, &end); if (begin < end) { bio->bi_bdev = sc->stripe[target_stripe].dev->bdev; - bio->bi_sector = begin + sc->stripe[target_stripe].physical_start; - bio->bi_size = to_bytes(end - begin); + bio->bi_iter.bi_sector = begin + + sc->stripe[target_stripe].physical_start; + bio->bi_iter.bi_size = to_bytes(end - begin); return DM_MAPIO_REMAPPED; } else { /* The range doesn't map to the target stripe */ @@ -293,9 +295,10 @@ static int stripe_map(struct dm_target *ti, struct bio *bio) return stripe_map_range(sc, bio, target_bio_nr); } - stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); + stripe_map_sector(sc, bio->bi_iter.bi_sector, + &stripe, &bio->bi_iter.bi_sector); - bio->bi_sector += sc->stripe[stripe].physical_start; + bio->bi_iter.bi_sector += sc->stripe[stripe].physical_start; bio->bi_bdev = sc->stripe[stripe].dev->bdev; return DM_MAPIO_REMAPPED; diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c index ff9ac4be4721..09a688b3d48c 100644 --- a/drivers/md/dm-switch.c +++ b/drivers/md/dm-switch.c @@ -311,11 +311,11 @@ error: static int switch_map(struct dm_target *ti, struct bio *bio) { struct switch_ctx *sctx = ti->private; - sector_t offset = dm_target_offset(ti, bio->bi_sector); + sector_t offset = dm_target_offset(ti, bio->bi_iter.bi_sector); unsigned path_nr = switch_get_path_nr(sctx, offset); bio->bi_bdev = sctx->path_list[path_nr].dmdev->bdev; - bio->bi_sector = sctx->path_list[path_nr].start + offset; + bio->bi_iter.bi_sector = sctx->path_list[path_nr].start + offset; return DM_MAPIO_REMAPPED; } diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 2c0cf511ec23..a65402480c8c 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -413,7 +413,7 @@ static bool block_size_is_power_of_two(struct pool *pool) static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio) { struct pool *pool = tc->pool; - sector_t block_nr = bio->bi_sector; + sector_t block_nr = bio->bi_iter.bi_sector; if (block_size_is_power_of_two(pool)) block_nr >>= pool->sectors_per_block_shift; @@ -426,14 +426,15 @@ static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio) static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block) { struct pool *pool = tc->pool; - sector_t bi_sector = bio->bi_sector; + sector_t bi_sector = bio->bi_iter.bi_sector; bio->bi_bdev = tc->pool_dev->bdev; if (block_size_is_power_of_two(pool)) - bio->bi_sector = (block << pool->sectors_per_block_shift) | - (bi_sector & (pool->sectors_per_block - 1)); + bio->bi_iter.bi_sector = + (block << pool->sectors_per_block_shift) | + (bi_sector & (pool->sectors_per_block - 1)); else - bio->bi_sector = (block * pool->sectors_per_block) + + bio->bi_iter.bi_sector = (block * pool->sectors_per_block) + sector_div(bi_sector, pool->sectors_per_block); } @@ -721,7 +722,8 @@ static void process_prepared(struct pool *pool, struct list_head *head, */ static int io_overlaps_block(struct pool *pool, struct bio *bio) { - return bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT); + return bio->bi_iter.bi_size == + (pool->sectors_per_block << SECTOR_SHIFT); } static int io_overwrites_block(struct pool *pool, struct bio *bio) @@ -1130,7 +1132,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, if (bio_detain(pool, &key, bio, &cell)) return; - if (bio_data_dir(bio) == WRITE && bio->bi_size) + if (bio_data_dir(bio) == WRITE && bio->bi_iter.bi_size) break_sharing(tc, bio, block, &key, lookup_result, cell); else { struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); @@ -1153,7 +1155,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block /* * Remap empty bios (flushes) immediately, without provisioning. */ - if (!bio->bi_size) { + if (!bio->bi_iter.bi_size) { inc_all_io_entry(pool, bio); cell_defer_no_holder(tc, cell); @@ -1253,7 +1255,7 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio) r = dm_thin_find_block(tc->td, block, 1, &lookup_result); switch (r) { case 0: - if (lookup_result.shared && (rw == WRITE) && bio->bi_size) + if (lookup_result.shared && (rw == WRITE) && bio->bi_iter.bi_size) bio_io_error(bio); else { inc_all_io_entry(tc->pool, bio); @@ -2867,7 +2869,7 @@ out_unlock: static int thin_map(struct dm_target *ti, struct bio *bio) { - bio->bi_sector = dm_target_offset(ti, bio->bi_sector); + bio->bi_iter.bi_sector = dm_target_offset(ti, bio->bi_iter.bi_sector); return thin_bio_map(ti, bio); } diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 4b7941db3aff..132b3154d466 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -493,9 +493,9 @@ static int verity_map(struct dm_target *ti, struct bio *bio) struct dm_verity_io *io; bio->bi_bdev = v->data_dev->bdev; - bio->bi_sector = verity_map_sector(v, bio->bi_sector); + bio->bi_iter.bi_sector = verity_map_sector(v, bio->bi_iter.bi_sector); - if (((unsigned)bio->bi_sector | bio_sectors(bio)) & + if (((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) & ((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) { DMERR_LIMIT("unaligned io"); return -EIO; @@ -514,8 +514,8 @@ static int verity_map(struct dm_target *ti, struct bio *bio) io->v = v; io->orig_bi_end_io = bio->bi_end_io; io->orig_bi_private = bio->bi_private; - io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT); - io->n_blocks = bio->bi_size >> v->data_dev_block_bits; + io->block = bio->bi_iter.bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT); + io->n_blocks = bio->bi_iter.bi_size >> v->data_dev_block_bits; bio->bi_end_io = verity_end_io; bio->bi_private = io; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0704c523a76b..ccd064ea4fe6 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -575,7 +575,7 @@ static void start_io_acct(struct dm_io *io) atomic_inc_return(&md->pending[rw])); if (unlikely(dm_stats_used(&md->stats))) - dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_sector, + dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_iter.bi_sector, bio_sectors(bio), false, 0, &io->stats_aux); } @@ -593,7 +593,7 @@ static void end_io_acct(struct dm_io *io) part_stat_unlock(); if (unlikely(dm_stats_used(&md->stats))) - dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_sector, + dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_iter.bi_sector, bio_sectors(bio), true, duration, &io->stats_aux); /* @@ -742,7 +742,7 @@ static void dec_pending(struct dm_io *io, int error) if (io_error == DM_ENDIO_REQUEUE) return; - if ((bio->bi_rw & REQ_FLUSH) && bio->bi_size) { + if ((bio->bi_rw & REQ_FLUSH) && bio->bi_iter.bi_size) { /* * Preflush done for flush with data, reissue * without REQ_FLUSH. @@ -797,7 +797,7 @@ static void end_clone_bio(struct bio *clone, int error) struct dm_rq_clone_bio_info *info = clone->bi_private; struct dm_rq_target_io *tio = info->tio; struct bio *bio = info->orig; - unsigned int nr_bytes = info->orig->bi_size; + unsigned int nr_bytes = info->orig->bi_iter.bi_size; bio_put(clone); @@ -1128,7 +1128,7 @@ static void __map_bio(struct dm_target_io *tio) * this io. */ atomic_inc(&tio->io->io_count); - sector = clone->bi_sector; + sector = clone->bi_iter.bi_sector; r = ti->type->map(ti, clone); if (r == DM_MAPIO_REMAPPED) { /* the bio has been remapped so dispatch it */ @@ -1160,13 +1160,13 @@ struct clone_info { static void bio_setup_sector(struct bio *bio, sector_t sector, sector_t len) { - bio->bi_sector = sector; - bio->bi_size = to_bytes(len); + bio->bi_iter.bi_sector = sector; + bio->bi_iter.bi_size = to_bytes(len); } static void bio_setup_bv(struct bio *bio, unsigned short idx, unsigned short bv_count) { - bio->bi_idx = idx; + bio->bi_iter.bi_idx = idx; bio->bi_vcnt = idx + bv_count; bio->bi_flags &= ~(1 << BIO_SEG_VALID); } @@ -1202,7 +1202,7 @@ static void clone_split_bio(struct dm_target_io *tio, struct bio *bio, clone->bi_rw = bio->bi_rw; clone->bi_vcnt = 1; clone->bi_io_vec->bv_offset = offset; - clone->bi_io_vec->bv_len = clone->bi_size; + clone->bi_io_vec->bv_len = clone->bi_iter.bi_size; clone->bi_flags |= 1 << BIO_CLONED; clone_bio_integrity(bio, clone, idx, len, offset, 1); @@ -1222,7 +1222,8 @@ static void clone_bio(struct dm_target_io *tio, struct bio *bio, bio_setup_sector(clone, sector, len); bio_setup_bv(clone, idx, bv_count); - if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) + if (idx != bio->bi_iter.bi_idx || + clone->bi_iter.bi_size < bio->bi_iter.bi_size) trim = 1; clone_bio_integrity(bio, clone, idx, len, 0, trim); } @@ -1510,8 +1511,8 @@ static void __split_and_process_bio(struct mapped_device *md, ci.io->bio = bio; ci.io->md = md; spin_lock_init(&ci.io->endio_lock); - ci.sector = bio->bi_sector; - ci.idx = bio->bi_idx; + ci.sector = bio->bi_iter.bi_sector; + ci.idx = bio->bi_iter.bi_idx; start_io_acct(ci.io); diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 3193aefe982b..e8b4574956c7 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -74,8 +74,8 @@ static void faulty_fail(struct bio *bio, int error) { struct bio *b = bio->bi_private; - b->bi_size = bio->bi_size; - b->bi_sector = bio->bi_sector; + b->bi_iter.bi_size = bio->bi_iter.bi_size; + b->bi_iter.bi_sector = bio->bi_iter.bi_sector; bio_put(bio); @@ -185,26 +185,31 @@ static void make_request(struct mddev *mddev, struct bio *bio) return; } - if (check_sector(conf, bio->bi_sector, bio_end_sector(bio), WRITE)) + if (check_sector(conf, bio->bi_iter.bi_sector, + bio_end_sector(bio), WRITE)) failit = 1; if (check_mode(conf, WritePersistent)) { - add_sector(conf, bio->bi_sector, WritePersistent); + add_sector(conf, bio->bi_iter.bi_sector, + WritePersistent); failit = 1; } if (check_mode(conf, WriteTransient)) failit = 1; } else { /* read request */ - if (check_sector(conf, bio->bi_sector, bio_end_sector(bio), READ)) + if (check_sector(conf, bio->bi_iter.bi_sector, + bio_end_sector(bio), READ)) failit = 1; if (check_mode(conf, ReadTransient)) failit = 1; if (check_mode(conf, ReadPersistent)) { - add_sector(conf, bio->bi_sector, ReadPersistent); + add_sector(conf, bio->bi_iter.bi_sector, + ReadPersistent); failit = 1; } if (check_mode(conf, ReadFixable)) { - add_sector(conf, bio->bi_sector, ReadFixable); + add_sector(conf, bio->bi_iter.bi_sector, + ReadFixable); failit = 1; } } diff --git a/drivers/md/linear.c b/drivers/md/linear.c index f03fabd2b37b..fb3b0d04edfb 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -297,19 +297,19 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) } rcu_read_lock(); - tmp_dev = which_dev(mddev, bio->bi_sector); + tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; - if (unlikely(bio->bi_sector >= (tmp_dev->end_sector) - || (bio->bi_sector < start_sector))) { + if (unlikely(bio->bi_iter.bi_sector >= (tmp_dev->end_sector) + || (bio->bi_iter.bi_sector < start_sector))) { char b[BDEVNAME_SIZE]; printk(KERN_ERR "md/linear:%s: make_request: Sector %llu out of bounds on " "dev %s: %llu sectors, offset %llu\n", mdname(mddev), - (unsigned long long)bio->bi_sector, + (unsigned long long)bio->bi_iter.bi_sector, bdevname(tmp_dev->rdev->bdev, b), (unsigned long long)tmp_dev->rdev->sectors, (unsigned long long)start_sector); @@ -326,7 +326,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) rcu_read_unlock(); - bp = bio_split(bio, end_sector - bio->bi_sector); + bp = bio_split(bio, end_sector - bio->bi_iter.bi_sector); linear_make_request(mddev, &bp->bio1); linear_make_request(mddev, &bp->bio2); @@ -335,7 +335,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) } bio->bi_bdev = tmp_dev->rdev->bdev; - bio->bi_sector = bio->bi_sector - start_sector + bio->bi_iter.bi_sector = bio->bi_iter.bi_sector - start_sector + tmp_dev->rdev->data_offset; rcu_read_unlock(); diff --git a/drivers/md/md.c b/drivers/md/md.c index 739b1ec54e28..b07fed398fd7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -393,7 +393,7 @@ static void md_submit_flush_data(struct work_struct *ws) struct mddev *mddev = container_of(ws, struct mddev, flush_work); struct bio *bio = mddev->flush_bio; - if (bio->bi_size == 0) + if (bio->bi_iter.bi_size == 0) /* an empty barrier - all done */ bio_endio(bio, 0); else { @@ -754,7 +754,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev); bio->bi_bdev = rdev->meta_bdev ? rdev->meta_bdev : rdev->bdev; - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; @@ -785,13 +785,13 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, bio->bi_bdev = (metadata_op && rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; if (metadata_op) - bio->bi_sector = sector + rdev->sb_start; + bio->bi_iter.bi_sector = sector + rdev->sb_start; else if (rdev->mddev->reshape_position != MaxSector && (rdev->mddev->reshape_backwards == (sector >= rdev->mddev->reshape_position))) - bio->bi_sector = sector + rdev->new_data_offset; + bio->bi_iter.bi_sector = sector + rdev->new_data_offset; else - bio->bi_sector = sector + rdev->data_offset; + bio->bi_iter.bi_sector = sector + rdev->data_offset; bio_add_page(bio, page, size, 0); submit_bio_wait(rw, bio); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 1642eae75a33..849ad39f547b 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -100,7 +100,7 @@ static void multipath_end_request(struct bio *bio, int error) md_error (mp_bh->mddev, rdev); printk(KERN_ERR "multipath: %s: rescheduling sector %llu\n", bdevname(rdev->bdev,b), - (unsigned long long)bio->bi_sector); + (unsigned long long)bio->bi_iter.bi_sector); multipath_reschedule_retry(mp_bh); } else multipath_end_bh_io(mp_bh, error); @@ -132,7 +132,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio) multipath = conf->multipaths + mp_bh->path; mp_bh->bio = *bio; - mp_bh->bio.bi_sector += multipath->rdev->data_offset; + mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset; mp_bh->bio.bi_bdev = multipath->rdev->bdev; mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT; mp_bh->bio.bi_end_io = multipath_end_request; @@ -355,21 +355,22 @@ static void multipathd(struct md_thread *thread) spin_unlock_irqrestore(&conf->device_lock, flags); bio = &mp_bh->bio; - bio->bi_sector = mp_bh->master_bio->bi_sector; + bio->bi_iter.bi_sector = mp_bh->master_bio->bi_iter.bi_sector; if ((mp_bh->path = multipath_map (conf))<0) { printk(KERN_ALERT "multipath: %s: unrecoverable IO read" " error for block %llu\n", bdevname(bio->bi_bdev,b), - (unsigned long long)bio->bi_sector); + (unsigned long long)bio->bi_iter.bi_sector); multipath_end_bh_io(mp_bh, -EIO); } else { printk(KERN_ERR "multipath: %s: redirecting sector %llu" " to another IO path\n", bdevname(bio->bi_bdev,b), - (unsigned long long)bio->bi_sector); + (unsigned long long)bio->bi_iter.bi_sector); *bio = *(mp_bh->master_bio); - bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset; + bio->bi_iter.bi_sector += + conf->multipaths[mp_bh->path].rdev->data_offset; bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev; bio->bi_rw |= REQ_FAILFAST_TRANSPORT; bio->bi_end_io = multipath_end_request; diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c4d420b7d2f4..e38d1d3226f3 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -501,10 +501,11 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev, unsigned int chunk_sects, struct bio *bio) { if (likely(is_power_of_2(chunk_sects))) { - return chunk_sects >= ((bio->bi_sector & (chunk_sects-1)) + return chunk_sects >= + ((bio->bi_iter.bi_sector & (chunk_sects-1)) + bio_sectors(bio)); } else{ - sector_t sector = bio->bi_sector; + sector_t sector = bio->bi_iter.bi_sector; return chunk_sects >= (sector_div(sector, chunk_sects) + bio_sectors(bio)); } @@ -524,7 +525,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) chunk_sects = mddev->chunk_sectors; if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) { - sector_t sector = bio->bi_sector; + sector_t sector = bio->bi_iter.bi_sector; struct bio_pair *bp; /* Sanity check -- queue functions should prevent this happening */ if (bio_segments(bio) > 1) @@ -544,12 +545,12 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) return; } - sector_offset = bio->bi_sector; + sector_offset = bio->bi_iter.bi_sector; zone = find_zone(mddev->private, §or_offset); - tmp_dev = map_sector(mddev, zone, bio->bi_sector, + tmp_dev = map_sector(mddev, zone, bio->bi_iter.bi_sector, §or_offset); bio->bi_bdev = tmp_dev->bdev; - bio->bi_sector = sector_offset + zone->dev_start + + bio->bi_iter.bi_sector = sector_offset + zone->dev_start + tmp_dev->data_offset; if (unlikely((bio->bi_rw & REQ_DISCARD) && @@ -566,7 +567,8 @@ bad_map: printk("md/raid0:%s: make_request bug: can't convert block across chunks" " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects / 2, - (unsigned long long)bio->bi_sector, bio_sectors(bio) / 2); + (unsigned long long)bio->bi_iter.bi_sector, + bio_sectors(bio) / 2); bio_io_error(bio); return; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1e5a540995e9..db3b9d7314f1 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -229,7 +229,7 @@ static void call_bio_endio(struct r1bio *r1_bio) int done; struct r1conf *conf = r1_bio->mddev->private; sector_t start_next_window = r1_bio->start_next_window; - sector_t bi_sector = bio->bi_sector; + sector_t bi_sector = bio->bi_iter.bi_sector; if (bio->bi_phys_segments) { unsigned long flags; @@ -265,9 +265,8 @@ static void raid_end_bio_io(struct r1bio *r1_bio) if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) { pr_debug("raid1: sync end %s on sectors %llu-%llu\n", (bio_data_dir(bio) == WRITE) ? "write" : "read", - (unsigned long long) bio->bi_sector, - (unsigned long long) bio->bi_sector + - bio_sectors(bio) - 1); + (unsigned long long) bio->bi_iter.bi_sector, + (unsigned long long) bio_end_sector(bio) - 1); call_bio_endio(r1_bio); } @@ -466,9 +465,8 @@ static void raid1_end_write_request(struct bio *bio, int error) struct bio *mbio = r1_bio->master_bio; pr_debug("raid1: behind end write sectors" " %llu-%llu\n", - (unsigned long long) mbio->bi_sector, - (unsigned long long) mbio->bi_sector + - bio_sectors(mbio) - 1); + (unsigned long long) mbio->bi_iter.bi_sector, + (unsigned long long) bio_end_sector(mbio) - 1); call_bio_endio(r1_bio); } } @@ -875,7 +873,7 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio) else if ((conf->next_resync - RESYNC_WINDOW_SECTORS >= bio_end_sector(bio)) || (conf->next_resync + NEXT_NORMALIO_DISTANCE - <= bio->bi_sector)) + <= bio->bi_iter.bi_sector)) wait = false; else wait = true; @@ -913,19 +911,19 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) if (bio && bio_data_dir(bio) == WRITE) { if (conf->next_resync + NEXT_NORMALIO_DISTANCE - <= bio->bi_sector) { + <= bio->bi_iter.bi_sector) { if (conf->start_next_window == MaxSector) conf->start_next_window = conf->next_resync + NEXT_NORMALIO_DISTANCE; if ((conf->start_next_window + NEXT_NORMALIO_DISTANCE) - <= bio->bi_sector) + <= bio->bi_iter.bi_sector) conf->next_window_requests++; else conf->current_window_requests++; } - if (bio->bi_sector >= conf->start_next_window) + if (bio->bi_iter.bi_sector >= conf->start_next_window) sector = conf->start_next_window; } @@ -1028,7 +1026,8 @@ do_sync_io: if (bvecs[i].bv_page) put_page(bvecs[i].bv_page); kfree(bvecs); - pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size); + pr_debug("%dB behind alloc failed, doing sync I/O\n", + bio->bi_iter.bi_size); } struct raid1_plug_cb { @@ -1108,7 +1107,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) if (bio_data_dir(bio) == WRITE && bio_end_sector(bio) > mddev->suspend_lo && - bio->bi_sector < mddev->suspend_hi) { + bio->bi_iter.bi_sector < mddev->suspend_hi) { /* As the suspend_* range is controlled by * userspace, we want an interruptible * wait. @@ -1119,7 +1118,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) prepare_to_wait(&conf->wait_barrier, &w, TASK_INTERRUPTIBLE); if (bio_end_sector(bio) <= mddev->suspend_lo || - bio->bi_sector >= mddev->suspend_hi) + bio->bi_iter.bi_sector >= mddev->suspend_hi) break; schedule(); } @@ -1141,7 +1140,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) r1_bio->sectors = bio_sectors(bio); r1_bio->state = 0; r1_bio->mddev = mddev; - r1_bio->sector = bio->bi_sector; + r1_bio->sector = bio->bi_iter.bi_sector; /* We might need to issue multiple reads to different * devices if there are bad blocks around, so we keep @@ -1181,12 +1180,13 @@ read_again: r1_bio->read_disk = rdisk; read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev); - bio_trim(read_bio, r1_bio->sector - bio->bi_sector, + bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector, max_sectors); r1_bio->bios[rdisk] = read_bio; - read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; + read_bio->bi_iter.bi_sector = r1_bio->sector + + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = raid1_end_read_request; read_bio->bi_rw = READ | do_sync; @@ -1198,7 +1198,7 @@ read_again: */ sectors_handled = (r1_bio->sector + max_sectors - - bio->bi_sector); + - bio->bi_iter.bi_sector); r1_bio->sectors = max_sectors; spin_lock_irq(&conf->device_lock); if (bio->bi_phys_segments == 0) @@ -1219,7 +1219,8 @@ read_again: r1_bio->sectors = bio_sectors(bio) - sectors_handled; r1_bio->state = 0; r1_bio->mddev = mddev; - r1_bio->sector = bio->bi_sector + sectors_handled; + r1_bio->sector = bio->bi_iter.bi_sector + + sectors_handled; goto read_again; } else generic_make_request(read_bio); @@ -1322,7 +1323,7 @@ read_again: if (r1_bio->bios[j]) rdev_dec_pending(conf->mirrors[j].rdev, mddev); r1_bio->state = 0; - allow_barrier(conf, start_next_window, bio->bi_sector); + allow_barrier(conf, start_next_window, bio->bi_iter.bi_sector); md_wait_for_blocked_rdev(blocked_rdev, mddev); start_next_window = wait_barrier(conf, bio); /* @@ -1349,7 +1350,7 @@ read_again: bio->bi_phys_segments++; spin_unlock_irq(&conf->device_lock); } - sectors_handled = r1_bio->sector + max_sectors - bio->bi_sector; + sectors_handled = r1_bio->sector + max_sectors - bio->bi_iter.bi_sector; atomic_set(&r1_bio->remaining, 1); atomic_set(&r1_bio->behind_remaining, 0); @@ -1361,7 +1362,7 @@ read_again: continue; mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - bio_trim(mbio, r1_bio->sector - bio->bi_sector, max_sectors); + bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector, max_sectors); if (first_clone) { /* do behind I/O ? @@ -1395,7 +1396,7 @@ read_again: r1_bio->bios[i] = mbio; - mbio->bi_sector = (r1_bio->sector + + mbio->bi_iter.bi_sector = (r1_bio->sector + conf->mirrors[i].rdev->data_offset); mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; @@ -1435,7 +1436,7 @@ read_again: r1_bio->sectors = bio_sectors(bio) - sectors_handled; r1_bio->state = 0; r1_bio->mddev = mddev; - r1_bio->sector = bio->bi_sector + sectors_handled; + r1_bio->sector = bio->bi_iter.bi_sector + sectors_handled; goto retry_write; } @@ -1959,14 +1960,14 @@ static int process_checks(struct r1bio *r1_bio) /* fixup the bio for reuse */ bio_reset(b); b->bi_vcnt = vcnt; - b->bi_size = r1_bio->sectors << 9; - b->bi_sector = r1_bio->sector + + b->bi_iter.bi_size = r1_bio->sectors << 9; + b->bi_iter.bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; b->bi_bdev = conf->mirrors[i].rdev->bdev; b->bi_end_io = end_sync_read; b->bi_private = r1_bio; - size = b->bi_size; + size = b->bi_iter.bi_size; for (j = 0; j < vcnt ; j++) { struct bio_vec *bi; bi = &b->bi_io_vec[j]; @@ -2221,11 +2222,11 @@ static int narrow_write_error(struct r1bio *r1_bio, int i) } wbio->bi_rw = WRITE; - wbio->bi_sector = r1_bio->sector; - wbio->bi_size = r1_bio->sectors << 9; + wbio->bi_iter.bi_sector = r1_bio->sector; + wbio->bi_iter.bi_size = r1_bio->sectors << 9; bio_trim(wbio, sector - r1_bio->sector, sectors); - wbio->bi_sector += rdev->data_offset; + wbio->bi_iter.bi_sector += rdev->data_offset; wbio->bi_bdev = rdev->bdev; if (submit_bio_wait(WRITE, wbio) == 0) /* failure! */ @@ -2339,7 +2340,8 @@ read_more: } r1_bio->read_disk = disk; bio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev); - bio_trim(bio, r1_bio->sector - bio->bi_sector, max_sectors); + bio_trim(bio, r1_bio->sector - bio->bi_iter.bi_sector, + max_sectors); r1_bio->bios[r1_bio->read_disk] = bio; rdev = conf->mirrors[disk].rdev; printk_ratelimited(KERN_ERR @@ -2348,7 +2350,7 @@ read_more: mdname(mddev), (unsigned long long)r1_bio->sector, bdevname(rdev->bdev, b)); - bio->bi_sector = r1_bio->sector + rdev->data_offset; + bio->bi_iter.bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_bdev = rdev->bdev; bio->bi_end_io = raid1_end_read_request; bio->bi_rw = READ | do_sync; @@ -2357,7 +2359,7 @@ read_more: /* Drat - have to split this up more */ struct bio *mbio = r1_bio->master_bio; int sectors_handled = (r1_bio->sector + max_sectors - - mbio->bi_sector); + - mbio->bi_iter.bi_sector); r1_bio->sectors = max_sectors; spin_lock_irq(&conf->device_lock); if (mbio->bi_phys_segments == 0) @@ -2375,7 +2377,8 @@ read_more: r1_bio->state = 0; set_bit(R1BIO_ReadError, &r1_bio->state); r1_bio->mddev = mddev; - r1_bio->sector = mbio->bi_sector + sectors_handled; + r1_bio->sector = mbio->bi_iter.bi_sector + + sectors_handled; goto read_more; } else @@ -2599,7 +2602,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp } if (bio->bi_end_io) { atomic_inc(&rdev->nr_pending); - bio->bi_sector = sector_nr + rdev->data_offset; + bio->bi_iter.bi_sector = sector_nr + rdev->data_offset; bio->bi_bdev = rdev->bdev; bio->bi_private = r1_bio; } @@ -2699,7 +2702,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp continue; /* remove last page from this bio */ bio->bi_vcnt--; - bio->bi_size -= len; + bio->bi_iter.bi_size -= len; bio->bi_flags &= ~(1<< BIO_SEG_VALID); } goto bio_full; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c504e8389e69..dbf3b63c2754 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1182,7 +1182,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) /* If this request crosses a chunk boundary, we need to * split it. This will only happen for 1 PAGE (or less) requests. */ - if (unlikely((bio->bi_sector & chunk_mask) + bio_sectors(bio) + if (unlikely((bio->bi_iter.bi_sector & chunk_mask) + bio_sectors(bio) > chunk_sects && (conf->geo.near_copies < conf->geo.raid_disks || conf->prev.near_copies < conf->prev.raid_disks))) { @@ -1193,8 +1193,8 @@ static void make_request(struct mddev *mddev, struct bio * bio) /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. */ - bp = bio_split(bio, - chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); + bp = bio_split(bio, chunk_sects - + (bio->bi_iter.bi_sector & (chunk_sects - 1))); /* Each of these 'make_request' calls will call 'wait_barrier'. * If the first succeeds but the second blocks due to the resync @@ -1221,7 +1221,8 @@ static void make_request(struct mddev *mddev, struct bio * bio) bad_map: printk("md/raid10:%s: make_request bug: can't convert block across chunks" " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2, - (unsigned long long)bio->bi_sector, bio_sectors(bio) / 2); + (unsigned long long)bio->bi_iter.bi_sector, + bio_sectors(bio) / 2); bio_io_error(bio); return; @@ -1238,24 +1239,25 @@ static void make_request(struct mddev *mddev, struct bio * bio) sectors = bio_sectors(bio); while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && - bio->bi_sector < conf->reshape_progress && - bio->bi_sector + sectors > conf->reshape_progress) { + bio->bi_iter.bi_sector < conf->reshape_progress && + bio->bi_iter.bi_sector + sectors > conf->reshape_progress) { /* IO spans the reshape position. Need to wait for * reshape to pass */ allow_barrier(conf); wait_event(conf->wait_barrier, - conf->reshape_progress <= bio->bi_sector || - conf->reshape_progress >= bio->bi_sector + sectors); + conf->reshape_progress <= bio->bi_iter.bi_sector || + conf->reshape_progress >= bio->bi_iter.bi_sector + + sectors); wait_barrier(conf); } if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && bio_data_dir(bio) == WRITE && (mddev->reshape_backwards - ? (bio->bi_sector < conf->reshape_safe && - bio->bi_sector + sectors > conf->reshape_progress) - : (bio->bi_sector + sectors > conf->reshape_safe && - bio->bi_sector < conf->reshape_progress))) { + ? (bio->bi_iter.bi_sector < conf->reshape_safe && + bio->bi_iter.bi_sector + sectors > conf->reshape_progress) + : (bio->bi_iter.bi_sector + sectors > conf->reshape_safe && + bio->bi_iter.bi_sector < conf->reshape_progress))) { /* Need to update reshape_position in metadata */ mddev->reshape_position = conf->reshape_progress; set_bit(MD_CHANGE_DEVS, &mddev->flags); @@ -1273,7 +1275,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) r10_bio->sectors = sectors; r10_bio->mddev = mddev; - r10_bio->sector = bio->bi_sector; + r10_bio->sector = bio->bi_iter.bi_sector; r10_bio->state = 0; /* We might need to issue multiple reads to different @@ -1302,13 +1304,13 @@ read_again: slot = r10_bio->read_slot; read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev); - bio_trim(read_bio, r10_bio->sector - bio->bi_sector, + bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector, max_sectors); r10_bio->devs[slot].bio = read_bio; r10_bio->devs[slot].rdev = rdev; - read_bio->bi_sector = r10_bio->devs[slot].addr + + read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr + choose_data_offset(r10_bio, rdev); read_bio->bi_bdev = rdev->bdev; read_bio->bi_end_io = raid10_end_read_request; @@ -1320,7 +1322,7 @@ read_again: * need another r10_bio. */ sectors_handled = (r10_bio->sectors + max_sectors - - bio->bi_sector); + - bio->bi_iter.bi_sector); r10_bio->sectors = max_sectors; spin_lock_irq(&conf->device_lock); if (bio->bi_phys_segments == 0) @@ -1341,7 +1343,8 @@ read_again: r10_bio->sectors = bio_sectors(bio) - sectors_handled; r10_bio->state = 0; r10_bio->mddev = mddev; - r10_bio->sector = bio->bi_sector + sectors_handled; + r10_bio->sector = bio->bi_iter.bi_sector + + sectors_handled; goto read_again; } else generic_make_request(read_bio); @@ -1499,7 +1502,8 @@ retry_write: bio->bi_phys_segments++; spin_unlock_irq(&conf->device_lock); } - sectors_handled = r10_bio->sector + max_sectors - bio->bi_sector; + sectors_handled = r10_bio->sector + max_sectors - + bio->bi_iter.bi_sector; atomic_set(&r10_bio->remaining, 1); bitmap_startwrite(mddev->bitmap, r10_bio->sector, r10_bio->sectors, 0); @@ -1510,11 +1514,11 @@ retry_write: if (r10_bio->devs[i].bio) { struct md_rdev *rdev = conf->mirrors[d].rdev; mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - bio_trim(mbio, r10_bio->sector - bio->bi_sector, + bio_trim(mbio, r10_bio->sector - bio->bi_iter.bi_sector, max_sectors); r10_bio->devs[i].bio = mbio; - mbio->bi_sector = (r10_bio->devs[i].addr+ + mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+ choose_data_offset(r10_bio, rdev)); mbio->bi_bdev = rdev->bdev; @@ -1553,11 +1557,11 @@ retry_write: rdev = conf->mirrors[d].rdev; } mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - bio_trim(mbio, r10_bio->sector - bio->bi_sector, + bio_trim(mbio, r10_bio->sector - bio->bi_iter.bi_sector, max_sectors); r10_bio->devs[i].repl_bio = mbio; - mbio->bi_sector = (r10_bio->devs[i].addr + + mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr + choose_data_offset( r10_bio, rdev)); mbio->bi_bdev = rdev->bdev; @@ -1591,7 +1595,7 @@ retry_write: r10_bio->sectors = bio_sectors(bio) - sectors_handled; r10_bio->mddev = mddev; - r10_bio->sector = bio->bi_sector + sectors_handled; + r10_bio->sector = bio->bi_iter.bi_sector + sectors_handled; r10_bio->state = 0; goto retry_write; } @@ -2124,10 +2128,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) bio_reset(tbio); tbio->bi_vcnt = vcnt; - tbio->bi_size = r10_bio->sectors << 9; + tbio->bi_iter.bi_size = r10_bio->sectors << 9; tbio->bi_rw = WRITE; tbio->bi_private = r10_bio; - tbio->bi_sector = r10_bio->devs[i].addr; + tbio->bi_iter.bi_sector = r10_bio->devs[i].addr; for (j=0; j < vcnt ; j++) { tbio->bi_io_vec[j].bv_offset = 0; @@ -2144,7 +2148,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) atomic_inc(&r10_bio->remaining); md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(tbio)); - tbio->bi_sector += conf->mirrors[d].rdev->data_offset; + tbio->bi_iter.bi_sector += conf->mirrors[d].rdev->data_offset; tbio->bi_bdev = conf->mirrors[d].rdev->bdev; generic_make_request(tbio); } @@ -2614,8 +2618,8 @@ static int narrow_write_error(struct r10bio *r10_bio, int i) sectors = sect_to_write; /* Write at 'sector' for 'sectors' */ wbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - bio_trim(wbio, sector - bio->bi_sector, sectors); - wbio->bi_sector = (r10_bio->devs[i].addr+ + bio_trim(wbio, sector - bio->bi_iter.bi_sector, sectors); + wbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+ choose_data_offset(r10_bio, rdev) + (sector - r10_bio->sector)); wbio->bi_bdev = rdev->bdev; @@ -2687,10 +2691,10 @@ read_more: (unsigned long long)r10_bio->sector); bio = bio_clone_mddev(r10_bio->master_bio, GFP_NOIO, mddev); - bio_trim(bio, r10_bio->sector - bio->bi_sector, max_sectors); + bio_trim(bio, r10_bio->sector - bio->bi_iter.bi_sector, max_sectors); r10_bio->devs[slot].bio = bio; r10_bio->devs[slot].rdev = rdev; - bio->bi_sector = r10_bio->devs[slot].addr + bio->bi_iter.bi_sector = r10_bio->devs[slot].addr + choose_data_offset(r10_bio, rdev); bio->bi_bdev = rdev->bdev; bio->bi_rw = READ | do_sync; @@ -2701,7 +2705,7 @@ read_more: struct bio *mbio = r10_bio->master_bio; int sectors_handled = r10_bio->sector + max_sectors - - mbio->bi_sector; + - mbio->bi_iter.bi_sector; r10_bio->sectors = max_sectors; spin_lock_irq(&conf->device_lock); if (mbio->bi_phys_segments == 0) @@ -2719,7 +2723,7 @@ read_more: set_bit(R10BIO_ReadError, &r10_bio->state); r10_bio->mddev = mddev; - r10_bio->sector = mbio->bi_sector + r10_bio->sector = mbio->bi_iter.bi_sector + sectors_handled; goto read_more; @@ -3157,7 +3161,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, bio->bi_end_io = end_sync_read; bio->bi_rw = READ; from_addr = r10_bio->devs[j].addr; - bio->bi_sector = from_addr + rdev->data_offset; + bio->bi_iter.bi_sector = from_addr + + rdev->data_offset; bio->bi_bdev = rdev->bdev; atomic_inc(&rdev->nr_pending); /* and we write to 'i' (if not in_sync) */ @@ -3181,7 +3186,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; bio->bi_rw = WRITE; - bio->bi_sector = to_addr + bio->bi_iter.bi_sector = to_addr + rdev->data_offset; bio->bi_bdev = rdev->bdev; atomic_inc(&r10_bio->remaining); @@ -3210,7 +3215,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; bio->bi_rw = WRITE; - bio->bi_sector = to_addr + rdev->data_offset; + bio->bi_iter.bi_sector = to_addr + + rdev->data_offset; bio->bi_bdev = rdev->bdev; atomic_inc(&r10_bio->remaining); break; @@ -3328,7 +3334,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, bio->bi_private = r10_bio; bio->bi_end_io = end_sync_read; bio->bi_rw = READ; - bio->bi_sector = sector + + bio->bi_iter.bi_sector = sector + conf->mirrors[d].rdev->data_offset; bio->bi_bdev = conf->mirrors[d].rdev->bdev; count++; @@ -3350,7 +3356,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; bio->bi_rw = WRITE; - bio->bi_sector = sector + + bio->bi_iter.bi_sector = sector + conf->mirrors[d].replacement->data_offset; bio->bi_bdev = conf->mirrors[d].replacement->bdev; count++; @@ -3397,7 +3403,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, bio2 = bio2->bi_next) { /* remove last page from this bio */ bio2->bi_vcnt--; - bio2->bi_size -= len; + bio2->bi_iter.bi_size -= len; bio2->bi_flags &= ~(1<< BIO_SEG_VALID); } goto bio_full; @@ -4417,7 +4423,7 @@ read_more: read_bio = bio_alloc_mddev(GFP_KERNEL, RESYNC_PAGES, mddev); read_bio->bi_bdev = rdev->bdev; - read_bio->bi_sector = (r10_bio->devs[r10_bio->read_slot].addr + read_bio->bi_iter.bi_sector = (r10_bio->devs[r10_bio->read_slot].addr + rdev->data_offset); read_bio->bi_private = r10_bio; read_bio->bi_end_io = end_sync_read; @@ -4425,7 +4431,7 @@ read_more: read_bio->bi_flags &= ~(BIO_POOL_MASK - 1); read_bio->bi_flags |= 1 << BIO_UPTODATE; read_bio->bi_vcnt = 0; - read_bio->bi_size = 0; + read_bio->bi_iter.bi_size = 0; r10_bio->master_bio = read_bio; r10_bio->read_slot = r10_bio->devs[r10_bio->read_slot].devnum; @@ -4451,7 +4457,8 @@ read_more: bio_reset(b); b->bi_bdev = rdev2->bdev; - b->bi_sector = r10_bio->devs[s/2].addr + rdev2->new_data_offset; + b->bi_iter.bi_sector = r10_bio->devs[s/2].addr + + rdev2->new_data_offset; b->bi_private = r10_bio; b->bi_end_io = end_reshape_write; b->bi_rw = WRITE; @@ -4478,7 +4485,7 @@ read_more: bio2 = bio2->bi_next) { /* Remove last page from this bio */ bio2->bi_vcnt--; - bio2->bi_size -= len; + bio2->bi_iter.bi_size -= len; bio2->bi_flags &= ~(1<bi_sector + sectors < sector + STRIPE_SECTORS) + if (bio->bi_iter.bi_sector + sectors < sector + STRIPE_SECTORS) return bio->bi_next; else return NULL; @@ -225,7 +225,7 @@ static void return_io(struct bio *return_bi) return_bi = bi->bi_next; bi->bi_next = NULL; - bi->bi_size = 0; + bi->bi_iter.bi_size = 0; trace_block_bio_complete(bdev_get_queue(bi->bi_bdev), bi, 0); bio_endio(bi, 0); @@ -854,10 +854,10 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi->bi_rw, i); atomic_inc(&sh->count); if (use_new_offset(conf, sh)) - bi->bi_sector = (sh->sector + bi->bi_iter.bi_sector = (sh->sector + rdev->new_data_offset); else - bi->bi_sector = (sh->sector + bi->bi_iter.bi_sector = (sh->sector + rdev->data_offset); if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) bi->bi_rw |= REQ_NOMERGE; @@ -865,7 +865,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi->bi_vcnt = 1; bi->bi_io_vec[0].bv_len = STRIPE_SIZE; bi->bi_io_vec[0].bv_offset = 0; - bi->bi_size = STRIPE_SIZE; + bi->bi_iter.bi_size = STRIPE_SIZE; /* * If this is discard request, set bi_vcnt 0. We don't * want to confuse SCSI because SCSI will replace payload @@ -901,15 +901,15 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) rbi->bi_rw, i); atomic_inc(&sh->count); if (use_new_offset(conf, sh)) - rbi->bi_sector = (sh->sector + rbi->bi_iter.bi_sector = (sh->sector + rrdev->new_data_offset); else - rbi->bi_sector = (sh->sector + rbi->bi_iter.bi_sector = (sh->sector + rrdev->data_offset); rbi->bi_vcnt = 1; rbi->bi_io_vec[0].bv_len = STRIPE_SIZE; rbi->bi_io_vec[0].bv_offset = 0; - rbi->bi_size = STRIPE_SIZE; + rbi->bi_iter.bi_size = STRIPE_SIZE; /* * If this is discard request, set bi_vcnt 0. We don't * want to confuse SCSI because SCSI will replace payload @@ -944,10 +944,10 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, struct async_submit_ctl submit; enum async_tx_flags flags = 0; - if (bio->bi_sector >= sector) - page_offset = (signed)(bio->bi_sector - sector) * 512; + if (bio->bi_iter.bi_sector >= sector) + page_offset = (signed)(bio->bi_iter.bi_sector - sector) * 512; else - page_offset = (signed)(sector - bio->bi_sector) * -512; + page_offset = (signed)(sector - bio->bi_iter.bi_sector) * -512; if (frombio) flags |= ASYNC_TX_FENCE; @@ -1014,7 +1014,7 @@ static void ops_complete_biofill(void *stripe_head_ref) BUG_ON(!dev->read); rbi = dev->read; dev->read = NULL; - while (rbi && rbi->bi_sector < + while (rbi && rbi->bi_iter.bi_sector < dev->sector + STRIPE_SECTORS) { rbi2 = r5_next_bio(rbi, dev->sector); if (!raid5_dec_bi_active_stripes(rbi)) { @@ -1050,7 +1050,7 @@ static void ops_run_biofill(struct stripe_head *sh) dev->read = rbi = dev->toread; dev->toread = NULL; spin_unlock_irq(&sh->stripe_lock); - while (rbi && rbi->bi_sector < + while (rbi && rbi->bi_iter.bi_sector < dev->sector + STRIPE_SECTORS) { tx = async_copy_data(0, rbi, dev->page, dev->sector, tx); @@ -1392,7 +1392,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) wbi = dev->written = chosen; spin_unlock_irq(&sh->stripe_lock); - while (wbi && wbi->bi_sector < + while (wbi && wbi->bi_iter.bi_sector < dev->sector + STRIPE_SECTORS) { if (wbi->bi_rw & REQ_FUA) set_bit(R5_WantFUA, &dev->flags); @@ -2616,7 +2616,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in int firstwrite=0; pr_debug("adding bi b#%llu to stripe s#%llu\n", - (unsigned long long)bi->bi_sector, + (unsigned long long)bi->bi_iter.bi_sector, (unsigned long long)sh->sector); /* @@ -2634,12 +2634,12 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in firstwrite = 1; } else bip = &sh->dev[dd_idx].toread; - while (*bip && (*bip)->bi_sector < bi->bi_sector) { - if (bio_end_sector(*bip) > bi->bi_sector) + while (*bip && (*bip)->bi_iter.bi_sector < bi->bi_iter.bi_sector) { + if (bio_end_sector(*bip) > bi->bi_iter.bi_sector) goto overlap; bip = & (*bip)->bi_next; } - if (*bip && (*bip)->bi_sector < bio_end_sector(bi)) + if (*bip && (*bip)->bi_iter.bi_sector < bio_end_sector(bi)) goto overlap; BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next); @@ -2653,7 +2653,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in sector_t sector = sh->dev[dd_idx].sector; for (bi=sh->dev[dd_idx].towrite; sector < sh->dev[dd_idx].sector + STRIPE_SECTORS && - bi && bi->bi_sector <= sector; + bi && bi->bi_iter.bi_sector <= sector; bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) { if (bio_end_sector(bi) >= sector) sector = bio_end_sector(bi); @@ -2663,7 +2663,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in } pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n", - (unsigned long long)(*bip)->bi_sector, + (unsigned long long)(*bip)->bi_iter.bi_sector, (unsigned long long)sh->sector, dd_idx); spin_unlock_irq(&sh->stripe_lock); @@ -2738,7 +2738,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh, if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) wake_up(&conf->wait_for_overlap); - while (bi && bi->bi_sector < + while (bi && bi->bi_iter.bi_sector < sh->dev[i].sector + STRIPE_SECTORS) { struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); @@ -2757,7 +2757,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh, bi = sh->dev[i].written; sh->dev[i].written = NULL; if (bi) bitmap_end = 1; - while (bi && bi->bi_sector < + while (bi && bi->bi_iter.bi_sector < sh->dev[i].sector + STRIPE_SECTORS) { struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); @@ -2781,7 +2781,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh, spin_unlock_irq(&sh->stripe_lock); if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) wake_up(&conf->wait_for_overlap); - while (bi && bi->bi_sector < + while (bi && bi->bi_iter.bi_sector < sh->dev[i].sector + STRIPE_SECTORS) { struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); @@ -3005,7 +3005,7 @@ static void handle_stripe_clean_event(struct r5conf *conf, clear_bit(R5_UPTODATE, &dev->flags); wbi = dev->written; dev->written = NULL; - while (wbi && wbi->bi_sector < + while (wbi && wbi->bi_iter.bi_sector < dev->sector + STRIPE_SECTORS) { wbi2 = r5_next_bio(wbi, dev->sector); if (!raid5_dec_bi_active_stripes(wbi)) { @@ -4097,7 +4097,7 @@ static int raid5_mergeable_bvec(struct request_queue *q, static int in_chunk_boundary(struct mddev *mddev, struct bio *bio) { - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); + sector_t sector = bio->bi_iter.bi_sector + get_start_sect(bio->bi_bdev); unsigned int chunk_sectors = mddev->chunk_sectors; unsigned int bio_sectors = bio_sectors(bio); @@ -4234,9 +4234,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) /* * compute position */ - align_bi->bi_sector = raid5_compute_sector(conf, raid_bio->bi_sector, - 0, - &dd_idx, NULL); + align_bi->bi_iter.bi_sector = + raid5_compute_sector(conf, raid_bio->bi_iter.bi_sector, + 0, &dd_idx, NULL); end_sector = bio_end_sector(align_bi); rcu_read_lock(); @@ -4261,7 +4261,8 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) align_bi->bi_flags &= ~(1 << BIO_SEG_VALID); if (!bio_fits_rdev(align_bi) || - is_badblock(rdev, align_bi->bi_sector, bio_sectors(align_bi), + is_badblock(rdev, align_bi->bi_iter.bi_sector, + bio_sectors(align_bi), &first_bad, &bad_sectors)) { /* too big in some way, or has a known bad block */ bio_put(align_bi); @@ -4270,7 +4271,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) } /* No reshape active, so we can trust rdev->data_offset */ - align_bi->bi_sector += rdev->data_offset; + align_bi->bi_iter.bi_sector += rdev->data_offset; spin_lock_irq(&conf->device_lock); wait_event_lock_irq(conf->wait_for_stripe, @@ -4282,7 +4283,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) if (mddev->gendisk) trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev), align_bi, disk_devt(mddev->gendisk), - raid_bio->bi_sector); + raid_bio->bi_iter.bi_sector); generic_make_request(align_bi); return 1; } else { @@ -4465,8 +4466,8 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi) /* Skip discard while reshape is happening */ return; - logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); - last_sector = bi->bi_sector + (bi->bi_size>>9); + logical_sector = bi->bi_iter.bi_sector & ~((sector_t)STRIPE_SECTORS-1); + last_sector = bi->bi_iter.bi_sector + (bi->bi_iter.bi_size>>9); bi->bi_next = NULL; bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ @@ -4570,7 +4571,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) return; } - logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); + logical_sector = bi->bi_iter.bi_sector & ~((sector_t)STRIPE_SECTORS-1); last_sector = bio_end_sector(bi); bi->bi_next = NULL; bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ @@ -5054,7 +5055,8 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio) int remaining; int handled = 0; - logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1); + logical_sector = raid_bio->bi_iter.bi_sector & + ~((sector_t)STRIPE_SECTORS-1); sector = raid5_compute_sector(conf, logical_sector, 0, &dd_idx, NULL); last_sector = bio_end_sector(raid_bio); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 6eca019bcf30..16814a8457f8 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -819,7 +819,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) dev_info = bio->bi_bdev->bd_disk->private_data; if (dev_info == NULL) goto fail; - if ((bio->bi_sector & 7) != 0 || (bio->bi_size & 4095) != 0) + if ((bio->bi_iter.bi_sector & 7) != 0 || + (bio->bi_iter.bi_size & 4095) != 0) /* Request is not page-aligned. */ goto fail; if (bio_end_sector(bio) > get_capacity(bio->bi_bdev->bd_disk)) { @@ -842,7 +843,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) } } - index = (bio->bi_sector >> 3); + index = (bio->bi_iter.bi_sector >> 3); bio_for_each_segment(bvec, bio, i) { page_addr = (unsigned long) page_address(bvec->bv_page) + bvec->bv_offset; diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 464dd29d06c0..dd4e73fdb323 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -190,15 +190,16 @@ static void xpram_make_request(struct request_queue *q, struct bio *bio) unsigned long bytes; int i; - if ((bio->bi_sector & 7) != 0 || (bio->bi_size & 4095) != 0) + if ((bio->bi_iter.bi_sector & 7) != 0 || + (bio->bi_iter.bi_size & 4095) != 0) /* Request is not page-aligned. */ goto fail; - if ((bio->bi_size >> 12) > xdev->size) + if ((bio->bi_iter.bi_size >> 12) > xdev->size) /* Request size is no page-aligned. */ goto fail; - if ((bio->bi_sector >> 3) > 0xffffffffU - xdev->offset) + if ((bio->bi_iter.bi_sector >> 3) > 0xffffffffU - xdev->offset) goto fail; - index = (bio->bi_sector >> 3) + xdev->offset; + index = (bio->bi_iter.bi_sector >> 3) + xdev->offset; bio_for_each_segment(bvec, bio, i) { page_addr = (unsigned long) kmap(bvec->bv_page) + bvec->bv_offset; diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index aa66361ed44b..bac04c2335aa 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -731,7 +731,7 @@ static int _osd_req_list_objects(struct osd_request *or, bio->bi_rw &= ~REQ_WRITE; or->in.bio = bio; - or->in.total_bytes = bio->bi_size; + or->in.total_bytes = bio->bi_iter.bi_size; return 0; } diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index e2421ea61352..53741be754b4 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -220,7 +220,7 @@ static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head) for (bio = head; bio != NULL; bio = bio->bi_next) { LASSERT(rw == bio->bi_rw); - offset = (pgoff_t)(bio->bi_sector << 9) + lo->lo_offset; + offset = (pgoff_t)(bio->bi_iter.bi_sector << 9) + lo->lo_offset; bio_for_each_segment(bvec, bio, i) { BUG_ON(bvec->bv_offset != 0); BUG_ON(bvec->bv_len != PAGE_CACHE_SIZE); @@ -313,7 +313,8 @@ static unsigned int loop_get_bio(struct lloop_device *lo, struct bio **req) bio = &lo->lo_bio; while (*bio && (*bio)->bi_rw == rw) { CDEBUG(D_INFO, "bio sector %llu size %u count %u vcnt%u \n", - (unsigned long long)(*bio)->bi_sector, (*bio)->bi_size, + (unsigned long long)(*bio)->bi_iter.bi_sector, + (*bio)->bi_iter.bi_size, page_count, (*bio)->bi_vcnt); if (page_count + (*bio)->bi_vcnt > LLOOP_MAX_SEGMENTS) break; @@ -347,7 +348,8 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio) goto err; CDEBUG(D_INFO, "submit bio sector %llu size %u\n", - (unsigned long long)old_bio->bi_sector, old_bio->bi_size); + (unsigned long long)old_bio->bi_iter.bi_sector, + old_bio->bi_iter.bi_size); spin_lock_irq(&lo->lo_lock); inactive = (lo->lo_state != LLOOP_BOUND); @@ -367,7 +369,7 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio) loop_add_bio(lo, old_bio); return; err: - cfs_bio_io_error(old_bio, old_bio->bi_size); + cfs_bio_io_error(old_bio, old_bio->bi_iter.bi_size); } @@ -378,7 +380,7 @@ static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio) while (bio) { struct bio *tmp = bio->bi_next; bio->bi_next = NULL; - cfs_bio_endio(bio, bio->bi_size, ret); + cfs_bio_endio(bio, bio->bi_iter.bi_size, ret); bio = tmp; } } diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 79ce363b2ea9..e9e6f984092b 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -171,13 +171,14 @@ static inline int valid_io_request(struct zram *zram, struct bio *bio) u64 start, end, bound; /* unaligned request */ - if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1))) + if (unlikely(bio->bi_iter.bi_sector & + (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1))) return 0; - if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1))) + if (unlikely(bio->bi_iter.bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1))) return 0; - start = bio->bi_sector; - end = start + (bio->bi_size >> SECTOR_SHIFT); + start = bio->bi_iter.bi_sector; + end = start + (bio->bi_iter.bi_size >> SECTOR_SHIFT); bound = zram->disksize >> SECTOR_SHIFT; /* out of range range */ if (unlikely(start >= bound || end > bound || start > end)) @@ -684,8 +685,9 @@ static void __zram_make_request(struct zram *zram, struct bio *bio, int rw) break; } - index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; - offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; + index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; + offset = (bio->bi_iter.bi_sector & + (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; bio_for_each_segment(bvec, bio, i) { int max_transfer_size = PAGE_SIZE - offset; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index c87959f12760..2d29356d0c85 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -319,7 +319,7 @@ iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) bio->bi_bdev = ib_dev->ibd_bd; bio->bi_private = cmd; bio->bi_end_io = &iblock_bio_done; - bio->bi_sector = lba; + bio->bi_iter.bi_sector = lba; return bio; } diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index fc60b31453ee..08e3d1388c65 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -215,9 +215,9 @@ unsigned int bio_integrity_tag_size(struct bio *bio) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); - BUG_ON(bio->bi_size == 0); + BUG_ON(bio->bi_iter.bi_size == 0); - return bi->tag_size * (bio->bi_size / bi->sector_size); + return bi->tag_size * (bio->bi_iter.bi_size / bi->sector_size); } EXPORT_SYMBOL(bio_integrity_tag_size); @@ -300,7 +300,7 @@ static void bio_integrity_generate(struct bio *bio) struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); struct blk_integrity_exchg bix; struct bio_vec *bv; - sector_t sector = bio->bi_sector; + sector_t sector = bio->bi_iter.bi_sector; unsigned int i, sectors, total; void *prot_buf = bio->bi_integrity->bip_buf; @@ -387,7 +387,7 @@ int bio_integrity_prep(struct bio *bio) bip->bip_owns_buf = 1; bip->bip_buf = buf; bip->bip_size = len; - bip->bip_sector = bio->bi_sector; + bip->bip_sector = bio->bi_iter.bi_sector; /* Map it */ offset = offset_in_page(buf); diff --git a/fs/bio.c b/fs/bio.c index 33d79a4eb92d..a402ad6e753f 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -532,13 +532,13 @@ void __bio_clone(struct bio *bio, struct bio *bio_src) * most users will be overriding ->bi_bdev with a new target, * so we don't set nor calculate new physical/hw segment counts here */ - bio->bi_sector = bio_src->bi_sector; + bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_bdev = bio_src->bi_bdev; bio->bi_flags |= 1 << BIO_CLONED; bio->bi_rw = bio_src->bi_rw; bio->bi_vcnt = bio_src->bi_vcnt; - bio->bi_size = bio_src->bi_size; - bio->bi_idx = bio_src->bi_idx; + bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; + bio->bi_iter.bi_idx = bio_src->bi_iter.bi_idx; } EXPORT_SYMBOL(__bio_clone); @@ -612,7 +612,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page if (unlikely(bio_flagged(bio, BIO_CLONED))) return 0; - if (((bio->bi_size + len) >> 9) > max_sectors) + if (((bio->bi_iter.bi_size + len) >> 9) > max_sectors) return 0; /* @@ -635,8 +635,9 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page simulate merging updated prev_bvec as new bvec. */ .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_sector, - .bi_size = bio->bi_size - prev_bv_len, + .bi_sector = bio->bi_iter.bi_sector, + .bi_size = bio->bi_iter.bi_size - + prev_bv_len, .bi_rw = bio->bi_rw, }; @@ -684,8 +685,8 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page if (q->merge_bvec_fn) { struct bvec_merge_data bvm = { .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_sector, - .bi_size = bio->bi_size, + .bi_sector = bio->bi_iter.bi_sector, + .bi_size = bio->bi_iter.bi_size, .bi_rw = bio->bi_rw, }; @@ -708,7 +709,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page bio->bi_vcnt++; bio->bi_phys_segments++; done: - bio->bi_size += len; + bio->bi_iter.bi_size += len; return len; } @@ -807,22 +808,22 @@ void bio_advance(struct bio *bio, unsigned bytes) if (bio_integrity(bio)) bio_integrity_advance(bio, bytes); - bio->bi_sector += bytes >> 9; - bio->bi_size -= bytes; + bio->bi_iter.bi_sector += bytes >> 9; + bio->bi_iter.bi_size -= bytes; if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) return; while (bytes) { - if (unlikely(bio->bi_idx >= bio->bi_vcnt)) { + if (unlikely(bio->bi_iter.bi_idx >= bio->bi_vcnt)) { WARN_ONCE(1, "bio idx %d >= vcnt %d\n", - bio->bi_idx, bio->bi_vcnt); + bio->bi_iter.bi_idx, bio->bi_vcnt); break; } if (bytes >= bio_iovec(bio)->bv_len) { bytes -= bio_iovec(bio)->bv_len; - bio->bi_idx++; + bio->bi_iter.bi_idx++; } else { bio_iovec(bio)->bv_len -= bytes; bio_iovec(bio)->bv_offset += bytes; @@ -1485,7 +1486,7 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len, if (IS_ERR(bio)) return bio; - if (bio->bi_size == len) + if (bio->bi_iter.bi_size == len) return bio; /* @@ -1763,16 +1764,16 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors) return bp; trace_block_split(bdev_get_queue(bi->bi_bdev), bi, - bi->bi_sector + first_sectors); + bi->bi_iter.bi_sector + first_sectors); BUG_ON(bio_segments(bi) > 1); atomic_set(&bp->cnt, 3); bp->error = 0; bp->bio1 = *bi; bp->bio2 = *bi; - bp->bio2.bi_sector += first_sectors; - bp->bio2.bi_size -= first_sectors << 9; - bp->bio1.bi_size = first_sectors << 9; + bp->bio2.bi_iter.bi_sector += first_sectors; + bp->bio2.bi_iter.bi_size -= first_sectors << 9; + bp->bio1.bi_iter.bi_size = first_sectors << 9; if (bi->bi_vcnt != 0) { bp->bv1 = *bio_iovec(bi); @@ -1821,21 +1822,22 @@ void bio_trim(struct bio *bio, int offset, int size) int sofar = 0; size <<= 9; - if (offset == 0 && size == bio->bi_size) + if (offset == 0 && size == bio->bi_iter.bi_size) return; clear_bit(BIO_SEG_VALID, &bio->bi_flags); bio_advance(bio, offset << 9); - bio->bi_size = size; + bio->bi_iter.bi_size = size; /* avoid any complications with bi_idx being non-zero*/ - if (bio->bi_idx) { - memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_idx, - (bio->bi_vcnt - bio->bi_idx) * sizeof(struct bio_vec)); - bio->bi_vcnt -= bio->bi_idx; - bio->bi_idx = 0; + if (bio->bi_iter.bi_idx) { + memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_iter.bi_idx, + (bio->bi_vcnt - bio->bi_iter.bi_idx) * + sizeof(struct bio_vec)); + bio->bi_vcnt -= bio->bi_iter.bi_idx; + bio->bi_iter.bi_idx = 0; } /* Make sure vcnt and last bv are not too big */ bio_for_each_segment(bvec, bio, i) { @@ -1871,7 +1873,7 @@ sector_t bio_sector_offset(struct bio *bio, unsigned short index, sector_sz = queue_logical_block_size(bio->bi_bdev->bd_disk->queue); sectors = 0; - if (index >= bio->bi_idx) + if (index >= bio->bi_iter.bi_idx) index = bio->bi_vcnt - 1; bio_for_each_segment_all(bv, bio, i) { diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 131d82800b3a..cb05e1c842c5 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1695,7 +1695,7 @@ static int btrfsic_read_block(struct btrfsic_state *state, return -1; } bio->bi_bdev = block_ctx->dev->bdev; - bio->bi_sector = dev_bytenr >> 9; + bio->bi_iter.bi_sector = dev_bytenr >> 9; for (j = i; j < num_pages; j++) { ret = bio_add_page(bio, block_ctx->pagev[j], @@ -3013,7 +3013,7 @@ static void __btrfsic_submit_bio(int rw, struct bio *bio) int bio_is_patched; char **mapped_datav; - dev_bytenr = 512 * bio->bi_sector; + dev_bytenr = 512 * bio->bi_iter.bi_sector; bio_is_patched = 0; if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) @@ -3021,8 +3021,8 @@ static void __btrfsic_submit_bio(int rw, struct bio *bio) "submit_bio(rw=0x%x, bi_vcnt=%u," " bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n", rw, bio->bi_vcnt, - (unsigned long long)bio->bi_sector, dev_bytenr, - bio->bi_bdev); + (unsigned long long)bio->bi_iter.bi_sector, + dev_bytenr, bio->bi_bdev); mapped_datav = kmalloc(sizeof(*mapped_datav) * bio->bi_vcnt, GFP_NOFS); diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index eac6784e43d7..f5cdeb4b5538 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -172,7 +172,8 @@ static void end_compressed_bio_read(struct bio *bio, int err) goto out; inode = cb->inode; - ret = check_compressed_csum(inode, cb, (u64)bio->bi_sector << 9); + ret = check_compressed_csum(inode, cb, + (u64)bio->bi_iter.bi_sector << 9); if (ret) goto csum_failed; @@ -370,7 +371,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, for (pg_index = 0; pg_index < cb->nr_pages; pg_index++) { page = compressed_pages[pg_index]; page->mapping = inode->i_mapping; - if (bio->bi_size) + if (bio->bi_iter.bi_size) ret = io_tree->ops->merge_bio_hook(WRITE, page, 0, PAGE_CACHE_SIZE, bio, 0); @@ -504,7 +505,7 @@ static noinline int add_ra_bio_pages(struct inode *inode, if (!em || last_offset < em->start || (last_offset + PAGE_CACHE_SIZE > extent_map_end(em)) || - (em->block_start >> 9) != cb->orig_bio->bi_sector) { + (em->block_start >> 9) != cb->orig_bio->bi_iter.bi_sector) { free_extent_map(em); unlock_extent(tree, last_offset, end); unlock_page(page); @@ -550,7 +551,7 @@ next: * in it. We don't actually do IO on those pages but allocate new ones * to hold the compressed pages on disk. * - * bio->bi_sector points to the compressed extent on disk + * bio->bi_iter.bi_sector points to the compressed extent on disk * bio->bi_io_vec points to all of the inode pages * bio->bi_vcnt is a count of pages * @@ -571,7 +572,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, struct page *page; struct block_device *bdev; struct bio *comp_bio; - u64 cur_disk_byte = (u64)bio->bi_sector << 9; + u64 cur_disk_byte = (u64)bio->bi_iter.bi_sector << 9; u64 em_len; u64 em_start; struct extent_map *em; @@ -657,7 +658,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, page->mapping = inode->i_mapping; page->index = em_start >> PAGE_CACHE_SHIFT; - if (comp_bio->bi_size) + if (comp_bio->bi_iter.bi_size) ret = tree->ops->merge_bio_hook(READ, page, 0, PAGE_CACHE_SIZE, comp_bio, 0); @@ -685,8 +686,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, comp_bio, sums); BUG_ON(ret); /* -ENOMEM */ } - sums += (comp_bio->bi_size + root->sectorsize - 1) / - root->sectorsize; + sums += (comp_bio->bi_iter.bi_size + + root->sectorsize - 1) / root->sectorsize; ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8b5f9e1d1f0e..bcb6f1b780d6 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1984,7 +1984,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start, bio = btrfs_io_bio_alloc(GFP_NOFS, 1); if (!bio) return -EIO; - bio->bi_size = 0; + bio->bi_iter.bi_size = 0; map_length = length; ret = btrfs_map_block(fs_info, WRITE, logical, @@ -1995,7 +1995,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start, } BUG_ON(mirror_num != bbio->mirror_num); sector = bbio->stripes[mirror_num-1].physical >> 9; - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; dev = bbio->stripes[mirror_num-1].dev; kfree(bbio); if (!dev || !dev->bdev || !dev->writeable) { @@ -2268,9 +2268,9 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, return -EIO; } bio->bi_end_io = failed_bio->bi_end_io; - bio->bi_sector = failrec->logical >> 9; + bio->bi_iter.bi_sector = failrec->logical >> 9; bio->bi_bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; - bio->bi_size = 0; + bio->bi_iter.bi_size = 0; btrfs_failed_bio = btrfs_io_bio(failed_bio); if (btrfs_failed_bio->csum) { @@ -2412,7 +2412,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) struct inode *inode = page->mapping->host; pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, " - "mirror=%lu\n", (u64)bio->bi_sector, err, + "mirror=%lu\n", (u64)bio->bi_iter.bi_sector, err, io_bio->mirror_num); tree = &BTRFS_I(inode)->io_tree; @@ -2543,7 +2543,7 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs, if (bio) { bio->bi_bdev = bdev; - bio->bi_sector = first_sector; + bio->bi_iter.bi_sector = first_sector; btrfs_bio = btrfs_io_bio(bio); btrfs_bio->csum = NULL; btrfs_bio->csum_allocated = NULL; @@ -2637,7 +2637,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, if (bio_ret && *bio_ret) { bio = *bio_ret; if (old_compressed) - contig = bio->bi_sector == sector; + contig = bio->bi_iter.bi_sector == sector; else contig = bio_end_sector(bio) == sector; diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 6f3848860283..84a46a42d262 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -182,7 +182,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, if (!path) return -ENOMEM; - nblocks = bio->bi_size >> inode->i_sb->s_blocksize_bits; + nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits; if (!dst) { if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) { btrfs_bio->csum_allocated = kmalloc(nblocks * csum_size, @@ -201,7 +201,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, csum = (u8 *)dst; } - if (bio->bi_size > PAGE_CACHE_SIZE * 8) + if (bio->bi_iter.bi_size > PAGE_CACHE_SIZE * 8) path->reada = 2; WARN_ON(bio->bi_vcnt <= 0); @@ -217,7 +217,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, path->skip_locking = 1; } - disk_bytenr = (u64)bio->bi_sector << 9; + disk_bytenr = (u64)bio->bi_iter.bi_sector << 9; if (dio) offset = logical_offset; while (bio_index < bio->bi_vcnt) { @@ -302,7 +302,7 @@ int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, struct btrfs_dio_private *dip, struct bio *bio, u64 offset) { - int len = (bio->bi_sector << 9) - dip->disk_bytenr; + int len = (bio->bi_iter.bi_sector << 9) - dip->disk_bytenr; u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); int ret; @@ -447,11 +447,12 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, u64 offset; WARN_ON(bio->bi_vcnt <= 0); - sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); + sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_iter.bi_size), + GFP_NOFS); if (!sums) return -ENOMEM; - sums->len = bio->bi_size; + sums->len = bio->bi_iter.bi_size; INIT_LIST_HEAD(&sums->list); if (contig) @@ -461,7 +462,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, ordered = btrfs_lookup_ordered_extent(inode, offset); BUG_ON(!ordered); /* Logic error */ - sums->bytenr = (u64)bio->bi_sector << 9; + sums->bytenr = (u64)bio->bi_iter.bi_sector << 9; index = 0; while (bio_index < bio->bi_vcnt) { @@ -476,7 +477,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, btrfs_add_ordered_sum(inode, ordered, sums); btrfs_put_ordered_extent(ordered); - bytes_left = bio->bi_size - total_bytes; + bytes_left = bio->bi_iter.bi_size - total_bytes; sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), GFP_NOFS); @@ -484,7 +485,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, sums->len = bytes_left; ordered = btrfs_lookup_ordered_extent(inode, offset); BUG_ON(!ordered); /* Logic error */ - sums->bytenr = ((u64)bio->bi_sector << 9) + + sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) + total_bytes; index = 0; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d6630dc130ba..7ab0e94ad492 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1577,7 +1577,7 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, unsigned long bio_flags) { struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; - u64 logical = (u64)bio->bi_sector << 9; + u64 logical = (u64)bio->bi_iter.bi_sector << 9; u64 length = 0; u64 map_length; int ret; @@ -1585,7 +1585,7 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, if (bio_flags & EXTENT_BIO_COMPRESSED) return 0; - length = bio->bi_size; + length = bio->bi_iter.bi_size; map_length = length; ret = btrfs_map_block(root->fs_info, rw, logical, &map_length, NULL, 0); @@ -6894,7 +6894,8 @@ static void btrfs_end_dio_bio(struct bio *bio, int err) printk(KERN_ERR "btrfs direct IO failed ino %llu rw %lu " "sector %#Lx len %u err no %d\n", btrfs_ino(dip->inode), bio->bi_rw, - (unsigned long long)bio->bi_sector, bio->bi_size, err); + (unsigned long long)bio->bi_iter.bi_sector, + bio->bi_iter.bi_size, err); dip->errors = 1; /* @@ -6985,7 +6986,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, struct bio *bio; struct bio *orig_bio = dip->orig_bio; struct bio_vec *bvec = orig_bio->bi_io_vec; - u64 start_sector = orig_bio->bi_sector; + u64 start_sector = orig_bio->bi_iter.bi_sector; u64 file_offset = dip->logical_offset; u64 submit_len = 0; u64 map_length; @@ -6993,7 +6994,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, int ret = 0; int async_submit = 0; - map_length = orig_bio->bi_size; + map_length = orig_bio->bi_iter.bi_size; ret = btrfs_map_block(root->fs_info, rw, start_sector << 9, &map_length, NULL, 0); if (ret) { @@ -7001,7 +7002,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, return -EIO; } - if (map_length >= orig_bio->bi_size) { + if (map_length >= orig_bio->bi_iter.bi_size) { bio = orig_bio; goto submit; } @@ -7053,7 +7054,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, bio->bi_private = dip; bio->bi_end_io = btrfs_end_dio_bio; - map_length = orig_bio->bi_size; + map_length = orig_bio->bi_iter.bi_size; ret = btrfs_map_block(root->fs_info, rw, start_sector << 9, &map_length, NULL, 0); @@ -7111,7 +7112,8 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, if (!skip_sum && !write) { csum_size = btrfs_super_csum_size(root->fs_info->super_copy); - sum_len = dio_bio->bi_size >> inode->i_sb->s_blocksize_bits; + sum_len = dio_bio->bi_iter.bi_size >> + inode->i_sb->s_blocksize_bits; sum_len *= csum_size; } else { sum_len = 0; @@ -7126,8 +7128,8 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, dip->private = dio_bio->bi_private; dip->inode = inode; dip->logical_offset = file_offset; - dip->bytes = dio_bio->bi_size; - dip->disk_bytenr = (u64)dio_bio->bi_sector << 9; + dip->bytes = dio_bio->bi_iter.bi_size; + dip->disk_bytenr = (u64)dio_bio->bi_iter.bi_sector << 9; io_bio->bi_private = dip; dip->errors = 0; dip->orig_bio = io_bio; diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 24ac21840a9a..9af0b25d991a 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -1032,8 +1032,8 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio, /* see if we can add this page onto our existing bio */ if (last) { - last_end = (u64)last->bi_sector << 9; - last_end += last->bi_size; + last_end = (u64)last->bi_iter.bi_sector << 9; + last_end += last->bi_iter.bi_size; /* * we can't merge these if they are from different @@ -1053,9 +1053,9 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio, if (!bio) return -ENOMEM; - bio->bi_size = 0; + bio->bi_iter.bi_size = 0; bio->bi_bdev = stripe->dev->bdev; - bio->bi_sector = disk_start >> 9; + bio->bi_iter.bi_sector = disk_start >> 9; set_bit(BIO_UPTODATE, &bio->bi_flags); bio_add_page(bio, page, PAGE_CACHE_SIZE, 0); @@ -1111,7 +1111,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio) spin_lock_irq(&rbio->bio_list_lock); bio_list_for_each(bio, &rbio->bio_list) { - start = (u64)bio->bi_sector << 9; + start = (u64)bio->bi_iter.bi_sector << 9; stripe_offset = start - rbio->raid_map[0]; page_index = stripe_offset >> PAGE_CACHE_SHIFT; @@ -1272,7 +1272,7 @@ cleanup: static int find_bio_stripe(struct btrfs_raid_bio *rbio, struct bio *bio) { - u64 physical = bio->bi_sector; + u64 physical = bio->bi_iter.bi_sector; u64 stripe_start; int i; struct btrfs_bio_stripe *stripe; @@ -1298,7 +1298,7 @@ static int find_bio_stripe(struct btrfs_raid_bio *rbio, static int find_logical_bio_stripe(struct btrfs_raid_bio *rbio, struct bio *bio) { - u64 logical = bio->bi_sector; + u64 logical = bio->bi_iter.bi_sector; u64 stripe_start; int i; @@ -1602,8 +1602,8 @@ static int plug_cmp(void *priv, struct list_head *a, struct list_head *b) plug_list); struct btrfs_raid_bio *rb = container_of(b, struct btrfs_raid_bio, plug_list); - u64 a_sector = ra->bio_list.head->bi_sector; - u64 b_sector = rb->bio_list.head->bi_sector; + u64 a_sector = ra->bio_list.head->bi_iter.bi_sector; + u64 b_sector = rb->bio_list.head->bi_iter.bi_sector; if (a_sector < b_sector) return -1; @@ -1691,7 +1691,7 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio, if (IS_ERR(rbio)) return PTR_ERR(rbio); bio_list_add(&rbio->bio_list, bio); - rbio->bio_list_bytes = bio->bi_size; + rbio->bio_list_bytes = bio->bi_iter.bi_size; /* * don't plug on full rbios, just get them out the door @@ -2044,7 +2044,7 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, rbio->read_rebuild = 1; bio_list_add(&rbio->bio_list, bio); - rbio->bio_list_bytes = bio->bi_size; + rbio->bio_list_bytes = bio->bi_iter.bi_size; rbio->faila = find_logical_bio_stripe(rbio, bio); if (rbio->faila == -1) { diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 1fd3f33c330a..bb9a928fa3a8 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1308,7 +1308,7 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info, continue; } bio->bi_bdev = page->dev->bdev; - bio->bi_sector = page->physical >> 9; + bio->bi_iter.bi_sector = page->physical >> 9; bio_add_page(bio, page->page, PAGE_SIZE, 0); if (btrfsic_submit_bio_wait(READ, bio)) @@ -1427,7 +1427,7 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, if (!bio) return -EIO; bio->bi_bdev = page_bad->dev->bdev; - bio->bi_sector = page_bad->physical >> 9; + bio->bi_iter.bi_sector = page_bad->physical >> 9; ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0); if (PAGE_SIZE != ret) { @@ -1520,7 +1520,7 @@ again: bio->bi_private = sbio; bio->bi_end_io = scrub_wr_bio_end_io; bio->bi_bdev = sbio->dev->bdev; - bio->bi_sector = sbio->physical >> 9; + bio->bi_iter.bi_sector = sbio->physical >> 9; sbio->err = 0; } else if (sbio->physical + sbio->page_count * PAGE_SIZE != spage->physical_for_dev_replace || @@ -1926,7 +1926,7 @@ again: bio->bi_private = sbio; bio->bi_end_io = scrub_bio_end_io; bio->bi_bdev = sbio->dev->bdev; - bio->bi_sector = sbio->physical >> 9; + bio->bi_iter.bi_sector = sbio->physical >> 9; sbio->err = 0; } else if (sbio->physical + sbio->page_count * PAGE_SIZE != spage->physical || @@ -3371,8 +3371,8 @@ static int write_page_nocow(struct scrub_ctx *sctx, spin_unlock(&sctx->stat_lock); return -ENOMEM; } - bio->bi_size = 0; - bio->bi_sector = physical_for_dev_replace >> 9; + bio->bi_iter.bi_size = 0; + bio->bi_iter.bi_sector = physical_for_dev_replace >> 9; bio->bi_bdev = dev->bdev; ret = bio_add_page(bio, page, PAGE_CACHE_SIZE, 0); if (ret != PAGE_CACHE_SIZE) { diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 92303f42baaa..f2130de0ddc2 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -5411,7 +5411,7 @@ static int bio_size_ok(struct block_device *bdev, struct bio *bio, if (!q->merge_bvec_fn) return 1; - bvm.bi_size = bio->bi_size - prev->bv_len; + bvm.bi_size = bio->bi_iter.bi_size - prev->bv_len; if (q->merge_bvec_fn(q, &bvm, prev) < prev->bv_len) return 0; return 1; @@ -5426,7 +5426,7 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio, bio->bi_private = bbio; btrfs_io_bio(bio)->stripe_index = dev_nr; bio->bi_end_io = btrfs_end_bio; - bio->bi_sector = physical >> 9; + bio->bi_iter.bi_sector = physical >> 9; #ifdef DEBUG { struct rcu_string *name; @@ -5464,7 +5464,7 @@ again: while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) { if (bio_add_page(bio, bvec->bv_page, bvec->bv_len, bvec->bv_offset) < bvec->bv_len) { - u64 len = bio->bi_size; + u64 len = bio->bi_iter.bi_size; atomic_inc(&bbio->stripes_pending); submit_stripe_bio(root, bbio, bio, physical, dev_nr, @@ -5486,7 +5486,7 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical) bio->bi_private = bbio->private; bio->bi_end_io = bbio->end_io; btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; - bio->bi_sector = logical >> 9; + bio->bi_iter.bi_sector = logical >> 9; kfree(bbio); bio_endio(bio, -EIO); } @@ -5497,7 +5497,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, { struct btrfs_device *dev; struct bio *first_bio = bio; - u64 logical = (u64)bio->bi_sector << 9; + u64 logical = (u64)bio->bi_iter.bi_sector << 9; u64 length = 0; u64 map_length; u64 *raid_map = NULL; @@ -5506,7 +5506,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, int total_devs = 1; struct btrfs_bio *bbio = NULL; - length = bio->bi_size; + length = bio->bi_iter.bi_size; map_length = length; ret = __btrfs_map_block(root->fs_info, rw, logical, &map_length, &bbio, diff --git a/fs/buffer.c b/fs/buffer.c index 6024877335ca..1c04ec66974e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2982,11 +2982,11 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh) * let it through, and the IO layer will turn it into * an EIO. */ - if (unlikely(bio->bi_sector >= maxsector)) + if (unlikely(bio->bi_iter.bi_sector >= maxsector)) return; - maxsector -= bio->bi_sector; - bytes = bio->bi_size; + maxsector -= bio->bi_iter.bi_sector; + bytes = bio->bi_iter.bi_size; if (likely((bytes >> 9) <= maxsector)) return; @@ -2994,7 +2994,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh) bytes = maxsector << 9; /* Truncate the bio.. */ - bio->bi_size = bytes; + bio->bi_iter.bi_size = bytes; bio->bi_io_vec[0].bv_len = bytes; /* ..and clear the end of the buffer for reads */ @@ -3029,14 +3029,14 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) */ bio = bio_alloc(GFP_NOIO, 1); - bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); + bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_bdev = bh->b_bdev; bio->bi_io_vec[0].bv_page = bh->b_page; bio->bi_io_vec[0].bv_len = bh->b_size; bio->bi_io_vec[0].bv_offset = bh_offset(bh); bio->bi_vcnt = 1; - bio->bi_size = bh->b_size; + bio->bi_iter.bi_size = bh->b_size; bio->bi_end_io = end_bio_bh_io_sync; bio->bi_private = bh; diff --git a/fs/direct-io.c b/fs/direct-io.c index 0e04142d5962..160a5489a939 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -375,7 +375,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, bio = bio_alloc(GFP_KERNEL, nr_vecs); bio->bi_bdev = bdev; - bio->bi_sector = first_sector; + bio->bi_iter.bi_sector = first_sector; if (dio->is_async) bio->bi_end_io = dio_bio_end_aio; else @@ -719,7 +719,7 @@ static inline int dio_send_cur_page(struct dio *dio, struct dio_submit *sdio, if (sdio->bio) { loff_t cur_offset = sdio->cur_page_fs_offset; loff_t bio_next_offset = sdio->logical_offset_in_bio + - sdio->bio->bi_size; + sdio->bio->bi_iter.bi_size; /* * See whether this new request is contiguous with the old. diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index a31e4da14508..ab95508e3d40 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -298,7 +298,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end) static void ext4_end_bio(struct bio *bio, int error) { ext4_io_end_t *io_end = bio->bi_private; - sector_t bi_sector = bio->bi_sector; + sector_t bi_sector = bio->bi_iter.bi_sector; BUG_ON(!io_end); bio->bi_end_io = NULL; @@ -366,7 +366,7 @@ static int io_submit_init_bio(struct ext4_io_submit *io, bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES)); if (!bio) return -ENOMEM; - bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); + bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_bdev = bh->b_bdev; bio->bi_end_io = ext4_end_bio; bio->bi_private = ext4_get_io_end(io->io_end); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index a4949096cf4c..a2c8de8ba6ce 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -386,7 +386,7 @@ int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page, bio = f2fs_bio_alloc(bdev, 1); /* Initialize the bio */ - bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); + bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); bio->bi_end_io = read_end_io; if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index a90c6bc0d129..36e8afd8e1e4 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -682,7 +682,7 @@ retry: bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); sbi->bio[type] = f2fs_bio_alloc(bdev, bio_blocks); - sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); + sbi->bio[type]->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); sbi->bio[type]->bi_private = priv; /* * The end_io will be assigned at the sumbission phase. diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 010b9fb9fec6..985da945f0b5 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -272,7 +272,7 @@ static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno) nrvecs = max(nrvecs/2, 1U); } - bio->bi_sector = blkno * (sb->s_blocksize >> 9); + bio->bi_iter.bi_sector = blkno * (sb->s_blocksize >> 9); bio->bi_bdev = sb->s_bdev; bio->bi_end_io = gfs2_end_log_write; bio->bi_private = sdp; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 82303b474958..16194da91652 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -224,7 +224,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) lock_page(page); bio = bio_alloc(GFP_NOFS, 1); - bio->bi_sector = sector * (sb->s_blocksize >> 9); + bio->bi_iter.bi_sector = sector * (sb->s_blocksize >> 9); bio->bi_bdev = sb->s_bdev; bio_add_page(bio, page, PAGE_SIZE, 0); diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index e9a97a0d4314..3f999649587f 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -63,7 +63,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1); bio = bio_alloc(GFP_NOIO, 1); - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_bdev = sb->s_bdev; if (!(rw & WRITE) && data) diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 360d27c48887..8d811e02b4b9 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1998,20 +1998,20 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bio = bio_alloc(GFP_NOFS, 1); - bio->bi_sector = bp->l_blkno << (log->l2bsize - 9); + bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9); bio->bi_bdev = log->bdev; bio->bi_io_vec[0].bv_page = bp->l_page; bio->bi_io_vec[0].bv_len = LOGPSIZE; bio->bi_io_vec[0].bv_offset = bp->l_offset; bio->bi_vcnt = 1; - bio->bi_size = LOGPSIZE; + bio->bi_iter.bi_size = LOGPSIZE; bio->bi_end_io = lbmIODone; bio->bi_private = bp; /*check if journaling to disk has been disabled*/ if (log->no_integrity) { - bio->bi_size = 0; + bio->bi_iter.bi_size = 0; lbmIODone(bio, 0); } else { submit_bio(READ_SYNC, bio); @@ -2144,21 +2144,21 @@ static void lbmStartIO(struct lbuf * bp) jfs_info("lbmStartIO\n"); bio = bio_alloc(GFP_NOFS, 1); - bio->bi_sector = bp->l_blkno << (log->l2bsize - 9); + bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9); bio->bi_bdev = log->bdev; bio->bi_io_vec[0].bv_page = bp->l_page; bio->bi_io_vec[0].bv_len = LOGPSIZE; bio->bi_io_vec[0].bv_offset = bp->l_offset; bio->bi_vcnt = 1; - bio->bi_size = LOGPSIZE; + bio->bi_iter.bi_size = LOGPSIZE; bio->bi_end_io = lbmIODone; bio->bi_private = bp; /* check if journaling to disk has been disabled */ if (log->no_integrity) { - bio->bi_size = 0; + bio->bi_iter.bi_size = 0; lbmIODone(bio, 0); } else { submit_bio(WRITE_SYNC, bio); diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index d165cde0c68d..49ba7ff1bbb9 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -416,7 +416,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) * count from hitting zero before we're through */ inc_io(page); - if (!bio->bi_size) + if (!bio->bi_iter.bi_size) goto dump_bio; submit_bio(WRITE, bio); nr_underway++; @@ -438,7 +438,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) bio = bio_alloc(GFP_NOFS, 1); bio->bi_bdev = inode->i_sb->s_bdev; - bio->bi_sector = pblock << (inode->i_blkbits - 9); + bio->bi_iter.bi_sector = pblock << (inode->i_blkbits - 9); bio->bi_end_io = metapage_write_end_io; bio->bi_private = page; @@ -452,7 +452,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) if (bio) { if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes) goto add_failed; - if (!bio->bi_size) + if (!bio->bi_iter.bi_size) goto dump_bio; submit_bio(WRITE, bio); @@ -517,7 +517,8 @@ static int metapage_readpage(struct file *fp, struct page *page) bio = bio_alloc(GFP_NOFS, 1); bio->bi_bdev = inode->i_sb->s_bdev; - bio->bi_sector = pblock << (inode->i_blkbits - 9); + bio->bi_iter.bi_sector = + pblock << (inode->i_blkbits - 9); bio->bi_end_io = metapage_read_end_io; bio->bi_private = page; len = xlen << inode->i_blkbits; diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index e6df3be3b31b..76279e11982d 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -26,9 +26,9 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) bio_vec.bv_len = PAGE_SIZE; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; - bio.bi_size = PAGE_SIZE; bio.bi_bdev = bdev; - bio.bi_sector = page->index * (PAGE_SIZE >> 9); + bio.bi_iter.bi_sector = page->index * (PAGE_SIZE >> 9); + bio.bi_iter.bi_size = PAGE_SIZE; return submit_bio_wait(rw, &bio); } @@ -92,9 +92,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, if (i >= max_pages) { /* Block layer cannot split bios :( */ bio->bi_vcnt = i; - bio->bi_size = i * PAGE_SIZE; + bio->bi_iter.bi_size = i * PAGE_SIZE; bio->bi_bdev = super->s_bdev; - bio->bi_sector = ofs >> 9; + bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = writeseg_end_io; atomic_inc(&super->s_pending_writes); @@ -119,9 +119,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, unlock_page(page); } bio->bi_vcnt = nr_pages; - bio->bi_size = nr_pages * PAGE_SIZE; + bio->bi_iter.bi_size = nr_pages * PAGE_SIZE; bio->bi_bdev = super->s_bdev; - bio->bi_sector = ofs >> 9; + bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = writeseg_end_io; atomic_inc(&super->s_pending_writes); @@ -184,9 +184,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, if (i >= max_pages) { /* Block layer cannot split bios :( */ bio->bi_vcnt = i; - bio->bi_size = i * PAGE_SIZE; + bio->bi_iter.bi_size = i * PAGE_SIZE; bio->bi_bdev = super->s_bdev; - bio->bi_sector = ofs >> 9; + bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = erase_end_io; atomic_inc(&super->s_pending_writes); @@ -205,9 +205,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_io_vec[i].bv_offset = 0; } bio->bi_vcnt = nr_pages; - bio->bi_size = nr_pages * PAGE_SIZE; + bio->bi_iter.bi_size = nr_pages * PAGE_SIZE; bio->bi_bdev = super->s_bdev; - bio->bi_sector = ofs >> 9; + bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = erase_end_io; atomic_inc(&super->s_pending_writes); diff --git a/fs/mpage.c b/fs/mpage.c index dd6d5878f4d9..4979ffa60aaa 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -93,7 +93,7 @@ mpage_alloc(struct block_device *bdev, if (bio) { bio->bi_bdev = bdev; - bio->bi_sector = first_sector; + bio->bi_iter.bi_sector = first_sector; } return bio; } diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index da768923bf7c..56ff823ca82e 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -134,8 +134,8 @@ bl_submit_bio(int rw, struct bio *bio) if (bio) { get_parallel(bio->bi_private); dprintk("%s submitting %s bio %u@%llu\n", __func__, - rw == READ ? "read" : "write", - bio->bi_size, (unsigned long long)bio->bi_sector); + rw == READ ? "read" : "write", bio->bi_iter.bi_size, + (unsigned long long)bio->bi_iter.bi_sector); submit_bio(rw, bio); } return NULL; @@ -156,7 +156,8 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, } if (bio) { - bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; + bio->bi_iter.bi_sector = isect - be->be_f_offset + + be->be_v_offset; bio->bi_bdev = be->be_mdev; bio->bi_end_io = end_io; bio->bi_private = par; @@ -511,7 +512,7 @@ bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be, isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) + (offset / SECTOR_SIZE); - bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; + bio->bi_iter.bi_sector = isect - be->be_f_offset + be->be_v_offset; bio->bi_bdev = be->be_mdev; bio->bi_end_io = bl_read_single_end_io; diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 2d8be51f90dc..dc3a9efdaab8 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -416,7 +416,8 @@ static struct bio *nilfs_alloc_seg_bio(struct the_nilfs *nilfs, sector_t start, } if (likely(bio)) { bio->bi_bdev = nilfs->ns_bdev; - bio->bi_sector = start << (nilfs->ns_blocksize_bits - 9); + bio->bi_iter.bi_sector = + start << (nilfs->ns_blocksize_bits - 9); } return bio; } diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 73920ffda05b..bf482dfed14f 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -413,7 +413,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, } /* Must put everything in 512 byte sectors for the bio... */ - bio->bi_sector = (reg->hr_start_block + cs) << (bits - 9); + bio->bi_iter.bi_sector = (reg->hr_start_block + cs) << (bits - 9); bio->bi_bdev = reg->hr_bdev; bio->bi_private = wc; bio->bi_end_io = o2hb_bio_end_io; diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 71c8c9d2b882..1b19b9cd692a 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -407,7 +407,7 @@ xfs_alloc_ioend_bio( struct bio *bio = bio_alloc(GFP_NOIO, nvecs); ASSERT(bio->bi_private == NULL); - bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); + bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_bdev = bh->b_bdev; return bio; } diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index c7f0b77dcb00..5f3ea443ebbe 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1255,7 +1255,7 @@ next_chunk: bio = bio_alloc(GFP_NOIO, nr_pages); bio->bi_bdev = bp->b_target->bt_bdev; - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_end_io = xfs_buf_bio_end_io; bio->bi_private = bp; @@ -1277,7 +1277,7 @@ next_chunk: total_nr_pages--; } - if (likely(bio->bi_size)) { + if (likely(bio->bi_iter.bi_size)) { if (xfs_buf_is_vmapped(bp)) { flush_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); diff --git a/include/linux/bio.h b/include/linux/bio.h index 060ff695085c..e2e0bc642ed1 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -62,19 +62,19 @@ * on highmem page vectors */ #define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)])) -#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx) +#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) #define bio_page(bio) bio_iovec((bio))->bv_page #define bio_offset(bio) bio_iovec((bio))->bv_offset -#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx) -#define bio_sectors(bio) ((bio)->bi_size >> 9) -#define bio_end_sector(bio) ((bio)->bi_sector + bio_sectors((bio))) +#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx) +#define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9) +#define bio_end_sector(bio) ((bio)->bi_iter.bi_sector + bio_sectors((bio))) static inline unsigned int bio_cur_bytes(struct bio *bio) { if (bio->bi_vcnt) return bio_iovec(bio)->bv_len; else /* dataless requests such as discard */ - return bio->bi_size; + return bio->bi_iter.bi_size; } static inline void *bio_data(struct bio *bio) @@ -108,7 +108,7 @@ static inline void *bio_data(struct bio *bio) */ #define __BVEC_END(bio) bio_iovec_idx((bio), (bio)->bi_vcnt - 1) -#define __BVEC_START(bio) bio_iovec_idx((bio), (bio)->bi_idx) +#define __BVEC_START(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) /* Default implementation of BIOVEC_PHYS_MERGEABLE */ #define __BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ @@ -150,7 +150,7 @@ static inline void *bio_data(struct bio *bio) i++) #define bio_for_each_segment(bvl, bio, i) \ - for (i = (bio)->bi_idx; \ + for (i = (bio)->bi_iter.bi_idx; \ bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt; \ i++) @@ -365,7 +365,7 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx, #define __bio_kunmap_irq(buf, flags) bvec_kunmap_irq(buf, flags) #define bio_kmap_irq(bio, flags) \ - __bio_kmap_irq((bio), (bio)->bi_idx, (flags)) + __bio_kmap_irq((bio), (bio)->bi_iter.bi_idx, (flags)) #define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags) /* diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 238ef0ed62f8..29b5b84d8a29 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -28,13 +28,19 @@ struct bio_vec { unsigned int bv_offset; }; +struct bvec_iter { + sector_t bi_sector; /* device address in 512 byte + sectors */ + unsigned int bi_size; /* residual I/O count */ + + unsigned int bi_idx; /* current index into bvl_vec */ +}; + /* * main unit of I/O for the block layer and lower layers (ie drivers and * stacking drivers) */ struct bio { - sector_t bi_sector; /* device address in 512 byte - sectors */ struct bio *bi_next; /* request queue link */ struct block_device *bi_bdev; unsigned long bi_flags; /* status, command, etc */ @@ -42,16 +48,13 @@ struct bio { * top bits priority */ - unsigned short bi_vcnt; /* how many bio_vec's */ - unsigned short bi_idx; /* current index into bvl_vec */ + struct bvec_iter bi_iter; /* Number of segments in this BIO after * physical address coalescing is performed. */ unsigned int bi_phys_segments; - unsigned int bi_size; /* residual I/O count */ - /* * To keep track of the max segment size, we account for the * sizes of the first and last mergeable segments in this bio. @@ -74,11 +77,13 @@ struct bio { struct bio_integrity_payload *bi_integrity; /* data integrity */ #endif + unsigned short bi_vcnt; /* how many bio_vec's */ + /* * Everything starting with bi_max_vecs will be preserved by bio_reset() */ - unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ + unsigned short bi_max_vecs; /* max bvl_vecs we can hold */ atomic_t bi_cnt; /* pin count */ diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h index e2b9576d00e2..095c6e4fe1e8 100644 --- a/include/trace/events/bcache.h +++ b/include/trace/events/bcache.h @@ -24,10 +24,10 @@ DECLARE_EVENT_CLASS(bcache_request, __entry->dev = bio->bi_bdev->bd_dev; __entry->orig_major = d->disk->major; __entry->orig_minor = d->disk->first_minor; - __entry->sector = bio->bi_sector; - __entry->orig_sector = bio->bi_sector - 16; - __entry->nr_sector = bio->bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + __entry->sector = bio->bi_iter.bi_sector; + __entry->orig_sector = bio->bi_iter.bi_sector - 16; + __entry->nr_sector = bio->bi_iter.bi_size >> 9; + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u (from %d,%d @ %llu)", @@ -99,9 +99,9 @@ DECLARE_EVENT_CLASS(bcache_bio, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; - __entry->nr_sector = bio->bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + __entry->sector = bio->bi_iter.bi_sector; + __entry->nr_sector = bio->bi_iter.bi_size >> 9; + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u", @@ -134,9 +134,9 @@ TRACE_EVENT(bcache_read, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; - __entry->nr_sector = bio->bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + __entry->sector = bio->bi_iter.bi_sector; + __entry->nr_sector = bio->bi_iter.bi_size >> 9; + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); __entry->cache_hit = hit; __entry->bypass = bypass; ), @@ -162,9 +162,9 @@ TRACE_EVENT(bcache_write, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; - __entry->nr_sector = bio->bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + __entry->sector = bio->bi_iter.bi_sector; + __entry->nr_sector = bio->bi_iter.bi_size >> 9; + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); __entry->writeback = writeback; __entry->bypass = bypass; ), diff --git a/include/trace/events/block.h b/include/trace/events/block.h index 4c2301d2ef1a..e76ae19a8d6f 100644 --- a/include/trace/events/block.h +++ b/include/trace/events/block.h @@ -243,9 +243,9 @@ TRACE_EVENT(block_bio_bounce, TP_fast_assign( __entry->dev = bio->bi_bdev ? bio->bi_bdev->bd_dev : 0; - __entry->sector = bio->bi_sector; + __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -280,10 +280,10 @@ TRACE_EVENT(block_bio_complete, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; + __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); __entry->error = error; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u [%d]", @@ -308,9 +308,9 @@ DECLARE_EVENT_CLASS(block_bio_merge, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; + __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -375,9 +375,9 @@ TRACE_EVENT(block_bio_queue, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; + __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -403,7 +403,7 @@ DECLARE_EVENT_CLASS(block_get_rq, TP_fast_assign( __entry->dev = bio ? bio->bi_bdev->bd_dev : 0; - __entry->sector = bio ? bio->bi_sector : 0; + __entry->sector = bio ? bio->bi_iter.bi_sector : 0; __entry->nr_sector = bio ? bio_sectors(bio) : 0; blk_fill_rwbs(__entry->rwbs, bio ? bio->bi_rw : 0, __entry->nr_sector); @@ -538,9 +538,9 @@ TRACE_EVENT(block_split, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; + __entry->sector = bio->bi_iter.bi_sector; __entry->new_sector = new_sector; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -579,11 +579,11 @@ TRACE_EVENT(block_bio_remap, TP_fast_assign( __entry->dev = bio->bi_bdev->bd_dev; - __entry->sector = bio->bi_sector; + __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); __entry->old_dev = dev; __entry->old_sector = from; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); + blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index e0dc355fa317..bd3ee4fbe7a7 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -616,8 +616,8 @@ TRACE_EVENT(f2fs_do_submit_bio, __entry->dev = sb->s_dev; __entry->btype = btype; __entry->sync = sync; - __entry->sector = bio->bi_sector; - __entry->size = bio->bi_size; + __entry->sector = bio->bi_iter.bi_sector; + __entry->size = bio->bi_iter.bi_size; ), TP_printk("dev = (%d,%d), type = %s, io = %s, sector = %lld, size = %u", diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c index d09dd10c5a5e..9a58bc258810 100644 --- a/kernel/power/block_io.c +++ b/kernel/power/block_io.c @@ -32,7 +32,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector, struct bio *bio; bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); - bio->bi_sector = sector; + bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; bio->bi_end_io = end_swap_bio_read; diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index f785aef65799..b418cb0d7242 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -781,8 +781,8 @@ static void blk_add_trace_bio(struct request_queue *q, struct bio *bio, if (!error && !bio_flagged(bio, BIO_UPTODATE)) error = EIO; - __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, - error, 0, NULL); + __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size, + bio->bi_rw, what, error, 0, NULL); } static void blk_add_trace_bio_bounce(void *ignore, @@ -885,8 +885,9 @@ static void blk_add_trace_split(void *ignore, if (bt) { __be64 rpdu = cpu_to_be64(pdu); - __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, - BLK_TA_SPLIT, !bio_flagged(bio, BIO_UPTODATE), + __blk_add_trace(bt, bio->bi_iter.bi_sector, + bio->bi_iter.bi_size, bio->bi_rw, BLK_TA_SPLIT, + !bio_flagged(bio, BIO_UPTODATE), sizeof(rpdu), &rpdu); } } @@ -918,9 +919,9 @@ static void blk_add_trace_bio_remap(void *ignore, r.device_to = cpu_to_be32(bio->bi_bdev->bd_dev); r.sector_from = cpu_to_be64(from); - __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, - BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), - sizeof(r), &r); + __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size, + bio->bi_rw, BLK_TA_REMAP, + !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); } /** diff --git a/mm/page_io.c b/mm/page_io.c index 8c79a4764be0..f14eded987fa 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -31,13 +31,13 @@ static struct bio *get_swap_bio(gfp_t gfp_flags, bio = bio_alloc(gfp_flags, 1); if (bio) { - bio->bi_sector = map_swap_page(page, &bio->bi_bdev); - bio->bi_sector <<= PAGE_SHIFT - 9; + bio->bi_iter.bi_sector = map_swap_page(page, &bio->bi_bdev); + bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9; bio->bi_io_vec[0].bv_page = page; bio->bi_io_vec[0].bv_len = PAGE_SIZE; bio->bi_io_vec[0].bv_offset = 0; bio->bi_vcnt = 1; - bio->bi_size = PAGE_SIZE; + bio->bi_iter.bi_size = PAGE_SIZE; bio->bi_end_io = end_io; } return bio; @@ -62,7 +62,7 @@ void end_swap_bio_write(struct bio *bio, int err) printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n", imajor(bio->bi_bdev->bd_inode), iminor(bio->bi_bdev->bd_inode), - (unsigned long long)bio->bi_sector); + (unsigned long long)bio->bi_iter.bi_sector); ClearPageReclaim(page); } end_page_writeback(page); @@ -80,7 +80,7 @@ void end_swap_bio_read(struct bio *bio, int err) printk(KERN_ALERT "Read-error on swap-device (%u:%u:%Lu)\n", imajor(bio->bi_bdev->bd_inode), iminor(bio->bi_bdev->bd_inode), - (unsigned long long)bio->bi_sector); + (unsigned long long)bio->bi_iter.bi_sector); goto out; } -- cgit v1.2.3 From 75d5d8156500cd3833d66806889372e294af514d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 7 Aug 2013 14:24:19 -0700 Subject: dm: Use bvec_iter for dm_bio_record() This patch doesn't itself have any functional changes, but immutable biovecs are going to add a bi_bvec_done member to bi_iter, which will need to be saved too here. Signed-off-by: Kent Overstreet Cc: Alasdair Kergon Cc: dm-devel@redhat.com Reviewed-by: Mike Snitzer --- drivers/md/dm-bio-record.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h index 5ace48ee9f58..4f46e8e528de 100644 --- a/drivers/md/dm-bio-record.h +++ b/drivers/md/dm-bio-record.h @@ -28,11 +28,9 @@ struct dm_bio_vec_details { }; struct dm_bio_details { - sector_t bi_sector; struct block_device *bi_bdev; - unsigned int bi_size; - unsigned short bi_idx; unsigned long bi_flags; + struct bvec_iter bi_iter; struct dm_bio_vec_details bi_io_vec[BIO_MAX_PAGES]; }; @@ -40,11 +38,9 @@ static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio) { unsigned i; - bd->bi_sector = bio->bi_iter.bi_sector; bd->bi_bdev = bio->bi_bdev; - bd->bi_size = bio->bi_iter.bi_size; - bd->bi_idx = bio->bi_iter.bi_idx; bd->bi_flags = bio->bi_flags; + bd->bi_iter = bio->bi_iter; for (i = 0; i < bio->bi_vcnt; i++) { bd->bi_io_vec[i].bv_len = bio->bi_io_vec[i].bv_len; @@ -56,11 +52,9 @@ static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio) { unsigned i; - bio->bi_iter.bi_sector = bd->bi_sector; bio->bi_bdev = bd->bi_bdev; - bio->bi_iter.bi_size = bd->bi_size; - bio->bi_iter.bi_idx = bd->bi_idx; bio->bi_flags = bd->bi_flags; + bio->bi_iter = bd->bi_iter; for (i = 0; i < bio->bi_vcnt; i++) { bio->bi_io_vec[i].bv_len = bd->bi_io_vec[i].bv_len; -- cgit v1.2.3 From a4ad39b1d10584dfcfcfb0d510faab2c7f034399 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 7 Aug 2013 14:24:32 -0700 Subject: block: Convert bio_iovec() to bvec_iter For immutable biovecs, we'll be introducing a new bio_iovec() that uses our new bvec iterator to construct a biovec, taking into account bvec_iter->bi_bvec_done - this patch updates existing users for the new usage. Some of the existing users really do need a pointer into the bvec array - those uses are all going to be removed, but we'll need the functionality from immutable to remove them - so for now rename the existing bio_iovec() -> __bio_iovec(), and it'll be removed in a couple patches. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: "Ed L. Cashin" Cc: Alasdair Kergon Cc: dm-devel@redhat.com Cc: "James E.J. Bottomley" --- drivers/block/aoe/aoecmd.c | 2 +- drivers/md/bcache/io.c | 13 +++++++------ drivers/md/dm-verity.c | 2 +- drivers/scsi/sd.c | 2 +- fs/bio.c | 20 ++++++++++---------- include/linux/bio.h | 10 ++++++---- 6 files changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 877ba119b3f8..77c24ab1898a 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -932,7 +932,7 @@ bufinit(struct buf *buf, struct request *rq, struct bio *bio) buf->resid = bio->bi_iter.bi_size; buf->sector = bio->bi_iter.bi_sector; bio_pageinc(bio); - buf->bv = bio_iovec(bio); + buf->bv = __bio_iovec(bio); buf->bv_resid = buf->bv->bv_len; WARN_ON(buf->bv_resid == 0); } diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index cc4ba2da5fb6..dc44f0689eb7 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -22,11 +22,12 @@ static void bch_bi_idx_hack_endio(struct bio *bio, int error) static void bch_generic_make_request_hack(struct bio *bio) { if (bio->bi_iter.bi_idx) { + int i; + struct bio_vec *bv; struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio)); - memcpy(clone->bi_io_vec, - bio_iovec(bio), - bio_segments(bio) * sizeof(struct bio_vec)); + bio_for_each_segment(bv, bio, i) + clone->bi_io_vec[clone->bi_vcnt++] = *bv; clone->bi_iter.bi_sector = bio->bi_iter.bi_sector; clone->bi_bdev = bio->bi_bdev; @@ -97,7 +98,7 @@ struct bio *bch_bio_split(struct bio *bio, int sectors, if (!ret) return NULL; - memcpy(ret->bi_io_vec, bio_iovec(bio), + memcpy(ret->bi_io_vec, __bio_iovec(bio), sizeof(struct bio_vec) * vcnt); break; @@ -106,7 +107,7 @@ struct bio *bch_bio_split(struct bio *bio, int sectors, if (!ret) return NULL; - memcpy(ret->bi_io_vec, bio_iovec(bio), + memcpy(ret->bi_io_vec, __bio_iovec(bio), sizeof(struct bio_vec) * vcnt); ret->bi_io_vec[vcnt - 1].bv_len = nbytes; @@ -182,7 +183,7 @@ static unsigned bch_bio_max_sectors(struct bio *bio) ret = min(ret, queue_max_sectors(q)); WARN_ON(!ret); - ret = max_t(int, ret, bio_iovec(bio)->bv_len >> 9); + ret = max_t(int, ret, bio_iovec(bio).bv_len >> 9); return ret; } diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 132b3154d466..5392135924ca 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -524,7 +524,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio) io->io_vec = io->io_vec_inline; else io->io_vec = mempool_alloc(v->vec_mempool, GFP_NOIO); - memcpy(io->io_vec, bio_iovec(bio), + memcpy(io->io_vec, __bio_iovec(bio), io->io_vec_size * sizeof(struct bio_vec)); verity_submit_prefetch(v, io); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e6c4bff04339..200d6bc81240 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -801,7 +801,7 @@ static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) if (sdkp->device->no_write_same) return BLKPREP_KILL; - BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size); + BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size); sector >>= ilog2(sdp->sector_size) - 9; nr_sectors >>= ilog2(sdp->sector_size) - 9; diff --git a/fs/bio.c b/fs/bio.c index a402ad6e753f..7bb281fc3d5c 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -821,12 +821,12 @@ void bio_advance(struct bio *bio, unsigned bytes) break; } - if (bytes >= bio_iovec(bio)->bv_len) { - bytes -= bio_iovec(bio)->bv_len; + if (bytes >= bio_iovec(bio).bv_len) { + bytes -= bio_iovec(bio).bv_len; bio->bi_iter.bi_idx++; } else { - bio_iovec(bio)->bv_len -= bytes; - bio_iovec(bio)->bv_offset += bytes; + bio_iovec(bio).bv_len -= bytes; + bio_iovec(bio).bv_offset += bytes; bytes = 0; } } @@ -879,8 +879,8 @@ void bio_copy_data(struct bio *dst, struct bio *src) unsigned src_offset, dst_offset, bytes; void *src_p, *dst_p; - src_bv = bio_iovec(src); - dst_bv = bio_iovec(dst); + src_bv = __bio_iovec(src); + dst_bv = __bio_iovec(dst); src_offset = src_bv->bv_offset; dst_offset = dst_bv->bv_offset; @@ -893,7 +893,7 @@ void bio_copy_data(struct bio *dst, struct bio *src) if (!src) break; - src_bv = bio_iovec(src); + src_bv = __bio_iovec(src); } src_offset = src_bv->bv_offset; @@ -906,7 +906,7 @@ void bio_copy_data(struct bio *dst, struct bio *src) if (!dst) break; - dst_bv = bio_iovec(dst); + dst_bv = __bio_iovec(dst); } dst_offset = dst_bv->bv_offset; @@ -1776,8 +1776,8 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors) bp->bio1.bi_iter.bi_size = first_sectors << 9; if (bi->bi_vcnt != 0) { - bp->bv1 = *bio_iovec(bi); - bp->bv2 = *bio_iovec(bi); + bp->bv1 = bio_iovec(bi); + bp->bv2 = bio_iovec(bi); if (bio_is_rw(bi)) { bp->bv2.bv_offset += first_sectors << 9; diff --git a/include/linux/bio.h b/include/linux/bio.h index e2e0bc642ed1..9f182fcbe714 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -62,9 +62,11 @@ * on highmem page vectors */ #define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)])) -#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) -#define bio_page(bio) bio_iovec((bio))->bv_page -#define bio_offset(bio) bio_iovec((bio))->bv_offset +#define __bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) +#define bio_iovec(bio) (*__bio_iovec(bio)) + +#define bio_page(bio) (bio_iovec((bio)).bv_page) +#define bio_offset(bio) (bio_iovec((bio)).bv_offset) #define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx) #define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9) #define bio_end_sector(bio) ((bio)->bi_iter.bi_sector + bio_sectors((bio))) @@ -72,7 +74,7 @@ static inline unsigned int bio_cur_bytes(struct bio *bio) { if (bio->bi_vcnt) - return bio_iovec(bio)->bv_len; + return bio_iovec(bio).bv_len; else /* dataless requests such as discard */ return bio->bi_iter.bi_size; } -- cgit v1.2.3 From 7988613b0e5b2638caf6cd493cc78e9595eba19c Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 23 Nov 2013 17:19:00 -0800 Subject: block: Convert bio_for_each_segment() to bvec_iter More prep work for immutable biovecs - with immutable bvecs drivers won't be able to use the biovec directly, they'll need to use helpers that take into account bio->bi_iter.bi_bvec_done. This updates callers for the new usage without changing the implementation yet. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Geert Uytterhoeven Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: "Ed L. Cashin" Cc: Nick Piggin Cc: Lars Ellenberg Cc: Jiri Kosina Cc: Paul Clements Cc: Jim Paris Cc: Geoff Levand Cc: Yehuda Sadeh Cc: Sage Weil Cc: Alex Elder Cc: ceph-devel@vger.kernel.org Cc: Joshua Morris Cc: Philip Kelleher Cc: Konrad Rzeszutek Wilk Cc: Jeremy Fitzhardinge Cc: Neil Brown Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: Nagalakshmi Nandigama Cc: Sreekanth Reddy Cc: support@lsi.com Cc: "James E.J. Bottomley" Cc: Greg Kroah-Hartman Cc: Alexander Viro Cc: Steven Whitehouse Cc: Herton Ronaldo Krzesinski Cc: Tejun Heo Cc: Andrew Morton Cc: Guo Chao Cc: Asai Thambi S P Cc: Selvan Mani Cc: Sam Bradshaw Cc: Matthew Wilcox Cc: Keith Busch Cc: Stephen Hemminger Cc: Quoc-Son Anh Cc: Sebastian Ott Cc: Nitin Gupta Cc: Minchan Kim Cc: Jerome Marchand Cc: Seth Jennings Cc: "Martin K. Petersen" Cc: Mike Snitzer Cc: Vivek Goyal Cc: "Darrick J. Wong" Cc: Chris Metcalf Cc: Jan Kara Cc: linux-m68k@lists.linux-m68k.org Cc: linuxppc-dev@lists.ozlabs.org Cc: drbd-user@lists.linbit.com Cc: nbd-general@lists.sourceforge.net Cc: cbe-oss-dev@lists.ozlabs.org Cc: xen-devel@lists.xensource.com Cc: virtualization@lists.linux-foundation.org Cc: linux-raid@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: DL-MPTFusionLinux@lsi.com Cc: linux-scsi@vger.kernel.org Cc: devel@driverdev.osuosl.org Cc: linux-fsdevel@vger.kernel.org Cc: cluster-devel@redhat.com Cc: linux-mm@kvack.org Acked-by: Geoff Levand --- arch/m68k/emu/nfblock.c | 11 ++--- arch/powerpc/sysdev/axonram.c | 18 ++++---- block/blk-core.c | 4 +- block/blk-merge.c | 49 ++++++++++---------- drivers/block/aoe/aoecmd.c | 16 +++---- drivers/block/brd.c | 12 ++--- drivers/block/drbd/drbd_main.c | 27 ++++++----- drivers/block/drbd/drbd_receiver.c | 13 +++--- drivers/block/drbd/drbd_worker.c | 8 ++-- drivers/block/floppy.c | 12 ++--- drivers/block/loop.c | 23 +++++----- drivers/block/mtip32xx/mtip32xx.c | 13 +++--- drivers/block/nbd.c | 12 ++--- drivers/block/nvme-core.c | 33 ++++++++------ drivers/block/ps3disk.c | 10 ++--- drivers/block/ps3vram.c | 10 ++--- drivers/block/rbd.c | 38 ++++++++-------- drivers/block/rsxx/dma.c | 11 ++--- drivers/md/bcache/btree.c | 4 +- drivers/md/bcache/debug.c | 19 ++++---- drivers/md/bcache/io.c | 69 ++++++++++++----------------- drivers/md/bcache/request.c | 26 +++++------ drivers/md/raid5.c | 12 ++--- drivers/s390/block/dasd_diag.c | 10 ++--- drivers/s390/block/dasd_eckd.c | 48 ++++++++++---------- drivers/s390/block/dasd_fba.c | 26 +++++------ drivers/s390/block/dcssblk.c | 16 +++---- drivers/s390/block/scm_blk.c | 8 ++-- drivers/s390/block/scm_blk_cluster.c | 4 +- drivers/s390/block/xpram.c | 10 ++--- drivers/scsi/mpt2sas/mpt2sas_transport.c | 31 ++++++------- drivers/scsi/mpt3sas/mpt3sas_transport.c | 31 ++++++------- drivers/staging/lustre/lustre/llite/lloop.c | 14 +++--- drivers/staging/zram/zram_drv.c | 19 ++++---- fs/bio-integrity.c | 30 +++++++------ fs/bio.c | 22 ++++----- include/linux/bio.h | 28 ++++++------ include/linux/blkdev.h | 7 +-- mm/bounce.c | 44 +++++++++--------- 39 files changed, 401 insertions(+), 397 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/emu/nfblock.c b/arch/m68k/emu/nfblock.c index 0a9d0b3c794b..2d75ae246167 100644 --- a/arch/m68k/emu/nfblock.c +++ b/arch/m68k/emu/nfblock.c @@ -62,17 +62,18 @@ struct nfhd_device { static void nfhd_make_request(struct request_queue *queue, struct bio *bio) { struct nfhd_device *dev = queue->queuedata; - struct bio_vec *bvec; - int i, dir, len, shift; + struct bio_vec bvec; + struct bvec_iter iter; + int dir, len, shift; sector_t sec = bio->bi_iter.bi_sector; dir = bio_data_dir(bio); shift = dev->bshift; - bio_for_each_segment(bvec, bio, i) { - len = bvec->bv_len; + bio_for_each_segment(bvec, bio, iter) { + len = bvec.bv_len; len >>= 9; nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift, - bvec_to_phys(bvec)); + bvec_to_phys(&bvec)); sec += len; } bio_endio(bio, 0); diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index f33bcbaa6a07..47b6b9f81d43 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -109,28 +109,28 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio) struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data; unsigned long phys_mem, phys_end; void *user_mem; - struct bio_vec *vec; + struct bio_vec vec; unsigned int transfered; - unsigned short idx; + struct bvec_iter iter; phys_mem = bank->io_addr + (bio->bi_iter.bi_sector << AXON_RAM_SECTOR_SHIFT); phys_end = bank->io_addr + bank->size; transfered = 0; - bio_for_each_segment(vec, bio, idx) { - if (unlikely(phys_mem + vec->bv_len > phys_end)) { + bio_for_each_segment(vec, bio, iter) { + if (unlikely(phys_mem + vec.bv_len > phys_end)) { bio_io_error(bio); return; } - user_mem = page_address(vec->bv_page) + vec->bv_offset; + user_mem = page_address(vec.bv_page) + vec.bv_offset; if (bio_data_dir(bio) == READ) - memcpy(user_mem, (void *) phys_mem, vec->bv_len); + memcpy(user_mem, (void *) phys_mem, vec.bv_len); else - memcpy((void *) phys_mem, user_mem, vec->bv_len); + memcpy((void *) phys_mem, user_mem, vec.bv_len); - phys_mem += vec->bv_len; - transfered += vec->bv_len; + phys_mem += vec.bv_len; + transfered += vec.bv_len; } bio_endio(bio, 0); } diff --git a/block/blk-core.c b/block/blk-core.c index 5c2ab2c74066..5da8e900d3b1 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2746,10 +2746,10 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, void rq_flush_dcache_pages(struct request *rq) { struct req_iterator iter; - struct bio_vec *bvec; + struct bio_vec bvec; rq_for_each_segment(bvec, rq, iter) - flush_dcache_page(bvec->bv_page); + flush_dcache_page(bvec.bv_page); } EXPORT_SYMBOL_GPL(rq_flush_dcache_pages); #endif diff --git a/block/blk-merge.c b/block/blk-merge.c index 03bc083c28cf..a1ead9049ed6 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -12,10 +12,11 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio *bio) { - struct bio_vec *bv, *bvprv = NULL; - int cluster, i, high, highprv = 1; + struct bio_vec bv, bvprv = { NULL }; + int cluster, high, highprv = 1; unsigned int seg_size, nr_phys_segs; struct bio *fbio, *bbio; + struct bvec_iter iter; if (!bio) return 0; @@ -25,25 +26,23 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, seg_size = 0; nr_phys_segs = 0; for_each_bio(bio) { - bio_for_each_segment(bv, bio, i) { + bio_for_each_segment(bv, bio, iter) { /* * the trick here is making sure that a high page is * never considered part of another segment, since that * might change with the bounce page. */ - high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q); - if (high || highprv) - goto new_segment; - if (cluster) { - if (seg_size + bv->bv_len + high = page_to_pfn(bv.bv_page) > queue_bounce_pfn(q); + if (!high && !highprv && cluster) { + if (seg_size + bv.bv_len > queue_max_segment_size(q)) goto new_segment; - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) + if (!BIOVEC_PHYS_MERGEABLE(&bvprv, &bv)) goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) + if (!BIOVEC_SEG_BOUNDARY(q, &bvprv, &bv)) goto new_segment; - seg_size += bv->bv_len; + seg_size += bv.bv_len; bvprv = bv; continue; } @@ -54,7 +53,7 @@ new_segment: nr_phys_segs++; bvprv = bv; - seg_size = bv->bv_len; + seg_size = bv.bv_len; highprv = high; } bbio = bio; @@ -110,21 +109,21 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, return 0; } -static void +static inline void __blk_segment_map_sg(struct request_queue *q, struct bio_vec *bvec, - struct scatterlist *sglist, struct bio_vec **bvprv, + struct scatterlist *sglist, struct bio_vec *bvprv, struct scatterlist **sg, int *nsegs, int *cluster) { int nbytes = bvec->bv_len; - if (*bvprv && *cluster) { + if (*sg && *cluster) { if ((*sg)->length + nbytes > queue_max_segment_size(q)) goto new_segment; - if (!BIOVEC_PHYS_MERGEABLE(*bvprv, bvec)) + if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, *bvprv, bvec)) + if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) goto new_segment; (*sg)->length += nbytes; @@ -150,7 +149,7 @@ new_segment: sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset); (*nsegs)++; } - *bvprv = bvec; + *bvprv = *bvec; } /* @@ -160,7 +159,7 @@ new_segment: int blk_rq_map_sg(struct request_queue *q, struct request *rq, struct scatterlist *sglist) { - struct bio_vec *bvec, *bvprv; + struct bio_vec bvec, bvprv; struct req_iterator iter; struct scatterlist *sg; int nsegs, cluster; @@ -171,10 +170,9 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, /* * for each bio in rq */ - bvprv = NULL; sg = NULL; rq_for_each_segment(bvec, rq, iter) { - __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg, + __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg, &nsegs, &cluster); } /* segments in rq */ @@ -223,18 +221,17 @@ EXPORT_SYMBOL(blk_rq_map_sg); int blk_bio_map_sg(struct request_queue *q, struct bio *bio, struct scatterlist *sglist) { - struct bio_vec *bvec, *bvprv; + struct bio_vec bvec, bvprv; struct scatterlist *sg; int nsegs, cluster; - unsigned long i; + struct bvec_iter iter; nsegs = 0; cluster = blk_queue_cluster(q); - bvprv = NULL; sg = NULL; - bio_for_each_segment(bvec, bio, i) { - __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg, + bio_for_each_segment(bvec, bio, iter) { + __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg, &nsegs, &cluster); } /* segments in bio */ diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 77c24ab1898a..7a06aec1dedc 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -897,15 +897,15 @@ rqbiocnt(struct request *r) static void bio_pageinc(struct bio *bio) { - struct bio_vec *bv; + struct bio_vec bv; struct page *page; - int i; + struct bvec_iter iter; - bio_for_each_segment(bv, bio, i) { + bio_for_each_segment(bv, bio, iter) { /* Non-zero page count for non-head members of * compound pages is no longer allowed by the kernel. */ - page = compound_trans_head(bv->bv_page); + page = compound_trans_head(bv.bv_page); atomic_inc(&page->_count); } } @@ -913,12 +913,12 @@ bio_pageinc(struct bio *bio) static void bio_pagedec(struct bio *bio) { - struct bio_vec *bv; struct page *page; - int i; + struct bio_vec bv; + struct bvec_iter iter; - bio_for_each_segment(bv, bio, i) { - page = compound_trans_head(bv->bv_page); + bio_for_each_segment(bv, bio, iter) { + page = compound_trans_head(bv.bv_page); atomic_dec(&page->_count); } } diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 66f5aaae15a2..e73b85cf0756 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -328,9 +328,9 @@ static void brd_make_request(struct request_queue *q, struct bio *bio) struct block_device *bdev = bio->bi_bdev; struct brd_device *brd = bdev->bd_disk->private_data; int rw; - struct bio_vec *bvec; + struct bio_vec bvec; sector_t sector; - int i; + struct bvec_iter iter; int err = -EIO; sector = bio->bi_iter.bi_sector; @@ -347,10 +347,10 @@ static void brd_make_request(struct request_queue *q, struct bio *bio) if (rw == READA) rw = READ; - bio_for_each_segment(bvec, bio, i) { - unsigned int len = bvec->bv_len; - err = brd_do_bvec(brd, bvec->bv_page, len, - bvec->bv_offset, rw, sector); + bio_for_each_segment(bvec, bio, iter) { + unsigned int len = bvec.bv_len; + err = brd_do_bvec(brd, bvec.bv_page, len, + bvec.bv_offset, rw, sector); if (err) break; sector += len >> SECTOR_SHIFT; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9e3818b1bc83..f4e5440aba05 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1537,15 +1537,17 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page, static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio) { - struct bio_vec *bvec; - int i; + struct bio_vec bvec; + struct bvec_iter iter; + /* hint all but last page with MSG_MORE */ - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { int err; - err = _drbd_no_send_page(mdev, bvec->bv_page, - bvec->bv_offset, bvec->bv_len, - i == bio->bi_vcnt - 1 ? 0 : MSG_MORE); + err = _drbd_no_send_page(mdev, bvec.bv_page, + bvec.bv_offset, bvec.bv_len, + bio_iter_last(bio, iter) + ? 0 : MSG_MORE); if (err) return err; } @@ -1554,15 +1556,16 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio) static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio) { - struct bio_vec *bvec; - int i; + struct bio_vec bvec; + struct bvec_iter iter; + /* hint all but last page with MSG_MORE */ - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { int err; - err = _drbd_send_page(mdev, bvec->bv_page, - bvec->bv_offset, bvec->bv_len, - i == bio->bi_vcnt - 1 ? 0 : MSG_MORE); + err = _drbd_send_page(mdev, bvec.bv_page, + bvec.bv_offset, bvec.bv_len, + bio_iter_last(bio, iter) ? 0 : MSG_MORE); if (err) return err; } diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 5326c22cdb9d..d073305ffd5e 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1595,9 +1595,10 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size) static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req, sector_t sector, int data_size) { - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; struct bio *bio; - int dgs, err, i, expect; + int dgs, err, expect; void *dig_in = mdev->tconn->int_dig_in; void *dig_vv = mdev->tconn->int_dig_vv; @@ -1617,11 +1618,11 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req, bio = req->master_bio; D_ASSERT(sector == bio->bi_iter.bi_sector); - bio_for_each_segment(bvec, bio, i) { - void *mapped = kmap(bvec->bv_page) + bvec->bv_offset; - expect = min_t(int, data_size, bvec->bv_len); + bio_for_each_segment(bvec, bio, iter) { + void *mapped = kmap(bvec.bv_page) + bvec.bv_offset; + expect = min_t(int, data_size, bvec.bv_len); err = drbd_recv_all_warn(mdev->tconn, mapped, expect); - kunmap(bvec->bv_page); + kunmap(bvec.bv_page); if (err) return err; data_size -= expect; diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 891c0ecaa292..84d3175d493a 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -313,8 +313,8 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio * { struct hash_desc desc; struct scatterlist sg; - struct bio_vec *bvec; - int i; + struct bio_vec bvec; + struct bvec_iter iter; desc.tfm = tfm; desc.flags = 0; @@ -322,8 +322,8 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio * sg_init_table(&sg, 1); crypto_hash_init(&desc); - bio_for_each_segment(bvec, bio, i) { - sg_set_page(&sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); + bio_for_each_segment(bvec, bio, iter) { + sg_set_page(&sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); crypto_hash_update(&desc, &sg, sg.length); } crypto_hash_final(&desc, digest); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 6a86fe7b730f..6b29c4422828 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2351,7 +2351,7 @@ static void rw_interrupt(void) /* Compute maximal contiguous buffer size. */ static int buffer_chain_size(void) { - struct bio_vec *bv; + struct bio_vec bv; int size; struct req_iterator iter; char *base; @@ -2360,10 +2360,10 @@ static int buffer_chain_size(void) size = 0; rq_for_each_segment(bv, current_req, iter) { - if (page_address(bv->bv_page) + bv->bv_offset != base + size) + if (page_address(bv.bv_page) + bv.bv_offset != base + size) break; - size += bv->bv_len; + size += bv.bv_len; } return size >> 9; @@ -2389,7 +2389,7 @@ static int transfer_size(int ssize, int max_sector, int max_size) static void copy_buffer(int ssize, int max_sector, int max_sector_2) { int remaining; /* number of transferred 512-byte sectors */ - struct bio_vec *bv; + struct bio_vec bv; char *buffer; char *dma_buffer; int size; @@ -2427,10 +2427,10 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) if (!remaining) break; - size = bv->bv_len; + size = bv.bv_len; SUPBOUND(size, remaining); - buffer = page_address(bv->bv_page) + bv->bv_offset; + buffer = page_address(bv.bv_page) + bv.bv_offset; if (dma_buffer + size > floppy_track_buffer + (max_buffer_sectors << 10) || dma_buffer < floppy_track_buffer) { diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f5e39989adde..33fde3a39759 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -288,9 +288,10 @@ static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos) { int (*do_lo_send)(struct loop_device *, struct bio_vec *, loff_t, struct page *page); - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; struct page *page = NULL; - int i, ret = 0; + int ret = 0; if (lo->transfer != transfer_none) { page = alloc_page(GFP_NOIO | __GFP_HIGHMEM); @@ -302,11 +303,11 @@ static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos) do_lo_send = do_lo_send_direct_write; } - bio_for_each_segment(bvec, bio, i) { - ret = do_lo_send(lo, bvec, pos, page); + bio_for_each_segment(bvec, bio, iter) { + ret = do_lo_send(lo, &bvec, pos, page); if (ret < 0) break; - pos += bvec->bv_len; + pos += bvec.bv_len; } if (page) { kunmap(page); @@ -392,20 +393,20 @@ do_lo_receive(struct loop_device *lo, static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) { - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; ssize_t s; - int i; - bio_for_each_segment(bvec, bio, i) { - s = do_lo_receive(lo, bvec, bsize, pos); + bio_for_each_segment(bvec, bio, iter) { + s = do_lo_receive(lo, &bvec, bsize, pos); if (s < 0) return s; - if (s != bvec->bv_len) { + if (s != bvec.bv_len) { zero_fill_bio(bio); break; } - pos += bvec->bv_len; + pos += bvec.bv_len; } return 0; } diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 69e9eb5a6b34..52b2f2a71470 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -3962,8 +3962,9 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) { struct driver_data *dd = queue->queuedata; struct scatterlist *sg; - struct bio_vec *bvec; - int i, nents = 0; + struct bio_vec bvec; + struct bvec_iter iter; + int nents = 0; int tag = 0, unaligned = 0; if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) { @@ -4026,11 +4027,11 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) } /* Create the scatter list for this bio. */ - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { sg_set_page(&sg[nents], - bvec->bv_page, - bvec->bv_len, - bvec->bv_offset); + bvec.bv_page, + bvec.bv_len, + bvec.bv_offset); nents++; } diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 2dc3b5153f0d..aa362f493216 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -271,7 +271,7 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) if (nbd_cmd(req) == NBD_CMD_WRITE) { struct req_iterator iter; - struct bio_vec *bvec; + struct bio_vec bvec; /* * we are really probing at internals to determine * whether to set MSG_MORE or not... @@ -281,8 +281,8 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) if (!rq_iter_last(req, iter)) flags = MSG_MORE; dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", - nbd->disk->disk_name, req, bvec->bv_len); - result = sock_send_bvec(nbd, bvec, flags); + nbd->disk->disk_name, req, bvec.bv_len); + result = sock_send_bvec(nbd, &bvec, flags); if (result <= 0) { dev_err(disk_to_dev(nbd->disk), "Send data failed (result %d)\n", @@ -378,10 +378,10 @@ static struct request *nbd_read_stat(struct nbd_device *nbd) nbd->disk->disk_name, req); if (nbd_cmd(req) == NBD_CMD_READ) { struct req_iterator iter; - struct bio_vec *bvec; + struct bio_vec bvec; rq_for_each_segment(bvec, req, iter) { - result = sock_recv_bvec(nbd, bvec); + result = sock_recv_bvec(nbd, &bvec); if (result <= 0) { dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n", result); @@ -389,7 +389,7 @@ static struct request *nbd_read_stat(struct nbd_device *nbd) return req; } dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", - nbd->disk->disk_name, req, bvec->bv_len); + nbd->disk->disk_name, req, bvec.bv_len); } } return req; diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 53d217381873..5539d2920872 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -550,9 +550,11 @@ static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq, static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, struct bio *bio, enum dma_data_direction dma_dir, int psegs) { - struct bio_vec *bvec, *bvprv = NULL; + struct bio_vec bvec, bvprv; + struct bvec_iter iter; struct scatterlist *sg = NULL; - int i, length = 0, nsegs = 0, split_len = bio->bi_iter.bi_size; + int length = 0, nsegs = 0, split_len = bio->bi_iter.bi_size; + int first = 1; if (nvmeq->dev->stripe_size) split_len = nvmeq->dev->stripe_size - @@ -560,25 +562,28 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, (nvmeq->dev->stripe_size - 1)); sg_init_table(iod->sg, psegs); - bio_for_each_segment(bvec, bio, i) { - if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) { - sg->length += bvec->bv_len; + bio_for_each_segment(bvec, bio, iter) { + if (!first && BIOVEC_PHYS_MERGEABLE(&bvprv, &bvec)) { + sg->length += bvec.bv_len; } else { - if (bvprv && BIOVEC_NOT_VIRT_MERGEABLE(bvprv, bvec)) - return nvme_split_and_submit(bio, nvmeq, i, - length, 0); + if (!first && BIOVEC_NOT_VIRT_MERGEABLE(&bvprv, &bvec)) + return nvme_split_and_submit(bio, nvmeq, + iter.bi_idx, + length, 0); sg = sg ? sg + 1 : iod->sg; - sg_set_page(sg, bvec->bv_page, bvec->bv_len, - bvec->bv_offset); + sg_set_page(sg, bvec.bv_page, + bvec.bv_len, bvec.bv_offset); nsegs++; } - if (split_len - length < bvec->bv_len) - return nvme_split_and_submit(bio, nvmeq, i, split_len, - split_len - length); - length += bvec->bv_len; + if (split_len - length < bvec.bv_len) + return nvme_split_and_submit(bio, nvmeq, iter.bi_idx, + split_len, + split_len - length); + length += bvec.bv_len; bvprv = bvec; + first = 0; } iod->nents = nsegs; sg_mark_end(sg); diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 464be78a0836..1c6edb9a9960 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -94,7 +94,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, { unsigned int offset = 0; struct req_iterator iter; - struct bio_vec *bvec; + struct bio_vec bvec; unsigned int i = 0; size_t size; void *buf; @@ -106,14 +106,14 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, __func__, __LINE__, i, bio_segments(iter.bio), bio_sectors(iter.bio), iter.bio->bi_iter.bi_sector); - size = bvec->bv_len; - buf = bvec_kmap_irq(bvec, &flags); + size = bvec.bv_len; + buf = bvec_kmap_irq(&bvec, &flags); if (gather) memcpy(dev->bounce_buf+offset, buf, size); else memcpy(buf, dev->bounce_buf+offset, size); offset += size; - flush_kernel_dcache_page(bvec->bv_page); + flush_kernel_dcache_page(bvec.bv_page); bvec_kunmap_irq(buf, &flags); i++; } @@ -130,7 +130,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, #ifdef DEBUG unsigned int n = 0; - struct bio_vec *bv; + struct bio_vec bv; struct req_iterator iter; rq_for_each_segment(bv, req, iter) diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index 320bbfc9b902..ef45cfb98fd2 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c @@ -555,14 +555,14 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev, const char *op = write ? "write" : "read"; loff_t offset = bio->bi_iter.bi_sector << 9; int error = 0; - struct bio_vec *bvec; - unsigned int i; + struct bio_vec bvec; + struct bvec_iter iter; struct bio *next; - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { /* PS3 is ppc64, so we don't handle highmem */ - char *ptr = page_address(bvec->bv_page) + bvec->bv_offset; - size_t len = bvec->bv_len, retlen; + char *ptr = page_address(bvec.bv_page) + bvec.bv_offset; + size_t len = bvec.bv_len, retlen; dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, len, offset); diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index a8f4fe2d4d1b..20e8ab35736b 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1109,23 +1109,23 @@ static void bio_chain_put(struct bio *chain) */ static void zero_bio_chain(struct bio *chain, int start_ofs) { - struct bio_vec *bv; + struct bio_vec bv; + struct bvec_iter iter; unsigned long flags; void *buf; - int i; int pos = 0; while (chain) { - bio_for_each_segment(bv, chain, i) { - if (pos + bv->bv_len > start_ofs) { + bio_for_each_segment(bv, chain, iter) { + if (pos + bv.bv_len > start_ofs) { int remainder = max(start_ofs - pos, 0); - buf = bvec_kmap_irq(bv, &flags); + buf = bvec_kmap_irq(&bv, &flags); memset(buf + remainder, 0, - bv->bv_len - remainder); - flush_dcache_page(bv->bv_page); + bv.bv_len - remainder); + flush_dcache_page(bv.bv_page); bvec_kunmap_irq(buf, &flags); } - pos += bv->bv_len; + pos += bv.bv_len; } chain = chain->bi_next; @@ -1173,11 +1173,11 @@ static struct bio *bio_clone_range(struct bio *bio_src, unsigned int len, gfp_t gfpmask) { - struct bio_vec *bv; + struct bio_vec bv; + struct bvec_iter iter; + struct bvec_iter end_iter; unsigned int resid; - unsigned short idx; unsigned int voff; - unsigned short end_idx; unsigned short vcnt; struct bio *bio; @@ -1196,22 +1196,22 @@ static struct bio *bio_clone_range(struct bio *bio_src, /* Find first affected segment... */ resid = offset; - bio_for_each_segment(bv, bio_src, idx) { - if (resid < bv->bv_len) + bio_for_each_segment(bv, bio_src, iter) { + if (resid < bv.bv_len) break; - resid -= bv->bv_len; + resid -= bv.bv_len; } voff = resid; /* ...and the last affected segment */ resid += len; - __bio_for_each_segment(bv, bio_src, end_idx, idx) { - if (resid <= bv->bv_len) + __bio_for_each_segment(bv, bio_src, end_iter, iter) { + if (resid <= bv.bv_len) break; - resid -= bv->bv_len; + resid -= bv.bv_len; } - vcnt = end_idx - idx + 1; + vcnt = end_iter.bi_idx = iter.bi_idx + 1; /* Build the clone */ @@ -1229,7 +1229,7 @@ static struct bio *bio_clone_range(struct bio *bio_src, * Copy over our part of the bio_vec, then update the first * and last (or only) entries. */ - memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[idx], + memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[iter.bi_idx], vcnt * sizeof (struct bio_vec)); bio->bi_io_vec[0].bv_offset += voff; if (vcnt > 1) { diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c index 3716633be3c2..cf8cd293abb5 100644 --- a/drivers/block/rsxx/dma.c +++ b/drivers/block/rsxx/dma.c @@ -684,7 +684,8 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, void *cb_data) { struct list_head dma_list[RSXX_MAX_TARGETS]; - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; unsigned long long addr8; unsigned int laddr; unsigned int bv_len; @@ -722,9 +723,9 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, bv_len -= RSXX_HW_BLK_SIZE; } } else { - bio_for_each_segment(bvec, bio, i) { - bv_len = bvec->bv_len; - bv_off = bvec->bv_offset; + bio_for_each_segment(bvec, bio, iter) { + bv_len = bvec.bv_len; + bv_off = bvec.bv_offset; while (bv_len > 0) { tgt = rsxx_get_dma_tgt(card, addr8); @@ -736,7 +737,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, st = rsxx_queue_dma(card, &dma_list[tgt], bio_data_dir(bio), dma_off, dma_len, - laddr, bvec->bv_page, + laddr, bvec.bv_page, bv_off, cb, cb_data); if (st) goto bvec_err; diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 038a6d2aced3..b62f37925374 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -362,7 +362,7 @@ static void btree_node_write_done(struct closure *cl) struct bio_vec *bv; int n; - __bio_for_each_segment(bv, b->bio, n, 0) + bio_for_each_segment_all(bv, b->bio, n) __free_page(bv->bv_page); __btree_node_write_done(cl); @@ -421,7 +421,7 @@ static void do_btree_node_write(struct btree *b) struct bio_vec *bv; void *base = (void *) ((unsigned long) i & ~(PAGE_SIZE - 1)); - bio_for_each_segment(bv, b->bio, j) + bio_for_each_segment_all(bv, b->bio, j) memcpy(page_address(bv->bv_page), base + j * PAGE_SIZE, PAGE_SIZE); diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c index 92b3fd468a03..03cb4d114e16 100644 --- a/drivers/md/bcache/debug.c +++ b/drivers/md/bcache/debug.c @@ -173,7 +173,8 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) { char name[BDEVNAME_SIZE]; struct bio *check; - struct bio_vec *bv; + struct bio_vec bv, *bv2; + struct bvec_iter iter; int i; check = bio_clone(bio, GFP_NOIO); @@ -185,13 +186,13 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) submit_bio_wait(READ_SYNC, check); - bio_for_each_segment(bv, bio, i) { - void *p1 = kmap_atomic(bv->bv_page); - void *p2 = page_address(check->bi_io_vec[i].bv_page); + bio_for_each_segment(bv, bio, iter) { + void *p1 = kmap_atomic(bv.bv_page); + void *p2 = page_address(check->bi_io_vec[iter.bi_idx].bv_page); - cache_set_err_on(memcmp(p1 + bv->bv_offset, - p2 + bv->bv_offset, - bv->bv_len), + cache_set_err_on(memcmp(p1 + bv.bv_offset, + p2 + bv.bv_offset, + bv.bv_len), dc->disk.c, "verify failed at dev %s sector %llu", bdevname(dc->bdev, name), @@ -200,8 +201,8 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) kunmap_atomic(p1); } - bio_for_each_segment_all(bv, check, i) - __free_page(bv->bv_page); + bio_for_each_segment_all(bv2, check, i) + __free_page(bv2->bv_page); out_put: bio_put(check); } diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index dc44f0689eb7..9b5b6a41a9b6 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -22,12 +22,12 @@ static void bch_bi_idx_hack_endio(struct bio *bio, int error) static void bch_generic_make_request_hack(struct bio *bio) { if (bio->bi_iter.bi_idx) { - int i; - struct bio_vec *bv; + struct bio_vec bv; + struct bvec_iter iter; struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio)); - bio_for_each_segment(bv, bio, i) - clone->bi_io_vec[clone->bi_vcnt++] = *bv; + bio_for_each_segment(bv, bio, iter) + clone->bi_io_vec[clone->bi_vcnt++] = bv; clone->bi_iter.bi_sector = bio->bi_iter.bi_sector; clone->bi_bdev = bio->bi_bdev; @@ -73,8 +73,9 @@ static void bch_generic_make_request_hack(struct bio *bio) struct bio *bch_bio_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs) { - unsigned idx = bio->bi_iter.bi_idx, vcnt = 0, nbytes = sectors << 9; - struct bio_vec *bv; + unsigned vcnt = 0, nbytes = sectors << 9; + struct bio_vec bv; + struct bvec_iter iter; struct bio *ret = NULL; BUG_ON(sectors <= 0); @@ -86,49 +87,35 @@ struct bio *bch_bio_split(struct bio *bio, int sectors, ret = bio_alloc_bioset(gfp, 1, bs); if (!ret) return NULL; - idx = 0; goto out; } - bio_for_each_segment(bv, bio, idx) { - vcnt = idx - bio->bi_iter.bi_idx; + bio_for_each_segment(bv, bio, iter) { + vcnt++; - if (!nbytes) { - ret = bio_alloc_bioset(gfp, vcnt, bs); - if (!ret) - return NULL; + if (nbytes <= bv.bv_len) + break; - memcpy(ret->bi_io_vec, __bio_iovec(bio), - sizeof(struct bio_vec) * vcnt); + nbytes -= bv.bv_len; + } - break; - } else if (nbytes < bv->bv_len) { - ret = bio_alloc_bioset(gfp, ++vcnt, bs); - if (!ret) - return NULL; + ret = bio_alloc_bioset(gfp, vcnt, bs); + if (!ret) + return NULL; - memcpy(ret->bi_io_vec, __bio_iovec(bio), - sizeof(struct bio_vec) * vcnt); + bio_for_each_segment(bv, bio, iter) { + ret->bi_io_vec[ret->bi_vcnt++] = bv; - ret->bi_io_vec[vcnt - 1].bv_len = nbytes; - bv->bv_offset += nbytes; - bv->bv_len -= nbytes; + if (ret->bi_vcnt == vcnt) break; - } - - nbytes -= bv->bv_len; } + + ret->bi_io_vec[ret->bi_vcnt - 1].bv_len = nbytes; out: ret->bi_bdev = bio->bi_bdev; ret->bi_iter.bi_sector = bio->bi_iter.bi_sector; ret->bi_iter.bi_size = sectors << 9; ret->bi_rw = bio->bi_rw; - ret->bi_vcnt = vcnt; - ret->bi_max_vecs = vcnt; - - bio->bi_iter.bi_sector += sectors; - bio->bi_iter.bi_size -= sectors << 9; - bio->bi_iter.bi_idx = idx; if (bio_integrity(bio)) { if (bio_integrity_clone(ret, bio, gfp)) { @@ -137,9 +124,10 @@ out: } bio_integrity_trim(ret, 0, bio_sectors(ret)); - bio_integrity_trim(bio, bio_sectors(ret), bio_sectors(bio)); } + bio_advance(bio, ret->bi_iter.bi_size); + return ret; } @@ -155,12 +143,13 @@ static unsigned bch_bio_max_sectors(struct bio *bio) if (bio_segments(bio) > max_segments || q->merge_bvec_fn) { - struct bio_vec *bv; - int i, seg = 0; + struct bio_vec bv; + struct bvec_iter iter; + unsigned seg = 0; ret = 0; - bio_for_each_segment(bv, bio, i) { + bio_for_each_segment(bv, bio, iter) { struct bvec_merge_data bvm = { .bi_bdev = bio->bi_bdev, .bi_sector = bio->bi_iter.bi_sector, @@ -172,11 +161,11 @@ static unsigned bch_bio_max_sectors(struct bio *bio) break; if (q->merge_bvec_fn && - q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len) + q->merge_bvec_fn(q, &bvm, &bv) < (int) bv.bv_len) break; seg++; - ret += bv->bv_len >> 9; + ret += bv.bv_len >> 9; } } diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 47a9bbc75124..4c0a422fd49f 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -198,14 +198,14 @@ static bool verify(struct cached_dev *dc, struct bio *bio) static void bio_csum(struct bio *bio, struct bkey *k) { - struct bio_vec *bv; + struct bio_vec bv; + struct bvec_iter iter; uint64_t csum = 0; - int i; - bio_for_each_segment(bv, bio, i) { - void *d = kmap(bv->bv_page) + bv->bv_offset; - csum = bch_crc64_update(csum, d, bv->bv_len); - kunmap(bv->bv_page); + bio_for_each_segment(bv, bio, iter) { + void *d = kmap(bv.bv_page) + bv.bv_offset; + csum = bch_crc64_update(csum, d, bv.bv_len); + kunmap(bv.bv_page); } k->ptr[KEY_PTRS(k)] = csum & (~0ULL >> 1); @@ -1182,17 +1182,17 @@ void bch_cached_dev_request_init(struct cached_dev *dc) static int flash_dev_cache_miss(struct btree *b, struct search *s, struct bio *bio, unsigned sectors) { - struct bio_vec *bv; - int i; + struct bio_vec bv; + struct bvec_iter iter; /* Zero fill bio */ - bio_for_each_segment(bv, bio, i) { - unsigned j = min(bv->bv_len >> 9, sectors); + bio_for_each_segment(bv, bio, iter) { + unsigned j = min(bv.bv_len >> 9, sectors); - void *p = kmap(bv->bv_page); - memset(p + bv->bv_offset, 0, j << 9); - kunmap(bv->bv_page); + void *p = kmap(bv.bv_page); + memset(p + bv.bv_offset, 0, j << 9); + kunmap(bv.bv_page); sectors -= j; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a5d9c0ee4d60..bef353c51c04 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -937,9 +937,9 @@ static struct dma_async_tx_descriptor * async_copy_data(int frombio, struct bio *bio, struct page *page, sector_t sector, struct dma_async_tx_descriptor *tx) { - struct bio_vec *bvl; + struct bio_vec bvl; + struct bvec_iter iter; struct page *bio_page; - int i; int page_offset; struct async_submit_ctl submit; enum async_tx_flags flags = 0; @@ -953,8 +953,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, flags |= ASYNC_TX_FENCE; init_async_submit(&submit, flags, tx, NULL, NULL, NULL); - bio_for_each_segment(bvl, bio, i) { - int len = bvl->bv_len; + bio_for_each_segment(bvl, bio, iter) { + int len = bvl.bv_len; int clen; int b_offset = 0; @@ -970,8 +970,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, clen = len; if (clen > 0) { - b_offset += bvl->bv_offset; - bio_page = bvl->bv_page; + b_offset += bvl.bv_offset; + bio_page = bvl.bv_page; if (frombio) tx = async_memcpy(page, bio_page, page_offset, b_offset, clen, &submit); diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 92bd22ce6760..9cbc567698ce 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -504,7 +504,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, struct dasd_diag_req *dreq; struct dasd_diag_bio *dbio; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst; unsigned int count, datasize; sector_t recid, first_rec, last_rec; @@ -525,10 +525,10 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, /* Check struct bio and count the number of blocks for the request. */ count = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) + if (bv.bv_len & (blksize - 1)) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); - count += bv->bv_len >> (block->s2b_shift + 9); + count += bv.bv_len >> (block->s2b_shift + 9); } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -545,8 +545,8 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, dbio = dreq->bio; recid = first_rec; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; off += blksize) { + dst = page_address(bv.bv_page) + bv.bv_offset; + for (off = 0; off < bv.bv_len; off += blksize) { memset(dbio, 0, sizeof (struct dasd_diag_bio)); dbio->type = rw_cmd; dbio->block_number = recid + 1; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index cee7e2708a1f..70d177017329 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2551,7 +2551,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( struct dasd_ccw_req *cqr; struct ccw1 *ccw; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst; unsigned int off; int count, cidaw, cplength, datasize; @@ -2573,13 +2573,13 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( count = 0; cidaw = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) + if (bv.bv_len & (blksize - 1)) /* Eckd can only do full blocks. */ return ERR_PTR(-EINVAL); - count += bv->bv_len >> (block->s2b_shift + 9); + count += bv.bv_len >> (block->s2b_shift + 9); #if defined(CONFIG_64BIT) - if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) - cidaw += bv->bv_len >> (block->s2b_shift + 9); + if (idal_is_needed (page_address(bv.bv_page), bv.bv_len)) + cidaw += bv.bv_len >> (block->s2b_shift + 9); #endif } /* Paranoia. */ @@ -2650,16 +2650,16 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( last_rec - recid + 1, cmd, basedev, blksize); } rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; + dst = page_address(bv.bv_page) + bv.bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, GFP_DMA | __GFP_NOWARN); if (copy && rq_data_dir(req) == WRITE) - memcpy(copy + bv->bv_offset, dst, bv->bv_len); + memcpy(copy + bv.bv_offset, dst, bv.bv_len); if (copy) - dst = copy + bv->bv_offset; + dst = copy + bv.bv_offset; } - for (off = 0; off < bv->bv_len; off += blksize) { + for (off = 0; off < bv.bv_len; off += blksize) { sector_t trkid = recid; unsigned int recoffs = sector_div(trkid, blk_per_trk); rcmd = cmd; @@ -2735,7 +2735,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( struct dasd_ccw_req *cqr; struct ccw1 *ccw; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst, *idaw_dst; unsigned int cidaw, cplength, datasize; unsigned int tlf; @@ -2813,8 +2813,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( idaw_dst = NULL; idaw_len = 0; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - seg_len = bv->bv_len; + dst = page_address(bv.bv_page) + bv.bv_offset; + seg_len = bv.bv_len; while (seg_len) { if (new_track) { trkid = recid; @@ -3039,7 +3039,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( { struct dasd_ccw_req *cqr; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst; unsigned int trkcount, ctidaw; unsigned char cmd; @@ -3125,8 +3125,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( new_track = 1; recid = first_rec; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - seg_len = bv->bv_len; + dst = page_address(bv.bv_page) + bv.bv_offset; + seg_len = bv.bv_len; while (seg_len) { if (new_track) { trkid = recid; @@ -3158,9 +3158,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( } } else { rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; + dst = page_address(bv.bv_page) + bv.bv_offset; last_tidaw = itcw_add_tidaw(itcw, 0x00, - dst, bv->bv_len); + dst, bv.bv_len); if (IS_ERR(last_tidaw)) { ret = -EINVAL; goto out_error; @@ -3276,7 +3276,7 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, struct dasd_ccw_req *cqr; struct ccw1 *ccw; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst; unsigned char cmd; unsigned int trkcount; @@ -3376,8 +3376,8 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, idaws = idal_create_words(idaws, rawpadpage, PAGE_SIZE); } rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - seg_len = bv->bv_len; + dst = page_address(bv.bv_page) + bv.bv_offset; + seg_len = bv.bv_len; if (cmd == DASD_ECKD_CCW_READ_TRACK) memset(dst, 0, seg_len); if (!len_to_track_end) { @@ -3422,7 +3422,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) struct dasd_eckd_private *private; struct ccw1 *ccw; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst, *cda; unsigned int blksize, blk_per_trk, off; sector_t recid; @@ -3440,8 +3440,8 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) if (private->uses_cdl == 0 || recid > 2*blk_per_trk) ccw++; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; off += blksize) { + dst = page_address(bv.bv_page) + bv.bv_offset; + for (off = 0; off < bv.bv_len; off += blksize) { /* Skip locate record. */ if (private->uses_cdl && recid <= 2*blk_per_trk) ccw++; @@ -3452,7 +3452,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) cda = (char *)((addr_t) ccw->cda); if (dst != cda) { if (rq_data_dir(req) == READ) - memcpy(dst, cda, bv->bv_len); + memcpy(dst, cda, bv.bv_len); kmem_cache_free(dasd_page_cache, (void *)((addr_t)cda & PAGE_MASK)); } diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 9cbc8c32ba59..2c8e68bf9a1c 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -260,7 +260,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, struct dasd_ccw_req *cqr; struct ccw1 *ccw; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst; int count, cidaw, cplength, datasize; sector_t recid, first_rec, last_rec; @@ -283,13 +283,13 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, count = 0; cidaw = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) + if (bv.bv_len & (blksize - 1)) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); - count += bv->bv_len >> (block->s2b_shift + 9); + count += bv.bv_len >> (block->s2b_shift + 9); #if defined(CONFIG_64BIT) - if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) - cidaw += bv->bv_len / blksize; + if (idal_is_needed (page_address(bv.bv_page), bv.bv_len)) + cidaw += bv.bv_len / blksize; #endif } /* Paranoia. */ @@ -326,16 +326,16 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, } recid = first_rec; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; + dst = page_address(bv.bv_page) + bv.bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, GFP_DMA | __GFP_NOWARN); if (copy && rq_data_dir(req) == WRITE) - memcpy(copy + bv->bv_offset, dst, bv->bv_len); + memcpy(copy + bv.bv_offset, dst, bv.bv_len); if (copy) - dst = copy + bv->bv_offset; + dst = copy + bv.bv_offset; } - for (off = 0; off < bv->bv_len; off += blksize) { + for (off = 0; off < bv.bv_len; off += blksize) { /* Locate record for stupid devices. */ if (private->rdc_data.mode.bits.data_chain == 0) { ccw[-1].flags |= CCW_FLAG_CC; @@ -384,7 +384,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) struct dasd_fba_private *private; struct ccw1 *ccw; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; char *dst, *cda; unsigned int blksize, off; int status; @@ -399,8 +399,8 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) if (private->rdc_data.mode.bits.data_chain != 0) ccw++; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; off += blksize) { + dst = page_address(bv.bv_page) + bv.bv_offset; + for (off = 0; off < bv.bv_len; off += blksize) { /* Skip locate record. */ if (private->rdc_data.mode.bits.data_chain == 0) ccw++; @@ -411,7 +411,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) cda = (char *)((addr_t) ccw->cda); if (dst != cda) { if (rq_data_dir(req) == READ) - memcpy(dst, cda, bv->bv_len); + memcpy(dst, cda, bv.bv_len); kmem_cache_free(dasd_page_cache, (void *)((addr_t)cda & PAGE_MASK)); } diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 16814a8457f8..ebf41e228e55 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -808,12 +808,12 @@ static void dcssblk_make_request(struct request_queue *q, struct bio *bio) { struct dcssblk_dev_info *dev_info; - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; unsigned long index; unsigned long page_addr; unsigned long source_addr; unsigned long bytes_done; - int i; bytes_done = 0; dev_info = bio->bi_bdev->bd_disk->private_data; @@ -844,21 +844,21 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) } index = (bio->bi_iter.bi_sector >> 3); - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { page_addr = (unsigned long) - page_address(bvec->bv_page) + bvec->bv_offset; + page_address(bvec.bv_page) + bvec.bv_offset; source_addr = dev_info->start + (index<<12) + bytes_done; - if (unlikely((page_addr & 4095) != 0) || (bvec->bv_len & 4095) != 0) + if (unlikely((page_addr & 4095) != 0) || (bvec.bv_len & 4095) != 0) // More paranoia. goto fail; if (bio_data_dir(bio) == READ) { memcpy((void*)page_addr, (void*)source_addr, - bvec->bv_len); + bvec.bv_len); } else { memcpy((void*)source_addr, (void*)page_addr, - bvec->bv_len); + bvec.bv_len); } - bytes_done += bvec->bv_len; + bytes_done += bvec.bv_len; } bio_endio(bio, 0); return; diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c index d0ab5019d885..76bed1743db1 100644 --- a/drivers/s390/block/scm_blk.c +++ b/drivers/s390/block/scm_blk.c @@ -130,7 +130,7 @@ static void scm_request_prepare(struct scm_request *scmrq) struct aidaw *aidaw = scmrq->aidaw; struct msb *msb = &scmrq->aob->msb[0]; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; msb->bs = MSB_BS_4K; scmrq->aob->request.msb_count = 1; @@ -142,9 +142,9 @@ static void scm_request_prepare(struct scm_request *scmrq) msb->data_addr = (u64) aidaw; rq_for_each_segment(bv, scmrq->request, iter) { - WARN_ON(bv->bv_offset); - msb->blk_count += bv->bv_len >> 12; - aidaw->data_addr = (u64) page_address(bv->bv_page); + WARN_ON(bv.bv_offset); + msb->blk_count += bv.bv_len >> 12; + aidaw->data_addr = (u64) page_address(bv.bv_page); aidaw++; } } diff --git a/drivers/s390/block/scm_blk_cluster.c b/drivers/s390/block/scm_blk_cluster.c index 27f930cd657f..9aae909d47a5 100644 --- a/drivers/s390/block/scm_blk_cluster.c +++ b/drivers/s390/block/scm_blk_cluster.c @@ -122,7 +122,7 @@ static void scm_prepare_cluster_request(struct scm_request *scmrq) struct aidaw *aidaw = scmrq->aidaw; struct msb *msb = &scmrq->aob->msb[0]; struct req_iterator iter; - struct bio_vec *bv; + struct bio_vec bv; int i = 0; u64 addr; @@ -163,7 +163,7 @@ static void scm_prepare_cluster_request(struct scm_request *scmrq) i++; } rq_for_each_segment(bv, req, iter) { - aidaw->data_addr = (u64) page_address(bv->bv_page); + aidaw->data_addr = (u64) page_address(bv.bv_page); aidaw++; i++; } diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index dd4e73fdb323..3e530f9da8c4 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -184,11 +184,11 @@ static unsigned long xpram_highest_page_index(void) static void xpram_make_request(struct request_queue *q, struct bio *bio) { xpram_device_t *xdev = bio->bi_bdev->bd_disk->private_data; - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; unsigned int index; unsigned long page_addr; unsigned long bytes; - int i; if ((bio->bi_iter.bi_sector & 7) != 0 || (bio->bi_iter.bi_size & 4095) != 0) @@ -200,10 +200,10 @@ static void xpram_make_request(struct request_queue *q, struct bio *bio) if ((bio->bi_iter.bi_sector >> 3) > 0xffffffffU - xdev->offset) goto fail; index = (bio->bi_iter.bi_sector >> 3) + xdev->offset; - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { page_addr = (unsigned long) - kmap(bvec->bv_page) + bvec->bv_offset; - bytes = bvec->bv_len; + kmap(bvec.bv_page) + bvec.bv_offset; + bytes = bvec.bv_len; if ((page_addr & 4095) != 0 || (bytes & 4095) != 0) /* More paranoia. */ goto fail; diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 9d26637308be..7143e86af326 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -1901,7 +1901,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); Mpi2SmpPassthroughRequest_t *mpi_request; Mpi2SmpPassthroughReply_t *mpi_reply; - int rc, i; + int rc; u16 smid; u32 ioc_state; unsigned long timeleft; @@ -1916,7 +1916,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, void *pci_addr_out = NULL; u16 wait_state_count; struct request *rsp = req->next_rq; - struct bio_vec *bvec = NULL; + struct bio_vec bvec; + struct bvec_iter iter; if (!rsp) { printk(MPT2SAS_ERR_FMT "%s: the smp response space is " @@ -1955,11 +1956,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, goto out; } - bio_for_each_segment(bvec, req->bio, i) { + bio_for_each_segment(bvec, req->bio, iter) { memcpy(pci_addr_out + offset, - page_address(bvec->bv_page) + bvec->bv_offset, - bvec->bv_len); - offset += bvec->bv_len; + page_address(bvec.bv_page) + bvec.bv_offset, + bvec.bv_len); + offset += bvec.bv_len; } } else { dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), @@ -2106,19 +2107,19 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, u32 offset = 0; u32 bytes_to_copy = le16_to_cpu(mpi_reply->ResponseDataLength); - bio_for_each_segment(bvec, rsp->bio, i) { - if (bytes_to_copy <= bvec->bv_len) { - memcpy(page_address(bvec->bv_page) + - bvec->bv_offset, pci_addr_in + + bio_for_each_segment(bvec, rsp->bio, iter) { + if (bytes_to_copy <= bvec.bv_len) { + memcpy(page_address(bvec.bv_page) + + bvec.bv_offset, pci_addr_in + offset, bytes_to_copy); break; } else { - memcpy(page_address(bvec->bv_page) + - bvec->bv_offset, pci_addr_in + - offset, bvec->bv_len); - bytes_to_copy -= bvec->bv_len; + memcpy(page_address(bvec.bv_page) + + bvec.bv_offset, pci_addr_in + + offset, bvec.bv_len); + bytes_to_copy -= bvec.bv_len; } - offset += bvec->bv_len; + offset += bvec.bv_len; } } } else { diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index e771a88c6a74..196a67f2e95f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -1884,7 +1884,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); Mpi2SmpPassthroughRequest_t *mpi_request; Mpi2SmpPassthroughReply_t *mpi_reply; - int rc, i; + int rc; u16 smid; u32 ioc_state; unsigned long timeleft; @@ -1898,7 +1898,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, void *pci_addr_out = NULL; u16 wait_state_count; struct request *rsp = req->next_rq; - struct bio_vec *bvec = NULL; + struct bio_vec bvec; + struct bvec_iter iter; if (!rsp) { pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n", @@ -1938,11 +1939,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, goto out; } - bio_for_each_segment(bvec, req->bio, i) { + bio_for_each_segment(bvec, req->bio, iter) { memcpy(pci_addr_out + offset, - page_address(bvec->bv_page) + bvec->bv_offset, - bvec->bv_len); - offset += bvec->bv_len; + page_address(bvec.bv_page) + bvec.bv_offset, + bvec.bv_len); + offset += bvec.bv_len; } } else { dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), @@ -2067,19 +2068,19 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, u32 offset = 0; u32 bytes_to_copy = le16_to_cpu(mpi_reply->ResponseDataLength); - bio_for_each_segment(bvec, rsp->bio, i) { - if (bytes_to_copy <= bvec->bv_len) { - memcpy(page_address(bvec->bv_page) + - bvec->bv_offset, pci_addr_in + + bio_for_each_segment(bvec, rsp->bio, iter) { + if (bytes_to_copy <= bvec.bv_len) { + memcpy(page_address(bvec.bv_page) + + bvec.bv_offset, pci_addr_in + offset, bytes_to_copy); break; } else { - memcpy(page_address(bvec->bv_page) + - bvec->bv_offset, pci_addr_in + - offset, bvec->bv_len); - bytes_to_copy -= bvec->bv_len; + memcpy(page_address(bvec.bv_page) + + bvec.bv_offset, pci_addr_in + + offset, bvec.bv_len); + bytes_to_copy -= bvec.bv_len; } - offset += bvec->bv_len; + offset += bvec.bv_len; } } } else { diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 53741be754b4..581ff78be1a2 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -194,10 +194,10 @@ static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head) struct cl_object *obj = ll_i2info(inode)->lli_clob; pgoff_t offset; int ret; - int i; int rw; obd_count page_count = 0; - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; struct bio *bio; ssize_t bytes; @@ -221,14 +221,14 @@ static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head) LASSERT(rw == bio->bi_rw); offset = (pgoff_t)(bio->bi_iter.bi_sector << 9) + lo->lo_offset; - bio_for_each_segment(bvec, bio, i) { - BUG_ON(bvec->bv_offset != 0); - BUG_ON(bvec->bv_len != PAGE_CACHE_SIZE); + bio_for_each_segment(bvec, bio, iter) { + BUG_ON(bvec.bv_offset != 0); + BUG_ON(bvec.bv_len != PAGE_CACHE_SIZE); - pages[page_count] = bvec->bv_page; + pages[page_count] = bvec.bv_page; offsets[page_count] = offset; page_count++; - offset += bvec->bv_len; + offset += bvec.bv_len; } LASSERT(page_count <= LLOOP_MAX_SEGMENTS); } diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index e9e6f984092b..6f988382b174 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -672,9 +672,10 @@ static ssize_t reset_store(struct device *dev, static void __zram_make_request(struct zram *zram, struct bio *bio, int rw) { - int i, offset; + int offset; u32 index; - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; switch (rw) { case READ: @@ -689,33 +690,33 @@ static void __zram_make_request(struct zram *zram, struct bio *bio, int rw) offset = (bio->bi_iter.bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment(bvec, bio, iter) { int max_transfer_size = PAGE_SIZE - offset; - if (bvec->bv_len > max_transfer_size) { + if (bvec.bv_len > max_transfer_size) { /* * zram_bvec_rw() can only make operation on a single * zram page. Split the bio vector. */ struct bio_vec bv; - bv.bv_page = bvec->bv_page; + bv.bv_page = bvec.bv_page; bv.bv_len = max_transfer_size; - bv.bv_offset = bvec->bv_offset; + bv.bv_offset = bvec.bv_offset; if (zram_bvec_rw(zram, &bv, index, offset, bio, rw) < 0) goto out; - bv.bv_len = bvec->bv_len - max_transfer_size; + bv.bv_len = bvec.bv_len - max_transfer_size; bv.bv_offset += max_transfer_size; if (zram_bvec_rw(zram, &bv, index+1, 0, bio, rw) < 0) goto out; } else - if (zram_bvec_rw(zram, bvec, index, offset, bio, rw) + if (zram_bvec_rw(zram, &bvec, index, offset, bio, rw) < 0) goto out; - update_position(&index, &offset, bvec); + update_position(&index, &offset, &bvec); } set_bit(BIO_UPTODATE, &bio->bi_flags); diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 08e3d1388c65..9127db86f315 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -299,25 +299,26 @@ static void bio_integrity_generate(struct bio *bio) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); struct blk_integrity_exchg bix; - struct bio_vec *bv; + struct bio_vec bv; + struct bvec_iter iter; sector_t sector = bio->bi_iter.bi_sector; - unsigned int i, sectors, total; + unsigned int sectors, total; void *prot_buf = bio->bi_integrity->bip_buf; total = 0; bix.disk_name = bio->bi_bdev->bd_disk->disk_name; bix.sector_size = bi->sector_size; - bio_for_each_segment(bv, bio, i) { - void *kaddr = kmap_atomic(bv->bv_page); - bix.data_buf = kaddr + bv->bv_offset; - bix.data_size = bv->bv_len; + bio_for_each_segment(bv, bio, iter) { + void *kaddr = kmap_atomic(bv.bv_page); + bix.data_buf = kaddr + bv.bv_offset; + bix.data_size = bv.bv_len; bix.prot_buf = prot_buf; bix.sector = sector; bi->generate_fn(&bix); - sectors = bv->bv_len / bi->sector_size; + sectors = bv.bv_len / bi->sector_size; sector += sectors; prot_buf += sectors * bi->tuple_size; total += sectors * bi->tuple_size; @@ -441,19 +442,20 @@ static int bio_integrity_verify(struct bio *bio) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); struct blk_integrity_exchg bix; - struct bio_vec *bv; + struct bio_vec bv; + struct bvec_iter iter; sector_t sector = bio->bi_integrity->bip_sector; - unsigned int i, sectors, total, ret; + unsigned int sectors, total, ret; void *prot_buf = bio->bi_integrity->bip_buf; ret = total = 0; bix.disk_name = bio->bi_bdev->bd_disk->disk_name; bix.sector_size = bi->sector_size; - bio_for_each_segment(bv, bio, i) { - void *kaddr = kmap_atomic(bv->bv_page); - bix.data_buf = kaddr + bv->bv_offset; - bix.data_size = bv->bv_len; + bio_for_each_segment(bv, bio, iter) { + void *kaddr = kmap_atomic(bv.bv_page); + bix.data_buf = kaddr + bv.bv_offset; + bix.data_size = bv.bv_len; bix.prot_buf = prot_buf; bix.sector = sector; @@ -464,7 +466,7 @@ static int bio_integrity_verify(struct bio *bio) return ret; } - sectors = bv->bv_len / bi->sector_size; + sectors = bv.bv_len / bi->sector_size; sector += sectors; prot_buf += sectors * bi->tuple_size; total += sectors * bi->tuple_size; diff --git a/fs/bio.c b/fs/bio.c index 7bb281fc3d5c..8b7f14a95503 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -473,13 +473,13 @@ EXPORT_SYMBOL(bio_alloc_bioset); void zero_fill_bio(struct bio *bio) { unsigned long flags; - struct bio_vec *bv; - int i; + struct bio_vec bv; + struct bvec_iter iter; - bio_for_each_segment(bv, bio, i) { - char *data = bvec_kmap_irq(bv, &flags); - memset(data, 0, bv->bv_len); - flush_dcache_page(bv->bv_page); + bio_for_each_segment(bv, bio, iter) { + char *data = bvec_kmap_irq(&bv, &flags); + memset(data, 0, bv.bv_len); + flush_dcache_page(bv.bv_page); bvec_kunmap_irq(data, &flags); } } @@ -1687,11 +1687,11 @@ void bio_check_pages_dirty(struct bio *bio) #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE void bio_flush_dcache_pages(struct bio *bi) { - int i; - struct bio_vec *bvec; + struct bio_vec bvec; + struct bvec_iter iter; - bio_for_each_segment(bvec, bi, i) - flush_dcache_page(bvec->bv_page); + bio_for_each_segment(bvec, bi, iter) + flush_dcache_page(bvec.bv_page); } EXPORT_SYMBOL(bio_flush_dcache_pages); #endif @@ -1840,7 +1840,7 @@ void bio_trim(struct bio *bio, int offset, int size) bio->bi_iter.bi_idx = 0; } /* Make sure vcnt and last bv are not too big */ - bio_for_each_segment(bvec, bio, i) { + bio_for_each_segment_all(bvec, bio, i) { if (sofar + bvec->bv_len > size) bvec->bv_len = size - sofar; if (bvec->bv_len == 0) { diff --git a/include/linux/bio.h b/include/linux/bio.h index 9f182fcbe714..c16adb5f69f8 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -63,10 +63,13 @@ */ #define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)])) #define __bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) -#define bio_iovec(bio) (*__bio_iovec(bio)) + +#define bio_iter_iovec(bio, iter) ((bio)->bi_io_vec[(iter).bi_idx]) #define bio_page(bio) (bio_iovec((bio)).bv_page) #define bio_offset(bio) (bio_iovec((bio)).bv_offset) +#define bio_iovec(bio) (*__bio_iovec(bio)) + #define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx) #define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9) #define bio_end_sector(bio) ((bio)->bi_iter.bi_sector + bio_sectors((bio))) @@ -133,15 +136,6 @@ static inline void *bio_data(struct bio *bio) #define bio_io_error(bio) bio_endio((bio), -EIO) -/* - * drivers should not use the __ version unless they _really_ know what - * they're doing - */ -#define __bio_for_each_segment(bvl, bio, i, start_idx) \ - for (bvl = bio_iovec_idx((bio), (start_idx)), i = (start_idx); \ - i < (bio)->bi_vcnt; \ - bvl++, i++) - /* * drivers should _never_ use the all version - the bio may have been split * before it got to the driver and the driver won't own all of it @@ -151,10 +145,16 @@ static inline void *bio_data(struct bio *bio) bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt; \ i++) -#define bio_for_each_segment(bvl, bio, i) \ - for (i = (bio)->bi_iter.bi_idx; \ - bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt; \ - i++) +#define __bio_for_each_segment(bvl, bio, iter, start) \ + for (iter = (start); \ + bvl = bio_iter_iovec((bio), (iter)), \ + (iter).bi_idx < (bio)->bi_vcnt; \ + (iter).bi_idx++) + +#define bio_for_each_segment(bvl, bio, iter) \ + __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter) + +#define bio_iter_last(bio, iter) ((iter).bi_idx == (bio)->bi_vcnt - 1) /* * get a reference to a bio, so it won't disappear. the intended use is diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1b135d49b279..337b92a54658 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -735,7 +735,7 @@ struct rq_map_data { }; struct req_iterator { - int i; + struct bvec_iter iter; struct bio *bio; }; @@ -748,10 +748,11 @@ struct req_iterator { #define rq_for_each_segment(bvl, _rq, _iter) \ __rq_for_each_bio(_iter.bio, _rq) \ - bio_for_each_segment(bvl, _iter.bio, _iter.i) + bio_for_each_segment(bvl, _iter.bio, _iter.iter) #define rq_iter_last(rq, _iter) \ - (_iter.bio->bi_next == NULL && _iter.i == _iter.bio->bi_vcnt-1) + (_iter.bio->bi_next == NULL && \ + bio_iter_last(_iter.bio, _iter.iter)) #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE # error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform" diff --git a/mm/bounce.c b/mm/bounce.c index 5a7d58fb883b..523918b8c6dc 100644 --- a/mm/bounce.c +++ b/mm/bounce.c @@ -98,27 +98,24 @@ int init_emergency_isa_pool(void) static void copy_to_high_bio_irq(struct bio *to, struct bio *from) { unsigned char *vfrom; - struct bio_vec *tovec, *fromvec; - int i; - - bio_for_each_segment(tovec, to, i) { - fromvec = from->bi_io_vec + i; - - /* - * not bounced - */ - if (tovec->bv_page == fromvec->bv_page) - continue; - - /* - * fromvec->bv_offset and fromvec->bv_len might have been - * modified by the block layer, so use the original copy, - * bounce_copy_vec already uses tovec->bv_len - */ - vfrom = page_address(fromvec->bv_page) + tovec->bv_offset; + struct bio_vec tovec, *fromvec = from->bi_io_vec; + struct bvec_iter iter; + + bio_for_each_segment(tovec, to, iter) { + if (tovec.bv_page != fromvec->bv_page) { + /* + * fromvec->bv_offset and fromvec->bv_len might have + * been modified by the block layer, so use the original + * copy, bounce_copy_vec already uses tovec->bv_len + */ + vfrom = page_address(fromvec->bv_page) + + tovec.bv_offset; + + bounce_copy_vec(&tovec, vfrom); + flush_dcache_page(tovec.bv_page); + } - bounce_copy_vec(tovec, vfrom); - flush_dcache_page(tovec->bv_page); + fromvec++; } } @@ -201,13 +198,14 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig, { struct bio *bio; int rw = bio_data_dir(*bio_orig); - struct bio_vec *to, *from; + struct bio_vec *to, from; + struct bvec_iter iter; unsigned i; if (force) goto bounce; - bio_for_each_segment(from, *bio_orig, i) - if (page_to_pfn(from->bv_page) > queue_bounce_pfn(q)) + bio_for_each_segment(from, *bio_orig, iter) + if (page_to_pfn(from.bv_page) > queue_bounce_pfn(q)) goto bounce; return; -- cgit v1.2.3 From 4550dd6c6b062fc5e5b647296d55da22616123c3 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 7 Aug 2013 14:26:21 -0700 Subject: block: Immutable bio vecs This adds a mechanism by which we can advance a bio by an arbitrary number of bytes without modifying the biovec: bio->bi_iter.bi_bvec_done indicates the number of bytes completed in the current bvec. Various driver code still needs to be updated to not refer to the bvec directly before we can use this for interesting things, like efficient bio splitting. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Lars Ellenberg Cc: Paul Clements Cc: drbd-user@lists.linbit.com Cc: nbd-general@lists.sourceforge.net --- Documentation/block/biovecs.txt | 111 ++++++++++++++++++++++++++++++++++++++++ drivers/block/drbd/drbd_main.c | 4 +- drivers/block/nbd.c | 2 +- fs/bio.c | 27 +--------- include/linux/bio.h | 81 ++++++++++++++++++++++++++--- include/linux/blk_types.h | 3 ++ include/linux/blkdev.h | 4 +- 7 files changed, 194 insertions(+), 38 deletions(-) create mode 100644 Documentation/block/biovecs.txt (limited to 'drivers') diff --git a/Documentation/block/biovecs.txt b/Documentation/block/biovecs.txt new file mode 100644 index 000000000000..74a32ad52f53 --- /dev/null +++ b/Documentation/block/biovecs.txt @@ -0,0 +1,111 @@ + +Immutable biovecs and biovec iterators: +======================================= + +Kent Overstreet + +As of 3.13, biovecs should never be modified after a bio has been submitted. +Instead, we have a new struct bvec_iter which represents a range of a biovec - +the iterator will be modified as the bio is completed, not the biovec. + +More specifically, old code that needed to partially complete a bio would +update bi_sector and bi_size, and advance bi_idx to the next biovec. If it +ended up partway through a biovec, it would increment bv_offset and decrement +bv_len by the number of bytes completed in that biovec. + +In the new scheme of things, everything that must be mutated in order to +partially complete a bio is segregated into struct bvec_iter: bi_sector, +bi_size and bi_idx have been moved there; and instead of modifying bv_offset +and bv_len, struct bvec_iter has bi_bvec_done, which represents the number of +bytes completed in the current bvec. + +There are a bunch of new helper macros for hiding the gory details - in +particular, presenting the illusion of partially completed biovecs so that +normal code doesn't have to deal with bi_bvec_done. + + * Driver code should no longer refer to biovecs directly; we now have + bio_iovec() and bio_iovec_iter() macros that return literal struct biovecs, + constructed from the raw biovecs but taking into account bi_bvec_done and + bi_size. + + bio_for_each_segment() has been updated to take a bvec_iter argument + instead of an integer (that corresponded to bi_idx); for a lot of code the + conversion just required changing the types of the arguments to + bio_for_each_segment(). + + * Advancing a bvec_iter is done with bio_advance_iter(); bio_advance() is a + wrapper around bio_advance_iter() that operates on bio->bi_iter, and also + advances the bio integrity's iter if present. + + There is a lower level advance function - bvec_iter_advance() - which takes + a pointer to a biovec, not a bio; this is used by the bio integrity code. + +What's all this get us? +======================= + +Having a real iterator, and making biovecs immutable, has a number of +advantages: + + * Before, iterating over bios was very awkward when you weren't processing + exactly one bvec at a time - for example, bio_copy_data() in fs/bio.c, + which copies the contents of one bio into another. Because the biovecs + wouldn't necessarily be the same size, the old code was tricky convoluted - + it had to walk two different bios at the same time, keeping both bi_idx and + and offset into the current biovec for each. + + The new code is much more straightforward - have a look. This sort of + pattern comes up in a lot of places; a lot of drivers were essentially open + coding bvec iterators before, and having common implementation considerably + simplifies a lot of code. + + * Before, any code that might need to use the biovec after the bio had been + completed (perhaps to copy the data somewhere else, or perhaps to resubmit + it somewhere else if there was an error) had to save the entire bvec array + - again, this was being done in a fair number of places. + + * Biovecs can be shared between multiple bios - a bvec iter can represent an + arbitrary range of an existing biovec, both starting and ending midway + through biovecs. This is what enables efficient splitting of arbitrary + bios. Note that this means we _only_ use bi_size to determine when we've + reached the end of a bio, not bi_vcnt - and the bio_iovec() macro takes + bi_size into account when constructing biovecs. + + * Splitting bios is now much simpler. The old bio_split() didn't even work on + bios with more than a single bvec! Now, we can efficiently split arbitrary + size bios - because the new bio can share the old bio's biovec. + + Care must be taken to ensure the biovec isn't freed while the split bio is + still using it, in case the original bio completes first, though. Using + bio_chain() when splitting bios helps with this. + + * Submitting partially completed bios is now perfectly fine - this comes up + occasionally in stacking block drivers and various code (e.g. md and + bcache) had some ugly workarounds for this. + + It used to be the case that submitting a partially completed bio would work + fine to _most_ devices, but since accessing the raw bvec array was the + norm, not all drivers would respect bi_idx and those would break. Now, + since all drivers _must_ go through the bvec iterator - and have been + audited to make sure they are - submitting partially completed bios is + perfectly fine. + +Other implications: +=================== + + * Almost all usage of bi_idx is now incorrect and has been removed; instead, + where previously you would have used bi_idx you'd now use a bvec_iter, + probably passing it to one of the helper macros. + + I.e. instead of using bio_iovec_idx() (or bio->bi_iovec[bio->bi_idx]), you + now use bio_iter_iovec(), which takes a bvec_iter and returns a + literal struct bio_vec - constructed on the fly from the raw biovec but + taking into account bi_bvec_done (and bi_size). + + * bi_vcnt can't be trusted or relied upon by driver code - i.e. anything that + doesn't actually own the bio. The reason is twofold: firstly, it's not + actually needed for iterating over the bio anymore - we only use bi_size. + Secondly, when cloning a bio and reusing (a portion of) the original bio's + biovec, in order to calculate bi_vcnt for the new bio we'd have to iterate + over all the biovecs in the new bio - which is silly as it's not needed. + + So, don't use bi_vcnt anymore. diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index f4e5440aba05..929468e1512a 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1546,7 +1546,7 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio) err = _drbd_no_send_page(mdev, bvec.bv_page, bvec.bv_offset, bvec.bv_len, - bio_iter_last(bio, iter) + bio_iter_last(bvec, iter) ? 0 : MSG_MORE); if (err) return err; @@ -1565,7 +1565,7 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio) err = _drbd_send_page(mdev, bvec.bv_page, bvec.bv_offset, bvec.bv_len, - bio_iter_last(bio, iter) ? 0 : MSG_MORE); + bio_iter_last(bvec, iter) ? 0 : MSG_MORE); if (err) return err; } diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index aa362f493216..55298db36b2d 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -278,7 +278,7 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) */ rq_for_each_segment(bvec, req, iter) { flags = 0; - if (!rq_iter_last(req, iter)) + if (!rq_iter_last(bvec, iter)) flags = MSG_MORE; dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", nbd->disk->disk_name, req, bvec.bv_len); diff --git a/fs/bio.c b/fs/bio.c index 8b7f14a95503..07b4b7afa695 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -532,13 +532,11 @@ void __bio_clone(struct bio *bio, struct bio *bio_src) * most users will be overriding ->bi_bdev with a new target, * so we don't set nor calculate new physical/hw segment counts here */ - bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_bdev = bio_src->bi_bdev; bio->bi_flags |= 1 << BIO_CLONED; bio->bi_rw = bio_src->bi_rw; bio->bi_vcnt = bio_src->bi_vcnt; - bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; - bio->bi_iter.bi_idx = bio_src->bi_iter.bi_idx; + bio->bi_iter = bio_src->bi_iter; } EXPORT_SYMBOL(__bio_clone); @@ -808,28 +806,7 @@ void bio_advance(struct bio *bio, unsigned bytes) if (bio_integrity(bio)) bio_integrity_advance(bio, bytes); - bio->bi_iter.bi_sector += bytes >> 9; - bio->bi_iter.bi_size -= bytes; - - if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) - return; - - while (bytes) { - if (unlikely(bio->bi_iter.bi_idx >= bio->bi_vcnt)) { - WARN_ONCE(1, "bio idx %d >= vcnt %d\n", - bio->bi_iter.bi_idx, bio->bi_vcnt); - break; - } - - if (bytes >= bio_iovec(bio).bv_len) { - bytes -= bio_iovec(bio).bv_len; - bio->bi_iter.bi_idx++; - } else { - bio_iovec(bio).bv_len -= bytes; - bio_iovec(bio).bv_offset += bytes; - bytes = 0; - } - } + bio_advance_iter(bio, &bio->bi_iter, bytes); } EXPORT_SYMBOL(bio_advance); diff --git a/include/linux/bio.h b/include/linux/bio.h index c16adb5f69f8..04e592e74c92 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -64,11 +64,38 @@ #define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)])) #define __bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) -#define bio_iter_iovec(bio, iter) ((bio)->bi_io_vec[(iter).bi_idx]) +#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx]) -#define bio_page(bio) (bio_iovec((bio)).bv_page) -#define bio_offset(bio) (bio_iovec((bio)).bv_offset) -#define bio_iovec(bio) (*__bio_iovec(bio)) +#define bvec_iter_page(bvec, iter) \ + (__bvec_iter_bvec((bvec), (iter))->bv_page) + +#define bvec_iter_len(bvec, iter) \ + min((iter).bi_size, \ + __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done) + +#define bvec_iter_offset(bvec, iter) \ + (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done) + +#define bvec_iter_bvec(bvec, iter) \ +((struct bio_vec) { \ + .bv_page = bvec_iter_page((bvec), (iter)), \ + .bv_len = bvec_iter_len((bvec), (iter)), \ + .bv_offset = bvec_iter_offset((bvec), (iter)), \ +}) + +#define bio_iter_iovec(bio, iter) \ + bvec_iter_bvec((bio)->bi_io_vec, (iter)) + +#define bio_iter_page(bio, iter) \ + bvec_iter_page((bio)->bi_io_vec, (iter)) +#define bio_iter_len(bio, iter) \ + bvec_iter_len((bio)->bi_io_vec, (iter)) +#define bio_iter_offset(bio, iter) \ + bvec_iter_offset((bio)->bi_io_vec, (iter)) + +#define bio_page(bio) bio_iter_page((bio), (bio)->bi_iter) +#define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter) +#define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter) #define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx) #define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9) @@ -145,16 +172,54 @@ static inline void *bio_data(struct bio *bio) bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt; \ i++) +static inline void bvec_iter_advance(struct bio_vec *bv, struct bvec_iter *iter, + unsigned bytes) +{ + WARN_ONCE(bytes > iter->bi_size, + "Attempted to advance past end of bvec iter\n"); + + while (bytes) { + unsigned len = min(bytes, bvec_iter_len(bv, *iter)); + + bytes -= len; + iter->bi_size -= len; + iter->bi_bvec_done += len; + + if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) { + iter->bi_bvec_done = 0; + iter->bi_idx++; + } + } +} + +#define for_each_bvec(bvl, bio_vec, iter, start) \ + for ((iter) = start; \ + (bvl) = bvec_iter_bvec((bio_vec), (iter)), \ + (iter).bi_size; \ + bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len)) + + +static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, + unsigned bytes) +{ + iter->bi_sector += bytes >> 9; + + if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) + iter->bi_size -= bytes; + else + bvec_iter_advance(bio->bi_io_vec, iter, bytes); +} + #define __bio_for_each_segment(bvl, bio, iter, start) \ for (iter = (start); \ - bvl = bio_iter_iovec((bio), (iter)), \ - (iter).bi_idx < (bio)->bi_vcnt; \ - (iter).bi_idx++) + (iter).bi_size && \ + ((bvl = bio_iter_iovec((bio), (iter))), 1); \ + bio_advance_iter((bio), &(iter), (bvl).bv_len)) #define bio_for_each_segment(bvl, bio, iter) \ __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter) -#define bio_iter_last(bio, iter) ((iter).bi_idx == (bio)->bi_vcnt - 1) +#define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len) /* * get a reference to a bio, so it won't disappear. the intended use is diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 29b5b84d8a29..d369f8f6af79 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -34,6 +34,9 @@ struct bvec_iter { unsigned int bi_size; /* residual I/O count */ unsigned int bi_idx; /* current index into bvl_vec */ + + unsigned int bi_bvec_done; /* number of bytes completed in + current bvec */ }; /* diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 337b92a54658..02cb6f0ea71d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -750,9 +750,9 @@ struct req_iterator { __rq_for_each_bio(_iter.bio, _rq) \ bio_for_each_segment(bvl, _iter.bio, _iter.iter) -#define rq_iter_last(rq, _iter) \ +#define rq_iter_last(bvec, _iter) \ (_iter.bio->bi_next == NULL && \ - bio_iter_last(_iter.bio, _iter.iter)) + bio_iter_last(bvec, _iter.iter)) #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE # error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform" -- cgit v1.2.3 From d57a5f7c6605f15f3b5134837e68b448a7cea88e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 23 Nov 2013 17:20:16 -0800 Subject: bio-integrity: Convert to bvec_iter The bio integrity is also stored in a bvec array, so if we use the bvec iter code we just added, the integrity code won't need to implement its own iteration stuff (bio_integrity_mark_head(), bio_integrity_mark_tail()) Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: "Martin K. Petersen" Cc: "James E.J. Bottomley" --- block/blk-integrity.c | 40 ++++++++++--------- drivers/scsi/sd_dif.c | 30 +++++++------- fs/bio-integrity.c | 108 ++++++++++++-------------------------------------- include/linux/bio.h | 19 ++++----- 4 files changed, 71 insertions(+), 126 deletions(-) (limited to 'drivers') diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 03cf7179e8ef..7fbab84399e6 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -43,30 +43,32 @@ static const char *bi_unsupported_name = "unsupported"; */ int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio) { - struct bio_vec *iv, *ivprv = NULL; + struct bio_vec iv, ivprv = { NULL }; unsigned int segments = 0; unsigned int seg_size = 0; - unsigned int i = 0; + struct bvec_iter iter; + int prev = 0; - bio_for_each_integrity_vec(iv, bio, i) { + bio_for_each_integrity_vec(iv, bio, iter) { - if (ivprv) { - if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv)) + if (prev) { + if (!BIOVEC_PHYS_MERGEABLE(&ivprv, &iv)) goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv)) + if (!BIOVEC_SEG_BOUNDARY(q, &ivprv, &iv)) goto new_segment; - if (seg_size + iv->bv_len > queue_max_segment_size(q)) + if (seg_size + iv.bv_len > queue_max_segment_size(q)) goto new_segment; - seg_size += iv->bv_len; + seg_size += iv.bv_len; } else { new_segment: segments++; - seg_size = iv->bv_len; + seg_size = iv.bv_len; } + prev = 1; ivprv = iv; } @@ -87,24 +89,25 @@ EXPORT_SYMBOL(blk_rq_count_integrity_sg); int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio, struct scatterlist *sglist) { - struct bio_vec *iv, *ivprv = NULL; + struct bio_vec iv, ivprv = { NULL }; struct scatterlist *sg = NULL; unsigned int segments = 0; - unsigned int i = 0; + struct bvec_iter iter; + int prev = 0; - bio_for_each_integrity_vec(iv, bio, i) { + bio_for_each_integrity_vec(iv, bio, iter) { - if (ivprv) { - if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv)) + if (prev) { + if (!BIOVEC_PHYS_MERGEABLE(&ivprv, &iv)) goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv)) + if (!BIOVEC_SEG_BOUNDARY(q, &ivprv, &iv)) goto new_segment; - if (sg->length + iv->bv_len > queue_max_segment_size(q)) + if (sg->length + iv.bv_len > queue_max_segment_size(q)) goto new_segment; - sg->length += iv->bv_len; + sg->length += iv.bv_len; } else { new_segment: if (!sg) @@ -114,10 +117,11 @@ new_segment: sg = sg_next(sg); } - sg_set_page(sg, iv->bv_page, iv->bv_len, iv->bv_offset); + sg_set_page(sg, iv.bv_page, iv.bv_len, iv.bv_offset); segments++; } + prev = 1; ivprv = iv; } diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 6174ca4ea275..a7a691d0af7d 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -365,7 +365,6 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector, struct bio *bio; struct scsi_disk *sdkp; struct sd_dif_tuple *sdt; - unsigned int i, j; u32 phys, virt; sdkp = rq->bio->bi_bdev->bd_disk->private_data; @@ -376,19 +375,21 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector, phys = hw_sector & 0xffffffff; __rq_for_each_bio(bio, rq) { - struct bio_vec *iv; + struct bio_vec iv; + struct bvec_iter iter; + unsigned int j; /* Already remapped? */ if (bio_flagged(bio, BIO_MAPPED_INTEGRITY)) break; - virt = bio->bi_integrity->bip_sector & 0xffffffff; + virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff; - bip_for_each_vec(iv, bio->bi_integrity, i) { - sdt = kmap_atomic(iv->bv_page) - + iv->bv_offset; + bip_for_each_vec(iv, bio->bi_integrity, iter) { + sdt = kmap_atomic(iv.bv_page) + + iv.bv_offset; - for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) { + for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { if (be32_to_cpu(sdt->ref_tag) == virt) sdt->ref_tag = cpu_to_be32(phys); @@ -414,7 +415,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) struct scsi_disk *sdkp; struct bio *bio; struct sd_dif_tuple *sdt; - unsigned int i, j, sectors, sector_sz; + unsigned int j, sectors, sector_sz; u32 phys, virt; sdkp = scsi_disk(scmd->request->rq_disk); @@ -430,15 +431,16 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) phys >>= 3; __rq_for_each_bio(bio, scmd->request) { - struct bio_vec *iv; + struct bio_vec iv; + struct bvec_iter iter; - virt = bio->bi_integrity->bip_sector & 0xffffffff; + virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff; - bip_for_each_vec(iv, bio->bi_integrity, i) { - sdt = kmap_atomic(iv->bv_page) - + iv->bv_offset; + bip_for_each_vec(iv, bio->bi_integrity, iter) { + sdt = kmap_atomic(iv.bv_page) + + iv.bv_offset; - for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) { + for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) { if (sectors == 0) { kunmap_atomic(sdt); diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 9127db86f315..fed744b8c9e5 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -134,8 +134,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, return 0; } - iv = bip_vec_idx(bip, bip->bip_vcnt); - BUG_ON(iv == NULL); + iv = bip->bip_vec + bip->bip_vcnt; iv->bv_page = page; iv->bv_len = len; @@ -203,6 +202,12 @@ static inline unsigned int bio_integrity_hw_sectors(struct blk_integrity *bi, return sectors; } +static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi, + unsigned int sectors) +{ + return bio_integrity_hw_sectors(bi, sectors) * bi->tuple_size; +} + /** * bio_integrity_tag_size - Retrieve integrity tag space * @bio: bio to inspect @@ -235,9 +240,9 @@ int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set) nr_sectors = bio_integrity_hw_sectors(bi, DIV_ROUND_UP(len, bi->tag_size)); - if (nr_sectors * bi->tuple_size > bip->bip_size) { - printk(KERN_ERR "%s: tag too big for bio: %u > %u\n", - __func__, nr_sectors * bi->tuple_size, bip->bip_size); + if (nr_sectors * bi->tuple_size > bip->bip_iter.bi_size) { + printk(KERN_ERR "%s: tag too big for bio: %u > %u\n", __func__, + nr_sectors * bi->tuple_size, bip->bip_iter.bi_size); return -1; } @@ -322,7 +327,7 @@ static void bio_integrity_generate(struct bio *bio) sector += sectors; prot_buf += sectors * bi->tuple_size; total += sectors * bi->tuple_size; - BUG_ON(total > bio->bi_integrity->bip_size); + BUG_ON(total > bio->bi_integrity->bip_iter.bi_size); kunmap_atomic(kaddr); } @@ -387,8 +392,8 @@ int bio_integrity_prep(struct bio *bio) bip->bip_owns_buf = 1; bip->bip_buf = buf; - bip->bip_size = len; - bip->bip_sector = bio->bi_iter.bi_sector; + bip->bip_iter.bi_size = len; + bip->bip_iter.bi_sector = bio->bi_iter.bi_sector; /* Map it */ offset = offset_in_page(buf); @@ -444,7 +449,7 @@ static int bio_integrity_verify(struct bio *bio) struct blk_integrity_exchg bix; struct bio_vec bv; struct bvec_iter iter; - sector_t sector = bio->bi_integrity->bip_sector; + sector_t sector = bio->bi_integrity->bip_iter.bi_sector; unsigned int sectors, total, ret; void *prot_buf = bio->bi_integrity->bip_buf; @@ -470,7 +475,7 @@ static int bio_integrity_verify(struct bio *bio) sector += sectors; prot_buf += sectors * bi->tuple_size; total += sectors * bi->tuple_size; - BUG_ON(total > bio->bi_integrity->bip_size); + BUG_ON(total > bio->bi_integrity->bip_iter.bi_size); kunmap_atomic(kaddr); } @@ -534,56 +539,6 @@ void bio_integrity_endio(struct bio *bio, int error) } EXPORT_SYMBOL(bio_integrity_endio); -/** - * bio_integrity_mark_head - Advance bip_vec skip bytes - * @bip: Integrity vector to advance - * @skip: Number of bytes to advance it - */ -void bio_integrity_mark_head(struct bio_integrity_payload *bip, - unsigned int skip) -{ - struct bio_vec *iv; - unsigned int i; - - bip_for_each_vec(iv, bip, i) { - if (skip == 0) { - bip->bip_idx = i; - return; - } else if (skip >= iv->bv_len) { - skip -= iv->bv_len; - } else { /* skip < iv->bv_len) */ - iv->bv_offset += skip; - iv->bv_len -= skip; - bip->bip_idx = i; - return; - } - } -} - -/** - * bio_integrity_mark_tail - Truncate bip_vec to be len bytes long - * @bip: Integrity vector to truncate - * @len: New length of integrity vector - */ -void bio_integrity_mark_tail(struct bio_integrity_payload *bip, - unsigned int len) -{ - struct bio_vec *iv; - unsigned int i; - - bip_for_each_vec(iv, bip, i) { - if (len == 0) { - bip->bip_vcnt = i; - return; - } else if (len >= iv->bv_len) { - len -= iv->bv_len; - } else { /* len < iv->bv_len) */ - iv->bv_len = len; - len = 0; - } - } -} - /** * bio_integrity_advance - Advance integrity vector * @bio: bio whose integrity vector to update @@ -597,13 +552,9 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done) { struct bio_integrity_payload *bip = bio->bi_integrity; struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); - unsigned int nr_sectors; + unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9); - BUG_ON(bip == NULL); - BUG_ON(bi == NULL); - - nr_sectors = bio_integrity_hw_sectors(bi, bytes_done >> 9); - bio_integrity_mark_head(bip, nr_sectors * bi->tuple_size); + bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes); } EXPORT_SYMBOL(bio_integrity_advance); @@ -623,16 +574,9 @@ void bio_integrity_trim(struct bio *bio, unsigned int offset, { struct bio_integrity_payload *bip = bio->bi_integrity; struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); - unsigned int nr_sectors; - BUG_ON(bip == NULL); - BUG_ON(bi == NULL); - BUG_ON(!bio_flagged(bio, BIO_CLONED)); - - nr_sectors = bio_integrity_hw_sectors(bi, sectors); - bip->bip_sector = bip->bip_sector + offset; - bio_integrity_mark_head(bip, offset * bi->tuple_size); - bio_integrity_mark_tail(bip, sectors * bi->tuple_size); + bio_integrity_advance(bio, offset << 9); + bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors); } EXPORT_SYMBOL(bio_integrity_trim); @@ -662,8 +606,8 @@ void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors) bp->bio1.bi_integrity = &bp->bip1; bp->bio2.bi_integrity = &bp->bip2; - bp->iv1 = bip->bip_vec[bip->bip_idx]; - bp->iv2 = bip->bip_vec[bip->bip_idx]; + bp->iv1 = bip->bip_vec[bip->bip_iter.bi_idx]; + bp->iv2 = bip->bip_vec[bip->bip_iter.bi_idx]; bp->bip1.bip_vec = &bp->iv1; bp->bip2.bip_vec = &bp->iv2; @@ -672,11 +616,12 @@ void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors) bp->iv2.bv_offset += sectors * bi->tuple_size; bp->iv2.bv_len -= sectors * bi->tuple_size; - bp->bip1.bip_sector = bio->bi_integrity->bip_sector; - bp->bip2.bip_sector = bio->bi_integrity->bip_sector + nr_sectors; + bp->bip1.bip_iter.bi_sector = bio->bi_integrity->bip_iter.bi_sector; + bp->bip2.bip_iter.bi_sector = + bio->bi_integrity->bip_iter.bi_sector + nr_sectors; bp->bip1.bip_vcnt = bp->bip2.bip_vcnt = 1; - bp->bip1.bip_idx = bp->bip2.bip_idx = 0; + bp->bip1.bip_iter.bi_idx = bp->bip2.bip_iter.bi_idx = 0; } EXPORT_SYMBOL(bio_integrity_split); @@ -704,9 +649,8 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src, memcpy(bip->bip_vec, bip_src->bip_vec, bip_src->bip_vcnt * sizeof(struct bio_vec)); - bip->bip_sector = bip_src->bip_sector; bip->bip_vcnt = bip_src->bip_vcnt; - bip->bip_idx = bip_src->bip_idx; + bip->bip_iter = bip_src->bip_iter; return 0; } diff --git a/include/linux/bio.h b/include/linux/bio.h index 04e592e74c92..930cb73c894b 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -244,16 +244,15 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, struct bio_integrity_payload { struct bio *bip_bio; /* parent bio */ - sector_t bip_sector; /* virtual start sector */ + struct bvec_iter bip_iter; + /* kill - should just use bip_vec */ void *bip_buf; /* generated integrity data */ - bio_end_io_t *bip_end_io; /* saved I/O completion fn */ - unsigned int bip_size; + bio_end_io_t *bip_end_io; /* saved I/O completion fn */ unsigned short bip_slab; /* slab the bip came from */ unsigned short bip_vcnt; /* # of integrity bio_vecs */ - unsigned short bip_idx; /* current bip_vec index */ unsigned bip_owns_buf:1; /* should free bip_buf */ struct work_struct bip_work; /* I/O completion */ @@ -626,16 +625,12 @@ struct biovec_slab { #if defined(CONFIG_BLK_DEV_INTEGRITY) -#define bip_vec_idx(bip, idx) (&(bip->bip_vec[(idx)])) -#define bip_vec(bip) bip_vec_idx(bip, 0) -#define __bip_for_each_vec(bvl, bip, i, start_idx) \ - for (bvl = bip_vec_idx((bip), (start_idx)), i = (start_idx); \ - i < (bip)->bip_vcnt; \ - bvl++, i++) -#define bip_for_each_vec(bvl, bip, i) \ - __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx) +#define bip_vec_idx(bip, idx) (&(bip->bip_vec[(idx)])) + +#define bip_for_each_vec(bvl, bip, iter) \ + for_each_bvec(bvl, (bip)->bip_vec, iter, (bip)->bip_iter) #define bio_for_each_integrity_vec(_bvl, _bio, _iter) \ for_each_bio(_bio) \ -- cgit v1.2.3 From 458b76ed2f9517becb74dcc8eedd70d3068ea6e4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 24 Sep 2013 16:26:05 -0700 Subject: block: Kill bio_segments()/bi_vcnt usage When we start sharing biovecs, keeping bi_vcnt accurate for splits is going to be error prone - and unnecessary, if we refactor some code. So bio_segments() has to go - but most of the existing users just needed to know if the bio had multiple segments, which is easier - add a bio_multiple_segments() for them. (Two of the current uses of bio_segments() are going to go away in a couple patches, but the current implementation of bio_segments() is unsafe as soon as we start doing driver conversions for immutable biovecs - so implement a dumb version for bisectability, it'll go away in a couple patches) Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Neil Brown Cc: Nagalakshmi Nandigama Cc: Sreekanth Reddy Cc: "James E.J. Bottomley" --- drivers/block/ps3disk.c | 7 ++- drivers/md/bcache/io.c | 53 +++++++++------------ drivers/md/raid0.c | 2 +- drivers/md/raid10.c | 2 +- drivers/message/fusion/mptsas.c | 8 ++-- drivers/scsi/libsas/sas_expander.c | 8 ++-- drivers/scsi/mpt2sas/mpt2sas_transport.c | 10 ++-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 8 ++-- fs/bio.c | 2 +- include/linux/bio.h | 81 +++++++++++++++++++------------- 10 files changed, 94 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 1c6edb9a9960..c120d70d3fb3 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -101,10 +101,9 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, rq_for_each_segment(bvec, req, iter) { unsigned long flags; - dev_dbg(&dev->sbd.core, - "%s:%u: bio %u: %u segs %u sectors from %lu\n", - __func__, __LINE__, i, bio_segments(iter.bio), - bio_sectors(iter.bio), iter.bio->bi_iter.bi_sector); + dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u sectors from %lu\n", + __func__, __LINE__, i, bio_sectors(iter.bio), + iter.bio->bi_iter.bi_sector); size = bvec.bv_len; buf = bvec_kmap_irq(&bvec, &flags); diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 9b5b6a41a9b6..6e04f3bb0286 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -24,7 +24,8 @@ static void bch_generic_make_request_hack(struct bio *bio) if (bio->bi_iter.bi_idx) { struct bio_vec bv; struct bvec_iter iter; - struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio)); + unsigned segs = bio_segments(bio); + struct bio *clone = bio_alloc(GFP_NOIO, segs); bio_for_each_segment(bv, bio, iter) clone->bi_io_vec[clone->bi_vcnt++] = bv; @@ -32,7 +33,7 @@ static void bch_generic_make_request_hack(struct bio *bio) clone->bi_iter.bi_sector = bio->bi_iter.bi_sector; clone->bi_bdev = bio->bi_bdev; clone->bi_rw = bio->bi_rw; - clone->bi_vcnt = bio_segments(bio); + clone->bi_vcnt = segs; clone->bi_iter.bi_size = bio->bi_iter.bi_size; clone->bi_private = bio; @@ -133,40 +134,32 @@ out: static unsigned bch_bio_max_sectors(struct bio *bio) { - unsigned ret = bio_sectors(bio); struct request_queue *q = bdev_get_queue(bio->bi_bdev); - unsigned max_segments = min_t(unsigned, BIO_MAX_PAGES, - queue_max_segments(q)); + struct bio_vec bv; + struct bvec_iter iter; + unsigned ret = 0, seg = 0; if (bio->bi_rw & REQ_DISCARD) - return min(ret, q->limits.max_discard_sectors); - - if (bio_segments(bio) > max_segments || - q->merge_bvec_fn) { - struct bio_vec bv; - struct bvec_iter iter; - unsigned seg = 0; - - ret = 0; + return min(bio_sectors(bio), q->limits.max_discard_sectors); - bio_for_each_segment(bv, bio, iter) { - struct bvec_merge_data bvm = { - .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_iter.bi_sector, - .bi_size = ret << 9, - .bi_rw = bio->bi_rw, - }; - - if (seg == max_segments) - break; + bio_for_each_segment(bv, bio, iter) { + struct bvec_merge_data bvm = { + .bi_bdev = bio->bi_bdev, + .bi_sector = bio->bi_iter.bi_sector, + .bi_size = ret << 9, + .bi_rw = bio->bi_rw, + }; + + if (seg == min_t(unsigned, BIO_MAX_PAGES, + queue_max_segments(q))) + break; - if (q->merge_bvec_fn && - q->merge_bvec_fn(q, &bvm, &bv) < (int) bv.bv_len) - break; + if (q->merge_bvec_fn && + q->merge_bvec_fn(q, &bvm, &bv) < (int) bv.bv_len) + break; - seg++; - ret += bv.bv_len >> 9; - } + seg++; + ret += bv.bv_len >> 9; } ret = min(ret, queue_max_sectors(q)); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index e38d1d3226f3..8ee1a6c658b4 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -528,7 +528,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) sector_t sector = bio->bi_iter.bi_sector; struct bio_pair *bp; /* Sanity check -- queue functions should prevent this happening */ - if (bio_segments(bio) > 1) + if (bio_multiple_segments(bio)) goto bad_map; /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index dbf3b63c2754..ac4bfa438c57 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1188,7 +1188,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) || conf->prev.near_copies < conf->prev.raid_disks))) { struct bio_pair *bp; /* Sanity check -- queue functions should prevent this happening */ - if (bio_segments(bio) > 1) + if (bio_multiple_segments(bio)) goto bad_map; /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index dd239bdbfcb4..00d339c361fc 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -2235,10 +2235,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, } /* do we need to support multiple segments? */ - if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) { - printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", - ioc->name, __func__, bio_segments(req->bio), blk_rq_bytes(req), - bio_segments(rsp->bio), blk_rq_bytes(rsp)); + if (bio_multiple_segments(req->bio) || + bio_multiple_segments(rsp->bio)) { + printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u, rsp %u\n", + ioc->name, __func__, blk_rq_bytes(req), blk_rq_bytes(rsp)); return -EINVAL; } diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 446b85110a1f..0cac7d8fd0f7 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -2163,10 +2163,10 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, } /* do we need to support multiple segments? */ - if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) { - printk("%s: multiple segments req %u %u, rsp %u %u\n", - __func__, bio_segments(req->bio), blk_rq_bytes(req), - bio_segments(rsp->bio), blk_rq_bytes(rsp)); + if (bio_multiple_segments(req->bio) || + bio_multiple_segments(rsp->bio)) { + printk("%s: multiple segments req %u, rsp %u\n", + __func__, blk_rq_bytes(req), blk_rq_bytes(rsp)); return -EINVAL; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 7143e86af326..410f4a3e8888 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -1943,7 +1943,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, ioc->transport_cmds.status = MPT2_CMD_PENDING; /* Check if the request is split across multiple segments */ - if (bio_segments(req->bio) > 1) { + if (bio_multiple_segments(req->bio)) { u32 offset = 0; /* Allocate memory and copy the request */ @@ -1975,7 +1975,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, /* Check if the response needs to be populated across * multiple segments */ - if (bio_segments(rsp->bio) > 1) { + if (bio_multiple_segments(rsp->bio)) { pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp), &pci_dma_in); if (!pci_addr_in) { @@ -2042,7 +2042,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - if (bio_segments(req->bio) > 1) { + if (bio_multiple_segments(req->bio)) { ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4), pci_dma_out); } else { @@ -2058,7 +2058,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST); sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - if (bio_segments(rsp->bio) > 1) { + if (bio_multiple_segments(rsp->bio)) { ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4), pci_dma_in); } else { @@ -2103,7 +2103,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, le16_to_cpu(mpi_reply->ResponseDataLength); /* check if the resp needs to be copied from the allocated * pci mem */ - if (bio_segments(rsp->bio) > 1) { + if (bio_multiple_segments(rsp->bio)) { u32 offset = 0; u32 bytes_to_copy = le16_to_cpu(mpi_reply->ResponseDataLength); diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 196a67f2e95f..65170cb1a00f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -1926,7 +1926,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, ioc->transport_cmds.status = MPT3_CMD_PENDING; /* Check if the request is split across multiple segments */ - if (req->bio->bi_vcnt > 1) { + if (bio_multiple_segments(req->bio)) { u32 offset = 0; /* Allocate memory and copy the request */ @@ -1958,7 +1958,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, /* Check if the response needs to be populated across * multiple segments */ - if (rsp->bio->bi_vcnt > 1) { + if (bio_multiple_segments(rsp->bio)) { pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp), &pci_dma_in); if (!pci_addr_in) { @@ -2019,7 +2019,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); psge = &mpi_request->SGL; - if (req->bio->bi_vcnt > 1) + if (bio_multiple_segments(req->bio)) ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4), pci_dma_in, (blk_rq_bytes(rsp) + 4)); else @@ -2064,7 +2064,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, /* check if the resp needs to be copied from the allocated * pci mem */ - if (rsp->bio->bi_vcnt > 1) { + if (bio_multiple_segments(rsp->bio)) { u32 offset = 0; u32 bytes_to_copy = le16_to_cpu(mpi_reply->ResponseDataLength); diff --git a/fs/bio.c b/fs/bio.c index f61e59b38815..e32f2ffc3f33 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1733,7 +1733,7 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors) trace_block_split(bdev_get_queue(bi->bi_bdev), bi, bi->bi_iter.bi_sector + first_sectors); - BUG_ON(bio_segments(bi) > 1); + BUG_ON(bio_multiple_segments(bi)); atomic_set(&bp->cnt, 3); bp->error = 0; bp->bio1 = *bi; diff --git a/include/linux/bio.h b/include/linux/bio.h index 930cb73c894b..aea9896a6289 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -97,13 +97,46 @@ #define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter) #define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter) -#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx) +#define bio_multiple_segments(bio) \ + ((bio)->bi_iter.bi_size != bio_iovec(bio).bv_len) #define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9) #define bio_end_sector(bio) ((bio)->bi_iter.bi_sector + bio_sectors((bio))) +/* + * Check whether this bio carries any data or not. A NULL bio is allowed. + */ +static inline bool bio_has_data(struct bio *bio) +{ + if (bio && + bio->bi_iter.bi_size && + !(bio->bi_rw & REQ_DISCARD)) + return true; + + return false; +} + +static inline bool bio_is_rw(struct bio *bio) +{ + if (!bio_has_data(bio)) + return false; + + if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) + return false; + + return true; +} + +static inline bool bio_mergeable(struct bio *bio) +{ + if (bio->bi_rw & REQ_NOMERGE_FLAGS) + return false; + + return true; +} + static inline unsigned int bio_cur_bytes(struct bio *bio) { - if (bio->bi_vcnt) + if (bio_has_data(bio)) return bio_iovec(bio).bv_len; else /* dataless requests such as discard */ return bio->bi_iter.bi_size; @@ -111,7 +144,7 @@ static inline unsigned int bio_cur_bytes(struct bio *bio) static inline void *bio_data(struct bio *bio) { - if (bio->bi_vcnt) + if (bio_has_data(bio)) return page_address(bio_page(bio)) + bio_offset(bio); return NULL; @@ -221,6 +254,18 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len) +static inline unsigned bio_segments(struct bio *bio) +{ + unsigned segs = 0; + struct bio_vec bv; + struct bvec_iter iter; + + bio_for_each_segment(bv, bio, iter) + segs++; + + return segs; +} + /* * get a reference to a bio, so it won't disappear. the intended use is * something like: @@ -434,36 +479,6 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx, __bio_kmap_irq((bio), (bio)->bi_iter.bi_idx, (flags)) #define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags) -/* - * Check whether this bio carries any data or not. A NULL bio is allowed. - */ -static inline bool bio_has_data(struct bio *bio) -{ - if (bio && bio->bi_vcnt) - return true; - - return false; -} - -static inline bool bio_is_rw(struct bio *bio) -{ - if (!bio_has_data(bio)) - return false; - - if (bio->bi_rw & REQ_WRITE_SAME) - return false; - - return true; -} - -static inline bool bio_mergeable(struct bio *bio) -{ - if (bio->bi_rw & REQ_NOMERGE_FLAGS) - return false; - - return true; -} - /* * BIO list management for use by remapping drivers (e.g. DM or MD) and loop. * -- cgit v1.2.3 From 003b5c5719f159f4f4bf97511c4702a0638313dd Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 11 Oct 2013 15:45:43 -0700 Subject: block: Convert drivers to immutable biovecs Now that we've got a mechanism for immutable biovecs - bi_iter.bi_bvec_done - we need to convert drivers to use primitives that respect it instead of using the bvec array directly. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: NeilBrown Cc: Alasdair Kergon Cc: dm-devel@redhat.com --- drivers/block/umem.c | 50 ++++++++++++++++++++++-------------------------- drivers/md/dm-crypt.c | 49 +++++++++++++++++------------------------------ drivers/md/dm-io.c | 31 ++++++++++++++++-------------- drivers/md/dm-raid1.c | 8 ++++---- drivers/md/dm-verity.c | 52 ++++++++++++++------------------------------------ fs/bio.c | 14 +++++++++++--- include/linux/dm-io.h | 4 ++-- 7 files changed, 89 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/block/umem.c b/drivers/block/umem.c index dab4f1afeae9..4cf81b5bf0f7 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -108,8 +108,7 @@ struct cardinfo { * have been written */ struct bio *bio, *currentbio, **biotail; - int current_idx; - sector_t current_sector; + struct bvec_iter current_iter; struct request_queue *queue; @@ -118,7 +117,7 @@ struct cardinfo { struct mm_dma_desc *desc; int cnt, headcnt; struct bio *bio, **biotail; - int idx; + struct bvec_iter iter; } mm_pages[2]; #define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc)) @@ -344,16 +343,13 @@ static int add_bio(struct cardinfo *card) dma_addr_t dma_handle; int offset; struct bio *bio; - struct bio_vec *vec; - int idx; + struct bio_vec vec; int rw; - int len; bio = card->currentbio; if (!bio && card->bio) { card->currentbio = card->bio; - card->current_idx = card->bio->bi_iter.bi_idx; - card->current_sector = card->bio->bi_iter.bi_sector; + card->current_iter = card->bio->bi_iter; card->bio = card->bio->bi_next; if (card->bio == NULL) card->biotail = &card->bio; @@ -362,18 +358,17 @@ static int add_bio(struct cardinfo *card) } if (!bio) return 0; - idx = card->current_idx; rw = bio_rw(bio); if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE) return 0; - vec = bio_iovec_idx(bio, idx); - len = vec->bv_len; + vec = bio_iter_iovec(bio, card->current_iter); + dma_handle = pci_map_page(card->dev, - vec->bv_page, - vec->bv_offset, - len, + vec.bv_page, + vec.bv_offset, + vec.bv_len, (rw == READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); @@ -381,7 +376,7 @@ static int add_bio(struct cardinfo *card) desc = &p->desc[p->cnt]; p->cnt++; if (p->bio == NULL) - p->idx = idx; + p->iter = card->current_iter; if ((p->biotail) != &bio->bi_next) { *(p->biotail) = bio; p->biotail = &(bio->bi_next); @@ -391,8 +386,8 @@ static int add_bio(struct cardinfo *card) desc->data_dma_handle = dma_handle; desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle); - desc->local_addr = cpu_to_le64(card->current_sector << 9); - desc->transfer_size = cpu_to_le32(len); + desc->local_addr = cpu_to_le64(card->current_iter.bi_sector << 9); + desc->transfer_size = cpu_to_le32(vec.bv_len); offset = (((char *)&desc->sem_control_bits) - ((char *)p->desc)); desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset)); desc->zero1 = desc->zero2 = 0; @@ -407,10 +402,9 @@ static int add_bio(struct cardinfo *card) desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ); desc->sem_control_bits = desc->control_bits; - card->current_sector += (len >> 9); - idx++; - card->current_idx = idx; - if (idx >= bio->bi_vcnt) + + bio_advance_iter(bio, &card->current_iter, vec.bv_len); + if (!card->current_iter.bi_size) card->currentbio = NULL; return 1; @@ -439,23 +433,25 @@ static void process_page(unsigned long data) struct mm_dma_desc *desc = &page->desc[page->headcnt]; int control = le32_to_cpu(desc->sem_control_bits); int last = 0; - int idx; + struct bio_vec vec; if (!(control & DMASCR_DMA_COMPLETE)) { control = dma_status; last = 1; } + page->headcnt++; - idx = page->idx; - page->idx++; - if (page->idx >= bio->bi_vcnt) { + vec = bio_iter_iovec(bio, page->iter); + bio_advance_iter(bio, &page->iter, vec.bv_len); + + if (!page->iter.bi_size) { page->bio = bio->bi_next; if (page->bio) - page->idx = page->bio->bi_iter.bi_idx; + page->iter = page->bio->bi_iter; } pci_unmap_page(card->dev, desc->data_dma_handle, - bio_iovec_idx(bio, idx)->bv_len, + vec.bv_len, (control & DMASCR_TRANSFER_READ) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); if (control & DMASCR_HARD_ERROR) { diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 1e2e5465d28e..784695d22fde 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -39,10 +39,8 @@ struct convert_context { struct completion restart; struct bio *bio_in; struct bio *bio_out; - unsigned int offset_in; - unsigned int offset_out; - unsigned int idx_in; - unsigned int idx_out; + struct bvec_iter iter_in; + struct bvec_iter iter_out; sector_t cc_sector; atomic_t cc_pending; }; @@ -826,10 +824,10 @@ static void crypt_convert_init(struct crypt_config *cc, { ctx->bio_in = bio_in; ctx->bio_out = bio_out; - ctx->offset_in = 0; - ctx->offset_out = 0; - ctx->idx_in = bio_in ? bio_in->bi_iter.bi_idx : 0; - ctx->idx_out = bio_out ? bio_out->bi_iter.bi_idx : 0; + if (bio_in) + ctx->iter_in = bio_in->bi_iter; + if (bio_out) + ctx->iter_out = bio_out->bi_iter; ctx->cc_sector = sector + cc->iv_offset; init_completion(&ctx->restart); } @@ -857,8 +855,8 @@ static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, struct ablkcipher_request *req) { - struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in); - struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out); + struct bio_vec bv_in = bio_iter_iovec(ctx->bio_in, ctx->iter_in); + struct bio_vec bv_out = bio_iter_iovec(ctx->bio_out, ctx->iter_out); struct dm_crypt_request *dmreq; u8 *iv; int r; @@ -869,24 +867,15 @@ static int crypt_convert_block(struct crypt_config *cc, dmreq->iv_sector = ctx->cc_sector; dmreq->ctx = ctx; sg_init_table(&dmreq->sg_in, 1); - sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, - bv_in->bv_offset + ctx->offset_in); + sg_set_page(&dmreq->sg_in, bv_in.bv_page, 1 << SECTOR_SHIFT, + bv_in.bv_offset); sg_init_table(&dmreq->sg_out, 1); - sg_set_page(&dmreq->sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, - bv_out->bv_offset + ctx->offset_out); + sg_set_page(&dmreq->sg_out, bv_out.bv_page, 1 << SECTOR_SHIFT, + bv_out.bv_offset); - ctx->offset_in += 1 << SECTOR_SHIFT; - if (ctx->offset_in >= bv_in->bv_len) { - ctx->offset_in = 0; - ctx->idx_in++; - } - - ctx->offset_out += 1 << SECTOR_SHIFT; - if (ctx->offset_out >= bv_out->bv_len) { - ctx->offset_out = 0; - ctx->idx_out++; - } + bio_advance_iter(ctx->bio_in, &ctx->iter_in, 1 << SECTOR_SHIFT); + bio_advance_iter(ctx->bio_out, &ctx->iter_out, 1 << SECTOR_SHIFT); if (cc->iv_gen_ops) { r = cc->iv_gen_ops->generator(cc, iv, dmreq); @@ -937,8 +926,7 @@ static int crypt_convert(struct crypt_config *cc, atomic_set(&ctx->cc_pending, 1); - while(ctx->idx_in < ctx->bio_in->bi_vcnt && - ctx->idx_out < ctx->bio_out->bi_vcnt) { + while (ctx->iter_in.bi_size && ctx->iter_out.bi_size) { crypt_alloc_req(cc, ctx); @@ -1207,7 +1195,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) } /* crypt_convert should have filled the clone bio */ - BUG_ON(io->ctx.idx_out < clone->bi_vcnt); + BUG_ON(io->ctx.iter_out.bi_size); clone->bi_iter.bi_sector = cc->start + io->sector; @@ -1246,7 +1234,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) } io->ctx.bio_out = clone; - io->ctx.idx_out = 0; + io->ctx.iter_out = clone->bi_iter; remaining -= clone->bi_iter.bi_size; sector += bio_sectors(clone); @@ -1290,8 +1278,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) crypt_inc_pending(new_io); crypt_convert_init(cc, &new_io->ctx, NULL, io->base_bio, sector); - new_io->ctx.idx_in = io->ctx.idx_in; - new_io->ctx.offset_in = io->ctx.offset_in; + new_io->ctx.iter_in = io->ctx.iter_in; /* * Fragments after the first use the base_io diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 01558b093307..b2b8a10e8427 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -201,26 +201,29 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse /* * Functions for getting the pages from a bvec. */ -static void bvec_get_page(struct dpages *dp, +static void bio_get_page(struct dpages *dp, struct page **p, unsigned long *len, unsigned *offset) { - struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr; - *p = bvec->bv_page; - *len = bvec->bv_len; - *offset = bvec->bv_offset; + struct bio *bio = dp->context_ptr; + struct bio_vec bvec = bio_iovec(bio); + *p = bvec.bv_page; + *len = bvec.bv_len; + *offset = bvec.bv_offset; } -static void bvec_next_page(struct dpages *dp) +static void bio_next_page(struct dpages *dp) { - struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr; - dp->context_ptr = bvec + 1; + struct bio *bio = dp->context_ptr; + struct bio_vec bvec = bio_iovec(bio); + + bio_advance(bio, bvec.bv_len); } -static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec) +static void bio_dp_init(struct dpages *dp, struct bio *bio) { - dp->get_page = bvec_get_page; - dp->next_page = bvec_next_page; - dp->context_ptr = bvec; + dp->get_page = bio_get_page; + dp->next_page = bio_next_page; + dp->context_ptr = bio; } /* @@ -457,8 +460,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp, list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset); break; - case DM_IO_BVEC: - bvec_dp_init(dp, io_req->mem.ptr.bvec); + case DM_IO_BIO: + bio_dp_init(dp, io_req->mem.ptr.bio); break; case DM_IO_VMA: diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 9f6d8e6baa7d..f284e0bfb25f 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -526,8 +526,8 @@ static void read_async_bio(struct mirror *m, struct bio *bio) struct dm_io_region io; struct dm_io_request io_req = { .bi_rw = READ, - .mem.type = DM_IO_BVEC, - .mem.ptr.bvec = bio->bi_io_vec + bio->bi_iter.bi_idx, + .mem.type = DM_IO_BIO, + .mem.ptr.bio = bio, .notify.fn = read_callback, .notify.context = bio, .client = m->ms->io_client, @@ -629,8 +629,8 @@ static void do_write(struct mirror_set *ms, struct bio *bio) struct mirror *m; struct dm_io_request io_req = { .bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA), - .mem.type = DM_IO_BVEC, - .mem.ptr.bvec = bio->bi_io_vec + bio->bi_iter.bi_idx, + .mem.type = DM_IO_BIO, + .mem.ptr.bio = bio, .notify.fn = write_callback, .notify.context = bio, .client = ms->io_client, diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 5392135924ca..ac35e959d49b 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -73,15 +73,10 @@ struct dm_verity_io { sector_t block; unsigned n_blocks; - /* saved bio vector */ - struct bio_vec *io_vec; - unsigned io_vec_size; + struct bvec_iter iter; struct work_struct work; - /* A space for short vectors; longer vectors are allocated separately. */ - struct bio_vec io_vec_inline[DM_VERITY_IO_VEC_INLINE]; - /* * Three variably-size fields follow this struct: * @@ -284,9 +279,10 @@ release_ret_r: static int verity_verify_io(struct dm_verity_io *io) { struct dm_verity *v = io->v; + struct bio *bio = dm_bio_from_per_bio_data(io, + v->ti->per_bio_data_size); unsigned b; int i; - unsigned vector = 0, offset = 0; for (b = 0; b < io->n_blocks; b++) { struct shash_desc *desc; @@ -336,31 +332,22 @@ test_block_hash: } todo = 1 << v->data_dev_block_bits; - do { - struct bio_vec *bv; + while (io->iter.bi_size) { u8 *page; - unsigned len; - - BUG_ON(vector >= io->io_vec_size); - bv = &io->io_vec[vector]; - page = kmap_atomic(bv->bv_page); - len = bv->bv_len - offset; - if (likely(len >= todo)) - len = todo; - r = crypto_shash_update(desc, - page + bv->bv_offset + offset, len); + struct bio_vec bv = bio_iter_iovec(bio, io->iter); + + page = kmap_atomic(bv.bv_page); + r = crypto_shash_update(desc, page + bv.bv_offset, + bv.bv_len); kunmap_atomic(page); + if (r < 0) { DMERR("crypto_shash_update failed: %d", r); return r; } - offset += len; - if (likely(offset == bv->bv_len)) { - offset = 0; - vector++; - } - todo -= len; - } while (todo); + + bio_advance_iter(bio, &io->iter, bv.bv_len); + } if (!v->version) { r = crypto_shash_update(desc, v->salt, v->salt_size); @@ -383,8 +370,6 @@ test_block_hash: return -EIO; } } - BUG_ON(vector != io->io_vec_size); - BUG_ON(offset); return 0; } @@ -400,9 +385,6 @@ static void verity_finish_io(struct dm_verity_io *io, int error) bio->bi_end_io = io->orig_bi_end_io; bio->bi_private = io->orig_bi_private; - if (io->io_vec != io->io_vec_inline) - mempool_free(io->io_vec, v->vec_mempool); - bio_endio(bio, error); } @@ -519,13 +501,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio) bio->bi_end_io = verity_end_io; bio->bi_private = io; - io->io_vec_size = bio_segments(bio); - if (io->io_vec_size < DM_VERITY_IO_VEC_INLINE) - io->io_vec = io->io_vec_inline; - else - io->io_vec = mempool_alloc(v->vec_mempool, GFP_NOIO); - memcpy(io->io_vec, __bio_iovec(bio), - io->io_vec_size * sizeof(struct bio_vec)); + io->iter = bio->bi_iter; verity_submit_prefetch(v, io); diff --git a/fs/bio.c b/fs/bio.c index e32f2ffc3f33..a082ce2d197b 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -525,8 +525,17 @@ EXPORT_SYMBOL(bio_phys_segments); */ void __bio_clone(struct bio *bio, struct bio *bio_src) { - memcpy(bio->bi_io_vec, bio_src->bi_io_vec, - bio_src->bi_max_vecs * sizeof(struct bio_vec)); + if (bio_is_rw(bio_src)) { + struct bio_vec bv; + struct bvec_iter iter; + + bio_for_each_segment(bv, bio_src, iter) + bio->bi_io_vec[bio->bi_vcnt++] = bv; + } else if (bio_has_data(bio_src)) { + memcpy(bio->bi_io_vec, bio_src->bi_io_vec, + bio_src->bi_max_vecs * sizeof(struct bio_vec)); + bio->bi_vcnt = bio_src->bi_vcnt; + } /* * most users will be overriding ->bi_bdev with a new target, @@ -535,7 +544,6 @@ void __bio_clone(struct bio *bio, struct bio *bio_src) bio->bi_bdev = bio_src->bi_bdev; bio->bi_flags |= 1 << BIO_CLONED; bio->bi_rw = bio_src->bi_rw; - bio->bi_vcnt = bio_src->bi_vcnt; bio->bi_iter = bio_src->bi_iter; } EXPORT_SYMBOL(__bio_clone); diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h index f4b0aa3126f5..a68cbe59e6ad 100644 --- a/include/linux/dm-io.h +++ b/include/linux/dm-io.h @@ -29,7 +29,7 @@ typedef void (*io_notify_fn)(unsigned long error, void *context); enum dm_io_mem_type { DM_IO_PAGE_LIST,/* Page list */ - DM_IO_BVEC, /* Bio vector */ + DM_IO_BIO, /* Bio vector */ DM_IO_VMA, /* Virtual memory area */ DM_IO_KMEM, /* Kernel memory */ }; @@ -41,7 +41,7 @@ struct dm_io_memory { union { struct page_list *pl; - struct bio_vec *bvec; + struct bio *bio; void *vma; void *addr; } ptr; -- cgit v1.2.3 From feb261e2ee5d782c7e9c71fe1ef0828244a42cc1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 13 Aug 2013 11:41:43 -0700 Subject: aoe: Convert to immutable biovecs Now that we've got a mechanism for immutable biovecs - bi_iter.bi_bvec_done - we need to convert drivers to use primitives that respect it instead of using the bvec array directly. The aoe code no longer has to manually iterate over partial bvecs, so some struct members go away - other struct members are effectively renamed: buf->resid -> buf->iter.bi_size buf->sector -> buf->iter.bi_sector f->bcnt -> f->iter.bi_size f->lba -> f->iter.bi_sector Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: "Ed L. Cashin" --- drivers/block/aoe/aoe.h | 10 +--- drivers/block/aoe/aoecmd.c | 135 +++++++++++++++++---------------------------- 2 files changed, 53 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 14a9d1912318..9220f8e833d0 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -100,11 +100,8 @@ enum { struct buf { ulong nframesout; - ulong resid; - ulong bv_resid; - sector_t sector; struct bio *bio; - struct bio_vec *bv; + struct bvec_iter iter; struct request *rq; }; @@ -120,13 +117,10 @@ struct frame { ulong waited; ulong waited_total; struct aoetgt *t; /* parent target I belong to */ - sector_t lba; struct sk_buff *skb; /* command skb freed on module exit */ struct sk_buff *r_skb; /* response skb for async processing */ struct buf *buf; - struct bio_vec *bv; - ulong bcnt; - ulong bv_off; + struct bvec_iter iter; char flags; }; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 7a06aec1dedc..8184451b57c0 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -196,8 +196,7 @@ aoe_freetframe(struct frame *f) t = f->t; f->buf = NULL; - f->lba = 0; - f->bv = NULL; + memset(&f->iter, 0, sizeof(f->iter)); f->r_skb = NULL; f->flags = 0; list_add(&f->head, &t->ffree); @@ -295,21 +294,14 @@ newframe(struct aoedev *d) } static void -skb_fillup(struct sk_buff *skb, struct bio_vec *bv, ulong off, ulong cnt) +skb_fillup(struct sk_buff *skb, struct bio *bio, struct bvec_iter iter) { int frag = 0; - ulong fcnt; -loop: - fcnt = bv->bv_len - (off - bv->bv_offset); - if (fcnt > cnt) - fcnt = cnt; - skb_fill_page_desc(skb, frag++, bv->bv_page, off, fcnt); - cnt -= fcnt; - if (cnt <= 0) - return; - bv++; - off = bv->bv_offset; - goto loop; + struct bio_vec bv; + + __bio_for_each_segment(bv, bio, iter, iter) + skb_fill_page_desc(skb, frag++, bv.bv_page, + bv.bv_offset, bv.bv_len); } static void @@ -346,12 +338,10 @@ ata_rw_frameinit(struct frame *f) t->nout++; f->waited = 0; f->waited_total = 0; - if (f->buf) - f->lba = f->buf->sector; /* set up ata header */ - ah->scnt = f->bcnt >> 9; - put_lba(ah, f->lba); + ah->scnt = f->iter.bi_size >> 9; + put_lba(ah, f->iter.bi_sector); if (t->d->flags & DEVFL_EXT) { ah->aflags |= AOEAFL_EXT; } else { @@ -360,11 +350,11 @@ ata_rw_frameinit(struct frame *f) ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ } if (f->buf && bio_data_dir(f->buf->bio) == WRITE) { - skb_fillup(skb, f->bv, f->bv_off, f->bcnt); + skb_fillup(skb, f->buf->bio, f->iter); ah->aflags |= AOEAFL_WRITE; - skb->len += f->bcnt; - skb->data_len = f->bcnt; - skb->truesize += f->bcnt; + skb->len += f->iter.bi_size; + skb->data_len = f->iter.bi_size; + skb->truesize += f->iter.bi_size; t->wpkts++; } else { t->rpkts++; @@ -382,7 +372,6 @@ aoecmd_ata_rw(struct aoedev *d) struct buf *buf; struct sk_buff *skb; struct sk_buff_head queue; - ulong bcnt, fbcnt; buf = nextbuf(d); if (buf == NULL) @@ -390,39 +379,22 @@ aoecmd_ata_rw(struct aoedev *d) f = newframe(d); if (f == NULL) return 0; - bcnt = d->maxbcnt; - if (bcnt == 0) - bcnt = DEFAULTBCNT; - if (bcnt > buf->resid) - bcnt = buf->resid; - fbcnt = bcnt; - f->bv = buf->bv; - f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid); - do { - if (fbcnt < buf->bv_resid) { - buf->bv_resid -= fbcnt; - buf->resid -= fbcnt; - break; - } - fbcnt -= buf->bv_resid; - buf->resid -= buf->bv_resid; - if (buf->resid == 0) { - d->ip.buf = NULL; - break; - } - buf->bv++; - buf->bv_resid = buf->bv->bv_len; - WARN_ON(buf->bv_resid == 0); - } while (fbcnt); /* initialize the headers & frame */ f->buf = buf; - f->bcnt = bcnt; - ata_rw_frameinit(f); + f->iter = buf->iter; + f->iter.bi_size = min_t(unsigned long, + d->maxbcnt ?: DEFAULTBCNT, + f->iter.bi_size); + bio_advance_iter(buf->bio, &buf->iter, f->iter.bi_size); + + if (!buf->iter.bi_size) + d->ip.buf = NULL; /* mark all tracking fields and load out */ buf->nframesout += 1; - buf->sector += bcnt >> 9; + + ata_rw_frameinit(f); skb = skb_clone(f->skb, GFP_ATOMIC); if (skb) { @@ -613,10 +585,7 @@ reassign_frame(struct frame *f) skb = nf->skb; nf->skb = f->skb; nf->buf = f->buf; - nf->bcnt = f->bcnt; - nf->lba = f->lba; - nf->bv = f->bv; - nf->bv_off = f->bv_off; + nf->iter = f->iter; nf->waited = 0; nf->waited_total = f->waited_total; nf->sent = f->sent; @@ -648,19 +617,19 @@ probe(struct aoetgt *t) } f->flags |= FFL_PROBE; ifrotate(t); - f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT; + f->iter.bi_size = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT; ata_rw_frameinit(f); skb = f->skb; - for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) { + for (frag = 0, n = f->iter.bi_size; n > 0; ++frag, n -= m) { if (n < PAGE_SIZE) m = n; else m = PAGE_SIZE; skb_fill_page_desc(skb, frag, empty_page, 0, m); } - skb->len += f->bcnt; - skb->data_len = f->bcnt; - skb->truesize += f->bcnt; + skb->len += f->iter.bi_size; + skb->data_len = f->iter.bi_size; + skb->truesize += f->iter.bi_size; skb = skb_clone(f->skb, GFP_ATOMIC); if (skb) { @@ -929,12 +898,8 @@ bufinit(struct buf *buf, struct request *rq, struct bio *bio) memset(buf, 0, sizeof(*buf)); buf->rq = rq; buf->bio = bio; - buf->resid = bio->bi_iter.bi_size; - buf->sector = bio->bi_iter.bi_sector; + buf->iter = bio->bi_iter; bio_pageinc(bio); - buf->bv = __bio_iovec(bio); - buf->bv_resid = buf->bv->bv_len; - WARN_ON(buf->bv_resid == 0); } static struct buf * @@ -1119,24 +1084,18 @@ gettgt(struct aoedev *d, char *addr) } static void -bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt) +bvcpy(struct sk_buff *skb, struct bio *bio, struct bvec_iter iter, long cnt) { - ulong fcnt; - char *p; int soff = 0; -loop: - fcnt = bv->bv_len - (off - bv->bv_offset); - if (fcnt > cnt) - fcnt = cnt; - p = page_address(bv->bv_page) + off; - skb_copy_bits(skb, soff, p, fcnt); - soff += fcnt; - cnt -= fcnt; - if (cnt <= 0) - return; - bv++; - off = bv->bv_offset; - goto loop; + struct bio_vec bv; + + iter.bi_size = cnt; + + __bio_for_each_segment(bv, bio, iter, iter) { + char *p = page_address(bv.bv_page) + bv.bv_offset; + skb_copy_bits(skb, soff, p, bv.bv_len); + soff += bv.bv_len; + } } void @@ -1229,7 +1188,15 @@ noskb: if (buf) clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); break; } - bvcpy(f->bv, f->bv_off, skb, n); + if (n > f->iter.bi_size) { + pr_err_ratelimited("%s e%ld.%d. bytes=%ld need=%u\n", + "aoe: too-large data size in read from", + (long) d->aoemajor, d->aoeminor, + n, f->iter.bi_size); + clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); + break; + } + bvcpy(skb, f->buf->bio, f->iter, n); case ATA_CMD_PIO_WRITE: case ATA_CMD_PIO_WRITE_EXT: spin_lock_irq(&d->lock); @@ -1272,7 +1239,7 @@ out: aoe_freetframe(f); - if (buf && --buf->nframesout == 0 && buf->resid == 0) + if (buf && --buf->nframesout == 0 && buf->iter.bi_size == 0) aoe_end_buf(d, buf); spin_unlock_irq(&d->lock); @@ -1727,7 +1694,7 @@ aoe_failbuf(struct aoedev *d, struct buf *buf) { if (buf == NULL) return; - buf->resid = 0; + buf->iter.bi_size = 0; clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); if (buf->nframesout == 0) aoe_end_buf(d, buf); -- cgit v1.2.3 From 59d276fe02d7e887a4825ef05c80b8f8c54ba60a Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 23 Nov 2013 18:19:27 -0800 Subject: block: Add bio_clone_fast() bio_clone() just got more expensive - however, most users of bio_clone() don't actually need to modify the biovec. If they aren't modifying the biovec, and they can guarantee that the original bio isn't freed before the clone (also true in most cases), we can just point the clone at the original bio's biovec. Signed-off-by: Kent Overstreet --- drivers/md/bcache/request.c | 8 ++---- fs/bio.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/bio.h | 2 ++ 3 files changed, 64 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 4c0a422fd49f..63451c724781 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -613,7 +613,6 @@ struct search { struct btree_op op; struct data_insert_op iop; - struct bio_vec bv[BIO_MAX_PAGES]; }; static void bch_cache_read_endio(struct bio *bio, int error) @@ -761,9 +760,7 @@ static void do_bio_hook(struct search *s) struct bio *bio = &s->bio.bio; bio_init(bio); - bio->bi_io_vec = s->bv; - bio->bi_max_vecs = BIO_MAX_PAGES; - __bio_clone(bio, s->orig_bio); + __bio_clone_fast(bio, s->orig_bio); bio->bi_end_io = request_endio; bio->bi_private = &s->cl; @@ -1065,8 +1062,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) closure_bio_submit(flush, cl, s->d); } } else { - s->iop.bio = bio_clone_bioset(bio, GFP_NOIO, - dc->disk.bio_split); + s->iop.bio = bio_clone_fast(bio, GFP_NOIO, dc->disk.bio_split); closure_bio_submit(bio, cl, s->d); } diff --git a/fs/bio.c b/fs/bio.c index 1628917e262a..00dc1893c6ee 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -548,6 +548,66 @@ void __bio_clone(struct bio *bio, struct bio *bio_src) } EXPORT_SYMBOL(__bio_clone); +/** + * __bio_clone_fast - clone a bio that shares the original bio's biovec + * @bio: destination bio + * @bio_src: bio to clone + * + * Clone a &bio. Caller will own the returned bio, but not + * the actual data it points to. Reference count of returned + * bio will be one. + * + * Caller must ensure that @bio_src is not freed before @bio. + */ +void __bio_clone_fast(struct bio *bio, struct bio *bio_src) +{ + BUG_ON(bio->bi_pool && BIO_POOL_IDX(bio) != BIO_POOL_NONE); + + /* + * most users will be overriding ->bi_bdev with a new target, + * so we don't set nor calculate new physical/hw segment counts here + */ + bio->bi_bdev = bio_src->bi_bdev; + bio->bi_flags |= 1 << BIO_CLONED; + bio->bi_rw = bio_src->bi_rw; + bio->bi_iter = bio_src->bi_iter; + bio->bi_io_vec = bio_src->bi_io_vec; +} +EXPORT_SYMBOL(__bio_clone_fast); + +/** + * bio_clone_fast - clone a bio that shares the original bio's biovec + * @bio: bio to clone + * @gfp_mask: allocation priority + * @bs: bio_set to allocate from + * + * Like __bio_clone_fast, only also allocates the returned bio + */ +struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs) +{ + struct bio *b; + + b = bio_alloc_bioset(gfp_mask, 0, bs); + if (!b) + return NULL; + + __bio_clone_fast(b, bio); + + if (bio_integrity(bio)) { + int ret; + + ret = bio_integrity_clone(b, bio, gfp_mask); + + if (ret < 0) { + bio_put(b); + return NULL; + } + } + + return b; +} +EXPORT_SYMBOL(bio_clone_fast); + /** * bio_clone_bioset - clone a bio * @bio_src: bio to clone diff --git a/include/linux/bio.h b/include/linux/bio.h index 1a31f9d9e057..1f83f4a3083e 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -328,6 +328,8 @@ extern mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries); extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); +extern void __bio_clone_fast(struct bio *, struct bio *); +extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *); extern void __bio_clone(struct bio *, struct bio *); extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); -- cgit v1.2.3 From 5341a6278bc5d10dbbb2ab6031b41d95c8db7a35 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 7 Aug 2013 14:31:11 -0700 Subject: rbd: Refactor bio cloning Now that we've got drivers converted to the new immutable bvec primitives, bio splitting becomes much easier - this is how the new bio_split() will work. (Someone more familiar with the ceph code could probably use bio_clone_fast() instead of bio_clone() here). Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Yehuda Sadeh Cc: Alex Elder Cc: ceph-devel@vger.kernel.org --- drivers/block/rbd.c | 64 ++--------------------------------------------------- 1 file changed, 2 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 20e8ab35736b..3624368b910d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1173,73 +1173,13 @@ static struct bio *bio_clone_range(struct bio *bio_src, unsigned int len, gfp_t gfpmask) { - struct bio_vec bv; - struct bvec_iter iter; - struct bvec_iter end_iter; - unsigned int resid; - unsigned int voff; - unsigned short vcnt; struct bio *bio; - /* Handle the easy case for the caller */ - - if (!offset && len == bio_src->bi_iter.bi_size) - return bio_clone(bio_src, gfpmask); - - if (WARN_ON_ONCE(!len)) - return NULL; - if (WARN_ON_ONCE(len > bio_src->bi_iter.bi_size)) - return NULL; - if (WARN_ON_ONCE(offset > bio_src->bi_iter.bi_size - len)) - return NULL; - - /* Find first affected segment... */ - - resid = offset; - bio_for_each_segment(bv, bio_src, iter) { - if (resid < bv.bv_len) - break; - resid -= bv.bv_len; - } - voff = resid; - - /* ...and the last affected segment */ - - resid += len; - __bio_for_each_segment(bv, bio_src, end_iter, iter) { - if (resid <= bv.bv_len) - break; - resid -= bv.bv_len; - } - vcnt = end_iter.bi_idx = iter.bi_idx + 1; - - /* Build the clone */ - - bio = bio_alloc(gfpmask, (unsigned int) vcnt); + bio = bio_clone(bio_src, gfpmask); if (!bio) return NULL; /* ENOMEM */ - bio->bi_bdev = bio_src->bi_bdev; - bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector + - (offset >> SECTOR_SHIFT); - bio->bi_rw = bio_src->bi_rw; - bio->bi_flags |= 1 << BIO_CLONED; - - /* - * Copy over our part of the bio_vec, then update the first - * and last (or only) entries. - */ - memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[iter.bi_idx], - vcnt * sizeof (struct bio_vec)); - bio->bi_io_vec[0].bv_offset += voff; - if (vcnt > 1) { - bio->bi_io_vec[0].bv_len -= voff; - bio->bi_io_vec[vcnt - 1].bv_len = resid; - } else { - bio->bi_io_vec[0].bv_len = len; - } - - bio->bi_vcnt = vcnt; + bio_advance(bio, offset); bio->bi_iter.bi_size = len; return bio; -- cgit v1.2.3 From 1c3b13e64cf70d652fb04e32d13ae3e36810c2e4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 29 Oct 2013 17:17:49 -0700 Subject: dm: Refactor for new bio cloning/splitting We need to convert the dm code to the new bvec_iter primitives which respect bi_bvec_done; they also allow us to drastically simplify dm's bio splitting code. Also, it's no longer necessary to save/restore the bvec array anymore - driver conversions for immutable bvecs are done, so drivers should never be modifying it. Also kill bio_sector_offset(), dm was the only user and it doesn't make much sense anymore. Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Alasdair Kergon Cc: dm-devel@redhat.com Reviewed-by: Mike Snitzer --- drivers/md/dm-bio-record.h | 25 ------- drivers/md/dm.c | 174 ++++++--------------------------------------- fs/bio.c | 72 ------------------- include/linux/bio.h | 2 - 4 files changed, 20 insertions(+), 253 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h index 4f46e8e528de..dd3646111561 100644 --- a/drivers/md/dm-bio-record.h +++ b/drivers/md/dm-bio-record.h @@ -17,49 +17,24 @@ * original bio state. */ -struct dm_bio_vec_details { -#if PAGE_SIZE < 65536 - __u16 bv_len; - __u16 bv_offset; -#else - unsigned bv_len; - unsigned bv_offset; -#endif -}; - struct dm_bio_details { struct block_device *bi_bdev; unsigned long bi_flags; struct bvec_iter bi_iter; - struct dm_bio_vec_details bi_io_vec[BIO_MAX_PAGES]; }; static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio) { - unsigned i; - bd->bi_bdev = bio->bi_bdev; bd->bi_flags = bio->bi_flags; bd->bi_iter = bio->bi_iter; - - for (i = 0; i < bio->bi_vcnt; i++) { - bd->bi_io_vec[i].bv_len = bio->bi_io_vec[i].bv_len; - bd->bi_io_vec[i].bv_offset = bio->bi_io_vec[i].bv_offset; - } } static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio) { - unsigned i; - bio->bi_bdev = bd->bi_bdev; bio->bi_flags = bd->bi_flags; bio->bi_iter = bd->bi_iter; - - for (i = 0; i < bio->bi_vcnt; i++) { - bio->bi_io_vec[i].bv_len = bd->bi_io_vec[i].bv_len; - bio->bi_io_vec[i].bv_offset = bd->bi_io_vec[i].bv_offset; - } } #endif diff --git a/drivers/md/dm.c b/drivers/md/dm.c index ccd064ea4fe6..44a2fa6814ce 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1155,7 +1155,6 @@ struct clone_info { struct dm_io *io; sector_t sector; sector_t sector_count; - unsigned short idx; }; static void bio_setup_sector(struct bio *bio, sector_t sector, sector_t len) @@ -1164,68 +1163,24 @@ static void bio_setup_sector(struct bio *bio, sector_t sector, sector_t len) bio->bi_iter.bi_size = to_bytes(len); } -static void bio_setup_bv(struct bio *bio, unsigned short idx, unsigned short bv_count) -{ - bio->bi_iter.bi_idx = idx; - bio->bi_vcnt = idx + bv_count; - bio->bi_flags &= ~(1 << BIO_SEG_VALID); -} - -static void clone_bio_integrity(struct bio *bio, struct bio *clone, - unsigned short idx, unsigned len, unsigned offset, - unsigned trim) -{ - if (!bio_integrity(bio)) - return; - - bio_integrity_clone(clone, bio, GFP_NOIO); - - if (trim) - bio_integrity_trim(clone, bio_sector_offset(bio, idx, offset), len); -} - -/* - * Creates a little bio that just does part of a bvec. - */ -static void clone_split_bio(struct dm_target_io *tio, struct bio *bio, - sector_t sector, unsigned short idx, - unsigned offset, unsigned len) -{ - struct bio *clone = &tio->clone; - struct bio_vec *bv = bio->bi_io_vec + idx; - - *clone->bi_io_vec = *bv; - - bio_setup_sector(clone, sector, len); - - clone->bi_bdev = bio->bi_bdev; - clone->bi_rw = bio->bi_rw; - clone->bi_vcnt = 1; - clone->bi_io_vec->bv_offset = offset; - clone->bi_io_vec->bv_len = clone->bi_iter.bi_size; - clone->bi_flags |= 1 << BIO_CLONED; - - clone_bio_integrity(bio, clone, idx, len, offset, 1); -} - /* * Creates a bio that consists of range of complete bvecs. */ static void clone_bio(struct dm_target_io *tio, struct bio *bio, - sector_t sector, unsigned short idx, - unsigned short bv_count, unsigned len) + sector_t sector, unsigned len) { struct bio *clone = &tio->clone; - unsigned trim = 0; - __bio_clone(clone, bio); - bio_setup_sector(clone, sector, len); - bio_setup_bv(clone, idx, bv_count); + __bio_clone_fast(clone, bio); + + if (bio_integrity(bio)) + bio_integrity_clone(clone, bio, GFP_NOIO); + + bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector)); + clone->bi_iter.bi_size = to_bytes(len); - if (idx != bio->bi_iter.bi_idx || - clone->bi_iter.bi_size < bio->bi_iter.bi_size) - trim = 1; - clone_bio_integrity(bio, clone, idx, len, 0, trim); + if (bio_integrity(bio)) + bio_integrity_trim(clone, 0, len); } static struct dm_target_io *alloc_tio(struct clone_info *ci, @@ -1258,7 +1213,7 @@ static void __clone_and_map_simple_bio(struct clone_info *ci, * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush * and discard, so no need for concern about wasted bvec allocations. */ - __bio_clone(clone, ci->bio); + __bio_clone_fast(clone, ci->bio); if (len) bio_setup_sector(clone, ci->sector, len); @@ -1287,10 +1242,7 @@ static int __send_empty_flush(struct clone_info *ci) } static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti, - sector_t sector, int nr_iovecs, - unsigned short idx, unsigned short bv_count, - unsigned offset, unsigned len, - unsigned split_bvec) + sector_t sector, unsigned len) { struct bio *bio = ci->bio; struct dm_target_io *tio; @@ -1304,11 +1256,8 @@ static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti num_target_bios = ti->num_write_bios(ti, bio); for (target_bio_nr = 0; target_bio_nr < num_target_bios; target_bio_nr++) { - tio = alloc_tio(ci, ti, nr_iovecs, target_bio_nr); - if (split_bvec) - clone_split_bio(tio, bio, sector, idx, offset, len); - else - clone_bio(tio, bio, sector, idx, bv_count, len); + tio = alloc_tio(ci, ti, 0, target_bio_nr); + clone_bio(tio, bio, sector, len); __map_bio(tio); } } @@ -1379,60 +1328,6 @@ static int __send_write_same(struct clone_info *ci) return __send_changing_extent_only(ci, get_num_write_same_bios, NULL); } -/* - * Find maximum number of sectors / bvecs we can process with a single bio. - */ -static sector_t __len_within_target(struct clone_info *ci, sector_t max, int *idx) -{ - struct bio *bio = ci->bio; - sector_t bv_len, total_len = 0; - - for (*idx = ci->idx; max && (*idx < bio->bi_vcnt); (*idx)++) { - bv_len = to_sector(bio->bi_io_vec[*idx].bv_len); - - if (bv_len > max) - break; - - max -= bv_len; - total_len += bv_len; - } - - return total_len; -} - -static int __split_bvec_across_targets(struct clone_info *ci, - struct dm_target *ti, sector_t max) -{ - struct bio *bio = ci->bio; - struct bio_vec *bv = bio->bi_io_vec + ci->idx; - sector_t remaining = to_sector(bv->bv_len); - unsigned offset = 0; - sector_t len; - - do { - if (offset) { - ti = dm_table_find_target(ci->map, ci->sector); - if (!dm_target_is_valid(ti)) - return -EIO; - - max = max_io_len(ci->sector, ti); - } - - len = min(remaining, max); - - __clone_and_map_data_bio(ci, ti, ci->sector, 1, ci->idx, 0, - bv->bv_offset + offset, len, 1); - - ci->sector += len; - ci->sector_count -= len; - offset += to_bytes(len); - } while (remaining -= len); - - ci->idx++; - - return 0; -} - /* * Select the correct strategy for processing a non-flush bio. */ @@ -1440,8 +1335,7 @@ static int __split_and_process_non_flush(struct clone_info *ci) { struct bio *bio = ci->bio; struct dm_target *ti; - sector_t len, max; - int idx; + unsigned len; if (unlikely(bio->bi_rw & REQ_DISCARD)) return __send_discard(ci); @@ -1452,41 +1346,14 @@ static int __split_and_process_non_flush(struct clone_info *ci) if (!dm_target_is_valid(ti)) return -EIO; - max = max_io_len(ci->sector, ti); - - /* - * Optimise for the simple case where we can do all of - * the remaining io with a single clone. - */ - if (ci->sector_count <= max) { - __clone_and_map_data_bio(ci, ti, ci->sector, bio->bi_max_vecs, - ci->idx, bio->bi_vcnt - ci->idx, 0, - ci->sector_count, 0); - ci->sector_count = 0; - return 0; - } - - /* - * There are some bvecs that don't span targets. - * Do as many of these as possible. - */ - if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { - len = __len_within_target(ci, max, &idx); - - __clone_and_map_data_bio(ci, ti, ci->sector, bio->bi_max_vecs, - ci->idx, idx - ci->idx, 0, len, 0); + len = min_t(sector_t, max_io_len(ci->sector, ti), ci->sector_count); - ci->sector += len; - ci->sector_count -= len; - ci->idx = idx; + __clone_and_map_data_bio(ci, ti, ci->sector, len); - return 0; - } + ci->sector += len; + ci->sector_count -= len; - /* - * Handle a bvec that must be split between two or more targets. - */ - return __split_bvec_across_targets(ci, ti, max); + return 0; } /* @@ -1512,7 +1379,6 @@ static void __split_and_process_bio(struct mapped_device *md, ci.io->md = md; spin_lock_init(&ci.io->endio_lock); ci.sector = bio->bi_iter.bi_sector; - ci.idx = bio->bi_iter.bi_idx; start_io_acct(ci.io); diff --git a/fs/bio.c b/fs/bio.c index 00dc1893c6ee..6e42b68ab0ac 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -514,40 +514,6 @@ inline int bio_phys_segments(struct request_queue *q, struct bio *bio) } EXPORT_SYMBOL(bio_phys_segments); -/** - * __bio_clone - clone a bio - * @bio: destination bio - * @bio_src: bio to clone - * - * Clone a &bio. Caller will own the returned bio, but not - * the actual data it points to. Reference count of returned - * bio will be one. - */ -void __bio_clone(struct bio *bio, struct bio *bio_src) -{ - if (bio_is_rw(bio_src)) { - struct bio_vec bv; - struct bvec_iter iter; - - bio_for_each_segment(bv, bio_src, iter) - bio->bi_io_vec[bio->bi_vcnt++] = bv; - } else if (bio_has_data(bio_src)) { - memcpy(bio->bi_io_vec, bio_src->bi_io_vec, - bio_src->bi_max_vecs * sizeof(struct bio_vec)); - bio->bi_vcnt = bio_src->bi_vcnt; - } - - /* - * most users will be overriding ->bi_bdev with a new target, - * so we don't set nor calculate new physical/hw segment counts here - */ - bio->bi_bdev = bio_src->bi_bdev; - bio->bi_flags |= 1 << BIO_CLONED; - bio->bi_rw = bio_src->bi_rw; - bio->bi_iter = bio_src->bi_iter; -} -EXPORT_SYMBOL(__bio_clone); - /** * __bio_clone_fast - clone a bio that shares the original bio's biovec * @bio: destination bio @@ -1921,44 +1887,6 @@ void bio_trim(struct bio *bio, int offset, int size) } EXPORT_SYMBOL_GPL(bio_trim); -/** - * bio_sector_offset - Find hardware sector offset in bio - * @bio: bio to inspect - * @index: bio_vec index - * @offset: offset in bv_page - * - * Return the number of hardware sectors between beginning of bio - * and an end point indicated by a bio_vec index and an offset - * within that vector's page. - */ -sector_t bio_sector_offset(struct bio *bio, unsigned short index, - unsigned int offset) -{ - unsigned int sector_sz; - struct bio_vec *bv; - sector_t sectors; - int i; - - sector_sz = queue_logical_block_size(bio->bi_bdev->bd_disk->queue); - sectors = 0; - - if (index >= bio->bi_iter.bi_idx) - index = bio->bi_vcnt - 1; - - bio_for_each_segment_all(bv, bio, i) { - if (i == index) { - if (offset > bv->bv_offset) - sectors += (offset - bv->bv_offset) / sector_sz; - break; - } - - sectors += bv->bv_len / sector_sz; - } - - return sectors; -} -EXPORT_SYMBOL(bio_sector_offset); - /* * create memory pools for biovec's in a bio_set. * use the global biovec slabs created for general use. diff --git a/include/linux/bio.h b/include/linux/bio.h index 1f83f4a3083e..0c32a45a419c 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -330,7 +330,6 @@ extern void bio_put(struct bio *); extern void __bio_clone_fast(struct bio *, struct bio *); extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *); -extern void __bio_clone(struct bio *, struct bio *); extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); extern struct bio_set *fs_bio_set; @@ -370,7 +369,6 @@ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, unsigned int, unsigned int); extern int bio_get_nr_vecs(struct block_device *); -extern sector_t bio_sector_offset(struct bio *, unsigned short, unsigned int); extern struct bio *bio_map_user(struct request_queue *, struct block_device *, unsigned long, unsigned int, int, gfp_t); struct sg_iovec; -- cgit v1.2.3 From e90abc8ec323c1fd2a25600097ef7ae1e91f39b0 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 7 Aug 2013 14:31:42 -0700 Subject: block: Remove bi_idx hacks Now that drivers have been converted to the new bvec_iter primitives, there's no need to trim the bvec before we submit it; and we can't trim it once we start sharing bvecs. It used to be that passing a partially completed bio (i.e. one with nonzero bi_idx) to generic_make_request() was a dangerous thing - various drivers would choke on such things. But with immutable biovecs and our new bio splitting that shares the biovecs, submitting partially completed bios has to work (and should work, now that all the drivers have been completed to the new primitives) Signed-off-by: Kent Overstreet Cc: Jens Axboe --- drivers/md/bcache/io.c | 47 ++--------------------------------------------- fs/bio.c | 23 ----------------------- 2 files changed, 2 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 6e04f3bb0286..0f0ab659914d 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -11,49 +11,6 @@ #include -static void bch_bi_idx_hack_endio(struct bio *bio, int error) -{ - struct bio *p = bio->bi_private; - - bio_endio(p, error); - bio_put(bio); -} - -static void bch_generic_make_request_hack(struct bio *bio) -{ - if (bio->bi_iter.bi_idx) { - struct bio_vec bv; - struct bvec_iter iter; - unsigned segs = bio_segments(bio); - struct bio *clone = bio_alloc(GFP_NOIO, segs); - - bio_for_each_segment(bv, bio, iter) - clone->bi_io_vec[clone->bi_vcnt++] = bv; - - clone->bi_iter.bi_sector = bio->bi_iter.bi_sector; - clone->bi_bdev = bio->bi_bdev; - clone->bi_rw = bio->bi_rw; - clone->bi_vcnt = segs; - clone->bi_iter.bi_size = bio->bi_iter.bi_size; - - clone->bi_private = bio; - clone->bi_end_io = bch_bi_idx_hack_endio; - - bio = clone; - } - - /* - * Hack, since drivers that clone bios clone up to bi_max_vecs, but our - * bios might have had more than that (before we split them per device - * limitations). - * - * To be taken out once immutable bvec stuff is in. - */ - bio->bi_max_vecs = bio->bi_vcnt; - - generic_make_request(bio); -} - /** * bch_bio_split - split a bio * @bio: bio to split @@ -222,12 +179,12 @@ void bch_generic_make_request(struct bio *bio, struct bio_split_pool *p) n->bi_private = &s->cl; closure_get(&s->cl); - bch_generic_make_request_hack(n); + generic_make_request(n); } while (n != bio); continue_at(&s->cl, bch_bio_submit_split_done, NULL); submit: - bch_generic_make_request_hack(bio); + generic_make_request(bio); } /* Bios with headers */ diff --git a/fs/bio.c b/fs/bio.c index 9cff939b1bc6..e6dfa06773ac 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1822,11 +1822,7 @@ void bio_trim(struct bio *bio, int offset, int size) { /* 'bio' is a cloned bio which we need to trim to match * the given offset and size. - * This requires adjusting bi_sector, bi_size, and bi_io_vec */ - int i; - struct bio_vec *bvec; - int sofar = 0; size <<= 9; if (offset == 0 && size == bio->bi_iter.bi_size) @@ -1837,25 +1833,6 @@ void bio_trim(struct bio *bio, int offset, int size) bio_advance(bio, offset << 9); bio->bi_iter.bi_size = size; - - /* avoid any complications with bi_idx being non-zero*/ - if (bio->bi_iter.bi_idx) { - memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_iter.bi_idx, - (bio->bi_vcnt - bio->bi_iter.bi_idx) * - sizeof(struct bio_vec)); - bio->bi_vcnt -= bio->bi_iter.bi_idx; - bio->bi_iter.bi_idx = 0; - } - /* Make sure vcnt and last bv are not too big */ - bio_for_each_segment_all(bvec, bio, i) { - if (sofar + bvec->bv_len > size) - bvec->bv_len = size - sofar; - if (bvec->bv_len == 0) { - bio->bi_vcnt = i; - break; - } - sofar += bvec->bv_len; - } } EXPORT_SYMBOL_GPL(bio_trim); -- cgit v1.2.3 From 196d38bccfcfa32faed8c561868336fdfa0fe8e4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 23 Nov 2013 18:34:15 -0800 Subject: block: Generic bio chaining This adds a generic mechanism for chaining bio completions. This is going to be used for a bio_split() replacement, and it turns out to be very useful in a fair amount of driver code - a fair number of drivers were implementing this in their own roundabout ways, often painfully. Note that this means it's no longer to call bio_endio() more than once on the same bio! This can cause problems for drivers that save/restore bi_end_io. Arguably they shouldn't be saving/restoring bi_end_io at all - in all but the simplest cases they'd be better off just cloning the bio, and immutable biovecs is making bio cloning cheaper. But for now, we add a bio_endio_nodec() for these cases. Signed-off-by: Kent Overstreet Cc: Jens Axboe --- drivers/md/bcache/io.c | 2 +- drivers/md/dm-cache-target.c | 6 ++++ drivers/md/dm-snap.c | 1 + drivers/md/dm-thin.c | 8 +++-- drivers/md/dm-verity.c | 2 +- fs/bio-integrity.c | 2 +- fs/bio.c | 76 ++++++++++++++++++++++++++++++++++++++++---- include/linux/bio.h | 2 ++ include/linux/blk_types.h | 2 ++ 9 files changed, 90 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 0f0ab659914d..522f95778443 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -133,7 +133,7 @@ static void bch_bio_submit_split_done(struct closure *cl) s->bio->bi_end_io = s->bi_end_io; s->bio->bi_private = s->bi_private; - bio_endio(s->bio, 0); + bio_endio_nodec(s->bio, 0); closure_debug_destroy(&s->cl); mempool_free(s, s->p->bio_split_hook); diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 86f9c83eb30c..bf3a206abd78 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -765,6 +765,12 @@ static void writethrough_endio(struct bio *bio, int err) dm_unhook_bio(&pb->hook_info, bio); + /* + * Must bump bi_remaining to allow bio to complete with + * restored bi_end_io. + */ + atomic_inc(&bio->bi_remaining); + if (err) { bio_endio(bio, err); return; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 3ded8c729dfb..80b5cabbea29 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1415,6 +1415,7 @@ out: if (full_bio) { full_bio->bi_end_io = pe->full_bio_end_io; full_bio->bi_private = pe->full_bio_private; + atomic_inc(&full_bio->bi_remaining); } free_pending_exception(pe); diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index a65402480c8c..1abb4a24c338 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -611,8 +611,10 @@ static void cell_defer_no_holder(struct thin_c *tc, struct dm_bio_prison_cell *c static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m) { - if (m->bio) + if (m->bio) { m->bio->bi_end_io = m->saved_bi_end_io; + atomic_inc(&m->bio->bi_remaining); + } cell_error(m->tc->pool, m->cell); list_del(&m->list); mempool_free(m, m->tc->pool->mapping_pool); @@ -626,8 +628,10 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) int r; bio = m->bio; - if (bio) + if (bio) { bio->bi_end_io = m->saved_bi_end_io; + atomic_inc(&bio->bi_remaining); + } if (m->err) { cell_error(pool, m->cell); diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index ac35e959d49b..796007a5e0e1 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -385,7 +385,7 @@ static void verity_finish_io(struct dm_verity_io *io, int error) bio->bi_end_io = io->orig_bi_end_io; bio->bi_private = io->orig_bi_private; - bio_endio(bio, error); + bio_endio_nodec(bio, error); } static void verity_work(struct work_struct *w) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index fed744b8c9e5..9d547d2e357c 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -502,7 +502,7 @@ static void bio_integrity_verify_fn(struct work_struct *work) /* Restore original bio completion handler */ bio->bi_end_io = bip->bip_end_io; - bio_endio(bio, error); + bio_endio_nodec(bio, error); } /** diff --git a/fs/bio.c b/fs/bio.c index e6dfa06773ac..b0a16dbc71ef 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -273,6 +273,7 @@ void bio_init(struct bio *bio) { memset(bio, 0, sizeof(*bio)); bio->bi_flags = 1 << BIO_UPTODATE; + atomic_set(&bio->bi_remaining, 1); atomic_set(&bio->bi_cnt, 1); } EXPORT_SYMBOL(bio_init); @@ -295,9 +296,35 @@ void bio_reset(struct bio *bio) memset(bio, 0, BIO_RESET_BYTES); bio->bi_flags = flags|(1 << BIO_UPTODATE); + atomic_set(&bio->bi_remaining, 1); } EXPORT_SYMBOL(bio_reset); +static void bio_chain_endio(struct bio *bio, int error) +{ + bio_endio(bio->bi_private, error); + bio_put(bio); +} + +/** + * bio_chain - chain bio completions + * + * The caller won't have a bi_end_io called when @bio completes - instead, + * @parent's bi_end_io won't be called until both @parent and @bio have + * completed; the chained bio will also be freed when it completes. + * + * The caller must not set bi_private or bi_end_io in @bio. + */ +void bio_chain(struct bio *bio, struct bio *parent) +{ + BUG_ON(bio->bi_private || bio->bi_end_io); + + bio->bi_private = parent; + bio->bi_end_io = bio_chain_endio; + atomic_inc(&parent->bi_remaining); +} +EXPORT_SYMBOL(bio_chain); + static void bio_alloc_rescue(struct work_struct *work) { struct bio_set *bs = container_of(work, struct bio_set, rescue_work); @@ -1719,16 +1746,53 @@ EXPORT_SYMBOL(bio_flush_dcache_pages); **/ void bio_endio(struct bio *bio, int error) { - if (error) - clear_bit(BIO_UPTODATE, &bio->bi_flags); - else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - error = -EIO; + while (bio) { + BUG_ON(atomic_read(&bio->bi_remaining) <= 0); + + if (error) + clear_bit(BIO_UPTODATE, &bio->bi_flags); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + error = -EIO; + + if (!atomic_dec_and_test(&bio->bi_remaining)) + return; - if (bio->bi_end_io) - bio->bi_end_io(bio, error); + /* + * Need to have a real endio function for chained bios, + * otherwise various corner cases will break (like stacking + * block devices that save/restore bi_end_io) - however, we want + * to avoid unbounded recursion and blowing the stack. Tail call + * optimization would handle this, but compiling with frame + * pointers also disables gcc's sibling call optimization. + */ + if (bio->bi_end_io == bio_chain_endio) { + struct bio *parent = bio->bi_private; + bio_put(bio); + bio = parent; + } else { + if (bio->bi_end_io) + bio->bi_end_io(bio, error); + bio = NULL; + } + } } EXPORT_SYMBOL(bio_endio); +/** + * bio_endio_nodec - end I/O on a bio, without decrementing bi_remaining + * @bio: bio + * @error: error, if any + * + * For code that has saved and restored bi_end_io; thing hard before using this + * function, probably you should've cloned the entire bio. + **/ +void bio_endio_nodec(struct bio *bio, int error) +{ + atomic_inc(&bio->bi_remaining); + bio_endio(bio, error); +} +EXPORT_SYMBOL(bio_endio_nodec); + void bio_pair_release(struct bio_pair *bp) { if (atomic_dec_and_test(&bp->cnt)) { diff --git a/include/linux/bio.h b/include/linux/bio.h index 0c32a45a419c..64f5169c224b 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -356,6 +356,7 @@ static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask) } extern void bio_endio(struct bio *, int); +extern void bio_endio_nodec(struct bio *, int); struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); @@ -364,6 +365,7 @@ extern void bio_advance(struct bio *, unsigned); extern void bio_init(struct bio *); extern void bio_reset(struct bio *); +void bio_chain(struct bio *, struct bio *); extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index d369f8f6af79..bbc3a6c88fce 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -65,6 +65,8 @@ struct bio { unsigned int bi_seg_front_size; unsigned int bi_seg_back_size; + atomic_t bi_remaining; + bio_end_io_t *bi_end_io; void *bi_private; -- cgit v1.2.3 From ee67891bf132612feb7b999ee1f3350b40867cb4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 7 Aug 2013 14:32:45 -0700 Subject: block: Rename bio_split() -> bio_pair_split() This is prep work for introducing a more general bio_split(). Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: NeilBrown Cc: Alasdair Kergon Cc: Lars Ellenberg Cc: Peter Osterlund Cc: Sage Weil --- drivers/block/pktcdvd.c | 2 +- drivers/md/linear.c | 2 +- drivers/md/raid0.c | 6 +++--- drivers/md/raid10.c | 2 +- fs/bio.c | 4 ++-- include/linux/bio.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index ce986bacf7b7..28789b82ae7d 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2399,7 +2399,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) if (last_zone != zone) { BUG_ON(last_zone != zone + pd->settings.size); first_sectors = last_zone - bio->bi_iter.bi_sector; - bp = bio_split(bio, first_sectors); + bp = bio_pair_split(bio, first_sectors); BUG_ON(!bp); pkt_make_request(q, &bp->bio1); pkt_make_request(q, &bp->bio2); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index fb3b0d04edfb..e9b53e9793bf 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -326,7 +326,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) rcu_read_unlock(); - bp = bio_split(bio, end_sector - bio->bi_iter.bi_sector); + bp = bio_pair_split(bio, end_sector - bio->bi_iter.bi_sector); linear_make_request(mddev, &bp->bio1); linear_make_request(mddev, &bp->bio2); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 8ee1a6c658b4..ea754dd1a5f5 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -534,11 +534,11 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) * refuse to split for us, so we need to split it. */ if (likely(is_power_of_2(chunk_sects))) - bp = bio_split(bio, chunk_sects - (sector & + bp = bio_pair_split(bio, chunk_sects - (sector & (chunk_sects-1))); else - bp = bio_split(bio, chunk_sects - - sector_div(sector, chunk_sects)); + bp = bio_pair_split(bio, chunk_sects - + sector_div(sector, chunk_sects)); raid0_make_request(mddev, &bp->bio1); raid0_make_request(mddev, &bp->bio2); bio_pair_release(bp); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index ac4bfa438c57..69c1bc8da88f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1193,7 +1193,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. */ - bp = bio_split(bio, chunk_sects - + bp = bio_pair_split(bio, chunk_sects - (bio->bi_iter.bi_sector & (chunk_sects - 1))); /* Each of these 'make_request' calls will call 'wait_barrier'. diff --git a/fs/bio.c b/fs/bio.c index b0a16dbc71ef..a3e753f4d5a6 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1827,7 +1827,7 @@ static void bio_pair_end_2(struct bio *bi, int err) /* * split a bio - only worry about a bio with a single page in its iovec */ -struct bio_pair *bio_split(struct bio *bi, int first_sectors) +struct bio_pair *bio_pair_split(struct bio *bi, int first_sectors) { struct bio_pair *bp = mempool_alloc(bio_split_pool, GFP_NOIO); @@ -1874,7 +1874,7 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors) return bp; } -EXPORT_SYMBOL(bio_split); +EXPORT_SYMBOL(bio_pair_split); /** * bio_trim - trim a bio diff --git a/include/linux/bio.h b/include/linux/bio.h index 64f5169c224b..aa67af0b31ac 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -317,7 +317,7 @@ struct bio_pair { atomic_t cnt; int error; }; -extern struct bio_pair *bio_split(struct bio *bi, int first_sectors); +extern struct bio_pair *bio_pair_split(struct bio *bi, int first_sectors); extern void bio_pair_release(struct bio_pair *dbio); extern void bio_trim(struct bio *bio, int offset, int size); -- cgit v1.2.3 From 20d0189b1012a37d2533a87fb451f7852f2418d1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 23 Nov 2013 18:21:01 -0800 Subject: block: Introduce new bio_split() The new bio_split() can split arbitrary bios - it's not restricted to single page bios, like the old bio_split() (previously renamed to bio_pair_split()). It also has different semantics - it doesn't allocate a struct bio_pair, leaving it up to the caller to handle completions. Then convert the existing bio_pair_split() users to the new bio_split() - and also nvme, which was open coding bio splitting. (We have to take that BUG_ON() out of bio_integrity_trim() because this bio_split() needs to use it, and there's no reason it has to be used on bios marked as cloned; BIO_CLONED doesn't seem to have clearly documented semantics anyways.) Signed-off-by: Kent Overstreet Cc: Jens Axboe Cc: Martin K. Petersen Cc: Matthew Wilcox Cc: Keith Busch Cc: Vishal Verma Cc: Jiri Kosina Cc: Neil Brown --- drivers/block/nvme-core.c | 106 +++------------------------------- drivers/block/pktcdvd.c | 136 ++++++++++++++++++++++++-------------------- drivers/md/bcache/bcache.h | 1 - drivers/md/bcache/io.c | 82 +------------------------- drivers/md/bcache/request.c | 12 ++-- drivers/md/linear.c | 96 +++++++++++++++---------------- drivers/md/raid0.c | 77 +++++++++---------------- drivers/md/raid10.c | 113 +++++++++++++++--------------------- fs/bio.c | 36 ++++++++++++ include/linux/bio.h | 22 +++++++ 10 files changed, 272 insertions(+), 409 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 5539d2920872..1f14ac403945 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -441,104 +441,19 @@ int nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd, return total_len; } -struct nvme_bio_pair { - struct bio b1, b2, *parent; - struct bio_vec *bv1, *bv2; - int err; - atomic_t cnt; -}; - -static void nvme_bio_pair_endio(struct bio *bio, int err) -{ - struct nvme_bio_pair *bp = bio->bi_private; - - if (err) - bp->err = err; - - if (atomic_dec_and_test(&bp->cnt)) { - bio_endio(bp->parent, bp->err); - kfree(bp->bv1); - kfree(bp->bv2); - kfree(bp); - } -} - -static struct nvme_bio_pair *nvme_bio_split(struct bio *bio, int idx, - int len, int offset) -{ - struct nvme_bio_pair *bp; - - BUG_ON(len > bio->bi_iter.bi_size); - BUG_ON(idx > bio->bi_vcnt); - - bp = kmalloc(sizeof(*bp), GFP_ATOMIC); - if (!bp) - return NULL; - bp->err = 0; - - bp->b1 = *bio; - bp->b2 = *bio; - - bp->b1.bi_iter.bi_size = len; - bp->b2.bi_iter.bi_size -= len; - bp->b1.bi_vcnt = idx; - bp->b2.bi_iter.bi_idx = idx; - bp->b2.bi_iter.bi_sector += len >> 9; - - if (offset) { - bp->bv1 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec), - GFP_ATOMIC); - if (!bp->bv1) - goto split_fail_1; - - bp->bv2 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec), - GFP_ATOMIC); - if (!bp->bv2) - goto split_fail_2; - - memcpy(bp->bv1, bio->bi_io_vec, - bio->bi_max_vecs * sizeof(struct bio_vec)); - memcpy(bp->bv2, bio->bi_io_vec, - bio->bi_max_vecs * sizeof(struct bio_vec)); - - bp->b1.bi_io_vec = bp->bv1; - bp->b2.bi_io_vec = bp->bv2; - bp->b2.bi_io_vec[idx].bv_offset += offset; - bp->b2.bi_io_vec[idx].bv_len -= offset; - bp->b1.bi_io_vec[idx].bv_len = offset; - bp->b1.bi_vcnt++; - } else - bp->bv1 = bp->bv2 = NULL; - - bp->b1.bi_private = bp; - bp->b2.bi_private = bp; - - bp->b1.bi_end_io = nvme_bio_pair_endio; - bp->b2.bi_end_io = nvme_bio_pair_endio; - - bp->parent = bio; - atomic_set(&bp->cnt, 2); - - return bp; - - split_fail_2: - kfree(bp->bv1); - split_fail_1: - kfree(bp); - return NULL; -} - static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq, - int idx, int len, int offset) + int len) { - struct nvme_bio_pair *bp = nvme_bio_split(bio, idx, len, offset); - if (!bp) + struct bio *split = bio_split(bio, len >> 9, GFP_ATOMIC, NULL); + if (!split) return -ENOMEM; + bio_chain(split, bio); + if (bio_list_empty(&nvmeq->sq_cong)) add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait); - bio_list_add(&nvmeq->sq_cong, &bp->b1); - bio_list_add(&nvmeq->sq_cong, &bp->b2); + bio_list_add(&nvmeq->sq_cong, split); + bio_list_add(&nvmeq->sq_cong, bio); return 0; } @@ -568,8 +483,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, } else { if (!first && BIOVEC_NOT_VIRT_MERGEABLE(&bvprv, &bvec)) return nvme_split_and_submit(bio, nvmeq, - iter.bi_idx, - length, 0); + length); sg = sg ? sg + 1 : iod->sg; sg_set_page(sg, bvec.bv_page, @@ -578,9 +492,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, } if (split_len - length < bvec.bv_len) - return nvme_split_and_submit(bio, nvmeq, iter.bi_idx, - split_len, - split_len - length); + return nvme_split_and_submit(bio, nvmeq, split_len); length += bvec.bv_len; bvprv = bvec; first = 0; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 28789b82ae7d..3dda09a5ec41 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2338,75 +2338,29 @@ static void pkt_end_io_read_cloned(struct bio *bio, int err) pkt_bio_finished(pd); } -static void pkt_make_request(struct request_queue *q, struct bio *bio) +static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio) { - struct pktcdvd_device *pd; - char b[BDEVNAME_SIZE]; + struct bio *cloned_bio = bio_clone(bio, GFP_NOIO); + struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO); + + psd->pd = pd; + psd->bio = bio; + cloned_bio->bi_bdev = pd->bdev; + cloned_bio->bi_private = psd; + cloned_bio->bi_end_io = pkt_end_io_read_cloned; + pd->stats.secs_r += bio_sectors(bio); + pkt_queue_bio(pd, cloned_bio); +} + +static void pkt_make_request_write(struct request_queue *q, struct bio *bio) +{ + struct pktcdvd_device *pd = q->queuedata; sector_t zone; struct packet_data *pkt; int was_empty, blocked_bio; struct pkt_rb_node *node; - pd = q->queuedata; - if (!pd) { - pr_err("%s incorrect request queue\n", - bdevname(bio->bi_bdev, b)); - goto end_io; - } - - /* - * Clone READ bios so we can have our own bi_end_io callback. - */ - if (bio_data_dir(bio) == READ) { - struct bio *cloned_bio = bio_clone(bio, GFP_NOIO); - struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO); - - psd->pd = pd; - psd->bio = bio; - cloned_bio->bi_bdev = pd->bdev; - cloned_bio->bi_private = psd; - cloned_bio->bi_end_io = pkt_end_io_read_cloned; - pd->stats.secs_r += bio_sectors(bio); - pkt_queue_bio(pd, cloned_bio); - return; - } - - if (!test_bit(PACKET_WRITABLE, &pd->flags)) { - pkt_notice(pd, "WRITE for ro device (%llu)\n", - (unsigned long long)bio->bi_iter.bi_sector); - goto end_io; - } - - if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { - pkt_err(pd, "wrong bio size\n"); - goto end_io; - } - - blk_queue_bounce(q, &bio); - zone = get_zone(bio->bi_iter.bi_sector, pd); - pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", - (unsigned long long)bio->bi_iter.bi_sector, - (unsigned long long)bio_end_sector(bio)); - - /* Check if we have to split the bio */ - { - struct bio_pair *bp; - sector_t last_zone; - int first_sectors; - - last_zone = get_zone(bio_end_sector(bio) - 1, pd); - if (last_zone != zone) { - BUG_ON(last_zone != zone + pd->settings.size); - first_sectors = last_zone - bio->bi_iter.bi_sector; - bp = bio_pair_split(bio, first_sectors); - BUG_ON(!bp); - pkt_make_request(q, &bp->bio1); - pkt_make_request(q, &bp->bio2); - bio_pair_release(bp); - return; - } - } /* * If we find a matching packet in state WAITING or READ_WAIT, we can @@ -2480,6 +2434,64 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) */ wake_up(&pd->wqueue); } +} + +static void pkt_make_request(struct request_queue *q, struct bio *bio) +{ + struct pktcdvd_device *pd; + char b[BDEVNAME_SIZE]; + struct bio *split; + + pd = q->queuedata; + if (!pd) { + pr_err("%s incorrect request queue\n", + bdevname(bio->bi_bdev, b)); + goto end_io; + } + + pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", + (unsigned long long)bio->bi_iter.bi_sector, + (unsigned long long)bio_end_sector(bio)); + + /* + * Clone READ bios so we can have our own bi_end_io callback. + */ + if (bio_data_dir(bio) == READ) { + pkt_make_request_read(pd, bio); + return; + } + + if (!test_bit(PACKET_WRITABLE, &pd->flags)) { + pkt_notice(pd, "WRITE for ro device (%llu)\n", + (unsigned long long)bio->bi_iter.bi_sector); + goto end_io; + } + + if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { + pkt_err(pd, "wrong bio size\n"); + goto end_io; + } + + blk_queue_bounce(q, &bio); + + do { + sector_t zone = get_zone(bio->bi_iter.bi_sector, pd); + sector_t last_zone = get_zone(bio_end_sector(bio) - 1, pd); + + if (last_zone != zone) { + BUG_ON(last_zone != zone + pd->settings.size); + + split = bio_split(bio, last_zone - + bio->bi_iter.bi_sector, + GFP_NOIO, fs_bio_set); + bio_chain(split, bio); + } else { + split = bio; + } + + pkt_make_request_write(q, split); + } while (split != bio); + return; end_io: bio_io_error(bio); diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 6b6fe935be73..964353c5329d 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -901,7 +901,6 @@ void bch_bbio_endio(struct cache_set *, struct bio *, int, const char *); void bch_bbio_free(struct bio *, struct cache_set *); struct bio *bch_bbio_alloc(struct cache_set *); -struct bio *bch_bio_split(struct bio *, int, gfp_t, struct bio_set *); void bch_generic_make_request(struct bio *, struct bio_split_pool *); void __bch_submit_bbio(struct bio *, struct cache_set *); void bch_submit_bbio(struct bio *, struct cache_set *, struct bkey *, unsigned); diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 522f95778443..fa028fa82df4 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -11,84 +11,6 @@ #include -/** - * bch_bio_split - split a bio - * @bio: bio to split - * @sectors: number of sectors to split from the front of @bio - * @gfp: gfp mask - * @bs: bio set to allocate from - * - * Allocates and returns a new bio which represents @sectors from the start of - * @bio, and updates @bio to represent the remaining sectors. - * - * If bio_sectors(@bio) was less than or equal to @sectors, returns @bio - * unchanged. - * - * The newly allocated bio will point to @bio's bi_io_vec, if the split was on a - * bvec boundry; it is the caller's responsibility to ensure that @bio is not - * freed before the split. - */ -struct bio *bch_bio_split(struct bio *bio, int sectors, - gfp_t gfp, struct bio_set *bs) -{ - unsigned vcnt = 0, nbytes = sectors << 9; - struct bio_vec bv; - struct bvec_iter iter; - struct bio *ret = NULL; - - BUG_ON(sectors <= 0); - - if (sectors >= bio_sectors(bio)) - return bio; - - if (bio->bi_rw & REQ_DISCARD) { - ret = bio_alloc_bioset(gfp, 1, bs); - if (!ret) - return NULL; - goto out; - } - - bio_for_each_segment(bv, bio, iter) { - vcnt++; - - if (nbytes <= bv.bv_len) - break; - - nbytes -= bv.bv_len; - } - - ret = bio_alloc_bioset(gfp, vcnt, bs); - if (!ret) - return NULL; - - bio_for_each_segment(bv, bio, iter) { - ret->bi_io_vec[ret->bi_vcnt++] = bv; - - if (ret->bi_vcnt == vcnt) - break; - } - - ret->bi_io_vec[ret->bi_vcnt - 1].bv_len = nbytes; -out: - ret->bi_bdev = bio->bi_bdev; - ret->bi_iter.bi_sector = bio->bi_iter.bi_sector; - ret->bi_iter.bi_size = sectors << 9; - ret->bi_rw = bio->bi_rw; - - if (bio_integrity(bio)) { - if (bio_integrity_clone(ret, bio, gfp)) { - bio_put(ret); - return NULL; - } - - bio_integrity_trim(ret, 0, bio_sectors(ret)); - } - - bio_advance(bio, ret->bi_iter.bi_size); - - return ret; -} - static unsigned bch_bio_max_sectors(struct bio *bio) { struct request_queue *q = bdev_get_queue(bio->bi_bdev); @@ -172,8 +94,8 @@ void bch_generic_make_request(struct bio *bio, struct bio_split_pool *p) bio_get(bio); do { - n = bch_bio_split(bio, bch_bio_max_sectors(bio), - GFP_NOIO, s->p->bio_split); + n = bio_next_split(bio, bch_bio_max_sectors(bio), + GFP_NOIO, s->p->bio_split); n->bi_end_io = bch_bio_submit_split_endio; n->bi_private = &s->cl; diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 63451c724781..5878cdb39529 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -371,7 +371,7 @@ static void bch_data_insert_start(struct closure *cl) op->writeback)) goto err; - n = bch_bio_split(bio, KEY_SIZE(k), GFP_NOIO, split); + n = bio_next_split(bio, KEY_SIZE(k), GFP_NOIO, split); n->bi_end_io = bch_data_insert_endio; n->bi_private = cl; @@ -679,9 +679,9 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k) if (KEY_DIRTY(k)) s->read_dirty_data = true; - n = bch_bio_split(bio, min_t(uint64_t, INT_MAX, - KEY_OFFSET(k) - bio->bi_iter.bi_sector), - GFP_NOIO, s->d->bio_split); + n = bio_next_split(bio, min_t(uint64_t, INT_MAX, + KEY_OFFSET(k) - bio->bi_iter.bi_sector), + GFP_NOIO, s->d->bio_split); bio_key = &container_of(n, struct bbio, bio)->key; bch_bkey_copy_single_ptr(bio_key, k, ptr); @@ -920,7 +920,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s, struct bio *miss, *cache_bio; if (s->cache_miss || s->iop.bypass) { - miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split); + miss = bio_next_split(bio, sectors, GFP_NOIO, s->d->bio_split); ret = miss == bio ? MAP_DONE : MAP_CONTINUE; goto out_submit; } @@ -943,7 +943,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s, s->iop.replace = true; - miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split); + miss = bio_next_split(bio, sectors, GFP_NOIO, s->d->bio_split); /* btree_search_recurse()'s btree iterator is no good anymore */ ret = miss == bio ? MAP_DONE : -EINTR; diff --git a/drivers/md/linear.c b/drivers/md/linear.c index e9b53e9793bf..56f534b4a2d2 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -288,65 +288,65 @@ static int linear_stop (struct mddev *mddev) static void linear_make_request(struct mddev *mddev, struct bio *bio) { + char b[BDEVNAME_SIZE]; struct dev_info *tmp_dev; - sector_t start_sector; + struct bio *split; + sector_t start_sector, end_sector, data_offset; if (unlikely(bio->bi_rw & REQ_FLUSH)) { md_flush_request(mddev, bio); return; } - rcu_read_lock(); - tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); - start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; - - - if (unlikely(bio->bi_iter.bi_sector >= (tmp_dev->end_sector) - || (bio->bi_iter.bi_sector < start_sector))) { - char b[BDEVNAME_SIZE]; - - printk(KERN_ERR - "md/linear:%s: make_request: Sector %llu out of bounds on " - "dev %s: %llu sectors, offset %llu\n", - mdname(mddev), - (unsigned long long)bio->bi_iter.bi_sector, - bdevname(tmp_dev->rdev->bdev, b), - (unsigned long long)tmp_dev->rdev->sectors, - (unsigned long long)start_sector); - rcu_read_unlock(); - bio_io_error(bio); - return; - } - if (unlikely(bio_end_sector(bio) > tmp_dev->end_sector)) { - /* This bio crosses a device boundary, so we have to - * split it. - */ - struct bio_pair *bp; - sector_t end_sector = tmp_dev->end_sector; + do { + rcu_read_lock(); - rcu_read_unlock(); - - bp = bio_pair_split(bio, end_sector - bio->bi_iter.bi_sector); + tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); + start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; + end_sector = tmp_dev->end_sector; + data_offset = tmp_dev->rdev->data_offset; + bio->bi_bdev = tmp_dev->rdev->bdev; - linear_make_request(mddev, &bp->bio1); - linear_make_request(mddev, &bp->bio2); - bio_pair_release(bp); - return; - } - - bio->bi_bdev = tmp_dev->rdev->bdev; - bio->bi_iter.bi_sector = bio->bi_iter.bi_sector - start_sector - + tmp_dev->rdev->data_offset; - rcu_read_unlock(); + rcu_read_unlock(); - if (unlikely((bio->bi_rw & REQ_DISCARD) && - !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) { - /* Just ignore it */ - bio_endio(bio, 0); - return; - } + if (unlikely(bio->bi_iter.bi_sector >= end_sector || + bio->bi_iter.bi_sector < start_sector)) + goto out_of_bounds; + + if (unlikely(bio_end_sector(bio) > end_sector)) { + /* This bio crosses a device boundary, so we have to + * split it. + */ + split = bio_split(bio, end_sector - + bio->bi_iter.bi_sector, + GFP_NOIO, fs_bio_set); + bio_chain(split, bio); + } else { + split = bio; + } - generic_make_request(bio); + split->bi_iter.bi_sector = split->bi_iter.bi_sector - + start_sector + data_offset; + + if (unlikely((split->bi_rw & REQ_DISCARD) && + !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) { + /* Just ignore it */ + bio_endio(split, 0); + } else + generic_make_request(split); + } while (split != bio); + return; + +out_of_bounds: + printk(KERN_ERR + "md/linear:%s: make_request: Sector %llu out of bounds on " + "dev %s: %llu sectors, offset %llu\n", + mdname(mddev), + (unsigned long long)bio->bi_iter.bi_sector, + bdevname(tmp_dev->rdev->bdev, b), + (unsigned long long)tmp_dev->rdev->sectors, + (unsigned long long)start_sector); + bio_io_error(bio); } static void linear_status (struct seq_file *seq, struct mddev *mddev) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index ea754dd1a5f5..407a99e46f69 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -513,65 +513,44 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev, static void raid0_make_request(struct mddev *mddev, struct bio *bio) { - unsigned int chunk_sects; - sector_t sector_offset; struct strip_zone *zone; struct md_rdev *tmp_dev; + struct bio *split; if (unlikely(bio->bi_rw & REQ_FLUSH)) { md_flush_request(mddev, bio); return; } - chunk_sects = mddev->chunk_sectors; - if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) { + do { sector_t sector = bio->bi_iter.bi_sector; - struct bio_pair *bp; - /* Sanity check -- queue functions should prevent this happening */ - if (bio_multiple_segments(bio)) - goto bad_map; - /* This is a one page bio that upper layers - * refuse to split for us, so we need to split it. - */ - if (likely(is_power_of_2(chunk_sects))) - bp = bio_pair_split(bio, chunk_sects - (sector & - (chunk_sects-1))); - else - bp = bio_pair_split(bio, chunk_sects - - sector_div(sector, chunk_sects)); - raid0_make_request(mddev, &bp->bio1); - raid0_make_request(mddev, &bp->bio2); - bio_pair_release(bp); - return; - } - - sector_offset = bio->bi_iter.bi_sector; - zone = find_zone(mddev->private, §or_offset); - tmp_dev = map_sector(mddev, zone, bio->bi_iter.bi_sector, - §or_offset); - bio->bi_bdev = tmp_dev->bdev; - bio->bi_iter.bi_sector = sector_offset + zone->dev_start + - tmp_dev->data_offset; - - if (unlikely((bio->bi_rw & REQ_DISCARD) && - !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) { - /* Just ignore it */ - bio_endio(bio, 0); - return; - } - - generic_make_request(bio); - return; - -bad_map: - printk("md/raid0:%s: make_request bug: can't convert block across chunks" - " or bigger than %dk %llu %d\n", - mdname(mddev), chunk_sects / 2, - (unsigned long long)bio->bi_iter.bi_sector, - bio_sectors(bio) / 2); + unsigned chunk_sects = mddev->chunk_sectors; + + unsigned sectors = chunk_sects - + (likely(is_power_of_2(chunk_sects)) + ? (sector & (chunk_sects-1)) + : sector_div(sector, chunk_sects)); + + if (sectors < bio_sectors(bio)) { + split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set); + bio_chain(split, bio); + } else { + split = bio; + } - bio_io_error(bio); - return; + zone = find_zone(mddev->private, §or); + tmp_dev = map_sector(mddev, zone, sector, §or); + split->bi_bdev = tmp_dev->bdev; + split->bi_iter.bi_sector = sector + zone->dev_start + + tmp_dev->data_offset; + + if (unlikely((split->bi_rw & REQ_DISCARD) && + !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) { + /* Just ignore it */ + bio_endio(split, 0); + } else + generic_make_request(split); + } while (split != bio); } static void raid0_status(struct seq_file *seq, struct mddev *mddev) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 69c1bc8da88f..6d43d88657aa 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1152,14 +1152,12 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) kfree(plug); } -static void make_request(struct mddev *mddev, struct bio * bio) +static void __make_request(struct mddev *mddev, struct bio *bio) { struct r10conf *conf = mddev->private; struct r10bio *r10_bio; struct bio *read_bio; int i; - sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask); - int chunk_sects = chunk_mask + 1; const int rw = bio_data_dir(bio); const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); const unsigned long do_fua = (bio->bi_rw & REQ_FUA); @@ -1174,69 +1172,6 @@ static void make_request(struct mddev *mddev, struct bio * bio) int max_sectors; int sectors; - if (unlikely(bio->bi_rw & REQ_FLUSH)) { - md_flush_request(mddev, bio); - return; - } - - /* If this request crosses a chunk boundary, we need to - * split it. This will only happen for 1 PAGE (or less) requests. - */ - if (unlikely((bio->bi_iter.bi_sector & chunk_mask) + bio_sectors(bio) - > chunk_sects - && (conf->geo.near_copies < conf->geo.raid_disks - || conf->prev.near_copies < conf->prev.raid_disks))) { - struct bio_pair *bp; - /* Sanity check -- queue functions should prevent this happening */ - if (bio_multiple_segments(bio)) - goto bad_map; - /* This is a one page bio that upper layers - * refuse to split for us, so we need to split it. - */ - bp = bio_pair_split(bio, chunk_sects - - (bio->bi_iter.bi_sector & (chunk_sects - 1))); - - /* Each of these 'make_request' calls will call 'wait_barrier'. - * If the first succeeds but the second blocks due to the resync - * thread raising the barrier, we will deadlock because the - * IO to the underlying device will be queued in generic_make_request - * and will never complete, so will never reduce nr_pending. - * So increment nr_waiting here so no new raise_barriers will - * succeed, and so the second wait_barrier cannot block. - */ - spin_lock_irq(&conf->resync_lock); - conf->nr_waiting++; - spin_unlock_irq(&conf->resync_lock); - - make_request(mddev, &bp->bio1); - make_request(mddev, &bp->bio2); - - spin_lock_irq(&conf->resync_lock); - conf->nr_waiting--; - wake_up(&conf->wait_barrier); - spin_unlock_irq(&conf->resync_lock); - - bio_pair_release(bp); - return; - bad_map: - printk("md/raid10:%s: make_request bug: can't convert block across chunks" - " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2, - (unsigned long long)bio->bi_iter.bi_sector, - bio_sectors(bio) / 2); - - bio_io_error(bio); - return; - } - - md_write_start(mddev, bio); - - /* - * Register the new request and wait if the reconstruction - * thread has put up a bar for new requests. - * Continue immediately if no resync is active currently. - */ - wait_barrier(conf); - sectors = bio_sectors(bio); while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && bio->bi_iter.bi_sector < conf->reshape_progress && @@ -1600,6 +1535,52 @@ retry_write: goto retry_write; } one_write_done(r10_bio); +} + +static void make_request(struct mddev *mddev, struct bio *bio) +{ + struct r10conf *conf = mddev->private; + sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask); + int chunk_sects = chunk_mask + 1; + + struct bio *split; + + if (unlikely(bio->bi_rw & REQ_FLUSH)) { + md_flush_request(mddev, bio); + return; + } + + md_write_start(mddev, bio); + + /* + * Register the new request and wait if the reconstruction + * thread has put up a bar for new requests. + * Continue immediately if no resync is active currently. + */ + wait_barrier(conf); + + do { + + /* + * If this request crosses a chunk boundary, we need to split + * it. + */ + if (unlikely((bio->bi_iter.bi_sector & chunk_mask) + + bio_sectors(bio) > chunk_sects + && (conf->geo.near_copies < conf->geo.raid_disks + || conf->prev.near_copies < + conf->prev.raid_disks))) { + split = bio_split(bio, chunk_sects - + (bio->bi_iter.bi_sector & + (chunk_sects - 1)), + GFP_NOIO, fs_bio_set); + bio_chain(split, bio); + } else { + split = bio; + } + + __make_request(mddev, split); + } while (split != bio); /* In case raid10d snuck in to freeze_array */ wake_up(&conf->wait_barrier); diff --git a/fs/bio.c b/fs/bio.c index a3e753f4d5a6..7b062befac82 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1793,6 +1793,42 @@ void bio_endio_nodec(struct bio *bio, int error) } EXPORT_SYMBOL(bio_endio_nodec); +/** + * bio_split - split a bio + * @bio: bio to split + * @sectors: number of sectors to split from the front of @bio + * @gfp: gfp mask + * @bs: bio set to allocate from + * + * Allocates and returns a new bio which represents @sectors from the start of + * @bio, and updates @bio to represent the remaining sectors. + * + * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's + * responsibility to ensure that @bio is not freed before the split. + */ +struct bio *bio_split(struct bio *bio, int sectors, + gfp_t gfp, struct bio_set *bs) +{ + struct bio *split = NULL; + + BUG_ON(sectors <= 0); + BUG_ON(sectors >= bio_sectors(bio)); + + split = bio_clone_fast(bio, gfp, bs); + if (!split) + return NULL; + + split->bi_iter.bi_size = sectors << 9; + + if (bio_integrity(split)) + bio_integrity_trim(split, 0, sectors); + + bio_advance(bio, split->bi_iter.bi_size); + + return split; +} +EXPORT_SYMBOL(bio_split); + void bio_pair_release(struct bio_pair *bp) { if (atomic_dec_and_test(&bp->cnt)) { diff --git a/include/linux/bio.h b/include/linux/bio.h index aa67af0b31ac..19e31b2f5b2c 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -321,6 +321,28 @@ extern struct bio_pair *bio_pair_split(struct bio *bi, int first_sectors); extern void bio_pair_release(struct bio_pair *dbio); extern void bio_trim(struct bio *bio, int offset, int size); +extern struct bio *bio_split(struct bio *bio, int sectors, + gfp_t gfp, struct bio_set *bs); + +/** + * bio_next_split - get next @sectors from a bio, splitting if necessary + * @bio: bio to split + * @sectors: number of sectors to split from the front of @bio + * @gfp: gfp mask + * @bs: bio set to allocate from + * + * Returns a bio representing the next @sectors of @bio - if the bio is smaller + * than @sectors, returns the original bio unchanged. + */ +static inline struct bio *bio_next_split(struct bio *bio, int sectors, + gfp_t gfp, struct bio_set *bs) +{ + if (sectors >= bio_sectors(bio)) + return bio; + + return bio_split(bio, sectors, gfp, bs); +} + extern struct bio_set *bioset_create(unsigned int, unsigned int); extern void bioset_free(struct bio_set *); extern mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries); -- cgit v1.2.3 From e55bc55867585e6628359fd5496316576fe58a2f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 9 Nov 2013 13:18:01 +0100 Subject: irqchip: renesas-intc-irqpin: Fix register bitfield shift calculation The SENSE register bitfield position is incorrectly computed for SoCs that use 2-bit IRQ sense fields. Fix it. This has been tested on the Marzen (H1) and Bockw (M1) boards. This bug has been present since the renesas-intc-irqpin driver was introduced by 443580486e3b9657 ("irqchip: Renesas INTC External IRQ pin driver") in v3.10-rc1. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Tested-by: Simon Horman Signed-off-by: Simon Horman --- drivers/irqchip/irq-renesas-intc-irqpin.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 82cec63a9011..3ee78f02e5d7 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c @@ -149,8 +149,9 @@ static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p, static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p, int irq, int do_mask) { - int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */ - int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */ + /* The PRIO register is assumed to be 32-bit with fixed 4-bit fields. */ + int bitfield_width = 4; + int shift = 32 - (irq + 1) * bitfield_width; intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO, shift, bitfield_width, @@ -159,8 +160,9 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p, static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value) { + /* The SENSE register is assumed to be 32-bit. */ int bitfield_width = p->config.sense_bitfield_width; - int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */ + int shift = 32 - (irq + 1) * bitfield_width; dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value); -- cgit v1.2.3 From 7663cfd3f49f9e48e74fc2258b040d6828b20f0b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Nov 2013 10:50:24 +0300 Subject: bus: mvebu-mbus: potential forever loop in mvebu_mbus_init() "of_id->compatible" is an array and not a pointer so it can never be NULL. Signed-off-by: Dan Carpenter Acked-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- drivers/bus/mvebu-mbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 2394e9753ef5..c646a769e1f5 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -734,11 +734,11 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, { const struct of_device_id *of_id; - for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++) + for (of_id = of_mvebu_mbus_ids; of_id->compatible[0]; of_id++) if (!strcmp(of_id->compatible, soc)) break; - if (!of_id->compatible) { + if (!of_id->compatible[0]) { pr_err("could not find a matching SoC family\n"); return -ENODEV; } -- cgit v1.2.3 From 6930db1e989c79ce3d7b77609efffc4b5183fe4b Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Tue, 18 Jun 2013 13:30:13 +0300 Subject: regulator: tps51632: Get regulator name from i2c_client Commit "i2c: core: make it possible to match a pure device tree driver" changed semantics of the i2c probing for device tree devices. Device tree probed devices now get a NULL i2c_device_id pointer. This causes the regulator name to be set to NULL and the regulator registration to fail. Signed-off-by: Mikko Perttunen Signed-off-by: Mark Brown --- drivers/regulator/tps51632-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index b0a3f0917a27..3486be935bec 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -305,7 +305,7 @@ static int tps51632_probe(struct i2c_client *client, } tps->dev = &client->dev; - tps->desc.name = id->name; + tps->desc.name = client->name; tps->desc.id = 0; tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY; tps->desc.min_uV = TPS51632_MIN_VOLATGE; -- cgit v1.2.3 From bd60e381fab88979c3312265d18bb635c314d242 Mon Sep 17 00:00:00 2001 From: Cai Zhiyong Date: Mon, 18 Nov 2013 20:21:49 +0800 Subject: regmap: Fix 'ret' would return an uninitialized value This patch give a warning when calling regmap_register_patch with parameter num_regs <= 0. When the num_regs parameter is zero and krealloc doesn't fail, then the code would return an uninitialized value. However, calling this function with num_regs == 0, would be a waste as it essentially does nothing. Signed-off-by: Cai Zhiyong Reviewed-by: Geyslan G. Bem Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 9c021d9cace0..9a36ac14b0b5 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2173,6 +2173,10 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, int i, ret; bool bypass; + if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n", + num_regs)) + return 0; + map->lock(map->lock_arg); bypass = map->cache_bypass; -- cgit v1.2.3 From 71979aa3c431f0b2e00c4151f399813fceea6e0d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 15 Nov 2013 13:13:32 +0000 Subject: regulator: arizona-micsupp: Convert to use linear ranges Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 52 ++++++++----------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 724706a97dc4..3c75bf82eeb5 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -28,8 +28,6 @@ #include #include -#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f - struct arizona_micsupp { struct regulator_dev *regulator; struct arizona *arizona; @@ -40,42 +38,6 @@ struct arizona_micsupp { struct work_struct check_cp_work; }; -static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector > ARIZONA_MICSUPP_MAX_SELECTOR) - return -EINVAL; - - if (selector == ARIZONA_MICSUPP_MAX_SELECTOR) - return 3300000; - else - return (selector * 50000) + 1700000; -} - -static int arizona_micsupp_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - unsigned int voltage; - int selector; - - if (min_uV < 1700000) - min_uV = 1700000; - - if (min_uV > 3200000) - selector = ARIZONA_MICSUPP_MAX_SELECTOR; - else - selector = DIV_ROUND_UP(min_uV - 1700000, 50000); - - if (selector < 0) - return -EINVAL; - - voltage = arizona_micsupp_list_voltage(rdev, selector); - if (voltage < min_uV || voltage > max_uV) - return -EINVAL; - - return selector; -} - static void arizona_micsupp_check_cp(struct work_struct *work) { struct arizona_micsupp *micsupp = @@ -145,8 +107,8 @@ static struct regulator_ops arizona_micsupp_ops = { .disable = arizona_micsupp_disable, .is_enabled = regulator_is_enabled_regmap, - .list_voltage = arizona_micsupp_list_voltage, - .map_voltage = arizona_micsupp_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -155,11 +117,16 @@ static struct regulator_ops arizona_micsupp_ops = { .set_bypass = arizona_micsupp_set_bypass, }; +static const struct regulator_linear_range arizona_micsupp_ranges[] = { + REGULATOR_LINEAR_RANGE(1700000, 0, 0x1e, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0), +}; + static const struct regulator_desc arizona_micsupp = { .name = "MICVDD", .supply_name = "CPVDD", .type = REGULATOR_VOLTAGE, - .n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1, + .n_voltages = 32, .ops = &arizona_micsupp_ops, .vsel_reg = ARIZONA_LDO2_CONTROL_1, @@ -169,6 +136,9 @@ static const struct regulator_desc arizona_micsupp = { .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, .bypass_mask = ARIZONA_CPMIC_BYPASS, + .linear_ranges = arizona_micsupp_ranges, + .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ranges), + .enable_time = 3000, .owner = THIS_MODULE, -- cgit v1.2.3 From 93227c801372522d6f667aac0de2cacc7995d8b9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Nov 2013 14:55:14 +0800 Subject: regulator: lp3972: Convert to devm_regulator_register Both num_regulators and **rdev are no longer required after this conversion, thus remove them from struct lp3972. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/lp3972.c | 41 ++++++----------------------------------- 1 file changed, 6 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 093e6f44ff8a..aea485afcc1a 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -22,8 +22,6 @@ struct lp3972 { struct device *dev; struct mutex io_lock; struct i2c_client *i2c; - int num_regulators; - struct regulator_dev **rdev; }; /* LP3972 Control Registers */ @@ -478,41 +476,27 @@ static int setup_regulators(struct lp3972 *lp3972, { int i, err; - lp3972->num_regulators = pdata->num_regulators; - lp3972->rdev = kcalloc(pdata->num_regulators, - sizeof(struct regulator_dev *), GFP_KERNEL); - if (!lp3972->rdev) { - err = -ENOMEM; - goto err_nomem; - } - /* Instantiate the regulators */ for (i = 0; i < pdata->num_regulators; i++) { struct lp3972_regulator_subdev *reg = &pdata->regulators[i]; struct regulator_config config = { }; + struct regulator_dev *rdev; config.dev = lp3972->dev; config.init_data = reg->initdata; config.driver_data = lp3972; - lp3972->rdev[i] = regulator_register(®ulators[reg->id], - &config); - if (IS_ERR(lp3972->rdev[i])) { - err = PTR_ERR(lp3972->rdev[i]); + rdev = devm_regulator_register(lp3972->dev, + ®ulators[reg->id], &config); + if (IS_ERR(rdev)) { + err = PTR_ERR(rdev); dev_err(lp3972->dev, "regulator init failed: %d\n", err); - goto error; + return err; } } return 0; -error: - while (--i >= 0) - regulator_unregister(lp3972->rdev[i]); - kfree(lp3972->rdev); - lp3972->rdev = NULL; -err_nomem: - return err; } static int lp3972_i2c_probe(struct i2c_client *i2c, @@ -557,18 +541,6 @@ static int lp3972_i2c_probe(struct i2c_client *i2c, return 0; } -static int lp3972_i2c_remove(struct i2c_client *i2c) -{ - struct lp3972 *lp3972 = i2c_get_clientdata(i2c); - int i; - - for (i = 0; i < lp3972->num_regulators; i++) - regulator_unregister(lp3972->rdev[i]); - kfree(lp3972->rdev); - - return 0; -} - static const struct i2c_device_id lp3972_i2c_id[] = { { "lp3972", 0 }, { } @@ -581,7 +553,6 @@ static struct i2c_driver lp3972_i2c_driver = { .owner = THIS_MODULE, }, .probe = lp3972_i2c_probe, - .remove = lp3972_i2c_remove, .id_table = lp3972_i2c_id, }; -- cgit v1.2.3 From 90808738fd242ef2533e86f2f481bebe8a7aa11b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 13 Nov 2013 23:44:15 +0000 Subject: spi: Factor validation and initialisation of messages outside lock Currently we do a bunch of per-message validation and initialisation in __spi_async() which is called with the bus lock held. Since none of this validation depends on the current bus status there's no need to hold the lock to do it so split it out into a separate __spi_validate() function which is called prior to taking the bus lock. This could be slightly neater but keep things simple for now to show the code motion clearly. Based on observations from Martin Sperl. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 18cc625d887f..857ee8c407b1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1596,15 +1596,11 @@ int spi_setup(struct spi_device *spi) } EXPORT_SYMBOL_GPL(spi_setup); -static int __spi_async(struct spi_device *spi, struct spi_message *message) +static int __spi_validate(struct spi_device *spi, struct spi_message *message) { struct spi_master *master = spi->master; struct spi_transfer *xfer; - message->spi = spi; - - trace_spi_message_submit(message); - if (list_empty(&message->transfers)) return -EINVAL; if (!message->complete) @@ -1705,6 +1701,18 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) } message->status = -EINPROGRESS; + + return 0; +} + +static int __spi_async(struct spi_device *spi, struct spi_message *message) +{ + struct spi_master *master = spi->master; + + message->spi = spi; + + trace_spi_message_submit(message); + return master->transfer(spi, message); } @@ -1743,6 +1751,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; + ret = __spi_validate(spi, message); + if (ret != 0) + return ret; + spin_lock_irqsave(&master->bus_lock_spinlock, flags); if (master->bus_lock_flag) @@ -1791,6 +1803,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; + ret = __spi_validate(spi, message); + if (ret != 0) + return ret; + spin_lock_irqsave(&master->bus_lock_spinlock, flags); ret = __spi_async(spi, message); -- cgit v1.2.3 From a4ee96e4886768a177e4dc4935ac676513913581 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 30 Sep 2013 14:52:59 -0400 Subject: spi: davinci: Fix the build warning with CONFIG_ARM_LPAE=y MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With CONFIG_ARM_LPAE=y spi driver throws below warning drivers/spi/spi-davinci.c: In function ‘davinci_spi_probe’: drivers/spi/spi-davinci.c:965:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘resource_size_t’ [-Wformat] drivers/spi/spi-davinci.c:965:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘resource_size_t’ [-Wformat] Lets use '%pa' to properly print 'resource_size_t' type variables. Signed-off-by: Santosh Shilimkar Signed-off-by: Mark Brown --- drivers/spi/spi-davinci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 50b2d88c8190..d3f638613b40 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -963,8 +963,8 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_clk; dev_info(&pdev->dev, "DMA: supported\n"); - dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, " - "event queue: %d\n", dma_rx_chan, dma_tx_chan, + dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, " + "event queue: %d\n", &dma_rx_chan, &dma_tx_chan, pdata->dma_event_q); } -- cgit v1.2.3 From 21b2ce5e992f274c9cc45710d29aec11c8b5599a Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Sat, 16 Nov 2013 02:01:16 +0200 Subject: spi: omap2-mcspi: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 443df39840bc..a72127f08e39 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -157,14 +157,14 @@ static inline void mcspi_write_reg(struct spi_master *master, { struct omap2_mcspi *mcspi = spi_master_get_devdata(master); - __raw_writel(val, mcspi->base + idx); + writel_relaxed(val, mcspi->base + idx); } static inline u32 mcspi_read_reg(struct spi_master *master, int idx) { struct omap2_mcspi *mcspi = spi_master_get_devdata(master); - return __raw_readl(mcspi->base + idx); + return readl_relaxed(mcspi->base + idx); } static inline void mcspi_write_cs_reg(const struct spi_device *spi, @@ -172,14 +172,14 @@ static inline void mcspi_write_cs_reg(const struct spi_device *spi, { struct omap2_mcspi_cs *cs = spi->controller_state; - __raw_writel(val, cs->base + idx); + writel_relaxed(val, cs->base + idx); } static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx) { struct omap2_mcspi_cs *cs = spi->controller_state; - return __raw_readl(cs->base + idx); + return readl_relaxed(cs->base + idx); } static inline u32 mcspi_cached_chconf0(const struct spi_device *spi) @@ -338,7 +338,7 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); list_for_each_entry(cs, &ctx->cs, node) - __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); + writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); } static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) @@ -346,9 +346,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) unsigned long timeout; timeout = jiffies + msecs_to_jiffies(1000); - while (!(__raw_readl(reg) & bit)) { + while (!(readl_relaxed(reg) & bit)) { if (time_after(jiffies, timeout)) { - if (!(__raw_readl(reg) & bit)) + if (!(readl_relaxed(reg) & bit)) return -ETIMEDOUT; else return 0; @@ -675,7 +675,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) } dev_vdbg(&spi->dev, "write-%d %02x\n", word_len, *tx); - __raw_writel(*tx++, tx_reg); + writel_relaxed(*tx++, tx_reg); } if (rx != NULL) { if (mcspi_wait_for_reg_bit(chstat_reg, @@ -687,7 +687,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) if (c == 1 && tx == NULL && (l & OMAP2_MCSPI_CHCONF_TURBO)) { omap2_mcspi_set_enable(spi, 0); - *rx++ = __raw_readl(rx_reg); + *rx++ = readl_relaxed(rx_reg); dev_vdbg(&spi->dev, "read-%d %02x\n", word_len, *(rx - 1)); if (mcspi_wait_for_reg_bit(chstat_reg, @@ -701,7 +701,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) omap2_mcspi_set_enable(spi, 0); } - *rx++ = __raw_readl(rx_reg); + *rx++ = readl_relaxed(rx_reg); dev_vdbg(&spi->dev, "read-%d %02x\n", word_len, *(rx - 1)); } @@ -722,7 +722,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) } dev_vdbg(&spi->dev, "write-%d %04x\n", word_len, *tx); - __raw_writel(*tx++, tx_reg); + writel_relaxed(*tx++, tx_reg); } if (rx != NULL) { if (mcspi_wait_for_reg_bit(chstat_reg, @@ -734,7 +734,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) if (c == 2 && tx == NULL && (l & OMAP2_MCSPI_CHCONF_TURBO)) { omap2_mcspi_set_enable(spi, 0); - *rx++ = __raw_readl(rx_reg); + *rx++ = readl_relaxed(rx_reg); dev_vdbg(&spi->dev, "read-%d %04x\n", word_len, *(rx - 1)); if (mcspi_wait_for_reg_bit(chstat_reg, @@ -748,7 +748,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) omap2_mcspi_set_enable(spi, 0); } - *rx++ = __raw_readl(rx_reg); + *rx++ = readl_relaxed(rx_reg); dev_vdbg(&spi->dev, "read-%d %04x\n", word_len, *(rx - 1)); } @@ -769,7 +769,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) } dev_vdbg(&spi->dev, "write-%d %08x\n", word_len, *tx); - __raw_writel(*tx++, tx_reg); + writel_relaxed(*tx++, tx_reg); } if (rx != NULL) { if (mcspi_wait_for_reg_bit(chstat_reg, @@ -781,7 +781,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) if (c == 4 && tx == NULL && (l & OMAP2_MCSPI_CHCONF_TURBO)) { omap2_mcspi_set_enable(spi, 0); - *rx++ = __raw_readl(rx_reg); + *rx++ = readl_relaxed(rx_reg); dev_vdbg(&spi->dev, "read-%d %08x\n", word_len, *(rx - 1)); if (mcspi_wait_for_reg_bit(chstat_reg, @@ -795,7 +795,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) omap2_mcspi_set_enable(spi, 0); } - *rx++ = __raw_readl(rx_reg); + *rx++ = readl_relaxed(rx_reg); dev_vdbg(&spi->dev, "read-%d %08x\n", word_len, *(rx - 1)); } @@ -1107,7 +1107,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) /* RX_ONLY mode needs dummy data in TX reg */ if (t->tx_buf == NULL) - __raw_writel(0, cs->base + writel_relaxed(0, cs->base + OMAP2_MCSPI_TX0); if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && @@ -1470,9 +1470,9 @@ static int omap2_mcspi_resume(struct device *dev) * change in account. */ cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; - __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); + writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE; - __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); + writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); } } pm_runtime_mark_last_busy(mcspi->dev); -- cgit v1.2.3 From d9dda5a1917a01e6317f7bee81e7e6ed236d7e0a Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sun, 24 Nov 2013 09:37:01 -0300 Subject: spi: spi-gpio: Use 'cansleep' variants to access GPIO The GPIO chip in use could be of any kind, and therefore might sleep when accesing the GPIO lines. Take account of this by using cansleep instead, which is the most generic case. Signed-off-by: Ezequiel Garcia Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 3fb09f981980..7beeb29472ac 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -115,17 +115,17 @@ spi_to_pdata(const struct spi_device *spi) static inline void setsck(const struct spi_device *spi, int is_on) { - gpio_set_value(SPI_SCK_GPIO, is_on); + gpio_set_value_cansleep(SPI_SCK_GPIO, is_on); } static inline void setmosi(const struct spi_device *spi, int is_on) { - gpio_set_value(SPI_MOSI_GPIO, is_on); + gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on); } static inline int getmiso(const struct spi_device *spi) { - return !!gpio_get_value(SPI_MISO_GPIO); + return !!gpio_get_value_cansleep(SPI_MISO_GPIO); } #undef pdata @@ -229,7 +229,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) if (cs != SPI_GPIO_NO_CHIPSELECT) { /* SPI is normally active-low */ - gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); + gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); } } -- cgit v1.2.3 From 0079aae0f1e6179d85323b22b370a9cc15c89d45 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 24 Nov 2013 14:29:25 +0000 Subject: spi: omap2: Add build dependencies for writel_relaxed() It's not reliably available. Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index eb1f1ef5fa2e..49bf35633040 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -301,6 +301,7 @@ config SPI_OMAP_UWIRE config SPI_OMAP24XX tristate "McSPI driver for OMAP" + depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH depends on ARCH_OMAP2PLUS || COMPILE_TEST help SPI master controller for OMAP24XX and later Multichannel SPI -- cgit v1.2.3 From 1b49f10c69b45a8b169c69eaa127e7f91a32f7c7 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 16 Oct 2013 21:10:52 +0200 Subject: spi: s3c64xx: Do not require legacy DMA API in case of S3C64XX With support for amba-pl08x driver, on S3C64xx the generic DMA engine API can be used instead of the private s3c-dma interface. Signed-off-by: Tomasz Figa Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index eb1f1ef5fa2e..760d7b6b8591 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -395,7 +395,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" depends on PLAT_SAMSUNG - select S3C64XX_DMA if ARCH_S3C64XX + select S3C64XX_DMA if ARCH_S3C64XX && !S3C64XX_PL080 help SPI driver for Samsung S3C64XX and newer SoCs. -- cgit v1.2.3 From d37f7617bd677c46c49daa3c023920cb91fe14db Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 16 Oct 2013 21:10:55 +0200 Subject: clk: samsung: s3c64xx: Add aliases for DMA clocks This patch adds clkdev aliases for clocks used by PL08x DMA driver. Signed-off-by: Tomasz Figa Signed-off-by: Mark Brown --- drivers/clk/samsung/clk-s3c64xx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 7d2c84265947..06cf10592f52 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -332,7 +332,9 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = { ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), ALIAS(HCLK_DMA1, NULL, "dma1"), + ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"), ALIAS(HCLK_DMA0, NULL, "dma0"), + ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"), ALIAS(HCLK_CAMIF, "s3c-camif", "camif"), ALIAS(HCLK_LCD, "s3c-fb", "lcd"), ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"), -- cgit v1.2.3 From a7a996d19219424c8ca8f16474138b4ee170727f Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 16 Oct 2013 21:10:57 +0200 Subject: clk: samsung: s3c64xx: Remove clock aliases of old DMA driver Since the old DMA driver got removed, these aliases are no longer necessary. Signed-off-by: Tomasz Figa Signed-off-by: Mark Brown --- drivers/clk/samsung/clk-s3c64xx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 06cf10592f52..8e27aee6887e 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -331,9 +331,7 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = { ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"), ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), - ALIAS(HCLK_DMA1, NULL, "dma1"), ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"), - ALIAS(HCLK_DMA0, NULL, "dma0"), ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"), ALIAS(HCLK_CAMIF, "s3c-camif", "camif"), ALIAS(HCLK_LCD, "s3c-fb", "lcd"), -- cgit v1.2.3 From 3faecea70b0d6d050e0ae911032ec340341dc389 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 16 Oct 2013 21:10:58 +0200 Subject: spi: s3c64xx: Always select S3C64XX_PL080 when ARCH_S3C64XX is enabled The legacy S3C64xx DMA driver has been removed, DMA support on S3C64xx is provided only by the generic PL08x driver. This patch modifies the Kconfig entry of spi-s3c64xx driver, which relies on availability of DMA, to always select the S3C64XX_PL080 symbol. Signed-off-by: Tomasz Figa Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 760d7b6b8591..e2dd2fbec5ee 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -395,7 +395,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" depends on PLAT_SAMSUNG - select S3C64XX_DMA if ARCH_S3C64XX && !S3C64XX_PL080 + select S3C64XX_PL080 if ARCH_S3C64XX help SPI driver for Samsung S3C64XX and newer SoCs. -- cgit v1.2.3 From 9c8eca3ca43d7337be2485169d4d86a9b6f477d2 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 13 Nov 2013 14:39:47 -0300 Subject: bus: mvebu-mbus: Remove deprecated comment Remove a comment about the lack of a devicetree binding: this driver's binding is already implemented and in use. Signed-off-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- drivers/bus/mvebu-mbus.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index c646a769e1f5..725c46162bbd 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -588,12 +588,6 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { .show_cpu_target = mvebu_sdram_debug_show_orion, }; -/* - * The driver doesn't yet have a DT binding because the details of - * this DT binding still need to be sorted out. However, as a - * preparation, we already use of_device_id to match a SoC description - * string against the SoC specific details of this driver. - */ static const struct of_device_id of_mvebu_mbus_ids[] = { { .compatible = "marvell,armada370-mbus", .data = &armada_370_xp_mbus_data, }, -- cgit v1.2.3 From a2473b6c8279b95c5fa954f765da65cc27d6e2d2 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 26 Sep 2013 16:35:27 -0300 Subject: clk: mvebu: Add Core Divider clock This commit introduces a new group of clocks present in Armada 370/XP SoCs (called "Core Divider" clocks) and add a provider for them. The only clock supported for now is the NAND clock (ndclk), but the infrastructure to add the rest is already set. Reviewed-by: Gregory CLEMENT Signed-off-by: Ezequiel Garcia Signed-off-by: Mike Turquette --- drivers/clk/mvebu/Kconfig | 5 + drivers/clk/mvebu/Makefile | 1 + drivers/clk/mvebu/clk-corediv.c | 223 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/clk/mvebu/clk-corediv.c (limited to 'drivers') diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig index 0b0f3e729cf7..c339b829d3e3 100644 --- a/drivers/clk/mvebu/Kconfig +++ b/drivers/clk/mvebu/Kconfig @@ -4,15 +4,20 @@ config MVEBU_CLK_COMMON config MVEBU_CLK_CPU bool +config MVEBU_CLK_COREDIV + bool + config ARMADA_370_CLK bool select MVEBU_CLK_COMMON select MVEBU_CLK_CPU + select MVEBU_CLK_COREDIV config ARMADA_XP_CLK bool select MVEBU_CLK_COMMON select MVEBU_CLK_CPU + select MVEBU_CLK_COREDIV config DOVE_CLK bool diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile index 1c7e70c63fb2..21bbfb4a9f42 100644 --- a/drivers/clk/mvebu/Makefile +++ b/drivers/clk/mvebu/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o +obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c new file mode 100644 index 000000000000..7162615bcdcd --- /dev/null +++ b/drivers/clk/mvebu/clk-corediv.c @@ -0,0 +1,223 @@ +/* + * MVEBU Core divider clock + * + * Copyright (C) 2013 Marvell + * + * Ezequiel Garcia + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include "common.h" + +#define CORE_CLK_DIV_RATIO_MASK 0xff +#define CORE_CLK_DIV_RATIO_RELOAD BIT(8) +#define CORE_CLK_DIV_ENABLE_OFFSET 24 +#define CORE_CLK_DIV_RATIO_OFFSET 0x8 + +struct clk_corediv_desc { + unsigned int mask; + unsigned int offset; + unsigned int fieldbit; +}; + +struct clk_corediv { + struct clk_hw hw; + void __iomem *reg; + struct clk_corediv_desc desc; + spinlock_t lock; +}; + +static struct clk_onecell_data clk_data; + +static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = { + { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */ +}; + +#define to_corediv_clk(p) container_of(p, struct clk_corediv, hw) + +static int clk_corediv_is_enabled(struct clk_hw *hwclk) +{ + struct clk_corediv *corediv = to_corediv_clk(hwclk); + struct clk_corediv_desc *desc = &corediv->desc; + u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET; + + return !!(readl(corediv->reg) & enable_mask); +} + +static int clk_corediv_enable(struct clk_hw *hwclk) +{ + struct clk_corediv *corediv = to_corediv_clk(hwclk); + struct clk_corediv_desc *desc = &corediv->desc; + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(&corediv->lock, flags); + + reg = readl(corediv->reg); + reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); + writel(reg, corediv->reg); + + spin_unlock_irqrestore(&corediv->lock, flags); + + return 0; +} + +static void clk_corediv_disable(struct clk_hw *hwclk) +{ + struct clk_corediv *corediv = to_corediv_clk(hwclk); + struct clk_corediv_desc *desc = &corediv->desc; + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(&corediv->lock, flags); + + reg = readl(corediv->reg); + reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); + writel(reg, corediv->reg); + + spin_unlock_irqrestore(&corediv->lock, flags); +} + +static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk, + unsigned long parent_rate) +{ + struct clk_corediv *corediv = to_corediv_clk(hwclk); + struct clk_corediv_desc *desc = &corediv->desc; + u32 reg, div; + + reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); + div = (reg >> desc->offset) & desc->mask; + return parent_rate / div; +} + +static long clk_corediv_round_rate(struct clk_hw *hwclk, unsigned long rate, + unsigned long *parent_rate) +{ + /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */ + u32 div; + + div = *parent_rate / rate; + if (div < 4) + div = 4; + else if (div > 6) + div = 8; + + return *parent_rate / div; +} + +static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_corediv *corediv = to_corediv_clk(hwclk); + struct clk_corediv_desc *desc = &corediv->desc; + unsigned long flags = 0; + u32 reg, div; + + div = parent_rate / rate; + + spin_lock_irqsave(&corediv->lock, flags); + + /* Write new divider to the divider ratio register */ + reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); + reg &= ~(desc->mask << desc->offset); + reg |= (div & desc->mask) << desc->offset; + writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); + + /* Set reload-force for this clock */ + reg = readl(corediv->reg) | BIT(desc->fieldbit); + writel(reg, corediv->reg); + + /* Now trigger the clock update */ + reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD; + writel(reg, corediv->reg); + + /* + * Wait for clocks to settle down, and then clear all the + * ratios request and the reload request. + */ + udelay(1000); + reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD); + writel(reg, corediv->reg); + udelay(1000); + + spin_unlock_irqrestore(&corediv->lock, flags); + + return 0; +} + +static const struct clk_ops corediv_ops = { + .enable = clk_corediv_enable, + .disable = clk_corediv_disable, + .is_enabled = clk_corediv_is_enabled, + .recalc_rate = clk_corediv_recalc_rate, + .round_rate = clk_corediv_round_rate, + .set_rate = clk_corediv_set_rate, +}; + +static void __init mvebu_corediv_clk_init(struct device_node *node) +{ + struct clk_init_data init; + struct clk_corediv *corediv; + struct clk **clks; + void __iomem *base; + const char *parent_name; + const char *clk_name; + int i; + + base = of_iomap(node, 0); + if (WARN_ON(!base)) + return; + + parent_name = of_clk_get_parent_name(node, 0); + + clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc); + + /* clks holds the clock array */ + clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), + GFP_KERNEL); + if (WARN_ON(!clks)) + goto err_unmap; + /* corediv holds the clock specific array */ + corediv = kcalloc(clk_data.clk_num, sizeof(struct clk_corediv), + GFP_KERNEL); + if (WARN_ON(!corediv)) + goto err_free_clks; + + spin_lock_init(&corediv->lock); + + for (i = 0; i < clk_data.clk_num; i++) { + of_property_read_string_index(node, "clock-output-names", + i, &clk_name); + init.num_parents = 1; + init.parent_names = &parent_name; + init.name = clk_name; + init.ops = &corediv_ops; + init.flags = 0; + + corediv[i].desc = mvebu_corediv_desc[i]; + corediv[i].reg = base; + corediv[i].hw.init = &init; + + clks[i] = clk_register(NULL, &corediv[i].hw); + WARN_ON(IS_ERR(clks[i])); + } + + clk_data.clks = clks; + of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data); + return; + +err_free_clks: + kfree(clks); +err_unmap: + iounmap(base); +} +CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock", + mvebu_corediv_clk_init); -- cgit v1.2.3 From 8caa07c0e565a15f49f290ca4c6a3adf968ddd38 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: core: Implement devm_iio_device_{register,unregister} Add device managed devm_iio_device_{register,unregister}() to automatically unregister IIO drivers thus leading to simplified IIO driver code. Signed-off-by: Sachin Kamat Cc: Lars-Peter Clausen Tested-by: Lars-Peter Clausen Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- Documentation/driver-model/devres.txt | 2 ++ drivers/iio/industrialio-core.c | 59 +++++++++++++++++++++++++++++++++++ include/linux/iio/iio.h | 3 ++ 3 files changed, 64 insertions(+) (limited to 'drivers') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index fcb34a5697ea..ffeab1dded0a 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -242,6 +242,8 @@ IIO devm_iio_device_free() devm_iio_trigger_alloc() devm_iio_trigger_free() + devm_iio_device_register() + devm_iio_device_unregister() IO region devm_request_region() diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 18f72e3d0ed6..1c280b50c74b 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1161,6 +1161,65 @@ void iio_device_unregister(struct iio_dev *indio_dev) mutex_unlock(&indio_dev->info_exist_lock); } EXPORT_SYMBOL(iio_device_unregister); + +static void devm_iio_device_unreg(struct device *dev, void *res) +{ + iio_device_unregister(*(struct iio_dev **)res); +} + +/** + * devm_iio_device_register - Resource-managed iio_device_register() + * @dev: Device to allocate iio_dev for + * @indio_dev: Device structure filled by the device driver + * + * Managed iio_device_register. The IIO device registered with this + * function is automatically unregistered on driver detach. This function + * calls iio_device_register() internally. Refer to that function for more + * information. + * + * If an iio_dev registered with this function needs to be unregistered + * separately, devm_iio_device_unregister() must be used. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev) +{ + struct iio_dev **ptr; + int ret; + + ptr = devres_alloc(devm_iio_device_unreg, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + *ptr = indio_dev; + ret = iio_device_register(indio_dev); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_device_register); + +/** + * devm_iio_device_unregister - Resource-managed iio_device_unregister() + * @dev: Device this iio_dev belongs to + * @indio_dev: the iio_dev associated with the device + * + * Unregister iio_dev registered with devm_iio_device_register(). + */ +void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev) +{ + int rc; + + rc = devres_release(dev, devm_iio_device_unreg, + devm_iio_device_match, indio_dev); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_device_unregister); + subsys_initcall(iio_init); module_exit(iio_exit); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 256a90a1bea6..a8cabda4d108 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -510,6 +510,9 @@ int iio_device_register(struct iio_dev *indio_dev); **/ void iio_device_unregister(struct iio_dev *indio_dev); +int devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev); +void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev); + /** * iio_push_event() - try to add event to the list for userspace reading * @indio_dev: IIO device structure -- cgit v1.2.3 From a7e57dce02ceb8212f106191fdfbc0fcb61ce9e0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: core: Move kernel doc to the right location Documentation related to function should be placed above its implementation. Move it accordingly. Signed-off-by: Sachin Kamat Cc: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 42 ++++++++++++++++++++ drivers/iio/industrialio-event.c | 6 +++ drivers/iio/industrialio-trigger.c | 24 ++++++++++++ include/linux/iio/iio.h | 80 -------------------------------------- 4 files changed, 72 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 1c280b50c74b..2fe88c189f74 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -107,6 +107,11 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_INT_TIME] = "integration_time", }; +/** + * iio_find_channel_from_si() - get channel from its scan index + * @indio_dev: device + * @si: scan index to match + */ const struct iio_chan_spec *iio_find_channel_from_si(struct iio_dev *indio_dev, int si) { @@ -922,6 +927,10 @@ struct device_type iio_device_type = { .release = iio_dev_release, }; +/** + * iio_device_alloc() - allocate an iio_dev from a driver + * @sizeof_priv: Space to allocate for private structure. + **/ struct iio_dev *iio_device_alloc(int sizeof_priv) { struct iio_dev *dev; @@ -962,6 +971,10 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) } EXPORT_SYMBOL(iio_device_alloc); +/** + * iio_device_free() - free an iio_dev from a driver + * @dev: the iio_dev associated with the device + **/ void iio_device_free(struct iio_dev *dev) { if (dev) @@ -984,6 +997,20 @@ static int devm_iio_device_match(struct device *dev, void *res, void *data) return *r == data; } +/** + * devm_iio_device_alloc - Resource-managed iio_device_alloc() + * @dev: Device to allocate iio_dev for + * @sizeof_priv: Space to allocate for private structure. + * + * Managed iio_device_alloc. iio_dev allocated with this function is + * automatically freed on driver detach. + * + * If an iio_dev allocated with this function needs to be freed separately, + * devm_iio_device_free() must be used. + * + * RETURNS: + * Pointer to allocated iio_dev on success, NULL on failure. + */ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) { struct iio_dev **ptr, *iio_dev; @@ -1006,6 +1033,13 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) } EXPORT_SYMBOL_GPL(devm_iio_device_alloc); +/** + * devm_iio_device_free - Resource-managed iio_device_free() + * @dev: Device this iio_dev belongs to + * @iio_dev: the iio_dev associated with the device + * + * Free iio_dev allocated with devm_iio_device_alloc(). + */ void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev) { int rc; @@ -1080,6 +1114,10 @@ static const struct file_operations iio_buffer_fileops = { static const struct iio_buffer_setup_ops noop_ring_setup_ops; +/** + * iio_device_register() - register a device with the IIO subsystem + * @indio_dev: Device structure filled by the device driver + **/ int iio_device_register(struct iio_dev *indio_dev) { int ret; @@ -1141,6 +1179,10 @@ error_ret: } EXPORT_SYMBOL(iio_device_register); +/** + * iio_device_unregister() - unregister a device from the IIO subsystem + * @indio_dev: Device structure representing the device. + **/ void iio_device_unregister(struct iio_dev *indio_dev) { mutex_lock(&indio_dev->info_exist_lock); diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index dac15b9f9df8..32b2c2d8d237 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -42,6 +42,12 @@ struct iio_event_interface { struct attribute_group group; }; +/** + * iio_push_event() - try to add event to the list for userspace reading + * @indio_dev: IIO device structure + * @ev_code: What event + * @timestamp: When the event occurred + **/ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) { struct iio_event_interface *ev_int = indio_dev->event_interface; diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index bf5e70a32d3f..8bd092b9327e 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -506,6 +506,23 @@ static int devm_iio_trigger_match(struct device *dev, void *res, void *data) return *r == data; } +/** + * devm_iio_trigger_alloc - Resource-managed iio_trigger_alloc() + * @dev: Device to allocate iio_trigger for + * @fmt: trigger name format. If it includes format + * specifiers, the additional arguments following + * format are formatted and inserted in the resulting + * string replacing their respective specifiers. + * + * Managed iio_trigger_alloc. iio_trigger allocated with this function is + * automatically freed on driver detach. + * + * If an iio_trigger allocated with this function needs to be freed separately, + * devm_iio_trigger_free() must be used. + * + * RETURNS: + * Pointer to allocated iio_trigger on success, NULL on failure. + */ struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, const char *fmt, ...) { @@ -532,6 +549,13 @@ struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, } EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc); +/** + * devm_iio_trigger_free - Resource-managed iio_trigger_free() + * @dev: Device this iio_dev belongs to + * @iio_trig: the iio_trigger associated with the device + * + * Free iio_trigger allocated with devm_iio_trigger_alloc(). + */ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig) { int rc; diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index a8cabda4d108..5b125fd554e4 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -490,35 +490,12 @@ struct iio_dev { #endif }; -/** - * iio_find_channel_from_si() - get channel from its scan index - * @indio_dev: device - * @si: scan index to match - */ const struct iio_chan_spec *iio_find_channel_from_si(struct iio_dev *indio_dev, int si); - -/** - * iio_device_register() - register a device with the IIO subsystem - * @indio_dev: Device structure filled by the device driver - **/ int iio_device_register(struct iio_dev *indio_dev); - -/** - * iio_device_unregister() - unregister a device from the IIO subsystem - * @indio_dev: Device structure representing the device. - **/ void iio_device_unregister(struct iio_dev *indio_dev); - int devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev); void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev); - -/** - * iio_push_event() - try to add event to the list for userspace reading - * @indio_dev: IIO device structure - * @ev_code: What event - * @timestamp: When the event occurred - **/ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); extern struct bus_type iio_bus_type; @@ -582,10 +559,6 @@ static inline void *iio_device_get_drvdata(struct iio_dev *indio_dev) /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES -/** - * iio_device_alloc() - allocate an iio_dev from a driver - * @sizeof_priv: Space to allocate for private structure. - **/ struct iio_dev *iio_device_alloc(int sizeof_priv); static inline void *iio_priv(const struct iio_dev *indio_dev) @@ -599,64 +572,11 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); } -/** - * iio_device_free() - free an iio_dev from a driver - * @indio_dev: the iio_dev associated with the device - **/ void iio_device_free(struct iio_dev *indio_dev); - -/** - * devm_iio_device_alloc - Resource-managed iio_device_alloc() - * @dev: Device to allocate iio_dev for - * @sizeof_priv: Space to allocate for private structure. - * - * Managed iio_device_alloc. iio_dev allocated with this function is - * automatically freed on driver detach. - * - * If an iio_dev allocated with this function needs to be freed separately, - * devm_iio_device_free() must be used. - * - * RETURNS: - * Pointer to allocated iio_dev on success, NULL on failure. - */ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv); - -/** - * devm_iio_device_free - Resource-managed iio_device_free() - * @dev: Device this iio_dev belongs to - * @indio_dev: the iio_dev associated with the device - * - * Free iio_dev allocated with devm_iio_device_alloc(). - */ void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev); - -/** - * devm_iio_trigger_alloc - Resource-managed iio_trigger_alloc() - * @dev: Device to allocate iio_trigger for - * @fmt: trigger name format. If it includes format - * specifiers, the additional arguments following - * format are formatted and inserted in the resulting - * string replacing their respective specifiers. - * - * Managed iio_trigger_alloc. iio_trigger allocated with this function is - * automatically freed on driver detach. - * - * If an iio_trigger allocated with this function needs to be freed separately, - * devm_iio_trigger_free() must be used. - * - * RETURNS: - * Pointer to allocated iio_trigger on success, NULL on failure. - */ struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, const char *fmt, ...); - -/** - * devm_iio_trigger_free - Resource-managed iio_trigger_free() - * @dev: Device this iio_dev belongs to - * @iio_trig: the iio_trigger associated with the device - * - * Free iio_trigger allocated with devm_iio_trigger_alloc(). - */ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig); /** -- cgit v1.2.3 From 2842d4cc729882489ae73dae48dfc63f5ce404ba Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: adc: mcp3422: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp3422.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 12948325431c..dbdbd77f69ea 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -362,7 +362,7 @@ static int mcp3422_probe(struct i2c_client *client, | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); mcp3422_update_config(adc, config); - err = iio_device_register(indio_dev); + err = devm_iio_device_register(&client->dev, indio_dev); if (err < 0) return err; @@ -371,12 +371,6 @@ static int mcp3422_probe(struct i2c_client *client, return 0; } -static int mcp3422_remove(struct i2c_client *client) -{ - iio_device_unregister(i2c_get_clientdata(client)); - return 0; -} - static const struct i2c_device_id mcp3422_id[] = { { "mcp3422", 2 }, { "mcp3423", 3 }, @@ -400,7 +394,6 @@ static struct i2c_driver mcp3422_driver = { .of_match_table = of_match_ptr(mcp3422_of_match), }, .probe = mcp3422_probe, - .remove = mcp3422_remove, .id_table = mcp3422_id, }; module_i2c_driver(mcp3422_driver); -- cgit v1.2.3 From 17666ef3c765afa9f70de1f3c733a2f7ea2f6ca3 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Nov 2013 21:49:00 +0000 Subject: iio: Minor kerneldoc fix for iio_trigger_write_current() Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 8bd092b9327e..b1b25294e35d 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -318,7 +318,7 @@ static ssize_t iio_trigger_read_current(struct device *dev, * iio_trigger_write_current() - trigger consumer sysfs set current trigger * * For trigger consumers the current_trigger interface allows the trigger - * used for this device to be specified at run time based on the triggers + * used for this device to be specified at run time based on the trigger's * name. **/ static ssize_t iio_trigger_write_current(struct device *dev, -- cgit v1.2.3 From a35e1fd26826faa5595bcb4c8ab370f331221ff7 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Nov 2013 21:49:00 +0000 Subject: iio: Remove redundant check that new trigger is different from old same check is performed a new lines above Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index b1b25294e35d..7ba2f002ffca 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -356,7 +356,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, indio_dev->trig = trig; - if (oldtrig && indio_dev->trig != oldtrig) + if (oldtrig) iio_trigger_put(oldtrig); if (indio_dev->trig) iio_trigger_get(indio_dev->trig); -- cgit v1.2.3 From cc26ad455f57b42dd40ca01c4c220516218390f6 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Tue, 12 Nov 2013 19:43:00 +0000 Subject: iio: Add Freescale MPL3115A2 pressure / temperature sensor driver I2C-controlled MEMS sensor with 20-bit pressure measurement (pascal) and 12-bit temperature measurement driver only exposes basic functionality, see TODO remarks datasheet: http://cache.freescale.com/files/sensors/doc/data_sheet/MPL3115A2.pdf v2: * store 20-bit value in 32-bit buffer element (instead of 24-bit) * zero buffer to prevent kernel data leak to userspace * fix mutex unlock in trigger handler (thanks Andi Shyti) Signed-off-by: Peter Meerwald Reviewed-by: Andi Shyti Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 12 ++ drivers/iio/pressure/Makefile | 1 + drivers/iio/pressure/mpl3115.c | 329 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 drivers/iio/pressure/mpl3115.c (limited to 'drivers') diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 4f2e0f9bad8c..a8b9cae5c173 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -5,6 +5,18 @@ menu "Pressure sensors" +config MPL3115 + tristate "Freescale MPL3115A2 pressure sensor driver" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for the Freescale MPL3115A2 + pressure sensor / altimeter. + + To compile this driver as a module, choose M here: the module + will be called mpl3115. + config IIO_ST_PRESS tristate "STMicroelectronics pressure sensor Driver" depends on (I2C || SPI_MASTER) && SYSFS diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index be71464c2752..42bb9fcf5436 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_MPL3115) += mpl3115.o obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o st_pressure-y := st_pressure_core.o st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c new file mode 100644 index 000000000000..ac8c8ab723e5 --- /dev/null +++ b/drivers/iio/pressure/mpl3115.c @@ -0,0 +1,329 @@ +/* + * mpl3115.c - Support for Freescale MPL3115A2 pressure/temperature sensor + * + * Copyright (c) 2013 Peter Meerwald + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * (7-bit I2C slave address 0x60) + * + * TODO: FIFO buffer, altimeter mode, oversampling, continuous mode, + * interrupts, user offset correction, raw mode + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPL3115_STATUS 0x00 +#define MPL3115_OUT_PRESS 0x01 /* MSB first, 20 bit */ +#define MPL3115_OUT_TEMP 0x04 /* MSB first, 12 bit */ +#define MPL3115_WHO_AM_I 0x0c +#define MPL3115_CTRL_REG1 0x26 + +#define MPL3115_DEVICE_ID 0xc4 + +#define MPL3115_STATUS_PRESS_RDY BIT(2) +#define MPL3115_STATUS_TEMP_RDY BIT(1) + +#define MPL3115_CTRL_RESET BIT(2) /* software reset */ +#define MPL3115_CTRL_OST BIT(1) /* initiate measurement */ +#define MPL3115_CTRL_ACTIVE BIT(0) /* continuous measurement */ +#define MPL3115_CTRL_OS_258MS (BIT(5) | BIT(4)) /* 64x oversampling */ + +struct mpl3115_data { + struct i2c_client *client; + struct mutex lock; + u8 ctrl_reg1; +}; + +static int mpl3115_request(struct mpl3115_data *data) +{ + int ret, tries = 15; + + /* trigger measurement */ + ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1, + data->ctrl_reg1 | MPL3115_CTRL_OST); + if (ret < 0) + return ret; + + while (tries-- > 0) { + ret = i2c_smbus_read_byte_data(data->client, MPL3115_CTRL_REG1); + if (ret < 0) + return ret; + /* wait for data ready, i.e. OST cleared */ + if (!(ret & MPL3115_CTRL_OST)) + break; + msleep(20); + } + + if (tries < 0) { + dev_err(&data->client->dev, "data not ready\n"); + return -EIO; + } + + return 0; +} + +static int mpl3115_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mpl3115_data *data = iio_priv(indio_dev); + s32 tmp = 0; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + + switch (chan->type) { + case IIO_PRESSURE: /* in 0.25 pascal / LSB */ + mutex_lock(&data->lock); + ret = mpl3115_request(data); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + ret = i2c_smbus_read_i2c_block_data(data->client, + MPL3115_OUT_PRESS, 3, (u8 *) &tmp); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = sign_extend32(be32_to_cpu(tmp) >> 12, 23); + return IIO_VAL_INT; + case IIO_TEMP: /* in 0.0625 celsius / LSB */ + mutex_lock(&data->lock); + ret = mpl3115_request(data); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + ret = i2c_smbus_read_i2c_block_data(data->client, + MPL3115_OUT_TEMP, 2, (u8 *) &tmp); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = sign_extend32(be32_to_cpu(tmp) >> 20, 15); + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PRESSURE: + *val = 0; + *val2 = 250; /* want kilopascal */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + *val = 0; + *val2 = 62500; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + } + return -EINVAL; +} + +static irqreturn_t mpl3115_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct mpl3115_data *data = iio_priv(indio_dev); + u8 buffer[16]; /* 32-bit channel + 16-bit channel + padding + ts */ + int ret, pos = 0; + + mutex_lock(&data->lock); + ret = mpl3115_request(data); + if (ret < 0) { + mutex_unlock(&data->lock); + goto done; + } + + memset(buffer, 0, sizeof(buffer)); + if (test_bit(0, indio_dev->active_scan_mask)) { + ret = i2c_smbus_read_i2c_block_data(data->client, + MPL3115_OUT_PRESS, 3, &buffer[pos]); + if (ret < 0) { + mutex_unlock(&data->lock); + goto done; + } + pos += 4; + } + + if (test_bit(1, indio_dev->active_scan_mask)) { + ret = i2c_smbus_read_i2c_block_data(data->client, + MPL3115_OUT_TEMP, 2, &buffer[pos]); + if (ret < 0) { + mutex_unlock(&data->lock); + goto done; + } + } + mutex_unlock(&data->lock); + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_get_time_ns()); + +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static const struct iio_chan_spec mpl3115_channels[] = { + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 20, + .storagebits = 32, + .shift = 12, + .endianness = IIO_BE, + } + }, + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 12, + .storagebits = 16, + .shift = 4, + .endianness = IIO_BE, + } + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static const struct iio_info mpl3115_info = { + .read_raw = &mpl3115_read_raw, + .driver_module = THIS_MODULE, +}; + +static int mpl3115_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mpl3115_data *data; + struct iio_dev *indio_dev; + int ret; + + ret = i2c_smbus_read_byte_data(client, MPL3115_WHO_AM_I); + if (ret < 0) + return ret; + if (ret != MPL3115_DEVICE_ID) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + mutex_init(&data->lock); + + i2c_set_clientdata(client, indio_dev); + indio_dev->info = &mpl3115_info; + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mpl3115_channels; + indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels); + + /* software reset, I2C transfer is aborted (fails) */ + i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1, + MPL3115_CTRL_RESET); + msleep(50); + + data->ctrl_reg1 = MPL3115_CTRL_OS_258MS; + ret = i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1, + data->ctrl_reg1); + if (ret < 0) + return ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + mpl3115_trigger_handler, NULL); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto buffer_cleanup; + return 0; + +buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; +} + +static int mpl3115_standby(struct mpl3115_data *data) +{ + return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1, + data->ctrl_reg1 & ~MPL3115_CTRL_ACTIVE); +} + +static int mpl3115_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + mpl3115_standby(iio_priv(indio_dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mpl3115_suspend(struct device *dev) +{ + return mpl3115_standby(iio_priv(i2c_get_clientdata( + to_i2c_client(dev)))); +} + +static int mpl3115_resume(struct device *dev) +{ + struct mpl3115_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + + return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1, + data->ctrl_reg1); +} + +static SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend, mpl3115_resume); +#define MPL3115_PM_OPS (&mpl3115_pm_ops) +#else +#define MPL3115_PM_OPS NULL +#endif + +static const struct i2c_device_id mpl3115_id[] = { + { "mpl3115", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mpl3115_id); + +static struct i2c_driver mpl3115_driver = { + .driver = { + .name = "mpl3115", + .pm = MPL3115_PM_OPS, + }, + .probe = mpl3115_probe, + .remove = mpl3115_remove, + .id_table = mpl3115_id, +}; +module_i2c_driver(mpl3115_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("Freescale MPL3115 pressure/temperature driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8175bff5b47eae171a393f5bd67673de50630973 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Fri, 25 Oct 2013 10:10:00 +0100 Subject: iio:light:tsl2563: Add DT support Add Device Tree support for the TSL2563 driver, document the binding and add AMS-TAOS Inc. to the list of vendor prefixes. Signed-off-by: Sebastian Reichel Acked-by: Kumar Gala Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/light/tsl2563.txt | 19 +++++++++++++++++++ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + drivers/iio/light/tsl2563.c | 4 ++++ 3 files changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/tsl2563.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/light/tsl2563.txt b/Documentation/devicetree/bindings/iio/light/tsl2563.txt new file mode 100644 index 000000000000..f91e809e736e --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/tsl2563.txt @@ -0,0 +1,19 @@ +* AMS TAOS TSL2563 ambient light sensor + +Required properties: + + - compatible : should be "amstaos,tsl2563" + - reg : the I2C address of the sensor + +Optional properties: + + - amstaos,cover-comp-gain : integer used as multiplier for gain + compensation (default = 1) + +Example: + +tsl2563@29 { + compatible = "amstaos,tsl2563"; + reg = <0x29>; + amstaos,cover-comp-gain = <16>; +}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 04eab45dd148..b65a44041ec1 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -9,6 +9,7 @@ aeroflexgaisler Aeroflex Gaisler AB ak Asahi Kasei Corp. altr Altera Corp. amcc Applied Micro Circuits Corporation (APM, formally AMCC) +amstaos AMS-Taos Inc. apm Applied Micro Circuits Corporation (APM) arm ARM Ltd. atmel Atmel Corporation diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 5e5d9dea22c5..0c6e459c86b1 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -714,6 +714,7 @@ static int tsl2563_probe(struct i2c_client *client, struct iio_dev *indio_dev; struct tsl2563_chip *chip; struct tsl2563_platform_data *pdata = client->dev.platform_data; + struct device_node *np = client->dev.of_node; int err = 0; u8 id = 0; @@ -750,6 +751,9 @@ static int tsl2563_probe(struct i2c_client *client, if (pdata) chip->cover_comp_gain = pdata->cover_comp_gain; + else if (np) + of_property_read_u32(np, "amstaos,cover-comp-gain", + &chip->cover_comp_gain); else chip->cover_comp_gain = 1; -- cgit v1.2.3 From 27b832427e060d4e963c610d07860e5dbe1daafa Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 1 Nov 2013 05:35:00 +0000 Subject: iio:magnetometer:hmc5843 - add basic dt support Compatible string, documenation and an optional gpio for the dataready pin. Signed-off-by: NeilBrown Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/magnetometer/hmc5843.txt | 17 +++++++++++++++++ drivers/staging/iio/magnetometer/hmc5843.c | 7 +++++++ 2 files changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt b/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt new file mode 100644 index 000000000000..90d5f34db04e --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt @@ -0,0 +1,17 @@ +* Honeywell HMC5843 magnetometer sensor + +Required properties: + + - compatible : should be "honeywell,hmc5843" + - reg : the I2C address of the magnetometer - typically 0x1e + +Optional properties: + + - gpios : should be device tree identifier of the magnetometer DRDY pin + +Example: + +hmc5843@1e { + compatible = "honeywell,hmc5843" + reg = <0x1e>; +}; diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 99421f90d189..bdb018878296 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -624,10 +624,17 @@ static const struct i2c_device_id hmc5843_id[] = { }; MODULE_DEVICE_TABLE(i2c, hmc5843_id); +static const struct of_device_id hmc5843_of_match[] = { + { .compatible = "honeywell,hmc5843" }, + {} +}; +MODULE_DEVICE_TABLE(of, hmc5843_of_match); + static struct i2c_driver hmc5843_driver = { .driver = { .name = "hmc5843", .pm = HMC5843_PM_OPS, + .of_match_table = of_match_ptr(hmc5843_of_match), }, .id_table = hmc5843_id, .probe = hmc5843_probe, -- cgit v1.2.3 From 2191d0fba75c77efef8e4fd50641fb19772b72eb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: adc: viperboard: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/adc/viperboard_adc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c index ee695e50cfa3..d0add8f9416b 100644 --- a/drivers/iio/adc/viperboard_adc.c +++ b/drivers/iio/adc/viperboard_adc.c @@ -133,7 +133,7 @@ static int vprbrd_adc_probe(struct platform_device *pdev) indio_dev->channels = vprbrd_adc_iio_channels; indio_dev->num_channels = ARRAY_SIZE(vprbrd_adc_iio_channels); - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&pdev->dev, indio_dev); if (ret) { dev_err(&pdev->dev, "could not register iio (adc)"); return ret; @@ -144,22 +144,12 @@ static int vprbrd_adc_probe(struct platform_device *pdev) return 0; } -static int vprbrd_adc_remove(struct platform_device *pdev) -{ - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - - iio_device_unregister(indio_dev); - - return 0; -} - static struct platform_driver vprbrd_adc_driver = { .driver = { .name = "viperboard-adc", .owner = THIS_MODULE, }, .probe = vprbrd_adc_probe, - .remove = vprbrd_adc_remove, }; module_platform_driver(vprbrd_adc_driver); -- cgit v1.2.3 From 365736e77cb7facea72b212aaef66d88b8f38a8d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: dac: ad5421: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5421.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index 3eeaa82075f7..7d1e90811c71 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -514,16 +514,7 @@ static int ad5421_probe(struct spi_device *spi) return ret; } - return iio_device_register(indio_dev); -} - -static int ad5421_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver ad5421_driver = { @@ -532,7 +523,6 @@ static struct spi_driver ad5421_driver = { .owner = THIS_MODULE, }, .probe = ad5421_probe, - .remove = ad5421_remove, }; module_spi_driver(ad5421_driver); -- cgit v1.2.3 From 1baeec9c37e52e0f3744137981d47a1353353ae5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: dac: ad5755: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5755.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 9a78d5abb2f6..ee1e95a3a0c3 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -589,16 +589,7 @@ static int ad5755_probe(struct spi_device *spi) if (ret) return ret; - return iio_device_register(indio_dev); -} - -static int ad5755_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ad5755_id[] = { @@ -617,7 +608,6 @@ static struct spi_driver ad5755_driver = { .owner = THIS_MODULE, }, .probe = ad5755_probe, - .remove = ad5755_remove, .id_table = ad5755_id, }; module_spi_driver(ad5755_driver); -- cgit v1.2.3 From 79788b7c448e3afb94e440a84eb60e425551de42 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: gyro: adis16130: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16130.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c index 445c2aecfadd..8d08c7ed1ea6 100644 --- a/drivers/iio/gyro/adis16130.c +++ b/drivers/iio/gyro/adis16130.c @@ -161,13 +161,7 @@ static int adis16130_probe(struct spi_device *spi) indio_dev->info = &adis16130_info; indio_dev->modes = INDIO_DIRECT_MODE; - return iio_device_register(indio_dev); -} - -static int adis16130_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver adis16130_driver = { @@ -176,7 +170,6 @@ static struct spi_driver adis16130_driver = { .owner = THIS_MODULE, }, .probe = adis16130_probe, - .remove = adis16130_remove, }; module_spi_driver(adis16130_driver); -- cgit v1.2.3 From 9bcbf02ae38abd45fecf618d6f648927bd12d34d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: gyro: adxrs450: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adxrs450.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c index 1e546ba7ba45..eb0e08ec9e20 100644 --- a/drivers/iio/gyro/adxrs450.c +++ b/drivers/iio/gyro/adxrs450.c @@ -434,23 +434,14 @@ static int adxrs450_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); indio_dev->name = spi->dev.driver->name; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; /* Get the device into a sane initial state */ ret = adxrs450_initial_setup(indio_dev); if (ret) - goto error_initial; - return 0; -error_initial: - iio_device_unregister(indio_dev); - return ret; -} - -static int adxrs450_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); + return ret; return 0; } @@ -468,7 +459,6 @@ static struct spi_driver adxrs450_driver = { .owner = THIS_MODULE, }, .probe = adxrs450_probe, - .remove = adxrs450_remove, .id_table = adxrs450_id, }; module_spi_driver(adxrs450_driver); -- cgit v1.2.3 From 691dab4291f5df64e08d49529e3eafc481811555 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: iio: light: vcnl4000: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/iio/light/vcnl4000.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index ecb3341ef9c0..384ac23f576f 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -179,13 +179,7 @@ static int vcnl4000_probe(struct i2c_client *client, indio_dev->name = VCNL4000_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - return iio_device_register(indio_dev); -} - -static int vcnl4000_remove(struct i2c_client *client) -{ - iio_device_unregister(i2c_get_clientdata(client)); - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static struct i2c_driver vcnl4000_driver = { @@ -194,7 +188,6 @@ static struct i2c_driver vcnl4000_driver = { .owner = THIS_MODULE, }, .probe = vcnl4000_probe, - .remove = vcnl4000_remove, .id_table = vcnl4000_id, }; -- cgit v1.2.3 From 8fb8125aa56de8f1618973cc3ae85ebde81bb656 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: adis16220: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16220_core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 4c9364b63c77..6f38ca95f9bb 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -439,13 +439,13 @@ static int adis16220_probe(struct spi_device *spi) indio_dev->channels = adis16220_channels; indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); if (ret) - goto error_unregister_dev; + return ret; ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); if (ret) @@ -470,8 +470,6 @@ error_rm_adc1_bin: sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); error_rm_accel_bin: sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); -error_unregister_dev: - iio_device_unregister(indio_dev); return ret; } @@ -482,7 +480,6 @@ static int adis16220_remove(struct spi_device *spi) sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); - iio_device_unregister(indio_dev); return 0; } -- cgit v1.2.3 From 5404dc77266e3159486bd89a482d11e80a3b173e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: ad7816: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7816.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 9f48e5c74eed..2369cf28412e 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -412,7 +412,7 @@ static int ad7816_probe(struct spi_device *spi_dev) return ret; } - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi_dev->dev, indio_dev); if (ret) return ret; @@ -422,15 +422,6 @@ static int ad7816_probe(struct spi_device *spi_dev) return 0; } -static int ad7816_remove(struct spi_device *spi_dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev); - - iio_device_unregister(indio_dev); - - return 0; -} - static const struct spi_device_id ad7816_id[] = { { "ad7816", 0 }, { "ad7817", 0 }, @@ -446,7 +437,6 @@ static struct spi_driver ad7816_driver = { .owner = THIS_MODULE, }, .probe = ad7816_probe, - .remove = ad7816_remove, .id_table = ad7816_id, }; module_spi_driver(ad7816_driver); -- cgit v1.2.3 From afb6fd5fca84c7ee4ba311f1c6e0479e705de330 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: lpc32xx_adc: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/lpc32xx_adc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c index ef0a21d8ce15..a876ce755351 100644 --- a/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/drivers/staging/iio/adc/lpc32xx_adc.c @@ -183,7 +183,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) iodev->channels = lpc32xx_adc_iio_channels; iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels); - retval = iio_device_register(iodev); + retval = devm_iio_device_register(&pdev->dev, iodev); if (retval) return retval; @@ -192,15 +192,6 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) return 0; } -static int lpc32xx_adc_remove(struct platform_device *pdev) -{ - struct iio_dev *iodev = platform_get_drvdata(pdev); - - iio_device_unregister(iodev); - - return 0; -} - #ifdef CONFIG_OF static const struct of_device_id lpc32xx_adc_match[] = { { .compatible = "nxp,lpc3220-adc" }, @@ -211,7 +202,6 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match); static struct platform_driver lpc32xx_adc_driver = { .probe = lpc32xx_adc_probe, - .remove = lpc32xx_adc_remove, .driver = { .name = MOD_NAME, .owner = THIS_MODULE, -- cgit v1.2.3 From 334696bd603619bc001eb022e60c120fc8223ecb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: addac: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316-i2c.c | 6 ------ drivers/staging/iio/addac/adt7316-spi.c | 6 ------ drivers/staging/iio/addac/adt7316.c | 12 +----------- drivers/staging/iio/addac/adt7316.h | 1 - 4 files changed, 1 insertion(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 0feea5541d02..75ddd4f801a3 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -108,11 +108,6 @@ static int adt7316_i2c_probe(struct i2c_client *client, return adt7316_probe(&client->dev, &bus, id->name); } -static int adt7316_i2c_remove(struct i2c_client *client) -{ - return adt7316_remove(&client->dev); -} - static const struct i2c_device_id adt7316_i2c_id[] = { { "adt7316", 0 }, { "adt7317", 0 }, @@ -132,7 +127,6 @@ static struct i2c_driver adt7316_driver = { .owner = THIS_MODULE, }, .probe = adt7316_i2c_probe, - .remove = adt7316_i2c_remove, .id_table = adt7316_i2c_id, }; module_i2c_driver(adt7316_driver); diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c index 7f4f0a8245b4..e480abb72e4a 100644 --- a/drivers/staging/iio/addac/adt7316-spi.c +++ b/drivers/staging/iio/addac/adt7316-spi.c @@ -116,11 +116,6 @@ static int adt7316_spi_probe(struct spi_device *spi_dev) return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias); } -static int adt7316_spi_remove(struct spi_device *spi_dev) -{ - return adt7316_remove(&spi_dev->dev); -} - static const struct spi_device_id adt7316_spi_id[] = { { "adt7316", 0 }, { "adt7317", 0 }, @@ -140,7 +135,6 @@ static struct spi_driver adt7316_driver = { .owner = THIS_MODULE, }, .probe = adt7316_spi_probe, - .remove = adt7316_spi_remove, .id_table = adt7316_spi_id, }; module_spi_driver(adt7316_driver); diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 80266e801d56..16a8201228ff 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2166,7 +2166,7 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, if (ret) return -EIO; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) return ret; @@ -2177,16 +2177,6 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, } EXPORT_SYMBOL(adt7316_probe); -int adt7316_remove(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - iio_device_unregister(indio_dev); - - return 0; -} -EXPORT_SYMBOL(adt7316_remove); - MODULE_AUTHOR("Sonic Zhang "); MODULE_DESCRIPTION("Analog Devices ADT7316/7/8 and ADT7516/7/9 digital" " temperature sensor, ADC and DAC driver"); diff --git a/drivers/staging/iio/addac/adt7316.h b/drivers/staging/iio/addac/adt7316.h index 4d3efff46ae7..2dbfb499528d 100644 --- a/drivers/staging/iio/addac/adt7316.h +++ b/drivers/staging/iio/addac/adt7316.h @@ -31,6 +31,5 @@ extern const struct dev_pm_ops adt7316_pm_ops; #define ADT7316_PM_OPS NULL #endif int adt7316_probe(struct device *dev, struct adt7316_bus *bus, const char *name); -int adt7316_remove(struct device *dev); #endif -- cgit v1.2.3 From f952a30c39ea6d1dd44a33af7532d3a043c0c6a3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: adis16060: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adis16060_core.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index 6d3d771154f3..d5d395c2e3e4 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -167,7 +167,7 @@ static int adis16060_r_probe(struct spi_device *spi) indio_dev->channels = adis16060_channels; indio_dev->num_channels = ARRAY_SIZE(adis16060_channels); - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; @@ -175,13 +175,6 @@ static int adis16060_r_probe(struct spi_device *spi) return 0; } -/* fixme, confirm ordering in this function */ -static int adis16060_r_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - return 0; -} - static int adis16060_w_probe(struct spi_device *spi) { int ret; @@ -211,7 +204,6 @@ static struct spi_driver adis16060_r_driver = { .owner = THIS_MODULE, }, .probe = adis16060_r_probe, - .remove = adis16060_r_remove, }; static struct spi_driver adis16060_w_driver = { -- cgit v1.2.3 From 8664ed09aa63af9841da97645f42ff12ae39dd65 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: isl29018: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 488e690388c9..3660a43b5f08 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -585,7 +585,7 @@ static int isl29018_probe(struct i2c_client *client, indio_dev->name = id->name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; - err = iio_device_register(indio_dev); + err = devm_iio_device_register(&client->dev, indio_dev); if (err) { dev_err(&client->dev, "iio registration fails\n"); return err; @@ -594,16 +594,6 @@ static int isl29018_probe(struct i2c_client *client, return 0; } -static int isl29018_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - - dev_dbg(&client->dev, "%s()\n", __func__); - iio_device_unregister(indio_dev); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int isl29018_suspend(struct device *dev) { @@ -664,7 +654,6 @@ static struct i2c_driver isl29018_driver = { .of_match_table = isl29018_of_match, }, .probe = isl29018_probe, - .remove = isl29018_remove, .id_table = isl29018_id, }; module_i2c_driver(isl29018_driver); -- cgit v1.2.3 From 794a870e776717ccbd27676a551250613de9c40c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 29 Oct 2013 11:39:00 +0000 Subject: staging: iio: ad2s1200: Use devm_iio_device_register devm_iio_device_register simplifies the code. Signed-off-by: Sachin Kamat Signed-off-by: Jonathan Cameron --- drivers/staging/iio/resolver/ad2s1200.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index 62d30179301f..36eedd8a0ea9 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -131,7 +131,7 @@ static int ad2s1200_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(ad2s1200_channels); indio_dev->name = spi_get_device_id(spi)->name; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; @@ -142,13 +142,6 @@ static int ad2s1200_probe(struct spi_device *spi) return 0; } -static int ad2s1200_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - - return 0; -} - static const struct spi_device_id ad2s1200_id[] = { { "ad2s1200" }, { "ad2s1205" }, @@ -162,7 +155,6 @@ static struct spi_driver ad2s1200_driver = { .owner = THIS_MODULE, }, .probe = ad2s1200_probe, - .remove = ad2s1200_remove, .id_table = ad2s1200_id, }; module_spi_driver(ad2s1200_driver); -- cgit v1.2.3 From 2c22e6520ac87d8b12d4d9941e81d4119f2d903c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 25 Nov 2013 00:52:21 +0100 Subject: ACPI / scan: Use direct recurrence for device hierarchy walks Rework acpi_bus_trim() and acpi_bus_device_attach(), which is renamed as acpi_bus_attach(), to walk the list of each device object's children directly and call themselves recursively for each child instead of using acpi_walk_namespace(). This simplifies the code quite a bit and avoids the overhead of callbacks and the ACPICA's internal processing which are not really necessary for these two routines. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 120 ++++++++++++++++++++-------------------------------- 1 file changed, 45 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index cf773c918102..311904c720b1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1909,54 +1909,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device) return ret; } -static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_not_used) +static void acpi_bus_attach(struct acpi_device *device) { - struct acpi_device *device; - unsigned long long sta; + struct acpi_device *child; int ret; - /* - * Ignore errors ignored by acpi_bus_check_add() to avoid terminating - * namespace walks prematurely. - */ - if (acpi_bus_type_and_status(handle, &ret, &sta)) - return AE_OK; - - if (acpi_bus_get_device(handle, &device)) - return AE_CTRL_DEPTH; - - acpi_set_device_status(device, sta); + acpi_bus_get_status(device); /* Skip devices that are not present. */ - if (!acpi_device_is_present(device)) - goto err; - + if (!acpi_device_is_present(device)) { + device->flags.visited = false; + return; + } if (device->handler) - return AE_OK; + goto ok; if (!device->flags.initialized) { acpi_bus_update_power(device, NULL); device->flags.initialized = true; } + device->flags.visited = false; ret = acpi_scan_attach_handler(device); if (ret < 0) - goto err; + return; device->flags.match_driver = true; - if (ret > 0) - goto ok; - - ret = device_attach(&device->dev); - if (ret < 0) - goto err; - - ok: + if (!ret) { + ret = device_attach(&device->dev); + if (ret < 0) + return; + } device->flags.visited = true; - return AE_OK; - err: - device->flags.visited = false; - return AE_CTRL_DEPTH; + ok: + list_for_each_entry(child, &device->children, node) + acpi_bus_attach(child); } /** @@ -1976,64 +1962,48 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, int acpi_bus_scan(acpi_handle handle) { void *device = NULL; - int error = 0; if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, NULL, &device); - if (!device) - error = -ENODEV; - else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_device_attach, NULL, NULL, NULL); - - return error; -} -EXPORT_SYMBOL(acpi_bus_scan); - -static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_not_used) -{ - struct acpi_device *device = NULL; - - if (!acpi_bus_get_device(handle, &device)) { - struct acpi_scan_handler *dev_handler = device->handler; - - if (dev_handler) { - if (dev_handler->detach) - dev_handler->detach(device); - - device->handler = NULL; - } else { - device_release_driver(&device->dev); - } - /* - * Most likely, the device is going away, so put it into D3cold - * before that. - */ - acpi_device_set_power(device, ACPI_STATE_D3_COLD); - device->flags.initialized = false; - device->flags.visited = false; + if (device) { + acpi_bus_attach(device); + return 0; } - return AE_OK; + return -ENODEV; } +EXPORT_SYMBOL(acpi_bus_scan); /** - * acpi_bus_trim - Remove ACPI device node and all of its descendants - * @start: Root of the ACPI device nodes subtree to remove. + * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects. + * @adev: Root of the ACPI namespace scope to walk. * * Must be called under acpi_scan_lock. */ -void acpi_bus_trim(struct acpi_device *start) +void acpi_bus_trim(struct acpi_device *adev) { + struct acpi_scan_handler *handler = adev->handler; + struct acpi_device *child; + + list_for_each_entry_reverse(child, &adev->children, node) + acpi_bus_trim(child); + + if (handler) { + if (handler->detach) + handler->detach(adev); + + adev->handler = NULL; + } else { + device_release_driver(&adev->dev); + } /* - * Execute acpi_bus_device_detach() as a post-order callback to detach - * all ACPI drivers from the device nodes being removed. + * Most likely, the device is going away, so put it into D3cold before + * that. */ - acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, - acpi_bus_device_detach, NULL, NULL); - acpi_bus_device_detach(start->handle, 0, NULL, NULL); + acpi_device_set_power(adev, ACPI_STATE_D3_COLD); + adev->flags.initialized = false; + adev->flags.visited = false; } EXPORT_SYMBOL_GPL(acpi_bus_trim); -- cgit v1.2.3 From 4edd7901eee13f878e7b5fd5efba610e70b09313 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 12 Nov 2013 11:52:32 +0200 Subject: gpio/lynxpoint: add new ACPI ID Newer Intel PCHs have the same GPIO controller than Haswell but the ACPI ID is different. Add this ID to the driver supported IDs list. Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lynxpoint.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index a0804740a0b7..f1ca9d5880b6 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -438,6 +438,7 @@ static const struct dev_pm_ops lp_gpio_pm_ops = { static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { { "INT33C7", 0 }, + { "INT3437", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); -- cgit v1.2.3 From 661553b9c67c1c7496de5f603ee3d338ecad6850 Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Sat, 16 Nov 2013 02:01:04 +0200 Subject: gpio/omap: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Acked-by: Tony Lindgren Acked-by: Kevin Hilman Acked-by: Santosh Shilimkar Tested-by: Javier Martinez Canillas Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 188 +++++++++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f319c9ffd4a8..424319061e09 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -108,12 +108,12 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) u32 l; reg += bank->regs->direction; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (is_input) l |= 1 << gpio; else l &= ~(1 << gpio); - __raw_writel(l, reg); + writel_relaxed(l, reg); bank->context.oe = l; } @@ -132,7 +132,7 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable) bank->context.dataout &= ~l; } - __raw_writel(l, reg); + writel_relaxed(l, reg); } /* set data out value using mask register */ @@ -142,12 +142,12 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable) u32 gpio_bit = GPIO_BIT(bank, gpio); u32 l; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (enable) l |= gpio_bit; else l &= ~gpio_bit; - __raw_writel(l, reg); + writel_relaxed(l, reg); bank->context.dataout = l; } @@ -155,26 +155,26 @@ static int _get_gpio_datain(struct gpio_bank *bank, int offset) { void __iomem *reg = bank->base + bank->regs->datain; - return (__raw_readl(reg) & (1 << offset)) != 0; + return (readl_relaxed(reg) & (1 << offset)) != 0; } static int _get_gpio_dataout(struct gpio_bank *bank, int offset) { void __iomem *reg = bank->base + bank->regs->dataout; - return (__raw_readl(reg) & (1 << offset)) != 0; + return (readl_relaxed(reg) & (1 << offset)) != 0; } static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) { - int l = __raw_readl(base + reg); + int l = readl_relaxed(base + reg); if (set) l |= mask; else l &= ~mask; - __raw_writel(l, base + reg); + writel_relaxed(l, base + reg); } static inline void _gpio_dbck_enable(struct gpio_bank *bank) @@ -183,7 +183,7 @@ static inline void _gpio_dbck_enable(struct gpio_bank *bank) clk_enable(bank->dbck); bank->dbck_enabled = true; - __raw_writel(bank->dbck_enable_mask, + writel_relaxed(bank->dbck_enable_mask, bank->base + bank->regs->debounce_en); } } @@ -196,7 +196,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank) * enabled but the clock is not, GPIO module seems to be unable * to detect events and generate interrupts at least on OMAP3. */ - __raw_writel(0, bank->base + bank->regs->debounce_en); + writel_relaxed(0, bank->base + bank->regs->debounce_en); clk_disable(bank->dbck); bank->dbck_enabled = false; @@ -233,10 +233,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, clk_enable(bank->dbck); reg = bank->base + bank->regs->debounce; - __raw_writel(debounce, reg); + writel_relaxed(debounce, reg); reg = bank->base + bank->regs->debounce_en; - val = __raw_readl(reg); + val = readl_relaxed(reg); if (debounce) val |= l; @@ -244,7 +244,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, val &= ~l; bank->dbck_enable_mask = val; - __raw_writel(val, reg); + writel_relaxed(val, reg); clk_disable(bank->dbck); /* * Enable debounce clock per module. @@ -283,12 +283,12 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) bank->dbck_enable_mask &= ~gpio_bit; bank->context.debounce_en &= ~gpio_bit; - __raw_writel(bank->context.debounce_en, + writel_relaxed(bank->context.debounce_en, bank->base + bank->regs->debounce_en); if (!bank->dbck_enable_mask) { bank->context.debounce = 0; - __raw_writel(bank->context.debounce, bank->base + + writel_relaxed(bank->context.debounce, bank->base + bank->regs->debounce); clk_disable(bank->dbck); bank->dbck_enabled = false; @@ -311,18 +311,18 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, trigger & IRQ_TYPE_EDGE_FALLING); bank->context.leveldetect0 = - __raw_readl(bank->base + bank->regs->leveldetect0); + readl_relaxed(bank->base + bank->regs->leveldetect0); bank->context.leveldetect1 = - __raw_readl(bank->base + bank->regs->leveldetect1); + readl_relaxed(bank->base + bank->regs->leveldetect1); bank->context.risingdetect = - __raw_readl(bank->base + bank->regs->risingdetect); + readl_relaxed(bank->base + bank->regs->risingdetect); bank->context.fallingdetect = - __raw_readl(bank->base + bank->regs->fallingdetect); + readl_relaxed(bank->base + bank->regs->fallingdetect); if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); + readl_relaxed(bank->base + bank->regs->wkup_en); } /* This part needs to be executed always for OMAP{34xx, 44xx} */ @@ -347,8 +347,8 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, exit: bank->level_mask = - __raw_readl(bank->base + bank->regs->leveldetect0) | - __raw_readl(bank->base + bank->regs->leveldetect1); + readl_relaxed(bank->base + bank->regs->leveldetect0) | + readl_relaxed(bank->base + bank->regs->leveldetect1); } #ifdef CONFIG_ARCH_OMAP1 @@ -366,13 +366,13 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) reg += bank->regs->irqctrl; - l = __raw_readl(reg); + l = readl_relaxed(reg); if ((l >> gpio) & 1) l &= ~(1 << gpio); else l |= 1 << gpio; - __raw_writel(l, reg); + writel_relaxed(l, reg); } #else static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {} @@ -390,7 +390,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, } else if (bank->regs->irqctrl) { reg += bank->regs->irqctrl; - l = __raw_readl(reg); + l = readl_relaxed(reg); if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) bank->toggle_mask |= 1 << gpio; if (trigger & IRQ_TYPE_EDGE_RISING) @@ -400,7 +400,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, else return -EINVAL; - __raw_writel(l, reg); + writel_relaxed(l, reg); } else if (bank->regs->edgectrl1) { if (gpio & 0x08) reg += bank->regs->edgectrl2; @@ -408,7 +408,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, reg += bank->regs->edgectrl1; gpio &= 0x07; - l = __raw_readl(reg); + l = readl_relaxed(reg); l &= ~(3 << (gpio << 1)); if (trigger & IRQ_TYPE_EDGE_RISING) l |= 2 << (gpio << 1); @@ -418,8 +418,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, /* Enable wake-up during idle for dynamic tick */ _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); - __raw_writel(l, reg); + readl_relaxed(bank->base + bank->regs->wkup_en); + writel_relaxed(l, reg); } return 0; } @@ -430,17 +430,17 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset) void __iomem *reg = bank->base + bank->regs->pinctrl; /* Claim the pin for MPU */ - __raw_writel(__raw_readl(reg) | (1 << offset), reg); + writel_relaxed(readl_relaxed(reg) | (1 << offset), reg); } if (bank->regs->ctrl && !BANK_USED(bank)) { void __iomem *reg = bank->base + bank->regs->ctrl; u32 ctrl; - ctrl = __raw_readl(reg); + ctrl = readl_relaxed(reg); /* Module is enabled, clocks are not gated */ ctrl &= ~GPIO_MOD_CTRL_BIT; - __raw_writel(ctrl, reg); + writel_relaxed(ctrl, reg); bank->context.ctrl = ctrl; } } @@ -455,17 +455,17 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset) /* Disable wake-up during idle for dynamic tick */ _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); + readl_relaxed(bank->base + bank->regs->wkup_en); } if (bank->regs->ctrl && !BANK_USED(bank)) { void __iomem *reg = bank->base + bank->regs->ctrl; u32 ctrl; - ctrl = __raw_readl(reg); + ctrl = readl_relaxed(reg); /* Module is disabled, clocks are gated */ ctrl |= GPIO_MOD_CTRL_BIT; - __raw_writel(ctrl, reg); + writel_relaxed(ctrl, reg); bank->context.ctrl = ctrl; } } @@ -474,7 +474,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask) { void __iomem *reg = bank->base + bank->regs->direction; - return __raw_readl(reg) & mask; + return readl_relaxed(reg) & mask; } static int gpio_irq_type(struct irq_data *d, unsigned type) @@ -538,16 +538,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) void __iomem *reg = bank->base; reg += bank->regs->irqstatus; - __raw_writel(gpio_mask, reg); + writel_relaxed(gpio_mask, reg); /* Workaround for clearing DSP GPIO interrupts to allow retention */ if (bank->regs->irqstatus2) { reg = bank->base + bank->regs->irqstatus2; - __raw_writel(gpio_mask, reg); + writel_relaxed(gpio_mask, reg); } /* Flush posted write for the irq status to avoid spurious interrupts */ - __raw_readl(reg); + readl_relaxed(reg); } static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) @@ -562,7 +562,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) u32 mask = (1 << bank->width) - 1; reg += bank->regs->irqenable; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (bank->regs->irqenable_inv) l = ~l; l &= mask; @@ -580,7 +580,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 |= gpio_mask; } else { reg += bank->regs->irqenable; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (bank->regs->irqenable_inv) l &= ~gpio_mask; else @@ -588,7 +588,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 = l; } - __raw_writel(l, reg); + writel_relaxed(l, reg); } static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) @@ -602,7 +602,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 &= ~gpio_mask; } else { reg += bank->regs->irqenable; - l = __raw_readl(reg); + l = readl_relaxed(reg); if (bank->regs->irqenable_inv) l |= gpio_mask; else @@ -610,7 +610,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) bank->context.irqenable1 = l; } - __raw_writel(l, reg); + writel_relaxed(l, reg); } static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) @@ -646,7 +646,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) else bank->context.wake_en &= ~gpio_bit; - __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); + writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -748,7 +748,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) u32 enabled; enabled = _get_gpio_irqbank_mask(bank); - isr_saved = isr = __raw_readl(isr_reg) & enabled; + isr_saved = isr = readl_relaxed(isr_reg) & enabled; if (bank->level_mask) level_mask = bank->level_mask & enabled; @@ -883,7 +883,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev) unsigned long flags; spin_lock_irqsave(&bank->lock, flags); - __raw_writel(0xffff & ~bank->context.wake_en, mask_reg); + writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -898,7 +898,7 @@ static int omap_mpuio_resume_noirq(struct device *dev) unsigned long flags; spin_lock_irqsave(&bank->lock, flags); - __raw_writel(bank->context.wake_en, mask_reg); + writel_relaxed(bank->context.wake_en, mask_reg); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1011,7 +1011,7 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank) if (called || bank->regs->revision == USHRT_MAX) return; - rev = __raw_readw(bank->base + bank->regs->revision); + rev = readw_relaxed(bank->base + bank->regs->revision); pr_info("OMAP GPIO hardware version %d.%d\n", (rev >> 4) & 0x0f, rev & 0x0f); @@ -1032,20 +1032,20 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) l = 0xffff; if (bank->is_mpuio) { - __raw_writel(l, bank->base + bank->regs->irqenable); + writel_relaxed(l, bank->base + bank->regs->irqenable); return; } _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv); if (bank->regs->debounce_en) - __raw_writel(0, base + bank->regs->debounce_en); + writel_relaxed(0, base + bank->regs->debounce_en); /* Save OE default value (0xffffffff) in the context */ - bank->context.oe = __raw_readl(bank->base + bank->regs->direction); + bank->context.oe = readl_relaxed(bank->base + bank->regs->direction); /* Initialize interface clk ungated, module enabled */ if (bank->regs->ctrl) - __raw_writel(0, base + bank->regs->ctrl); + writel_relaxed(0, base + bank->regs->ctrl); bank->dbck = clk_get(bank->dev, "dbclk"); if (IS_ERR(bank->dbck)) @@ -1282,11 +1282,11 @@ static int omap_gpio_runtime_suspend(struct device *dev) */ wake_low = bank->context.leveldetect0 & bank->context.wake_en; if (wake_low) - __raw_writel(wake_low | bank->context.fallingdetect, + writel_relaxed(wake_low | bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); wake_hi = bank->context.leveldetect1 & bank->context.wake_en; if (wake_hi) - __raw_writel(wake_hi | bank->context.risingdetect, + writel_relaxed(wake_hi | bank->context.risingdetect, bank->base + bank->regs->risingdetect); if (!bank->enabled_non_wakeup_gpios) @@ -1301,7 +1301,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) * non-wakeup GPIOs. Otherwise spurious IRQs will be * generated. See OMAP2420 Errata item 1.101. */ - bank->saved_datain = __raw_readl(bank->base + + bank->saved_datain = readl_relaxed(bank->base + bank->regs->datain); l1 = bank->context.fallingdetect; l2 = bank->context.risingdetect; @@ -1309,8 +1309,8 @@ static int omap_gpio_runtime_suspend(struct device *dev) l1 &= ~bank->enabled_non_wakeup_gpios; l2 &= ~bank->enabled_non_wakeup_gpios; - __raw_writel(l1, bank->base + bank->regs->fallingdetect); - __raw_writel(l2, bank->base + bank->regs->risingdetect); + writel_relaxed(l1, bank->base + bank->regs->fallingdetect); + writel_relaxed(l2, bank->base + bank->regs->risingdetect); bank->workaround_enabled = true; @@ -1358,9 +1358,9 @@ static int omap_gpio_runtime_resume(struct device *dev) * generate a PRCM wakeup. Here we restore the * pre-runtime_suspend() values for edge triggering. */ - __raw_writel(bank->context.fallingdetect, + writel_relaxed(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); - __raw_writel(bank->context.risingdetect, + writel_relaxed(bank->context.risingdetect, bank->base + bank->regs->risingdetect); if (bank->loses_context) { @@ -1382,7 +1382,7 @@ static int omap_gpio_runtime_resume(struct device *dev) return 0; } - l = __raw_readl(bank->base + bank->regs->datain); + l = readl_relaxed(bank->base + bank->regs->datain); /* * Check if any of the non-wakeup interrupt GPIOs have changed @@ -1412,24 +1412,24 @@ static int omap_gpio_runtime_resume(struct device *dev) if (gen) { u32 old0, old1; - old0 = __raw_readl(bank->base + bank->regs->leveldetect0); - old1 = __raw_readl(bank->base + bank->regs->leveldetect1); + old0 = readl_relaxed(bank->base + bank->regs->leveldetect0); + old1 = readl_relaxed(bank->base + bank->regs->leveldetect1); if (!bank->regs->irqstatus_raw0) { - __raw_writel(old0 | gen, bank->base + + writel_relaxed(old0 | gen, bank->base + bank->regs->leveldetect0); - __raw_writel(old1 | gen, bank->base + + writel_relaxed(old1 | gen, bank->base + bank->regs->leveldetect1); } if (bank->regs->irqstatus_raw0) { - __raw_writel(old0 | l, bank->base + + writel_relaxed(old0 | l, bank->base + bank->regs->leveldetect0); - __raw_writel(old1 | l, bank->base + + writel_relaxed(old1 | l, bank->base + bank->regs->leveldetect1); } - __raw_writel(old0, bank->base + bank->regs->leveldetect0); - __raw_writel(old1, bank->base + bank->regs->leveldetect1); + writel_relaxed(old0, bank->base + bank->regs->leveldetect0); + writel_relaxed(old1, bank->base + bank->regs->leveldetect1); } bank->workaround_enabled = false; @@ -1471,55 +1471,55 @@ static void omap_gpio_init_context(struct gpio_bank *p) struct omap_gpio_reg_offs *regs = p->regs; void __iomem *base = p->base; - p->context.ctrl = __raw_readl(base + regs->ctrl); - p->context.oe = __raw_readl(base + regs->direction); - p->context.wake_en = __raw_readl(base + regs->wkup_en); - p->context.leveldetect0 = __raw_readl(base + regs->leveldetect0); - p->context.leveldetect1 = __raw_readl(base + regs->leveldetect1); - p->context.risingdetect = __raw_readl(base + regs->risingdetect); - p->context.fallingdetect = __raw_readl(base + regs->fallingdetect); - p->context.irqenable1 = __raw_readl(base + regs->irqenable); - p->context.irqenable2 = __raw_readl(base + regs->irqenable2); + p->context.ctrl = readl_relaxed(base + regs->ctrl); + p->context.oe = readl_relaxed(base + regs->direction); + p->context.wake_en = readl_relaxed(base + regs->wkup_en); + p->context.leveldetect0 = readl_relaxed(base + regs->leveldetect0); + p->context.leveldetect1 = readl_relaxed(base + regs->leveldetect1); + p->context.risingdetect = readl_relaxed(base + regs->risingdetect); + p->context.fallingdetect = readl_relaxed(base + regs->fallingdetect); + p->context.irqenable1 = readl_relaxed(base + regs->irqenable); + p->context.irqenable2 = readl_relaxed(base + regs->irqenable2); if (regs->set_dataout && p->regs->clr_dataout) - p->context.dataout = __raw_readl(base + regs->set_dataout); + p->context.dataout = readl_relaxed(base + regs->set_dataout); else - p->context.dataout = __raw_readl(base + regs->dataout); + p->context.dataout = readl_relaxed(base + regs->dataout); p->context_valid = true; } static void omap_gpio_restore_context(struct gpio_bank *bank) { - __raw_writel(bank->context.wake_en, + writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); - __raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); - __raw_writel(bank->context.leveldetect0, + writel_relaxed(bank->context.ctrl, bank->base + bank->regs->ctrl); + writel_relaxed(bank->context.leveldetect0, bank->base + bank->regs->leveldetect0); - __raw_writel(bank->context.leveldetect1, + writel_relaxed(bank->context.leveldetect1, bank->base + bank->regs->leveldetect1); - __raw_writel(bank->context.risingdetect, + writel_relaxed(bank->context.risingdetect, bank->base + bank->regs->risingdetect); - __raw_writel(bank->context.fallingdetect, + writel_relaxed(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); if (bank->regs->set_dataout && bank->regs->clr_dataout) - __raw_writel(bank->context.dataout, + writel_relaxed(bank->context.dataout, bank->base + bank->regs->set_dataout); else - __raw_writel(bank->context.dataout, + writel_relaxed(bank->context.dataout, bank->base + bank->regs->dataout); - __raw_writel(bank->context.oe, bank->base + bank->regs->direction); + writel_relaxed(bank->context.oe, bank->base + bank->regs->direction); if (bank->dbck_enable_mask) { - __raw_writel(bank->context.debounce, bank->base + + writel_relaxed(bank->context.debounce, bank->base + bank->regs->debounce); - __raw_writel(bank->context.debounce_en, + writel_relaxed(bank->context.debounce_en, bank->base + bank->regs->debounce_en); } - __raw_writel(bank->context.irqenable1, + writel_relaxed(bank->context.irqenable1, bank->base + bank->regs->irqenable); - __raw_writel(bank->context.irqenable2, + writel_relaxed(bank->context.irqenable2, bank->base + bank->regs->irqenable2); } #endif /* CONFIG_PM_RUNTIME */ -- cgit v1.2.3 From fba968a1e6b84be01e548f4b28b78e0542f3adaa Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:08 +0900 Subject: gpio: rcar: Use lazy disable Set the ->irq_enable() and ->irq_disable() methods to NULL to enable lazy disable of interrupts. This by itself provides some level of optimization, but is mainly enabled as ground work for future Suspend-to-RAM wake up support. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d3f15ae93bd3..a194bdb413fd 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -369,8 +369,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip->name = name; irq_chip->irq_mask = gpio_rcar_irq_disable; irq_chip->irq_unmask = gpio_rcar_irq_enable; - irq_chip->irq_enable = gpio_rcar_irq_enable; - irq_chip->irq_disable = gpio_rcar_irq_disable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED; -- cgit v1.2.3 From 403961120667bed7161777d33483596edd0b05f2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:17 +0900 Subject: gpio: rcar: Enable mask on suspend Now when lazy interrupt disable has been enabled in the driver then extend the code to set IRQCHIP_MASK_ON_SUSPEND which tells the core that only IRQs marked as wakeups need to stay enabled during Suspend-to-RAM. Tested on the Lager board with GPIO-keys and Suspend-to-RAM. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index a194bdb413fd..d2c34da7b3bf 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -370,7 +370,8 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip->irq_mask = gpio_rcar_irq_disable; irq_chip->irq_unmask = gpio_rcar_irq_enable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; - irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED; + irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED + | IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->config.number_of_pins, -- cgit v1.2.3 From 969bf7aec86ccd6ce1934ed634e29517ae2b8e10 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:26 +0900 Subject: gpio: em: Setup gpiochip->dev Make sure gpio_chip->dev is setup so of_gpiochip_add() will work as expected. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index ec190361bf2e..b1decec9b359 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -328,6 +328,7 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->request = em_gio_request; gpio_chip->free = em_gio_free; gpio_chip->label = name; + gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = pdata->gpio_base; gpio_chip->ngpio = pdata->number_of_pins; -- cgit v1.2.3 From 664734c012e6f3a88b2da4c586002cd62a277003 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:35 +0900 Subject: gpio: em: Use lazy disable Set the ->irq_enable() and ->irq_disable() methods to NULL to enable lazy disable of interrupts. This by itself provides some level of optimization, but is mainly enabled as ground work for future Suspend-to-RAM wake up support. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index b1decec9b359..225eda662c6c 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -337,8 +337,6 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->name = name; irq_chip->irq_mask = em_gio_irq_disable; irq_chip->irq_unmask = em_gio_irq_enable; - irq_chip->irq_enable = em_gio_irq_enable; - irq_chip->irq_disable = em_gio_irq_disable; irq_chip->irq_set_type = em_gio_irq_set_type; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; -- cgit v1.2.3 From 03621b60529edfbeb32d199fa754da19574cfefc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Nov 2013 09:23:44 +0900 Subject: gpio: em: Enable mask on suspend Now when lazy interrupt disable has been enabled in the driver then extend the code to set IRQCHIP_MASK_ON_SUSPEND which tells the core that only IRQs marked as wakeups need to stay enabled during Suspend-to-RAM. Tested on the KZM9D board with GPIO-keys. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index 225eda662c6c..be7e3b92f986 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -338,7 +338,7 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_mask = em_gio_irq_disable; irq_chip->irq_unmask = em_gio_irq_enable; irq_chip->irq_set_type = em_gio_irq_set_type; - irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; + irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, pdata->number_of_pins, -- cgit v1.2.3 From bc41f9f138bd93b82b08f84ca55b7da2acb847b3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Nov 2013 13:46:17 +0100 Subject: sh-pfc: r8a7791: Fix DU pin groups organisation Rename the sync_1 group to sync as the device has a single sync pin group for the DU, move the cde_disp mux array right after the corresponding pins array, and split the clk_in pins in three separate groups as the pins can be used independently. Signed-off-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index bf76a654c02f..d26c16360161 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -1730,11 +1730,11 @@ static const unsigned int du_clk_out_1_pins[] = { static const unsigned int du_clk_out_1_mux[] = { DU1_DOTCLKOUT1_MARK }; -static const unsigned int du_sync_1_pins[] = { +static const unsigned int du_sync_pins[] = { /* EXVSYNC/VSYNC, EXHSYNC/HSYNC, EXDISP/EXODDF/EXCDE */ RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 27), }; -static const unsigned int du_sync_1_mux[] = { +static const unsigned int du_sync_mux[] = { DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK, DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK }; @@ -1742,6 +1742,9 @@ static const unsigned int du_cde_disp_pins[] = { /* CDE DISP */ RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30), }; +static const unsigned int du_cde_disp_mux[] = { + DU1_CDE_MARK, DU1_DISP_MARK +}; static const unsigned int du0_clk_in_pins[] = { /* CLKIN */ RCAR_GP_PIN(6, 31), @@ -1749,15 +1752,26 @@ static const unsigned int du0_clk_in_pins[] = { static const unsigned int du0_clk_in_mux[] = { DU0_DOTCLKIN_MARK }; -static const unsigned int du_cde_disp_mux[] = { - DU1_CDE_MARK, DU1_DISP_MARK -}; static const unsigned int du1_clk_in_pins[] = { /* CLKIN */ - RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 19), RCAR_GP_PIN(3, 24), + RCAR_GP_PIN(3, 24), }; static const unsigned int du1_clk_in_mux[] = { - DU1_DOTCLKIN_C_MARK, DU1_DOTCLKIN_B_MARK, DU1_DOTCLKIN_MARK + DU1_DOTCLKIN_MARK +}; +static const unsigned int du1_clk_in_b_pins[] = { + /* CLKIN */ + RCAR_GP_PIN(7, 19), +}; +static const unsigned int du1_clk_in_b_mux[] = { + DU1_DOTCLKIN_B_MARK, +}; +static const unsigned int du1_clk_in_c_pins[] = { + /* CLKIN */ + RCAR_GP_PIN(7, 20), +}; +static const unsigned int du1_clk_in_c_mux[] = { + DU1_DOTCLKIN_C_MARK, }; /* - ETH -------------------------------------------------------------------- */ static const unsigned int eth_link_pins[] = { @@ -2670,10 +2684,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(du_rgb888), SH_PFC_PIN_GROUP(du_clk_out_0), SH_PFC_PIN_GROUP(du_clk_out_1), - SH_PFC_PIN_GROUP(du_sync_1), + SH_PFC_PIN_GROUP(du_sync), SH_PFC_PIN_GROUP(du_cde_disp), SH_PFC_PIN_GROUP(du0_clk_in), SH_PFC_PIN_GROUP(du1_clk_in), + SH_PFC_PIN_GROUP(du1_clk_in_b), + SH_PFC_PIN_GROUP(du1_clk_in_c), SH_PFC_PIN_GROUP(eth_link), SH_PFC_PIN_GROUP(eth_magic), SH_PFC_PIN_GROUP(eth_mdio), @@ -2805,7 +2821,7 @@ static const char * const du_groups[] = { "du_rgb888", "du_clk_out_0", "du_clk_out_1", - "du_sync_1", + "du_sync", "du_cde_disp", }; @@ -2815,6 +2831,8 @@ static const char * const du0_groups[] = { static const char * const du1_groups[] = { "du1_clk_in", + "du1_clk_in_b", + "du1_clk_in_c", }; static const char * const eth_groups[] = { -- cgit v1.2.3 From 4705845b30e56a49f50ed84ba2dbff4f8fd389e9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 14 Nov 2013 19:51:18 +0100 Subject: pinctrl: nomadik: always display IRQ in debugfs As we now grab IRQs also without first reserving the GPIO line, let's print the mapped IRQ unconditionally in the debugfs file as well. Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 7111c3b59130..cea951f5fa49 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -846,14 +846,14 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, (mode < 0) ? "unknown" : modes[mode], pull ? "pull" : "none"); - if (label && !is_out) { - int irq = gpio_to_irq(gpio); + if (!is_out) { + int irq = gpio_to_irq(gpio); struct irq_desc *desc = irq_to_desc(irq); /* This races with request_irq(), set_irq_type(), * and set_irq_wake() ... but those are "rare". */ - if (irq >= 0 && desc->action) { + if (irq > 0 && desc && desc->action) { char *trigger; u32 bitmask = nmk_gpio_get_bitmask(gpio); -- cgit v1.2.3 From b9f2f2ecce737910be1333609d43c8fbbfe8e68f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 16 Nov 2013 22:17:34 +0800 Subject: pinctrl: imx: drop redundant OF dependency The IMX/MXC selects USE_OF at architecture level, so the OF dependency at individual SoC pinctrl driver level can just be dropped. Signed-off-by: Shawn Guo Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 33f9dc1f14fd..e216a46f4194 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -116,7 +116,6 @@ config PINCTRL_IMX1_CORE config PINCTRL_IMX27 bool "IMX27 pinctrl driver" - depends on OF depends on SOC_IMX27 select PINCTRL_IMX1_CORE help @@ -124,7 +123,6 @@ config PINCTRL_IMX27 config PINCTRL_IMX35 bool "IMX35 pinctrl driver" - depends on OF depends on SOC_IMX35 select PINCTRL_IMX help @@ -132,7 +130,6 @@ config PINCTRL_IMX35 config PINCTRL_IMX50 bool "IMX50 pinctrl driver" - depends on OF depends on SOC_IMX50 select PINCTRL_IMX help @@ -140,7 +137,6 @@ config PINCTRL_IMX50 config PINCTRL_IMX51 bool "IMX51 pinctrl driver" - depends on OF depends on SOC_IMX51 select PINCTRL_IMX help @@ -148,7 +144,6 @@ config PINCTRL_IMX51 config PINCTRL_IMX53 bool "IMX53 pinctrl driver" - depends on OF depends on SOC_IMX53 select PINCTRL_IMX help @@ -156,7 +151,6 @@ config PINCTRL_IMX53 config PINCTRL_IMX6Q bool "IMX6Q/DL pinctrl driver" - depends on OF depends on SOC_IMX6Q select PINCTRL_IMX help @@ -164,7 +158,6 @@ config PINCTRL_IMX6Q config PINCTRL_IMX6SL bool "IMX6SL pinctrl driver" - depends on OF depends on SOC_IMX6SL select PINCTRL_IMX help @@ -172,7 +165,6 @@ config PINCTRL_IMX6SL config PINCTRL_VF610 bool "Freescale Vybrid VF610 pinctrl driver" - depends on OF depends on SOC_VF610 select PINCTRL_IMX help -- cgit v1.2.3 From 31d610f19670825a0058b70f44570e9ab21a0011 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 11 Nov 2013 19:19:47 +0100 Subject: pinctrl: imx1-core populate subdevices Support gpio devicetree subnodes to allow a more detailed DT hardware description. Signed-off-by: Markus Pargmann Signed-off-by: Linus Walleij --- .../bindings/pinctrl/fsl,imx27-pinctrl.txt | 22 ++++++++++++++++++++++ drivers/pinctrl/pinctrl-imx1-core.c | 7 +++++++ 2 files changed, 29 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt index 353eca0efbf8..d1706ea82572 100644 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt @@ -52,12 +52,25 @@ Required properties for pin configuration node: CONFIG can be 0 or 1, meaning Pullup disable/enable. +The iomux controller has gpio child nodes which are embedded in the iomux +control registers. They have to be defined as child nodes of the iomux device +node. If gpio subnodes are defined "#address-cells", "#size-cells" and "ranges" +properties for the iomux device node are required. Example: iomuxc: iomuxc@10015000 { compatible = "fsl,imx27-iomuxc"; reg = <0x10015000 0x600>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio1: gpio@10015000 { + ... + }; + + ... uart { pinctrl_uart1: uart-1 { @@ -83,6 +96,15 @@ The above example using macros: iomuxc: iomuxc@10015000 { compatible = "fsl,imx27-iomuxc"; reg = <0x10015000 0x600>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio1: gpio@10015000 { + ... + }; + + ... uart { pinctrl_uart1: uart-1 { diff --git a/drivers/pinctrl/pinctrl-imx1-core.c b/drivers/pinctrl/pinctrl-imx1-core.c index f77914ac081a..17aecde1b51d 100644 --- a/drivers/pinctrl/pinctrl-imx1-core.c +++ b/drivers/pinctrl/pinctrl-imx1-core.c @@ -638,6 +638,13 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev, return -EINVAL; } + ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (ret) { + pinctrl_unregister(ipctl->pctl); + dev_err(&pdev->dev, "Failed to populate subdevices\n"); + return ret; + } + dev_info(&pdev->dev, "initialized IMX pinctrl driver\n"); return 0; -- cgit v1.2.3 From b4a87c9b966f71922e54a336e90b485a5fba19b8 Mon Sep 17 00:00:00 2001 From: Denis Carikli Date: Wed, 6 Nov 2013 09:52:15 +0100 Subject: pinctrl: pinctrl-imx: add imx25 pinctrl driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is mostly cut and paste from the imx35 pinctrl driver. The data was generated using sed and awk on arch/arm/plat-mxc/include/mach/iomux-mx25.h. Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: Stephen Warren Cc: Ian Campbell Cc: devicetree@vger.kernel.org Cc: Shawn Guo Cc: Sascha Hauer Cc: linux-arm-kernel@lists.infradead.org Cc: Russell King Cc: Linus Walleij Cc: Eric Bénard Signed-off-by: Denis Carikli Acked-by: Sascha Hauer Signed-off-by: Linus Walleij --- .../bindings/pinctrl/fsl,imx25-pinctrl.txt | 23 ++ drivers/pinctrl/Kconfig | 9 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-imx25.c | 351 +++++++++++++++++++++ 4 files changed, 384 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt create mode 100644 drivers/pinctrl/pinctrl-imx25.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt new file mode 100644 index 000000000000..fd653bde18d5 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt @@ -0,0 +1,23 @@ +* Freescale IMX25 IOMUX Controller + +Please refer to fsl,imx-pinctrl.txt in this directory for common binding part +and usage. + +CONFIG bits definition: +PAD_CTL_HYS (1 << 8) +PAD_CTL_PKE (1 << 7) +PAD_CTL_PUE (1 << 6) +PAD_CTL_PUS_100K_DOWN (0 << 4) +PAD_CTL_PUS_47K_UP (1 << 4) +PAD_CTL_PUS_100K_UP (2 << 4) +PAD_CTL_PUS_22K_UP (3 << 4) +PAD_CTL_ODE_CMOS (0 << 3) +PAD_CTL_ODE_OPENDRAIN (1 << 3) +PAD_CTL_DSE_NOMINAL (0 << 1) +PAD_CTL_DSE_HIGH (1 << 1) +PAD_CTL_DSE_MAX (2 << 1) +PAD_CTL_SRE_FAST (1 << 0) +PAD_CTL_SRE_SLOW (0 << 0) + +Refer to imx25-pinfunc.h in device tree source folder for all available +imx25 PIN_FUNC_ID. diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e216a46f4194..5e4418f4282b 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -121,6 +121,15 @@ config PINCTRL_IMX27 help Say Y here to enable the imx27 pinctrl driver + +config PINCTRL_IMX25 + bool "IMX25 pinctrl driver" + depends on OF + depends on SOC_IMX25 + select PINCTRL_IMX + help + Say Y here to enable the imx25 pinctrl driver + config PINCTRL_IMX35 bool "IMX35 pinctrl driver" depends on SOC_IMX35 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 4f7be2921aa5..dcb01a4ef653 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o +obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o diff --git a/drivers/pinctrl/pinctrl-imx25.c b/drivers/pinctrl/pinctrl-imx25.c new file mode 100644 index 000000000000..1aae1b61c4dc --- /dev/null +++ b/drivers/pinctrl/pinctrl-imx25.c @@ -0,0 +1,351 @@ +/* + * imx25 pinctrl driver. + * + * Copyright 2013 Eukréa Electromatique + * + * This driver was mostly copied from the imx51 pinctrl driver which has: + * + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012 Linaro, Inc. + * + * Author: Denis Carikli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pinctrl-imx.h" + +enum imx25_pads { + MX25_PAD_RESERVE0 = 1, + MX25_PAD_RESERVE1 = 2, + MX25_PAD_A10 = 3, + MX25_PAD_A13 = 4, + MX25_PAD_A14 = 5, + MX25_PAD_A15 = 6, + MX25_PAD_A16 = 7, + MX25_PAD_A17 = 8, + MX25_PAD_A18 = 9, + MX25_PAD_A19 = 10, + MX25_PAD_A20 = 11, + MX25_PAD_A21 = 12, + MX25_PAD_A22 = 13, + MX25_PAD_A23 = 14, + MX25_PAD_A24 = 15, + MX25_PAD_A25 = 16, + MX25_PAD_EB0 = 17, + MX25_PAD_EB1 = 18, + MX25_PAD_OE = 19, + MX25_PAD_CS0 = 20, + MX25_PAD_CS1 = 21, + MX25_PAD_CS4 = 22, + MX25_PAD_CS5 = 23, + MX25_PAD_NF_CE0 = 24, + MX25_PAD_ECB = 25, + MX25_PAD_LBA = 26, + MX25_PAD_BCLK = 27, + MX25_PAD_RW = 28, + MX25_PAD_NFWE_B = 29, + MX25_PAD_NFRE_B = 30, + MX25_PAD_NFALE = 31, + MX25_PAD_NFCLE = 32, + MX25_PAD_NFWP_B = 33, + MX25_PAD_NFRB = 34, + MX25_PAD_D15 = 35, + MX25_PAD_D14 = 36, + MX25_PAD_D13 = 37, + MX25_PAD_D12 = 38, + MX25_PAD_D11 = 39, + MX25_PAD_D10 = 40, + MX25_PAD_D9 = 41, + MX25_PAD_D8 = 42, + MX25_PAD_D7 = 43, + MX25_PAD_D6 = 44, + MX25_PAD_D5 = 45, + MX25_PAD_D4 = 46, + MX25_PAD_D3 = 47, + MX25_PAD_D2 = 48, + MX25_PAD_D1 = 49, + MX25_PAD_D0 = 50, + MX25_PAD_LD0 = 51, + MX25_PAD_LD1 = 52, + MX25_PAD_LD2 = 53, + MX25_PAD_LD3 = 54, + MX25_PAD_LD4 = 55, + MX25_PAD_LD5 = 56, + MX25_PAD_LD6 = 57, + MX25_PAD_LD7 = 58, + MX25_PAD_LD8 = 59, + MX25_PAD_LD9 = 60, + MX25_PAD_LD10 = 61, + MX25_PAD_LD11 = 62, + MX25_PAD_LD12 = 63, + MX25_PAD_LD13 = 64, + MX25_PAD_LD14 = 65, + MX25_PAD_LD15 = 66, + MX25_PAD_HSYNC = 67, + MX25_PAD_VSYNC = 68, + MX25_PAD_LSCLK = 69, + MX25_PAD_OE_ACD = 70, + MX25_PAD_CONTRAST = 71, + MX25_PAD_PWM = 72, + MX25_PAD_CSI_D2 = 73, + MX25_PAD_CSI_D3 = 74, + MX25_PAD_CSI_D4 = 75, + MX25_PAD_CSI_D5 = 76, + MX25_PAD_CSI_D6 = 77, + MX25_PAD_CSI_D7 = 78, + MX25_PAD_CSI_D8 = 79, + MX25_PAD_CSI_D9 = 80, + MX25_PAD_CSI_MCLK = 81, + MX25_PAD_CSI_VSYNC = 82, + MX25_PAD_CSI_HSYNC = 83, + MX25_PAD_CSI_PIXCLK = 84, + MX25_PAD_I2C1_CLK = 85, + MX25_PAD_I2C1_DAT = 86, + MX25_PAD_CSPI1_MOSI = 87, + MX25_PAD_CSPI1_MISO = 88, + MX25_PAD_CSPI1_SS0 = 89, + MX25_PAD_CSPI1_SS1 = 90, + MX25_PAD_CSPI1_SCLK = 91, + MX25_PAD_CSPI1_RDY = 92, + MX25_PAD_UART1_RXD = 93, + MX25_PAD_UART1_TXD = 94, + MX25_PAD_UART1_RTS = 95, + MX25_PAD_UART1_CTS = 96, + MX25_PAD_UART2_RXD = 97, + MX25_PAD_UART2_TXD = 98, + MX25_PAD_UART2_RTS = 99, + MX25_PAD_UART2_CTS = 100, + MX25_PAD_SD1_CMD = 101, + MX25_PAD_SD1_CLK = 102, + MX25_PAD_SD1_DATA0 = 103, + MX25_PAD_SD1_DATA1 = 104, + MX25_PAD_SD1_DATA2 = 105, + MX25_PAD_SD1_DATA3 = 106, + MX25_PAD_KPP_ROW0 = 107, + MX25_PAD_KPP_ROW1 = 108, + MX25_PAD_KPP_ROW2 = 109, + MX25_PAD_KPP_ROW3 = 110, + MX25_PAD_KPP_COL0 = 111, + MX25_PAD_KPP_COL1 = 112, + MX25_PAD_KPP_COL2 = 113, + MX25_PAD_KPP_COL3 = 114, + MX25_PAD_FEC_MDC = 115, + MX25_PAD_FEC_MDIO = 116, + MX25_PAD_FEC_TDATA0 = 117, + MX25_PAD_FEC_TDATA1 = 118, + MX25_PAD_FEC_TX_EN = 119, + MX25_PAD_FEC_RDATA0 = 120, + MX25_PAD_FEC_RDATA1 = 121, + MX25_PAD_FEC_RX_DV = 122, + MX25_PAD_FEC_TX_CLK = 123, + MX25_PAD_RTCK = 124, + MX25_PAD_DE_B = 125, + MX25_PAD_GPIO_A = 126, + MX25_PAD_GPIO_B = 127, + MX25_PAD_GPIO_C = 128, + MX25_PAD_GPIO_D = 129, + MX25_PAD_GPIO_E = 130, + MX25_PAD_GPIO_F = 131, + MX25_PAD_EXT_ARMCLK = 132, + MX25_PAD_UPLL_BYPCLK = 133, + MX25_PAD_VSTBY_REQ = 134, + MX25_PAD_VSTBY_ACK = 135, + MX25_PAD_POWER_FAIL = 136, + MX25_PAD_CLKO = 137, + MX25_PAD_BOOT_MODE0 = 138, + MX25_PAD_BOOT_MODE1 = 139, +}; + +/* Pad names for the pinmux subsystem */ +static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = { + IMX_PINCTRL_PIN(MX25_PAD_RESERVE0), + IMX_PINCTRL_PIN(MX25_PAD_RESERVE1), + IMX_PINCTRL_PIN(MX25_PAD_A10), + IMX_PINCTRL_PIN(MX25_PAD_A13), + IMX_PINCTRL_PIN(MX25_PAD_A14), + IMX_PINCTRL_PIN(MX25_PAD_A15), + IMX_PINCTRL_PIN(MX25_PAD_A16), + IMX_PINCTRL_PIN(MX25_PAD_A17), + IMX_PINCTRL_PIN(MX25_PAD_A18), + IMX_PINCTRL_PIN(MX25_PAD_A19), + IMX_PINCTRL_PIN(MX25_PAD_A20), + IMX_PINCTRL_PIN(MX25_PAD_A21), + IMX_PINCTRL_PIN(MX25_PAD_A22), + IMX_PINCTRL_PIN(MX25_PAD_A23), + IMX_PINCTRL_PIN(MX25_PAD_A24), + IMX_PINCTRL_PIN(MX25_PAD_A25), + IMX_PINCTRL_PIN(MX25_PAD_EB0), + IMX_PINCTRL_PIN(MX25_PAD_EB1), + IMX_PINCTRL_PIN(MX25_PAD_OE), + IMX_PINCTRL_PIN(MX25_PAD_CS0), + IMX_PINCTRL_PIN(MX25_PAD_CS1), + IMX_PINCTRL_PIN(MX25_PAD_CS4), + IMX_PINCTRL_PIN(MX25_PAD_CS5), + IMX_PINCTRL_PIN(MX25_PAD_NF_CE0), + IMX_PINCTRL_PIN(MX25_PAD_ECB), + IMX_PINCTRL_PIN(MX25_PAD_LBA), + IMX_PINCTRL_PIN(MX25_PAD_BCLK), + IMX_PINCTRL_PIN(MX25_PAD_RW), + IMX_PINCTRL_PIN(MX25_PAD_NFWE_B), + IMX_PINCTRL_PIN(MX25_PAD_NFRE_B), + IMX_PINCTRL_PIN(MX25_PAD_NFALE), + IMX_PINCTRL_PIN(MX25_PAD_NFCLE), + IMX_PINCTRL_PIN(MX25_PAD_NFWP_B), + IMX_PINCTRL_PIN(MX25_PAD_NFRB), + IMX_PINCTRL_PIN(MX25_PAD_D15), + IMX_PINCTRL_PIN(MX25_PAD_D14), + IMX_PINCTRL_PIN(MX25_PAD_D13), + IMX_PINCTRL_PIN(MX25_PAD_D12), + IMX_PINCTRL_PIN(MX25_PAD_D11), + IMX_PINCTRL_PIN(MX25_PAD_D10), + IMX_PINCTRL_PIN(MX25_PAD_D9), + IMX_PINCTRL_PIN(MX25_PAD_D8), + IMX_PINCTRL_PIN(MX25_PAD_D7), + IMX_PINCTRL_PIN(MX25_PAD_D6), + IMX_PINCTRL_PIN(MX25_PAD_D5), + IMX_PINCTRL_PIN(MX25_PAD_D4), + IMX_PINCTRL_PIN(MX25_PAD_D3), + IMX_PINCTRL_PIN(MX25_PAD_D2), + IMX_PINCTRL_PIN(MX25_PAD_D1), + IMX_PINCTRL_PIN(MX25_PAD_D0), + IMX_PINCTRL_PIN(MX25_PAD_LD0), + IMX_PINCTRL_PIN(MX25_PAD_LD1), + IMX_PINCTRL_PIN(MX25_PAD_LD2), + IMX_PINCTRL_PIN(MX25_PAD_LD3), + IMX_PINCTRL_PIN(MX25_PAD_LD4), + IMX_PINCTRL_PIN(MX25_PAD_LD5), + IMX_PINCTRL_PIN(MX25_PAD_LD6), + IMX_PINCTRL_PIN(MX25_PAD_LD7), + IMX_PINCTRL_PIN(MX25_PAD_LD8), + IMX_PINCTRL_PIN(MX25_PAD_LD9), + IMX_PINCTRL_PIN(MX25_PAD_LD10), + IMX_PINCTRL_PIN(MX25_PAD_LD11), + IMX_PINCTRL_PIN(MX25_PAD_LD12), + IMX_PINCTRL_PIN(MX25_PAD_LD13), + IMX_PINCTRL_PIN(MX25_PAD_LD14), + IMX_PINCTRL_PIN(MX25_PAD_LD15), + IMX_PINCTRL_PIN(MX25_PAD_HSYNC), + IMX_PINCTRL_PIN(MX25_PAD_VSYNC), + IMX_PINCTRL_PIN(MX25_PAD_LSCLK), + IMX_PINCTRL_PIN(MX25_PAD_OE_ACD), + IMX_PINCTRL_PIN(MX25_PAD_CONTRAST), + IMX_PINCTRL_PIN(MX25_PAD_PWM), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D2), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D3), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D4), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D5), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D6), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D7), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D8), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D9), + IMX_PINCTRL_PIN(MX25_PAD_CSI_MCLK), + IMX_PINCTRL_PIN(MX25_PAD_CSI_VSYNC), + IMX_PINCTRL_PIN(MX25_PAD_CSI_HSYNC), + IMX_PINCTRL_PIN(MX25_PAD_CSI_PIXCLK), + IMX_PINCTRL_PIN(MX25_PAD_I2C1_CLK), + IMX_PINCTRL_PIN(MX25_PAD_I2C1_DAT), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_MOSI), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_MISO), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_SS0), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_SS1), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_SCLK), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_RDY), + IMX_PINCTRL_PIN(MX25_PAD_UART1_RXD), + IMX_PINCTRL_PIN(MX25_PAD_UART1_TXD), + IMX_PINCTRL_PIN(MX25_PAD_UART1_RTS), + IMX_PINCTRL_PIN(MX25_PAD_UART1_CTS), + IMX_PINCTRL_PIN(MX25_PAD_UART2_RXD), + IMX_PINCTRL_PIN(MX25_PAD_UART2_TXD), + IMX_PINCTRL_PIN(MX25_PAD_UART2_RTS), + IMX_PINCTRL_PIN(MX25_PAD_UART2_CTS), + IMX_PINCTRL_PIN(MX25_PAD_SD1_CMD), + IMX_PINCTRL_PIN(MX25_PAD_SD1_CLK), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA0), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA1), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA2), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA3), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW0), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW1), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW2), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW3), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL0), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL1), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL2), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL3), + IMX_PINCTRL_PIN(MX25_PAD_FEC_MDC), + IMX_PINCTRL_PIN(MX25_PAD_FEC_MDIO), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TDATA0), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TDATA1), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TX_EN), + IMX_PINCTRL_PIN(MX25_PAD_FEC_RDATA0), + IMX_PINCTRL_PIN(MX25_PAD_FEC_RDATA1), + IMX_PINCTRL_PIN(MX25_PAD_FEC_RX_DV), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TX_CLK), + IMX_PINCTRL_PIN(MX25_PAD_RTCK), + IMX_PINCTRL_PIN(MX25_PAD_DE_B), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_A), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_B), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_C), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_D), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_E), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_F), + IMX_PINCTRL_PIN(MX25_PAD_EXT_ARMCLK), + IMX_PINCTRL_PIN(MX25_PAD_UPLL_BYPCLK), + IMX_PINCTRL_PIN(MX25_PAD_VSTBY_REQ), + IMX_PINCTRL_PIN(MX25_PAD_VSTBY_ACK), + IMX_PINCTRL_PIN(MX25_PAD_POWER_FAIL), + IMX_PINCTRL_PIN(MX25_PAD_CLKO), + IMX_PINCTRL_PIN(MX25_PAD_BOOT_MODE0), + IMX_PINCTRL_PIN(MX25_PAD_BOOT_MODE1), +}; + +static struct imx_pinctrl_soc_info imx25_pinctrl_info = { + .pins = imx25_pinctrl_pads, + .npins = ARRAY_SIZE(imx25_pinctrl_pads), +}; + +static struct of_device_id imx25_pinctrl_of_match[] = { + { .compatible = "fsl,imx25-iomuxc", }, + { /* sentinel */ } +}; + +static int imx25_pinctrl_probe(struct platform_device *pdev) +{ + return imx_pinctrl_probe(pdev, &imx25_pinctrl_info); +} + +static struct platform_driver imx25_pinctrl_driver = { + .driver = { + .name = "imx25-pinctrl", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(imx25_pinctrl_of_match), + }, + .probe = imx25_pinctrl_probe, + .remove = imx_pinctrl_remove, +}; + +static int __init imx25_pinctrl_init(void) +{ + return platform_driver_register(&imx25_pinctrl_driver); +} +arch_initcall(imx25_pinctrl_init); + +static void __exit imx25_pinctrl_exit(void) +{ + platform_driver_unregister(&imx25_pinctrl_driver); +} +module_exit(imx25_pinctrl_exit); +MODULE_AUTHOR("Denis Carikli "); +MODULE_DESCRIPTION("Freescale IMX25 pinctrl driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From b33ecdd1cdeb90ca07dd28d648558e87c8680443 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 15 Nov 2013 17:16:33 +0100 Subject: drm/i915: Fix module unloading with DRM_I915_UMS=n Oops, makes testing early boot failures in i915.ko a bit more pain, so let's fix it. v2: We already have a bit of static storage to track this (Chris). Reviewed-by: Paulo Zanoni Tested-by: Paulo Zanoni Cc: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 583adcbef5e4..804a139901a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1022,6 +1022,11 @@ static int __init i915_init(void) static void __exit i915_exit(void) { +#ifndef CONFIG_DRM_I915_UMS + if (!(driver.driver_features & DRIVER_MODESET)) + return; /* Never loaded a driver. */ +#endif + drm_pci_exit(&driver, &i915_pci_driver); } -- cgit v1.2.3 From d629336b6af9ff214e9d1e7224946a000fc8f70f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 21 Nov 2013 21:29:45 +0200 Subject: drm/i915: Don't set the fence number in DPFC_CTL on SNB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SNB has another register where the actual FBC CPU fence number is stored. The documenation explicitly states that the fence number in DPFC_CTL must be 0 on SNB. And in fact when it's not zero, the GTT tracking simply doesn't work. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0fcd591b0a4b..de4cf565ec4c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -222,7 +222,9 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); /* Set persistent mode for front-buffer rendering, ala X. */ dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE; - dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg); + dpfc_ctl |= DPFC_CTL_FENCE_EN; + if (IS_GEN5(dev)) + dpfc_ctl |= obj->fence_reg; I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | -- cgit v1.2.3 From c92132f5980666c7a52ecb53d98226c9986d32cd Mon Sep 17 00:00:00 2001 From: Chunhe Lan Date: Mon, 25 Nov 2013 11:28:41 +0100 Subject: edac/85xx: Add PCIe error interrupt edac support Add pcie error interrupt edac support for mpc85xx, p3041, p4080, and p5020. The mpc85xx uses the legacy interrupt report mechanism - the error interrupts are reported directly to mpic. While the p3041/ p4080/p5020 attaches the most of error interrupts to interrupt zero. And report error interrupts to mpic via interrupt 0. This patch can handle both of them. Signed-off-by: Chunhe Lan Link: http://lkml.kernel.org/r/1384712714-8826-3-git-send-email-morbidrsa@gmail.com Cc: Doug Thompson Cc: Dave Jiang Signed-off-by: Johannes Thumshirn Signed-off-by: Borislav Petkov --- drivers/edac/mpc85xx_edac.c | 98 ++++++++++++++++++++++++++++++++++++++++----- drivers/edac/mpc85xx_edac.h | 7 ++++ 2 files changed, 94 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index fd46b0bd5f2a..8f9182179a7c 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -1,6 +1,8 @@ /* * Freescale MPC85xx Memory Controller kenel module * + * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc. + * * Author: Dave Jiang * * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under @@ -196,6 +198,42 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci) edac_pci_handle_npe(pci, pci->ctl_name); } +static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci) +{ + struct mpc85xx_pci_pdata *pdata = pci->pvt_info; + u32 err_detect; + + err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR); + + pr_err("PCIe error(s) detected\n"); + pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect); + pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n", + in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR)); + pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n", + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0)); + pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n", + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1)); + pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n", + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2)); + pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n", + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3)); + + /* clear error bits */ + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect); +} + +static int mpc85xx_pcie_find_capability(struct device_node *np) +{ + struct pci_controller *hose; + + if (!np) + return -EINVAL; + + hose = pci_find_hose_for_OF_device(np); + + return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); +} + static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) { struct edac_pci_ctl_info *pci = dev_id; @@ -207,7 +245,10 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) if (!err_detect) return IRQ_NONE; - mpc85xx_pci_check(pci); + if (pdata->is_pcie) + mpc85xx_pcie_check(pci); + else + mpc85xx_pci_check(pci); return IRQ_HANDLED; } @@ -239,14 +280,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op) pdata = pci->pvt_info; pdata->name = "mpc85xx_pci_err"; pdata->irq = NO_IRQ; + + if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0) + pdata->is_pcie = true; + dev_set_drvdata(&op->dev, pci); pci->dev = &op->dev; pci->mod_name = EDAC_MOD_STR; pci->ctl_name = pdata->name; pci->dev_name = dev_name(&op->dev); - if (edac_op_state == EDAC_OPSTATE_POLL) - pci->edac_check = mpc85xx_pci_check; + if (edac_op_state == EDAC_OPSTATE_POLL) { + if (pdata->is_pcie) + pci->edac_check = mpc85xx_pcie_check; + else + pci->edac_check = mpc85xx_pci_check; + } pdata->edac_idx = edac_pci_idx++; @@ -275,16 +324,26 @@ int mpc85xx_pci_err_probe(struct platform_device *op) goto err; } - orig_pci_err_cap_dr = - in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR); + if (pdata->is_pcie) { + orig_pci_err_cap_dr = + in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR); + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0); + orig_pci_err_en = + in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0); + } else { + orig_pci_err_cap_dr = + in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR); - /* PCI master abort is expected during config cycles */ - out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40); + /* PCI master abort is expected during config cycles */ + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40); - orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); + orig_pci_err_en = + in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); - /* disable master abort reporting */ - out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40); + /* disable master abort reporting */ + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40); + } /* clear error bits */ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); @@ -297,7 +356,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op) if (edac_op_state == EDAC_OPSTATE_INT) { pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0); res = devm_request_irq(&op->dev, pdata->irq, - mpc85xx_pci_isr, IRQF_DISABLED, + mpc85xx_pci_isr, + IRQF_DISABLED | IRQF_SHARED, "[EDAC] PCI err", pci); if (res < 0) { printk(KERN_ERR @@ -312,6 +372,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op) pdata->irq); } + if (pdata->is_pcie) { + /* + * Enable all PCIe error interrupt & error detect except invalid + * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation + * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access + * detection enable bit. Because PCIe bus code to initialize and + * configure these PCIe devices on booting will use some invalid + * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much + * notice information. So disable this detect to fix ugly print. + */ + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0 + & ~PEX_ERR_ICCAIE_EN_BIT); + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0 + | PEX_ERR_ICCAD_DISR_BIT); + } + devres_remove_group(&op->dev, mpc85xx_pci_err_probe); edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 932016f2cf06..8c6256436227 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h @@ -134,13 +134,19 @@ #define MPC85XX_PCI_ERR_DR 0x0000 #define MPC85XX_PCI_ERR_CAP_DR 0x0004 #define MPC85XX_PCI_ERR_EN 0x0008 +#define PEX_ERR_ICCAIE_EN_BIT 0x00020000 #define MPC85XX_PCI_ERR_ATTRIB 0x000c #define MPC85XX_PCI_ERR_ADDR 0x0010 +#define PEX_ERR_ICCAD_DISR_BIT 0x00020000 #define MPC85XX_PCI_ERR_EXT_ADDR 0x0014 #define MPC85XX_PCI_ERR_DL 0x0018 #define MPC85XX_PCI_ERR_DH 0x001c #define MPC85XX_PCI_GAS_TIMR 0x0020 #define MPC85XX_PCI_PCIX_TIMR 0x0024 +#define MPC85XX_PCIE_ERR_CAP_R0 0x0028 +#define MPC85XX_PCIE_ERR_CAP_R1 0x002c +#define MPC85XX_PCIE_ERR_CAP_R2 0x0030 +#define MPC85XX_PCIE_ERR_CAP_R3 0x0034 struct mpc85xx_mc_pdata { char *name; @@ -158,6 +164,7 @@ struct mpc85xx_l2_pdata { struct mpc85xx_pci_pdata { char *name; + bool is_pcie; int edac_idx; void __iomem *pci_vbase; int irq; -- cgit v1.2.3 From c9e2d69a1801045f28668e6853d9dccadbfbe494 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 22 Aug 2013 15:27:46 +0300 Subject: clk: tegra: replace enum tegra114_clk by binding header As the clock IDs are now specified in a header file, we can use those definitions instead of maintaining an internal enum. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 431 ++++++++++++++++++--------------------- 1 file changed, 198 insertions(+), 233 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 9467da7dee49..15d94d0d44d9 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "clk.h" @@ -864,43 +865,6 @@ static unsigned long tegra114_input_freq[] = { periph_clk_enb_refcnt, _gate_flags , _clk_id, \ mux_d_audio_clk_idx, 0) -enum tegra114_clk { - rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12, - ndflash = 13, sdmmc1 = 14, sdmmc4 = 15, pwm = 17, i2s2 = 18, epp = 19, - gr_2d = 21, usbd = 22, isp = 23, gr_3d = 24, disp2 = 26, disp1 = 27, - host1x = 28, vcp = 29, i2s0 = 30, apbdma = 34, kbc = 36, kfuse = 40, - sbc1 = 41, nor = 42, sbc2 = 44, sbc3 = 46, i2c5 = 47, dsia = 48, - mipi = 50, hdmi = 51, csi = 52, i2c2 = 54, uartc = 55, mipi_cal = 56, - emc, usb2, usb3, vde = 61, bsea = 62, bsev = 63, uartd = 65, - i2c3 = 67, sbc4 = 68, sdmmc3 = 69, owr = 71, csite = 73, - la = 76, trace = 77, soc_therm = 78, dtv = 79, ndspeed = 80, - i2cslow = 81, dsib = 82, tsec = 83, xusb_host = 89, msenc = 91, - csus = 92, mselect = 99, tsensor = 100, i2s3 = 101, i2s4 = 102, - i2c4 = 103, sbc5 = 104, sbc6 = 105, d_audio, apbif = 107, dam0, dam1, - dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x, - audio3_2x, audio4_2x, spdif_2x, actmon = 119, extern1 = 120, - extern2 = 121, extern3 = 122, hda = 125, se = 127, hda2hdmi = 128, - cilab = 144, cilcd = 145, cile = 146, dsialp = 147, dsiblp = 148, - dds = 150, dp2 = 152, amx = 153, adx = 154, xusb_ss = 156, uartb = 192, - vfir, spdif_in, spdif_out, vi, vi_sensor, fuse, fuse_burn, clk_32k, - clk_m, clk_m_div2, clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_c2, - pll_c3, pll_m, pll_m_out1, pll_p, pll_p_out1, pll_p_out2, pll_p_out3, - pll_p_out4, pll_a, pll_a_out0, pll_d, pll_d_out0, pll_d2, pll_d2_out0, - pll_u, pll_u_480M, pll_u_60M, pll_u_48M, pll_u_12M, pll_x, pll_x_out0, - pll_re_vco, pll_re_out, pll_e_out0, spdif_in_sync, i2s0_sync, - i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, vimclk_sync, audio0, - audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3, - blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src, - xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp, - dfll_ref = 264, dfll_soc, - - /* Mux clocks */ - - audio0_mux = 300, audio1_mux, audio2_mux, audio3_mux, audio4_mux, - spdif_mux, clk_out_1_mux, clk_out_2_mux, clk_out_3_mux, dsia_mux, - dsib_mux, clk_max, -}; - struct utmi_clk_param { /* Oscillator Frequency in KHz */ u32 osc_frequency; @@ -1064,7 +1028,7 @@ static const struct clk_div_table pll_re_div_table[] = { { .val = 0, .div = 0 }, }; -static struct clk *clks[clk_max]; +static struct clk *clks[TEGRA114_CLK_CLK_MAX]; static struct clk_onecell_data clk_data; static unsigned long osc_freq; @@ -1087,7 +1051,7 @@ static int __init tegra114_osc_clk_init(void __iomem *clk_base) clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, osc_freq); clk_register_clkdev(clk, "clk_m", NULL); - clks[clk_m] = clk; + clks[TEGRA114_CLK_CLK_M] = clk; /* pll_ref */ val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3; @@ -1095,7 +1059,7 @@ static int __init tegra114_osc_clk_init(void __iomem *clk_base) clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", CLK_SET_RATE_PARENT, 1, pll_ref_div); clk_register_clkdev(clk, "pll_ref", NULL); - clks[pll_ref] = clk; + clks[TEGRA114_CLK_PLL_REF] = clk; pll_ref_freq = osc_freq / pll_ref_div; @@ -1110,19 +1074,19 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base) clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, 32768); clk_register_clkdev(clk, "clk_32k", NULL); - clks[clk_32k] = clk; + clks[TEGRA114_CLK_CLK_32K] = clk; /* clk_m_div2 */ clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", CLK_SET_RATE_PARENT, 1, 2); clk_register_clkdev(clk, "clk_m_div2", NULL); - clks[clk_m_div2] = clk; + clks[TEGRA114_CLK_CLK_M_DIV2] = clk; /* clk_m_div4 */ clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", CLK_SET_RATE_PARENT, 1, 4); clk_register_clkdev(clk, "clk_m_div4", NULL); - clks[clk_m_div4] = clk; + clks[TEGRA114_CLK_CLK_M_DIV4] = clk; } @@ -1279,7 +1243,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK, pll_c_freq_table, NULL); clk_register_clkdev(clk, "pll_c", NULL); - clks[pll_c] = clk; + clks[TEGRA114_CLK_PLL_C] = clk; /* PLLC_OUT1 */ clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", @@ -1289,7 +1253,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); clk_register_clkdev(clk, "pll_c_out1", NULL); - clks[pll_c_out1] = clk; + clks[TEGRA114_CLK_PLL_C_OUT1] = clk; } /* PLLC2 */ @@ -1298,7 +1262,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, &pll_c2_params, TEGRA_PLL_USE_LOCK, pll_cx_freq_table, NULL); clk_register_clkdev(clk, "pll_c2", NULL); - clks[pll_c2] = clk; + clks[TEGRA114_CLK_PLL_C2] = clk; /* PLLC3 */ _clip_vco_min(&pll_c3_params); @@ -1306,7 +1270,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, &pll_c3_params, TEGRA_PLL_USE_LOCK, pll_cx_freq_table, NULL); clk_register_clkdev(clk, "pll_c3", NULL); - clks[pll_c3] = clk; + clks[TEGRA114_CLK_PLL_C3] = clk; /* PLLP */ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0, @@ -1314,7 +1278,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, pll_p_freq_table, NULL); clk_register_clkdev(clk, "pll_p", NULL); - clks[pll_p] = clk; + clks[TEGRA114_CLK_PLL_P] = clk; /* PLLP_OUT1 */ clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", @@ -1325,7 +1289,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); clk_register_clkdev(clk, "pll_p_out1", NULL); - clks[pll_p_out1] = clk; + clks[TEGRA114_CLK_PLL_P_OUT1] = clk; /* PLLP_OUT2 */ clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", @@ -1337,7 +1301,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); clk_register_clkdev(clk, "pll_p_out2", NULL); - clks[pll_p_out2] = clk; + clks[TEGRA114_CLK_PLL_P_OUT2] = clk; /* PLLP_OUT3 */ clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", @@ -1348,7 +1312,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); clk_register_clkdev(clk, "pll_p_out3", NULL); - clks[pll_p_out3] = clk; + clks[TEGRA114_CLK_PLL_P_OUT3] = clk; /* PLLP_OUT4 */ clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", @@ -1360,7 +1324,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); clk_register_clkdev(clk, "pll_p_out4", NULL); - clks[pll_p_out4] = clk; + clks[TEGRA114_CLK_PLL_P_OUT4] = clk; /* PLLM */ _clip_vco_min(&pll_m_params); @@ -1369,7 +1333,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, &pll_m_params, TEGRA_PLL_USE_LOCK, pll_m_freq_table, NULL); clk_register_clkdev(clk, "pll_m", NULL); - clks[pll_m] = clk; + clks[TEGRA114_CLK_PLL_M] = clk; /* PLLM_OUT1 */ clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", @@ -1379,7 +1343,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); clk_register_clkdev(clk, "pll_m_out1", NULL); - clks[pll_m_out1] = clk; + clks[TEGRA114_CLK_PLL_M_OUT1] = clk; /* PLLM_UD */ clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", @@ -1393,14 +1357,14 @@ static void __init tegra114_pll_init(void __iomem *clk_base, pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params, TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL); clk_register_clkdev(clk, "pll_x", NULL); - clks[pll_x] = clk; + clks[TEGRA114_CLK_PLL_X] = clk; } /* PLLX_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", CLK_SET_RATE_PARENT, 1, 2); clk_register_clkdev(clk, "pll_x_out0", NULL); - clks[pll_x_out0] = clk; + clks[TEGRA114_CLK_PLL_X_OUT0] = clk; /* PLLU */ val = readl(clk_base + pll_u_params.base_reg); @@ -1412,7 +1376,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock); clk_register_clkdev(clk, "pll_u", NULL); - clks[pll_u] = clk; + clks[TEGRA114_CLK_PLL_U] = clk; tegra114_utmi_param_configure(clk_base); @@ -1421,25 +1385,25 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, 22, 0, &pll_u_lock); clk_register_clkdev(clk, "pll_u_480M", NULL); - clks[pll_u_480M] = clk; + clks[TEGRA114_CLK_PLL_U_480M] = clk; /* PLLU_60M */ clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u", CLK_SET_RATE_PARENT, 1, 8); clk_register_clkdev(clk, "pll_u_60M", NULL); - clks[pll_u_60M] = clk; + clks[TEGRA114_CLK_PLL_U_60M] = clk; /* PLLU_48M */ clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u", CLK_SET_RATE_PARENT, 1, 10); clk_register_clkdev(clk, "pll_u_48M", NULL); - clks[pll_u_48M] = clk; + clks[TEGRA114_CLK_PLL_U_48M] = clk; /* PLLU_12M */ clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u", CLK_SET_RATE_PARENT, 1, 40); clk_register_clkdev(clk, "pll_u_12M", NULL); - clks[pll_u_12M] = clk; + clks[TEGRA114_CLK_PLL_U_12M] = clk; /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0, @@ -1447,13 +1411,13 @@ static void __init tegra114_pll_init(void __iomem *clk_base, TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock); clk_register_clkdev(clk, "pll_d", NULL); - clks[pll_d] = clk; + clks[TEGRA114_CLK_PLL_D] = clk; /* PLLD_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", CLK_SET_RATE_PARENT, 1, 2); clk_register_clkdev(clk, "pll_d_out0", NULL); - clks[pll_d_out0] = clk; + clks[TEGRA114_CLK_PLL_D_OUT0] = clk; /* PLLD2 */ clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0, @@ -1461,20 +1425,20 @@ static void __init tegra114_pll_init(void __iomem *clk_base, TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock); clk_register_clkdev(clk, "pll_d2", NULL); - clks[pll_d2] = clk; + clks[TEGRA114_CLK_PLL_D2] = clk; /* PLLD2_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", CLK_SET_RATE_PARENT, 1, 2); clk_register_clkdev(clk, "pll_d2_out0", NULL); - clks[pll_d2_out0] = clk; + clks[TEGRA114_CLK_PLL_D2_OUT0] = clk; /* PLLA */ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0, 0, &pll_a_params, TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL); clk_register_clkdev(clk, "pll_a", NULL); - clks[pll_a] = clk; + clks[TEGRA114_CLK_PLL_A] = clk; /* PLLA_OUT0 */ clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", @@ -1484,7 +1448,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); clk_register_clkdev(clk, "pll_a_out0", NULL); - clks[pll_a_out0] = clk; + clks[TEGRA114_CLK_PLL_A_OUT0] = clk; /* PLLRE */ _clip_vco_min(&pll_re_vco_params); @@ -1492,20 +1456,20 @@ static void __init tegra114_pll_init(void __iomem *clk_base, 0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK, NULL, &pll_re_lock, pll_ref_freq); clk_register_clkdev(clk, "pll_re_vco", NULL); - clks[pll_re_vco] = clk; + clks[TEGRA114_CLK_PLL_RE_VCO] = clk; clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0, clk_base + PLLRE_BASE, 16, 4, 0, pll_re_div_table, &pll_re_lock); clk_register_clkdev(clk, "pll_re_out", NULL); - clks[pll_re_out] = clk; + clks[TEGRA114_CLK_PLL_RE_OUT] = clk; /* PLLE */ clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco", clk_base, 0, 100000000, &pll_e_params, pll_e_freq_table, NULL); clk_register_clkdev(clk, "pll_e_out0", NULL); - clks[pll_e_out0] = clk; + clks[TEGRA114_CLK_PLL_E_OUT0] = clk; } static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", @@ -1532,37 +1496,37 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000, 24000000); clk_register_clkdev(clk, "spdif_in_sync", NULL); - clks[spdif_in_sync] = clk; + clks[TEGRA114_CLK_SPDIF_IN_SYNC] = clk; /* i2s0_sync */ clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000); clk_register_clkdev(clk, "i2s0_sync", NULL); - clks[i2s0_sync] = clk; + clks[TEGRA114_CLK_I2S0_SYNC] = clk; /* i2s1_sync */ clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000); clk_register_clkdev(clk, "i2s1_sync", NULL); - clks[i2s1_sync] = clk; + clks[TEGRA114_CLK_I2S1_SYNC] = clk; /* i2s2_sync */ clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000); clk_register_clkdev(clk, "i2s2_sync", NULL); - clks[i2s2_sync] = clk; + clks[TEGRA114_CLK_I2S2_SYNC] = clk; /* i2s3_sync */ clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000); clk_register_clkdev(clk, "i2s3_sync", NULL); - clks[i2s3_sync] = clk; + clks[TEGRA114_CLK_I2S3_SYNC] = clk; /* i2s4_sync */ clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000); clk_register_clkdev(clk, "i2s4_sync", NULL); - clks[i2s4_sync] = clk; + clks[TEGRA114_CLK_I2S4_SYNC] = clk; /* vimclk_sync */ clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000); clk_register_clkdev(clk, "vimclk_sync", NULL); - clks[vimclk_sync] = clk; + clks[TEGRA114_CLK_VIMCLK_SYNC] = clk; /* audio0 */ clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, @@ -1570,12 +1534,12 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL); - clks[audio0_mux] = clk; + clks[TEGRA114_CLK_AUDIO0_MUX] = clk; clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S0, 4, CLK_GATE_SET_TO_DISABLE, NULL); clk_register_clkdev(clk, "audio0", NULL); - clks[audio0] = clk; + clks[TEGRA114_CLK_AUDIO0] = clk; /* audio1 */ clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, @@ -1583,12 +1547,12 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL); - clks[audio1_mux] = clk; + clks[TEGRA114_CLK_AUDIO1_MUX] = clk; clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S1, 4, CLK_GATE_SET_TO_DISABLE, NULL); clk_register_clkdev(clk, "audio1", NULL); - clks[audio1] = clk; + clks[TEGRA114_CLK_AUDIO1] = clk; /* audio2 */ clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, @@ -1596,12 +1560,12 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL); - clks[audio2_mux] = clk; + clks[TEGRA114_CLK_AUDIO2_MUX] = clk; clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S2, 4, CLK_GATE_SET_TO_DISABLE, NULL); clk_register_clkdev(clk, "audio2", NULL); - clks[audio2] = clk; + clks[TEGRA114_CLK_AUDIO2] = clk; /* audio3 */ clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, @@ -1609,12 +1573,12 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL); - clks[audio3_mux] = clk; + clks[TEGRA114_CLK_AUDIO3_MUX] = clk; clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S3, 4, CLK_GATE_SET_TO_DISABLE, NULL); clk_register_clkdev(clk, "audio3", NULL); - clks[audio3] = clk; + clks[TEGRA114_CLK_AUDIO3] = clk; /* audio4 */ clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, @@ -1622,12 +1586,12 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL); - clks[audio4_mux] = clk; + clks[TEGRA114_CLK_AUDIO4_MUX] = clk; clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S4, 4, CLK_GATE_SET_TO_DISABLE, NULL); clk_register_clkdev(clk, "audio4", NULL); - clks[audio4] = clk; + clks[TEGRA114_CLK_AUDIO4] = clk; /* spdif */ clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, @@ -1635,12 +1599,12 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL); - clks[spdif_mux] = clk; + clks[TEGRA114_CLK_SPDIF_MUX] = clk; clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, clk_base + AUDIO_SYNC_CLK_SPDIF, 4, CLK_GATE_SET_TO_DISABLE, NULL); clk_register_clkdev(clk, "spdif", NULL); - clks[spdif] = clk; + clks[TEGRA114_CLK_SPDIF] = clk; /* audio0_2x */ clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0", @@ -1653,7 +1617,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, 113, &periph_v_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio0_2x", NULL); - clks[audio0_2x] = clk; + clks[TEGRA114_CLK_AUDIO0_2X] = clk; /* audio1_2x */ clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1", @@ -1666,7 +1630,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, 114, &periph_v_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio1_2x", NULL); - clks[audio1_2x] = clk; + clks[TEGRA114_CLK_AUDIO1_2X] = clk; /* audio2_2x */ clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2", @@ -1679,7 +1643,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, 115, &periph_v_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio2_2x", NULL); - clks[audio2_2x] = clk; + clks[TEGRA114_CLK_AUDIO2_2X] = clk; /* audio3_2x */ clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3", @@ -1692,7 +1656,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, 116, &periph_v_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio3_2x", NULL); - clks[audio3_2x] = clk; + clks[TEGRA114_CLK_AUDIO3_2X] = clk; /* audio4_2x */ clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4", @@ -1705,7 +1669,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, 117, &periph_v_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio4_2x", NULL); - clks[audio4_2x] = clk; + clks[TEGRA114_CLK_AUDIO4_2X] = clk; /* spdif_2x */ clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif", @@ -1718,7 +1682,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, 118, &periph_v_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, "spdif_2x", NULL); - clks[spdif_2x] = clk; + clks[TEGRA114_CLK_SPDIF_2X] = clk; } static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) @@ -1731,12 +1695,12 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, &clk_out_lock); - clks[clk_out_1_mux] = clk; + clks[TEGRA114_CLK_CLK_OUT_1_MUX] = clk; clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, &clk_out_lock); clk_register_clkdev(clk, "extern1", "clk_out_1"); - clks[clk_out_1] = clk; + clks[TEGRA114_CLK_CLK_OUT_1] = clk; /* clk_out_2 */ clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, @@ -1744,12 +1708,12 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, &clk_out_lock); - clks[clk_out_2_mux] = clk; + clks[TEGRA114_CLK_CLK_OUT_2_MUX] = clk; clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, &clk_out_lock); clk_register_clkdev(clk, "extern2", "clk_out_2"); - clks[clk_out_2] = clk; + clks[TEGRA114_CLK_CLK_OUT_2] = clk; /* clk_out_3 */ clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, @@ -1757,12 +1721,12 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, &clk_out_lock); - clks[clk_out_3_mux] = clk; + clks[TEGRA114_CLK_CLK_OUT_3_MUX] = clk; clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, &clk_out_lock); clk_register_clkdev(clk, "extern3", "clk_out_3"); - clks[clk_out_3] = clk; + clks[TEGRA114_CLK_CLK_OUT_3] = clk; /* blink */ /* clear the blink timer register to directly output clk_32k */ @@ -1774,7 +1738,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) pmc_base + PMC_CTRL, PMC_CTRL_BLINK_ENB, 0, NULL); clk_register_clkdev(clk, "blink", NULL); - clks[blink] = clk; + clks[TEGRA114_CLK_BLINK] = clk; } @@ -1801,7 +1765,7 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) clk_base + CCLKG_BURST_POLICY, 0, 4, 0, 0, NULL); clk_register_clkdev(clk, "cclk_g", NULL); - clks[cclk_g] = clk; + clks[TEGRA114_CLK_CCLK_G] = clk; /* CCLKLP */ clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents, @@ -1810,7 +1774,7 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) clk_base + CCLKLP_BURST_POLICY, 0, 4, 8, 9, NULL); clk_register_clkdev(clk, "cclk_lp", NULL); - clks[cclk_lp] = clk; + clks[TEGRA114_CLK_CCLK_LP] = clk; /* SCLK */ clk = tegra_clk_register_super_mux("sclk", sclk_parents, @@ -1819,7 +1783,7 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); clk_register_clkdev(clk, "sclk", NULL); - clks[sclk] = clk; + clks[TEGRA114_CLK_SCLK] = clk; /* HCLK */ clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, @@ -1829,7 +1793,7 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, 7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); clk_register_clkdev(clk, "hclk", NULL); - clks[hclk] = clk; + clks[TEGRA114_CLK_HCLK] = clk; /* PCLK */ clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, @@ -1839,90 +1803,90 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); clk_register_clkdev(clk, "pclk", NULL); - clks[pclk] = clk; + clks[TEGRA114_CLK_PCLK] = clk; } static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0), - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), - TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3), - TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), - TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, pwm), - TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, adx), - TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, amx), - TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda), - TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda2codec_2x), - TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), - TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), - TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), - TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), - TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5), - TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6), - TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed), - TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), - TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), - TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la), - TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, trace), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), - TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, i2c1), - TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, i2c2), - TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, i2c3), - TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, i2c4), - TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, i2c5), - TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta), - TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb), - TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc), - TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd), - TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, gr_3d), - TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr_2d), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), - TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), - TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), - TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_u_regs, TEGRA_PERIPH_WAR_1005168, msenc), - TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec), - TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), - TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), - TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, cilab), - TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, cilcd), - TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, cile), - TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, dsialp), - TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, dsiblp), - TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor), - TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon), - TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1), - TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2), - TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3), - TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow), - TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se), - TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_ref), - TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_soc), - TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm), - TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src), - TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src), - TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_fs_src), - TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_ss_src), - TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_dev_src), - TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, d_audio), - TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam0), - TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam1), - TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam2), + TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S0), + TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S1), + TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S2), + TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S3), + TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S4), + TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_OUT), + TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_IN), + TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_PWM), + TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_ADX), + TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), + TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), + TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), + TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), + TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), + TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), + TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), + TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), + TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), + TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), + TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), + TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), + TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, TEGRA114_CLK_SDMMC1), + TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, TEGRA114_CLK_SDMMC2), + TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, TEGRA114_CLK_SDMMC3), + TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, TEGRA114_CLK_SDMMC4), + TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, TEGRA114_CLK_VDE), + TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), + TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), + TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), + TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_OWR), + TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, TEGRA114_CLK_NOR), + TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_MIPI), + TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA114_CLK_I2C1), + TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA114_CLK_I2C2), + TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA114_CLK_I2C3), + TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, TEGRA114_CLK_I2C4), + TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, TEGRA114_CLK_I2C5), + TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, TEGRA114_CLK_UARTA), + TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, TEGRA114_CLK_UARTB), + TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, TEGRA114_CLK_UARTC), + TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, TEGRA114_CLK_UARTD), + TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, TEGRA114_CLK_GR_3D), + TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, TEGRA114_CLK_GR_2D), + TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), + TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, TEGRA114_CLK_VI), + TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, TEGRA114_CLK_EPP), + TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_u_regs, TEGRA_PERIPH_WAR_1005168, TEGRA114_CLK_MSENC), + TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, TEGRA114_CLK_TSEC), + TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, TEGRA114_CLK_HOST1X), + TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, TEGRA114_CLK_HDMI), + TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, TEGRA114_CLK_CILAB), + TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, TEGRA114_CLK_CILCD), + TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, TEGRA114_CLK_CILE), + TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, TEGRA114_CLK_DSIALP), + TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, TEGRA114_CLK_DSIBLP), + TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TSENSOR), + TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, TEGRA114_CLK_ACTMON), + TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, TEGRA114_CLK_EXTERN1), + TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, TEGRA114_CLK_EXTERN2), + TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, TEGRA114_CLK_EXTERN3), + TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2CSLOW), + TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SE), + TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, TEGRA114_CLK_MSELECT, CLK_IGNORE_UNUSED), + TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_REF), + TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_SOC), + TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SOC_THERM), + TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_HOST_SRC), + TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FALCON_SRC), + TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FS_SRC), + TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_SS_SRC), + TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_DEV_SRC), + TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_D_AUDIO), + TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM0), + TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM1), + TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM2), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, &periph_l_regs, 0, disp1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, &periph_l_regs, 0, disp2), + TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, &periph_l_regs, 0, TEGRA114_CLK_DISP1), + TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, &periph_l_regs, 0, TEGRA114_CLK_DISP2), }; static __init void tegra114_periph_clk_init(void __iomem *clk_base) @@ -1936,7 +1900,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, 0, 34, &periph_h_regs, periph_clk_enb_refcnt); - clks[apbdma] = clk; + clks[TEGRA114_CLK_APBDMA] = clk; /* rtc */ clk = tegra_clk_register_periph_gate("rtc", "clk_32k", @@ -1945,7 +1909,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) 0, 4, &periph_l_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "rtc-tegra"); - clks[rtc] = clk; + clks[TEGRA114_CLK_RTC] = clk; /* kbc */ clk = tegra_clk_register_periph_gate("kbc", "clk_32k", @@ -1953,144 +1917,144 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, 0, 36, &periph_h_regs, periph_clk_enb_refcnt); - clks[kbc] = clk; + clks[TEGRA114_CLK_KBC] = clk; /* timer */ clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0, 5, &periph_l_regs, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "timer"); - clks[timer] = clk; + clks[TEGRA114_CLK_TIMER] = clk; /* kfuse */ clk = tegra_clk_register_periph_gate("kfuse", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 40, &periph_h_regs, periph_clk_enb_refcnt); - clks[kfuse] = clk; + clks[TEGRA114_CLK_KFUSE] = clk; /* fuse */ clk = tegra_clk_register_periph_gate("fuse", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 39, &periph_h_regs, periph_clk_enb_refcnt); - clks[fuse] = clk; + clks[TEGRA114_CLK_FUSE] = clk; /* fuse_burn */ clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 39, &periph_h_regs, periph_clk_enb_refcnt); - clks[fuse_burn] = clk; + clks[TEGRA114_CLK_FUSE_BURN] = clk; /* apbif */ clk = tegra_clk_register_periph_gate("apbif", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 107, &periph_v_regs, periph_clk_enb_refcnt); - clks[apbif] = clk; + clks[TEGRA114_CLK_APBIF] = clk; /* hda2hdmi */ clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 128, &periph_w_regs, periph_clk_enb_refcnt); - clks[hda2hdmi] = clk; + clks[TEGRA114_CLK_HDA2HDMI] = clk; /* vcp */ clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, 29, &periph_l_regs, periph_clk_enb_refcnt); - clks[vcp] = clk; + clks[TEGRA114_CLK_VCP] = clk; /* bsea */ clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, 0, 62, &periph_h_regs, periph_clk_enb_refcnt); - clks[bsea] = clk; + clks[TEGRA114_CLK_BSEA] = clk; /* bsev */ clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, 0, 63, &periph_h_regs, periph_clk_enb_refcnt); - clks[bsev] = clk; + clks[TEGRA114_CLK_BSEV] = clk; /* mipi-cal */ clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base, 0, 56, &periph_h_regs, periph_clk_enb_refcnt); - clks[mipi_cal] = clk; + clks[TEGRA114_CLK_MIPI_CAL] = clk; /* usbd */ clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, 22, &periph_l_regs, periph_clk_enb_refcnt); - clks[usbd] = clk; + clks[TEGRA114_CLK_USBD] = clk; /* usb2 */ clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, 58, &periph_h_regs, periph_clk_enb_refcnt); - clks[usb2] = clk; + clks[TEGRA114_CLK_USB2] = clk; /* usb3 */ clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, 59, &periph_h_regs, periph_clk_enb_refcnt); - clks[usb3] = clk; + clks[TEGRA114_CLK_USB3] = clk; /* csi */ clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, 0, 52, &periph_h_regs, periph_clk_enb_refcnt); - clks[csi] = clk; + clks[TEGRA114_CLK_CSI] = clk; /* isp */ clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, &periph_l_regs, periph_clk_enb_refcnt); - clks[isp] = clk; + clks[TEGRA114_CLK_ISP] = clk; /* csus */ clk = tegra_clk_register_periph_gate("csus", "clk_m", TEGRA_PERIPH_NO_RESET, clk_base, 0, 92, &periph_u_regs, periph_clk_enb_refcnt); - clks[csus] = clk; + clks[TEGRA114_CLK_CSUS] = clk; /* dds */ clk = tegra_clk_register_periph_gate("dds", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 150, &periph_w_regs, periph_clk_enb_refcnt); - clks[dds] = clk; + clks[TEGRA114_CLK_DDS] = clk; /* dp2 */ clk = tegra_clk_register_periph_gate("dp2", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 152, &periph_w_regs, periph_clk_enb_refcnt); - clks[dp2] = clk; + clks[TEGRA114_CLK_DP2] = clk; /* dtv */ clk = tegra_clk_register_periph_gate("dtv", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 79, &periph_u_regs, periph_clk_enb_refcnt); - clks[dtv] = clk; + clks[TEGRA114_CLK_DTV] = clk; /* dsia */ clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, ARRAY_SIZE(mux_plld_out0_plld2_out0), CLK_SET_RATE_NO_REPARENT, clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock); - clks[dsia_mux] = clk; + clks[TEGRA114_CLK_DSIA_MUX] = clk; clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base, 0, 48, &periph_h_regs, periph_clk_enb_refcnt); - clks[dsia] = clk; + clks[TEGRA114_CLK_DSIA] = clk; /* dsib */ clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0, ARRAY_SIZE(mux_plld_out0_plld2_out0), CLK_SET_RATE_NO_REPARENT, clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock); - clks[dsib_mux] = clk; + clks[TEGRA114_CLK_DSIB_MUX] = clk; clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base, 0, 82, &periph_u_regs, periph_clk_enb_refcnt); - clks[dsib] = clk; + clks[TEGRA114_CLK_DSIB] = clk; /* xusb_hs_src */ val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC); @@ -2099,25 +2063,25 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, 1, 1); - clks[xusb_hs_src] = clk; + clks[TEGRA114_CLK_XUSB_HS_SRC] = clk; /* xusb_host */ clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0, clk_base, 0, 89, &periph_u_regs, periph_clk_enb_refcnt); - clks[xusb_host] = clk; + clks[TEGRA114_CLK_XUSB_HOST] = clk; /* xusb_ss */ clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0, clk_base, 0, 156, &periph_w_regs, periph_clk_enb_refcnt); - clks[xusb_host] = clk; + clks[TEGRA114_CLK_XUSB_HOST] = clk; /* xusb_dev */ clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0, clk_base, 0, 95, &periph_u_regs, periph_clk_enb_refcnt); - clks[xusb_dev] = clk; + clks[TEGRA114_CLK_XUSB_DEV] = clk; /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, @@ -2128,7 +2092,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, CLK_IGNORE_UNUSED, 57, &periph_h_regs, periph_clk_enb_refcnt); - clks[emc] = clk; + clks[TEGRA114_CLK_EMC] = clk; for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; @@ -2207,28 +2171,29 @@ static const struct of_device_id pmc_match[] __initconst = { * breaks */ static struct tegra_clk_init_table init_table[] __initdata = { - {uarta, pll_p, 408000000, 0}, - {uartb, pll_p, 408000000, 0}, - {uartc, pll_p, 408000000, 0}, - {uartd, pll_p, 408000000, 0}, - {pll_a, clk_max, 564480000, 1}, - {pll_a_out0, clk_max, 11289600, 1}, - {extern1, pll_a_out0, 0, 1}, - {clk_out_1_mux, extern1, 0, 1}, - {clk_out_1, clk_max, 0, 1}, - {i2s0, pll_a_out0, 11289600, 0}, - {i2s1, pll_a_out0, 11289600, 0}, - {i2s2, pll_a_out0, 11289600, 0}, - {i2s3, pll_a_out0, 11289600, 0}, - {i2s4, pll_a_out0, 11289600, 0}, - {dfll_soc, pll_p, 51000000, 1}, - {dfll_ref, pll_p, 51000000, 1}, - {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ + {TEGRA114_CLK_UARTA, TEGRA114_CLK_PLL_P, 408000000, 0}, + {TEGRA114_CLK_UARTB, TEGRA114_CLK_PLL_P, 408000000, 0}, + {TEGRA114_CLK_UARTC, TEGRA114_CLK_PLL_P, 408000000, 0}, + {TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0}, + {TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1}, + {TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1}, + {TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1}, + {TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1}, + {TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1}, + {TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1}, + {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1}, + /* This MUST be the last entry. */ + {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0}, }; static void __init tegra114_clock_apply_init_table(void) { - tegra_init_from_table(init_table, clks, clk_max); + tegra_init_from_table(init_table, clks, TEGRA114_CLK_CLK_MAX); } -- cgit v1.2.3 From 2b54ffc2693b917743de6f34815b63638ad3853f Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Thu, 8 Aug 2013 13:55:27 +0800 Subject: clk: tegra: Correct sbc mux width & parent Tegra114 sbc1-sbc6 have more possible parent clocks than Tegra30. So correct the parents and mux width for them. Signed-off-by: Mark Zhang Acked-by: Stephen Warren Acked-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 15d94d0d44d9..519f9556d0c9 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1819,12 +1819,12 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), - TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), - TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), - TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), - TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), - TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), - TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), + TEGRA_INIT_DATA_MUX8("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), + TEGRA_INIT_DATA_MUX8("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), + TEGRA_INIT_DATA_MUX8("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), + TEGRA_INIT_DATA_MUX8("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), + TEGRA_INIT_DATA_MUX8("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), + TEGRA_INIT_DATA_MUX8("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), -- cgit v1.2.3 From d17cb95fa0b8676a38c0d07e2da26885d4ff8187 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Wed, 7 Aug 2013 19:25:07 +0800 Subject: clk: tegra: Fix vde/2d/3d clock src offset In Tegra114, vde/gr_2d/gr_3d have 3 bits for clock source selection. So change the clock init macro for these clocks from "TEGRA_INIT_DATA_INT" to "TEGRA_INIT_DATA_INT8". Besides, no one uses "TEGRA_INIT_DATA_INT" after this change, so remove this macro. Signed-off-by: Mark Zhang Acked-by: Stephen Warren Acked-By: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 519f9556d0c9..6d6491c7b479 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -809,13 +809,6 @@ static unsigned long tegra114_input_freq[] = { periph_clk_enb_refcnt, _gate_flags, _clk_id, \ _parents##_idx, 0) -#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id, _parents##_idx, 0) - #define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ @@ -1832,7 +1825,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, TEGRA114_CLK_SDMMC2), TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, TEGRA114_CLK_SDMMC3), TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, TEGRA114_CLK_SDMMC4), - TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, TEGRA114_CLK_VDE), + TEGRA_INIT_DATA_INT8("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, TEGRA114_CLK_VDE), TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), @@ -1848,8 +1841,8 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, TEGRA114_CLK_UARTB), TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, TEGRA114_CLK_UARTC), TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, TEGRA114_CLK_UARTD), - TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, TEGRA114_CLK_GR_3D), - TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, TEGRA114_CLK_GR_2D), + TEGRA_INIT_DATA_INT8("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, TEGRA114_CLK_GR_3D), + TEGRA_INIT_DATA_INT8("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, TEGRA114_CLK_GR_2D), TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, TEGRA114_CLK_VI), TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, TEGRA114_CLK_EPP), -- cgit v1.2.3 From fc20eeff6c03fcdbb2b5ac21472778b573850e77 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Wed, 7 Aug 2013 19:25:08 +0800 Subject: clk: tegra: Set the clock parent of gr2d/gr3d to pll_c2 pll_m will be the parent of gr2d/gr3d if we don't do this. And because pll_m runs at a high rate so gr2d/gr3d will be unstable. So change the parent of them to pll_c2. Signed-off-by: Mark Zhang Acked-By: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 6d6491c7b479..76611289b8e6 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -2180,6 +2180,9 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1}, {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1}, + {TEGRA114_CLK_GR_2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, + {TEGRA114_CLK_GR_3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, + /* This MUST be the last entry. */ {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0}, }; -- cgit v1.2.3 From 44c5f629f1abb70be239a289f4c9bfd380f67f2a Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:52 +0530 Subject: Staging: comedi: fix line over 80 character warning in unioxx5.c This is a patch to unioxx5.c that fixes the line over 80 character warning found by checkpatch.pl by initializing n_subd before the for loop Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 93eec2fc254c..725595f0ff6e 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -435,9 +435,10 @@ static int unioxx5_attach(struct comedi_device *dev, dev->iobase = iobase; iobase += UNIOXX5_SUBDEV_BASE; + n_subd = 0; /* defining number of subdevices and getting they types (it must be 'g01') */ - for (i = n_subd = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) { + for (i = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) { id = inb(ba + 0xE); num = inb(ba + 0xF); -- cgit v1.2.3 From 2e9cf8489bebc414fbaeee9496656edf6ab57f64 Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:53 +0530 Subject: Staging: comedi: fix line over 80 character warning in unioxx5.c This is a patch to fix a line over 80 character warning found by checkpatch.pl in a comment. The comment was reworded to fix the warning Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 725595f0ff6e..2b1ece8fd877 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -437,7 +437,7 @@ static int unioxx5_attach(struct comedi_device *dev, iobase += UNIOXX5_SUBDEV_BASE; n_subd = 0; - /* defining number of subdevices and getting they types (it must be 'g01') */ + /* getting number of subdevices with types 'g01' */ for (i = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) { id = inb(ba + 0xE); num = inb(ba + 0xF); -- cgit v1.2.3 From 2851fcd52073b03e865128cad8161891094ecc02 Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:54 +0530 Subject: Staging: comedi: change printk to dev_err/dev_dbg in unioxx5.c This is a patch which fixes coding style issues due to printk usage in unioxx5.c found by checkpatch.pl in the following functions: 1) __unioxx5_digital_read 2) __unioxx5_analog_read 3) __unioxx5_digital_config To subsitute printk with dev_err/dev_dbg, access to the struct device is required. The function definitions of the above functions have been changed to take the pointer to the struct comedi_subdevice as a parameter instead of the pointer to struct unioxx5_subd_priv. The pointers to the stuct device and the struct unioxx5_subd_priv are obtained through the pointer to the struct comedi_subdevice in these functions. The function calls of __unioxx5_digital_read and __unioxx5_analog_read in unioxx5_subdev_read have been changed to pass the pointer to the struct comedi_subdevice. Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 2b1ece8fd877..31736eddd615 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -91,12 +91,14 @@ static int __unioxx5_define_chan_offset(int chan_num) } #if 0 /* not used? */ -static void __unioxx5_digital_config(struct unioxx5_subd_priv *usp, int mode) +static void __unioxx5_digital_config(struct comedi_subdevice *s, int mode) { + struct unioxx5_subd_priv *usp = s->private; + struct device *csdev = s->device->class_dev; int i, mask; mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00; - printk("COMEDI: mode = %d\n", mask); + dev_dbg(csdev, "mode = %d\n", mask); outb(1, usp->usp_iobase + 0); @@ -135,15 +137,18 @@ static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel) usp->usp_prev_cn_val[channel_offset - 1] = conf; } -static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp, +static int __unioxx5_digital_read(struct comedi_subdevice *s, unsigned int *data, int channel, int minor) { + struct unioxx5_subd_priv *usp = s->private; + struct device *csdev = s->device->class_dev; int channel_offset, mask = 1 << (channel & 0x07); channel_offset = __unioxx5_define_chan_offset(channel); if (channel_offset < 0) { - pr_err("comedi%d: undefined channel %d. channel range is 0 .. 23\n", - minor, channel); + dev_err(csdev, + "comedi%d: undefined channel %d. channel range is 0 .. 23\n", + minor, channel); return 0; } @@ -157,9 +162,11 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp, return 1; } -static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp, +static int __unioxx5_analog_read(struct comedi_subdevice *s, unsigned int *data, int channel, int minor) { + struct unioxx5_subd_priv *usp = s->private; + struct device *csdev = s->device->class_dev; int module_no, read_ch; char control; @@ -185,7 +192,8 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp, /* if four bytes readding error occurs - return 0(false) */ if ((control & Rx4CA_ERR_MASK)) { - printk("COMEDI: 4 bytes error\n"); + dev_err(csdev, + "comedi%d: 4 bytes error\n", minor); return 0; } @@ -273,10 +281,10 @@ static int unioxx5_subdev_read(struct comedi_device *dev, type = usp->usp_module_type[channel / 2]; if (type == MODULE_DIGITAL) { - if (!__unioxx5_digital_read(usp, data, channel, dev->minor)) + if (!__unioxx5_digital_read(subdev, data, channel, dev->minor)) return -1; } else { - if (!__unioxx5_analog_read(usp, data, channel, dev->minor)) + if (!__unioxx5_analog_read(subdev, data, channel, dev->minor)) return -1; } -- cgit v1.2.3 From 698fa7a3cc364ea6667016feed129d402cdeca2b Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:55 +0530 Subject: Staging: comedi: change pr_err to dev_err in __unioxx5_analog_read This is a patch which subsitutes pr_err with dev_err in __unioxx5_analog_read as it is the preferred way to log in device drivers Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 31736eddd615..7edbd5e97731 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -175,7 +175,7 @@ static int __unioxx5_analog_read(struct comedi_subdevice *s, /* defining if given module can work on input */ if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) { - pr_err("comedi%d: module in position %d with id 0x%02x is for output only", + dev_err(csdev, "comedi%d: module in position %d with id 0x%02x is for output only", minor, module_no, usp->usp_module_type[module_no]); return 0; } -- cgit v1.2.3 From 10394e57629f55f37e577fa6d515be3e5351dc6f Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:56 +0530 Subject: Staging: comedi: change pr_err to dev_err in __unioxx5_digital_write This is a patch which subsitutes pr_err with the preferred dev_err for device drivers in __unioxx5_digital_write. The function definition of __unioxx5_digital_write has been changed to take the pointer to the struct comedi_subdevice as a parameter instead of the pointer to struct unioxx5_subd_priv. The pointers to the stuct device and the struct unioxx5_subd_priv are obtained through the pointer to the struct comedi_subdevice in this function. The function call to __unioxx5_digital_write in unioxx5_subdev_write has been changed to pass the pointer to the struct comedi_subdevice Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 7edbd5e97731..343ba9673e88 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -205,15 +205,17 @@ static int __unioxx5_analog_read(struct comedi_subdevice *s, return 1; } -static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp, +static int __unioxx5_digital_write(struct comedi_subdevice *s, unsigned int *data, int channel, int minor) { + struct unioxx5_subd_priv *usp = s->private; + struct device *csdev = s->device->class_dev; int channel_offset, val; int mask = 1 << (channel & 0x07); channel_offset = __unioxx5_define_chan_offset(channel); if (channel_offset < 0) { - pr_err("comedi%d: undefined channel %d. channel range is 0 .. 23\n", + dev_err(csdev, "comedi%d: undefined channel %d. channel range is 0 .. 23\n", minor, channel); return 0; } @@ -303,7 +305,7 @@ static int unioxx5_subdev_write(struct comedi_device *dev, type = usp->usp_module_type[channel / 2]; if (type == MODULE_DIGITAL) { - if (!__unioxx5_digital_write(usp, data, channel, dev->minor)) + if (!__unioxx5_digital_write(subdev, data, channel, dev->minor)) return -1; } else { if (!__unioxx5_analog_write(usp, data, channel, dev->minor)) -- cgit v1.2.3 From c29d9a8816d20f90cf3d7ff830d07adf922be394 Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:57 +0530 Subject: Staging: comedi: change pr_err to dev_err in __unioxx5_analog_write This is a patch which subsitutes pr_err with the preferred dev_err for device drivers in __unioxx5_analog_write. The function definition of __unioxx5_analog_write has been changed to take the pointer to the struct comedi_subdevice as a parameter instead of the pointer to struct unioxx5_subd_priv. The pointers to the stuct device and the struct unioxx5_subd_priv are obtained through the pointer to the struct comedi_subdevice in this function. The function call to __unioxx5_analog_write in unioxx5_subdev_write has been changed to pass the pointer to the struct comedi_subdevice Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 343ba9673e88..6bbc934852fa 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -235,9 +235,11 @@ static int __unioxx5_digital_write(struct comedi_subdevice *s, return 1; } -static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp, +static int __unioxx5_analog_write(struct comedi_subdevice *s, unsigned int *data, int channel, int minor) { + struct unioxx5_subd_priv *usp = s->private; + struct device *csdev = s->device->class_dev; int module, i; module = channel / 2; /* definig module number(0 .. 11) */ @@ -245,7 +247,7 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp, /* defining if given module can work on output */ if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) { - pr_err("comedi%d: module in position %d with id 0x%0x is for input only!\n", + dev_err(csdev, "comedi%d: module in position %d with id 0x%0x is for input only!\n", minor, module, usp->usp_module_type[module]); return 0; } @@ -308,7 +310,7 @@ static int unioxx5_subdev_write(struct comedi_device *dev, if (!__unioxx5_digital_write(subdev, data, channel, dev->minor)) return -1; } else { - if (!__unioxx5_analog_write(usp, data, channel, dev->minor)) + if (!__unioxx5_analog_write(subdev, data, channel, dev->minor)) return -1; } -- cgit v1.2.3 From cf328c2a0bfe3f9f3f5ed94ee0bcdd333bc44951 Mon Sep 17 00:00:00 2001 From: Conrad Gomes Date: Fri, 22 Nov 2013 01:27:58 +0530 Subject: Staging: comedi: remove MACRO pr_fmt in unioxx5.c This patch removes MACRO definition pr_fmt which was initially required by pr_info and pr_err logging functions. Signed-off-by: Conrad Gomes Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 6bbc934852fa..d6b75d68a36a 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -38,7 +38,6 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5), */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include -- cgit v1.2.3 From 18fd15f667135433a51d4b952f10b0fd6b5d8959 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:41:39 -0700 Subject: staging: comedi: das6402: remove DEBUG noise The private data does not contain 'das6402_irqcount' or 'das6402_wordsread' members so the printk noise produces build errors when DEBUG is defined. The other printk is just added noise. Remove the printk's to fix the build errors and remove the noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das6402.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index fb25cb847032..e80c19a892cd 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -152,21 +152,12 @@ static irqreturn_t intr_handler(int irq, void *d) dev_warn(dev->class_dev, "BUG: spurious interrupt\n"); return IRQ_HANDLED; } -#ifdef DEBUG - printk("das6402: interrupt! das6402_irqcount=%i\n", - devpriv->das6402_irqcount); - printk("das6402: iobase+2=%i\n", inw_p(dev->iobase + 2)); -#endif das6402_ai_fifo_dregs(dev, s); if (s->async->buf_write_count >= devpriv->ai_bytes_to_read) { outw_p(SCANL, dev->iobase + 2); /* clears the fifo */ outb(0x07, dev->iobase + 8); /* clears all flip-flops */ -#ifdef DEBUG - printk("das6402: Got %i samples\n\n", - devpriv->das6402_wordsread - diff); -#endif s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); } -- cgit v1.2.3 From 76b9e33eaab6482c9fb46b1e6304168586e4f029 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:42:10 -0700 Subject: staging: comedi: pcl816: remove DEBUG macro This macro is only used to output some function tracing debug messages. These messages are just added noise so remove the DEBUG macro as well as the noise. Also, remove pcl816_cmdtest_out() which was only called as part of the DEBUG() in pcl816_ai_cmdtest(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 38 +-------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index ab9d2bd26a20..36a96574b07d 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -44,8 +44,6 @@ Configuration Options: #include "comedi_fc.h" #include "8253.h" -#define DEBUG(x) x - /* boards constants */ /* IO space len */ #define PCLx1x_RANGE 16 @@ -403,22 +401,6 @@ static irqreturn_t interrupt_pcl816(int irq, void *d) return IRQ_NONE; } -/* -============================================================================== - COMMAND MODE -*/ -static void pcl816_cmdtest_out(int e, struct comedi_cmd *cmd) -{ - printk(KERN_INFO "pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, - cmd->start_src, cmd->scan_begin_src, cmd->convert_src); - printk(KERN_INFO "pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n", e, - cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); - printk(KERN_INFO "pcl816 e=%d stopsrc=%x scanend=%x\n", e, - cmd->stop_src, cmd->scan_end_src); - printk(KERN_INFO "pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", - e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); -} - /* ============================================================================== */ @@ -429,10 +411,6 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, int err = 0; int tmp, divisor1 = 0, divisor2 = 0; - DEBUG(printk(KERN_INFO "pcl816 pcl812_ai_cmdtest\n"); - pcl816_cmdtest_out(-1, cmd); - ); - /* Step 1 : check if triggers are trivially valid */ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); @@ -685,8 +663,6 @@ static int pcl816_ai_cancel(struct comedi_device *dev, { struct pcl816_private *devpriv = dev->private; -/* DEBUG(printk("pcl816_ai_cancel()\n");) */ - if (devpriv->irq_blocked > 0) { switch (devpriv->int816_mode) { case INT_TYPE_AI1_DMA: @@ -719,9 +695,7 @@ static int pcl816_ai_cancel(struct comedi_device *dev, break; } } - - DEBUG(printk("comedi: pcl816_ai_cancel() successful\n");) - return 0; + return 0; } /* @@ -823,11 +797,6 @@ check_channel_list(struct comedi_device *dev, /* first channel is every time ok */ chansegment[0] = chanlist[0]; for (i = 1, seglen = 1; i < chanlen; i++, seglen++) { - /* build part of chanlist */ - DEBUG(printk(KERN_INFO "%d. %d %d\n", i, - CR_CHAN(chanlist[i]), - CR_RANGE(chanlist[i]));) - /* we detect loop, this must by finish */ if (chanlist[0] == chanlist[i]) break; @@ -849,11 +818,6 @@ check_channel_list(struct comedi_device *dev, /* check whole chanlist */ for (i = 0, segpos = 0; i < chanlen; i++) { - DEBUG(printk("%d %d=%d %d\n", - CR_CHAN(chansegment[i % seglen]), - CR_RANGE(chansegment[i % seglen]), - CR_CHAN(chanlist[i]), - CR_RANGE(chanlist[i]));) if (chanlist[i] != chansegment[i % seglen]) { printk(KERN_WARNING "comedi%d: pcl816: bad channel or range" -- cgit v1.2.3 From 84f3da09858c821d008d6efd5190565f7e8048c5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:42:34 -0700 Subject: staging: comedi: dt282x: remove DEBUG define This define is only used to enable a debug message during the board attach. The message is just added noise, remove it as well as the DEBUG define. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index a01e6b553887..c4ffedbdde21 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -63,8 +63,6 @@ Notes: #include "comedi_fc.h" -#define DEBUG - #define DT2821_TIMEOUT 100 /* 500 us */ #define DT2821_SIZE 0x10 @@ -1130,14 +1128,6 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) outw(DT2821_BDINIT, dev->iobase + DT2821_SUPCSR); i = inw(dev->iobase + DT2821_ADCSR); -#ifdef DEBUG - printk(KERN_DEBUG " fingerprint=%x,%x,%x,%x,%x", - inw(dev->iobase + DT2821_ADCSR), - inw(dev->iobase + DT2821_CHANCSR), - inw(dev->iobase + DT2821_DACSR), - inw(dev->iobase + DT2821_SUPCSR), - inw(dev->iobase + DT2821_TMRCTR)); -#endif if (((inw(dev->iobase + DT2821_ADCSR) & DT2821_ADCSR_MASK) != DT2821_ADCSR_VAL) || -- cgit v1.2.3 From 9e0c0db6ea38d11c6eb120a2f48bf055d0f679a3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:42:55 -0700 Subject: staging: comedi: fl512: remove DEBUG define This define is not used by the driver. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/fl512.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index e3ff4c438979..aff1e7db138e 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -16,8 +16,6 @@ Configuration options: [0] - I/O port base address */ -#define DEBUG 0 - #include #include "../comedidev.h" -- cgit v1.2.3 From ac50a923858651752e1d08b04c7df8b490787a35 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:43:17 -0700 Subject: staging: comedi: ni_pcidio: remove custom DPRINTK macro The comedi core defines a DPRINTK macro in comedidev.h. Use that macro instead of defining a private version in this driver. Also, remove the DEBUG define since it was only used to enable the DPRINTK macro. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index e3a8fa96d9b3..75da358b7a32 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -47,7 +47,6 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org */ #define USE_DMA -/* #define DEBUG 1 */ /* #define DEBUG_FLAGS */ #include @@ -60,13 +59,6 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org #include "comedi_fc.h" #include "mite.h" -#undef DPRINTK -#ifdef DEBUG -#define DPRINTK(format, args...) pr_debug(format, ## args) -#else -#define DPRINTK(format, args...) do { } while (0) -#endif - #define PCI_DIO_SIZE 4096 #define PCI_MITE_SIZE 4096 -- cgit v1.2.3 From 8fe02e167efa8ed4a4503a5eedc0f49fcb7e3eb9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Oct 2013 19:22:25 +0200 Subject: cfg80211: consolidate passive-scan and no-ibss flags These two flags are used for the same purpose, just combine them into a no-ir flag to annotate no initiating radiation is allowed. Old userspace sending either flag will have it treated as the no-ir flag. To be considerate to older userspace we also send both the no-ir flag and the old no-ibss flags. Newer userspace will have to be aware of older kernels. Update all places in the tree using these flags with the following semantic patch: @@ @@ -NL80211_RRF_PASSIVE_SCAN +NL80211_RRF_NO_IR @@ @@ -NL80211_RRF_NO_IBSS +NL80211_RRF_NO_IR @@ @@ -IEEE80211_CHAN_PASSIVE_SCAN +IEEE80211_CHAN_NO_IR @@ @@ -IEEE80211_CHAN_NO_IBSS +IEEE80211_CHAN_NO_IR @@ @@ -NL80211_RRF_NO_IR | NL80211_RRF_NO_IR +NL80211_RRF_NO_IR @@ @@ -IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_IR +IEEE80211_CHAN_NO_IR @@ @@ -(NL80211_RRF_NO_IR) +NL80211_RRF_NO_IR @@ @@ -(IEEE80211_CHAN_NO_IR) +IEEE80211_CHAN_NO_IR Along with some hand-optimisations in documentation, to remove duplicates and to fix some indentation. Signed-off-by: Luis R. Rodriguez [do all the driver updates in one go] Signed-off-by: Johannes Berg --- Documentation/networking/regulatory.txt | 4 +- drivers/net/wireless/ath/ath10k/mac.c | 4 +- drivers/net/wireless/ath/regd.c | 47 +++++++-------- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 2 +- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 10 ++-- drivers/net/wireless/brcm80211/brcmsmac/channel.c | 31 ++++------ .../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 66 +++++++++++----------- drivers/net/wireless/cw1200/scan.c | 10 ++-- drivers/net/wireless/ipw2x00/ipw2100.c | 4 +- drivers/net/wireless/ipw2x00/ipw2200.c | 8 +-- drivers/net/wireless/iwlegacy/3945-mac.c | 2 +- drivers/net/wireless/iwlegacy/4965-mac.c | 2 +- drivers/net/wireless/iwlegacy/common.c | 4 +- drivers/net/wireless/iwlegacy/debug.c | 8 +-- drivers/net/wireless/iwlwifi/dvm/debugfs.c | 8 +-- drivers/net/wireless/iwlwifi/dvm/scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | 4 +- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 4 +- drivers/net/wireless/iwlwifi/mvm/scan.c | 4 +- drivers/net/wireless/mac80211_hwsim.c | 4 +- drivers/net/wireless/mwifiex/cfg80211.c | 14 ++--- drivers/net/wireless/mwifiex/scan.c | 4 +- drivers/net/wireless/rtlwifi/regd.c | 48 +++++++--------- drivers/net/wireless/ti/wl12xx/scan.c | 2 +- drivers/net/wireless/ti/wlcore/cmd.c | 2 +- drivers/net/wireless/ti/wlcore/main.c | 3 +- drivers/net/wireless/ti/wlcore/scan.c | 12 ++-- include/net/cfg80211.h | 9 ++- include/uapi/linux/nl80211.h | 30 ++++++---- net/mac80211/scan.c | 10 ++-- net/mac80211/tx.c | 3 +- net/wireless/chan.c | 3 +- net/wireless/genregdb.awk | 7 ++- net/wireless/ibss.c | 4 +- net/wireless/mesh.c | 3 +- net/wireless/nl80211.c | 12 ++-- net/wireless/reg.c | 33 ++++------- 37 files changed, 197 insertions(+), 230 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt index 9551622d0a7b..356f791af574 100644 --- a/Documentation/networking/regulatory.txt +++ b/Documentation/networking/regulatory.txt @@ -159,10 +159,10 @@ struct ieee80211_regdomain mydriver_jp_regdom = { REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), /* IEEE 802.11a, channels 34..48 */ REG_RULE(5170-20, 5240+20, 40, 6, 20, - NL80211_RRF_PASSIVE_SCAN), + NL80211_RRF_NO_IR), /* IEEE 802.11a, channels 52..64 */ REG_RULE(5260-20, 5320+20, 40, 6, 20, - NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR| NL80211_RRF_DFS), } }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0b1cc516e778..f23d61fda243 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1351,12 +1351,12 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->allow_vht = true; ch->allow_ibss = - !(channel->flags & IEEE80211_CHAN_NO_IBSS); + !(channel->flags & IEEE80211_CHAN_NO_IR); ch->ht40plus = !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS); - passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN; + passive = channel->flags & IEEE80211_CHAN_NO_IR; ch->passive = passive; ch->freq = channel->center_freq; diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index c00687e05688..e93e517a699f 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -37,17 +37,18 @@ static int __ath_regd_init(struct ath_regulatory *reg); /* We enable active scan on these a case by case basis by regulatory domain */ #define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN) + NL80211_RRF_NO_IR) #define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) + NL80211_RRF_NO_IR | \ + NL80211_RRF_NO_OFDM) /* We allow IBSS on these on a case by case basis by regulatory domain */ #define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ ATH9K_2GHZ_CH12_13, \ @@ -223,18 +224,11 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, * default during init, prior to calling our * regulatory_hint(). */ - if (!(reg_rule->flags & - NL80211_RRF_NO_IBSS)) - ch->flags &= - ~IEEE80211_CHAN_NO_IBSS; - if (!(reg_rule->flags & - NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= - ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } else { if (ch->beacon_found) - ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN); + ch->flags &= ~IEEE80211_CHAN_NO_IR; } } } @@ -260,11 +254,11 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, */ if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { ch = &sband->channels[11]; /* CH 12 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; ch = &sband->channels[12]; /* CH 13 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; return; } @@ -278,17 +272,17 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, ch = &sband->channels[11]; /* CH 12 */ reg_rule = freq_reg_info(wiphy, ch->center_freq); if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } ch = &sband->channels[12]; /* CH 13 */ reg_rule = freq_reg_info(wiphy, ch->center_freq); if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } } @@ -320,8 +314,7 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy) */ if (!(ch->flags & IEEE80211_CHAN_DISABLED)) ch->flags |= IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR; } } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index d7a974532909..fd0a4971244a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -812,7 +812,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, struct ieee80211_channel *chan = request->channels[i]; if (chan->flags & (IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_PASSIVE_SCAN)) + IEEE80211_CHAN_NO_IR)) continue; chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 571f013cebbb..b6a09f97f9a3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -202,9 +202,9 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { /* This is to override regulatory domains defined in cfg80211 module (reg.c) * By default world regulatory domain defined in reg.c puts the flags - * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for - * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't - * start p2p operations on 5GHz channels. All the changes in world regulatory + * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165). + * With respect to these flags, wpa_supplicant doesn't * start p2p + * operations on 5GHz channels. All the changes in world regulatory * domain are to be done here. */ static const struct ieee80211_regdomain brcmf_regdom = { @@ -5197,10 +5197,10 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) if (channel & WL_CHAN_RADAR) band_chan_arr[index].flags |= (IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS); + IEEE80211_CHAN_NO_IR); if (channel & WL_CHAN_PASSIVE) band_chan_arr[index].flags |= - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR; } } if (!update) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index cc87926f5055..7d8f3fd69a87 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -59,23 +59,18 @@ #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) #define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ - NL80211_RRF_PASSIVE_SCAN | \ NL80211_RRF_DFS | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ - NL80211_RRF_PASSIVE_SCAN | \ NL80211_RRF_DFS | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) static const struct ieee80211_regdomain brcms_regdom_x2 = { .n_reg_rules = 6, @@ -395,7 +390,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); brcms_b_set_chanspec(wlc->hw, chanspec, - !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN), + !!(ch->flags & IEEE80211_CHAN_NO_IR), &txpwr); } @@ -657,8 +652,8 @@ static void brcms_reg_apply_radar_flags(struct wiphy *wiphy) */ if (!(ch->flags & IEEE80211_CHAN_DISABLED)) ch->flags |= IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR | + IEEE80211_CHAN_NO_IR; } } @@ -688,14 +683,10 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, if (IS_ERR(rule)) continue; - if (!(rule->flags & NL80211_RRF_NO_IBSS)) - ch->flags &= ~IEEE80211_CHAN_NO_IBSS; - if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= - ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(rule->flags & NL80211_RRF_NO_IR)) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } else if (ch->beacon_found) { - ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN); + ch->flags &= ~IEEE80211_CHAN_NO_IR; } } } diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index edc5d105ff98..e71ce8c842a2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -125,13 +125,13 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = { CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), CHAN2GHZ(12, 2467, - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN2GHZ(13, 2472, - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN2GHZ(14, 2484, - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | IEEE80211_CHAN_NO_OFDM) }; @@ -144,51 +144,51 @@ static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), /* UNII-2 */ CHAN5GHZ(52, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(56, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN5GHZ(60, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(64, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), /* MID */ CHAN5GHZ(100, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(104, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN5GHZ(108, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(112, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN5GHZ(116, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(120, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN5GHZ(124, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(128, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN5GHZ(132, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), CHAN5GHZ(136, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), CHAN5GHZ(140, - IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS | + IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS), /* UNII-3 */ CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index ee3c19037aac..8c017bfd2ffc 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c @@ -197,9 +197,9 @@ void cw1200_scan_work(struct work_struct *work) if ((*it)->band != first->band) break; if (((*it)->flags ^ first->flags) & - IEEE80211_CHAN_PASSIVE_SCAN) + IEEE80211_CHAN_NO_IR) break; - if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + if (!(first->flags & IEEE80211_CHAN_NO_IR) && (*it)->max_power != first->max_power) break; } @@ -210,7 +210,7 @@ void cw1200_scan_work(struct work_struct *work) else scan.max_tx_rate = WSM_TRANSMIT_RATE_1; scan.num_probes = - (first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2; + (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2; scan.num_ssids = priv->scan.n_ssids; scan.ssids = &priv->scan.ssids[0]; scan.num_channels = it - priv->scan.curr; @@ -233,7 +233,7 @@ void cw1200_scan_work(struct work_struct *work) } for (i = 0; i < scan.num_channels; ++i) { scan.ch[i].number = priv->scan.curr[i]->hw_value; - if (priv->scan.curr[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) { + if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) { scan.ch[i].min_chan_time = 50; scan.ch[i].max_chan_time = 100; } else { @@ -241,7 +241,7 @@ void cw1200_scan_work(struct work_struct *work) scan.ch[i].max_chan_time = 25; } } - if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + if (!(first->flags & IEEE80211_CHAN_NO_IR) && priv->scan.output_power != first->max_power) { priv->scan.output_power = first->max_power; wsm_set_output_power(priv, diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index f8ab193009cd..813c9af0ebd6 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1930,10 +1930,10 @@ static int ipw2100_wdev_init(struct net_device *dev) bg_band->channels[i].max_power = geo->bg[i].max_power; if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) bg_band->channels[i].flags |= - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR; if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) bg_band->channels[i].flags |= - IEEE80211_CHAN_NO_IBSS; + IEEE80211_CHAN_NO_IR; if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) bg_band->channels[i].flags |= IEEE80211_CHAN_RADAR; diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index f394af777cf5..4eca9e20adea 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11472,10 +11472,10 @@ static int ipw_wdev_init(struct net_device *dev) bg_band->channels[i].max_power = geo->bg[i].max_power; if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) bg_band->channels[i].flags |= - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR; if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) bg_band->channels[i].flags |= - IEEE80211_CHAN_NO_IBSS; + IEEE80211_CHAN_NO_IR; if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) bg_band->channels[i].flags |= IEEE80211_CHAN_RADAR; @@ -11511,10 +11511,10 @@ static int ipw_wdev_init(struct net_device *dev) a_band->channels[i].max_power = geo->a[i].max_power; if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) a_band->channels[i].flags |= - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR; if (geo->a[i].flags & LIBIPW_CH_NO_IBSS) a_band->channels[i].flags |= - IEEE80211_CHAN_NO_IBSS; + IEEE80211_CHAN_NO_IR; if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT) a_band->channels[i].flags |= IEEE80211_CHAN_RADAR; diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index dea3b50d68b9..5a66595b0faf 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -1595,7 +1595,7 @@ il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band, * and use long active_dwell time. */ if (!is_active || il_is_channel_passive(ch_info) || - (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) { + (chan->flags & IEEE80211_CHAN_NO_IR)) { scan_ch->type = 0; /* passive */ if (IL_UCODE_API(il->ucode_ver) == 1) scan_ch->active_dwell = diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 3982ab76f375..1c5f8cdbd3a5 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -805,7 +805,7 @@ il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif, } if (!is_active || il_is_channel_passive(ch_info) || - (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) + (chan->flags & IEEE80211_CHAN_NO_IR)) scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; else scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index b03e22ef5462..a27b14cfeaec 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -3445,10 +3445,10 @@ il_init_geos(struct il_priv *il) if (il_is_channel_valid(ch)) { if (!(ch->flags & EEPROM_CHANNEL_IBSS)) - geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; + geo_ch->flags |= IEEE80211_CHAN_NO_IR; if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) - geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; + geo_ch->flags |= IEEE80211_CHAN_NO_IR; if (ch->flags & EEPROM_CHANNEL_RADAR) geo_ch->flags |= IEEE80211_CHAN_RADAR; diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index eff26501d60a..3a487a3bb5de 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -567,12 +567,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", ((channels[i]. - flags & IEEE80211_CHAN_NO_IBSS) || + flags & IEEE80211_CHAN_NO_IR) || (channels[i]. flags & IEEE80211_CHAN_RADAR)) ? "" : ", IBSS", channels[i]. - flags & IEEE80211_CHAN_PASSIVE_SCAN ? + flags & IEEE80211_CHAN_NO_IR ? "passive only" : "active/passive"); } supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); @@ -594,12 +594,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", ((channels[i]. - flags & IEEE80211_CHAN_NO_IBSS) || + flags & IEEE80211_CHAN_NO_IR) || (channels[i]. flags & IEEE80211_CHAN_RADAR)) ? "" : ", IBSS", channels[i]. - flags & IEEE80211_CHAN_PASSIVE_SCAN ? + flags & IEEE80211_CHAN_NO_IR ? "passive only" : "active/passive"); } ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index d94f8ab15004..f69301e505ee 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c @@ -352,12 +352,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, channels[i].max_power, channels[i].flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", - ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) + ((channels[i].flags & IEEE80211_CHAN_NO_IR) || (channels[i].flags & IEEE80211_CHAN_RADAR)) ? "" : ", IBSS", channels[i].flags & - IEEE80211_CHAN_PASSIVE_SCAN ? + IEEE80211_CHAN_NO_IR ? "passive only" : "active/passive"); } supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); @@ -375,12 +375,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, channels[i].max_power, channels[i].flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", - ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) + ((channels[i].flags & IEEE80211_CHAN_NO_IR) || (channels[i].flags & IEEE80211_CHAN_RADAR)) ? "" : ", IBSS", channels[i].flags & - IEEE80211_CHAN_PASSIVE_SCAN ? + IEEE80211_CHAN_NO_IR ? "passive only" : "active/passive"); } ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 35e0ee8b4e5b..928f8640a0a7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c @@ -544,7 +544,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, channel = chan->hw_value; scan_ch->channel = cpu_to_le16(channel); - if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) + if (!is_active || (chan->flags & IEEE80211_CHAN_NO_IR)) scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; else scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 4c887f365908..f4a6d317a023 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c @@ -614,10 +614,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, channel->flags = IEEE80211_CHAN_NO_HT40; if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) - channel->flags |= IEEE80211_CHAN_NO_IBSS; + channel->flags |= IEEE80211_CHAN_NO_IR; if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) - channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; + channel->flags |= IEEE80211_CHAN_NO_IR; if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) channel->flags |= IEEE80211_CHAN_RADAR; diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index b76a9a8fc0b3..2fab203d3027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -223,10 +223,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, channel->flags |= IEEE80211_CHAN_NO_160MHZ; if (!(ch_flags & NVM_CHANNEL_IBSS)) - channel->flags |= IEEE80211_CHAN_NO_IBSS; + channel->flags |= IEEE80211_CHAN_NO_IR; if (!(ch_flags & NVM_CHANNEL_ACTIVE)) - channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; + channel->flags |= IEEE80211_CHAN_NO_IR; if (ch_flags & NVM_CHANNEL_RADAR) channel->flags |= IEEE80211_CHAN_RADAR; diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index dff7592e1ff8..e0cd100b40cd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -192,7 +192,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, for (i = 0; i < cmd->channel_count; i++) { chan->channel = cpu_to_le16(req->channels[i]->hw_value); chan->type = cpu_to_le32(type); - if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) + if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); chan->active_dwell = cpu_to_le16(active_dwell); chan->passive_dwell = cpu_to_le16(passive_dwell); @@ -642,7 +642,7 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, channels->iter_count[index] = cpu_to_le16(1); channels->iter_interval[index] = 0; - if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) + if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR)) channels->type[index] |= cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index de0df86704e7..33d4b31995da 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -159,7 +159,7 @@ static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { .reg_rules = { REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), REG_RULE(5725-10, 5850+10, 40, 0, 30, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), } }; @@ -1485,7 +1485,7 @@ static void hw_scan_work(struct work_struct *work) req->channels[hwsim->scan_chan_idx]->center_freq); hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; - if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || + if (hwsim->tmp_chan->flags & IEEE80211_CHAN_NO_IR || !req->n_ssids) { dwell = 120; } else { diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index fbad00a5abc8..7f68943f02c2 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -50,24 +50,24 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = { REG_RULE(2412-10, 2462+10, 40, 3, 20, 0), /* Channel 12 - 13 */ REG_RULE(2467-10, 2472+10, 20, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* Channel 14 */ REG_RULE(2484-10, 2484+10, 20, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM), /* Channel 36 - 48 */ REG_RULE(5180-10, 5240+10, 40, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* Channel 149 - 165 */ REG_RULE(5745-10, 5825+10, 40, 3, 20, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* Channel 52 - 64 */ REG_RULE(5260-10, 5320+10, 40, 3, 30, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_DFS), /* Channel 100 - 140 */ REG_RULE(5500-10, 5700+10, 40, 3, 30, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_DFS), } }; @@ -1968,7 +1968,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, user_scan_cfg->chan_list[i].chan_number = chan->hw_value; user_scan_cfg->chan_list[i].radio_type = chan->band; - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + if (chan->flags & IEEE80211_CHAN_NO_IR) user_scan_cfg->chan_list[i].scan_type = MWIFIEX_SCAN_TYPE_PASSIVE; else diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 8cf7d50a7603..0ed06646f19a 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -515,14 +515,14 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, scan_chan_list[chan_idx].max_scan_time = cpu_to_le16((u16) user_scan_in-> chan_list[0].scan_time); - else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + else if (ch->flags & IEEE80211_CHAN_NO_IR) scan_chan_list[chan_idx].max_scan_time = cpu_to_le16(adapter->passive_scan_time); else scan_chan_list[chan_idx].max_scan_time = cpu_to_le16(adapter->active_scan_time); - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + if (ch->flags & IEEE80211_CHAN_NO_IR) scan_chan_list[chan_idx].chan_scan_mode_bitmap |= MWIFIEX_PASSIVE_SCAN; else diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index d7d0d4948b01..8453c53143f5 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -59,30 +59,26 @@ static struct country_code_to_enum_rd allCountries[] = { */ #define RTL819x_2GHZ_CH12_13 \ REG_RULE(2467-10, 2472+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN) + NL80211_RRF_NO_IR) #define RTL819x_2GHZ_CH14 \ REG_RULE(2484-10, 2484+10, 40, 0, 20, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_OFDM) + NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM) /* 5G chan 36 - chan 64*/ #define RTL819x_5GHZ_5150_5350 \ REG_RULE(5150-10, 5350+10, 40, 0, 30, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) /* 5G chan 100 - chan 165*/ #define RTL819x_5GHZ_5470_5850 \ REG_RULE(5470-10, 5850+10, 40, 0, 30, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) /* 5G chan 149 - chan 165*/ #define RTL819x_5GHZ_5725_5850 \ REG_RULE(5725-10, 5850+10, 40, 0, 30, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) + NL80211_RRF_NO_IR) #define RTL819x_5GHZ_ALL \ (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) @@ -185,16 +181,11 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, *regulatory_hint(). */ - if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) - ch->flags &= ~IEEE80211_CHAN_NO_IBSS; - if (!(reg_rule-> - flags & NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= - ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } else { if (ch->beacon_found) - ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN); + ch->flags &= ~IEEE80211_CHAN_NO_IR; } } } @@ -219,11 +210,11 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, */ if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { ch = &sband->channels[11]; /* CH 12 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; ch = &sband->channels[12]; /* CH 13 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; return; } @@ -237,17 +228,17 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, ch = &sband->channels[11]; /* CH 12 */ reg_rule = freq_reg_info(wiphy, ch->center_freq); if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } ch = &sband->channels[12]; /* CH 13 */ reg_rule = freq_reg_info(wiphy, ch->center_freq); if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; } } @@ -284,8 +275,7 @@ static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) */ if (!(ch->flags & IEEE80211_CHAN_DISABLED)) ch->flags |= IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; + IEEE80211_CHAN_NO_IR; } } diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index 4a0bbb13806b..7541bd1a4a4b 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c @@ -47,7 +47,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, * In active scans, we only scan channels not * marked as passive. */ - (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { + (passive || !(flags & IEEE80211_CHAN_NO_IR))) { wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", req->channels[i]->band, req->channels[i]->center_freq); diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 34d9dfff2ad3..9b2ecf52449f 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1688,7 +1688,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) if (channel->flags & (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_PASSIVE_SCAN)) + IEEE80211_CHAN_NO_IR)) continue; ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 0368b9cbfb89..e9da47cead58 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -91,8 +91,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy, continue; if (ch->flags & IEEE80211_CHAN_RADAR) - ch->flags |= IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; + ch->flags |= IEEE80211_CHAN_NO_IR; } diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index 7ed86203304b..1e3d51cd673a 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -188,16 +188,14 @@ wlcore_scan_get_channels(struct wl1271 *wl, flags = req_channels[i]->flags; if (force_passive) - flags |= IEEE80211_CHAN_PASSIVE_SCAN; + flags |= IEEE80211_CHAN_NO_IR; if ((req_channels[i]->band == band) && !(flags & IEEE80211_CHAN_DISABLED) && (!!(flags & IEEE80211_CHAN_RADAR) == radar) && /* if radar is set, we ignore the passive flag */ (radar || - !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { - - + !!(flags & IEEE80211_CHAN_NO_IR) == passive)) { if (flags & IEEE80211_CHAN_RADAR) { channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; @@ -220,7 +218,7 @@ wlcore_scan_get_channels(struct wl1271 *wl, (band == IEEE80211_BAND_2GHZ) && (channels[j].channel >= 12) && (channels[j].channel <= 14) && - (flags & IEEE80211_CHAN_PASSIVE_SCAN) && + (flags & IEEE80211_CHAN_NO_IR) && !force_passive) { /* pactive channels treated as DFS */ channels[j].flags = SCAN_CHANNEL_FLAGS_DFS; @@ -243,8 +241,8 @@ wlcore_scan_get_channels(struct wl1271 *wl, max_dwell_time_active, flags & IEEE80211_CHAN_RADAR ? ", DFS" : "", - flags & IEEE80211_CHAN_PASSIVE_SCAN ? - ", PASSIVE" : ""); + flags & IEEE80211_CHAN_NO_IR ? + ", NO-IR" : ""); j++; } } diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3eae46cb1acf..c1b887413234 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -91,9 +91,8 @@ enum ieee80211_band { * Channel flags set by the regulatory control code. * * @IEEE80211_CHAN_DISABLED: This channel is disabled. - * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted - * on this channel. - * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. + * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes + * sending probe requests or beaconing. * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel * is not permitted. @@ -113,8 +112,8 @@ enum ieee80211_band { */ enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, - IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, - IEEE80211_CHAN_NO_IBSS = 1<<2, + IEEE80211_CHAN_NO_IR = 1<<1, + /* hole at 1<<2 */ IEEE80211_CHAN_RADAR = 1<<3, IEEE80211_CHAN_NO_HT40PLUS = 1<<4, IEEE80211_CHAN_NO_HT40MINUS = 1<<5, diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 3d8325bb50cd..7e25164adfe9 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2231,10 +2231,9 @@ enum nl80211_band_attr { * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current * regulatory domain. - * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is - * permitted on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted - * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation + * are permitted on this channel, this includes sending probe + * requests, or modes of operation that require beaconing. * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory * on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm @@ -2261,8 +2260,8 @@ enum nl80211_frequency_attr { __NL80211_FREQUENCY_ATTR_INVALID, NL80211_FREQUENCY_ATTR_FREQ, NL80211_FREQUENCY_ATTR_DISABLED, - NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, - NL80211_FREQUENCY_ATTR_NO_IBSS, + NL80211_FREQUENCY_ATTR_NO_IR, + __NL80211_FREQUENCY_ATTR_NO_IBSS, NL80211_FREQUENCY_ATTR_RADAR, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, NL80211_FREQUENCY_ATTR_DFS_STATE, @@ -2278,6 +2277,9 @@ enum nl80211_frequency_attr { }; #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER +#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR /** * enum nl80211_bitrate_attr - bitrate attributes @@ -2420,8 +2422,9 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_DFS: DFS support is required to be used * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links - * @NL80211_RRF_PASSIVE_SCAN: passive scan is required - * @NL80211_RRF_NO_IBSS: no IBSS is allowed + * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, + * this includes probe requests or modes of operation that require + * beaconing. */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, @@ -2431,10 +2434,17 @@ enum nl80211_reg_rule_flags { NL80211_RRF_DFS = 1<<4, NL80211_RRF_PTP_ONLY = 1<<5, NL80211_RRF_PTMP_ONLY = 1<<6, - NL80211_RRF_PASSIVE_SCAN = 1<<7, - NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_NO_IR = 1<<7, + __NL80211_RRF_NO_IBSS = 1<<8, }; +#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR + +/* For backport compatibility with older userspace */ +#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) + /** * enum nl80211_dfs_regions - regulatory DFS regions * diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5ad66a83ef7f..c22cbb57b49d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -526,7 +526,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, ieee80211_hw_config(local, 0); if ((req->channels[0]->flags & - IEEE80211_CHAN_PASSIVE_SCAN) || + IEEE80211_CHAN_NO_IR) || !local->scan_req->n_ssids) { next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; } else { @@ -572,7 +572,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) * TODO: channel switching also consumes quite some time, * add that delay as well to get a better estimation */ - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + if (chan->flags & IEEE80211_CHAN_NO_IR) return IEEE80211_PASSIVE_CHANNEL_TIME; return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; } @@ -696,7 +696,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, * * In any case, it is not necessary for a passive scan. */ - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || + if (chan->flags & IEEE80211_CHAN_NO_IR || !local->scan_req->n_ssids) { *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; local->next_scan_state = SCAN_DECISION; @@ -881,7 +881,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *tmp_ch = &local->hw.wiphy->bands[band]->channels[i]; - if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | + if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_DISABLED)) continue; @@ -895,7 +895,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, local->int_scan_req->n_channels = n_ch; } else { - if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | + if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_DISABLED))) goto unlock; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c558b246ef00..5ad2e8b1f92c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1724,8 +1724,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, * radar detection by itself. We can do that later by adding a * monitor flag interfaces used for AP support. */ - if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_PASSIVE_SCAN))) + if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))) goto fail_rcu; ieee80211_xmit(sdata, skb, chan->band); diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 9b8cc877eb19..344966496b70 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -467,8 +467,7 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, res = cfg80211_chandef_usable(wiphy, chandef, IEEE80211_CHAN_DISABLED | - IEEE80211_CHAN_PASSIVE_SCAN | - IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR); trace_cfg80211_return_bool(res); diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 42ed274e81f4..c808619ac9c6 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk @@ -107,10 +107,13 @@ active && /^[ \t]*\(/ { } else if (flagarray[arg] == "PTMP-ONLY") { flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " } else if (flagarray[arg] == "PASSIVE-SCAN") { - flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | " + flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " } else if (flagarray[arg] == "NO-IBSS") { - flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | " + flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " + } else if (flagarray[arg] == "NO-IR") { + flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " } + } flags = flags "0" printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 9d797df56649..f79105712949 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -274,7 +274,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; - if (chan->flags & IEEE80211_CHAN_NO_IBSS) + if (chan->flags & IEEE80211_CHAN_NO_IR) continue; if (chan->flags & IEEE80211_CHAN_DISABLED) continue; @@ -345,7 +345,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, chan = ieee80211_get_channel(wdev->wiphy, freq); if (!chan) return -EINVAL; - if (chan->flags & IEEE80211_CHAN_NO_IBSS || + if (chan->flags & IEEE80211_CHAN_NO_IR || chan->flags & IEEE80211_CHAN_DISABLED) return -EINVAL; } diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 0553fd4d85ae..b0e1869de7de 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -141,8 +141,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; - if (chan->flags & (IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN | + if (chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR)) continue; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a7f4e7902104..41af3a0e9961 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -545,12 +545,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, if ((chan->flags & IEEE80211_CHAN_DISABLED) && nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN)) - goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) - goto nla_put_failure; + if (chan->flags & IEEE80211_CHAN_NO_IR) { + if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR)) + goto nla_put_failure; + if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS)) + goto nla_put_failure; + } if (chan->flags & IEEE80211_CHAN_RADAR) { if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) goto nla_put_failure; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7da67fd0b418..e4e3337ba296 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -163,35 +163,29 @@ static const struct ieee80211_regdomain world_regdom = { REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), /* IEEE 802.11b/g, channels 12..13. */ REG_RULE(2467-10, 2472+10, 40, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* IEEE 802.11 channel 14 - Only JP enables * this and for 802.11b only */ REG_RULE(2484-10, 2484+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM), /* IEEE 802.11a, channel 36..48 */ REG_RULE(5180-10, 5240+10, 160, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* IEEE 802.11a, channel 52..64 - DFS required */ REG_RULE(5260-10, 5320+10, 160, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_DFS), /* IEEE 802.11a, channel 100..144 - DFS required */ REG_RULE(5500-10, 5720+10, 160, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_IR | NL80211_RRF_DFS), /* IEEE 802.11a, channel 149..165 */ REG_RULE(5745-10, 5825+10, 80, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), + NL80211_RRF_NO_IR), /* IEEE 802.11ad (60gHz), channels 1..3 */ REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), @@ -698,10 +692,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, static u32 map_regdom_flags(u32 rd_flags) { u32 channel_flags = 0; - if (rd_flags & NL80211_RRF_PASSIVE_SCAN) - channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN; - if (rd_flags & NL80211_RRF_NO_IBSS) - channel_flags |= IEEE80211_CHAN_NO_IBSS; + if (rd_flags & NL80211_RRF_NO_IR_ALL) + channel_flags |= IEEE80211_CHAN_NO_IR; if (rd_flags & NL80211_RRF_DFS) channel_flags |= IEEE80211_CHAN_RADAR; if (rd_flags & NL80211_RRF_NO_OFDM) @@ -1066,13 +1058,8 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, chan_before.center_freq = chan->center_freq; chan_before.flags = chan->flags; - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { - chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - channel_changed = true; - } - - if (chan->flags & IEEE80211_CHAN_NO_IBSS) { - chan->flags &= ~IEEE80211_CHAN_NO_IBSS; + if (chan->flags & IEEE80211_CHAN_NO_IR) { + chan->flags &= ~IEEE80211_CHAN_NO_IR; channel_changed = true; } -- cgit v1.2.3 From 70526e543c8087b7fa136fd5e6be98332d609848 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Fri, 1 Nov 2013 20:35:58 +0100 Subject: mac80211_hwsim: use debugfs_remove_recursive Use debugfs_remove_recursive. That avoids the need for the new dentry pointers and extra debugfs_remove calls. Signed-off-by: Janusz Dziedzic Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 33d4b31995da..76b362ed76bd 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -353,7 +353,6 @@ struct mac80211_hwsim_data { } ps; bool ps_poll_pending; struct dentry *debugfs; - struct dentry *debugfs_ps; struct sk_buff_head pending; /* packets pending */ /* @@ -362,7 +361,6 @@ struct mac80211_hwsim_data { * radio can be in more then one group. */ u64 group; - struct dentry *debugfs_group; int power_level; @@ -1734,9 +1732,7 @@ static void mac80211_hwsim_free(void) spin_unlock_bh(&hwsim_radio_lock); list_for_each_entry_safe(data, tmpdata, &tmplist, list) { - debugfs_remove(data->debugfs_group); - debugfs_remove(data->debugfs_ps); - debugfs_remove(data->debugfs); + debugfs_remove_recursive(data->debugfs); ieee80211_unregister_hw(data->hw); device_release_driver(data->dev); device_unregister(data->dev); @@ -2534,12 +2530,10 @@ static int __init init_mac80211_hwsim(void) data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); - data->debugfs_ps = debugfs_create_file("ps", 0666, - data->debugfs, data, - &hwsim_fops_ps); - data->debugfs_group = debugfs_create_file("group", 0666, - data->debugfs, data, - &hwsim_fops_group); + debugfs_create_file("ps", 0666, data->debugfs, data, + &hwsim_fops_ps); + debugfs_create_file("group", 0666, data->debugfs, data, + &hwsim_fops_group); tasklet_hrtimer_init(&data->beacon_timer, mac80211_hwsim_beacon, -- cgit v1.2.3 From bba05e3d5afb6ed31c00068f12418a9dacb42328 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Tue, 5 Nov 2013 13:03:53 +0100 Subject: mac80211_hwsim: Add iface comb for DFS Add iface combination that will allow DFS support. Add also debugfs dfs_simulate_radar file that can be used to simulate radar event. This could be useful for mac80211/cfg80211/ regulatory/hostap code testing without real HW. Signed-off-by: Janusz Dziedzic Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 50 +++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 76b362ed76bd..bad66e3cdd12 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1889,6 +1889,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val) DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, "%llu\n"); +static int hwsim_write_simulate_radar(void *dat, u64 val) +{ + struct mac80211_hwsim_data *data = dat; + + ieee80211_radar_detected(data->hw); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL, + hwsim_write_simulate_radar, "%llu\n"); static int hwsim_fops_group_read(void *dat, u64 *val) { @@ -2190,11 +2201,28 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, }; -static struct ieee80211_iface_combination hwsim_if_comb = { - .limits = hwsim_if_limits, - .n_limits = ARRAY_SIZE(hwsim_if_limits), - .max_interfaces = 2048, - .num_different_channels = 1, +static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { + { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, +}; + +static struct ieee80211_iface_combination hwsim_if_comb[] = { + { + .limits = hwsim_if_limits, + .n_limits = ARRAY_SIZE(hwsim_if_limits), + .max_interfaces = 2048, + .num_different_channels = 1, + }, + { + .limits = hwsim_if_dfs_limits, + .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits), + .max_interfaces = 8, + .num_different_channels = 1, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_160), + } }; static int __init init_mac80211_hwsim(void) @@ -2212,7 +2240,7 @@ static int __init init_mac80211_hwsim(void) return -EINVAL; if (channels > 1) { - hwsim_if_comb.num_different_channels = channels; + hwsim_if_comb[0].num_different_channels = channels; mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; mac80211_hwsim_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan; @@ -2292,13 +2320,15 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->n_addresses = 2; hw->wiphy->addresses = data->addresses; - hw->wiphy->iface_combinations = &hwsim_if_comb; - hw->wiphy->n_iface_combinations = 1; + hw->wiphy->iface_combinations = hwsim_if_comb; + hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); if (channels > 1) { hw->wiphy->max_scan_ssids = 255; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; hw->wiphy->max_remain_on_channel_duration = 1000; + /* For channels > 1 DFS is not allowed */ + hw->wiphy->n_iface_combinations = 1; } INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); @@ -2534,6 +2564,10 @@ static int __init init_mac80211_hwsim(void) &hwsim_fops_ps); debugfs_create_file("group", 0666, data->debugfs, data, &hwsim_fops_group); + if (channels == 1) + debugfs_create_file("dfs_simulate_radar", 0222, + data->debugfs, + data, &hwsim_simulate_radar); tasklet_hrtimer_init(&data->beacon_timer, mac80211_hwsim_beacon, -- cgit v1.2.3 From c17aa52c5bf571533cc8561292f7316b9216eddc Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Tue, 5 Nov 2013 13:03:54 +0100 Subject: mac80211_hwsim: VHT add 160MHz width support Add 160MHz width support. This could be usefull for testing VHT160 DFS functionality. This could be also usefull in the future when DFS and non-DFS channels could be mixed. Signed-off-by: Janusz Dziedzic Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index bad66e3cdd12..bd7dd0d242d6 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2412,6 +2412,7 @@ static int __init init_mac80211_hwsim(void) sband->vht_cap.cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | IEEE80211_VHT_CAP_RXLDPC | IEEE80211_VHT_CAP_SHORT_GI_80 | IEEE80211_VHT_CAP_SHORT_GI_160 | -- cgit v1.2.3 From b5e2396de75862459b3ad323b4d9c85ead0a7a6d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:44:31 -0700 Subject: staging: comedi: ni_pcidio: remove DEBUG and DEBUG_FLAGS defines These defines are not used in the driver. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_65xx.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 853f62b2b1a9..aae708bfbe15 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -43,9 +43,6 @@ except maybe the 6514. */ -#define DEBUG 1 -#define DEBUG_FLAGS - #include #include #include -- cgit v1.2.3 From afb1b61fde4ee679f2a6b159c6aec7f61a749c26 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:44:58 -0700 Subject: staging: comedi: ni_pcidio: remove DEBUG define This define is only used to enable some debug messages during the board attach. These are just added noise, remove them as well as the DEBUG define. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 856c73d8b7cd..d03935257b97 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -98,8 +98,6 @@ are not supported. #include "ni_stc.h" #include "8255.h" -#undef DEBUG - #define ATMIO 1 #undef PCIMIO @@ -437,19 +435,6 @@ static int ni_atmio_attach(struct comedi_device *dev, if (ret) return ret; -#ifdef DEBUG - /* board existence sanity check */ - { - int i; - - printk(" board fingerprint:"); - for (i = 0; i < 16; i += 2) { - printk(" %04x %02x", inw(dev->iobase + i), - inb(dev->iobase + i + 1)); - } - } -#endif - /* get board type */ board = ni_getboardtype(dev); -- cgit v1.2.3 From f9a431f2e0a680cdf4fad43762c302d062fa10d0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:45:18 -0700 Subject: staging: comedi: dt3000: remove DEBUG define This define unables some debug code that prints the status flags during the interrupt handler. These messages are just added noise and it's probably not a good idea to spew them during the interrupt anyway. Remove the DEBUG define as well as the debug code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt3000.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 292226eeff92..3073efd79248 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -48,8 +48,6 @@ AO commands are not supported. you the docs without one, also. */ -#define DEBUG 1 - #include #include #include @@ -253,24 +251,6 @@ struct dt3k_private { unsigned int ai_rear; }; -#ifdef DEBUG -static char *intr_flags[] = { - "AdFull", "AdSwError", "AdHwError", "DaEmpty", - "DaSwError", "DaHwError", "CtDone", "CmDone", -}; - -static void debug_intr_flags(unsigned int flags) -{ - int i; - printk(KERN_DEBUG "dt3k: intr_flags:"); - for (i = 0; i < 8; i++) { - if (flags & (1 << i)) - printk(KERN_CONT " %s", intr_flags[i]); - } - printk(KERN_CONT "\n"); -} -#endif - #define TIMEOUT 100 static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd) @@ -380,9 +360,6 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) s = &dev->subdevices[0]; status = readw(devpriv->io_addr + DPR_Intr_Flag); -#ifdef DEBUG - debug_intr_flags(status); -#endif if (status & DT3000_ADFULL) { dt3k_ai_empty_fifo(dev, s); -- cgit v1.2.3 From d2601699d3381525d87cc7ccb3e886697c5af812 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:45:38 -0700 Subject: staging: comedi: remove comedi_debug module parameter Remove this module parameter and use the CONFIG_COMEDI_DEBUG option to enable normal kernel debugging with -DDEBUG flag. Remove the #undef DEBUG from all the comedi source files so they will honour the -DDEBUG flag. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Makefile | 2 ++ drivers/staging/comedi/comedi_fops.c | 11 ----------- drivers/staging/comedi/comedidev.h | 11 +---------- drivers/staging/comedi/drivers/Makefile | 1 + drivers/staging/comedi/drivers/ni_mio_cs.c | 2 -- drivers/staging/comedi/kcomedilib/Makefile | 2 ++ 6 files changed, 6 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/Makefile b/drivers/staging/comedi/Makefile index e6dfc98f8c8e..fae2d9090006 100644 --- a/drivers/staging/comedi/Makefile +++ b/drivers/staging/comedi/Makefile @@ -1,3 +1,5 @@ +ccflags-$(CONFIG_COMEDI_DEBUG) := -DDEBUG + comedi-y := comedi_fops.o range.o drivers.o \ comedi_buf.o comedi-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_pci.o diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 58f2b27144ca..1071c9601d1a 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -16,8 +16,6 @@ GNU General Public License for more details. */ -#undef DEBUG - #include "comedi_compat32.h" #include @@ -47,15 +45,6 @@ #define COMEDI_NUM_SUBDEVICE_MINORS \ (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS) -#ifdef CONFIG_COMEDI_DEBUG -int comedi_debug; -EXPORT_SYMBOL_GPL(comedi_debug); -module_param(comedi_debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(comedi_debug, - "enable comedi core and driver debugging if non-zero (default 0)" - ); -#endif - static int comedi_num_legacy_minors; module_param(comedi_num_legacy_minors, int, S_IRUGO); MODULE_PARM_DESC(comedi_num_legacy_minors, diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index a7b8937aa4a3..3c6329bed508 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -27,10 +27,7 @@ #include "comedi.h" -#define DPRINTK(format, args...) do { \ - if (comedi_debug) \ - pr_debug("comedi: " format, ## args); \ -} while (0) +#define DPRINTK(format, args...) pr_debug("comedi: " format, ## args); #define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) #define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, \ @@ -216,12 +213,6 @@ static inline const void *comedi_board(const struct comedi_device *dev) return dev->board_ptr; } -#ifdef CONFIG_COMEDI_DEBUG -extern int comedi_debug; -#else -static const int comedi_debug; -#endif - /* * function prototypes */ diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 94cbd2618fc8..a16e674e2a2b 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -1,5 +1,6 @@ # Makefile for individual comedi drivers # +ccflags-$(CONFIG_COMEDI_DEBUG) := -DDEBUG # Comedi "helper" modules diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 229a273f2016..de421486b758 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -47,8 +47,6 @@ See the notes in the ni_atmio.o driver. #include #include -#undef DEBUG - #define ATMIO 1 #undef PCIMIO diff --git a/drivers/staging/comedi/kcomedilib/Makefile b/drivers/staging/comedi/kcomedilib/Makefile index 18ee99bdde08..3aff8ed08e2d 100644 --- a/drivers/staging/comedi/kcomedilib/Makefile +++ b/drivers/staging/comedi/kcomedilib/Makefile @@ -1,3 +1,5 @@ +ccflags-$(CONFIG_COMEDI_DEBUG) := -DDEBUG + obj-$(CONFIG_COMEDI_KCOMEDILIB) += kcomedilib.o kcomedilib-objs := kcomedilib_main.o -- cgit v1.2.3 From 2cde476df4155a89342a6cdf27581a4c811689b7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:45:58 -0700 Subject: staging: comedi: range: remove use of DPRINTK Use dev_dbg() instead of the DPRINTK macro to output the comedi debugging information. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/range.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 8fde55495d34..46b3da686384 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -83,8 +83,10 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, } if (RANGE_LENGTH(it.range_type) != lr->length) { - DPRINTK("wrong length %d should be %d (0x%08x)\n", - RANGE_LENGTH(it.range_type), lr->length, it.range_type); + dev_dbg(dev->class_dev, + "wrong length %d should be %d (0x%08x)\n", + RANGE_LENGTH(it.range_type), + lr->length, it.range_type); return -EINVAL; } @@ -123,7 +125,8 @@ static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec) default: break; } - DPRINTK("subdevice does not support aref %i", aref); + dev_dbg(s->device->class_dev, "subdevice does not support aref %i", + aref); return 1; } -- cgit v1.2.3 From c001798aa1346561cc97af96d8145d7f44d7d6c2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:46:21 -0700 Subject: staging: comedi: pcl816: remove use of DPRINTK Remove the DPRINTK messages that are just function trace noise. Use dev_dbg() instead of the DPRINTK macro to output the comedi debugging information. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 36a96574b07d..7b92aa50aa7f 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -174,7 +174,6 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, int n; int timeout; - DPRINTK("mode 0 analog input\n"); /* software trigger, DMA and INT off */ outb(0, dev->iobase + PCL816_CONTROL); /* clear INT (conversion end) flag */ @@ -370,8 +369,6 @@ static irqreturn_t interrupt_pcl816(int irq, void *d) struct comedi_device *dev = d; struct pcl816_private *devpriv = dev->private; - DPRINTK(""); - if (!dev->attached) { comedi_error(dev, "premature interrupt"); return IRQ_HANDLED; @@ -608,7 +605,6 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; } - DPRINTK("pcl816 END: pcl812_ai_cmd()\n"); return 0; } @@ -762,8 +758,8 @@ start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, udelay(1); if (mode == 1) { - DPRINTK("mode %d, divisor1 %d, divisor2 %d\n", mode, divisor1, - divisor2); + dev_dbg(dev->class_dev, "mode %d, divisor1 %d, divisor2 %d\n", + mode, divisor1, divisor2); outb(divisor2 & 0xff, dev->iobase + PCL816_CTR2); outb((divisor2 >> 8) & 0xff, dev->iobase + PCL816_CTR2); outb(divisor1 & 0xff, dev->iobase + PCL816_CTR1); -- cgit v1.2.3 From 0a783410a1051fdd9238247ed6518eb5ea001f5e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:46:42 -0700 Subject: staging: comedi: amplc_pci224: remove use of DPRINTK Use dev_dbg() instead of the DPRINTK macro to output the comedi debugging information. The dev_dbg() will prefix the messages appropriately so remove the "comedi%d: " DRIVER_NAME portion and use __func__ to show the actual function name for debugging. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 810e397d8fd7..dcccdce53c18 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -909,16 +909,14 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, } if (errors) { if (errors & dupchan_err) { - DPRINTK("comedi%d: " DRIVER_NAME - ": ao_cmdtest: " - "entries in chanlist must contain no " - "duplicate channels\n", dev->minor); + dev_dbg(dev->class_dev, + "%s: entries in chanlist must contain no duplicate channels\n", + __func__); } if (errors & range_err) { - DPRINTK("comedi%d: " DRIVER_NAME - ": ao_cmdtest: " - "entries in chanlist must all have " - "the same range index\n", dev->minor); + dev_dbg(dev->class_dev, + "%s: entries in chanlist must all have the same range index\n", + __func__); } err++; } -- cgit v1.2.3 From 2ec3839416e34ebf8103458f2fa64db53b5f13bd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:47:01 -0700 Subject: staging: comedi: amplc_pci230: remove use of DPRINTK Use dev_dbg() instead of the DPRINTK macro to output the comedi debugging information. The dev_dbg() will prefix the messages appropriately so remove the "comedi%d: amplc_pci230: " portion and use __func__ to show the actual function name for debugging. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 52 +++++++++++++-------------- 1 file changed, 24 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index a97bbd6ca3db..e11d7cec11e6 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -818,9 +818,9 @@ static int pci230_ai_rinsn(struct comedi_device *dev, if (aref == AREF_DIFF) { /* Differential. */ if (chan >= s->n_chan / 2) { - DPRINTK("comedi%d: amplc_pci230: ai_rinsn: " - "differential channel number out of range " - "0 to %u\n", dev->minor, (s->n_chan / 2) - 1); + dev_dbg(dev->class_dev, + "%s: differential channel number out of range 0 to %u\n", + __func__, (s->n_chan / 2) - 1); return -EINVAL; } } @@ -1092,14 +1092,14 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, if (errors != 0) { err++; if ((errors & seq_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: " - "channel numbers must increase\n", - dev->minor); + dev_dbg(dev->class_dev, + "%s: channel numbers must increase\n", + __func__); } if ((errors & range_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: " - "channels must have the same range\n", - dev->minor); + dev_dbg(dev->class_dev, + "%s: channels must have the same range\n", + __func__); } } } @@ -1835,33 +1835,29 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, if (errors != 0) { err++; if ((errors & seq_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " - "channel numbers must increase or " - "sequence must repeat exactly\n", - dev->minor); + dev_dbg(dev->class_dev, + "%s: channel numbers must increase or sequence must repeat exactly\n", + __func__); } if ((errors & rangepair_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " - "single-ended channel pairs must " - "have the same range\n", dev->minor); + dev_dbg(dev->class_dev, + "%s: single-ended channel pairs must have the same range\n", + __func__); } if ((errors & polarity_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " - "channel sequence ranges must be all " - "bipolar or all unipolar\n", - dev->minor); + dev_dbg(dev->class_dev, + "%s: channel sequence ranges must be all bipolar or all unipolar\n", + __func__); } if ((errors & aref_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " - "channel sequence analogue references " - "must be all the same (single-ended " - "or differential)\n", dev->minor); + dev_dbg(dev->class_dev, + "%s: channel sequence analogue references must be all the same (single-ended or differential)\n", + __func__); } if ((errors & diffchan_err) != 0) { - DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " - "differential channel number out of " - "range 0 to %u\n", dev->minor, - (s->n_chan / 2) - 1); + dev_dbg(dev->class_dev, + "%s: differential channel number out of range 0 to %u\n", + __func__, (s->n_chan / 2) - 1); } if ((errors & buggy_chan0_err) != 0) { dev_info(dev->class_dev, -- cgit v1.2.3 From 1e64126d97ab44814778c87d76f223140e28dbfb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 22 Nov 2013 10:47:20 -0700 Subject: staging: comedi: dt2801: remove use of DPRINTK The DPRINTK messages in this driver are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2801.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 811c8c59c017..1dd8190970e3 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -359,17 +359,12 @@ static int dt2801_reset(struct comedi_device *dev) unsigned int stat; int timeout; - DPRINTK("dt2801: resetting board...\n"); - DPRINTK("fingerprint: 0x%02x 0x%02x\n", inb_p(dev->iobase), - inb_p(dev->iobase + 1)); - /* pull random data from data port */ inb_p(dev->iobase + DT2801_DATA); inb_p(dev->iobase + DT2801_DATA); inb_p(dev->iobase + DT2801_DATA); inb_p(dev->iobase + DT2801_DATA); - DPRINTK("dt2801: stop\n"); /* dt2801_writecmd(dev,DT_C_STOP); */ outb_p(DT_C_STOP, dev->iobase + DT2801_CMD); @@ -387,7 +382,6 @@ static int dt2801_reset(struct comedi_device *dev) /* printk("dt2801: reading dummy\n"); */ /* dt2801_readdata(dev,&board_code); */ - DPRINTK("dt2801: reset\n"); outb_p(DT_C_RESET, dev->iobase + DT2801_CMD); /* dt2801_writecmd(dev,DT_C_RESET); */ @@ -401,11 +395,8 @@ static int dt2801_reset(struct comedi_device *dev) if (!timeout) printk("dt2801: timeout 2 status=0x%02x\n", stat); - DPRINTK("dt2801: reading code\n"); dt2801_readdata(dev, &board_code); - DPRINTK("dt2801: ok. code=0x%02x\n", board_code); - return board_code; } -- cgit v1.2.3 From 3751c4edc6275e345d5978b1cb92265945399f69 Mon Sep 17 00:00:00 2001 From: Karl Beldan Date: Mon, 11 Nov 2013 13:29:33 +0100 Subject: mac80211_hwsim: claim CCK support for HT clients Signed-off-by: Karl Beldan Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index bd7dd0d242d6..8c7f4ab70d29 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2352,7 +2352,8 @@ static int __init init_mac80211_hwsim(void) IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_WANT_MONITOR_VIF | - IEEE80211_HW_QUEUE_CONTROL; + IEEE80211_HW_QUEUE_CONTROL | + IEEE80211_HW_SUPPORTS_HT_CCK_RATES; if (rctbl) hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; -- cgit v1.2.3 From a2f73b6c5db3c272d87eaebb5bed355d75a0f25f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 11 Nov 2013 22:15:29 +0100 Subject: cfg80211: move regulatory flags to their own variable We'll expand this later, this will make it easier to classify and review what things are related to regulatory or not. Coccinelle only missed 4 hits, which I had to do manually, supplying the SmPL in case of merge conflicts. @@ struct wiphy *wiphy; @@ -wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY +wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG @@ expression e; @@ -e->flags |= WIPHY_FLAG_CUSTOM_REGULATORY +e->regulatory_flags |= REGULATORY_CUSTOM_REG @@ struct wiphy *wiphy; @@ -wiphy->flags &= ~WIPHY_FLAG_CUSTOM_REGULATORY +wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG @@ struct wiphy *wiphy; @@ -wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY +wiphy->regulatory_flags & REGULATORY_CUSTOM_REG @@ struct wiphy *wiphy; @@ -wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY +wiphy->regulatory_flags |= REGULATORY_STRICT_REG @@ expression e; @@ -e->flags |= WIPHY_FLAG_STRICT_REGULATORY +e->regulatory_flags |= REGULATORY_STRICT_REG @@ struct wiphy *wiphy; @@ -wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY +wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG @@ struct wiphy *wiphy; @@ -wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY +wiphy->regulatory_flags & REGULATORY_STRICT_REG @@ struct wiphy *wiphy; @@ -wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS +wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS @@ expression e; @@ -e->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS +e->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS @@ struct wiphy *wiphy; @@ -wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS +wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS @@ struct wiphy *wiphy; @@ -wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS +wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS Generated-by: Coccinelle SmPL Cc: Julia Lawall Cc: Peter Senna Tschudin Cc: Mihir Shete Cc: Henri Bahini Cc: Tushnim Bhattacharyya Signed-off-by: Luis R. Rodriguez [fix up whitespace damage, overly long lines] Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/regd.c | 4 +- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 2 +- drivers/net/wireless/brcm80211/brcmsmac/channel.c | 4 +- drivers/net/wireless/iwlegacy/3945-mac.c | 6 +-- drivers/net/wireless/iwlegacy/4965-mac.c | 6 +-- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 6 +-- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 6 +-- drivers/net/wireless/mac80211_hwsim.c | 25 +++++---- drivers/net/wireless/mwifiex/cfg80211.c | 5 +- drivers/net/wireless/rtlwifi/regd.c | 6 +-- include/net/cfg80211.h | 33 +++--------- include/net/regulatory.h | 59 +++++++++++++++++----- net/wireless/core.c | 2 +- net/wireless/reg.c | 32 ++++++------ 14 files changed, 108 insertions(+), 88 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index e93e517a699f..aba782cd09a2 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -601,7 +601,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, const struct ieee80211_regdomain *regd; wiphy->reg_notifier = reg_notifier; - wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; + wiphy->regulatory_flags |= REGULATORY_STRICT_REG; if (ath_is_world_regd(reg)) { /* @@ -609,7 +609,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, * saved on the wiphy orig_* parameters */ regd = ath_world_regdomain(reg); - wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; } else { /* * This gets applied in the case of the absence of CRDA, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index b6a09f97f9a3..1850efa83cf8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4341,7 +4341,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) wiphy->max_remain_on_channel_duration = 5000; brcmf_wiphy_pno_params(wiphy); brcmf_dbg(INFO, "Registering custom regulatory\n"); - wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); err = wiphy_register(wiphy); if (err < 0) { diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 7d8f3fd69a87..ef05df04136b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -766,8 +766,8 @@ void brcms_c_regd_init(struct brcms_c_info *wlc) } wlc->wiphy->reg_notifier = brcms_reg_notifier; - wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_STRICT_REGULATORY; + wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_STRICT_REG; wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain); brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER); } diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 5a66595b0faf..5c3bcedd679b 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3575,9 +3575,9 @@ il3945_setup_mac(struct il_priv *il) hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - hw->wiphy->flags |= - WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | - WIPHY_FLAG_IBSS_RSN; + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_DISABLE_BEACON_HINTS; hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1c5f8cdbd3a5..43f488a8cda2 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5778,9 +5778,9 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - hw->wiphy->flags |= - WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | - WIPHY_FLAG_IBSS_RSN; + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_DISABLE_BEACON_HINTS; /* * For now, disable PS by default because it affects diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cae4d3182e33..217f1ca321a0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -155,9 +155,9 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ARRAY_SIZE(iwlagn_iface_combinations_dualmode); } - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_DISABLE_BEACON_HINTS | - WIPHY_FLAG_IBSS_RSN; + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_DISABLE_BEACON_HINTS; #ifdef CONFIG_PM_SLEEP if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 74bc2c8af06d..b56c989ad784 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -199,9 +199,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_DISABLE_BEACON_HINTS | - WIPHY_FLAG_IBSS_RSN; + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_DISABLE_BEACON_HINTS; hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; hw->wiphy->n_iface_combinations = diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 8c7f4ab70d29..bcc7d8208f23 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2456,46 +2456,53 @@ static int __init init_mac80211_hwsim(void) break; case HWSIM_REGTEST_WORLD_ROAM: if (i == 0) { - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(hw->wiphy, &hwsim_world_regdom_custom_01); } break; case HWSIM_REGTEST_CUSTOM_WORLD: - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(hw->wiphy, &hwsim_world_regdom_custom_01); break; case HWSIM_REGTEST_CUSTOM_WORLD_2: if (i == 0) { - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(hw->wiphy, &hwsim_world_regdom_custom_01); } else if (i == 1) { - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(hw->wiphy, &hwsim_world_regdom_custom_02); } break; case HWSIM_REGTEST_STRICT_ALL: - hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; + hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; break; case HWSIM_REGTEST_STRICT_FOLLOW: case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: if (i == 0) - hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_STRICT_REG; break; case HWSIM_REGTEST_ALL: if (i == 0) { - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(hw->wiphy, &hwsim_world_regdom_custom_01); } else if (i == 1) { - hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG; wiphy_apply_custom_regulatory(hw->wiphy, &hwsim_world_regdom_custom_02); } else if (i == 4) - hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; + hw->wiphy->regulatory_flags |= + REGULATORY_STRICT_REG; break; default: break; diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 7f68943f02c2..d6d1d91a26dc 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -2687,9 +2687,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | - WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_STRICT_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + wiphy->regulatory_flags |= + REGULATORY_CUSTOM_REG | + REGULATORY_STRICT_REG; wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index 8453c53143f5..89e36568e70f 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -344,9 +344,9 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, wiphy->reg_notifier = reg_notifier; - wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; - wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; - wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; + wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; + wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; regd = _rtl_regdomain_select(reg); wiphy_apply_custom_regulatory(wiphy, regd); diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 968f2ad40ccd..bacc5033f0b6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2437,29 +2437,6 @@ struct cfg80211_ops { /** * enum wiphy_flags - wiphy capability flags * - * @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device - * has its own custom regulatory domain and cannot identify the - * ISO / IEC 3166 alpha2 it belongs to. When this is enabled - * we will disregard the first regulatory hint (when the - * initiator is %REGDOM_SET_BY_CORE). Drivers that use - * wiphy_apply_custom_regulatory() should have this flag set - * or the regulatory core will set it for wiphy. - * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will - * ignore regulatory domain settings until it gets its own regulatory - * domain via its regulatory_hint() unless the regulatory hint is - * from a country IE. After its gets its own regulatory domain it will - * only allow further regulatory domain settings to further enhance - * compliance. For example if channel 13 and 14 are disabled by this - * regulatory domain no user regulatory domain can enable these channels - * at a later time. This can be used for devices which do not have - * calibration information guaranteed for frequencies or settings - * outside of its regulatory domain. If used in combination with - * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings - * will be followed. - * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure - * that passive scan flags and beaconing flags may not be lifted by - * cfg80211 due to regulatory beacon hints. For more information on beacon - * hints read the documenation for regulatory_hint_found_beacon() * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this * wiphy at all * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled @@ -2498,9 +2475,9 @@ struct cfg80211_ops { * beaconing mode (AP, IBSS, Mesh, ...). */ enum wiphy_flags { - WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), - WIPHY_FLAG_STRICT_REGULATORY = BIT(1), - WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2), + /* use hole at 0 */ + /* use hole at 1 */ + /* use hole at 2 */ WIPHY_FLAG_NETNS_OK = BIT(3), WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), WIPHY_FLAG_4ADDR_AP = BIT(5), @@ -2722,6 +2699,8 @@ struct wiphy_coalesce_support { * @software_iftypes: bitmask of software interface types, these are not * subject to any restrictions since they are purely managed in SW. * @flags: wiphy flags, see &enum wiphy_flags + * @regulatory_flags: wiphy regulatory flags, see + * &enum ieee80211_regulatory_flags * @features: features advertised to nl80211, see &enum nl80211_feature_flags. * @bss_priv_size: each BSS struct has private data allocated with it, * this variable determines its size @@ -2810,7 +2789,7 @@ struct wiphy { u16 max_acl_mac_addrs; - u32 flags, features; + u32 flags, regulatory_flags, features; u32 ap_sme_capa; diff --git a/include/net/regulatory.h b/include/net/regulatory.h index f17ed590d64a..a6a20e2a54c4 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -38,17 +38,17 @@ enum environment_cap { * * @rcu_head: RCU head struct used to free the request * @wiphy_idx: this is set if this request's initiator is - * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This - * can be used by the wireless core to deal with conflicts - * and potentially inform users of which devices specifically - * cased the conflicts. + * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This + * can be used by the wireless core to deal with conflicts + * and potentially inform users of which devices specifically + * cased the conflicts. * @initiator: indicates who sent this request, could be any of - * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) + * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested - * regulatory domain. We have a few special codes: - * 00 - World regulatory domain - * 99 - built by driver but a specific alpha2 cannot be determined - * 98 - result of an intersection between two regulatory domains + * regulatory domain. We have a few special codes: + * 00 - World regulatory domain + * 99 - built by driver but a specific alpha2 cannot be determined + * 98 - result of an intersection between two regulatory domains * 97 - regulatory domain has not yet been configured * @dfs_region: If CRDA responded with a regulatory domain that requires * DFS master operation on a known DFS region (NL80211_DFS_*), @@ -59,8 +59,8 @@ enum environment_cap { * of hint passed. This could be any of the %NL80211_USER_REG_HINT_* * types. * @intersect: indicates whether the wireless core should intersect - * the requested regulatory domain with the presently set regulatory - * domain. + * the requested regulatory domain with the presently set regulatory + * domain. * @processed: indicates whether or not this requests has already been * processed. When the last request is processed it means that the * currently regulatory domain set on cfg80211 is updated from @@ -68,9 +68,9 @@ enum environment_cap { * the last request is not yet processed we must yield until it * is processed before processing any new requests. * @country_ie_checksum: checksum of the last processed and accepted - * country IE + * country IE * @country_ie_env: lets us know if the AP is telling us we are outdoor, - * indoor, or if it doesn't matter + * indoor, or if it doesn't matter * @list: used to insert into the reg_requests_list linked list */ struct regulatory_request { @@ -86,6 +86,39 @@ struct regulatory_request { struct list_head list; }; +/** + * enum ieee80211_regulatory_flags - device regulatory flags + * + * @REGULATORY_CUSTOM_REG: tells us the driver for this device + * has its own custom regulatory domain and cannot identify the + * ISO / IEC 3166 alpha2 it belongs to. When this is enabled + * we will disregard the first regulatory hint (when the + * initiator is %REGDOM_SET_BY_CORE). Drivers that use + * wiphy_apply_custom_regulatory() should have this flag set + * or the regulatory core will set it for the wiphy. + * @REGULATORY_STRICT_REG: tells us the driver for this device will + * ignore regulatory domain settings until it gets its own regulatory + * domain via its regulatory_hint() unless the regulatory hint is + * from a country IE. After its gets its own regulatory domain it will + * only allow further regulatory domain settings to further enhance + * compliance. For example if channel 13 and 14 are disabled by this + * regulatory domain no user regulatory domain can enable these channels + * at a later time. This can be used for devices which do not have + * calibration information guaranteed for frequencies or settings + * outside of its regulatory domain. If used in combination with + * REGULATORY_FLAG_CUSTOM_REG the inspected country IE power settings + * will be followed. + * @REGULATORY_DISABLE_BEACON_HINTS: enable this if your driver needs to + * ensure that passive scan flags and beaconing flags may not be lifted by + * cfg80211 due to regulatory beacon hints. For more information on beacon + * hints read the documenation for regulatory_hint_found_beacon() + */ +enum ieee80211_regulatory_flags { + REGULATORY_CUSTOM_REG = BIT(0), + REGULATORY_STRICT_REG = BIT(1), + REGULATORY_DISABLE_BEACON_HINTS = BIT(2), +}; + struct ieee80211_freq_range { u32 start_freq_khz; u32 end_freq_khz; diff --git a/net/wireless/core.c b/net/wireless/core.c index 9dca0925a1a9..fc968c861ee4 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -586,7 +586,7 @@ int wiphy_register(struct wiphy *wiphy) if (IS_ERR(rdev->wiphy.debugfsdir)) rdev->wiphy.debugfsdir = NULL; - if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { + if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { struct regulatory_request request; request.wiphy_idx = get_wiphy_idx(wiphy); diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a75c5eddd25f..e44b4bb20b92 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -868,7 +868,7 @@ static void handle_channel(struct wiphy *wiphy, if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && - request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { + request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) { REG_DBG_PRINT("Disabling freq %d MHz for good\n", chan->center_freq); chan->orig_flags |= IEEE80211_CHAN_DISABLED; @@ -895,7 +895,7 @@ static void handle_channel(struct wiphy *wiphy, if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && - request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { + request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) { /* * This guarantees the driver's requested regulatory domain * will always be used as a base for further regulatory @@ -922,12 +922,12 @@ static void handle_channel(struct wiphy *wiphy, if (chan->orig_mpwr) { /* * Devices that have their own custom regulatory domain - * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the + * but also use REGULATORY_STRICT_REG will follow the * passed country IE power settings. */ if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && - wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && - wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) + wiphy->regulatory_flags & REGULATORY_CUSTOM_REG && + wiphy->regulatory_flags & REGULATORY_STRICT_REG) chan->max_power = chan->max_reg_power; else chan->max_power = min(chan->orig_mpwr, @@ -997,8 +997,8 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy) { - if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && - !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) + if (wiphy->regulatory_flags & REGULATORY_STRICT_REG && + !(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) return true; return false; } @@ -1016,7 +1016,7 @@ static bool ignore_reg_update(struct wiphy *wiphy, } if (initiator == NL80211_REGDOM_SET_BY_CORE && - wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { + wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { REG_DBG_PRINT("Ignoring regulatory request set by %s " "since the driver uses its own custom " "regulatory domain\n", @@ -1054,7 +1054,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) return true; if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && - wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) + wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) return true; return false; @@ -1082,7 +1082,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, if (!reg_is_world_roaming(wiphy)) return; - if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS) + if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS) return; chan_before.center_freq = chan->center_freq; @@ -1242,7 +1242,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy, * as some drivers used this to restore its orig_* reg domain. */ if (initiator == NL80211_REGDOM_SET_BY_CORE && - wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) + wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) reg_call_notifier(wiphy, lr); return; } @@ -1328,9 +1328,9 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, enum ieee80211_band band; unsigned int bands_set = 0; - WARN(!(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY), - "wiphy should have WIPHY_FLAG_CUSTOM_REGULATORY\n"); - wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG), + "wiphy should have REGULATORY_CUSTOM_REG\n"); + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (!wiphy->bands[band]) @@ -1659,7 +1659,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) /* This is required so that the orig_* parameters are saved */ if (treatment == REG_REQ_ALREADY_SET && wiphy && - wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) + wiphy->regulatory_flags & REGULATORY_STRICT_REG) wiphy_update_regulatory(wiphy, reg_request->initiator); } @@ -1986,7 +1986,7 @@ static void restore_regulatory_settings(bool reset_user) world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; list_for_each_entry(rdev, &cfg80211_rdev_list, list) { - if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) + if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG) restore_custom_reg_settings(&rdev->wiphy); } -- cgit v1.2.3 From a09a85a013523a8b572dc5732b5c30e0785195f3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 11 Nov 2013 22:15:30 +0100 Subject: cfg80211: add flags to define country IE processing rules 802.11 cards may have different country IE parsing behavioural preferences and vendors may want to support these. These preferences were managed by the REGULATORY_CUSTOM_REG and the REGULATORY_STRICT_REG flags and their combination. Instead of using this existing notation, split out the country IE behavioural preferences as a new flag. This will allow us to add more customizations easily and make the code more maintainable. Cc: Mihir Shete Cc: Henri Bahini Cc: Tushnim Bhattacharyya Signed-off-by: Luis R. Rodriguez [fix up conflicts] Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/regd.c | 3 ++- include/net/regulatory.h | 36 ++++++++++++++++++++++++------------ net/wireless/reg.c | 8 +++----- 3 files changed, 29 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index aba782cd09a2..bef5539192c6 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -609,7 +609,8 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, * saved on the wiphy orig_* parameters */ regd = ath_world_regdomain(reg); - wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_COUNTRY_IE_FOLLOW_POWER; } else { /* * This gets applied in the case of the absence of CRDA, diff --git a/include/net/regulatory.h b/include/net/regulatory.h index a6a20e2a54c4..b03ddee3341d 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -96,27 +96,39 @@ struct regulatory_request { * initiator is %REGDOM_SET_BY_CORE). Drivers that use * wiphy_apply_custom_regulatory() should have this flag set * or the regulatory core will set it for the wiphy. - * @REGULATORY_STRICT_REG: tells us the driver for this device will - * ignore regulatory domain settings until it gets its own regulatory - * domain via its regulatory_hint() unless the regulatory hint is - * from a country IE. After its gets its own regulatory domain it will - * only allow further regulatory domain settings to further enhance - * compliance. For example if channel 13 and 14 are disabled by this - * regulatory domain no user regulatory domain can enable these channels - * at a later time. This can be used for devices which do not have - * calibration information guaranteed for frequencies or settings - * outside of its regulatory domain. If used in combination with - * REGULATORY_FLAG_CUSTOM_REG the inspected country IE power settings - * will be followed. + * @REGULATORY_STRICT_REG: tells us that the wiphy for this device + * has regulatory domain that it wishes to be considered as the + * superset for regulatory rules. After this device gets its regulatory + * domain programmed further regulatory hints shall only be considered + * for this device to enhance regulatory compliance, forcing the + * device to only possibly use subsets of the original regulatory + * rules. For example if channel 13 and 14 are disabled by this + * device's regulatory domain no user specified regulatory hint which + * has these channels enabled would enable them for this wiphy, + * the device's original regulatory domain will be trusted as the + * base. You can program the superset of regulatory rules for this + * wiphy with regulatory_hint() for cards programmed with an + * ISO3166-alpha2 country code. wiphys that use regulatory_hint() + * will have their wiphy->regd programmed once the regulatory + * domain is set, and all other regulatory hints will be ignored + * until their own regulatory domain gets programmed. * @REGULATORY_DISABLE_BEACON_HINTS: enable this if your driver needs to * ensure that passive scan flags and beaconing flags may not be lifted by * cfg80211 due to regulatory beacon hints. For more information on beacon * hints read the documenation for regulatory_hint_found_beacon() + * @REGULATORY_COUNTRY_IE_FOLLOW_POWER: for devices that have a preference + * that even though they may have programmed their own custom power + * setting prior to wiphy registration, they want to ensure their channel + * power settings are updated for this connection with the power settings + * derived from the regulatory domain. The regulatory domain used will be + * based on the ISO3166-alpha2 from country IE provided through + * regulatory_hint_country_ie() */ enum ieee80211_regulatory_flags { REGULATORY_CUSTOM_REG = BIT(0), REGULATORY_STRICT_REG = BIT(1), REGULATORY_DISABLE_BEACON_HINTS = BIT(2), + REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(3), }; struct ieee80211_freq_range { diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e44b4bb20b92..6b3051f6a8a7 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -921,13 +921,11 @@ static void handle_channel(struct wiphy *wiphy, chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); if (chan->orig_mpwr) { /* - * Devices that have their own custom regulatory domain - * but also use REGULATORY_STRICT_REG will follow the - * passed country IE power settings. + * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER + * will always follow the passed country IE power settings. */ if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && - wiphy->regulatory_flags & REGULATORY_CUSTOM_REG && - wiphy->regulatory_flags & REGULATORY_STRICT_REG) + wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER) chan->max_power = chan->max_reg_power; else chan->max_power = min(chan->orig_mpwr, -- cgit v1.2.3 From a7627714452df0cb7171652573c73e3613b24e6a Mon Sep 17 00:00:00 2001 From: Alexandre Demers Date: Tue, 12 Nov 2013 23:56:22 -0500 Subject: staging r8712u: Remove useless netdev_info slowly polluting dmesg Remove useless netdev_info slowly flooding dmesg. Fixes bug https://bugzilla.kernel.org/show_bug.cgi?id=64231 Signed-off-by: Alexandre Demers Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_mlme.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 8fa0f9d49a8a..3ea99aea4385 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1043,9 +1043,6 @@ void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf) struct sta_priv *pstapriv = &adapter->stapriv; struct recv_reorder_ctrl *precvreorder_ctrl = NULL; - netdev_info(adapter->pnetdev, "%s: mac = %pM, seq = %d, tid = %d\n", - __func__, pAddbareq_pram->MacAddress, - pAddbareq_pram->StartSeqNum, pAddbareq_pram->tid); psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress); if (psta) { precvreorder_ctrl = -- cgit v1.2.3 From b34085fdc2bb44b3d3cb16521ebd495f86fe717b Mon Sep 17 00:00:00 2001 From: Julien DELACOU Date: Fri, 15 Nov 2013 11:39:38 +0100 Subject: staging: dwc2: do not clear pending interrupts twice Pending interrupts clearing is done in dwc2_enable_common_interrupts so we don't need to do it twice. Signed-off-by: Julien Delacou Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 6d001b52f652..e4249404958a 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -451,9 +451,6 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg) writel(0, hsotg->regs + GINTMSK); writel(0, hsotg->regs + HAINTMSK); - /* Clear any pending interrupts */ - writel(0xffffffff, hsotg->regs + GINTSTS); - /* Enable the common interrupts */ dwc2_enable_common_interrupts(hsotg); -- cgit v1.2.3 From beb7e592bcfd750951c47580494f13065f0fd44c Mon Sep 17 00:00:00 2001 From: Julien DELACOU Date: Wed, 20 Nov 2013 17:29:49 +0100 Subject: staging: dwc2: add check on dwc2_core_reset return If the GRSTCTL_CSFTRST self-clearing bit never comes back to 0 for any reason, the controller is under reset state and cannot be used. It's preferable to abort initialization in such case. Signed-off-by: Julien Delacou Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 58 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index e4249404958a..53d540864cf0 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -114,7 +114,7 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) * Do core a soft reset of the core. Be careful with this because it * resets all the internal state machines of the core. */ -static void dwc2_core_reset(struct dwc2_hsotg *hsotg) +static int dwc2_core_reset(struct dwc2_hsotg *hsotg) { u32 greset; int count = 0; @@ -129,7 +129,7 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg) dev_warn(hsotg->dev, "%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, greset); - return; + return -EBUSY; } } while (!(greset & GRSTCTL_AHBIDLE)); @@ -144,7 +144,7 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg) dev_warn(hsotg->dev, "%s() HANG! Soft Reset GRSTCTL=%0x\n", __func__, greset); - break; + return -EBUSY; } } while (greset & GRSTCTL_CSFTRST); @@ -153,11 +153,14 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg) * not stay in host mode after a connector ID change! */ usleep_range(150000, 200000); + + return 0; } -static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) +static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg, i2cctl; + int retval = 0; /* * core_init() is now called on every switch so only call the @@ -170,7 +173,12 @@ static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) writel(usbcfg, hsotg->regs + GUSBCFG); /* Reset after a PHY select */ - dwc2_core_reset(hsotg); + retval = dwc2_core_reset(hsotg); + if (retval) { + dev_err(hsotg->dev, "%s() Reset failed, aborting", + __func__); + return retval; + } } /* @@ -198,14 +206,17 @@ static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) i2cctl |= GI2CCTL_I2CEN; writel(i2cctl, hsotg->regs + GI2CCTL); } + + return retval; } -static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) +static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg; + int retval = 0; if (!select_phy) - return; + return -ENODEV; usbcfg = readl(hsotg->regs + GUSBCFG); @@ -238,20 +249,32 @@ static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) writel(usbcfg, hsotg->regs + GUSBCFG); /* Reset after setting the PHY parameters */ - dwc2_core_reset(hsotg); + retval = dwc2_core_reset(hsotg); + if (retval) { + dev_err(hsotg->dev, "%s() Reset failed, aborting", + __func__); + return retval; + } + + return retval; } -static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) +static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg; + int retval = 0; if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL && hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { /* If FS mode with FS PHY */ - dwc2_fs_phy_init(hsotg, select_phy); + retval = dwc2_fs_phy_init(hsotg, select_phy); + if (retval) + return retval; } else { /* High speed PHY */ - dwc2_hs_phy_init(hsotg, select_phy); + retval = dwc2_hs_phy_init(hsotg, select_phy); + if (retval) + return retval; } if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && @@ -268,6 +291,8 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M; writel(usbcfg, hsotg->regs + GUSBCFG); } + + return retval; } static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) @@ -382,12 +407,19 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) writel(usbcfg, hsotg->regs + GUSBCFG); /* Reset the Controller */ - dwc2_core_reset(hsotg); + retval = dwc2_core_reset(hsotg); + if (retval) { + dev_err(hsotg->dev, "%s(): Reset failed, aborting\n", + __func__); + return retval; + } /* * This needs to happen in FS mode before any other programming occurs */ - dwc2_phy_init(hsotg, select_phy); + retval = dwc2_phy_init(hsotg, select_phy); + if (retval) + return retval; /* Program the GAHBCFG Register */ retval = dwc2_gahbcfg_init(hsotg); -- cgit v1.2.3 From 9bda1aac6b98d79f06df4ae40711bf08d23e766d Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:45 -0800 Subject: staging: dwc2: fix some functions to return a proper error code Fix some functions called by dwc2_hcd_qtd_add() to return either a proper error code or 0, instead of somewhat random values. Then change the caller of dwc2_hcd_qtd_add() to just check the return value for 0. Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 6 +++--- drivers/staging/dwc2/hcd_queue.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 3cfd2d5152c9..24a4efe874d6 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -369,7 +369,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, dwc2_hcd_qtd_init(qtd, urb); retval = dwc2_hcd_qtd_add(hsotg, qtd, (struct dwc2_qh **)ep_handle, mem_flags); - if (retval < 0) { + if (retval) { dev_err(hsotg->dev, "DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n", retval); @@ -378,7 +378,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, } intr_mask = readl(hsotg->regs + GINTMSK); - if (!(intr_mask & GINTSTS_SOF) && retval == 0) { + if (!(intr_mask & GINTSTS_SOF)) { enum dwc2_transaction_type tr_type; if (qtd->qh->ep_type == USB_ENDPOINT_XFER_BULK && @@ -396,7 +396,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, spin_unlock_irqrestore(&hsotg->lock, flags); } - return retval; + return 0; } /* Must be called with interrupt disabled and spinlock held */ diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c index 2f68fbc08827..729cc0b83df3 100644 --- a/drivers/staging/dwc2/hcd_queue.c +++ b/drivers/staging/dwc2/hcd_queue.c @@ -354,7 +354,7 @@ static int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) return i; } } - return -1; + return -ENOSPC; } /* @@ -413,7 +413,7 @@ static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) continue; } } - return -1; + return -ENOSPC; } static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) @@ -487,12 +487,12 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) frame = status - 1; /* Set the new frame up */ - if (frame > -1) { + if (frame >= 0) { qh->sched_frame &= ~0x7; qh->sched_frame |= (frame & 7); } - if (status != -1) + if (status > 0) status = 0; } else { status = dwc2_periodic_channel_available(hsotg); -- cgit v1.2.3 From fbd1cd202739558210fd8f441b36601b29050bf4 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:46 -0800 Subject: staging: dwc2: fix potential use after free dwc2_process_non_isoc_desc() can potentially free the qtd, so null out the qtd pointer if the call fails so we don't try to access it later Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_ddma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c index c7d434519776..72e9788c1a13 100644 --- a/drivers/staging/dwc2/hcd_ddma.c +++ b/drivers/staging/dwc2/hcd_ddma.c @@ -1103,8 +1103,10 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, for (i = 0; i < qtd->n_desc; i++) { if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd, desc_num, halt_status, - &xfer_done)) + &xfer_done)) { + qtd = NULL; break; + } desc_num++; } } -- cgit v1.2.3 From 498f06696a2f0fb38e59741a6fa05358edefff65 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:47 -0800 Subject: staging: dwc2: rename DWC2_PARAM_TEST to DWC2_OUT_OF_BOUNDS DWC2_PARAM_TEST is not a very good name for this macro, so rename it to DWC2_OUT_OF_BOUNDS Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 53d540864cf0..460aee68a3b0 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -1941,7 +1941,7 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg) udelay(1); } -#define DWC2_PARAM_TEST(a, b, c) ((a) < (b) || (a) > (c)) +#define DWC2_OUT_OF_BOUNDS(a, b, c) ((a) < (b) || (a) > (c)) /* Parameter access functions */ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) @@ -2055,7 +2055,7 @@ int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for host_support_fs_low_power\n"); @@ -2238,8 +2238,8 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) #endif int retval = 0; - if (DWC2_PARAM_TEST(val, DWC2_PHY_TYPE_PARAM_FS, - DWC2_PHY_TYPE_PARAM_ULPI)) { + if (DWC2_OUT_OF_BOUNDS(val, DWC2_PHY_TYPE_PARAM_FS, + DWC2_PHY_TYPE_PARAM_ULPI)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for phy_type\n"); dev_err(hsotg->dev, "phy_type must be 0, 1 or 2\n"); @@ -2301,7 +2301,7 @@ int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for speed parameter\n"); dev_err(hsotg->dev, "max_speed parameter must be 0 or 1\n"); @@ -2333,8 +2333,8 @@ int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (DWC2_PARAM_TEST(val, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ, - DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) { + if (DWC2_OUT_OF_BOUNDS(val, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ, + DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for host_ls_low_power_phy_clk parameter\n"); @@ -2369,7 +2369,7 @@ int dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val) { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for phy_ulpi_ddr\n"); dev_err(hsotg->dev, "phy_upli_ddr must be 0 or 1\n"); @@ -2387,7 +2387,7 @@ int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val) { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for phy_ulpi_ext_vbus\n"); @@ -2440,7 +2440,7 @@ int dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val) { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for ulpi_fs_ls\n"); dev_err(hsotg->dev, "ulpi_fs_ls must be 0 or 1\n"); @@ -2458,7 +2458,7 @@ int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val) { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for ts_dline\n"); dev_err(hsotg->dev, "ts_dline must be 0 or 1\n"); @@ -2479,7 +2479,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) #endif int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for i2c_enable\n"); dev_err(hsotg->dev, "i2c_enable must be 0 or 1\n"); @@ -2518,7 +2518,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for en_multiple_tx_fifo,\n"); @@ -2550,7 +2550,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "'%d' invalid for parameter reload_ctl\n", val); @@ -2590,7 +2590,7 @@ int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "'%d' invalid for parameter otg_ver\n", val); @@ -2769,7 +2769,7 @@ int dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) { int retval = 0; - if (DWC2_PARAM_TEST(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "'%d' invalid for parameter uframe_sched\n", -- cgit v1.2.3 From 7218dae7aa74c822f32c54492fb9a9488f5e52ba Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:48 -0800 Subject: staging: dwc2: make all the dwc2_set_param* functions void We were not checking the return value from any of these functions, so make them void functions Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 193 ++++++++++++-------------------------------- drivers/staging/dwc2/core.h | 60 +++++++------- drivers/staging/dwc2/hcd.h | 4 +- 3 files changed, 85 insertions(+), 172 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 460aee68a3b0..94cd0b4632b2 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -1944,10 +1944,9 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg) #define DWC2_OUT_OF_BOUNDS(a, b, c) ((a) < (b) || (a) > (c)) /* Parameter access functions */ -int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; switch (val) { case DWC2_CAP_PARAM_HNP_SRP_CAPABLE: @@ -1993,17 +1992,14 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) break; } dev_dbg(hsotg->dev, "Setting otg_cap to %d\n", val); - retval = -EINVAL; } hsotg->core_params->otg_cap = val; - return retval; } -int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val > 0 && hsotg->hw_params.arch == GHWCFG2_SLAVE_ONLY_ARCH) valid = 0; @@ -2017,17 +2013,14 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.arch != GHWCFG2_SLAVE_ONLY_ARCH; dev_dbg(hsotg->dev, "Setting dma_enable to %d\n", val); - retval = -EINVAL; } hsotg->core_params->dma_enable = val; - return retval; } -int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val > 0 && (hsotg->core_params->dma_enable <= 0 || !hsotg->hw_params.dma_desc_enable)) @@ -2043,18 +2036,14 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) val = (hsotg->core_params->dma_enable > 0 && hsotg->hw_params.dma_desc_enable); dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val); - retval = -EINVAL; } hsotg->core_params->dma_desc_enable = val; - return retval; } -int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, - int val) +void dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, + int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, @@ -2065,17 +2054,14 @@ int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, val = 0; dev_dbg(hsotg->dev, "Setting host_support_fs_low_power to %d\n", val); - retval = -EINVAL; } hsotg->core_params->host_support_fs_ls_low_power = val; - return retval; } -int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val > 0 && !hsotg->hw_params.enable_dynamic_fifo) valid = 0; @@ -2089,17 +2075,14 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.enable_dynamic_fifo; dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val); - retval = -EINVAL; } hsotg->core_params->enable_dynamic_fifo = val; - return retval; } -int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val < 16 || val > hsotg->hw_params.host_rx_fifo_size) valid = 0; @@ -2111,17 +2094,14 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.host_rx_fifo_size; dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val); - retval = -EINVAL; } hsotg->core_params->host_rx_fifo_size = val; - return retval; } -int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val < 16 || val > hsotg->hw_params.host_nperio_tx_fifo_size) valid = 0; @@ -2134,17 +2114,14 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) val = hsotg->hw_params.host_nperio_tx_fifo_size; dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n", val); - retval = -EINVAL; } hsotg->core_params->host_nperio_tx_fifo_size = val; - return retval; } -int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val < 16 || val > hsotg->hw_params.host_perio_tx_fifo_size) valid = 0; @@ -2157,17 +2134,14 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) val = hsotg->hw_params.host_perio_tx_fifo_size; dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n", val); - retval = -EINVAL; } hsotg->core_params->host_perio_tx_fifo_size = val; - return retval; } -int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val < 2047 || val > hsotg->hw_params.max_transfer_size) valid = 0; @@ -2179,17 +2153,14 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.max_transfer_size; dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val); - retval = -EINVAL; } hsotg->core_params->max_transfer_size = val; - return retval; } -int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val < 15 || val > hsotg->hw_params.max_packet_count) valid = 0; @@ -2201,17 +2172,14 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.max_packet_count; dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val); - retval = -EINVAL; } hsotg->core_params->max_packet_count = val; - return retval; } -int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (val < 1 || val > hsotg->hw_params.host_channels) valid = 0; @@ -2223,20 +2191,17 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.host_channels; dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val); - retval = -EINVAL; } hsotg->core_params->host_channels = val; - return retval; } -int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) { #ifndef NO_FS_PHY_HW_CHECKS int valid = 0; u32 hs_phy_type, fs_phy_type; #endif - int retval = 0; if (DWC2_OUT_OF_BOUNDS(val, DWC2_PHY_TYPE_PARAM_FS, DWC2_PHY_TYPE_PARAM_ULPI)) { @@ -2250,7 +2215,6 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) #else val = DWC2_PHY_TYPE_PARAM_FS; dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val); - retval = -EINVAL; #endif } @@ -2283,12 +2247,10 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) val = DWC2_PHY_TYPE_PARAM_ULPI; } dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val); - retval = -EINVAL; } #endif hsotg->core_params->phy_type = val; - return retval; } static int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg) @@ -2296,10 +2258,9 @@ static int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg) return hsotg->core_params->phy_type; } -int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { @@ -2321,17 +2282,14 @@ int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val) val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS ? DWC2_SPEED_PARAM_FULL : DWC2_SPEED_PARAM_HIGH; dev_dbg(hsotg->dev, "Setting speed to %d\n", val); - retval = -EINVAL; } hsotg->core_params->speed = val; - return retval; } -int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (DWC2_OUT_OF_BOUNDS(val, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) { @@ -2358,17 +2316,13 @@ int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, int val) : DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ; dev_dbg(hsotg->dev, "Setting host_ls_low_power_phy_clk to %d\n", val); - retval = -EINVAL; } hsotg->core_params->host_ls_low_power_phy_clk = val; - return retval; } -int dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for phy_ulpi_ddr\n"); @@ -2376,17 +2330,13 @@ int dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val) } val = 0; dev_dbg(hsotg->dev, "Setting phy_upli_ddr to %d\n", val); - retval = -EINVAL; } hsotg->core_params->phy_ulpi_ddr = val; - return retval; } -int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, @@ -2396,17 +2346,14 @@ int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val) } val = 0; dev_dbg(hsotg->dev, "Setting phy_ulpi_ext_vbus to %d\n", val); - retval = -EINVAL; } hsotg->core_params->phy_ulpi_ext_vbus = val; - return retval; } -int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val) { int valid = 0; - int retval = 0; switch (hsotg->hw_params.utmi_phy_data_width) { case GHWCFG4_UTMI_PHY_DATA_WIDTH_8: @@ -2429,17 +2376,13 @@ int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val) val = (hsotg->hw_params.utmi_phy_data_width == GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; dev_dbg(hsotg->dev, "Setting phy_utmi_width to %d\n", val); - retval = -EINVAL; } hsotg->core_params->phy_utmi_width = val; - return retval; } -int dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for ulpi_fs_ls\n"); @@ -2447,17 +2390,13 @@ int dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val) } val = 0; dev_dbg(hsotg->dev, "Setting ulpi_fs_ls to %d\n", val); - retval = -EINVAL; } hsotg->core_params->ulpi_fs_ls = val; - return retval; } -int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for ts_dline\n"); @@ -2465,19 +2404,16 @@ int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val) } val = 0; dev_dbg(hsotg->dev, "Setting ts_dline to %d\n", val); - retval = -EINVAL; } hsotg->core_params->ts_dline = val; - return retval; } -int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) { #ifndef NO_FS_PHY_HW_CHECKS int valid = 1; #endif - int retval = 0; if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { @@ -2490,7 +2426,6 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) #else val = 0; dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); - retval = -EINVAL; #endif } @@ -2505,18 +2440,15 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.i2c_enable; dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); - retval = -EINVAL; } #endif hsotg->core_params->i2c_enable = val; - return retval; } -int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { @@ -2538,17 +2470,14 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.en_multiple_tx_fifo; dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val); - retval = -EINVAL; } hsotg->core_params->en_multiple_tx_fifo = val; - return retval; } -int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - int retval = 0; if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { @@ -2569,27 +2498,22 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) val); val = hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_92a; dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val); - retval = -EINVAL; } hsotg->core_params->reload_ctl = val; - return retval; } -int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val) { if (val != -1) hsotg->core_params->ahbcfg = val; else hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT; - return 0; } -int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, @@ -2599,11 +2523,9 @@ int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) } val = 0; dev_dbg(hsotg->dev, "Setting otg_ver to %d\n", val); - retval = -EINVAL; } hsotg->core_params->otg_ver = val; - return retval; } /** @@ -2765,10 +2687,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) return 0; } -int dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) +void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) { - int retval = 0; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { dev_err(hsotg->dev, @@ -2778,62 +2698,55 @@ int dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) } val = 1; dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val); - retval = -EINVAL; } hsotg->core_params->uframe_sched = val; - return retval; } /* * This function is called during module intialization to pass module parameters * for the DWC_otg core. It returns non-0 if any parameters are invalid. */ -int dwc2_set_parameters(struct dwc2_hsotg *hsotg, - const struct dwc2_core_params *params) +void dwc2_set_parameters(struct dwc2_hsotg *hsotg, + const struct dwc2_core_params *params) { - int retval = 0; - dev_dbg(hsotg->dev, "%s()\n", __func__); - retval |= dwc2_set_param_otg_cap(hsotg, params->otg_cap); - retval |= dwc2_set_param_dma_enable(hsotg, params->dma_enable); - retval |= dwc2_set_param_dma_desc_enable(hsotg, - params->dma_desc_enable); - retval |= dwc2_set_param_host_support_fs_ls_low_power(hsotg, + dwc2_set_param_otg_cap(hsotg, params->otg_cap); + dwc2_set_param_dma_enable(hsotg, params->dma_enable); + dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable); + dwc2_set_param_host_support_fs_ls_low_power(hsotg, params->host_support_fs_ls_low_power); - retval |= dwc2_set_param_enable_dynamic_fifo(hsotg, + dwc2_set_param_enable_dynamic_fifo(hsotg, params->enable_dynamic_fifo); - retval |= dwc2_set_param_host_rx_fifo_size(hsotg, + dwc2_set_param_host_rx_fifo_size(hsotg, params->host_rx_fifo_size); - retval |= dwc2_set_param_host_nperio_tx_fifo_size(hsotg, + dwc2_set_param_host_nperio_tx_fifo_size(hsotg, params->host_nperio_tx_fifo_size); - retval |= dwc2_set_param_host_perio_tx_fifo_size(hsotg, + dwc2_set_param_host_perio_tx_fifo_size(hsotg, params->host_perio_tx_fifo_size); - retval |= dwc2_set_param_max_transfer_size(hsotg, + dwc2_set_param_max_transfer_size(hsotg, params->max_transfer_size); - retval |= dwc2_set_param_max_packet_count(hsotg, + dwc2_set_param_max_packet_count(hsotg, params->max_packet_count); - retval |= dwc2_set_param_host_channels(hsotg, params->host_channels); - retval |= dwc2_set_param_phy_type(hsotg, params->phy_type); - retval |= dwc2_set_param_speed(hsotg, params->speed); - retval |= dwc2_set_param_host_ls_low_power_phy_clk(hsotg, + dwc2_set_param_host_channels(hsotg, params->host_channels); + dwc2_set_param_phy_type(hsotg, params->phy_type); + dwc2_set_param_speed(hsotg, params->speed); + dwc2_set_param_host_ls_low_power_phy_clk(hsotg, params->host_ls_low_power_phy_clk); - retval |= dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr); - retval |= dwc2_set_param_phy_ulpi_ext_vbus(hsotg, + dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr); + dwc2_set_param_phy_ulpi_ext_vbus(hsotg, params->phy_ulpi_ext_vbus); - retval |= dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width); - retval |= dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls); - retval |= dwc2_set_param_ts_dline(hsotg, params->ts_dline); - retval |= dwc2_set_param_i2c_enable(hsotg, params->i2c_enable); - retval |= dwc2_set_param_en_multiple_tx_fifo(hsotg, + dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width); + dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls); + dwc2_set_param_ts_dline(hsotg, params->ts_dline); + dwc2_set_param_i2c_enable(hsotg, params->i2c_enable); + dwc2_set_param_en_multiple_tx_fifo(hsotg, params->en_multiple_tx_fifo); - retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); - retval |= dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); - retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver); - retval |= dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); - - return retval; + dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); + dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); + dwc2_set_param_otg_ver(hsotg, params->otg_ver); + dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); } u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h index fab718d9b326..6a1c09f2f493 100644 --- a/drivers/staging/dwc2/core.h +++ b/drivers/staging/dwc2/core.h @@ -571,7 +571,7 @@ extern irqreturn_t dwc2_handle_common_intr(int irq, void *dev); * 1 - SRP Only capable * 2 - No HNP/SRP capable */ -extern int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val); #define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0 #define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1 #define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 @@ -583,7 +583,7 @@ extern int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val); * 0 - Slave * 1 - DMA (default, if available) */ -extern int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val); /* * When DMA mode is enabled specifies whether to use @@ -593,7 +593,7 @@ extern int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val); * 0 - address DMA * 1 - DMA Descriptor(default, if available) */ -extern int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val); /* * Specifies the maximum speed of operation in host and device mode. @@ -603,7 +603,7 @@ extern int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val); * 0 - High Speed (default) * 1 - Full Speed */ -extern int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val); #define DWC2_SPEED_PARAM_HIGH 0 #define DWC2_SPEED_PARAM_FULL 1 @@ -614,8 +614,8 @@ extern int dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val); * 0 - Don't support low power mode (default) * 1 - Support low power mode */ -extern int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, - int val); +extern void dwc2_set_param_host_support_fs_ls_low_power( + struct dwc2_hsotg *hsotg, int val); /* * Specifies the PHY clock rate in low power mode when connected to a @@ -626,8 +626,8 @@ extern int dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, * 0 - 48 MHz * 1 - 6 MHz */ -extern int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, - int val); +extern void dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, + int val); #define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 #define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 @@ -635,50 +635,50 @@ extern int dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, * 0 - Use cC FIFO size parameters * 1 - Allow dynamic FIFO sizing (default) */ -extern int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, - int val); +extern void dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, + int val); /* * Number of 4-byte words in the Rx FIFO in host mode when dynamic * FIFO sizing is enabled. * 16 to 32768 (default 1024) */ -extern int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val); /* * Number of 4-byte words in the non-periodic Tx FIFO in host mode * when Dynamic FIFO sizing is enabled in the core. * 16 to 32768 (default 256) */ -extern int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, - int val); +extern void dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, + int val); /* * Number of 4-byte words in the host periodic Tx FIFO when dynamic * FIFO sizing is enabled. * 16 to 32768 (default 256) */ -extern int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, - int val); +extern void dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, + int val); /* * The maximum transfer size supported in bytes. * 2047 to 65,535 (default 65,535) */ -extern int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val); /* * The maximum number of packets in a transfer. * 15 to 511 (default 511) */ -extern int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val); /* * The number of host channel registers to use. * 1 to 16 (default 11) * Note: The FPGA configuration supports a maximum of 11 host channels. */ -extern int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val); /* * Specifies the type of PHY interface to use. By default, the driver @@ -688,7 +688,7 @@ extern int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val); * 1 - UTMI+ (default) * 2 - ULPI */ -extern int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val); #define DWC2_PHY_TYPE_PARAM_FS 0 #define DWC2_PHY_TYPE_PARAM_UTMI 1 #define DWC2_PHY_TYPE_PARAM_ULPI 2 @@ -704,7 +704,7 @@ extern int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val); * * 8 or 16 bits (default 16) */ -extern int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val); /* * Specifies whether the ULPI operates at double or single @@ -716,13 +716,13 @@ extern int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val); * 1 - double data rate ULPI interface with 4 bit wide data * bus */ -extern int dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val); /* * Specifies whether to use the internal or external supply to * drive the vbus with a ULPI phy. */ -extern int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val); #define DWC2_PHY_ULPI_INTERNAL_VBUS 0 #define DWC2_PHY_ULPI_EXTERNAL_VBUS 1 @@ -732,11 +732,11 @@ extern int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val); * 0 - No (default) * 1 - Yes */ -extern int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val); -extern int dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val); -extern int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val); /* * Specifies whether dedicated transmit FIFOs are @@ -744,14 +744,14 @@ extern int dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val); * 0 - No * 1 - Yes */ -extern int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, - int val); +extern void dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, + int val); -extern int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val); -extern int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val); -extern int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val); +extern void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val); /* * Dump core registers and SPRAM diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h index 89a5484f5b74..fdc6d489084a 100644 --- a/drivers/staging/dwc2/hcd.h +++ b/drivers/staging/dwc2/hcd.h @@ -452,8 +452,8 @@ static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe) extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, const struct dwc2_core_params *params); extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); -extern int dwc2_set_parameters(struct dwc2_hsotg *hsotg, - const struct dwc2_core_params *params); +extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg, + const struct dwc2_core_params *params); extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); -- cgit v1.2.3 From c17d482decb40c73429678d554cd7fad6afc238b Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:49 -0800 Subject: staging: dwc2: remove use of NO_FS_PHY_HW_CHECKS macro NO_FS_PHY_HW_CHECKS is never defined, so remove the conditional code that checks for it being set Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 94cd0b4632b2..82dbcf34b78d 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -2198,10 +2198,8 @@ void dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) { -#ifndef NO_FS_PHY_HW_CHECKS int valid = 0; u32 hs_phy_type, fs_phy_type; -#endif if (DWC2_OUT_OF_BOUNDS(val, DWC2_PHY_TYPE_PARAM_FS, DWC2_PHY_TYPE_PARAM_ULPI)) { @@ -2210,15 +2208,9 @@ void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "phy_type must be 0, 1 or 2\n"); } -#ifndef NO_FS_PHY_HW_CHECKS valid = 0; -#else - val = DWC2_PHY_TYPE_PARAM_FS; - dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val); -#endif } -#ifndef NO_FS_PHY_HW_CHECKS hs_phy_type = hsotg->hw_params.hs_phy_type; fs_phy_type = hsotg->hw_params.fs_phy_type; if (val == DWC2_PHY_TYPE_PARAM_UTMI && @@ -2248,7 +2240,6 @@ void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) } dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val); } -#endif hsotg->core_params->phy_type = val; } @@ -2411,9 +2402,7 @@ void dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val) void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) { -#ifndef NO_FS_PHY_HW_CHECKS int valid = 1; -#endif if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { @@ -2421,15 +2410,9 @@ void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "i2c_enable must be 0 or 1\n"); } -#ifndef NO_FS_PHY_HW_CHECKS valid = 0; -#else - val = 0; - dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); -#endif } -#ifndef NO_FS_PHY_HW_CHECKS if (val == 1 && !(hsotg->hw_params.i2c_enable)) valid = 0; @@ -2441,7 +2424,6 @@ void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) val = hsotg->hw_params.i2c_enable; dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); } -#endif hsotg->core_params->i2c_enable = val; } -- cgit v1.2.3 From b66a3f057332075bc4cf6f8d1f91a5bb87b6e761 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:50 -0800 Subject: staging: dwc2: remove useless cast Remove useless cast in dwc2_get_otg_version() Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 82dbcf34b78d..07b397412825 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -2733,7 +2733,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) { - return (u16)(hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103); + return hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103; } int dwc2_check_core_status(struct dwc2_hsotg *hsotg) -- cgit v1.2.3 From 057715f280f6f242dab649e4923866fd236723d5 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:51 -0800 Subject: staging: dwc2: rename dwc2_check_core_status() Rename dwc2_check_core_status() to dwc2_is_controller_alive(), and make it a boolean function. Also change the message when the controller is dead to say "dead" instead of "disconnected". Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 6 +++--- drivers/staging/dwc2/core.h | 2 +- drivers/staging/dwc2/core_intr.c | 4 ++-- drivers/staging/dwc2/hcd_intr.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 07b397412825..c0b122a67996 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -2736,12 +2736,12 @@ u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) return hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103; } -int dwc2_check_core_status(struct dwc2_hsotg *hsotg) +bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg) { if (readl(hsotg->regs + GSNPSID) == 0xffffffff) - return -1; + return false; else - return 0; + return true; } /** diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h index 6a1c09f2f493..648519c024b5 100644 --- a/drivers/staging/dwc2/core.h +++ b/drivers/staging/dwc2/core.h @@ -544,7 +544,7 @@ extern void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg); extern void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg); extern u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg); -extern int dwc2_check_core_status(struct dwc2_hsotg *hsotg); +extern bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg); /* * Common core Functions. diff --git a/drivers/staging/dwc2/core_intr.c b/drivers/staging/dwc2/core_intr.c index 07cfa2f6aa2b..c78bb5d74045 100644 --- a/drivers/staging/dwc2/core_intr.c +++ b/drivers/staging/dwc2/core_intr.c @@ -451,8 +451,8 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev) u32 gintsts; irqreturn_t retval = IRQ_NONE; - if (dwc2_check_core_status(hsotg) < 0) { - dev_warn(hsotg->dev, "Controller is disconnected\n"); + if (!dwc2_is_controller_alive(hsotg)) { + dev_warn(hsotg->dev, "Controller is dead\n"); goto out; } diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index dda18540f5a7..e672e6db2943 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -2059,8 +2059,8 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg) u32 gintsts, dbg_gintsts; irqreturn_t retval = IRQ_NONE; - if (dwc2_check_core_status(hsotg) < 0) { - dev_warn(hsotg->dev, "Controller is disconnected\n"); + if (!dwc2_is_controller_alive(hsotg) < 0) { + dev_warn(hsotg->dev, "Controller is dead\n"); return retval; } -- cgit v1.2.3 From c20e1c6a2d01b48bd19f77ac0b0932395743bedc Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 22 Nov 2013 16:43:52 -0800 Subject: staging: dwc2: remove #ifdef DEBUG from a couple of places Remove #ifdef DEBUG from a couple of places where it is not needed Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core_intr.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core_intr.c b/drivers/staging/dwc2/core_intr.c index c78bb5d74045..8205799e6db3 100644 --- a/drivers/staging/dwc2/core_intr.c +++ b/drivers/staging/dwc2/core_intr.c @@ -55,7 +55,6 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg) { -#ifdef DEBUG switch (hsotg->op_state) { case OTG_STATE_A_HOST: return "a_host"; @@ -70,9 +69,6 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg) default: return "unknown"; } -#else - return ""; -#endif } /** @@ -419,12 +415,10 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg) gintmsk = readl(hsotg->regs + GINTMSK); gahbcfg = readl(hsotg->regs + GAHBCFG); -#ifdef DEBUG /* If any common interrupts set */ if (gintsts & gintmsk_common) dev_dbg(hsotg->dev, "gintsts=%08x gintmsk=%08x\n", gintsts, gintmsk); -#endif if (gahbcfg & GAHBCFG_GLBL_INTR_EN) return gintsts & gintmsk & gintmsk_common; -- cgit v1.2.3 From d31e6ca405d448dd8d1ed6a4a13c42971fd6c853 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 25 Nov 2013 17:11:29 +0300 Subject: staging: dwc2: cleanups in dwc2_hcd_qh_add() I've made the success and error paths clearer and pulled some code in one indent level. Signed-off-by: Dan Carpenter Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_queue.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c index 729cc0b83df3..e2855ed94e6e 100644 --- a/drivers/staging/dwc2/hcd_queue.c +++ b/drivers/staging/dwc2/hcd_queue.c @@ -579,7 +579,7 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg, */ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { - int status = 0; + int status; u32 intr_mask; if (dbg_qh(qh)) @@ -587,7 +587,7 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) if (!list_empty(&qh->qh_list_entry)) /* QH already in a schedule */ - return status; + return 0; /* Add the new QH to the appropriate schedule */ if (dwc2_qh_is_non_per(qh)) { @@ -596,17 +596,17 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) &hsotg->non_periodic_sched_inactive); } else { status = dwc2_schedule_periodic(hsotg, qh); - if (status == 0) { - if (!hsotg->periodic_qh_count) { - intr_mask = readl(hsotg->regs + GINTMSK); - intr_mask |= GINTSTS_SOF; - writel(intr_mask, hsotg->regs + GINTMSK); - } - hsotg->periodic_qh_count++; + if (status) + return status; + if (!hsotg->periodic_qh_count) { + intr_mask = readl(hsotg->regs + GINTMSK); + intr_mask |= GINTSTS_SOF; + writel(intr_mask, hsotg->regs + GINTMSK); } + hsotg->periodic_qh_count++; } - return status; + return 0; } /** -- cgit v1.2.3 From 5e1284758a6702117b622a4983c5829ea583df2c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 25 Nov 2013 17:14:14 +0300 Subject: staging: dwc2: remove some indent levels Instead of writing code like: if (dwc2_qh_is_non_per(qh)) { ... } else { ... } return; write it like: if (dwc2_qh_is_non_per(qh)) { ... return; } ... Signed-off-by: Dan Carpenter Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_queue.c | 95 +++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c index e2855ed94e6e..9540f7e1e20e 100644 --- a/drivers/staging/dwc2/hcd_queue.c +++ b/drivers/staging/dwc2/hcd_queue.c @@ -594,18 +594,19 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) /* Always start in inactive schedule */ list_add_tail(&qh->qh_list_entry, &hsotg->non_periodic_sched_inactive); - } else { - status = dwc2_schedule_periodic(hsotg, qh); - if (status) - return status; - if (!hsotg->periodic_qh_count) { - intr_mask = readl(hsotg->regs + GINTMSK); - intr_mask |= GINTSTS_SOF; - writel(intr_mask, hsotg->regs + GINTMSK); - } - hsotg->periodic_qh_count++; + return 0; } + status = dwc2_schedule_periodic(hsotg, qh); + if (status) + return status; + if (!hsotg->periodic_qh_count) { + intr_mask = readl(hsotg->regs + GINTMSK); + intr_mask |= GINTSTS_SOF; + writel(intr_mask, hsotg->regs + GINTMSK); + } + hsotg->periodic_qh_count++; + return 0; } @@ -631,14 +632,15 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) hsotg->non_periodic_qh_ptr = hsotg->non_periodic_qh_ptr->next; list_del_init(&qh->qh_list_entry); - } else { - dwc2_deschedule_periodic(hsotg, qh); - hsotg->periodic_qh_count--; - if (!hsotg->periodic_qh_count) { - intr_mask = readl(hsotg->regs + GINTMSK); - intr_mask &= ~GINTSTS_SOF; - writel(intr_mask, hsotg->regs + GINTMSK); - } + return; + } + + dwc2_deschedule_periodic(hsotg, qh); + hsotg->periodic_qh_count--; + if (!hsotg->periodic_qh_count) { + intr_mask = readl(hsotg->regs + GINTMSK); + intr_mask &= ~GINTSTS_SOF; + writel(intr_mask, hsotg->regs + GINTMSK); } } @@ -693,6 +695,8 @@ static void dwc2_sched_periodic_split(struct dwc2_hsotg *hsotg, void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, int sched_next_periodic_split) { + u16 frame_number; + if (dbg_qh(qh)) dev_vdbg(hsotg->dev, "%s()\n", __func__); @@ -701,37 +705,36 @@ void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, if (!list_empty(&qh->qtd_list)) /* Add back to inactive non-periodic schedule */ dwc2_hcd_qh_add(hsotg, qh); + return; + } + + frame_number = dwc2_hcd_get_frame_number(hsotg); + + if (qh->do_split) { + dwc2_sched_periodic_split(hsotg, qh, frame_number, + sched_next_periodic_split); } else { - u16 frame_number = dwc2_hcd_get_frame_number(hsotg); - - if (qh->do_split) { - dwc2_sched_periodic_split(hsotg, qh, frame_number, - sched_next_periodic_split); - } else { - qh->sched_frame = dwc2_frame_num_inc(qh->sched_frame, - qh->interval); - if (dwc2_frame_num_le(qh->sched_frame, frame_number)) - qh->sched_frame = frame_number; - } + qh->sched_frame = dwc2_frame_num_inc(qh->sched_frame, + qh->interval); + if (dwc2_frame_num_le(qh->sched_frame, frame_number)) + qh->sched_frame = frame_number; + } - if (list_empty(&qh->qtd_list)) { - dwc2_hcd_qh_unlink(hsotg, qh); - } else { - /* - * Remove from periodic_sched_queued and move to - * appropriate queue - */ - if ((hsotg->core_params->uframe_sched > 0 && - dwc2_frame_num_le(qh->sched_frame, frame_number)) - || (hsotg->core_params->uframe_sched <= 0 && - qh->sched_frame == frame_number)) - list_move(&qh->qh_list_entry, - &hsotg->periodic_sched_ready); - else - list_move(&qh->qh_list_entry, - &hsotg->periodic_sched_inactive); - } + if (list_empty(&qh->qtd_list)) { + dwc2_hcd_qh_unlink(hsotg, qh); + return; } + /* + * Remove from periodic_sched_queued and move to + * appropriate queue + */ + if ((hsotg->core_params->uframe_sched > 0 && + dwc2_frame_num_le(qh->sched_frame, frame_number)) || + (hsotg->core_params->uframe_sched <= 0 && + qh->sched_frame == frame_number)) + list_move(&qh->qh_list_entry, &hsotg->periodic_sched_ready); + else + list_move(&qh->qh_list_entry, &hsotg->periodic_sched_inactive); } /** -- cgit v1.2.3 From a34c72b348703da43d605441b86a61688ec19a0d Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 16 Nov 2013 00:46:24 +0400 Subject: staging: gdm724x: fix leak at failure path in gdm_usb_probe() Error handling code in gdm_usb_probe() deallocates all resources, but calls usb_get_dev(usbdev) and returns error code after that. The patch fixes it and, by the way, several other issues: - no need to use GFP_ATOMIC in probe(); - return -ENODEV instead of -1; - kmalloc+memset -> kzalloc Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_usb.c | 40 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index 781134af69d1..33458a583142 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -830,24 +830,19 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id if (bInterfaceNumber > NETWORK_INTERFACE) { pr_info("not a network device\n"); - return -1; + return -ENODEV; } - phy_dev = kmalloc(sizeof(struct phy_dev), GFP_ATOMIC); - if (!phy_dev) { - ret = -ENOMEM; - goto out; - } + phy_dev = kzalloc(sizeof(struct phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; - udev = kmalloc(sizeof(struct lte_udev), GFP_ATOMIC); + udev = kzalloc(sizeof(struct lte_udev), GFP_KERNEL); if (!udev) { ret = -ENOMEM; - goto out; + goto err_udev; } - memset(phy_dev, 0, sizeof(struct phy_dev)); - memset(udev, 0, sizeof(struct lte_udev)); - phy_dev->priv_dev = (void *)udev; phy_dev->send_hci_func = gdm_usb_hci_send; phy_dev->send_sdu_func = gdm_usb_sdu_send; @@ -858,7 +853,7 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ret = init_usb(udev); if (ret < 0) { pr_err("init_usb func failed\n"); - goto out; + goto err_init_usb; } udev->intf = intf; @@ -875,23 +870,22 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ret = request_mac_address(udev); if (ret < 0) { pr_err("request Mac address failed\n"); - goto out; + goto err_mac_address; } start_rx_proc(phy_dev); -out: - - if (ret < 0) { - kfree(phy_dev); - if (udev) { - release_usb(udev); - kfree(udev); - } - } - usb_get_dev(usbdev); usb_set_intfdata(intf, phy_dev); + return 0; + +err_mac_address: + release_usb(udev); +err_init_usb: + kfree(udev); +err_udev: + kfree(phy_dev); + return ret; } -- cgit v1.2.3 From b831516cc5c4f3f06680cbe4411a57e192bdb676 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:22 +0800 Subject: staging/lustre/libcfs: remove filp_size/filp_poff Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h | 5 ----- drivers/staging/lustre/lustre/libcfs/tracefile.c | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h index eebf138f21e5..8fabe4b2f306 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h @@ -52,11 +52,6 @@ #include #include -#define filp_size(f) \ - (i_size_read((f)->f_dentry->d_inode)) -#define filp_poff(f) \ - (&(f)->f_pos) - # define do_fsync(fp, flag) \ ((fp)->f_op->fsync(fp, 0, LLONG_MAX, flag)) diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index f71a3cc63ad8..0ce4aaca27b4 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -709,7 +709,7 @@ int cfs_tracefile_dump_all_pages(char *filename) __LASSERT_TAGE_INVARIANT(tage); rc = filp_write(filp, page_address(tage->page), - tage->used, filp_poff(filp)); + tage->used, &filp->f_pos); if (rc != (int)tage->used) { printk(KERN_WARNING "wanted to write %u but wrote " "%d\n", tage->used, rc); @@ -1020,8 +1020,8 @@ static int tracefiled(void *arg) if (f_pos >= (off_t)cfs_tracefile_size) f_pos = 0; - else if (f_pos > (off_t)filp_size(filp)) - f_pos = filp_size(filp); + else if (f_pos > i_size_read(filp->f_dentry->d_inode)) + f_pos = i_size_read(filp->f_dentry->d_inode); rc = filp_write(filp, page_address(tage->page), tage->used, &f_pos); -- cgit v1.2.3 From a630b22d5120366ef83fc3b21edc0ad77cc8c1d2 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:23 +0800 Subject: staging/lustre/libcfs: remove filp_fsync we can just call generic vfs_fsync(). Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h | 6 ------ drivers/staging/lustre/lustre/libcfs/tracefile.c | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h index 8fabe4b2f306..e523004078df 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h @@ -52,18 +52,12 @@ #include #include -# define do_fsync(fp, flag) \ - ((fp)->f_op->fsync(fp, 0, LLONG_MAX, flag)) - #define filp_read(fp, buf, size, pos) \ ((fp)->f_op->read((fp), (buf), (size), pos)) #define filp_write(fp, buf, size, pos) \ ((fp)->f_op->write((fp), (buf), (size), pos)) -#define filp_fsync(fp) \ - do_fsync(fp, 1) - #define flock_type(fl) ((fl)->fl_type) #define flock_set_type(fl, type) do { (fl)->fl_type = (type); } while (0) #define flock_pid(fl) ((fl)->fl_pid) diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index 0ce4aaca27b4..4c3dad6fcf49 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -721,7 +721,7 @@ int cfs_tracefile_dump_all_pages(char *filename) cfs_tage_free(tage); } MMSPACE_CLOSE; - rc = filp_fsync(filp); + rc = vfs_fsync(filp, 1); if (rc) printk(KERN_ERR "sync returns %d\n", rc); close: -- cgit v1.2.3 From e23f875db9b3bab7769cb9f7148b4688c31ecfa9 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:24 +0800 Subject: staging/lustre/libcfs: remove filp_read no users. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h index e523004078df..573ab0895791 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h @@ -52,9 +52,6 @@ #include #include -#define filp_read(fp, buf, size, pos) \ - ((fp)->f_op->read((fp), (buf), (size), pos)) - #define filp_write(fp, buf, size, pos) \ ((fp)->f_op->write((fp), (buf), (size), pos)) -- cgit v1.2.3 From 7ebcb731fc078085e3f11c41526840eccbceff44 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:25 +0800 Subject: staging/lustre/libcfs: remove filp_write Use vfs_write instead and call kmap/kunmap to ensure that we can access high memory zone. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/linux/linux-fs.h | 3 --- drivers/staging/lustre/lustre/libcfs/tracefile.c | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h index 573ab0895791..102afa217f85 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h @@ -52,9 +52,6 @@ #include #include -#define filp_write(fp, buf, size, pos) \ - ((fp)->f_op->write((fp), (buf), (size), pos)) - #define flock_type(fl) ((fl)->fl_type) #define flock_set_type(fl, type) do { (fl)->fl_type = (type); } while (0) #define flock_pid(fl) ((fl)->fl_pid) diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index 4c3dad6fcf49..54290ce6bb43 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -678,6 +678,7 @@ int cfs_tracefile_dump_all_pages(char *filename) struct file *filp; struct cfs_trace_page *tage; struct cfs_trace_page *tmp; + char *buf; int rc; DECL_MMSPACE; @@ -708,8 +709,11 @@ int cfs_tracefile_dump_all_pages(char *filename) __LASSERT_TAGE_INVARIANT(tage); - rc = filp_write(filp, page_address(tage->page), - tage->used, &filp->f_pos); + buf = kmap(tage->page); + rc = vfs_write(filp, (__force const char __user *)buf, + tage->used, &filp->f_pos); + kunmap(tage->page); + if (rc != (int)tage->used) { printk(KERN_WARNING "wanted to write %u but wrote " "%d\n", tage->used, rc); @@ -971,6 +975,7 @@ static int tracefiled(void *arg) struct cfs_trace_page *tage; struct cfs_trace_page *tmp; struct file *filp; + char *buf; int last_loop = 0; int rc; @@ -1023,8 +1028,11 @@ static int tracefiled(void *arg) else if (f_pos > i_size_read(filp->f_dentry->d_inode)) f_pos = i_size_read(filp->f_dentry->d_inode); - rc = filp_write(filp, page_address(tage->page), - tage->used, &f_pos); + buf = kmap(tage->page); + rc = vfs_write(filp, (__force const char __user *)buf, + tage->used, &f_pos); + kunmap(tage->page); + if (rc != (int)tage->used) { printk(KERN_WARNING "wanted to write %u " "but wrote %d\n", tage->used, rc); -- cgit v1.2.3 From 79783924db1e2e090ea32b0076d262c321f9bf9c Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:26 +0800 Subject: staging/lustre: move IFTODT/DTTOIF to lustre_idl.h They are in fact definition of how client/server talks to each other about file type. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h | 11 ----------- drivers/staging/lustre/lustre/include/lustre/lustre_idl.h | 12 ++++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h index 102afa217f85..fdec53a6c8a3 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h @@ -61,15 +61,4 @@ #define flock_end(fl) ((fl)->fl_end) #define flock_set_end(fl, end) do { (fl)->fl_end = (end); } while (0) -#ifndef IFSHIFT -#define IFSHIFT 12 -#endif - -#ifndef IFTODT -#define IFTODT(type) (((type) & S_IFMT) >> IFSHIFT) -#endif -#ifndef DTTOIF -#define DTTOIF(dirtype) ((dirtype) << IFSHIFT) -#endif - #endif diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 4d8d8c34cd67..7dfb925a536b 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1025,6 +1025,18 @@ struct luda_type { __u16 lt_type; }; +#ifndef IFSHIFT +#define IFSHIFT 12 +#endif + +#ifndef IFTODT +#define IFTODT(type) (((type) & S_IFMT) >> IFSHIFT) +#endif +#ifndef DTTOIF +#define DTTOIF(dirtype) ((dirtype) << IFSHIFT) +#endif + + struct lu_dirpage { __u64 ldp_hash_start; __u64 ldp_hash_end; -- cgit v1.2.3 From d47b680e7b8bbed69df2a557a944d7a28c2b9ad8 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:27 +0800 Subject: staging/lustre/libcfs: remove flock wrappers Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/linux/linux-fs.h | 9 --------- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 17 +++++++---------- 2 files changed, 7 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h index fdec53a6c8a3..71e7594a835f 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h @@ -52,13 +52,4 @@ #include #include -#define flock_type(fl) ((fl)->fl_type) -#define flock_set_type(fl, type) do { (fl)->fl_type = (type); } while (0) -#define flock_pid(fl) ((fl)->fl_pid) -#define flock_set_pid(fl, pid) do { (fl)->fl_pid = (pid); } while (0) -#define flock_start(fl) ((fl)->fl_start) -#define flock_set_start(fl, st) do { (fl)->fl_start = (st); } while (0) -#define flock_end(fl) ((fl)->fl_end) -#define flock_set_end(fl, end) do { (fl)->fl_end = (end); } while (0) - #endif diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 39fcdacc51ed..456d5aa76960 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -665,23 +665,20 @@ granted: /* fcntl(F_GETLK) request */ /* The old mode was saved in getlk->fl_type so that if the mode * in the lock changes we can decref the appropriate refcount.*/ - ldlm_flock_destroy(lock, flock_type(getlk), - LDLM_FL_WAIT_NOREPROC); + ldlm_flock_destroy(lock, getlk->fl_type, LDLM_FL_WAIT_NOREPROC); switch (lock->l_granted_mode) { case LCK_PR: - flock_set_type(getlk, F_RDLCK); + getlk->fl_type = F_RDLCK; break; case LCK_PW: - flock_set_type(getlk, F_WRLCK); + getlk->fl_type = F_WRLCK; break; default: - flock_set_type(getlk, F_UNLCK); + getlk->fl_type = F_UNLCK; } - flock_set_pid(getlk, (pid_t)lock->l_policy_data.l_flock.pid); - flock_set_start(getlk, - (loff_t)lock->l_policy_data.l_flock.start); - flock_set_end(getlk, - (loff_t)lock->l_policy_data.l_flock.end); + getlk->fl_pid = (pid_t)lock->l_policy_data.l_flock.pid; + getlk->fl_start = (loff_t)lock->l_policy_data.l_flock.start; + getlk->fl_end = (loff_t)lock->l_policy_data.l_flock.end; } else { __u64 noreproc = LDLM_FL_WAIT_NOREPROC; -- cgit v1.2.3 From bfc79f3cdbacdeaf6275cdcca32f50d282e2ec36 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:28 +0800 Subject: staging/lustre/libcfs: remove linux-fs.h Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/linux/libcfs.h | 1 - .../lustre/include/linux/libcfs/linux/linux-fs.h | 55 ---------------------- 2 files changed, 56 deletions(-) delete mode 100644 drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h index 60ecaf63f9fb..a7bca40e9fb7 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h deleted file mode 100644 index 71e7594a835f..000000000000 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-fs.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * libcfs/include/libcfs/linux/linux-fs.h - * - * Basic library routines. - */ - -#ifndef __LIBCFS_LINUX_CFS_FS_H__ -#define __LIBCFS_LINUX_CFS_FS_H__ - -#ifndef __LIBCFS_LIBCFS_H__ -#error Do not #include this file directly. #include instead -#endif - - -#include -#include -#include -#include -#include - -#endif -- cgit v1.2.3 From da7a96ae19d30dfe2564ea67afae464fafe29933 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:29 +0800 Subject: staging/lustre/libcfs: remove lwt code It was never enabled. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_ioctl.h | 3 - .../lustre/include/linux/libcfs/linux/kp30.h | 96 -------- drivers/staging/lustre/lustre/libcfs/lwt.c | 266 --------------------- drivers/staging/lustre/lustre/libcfs/module.c | 53 +--- 4 files changed, 3 insertions(+), 415 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/libcfs/lwt.c (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 315743ec92e3..dd1a1f1ef1f6 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -113,9 +113,6 @@ struct libcfs_ioctl_handler { #define IOC_LIBCFS_PANIC _IOWR('e', 30, long) #define IOC_LIBCFS_CLEAR_DEBUG _IOWR('e', 31, long) #define IOC_LIBCFS_MARK_DEBUG _IOWR('e', 32, long) -#define IOC_LIBCFS_LWT_CONTROL _IOWR('e', 33, long) -#define IOC_LIBCFS_LWT_SNAPSHOT _IOWR('e', 34, long) -#define IOC_LIBCFS_LWT_LOOKUP_STRING _IOWR('e', 35, long) #define IOC_LIBCFS_MEMHOG _IOWR('e', 36, long) #define IOC_LIBCFS_PING_TEST _IOWR('e', 37, long) /* lnet ioctls */ diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 3a883f82e64f..ba14c3173a1a 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -77,102 +77,6 @@ module_param(name, type, perm);\ MODULE_PARM_DESC(name, desc) -/******************************************************************************/ -/* Light-weight trace - * Support for temporary event tracing with minimal Heisenberg effect. */ -#define LWT_SUPPORT 0 - -#define LWT_MEMORY (16<<20) - -#ifndef KLWT_SUPPORT -# if !defined(BITS_PER_LONG) -# error "BITS_PER_LONG not defined" -# endif - -/* kernel hasn't defined this? */ -typedef struct { - long long lwte_when; - char *lwte_where; - void *lwte_task; - long lwte_p1; - long lwte_p2; - long lwte_p3; - long lwte_p4; -# if BITS_PER_LONG > 32 - long lwte_pad; -# endif -} lwt_event_t; -#endif /* !KLWT_SUPPORT */ - -#if LWT_SUPPORT -# if !KLWT_SUPPORT - -typedef struct _lwt_page { - struct list_head lwtp_list; - struct page *lwtp_page; - lwt_event_t *lwtp_events; -} lwt_page_t; - -typedef struct { - int lwtc_current_index; - lwt_page_t *lwtc_current_page; -} lwt_cpu_t; - -extern int lwt_enabled; -extern lwt_cpu_t lwt_cpus[]; - -/* Note that we _don't_ define LWT_EVENT at all if LWT_SUPPORT isn't set. - * This stuff is meant for finding specific problems; it never stays in - * production code... */ - -#define LWTSTR(n) #n -#define LWTWHERE(f,l) f ":" LWTSTR(l) -#define LWT_EVENTS_PER_PAGE (PAGE_CACHE_SIZE / sizeof (lwt_event_t)) - -#define LWT_EVENT(p1, p2, p3, p4) \ -do { \ - unsigned long flags; \ - lwt_cpu_t *cpu; \ - lwt_page_t *p; \ - lwt_event_t *e; \ - \ - if (lwt_enabled) { \ - local_irq_save (flags); \ - \ - cpu = &lwt_cpus[smp_processor_id()]; \ - p = cpu->lwtc_current_page; \ - e = &p->lwtp_events[cpu->lwtc_current_index++]; \ - \ - if (cpu->lwtc_current_index >= LWT_EVENTS_PER_PAGE) { \ - cpu->lwtc_current_page = \ - list_entry (p->lwtp_list.next, \ - lwt_page_t, lwtp_list); \ - cpu->lwtc_current_index = 0; \ - } \ - \ - e->lwte_when = get_cycles(); \ - e->lwte_where = LWTWHERE(__FILE__,__LINE__); \ - e->lwte_task = current; \ - e->lwte_p1 = (long)(p1); \ - e->lwte_p2 = (long)(p2); \ - e->lwte_p3 = (long)(p3); \ - e->lwte_p4 = (long)(p4); \ - \ - local_irq_restore (flags); \ - } \ -} while (0) - -#endif /* !KLWT_SUPPORT */ - -extern int lwt_init (void); -extern void lwt_fini (void); -extern int lwt_lookup_string (int *size, char *knlptr, - char *usrptr, int usrsize); -extern int lwt_control (int enable, int clear); -extern int lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, - void *user_ptr, int user_size); -#endif /* LWT_SUPPORT */ - /* ------------------------------------------------------------------ */ # define LI_POISON 0x5a5a5a5a diff --git a/drivers/staging/lustre/lustre/libcfs/lwt.c b/drivers/staging/lustre/lustre/libcfs/lwt.c deleted file mode 100644 index b631f7dde8e7..000000000000 --- a/drivers/staging/lustre/lustre/libcfs/lwt.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * libcfs/libcfs/lwt.c - * - * Author: Eric Barton - */ - -#define DEBUG_SUBSYSTEM S_LNET - -#include - -#if LWT_SUPPORT - -#if !KLWT_SUPPORT -int lwt_enabled; -lwt_cpu_t lwt_cpus[NR_CPUS]; -#endif - -int lwt_pages_per_cpu; - -/* NB only root is allowed to retrieve LWT info; it's an open door into the - * kernel... */ - -int -lwt_lookup_string (int *size, char *knl_ptr, - char *user_ptr, int user_size) -{ - int maxsize = 128; - - /* knl_ptr was retrieved from an LWT snapshot and the caller wants to - * turn it into a string. NB we can crash with an access violation - * trying to determine the string length, so we're trusting our - * caller... */ - - if (!cfs_capable(CFS_CAP_SYS_ADMIN)) - return (-EPERM); - - if (user_size > 0 && - maxsize > user_size) - maxsize = user_size; - - *size = strnlen (knl_ptr, maxsize - 1) + 1; - - if (user_ptr != NULL) { - if (user_size < 4) - return (-EINVAL); - - if (copy_to_user (user_ptr, knl_ptr, *size)) - return (-EFAULT); - - /* Did I truncate the string? */ - if (knl_ptr[*size - 1] != 0) - copy_to_user (user_ptr + *size - 4, "...", 4); - } - - return (0); -} - -int -lwt_control (int enable, int clear) -{ - lwt_page_t *p; - int i; - int j; - - if (!cfs_capable(CFS_CAP_SYS_ADMIN)) - return (-EPERM); - - if (!enable) { - LWT_EVENT(0,0,0,0); - lwt_enabled = 0; - mb(); - /* give people some time to stop adding traces */ - schedule_timeout(10); - } - - for (i = 0; i < num_online_cpus(); i++) { - p = lwt_cpus[i].lwtc_current_page; - - if (p == NULL) - return (-ENODATA); - - if (!clear) - continue; - - for (j = 0; j < lwt_pages_per_cpu; j++) { - memset (p->lwtp_events, 0, PAGE_CACHE_SIZE); - - p = list_entry (p->lwtp_list.next, - lwt_page_t, lwtp_list); - } - } - - if (enable) { - lwt_enabled = 1; - mb(); - LWT_EVENT(0,0,0,0); - } - - return (0); -} - -int -lwt_snapshot (cfs_cycles_t *now, int *ncpu, int *total_size, - void *user_ptr, int user_size) -{ - const int events_per_page = PAGE_CACHE_SIZE / sizeof(lwt_event_t); - const int bytes_per_page = events_per_page * sizeof(lwt_event_t); - lwt_page_t *p; - int i; - int j; - - if (!cfs_capable(CFS_CAP_SYS_ADMIN)) - return (-EPERM); - - *ncpu = num_online_cpus(); - *total_size = num_online_cpus() * lwt_pages_per_cpu * - bytes_per_page; - *now = get_cycles(); - - if (user_ptr == NULL) - return (0); - - for (i = 0; i < num_online_cpus(); i++) { - p = lwt_cpus[i].lwtc_current_page; - - if (p == NULL) - return (-ENODATA); - - for (j = 0; j < lwt_pages_per_cpu; j++) { - if (copy_to_user(user_ptr, p->lwtp_events, - bytes_per_page)) - return (-EFAULT); - - user_ptr = ((char *)user_ptr) + bytes_per_page; - p = list_entry(p->lwtp_list.next, - lwt_page_t, lwtp_list); - } - } - - return (0); -} - -int -lwt_init () -{ - int i; - int j; - - for (i = 0; i < num_online_cpus(); i++) - if (lwt_cpus[i].lwtc_current_page != NULL) - return (-EALREADY); - - LASSERT (!lwt_enabled); - - /* NULL pointers, zero scalars */ - memset (lwt_cpus, 0, sizeof (lwt_cpus)); - lwt_pages_per_cpu = - LWT_MEMORY / (num_online_cpus() * PAGE_CACHE_SIZE); - - for (i = 0; i < num_online_cpus(); i++) - for (j = 0; j < lwt_pages_per_cpu; j++) { - struct page *page = alloc_page (GFP_KERNEL); - lwt_page_t *lwtp; - - if (page == NULL) { - CERROR ("Can't allocate page\n"); - lwt_fini (); - return (-ENOMEM); - } - - LIBCFS_ALLOC(lwtp, sizeof (*lwtp)); - if (lwtp == NULL) { - CERROR ("Can't allocate lwtp\n"); - __free_page(page); - lwt_fini (); - return (-ENOMEM); - } - - lwtp->lwtp_page = page; - lwtp->lwtp_events = page_address(page); - memset (lwtp->lwtp_events, 0, PAGE_CACHE_SIZE); - - if (j == 0) { - INIT_LIST_HEAD (&lwtp->lwtp_list); - lwt_cpus[i].lwtc_current_page = lwtp; - } else { - list_add (&lwtp->lwtp_list, - &lwt_cpus[i].lwtc_current_page->lwtp_list); - } - } - - lwt_enabled = 1; - mb(); - - LWT_EVENT(0,0,0,0); - - return (0); -} - -void -lwt_fini () -{ - int i; - - lwt_control(0, 0); - - for (i = 0; i < num_online_cpus(); i++) - while (lwt_cpus[i].lwtc_current_page != NULL) { - lwt_page_t *lwtp = lwt_cpus[i].lwtc_current_page; - - if (list_empty (&lwtp->lwtp_list)) { - lwt_cpus[i].lwtc_current_page = NULL; - } else { - lwt_cpus[i].lwtc_current_page = - list_entry (lwtp->lwtp_list.next, - lwt_page_t, lwtp_list); - - list_del (&lwtp->lwtp_list); - } - - __free_page (lwtp->lwtp_page); - LIBCFS_FREE (lwtp, sizeof (*lwtp)); - } -} - -EXPORT_SYMBOL(lwt_enabled); -EXPORT_SYMBOL(lwt_cpus); - -EXPORT_SYMBOL(lwt_init); -EXPORT_SYMBOL(lwt_fini); -EXPORT_SYMBOL(lwt_lookup_string); -EXPORT_SYMBOL(lwt_control); -EXPORT_SYMBOL(lwt_snapshot); -#endif diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index f3108c7f818e..463b3e17e282 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -235,41 +235,6 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile,unsigned long cmd, return -EINVAL; libcfs_debug_mark_buffer(data->ioc_inlbuf1); return 0; -#if LWT_SUPPORT - case IOC_LIBCFS_LWT_CONTROL: - err = lwt_control ((data->ioc_flags & 1) != 0, - (data->ioc_flags & 2) != 0); - break; - - case IOC_LIBCFS_LWT_SNAPSHOT: { - cfs_cycles_t now; - int ncpu; - int total_size; - - err = lwt_snapshot (&now, &ncpu, &total_size, - data->ioc_pbuf1, data->ioc_plen1); - data->ioc_u64[0] = now; - data->ioc_u32[0] = ncpu; - data->ioc_u32[1] = total_size; - - /* Hedge against broken user/kernel typedefs (e.g. cycles_t) */ - data->ioc_u32[2] = sizeof(lwt_event_t); - data->ioc_u32[3] = offsetof(lwt_event_t, lwte_where); - - if (err == 0 && - libcfs_ioctl_popdata(arg, data, sizeof (*data))) - err = -EFAULT; - break; - } - - case IOC_LIBCFS_LWT_LOOKUP_STRING: - err = lwt_lookup_string (&data->ioc_count, data->ioc_pbuf1, - data->ioc_pbuf2, data->ioc_plen2); - if (err == 0 && - libcfs_ioctl_popdata(arg, data, sizeof (*data))) - err = -EFAULT; - break; -#endif case IOC_LIBCFS_MEMHOG: if (pfile->private_data == NULL) { err = -EINVAL; @@ -392,17 +357,10 @@ static int init_libcfs_module(void) if (rc != 0) goto cleanup_debug; -#if LWT_SUPPORT - rc = lwt_init(); - if (rc != 0) { - CERROR("lwt_init: error %d\n", rc); - goto cleanup_debug; - } -#endif rc = misc_register(&libcfs_dev); if (rc) { CERROR("misc_register: error %d\n", rc); - goto cleanup_lwt; + goto cleanup_cpu; } rc = cfs_wi_startup(); @@ -441,10 +399,8 @@ static int init_libcfs_module(void) cfs_wi_shutdown(); cleanup_deregister: misc_deregister(&libcfs_dev); - cleanup_lwt: -#if LWT_SUPPORT - lwt_fini(); -#endif +cleanup_cpu: + cfs_cpu_fini(); cleanup_debug: libcfs_debug_cleanup(); return rc; @@ -471,9 +427,6 @@ static void exit_libcfs_module(void) if (rc) CERROR("misc_deregister error %d\n", rc); -#if LWT_SUPPORT - lwt_fini(); -#endif cfs_cpu_fini(); if (atomic_read(&libcfs_kmemory) != 0) -- cgit v1.2.3 From 8cc7b4b9f1ccf33e3174314c4095e019eafeb31a Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:30 +0800 Subject: staging/lustre: remove CFS_MODULE_PARM Patch generated by coccinelle: @generic_type@ declarer name CFS_MODULE_PARM; declarer name module_param; declarer name MODULE_PARM_DESC; expression E1, E2, E3, E4; type t; @@ -CFS_MODULE_PARM(E1, E2, t, E3, E4); +module_param(E1, t, E3); +MODULE_PARM_DESC(E1, E4); @charp@ expression E1, E2, E3, E4, E5; @@ -CFS_MODULE_PARM(E1, E2, E3, E4, E5); +module_param(E1, E3, E4); +MODULE_PARM_DESC(E1, E5); With manual modification to remove CFS_MODULE_PARM definition and fix up checkpatch.pl warnnings. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/linux/kp30.h | 7 -- .../lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c | 96 +++++++++--------- .../lustre/lnet/klnds/socklnd/socklnd_modparams.c | 112 ++++++++++----------- drivers/staging/lustre/lnet/lnet/acceptor.c | 16 +-- drivers/staging/lustre/lnet/lnet/api-ni.c | 16 +-- drivers/staging/lustre/lnet/lnet/lib-move.c | 4 +- drivers/staging/lustre/lnet/lnet/lib-ptl.c | 4 +- drivers/staging/lustre/lnet/lnet/module.c | 4 +- drivers/staging/lustre/lnet/lnet/router.c | 44 ++++---- drivers/staging/lustre/lnet/selftest/brw_test.c | 7 +- drivers/staging/lustre/lnet/selftest/framework.c | 8 +- drivers/staging/lustre/lnet/selftest/ping_test.c | 3 +- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 8 +- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 4 +- drivers/staging/lustre/lustre/libcfs/debug.c | 42 ++++---- drivers/staging/lustre/lustre/libcfs/hash.c | 4 +- .../staging/lustre/lustre/libcfs/linux/linux-cpu.c | 6 +- drivers/staging/lustre/lustre/llite/lloop.c | 3 +- .../lustre/lustre/obdclass/lprocfs_status.c | 4 +- drivers/staging/lustre/lustre/obdclass/lu_object.c | 4 +- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 3 +- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c | 8 +- drivers/staging/lustre/lustre/ptlrpc/service.c | 26 ++--- 23 files changed, 216 insertions(+), 217 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index ba14c3173a1a..8cab09c1f41d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -70,13 +70,6 @@ #include - -/******************************************************************************/ -/* Module parameter support */ -#define CFS_MODULE_PARM(name, t, type, perm, desc) \ - module_param(name, type, perm);\ - MODULE_PARM_DESC(name, desc) - /* ------------------------------------------------------------------ */ # define LI_POISON 0x5a5a5a5a diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c index cc291d00dba0..cefdfb6b1bec 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c @@ -41,95 +41,95 @@ #include "o2iblnd.h" static int service = 987; -CFS_MODULE_PARM(service, "i", int, 0444, - "service number (within RDMA_PS_TCP)"); +module_param(service, int, 0444); +MODULE_PARM_DESC(service, "service number (within RDMA_PS_TCP)"); static int cksum = 0; -CFS_MODULE_PARM(cksum, "i", int, 0644, - "set non-zero to enable message (not RDMA) checksums"); +module_param(cksum, int, 0644); +MODULE_PARM_DESC(cksum, "set non-zero to enable message (not RDMA) checksums"); static int timeout = 50; -CFS_MODULE_PARM(timeout, "i", int, 0644, - "timeout (seconds)"); +module_param(timeout, int, 0644); +MODULE_PARM_DESC(timeout, "timeout (seconds)"); /* Number of threads in each scheduler pool which is percpt, * we will estimate reasonable value based on CPUs if it's set to zero. */ static int nscheds; -CFS_MODULE_PARM(nscheds, "i", int, 0444, - "number of threads in each scheduler pool"); +module_param(nscheds, int, 0444); +MODULE_PARM_DESC(nscheds, "number of threads in each scheduler pool"); /* NB: this value is shared by all CPTs, it can grow at runtime */ static int ntx = 512; -CFS_MODULE_PARM(ntx, "i", int, 0444, - "# of message descriptors allocated for each pool"); +module_param(ntx, int, 0444); +MODULE_PARM_DESC(ntx, "# of message descriptors allocated for each pool"); /* NB: this value is shared by all CPTs */ static int credits = 256; -CFS_MODULE_PARM(credits, "i", int, 0444, - "# concurrent sends"); +module_param(credits, int, 0444); +MODULE_PARM_DESC(credits, "# concurrent sends"); static int peer_credits = 8; -CFS_MODULE_PARM(peer_credits, "i", int, 0444, - "# concurrent sends to 1 peer"); +module_param(peer_credits, int, 0444); +MODULE_PARM_DESC(peer_credits, "# concurrent sends to 1 peer"); static int peer_credits_hiw = 0; -CFS_MODULE_PARM(peer_credits_hiw, "i", int, 0444, - "when eagerly to return credits"); +module_param(peer_credits_hiw, int, 0444); +MODULE_PARM_DESC(peer_credits_hiw, "when eagerly to return credits"); static int peer_buffer_credits = 0; -CFS_MODULE_PARM(peer_buffer_credits, "i", int, 0444, - "# per-peer router buffer credits"); +module_param(peer_buffer_credits, int, 0444); +MODULE_PARM_DESC(peer_buffer_credits, "# per-peer router buffer credits"); static int peer_timeout = 180; -CFS_MODULE_PARM(peer_timeout, "i", int, 0444, - "Seconds without aliveness news to declare peer dead (<=0 to disable)"); +module_param(peer_timeout, int, 0444); +MODULE_PARM_DESC(peer_timeout, "Seconds without aliveness news to declare peer dead (<=0 to disable)"); static char *ipif_name = "ib0"; -CFS_MODULE_PARM(ipif_name, "s", charp, 0444, - "IPoIB interface name"); +module_param(ipif_name, charp, 0444); +MODULE_PARM_DESC(ipif_name, "IPoIB interface name"); static int retry_count = 5; -CFS_MODULE_PARM(retry_count, "i", int, 0644, - "Retransmissions when no ACK received"); +module_param(retry_count, int, 0644); +MODULE_PARM_DESC(retry_count, "Retransmissions when no ACK received"); static int rnr_retry_count = 6; -CFS_MODULE_PARM(rnr_retry_count, "i", int, 0644, - "RNR retransmissions"); +module_param(rnr_retry_count, int, 0644); +MODULE_PARM_DESC(rnr_retry_count, "RNR retransmissions"); static int keepalive = 100; -CFS_MODULE_PARM(keepalive, "i", int, 0644, - "Idle time in seconds before sending a keepalive"); +module_param(keepalive, int, 0644); +MODULE_PARM_DESC(keepalive, "Idle time in seconds before sending a keepalive"); static int ib_mtu = 0; -CFS_MODULE_PARM(ib_mtu, "i", int, 0444, - "IB MTU 256/512/1024/2048/4096"); +module_param(ib_mtu, int, 0444); +MODULE_PARM_DESC(ib_mtu, "IB MTU 256/512/1024/2048/4096"); static int concurrent_sends = 0; -CFS_MODULE_PARM(concurrent_sends, "i", int, 0444, - "send work-queue sizing"); +module_param(concurrent_sends, int, 0444); +MODULE_PARM_DESC(concurrent_sends, "send work-queue sizing"); static int map_on_demand = 0; -CFS_MODULE_PARM(map_on_demand, "i", int, 0444, - "map on demand"); +module_param(map_on_demand, int, 0444); +MODULE_PARM_DESC(map_on_demand, "map on demand"); /* NB: this value is shared by all CPTs, it can grow at runtime */ static int fmr_pool_size = 512; -CFS_MODULE_PARM(fmr_pool_size, "i", int, 0444, - "size of fmr pool on each CPT (>= ntx / 4)"); +module_param(fmr_pool_size, int, 0444); +MODULE_PARM_DESC(fmr_pool_size, "size of fmr pool on each CPT (>= ntx / 4)"); /* NB: this value is shared by all CPTs, it can grow at runtime */ static int fmr_flush_trigger = 384; -CFS_MODULE_PARM(fmr_flush_trigger, "i", int, 0444, - "# dirty FMRs that triggers pool flush"); +module_param(fmr_flush_trigger, int, 0444); +MODULE_PARM_DESC(fmr_flush_trigger, "# dirty FMRs that triggers pool flush"); static int fmr_cache = 1; -CFS_MODULE_PARM(fmr_cache, "i", int, 0444, - "non-zero to enable FMR caching"); +module_param(fmr_cache, int, 0444); +MODULE_PARM_DESC(fmr_cache, "non-zero to enable FMR caching"); /* NB: this value is shared by all CPTs, it can grow at runtime */ static int pmr_pool_size = 512; -CFS_MODULE_PARM(pmr_pool_size, "i", int, 0444, - "size of MR cache pmr pool on each CPT"); +module_param(pmr_pool_size, int, 0444); +MODULE_PARM_DESC(pmr_pool_size, "size of MR cache pmr pool on each CPT"); /* * 0: disable failover @@ -137,17 +137,17 @@ CFS_MODULE_PARM(pmr_pool_size, "i", int, 0444, * 2: force to failover (for debug) */ static int dev_failover = 0; -CFS_MODULE_PARM(dev_failover, "i", int, 0444, - "HCA failover for bonding (0 off, 1 on, other values reserved)"); +module_param(dev_failover, int, 0444); +MODULE_PARM_DESC(dev_failover, "HCA failover for bonding (0 off, 1 on, other values reserved)"); static int require_privileged_port = 0; -CFS_MODULE_PARM(require_privileged_port, "i", int, 0644, - "require privileged port when accepting connection"); +module_param(require_privileged_port, int, 0644); +MODULE_PARM_DESC(require_privileged_port, "require privileged port when accepting connection"); static int use_privileged_port = 1; -CFS_MODULE_PARM(use_privileged_port, "i", int, 0644, - "use privileged port when initiating connection"); +module_param(use_privileged_port, int, 0644); +MODULE_PARM_DESC(use_privileged_port, "use privileged port when initiating connection"); kib_tunables_t kiblnd_tunables = { .kib_dev_failover = &dev_failover, diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c index 9f4c64e51b0b..54c0019904ff 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c @@ -22,123 +22,123 @@ #include "socklnd.h" static int sock_timeout = 50; -CFS_MODULE_PARM(sock_timeout, "i", int, 0644, - "dead socket timeout (seconds)"); +module_param(sock_timeout, int, 0644); +MODULE_PARM_DESC(sock_timeout, "dead socket timeout (seconds)"); static int credits = 256; -CFS_MODULE_PARM(credits, "i", int, 0444, - "# concurrent sends"); +module_param(credits, int, 0444); +MODULE_PARM_DESC(credits, "# concurrent sends"); static int peer_credits = 8; -CFS_MODULE_PARM(peer_credits, "i", int, 0444, - "# concurrent sends to 1 peer"); +module_param(peer_credits, int, 0444); +MODULE_PARM_DESC(peer_credits, "# concurrent sends to 1 peer"); static int peer_buffer_credits = 0; -CFS_MODULE_PARM(peer_buffer_credits, "i", int, 0444, - "# per-peer router buffer credits"); +module_param(peer_buffer_credits, int, 0444); +MODULE_PARM_DESC(peer_buffer_credits, "# per-peer router buffer credits"); static int peer_timeout = 180; -CFS_MODULE_PARM(peer_timeout, "i", int, 0444, - "Seconds without aliveness news to declare peer dead (<=0 to disable)"); +module_param(peer_timeout, int, 0444); +MODULE_PARM_DESC(peer_timeout, "Seconds without aliveness news to declare peer dead (<=0 to disable)"); /* Number of daemons in each thread pool which is percpt, * we will estimate reasonable value based on CPUs if it's not set. */ static unsigned int nscheds; -CFS_MODULE_PARM(nscheds, "i", int, 0444, - "# scheduler daemons in each pool while starting"); +module_param(nscheds, int, 0444); +MODULE_PARM_DESC(nscheds, "# scheduler daemons in each pool while starting"); static int nconnds = 4; -CFS_MODULE_PARM(nconnds, "i", int, 0444, - "# connection daemons while starting"); +module_param(nconnds, int, 0444); +MODULE_PARM_DESC(nconnds, "# connection daemons while starting"); static int nconnds_max = 64; -CFS_MODULE_PARM(nconnds_max, "i", int, 0444, - "max # connection daemons"); +module_param(nconnds_max, int, 0444); +MODULE_PARM_DESC(nconnds_max, "max # connection daemons"); static int min_reconnectms = 1000; -CFS_MODULE_PARM(min_reconnectms, "i", int, 0644, - "min connection retry interval (mS)"); +module_param(min_reconnectms, int, 0644); +MODULE_PARM_DESC(min_reconnectms, "min connection retry interval (mS)"); static int max_reconnectms = 60000; -CFS_MODULE_PARM(max_reconnectms, "i", int, 0644, - "max connection retry interval (mS)"); +module_param(max_reconnectms, int, 0644); +MODULE_PARM_DESC(max_reconnectms, "max connection retry interval (mS)"); # define DEFAULT_EAGER_ACK 0 static int eager_ack = DEFAULT_EAGER_ACK; -CFS_MODULE_PARM(eager_ack, "i", int, 0644, - "send tcp ack packets eagerly"); +module_param(eager_ack, int, 0644); +MODULE_PARM_DESC(eager_ack, "send tcp ack packets eagerly"); static int typed_conns = 1; -CFS_MODULE_PARM(typed_conns, "i", int, 0444, - "use different sockets for bulk"); +module_param(typed_conns, int, 0444); +MODULE_PARM_DESC(typed_conns, "use different sockets for bulk"); static int min_bulk = (1<<10); -CFS_MODULE_PARM(min_bulk, "i", int, 0644, - "smallest 'large' message"); +module_param(min_bulk, int, 0644); +MODULE_PARM_DESC(min_bulk, "smallest 'large' message"); # define DEFAULT_BUFFER_SIZE 0 static int tx_buffer_size = DEFAULT_BUFFER_SIZE; -CFS_MODULE_PARM(tx_buffer_size, "i", int, 0644, - "socket tx buffer size (0 for system default)"); +module_param(tx_buffer_size, int, 0644); +MODULE_PARM_DESC(tx_buffer_size, "socket tx buffer size (0 for system default)"); static int rx_buffer_size = DEFAULT_BUFFER_SIZE; -CFS_MODULE_PARM(rx_buffer_size, "i", int, 0644, - "socket rx buffer size (0 for system default)"); +module_param(rx_buffer_size, int, 0644); +MODULE_PARM_DESC(rx_buffer_size, "socket rx buffer size (0 for system default)"); static int nagle = 0; -CFS_MODULE_PARM(nagle, "i", int, 0644, - "enable NAGLE?"); +module_param(nagle, int, 0644); +MODULE_PARM_DESC(nagle, "enable NAGLE?"); static int round_robin = 1; -CFS_MODULE_PARM(round_robin, "i", int, 0644, - "Round robin for multiple interfaces"); +module_param(round_robin, int, 0644); +MODULE_PARM_DESC(round_robin, "Round robin for multiple interfaces"); static int keepalive = 30; -CFS_MODULE_PARM(keepalive, "i", int, 0644, - "# seconds before send keepalive"); +module_param(keepalive, int, 0644); +MODULE_PARM_DESC(keepalive, "# seconds before send keepalive"); static int keepalive_idle = 30; -CFS_MODULE_PARM(keepalive_idle, "i", int, 0644, - "# idle seconds before probe"); +module_param(keepalive_idle, int, 0644); +MODULE_PARM_DESC(keepalive_idle, "# idle seconds before probe"); #define DEFAULT_KEEPALIVE_COUNT 5 static int keepalive_count = DEFAULT_KEEPALIVE_COUNT; -CFS_MODULE_PARM(keepalive_count, "i", int, 0644, - "# missed probes == dead"); +module_param(keepalive_count, int, 0644); +MODULE_PARM_DESC(keepalive_count, "# missed probes == dead"); static int keepalive_intvl = 5; -CFS_MODULE_PARM(keepalive_intvl, "i", int, 0644, - "seconds between probes"); +module_param(keepalive_intvl, int, 0644); +MODULE_PARM_DESC(keepalive_intvl, "seconds between probes"); static int enable_csum = 0; -CFS_MODULE_PARM(enable_csum, "i", int, 0644, - "enable check sum"); +module_param(enable_csum, int, 0644); +MODULE_PARM_DESC(enable_csum, "enable check sum"); static int inject_csum_error = 0; -CFS_MODULE_PARM(inject_csum_error, "i", int, 0644, - "set non-zero to inject a checksum error"); +module_param(inject_csum_error, int, 0644); +MODULE_PARM_DESC(inject_csum_error, "set non-zero to inject a checksum error"); static int nonblk_zcack = 1; -CFS_MODULE_PARM(nonblk_zcack, "i", int, 0644, - "always send ZC-ACK on non-blocking connection"); +module_param(nonblk_zcack, int, 0644); +MODULE_PARM_DESC(nonblk_zcack, "always send ZC-ACK on non-blocking connection"); static unsigned int zc_min_payload = (16 << 10); -CFS_MODULE_PARM(zc_min_payload, "i", int, 0644, - "minimum payload size to zero copy"); +module_param(zc_min_payload, int, 0644); +MODULE_PARM_DESC(zc_min_payload, "minimum payload size to zero copy"); static unsigned int zc_recv = 0; -CFS_MODULE_PARM(zc_recv, "i", int, 0644, - "enable ZC recv for Chelsio driver"); +module_param(zc_recv, int, 0644); +MODULE_PARM_DESC(zc_recv, "enable ZC recv for Chelsio driver"); static unsigned int zc_recv_min_nfrags = 16; -CFS_MODULE_PARM(zc_recv_min_nfrags, "i", int, 0644, - "minimum # of fragments to enable ZC recv"); +module_param(zc_recv_min_nfrags, int, 0644); +MODULE_PARM_DESC(zc_recv_min_nfrags, "minimum # of fragments to enable ZC recv"); #if SOCKNAL_VERSION_DEBUG static int protocol = 3; -CFS_MODULE_PARM(protocol, "i", int, 0644, - "protocol version"); +module_param(protocol, int, 0644); +MODULE_PARM_DESC(protocol, "protocol version"); #endif ksock_tunables_t ksocknal_tunables; diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index 92c60a756644..cb2ecd717714 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -64,14 +64,14 @@ lnet_accept_magic(__u32 magic, __u32 constant) static char *accept = "secure"; -CFS_MODULE_PARM(accept, "s", charp, 0444, - "Accept connections (secure|all|none)"); -CFS_MODULE_PARM(accept_port, "i", int, 0444, - "Acceptor's port (same on all nodes)"); -CFS_MODULE_PARM(accept_backlog, "i", int, 0444, - "Acceptor's listen backlog"); -CFS_MODULE_PARM(accept_timeout, "i", int, 0644, - "Acceptor's timeout (seconds)"); +module_param(accept, charp, 0444); +MODULE_PARM_DESC(accept, "Accept connections (secure|all|none)"); +module_param(accept_port, int, 0444); +MODULE_PARM_DESC(accept_port, "Acceptor's port (same on all nodes)"); +module_param(accept_backlog, int, 0444); +MODULE_PARM_DESC(accept_backlog, "Acceptor's listen backlog"); +module_param(accept_timeout, int, 0644); +MODULE_PARM_DESC(accept_timeout, "Acceptor's timeout (seconds)"); static char *accept_type; diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 160a4292c6ce..5719959c8005 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -45,20 +45,20 @@ EXPORT_SYMBOL(the_lnet); static char *ip2nets = ""; -CFS_MODULE_PARM(ip2nets, "s", charp, 0444, - "LNET network <- IP table"); +module_param(ip2nets, charp, 0444); +MODULE_PARM_DESC(ip2nets, "LNET network <- IP table"); static char *networks = ""; -CFS_MODULE_PARM(networks, "s", charp, 0444, - "local networks"); +module_param(networks, charp, 0444); +MODULE_PARM_DESC(networks, "local networks"); static char *routes = ""; -CFS_MODULE_PARM(routes, "s", charp, 0444, - "routes to non-local networks"); +module_param(routes, charp, 0444); +MODULE_PARM_DESC(routes, "routes to non-local networks"); static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT; -CFS_MODULE_PARM(rnet_htable_size, "i", int, 0444, - "size of remote network hash table"); +module_param(rnet_htable_size, int, 0444); +MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table"); char * lnet_get_routes(void) diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index b6f8ad38628b..2d611136da8f 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -43,8 +43,8 @@ #include static int local_nid_dist_zero = 1; -CFS_MODULE_PARM(local_nid_dist_zero, "i", int, 0444, - "Reserved"); +module_param(local_nid_dist_zero, int, 0444); +MODULE_PARM_DESC(local_nid_dist_zero, "Reserved"); int lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index 9b9e7d3139b0..6fffd5e96f9c 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -40,8 +40,8 @@ /* NB: add /proc interfaces in upcoming patches */ int portal_rotor = LNET_PTL_ROTOR_HASH_RT; -CFS_MODULE_PARM(portal_rotor, "i", int, 0644, - "redirect PUTs to different cpu-partitions"); +module_param(portal_rotor, int, 0644); +MODULE_PARM_DESC(portal_rotor, "redirect PUTs to different cpu-partitions"); static int lnet_ptl_match_type(unsigned int index, lnet_process_id_t match_id, diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index 6db8774ff7b7..3bd42a485a32 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -38,8 +38,8 @@ #include static int config_on_load; -CFS_MODULE_PARM(config_on_load, "i", int, 0444, - "configure network at module load"); +module_param(config_on_load, int, 0444); +MODULE_PARM_DESC(config_on_load, "configure network at module load"); static struct mutex lnet_config_mutex; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index a326ce06bc76..80b5ed1e9d64 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -34,25 +34,25 @@ #define LNET_NRB_LARGE (LNET_NRB_LARGE_MIN * 4) static char *forwarding = ""; -CFS_MODULE_PARM(forwarding, "s", charp, 0444, - "Explicitly enable/disable forwarding between networks"); +module_param(forwarding, charp, 0444); +MODULE_PARM_DESC(forwarding, "Explicitly enable/disable forwarding between networks"); static int tiny_router_buffers; -CFS_MODULE_PARM(tiny_router_buffers, "i", int, 0444, - "# of 0 payload messages to buffer in the router"); +module_param(tiny_router_buffers, int, 0444); +MODULE_PARM_DESC(tiny_router_buffers, "# of 0 payload messages to buffer in the router"); static int small_router_buffers; -CFS_MODULE_PARM(small_router_buffers, "i", int, 0444, - "# of small (1 page) messages to buffer in the router"); +module_param(small_router_buffers, int, 0444); +MODULE_PARM_DESC(small_router_buffers, "# of small (1 page) messages to buffer in the router"); static int large_router_buffers; -CFS_MODULE_PARM(large_router_buffers, "i", int, 0444, - "# of large messages to buffer in the router"); +module_param(large_router_buffers, int, 0444); +MODULE_PARM_DESC(large_router_buffers, "# of large messages to buffer in the router"); static int peer_buffer_credits = 0; -CFS_MODULE_PARM(peer_buffer_credits, "i", int, 0444, - "# router buffer credits per peer"); +module_param(peer_buffer_credits, int, 0444); +MODULE_PARM_DESC(peer_buffer_credits, "# router buffer credits per peer"); static int auto_down = 1; -CFS_MODULE_PARM(auto_down, "i", int, 0444, - "Automatically mark peers down on comms error"); +module_param(auto_down, int, 0444); +MODULE_PARM_DESC(auto_down, "Automatically mark peers down on comms error"); int lnet_peer_buffer_credits(lnet_ni_t *ni) @@ -81,24 +81,24 @@ lnet_peer_buffer_credits(lnet_ni_t *ni) #endif static int check_routers_before_use = 0; -CFS_MODULE_PARM(check_routers_before_use, "i", int, 0444, - "Assume routers are down and ping them before use"); +module_param(check_routers_before_use, int, 0444); +MODULE_PARM_DESC(check_routers_before_use, "Assume routers are down and ping them before use"); static int avoid_asym_router_failure = 1; -CFS_MODULE_PARM(avoid_asym_router_failure, "i", int, 0644, - "Avoid asymmetrical router failures (0 to disable)"); +module_param(avoid_asym_router_failure, int, 0644); +MODULE_PARM_DESC(avoid_asym_router_failure, "Avoid asymmetrical router failures (0 to disable)"); static int dead_router_check_interval = 60; -CFS_MODULE_PARM(dead_router_check_interval, "i", int, 0644, - "Seconds between dead router health checks (<= 0 to disable)"); +module_param(dead_router_check_interval, int, 0644); +MODULE_PARM_DESC(dead_router_check_interval, "Seconds between dead router health checks (<= 0 to disable)"); static int live_router_check_interval = 60; -CFS_MODULE_PARM(live_router_check_interval, "i", int, 0644, - "Seconds between live router health checks (<= 0 to disable)"); +module_param(live_router_check_interval, int, 0644); +MODULE_PARM_DESC(live_router_check_interval, "Seconds between live router health checks (<= 0 to disable)"); static int router_ping_timeout = 50; -CFS_MODULE_PARM(router_ping_timeout, "i", int, 0644, - "Seconds to wait for the reply to a router health query"); +module_param(router_ping_timeout, int, 0644); +MODULE_PARM_DESC(router_ping_timeout, "Seconds to wait for the reply to a router health query"); int lnet_peers_start_down(void) diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index b7613c828e76..3f8020cb93e6 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -41,11 +41,12 @@ #include "selftest.h" static int brw_srv_workitems = SFW_TEST_WI_MAX; -CFS_MODULE_PARM(brw_srv_workitems, "i", int, 0644, "# BRW server workitems"); +module_param(brw_srv_workitems, int, 0644); +MODULE_PARM_DESC(brw_srv_workitems, "# BRW server workitems"); static int brw_inject_errors; -CFS_MODULE_PARM(brw_inject_errors, "i", int, 0644, - "# data errors to inject randomly, zero by default"); +module_param(brw_inject_errors, int, 0644); +MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by default"); static void brw_client_fini(sfw_test_instance_t *tsi) diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 483c78564dae..050723a0243a 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -46,12 +46,12 @@ lst_sid_t LST_INVALID_SID = {LNET_NID_ANY, -1}; static int session_timeout = 100; -CFS_MODULE_PARM(session_timeout, "i", int, 0444, - "test session timeout in seconds (100 by default, 0 == never)"); +module_param(session_timeout, int, 0444); +MODULE_PARM_DESC(session_timeout, "test session timeout in seconds (100 by default, 0 == never)"); static int rpc_timeout = 64; -CFS_MODULE_PARM(rpc_timeout, "i", int, 0644, - "rpc timeout in seconds (64 by default, 0 == never)"); +module_param(rpc_timeout, int, 0644); +MODULE_PARM_DESC(rpc_timeout, "rpc timeout in seconds (64 by default, 0 == never)"); #define sfw_unpack_id(id) \ do { \ diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index f0f919482b56..a37c3ff03277 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -45,7 +45,8 @@ #define LST_PING_TEST_MAGIC 0xbabeface int ping_srv_workitems = SFW_TEST_WI_MAX; -CFS_MODULE_PARM(ping_srv_workitems, "i", int, 0644, "# PING server workitems"); +module_param(ping_srv_workitems, int, 0644); +MODULE_PARM_DESC(ping_srv_workitems, "# PING server workitems"); typedef struct { spinlock_t pnd_lock; /* serialize */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 40c58b7ae2ff..bbf42914b765 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -49,12 +49,12 @@ #include "ldlm_internal.h" static int ldlm_num_threads; -CFS_MODULE_PARM(ldlm_num_threads, "i", int, 0444, - "number of DLM service threads to start"); +module_param(ldlm_num_threads, int, 0444); +MODULE_PARM_DESC(ldlm_num_threads, "number of DLM service threads to start"); static char *ldlm_cpts; -CFS_MODULE_PARM(ldlm_cpts, "s", charp, 0444, - "CPU partitions ldlm threads should run on"); +module_param(ldlm_cpts, charp, 0444); +MODULE_PARM_DESC(ldlm_cpts, "CPU partitions ldlm threads should run on"); extern struct kmem_cache *ldlm_resource_slab; extern struct kmem_cache *ldlm_lock_slab; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 1ddcca34bb79..4974becb3d9b 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -68,8 +68,8 @@ #include "ldlm_internal.h" int ldlm_enqueue_min = OBD_TIMEOUT_DEFAULT; -CFS_MODULE_PARM(ldlm_enqueue_min, "i", int, 0644, - "lock enqueue timeout minimum"); +module_param(ldlm_enqueue_min, int, 0644); +MODULE_PARM_DESC(ldlm_enqueue_min, "lock enqueue timeout minimum"); /* in client side, whether the cached locks will be canceled before replay */ unsigned int ldlm_cancel_unused_locks_before_replay = 1; diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index 9b9c45116eee..f30c84f195aa 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -47,44 +47,44 @@ static char debug_file_name[1024]; unsigned int libcfs_subsystem_debug = ~0; -CFS_MODULE_PARM(libcfs_subsystem_debug, "i", int, 0644, - "Lustre kernel debug subsystem mask"); +module_param(libcfs_subsystem_debug, int, 0644); +MODULE_PARM_DESC(libcfs_subsystem_debug, "Lustre kernel debug subsystem mask"); EXPORT_SYMBOL(libcfs_subsystem_debug); unsigned int libcfs_debug = (D_CANTMASK | D_NETERROR | D_HA | D_CONFIG | D_IOCTL); -CFS_MODULE_PARM(libcfs_debug, "i", int, 0644, - "Lustre kernel debug mask"); +module_param(libcfs_debug, int, 0644); +MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask"); EXPORT_SYMBOL(libcfs_debug); unsigned int libcfs_debug_mb = 0; -CFS_MODULE_PARM(libcfs_debug_mb, "i", uint, 0644, - "Total debug buffer size."); +module_param(libcfs_debug_mb, uint, 0644); +MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); EXPORT_SYMBOL(libcfs_debug_mb); unsigned int libcfs_printk = D_CANTMASK; -CFS_MODULE_PARM(libcfs_printk, "i", uint, 0644, - "Lustre kernel debug console mask"); +module_param(libcfs_printk, uint, 0644); +MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask"); EXPORT_SYMBOL(libcfs_printk); unsigned int libcfs_console_ratelimit = 1; -CFS_MODULE_PARM(libcfs_console_ratelimit, "i", uint, 0644, - "Lustre kernel debug console ratelimit (0 to disable)"); +module_param(libcfs_console_ratelimit, uint, 0644); +MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)"); EXPORT_SYMBOL(libcfs_console_ratelimit); unsigned int libcfs_console_max_delay; -CFS_MODULE_PARM(libcfs_console_max_delay, "l", uint, 0644, - "Lustre kernel debug console max delay (jiffies)"); +module_param(libcfs_console_max_delay, uint, 0644); +MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)"); EXPORT_SYMBOL(libcfs_console_max_delay); unsigned int libcfs_console_min_delay; -CFS_MODULE_PARM(libcfs_console_min_delay, "l", uint, 0644, - "Lustre kernel debug console min delay (jiffies)"); +module_param(libcfs_console_min_delay, uint, 0644); +MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)"); EXPORT_SYMBOL(libcfs_console_min_delay); unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF; -CFS_MODULE_PARM(libcfs_console_backoff, "i", uint, 0644, - "Lustre kernel debug console backoff factor"); +module_param(libcfs_console_backoff, uint, 0644); +MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor"); EXPORT_SYMBOL(libcfs_console_backoff); unsigned int libcfs_debug_binary = 1; @@ -103,8 +103,8 @@ unsigned int libcfs_watchdog_ratelimit = 300; EXPORT_SYMBOL(libcfs_watchdog_ratelimit); unsigned int libcfs_panic_on_lbug = 1; -CFS_MODULE_PARM(libcfs_panic_on_lbug, "i", uint, 0644, - "Lustre kernel panic on LBUG"); +module_param(libcfs_panic_on_lbug, uint, 0644); +MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG"); EXPORT_SYMBOL(libcfs_panic_on_lbug); atomic_t libcfs_kmemory = ATOMIC_INIT(0); @@ -116,9 +116,9 @@ char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT; /* We need to pass a pointer here, but elsewhere this must be a const */ char *libcfs_debug_file_path; -CFS_MODULE_PARM(libcfs_debug_file_path, "s", charp, 0644, - "Path for dumping debug logs, " - "set 'NONE' to prevent log dumping"); +module_param(libcfs_debug_file_path, charp, 0644); +MODULE_PARM_DESC(libcfs_debug_file_path, + "Path for dumping debug logs, set 'NONE' to prevent log dumping"); int libcfs_panic_in_progress; diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c index e3e0578b27f9..85cbe91c29b9 100644 --- a/drivers/staging/lustre/lustre/libcfs/hash.c +++ b/drivers/staging/lustre/lustre/libcfs/hash.c @@ -112,8 +112,8 @@ #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 static unsigned int warn_on_depth = 8; -CFS_MODULE_PARM(warn_on_depth, "i", uint, 0644, - "warning when hash depth is high."); +module_param(warn_on_depth, uint, 0644); +MODULE_PARM_DESC(warn_on_depth, "warning when hash depth is high."); #endif struct cfs_wi_sched *cfs_sched_rehash; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c index 00ab8fdc1053..58bb256ee047 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c @@ -47,7 +47,8 @@ * >1 : specify number of partitions */ static int cpu_npartitions; -CFS_MODULE_PARM(cpu_npartitions, "i", int, 0444, "# of CPU partitions"); +module_param(cpu_npartitions, int, 0444); +MODULE_PARM_DESC(cpu_npartitions, "# of CPU partitions"); /** * modparam for setting CPU partitions patterns: @@ -61,7 +62,8 @@ CFS_MODULE_PARM(cpu_npartitions, "i", int, 0444, "# of CPU partitions"); * NB: If user specified cpu_pattern, cpu_npartitions will be ignored */ static char *cpu_pattern = ""; -CFS_MODULE_PARM(cpu_pattern, "s", charp, 0444, "CPU partitions pattern"); +module_param(cpu_pattern, charp, 0444); +MODULE_PARM_DESC(cpu_pattern, "CPU partitions pattern"); struct cfs_cpt_data { /* serialize hotplug etc */ diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index e2421ea61352..5338e8d4c50f 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -856,7 +856,8 @@ static void lloop_exit(void) module_init(lloop_init); module_exit(lloop_exit); -CFS_MODULE_PARM(max_loop, "i", int, 0444, "maximum of lloop_device"); +module_param(max_loop, int, 0444); +MODULE_PARM_DESC(max_loop, "maximum of lloop_device"); MODULE_AUTHOR("Sun Microsystems, Inc. "); MODULE_DESCRIPTION("Lustre virtual block device"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 02d76f8dbcb9..0f0750beab3b 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -49,8 +49,8 @@ #if defined(LPROCFS) static int lprocfs_no_percpu_stats = 0; -CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644, - "Do not alloc percpu data for lprocfs stats"); +module_param(lprocfs_no_percpu_stats, int, 0644); +MODULE_PARM_DESC(lprocfs_no_percpu_stats, "Do not alloc percpu data for lprocfs stats"); #define MAX_STRING_SIZE 128 diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 212823ab937b..d61b0dbe6ab6 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -830,8 +830,8 @@ enum { }; static unsigned int lu_cache_percent = LU_CACHE_PERCENT_DEFAULT; -CFS_MODULE_PARM(lu_cache_percent, "i", int, 0644, - "Percentage of memory to be used as lu_object cache"); +module_param(lu_cache_percent, int, 0644); +MODULE_PARM_DESC(lu_cache_percent, "Percentage of memory to be used as lu_object cache"); /** * Return desired hash table order. diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index a084eb1b1aca..1707e61c6f0c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -45,7 +45,8 @@ #include "ptlrpc_internal.h" static int suppress_pings; -CFS_MODULE_PARM(suppress_pings, "i", int, 0644, "Suppress pings"); +module_param(suppress_pings, int, 0644); +MODULE_PARM_DESC(suppress_pings, "Suppress pings"); struct mutex pinger_mutex; static LIST_HEAD(pinger_imports); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 89c9be96f454..2ebdb1b06dde 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -77,12 +77,12 @@ struct ptlrpcd { }; static int max_ptlrpcds; -CFS_MODULE_PARM(max_ptlrpcds, "i", int, 0644, - "Max ptlrpcd thread count to be started."); +module_param(max_ptlrpcds, int, 0644); +MODULE_PARM_DESC(max_ptlrpcds, "Max ptlrpcd thread count to be started."); static int ptlrpcd_bind_policy = PDB_POLICY_PAIR; -CFS_MODULE_PARM(ptlrpcd_bind_policy, "i", int, 0644, - "Ptlrpcd threads binding mode."); +module_param(ptlrpcd_bind_policy, int, 0644); +MODULE_PARM_DESC(ptlrpcd_bind_policy, "Ptlrpcd threads binding mode."); static struct ptlrpcd *ptlrpcds; struct mutex ptlrpcd_mutex; diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 2b10d6dea2d9..590fa8df8b7f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -44,19 +44,19 @@ /* The following are visible and mutable through /sys/module/ptlrpc */ int test_req_buffer_pressure = 0; -CFS_MODULE_PARM(test_req_buffer_pressure, "i", int, 0444, - "set non-zero to put pressure on request buffer pools"); -CFS_MODULE_PARM(at_min, "i", int, 0644, - "Adaptive timeout minimum (sec)"); -CFS_MODULE_PARM(at_max, "i", int, 0644, - "Adaptive timeout maximum (sec)"); -CFS_MODULE_PARM(at_history, "i", int, 0644, - "Adaptive timeouts remember the slowest event that took place " - "within this period (sec)"); -CFS_MODULE_PARM(at_early_margin, "i", int, 0644, - "How soon before an RPC deadline to send an early reply"); -CFS_MODULE_PARM(at_extra, "i", int, 0644, - "How much extra time to give with each early reply"); +module_param(test_req_buffer_pressure, int, 0444); +MODULE_PARM_DESC(test_req_buffer_pressure, "set non-zero to put pressure on request buffer pools"); +module_param(at_min, int, 0644); +MODULE_PARM_DESC(at_min, "Adaptive timeout minimum (sec)"); +module_param(at_max, int, 0644); +MODULE_PARM_DESC(at_max, "Adaptive timeout maximum (sec)"); +module_param(at_history, int, 0644); +MODULE_PARM_DESC(at_history, + "Adaptive timeouts remember the slowest event that took place within this period (sec)"); +module_param(at_early_margin, int, 0644); +MODULE_PARM_DESC(at_early_margin, "How soon before an RPC deadline to send an early reply"); +module_param(at_extra, int, 0644); +MODULE_PARM_DESC(at_extra, "How much extra time to give with each early reply"); /* forward ref */ -- cgit v1.2.3 From 76d791a07580d5ce07a2229e83e8f9bee924f4dd Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:28:31 +0800 Subject: staging/lustre/libcfs: remove LI_POISON The extactly same definition exitst in lustre_lib.h. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 8cab09c1f41d..5cc7ba000485 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -70,16 +70,6 @@ #include -/* ------------------------------------------------------------------ */ - -# define LI_POISON 0x5a5a5a5a -#if BITS_PER_LONG > 32 -# define LL_POISON 0x5a5a5a5a5a5a5a5aL -#else -# define LL_POISON 0x5a5a5a5aL -#endif -# define LP_POISON ((void *)LL_POISON) - /* this is a bit chunky */ # define LPU64 "%llu" -- cgit v1.2.3 From e780e3de6d67abb16edec6f88f1651bf19b7ec81 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 21 Nov 2013 22:42:46 +0800 Subject: staging/lustre/obdclass: add empty tailing member to ctl_table This was mistakenly removed by commit 7fb3d1c5. Now register_sysctl_table() complains about "No proc_handler". Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index d66be020983d..c1ef0c9b5a1a 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -392,7 +392,8 @@ static ctl_table_t obd_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_at_history - } + }, + {} }; static ctl_table_t parent_table[] = { @@ -402,7 +403,8 @@ static ctl_table_t parent_table[] = { .maxlen = 0, .mode = 0555, .child = obd_table - } + }, + {} }; #endif -- cgit v1.2.3 From c47b0a34538dcbabb8aface7b4397148e6e24f17 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 24 Nov 2013 11:51:49 +0000 Subject: staging: vt6656: Remove always 0 variable dwDiagRefCount Remove > 0 code. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/channel.c | 3 +-- drivers/staging/vt6656/device.h | 1 - drivers/staging/vt6656/rf.c | 3 --- drivers/staging/vt6656/rxtx.c | 56 ++++++++++++++-------------------------- drivers/staging/vt6656/wcmd.c | 2 -- 5 files changed, 21 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index e430b35463b6..5a4fa0e2581b 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -423,8 +423,7 @@ void CHvInitChannelTable(struct vnt_private *pDevice) break; } - if ((pDevice->dwDiagRefCount != 0) || - (pDevice->b11hEable == true)) { + if (pDevice->b11hEable == true) { if (bMultiBand == true) { for (ii = 0; ii < CB_MAX_CHANNEL; ii++) { sChannelTbl[ii+1].bValid = true; diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index b7a6e14e4d9f..ec8acbd4abaa 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -697,7 +697,6 @@ struct vnt_private { u8 byBBPreEDIndex; int bRadioCmd; - u32 dwDiagRefCount; /* For FOE Tuning */ u8 byFOETuning; diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index e545232f670b..1e8f64bff03c 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -740,9 +740,6 @@ int RFbSetPower(struct vnt_private *priv, u32 rate, u32 channel) int ret = true; u8 power = priv->byCCKPwr; - if (priv->dwDiagRefCount) - return true; - if (channel == 0) return -EINVAL; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 5601331708f3..a95575fdd408 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -978,28 +978,19 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, bSoftWEP = true; /* WEP 256 */ } - // Get pkt type - if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) { - if (pDevice->dwDiagRefCount == 0) { - cb802_1_H_len = 8; - } else { - cb802_1_H_len = 2; - } - } else { - cb802_1_H_len = 0; - } + /* Get pkt type */ + if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) + cb802_1_H_len = 8; + else + cb802_1_H_len = 0; cbFrameBodySize = uSkbPacketLen - ETH_HLEN + cb802_1_H_len; //Set packet type pTxBufHead->wFIFOCtl |= (u16)(byPktType<<8); - if (pDevice->dwDiagRefCount != 0) { - bNeedACK = false; - pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); - } else { //if (pDevice->dwDiagRefCount != 0) { if ((pDevice->eOPMode == OP_MODE_ADHOC) || - (pDevice->eOPMode == OP_MODE_AP)) { + (pDevice->eOPMode == OP_MODE_AP)) { if (is_multicast_ether_addr(psEthHeader->h_dest)) { bNeedACK = false; pTxBufHead->wFIFOCtl = @@ -1008,13 +999,11 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, bNeedACK = true; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; } - } - else { - // MSDUs in Infra mode always need ACK - bNeedACK = true; - pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; - } - } //if (pDevice->dwDiagRefCount != 0) { + } else { + /* MSDUs in Infra mode always need ACK */ + bNeedACK = true; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + } pTxBufHead->wTimeStamp = DEFAULT_MSDU_LIFETIME_RES_64us; @@ -1183,24 +1172,19 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, } } - // 802.1H - if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) { - if (pDevice->dwDiagRefCount == 0) { + /* 802.1H */ + if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) { if ((psEthHeader->h_proto == cpu_to_be16(ETH_P_IPX)) || - (psEthHeader->h_proto == cpu_to_le16(0xF380))) { + (psEthHeader->h_proto == cpu_to_le16(0xF380))) memcpy((u8 *) (pbyPayloadHead), - abySNAP_Bridgetunnel, 6); - } else { - memcpy((u8 *) (pbyPayloadHead), &abySNAP_RFC1042[0], 6); - } - pbyType = (u8 *) (pbyPayloadHead + 6); - memcpy(pbyType, &(psEthHeader->h_proto), sizeof(u16)); - } else { - memcpy((u8 *) (pbyPayloadHead), &(psEthHeader->h_proto), sizeof(u16)); + abySNAP_Bridgetunnel, 6); + else + memcpy((u8 *) (pbyPayloadHead), &abySNAP_RFC1042[0], 6); - } + pbyType = (u8 *) (pbyPayloadHead + 6); - } + memcpy(pbyType, &(psEthHeader->h_proto), sizeof(u16)); + } if (pPacket != NULL) { // Copy the Packet into a tx Buffer diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 2d05ccb58a7a..6b9522914634 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -283,8 +283,6 @@ void vRunCommand(struct work_struct *work) if (pDevice->Flags & fMP_DISCONNECTED) return; - if (pDevice->dwDiagRefCount != 0) - return; if (pDevice->bCmdRunning != true) return; -- cgit v1.2.3 From c7c57b24a5411c5314686a7916971e57adeded7d Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 24 Nov 2013 13:25:25 +0000 Subject: staging: vt6656: csBeacon_xmit merge structures. Merge structures typedef struct tagSTxShortBufHead and the members of struct vnt_tx_datahead_ab to form single structure vnt_tx_short_buf_head. Remove the duplicate members in struct vnt_beacon_buffer already in typedef struct tagSTxShortBufHead. This removes the need for any pointer arithmetic. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/desc.h | 8 ------ drivers/staging/vt6656/rxtx.c | 61 +++++++++++++++++++++---------------------- drivers/staging/vt6656/rxtx.h | 11 ++++++-- 3 files changed, 39 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h index afe7074c3037..7c6dd5f52295 100644 --- a/drivers/staging/vt6656/desc.h +++ b/drivers/staging/vt6656/desc.h @@ -146,14 +146,6 @@ /* * TX FIFO header */ - -typedef struct tagSTxShortBufHead { - u16 wFIFOCtl; - u16 wTimeStamp; -} __attribute__ ((__packed__)) -STxShortBufHead, *PSTxShortBufHead; -typedef const STxShortBufHead *PCSTxShortBufHead; - typedef struct tagSBEACONCtl { u32 BufReady:1; u32 TSF:15; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index a95575fdd408..a45604a4f81c 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1643,12 +1643,10 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, struct vnt_tx_mgmt *pPacket) { struct vnt_beacon_buffer *pTX_Buffer; + struct vnt_tx_short_buf_head *short_head; u32 cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; u32 cbHeaderSize = 0; - u16 wTxBufSize = sizeof(STxShortBufHead); - PSTxShortBufHead pTxBufHead; struct ieee80211_hdr *pMACHeader; - struct vnt_tx_datahead_ab *pTxDataHead; u16 wCurrentRate; u32 cbFrameBodySize; u32 cbReqCount; @@ -1664,39 +1662,40 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, } pTX_Buffer = (struct vnt_beacon_buffer *)&pContext->Data[0]; - pbyTxBufferAddr = (u8 *)&(pTX_Buffer->wFIFOCtl); + short_head = &pTX_Buffer->short_head; + pbyTxBufferAddr = (u8 *)&short_head->fifo_ctl; cbFrameBodySize = pPacket->cbPayloadLen; - pTxBufHead = (PSTxShortBufHead) pbyTxBufferAddr; - wTxBufSize = sizeof(STxShortBufHead); + cbHeaderSize = sizeof(struct vnt_tx_short_buf_head); - if (pDevice->byBBType == BB_TYPE_11A) { - wCurrentRate = RATE_6M; - pTxDataHead = (struct vnt_tx_datahead_ab *) - (pbyTxBufferAddr + wTxBufSize); - //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A, - &pTxDataHead->ab); - //Get Duration and TimeStampOff - pTxDataHead->wDuration = s_uGetDataDuration(pDevice, - PK_TYPE_11A, false); - pTxDataHead->wTimeStampOff = vnt_time_stamp_off(pDevice, wCurrentRate); - cbHeaderSize = wTxBufSize + sizeof(struct vnt_tx_datahead_ab); - } else { - wCurrentRate = RATE_1M; - pTxBufHead->wFIFOCtl |= FIFOCTL_11B; - pTxDataHead = (struct vnt_tx_datahead_ab *) - (pbyTxBufferAddr + wTxBufSize); - //Get SignalField,ServiceField,Length - BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B, - &pTxDataHead->ab); - //Get Duration and TimeStampOff - pTxDataHead->wDuration = s_uGetDataDuration(pDevice, + if (pDevice->byBBType == BB_TYPE_11A) { + wCurrentRate = RATE_6M; + + /* Get SignalField,ServiceField,Length */ + BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, + PK_TYPE_11A, &short_head->ab); + + /* Get Duration and TimeStampOff */ + short_head->duration = s_uGetDataDuration(pDevice, + PK_TYPE_11A, false); + short_head->time_stamp_off = + vnt_time_stamp_off(pDevice, wCurrentRate); + } else { + wCurrentRate = RATE_1M; + short_head->fifo_ctl |= FIFOCTL_11B; + + /* Get SignalField,ServiceField,Length */ + BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, + PK_TYPE_11B, &short_head->ab); + + /* Get Duration and TimeStampOff */ + short_head->duration = s_uGetDataDuration(pDevice, PK_TYPE_11B, false); - pTxDataHead->wTimeStampOff = vnt_time_stamp_off(pDevice, wCurrentRate); - cbHeaderSize = wTxBufSize + sizeof(struct vnt_tx_datahead_ab); - } + short_head->time_stamp_off = + vnt_time_stamp_off(pDevice, wCurrentRate); + } + //Generate Beacon Header pMACHeader = (struct ieee80211_hdr *)(pbyTxBufferAddr + cbHeaderSize); diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h index eecbe890027e..bb21ad6ae226 100644 --- a/drivers/staging/vt6656/rxtx.h +++ b/drivers/staging/vt6656/rxtx.h @@ -230,12 +230,19 @@ struct vnt_tx_buffer { union vnt_tx_head tx_head; } __packed; +struct vnt_tx_short_buf_head { + u16 fifo_ctl; + u16 time_stamp; + struct vnt_phy_field ab; + u16 duration; + u16 time_stamp_off; +} __packed; + struct vnt_beacon_buffer { u8 byType; u8 byPKTNO; u16 wTxByteCount; - u16 wFIFOCtl; - u16 wTimeStamp; + struct vnt_tx_short_buf_head short_head; } __packed; void vDMA0_tx_80211(struct vnt_private *, struct sk_buff *skb); -- cgit v1.2.3 From 0b71fe36c5fc6546ee6cd60bce2ba78a94f96353 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 24 Nov 2013 13:27:32 +0000 Subject: staging: vt6656: vnt_beacon_buffer attach mac header. Attach ieee80211_hdr to vnt_beacon_buffer and remove pointer arithmetic. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 19 +++++++++---------- drivers/staging/vt6656/rxtx.h | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index a45604a4f81c..723a8de3a466 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1650,7 +1650,6 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, u16 wCurrentRate; u32 cbFrameBodySize; u32 cbReqCount; - u8 *pbyTxBufferAddr; struct vnt_usb_send_context *pContext; CMD_STATUS status; @@ -1663,7 +1662,6 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, pTX_Buffer = (struct vnt_beacon_buffer *)&pContext->Data[0]; short_head = &pTX_Buffer->short_head; - pbyTxBufferAddr = (u8 *)&short_head->fifo_ctl; cbFrameBodySize = pPacket->cbPayloadLen; @@ -1697,15 +1695,16 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, } - //Generate Beacon Header - pMACHeader = (struct ieee80211_hdr *)(pbyTxBufferAddr + cbHeaderSize); - memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); + /* Generate Beacon Header */ + pMACHeader = &pTX_Buffer->hdr; - pMACHeader->duration_id = 0; - pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); - pDevice->wSeqCounter++ ; - if (pDevice->wSeqCounter > 0x0fff) - pDevice->wSeqCounter = 0; + memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); + + pMACHeader->duration_id = 0; + pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; cbReqCount = cbHeaderSize + WLAN_HDR_ADDR3_LEN + cbFrameBodySize; diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h index bb21ad6ae226..b3ee6d01aa88 100644 --- a/drivers/staging/vt6656/rxtx.h +++ b/drivers/staging/vt6656/rxtx.h @@ -243,6 +243,7 @@ struct vnt_beacon_buffer { u8 byPKTNO; u16 wTxByteCount; struct vnt_tx_short_buf_head short_head; + struct ieee80211_hdr hdr; } __packed; void vDMA0_tx_80211(struct vnt_private *, struct sk_buff *skb); -- cgit v1.2.3 From 8a76714dd3755536a28f0d0b9c5fc378c492da40 Mon Sep 17 00:00:00 2001 From: Adam Lee Date: Mon, 25 Nov 2013 15:07:36 +0800 Subject: staging: ft1000: fix uninitialized return variable in request_code_segment The return variable of request_code_segment() is used uninitialized if the argument boot_case is false, this patch fixes it. FYI, in ft1000_usb.h: STATUS_SUCCESS 0, and STATUS_FAILURE 0x1001. Signed-off-by: Adam Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_download.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index 3c2b085e7990..2c216a56891a 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -601,11 +601,11 @@ static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file, status = write_blk(ft1000dev, s_file, c_file, word_length); /*DEBUG("write_blk returned %d\n", status); */ } else { - write_blk_fifo(ft1000dev, s_file, c_file, word_length); + status = write_blk_fifo(ft1000dev, s_file, c_file, word_length); if (ft1000dev->usbboot == 0) ft1000dev->usbboot++; if (ft1000dev->usbboot == 1) - ft1000_write_dpram16(ft1000dev, + status |= ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_PS_HDR_LOC, 0, 0); } return status; -- cgit v1.2.3 From fa590c222fbaa428edb2ce2194638906cea1400a Mon Sep 17 00:00:00 2001 From: Micky Ching Date: Tue, 12 Nov 2013 17:16:08 +0800 Subject: staging: rts5208: add support for rts5208 and rts5288 There are still many rts5208/5288 card readers being used, but no drivers are supported them in kernel now. This driver can make a great convenience for people who use them. Many other rts-series card reader are supported by mfd driver, but due to much difference with others, rts5208/5288 can not add into mfd driver pretty now, so we provide a separated driver here to support the device. Signed-off-by: Micky Ching Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/rts5208/Kconfig | 15 + drivers/staging/rts5208/Makefile | 6 + drivers/staging/rts5208/TODO | 7 + drivers/staging/rts5208/debug.h | 43 + drivers/staging/rts5208/general.c | 35 + drivers/staging/rts5208/general.h | 31 + drivers/staging/rts5208/ms.c | 4208 +++++++++++++++++++++++++++ drivers/staging/rts5208/ms.h | 227 ++ drivers/staging/rts5208/rtsx.c | 1069 +++++++ drivers/staging/rts5208/rtsx.h | 186 ++ drivers/staging/rts5208/rtsx_card.c | 1126 ++++++++ drivers/staging/rts5208/rtsx_card.h | 1098 ++++++++ drivers/staging/rts5208/rtsx_chip.c | 1979 +++++++++++++ drivers/staging/rts5208/rtsx_chip.h | 1002 +++++++ drivers/staging/rts5208/rtsx_scsi.c | 3370 ++++++++++++++++++++++ drivers/staging/rts5208/rtsx_scsi.h | 143 + drivers/staging/rts5208/rtsx_sys.h | 50 + drivers/staging/rts5208/rtsx_transport.c | 769 +++++ drivers/staging/rts5208/rtsx_transport.h | 66 + drivers/staging/rts5208/sd.c | 4525 ++++++++++++++++++++++++++++++ drivers/staging/rts5208/sd.h | 301 ++ drivers/staging/rts5208/spi.c | 877 ++++++ drivers/staging/rts5208/spi.h | 65 + drivers/staging/rts5208/trace.h | 93 + drivers/staging/rts5208/xd.c | 2088 ++++++++++++++ drivers/staging/rts5208/xd.h | 188 ++ 28 files changed, 23570 insertions(+) create mode 100644 drivers/staging/rts5208/Kconfig create mode 100644 drivers/staging/rts5208/Makefile create mode 100644 drivers/staging/rts5208/TODO create mode 100644 drivers/staging/rts5208/debug.h create mode 100644 drivers/staging/rts5208/general.c create mode 100644 drivers/staging/rts5208/general.h create mode 100644 drivers/staging/rts5208/ms.c create mode 100644 drivers/staging/rts5208/ms.h create mode 100644 drivers/staging/rts5208/rtsx.c create mode 100644 drivers/staging/rts5208/rtsx.h create mode 100644 drivers/staging/rts5208/rtsx_card.c create mode 100644 drivers/staging/rts5208/rtsx_card.h create mode 100644 drivers/staging/rts5208/rtsx_chip.c create mode 100644 drivers/staging/rts5208/rtsx_chip.h create mode 100644 drivers/staging/rts5208/rtsx_scsi.c create mode 100644 drivers/staging/rts5208/rtsx_scsi.h create mode 100644 drivers/staging/rts5208/rtsx_sys.h create mode 100644 drivers/staging/rts5208/rtsx_transport.c create mode 100644 drivers/staging/rts5208/rtsx_transport.h create mode 100644 drivers/staging/rts5208/sd.c create mode 100644 drivers/staging/rts5208/sd.h create mode 100644 drivers/staging/rts5208/spi.c create mode 100644 drivers/staging/rts5208/spi.h create mode 100644 drivers/staging/rts5208/trace.h create mode 100644 drivers/staging/rts5208/xd.c create mode 100644 drivers/staging/rts5208/xd.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 3bfdaa8d80a9..facc025a5106 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -54,6 +54,8 @@ source "drivers/staging/rtl8188eu/Kconfig" source "drivers/staging/rts5139/Kconfig" +source "drivers/staging/rts5208/Kconfig" + source "drivers/staging/frontier/Kconfig" source "drivers/staging/phison/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index b0d3303b4680..094aba9419ed 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_R8188EU) += rtl8188eu/ obj-$(CONFIG_RTS5139) += rts5139/ +obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_IDE_PHISON) += phison/ obj-$(CONFIG_LINE6_USB) += line6/ diff --git a/drivers/staging/rts5208/Kconfig b/drivers/staging/rts5208/Kconfig new file mode 100644 index 000000000000..055655cecaf7 --- /dev/null +++ b/drivers/staging/rts5208/Kconfig @@ -0,0 +1,15 @@ +config RTS5208 + tristate "Realtek PCI-E Card Reader RTS5208/5288 support" + depends on PCI && SCSI + help + Say Y here to include driver code to support the Realtek + PCI-E card reader rts5208/rts5288. + + If this driver is compiled as a module, it will be named rts5208. + +config RTS5208_DEBUG + bool "Realtek PCI-E Card Reader RTS5208/5288 verbose debug" + depends on RTS5208 + help + Say Y here in order to have the rts5208 code generate + verbose debugging messages. diff --git a/drivers/staging/rts5208/Makefile b/drivers/staging/rts5208/Makefile new file mode 100644 index 000000000000..17b4471c4d6d --- /dev/null +++ b/drivers/staging/rts5208/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_RTS5208) := rts5208.o + +ccflags-y := -Idrivers/scsi + +rts5208-y := rtsx.o rtsx_chip.o rtsx_transport.o rtsx_scsi.o \ + rtsx_card.o general.o sd.o xd.o ms.o spi.o diff --git a/drivers/staging/rts5208/TODO b/drivers/staging/rts5208/TODO new file mode 100644 index 000000000000..57bcf5834c0c --- /dev/null +++ b/drivers/staging/rts5208/TODO @@ -0,0 +1,7 @@ +TODO: +- use kernel coding style +- checkpatch.pl fixes +- We will use the stack in drivers/mmc to implement + rts5208/5288 in the future + +Micky Ching \ No newline at end of file diff --git a/drivers/staging/rts5208/debug.h b/drivers/staging/rts5208/debug.h new file mode 100644 index 000000000000..5ba8a3a0fbdc --- /dev/null +++ b/drivers/staging/rts5208/debug.h @@ -0,0 +1,43 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_DEBUG_H +#define __REALTEK_RTSX_DEBUG_H + +#include + +#define RTSX_STOR "rts5208: " + +#ifdef CONFIG_RTS5208_DEBUG +#define RTSX_DEBUGP(x...) pr_debug(RTSX_STOR x) +#define RTSX_DEBUGPN(x...) pr_debug(x) +#define RTSX_DEBUGPX(x...) printk(x) +#define RTSX_DEBUG(x) x +#else +#define RTSX_DEBUGP(x...) +#define RTSX_DEBUGPN(x...) +#define RTSX_DEBUGPX(x...) +#define RTSX_DEBUG(x) +#endif + +#endif /* __REALTEK_RTSX_DEBUG_H */ diff --git a/drivers/staging/rts5208/general.c b/drivers/staging/rts5208/general.c new file mode 100644 index 000000000000..eada934288b2 --- /dev/null +++ b/drivers/staging/rts5208/general.c @@ -0,0 +1,35 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include "general.h" + +int bit1cnt_long(u32 data) +{ + int i, cnt = 0; + for (i = 0; i < 32; i++) { + if (data & 0x01) + cnt++; + data >>= 1; + } + return cnt; +} + diff --git a/drivers/staging/rts5208/general.h b/drivers/staging/rts5208/general.h new file mode 100644 index 000000000000..90a1f9297f5e --- /dev/null +++ b/drivers/staging/rts5208/general.h @@ -0,0 +1,31 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __RTSX_GENERAL_H +#define __RTSX_GENERAL_H + +#include "rtsx.h" + +int bit1cnt_long(u32 data); + +#endif /* __RTSX_GENERAL_H */ diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c new file mode 100644 index 000000000000..edf979f18a6c --- /dev/null +++ b/drivers/staging/rts5208/ms.c @@ -0,0 +1,4208 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" +#include "ms.h" + +static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct ms_info *ms_card = &(chip->ms_card); + + ms_card->err_code = err_code; +} + +static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct ms_info *ms_card = &(chip->ms_card); + + return (ms_card->err_code == err_code); +} + +static int ms_parse_err_code(struct rtsx_chip *chip) +{ + TRACE_RET(chip, STATUS_FAIL); +} + +static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, + u8 tpc, u8 cnt, u8 cfg) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + u8 *ptr; + + RTSX_DEBUGP("ms_transfer_tpc: tpc = 0x%x\n", tpc); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, + 0xFF, MS_TRANSFER_START | trans_mode); + rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, + MS_TRANSFER_END, MS_TRANSFER_END); + + rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0); + + retval = rtsx_send_cmd(chip, MS_CARD, 5000); + if (retval < 0) { + rtsx_clear_ms_error(chip); + ms_set_err_code(chip, MS_TO_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + + ptr = rtsx_get_cmd_data(chip) + 1; + + if (!(tpc & 0x08)) { /* Read Packet */ + if (*ptr & MS_CRC16_ERR) { + ms_set_err_code(chip, MS_CRC16_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + } else { /* Write Packet */ + if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) { + if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + } + } + + if (*ptr & MS_RDY_TIMEOUT) { + rtsx_clear_ms_error(chip); + ms_set_err_code(chip, MS_TO_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + + return STATUS_SUCCESS; +} + +static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, + u8 tpc, u16 sec_cnt, u8 cfg, int mode_2k, + int use_sg, void *buf, int buf_len) +{ + int retval; + u8 val, err_code = 0; + enum dma_data_direction dir; + + if (!buf || !buf_len) + TRACE_RET(chip, STATUS_FAIL); + + if (trans_mode == MS_TM_AUTO_READ) { + dir = DMA_FROM_DEVICE; + err_code = MS_FLASH_READ_ERROR; + } else if (trans_mode == MS_TM_AUTO_WRITE) { + dir = DMA_TO_DEVICE; + err_code = MS_FLASH_WRITE_ERROR; + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); + rtsx_add_cmd(chip, WRITE_REG_CMD, + MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); + + if (mode_2k) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + MS_CFG, MS_2K_SECTOR_MODE, MS_2K_SECTOR_MODE); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, 0); + } + + trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, + MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode); + rtsx_add_cmd(chip, CHECK_REG_CMD, + MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data(chip, MS_CARD, buf, buf_len, + use_sg, dir, chip->mspro_timeout); + if (retval < 0) { + ms_set_err_code(chip, err_code); + if (retval == -ETIMEDOUT) + retval = STATUS_TIMEDOUT; + else + retval = STATUS_FAIL; + + TRACE_RET(chip, retval); + } + + RTSX_READ_REG(chip, MS_TRANS_CFG, &val); + if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int ms_write_bytes(struct rtsx_chip *chip, + u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + + if (!data || (data_len < cnt)) + TRACE_RET(chip, STATUS_ERROR); + + rtsx_init_cmd(chip); + + for (i = 0; i < cnt; i++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + PPBUF_BASE2 + i, 0xFF, data[i]); + } + if (cnt % 2) + rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, + MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES); + rtsx_add_cmd(chip, CHECK_REG_CMD, + MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); + + retval = rtsx_send_cmd(chip, MS_CARD, 5000); + if (retval < 0) { + u8 val = 0; + + rtsx_read_register(chip, MS_TRANS_CFG, &val); + RTSX_DEBUGP("MS_TRANS_CFG: 0x%02x\n", val); + + rtsx_clear_ms_error(chip); + + if (!(tpc & 0x08)) { + if (val & MS_CRC16_ERR) { + ms_set_err_code(chip, MS_CRC16_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + } else { + if (CHK_MSPRO(ms_card) && !(val & 0x80)) { + if (val & (MS_INT_ERR | MS_INT_CMDNK)) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, + ms_parse_err_code(chip)); + } + } + } + + if (val & MS_RDY_TIMEOUT) { + ms_set_err_code(chip, MS_TO_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + + ms_set_err_code(chip, MS_TO_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + + return STATUS_SUCCESS; +} + +static int ms_read_bytes(struct rtsx_chip *chip, + u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 *ptr; + + if (!data) + TRACE_RET(chip, STATUS_ERROR); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, + MS_TRANSFER_START | MS_TM_READ_BYTES); + rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, + MS_TRANSFER_END, MS_TRANSFER_END); + + for (i = 0; i < data_len - 1; i++) + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); + + if (data_len % 2) + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0); + else + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, + 0, 0); + + retval = rtsx_send_cmd(chip, MS_CARD, 5000); + if (retval < 0) { + u8 val = 0; + + rtsx_read_register(chip, MS_TRANS_CFG, &val); + rtsx_clear_ms_error(chip); + + if (!(tpc & 0x08)) { + if (val & MS_CRC16_ERR) { + ms_set_err_code(chip, MS_CRC16_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + } else { + if (CHK_MSPRO(ms_card) && !(val & 0x80)) { + if (val & (MS_INT_ERR | MS_INT_CMDNK)) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, + ms_parse_err_code(chip)); + } + } + } + + if (val & MS_RDY_TIMEOUT) { + ms_set_err_code(chip, MS_TO_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + + ms_set_err_code(chip, MS_TO_ERROR); + TRACE_RET(chip, ms_parse_err_code(chip)); + } + + ptr = rtsx_get_cmd_data(chip) + 1; + + for (i = 0; i < data_len; i++) + data[i] = ptr[i]; + + if ((tpc == PRO_READ_SHORT_DATA) && (data_len == 8)) { + RTSX_DEBUGP("Read format progress:\n"); + RTSX_DUMP(ptr, cnt); + } + + return STATUS_SUCCESS; +} + +static int ms_set_rw_reg_addr(struct rtsx_chip *chip, + u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt) +{ + int retval, i; + u8 data[4]; + + data[0] = read_start; + data[1] = read_cnt; + data[2] = write_start; + data[3] = write_cnt; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, SET_RW_REG_ADRS, 4, + NO_WAIT_INT, data, 4); + if (retval == STATUS_SUCCESS) + return STATUS_SUCCESS; + rtsx_clear_ms_error(chip); + } + + TRACE_RET(chip, STATUS_FAIL); +} + +static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg) +{ + u8 data[2]; + + data[0] = cmd; + data[1] = 0; + + return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1); +} + +static int ms_set_init_para(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + if (CHK_HG8BIT(ms_card)) { + if (chip->asic_code) + ms_card->ms_clock = chip->asic_ms_hg_clk; + else + ms_card->ms_clock = chip->fpga_ms_hg_clk; + + } else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) { + if (chip->asic_code) + ms_card->ms_clock = chip->asic_ms_4bit_clk; + else + ms_card->ms_clock = chip->fpga_ms_4bit_clk; + + } else { + if (chip->asic_code) + ms_card->ms_clock = chip->asic_ms_1bit_clk; + else + ms_card->ms_clock = chip->fpga_ms_1bit_clk; + } + + retval = switch_clock(chip, ms_card->ms_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = select_card(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int ms_switch_clock(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + retval = select_card(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = switch_clock(chip, ms_card->ms_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int ms_pull_ctl_disable(struct rtsx_chip *chip) +{ + if (CHECK_PID(chip, 0x5208)) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, + MS_D1_PD | MS_D2_PD | MS_CLK_PD | MS_D6_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, + MS_D3_PD | MS_D0_PD | MS_BS_PD | XD_D4_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, + MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, + XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, + MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55); + RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55); + RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B); + RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69); + } + } + + return STATUS_SUCCESS; +} + +static int ms_pull_ctl_enable(struct rtsx_chip *chip) +{ + int retval; + + rtsx_init_cmd(chip); + + if (CHECK_PID(chip, 0x5208)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, + MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, + MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, + MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, + XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, + MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + CARD_PULL_CTL1, 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, + CARD_PULL_CTL2, 0xFF, 0x45); + rtsx_add_cmd(chip, WRITE_REG_CMD, + CARD_PULL_CTL3, 0xFF, 0x4B); + rtsx_add_cmd(chip, WRITE_REG_CMD, + CARD_PULL_CTL4, 0xFF, 0x29); + } + } + + retval = rtsx_send_cmd(chip, MS_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int ms_prepare_reset(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + u8 oc_mask = 0; + + ms_card->ms_type = 0; + ms_card->check_ms_flow = 0; + ms_card->switch_8bit_fail = 0; + ms_card->delay_write.delay_write_flag = 0; + + ms_card->pro_under_formatting = 0; + + retval = ms_power_off_card3v3(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!chip->ft2_fast_mode) + wait_timeout(250); + + retval = enable_card_clock(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (chip->asic_code) { + retval = ms_pull_ctl_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, + FPGA_MS_PULL_CTL_BIT | 0x20, 0); + } + + if (!chip->ft2_fast_mode) { + retval = card_power_on(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(150); + +#ifdef SUPPORT_OCP + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + oc_mask = MS_OC_NOW | MS_OC_EVER; + else + oc_mask = SD_OC_NOW | SD_OC_EVER; + + if (chip->ocp_stat & oc_mask) { + RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", + chip->ocp_stat); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + } + + RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, MS_OUTPUT_EN); + + if (chip->asic_code) { + RTSX_WRITE_REG(chip, MS_CFG, 0xFF, + SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT | + NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1); + } else { + RTSX_WRITE_REG(chip, MS_CFG, 0xFF, + SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT | + NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1); + } + RTSX_WRITE_REG(chip, MS_TRANS_CFG, + 0xFF, NO_WAIT_INT | NO_AUTO_READ_INT_REG); + RTSX_WRITE_REG(chip, CARD_STOP, + MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR); + + retval = ms_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 val; + + retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, + 6, NO_WAIT_INT); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_READ_REG(chip, PPBUF_BASE2 + 2, &val); + RTSX_DEBUGP("Type register: 0x%x\n", val); + if (val != 0x01) { + if (val != 0x02) + ms_card->check_ms_flow = 1; + + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_READ_REG(chip, PPBUF_BASE2 + 4, &val); + RTSX_DEBUGP("Category register: 0x%x\n", val); + if (val != 0) { + ms_card->check_ms_flow = 1; + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_READ_REG(chip, PPBUF_BASE2 + 5, &val); + RTSX_DEBUGP("Class register: 0x%x\n", val); + if (val == 0) { + RTSX_READ_REG(chip, PPBUF_BASE2, &val); + if (val & WRT_PRTCT) + chip->card_wp |= MS_CARD; + else + chip->card_wp &= ~MS_CARD; + + } else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) { + chip->card_wp |= MS_CARD; + } else { + ms_card->check_ms_flow = 1; + TRACE_RET(chip, STATUS_FAIL); + } + + ms_card->ms_type |= TYPE_MSPRO; + + RTSX_READ_REG(chip, PPBUF_BASE2 + 3, &val); + RTSX_DEBUGP("IF Mode register: 0x%x\n", val); + if (val == 0) { + ms_card->ms_type &= 0x0F; + } else if (val == 7) { + if (switch_8bit_bus) + ms_card->ms_type |= MS_HG; + else + ms_card->ms_type &= 0x0F; + + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int ms_confirm_cpu_startup(struct rtsx_chip *chip) +{ + int retval, i, k; + u8 val; + + /* Confirm CPU StartUp */ + k = 0; + do { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_read_bytes(chip, GET_INT, 1, + NO_WAIT_INT, &val, 1); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + if (k > 100) + TRACE_RET(chip, STATUS_FAIL); + + k++; + wait_timeout(100); + } while (!(val & INT_REG_CED)); + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_ERR) { + if (val & INT_REG_CMDNK) + chip->card_wp |= (MS_CARD); + else + TRACE_RET(chip, STATUS_FAIL); + } + /* -- end confirm CPU startup */ + + return STATUS_SUCCESS; +} + +static int ms_switch_parallel_bus(struct rtsx_chip *chip) +{ + int retval, i; + u8 data[2]; + + data[0] = PARALLEL_4BIT_IF; + data[1] = 0; + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, + data, 2); + if (retval == STATUS_SUCCESS) + break; + } + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int ms_switch_8bit_bus(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 data[2]; + + data[0] = PARALLEL_8BIT_IF; + data[1] = 0; + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, WRITE_REG, 1, + NO_WAIT_INT, data, 2); + if (retval == STATUS_SUCCESS) + break; + } + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, MS_CFG, 0x98, + MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING); + ms_card->ms_type |= MS_8BIT; + retval = ms_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, + 1, NO_WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + + for (i = 0; i < 3; i++) { + retval = ms_prepare_reset(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_identify_media_type(chip, switch_8bit_bus); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_confirm_cpu_startup(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_switch_parallel_bus(chip); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + continue; + } else { + break; + } + } + + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + /* Switch MS-PRO into Parallel mode */ + RTSX_WRITE_REG(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4); + RTSX_WRITE_REG(chip, MS_CFG, PUSH_TIME_ODD, PUSH_TIME_ODD); + + retval = ms_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + /* If MSPro HG Card, We shall try to switch to 8-bit bus */ + if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) { + retval = ms_switch_8bit_bus(chip); + if (retval != STATUS_SUCCESS) { + ms_card->switch_8bit_fail = 1; + TRACE_RET(chip, STATUS_FAIL); + } + } + + return STATUS_SUCCESS; +} + +#ifdef XC_POWERCLASS +static int msxc_change_power(struct rtsx_chip *chip, u8 mode) +{ + int retval; + u8 buf[6]; + + ms_cleanup_work(chip); + + retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf[0] = 0; + buf[1] = mode; + buf[2] = 0; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + + retval = ms_write_bytes(chip, PRO_WRITE_REG , 6, NO_WAIT_INT, buf, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_READ_REG(chip, MS_TRANS_CFG, buf); + if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} +#endif + +static int ms_read_attribute_info(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 val, *buf, class_code, device_type, sub_class, data[16]; + u16 total_blk = 0, blk_size = 0; +#ifdef SUPPORT_MSXC + u32 xc_total_blk = 0, xc_blk_size = 0; +#endif + u32 sys_info_addr = 0, sys_info_size; +#ifdef SUPPORT_PCGL_1P18 + u32 model_name_addr = 0, model_name_size; + int found_sys_info = 0, found_model_name = 0; +#endif + + retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_MS8BIT(ms_card)) + data[0] = PARALLEL_8BIT_IF; + else + data[0] = PARALLEL_4BIT_IF; + + data[1] = 0; + + data[2] = 0x40; + data[3] = 0; + data[4] = 0; + data[5] = 0; + data[6] = 0; + data[7] = 0; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT, + data, 8); + if (retval == STATUS_SUCCESS) + break; + } + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf = kmalloc(64 * 512, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, STATUS_ERROR); + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT); + if (retval != STATUS_SUCCESS) + continue; + + retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + if (!(val & MS_INT_BREQ)) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + retval = ms_transfer_data(chip, MS_TM_AUTO_READ, + PRO_READ_LONG_DATA, 0x40, WAIT_INT, + 0, 0, buf, 64 * 512); + if (retval == STATUS_SUCCESS) + break; + else + rtsx_clear_ms_error(chip); + } + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + i = 0; + do { + retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + if ((val & MS_INT_CED) || !(val & MS_INT_BREQ)) + break; + + retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, + PRO_READ_LONG_DATA, 0, WAIT_INT); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + i++; + } while (i < 1024); + + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + if ((buf[0] != 0xa5) && (buf[1] != 0xc3)) { + /* Signature code is wrong */ + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + if ((buf[4] < 1) || (buf[4] > 12)) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + for (i = 0; i < buf[4]; i++) { + int cur_addr_off = 16 + i * 12; + +#ifdef SUPPORT_MSXC + if ((buf[cur_addr_off + 8] == 0x10) || + (buf[cur_addr_off + 8] == 0x13)) +#else + if (buf[cur_addr_off + 8] == 0x10) +#endif + { + sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) | + ((u32)buf[cur_addr_off + 1] << 16) | + ((u32)buf[cur_addr_off + 2] << 8) | + buf[cur_addr_off + 3]; + sys_info_size = ((u32)buf[cur_addr_off + 4] << 24) | + ((u32)buf[cur_addr_off + 5] << 16) | + ((u32)buf[cur_addr_off + 6] << 8) | + buf[cur_addr_off + 7]; + RTSX_DEBUGP("sys_info_addr = 0x%x, sys_info_size = 0x%x\n", + sys_info_addr, sys_info_size); + if (sys_info_size != 96) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + if (sys_info_addr < 0x1A0) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + if ((sys_info_size + sys_info_addr) > 0x8000) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + +#ifdef SUPPORT_MSXC + if (buf[cur_addr_off + 8] == 0x13) + ms_card->ms_type |= MS_XC; +#endif +#ifdef SUPPORT_PCGL_1P18 + found_sys_info = 1; +#else + break; +#endif + } +#ifdef SUPPORT_PCGL_1P18 + if (buf[cur_addr_off + 8] == 0x15) { + model_name_addr = ((u32)buf[cur_addr_off + 0] << 24) | + ((u32)buf[cur_addr_off + 1] << 16) | + ((u32)buf[cur_addr_off + 2] << 8) | + buf[cur_addr_off + 3]; + model_name_size = ((u32)buf[cur_addr_off + 4] << 24) | + ((u32)buf[cur_addr_off + 5] << 16) | + ((u32)buf[cur_addr_off + 6] << 8) | + buf[cur_addr_off + 7]; + RTSX_DEBUGP("model_name_addr = 0x%x, model_name_size = 0x%x\n", + model_name_addr, model_name_size); + if (model_name_size != 48) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + if (model_name_addr < 0x1A0) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + if ((model_name_size + model_name_addr) > 0x8000) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + found_model_name = 1; + } + + if (found_sys_info && found_model_name) + break; +#endif + } + + if (i == buf[4]) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + class_code = buf[sys_info_addr + 0]; + device_type = buf[sys_info_addr + 56]; + sub_class = buf[sys_info_addr + 46]; +#ifdef SUPPORT_MSXC + if (CHK_MSXC(ms_card)) { + xc_total_blk = ((u32)buf[sys_info_addr + 6] << 24) | + ((u32)buf[sys_info_addr + 7] << 16) | + ((u32)buf[sys_info_addr + 8] << 8) | + buf[sys_info_addr + 9]; + xc_blk_size = ((u32)buf[sys_info_addr + 32] << 24) | + ((u32)buf[sys_info_addr + 33] << 16) | + ((u32)buf[sys_info_addr + 34] << 8) | + buf[sys_info_addr + 35]; + RTSX_DEBUGP("xc_total_blk = 0x%x, xc_blk_size = 0x%x\n", + xc_total_blk, xc_blk_size); + } else { + total_blk = ((u16)buf[sys_info_addr + 6] << 8) | + buf[sys_info_addr + 7]; + blk_size = ((u16)buf[sys_info_addr + 2] << 8) | + buf[sys_info_addr + 3]; + RTSX_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", + total_blk, blk_size); + } +#else + total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7]; + blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3]; + RTSX_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, blk_size); +#endif + + RTSX_DEBUGP("class_code = 0x%x, device_type = 0x%x, sub_class = 0x%x\n", + class_code, device_type, sub_class); + + memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96); +#ifdef SUPPORT_PCGL_1P18 + memcpy(ms_card->raw_model_name, buf + model_name_addr, 48); +#endif + + kfree(buf); + +#ifdef SUPPORT_MSXC + if (CHK_MSXC(ms_card)) { + if (class_code != 0x03) + TRACE_RET(chip, STATUS_FAIL); + } else { + if (class_code != 0x02) + TRACE_RET(chip, STATUS_FAIL); + } +#else + if (class_code != 0x02) + TRACE_RET(chip, STATUS_FAIL); +#endif + + if (device_type != 0x00) { + if ((device_type == 0x01) || (device_type == 0x02) || + (device_type == 0x03)) { + chip->card_wp |= MS_CARD; + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (sub_class & 0xC0) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n", + class_code, device_type, sub_class); + +#ifdef SUPPORT_MSXC + if (CHK_MSXC(ms_card)) { + chip->capacity[chip->card2lun[MS_CARD]] = + ms_card->capacity = xc_total_blk * xc_blk_size; + } else { + chip->capacity[chip->card2lun[MS_CARD]] = + ms_card->capacity = total_blk * blk_size; + } +#else + ms_card->capacity = total_blk * blk_size; + chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity; +#endif + + return STATUS_SUCCESS; +} + +#ifdef SUPPORT_MAGIC_GATE +static int mg_set_tpc_para_sub(struct rtsx_chip *chip, + int type, u8 mg_entry_num); +#endif + +static int reset_ms_pro(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; +#ifdef XC_POWERCLASS + u8 change_power_class; + + if (chip->ms_power_class_en & 0x02) + change_power_class = 2; + else if (chip->ms_power_class_en & 0x01) + change_power_class = 1; + else + change_power_class = 0; +#endif + +#ifdef XC_POWERCLASS +Retry: +#endif + retval = ms_pro_reset_flow(chip, 1); + if (retval != STATUS_SUCCESS) { + if (ms_card->switch_8bit_fail) { + retval = ms_pro_reset_flow(chip, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } + + retval = ms_read_attribute_info(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + +#ifdef XC_POWERCLASS + if (CHK_HG8BIT(ms_card)) + change_power_class = 0; + + if (change_power_class && CHK_MSXC(ms_card)) { + u8 power_class_en = chip->ms_power_class_en; + + RTSX_DEBUGP("power_class_en = 0x%x\n", power_class_en); + RTSX_DEBUGP("change_power_class = %d\n", change_power_class); + + if (change_power_class) + power_class_en &= (1 << (change_power_class - 1)); + else + power_class_en = 0; + + if (power_class_en) { + u8 power_class_mode = + (ms_card->raw_sys_info[46] & 0x18) >> 3; + RTSX_DEBUGP("power_class_mode = 0x%x", + power_class_mode); + if (change_power_class > power_class_mode) + change_power_class = power_class_mode; + if (change_power_class) { + retval = msxc_change_power(chip, + change_power_class); + if (retval != STATUS_SUCCESS) { + change_power_class--; + goto Retry; + } + } + } + } +#endif + +#ifdef SUPPORT_MAGIC_GATE + retval = mg_set_tpc_para_sub(chip, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); +#endif + + if (CHK_HG8BIT(ms_card)) + chip->card_bus_width[chip->card2lun[MS_CARD]] = 8; + else + chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; + + return STATUS_SUCCESS; +} + +static int ms_read_status_reg(struct rtsx_chip *chip) +{ + int retval; + u8 val[2]; + + retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) { + ms_set_err_code(chip, MS_FLASH_READ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + + +static int ms_read_extra_data(struct rtsx_chip *chip, + u16 block_addr, u8 page_num, u8 *buf, int buf_len) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 val, data[10]; + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_MS4BIT(ms_card)) { + /* Parallel interface */ + data[0] = 0x88; + } else { + /* Serial interface */ + data[0] = 0x80; + } + data[1] = 0; + data[2] = (u8)(block_addr >> 8); + data[3] = (u8)block_addr; + data[4] = 0x40; + data[5] = page_num; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, + data, 6); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + retval = ms_read_status_reg(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, + MS_EXTRA_SIZE, SystemParm, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + } + + retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, + data, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (buf && buf_len) { + if (buf_len > MS_EXTRA_SIZE) + buf_len = MS_EXTRA_SIZE; + memcpy(buf, data, buf_len); + } + + return STATUS_SUCCESS; +} + +static int ms_write_extra_data(struct rtsx_chip *chip, + u16 block_addr, u8 page_num, u8 *buf, int buf_len) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 val, data[16]; + + if (!buf || (buf_len < MS_EXTRA_SIZE)) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 6 + MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(block_addr >> 8); + data[3] = (u8)block_addr; + data[4] = 0x40; + data[5] = page_num; + + for (i = 6; i < MS_EXTRA_SIZE + 6; i++) + data[i] = buf[i - 6]; + + retval = ms_write_bytes(chip, WRITE_REG , (6+MS_EXTRA_SIZE), + NO_WAIT_INT, data, 16); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + return STATUS_SUCCESS; +} + + +static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + u8 val, data[6]; + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(block_addr >> 8); + data[3] = (u8)block_addr; + data[4] = 0x20; + data[5] = page_num; + + retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + if (!(val & INT_REG_BREQ)) { + ms_set_err_code(chip, MS_FLASH_READ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + retval = ms_read_status_reg(chip); + if (retval != STATUS_SUCCESS) + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + + } else { + if (!(val & INT_REG_BREQ)) { + ms_set_err_code(chip, MS_BREQ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, + 0, NO_WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + + +static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + u8 val, data[8], extra[MS_EXTRA_SIZE]; + + retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 7); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(phy_blk >> 8); + data[3] = (u8)phy_blk; + data[4] = 0x80; + data[5] = 0; + data[6] = extra[0] & 0x7F; + data[7] = 0xFF; + + retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 7); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + return STATUS_SUCCESS; +} + + +static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i = 0; + u8 val, data[6]; + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(phy_blk >> 8); + data[3] = (u8)phy_blk; + data[4] = 0; + data[5] = 0; + + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + +ERASE_RTY: + retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + if (i < 3) { + i++; + goto ERASE_RTY; + } + + ms_set_err_code(chip, MS_CMD_NK); + ms_set_bad_block(chip, phy_blk); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + return STATUS_SUCCESS; +} + + +static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len) +{ + if (!extra || (extra_len < MS_EXTRA_SIZE)) + return; + + memset(extra, 0xFF, MS_EXTRA_SIZE); + + if (type == setPS_NG) { + /* set page status as 1:NG,and block status keep 1:OK */ + extra[0] = 0xB8; + } else { + /* set page status as 0:Data Error,and block status keep 1:OK */ + extra[0] = 0x98; + } + + extra[2] = (u8)(log_blk >> 8); + extra[3] = (u8)log_blk; +} + +static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, + u8 start_page, u8 end_page) +{ + int retval; + u8 extra[MS_EXTRA_SIZE], i; + + memset(extra, 0xff, MS_EXTRA_SIZE); + + extra[0] = 0xf8; /* Block, page OK, data erased */ + extra[1] = 0xff; + extra[2] = (u8)(log_blk >> 8); + extra[3] = (u8)log_blk; + + for (i = start_page; i < end_page; i++) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_write_extra_data(chip, phy_blk, i, + extra, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, + u16 log_blk, u8 start_page, u8 end_page) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, rty_cnt, uncorrect_flag = 0; + u8 extra[MS_EXTRA_SIZE], val, i, j, data[16]; + + RTSX_DEBUGP("Copy page from 0x%x to 0x%x, logical block is 0x%x\n", + old_blk, new_blk, log_blk); + RTSX_DEBUGP("start_page = %d, end_page = %d\n", start_page, end_page); + + retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_read_status_reg(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_READ_REG(chip, PPBUF_BASE2, &val); + + if (val & BUF_FULL) { + retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!(val & INT_REG_CED)) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + for (i = start_page; i < end_page; i++) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE); + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, + MS_EXTRA_SIZE, SystemParm, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(old_blk >> 8); + data[3] = (u8)old_blk; + data[4] = 0x20; + data[5] = i; + + retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, + data, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + retval = ms_read_status_reg(chip); + if (retval != STATUS_SUCCESS) { + uncorrect_flag = 1; + RTSX_DEBUGP("Uncorrectable error\n"); + } else { + uncorrect_flag = 0; + } + + retval = ms_transfer_tpc(chip, + MS_TM_NORMAL_READ, + READ_PAGE_DATA, + 0, NO_WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (uncorrect_flag) { + ms_set_page_status(log_blk, setPS_NG, + extra, MS_EXTRA_SIZE); + if (i == 0) + extra[0] &= 0xEF; + + ms_write_extra_data(chip, old_blk, i, + extra, MS_EXTRA_SIZE); + RTSX_DEBUGP("page %d : extra[0] = 0x%x\n", i, extra[0]); + MS_SET_BAD_BLOCK_FLG(ms_card); + + ms_set_page_status(log_blk, setPS_Error, + extra, MS_EXTRA_SIZE); + ms_write_extra_data(chip, new_blk, i, + extra, MS_EXTRA_SIZE); + continue; + } + + for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT; + rty_cnt++) { + retval = ms_transfer_tpc( + chip, + MS_TM_NORMAL_WRITE, + WRITE_PAGE_DATA, + 0, NO_WAIT_INT); + if (retval == STATUS_SUCCESS) + break; + } + if (rty_cnt == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + } + + if (!(val & INT_REG_BREQ)) { + ms_set_err_code(chip, MS_BREQ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, + MS_EXTRA_SIZE, SystemParm, (6+MS_EXTRA_SIZE)); + + ms_set_err_code(chip, MS_NO_ERROR); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(new_blk >> 8); + data[3] = (u8)new_blk; + data[4] = 0x20; + data[5] = i; + + if ((extra[0] & 0x60) != 0x60) + data[6] = extra[0]; + else + data[6] = 0xF8; + + data[6 + 1] = 0xFF; + data[6 + 2] = (u8)(log_blk >> 8); + data[6 + 3] = (u8)log_blk; + + for (j = 4; j <= MS_EXTRA_SIZE; j++) + data[6 + j] = 0xFF; + + retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), + NO_WAIT_INT, data, 16); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (i == 0) { + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, + MS_EXTRA_SIZE, SystemParm, 7); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(old_blk >> 8); + data[3] = (u8)old_blk; + data[4] = 0x80; + data[5] = 0; + data[6] = 0xEF; + data[7] = 0xFF; + + retval = ms_write_bytes(chip, WRITE_REG, 7, + NO_WAIT_INT, data, 8); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_read_bytes(chip, GET_INT, 1, + NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CED) { + if (val & INT_REG_ERR) { + ms_set_err_code(chip, + MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + } + } + + return STATUS_SUCCESS; +} + + +static int reset_ms(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + u16 i, reg_addr, block_size; + u8 val, extra[MS_EXTRA_SIZE], j, *ptr; +#ifndef SUPPORT_MAGIC_GATE + u16 eblock_cnt; +#endif + + retval = ms_prepare_reset(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_card->ms_type |= TYPE_MS; + + retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_read_status_reg(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_READ_REG(chip, PPBUF_BASE2, &val); + if (val & WRT_PRTCT) + chip->card_wp |= MS_CARD; + else + chip->card_wp &= ~MS_CARD; + + i = 0; + +RE_SEARCH: + /* Search Boot Block */ + while (i < (MAX_DEFECTIVE_BLOCK + 2)) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) { + i++; + continue; + } + + if (extra[0] & BLOCK_OK) { + if (!(extra[1] & NOT_BOOT_BLOCK)) { + ms_card->boot_block = i; + break; + } + } + i++; + } + + if (i == (MAX_DEFECTIVE_BLOCK + 2)) { + RTSX_DEBUGP("No boot block found!"); + TRACE_RET(chip, STATUS_FAIL); + } + + for (j = 0; j < 3; j++) { + retval = ms_read_page(chip, ms_card->boot_block, j); + if (retval != STATUS_SUCCESS) { + if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) { + i = ms_card->boot_block + 1; + ms_set_err_code(chip, MS_NO_ERROR); + goto RE_SEARCH; + } + } + } + + retval = ms_read_page(chip, ms_card->boot_block, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + /* Read MS system information as sys_info */ + rtsx_init_cmd(chip); + + for (i = 0; i < 96; i++) + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0); + + retval = rtsx_send_cmd(chip, MS_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + ptr = rtsx_get_cmd_data(chip); + memcpy(ms_card->raw_sys_info, ptr, 96); + + /* Read useful block contents */ + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0); + rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0); + + for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + + for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + + rtsx_add_cmd(chip, READ_REG_CMD, MS_Device_Type, 0, 0); + rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0); + + retval = rtsx_send_cmd(chip, MS_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + ptr = rtsx_get_cmd_data(chip); + + RTSX_DEBUGP("Boot block data:\n"); + RTSX_DUMP(ptr, 16); + + /* Block ID error + * HEADER_ID0, HEADER_ID1 + */ + if (ptr[0] != 0x00 || ptr[1] != 0x01) { + i = ms_card->boot_block + 1; + goto RE_SEARCH; + } + + /* Page size error + * PAGE_SIZE_0, PAGE_SIZE_1 + */ + if (ptr[12] != 0x02 || ptr[13] != 0x00) { + i = ms_card->boot_block + 1; + goto RE_SEARCH; + } + + if ((ptr[14] == 1) || (ptr[14] == 3)) + chip->card_wp |= MS_CARD; + + /* BLOCK_SIZE_0, BLOCK_SIZE_1 */ + block_size = ((u16)ptr[6] << 8) | ptr[7]; + if (block_size == 0x0010) { + /* Block size 16KB */ + ms_card->block_shift = 5; + ms_card->page_off = 0x1F; + } else if (block_size == 0x0008) { + /* Block size 8KB */ + ms_card->block_shift = 4; + ms_card->page_off = 0x0F; + } + + /* BLOCK_COUNT_0, BLOCK_COUNT_1 */ + ms_card->total_block = ((u16)ptr[8] << 8) | ptr[9]; + +#ifdef SUPPORT_MAGIC_GATE + j = ptr[10]; + + if (ms_card->block_shift == 4) { /* 4MB or 8MB */ + if (j < 2) { /* Effective block for 4MB: 0x1F0 */ + ms_card->capacity = 0x1EE0; + } else { /* Effective block for 8MB: 0x3E0 */ + ms_card->capacity = 0x3DE0; + } + } else { /* 16MB, 32MB, 64MB or 128MB */ + if (j < 5) { /* Effective block for 16MB: 0x3E0 */ + ms_card->capacity = 0x7BC0; + } else if (j < 0xA) { /* Effective block for 32MB: 0x7C0 */ + ms_card->capacity = 0xF7C0; + } else if (j < 0x11) { /* Effective block for 64MB: 0xF80 */ + ms_card->capacity = 0x1EF80; + } else { /* Effective block for 128MB: 0x1F00 */ + ms_card->capacity = 0x3DF00; + } + } +#else + /* EBLOCK_COUNT_0, EBLOCK_COUNT_1 */ + eblock_cnt = ((u16)ptr[10] << 8) | ptr[11]; + + ms_card->capacity = ((u32)eblock_cnt - 2) << ms_card->block_shift; +#endif + + chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity; + + /* Switch I/F Mode */ + if (ptr[15]) { + retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88); + RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0); + + retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG , 1, + NO_WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT, + MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT); + + ms_card->ms_type |= MS_4BIT; + } + + if (CHK_MS4BIT(ms_card)) + chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; + else + chip->card_bus_width[chip->card2lun[MS_CARD]] = 1; + + return STATUS_SUCCESS; +} + +static int ms_init_l2p_tbl(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int size, i, seg_no, retval; + u16 defect_block, reg_addr; + u8 val1, val2; + + ms_card->segment_cnt = ms_card->total_block >> 9; + RTSX_DEBUGP("ms_card->segment_cnt = %d\n", ms_card->segment_cnt); + + size = ms_card->segment_cnt * sizeof(struct zone_entry); + ms_card->segment = vzalloc(size); + if (ms_card->segment == NULL) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_read_page(chip, ms_card->boot_block, 1); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, INIT_FAIL); + + reg_addr = PPBUF_BASE2; + for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) { + retval = rtsx_read_register(chip, reg_addr++, &val1); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, INIT_FAIL); + + retval = rtsx_read_register(chip, reg_addr++, &val2); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, INIT_FAIL); + + defect_block = ((u16)val1 << 8) | val2; + if (defect_block == 0xFFFF) + break; + + seg_no = defect_block / 512; + ms_card->segment[seg_no].defect_list[ms_card->segment[seg_no].disable_count++] = defect_block; + } + + for (i = 0; i < ms_card->segment_cnt; i++) { + ms_card->segment[i].build_flag = 0; + ms_card->segment[i].l2p_table = NULL; + ms_card->segment[i].free_table = NULL; + ms_card->segment[i].get_index = 0; + ms_card->segment[i].set_index = 0; + ms_card->segment[i].unused_blk_cnt = 0; + + RTSX_DEBUGP("defective block count of segment %d is %d\n", + i, ms_card->segment[i].disable_count); + } + + return STATUS_SUCCESS; + +INIT_FAIL: + if (ms_card->segment) { + vfree(ms_card->segment); + ms_card->segment = NULL; + } + + return STATUS_FAIL; +} + +static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct zone_entry *segment; + + if (ms_card->segment == NULL) + return 0xFFFF; + + segment = &(ms_card->segment[seg_no]); + + if (segment->l2p_table) + return segment->l2p_table[log_off]; + + return 0xFFFF; +} + +static void ms_set_l2p_tbl(struct rtsx_chip *chip, + int seg_no, u16 log_off, u16 phy_blk) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct zone_entry *segment; + + if (ms_card->segment == NULL) + return; + + segment = &(ms_card->segment[seg_no]); + if (segment->l2p_table) + segment->l2p_table[log_off] = phy_blk; +} + +static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct zone_entry *segment; + int seg_no; + + seg_no = (int)phy_blk >> 9; + segment = &(ms_card->segment[seg_no]); + + segment->free_table[segment->set_index++] = phy_blk; + if (segment->set_index >= MS_FREE_TABLE_CNT) + segment->set_index = 0; + + segment->unused_blk_cnt++; +} + +static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct zone_entry *segment; + u16 phy_blk; + + segment = &(ms_card->segment[seg_no]); + + if (segment->unused_blk_cnt <= 0) + return 0xFFFF; + + phy_blk = segment->free_table[segment->get_index]; + segment->free_table[segment->get_index++] = 0xFFFF; + if (segment->get_index >= MS_FREE_TABLE_CNT) + segment->get_index = 0; + + segment->unused_blk_cnt--; + + return phy_blk; +} + +static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478, + 2974, 3470, 3966, 4462, 4958, + 5454, 5950, 6446, 6942, 7438, + 7934}; + +static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, + u16 log_off, u8 us1, u8 us2) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct zone_entry *segment; + int seg_no; + u16 tmp_blk; + + seg_no = (int)phy_blk >> 9; + segment = &(ms_card->segment[seg_no]); + tmp_blk = segment->l2p_table[log_off]; + + if (us1 != us2) { + if (us1 == 0) { + if (!(chip->card_wp & MS_CARD)) + ms_erase_block(chip, tmp_blk); + + ms_set_unused_block(chip, tmp_blk); + segment->l2p_table[log_off] = phy_blk; + } else { + if (!(chip->card_wp & MS_CARD)) + ms_erase_block(chip, phy_blk); + + ms_set_unused_block(chip, phy_blk); + } + } else { + if (phy_blk < tmp_blk) { + if (!(chip->card_wp & MS_CARD)) + ms_erase_block(chip, phy_blk); + + ms_set_unused_block(chip, phy_blk); + } else { + if (!(chip->card_wp & MS_CARD)) + ms_erase_block(chip, tmp_blk); + + ms_set_unused_block(chip, tmp_blk); + segment->l2p_table[log_off] = phy_blk; + } + } + + return STATUS_SUCCESS; +} + +static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct zone_entry *segment; + int retval, table_size, disable_cnt, defect_flag, i; + u16 start, end, phy_blk, log_blk, tmp_blk; + u8 extra[MS_EXTRA_SIZE], us1, us2; + + RTSX_DEBUGP("ms_build_l2p_tbl: %d\n", seg_no); + + if (ms_card->segment == NULL) { + retval = ms_init_l2p_tbl(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, retval); + } + + if (ms_card->segment[seg_no].build_flag) { + RTSX_DEBUGP("l2p table of segment %d has been built\n", seg_no); + return STATUS_SUCCESS; + } + + if (seg_no == 0) + table_size = 494; + else + table_size = 496; + + segment = &(ms_card->segment[seg_no]); + + if (segment->l2p_table == NULL) { + segment->l2p_table = vmalloc(table_size * 2); + if (segment->l2p_table == NULL) + TRACE_GOTO(chip, BUILD_FAIL); + } + memset((u8 *)(segment->l2p_table), 0xff, table_size * 2); + + if (segment->free_table == NULL) { + segment->free_table = vmalloc(MS_FREE_TABLE_CNT * 2); + if (segment->free_table == NULL) + TRACE_GOTO(chip, BUILD_FAIL); + } + memset((u8 *)(segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2); + + start = (u16)seg_no << 9; + end = (u16)(seg_no + 1) << 9; + + disable_cnt = segment->disable_count; + + segment->get_index = segment->set_index = 0; + segment->unused_blk_cnt = 0; + + for (phy_blk = start; phy_blk < end; phy_blk++) { + if (disable_cnt) { + defect_flag = 0; + for (i = 0; i < segment->disable_count; i++) { + if (phy_blk == segment->defect_list[i]) { + defect_flag = 1; + break; + } + } + if (defect_flag) { + disable_cnt--; + continue; + } + } + + retval = ms_read_extra_data(chip, phy_blk, 0, + extra, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) { + RTSX_DEBUGP("read extra data fail\n"); + ms_set_bad_block(chip, phy_blk); + continue; + } + + if (seg_no == ms_card->segment_cnt - 1) { + if (!(extra[1] & NOT_TRANSLATION_TABLE)) { + if (!(chip->card_wp & MS_CARD)) { + retval = ms_erase_block(chip, phy_blk); + if (retval != STATUS_SUCCESS) + continue; + extra[2] = 0xff; + extra[3] = 0xff; + } + } + } + + if (!(extra[0] & BLOCK_OK)) + continue; + if (!(extra[1] & NOT_BOOT_BLOCK)) + continue; + if ((extra[0] & PAGE_OK) != PAGE_OK) + continue; + + log_blk = ((u16)extra[2] << 8) | extra[3]; + + if (log_blk == 0xFFFF) { + if (!(chip->card_wp & MS_CARD)) { + retval = ms_erase_block(chip, phy_blk); + if (retval != STATUS_SUCCESS) + continue; + } + ms_set_unused_block(chip, phy_blk); + continue; + } + + if ((log_blk < ms_start_idx[seg_no]) || + (log_blk >= ms_start_idx[seg_no+1])) { + if (!(chip->card_wp & MS_CARD)) { + retval = ms_erase_block(chip, phy_blk); + if (retval != STATUS_SUCCESS) + continue; + } + ms_set_unused_block(chip, phy_blk); + continue; + } + + if (segment->l2p_table[log_blk - ms_start_idx[seg_no]] == 0xFFFF) { + segment->l2p_table[log_blk - ms_start_idx[seg_no]] = phy_blk; + continue; + } + + us1 = extra[0] & 0x10; + tmp_blk = segment->l2p_table[log_blk - ms_start_idx[seg_no]]; + retval = ms_read_extra_data(chip, tmp_blk, 0, + extra, MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + continue; + us2 = extra[0] & 0x10; + + (void)ms_arbitrate_l2p(chip, phy_blk, + log_blk-ms_start_idx[seg_no], us1, us2); + continue; + } + + segment->build_flag = 1; + + RTSX_DEBUGP("unused block count: %d\n", segment->unused_blk_cnt); + + /* Logical Address Confirmation Process */ + if (seg_no == ms_card->segment_cnt - 1) { + if (segment->unused_blk_cnt < 2) + chip->card_wp |= MS_CARD; + } else { + if (segment->unused_blk_cnt < 1) + chip->card_wp |= MS_CARD; + } + + if (chip->card_wp & MS_CARD) + return STATUS_SUCCESS; + + for (log_blk = ms_start_idx[seg_no]; + log_blk < ms_start_idx[seg_no + 1]; log_blk++) { + if (segment->l2p_table[log_blk-ms_start_idx[seg_no]] == 0xFFFF) { + phy_blk = ms_get_unused_block(chip, seg_no); + if (phy_blk == 0xFFFF) { + chip->card_wp |= MS_CARD; + return STATUS_SUCCESS; + } + retval = ms_init_page(chip, phy_blk, log_blk, 0, 1); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, BUILD_FAIL); + + segment->l2p_table[log_blk-ms_start_idx[seg_no]] = phy_blk; + if (seg_no == ms_card->segment_cnt - 1) { + if (segment->unused_blk_cnt < 2) { + chip->card_wp |= MS_CARD; + return STATUS_SUCCESS; + } + } else { + if (segment->unused_blk_cnt < 1) { + chip->card_wp |= MS_CARD; + return STATUS_SUCCESS; + } + } + } + } + + /* Make boot block be the first normal block */ + if (seg_no == 0) { + for (log_blk = 0; log_blk < 494; log_blk++) { + tmp_blk = segment->l2p_table[log_blk]; + if (tmp_blk < ms_card->boot_block) { + RTSX_DEBUGP("Boot block is not the first normal block.\n"); + + if (chip->card_wp & MS_CARD) + break; + + phy_blk = ms_get_unused_block(chip, 0); + retval = ms_copy_page(chip, tmp_blk, phy_blk, + log_blk, 0, ms_card->page_off + 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + segment->l2p_table[log_blk] = phy_blk; + + retval = ms_set_bad_block(chip, tmp_blk); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + return STATUS_SUCCESS; + +BUILD_FAIL: + segment->build_flag = 0; + if (segment->l2p_table) { + vfree(segment->l2p_table); + segment->l2p_table = NULL; + } + if (segment->free_table) { + vfree(segment->free_table); + segment->free_table = NULL; + } + + return STATUS_FAIL; +} + + +int reset_ms_card(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + memset(ms_card, 0, sizeof(struct ms_info)); + + retval = enable_card_clock(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = select_card(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_card->ms_type = 0; + + retval = reset_ms_pro(chip); + if (retval != STATUS_SUCCESS) { + if (ms_card->check_ms_flow) { + retval = reset_ms(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } + + retval = ms_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!CHK_MSPRO(ms_card)) { + /* Build table for the last segment, + * to check if L2P table block exists, erasing it + */ + retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_DEBUGP("ms_card->ms_type = 0x%x\n", ms_card->ms_type); + + return STATUS_SUCCESS; +} + +static int mspro_set_rw_cmd(struct rtsx_chip *chip, + u32 start_sec, u16 sec_cnt, u8 cmd) +{ + int retval, i; + u8 data[8]; + + data[0] = cmd; + data[1] = (u8)(sec_cnt >> 8); + data[2] = (u8)sec_cnt; + data[3] = (u8)(start_sec >> 24); + data[4] = (u8)(start_sec >> 16); + data[5] = (u8)(start_sec >> 8); + data[6] = (u8)start_sec; + data[7] = 0; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, + WAIT_INT, data, 8); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + + +void mspro_stop_seq_mode(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + RTSX_DEBUGP("--%s--\n", __func__); + + if (ms_card->seq_mode) { + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + return; + + ms_card->seq_mode = 0; + ms_card->total_sec_cnt = 0; + ms_send_cmd(chip, PRO_STOP, WAIT_INT); + + rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + } +} + +static inline int ms_auto_tune_clock(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + RTSX_DEBUGP("--%s--\n", __func__); + + if (chip->asic_code) { + if (ms_card->ms_clock > 30) + ms_card->ms_clock -= 20; + } else { + if (ms_card->ms_clock == CLK_80) + ms_card->ms_clock = CLK_60; + else if (ms_card->ms_clock == CLK_60) + ms_card->ms_clock = CLK_40; + } + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int mspro_rw_multi_sector(struct scsi_cmnd *srb, + struct rtsx_chip *chip, u32 start_sector, + u16 sector_cnt) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, mode_2k = 0; + u16 count; + u8 val, trans_mode, rw_tpc, rw_cmd; + + ms_set_err_code(chip, MS_NO_ERROR); + + ms_card->cleanup_counter = 0; + + if (CHK_MSHG(ms_card)) { + if ((start_sector % 4) || (sector_cnt % 4)) { + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + rw_tpc = PRO_READ_LONG_DATA; + rw_cmd = PRO_READ_DATA; + } else { + rw_tpc = PRO_WRITE_LONG_DATA; + rw_cmd = PRO_WRITE_DATA; + } + } else { + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + rw_tpc = PRO_READ_QUAD_DATA; + rw_cmd = PRO_READ_2K_DATA; + } else { + rw_tpc = PRO_WRITE_QUAD_DATA; + rw_cmd = PRO_WRITE_2K_DATA; + } + mode_2k = 1; + } + } else { + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + rw_tpc = PRO_READ_LONG_DATA; + rw_cmd = PRO_READ_DATA; + } else { + rw_tpc = PRO_WRITE_LONG_DATA; + rw_cmd = PRO_WRITE_DATA; + } + } + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (srb->sc_data_direction == DMA_FROM_DEVICE) + trans_mode = MS_TM_AUTO_READ; + else + trans_mode = MS_TM_AUTO_WRITE; + + RTSX_READ_REG(chip, MS_TRANS_CFG, &val); + + if (ms_card->seq_mode) { + if ((ms_card->pre_dir != srb->sc_data_direction) + || ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != start_sector) + || (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) + || (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) + || !(val & MS_INT_BREQ) + || ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) { + ms_card->seq_mode = 0; + ms_card->total_sec_cnt = 0; + if (val & MS_INT_BREQ) { + retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + } + } + } + + if (!ms_card->seq_mode) { + ms_card->total_sec_cnt = 0; + if (sector_cnt >= SEQ_START_CRITERIA) { + if ((ms_card->capacity - start_sector) > 0xFE00) + count = 0xFE00; + else + count = (u16)(ms_card->capacity - start_sector); + + if (count > sector_cnt) { + if (mode_2k) + ms_card->seq_mode |= MODE_2K_SEQ; + else + ms_card->seq_mode |= MODE_512_SEQ; + } + } else { + count = sector_cnt; + } + retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd); + if (retval != STATUS_SUCCESS) { + ms_card->seq_mode = 0; + TRACE_RET(chip, STATUS_FAIL); + } + } + + retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt, + WAIT_INT, mode_2k, scsi_sg_count(srb), + scsi_sglist(srb), scsi_bufflen(srb)); + if (retval != STATUS_SUCCESS) { + ms_card->seq_mode = 0; + rtsx_read_register(chip, MS_TRANS_CFG, &val); + rtsx_clear_ms_error(chip); + + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + chip->rw_need_retry = 0; + RTSX_DEBUGP("No card exist, exit mspro_rw_multi_sector\n"); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & MS_INT_BREQ) + ms_send_cmd(chip, PRO_STOP, WAIT_INT); + + if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { + RTSX_DEBUGP("MSPro CRC error, tune clock!\n"); + chip->rw_need_retry = 1; + ms_auto_tune_clock(chip); + } + + TRACE_RET(chip, retval); + } + + if (ms_card->seq_mode) { + ms_card->pre_sec_addr = start_sector; + ms_card->pre_sec_cnt = sector_cnt; + ms_card->pre_dir = srb->sc_data_direction; + ms_card->total_sec_cnt += sector_cnt; + } + + return STATUS_SUCCESS; +} + +static int mspro_read_format_progress(struct rtsx_chip *chip, + const int short_data_len) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u32 total_progress, cur_progress; + u8 cnt, tmp; + u8 data[8]; + + RTSX_DEBUGP("mspro_read_format_progress, short_data_len = %d\n", + short_data_len); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp); + if (retval != STATUS_SUCCESS) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + if (!(tmp & MS_INT_BREQ)) { + if ((tmp & (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK | MS_INT_ERR)) == MS_INT_CED) { + ms_card->format_status = FORMAT_SUCCESS; + return STATUS_SUCCESS; + } + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + if (short_data_len >= 256) + cnt = 0; + else + cnt = (u8)short_data_len; + + retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, + MS_NO_CHECK_INT); + if (retval != STATUS_SUCCESS) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT, + data, 8); + if (retval != STATUS_SUCCESS) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + total_progress = (data[0] << 24) | (data[1] << 16) | + (data[2] << 8) | data[3]; + cur_progress = (data[4] << 24) | (data[5] << 16) | + (data[6] << 8) | data[7]; + + RTSX_DEBUGP("total_progress = %d, cur_progress = %d\n", + total_progress, cur_progress); + + if (total_progress == 0) { + ms_card->progress = 0; + } else { + u64 ulltmp = (u64)cur_progress * (u64)65535; + do_div(ulltmp, total_progress); + ms_card->progress = (u16)ulltmp; + } + RTSX_DEBUGP("progress = %d\n", ms_card->progress); + + for (i = 0; i < 5000; i++) { + retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp); + if (retval != STATUS_SUCCESS) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + if (tmp & (MS_INT_CED | MS_INT_CMDNK | + MS_INT_BREQ | MS_INT_ERR)) + break; + + wait_timeout(1); + } + + retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0); + if (retval != STATUS_SUCCESS) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + if (i == 5000) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) { + ms_card->format_status = FORMAT_FAIL; + TRACE_RET(chip, STATUS_FAIL); + } + + if (tmp & MS_INT_CED) { + ms_card->format_status = FORMAT_SUCCESS; + ms_card->pro_under_formatting = 0; + } else if (tmp & MS_INT_BREQ) { + ms_card->format_status = FORMAT_IN_PROGRESS; + } else { + ms_card->format_status = FORMAT_FAIL; + ms_card->pro_under_formatting = 0; + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +void mspro_polling_format_status(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int i; + + if (ms_card->pro_under_formatting && + (rtsx_get_stat(chip) != RTSX_STAT_SS)) { + rtsx_set_stat(chip, RTSX_STAT_RUN); + + for (i = 0; i < 65535; i++) { + mspro_read_format_progress(chip, MS_SHORT_DATA_LEN); + if (ms_card->format_status != FORMAT_IN_PROGRESS) + break; + } + } + + return; +} + +int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, + int short_data_len, int quick_format) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 buf[8], tmp; + u16 para; + + RTSX_DEBUGP("--%s--\n", __func__); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + memset(buf, 0, 2); + switch (short_data_len) { + case 32: + buf[0] = 0; + break; + case 64: + buf[0] = 1; + break; + case 128: + buf[0] = 2; + break; + case 256: + default: + buf[0] = 3; + break; + } + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, PRO_WRITE_REG, 1, + NO_WAIT_INT, buf, 2); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + if (quick_format) + para = 0x0000; + else + para = 0x0001; + + retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_READ_REG(chip, MS_TRANS_CFG, &tmp); + + if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) + TRACE_RET(chip, STATUS_FAIL); + + if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) { + ms_card->pro_under_formatting = 1; + ms_card->progress = 0; + ms_card->format_status = FORMAT_IN_PROGRESS; + return STATUS_SUCCESS; + } + + if (tmp & MS_INT_CED) { + ms_card->pro_under_formatting = 0; + ms_card->progress = 0; + ms_card->format_status = FORMAT_SUCCESS; + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE); + return STATUS_SUCCESS; + } + + TRACE_RET(chip, STATUS_FAIL); +} + + +static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, + u16 log_blk, u8 start_page, u8 end_page, + u8 *buf, unsigned int *index, + unsigned int *offset) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6]; + u8 *ptr; + + retval = ms_read_extra_data(chip, phy_blk, start_page, + extra, MS_EXTRA_SIZE); + if (retval == STATUS_SUCCESS) { + if ((extra[1] & 0x30) != 0x30) { + ms_set_err_code(chip, MS_FLASH_READ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(phy_blk >> 8); + data[3] = (u8)phy_blk; + data[4] = 0; + data[5] = start_page; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, + data, 6); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ptr = buf; + + for (page_addr = start_page; page_addr < end_page; page_addr++) { + ms_set_err_code(chip, MS_NO_ERROR); + + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + if (val & INT_REG_ERR) { + if (val & INT_REG_BREQ) { + retval = ms_read_status_reg(chip); + if (retval != STATUS_SUCCESS) { + if (!(chip->card_wp & MS_CARD)) { + reset_ms(chip); + ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE); + ms_write_extra_data(chip, phy_blk, + page_addr, extra, MS_EXTRA_SIZE); + } + ms_set_err_code(chip, MS_FLASH_READ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } else { + ms_set_err_code(chip, MS_FLASH_READ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } else { + if (!(val & INT_REG_BREQ)) { + ms_set_err_code(chip, MS_BREQ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (page_addr == (end_page - 1)) { + if (!(val & INT_REG_CED)) { + retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, + &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!(val & INT_REG_CED)) { + ms_set_err_code(chip, MS_FLASH_READ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + + trans_cfg = NO_WAIT_INT; + } else { + trans_cfg = WAIT_INT; + } + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, + 0xFF, trans_cfg); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, RING_BUFFER); + + trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, + MS_TRANSFER_START | MS_TM_NORMAL_READ); + rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, + MS_TRANSFER_END, MS_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, + 512, scsi_sg_count(chip->srb), + index, offset, DMA_FROM_DEVICE, + chip->ms_timeout); + if (retval < 0) { + if (retval == -ETIMEDOUT) { + ms_set_err_code(chip, MS_TO_ERROR); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_TIMEDOUT); + } + + retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); + if (retval != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_TO_ERROR); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_TIMEDOUT); + } + if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { + ms_set_err_code(chip, MS_CRC16_ERROR); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (scsi_sg_count(chip->srb) == 0) + ptr += 512; + } + + return STATUS_SUCCESS; +} + +static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, + u16 new_blk, u16 log_blk, u8 start_page, + u8 end_page, u8 *buf, unsigned int *index, + unsigned int *offset) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, i; + u8 page_addr, val, data[16]; + u8 *ptr; + + if (!start_page) { + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, 7); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(old_blk >> 8); + data[3] = (u8)old_blk; + data[4] = 0x80; + data[5] = 0; + data[6] = 0xEF; + data[7] = 0xFF; + + retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, + data, 8); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, + NO_WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, + SystemParm, (6 + MS_EXTRA_SIZE)); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ms_set_err_code(chip, MS_NO_ERROR); + + if (CHK_MS4BIT(ms_card)) + data[0] = 0x88; + else + data[0] = 0x80; + + data[1] = 0; + data[2] = (u8)(new_blk >> 8); + data[3] = (u8)new_blk; + if ((end_page - start_page) == 1) + data[4] = 0x20; + else + data[4] = 0; + + data[5] = start_page; + data[6] = 0xF8; + data[7] = 0xFF; + data[8] = (u8)(log_blk >> 8); + data[9] = (u8)log_blk; + + for (i = 0x0A; i < 0x10; i++) + data[i] = 0xFF; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE, + NO_WAIT_INT, data, 16); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + ptr = buf; + for (page_addr = start_page; page_addr < end_page; page_addr++) { + ms_set_err_code(chip, MS_NO_ERROR); + + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + ms_set_err_code(chip, MS_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + if (val & INT_REG_CMDNK) { + ms_set_err_code(chip, MS_CMD_NK); + TRACE_RET(chip, STATUS_FAIL); + } + if (val & INT_REG_ERR) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + if (!(val & INT_REG_BREQ)) { + ms_set_err_code(chip, MS_BREQ_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + + udelay(30); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, + 0xFF, WRITE_PAGE_DATA); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, + 0xFF, WAIT_INT); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, RING_BUFFER); + + trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, + MS_TRANSFER_START | MS_TM_NORMAL_WRITE); + rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, + MS_TRANSFER_END, MS_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, + 512, scsi_sg_count(chip->srb), + index, offset, DMA_TO_DEVICE, + chip->ms_timeout); + if (retval < 0) { + ms_set_err_code(chip, MS_TO_ERROR); + rtsx_clear_ms_error(chip); + + if (retval == -ETIMEDOUT) + TRACE_RET(chip, STATUS_TIMEDOUT); + else + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if ((end_page - start_page) == 1) { + if (!(val & INT_REG_CED)) { + ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } else { + if (page_addr == (end_page - 1)) { + if (!(val & INT_REG_CED)) { + retval = ms_send_cmd(chip, BLOCK_END, + WAIT_INT); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, GET_INT, 1, + NO_WAIT_INT, &val, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + if ((page_addr == (end_page - 1)) || + (page_addr == ms_card->page_off)) { + if (!(val & INT_REG_CED)) { + ms_set_err_code(chip, + MS_FLASH_WRITE_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + if (scsi_sg_count(chip->srb) == 0) + ptr += 512; + } + + return STATUS_SUCCESS; +} + + +static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, + u16 log_blk, u8 page_off) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval, seg_no; + + retval = ms_copy_page(chip, old_blk, new_blk, log_blk, + page_off, ms_card->page_off + 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + seg_no = old_blk >> 9; + + if (MS_TST_BAD_BLOCK_FLG(ms_card)) { + MS_CLR_BAD_BLOCK_FLG(ms_card); + ms_set_bad_block(chip, old_blk); + } else { + retval = ms_erase_block(chip, old_blk); + if (retval == STATUS_SUCCESS) + ms_set_unused_block(chip, old_blk); + } + + ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk); + + return STATUS_SUCCESS; +} + +static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, + u16 log_blk, u8 start_page) +{ + int retval; + + if (start_page) { + retval = ms_copy_page(chip, old_blk, new_blk, log_blk, + 0, start_page); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +#ifdef MS_DELAY_WRITE +int ms_delay_write(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); + int retval; + + if (delay_write->delay_write_flag) { + retval = ms_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + delay_write->delay_write_flag = 0; + retval = ms_finish_write(chip, + delay_write->old_phyblock, + delay_write->new_phyblock, + delay_write->logblock, + delay_write->pageoff); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} +#endif + +static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + if (srb->sc_data_direction == DMA_FROM_DEVICE) + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + else + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); +} + +static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 start_sector, u16 sector_cnt) +{ + struct ms_info *ms_card = &(chip->ms_card); + unsigned int lun = SCSI_LUN(srb); + int retval, seg_no; + unsigned int index = 0, offset = 0; + u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt; + u8 start_page, end_page = 0, page_cnt; + u8 *ptr; +#ifdef MS_DELAY_WRITE + struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); +#endif + + ms_set_err_code(chip, MS_NO_ERROR); + + ms_card->cleanup_counter = 0; + + ptr = (u8 *)scsi_sglist(srb); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + ms_rw_fail(srb, chip); + TRACE_RET(chip, STATUS_FAIL); + } + + log_blk = (u16)(start_sector >> ms_card->block_shift); + start_page = (u8)(start_sector & ms_card->page_off); + + for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) { + if (log_blk < ms_start_idx[seg_no+1]) + break; + } + + if (ms_card->segment[seg_no].build_flag == 0) { + retval = ms_build_l2p_tbl(chip, seg_no); + if (retval != STATUS_SUCCESS) { + chip->card_fail |= MS_CARD; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { +#ifdef MS_DELAY_WRITE + if (delay_write->delay_write_flag && + (delay_write->logblock == log_blk) && + (start_page > delay_write->pageoff)) { + delay_write->delay_write_flag = 0; + retval = ms_copy_page(chip, + delay_write->old_phyblock, + delay_write->new_phyblock, log_blk, + delay_write->pageoff, start_page); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + old_blk = delay_write->old_phyblock; + new_blk = delay_write->new_phyblock; + } else if (delay_write->delay_write_flag && + (delay_write->logblock == log_blk) && + (start_page == delay_write->pageoff)) { + delay_write->delay_write_flag = 0; + old_blk = delay_write->old_phyblock; + new_blk = delay_write->new_phyblock; + } else { + retval = ms_delay_write(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + old_blk = ms_get_l2p_tbl(chip, seg_no, + log_blk - ms_start_idx[seg_no]); + new_blk = ms_get_unused_block(chip, seg_no); + if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_prepare_write(chip, old_blk, new_blk, + log_blk, start_page); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#ifdef MS_DELAY_WRITE + } +#endif + } else { +#ifdef MS_DELAY_WRITE + retval = ms_delay_write(chip); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + old_blk = ms_get_l2p_tbl(chip, seg_no, + log_blk - ms_start_idx[seg_no]); + if (old_blk == 0xFFFF) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", + seg_no, old_blk, new_blk); + + while (total_sec_cnt) { + if ((start_page + total_sec_cnt) > (ms_card->page_off + 1)) + end_page = ms_card->page_off + 1; + else + end_page = start_page + (u8)total_sec_cnt; + + page_cnt = end_page - start_page; + + RTSX_DEBUGP("start_page = %d, end_page = %d, page_cnt = %d\n", + start_page, end_page, page_cnt); + + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + retval = ms_read_multiple_pages(chip, + old_blk, log_blk, start_page, end_page, + ptr, &index, &offset); + } else { + retval = ms_write_multiple_pages(chip, old_blk, + new_blk, log_blk, start_page, end_page, + ptr, &index, &offset); + } + + if (retval != STATUS_SUCCESS) { + toggle_gpio(chip, 1); + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + ms_rw_fail(srb, chip); + TRACE_RET(chip, STATUS_FAIL); + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { + if (end_page == (ms_card->page_off + 1)) { + retval = ms_erase_block(chip, old_blk); + if (retval == STATUS_SUCCESS) + ms_set_unused_block(chip, old_blk); + + ms_set_l2p_tbl(chip, seg_no, + log_blk - ms_start_idx[seg_no], + new_blk); + } + } + + total_sec_cnt -= page_cnt; + if (scsi_sg_count(srb) == 0) + ptr += page_cnt * 512; + + if (total_sec_cnt == 0) + break; + + log_blk++; + + for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; + seg_no++) { + if (log_blk < ms_start_idx[seg_no+1]) + break; + } + + if (ms_card->segment[seg_no].build_flag == 0) { + retval = ms_build_l2p_tbl(chip, seg_no); + if (retval != STATUS_SUCCESS) { + chip->card_fail |= MS_CARD; + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + } + + old_blk = ms_get_l2p_tbl(chip, seg_no, + log_blk - ms_start_idx[seg_no]); + if (old_blk == 0xFFFF) { + ms_rw_fail(srb, chip); + TRACE_RET(chip, STATUS_FAIL); + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { + new_blk = ms_get_unused_block(chip, seg_no); + if (new_blk == 0xFFFF) { + ms_rw_fail(srb, chip); + TRACE_RET(chip, STATUS_FAIL); + } + } + + RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", + seg_no, old_blk, new_blk); + + start_page = 0; + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { + if (end_page < (ms_card->page_off + 1)) { +#ifdef MS_DELAY_WRITE + delay_write->delay_write_flag = 1; + delay_write->old_phyblock = old_blk; + delay_write->new_phyblock = new_blk; + delay_write->logblock = log_blk; + delay_write->pageoff = end_page; +#else + retval = ms_finish_write(chip, old_blk, new_blk, + log_blk, end_page); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + + ms_rw_fail(srb, chip); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + } + } + + scsi_set_resid(srb, 0); + + return STATUS_SUCCESS; +} + +int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 start_sector, u16 sector_cnt) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + if (CHK_MSPRO(ms_card)) + retval = mspro_rw_multi_sector(srb, chip, start_sector, + sector_cnt); + else + retval = ms_rw_multi_sector(srb, chip, start_sector, + sector_cnt); + + return retval; +} + + +void ms_free_l2p_tbl(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int i = 0; + + if (ms_card->segment != NULL) { + for (i = 0; i < ms_card->segment_cnt; i++) { + if (ms_card->segment[i].l2p_table != NULL) { + vfree(ms_card->segment[i].l2p_table); + ms_card->segment[i].l2p_table = NULL; + } + if (ms_card->segment[i].free_table != NULL) { + vfree(ms_card->segment[i].free_table); + ms_card->segment[i].free_table = NULL; + } + } + vfree(ms_card->segment); + ms_card->segment = NULL; + } +} + +#ifdef SUPPORT_MAGIC_GATE + +#ifdef READ_BYTES_WAIT_INT +static int ms_poll_int(struct rtsx_chip *chip) +{ + int retval; + u8 val; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED); + + retval = rtsx_send_cmd(chip, MS_CARD, 5000); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + val = *rtsx_get_cmd_data(chip); + if (val & MS_INT_ERR) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} +#endif + +#ifdef MS_SAMPLE_INT_ERR +static int check_ms_err(struct rtsx_chip *chip) +{ + int retval; + u8 val; + + retval = rtsx_read_register(chip, MS_TRANSFER, &val); + if (retval != STATUS_SUCCESS) + return 1; + if (val & MS_TRANSFER_ERR) + return 1; + + retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); + if (retval != STATUS_SUCCESS) + return 1; + + if (val & (MS_INT_ERR | MS_INT_CMDNK)) + return 1; + + return 0; +} +#else +static int check_ms_err(struct rtsx_chip *chip) +{ + int retval; + u8 val; + + retval = rtsx_read_register(chip, MS_TRANSFER, &val); + if (retval != STATUS_SUCCESS) + return 1; + if (val & MS_TRANSFER_ERR) + return 1; + + return 0; +} +#endif + +static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num) +{ + int retval, i; + u8 data[8]; + + data[0] = cmd; + data[1] = 0; + data[2] = 0; + data[3] = 0; + data[4] = 0; + data[5] = 0; + data[6] = entry_num; + data[7] = 0; + + for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { + retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, + data, 8); + if (retval == STATUS_SUCCESS) + break; + } + if (i == MS_MAX_RETRY_COUNT) + TRACE_RET(chip, STATUS_FAIL); + + if (check_ms_err(chip)) { + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, + u8 mg_entry_num) +{ + int retval; + u8 buf[6]; + + RTSX_DEBUGP("--%s--\n", __func__); + + if (type == 0) + retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1); + else + retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); + + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf[0] = 0; + buf[1] = 0; + if (type == 1) { + buf[2] = 0; + buf[3] = 0; + buf[4] = 0; + buf[5] = mg_entry_num; + } + retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, + NO_WAIT_INT, buf, 6); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + int i; + unsigned int lun = SCSI_LUN(srb); + u8 buf1[32], buf2[12]; + + RTSX_DEBUGP("--%s--\n", __func__); + + if (scsi_bufflen(srb) < 12) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, STATUS_FAIL); + } + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = mg_send_ex_cmd(chip, MG_SET_LID, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + TRACE_RET(chip, STATUS_FAIL); + } + + memset(buf1, 0, 32); + rtsx_stor_get_xfer_buf(buf2, min_t(int, 12, scsi_bufflen(srb)), srb); + for (i = 0; i < 8; i++) + buf1[8+i] = buf2[4+i]; + + retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, + buf1, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + TRACE_RET(chip, STATUS_FAIL); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval = STATUS_FAIL; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 *buf = NULL; + + RTSX_DEBUGP("--%s--\n", __func__); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf = kmalloc(1540, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + buf[0] = 0x04; + buf[1] = 0x1A; + buf[2] = 0x00; + buf[3] = 0x00; + + retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_GOTO(chip, GetEKBFinish); + } + + retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, + 3, WAIT_INT, 0, 0, buf + 4, 1536); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + rtsx_clear_ms_error(chip); + TRACE_GOTO(chip, GetEKBFinish); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + bufflen = min_t(int, 1052, scsi_bufflen(srb)); + rtsx_stor_set_xfer_buf(buf, bufflen, srb); + +GetEKBFinish: + kfree(buf); + return retval; +} + +int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; + int i; + unsigned int lun = SCSI_LUN(srb); + u8 buf[32]; + + RTSX_DEBUGP("--%s--\n", __func__); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = mg_send_ex_cmd(chip, MG_GET_ID, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, + buf, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, STATUS_FAIL); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + memcpy(ms_card->magic_gate_id, buf, 16); + +#ifdef READ_BYTES_WAIT_INT + retval = ms_poll_int(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + + retval = mg_send_ex_cmd(chip, MG_SET_RD, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, STATUS_FAIL); + } + + bufflen = min_t(int, 12, scsi_bufflen(srb)); + rtsx_stor_get_xfer_buf(buf, bufflen, srb); + + for (i = 0; i < 8; i++) + buf[i] = buf[4+i]; + + for (i = 0; i < 24; i++) + buf[8+i] = 0; + + retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, + 32, WAIT_INT, buf, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, STATUS_FAIL); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + ms_card->mg_auth = 0; + + return STATUS_SUCCESS; +} + +int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 buf1[32], buf2[36]; + + RTSX_DEBUGP("--%s--\n", __func__); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, + buf1, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, STATUS_FAIL); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + buf2[0] = 0x00; + buf2[1] = 0x22; + buf2[2] = 0x00; + buf2[3] = 0x00; + + memcpy(buf2 + 4, ms_card->magic_gate_id, 16); + memcpy(buf2 + 20, buf1, 16); + + bufflen = min_t(int, 36, scsi_bufflen(srb)); + rtsx_stor_set_xfer_buf(buf2, bufflen, srb); + +#ifdef READ_BYTES_WAIT_INT + retval = ms_poll_int(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + + return STATUS_SUCCESS; +} + +int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int i; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 buf[32]; + + RTSX_DEBUGP("--%s--\n", __func__); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, STATUS_FAIL); + } + + bufflen = min_t(int, 12, scsi_bufflen(srb)); + rtsx_stor_get_xfer_buf(buf, bufflen, srb); + + for (i = 0; i < 8; i++) + buf[i] = buf[4+i]; + + for (i = 0; i < 24; i++) + buf[8+i] = 0; + + retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, + buf, 32); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + TRACE_RET(chip, STATUS_FAIL); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + ms_card->mg_auth = 1; + + return STATUS_SUCCESS; +} + +int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; + unsigned int lun = SCSI_LUN(srb); + u8 *buf = NULL; + + RTSX_DEBUGP("--%s--\n", __func__); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf = kmalloc(1028, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + buf[0] = 0x04; + buf[1] = 0x02; + buf[2] = 0x00; + buf[3] = 0x00; + + retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_GOTO(chip, GetICVFinish); + } + + retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, + 2, WAIT_INT, 0, 0, buf + 4, 1024); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + rtsx_clear_ms_error(chip); + TRACE_GOTO(chip, GetICVFinish); + } + if (check_ms_err(chip)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + rtsx_clear_ms_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + bufflen = min_t(int, 1028, scsi_bufflen(srb)); + rtsx_stor_set_xfer_buf(buf, bufflen, srb); + +GetICVFinish: + kfree(buf); + return retval; +} + +int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + int bufflen; +#ifdef MG_SET_ICV_SLOW + int i; +#endif + unsigned int lun = SCSI_LUN(srb); + u8 *buf = NULL; + + RTSX_DEBUGP("--%s--\n", __func__); + + ms_cleanup_work(chip); + + retval = ms_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf = kmalloc(1028, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + bufflen = min_t(int, 1028, scsi_bufflen(srb)); + rtsx_stor_get_xfer_buf(buf, bufflen, srb); + + retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num); + if (retval != STATUS_SUCCESS) { + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) + set_sense_type(chip, lun, + SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + else + set_sense_type(chip, lun, + SENSE_TYPE_MG_WRITE_ERR); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + TRACE_GOTO(chip, SetICVFinish); + } + +#ifdef MG_SET_ICV_SLOW + for (i = 0; i < 2; i++) { + udelay(50); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, + 0xFF, PRO_WRITE_LONG_DATA); + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, RING_BUFFER); + + trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, + MS_TRANSFER_START | MS_TM_NORMAL_WRITE); + rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, + MS_TRANSFER_END, MS_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i*512, + 512, 0, DMA_TO_DEVICE, 3000); + if ((retval < 0) || check_ms_err(chip)) { + rtsx_clear_ms_error(chip); + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) + set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + else + set_sense_type(chip, lun, + SENSE_TYPE_MG_WRITE_ERR); + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MG_WRITE_ERR); + } + retval = STATUS_FAIL; + TRACE_GOTO(chip, SetICVFinish); + } + } +#else + retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA, + 2, WAIT_INT, 0, 0, buf + 4, 1024); + if ((retval != STATUS_SUCCESS) || check_ms_err(chip)) { + rtsx_clear_ms_error(chip); + if (ms_card->mg_auth == 0) { + if ((buf[5] & 0xC0) != 0) + set_sense_type(chip, lun, + SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); + else + set_sense_type(chip, lun, + SENSE_TYPE_MG_WRITE_ERR); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); + } + TRACE_GOTO(chip, SetICVFinish); + } +#endif + +SetICVFinish: + kfree(buf); + return retval; +} + +#endif /* SUPPORT_MAGIC_GATE */ + +void ms_cleanup_work(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + + if (CHK_MSPRO(ms_card)) { + if (ms_card->seq_mode) { + RTSX_DEBUGP("MS Pro: stop transmission\n"); + mspro_stop_seq_mode(chip); + ms_card->cleanup_counter = 0; + } + if (CHK_MSHG(ms_card)) { + rtsx_write_register(chip, MS_CFG, + MS_2K_SECTOR_MODE, 0x00); + } + } +#ifdef MS_DELAY_WRITE + else if ((!CHK_MSPRO(ms_card)) && ms_card->delay_write.delay_write_flag) { + RTSX_DEBUGP("MS: delay write\n"); + ms_delay_write(chip); + ms_card->cleanup_counter = 0; + } +#endif +} + +int ms_power_off_card3v3(struct rtsx_chip *chip) +{ + int retval; + + retval = disable_card_clock(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (chip->asic_code) { + retval = ms_pull_ctl_disable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, + FPGA_MS_PULL_CTL_BIT | 0x20, FPGA_MS_PULL_CTL_BIT); + } + RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, 0); + if (!chip->ft2_fast_mode) { + retval = card_power_off(chip, MS_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int release_ms_card(struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + int retval; + + RTSX_DEBUGP("release_ms_card\n"); + +#ifdef MS_DELAY_WRITE + ms_card->delay_write.delay_write_flag = 0; +#endif + ms_card->pro_under_formatting = 0; + + chip->card_ready &= ~MS_CARD; + chip->card_fail &= ~MS_CARD; + chip->card_wp &= ~MS_CARD; + + ms_free_l2p_tbl(chip); + + memset(ms_card->raw_sys_info, 0, 96); +#ifdef SUPPORT_PCGL_1P18 + memset(ms_card->raw_model_name, 0, 48); +#endif + + retval = ms_power_off_card3v3(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h new file mode 100644 index 000000000000..26c5b03d535e --- /dev/null +++ b/drivers/staging/rts5208/ms.h @@ -0,0 +1,227 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_MS_H +#define __REALTEK_RTSX_MS_H + +#define MS_DELAY_WRITE + +#define MS_MAX_RETRY_COUNT 3 + +#define MS_EXTRA_SIZE 0x9 + +#define WRT_PRTCT 0x01 + +/* Error Code */ +#define MS_NO_ERROR 0x00 +#define MS_CRC16_ERROR 0x80 +#define MS_TO_ERROR 0x40 +#define MS_NO_CARD 0x20 +#define MS_NO_MEMORY 0x10 +#define MS_CMD_NK 0x08 +#define MS_FLASH_READ_ERROR 0x04 +#define MS_FLASH_WRITE_ERROR 0x02 +#define MS_BREQ_ERROR 0x01 +#define MS_NOT_FOUND 0x03 + +/* Transfer Protocol Command */ +#define READ_PAGE_DATA 0x02 +#define READ_REG 0x04 +#define GET_INT 0x07 +#define WRITE_PAGE_DATA 0x0D +#define WRITE_REG 0x0B +#define SET_RW_REG_ADRS 0x08 +#define SET_CMD 0x0E + +#define PRO_READ_LONG_DATA 0x02 +#define PRO_READ_SHORT_DATA 0x03 +#define PRO_READ_REG 0x04 +#define PRO_READ_QUAD_DATA 0x05 +#define PRO_GET_INT 0x07 +#define PRO_WRITE_LONG_DATA 0x0D +#define PRO_WRITE_SHORT_DATA 0x0C +#define PRO_WRITE_QUAD_DATA 0x0A +#define PRO_WRITE_REG 0x0B +#define PRO_SET_RW_REG_ADRS 0x08 +#define PRO_SET_CMD 0x0E +#define PRO_EX_SET_CMD 0x09 + +#ifdef SUPPORT_MAGIC_GATE + +#define MG_GET_ID 0x40 +#define MG_SET_LID 0x41 +#define MG_GET_LEKB 0x42 +#define MG_SET_RD 0x43 +#define MG_MAKE_RMS 0x44 +#define MG_MAKE_KSE 0x45 +#define MG_SET_IBD 0x46 +#define MG_GET_IBD 0x47 + +#endif + +#ifdef XC_POWERCLASS +#define XC_CHG_POWER 0x16 +#endif + +#define BLOCK_READ 0xAA +#define BLOCK_WRITE 0x55 +#define BLOCK_END 0x33 +#define BLOCK_ERASE 0x99 +#define FLASH_STOP 0xCC + +#define SLEEP 0x5A +#define CLEAR_BUF 0xC3 +#define MS_RESET 0x3C + +#define PRO_READ_DATA 0x20 +#define PRO_WRITE_DATA 0x21 +#define PRO_READ_ATRB 0x24 +#define PRO_STOP 0x25 +#define PRO_ERASE 0x26 +#define PRO_READ_2K_DATA 0x27 +#define PRO_WRITE_2K_DATA 0x28 + +#define PRO_FORMAT 0x10 +#define PRO_SLEEP 0x11 + +#define IntReg 0x01 +#define StatusReg0 0x02 +#define StatusReg1 0x03 + +#define SystemParm 0x10 +#define BlockAdrs 0x11 +#define CMDParm 0x14 +#define PageAdrs 0x15 + +#define OverwriteFlag 0x16 +#define ManagemenFlag 0x17 +#define LogicalAdrs 0x18 +#define ReserveArea 0x1A + +#define Pro_IntReg 0x01 +#define Pro_StatusReg 0x02 +#define Pro_TypeReg 0x04 +#define Pro_IFModeReg 0x05 +#define Pro_CatagoryReg 0x06 +#define Pro_ClassReg 0x07 + + +#define Pro_SystemParm 0x10 +#define Pro_DataCount1 0x11 +#define Pro_DataCount0 0x12 +#define Pro_DataAddr3 0x13 +#define Pro_DataAddr2 0x14 +#define Pro_DataAddr1 0x15 +#define Pro_DataAddr0 0x16 + +#define Pro_TPCParm 0x17 +#define Pro_CMDParm 0x18 + +#define INT_REG_CED 0x80 +#define INT_REG_ERR 0x40 +#define INT_REG_BREQ 0x20 +#define INT_REG_CMDNK 0x01 + +#define BLOCK_BOOT 0xC0 +#define BLOCK_OK 0x80 +#define PAGE_OK 0x60 +#define DATA_COMPL 0x10 + +#define NOT_BOOT_BLOCK 0x4 +#define NOT_TRANSLATION_TABLE 0x8 + +#define HEADER_ID0 PPBUF_BASE2 +#define HEADER_ID1 (PPBUF_BASE2 + 1) +#define DISABLED_BLOCK0 (PPBUF_BASE2 + 0x170 + 4) +#define DISABLED_BLOCK1 (PPBUF_BASE2 + 0x170 + 5) +#define DISABLED_BLOCK2 (PPBUF_BASE2 + 0x170 + 6) +#define DISABLED_BLOCK3 (PPBUF_BASE2 + 0x170 + 7) +#define BLOCK_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 2) +#define BLOCK_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 3) +#define BLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 4) +#define BLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 5) +#define EBLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 6) +#define EBLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 7) +#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8) +#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9) + +#define MS_Device_Type (PPBUF_BASE2 + 0x1D8) + +#define MS_4bit_Support (PPBUF_BASE2 + 0x1D3) + +#define setPS_NG 1 +#define setPS_Error 0 + +#define PARALLEL_8BIT_IF 0x40 +#define PARALLEL_4BIT_IF 0x00 +#define SERIAL_IF 0x80 + +#define BUF_FULL 0x10 +#define BUF_EMPTY 0x20 + +#define MEDIA_BUSY 0x80 +#define FLASH_BUSY 0x40 +#define DATA_ERROR 0x20 +#define STS_UCDT 0x10 +#define EXTRA_ERROR 0x08 +#define STS_UCEX 0x04 +#define FLAG_ERROR 0x02 +#define STS_UCFG 0x01 + +#define MS_SHORT_DATA_LEN 32 + +#define FORMAT_SUCCESS 0 +#define FORMAT_FAIL 1 +#define FORMAT_IN_PROGRESS 2 + +#define MS_SET_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag |= 0x80) +#define MS_CLR_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag &= 0x7F) +#define MS_TST_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag & 0x80) + +void mspro_polling_format_status(struct rtsx_chip *chip); + +void mspro_stop_seq_mode(struct rtsx_chip *chip); +int reset_ms_card(struct rtsx_chip *chip); +int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 start_sector, u16 sector_cnt); +int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, + int short_data_len, int quick_format); +void ms_free_l2p_tbl(struct rtsx_chip *chip); +void ms_cleanup_work(struct rtsx_chip *chip); +int ms_power_off_card3v3(struct rtsx_chip *chip); +int release_ms_card(struct rtsx_chip *chip); +#ifdef MS_DELAY_WRITE +int ms_delay_write(struct rtsx_chip *chip); +#endif + +#ifdef SUPPORT_MAGIC_GATE +int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip); +#endif + +#endif /* __REALTEK_RTSX_MS_H */ diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c new file mode 100644 index 000000000000..7882f578a8d9 --- /dev/null +++ b/drivers/staging/rts5208/rtsx.c @@ -0,0 +1,1069 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_chip.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" +#include "general.h" + +#include "ms.h" +#include "sd.h" +#include "xd.h" + +MODULE_DESCRIPTION("Realtek PCI-Express card reader rts5208/rts5288 driver"); +MODULE_LICENSE("GPL"); + +static unsigned int delay_use = 1; +module_param(delay_use, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); + +static int ss_en; +module_param(ss_en, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ss_en, "enable selective suspend"); + +static int ss_interval = 50; +module_param(ss_interval, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds"); + +static int auto_delink_en; +module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); + +static unsigned char aspm_l0s_l1_en; +module_param(aspm_l0s_l1_en, byte, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm"); + +static int msi_en; +module_param(msi_en, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(msi_en, "enable msi"); + +static irqreturn_t rtsx_interrupt(int irq, void *dev_id); + +/*********************************************************************** + * Host functions + ***********************************************************************/ + +static const char *host_info(struct Scsi_Host *host) +{ + return "SCSI emulation for PCI-Express Mass Storage devices"; +} + +static int slave_alloc(struct scsi_device *sdev) +{ + /* + * Set the INQUIRY transfer length to 36. We don't use any of + * the extra data and many devices choke if asked for more or + * less than 36 bytes. + */ + sdev->inquiry_len = 36; + return 0; +} + +static int slave_configure(struct scsi_device *sdev) +{ + /* Scatter-gather buffers (all but the last) must have a length + * divisible by the bulk maxpacket size. Otherwise a data packet + * would end up being short, causing a premature end to the data + * transfer. Since high-speed bulk pipes have a maxpacket size + * of 512, we'll use that as the scsi device queue's DMA alignment + * mask. Guaranteeing proper alignment of the first buffer will + * have the desired effect because, except at the beginning and + * the end, scatter-gather buffers follow page boundaries. */ + blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); + + /* Set the SCSI level to at least 2. We'll leave it at 3 if that's + * what is originally reported. We need this to avoid confusing + * the SCSI layer with devices that report 0 or 1, but need 10-byte + * commands (ala ATAPI devices behind certain bridges, or devices + * which simply have broken INQUIRY data). + * + * NOTE: This means /dev/sg programs (ala cdrecord) will get the + * actual information. This seems to be the preference for + * programs like that. + * + * NOTE: This also means that /proc/scsi/scsi and sysfs may report + * the actual value or the modified one, depending on where the + * data comes from. + */ + if (sdev->scsi_level < SCSI_2) + sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; + + return 0; +} + + +/*********************************************************************** + * /proc/scsi/ functions + ***********************************************************************/ + +/* we use this macro to help us write into the buffer */ +#undef SPRINTF +#define SPRINTF(args...) \ + do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) + +/* queue a command */ +/* This is always called with scsi_lock(host) held */ +static int queuecommand_lck(struct scsi_cmnd *srb, + void (*done)(struct scsi_cmnd *)) +{ + struct rtsx_dev *dev = host_to_rtsx(srb->device->host); + struct rtsx_chip *chip = dev->chip; + + /* check for state-transition errors */ + if (chip->srb != NULL) { + dev_err(&dev->pci->dev, "Error in %s: chip->srb = %p\n", + __func__, chip->srb); + return SCSI_MLQUEUE_HOST_BUSY; + } + + /* fail the command if we are disconnecting */ + if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { + dev_info(&dev->pci->dev, "Fail command during disconnect\n"); + srb->result = DID_NO_CONNECT << 16; + done(srb); + return 0; + } + + /* enqueue the command and wake up the control thread */ + srb->scsi_done = done; + chip->srb = srb; + complete(&dev->cmnd_ready); + + return 0; +} + +static DEF_SCSI_QCMD(queuecommand) + +/*********************************************************************** + * Error handling functions + ***********************************************************************/ + +/* Command timeout and abort */ +static int command_abort(struct scsi_cmnd *srb) +{ + struct Scsi_Host *host = srb->device->host; + struct rtsx_dev *dev = host_to_rtsx(host); + struct rtsx_chip *chip = dev->chip; + + dev_info(&dev->pci->dev, "%s called\n", __func__); + + scsi_lock(host); + + /* Is this command still active? */ + if (chip->srb != srb) { + scsi_unlock(host); + dev_info(&dev->pci->dev, "-- nothing to abort\n"); + return FAILED; + } + + rtsx_set_stat(chip, RTSX_STAT_ABORT); + + scsi_unlock(host); + + /* Wait for the aborted command to finish */ + wait_for_completion(&dev->notify); + + return SUCCESS; +} + +/* This invokes the transport reset mechanism to reset the state of the + * device */ +static int device_reset(struct scsi_cmnd *srb) +{ + int result = 0; + struct rtsx_dev *dev = host_to_rtsx(srb->device->host); + + dev_info(&dev->pci->dev, "%s called\n", __func__); + + return result < 0 ? FAILED : SUCCESS; +} + +/* Simulate a SCSI bus reset by resetting the device's USB port. */ +static int bus_reset(struct scsi_cmnd *srb) +{ + int result = 0; + struct rtsx_dev *dev = host_to_rtsx(srb->device->host); + + dev_info(&dev->pci->dev, "%s called\n", __func__); + + return result < 0 ? FAILED : SUCCESS; +} + + +/* + * this defines our host template, with which we'll allocate hosts + */ + +static struct scsi_host_template rtsx_host_template = { + /* basic userland interface stuff */ + .name = CR_DRIVER_NAME, + .proc_name = CR_DRIVER_NAME, + .info = host_info, + + /* command interface -- queued only */ + .queuecommand = queuecommand, + + /* error and abort handlers */ + .eh_abort_handler = command_abort, + .eh_device_reset_handler = device_reset, + .eh_bus_reset_handler = bus_reset, + + /* queue commands only, only one command per LUN */ + .can_queue = 1, + .cmd_per_lun = 1, + + /* unknown initiator id */ + .this_id = -1, + + .slave_alloc = slave_alloc, + .slave_configure = slave_configure, + + /* lots of sg segments can be handled */ + .sg_tablesize = SG_ALL, + + /* limit the total size of a transfer to 120 KB */ + .max_sectors = 240, + + /* merge commands... this seems to help performance, but + * periodically someone should test to see which setting is more + * optimal. + */ + .use_clustering = 1, + + /* emulated HBA */ + .emulated = 1, + + /* we do our own delay after a device or bus reset */ + .skip_settle_delay = 1, + + /* module management */ + .module = THIS_MODULE +}; + + +static int rtsx_acquire_irq(struct rtsx_dev *dev) +{ + struct rtsx_chip *chip = dev->chip; + + dev_info(&dev->pci->dev, "%s: chip->msi_en = %d, pci->irq = %d\n", + __func__, chip->msi_en, dev->pci->irq); + + if (request_irq(dev->pci->irq, rtsx_interrupt, + chip->msi_en ? 0 : IRQF_SHARED, + CR_DRIVER_NAME, dev)) { + dev_err(&dev->pci->dev, + "rtsx: unable to grab IRQ %d, disabling device\n", + dev->pci->irq); + return -1; + } + + dev->irq = dev->pci->irq; + pci_intx(dev->pci, !chip->msi_en); + + return 0; +} + + +int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val) +{ + struct pci_dev *pdev; + u8 data; + u8 devfn = (dev << 3) | func; + + pdev = pci_get_bus_and_slot(bus, devfn); + if (!pdev) + return -1; + + pci_read_config_byte(pdev, offset, &data); + if (val) + *val = data; + + return 0; +} + +#ifdef CONFIG_PM +/* + * power management + */ +static int rtsx_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); + struct rtsx_chip *chip; + + if (!dev) + return 0; + + /* lock the device pointers */ + mutex_lock(&(dev->dev_mutex)); + + chip = dev->chip; + + rtsx_do_before_power_down(chip, PM_S3); + + if (dev->irq >= 0) { + synchronize_irq(dev->irq); + free_irq(dev->irq, (void *)dev); + dev->irq = -1; + } + + if (chip->msi_en) + pci_disable_msi(pci); + + pci_save_state(pci); + pci_enable_wake(pci, pci_choose_state(pci, state), 1); + pci_disable_device(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); + + /* unlock the device pointers */ + mutex_unlock(&dev->dev_mutex); + + return 0; +} + +static int rtsx_resume(struct pci_dev *pci) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); + struct rtsx_chip *chip; + + if (!dev) + return 0; + + chip = dev->chip; + + /* lock the device pointers */ + mutex_lock(&(dev->dev_mutex)); + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + dev_err(&dev->pci->dev, + "%s: pci_enable_device failed, disabling device\n", + CR_DRIVER_NAME); + /* unlock the device pointers */ + mutex_unlock(&dev->dev_mutex); + return -EIO; + } + pci_set_master(pci); + + if (chip->msi_en) { + if (pci_enable_msi(pci) < 0) + chip->msi_en = 0; + } + + if (rtsx_acquire_irq(dev) < 0) { + /* unlock the device pointers */ + mutex_unlock(&dev->dev_mutex); + return -EIO; + } + + rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00); + rtsx_init_chip(chip); + + /* unlock the device pointers */ + mutex_unlock(&dev->dev_mutex); + + return 0; +} +#endif /* CONFIG_PM */ + +static void rtsx_shutdown(struct pci_dev *pci) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); + struct rtsx_chip *chip; + + if (!dev) + return; + + chip = dev->chip; + + rtsx_do_before_power_down(chip, PM_S1); + + if (dev->irq >= 0) { + synchronize_irq(dev->irq); + free_irq(dev->irq, (void *)dev); + dev->irq = -1; + } + + if (chip->msi_en) + pci_disable_msi(pci); + + pci_disable_device(pci); + + return; +} + +static int rtsx_control_thread(void *__dev) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)__dev; + struct rtsx_chip *chip = dev->chip; + struct Scsi_Host *host = rtsx_to_host(dev); + + for (;;) { + if (wait_for_completion_interruptible(&dev->cmnd_ready)) + break; + + /* lock the device pointers */ + mutex_lock(&(dev->dev_mutex)); + + /* if the device has disconnected, we are free to exit */ + if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { + dev_info(&dev->pci->dev, "-- rtsx-control exiting\n"); + mutex_unlock(&dev->dev_mutex); + break; + } + + /* lock access to the state */ + scsi_lock(host); + + /* has the command aborted ? */ + if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { + chip->srb->result = DID_ABORT << 16; + goto SkipForAbort; + } + + scsi_unlock(host); + + /* reject the command if the direction indicator + * is UNKNOWN + */ + if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { + dev_err(&dev->pci->dev, "UNKNOWN data direction\n"); + chip->srb->result = DID_ERROR << 16; + } + + /* reject if target != 0 or if LUN is higher than + * the maximum known LUN + */ + else if (chip->srb->device->id) { + dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n", + chip->srb->device->id, + chip->srb->device->lun); + chip->srb->result = DID_BAD_TARGET << 16; + } + + else if (chip->srb->device->lun > chip->max_lun) { + dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n", + chip->srb->device->id, + chip->srb->device->lun); + chip->srb->result = DID_BAD_TARGET << 16; + } + + /* we've got a command, let's do it! */ + else { + RTSX_DEBUG(scsi_show_command(chip->srb)); + rtsx_invoke_transport(chip->srb, chip); + } + + /* lock access to the state */ + scsi_lock(host); + + /* did the command already complete because of a disconnect? */ + if (!chip->srb) + ; /* nothing to do */ + + /* indicate that the command is done */ + else if (chip->srb->result != DID_ABORT << 16) { + chip->srb->scsi_done(chip->srb); + } else { +SkipForAbort: + dev_err(&dev->pci->dev, "scsi command aborted\n"); + } + + if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { + complete(&(dev->notify)); + + rtsx_set_stat(chip, RTSX_STAT_IDLE); + } + + /* finished working on this command */ + chip->srb = NULL; + scsi_unlock(host); + + /* unlock the device pointers */ + mutex_unlock(&dev->dev_mutex); + } /* for (;;) */ + + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + complete_and_exit(&dev->control_exit, 0); +} + + +static int rtsx_polling_thread(void *__dev) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)__dev; + struct rtsx_chip *chip = dev->chip; + struct sd_info *sd_card = &(chip->sd_card); + struct xd_info *xd_card = &(chip->xd_card); + struct ms_info *ms_card = &(chip->ms_card); + + sd_card->cleanup_counter = 0; + xd_card->cleanup_counter = 0; + ms_card->cleanup_counter = 0; + + /* Wait until SCSI scan finished */ + wait_timeout((delay_use + 5) * 1000); + + for (;;) { + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(POLLING_INTERVAL); + + /* lock the device pointers */ + mutex_lock(&(dev->dev_mutex)); + + /* if the device has disconnected, we are free to exit */ + if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { + dev_info(&dev->pci->dev, "-- rtsx-polling exiting\n"); + mutex_unlock(&dev->dev_mutex); + break; + } + + mutex_unlock(&dev->dev_mutex); + + mspro_polling_format_status(chip); + + /* lock the device pointers */ + mutex_lock(&(dev->dev_mutex)); + + rtsx_polling_func(chip); + + /* unlock the device pointers */ + mutex_unlock(&dev->dev_mutex); + } + + complete_and_exit(&dev->polling_exit, 0); +} + +/* + * interrupt handler + */ +static irqreturn_t rtsx_interrupt(int irq, void *dev_id) +{ + struct rtsx_dev *dev = dev_id; + struct rtsx_chip *chip; + int retval; + u32 status; + + if (dev) + chip = dev->chip; + else + return IRQ_NONE; + + if (!chip) + return IRQ_NONE; + + spin_lock(&dev->reg_lock); + + retval = rtsx_pre_handle_interrupt(chip); + if (retval == STATUS_FAIL) { + spin_unlock(&dev->reg_lock); + if (chip->int_reg == 0xFFFFFFFF) + return IRQ_HANDLED; + else + return IRQ_NONE; + } + + status = chip->int_reg; + + if (dev->check_card_cd) { + if (!(dev->check_card_cd & status)) { + /* card not exist, return TRANS_RESULT_FAIL */ + dev->trans_result = TRANS_RESULT_FAIL; + if (dev->done) + complete(dev->done); + goto Exit; + } + } + + if (status & (NEED_COMPLETE_INT | DELINK_INT)) { + if (status & (TRANS_FAIL_INT | DELINK_INT)) { + if (status & DELINK_INT) + RTSX_SET_DELINK(chip); + dev->trans_result = TRANS_RESULT_FAIL; + if (dev->done) + complete(dev->done); + } else if (status & TRANS_OK_INT) { + dev->trans_result = TRANS_RESULT_OK; + if (dev->done) + complete(dev->done); + } else if (status & DATA_DONE_INT) { + dev->trans_result = TRANS_NOT_READY; + if (dev->done && (dev->trans_state == STATE_TRANS_SG)) + complete(dev->done); + } + } + +Exit: + spin_unlock(&dev->reg_lock); + return IRQ_HANDLED; +} + + +/* Release all our dynamic resources */ +static void rtsx_release_resources(struct rtsx_dev *dev) +{ + dev_info(&dev->pci->dev, "-- %s\n", __func__); + + /* Tell the control thread to exit. The SCSI host must + * already have been removed so it won't try to queue + * any more commands. + */ + dev_info(&dev->pci->dev, "-- sending exit command to thread\n"); + complete(&dev->cmnd_ready); + if (dev->ctl_thread) + wait_for_completion(&dev->control_exit); + if (dev->polling_thread) + wait_for_completion(&dev->polling_exit); + + wait_timeout(200); + + if (dev->rtsx_resv_buf) { + dma_free_coherent(&(dev->pci->dev), RTSX_RESV_BUF_LEN, + dev->rtsx_resv_buf, dev->rtsx_resv_buf_addr); + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + } + + if (dev->irq > 0) + free_irq(dev->irq, (void *)dev); + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); + if (dev->remap_addr) + iounmap(dev->remap_addr); + + pci_disable_device(dev->pci); + pci_release_regions(dev->pci); + + rtsx_release_chip(dev->chip); + kfree(dev->chip); +} + +/* First stage of disconnect processing: stop all commands and remove + * the host */ +static void quiesce_and_remove_host(struct rtsx_dev *dev) +{ + struct Scsi_Host *host = rtsx_to_host(dev); + struct rtsx_chip *chip = dev->chip; + + /* Prevent new transfers, stop the current command, and + * interrupt a SCSI-scan or device-reset delay */ + mutex_lock(&dev->dev_mutex); + scsi_lock(host); + rtsx_set_stat(chip, RTSX_STAT_DISCONNECT); + scsi_unlock(host); + mutex_unlock(&dev->dev_mutex); + wake_up(&dev->delay_wait); + wait_for_completion(&dev->scanning_done); + + /* Wait some time to let other threads exist */ + wait_timeout(100); + + /* queuecommand won't accept any new commands and the control + * thread won't execute a previously-queued command. If there + * is such a command pending, complete it with an error. */ + mutex_lock(&dev->dev_mutex); + if (chip->srb) { + chip->srb->result = DID_NO_CONNECT << 16; + scsi_lock(host); + chip->srb->scsi_done(dev->chip->srb); + chip->srb = NULL; + scsi_unlock(host); + } + mutex_unlock(&dev->dev_mutex); + + /* Now we own no commands so it's safe to remove the SCSI host */ + scsi_remove_host(host); +} + +/* Second stage of disconnect processing: deallocate all resources */ +static void release_everything(struct rtsx_dev *dev) +{ + rtsx_release_resources(dev); + + /* Drop our reference to the host; the SCSI core will free it + * when the refcount becomes 0. */ + scsi_host_put(rtsx_to_host(dev)); +} + +/* Thread to carry out delayed SCSI-device scanning */ +static int rtsx_scan_thread(void *__dev) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)__dev; + struct rtsx_chip *chip = dev->chip; + + /* Wait for the timeout to expire or for a disconnect */ + if (delay_use > 0) { + dev_info(&dev->pci->dev, + "%s: waiting for device to settle before scanning\n", + CR_DRIVER_NAME); + wait_event_interruptible_timeout(dev->delay_wait, + rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), + delay_use * HZ); + } + + /* If the device is still connected, perform the scanning */ + if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { + scsi_scan_host(rtsx_to_host(dev)); + dev_info(&dev->pci->dev, "%s: device scan complete\n", + CR_DRIVER_NAME); + + /* Should we unbind if no devices were detected? */ + } + + complete_and_exit(&dev->scanning_done, 0); +} + +static void rtsx_init_options(struct rtsx_chip *chip) +{ + chip->vendor_id = chip->rtsx->pci->vendor; + chip->product_id = chip->rtsx->pci->device; + chip->adma_mode = 1; + chip->lun_mc = 0; + chip->driver_first_load = 1; +#ifdef HW_AUTO_SWITCH_SD_BUS + chip->sdio_in_charge = 0; +#endif + + chip->mspro_formatter_enable = 1; + chip->ignore_sd = 0; + chip->use_hw_setting = 0; + chip->lun_mode = DEFAULT_SINGLE; + chip->auto_delink_en = auto_delink_en; + chip->ss_en = ss_en; + chip->ss_idle_period = ss_interval * 1000; + chip->remote_wakeup_en = 0; + chip->aspm_l0s_l1_en = aspm_l0s_l1_en; + chip->dynamic_aspm = 1; + chip->fpga_sd_sdr104_clk = CLK_200; + chip->fpga_sd_ddr50_clk = CLK_100; + chip->fpga_sd_sdr50_clk = CLK_100; + chip->fpga_sd_hs_clk = CLK_100; + chip->fpga_mmc_52m_clk = CLK_80; + chip->fpga_ms_hg_clk = CLK_80; + chip->fpga_ms_4bit_clk = CLK_80; + chip->fpga_ms_1bit_clk = CLK_40; + chip->asic_sd_sdr104_clk = 203; + chip->asic_sd_sdr50_clk = 98; + chip->asic_sd_ddr50_clk = 98; + chip->asic_sd_hs_clk = 98; + chip->asic_mmc_52m_clk = 98; + chip->asic_ms_hg_clk = 117; + chip->asic_ms_4bit_clk = 78; + chip->asic_ms_1bit_clk = 39; + chip->ssc_depth_sd_sdr104 = SSC_DEPTH_2M; + chip->ssc_depth_sd_sdr50 = SSC_DEPTH_2M; + chip->ssc_depth_sd_ddr50 = SSC_DEPTH_1M; + chip->ssc_depth_sd_hs = SSC_DEPTH_1M; + chip->ssc_depth_mmc_52m = SSC_DEPTH_1M; + chip->ssc_depth_ms_hg = SSC_DEPTH_1M; + chip->ssc_depth_ms_4bit = SSC_DEPTH_512K; + chip->ssc_depth_low_speed = SSC_DEPTH_512K; + chip->ssc_en = 1; + chip->sd_speed_prior = 0x01040203; + chip->sd_current_prior = 0x00010203; + chip->sd_ctl = SD_PUSH_POINT_AUTO | + SD_SAMPLE_POINT_AUTO | + SUPPORT_MMC_DDR_MODE; + chip->sd_ddr_tx_phase = 0; + chip->mmc_ddr_tx_phase = 1; + chip->sd_default_tx_phase = 15; + chip->sd_default_rx_phase = 15; + chip->pmos_pwr_on_interval = 200; + chip->sd_voltage_switch_delay = 1000; + chip->ms_power_class_en = 3; + + chip->sd_400mA_ocp_thd = 1; + chip->sd_800mA_ocp_thd = 5; + chip->ms_ocp_thd = 2; + + chip->card_drive_sel = 0x55; + chip->sd30_drive_sel_1v8 = 0x03; + chip->sd30_drive_sel_3v3 = 0x01; + + chip->do_delink_before_power_down = 1; + chip->auto_power_down = 1; + chip->polling_config = 0; + + chip->force_clkreq_0 = 1; + chip->ft2_fast_mode = 0; + + chip->sdio_retry_cnt = 1; + + chip->xd_timeout = 2000; + chip->sd_timeout = 10000; + chip->ms_timeout = 2000; + chip->mspro_timeout = 15000; + + chip->power_down_in_ss = 1; + + chip->sdr104_en = 1; + chip->sdr50_en = 1; + chip->ddr50_en = 1; + + chip->delink_stage1_step = 100; + chip->delink_stage2_step = 40; + chip->delink_stage3_step = 20; + + chip->auto_delink_in_L1 = 1; + chip->blink_led = 1; + chip->msi_en = msi_en; + chip->hp_watch_bios_hotplug = 0; + chip->max_payload = 0; + chip->phy_voltage = 0; + + chip->support_ms_8bit = 1; + chip->s3_pwr_off_delay = 1000; +} + +static int rtsx_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct Scsi_Host *host; + struct rtsx_dev *dev; + int err = 0; + struct task_struct *th; + + RTSX_DEBUGP("Realtek PCI-E card reader detected\n"); + + err = pci_enable_device(pci); + if (err < 0) { + dev_err(&pci->dev, "PCI enable device failed!\n"); + return err; + } + + err = pci_request_regions(pci, CR_DRIVER_NAME); + if (err < 0) { + dev_err(&pci->dev, "PCI request regions for %s failed!\n", + CR_DRIVER_NAME); + pci_disable_device(pci); + return err; + } + + /* + * Ask the SCSI layer to allocate a host structure, with extra + * space at the end for our private rtsx_dev structure. + */ + host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev)); + if (!host) { + dev_err(&pci->dev, "Unable to allocate the scsi host\n"); + pci_release_regions(pci); + pci_disable_device(pci); + return -ENOMEM; + } + + dev = host_to_rtsx(host); + memset(dev, 0, sizeof(struct rtsx_dev)); + + dev->chip = kzalloc(sizeof(struct rtsx_chip), GFP_KERNEL); + if (dev->chip == NULL) + goto errout; + + spin_lock_init(&dev->reg_lock); + mutex_init(&(dev->dev_mutex)); + init_completion(&dev->cmnd_ready); + init_completion(&dev->control_exit); + init_completion(&dev->polling_exit); + init_completion(&(dev->notify)); + init_completion(&dev->scanning_done); + init_waitqueue_head(&dev->delay_wait); + + dev->pci = pci; + dev->irq = -1; + + dev_info(&pci->dev, "Resource length: 0x%x\n", + (unsigned int)pci_resource_len(pci, 0)); + dev->addr = pci_resource_start(pci, 0); + dev->remap_addr = ioremap_nocache(dev->addr, pci_resource_len(pci, 0)); + if (dev->remap_addr == NULL) { + dev_err(&pci->dev, "ioremap error\n"); + err = -ENXIO; + goto errout; + } + + /* + * Using "unsigned long" cast here to eliminate gcc warning in + * 64-bit system + */ + dev_info(&pci->dev, "Original address: 0x%lx, remapped address: 0x%lx\n", + (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr)); + + dev->rtsx_resv_buf = dma_alloc_coherent(&(pci->dev), RTSX_RESV_BUF_LEN, + &(dev->rtsx_resv_buf_addr), GFP_KERNEL); + if (dev->rtsx_resv_buf == NULL) { + dev_err(&pci->dev, "alloc dma buffer fail\n"); + err = -ENXIO; + goto errout; + } + dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; + dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; + dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN; + dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr + + HOST_CMDS_BUF_LEN; + + dev->chip->rtsx = dev; + + rtsx_init_options(dev->chip); + + dev_info(&pci->dev, "pci->irq = %d\n", pci->irq); + + if (dev->chip->msi_en) { + if (pci_enable_msi(pci) < 0) + dev->chip->msi_en = 0; + } + + if (rtsx_acquire_irq(dev) < 0) { + err = -EBUSY; + goto errout; + } + + pci_set_master(pci); + synchronize_irq(dev->irq); + + rtsx_init_chip(dev->chip); + + /* set the supported max_lun and max_id for the scsi host + * NOTE: the minimal value of max_id is 1 */ + host->max_id = 1; + host->max_lun = dev->chip->max_lun; + + /* Start up our control thread */ + th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME); + if (IS_ERR(th)) { + dev_err(&pci->dev, "Unable to start control thread\n"); + err = PTR_ERR(th); + goto errout; + } + dev->ctl_thread = th; + + err = scsi_add_host(host, &pci->dev); + if (err) { + dev_err(&pci->dev, "Unable to add the scsi host\n"); + goto errout; + } + + /* Start up the thread for delayed SCSI-device scanning */ + th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan"); + if (IS_ERR(th)) { + dev_err(&pci->dev, "Unable to start the device-scanning thread\n"); + complete(&dev->scanning_done); + quiesce_and_remove_host(dev); + err = PTR_ERR(th); + goto errout; + } + + /* Start up the thread for polling thread */ + th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); + if (IS_ERR(th)) { + dev_err(&pci->dev, "Unable to start the device-polling thread\n"); + quiesce_and_remove_host(dev); + err = PTR_ERR(th); + goto errout; + } + dev->polling_thread = th; + + pci_set_drvdata(pci, dev); + + return 0; + + /* We come here if there are any problems */ +errout: + dev_err(&pci->dev, "rtsx_probe() failed\n"); + release_everything(dev); + + return err; +} + + +static void rtsx_remove(struct pci_dev *pci) +{ + struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci); + + dev_info(&pci->dev, "rtsx_remove() called\n"); + + quiesce_and_remove_host(dev); + release_everything(dev); + + pci_set_drvdata(pci, NULL); +} + +/* PCI IDs */ +static DEFINE_PCI_DEVICE_TABLE(rtsx_ids) = { + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5208), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5288), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { 0, }, +}; + +MODULE_DEVICE_TABLE(pci, rtsx_ids); + +/* pci_driver definition */ +static struct pci_driver driver = { + .name = CR_DRIVER_NAME, + .id_table = rtsx_ids, + .probe = rtsx_probe, + .remove = rtsx_remove, +#ifdef CONFIG_PM + .suspend = rtsx_suspend, + .resume = rtsx_resume, +#endif + .shutdown = rtsx_shutdown, +}; + +static int __init rtsx_init(void) +{ + pr_info("Initializing Realtek PCIE storage driver...\n"); + + return pci_register_driver(&driver); +} + +static void __exit rtsx_exit(void) +{ + pr_info("rtsx_exit() called\n"); + + pci_unregister_driver(&driver); + + pr_info("%s module exit\n", CR_DRIVER_NAME); +} + +module_init(rtsx_init) +module_exit(rtsx_exit) diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h new file mode 100644 index 000000000000..3f048e061231 --- /dev/null +++ b/drivers/staging/rts5208/rtsx.h @@ -0,0 +1,186 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_H +#define __REALTEK_RTSX_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "trace.h" +#include "general.h" + +#define CR_DRIVER_NAME "rts5208" + +#define pci_get_bus_and_slot(bus, devfn) \ + pci_get_domain_bus_and_slot(0, (bus), (devfn)) + +/* + * macros for easy use + */ +#define rtsx_writel(chip, reg, value) \ + iowrite32(value, (chip)->rtsx->remap_addr + reg) +#define rtsx_readl(chip, reg) \ + ioread32((chip)->rtsx->remap_addr + reg) +#define rtsx_writew(chip, reg, value) \ + iowrite16(value, (chip)->rtsx->remap_addr + reg) +#define rtsx_readw(chip, reg) \ + ioread16((chip)->rtsx->remap_addr + reg) +#define rtsx_writeb(chip, reg, value) \ + iowrite8(value, (chip)->rtsx->remap_addr + reg) +#define rtsx_readb(chip, reg) \ + ioread8((chip)->rtsx->remap_addr + reg) + +#define rtsx_read_config_byte(chip, where, val) \ + pci_read_config_byte((chip)->rtsx->pci, where, val) + +#define rtsx_write_config_byte(chip, where, val) \ + pci_write_config_byte((chip)->rtsx->pci, where, val) + +#define wait_timeout_x(task_state, msecs) \ +do { \ + set_current_state((task_state)); \ + schedule_timeout((msecs) * HZ / 1000); \ +} while (0) +#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) + + +#define STATE_TRANS_NONE 0 +#define STATE_TRANS_CMD 1 +#define STATE_TRANS_BUF 2 +#define STATE_TRANS_SG 3 + +#define TRANS_NOT_READY 0 +#define TRANS_RESULT_OK 1 +#define TRANS_RESULT_FAIL 2 + +#define SCSI_LUN(srb) ((srb)->device->lun) + +typedef unsigned long DELAY_PARA_T; + +struct rtsx_chip; + +struct rtsx_dev { + struct pci_dev *pci; + + /* pci resources */ + unsigned long addr; + void __iomem *remap_addr; + int irq; + + /* locks */ + spinlock_t reg_lock; + + struct task_struct *ctl_thread; /* the control thread */ + struct task_struct *polling_thread; /* the polling thread */ + + /* mutual exclusion and synchronization structures */ + struct completion cmnd_ready; /* to sleep thread on */ + struct completion control_exit; /* control thread exit */ + struct completion polling_exit; /* polling thread exit */ + struct completion notify; /* thread begin/end */ + struct completion scanning_done; /* wait for scan thread */ + + wait_queue_head_t delay_wait; /* wait during scan, reset */ + struct mutex dev_mutex; + + /* host reserved buffer */ + void *rtsx_resv_buf; + dma_addr_t rtsx_resv_buf_addr; + + char trans_result; + char trans_state; + + struct completion *done; + /* Whether interrupt handler should care card cd info */ + u32 check_card_cd; + + struct rtsx_chip *chip; +}; + +typedef struct rtsx_dev rtsx_dev_t; + +/* Convert between rtsx_dev and the corresponding Scsi_Host */ +static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev) +{ + return container_of((void *) dev, struct Scsi_Host, hostdata); +} +static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host) +{ + return (struct rtsx_dev *) host->hostdata; +} + +static inline void get_current_time(u8 *timeval_buf, int buf_len) +{ + struct timeval tv; + + if (!timeval_buf || (buf_len < 8)) + return; + + do_gettimeofday(&tv); + + timeval_buf[0] = (u8)(tv.tv_sec >> 24); + timeval_buf[1] = (u8)(tv.tv_sec >> 16); + timeval_buf[2] = (u8)(tv.tv_sec >> 8); + timeval_buf[3] = (u8)(tv.tv_sec); + timeval_buf[4] = (u8)(tv.tv_usec >> 24); + timeval_buf[5] = (u8)(tv.tv_usec >> 16); + timeval_buf[6] = (u8)(tv.tv_usec >> 8); + timeval_buf[7] = (u8)(tv.tv_usec); +} + +/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the + * single queue element srb for write access */ +#define scsi_unlock(host) spin_unlock_irq(host->host_lock) +#define scsi_lock(host) spin_lock_irq(host->host_lock) + +#define lock_state(chip) spin_lock_irq(&((chip)->rtsx->reg_lock)) +#define unlock_state(chip) spin_unlock_irq(&((chip)->rtsx->reg_lock)) + +/* struct scsi_cmnd transfer buffer access utilities */ +enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; + +int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val); + +#endif /* __REALTEK_RTSX_H */ diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c new file mode 100644 index 000000000000..3055eb10c076 --- /dev/null +++ b/drivers/staging/rts5208/rtsx_card.c @@ -0,0 +1,1126 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" + +#include "rtsx_sys.h" +#include "general.h" + +#include "sd.h" +#include "xd.h" +#include "ms.h" + +void do_remaining_work(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); +#ifdef XD_DELAY_WRITE + struct xd_info *xd_card = &(chip->xd_card); +#endif + struct ms_info *ms_card = &(chip->ms_card); + + if (chip->card_ready & SD_CARD) { + if (sd_card->seq_mode) { + rtsx_set_stat(chip, RTSX_STAT_RUN); + sd_card->cleanup_counter++; + } else { + sd_card->cleanup_counter = 0; + } + } + +#ifdef XD_DELAY_WRITE + if (chip->card_ready & XD_CARD) { + if (xd_card->delay_write.delay_write_flag) { + rtsx_set_stat(chip, RTSX_STAT_RUN); + xd_card->cleanup_counter++; + } else { + xd_card->cleanup_counter = 0; + } + } +#endif + + if (chip->card_ready & MS_CARD) { + if (CHK_MSPRO(ms_card)) { + if (ms_card->seq_mode) { + rtsx_set_stat(chip, RTSX_STAT_RUN); + ms_card->cleanup_counter++; + } else { + ms_card->cleanup_counter = 0; + } + } else { +#ifdef MS_DELAY_WRITE + if (ms_card->delay_write.delay_write_flag) { + rtsx_set_stat(chip, RTSX_STAT_RUN); + ms_card->cleanup_counter++; + } else { + ms_card->cleanup_counter = 0; + } +#endif + } + } + + if (sd_card->cleanup_counter > POLLING_WAIT_CNT) + sd_cleanup_work(chip); + + if (xd_card->cleanup_counter > POLLING_WAIT_CNT) + xd_cleanup_work(chip); + + if (ms_card->cleanup_counter > POLLING_WAIT_CNT) + ms_cleanup_work(chip); +} + +void try_to_switch_sdio_ctrl(struct rtsx_chip *chip) +{ + u8 reg1 = 0, reg2 = 0; + + rtsx_read_register(chip, 0xFF34, ®1); + rtsx_read_register(chip, 0xFF38, ®2); + RTSX_DEBUGP("reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n", reg1, reg2); + if ((reg1 & 0xC0) && (reg2 & 0xC0)) { + chip->sd_int = 1; + rtsx_write_register(chip, SDIO_CTRL, 0xFF, SDIO_BUS_CTRL | SDIO_CD_CTRL); + rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON); + } +} + +#ifdef SUPPORT_SDIO_ASPM +void dynamic_configure_sdio_aspm(struct rtsx_chip *chip) +{ + u8 buf[12], reg; + int i; + + for (i = 0; i < 12; i++) + rtsx_read_register(chip, 0xFF08 + i, &buf[i]); + rtsx_read_register(chip, 0xFF25, ®); + if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) { + chip->sdio_counter = 0; + chip->sdio_idle = 0; + } else { + if (!chip->sdio_idle) { + chip->sdio_counter++; + if (chip->sdio_counter >= SDIO_IDLE_COUNT) { + chip->sdio_counter = 0; + chip->sdio_idle = 1; + } + } + } + memcpy(chip->sdio_raw_data, buf, 12); + + if (chip->sdio_idle) { + if (!chip->sdio_aspm) { + RTSX_DEBUGP("SDIO enter ASPM!\n"); + rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, + 0x30 | (chip->aspm_level[1] << 2)); + chip->sdio_aspm = 1; + } + } else { + if (chip->sdio_aspm) { + RTSX_DEBUGP("SDIO exit ASPM!\n"); + rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30); + chip->sdio_aspm = 0; + } + } +} +#endif + +void do_reset_sd_card(struct rtsx_chip *chip) +{ + int retval; + + RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__, + chip->sd_reset_counter, chip->card2lun[SD_CARD]); + + if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) { + clear_bit(SD_NR, &(chip->need_reset)); + chip->sd_reset_counter = 0; + chip->sd_show_cnt = 0; + return; + } + + chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0; + + rtsx_set_stat(chip, RTSX_STAT_RUN); + rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); + + retval = reset_sd_card(chip); + if (chip->need_release & SD_CARD) + return; + if (retval == STATUS_SUCCESS) { + clear_bit(SD_NR, &(chip->need_reset)); + chip->sd_reset_counter = 0; + chip->sd_show_cnt = 0; + chip->card_ready |= SD_CARD; + chip->card_fail &= ~SD_CARD; + chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw; + } else { + if (chip->sd_io || (chip->sd_reset_counter >= MAX_RESET_CNT)) { + clear_bit(SD_NR, &(chip->need_reset)); + chip->sd_reset_counter = 0; + chip->sd_show_cnt = 0; + } else { + chip->sd_reset_counter++; + } + chip->card_ready &= ~SD_CARD; + chip->card_fail |= SD_CARD; + chip->capacity[chip->card2lun[SD_CARD]] = 0; + chip->rw_card[chip->card2lun[SD_CARD]] = NULL; + + rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); + if (!chip->ft2_fast_mode) + card_power_off(chip, SD_CARD); + if (chip->sd_io) { + chip->sd_int = 0; + try_to_switch_sdio_ctrl(chip); + } else { + disable_card_clock(chip, SD_CARD); + } + } +} + +void do_reset_xd_card(struct rtsx_chip *chip) +{ + int retval; + + RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__, + chip->xd_reset_counter, chip->card2lun[XD_CARD]); + + if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) { + clear_bit(XD_NR, &(chip->need_reset)); + chip->xd_reset_counter = 0; + chip->xd_show_cnt = 0; + return; + } + + chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0; + + rtsx_set_stat(chip, RTSX_STAT_RUN); + rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); + + retval = reset_xd_card(chip); + if (chip->need_release & XD_CARD) + return; + if (retval == STATUS_SUCCESS) { + clear_bit(XD_NR, &(chip->need_reset)); + chip->xd_reset_counter = 0; + chip->card_ready |= XD_CARD; + chip->card_fail &= ~XD_CARD; + chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw; + } else { + if (chip->xd_reset_counter >= MAX_RESET_CNT) { + clear_bit(XD_NR, &(chip->need_reset)); + chip->xd_reset_counter = 0; + chip->xd_show_cnt = 0; + } else { + chip->xd_reset_counter++; + } + chip->card_ready &= ~XD_CARD; + chip->card_fail |= XD_CARD; + chip->capacity[chip->card2lun[XD_CARD]] = 0; + chip->rw_card[chip->card2lun[XD_CARD]] = NULL; + + rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0); + if (!chip->ft2_fast_mode) + card_power_off(chip, XD_CARD); + disable_card_clock(chip, XD_CARD); + } +} + +void do_reset_ms_card(struct rtsx_chip *chip) +{ + int retval; + + RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__, + chip->ms_reset_counter, chip->card2lun[MS_CARD]); + + if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) { + clear_bit(MS_NR, &(chip->need_reset)); + chip->ms_reset_counter = 0; + chip->ms_show_cnt = 0; + return; + } + + chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0; + + rtsx_set_stat(chip, RTSX_STAT_RUN); + rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); + + retval = reset_ms_card(chip); + if (chip->need_release & MS_CARD) + return; + if (retval == STATUS_SUCCESS) { + clear_bit(MS_NR, &(chip->need_reset)); + chip->ms_reset_counter = 0; + chip->card_ready |= MS_CARD; + chip->card_fail &= ~MS_CARD; + chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw; + } else { + if (chip->ms_reset_counter >= MAX_RESET_CNT) { + clear_bit(MS_NR, &(chip->need_reset)); + chip->ms_reset_counter = 0; + chip->ms_show_cnt = 0; + } else { + chip->ms_reset_counter++; + } + chip->card_ready &= ~MS_CARD; + chip->card_fail |= MS_CARD; + chip->capacity[chip->card2lun[MS_CARD]] = 0; + chip->rw_card[chip->card2lun[MS_CARD]] = NULL; + + rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); + if (!chip->ft2_fast_mode) + card_power_off(chip, MS_CARD); + disable_card_clock(chip, MS_CARD); + } +} + +static void release_sdio(struct rtsx_chip *chip) +{ + if (chip->sd_io) { + rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, + SD_STOP | SD_CLR_ERR); + + if (chip->chip_insert_with_sdio) { + chip->chip_insert_with_sdio = 0; + + if (CHECK_PID(chip, 0x5288)) + rtsx_write_register(chip, 0xFE5A, 0x08, 0x00); + else + rtsx_write_register(chip, 0xFE70, 0x80, 0x00); + } + + rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0); + chip->sd_io = 0; + } +} + +void rtsx_power_off_card(struct rtsx_chip *chip) +{ + if ((chip->card_ready & SD_CARD) || chip->sd_io) { + sd_cleanup_work(chip); + sd_power_off_card3v3(chip); + } + + if (chip->card_ready & XD_CARD) { + xd_cleanup_work(chip); + xd_power_off_card3v3(chip); + } + + if (chip->card_ready & MS_CARD) { + ms_cleanup_work(chip); + ms_power_off_card3v3(chip); + } +} + +void rtsx_release_cards(struct rtsx_chip *chip) +{ + chip->int_reg = rtsx_readl(chip, RTSX_BIPR); + + if ((chip->card_ready & SD_CARD) || chip->sd_io) { + if (chip->int_reg & SD_EXIST) + sd_cleanup_work(chip); + release_sd_card(chip); + } + + if (chip->card_ready & XD_CARD) { + if (chip->int_reg & XD_EXIST) + xd_cleanup_work(chip); + release_xd_card(chip); + } + + if (chip->card_ready & MS_CARD) { + if (chip->int_reg & MS_EXIST) + ms_cleanup_work(chip); + release_ms_card(chip); + } +} + +void rtsx_reset_cards(struct rtsx_chip *chip) +{ + if (!chip->need_reset) + return; + + rtsx_set_stat(chip, RTSX_STAT_RUN); + + rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); + + rtsx_disable_aspm(chip); + + if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio) + clear_bit(SD_NR, &(chip->need_reset)); + + if (chip->need_reset & XD_CARD) { + chip->card_exist |= XD_CARD; + + if (chip->xd_show_cnt >= MAX_SHOW_CNT) + do_reset_xd_card(chip); + else + chip->xd_show_cnt++; + } + if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { + if (chip->card_exist & XD_CARD) { + clear_bit(SD_NR, &(chip->need_reset)); + clear_bit(MS_NR, &(chip->need_reset)); + } + } + if (chip->need_reset & SD_CARD) { + chip->card_exist |= SD_CARD; + + if (chip->sd_show_cnt >= MAX_SHOW_CNT) { + rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + do_reset_sd_card(chip); + } else { + chip->sd_show_cnt++; + } + } + if (chip->need_reset & MS_CARD) { + chip->card_exist |= MS_CARD; + + if (chip->ms_show_cnt >= MAX_SHOW_CNT) + do_reset_ms_card(chip); + else + chip->ms_show_cnt++; + } +} + +void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip) +{ + rtsx_set_stat(chip, RTSX_STAT_RUN); + + rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); + + if (reset_chip) + rtsx_reset_chip(chip); + + chip->int_reg = rtsx_readl(chip, RTSX_BIPR); + + if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) { + release_sdio(chip); + release_sd_card(chip); + + wait_timeout(100); + + chip->card_exist |= SD_CARD; + do_reset_sd_card(chip); + } + + if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) { + release_xd_card(chip); + + wait_timeout(100); + + chip->card_exist |= XD_CARD; + do_reset_xd_card(chip); + } + + if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) { + release_ms_card(chip); + + wait_timeout(100); + + chip->card_exist |= MS_CARD; + do_reset_ms_card(chip); + } + + chip->need_reinit = 0; +} + +#ifdef DISABLE_CARD_INT +void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, unsigned long *need_release) +{ + u8 release_map = 0, reset_map = 0; + + chip->int_reg = rtsx_readl(chip, RTSX_BIPR); + + if (chip->card_exist) { + if (chip->card_exist & XD_CARD) { + if (!(chip->int_reg & XD_EXIST)) + release_map |= XD_CARD; + } else if (chip->card_exist & SD_CARD) { + if (!(chip->int_reg & SD_EXIST)) + release_map |= SD_CARD; + } else if (chip->card_exist & MS_CARD) { + if (!(chip->int_reg & MS_EXIST)) + release_map |= MS_CARD; + } + } else { + if (chip->int_reg & XD_EXIST) + reset_map |= XD_CARD; + else if (chip->int_reg & SD_EXIST) + reset_map |= SD_CARD; + else if (chip->int_reg & MS_EXIST) + reset_map |= MS_CARD; + } + + if (reset_map) { + int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0; + int i; + + for (i = 0; i < (DEBOUNCE_CNT); i++) { + chip->int_reg = rtsx_readl(chip, RTSX_BIPR); + + if (chip->int_reg & XD_EXIST) + xd_cnt++; + else + xd_cnt = 0; + + if (chip->int_reg & SD_EXIST) + sd_cnt++; + else + sd_cnt = 0; + + if (chip->int_reg & MS_EXIST) + ms_cnt++; + else + ms_cnt = 0; + + wait_timeout(30); + } + + reset_map = 0; + if (!(chip->card_exist & XD_CARD) && (xd_cnt > (DEBOUNCE_CNT-1))) + reset_map |= XD_CARD; + if (!(chip->card_exist & SD_CARD) && (sd_cnt > (DEBOUNCE_CNT-1))) + reset_map |= SD_CARD; + if (!(chip->card_exist & MS_CARD) && (ms_cnt > (DEBOUNCE_CNT-1))) + reset_map |= MS_CARD; + } + + if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) + rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00); + + if (need_reset) + *need_reset = reset_map; + if (need_release) + *need_release = release_map; +} +#endif + +void rtsx_init_cards(struct rtsx_chip *chip) +{ + if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) { + RTSX_DEBUGP("Reset chip in polling thread!\n"); + rtsx_reset_chip(chip); + RTSX_CLR_DELINK(chip); + } + +#ifdef DISABLE_CARD_INT + card_cd_debounce(chip, &(chip->need_reset), &(chip->need_release)); +#endif + + if (chip->need_release) { + if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { + if (chip->int_reg & XD_EXIST) { + clear_bit(SD_NR, &(chip->need_release)); + clear_bit(MS_NR, &(chip->need_release)); + } + } + + if (!(chip->card_exist & SD_CARD) && !chip->sd_io) + clear_bit(SD_NR, &(chip->need_release)); + if (!(chip->card_exist & XD_CARD)) + clear_bit(XD_NR, &(chip->need_release)); + if (!(chip->card_exist & MS_CARD)) + clear_bit(MS_NR, &(chip->need_release)); + + RTSX_DEBUGP("chip->need_release = 0x%x\n", (unsigned int)(chip->need_release)); + +#ifdef SUPPORT_OCP + if (chip->need_release) { + if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER)) + rtsx_write_register(chip, OCPCLR, + CARD_OC_INT_CLR | CARD_OC_CLR, + CARD_OC_INT_CLR | CARD_OC_CLR); + chip->ocp_stat = 0; + } +#endif + if (chip->need_release) { + rtsx_set_stat(chip, RTSX_STAT_RUN); + rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); + } + + if (chip->need_release & SD_CARD) { + clear_bit(SD_NR, &(chip->need_release)); + chip->card_exist &= ~SD_CARD; + chip->card_ejected &= ~SD_CARD; + chip->card_fail &= ~SD_CARD; + CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]); + chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0; + rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + + release_sdio(chip); + release_sd_card(chip); + } + + if (chip->need_release & XD_CARD) { + clear_bit(XD_NR, &(chip->need_release)); + chip->card_exist &= ~XD_CARD; + chip->card_ejected &= ~XD_CARD; + chip->card_fail &= ~XD_CARD; + CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]); + chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0; + + release_xd_card(chip); + + if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) + rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0xC0); + } + + if (chip->need_release & MS_CARD) { + clear_bit(MS_NR, &(chip->need_release)); + chip->card_exist &= ~MS_CARD; + chip->card_ejected &= ~MS_CARD; + chip->card_fail &= ~MS_CARD; + CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]); + chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0; + + release_ms_card(chip); + } + + RTSX_DEBUGP("chip->card_exist = 0x%x\n", chip->card_exist); + + if (!chip->card_exist) + turn_off_led(chip, LED_GPIO); + } + + if (chip->need_reset) { + RTSX_DEBUGP("chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset)); + + rtsx_reset_cards(chip); + } + + if (chip->need_reinit) { + RTSX_DEBUGP("chip->need_reinit = 0x%x\n", (unsigned int)(chip->need_reinit)); + + rtsx_reinit_cards(chip, 0); + } +} + +static inline u8 double_depth(u8 depth) +{ + return ((depth > 1) ? (depth - 1) : depth); +} + +int switch_ssc_clock(struct rtsx_chip *chip, int clk) +{ + int retval; + u8 N = (u8)(clk - 2), min_N, max_N; + u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask; + int sd_vpclk_phase_reset = 0; + + if (chip->cur_clk == clk) + return STATUS_SUCCESS; + + min_N = 60; + max_N = 120; + max_div = CLK_DIV_4; + + RTSX_DEBUGP("Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk); + + if ((clk <= 2) || (N > max_N)) + TRACE_RET(chip, STATUS_FAIL); + + mcu_cnt = (u8)(125/clk + 3); + if (mcu_cnt > 7) + mcu_cnt = 7; + + div = CLK_DIV_1; + while ((N < min_N) && (div < max_div)) { + N = (N + 2) * 2 - 2; + div++; + } + RTSX_DEBUGP("N = %d, div = %d\n", N, div); + + if (chip->ssc_en) { + ssc_depth = 0x01; + N -= 2; + } else { + ssc_depth = 0; + } + + ssc_depth_mask = 0x03; + + RTSX_DEBUGP("ssc_depth = %d\n", ssc_depth); + + rtsx_init_cmd(chip); + rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); + rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth); + rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N); + rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); + if (sd_vpclk_phase_reset) { + rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); + } + + retval = rtsx_send_cmd(chip, 0, WAIT_TIME); + if (retval < 0) + TRACE_RET(chip, STATUS_ERROR); + + udelay(10); + RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0); + + chip->cur_clk = clk; + + return STATUS_SUCCESS; +} + +int switch_normal_clock(struct rtsx_chip *chip, int clk) +{ + u8 sel, div, mcu_cnt; + int sd_vpclk_phase_reset = 0; + + if (chip->cur_clk == clk) + return STATUS_SUCCESS; + + switch (clk) { + case CLK_20: + RTSX_DEBUGP("Switch clock to 20MHz\n"); + sel = SSC_80; + div = CLK_DIV_4; + mcu_cnt = 7; + break; + + case CLK_30: + RTSX_DEBUGP("Switch clock to 30MHz\n"); + sel = SSC_120; + div = CLK_DIV_4; + mcu_cnt = 7; + break; + + case CLK_40: + RTSX_DEBUGP("Switch clock to 40MHz\n"); + sel = SSC_80; + div = CLK_DIV_2; + mcu_cnt = 7; + break; + + case CLK_50: + RTSX_DEBUGP("Switch clock to 50MHz\n"); + sel = SSC_100; + div = CLK_DIV_2; + mcu_cnt = 6; + break; + + case CLK_60: + RTSX_DEBUGP("Switch clock to 60MHz\n"); + sel = SSC_120; + div = CLK_DIV_2; + mcu_cnt = 6; + break; + + case CLK_80: + RTSX_DEBUGP("Switch clock to 80MHz\n"); + sel = SSC_80; + div = CLK_DIV_1; + mcu_cnt = 5; + break; + + case CLK_100: + RTSX_DEBUGP("Switch clock to 100MHz\n"); + sel = SSC_100; + div = CLK_DIV_1; + mcu_cnt = 5; + break; + + case CLK_120: + RTSX_DEBUGP("Switch clock to 120MHz\n"); + sel = SSC_120; + div = CLK_DIV_1; + mcu_cnt = 5; + break; + + case CLK_150: + RTSX_DEBUGP("Switch clock to 150MHz\n"); + sel = SSC_150; + div = CLK_DIV_1; + mcu_cnt = 4; + break; + + case CLK_200: + RTSX_DEBUGP("Switch clock to 200MHz\n"); + sel = SSC_200; + div = CLK_DIV_1; + mcu_cnt = 4; + break; + + default: + RTSX_DEBUGP("Try to switch to an illegal clock (%d)\n", clk); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ); + if (sd_vpclk_phase_reset) { + RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); + RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, 0); + } + RTSX_WRITE_REG(chip, CLK_DIV, 0xFF, (div << 4) | mcu_cnt); + RTSX_WRITE_REG(chip, CLK_SEL, 0xFF, sel); + + if (sd_vpclk_phase_reset) { + udelay(200); + RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); + RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); + udelay(200); + } + RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, 0); + + chip->cur_clk = clk; + + return STATUS_SUCCESS; +} + +void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size) +{ + if (pack_size > DMA_1024) + pack_size = DMA_512; + + rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT); + + rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24)); + rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt); + + if (dir == DMA_FROM_DEVICE) { + rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, + DMA_DIR_FROM_CARD | DMA_EN | pack_size); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, + DMA_DIR_TO_CARD | DMA_EN | pack_size); + } + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); +} + +int enable_card_clock(struct rtsx_chip *chip, u8 card) +{ + u8 clk_en = 0; + + if (card & XD_CARD) + clk_en |= XD_CLK_EN; + if (card & SD_CARD) + clk_en |= SD_CLK_EN; + if (card & MS_CARD) + clk_en |= MS_CLK_EN; + + RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, clk_en); + + return STATUS_SUCCESS; +} + +int disable_card_clock(struct rtsx_chip *chip, u8 card) +{ + u8 clk_en = 0; + + if (card & XD_CARD) + clk_en |= XD_CLK_EN; + if (card & SD_CARD) + clk_en |= SD_CLK_EN; + if (card & MS_CARD) + clk_en |= MS_CLK_EN; + + RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, 0); + + return STATUS_SUCCESS; +} + +int card_power_on(struct rtsx_chip *chip, u8 card) +{ + int retval; + u8 mask, val1, val2; + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) { + mask = MS_POWER_MASK; + val1 = MS_PARTIAL_POWER_ON; + val2 = MS_POWER_ON; + } else { + mask = SD_POWER_MASK; + val1 = SD_PARTIAL_POWER_ON; + val2 = SD_POWER_ON; + } + + rtsx_init_cmd(chip); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + udelay(chip->pmos_pwr_on_interval); + + rtsx_init_cmd(chip); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int card_power_off(struct rtsx_chip *chip, u8 card) +{ + u8 mask, val; + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) { + mask = MS_POWER_MASK; + val = MS_POWER_OFF; + } else { + mask = SD_POWER_MASK; + val = SD_POWER_OFF; + } + + RTSX_WRITE_REG(chip, CARD_PWR_CTL, mask, val); + + return STATUS_SUCCESS; +} + +int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt) +{ + int retval; + unsigned int lun = SCSI_LUN(srb); + int i; + + if (chip->rw_card[lun] == NULL) + TRACE_RET(chip, STATUS_FAIL); + + for (i = 0; i < 3; i++) { + chip->rw_need_retry = 0; + + retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt); + if (retval != STATUS_SUCCESS) { + if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) { + rtsx_release_chip(chip); + TRACE_RET(chip, STATUS_FAIL); + } + if (detect_card_cd(chip, chip->cur_card) != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!chip->rw_need_retry) { + RTSX_DEBUGP("RW fail, but no need to retry\n"); + break; + } + } else { + chip->rw_need_retry = 0; + break; + } + + RTSX_DEBUGP("Retry RW, (i = %d)\n", i); + } + + return retval; +} + +int card_share_mode(struct rtsx_chip *chip, int card) +{ + u8 mask, value; + + if (CHECK_PID(chip, 0x5208)) { + mask = CARD_SHARE_MASK; + if (card == SD_CARD) + value = CARD_SHARE_48_SD; + else if (card == MS_CARD) + value = CARD_SHARE_48_MS; + else if (card == XD_CARD) + value = CARD_SHARE_48_XD; + else + TRACE_RET(chip, STATUS_FAIL); + + } else if (CHECK_PID(chip, 0x5288)) { + mask = 0x03; + if (card == SD_CARD) + value = CARD_SHARE_BAROSSA_SD; + else if (card == MS_CARD) + value = CARD_SHARE_BAROSSA_MS; + else if (card == XD_CARD) + value = CARD_SHARE_BAROSSA_XD; + else + TRACE_RET(chip, STATUS_FAIL); + + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_WRITE_REG(chip, CARD_SHARE_MODE, mask, value); + + return STATUS_SUCCESS; +} + + +int select_card(struct rtsx_chip *chip, int card) +{ + int retval; + + if (chip->cur_card != card) { + u8 mod; + + if (card == SD_CARD) + mod = SD_MOD_SEL; + else if (card == MS_CARD) + mod = MS_MOD_SEL; + else if (card == XD_CARD) + mod = XD_MOD_SEL; + else if (card == SPI_CARD) + mod = SPI_MOD_SEL; + else + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_SELECT, 0x07, mod); + chip->cur_card = card; + + retval = card_share_mode(chip, card); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +void toggle_gpio(struct rtsx_chip *chip, u8 gpio) +{ + u8 temp_reg; + + rtsx_read_register(chip, CARD_GPIO, &temp_reg); + temp_reg ^= (0x01 << gpio); + rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg); +} + +void turn_on_led(struct rtsx_chip *chip, u8 gpio) +{ + if (CHECK_PID(chip, 0x5288)) + rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio)); + else + rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); +} + +void turn_off_led(struct rtsx_chip *chip, u8 gpio) +{ + if (CHECK_PID(chip, 0x5288)) + rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); + else + rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio)); +} + +int detect_card_cd(struct rtsx_chip *chip, int card) +{ + u32 card_cd, status; + + if (card == SD_CARD) { + card_cd = SD_EXIST; + } else if (card == MS_CARD) { + card_cd = MS_EXIST; + } else if (card == XD_CARD) { + card_cd = XD_EXIST; + } else { + RTSX_DEBUGP("Wrong card type: 0x%x\n", card); + TRACE_RET(chip, STATUS_FAIL); + } + + status = rtsx_readl(chip, RTSX_BIPR); + if (!(status & card_cd)) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int check_card_exist(struct rtsx_chip *chip, unsigned int lun) +{ + if (chip->card_exist & chip->lun2card[lun]) + return 1; + + return 0; +} + +int check_card_ready(struct rtsx_chip *chip, unsigned int lun) +{ + if (chip->card_ready & chip->lun2card[lun]) + return 1; + + return 0; +} + +int check_card_wp(struct rtsx_chip *chip, unsigned int lun) +{ + if (chip->card_wp & chip->lun2card[lun]) + return 1; + + return 0; +} + +int check_card_fail(struct rtsx_chip *chip, unsigned int lun) +{ + if (chip->card_fail & chip->lun2card[lun]) + return 1; + + return 0; +} + +int check_card_ejected(struct rtsx_chip *chip, unsigned int lun) +{ + if (chip->card_ejected & chip->lun2card[lun]) + return 1; + + return 0; +} + +u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun) +{ + if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) + return (u8)XD_CARD; + else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) + return (u8)SD_CARD; + else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) + return (u8)MS_CARD; + + return 0; +} + +void eject_card(struct rtsx_chip *chip, unsigned int lun) +{ + do_remaining_work(chip); + + if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) { + release_sd_card(chip); + chip->card_ejected |= SD_CARD; + chip->card_ready &= ~SD_CARD; + chip->capacity[lun] = 0; + } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) { + release_xd_card(chip); + chip->card_ejected |= XD_CARD; + chip->card_ready &= ~XD_CARD; + chip->capacity[lun] = 0; + } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) { + release_ms_card(chip); + chip->card_ejected |= MS_CARD; + chip->card_ready &= ~MS_CARD; + chip->capacity[lun] = 0; + } +} diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h new file mode 100644 index 000000000000..4528b619f6b3 --- /dev/null +++ b/drivers/staging/rts5208/rtsx_card.h @@ -0,0 +1,1098 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_CARD_H +#define __REALTEK_RTSX_CARD_H + +#include "debug.h" +#include "rtsx.h" +#include "rtsx_chip.h" +#include "rtsx_transport.h" +#include "sd.h" + +#define SSC_POWER_DOWN 0x01 +#define SD_OC_POWER_DOWN 0x02 +#define MS_OC_POWER_DOWN 0x04 +#define ALL_POWER_DOWN 0x07 +#define OC_POWER_DOWN 0x06 + +#define PMOS_STRG_MASK 0x10 +#define PMOS_STRG_800mA 0x10 +#define PMOS_STRG_400mA 0x00 + +#define POWER_OFF 0x03 +#define PARTIAL_POWER_ON 0x01 +#define POWER_ON 0x00 + +#define MS_POWER_OFF 0x0C +#define MS_PARTIAL_POWER_ON 0x04 +#define MS_POWER_ON 0x00 +#define MS_POWER_MASK 0x0C + +#define SD_POWER_OFF 0x03 +#define SD_PARTIAL_POWER_ON 0x01 +#define SD_POWER_ON 0x00 +#define SD_POWER_MASK 0x03 + +#define XD_OUTPUT_EN 0x02 +#define SD_OUTPUT_EN 0x04 +#define MS_OUTPUT_EN 0x08 +#define SPI_OUTPUT_EN 0x10 + +#define CLK_LOW_FREQ 0x01 + +#define CLK_DIV_1 0x01 +#define CLK_DIV_2 0x02 +#define CLK_DIV_4 0x03 +#define CLK_DIV_8 0x04 + +#define SSC_80 0 +#define SSC_100 1 +#define SSC_120 2 +#define SSC_150 3 +#define SSC_200 4 + +#define XD_CLK_EN 0x02 +#define SD_CLK_EN 0x04 +#define MS_CLK_EN 0x08 +#define SPI_CLK_EN 0x10 + +#define XD_MOD_SEL 1 +#define SD_MOD_SEL 2 +#define MS_MOD_SEL 3 +#define SPI_MOD_SEL 4 + +#define CHANGE_CLK 0x01 + +#define SD_CRC7_ERR 0x80 +#define SD_CRC16_ERR 0x40 +#define SD_CRC_WRITE_ERR 0x20 +#define SD_CRC_WRITE_ERR_MASK 0x1C +#define GET_CRC_TIME_OUT 0x02 +#define SD_TUNING_COMPARE_ERR 0x01 + +#define SD_RSP_80CLK_TIMEOUT 0x01 + +#define SD_CLK_TOGGLE_EN 0x80 +#define SD_CLK_FORCE_STOP 0x40 +#define SD_DAT3_STATUS 0x10 +#define SD_DAT2_STATUS 0x08 +#define SD_DAT1_STATUS 0x04 +#define SD_DAT0_STATUS 0x02 +#define SD_CMD_STATUS 0x01 + +#define SD_IO_USING_1V8 0x80 +#define SD_IO_USING_3V3 0x7F +#define TYPE_A_DRIVING 0x00 +#define TYPE_B_DRIVING 0x01 +#define TYPE_C_DRIVING 0x02 +#define TYPE_D_DRIVING 0x03 + +#define DDR_FIX_RX_DAT 0x00 +#define DDR_VAR_RX_DAT 0x80 +#define DDR_FIX_RX_DAT_EDGE 0x00 +#define DDR_FIX_RX_DAT_14_DELAY 0x40 +#define DDR_FIX_RX_CMD 0x00 +#define DDR_VAR_RX_CMD 0x20 +#define DDR_FIX_RX_CMD_POS_EDGE 0x00 +#define DDR_FIX_RX_CMD_14_DELAY 0x10 +#define SD20_RX_POS_EDGE 0x00 +#define SD20_RX_14_DELAY 0x08 +#define SD20_RX_SEL_MASK 0x08 + +#define DDR_FIX_TX_CMD_DAT 0x00 +#define DDR_VAR_TX_CMD_DAT 0x80 +#define DDR_FIX_TX_DAT_14_TSU 0x00 +#define DDR_FIX_TX_DAT_12_TSU 0x40 +#define DDR_FIX_TX_CMD_NEG_EDGE 0x00 +#define DDR_FIX_TX_CMD_14_AHEAD 0x20 +#define SD20_TX_NEG_EDGE 0x00 +#define SD20_TX_14_AHEAD 0x10 +#define SD20_TX_SEL_MASK 0x10 +#define DDR_VAR_SDCLK_POL_SWAP 0x01 + +#define SD_TRANSFER_START 0x80 +#define SD_TRANSFER_END 0x40 +#define SD_STAT_IDLE 0x20 +#define SD_TRANSFER_ERR 0x10 +#define SD_TM_NORMAL_WRITE 0x00 +#define SD_TM_AUTO_WRITE_3 0x01 +#define SD_TM_AUTO_WRITE_4 0x02 +#define SD_TM_AUTO_READ_3 0x05 +#define SD_TM_AUTO_READ_4 0x06 +#define SD_TM_CMD_RSP 0x08 +#define SD_TM_AUTO_WRITE_1 0x09 +#define SD_TM_AUTO_WRITE_2 0x0A +#define SD_TM_NORMAL_READ 0x0C +#define SD_TM_AUTO_READ_1 0x0D +#define SD_TM_AUTO_READ_2 0x0E +#define SD_TM_AUTO_TUNING 0x0F + +#define PHASE_CHANGE 0x80 +#define PHASE_NOT_RESET 0x40 + +#define DCMPS_CHANGE 0x80 +#define DCMPS_CHANGE_DONE 0x40 +#define DCMPS_ERROR 0x20 +#define DCMPS_CURRENT_PHASE 0x1F + +#define SD_CLK_DIVIDE_0 0x00 +#define SD_CLK_DIVIDE_256 0xC0 +#define SD_CLK_DIVIDE_128 0x80 +#define SD_BUS_WIDTH_1 0x00 +#define SD_BUS_WIDTH_4 0x01 +#define SD_BUS_WIDTH_8 0x02 +#define SD_ASYNC_FIFO_NOT_RST 0x10 +#define SD_20_MODE 0x00 +#define SD_DDR_MODE 0x04 +#define SD_30_MODE 0x08 + +#define SD_CLK_DIVIDE_MASK 0xC0 + +#define SD_CMD_IDLE 0x80 + +#define SD_DATA_IDLE 0x80 + +#define DCM_RESET 0x08 +#define DCM_LOCKED 0x04 +#define DCM_208M 0x00 +#define DCM_TX 0x01 +#define DCM_RX 0x02 + +#define DRP_START 0x80 +#define DRP_DONE 0x40 + +#define DRP_WRITE 0x80 +#define DRP_READ 0x00 +#define DCM_WRITE_ADDRESS_50 0x50 +#define DCM_WRITE_ADDRESS_51 0x51 +#define DCM_READ_ADDRESS_00 0x00 +#define DCM_READ_ADDRESS_51 0x51 + +#define SD_CALCULATE_CRC7 0x00 +#define SD_NO_CALCULATE_CRC7 0x80 +#define SD_CHECK_CRC16 0x00 +#define SD_NO_CHECK_CRC16 0x40 +#define SD_NO_CHECK_WAIT_CRC_TO 0x20 +#define SD_WAIT_BUSY_END 0x08 +#define SD_NO_WAIT_BUSY_END 0x00 +#define SD_CHECK_CRC7 0x00 +#define SD_NO_CHECK_CRC7 0x04 +#define SD_RSP_LEN_0 0x00 +#define SD_RSP_LEN_6 0x01 +#define SD_RSP_LEN_17 0x02 +#define SD_RSP_TYPE_R0 0x04 +#define SD_RSP_TYPE_R1 0x01 +#define SD_RSP_TYPE_R1b 0x09 +#define SD_RSP_TYPE_R2 0x02 +#define SD_RSP_TYPE_R3 0x05 +#define SD_RSP_TYPE_R4 0x05 +#define SD_RSP_TYPE_R5 0x01 +#define SD_RSP_TYPE_R6 0x01 +#define SD_RSP_TYPE_R7 0x01 + +#define SD_RSP_80CLK_TIMEOUT_EN 0x01 + +#define SAMPLE_TIME_RISING 0x00 +#define SAMPLE_TIME_FALLING 0x80 +#define PUSH_TIME_DEFAULT 0x00 +#define PUSH_TIME_ODD 0x40 +#define NO_EXTEND_TOGGLE 0x00 +#define EXTEND_TOGGLE_CHK 0x20 +#define MS_BUS_WIDTH_1 0x00 +#define MS_BUS_WIDTH_4 0x10 +#define MS_BUS_WIDTH_8 0x18 +#define MS_2K_SECTOR_MODE 0x04 +#define MS_512_SECTOR_MODE 0x00 +#define MS_TOGGLE_TIMEOUT_EN 0x00 +#define MS_TOGGLE_TIMEOUT_DISEN 0x01 +#define MS_NO_CHECK_INT 0x02 + +#define WAIT_INT 0x80 +#define NO_WAIT_INT 0x00 +#define NO_AUTO_READ_INT_REG 0x00 +#define AUTO_READ_INT_REG 0x40 +#define MS_CRC16_ERR 0x20 +#define MS_RDY_TIMEOUT 0x10 +#define MS_INT_CMDNK 0x08 +#define MS_INT_BREQ 0x04 +#define MS_INT_ERR 0x02 +#define MS_INT_CED 0x01 + +#define MS_TRANSFER_START 0x80 +#define MS_TRANSFER_END 0x40 +#define MS_TRANSFER_ERR 0x20 +#define MS_BS_STATE 0x10 +#define MS_TM_READ_BYTES 0x00 +#define MS_TM_NORMAL_READ 0x01 +#define MS_TM_WRITE_BYTES 0x04 +#define MS_TM_NORMAL_WRITE 0x05 +#define MS_TM_AUTO_READ 0x08 +#define MS_TM_AUTO_WRITE 0x0C + +#define CARD_SHARE_MASK 0x0F +#define CARD_SHARE_MULTI_LUN 0x00 +#define CARD_SHARE_NORMAL 0x00 +#define CARD_SHARE_48_XD 0x02 +#define CARD_SHARE_48_SD 0x04 +#define CARD_SHARE_48_MS 0x08 +#define CARD_SHARE_BAROSSA_XD 0x00 +#define CARD_SHARE_BAROSSA_SD 0x01 +#define CARD_SHARE_BAROSSA_MS 0x02 + +#define MS_DRIVE_8 0x00 +#define MS_DRIVE_4 0x40 +#define MS_DRIVE_12 0x80 +#define SD_DRIVE_8 0x00 +#define SD_DRIVE_4 0x10 +#define SD_DRIVE_12 0x20 +#define XD_DRIVE_8 0x00 +#define XD_DRIVE_4 0x04 +#define XD_DRIVE_12 0x08 + +#define SPI_STOP 0x01 +#define XD_STOP 0x02 +#define SD_STOP 0x04 +#define MS_STOP 0x08 +#define SPI_CLR_ERR 0x10 +#define XD_CLR_ERR 0x20 +#define SD_CLR_ERR 0x40 +#define MS_CLR_ERR 0x80 + +#define CRC_FIX_CLK (0x00 << 0) +#define CRC_VAR_CLK0 (0x01 << 0) +#define CRC_VAR_CLK1 (0x02 << 0) +#define SD30_FIX_CLK (0x00 << 2) +#define SD30_VAR_CLK0 (0x01 << 2) +#define SD30_VAR_CLK1 (0x02 << 2) +#define SAMPLE_FIX_CLK (0x00 << 4) +#define SAMPLE_VAR_CLK0 (0x01 << 4) +#define SAMPLE_VAR_CLK1 (0x02 << 4) + +#define SDIO_VER_20 0x80 +#define SDIO_VER_10 0x00 +#define SDIO_VER_CHG 0x40 +#define SDIO_BUS_AUTO_SWITCH 0x10 + +#define PINGPONG_BUFFER 0x01 +#define RING_BUFFER 0x00 + +#define RB_FLUSH 0x80 + +#define DMA_DONE_INT_EN 0x80 +#define SUSPEND_INT_EN 0x40 +#define LINK_RDY_INT_EN 0x20 +#define LINK_DOWN_INT_EN 0x10 + +#define DMA_DONE_INT 0x80 +#define SUSPEND_INT 0x40 +#define LINK_RDY_INT 0x20 +#define LINK_DOWN_INT 0x10 + +#define MRD_ERR_INT_EN 0x40 +#define MWR_ERR_INT_EN 0x20 +#define SCSI_CMD_INT_EN 0x10 +#define TLP_RCV_INT_EN 0x08 +#define TLP_TRSMT_INT_EN 0x04 +#define MRD_COMPLETE_INT_EN 0x02 +#define MWR_COMPLETE_INT_EN 0x01 + +#define MRD_ERR_INT 0x40 +#define MWR_ERR_INT 0x20 +#define SCSI_CMD_INT 0x10 +#define TLP_RX_INT 0x08 +#define TLP_TX_INT 0x04 +#define MRD_COMPLETE_INT 0x02 +#define MWR_COMPLETE_INT 0x01 + +#define MSG_RX_INT_EN 0x08 +#define MRD_RX_INT_EN 0x04 +#define MWR_RX_INT_EN 0x02 +#define CPLD_RX_INT_EN 0x01 + +#define MSG_RX_INT 0x08 +#define MRD_RX_INT 0x04 +#define MWR_RX_INT 0x02 +#define CPLD_RX_INT 0x01 + +#define MSG_TX_INT_EN 0x08 +#define MRD_TX_INT_EN 0x04 +#define MWR_TX_INT_EN 0x02 +#define CPLD_TX_INT_EN 0x01 + +#define MSG_TX_INT 0x08 +#define MRD_TX_INT 0x04 +#define MWR_TX_INT 0x02 +#define CPLD_TX_INT 0x01 + +#define DMA_RST 0x80 +#define DMA_BUSY 0x04 +#define DMA_DIR_TO_CARD 0x00 +#define DMA_DIR_FROM_CARD 0x02 +#define DMA_EN 0x01 +#define DMA_128 (0 << 4) +#define DMA_256 (1 << 4) +#define DMA_512 (2 << 4) +#define DMA_1024 (3 << 4) +#define DMA_PACK_SIZE_MASK 0x30 + +#define XD_PWR_OFF_DELAY0 0x00 +#define XD_PWR_OFF_DELAY1 0x02 +#define XD_PWR_OFF_DELAY2 0x04 +#define XD_PWR_OFF_DELAY3 0x06 +#define XD_AUTO_PWR_OFF_EN 0xF7 +#define XD_NO_AUTO_PWR_OFF 0x08 + +#define XD_TIME_RWN_1 0x00 +#define XD_TIME_RWN_STEP 0x20 +#define XD_TIME_RW_1 0x00 +#define XD_TIME_RW_STEP 0x04 +#define XD_TIME_SETUP_1 0x00 +#define XD_TIME_SETUP_STEP 0x01 + +#define XD_ECC2_UNCORRECTABLE 0x80 +#define XD_ECC2_ERROR 0x40 +#define XD_ECC1_UNCORRECTABLE 0x20 +#define XD_ECC1_ERROR 0x10 +#define XD_RDY 0x04 +#define XD_CE_EN 0xFD +#define XD_CE_DISEN 0x02 +#define XD_WP_EN 0xFE +#define XD_WP_DISEN 0x01 + +#define XD_TRANSFER_START 0x80 +#define XD_TRANSFER_END 0x40 +#define XD_PPB_EMPTY 0x20 +#define XD_RESET 0x00 +#define XD_ERASE 0x01 +#define XD_READ_STATUS 0x02 +#define XD_READ_ID 0x03 +#define XD_READ_REDUNDANT 0x04 +#define XD_READ_PAGES 0x05 +#define XD_SET_CMD 0x06 +#define XD_NORMAL_READ 0x07 +#define XD_WRITE_PAGES 0x08 +#define XD_NORMAL_WRITE 0x09 +#define XD_WRITE_REDUNDANT 0x0A +#define XD_SET_ADDR 0x0B + +#define XD_PPB_TO_SIE 0x80 +#define XD_TO_PPB_ONLY 0x00 +#define XD_BA_TRANSFORM 0x40 +#define XD_BA_NO_TRANSFORM 0x00 +#define XD_NO_CALC_ECC 0x20 +#define XD_CALC_ECC 0x00 +#define XD_IGNORE_ECC 0x10 +#define XD_CHECK_ECC 0x00 +#define XD_DIRECT_TO_RB 0x08 +#define XD_ADDR_LENGTH_0 0x00 +#define XD_ADDR_LENGTH_1 0x01 +#define XD_ADDR_LENGTH_2 0x02 +#define XD_ADDR_LENGTH_3 0x03 +#define XD_ADDR_LENGTH_4 0x04 + +#define XD_GPG 0xFF +#define XD_BPG 0x00 + +#define XD_GBLK 0xFF +#define XD_LATER_BBLK 0xF0 + +#define XD_ECC2_ALL1 0x80 +#define XD_ECC1_ALL1 0x40 +#define XD_BA2_ALL0 0x20 +#define XD_BA1_ALL0 0x10 +#define XD_BA1_BA2_EQL 0x04 +#define XD_BA2_VALID 0x02 +#define XD_BA1_VALID 0x01 + +#define XD_PGSTS_ZEROBIT_OVER4 0x00 +#define XD_PGSTS_NOT_FF 0x02 +#define XD_AUTO_CHK_DATA_STATUS 0x01 + +#define RSTB_MODE_DETECT 0x80 +#define MODE_OUT_VLD 0x40 +#define MODE_OUT_0_NONE 0x00 +#define MODE_OUT_10_NONE 0x04 +#define MODE_OUT_10_47 0x05 +#define MODE_OUT_10_180 0x06 +#define MODE_OUT_10_680 0x07 +#define MODE_OUT_16_NONE 0x08 +#define MODE_OUT_16_47 0x09 +#define MODE_OUT_16_180 0x0A +#define MODE_OUT_16_680 0x0B +#define MODE_OUT_NONE_NONE 0x0C +#define MODE_OUT_NONE_47 0x0D +#define MODE_OUT_NONE_180 0x0E +#define MODE_OUT_NONE_680 0x0F + +#define CARD_OC_INT_EN 0x20 +#define CARD_DETECT_EN 0x08 + +#define MS_DETECT_EN 0x80 +#define MS_OCP_INT_EN 0x40 +#define MS_OCP_INT_CLR 0x20 +#define MS_OC_CLR 0x10 +#define SD_DETECT_EN 0x08 +#define SD_OCP_INT_EN 0x04 +#define SD_OCP_INT_CLR 0x02 +#define SD_OC_CLR 0x01 + +#define CARD_OCP_DETECT 0x80 +#define CARD_OC_NOW 0x08 +#define CARD_OC_EVER 0x04 + +#define MS_OCP_DETECT 0x80 +#define MS_OC_NOW 0x40 +#define MS_OC_EVER 0x20 +#define SD_OCP_DETECT 0x08 +#define SD_OC_NOW 0x04 +#define SD_OC_EVER 0x02 + +#define CARD_OC_INT_CLR 0x08 +#define CARD_OC_CLR 0x02 + +#define SD_OCP_GLITCH_MASK 0x07 +#define SD_OCP_GLITCH_6_4 0x00 +#define SD_OCP_GLITCH_64 0x01 +#define SD_OCP_GLITCH_640 0x02 +#define SD_OCP_GLITCH_1000 0x03 +#define SD_OCP_GLITCH_2000 0x04 +#define SD_OCP_GLITCH_4000 0x05 +#define SD_OCP_GLITCH_8000 0x06 +#define SD_OCP_GLITCH_10000 0x07 + +#define MS_OCP_GLITCH_MASK 0x70 +#define MS_OCP_GLITCH_6_4 (0x00 << 4) +#define MS_OCP_GLITCH_64 (0x01 << 4) +#define MS_OCP_GLITCH_640 (0x02 << 4) +#define MS_OCP_GLITCH_1000 (0x03 << 4) +#define MS_OCP_GLITCH_2000 (0x04 << 4) +#define MS_OCP_GLITCH_4000 (0x05 << 4) +#define MS_OCP_GLITCH_8000 (0x06 << 4) +#define MS_OCP_GLITCH_10000 (0x07 << 4) + +#define OCP_TIME_60 0x00 +#define OCP_TIME_100 (0x01 << 3) +#define OCP_TIME_200 (0x02 << 3) +#define OCP_TIME_400 (0x03 << 3) +#define OCP_TIME_600 (0x04 << 3) +#define OCP_TIME_800 (0x05 << 3) +#define OCP_TIME_1100 (0x06 << 3) +#define OCP_TIME_MASK 0x38 + +#define MS_OCP_TIME_60 0x00 +#define MS_OCP_TIME_100 (0x01 << 4) +#define MS_OCP_TIME_200 (0x02 << 4) +#define MS_OCP_TIME_400 (0x03 << 4) +#define MS_OCP_TIME_600 (0x04 << 4) +#define MS_OCP_TIME_800 (0x05 << 4) +#define MS_OCP_TIME_1100 (0x06 << 4) +#define MS_OCP_TIME_MASK 0x70 + +#define SD_OCP_TIME_60 0x00 +#define SD_OCP_TIME_100 0x01 +#define SD_OCP_TIME_200 0x02 +#define SD_OCP_TIME_400 0x03 +#define SD_OCP_TIME_600 0x04 +#define SD_OCP_TIME_800 0x05 +#define SD_OCP_TIME_1100 0x06 +#define SD_OCP_TIME_MASK 0x07 + +#define OCP_THD_315_417 0x00 +#define OCP_THD_283_783 (0x01 << 6) +#define OCP_THD_244_946 (0x02 << 6) +#define OCP_THD_191_1080 (0x03 << 6) +#define OCP_THD_MASK 0xC0 + +#define MS_OCP_THD_450 0x00 +#define MS_OCP_THD_550 (0x01 << 4) +#define MS_OCP_THD_650 (0x02 << 4) +#define MS_OCP_THD_750 (0x03 << 4) +#define MS_OCP_THD_850 (0x04 << 4) +#define MS_OCP_THD_950 (0x05 << 4) +#define MS_OCP_THD_1050 (0x06 << 4) +#define MS_OCP_THD_1150 (0x07 << 4) +#define MS_OCP_THD_MASK 0x70 + +#define SD_OCP_THD_450 0x00 +#define SD_OCP_THD_550 0x01 +#define SD_OCP_THD_650 0x02 +#define SD_OCP_THD_750 0x03 +#define SD_OCP_THD_850 0x04 +#define SD_OCP_THD_950 0x05 +#define SD_OCP_THD_1050 0x06 +#define SD_OCP_THD_1150 0x07 +#define SD_OCP_THD_MASK 0x07 + +#define FPGA_MS_PULL_CTL_EN 0xEF +#define FPGA_SD_PULL_CTL_EN 0xF7 +#define FPGA_XD_PULL_CTL_EN1 0xFE +#define FPGA_XD_PULL_CTL_EN2 0xFD +#define FPGA_XD_PULL_CTL_EN3 0xFB + +#define FPGA_MS_PULL_CTL_BIT 0x10 +#define FPGA_SD_PULL_CTL_BIT 0x08 + +#define BLINK_EN 0x08 +#define LED_GPIO0 (0 << 4) +#define LED_GPIO1 (1 << 4) +#define LED_GPIO2 (2 << 4) + +#define SDIO_BUS_CTRL 0x01 +#define SDIO_CD_CTRL 0x02 + +#define SSC_RSTB 0x80 +#define SSC_8X_EN 0x40 +#define SSC_FIX_FRAC 0x20 +#define SSC_SEL_1M 0x00 +#define SSC_SEL_2M 0x08 +#define SSC_SEL_4M 0x10 +#define SSC_SEL_8M 0x18 + +#define SSC_DEPTH_MASK 0x07 +#define SSC_DEPTH_DISALBE 0x00 +#define SSC_DEPTH_4M 0x01 +#define SSC_DEPTH_2M 0x02 +#define SSC_DEPTH_1M 0x03 +#define SSC_DEPTH_512K 0x04 +#define SSC_DEPTH_256K 0x05 +#define SSC_DEPTH_128K 0x06 +#define SSC_DEPTH_64K 0x07 + +#define XD_D3_NP 0x00 +#define XD_D3_PD (0x01 << 6) +#define XD_D3_PU (0x02 << 6) +#define XD_D2_NP 0x00 +#define XD_D2_PD (0x01 << 4) +#define XD_D2_PU (0x02 << 4) +#define XD_D1_NP 0x00 +#define XD_D1_PD (0x01 << 2) +#define XD_D1_PU (0x02 << 2) +#define XD_D0_NP 0x00 +#define XD_D0_PD 0x01 +#define XD_D0_PU 0x02 + +#define SD_D7_NP 0x00 +#define SD_D7_PD (0x01 << 4) +#define SD_DAT7_PU (0x02 << 4) +#define SD_CLK_NP 0x00 +#define SD_CLK_PD (0x01 << 2) +#define SD_CLK_PU (0x02 << 2) +#define SD_D5_NP 0x00 +#define SD_D5_PD 0x01 +#define SD_D5_PU 0x02 + +#define MS_D1_NP 0x00 +#define MS_D1_PD (0x01 << 6) +#define MS_D1_PU (0x02 << 6) +#define MS_D2_NP 0x00 +#define MS_D2_PD (0x01 << 4) +#define MS_D2_PU (0x02 << 4) +#define MS_CLK_NP 0x00 +#define MS_CLK_PD (0x01 << 2) +#define MS_CLK_PU (0x02 << 2) +#define MS_D6_NP 0x00 +#define MS_D6_PD 0x01 +#define MS_D6_PU 0x02 + +#define XD_D7_NP 0x00 +#define XD_D7_PD (0x01 << 6) +#define XD_D7_PU (0x02 << 6) +#define XD_D6_NP 0x00 +#define XD_D6_PD (0x01 << 4) +#define XD_D6_PU (0x02 << 4) +#define XD_D5_NP 0x00 +#define XD_D5_PD (0x01 << 2) +#define XD_D5_PU (0x02 << 2) +#define XD_D4_NP 0x00 +#define XD_D4_PD 0x01 +#define XD_D4_PU 0x02 + +#define SD_D6_NP 0x00 +#define SD_D6_PD (0x01 << 6) +#define SD_D6_PU (0x02 << 6) +#define SD_D0_NP 0x00 +#define SD_D0_PD (0x01 << 4) +#define SD_D0_PU (0x02 << 4) +#define SD_D1_NP 0x00 +#define SD_D1_PD 0x01 +#define SD_D1_PU 0x02 + +#define MS_D3_NP 0x00 +#define MS_D3_PD (0x01 << 6) +#define MS_D3_PU (0x02 << 6) +#define MS_D0_NP 0x00 +#define MS_D0_PD (0x01 << 4) +#define MS_D0_PU (0x02 << 4) +#define MS_BS_NP 0x00 +#define MS_BS_PD (0x01 << 2) +#define MS_BS_PU (0x02 << 2) + +#define XD_WP_NP 0x00 +#define XD_WP_PD (0x01 << 6) +#define XD_WP_PU (0x02 << 6) +#define XD_CE_NP 0x00 +#define XD_CE_PD (0x01 << 3) +#define XD_CE_PU (0x02 << 3) +#define XD_CLE_NP 0x00 +#define XD_CLE_PD (0x01 << 1) +#define XD_CLE_PU (0x02 << 1) +#define XD_CD_PD 0x00 +#define XD_CD_PU 0x01 + +#define SD_D4_NP 0x00 +#define SD_D4_PD (0x01 << 6) +#define SD_D4_PU (0x02 << 6) + +#define MS_D7_NP 0x00 +#define MS_D7_PD (0x01 << 6) +#define MS_D7_PU (0x02 << 6) + +#define XD_RDY_NP 0x00 +#define XD_RDY_PD (0x01 << 6) +#define XD_RDY_PU (0x02 << 6) +#define XD_WE_NP 0x00 +#define XD_WE_PD (0x01 << 4) +#define XD_WE_PU (0x02 << 4) +#define XD_RE_NP 0x00 +#define XD_RE_PD (0x01 << 2) +#define XD_RE_PU (0x02 << 2) +#define XD_ALE_NP 0x00 +#define XD_ALE_PD 0x01 +#define XD_ALE_PU 0x02 + +#define SD_D3_NP 0x00 +#define SD_D3_PD (0x01 << 4) +#define SD_D3_PU (0x02 << 4) +#define SD_D2_NP 0x00 +#define SD_D2_PD (0x01 << 2) +#define SD_D2_PU (0x02 << 2) + +#define MS_INS_PD 0x00 +#define MS_INS_PU (0x01 << 7) +#define SD_WP_NP 0x00 +#define SD_WP_PD (0x01 << 5) +#define SD_WP_PU (0x02 << 5) +#define SD_CD_PD 0x00 +#define SD_CD_PU (0x01 << 4) +#define SD_CMD_NP 0x00 +#define SD_CMD_PD (0x01 << 2) +#define SD_CMD_PU (0x02 << 2) + +#define MS_D5_NP 0x00 +#define MS_D5_PD (0x01 << 2) +#define MS_D5_PU (0x02 << 2) +#define MS_D4_NP 0x00 +#define MS_D4_PD 0x01 +#define MS_D4_PU 0x02 + +#define FORCE_PM_CLOCK 0x10 +#define EN_CLOCK_PM 0x01 + +#define HOST_ENTER_S3 0x02 +#define HOST_ENTER_S1 0x01 + +#define AUX_PWR_DETECTED 0x01 + +#define PHY_DEBUG_MODE 0x01 + +#define SPI_COMMAND_BIT_8 0xE0 +#define SPI_ADDRESS_BIT_24 0x17 +#define SPI_ADDRESS_BIT_32 0x1F + +#define SPI_TRANSFER0_START 0x80 +#define SPI_TRANSFER0_END 0x40 +#define SPI_C_MODE0 0x00 +#define SPI_CA_MODE0 0x01 +#define SPI_CDO_MODE0 0x02 +#define SPI_CDI_MODE0 0x03 +#define SPI_CADO_MODE0 0x04 +#define SPI_CADI_MODE0 0x05 +#define SPI_POLLING_MODE0 0x06 + +#define SPI_TRANSFER1_START 0x80 +#define SPI_TRANSFER1_END 0x40 +#define SPI_DO_MODE1 0x00 +#define SPI_DI_MODE1 0x01 + +#define CS_POLARITY_HIGH 0x40 +#define CS_POLARITY_LOW 0x00 +#define DTO_MSB_FIRST 0x00 +#define DTO_LSB_FIRST 0x20 +#define SPI_MASTER 0x00 +#define SPI_SLAVE 0x10 +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x04 +#define SPI_MODE2 0x08 +#define SPI_MODE3 0x0C +#define SPI_MANUAL 0x00 +#define SPI_HALF_AUTO 0x01 +#define SPI_AUTO 0x02 +#define SPI_EEPROM_AUTO 0x03 + +#define EDO_TIMING_MASK 0x03 +#define SAMPLE_RISING 0x00 +#define SAMPLE_DELAY_HALF 0x01 +#define SAMPLE_DELAY_ONE 0x02 +#define SAPMLE_DELAY_ONE_HALF 0x03 +#define TCS_MASK 0x0C + +#define NOT_BYPASS_SD 0x02 +#define DISABLE_SDIO_FUNC 0x04 +#define SELECT_1LUN 0x08 + +#define PWR_GATE_EN 0x01 +#define LDO3318_PWR_MASK 0x06 +#define LDO_ON 0x00 +#define LDO_SUSPEND 0x04 +#define LDO_OFF 0x06 + +#define SD_CFG1 0xFDA0 +#define SD_CFG2 0xFDA1 +#define SD_CFG3 0xFDA2 +#define SD_STAT1 0xFDA3 +#define SD_STAT2 0xFDA4 +#define SD_BUS_STAT 0xFDA5 +#define SD_PAD_CTL 0xFDA6 +#define SD_SAMPLE_POINT_CTL 0xFDA7 +#define SD_PUSH_POINT_CTL 0xFDA8 +#define SD_CMD0 0xFDA9 +#define SD_CMD1 0xFDAA +#define SD_CMD2 0xFDAB +#define SD_CMD3 0xFDAC +#define SD_CMD4 0xFDAD +#define SD_CMD5 0xFDAE +#define SD_BYTE_CNT_L 0xFDAF +#define SD_BYTE_CNT_H 0xFDB0 +#define SD_BLOCK_CNT_L 0xFDB1 +#define SD_BLOCK_CNT_H 0xFDB2 +#define SD_TRANSFER 0xFDB3 +#define SD_CMD_STATE 0xFDB5 +#define SD_DATA_STATE 0xFDB6 + +#define DCM_DRP_CTL 0xFC23 +#define DCM_DRP_TRIG 0xFC24 +#define DCM_DRP_CFG 0xFC25 +#define DCM_DRP_WR_DATA_L 0xFC26 +#define DCM_DRP_WR_DATA_H 0xFC27 +#define DCM_DRP_RD_DATA_L 0xFC28 +#define DCM_DRP_RD_DATA_H 0xFC29 +#define SD_VPCLK0_CTL 0xFC2A +#define SD_VPCLK1_CTL 0xFC2B +#define SD_DCMPS0_CTL 0xFC2C +#define SD_DCMPS1_CTL 0xFC2D +#define SD_VPTX_CTL SD_VPCLK0_CTL +#define SD_VPRX_CTL SD_VPCLK1_CTL +#define SD_DCMPS_TX_CTL SD_DCMPS0_CTL +#define SD_DCMPS_RX_CTL SD_DCMPS1_CTL + +#define CARD_CLK_SOURCE 0xFC2E + +#define CARD_PWR_CTL 0xFD50 +#define CARD_CLK_SWITCH 0xFD51 +#define CARD_SHARE_MODE 0xFD52 +#define CARD_DRIVE_SEL 0xFD53 +#define CARD_STOP 0xFD54 +#define CARD_OE 0xFD55 +#define CARD_AUTO_BLINK 0xFD56 +#define CARD_GPIO_DIR 0xFD57 +#define CARD_GPIO 0xFD58 + +#define CARD_DATA_SOURCE 0xFD5B +#define CARD_SELECT 0xFD5C +#define SD30_DRIVE_SEL 0xFD5E + +#define CARD_CLK_EN 0xFD69 + +#define SDIO_CTRL 0xFD6B + +#define FPDCTL 0xFC00 +#define PDINFO 0xFC01 + +#define CLK_CTL 0xFC02 +#define CLK_DIV 0xFC03 +#define CLK_SEL 0xFC04 + +#define SSC_DIV_N_0 0xFC0F +#define SSC_DIV_N_1 0xFC10 + +#define RCCTL 0xFC14 + +#define FPGA_PULL_CTL 0xFC1D + +#define CARD_PULL_CTL1 0xFD60 +#define CARD_PULL_CTL2 0xFD61 +#define CARD_PULL_CTL3 0xFD62 +#define CARD_PULL_CTL4 0xFD63 +#define CARD_PULL_CTL5 0xFD64 +#define CARD_PULL_CTL6 0xFD65 + +#define IRQEN0 0xFE20 +#define IRQSTAT0 0xFE21 +#define IRQEN1 0xFE22 +#define IRQSTAT1 0xFE23 +#define TLPRIEN 0xFE24 +#define TLPRISTAT 0xFE25 +#define TLPTIEN 0xFE26 +#define TLPTISTAT 0xFE27 +#define DMATC0 0xFE28 +#define DMATC1 0xFE29 +#define DMATC2 0xFE2A +#define DMATC3 0xFE2B +#define DMACTL 0xFE2C +#define BCTL 0xFE2D +#define RBBC0 0xFE2E +#define RBBC1 0xFE2F +#define RBDAT 0xFE30 +#define RBCTL 0xFE34 +#define CFGADDR0 0xFE35 +#define CFGADDR1 0xFE36 +#define CFGDATA0 0xFE37 +#define CFGDATA1 0xFE38 +#define CFGDATA2 0xFE39 +#define CFGDATA3 0xFE3A +#define CFGRWCTL 0xFE3B +#define PHYRWCTL 0xFE3C +#define PHYDATA0 0xFE3D +#define PHYDATA1 0xFE3E +#define PHYADDR 0xFE3F +#define MSGRXDATA0 0xFE40 +#define MSGRXDATA1 0xFE41 +#define MSGRXDATA2 0xFE42 +#define MSGRXDATA3 0xFE43 +#define MSGTXDATA0 0xFE44 +#define MSGTXDATA1 0xFE45 +#define MSGTXDATA2 0xFE46 +#define MSGTXDATA3 0xFE47 +#define MSGTXCTL 0xFE48 +#define PETXCFG 0xFE49 + +#define CDRESUMECTL 0xFE52 +#define WAKE_SEL_CTL 0xFE54 +#define PME_FORCE_CTL 0xFE56 +#define ASPM_FORCE_CTL 0xFE57 +#define PM_CLK_FORCE_CTL 0xFE58 +#define PERST_GLITCH_WIDTH 0xFE5C +#define CHANGE_LINK_STATE 0xFE5B +#define RESET_LOAD_REG 0xFE5E +#define HOST_SLEEP_STATE 0xFE60 +#define MAIN_PWR_OFF_CTL 0xFE70 /* RTS5208 */ + +#define NFTS_TX_CTRL 0xFE72 + +#define PWR_GATE_CTRL 0xFE75 +#define PWD_SUSPEND_EN 0xFE76 + +#define EFUSE_CONTENT 0xFE5F + +#define XD_INIT 0xFD10 +#define XD_DTCTL 0xFD11 +#define XD_CTL 0xFD12 +#define XD_TRANSFER 0xFD13 +#define XD_CFG 0xFD14 +#define XD_ADDRESS0 0xFD15 +#define XD_ADDRESS1 0xFD16 +#define XD_ADDRESS2 0xFD17 +#define XD_ADDRESS3 0xFD18 +#define XD_ADDRESS4 0xFD19 +#define XD_DAT 0xFD1A +#define XD_PAGE_CNT 0xFD1B +#define XD_PAGE_STATUS 0xFD1C +#define XD_BLOCK_STATUS 0xFD1D +#define XD_BLOCK_ADDR1_L 0xFD1E +#define XD_BLOCK_ADDR1_H 0xFD1F +#define XD_BLOCK_ADDR2_L 0xFD20 +#define XD_BLOCK_ADDR2_H 0xFD21 +#define XD_BYTE_CNT_L 0xFD22 +#define XD_BYTE_CNT_H 0xFD23 +#define XD_PARITY 0xFD24 +#define XD_ECC_BIT1 0xFD25 +#define XD_ECC_BYTE1 0xFD26 +#define XD_ECC_BIT2 0xFD27 +#define XD_ECC_BYTE2 0xFD28 +#define XD_RESERVED0 0xFD29 +#define XD_RESERVED1 0xFD2A +#define XD_RESERVED2 0xFD2B +#define XD_RESERVED3 0xFD2C +#define XD_CHK_DATA_STATUS 0xFD2D +#define XD_CATCTL 0xFD2E + +#define MS_CFG 0xFD40 +#define MS_TPC 0xFD41 +#define MS_TRANS_CFG 0xFD42 +#define MS_TRANSFER 0xFD43 +#define MS_INT_REG 0xFD44 +#define MS_BYTE_CNT 0xFD45 +#define MS_SECTOR_CNT_L 0xFD46 +#define MS_SECTOR_CNT_H 0xFD47 +#define MS_DBUS_H 0xFD48 + +#define SSC_CTL1 0xFC11 +#define SSC_CTL2 0xFC12 + +#define OCPCTL 0xFC15 +#define OCPSTAT 0xFC16 +#define OCPCLR 0xFC17 /* 5208 */ +#define OCPPARA1 0xFC18 +#define OCPPARA2 0xFC19 + +#define EFUSE_OP 0xFC20 +#define EFUSE_CTRL 0xFC21 +#define EFUSE_DATA 0xFC22 + +#define SPI_COMMAND 0xFD80 +#define SPI_ADDR0 0xFD81 +#define SPI_ADDR1 0xFD82 +#define SPI_ADDR2 0xFD83 +#define SPI_ADDR3 0xFD84 +#define SPI_CA_NUMBER 0xFD85 +#define SPI_LENGTH0 0xFD86 +#define SPI_LENGTH1 0xFD87 +#define SPI_DATA 0xFD88 +#define SPI_DATA_NUMBER 0xFD89 +#define SPI_TRANSFER0 0xFD90 +#define SPI_TRANSFER1 0xFD91 +#define SPI_CONTROL 0xFD92 +#define SPI_SIG 0xFD93 +#define SPI_TCTL 0xFD94 +#define SPI_SLAVE_NUM 0xFD95 +#define SPI_CLK_DIVIDER0 0xFD96 +#define SPI_CLK_DIVIDER1 0xFD97 + +#define SRAM_BASE 0xE600 +#define RBUF_BASE 0xF400 +#define PPBUF_BASE1 0xF800 +#define PPBUF_BASE2 0xFA00 +#define IMAGE_FLAG_ADDR0 0xCE80 +#define IMAGE_FLAG_ADDR1 0xCE81 + +#define READ_OP 1 +#define WRITE_OP 2 + +#define LCTLR 0x80 + +#define POLLING_WAIT_CNT 1 +#define IDLE_MAX_COUNT 10 +#define SDIO_IDLE_COUNT 10 + +#define DEBOUNCE_CNT 5 + +void do_remaining_work(struct rtsx_chip *chip); +void try_to_switch_sdio_ctrl(struct rtsx_chip *chip); +void do_reset_sd_card(struct rtsx_chip *chip); +void do_reset_xd_card(struct rtsx_chip *chip); +void do_reset_ms_card(struct rtsx_chip *chip); +void rtsx_power_off_card(struct rtsx_chip *chip); +void rtsx_release_cards(struct rtsx_chip *chip); +void rtsx_reset_cards(struct rtsx_chip *chip); +void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip); +void rtsx_init_cards(struct rtsx_chip *chip); +int switch_ssc_clock(struct rtsx_chip *chip, int clk); +int switch_normal_clock(struct rtsx_chip *chip, int clk); +int enable_card_clock(struct rtsx_chip *chip, u8 card); +int disable_card_clock(struct rtsx_chip *chip, u8 card); +int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 sec_addr, u16 sec_cnt); +void trans_dma_enable(enum dma_data_direction dir, + struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size); +void toggle_gpio(struct rtsx_chip *chip, u8 gpio); +void turn_on_led(struct rtsx_chip *chip, u8 gpio); +void turn_off_led(struct rtsx_chip *chip, u8 gpio); + +int card_share_mode(struct rtsx_chip *chip, int card); +int select_card(struct rtsx_chip *chip, int card); +int detect_card_cd(struct rtsx_chip *chip, int card); +int check_card_exist(struct rtsx_chip *chip, unsigned int lun); +int check_card_ready(struct rtsx_chip *chip, unsigned int lun); +int check_card_wp(struct rtsx_chip *chip, unsigned int lun); +int check_card_fail(struct rtsx_chip *chip, unsigned int lun); +int check_card_ejected(struct rtsx_chip *chip, unsigned int lun); +void eject_card(struct rtsx_chip *chip, unsigned int lun); +u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun); + +static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun) +{ +#ifdef SUPPORT_SD_LOCK + struct sd_info *sd_card = &(chip->sd_card); + + if ((get_lun_card(chip, lun) == SD_CARD) && + (sd_card->sd_lock_status & SD_LOCKED)) + return 0; + else + return chip->capacity[lun]; +#else + return chip->capacity[lun]; +#endif +} + +static inline int switch_clock(struct rtsx_chip *chip, int clk) +{ + int retval = 0; + + if (chip->asic_code) + retval = switch_ssc_clock(chip, clk); + else + retval = switch_normal_clock(chip, clk); + + return retval; +} + +int card_power_on(struct rtsx_chip *chip, u8 card); +int card_power_off(struct rtsx_chip *chip, u8 card); + +static inline int card_power_off_all(struct rtsx_chip *chip) +{ + RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0x0F, 0x0F); + + return STATUS_SUCCESS; +} + +static inline void rtsx_clear_xd_error(struct rtsx_chip *chip) +{ + rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, + XD_STOP | XD_CLR_ERR); +} + +static inline void rtsx_clear_sd_error(struct rtsx_chip *chip) +{ + rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, + SD_STOP | SD_CLR_ERR); +} + +static inline void rtsx_clear_ms_error(struct rtsx_chip *chip) +{ + rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, + MS_STOP | MS_CLR_ERR); +} + +static inline void rtsx_clear_spi_error(struct rtsx_chip *chip) +{ + rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR, + SPI_STOP | SPI_CLR_ERR); +} + +#ifdef SUPPORT_SDIO_ASPM +void dynamic_configure_sdio_aspm(struct rtsx_chip *chip); +#endif + +#endif /* __REALTEK_RTSX_CARD_H */ diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c new file mode 100644 index 000000000000..6426807a906f --- /dev/null +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -0,0 +1,1979 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" +#include "rtsx_chip.h" +#include "rtsx_sys.h" +#include "general.h" + +#include "sd.h" +#include "xd.h" +#include "ms.h" + +static void rtsx_calibration(struct rtsx_chip *chip) +{ + rtsx_write_phy_register(chip, 0x1B, 0x135E); + wait_timeout(10); + rtsx_write_phy_register(chip, 0x00, 0x0280); + rtsx_write_phy_register(chip, 0x01, 0x7112); + rtsx_write_phy_register(chip, 0x01, 0x7110); + rtsx_write_phy_register(chip, 0x01, 0x7112); + rtsx_write_phy_register(chip, 0x01, 0x7113); + rtsx_write_phy_register(chip, 0x00, 0x0288); +} + +void rtsx_disable_card_int(struct rtsx_chip *chip) +{ + u32 reg = rtsx_readl(chip, RTSX_BIER); + + reg &= ~(XD_INT_EN | SD_INT_EN | MS_INT_EN); + rtsx_writel(chip, RTSX_BIER, reg); +} + +void rtsx_enable_card_int(struct rtsx_chip *chip) +{ + u32 reg = rtsx_readl(chip, RTSX_BIER); + int i; + + for (i = 0; i <= chip->max_lun; i++) { + if (chip->lun2card[i] & XD_CARD) + reg |= XD_INT_EN; + if (chip->lun2card[i] & SD_CARD) + reg |= SD_INT_EN; + if (chip->lun2card[i] & MS_CARD) + reg |= MS_INT_EN; + } + if (chip->hw_bypass_sd) + reg &= ~((u32)SD_INT_EN); + + rtsx_writel(chip, RTSX_BIER, reg); +} + +void rtsx_enable_bus_int(struct rtsx_chip *chip) +{ + u32 reg = 0; +#ifndef DISABLE_CARD_INT + int i; +#endif + + reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN; + +#ifndef DISABLE_CARD_INT + for (i = 0; i <= chip->max_lun; i++) { + RTSX_DEBUGP("lun2card[%d] = 0x%02x\n", i, chip->lun2card[i]); + + if (chip->lun2card[i] & XD_CARD) + reg |= XD_INT_EN; + if (chip->lun2card[i] & SD_CARD) + reg |= SD_INT_EN; + if (chip->lun2card[i] & MS_CARD) + reg |= MS_INT_EN; + } + if (chip->hw_bypass_sd) + reg &= ~((u32)SD_INT_EN); +#endif + + if (chip->ic_version >= IC_VER_C) + reg |= DELINK_INT_EN; +#ifdef SUPPORT_OCP + reg |= OC_INT_EN; +#endif + if (!chip->adma_mode) + reg |= DATA_DONE_INT_EN; + + /* Enable Bus Interrupt */ + rtsx_writel(chip, RTSX_BIER, reg); + + RTSX_DEBUGP("RTSX_BIER: 0x%08x\n", reg); +} + +void rtsx_disable_bus_int(struct rtsx_chip *chip) +{ + rtsx_writel(chip, RTSX_BIER, 0); +} + +static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip) +{ + if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) { + if (chip->asic_code) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, + FPGA_SD_PULL_CTL_EN); + } + RTSX_WRITE_REG(chip, CARD_SHARE_MODE, 0xFF, CARD_SHARE_48_SD); + + /* Enable SDIO internal clock */ + RTSX_WRITE_REG(chip, 0xFF2C, 0x01, 0x01); + + RTSX_WRITE_REG(chip, SDIO_CTRL, 0xFF, + SDIO_BUS_CTRL | SDIO_CD_CTRL); + + chip->sd_int = 1; + chip->sd_io = 1; + } else { + chip->need_reset |= SD_CARD; + } + + return STATUS_SUCCESS; +} + +#ifdef HW_AUTO_SWITCH_SD_BUS +static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip) +{ + u8 tmp; + int sw_bypass_sd = 0; + int retval; + + if (chip->driver_first_load) { + if (CHECK_PID(chip, 0x5288)) { + RTSX_READ_REG(chip, 0xFE5A, &tmp); + if (tmp & 0x08) + sw_bypass_sd = 1; + } else if (CHECK_PID(chip, 0x5208)) { + RTSX_READ_REG(chip, 0xFE70, &tmp); + if (tmp & 0x80) + sw_bypass_sd = 1; + } + } else { + if (chip->sdio_in_charge) + sw_bypass_sd = 1; + } + RTSX_DEBUGP("chip->sdio_in_charge = %d\n", chip->sdio_in_charge); + RTSX_DEBUGP("chip->driver_first_load = %d\n", chip->driver_first_load); + RTSX_DEBUGP("sw_bypass_sd = %d\n", sw_bypass_sd); + + if (sw_bypass_sd) { + u8 cd_toggle_mask = 0; + + RTSX_READ_REG(chip, TLPTISTAT, &tmp); + cd_toggle_mask = 0x08; + + if (tmp & cd_toggle_mask) { + /* Disable sdio_bus_auto_switch */ + if (CHECK_PID(chip, 0x5288)) + RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x00); + else if (CHECK_PID(chip, 0x5208)) + RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x00); + + RTSX_WRITE_REG(chip, TLPTISTAT, 0xFF, tmp); + + chip->need_reset |= SD_CARD; + } else { + RTSX_DEBUGP("Chip inserted with SDIO!\n"); + + if (chip->asic_code) { + retval = sd_pull_ctl_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, + FPGA_SD_PULL_CTL_BIT | 0x20, 0); + } + retval = card_share_mode(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + /* Enable sdio_bus_auto_switch */ + if (CHECK_PID(chip, 0x5288)) + RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x08); + else if (CHECK_PID(chip, 0x5208)) + RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x80); + + chip->chip_insert_with_sdio = 1; + chip->sd_io = 1; + } + } else { + RTSX_WRITE_REG(chip, TLPTISTAT, 0x08, 0x08); + + chip->need_reset |= SD_CARD; + } + + return STATUS_SUCCESS; +} +#endif + +int rtsx_reset_chip(struct rtsx_chip *chip) +{ + int retval; + + rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr); + + rtsx_disable_aspm(chip); + + RTSX_WRITE_REG(chip, HOST_SLEEP_STATE, 0x03, 0x00); + + /* Disable card clock */ + RTSX_WRITE_REG(chip, CARD_CLK_EN, 0x1E, 0); + +#ifdef SUPPORT_OCP + /* SSC power on, OCD power on */ + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, 0); + else + RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, MS_OC_POWER_DOWN); + + RTSX_WRITE_REG(chip, OCPPARA1, OCP_TIME_MASK, OCP_TIME_800); + RTSX_WRITE_REG(chip, OCPPARA2, OCP_THD_MASK, OCP_THD_244_946); + RTSX_WRITE_REG(chip, OCPCTL, 0xFF, CARD_OC_INT_EN | CARD_DETECT_EN); +#else + /* OC power down */ + RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, OC_POWER_DOWN); +#endif + + if (!CHECK_PID(chip, 0x5288)) + RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0xFF, 0x03); + + /* Turn off LED */ + RTSX_WRITE_REG(chip, CARD_GPIO, 0xFF, 0x03); + + /* Reset delink mode */ + RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x0A, 0); + + /* Card driving select */ + RTSX_WRITE_REG(chip, CARD_DRIVE_SEL, 0xFF, chip->card_drive_sel); + +#ifdef LED_AUTO_BLINK + RTSX_WRITE_REG(chip, CARD_AUTO_BLINK, 0xFF, + LED_BLINK_SPEED | BLINK_EN | LED_GPIO0); +#endif + + if (chip->asic_code) { + /* Enable SSC Clock */ + RTSX_WRITE_REG(chip, SSC_CTL1, 0xFF, SSC_8X_EN | SSC_SEL_4M); + RTSX_WRITE_REG(chip, SSC_CTL2, 0xFF, 0x12); + } + + /* Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0) + 0xFE5B + bit[1] u_cd_rst_core_en rst_value = 0 + bit[2] u_force_rst_core_en rst_value = 0 + bit[5] u_mac_phy_rst_n_dbg rst_value = 1 + bit[4] u_non_sticky_rst_n_dbg rst_value = 0 + */ + RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x16, 0x10); + + /* Enable ASPM */ + if (chip->aspm_l0s_l1_en) { + if (chip->dynamic_aspm) { + if (CHK_SDIO_EXIST(chip)) { + if (CHECK_PID(chip, 0x5288)) { + retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + } + } else { + if (CHECK_PID(chip, 0x5208)) + RTSX_WRITE_REG(chip, ASPM_FORCE_CTL, + 0xFF, 0x3F); + + retval = rtsx_write_config_byte(chip, LCTLR, + chip->aspm_l0s_l1_en); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + chip->aspm_level[0] = chip->aspm_l0s_l1_en; + if (CHK_SDIO_EXIST(chip)) { + chip->aspm_level[1] = chip->aspm_l0s_l1_en; + if (CHECK_PID(chip, 0x5288)) + retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en); + else + retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en); + + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } + + chip->aspm_enabled = 1; + } + } else { + if (chip->asic_code && CHECK_PID(chip, 0x5208)) { + retval = rtsx_write_phy_register(chip, 0x07, 0x0129); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + retval = rtsx_write_config_byte(chip, LCTLR, + chip->aspm_l0s_l1_en); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = rtsx_write_config_byte(chip, 0x81, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_SDIO_EXIST(chip)) { + if (CHECK_PID(chip, 0x5288)) + retval = rtsx_write_cfg_dw(chip, 2, 0xC0, + 0xFF00, 0x0100); + else + retval = rtsx_write_cfg_dw(chip, 1, 0xC0, + 0xFF00, 0x0100); + + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } + + if (CHECK_PID(chip, 0x5288)) { + if (!CHK_SDIO_EXIST(chip)) { + retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, + 0x0103); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } + } + + RTSX_WRITE_REG(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT); + + RTSX_WRITE_REG(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80); + + /* Enable PCIE interrupt */ + if (chip->asic_code) { + if (CHECK_PID(chip, 0x5208)) { + if (chip->phy_debug_mode) { + RTSX_WRITE_REG(chip, CDRESUMECTL, 0x77, 0); + rtsx_disable_bus_int(chip); + } else { + rtsx_enable_bus_int(chip); + } + + if (chip->ic_version >= IC_VER_D) { + u16 reg; + retval = rtsx_read_phy_register(chip, 0x00, + ®); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + reg &= 0xFE7F; + reg |= 0x80; + retval = rtsx_write_phy_register(chip, 0x00, + reg); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = rtsx_read_phy_register(chip, 0x1C, + ®); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + reg &= 0xFFF7; + retval = rtsx_write_phy_register(chip, 0x1C, + reg); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } + + if (chip->driver_first_load && + (chip->ic_version < IC_VER_C)) + rtsx_calibration(chip); + + } else { + rtsx_enable_bus_int(chip); + } + } else { + rtsx_enable_bus_int(chip); + } + + chip->need_reset = 0; + + chip->int_reg = rtsx_readl(chip, RTSX_BIPR); + + if (chip->hw_bypass_sd) + goto NextCard; + RTSX_DEBUGP("In rtsx_reset_chip, chip->int_reg = 0x%x\n", + chip->int_reg); + if (chip->int_reg & SD_EXIST) { +#ifdef HW_AUTO_SWITCH_SD_BUS + if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C)) + retval = rtsx_pre_handle_sdio_old(chip); + else + retval = rtsx_pre_handle_sdio_new(chip); + + RTSX_DEBUGP("chip->need_reset = 0x%x (rtsx_reset_chip)\n", + (unsigned int)(chip->need_reset)); +#else /* HW_AUTO_SWITCH_SD_BUS */ + retval = rtsx_pre_handle_sdio_old(chip); +#endif /* HW_AUTO_SWITCH_SD_BUS */ + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } else { + chip->sd_io = 0; + RTSX_WRITE_REG(chip, SDIO_CTRL, SDIO_BUS_CTRL | SDIO_CD_CTRL, + 0); + } + +NextCard: + if (chip->int_reg & XD_EXIST) + chip->need_reset |= XD_CARD; + if (chip->int_reg & MS_EXIST) + chip->need_reset |= MS_CARD; + if (chip->int_reg & CARD_EXIST) + RTSX_WRITE_REG(chip, SSC_CTL1, SSC_RSTB, SSC_RSTB); + + RTSX_DEBUGP("In rtsx_init_chip, chip->need_reset = 0x%x\n", + (unsigned int)(chip->need_reset)); + + RTSX_WRITE_REG(chip, RCCTL, 0x01, 0x00); + + if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) { + /* Turn off main power when entering S3/S4 state */ + RTSX_WRITE_REG(chip, MAIN_PWR_OFF_CTL, 0x03, 0x03); + } + + if (chip->remote_wakeup_en && !chip->auto_delink_en) { + RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x07); + if (chip->aux_pwr_exist) + RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x33); + } else { + RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x04); + RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x30); + } + + if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) + RTSX_WRITE_REG(chip, PETXCFG, 0x1C, 0x14); + + if (chip->asic_code && CHECK_PID(chip, 0x5208)) { + retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + if (chip->ft2_fast_mode) { + RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF, + MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON); + udelay(chip->pmos_pwr_on_interval); + RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF, + MS_POWER_ON | SD_POWER_ON); + + wait_timeout(200); + } + + /* Reset card */ + rtsx_reset_detected_cards(chip, 0); + + chip->driver_first_load = 0; + + return STATUS_SUCCESS; +} + +static inline int check_sd_speed_prior(u32 sd_speed_prior) +{ + int i, fake_para = 0; + + for (i = 0; i < 4; i++) { + u8 tmp = (u8)(sd_speed_prior >> (i*8)); + if ((tmp < 0x01) || (tmp > 0x04)) { + fake_para = 1; + break; + } + } + + return !fake_para; +} + +static inline int check_sd_current_prior(u32 sd_current_prior) +{ + int i, fake_para = 0; + + for (i = 0; i < 4; i++) { + u8 tmp = (u8)(sd_current_prior >> (i*8)); + if (tmp > 0x03) { + fake_para = 1; + break; + } + } + + return !fake_para; +} + +static int rts5208_init(struct rtsx_chip *chip) +{ + int retval; + u16 reg = 0; + u8 val = 0; + + RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03); + RTSX_READ_REG(chip, CLK_SEL, &val); + if (val == 0) + chip->asic_code = 1; + else + chip->asic_code = 0; + + if (chip->asic_code) { + retval = rtsx_read_phy_register(chip, 0x1C, ®); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("Value of phy register 0x1C is 0x%x\n", reg); + chip->ic_version = (reg >> 4) & 0x07; + if (reg & PHY_DEBUG_MODE) + chip->phy_debug_mode = 1; + else + chip->phy_debug_mode = 0; + + } else { + RTSX_READ_REG(chip, 0xFE80, &val); + chip->ic_version = val; + chip->phy_debug_mode = 0; + } + + RTSX_READ_REG(chip, PDINFO, &val); + RTSX_DEBUGP("PDINFO: 0x%x\n", val); + if (val & AUX_PWR_DETECTED) + chip->aux_pwr_exist = 1; + else + chip->aux_pwr_exist = 0; + + RTSX_READ_REG(chip, 0xFE50, &val); + if (val & 0x01) + chip->hw_bypass_sd = 1; + else + chip->hw_bypass_sd = 0; + + rtsx_read_config_byte(chip, 0x0E, &val); + if (val & 0x80) + SET_SDIO_EXIST(chip); + else + CLR_SDIO_EXIST(chip); + + if (chip->use_hw_setting) { + RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val); + if (val & 0x80) + chip->auto_delink_en = 1; + else + chip->auto_delink_en = 0; + } + + return STATUS_SUCCESS; +} + +static int rts5288_init(struct rtsx_chip *chip) +{ + int retval; + u8 val = 0, max_func; + u32 lval = 0; + + RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03); + RTSX_READ_REG(chip, CLK_SEL, &val); + if (val == 0) + chip->asic_code = 1; + else + chip->asic_code = 0; + + chip->ic_version = 0; + chip->phy_debug_mode = 0; + + RTSX_READ_REG(chip, PDINFO, &val); + RTSX_DEBUGP("PDINFO: 0x%x\n", val); + if (val & AUX_PWR_DETECTED) + chip->aux_pwr_exist = 1; + else + chip->aux_pwr_exist = 0; + + RTSX_READ_REG(chip, CARD_SHARE_MODE, &val); + RTSX_DEBUGP("CARD_SHARE_MODE: 0x%x\n", val); + if (val & 0x04) + chip->baro_pkg = QFN; + else + chip->baro_pkg = LQFP; + + RTSX_READ_REG(chip, 0xFE5A, &val); + if (val & 0x10) + chip->hw_bypass_sd = 1; + else + chip->hw_bypass_sd = 0; + + retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + max_func = (u8)((lval >> 29) & 0x07); + RTSX_DEBUGP("Max function number: %d\n", max_func); + if (max_func == 0x02) + SET_SDIO_EXIST(chip); + else + CLR_SDIO_EXIST(chip); + + if (chip->use_hw_setting) { + RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val); + if (val & 0x80) + chip->auto_delink_en = 1; + else + chip->auto_delink_en = 0; + + if (CHECK_BARO_PKG(chip, LQFP)) + chip->lun_mode = SD_MS_1LUN; + else + chip->lun_mode = DEFAULT_SINGLE; + + } + + return STATUS_SUCCESS; +} + +int rtsx_init_chip(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + struct xd_info *xd_card = &(chip->xd_card); + struct ms_info *ms_card = &(chip->ms_card); + int retval; + unsigned int i; + + RTSX_DEBUGP("Vendor ID: 0x%04x, Product ID: 0x%04x\n", + chip->vendor_id, chip->product_id); + + chip->ic_version = 0; + +#ifdef _MSG_TRACE + chip->msg_idx = 0; +#endif + + memset(xd_card, 0, sizeof(struct xd_info)); + memset(sd_card, 0, sizeof(struct sd_info)); + memset(ms_card, 0, sizeof(struct ms_info)); + + chip->xd_reset_counter = 0; + chip->sd_reset_counter = 0; + chip->ms_reset_counter = 0; + + chip->xd_show_cnt = MAX_SHOW_CNT; + chip->sd_show_cnt = MAX_SHOW_CNT; + chip->ms_show_cnt = MAX_SHOW_CNT; + + chip->sd_io = 0; + chip->auto_delink_cnt = 0; + chip->auto_delink_allowed = 1; + rtsx_set_stat(chip, RTSX_STAT_INIT); + + chip->aspm_enabled = 0; + chip->chip_insert_with_sdio = 0; + chip->sdio_aspm = 0; + chip->sdio_idle = 0; + chip->sdio_counter = 0; + chip->cur_card = 0; + chip->phy_debug_mode = 0; + chip->sdio_func_exist = 0; + memset(chip->sdio_raw_data, 0, 12); + + for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) { + set_sense_type(chip, i, SENSE_TYPE_NO_SENSE); + chip->rw_fail_cnt[i] = 0; + } + + if (!check_sd_speed_prior(chip->sd_speed_prior)) + chip->sd_speed_prior = 0x01040203; + + RTSX_DEBUGP("sd_speed_prior = 0x%08x\n", chip->sd_speed_prior); + + if (!check_sd_current_prior(chip->sd_current_prior)) + chip->sd_current_prior = 0x00010203; + + RTSX_DEBUGP("sd_current_prior = 0x%08x\n", chip->sd_current_prior); + + if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0)) + chip->sd_ddr_tx_phase = 0; + + if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0)) + chip->mmc_ddr_tx_phase = 0; + + RTSX_WRITE_REG(chip, FPDCTL, SSC_POWER_DOWN, 0); + wait_timeout(200); + RTSX_WRITE_REG(chip, CLK_DIV, 0x07, 0x07); + RTSX_DEBUGP("chip->use_hw_setting = %d\n", chip->use_hw_setting); + + if (CHECK_PID(chip, 0x5208)) { + retval = rts5208_init(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } else if (CHECK_PID(chip, 0x5288)) { + retval = rts5288_init(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + } + + if (chip->ss_en == 2) + chip->ss_en = 0; + + RTSX_DEBUGP("chip->asic_code = %d\n", chip->asic_code); + RTSX_DEBUGP("chip->ic_version = 0x%x\n", chip->ic_version); + RTSX_DEBUGP("chip->phy_debug_mode = %d\n", chip->phy_debug_mode); + RTSX_DEBUGP("chip->aux_pwr_exist = %d\n", chip->aux_pwr_exist); + RTSX_DEBUGP("chip->sdio_func_exist = %d\n", chip->sdio_func_exist); + RTSX_DEBUGP("chip->hw_bypass_sd = %d\n", chip->hw_bypass_sd); + RTSX_DEBUGP("chip->aspm_l0s_l1_en = %d\n", chip->aspm_l0s_l1_en); + RTSX_DEBUGP("chip->lun_mode = %d\n", chip->lun_mode); + RTSX_DEBUGP("chip->auto_delink_en = %d\n", chip->auto_delink_en); + RTSX_DEBUGP("chip->ss_en = %d\n", chip->ss_en); + RTSX_DEBUGP("chip->baro_pkg = %d\n", chip->baro_pkg); + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { + chip->card2lun[SD_CARD] = 0; + chip->card2lun[MS_CARD] = 1; + chip->card2lun[XD_CARD] = 0xFF; + chip->lun2card[0] = SD_CARD; + chip->lun2card[1] = MS_CARD; + chip->max_lun = 1; + SET_SDIO_IGNORED(chip); + } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) { + chip->card2lun[SD_CARD] = 0; + chip->card2lun[MS_CARD] = 0; + chip->card2lun[XD_CARD] = 0xFF; + chip->lun2card[0] = SD_CARD | MS_CARD; + chip->max_lun = 0; + } else { + chip->card2lun[XD_CARD] = 0; + chip->card2lun[SD_CARD] = 0; + chip->card2lun[MS_CARD] = 0; + chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD; + chip->max_lun = 0; + } + + retval = rtsx_reset_chip(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +void rtsx_release_chip(struct rtsx_chip *chip) +{ + xd_free_l2p_tbl(chip); + ms_free_l2p_tbl(chip); + chip->card_exist = 0; + chip->card_ready = 0; +} + +#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK) +static inline void rtsx_blink_led(struct rtsx_chip *chip) +{ + if (chip->card_exist && chip->blink_led) { + if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) { + chip->led_toggle_counter++; + } else { + chip->led_toggle_counter = 0; + toggle_gpio(chip, LED_GPIO); + } + } +} +#endif + +static void rtsx_monitor_aspm_config(struct rtsx_chip *chip) +{ + int maybe_support_aspm, reg_changed; + u32 tmp = 0; + u8 reg0 = 0, reg1 = 0; + + maybe_support_aspm = 0; + reg_changed = 0; + rtsx_read_config_byte(chip, LCTLR, ®0); + if (chip->aspm_level[0] != reg0) { + reg_changed = 1; + chip->aspm_level[0] = reg0; + } + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { + rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp); + reg1 = (u8)tmp; + if (chip->aspm_level[1] != reg1) { + reg_changed = 1; + chip->aspm_level[1] = reg1; + } + + if ((reg0 & 0x03) && (reg1 & 0x03)) + maybe_support_aspm = 1; + + } else { + if (reg0 & 0x03) + maybe_support_aspm = 1; + + } + + if (reg_changed) { + if (maybe_support_aspm) + chip->aspm_l0s_l1_en = 0x03; + + RTSX_DEBUGP("aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n", + chip->aspm_level[0], chip->aspm_level[1]); + + if (chip->aspm_l0s_l1_en) { + chip->aspm_enabled = 1; + } else { + chip->aspm_enabled = 0; + chip->sdio_aspm = 0; + } + rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, + 0x30 | chip->aspm_level[0] | + (chip->aspm_level[1] << 2)); + } +} + +void rtsx_polling_func(struct rtsx_chip *chip) +{ +#ifdef SUPPORT_SD_LOCK + struct sd_info *sd_card = &(chip->sd_card); +#endif + int ss_allowed; + + if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND)) + return; + + if (rtsx_chk_stat(chip, RTSX_STAT_DELINK)) + goto Delink_Stage; + + if (chip->polling_config) { + u8 val; + rtsx_read_config_byte(chip, 0, &val); + } + + if (rtsx_chk_stat(chip, RTSX_STAT_SS)) + return; + +#ifdef SUPPORT_OCP + if (chip->ocp_int) { + rtsx_read_register(chip, OCPSTAT, &(chip->ocp_stat)); + + if (chip->card_exist & SD_CARD) + sd_power_off_card3v3(chip); + else if (chip->card_exist & MS_CARD) + ms_power_off_card3v3(chip); + else if (chip->card_exist & XD_CARD) + xd_power_off_card3v3(chip); + + chip->ocp_int = 0; + } +#endif + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_erase_status) { + if (chip->card_exist & SD_CARD) { + u8 val; + rtsx_read_register(chip, 0xFD30, &val); + if (val & 0x02) { + sd_card->sd_erase_status = SD_NOT_ERASE; + sd_card->sd_lock_notify = 1; + chip->need_reinit |= SD_CARD; + } + } else { + sd_card->sd_erase_status = SD_NOT_ERASE; + } + } +#endif + + rtsx_init_cards(chip); + + if (chip->ss_en) { + ss_allowed = 1; + + if (CHECK_PID(chip, 0x5288)) { + ss_allowed = 0; + } else { + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { + u32 val; + rtsx_read_cfg_dw(chip, 1, 0x04, &val); + if (val & 0x07) + ss_allowed = 0; + + } + } + } else { + ss_allowed = 0; + } + + if (ss_allowed && !chip->sd_io) { + if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) { + chip->ss_counter = 0; + } else { + if (chip->ss_counter < + (chip->ss_idle_period / POLLING_INTERVAL)) { + chip->ss_counter++; + } else { + rtsx_exclusive_enter_ss(chip); + return; + } + } + } + + if (CHECK_PID(chip, 0x5208)) { + rtsx_monitor_aspm_config(chip); + +#ifdef SUPPORT_SDIO_ASPM + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && + chip->aspm_l0s_l1_en && chip->dynamic_aspm) { + if (chip->sd_io) { + dynamic_configure_sdio_aspm(chip); + } else { + if (!chip->sdio_aspm) { + RTSX_DEBUGP("SDIO enter ASPM!\n"); + rtsx_write_register(chip, + ASPM_FORCE_CTL, 0xFC, + 0x30 | (chip->aspm_level[1] << 2)); + chip->sdio_aspm = 1; + } + } + } +#endif + } + + if (chip->idle_counter < IDLE_MAX_COUNT) { + chip->idle_counter++; + } else { + if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) { + RTSX_DEBUGP("Idle state!\n"); + rtsx_set_stat(chip, RTSX_STAT_IDLE); + +#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK) + chip->led_toggle_counter = 0; +#endif + rtsx_force_power_on(chip, SSC_PDCTL); + + turn_off_led(chip, LED_GPIO); + + if (chip->auto_power_down && !chip->card_ready && !chip->sd_io) + rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); + + } + } + + switch (rtsx_get_stat(chip)) { + case RTSX_STAT_RUN: +#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK) + rtsx_blink_led(chip); +#endif + do_remaining_work(chip); + break; + + case RTSX_STAT_IDLE: + if (chip->sd_io && !chip->sd_int) + try_to_switch_sdio_ctrl(chip); + + rtsx_enable_aspm(chip); + break; + + default: + break; + } + + +#ifdef SUPPORT_OCP + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { +#ifdef CONFIG_RTS5208_DEBUG + if (chip->ocp_stat & + (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER)) + RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", + chip->ocp_stat); +#endif + + if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { + if (chip->card_exist & SD_CARD) { + rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, + 0); + card_power_off(chip, SD_CARD); + chip->card_fail |= SD_CARD; + } + } + if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) { + if (chip->card_exist & MS_CARD) { + rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, + 0); + card_power_off(chip, MS_CARD); + chip->card_fail |= MS_CARD; + } + } + } else { + if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { + RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", + chip->ocp_stat); + if (chip->card_exist & SD_CARD) { + rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, + 0); + chip->card_fail |= SD_CARD; + } else if (chip->card_exist & MS_CARD) { + rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, + 0); + chip->card_fail |= MS_CARD; + } else if (chip->card_exist & XD_CARD) { + rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, + 0); + chip->card_fail |= XD_CARD; + } + card_power_off(chip, SD_CARD); + } + } +#endif + +Delink_Stage: + if (chip->auto_delink_en && chip->auto_delink_allowed && + !chip->card_ready && !chip->card_ejected && !chip->sd_io) { + int enter_L1 = chip->auto_delink_in_L1 && ( + chip->aspm_l0s_l1_en || chip->ss_en); + int delink_stage1_cnt = chip->delink_stage1_step; + int delink_stage2_cnt = delink_stage1_cnt + + chip->delink_stage2_step; + int delink_stage3_cnt = delink_stage2_cnt + + chip->delink_stage3_step; + + if (chip->auto_delink_cnt <= delink_stage3_cnt) { + if (chip->auto_delink_cnt == delink_stage1_cnt) { + rtsx_set_stat(chip, RTSX_STAT_DELINK); + + if (chip->asic_code && CHECK_PID(chip, 0x5208)) + rtsx_set_phy_reg_bit(chip, 0x1C, 2); + + if (chip->card_exist) { + RTSX_DEBUGP("False card inserted, do force delink\n"); + + if (enter_L1) + rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1); + + rtsx_write_register(chip, + CHANGE_LINK_STATE, 0x0A, + 0x0A); + + if (enter_L1) + rtsx_enter_L1(chip); + + chip->auto_delink_cnt = delink_stage3_cnt + 1; + } else { + RTSX_DEBUGP("No card inserted, do delink\n"); + + if (enter_L1) + rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1); + + rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0x02); + + if (enter_L1) + rtsx_enter_L1(chip); + + } + } + + if (chip->auto_delink_cnt == delink_stage2_cnt) { + RTSX_DEBUGP("Try to do force delink\n"); + + if (enter_L1) + rtsx_exit_L1(chip); + + if (chip->asic_code && CHECK_PID(chip, 0x5208)) + rtsx_set_phy_reg_bit(chip, 0x1C, 2); + + rtsx_write_register(chip, CHANGE_LINK_STATE, + 0x0A, 0x0A); + } + + chip->auto_delink_cnt++; + } + } else { + chip->auto_delink_cnt = 0; + } +} + +void rtsx_undo_delink(struct rtsx_chip *chip) +{ + chip->auto_delink_allowed = 0; + rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x00); +} + +/** + * rtsx_stop_cmd - stop command transfer and DMA transfer + * @chip: Realtek's card reader chip + * @card: flash card type + * + * Stop command transfer and DMA transfer. + * This function is called in error handler. + */ +void rtsx_stop_cmd(struct rtsx_chip *chip, int card) +{ + int i; + + for (i = 0; i <= 8; i++) { + int addr = RTSX_HCBAR + i * 4; + u32 reg; + reg = rtsx_readl(chip, addr); + RTSX_DEBUGP("BAR (0x%02x): 0x%08x\n", addr, reg); + } + rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD); + rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA); + + for (i = 0; i < 16; i++) { + u16 addr = 0xFE20 + (u16)i; + u8 val; + rtsx_read_register(chip, addr, &val); + RTSX_DEBUGP("0x%04X: 0x%02x\n", addr, val); + } + + rtsx_write_register(chip, DMACTL, 0x80, 0x80); + rtsx_write_register(chip, RBCTL, 0x80, 0x80); +} + +#define MAX_RW_REG_CNT 1024 + +int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data) +{ + int i; + u32 val = 3 << 30; + + val |= (u32)(addr & 0x3FFF) << 16; + val |= (u32)mask << 8; + val |= (u32)data; + + rtsx_writel(chip, RTSX_HAIMR, val); + + for (i = 0; i < MAX_RW_REG_CNT; i++) { + val = rtsx_readl(chip, RTSX_HAIMR); + if ((val & (1 << 31)) == 0) { + if (data != (u8)val) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; + } + } + + TRACE_RET(chip, STATUS_TIMEDOUT); +} + +int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data) +{ + u32 val = 2 << 30; + int i; + + if (data) + *data = 0; + + val |= (u32)(addr & 0x3FFF) << 16; + + rtsx_writel(chip, RTSX_HAIMR, val); + + for (i = 0; i < MAX_RW_REG_CNT; i++) { + val = rtsx_readl(chip, RTSX_HAIMR); + if ((val & (1 << 31)) == 0) + break; + } + + if (i >= MAX_RW_REG_CNT) + TRACE_RET(chip, STATUS_TIMEDOUT); + + if (data) + *data = (u8)(val & 0xFF); + + return STATUS_SUCCESS; +} + +int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, + u32 val) +{ + u8 mode = 0, tmp; + int i; + + for (i = 0; i < 4; i++) { + if (mask & 0xFF) { + RTSX_WRITE_REG(chip, CFGDATA0 + i, + 0xFF, (u8)(val & mask & 0xFF)); + mode |= (1 << i); + } + mask >>= 8; + val >>= 8; + } + + if (mode) { + RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr); + RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8)); + + RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF, + 0x80 | mode | ((func_no & 0x03) << 4)); + + for (i = 0; i < MAX_RW_REG_CNT; i++) { + RTSX_READ_REG(chip, CFGRWCTL, &tmp); + if ((tmp & 0x80) == 0) + break; + } + } + + return STATUS_SUCCESS; +} + +int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val) +{ + int i; + u8 tmp; + u32 data = 0; + + RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr); + RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8)); + RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF, 0x80 | ((func_no & 0x03) << 4)); + + for (i = 0; i < MAX_RW_REG_CNT; i++) { + RTSX_READ_REG(chip, CFGRWCTL, &tmp); + if ((tmp & 0x80) == 0) + break; + } + + for (i = 0; i < 4; i++) { + RTSX_READ_REG(chip, CFGDATA0 + i, &tmp); + data |= (u32)tmp << (i * 8); + } + + if (val) + *val = data; + + return STATUS_SUCCESS; +} + +int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, + int len) +{ + u32 *data, *mask; + u16 offset = addr % 4; + u16 aligned_addr = addr - offset; + int dw_len, i, j; + int retval; + + RTSX_DEBUGP("%s\n", __func__); + + if (!buf) + TRACE_RET(chip, STATUS_NOMEM); + + if ((len + offset) % 4) + dw_len = (len + offset) / 4 + 1; + else + dw_len = (len + offset) / 4; + + RTSX_DEBUGP("dw_len = %d\n", dw_len); + + data = vzalloc(dw_len * 4); + if (!data) + TRACE_RET(chip, STATUS_NOMEM); + + mask = vzalloc(dw_len * 4); + if (!mask) { + vfree(data); + TRACE_RET(chip, STATUS_NOMEM); + } + + j = 0; + for (i = 0; i < len; i++) { + mask[j] |= 0xFF << (offset * 8); + data[j] |= buf[i] << (offset * 8); + if (++offset == 4) { + j++; + offset = 0; + } + } + + RTSX_DUMP(mask, dw_len * 4); + RTSX_DUMP(data, dw_len * 4); + + for (i = 0; i < dw_len; i++) { + retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4, + mask[i], data[i]); + if (retval != STATUS_SUCCESS) { + vfree(data); + vfree(mask); + TRACE_RET(chip, STATUS_FAIL); + } + } + + vfree(data); + vfree(mask); + + return STATUS_SUCCESS; +} + +int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, + int len) +{ + u32 *data; + u16 offset = addr % 4; + u16 aligned_addr = addr - offset; + int dw_len, i, j; + int retval; + + RTSX_DEBUGP("%s\n", __func__); + + if ((len + offset) % 4) + dw_len = (len + offset) / 4 + 1; + else + dw_len = (len + offset) / 4; + + RTSX_DEBUGP("dw_len = %d\n", dw_len); + + data = vmalloc(dw_len * 4); + if (!data) + TRACE_RET(chip, STATUS_NOMEM); + + for (i = 0; i < dw_len; i++) { + retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4, + data + i); + if (retval != STATUS_SUCCESS) { + vfree(data); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (buf) { + j = 0; + + for (i = 0; i < len; i++) { + buf[i] = (u8)(data[j] >> (offset * 8)); + if (++offset == 4) { + j++; + offset = 0; + } + } + } + + vfree(data); + + return STATUS_SUCCESS; +} + +int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val) +{ + int i, finished = 0; + u8 tmp; + + RTSX_WRITE_REG(chip, PHYDATA0, 0xFF, (u8)val); + RTSX_WRITE_REG(chip, PHYDATA1, 0xFF, (u8)(val >> 8)); + RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr); + RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x81); + + for (i = 0; i < 100000; i++) { + RTSX_READ_REG(chip, PHYRWCTL, &tmp); + if (!(tmp & 0x80)) { + finished = 1; + break; + } + } + + if (!finished) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val) +{ + int i, finished = 0; + u16 data = 0; + u8 tmp; + + RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr); + RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x80); + + for (i = 0; i < 100000; i++) { + RTSX_READ_REG(chip, PHYRWCTL, &tmp); + if (!(tmp & 0x80)) { + finished = 1; + break; + } + } + + if (!finished) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_READ_REG(chip, PHYDATA0, &tmp); + data = tmp; + RTSX_READ_REG(chip, PHYDATA1, &tmp); + data |= (u16)tmp << 8; + + if (val) + *val = data; + + return STATUS_SUCCESS; +} + +int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val) +{ + int i; + u8 data = 0; + + RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0x80|addr); + + for (i = 0; i < 100; i++) { + RTSX_READ_REG(chip, EFUSE_CTRL, &data); + if (!(data & 0x80)) + break; + udelay(1); + } + + if (data & 0x80) + TRACE_RET(chip, STATUS_TIMEDOUT); + + RTSX_READ_REG(chip, EFUSE_DATA, &data); + if (val) + *val = data; + + return STATUS_SUCCESS; +} + +int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val) +{ + int i, j; + u8 data = 0, tmp = 0xFF; + + for (i = 0; i < 8; i++) { + if (val & (u8)(1 << i)) + continue; + + tmp &= (~(u8)(1 << i)); + RTSX_DEBUGP("Write 0x%x to 0x%x\n", tmp, addr); + + RTSX_WRITE_REG(chip, EFUSE_DATA, 0xFF, tmp); + RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0xA0|addr); + + for (j = 0; j < 100; j++) { + RTSX_READ_REG(chip, EFUSE_CTRL, &data); + if (!(data & 0x80)) + break; + wait_timeout(3); + } + + if (data & 0x80) + TRACE_RET(chip, STATUS_TIMEDOUT); + + wait_timeout(5); + } + + return STATUS_SUCCESS; +} + +int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) +{ + int retval; + u16 value; + + retval = rtsx_read_phy_register(chip, reg, &value); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (value & (1 << bit)) { + value &= ~(1 << bit); + retval = rtsx_write_phy_register(chip, reg, value); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) +{ + int retval; + u16 value; + + retval = rtsx_read_phy_register(chip, reg, &value); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (0 == (value & (1 << bit))) { + value |= (1 << bit); + retval = rtsx_write_phy_register(chip, reg, value); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int rtsx_check_link_ready(struct rtsx_chip *chip) +{ + u8 val; + + RTSX_READ_REG(chip, IRQSTAT0, &val); + + RTSX_DEBUGP("IRQSTAT0: 0x%x\n", val); + if (val & LINK_RDY_INT) { + RTSX_DEBUGP("Delinked!\n"); + rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT); + return STATUS_FAIL; + } + + return STATUS_SUCCESS; +} + +static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate) +{ + u32 ultmp; + + RTSX_DEBUGP("%04x set pm_dstate to %d\n", chip->product_id, dstate); + + if (CHK_SDIO_EXIST(chip)) { + u8 func_no; + + if (CHECK_PID(chip, 0x5288)) + func_no = 2; + else + func_no = 1; + + rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp); + RTSX_DEBUGP("pm_dstate of function %d: 0x%x\n", (int)func_no, + ultmp); + rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate); + } + + rtsx_write_config_byte(chip, 0x44, dstate); + rtsx_write_config_byte(chip, 0x45, 0); +} + +void rtsx_enter_L1(struct rtsx_chip *chip) +{ + rtsx_handle_pm_dstate(chip, 2); +} + +void rtsx_exit_L1(struct rtsx_chip *chip) +{ + rtsx_write_config_byte(chip, 0x44, 0); + rtsx_write_config_byte(chip, 0x45, 0); +} + +void rtsx_enter_ss(struct rtsx_chip *chip) +{ + RTSX_DEBUGP("Enter Selective Suspend State!\n"); + + rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT); + + if (chip->power_down_in_ss) { + rtsx_power_off_card(chip); + rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); + } + + if (CHK_SDIO_EXIST(chip)) { + if (CHECK_PID(chip, 0x5288)) + rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100); + else + rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100); + } + + if (chip->auto_delink_en) { + rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01); + } else { + if (!chip->phy_debug_mode) { + u32 tmp; + tmp = rtsx_readl(chip, RTSX_BIER); + tmp |= CARD_INT; + rtsx_writel(chip, RTSX_BIER, tmp); + } + + rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0); + } + + rtsx_enter_L1(chip); + + RTSX_CLR_DELINK(chip); + rtsx_set_stat(chip, RTSX_STAT_SS); +} + +void rtsx_exit_ss(struct rtsx_chip *chip) +{ + RTSX_DEBUGP("Exit Selective Suspend State!\n"); + + rtsx_exit_L1(chip); + + if (chip->power_down_in_ss) { + rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); + udelay(1000); + } + + if (RTSX_TST_DELINK(chip)) { + chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; + rtsx_reinit_cards(chip, 1); + RTSX_CLR_DELINK(chip); + } else if (chip->power_down_in_ss) { + chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; + rtsx_reinit_cards(chip, 0); + } +} + +int rtsx_pre_handle_interrupt(struct rtsx_chip *chip) +{ + u32 status, int_enable; + int exit_ss = 0; +#ifdef SUPPORT_OCP + u32 ocp_int = 0; + + ocp_int = OC_INT; +#endif + + if (chip->ss_en) { + chip->ss_counter = 0; + if (rtsx_get_stat(chip) == RTSX_STAT_SS) { + exit_ss = 1; + rtsx_exit_L1(chip); + rtsx_set_stat(chip, RTSX_STAT_RUN); + } + } + + int_enable = rtsx_readl(chip, RTSX_BIER); + chip->int_reg = rtsx_readl(chip, RTSX_BIPR); + + if (((chip->int_reg & int_enable) == 0) || + (chip->int_reg == 0xFFFFFFFF)) + return STATUS_FAIL; + + status = chip->int_reg &= (int_enable | 0x7FFFFF); + + if (status & CARD_INT) { + chip->auto_delink_cnt = 0; + + if (status & SD_INT) { + if (status & SD_EXIST) { + set_bit(SD_NR, &(chip->need_reset)); + } else { + set_bit(SD_NR, &(chip->need_release)); + chip->sd_reset_counter = 0; + chip->sd_show_cnt = 0; + clear_bit(SD_NR, &(chip->need_reset)); + } + } else { + /* If multi-luns, it's possible that + when plugging/unplugging one card + there is another card which still + exists in the slot. In this case, + all existed cards should be reset. + */ + if (exit_ss && (status & SD_EXIST)) + set_bit(SD_NR, &(chip->need_reinit)); + } + if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) { + if (status & XD_INT) { + if (status & XD_EXIST) { + set_bit(XD_NR, &(chip->need_reset)); + } else { + set_bit(XD_NR, &(chip->need_release)); + chip->xd_reset_counter = 0; + chip->xd_show_cnt = 0; + clear_bit(XD_NR, &(chip->need_reset)); + } + } else { + if (exit_ss && (status & XD_EXIST)) + set_bit(XD_NR, &(chip->need_reinit)); + } + } + if (status & MS_INT) { + if (status & MS_EXIST) { + set_bit(MS_NR, &(chip->need_reset)); + } else { + set_bit(MS_NR, &(chip->need_release)); + chip->ms_reset_counter = 0; + chip->ms_show_cnt = 0; + clear_bit(MS_NR, &(chip->need_reset)); + } + } else { + if (exit_ss && (status & MS_EXIST)) + set_bit(MS_NR, &(chip->need_reinit)); + } + } + +#ifdef SUPPORT_OCP + chip->ocp_int = ocp_int & status; +#endif + + if (chip->sd_io) { + if (chip->int_reg & DATA_DONE_INT) + chip->int_reg &= ~(u32)DATA_DONE_INT; + } + + return STATUS_SUCCESS; +} + +void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat) +{ + int retval; + + RTSX_DEBUGP("rtsx_do_before_power_down, pm_stat = %d\n", pm_stat); + + rtsx_set_stat(chip, RTSX_STAT_SUSPEND); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) + return; + + rtsx_release_cards(chip); + rtsx_disable_bus_int(chip); + turn_off_led(chip, LED_GPIO); + +#ifdef HW_AUTO_SWITCH_SD_BUS + if (chip->sd_io) { + chip->sdio_in_charge = 1; + if (CHECK_PID(chip, 0x5208)) { + rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08); + /* Enable sdio_bus_auto_switch */ + rtsx_write_register(chip, 0xFE70, 0x80, 0x80); + } else if (CHECK_PID(chip, 0x5288)) { + rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08); + /* Enable sdio_bus_auto_switch */ + rtsx_write_register(chip, 0xFE5A, 0x08, 0x08); + } + } +#endif + + if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) { + /* u_force_clkreq_0 */ + rtsx_write_register(chip, PETXCFG, 0x08, 0x08); + } + + if (pm_stat == PM_S1) { + RTSX_DEBUGP("Host enter S1\n"); + rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, + HOST_ENTER_S1); + } else if (pm_stat == PM_S3) { + if (chip->s3_pwr_off_delay > 0) + wait_timeout(chip->s3_pwr_off_delay); + + RTSX_DEBUGP("Host enter S3\n"); + rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, + HOST_ENTER_S3); + } + + if (chip->do_delink_before_power_down && chip->auto_delink_en) + rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2); + + rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); + + chip->cur_clk = 0; + chip->cur_card = 0; + chip->card_exist = 0; +} + +void rtsx_enable_aspm(struct rtsx_chip *chip) +{ + if (chip->aspm_l0s_l1_en && chip->dynamic_aspm) { + if (!chip->aspm_enabled) { + RTSX_DEBUGP("Try to enable ASPM\n"); + chip->aspm_enabled = 1; + + if (chip->asic_code && CHECK_PID(chip, 0x5208)) + rtsx_write_phy_register(chip, 0x07, 0); + if (CHECK_PID(chip, 0x5208)) { + rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3, + 0x30 | chip->aspm_level[0]); + } else { + rtsx_write_config_byte(chip, LCTLR, + chip->aspm_l0s_l1_en); + } + + if (CHK_SDIO_EXIST(chip)) { + u16 val = chip->aspm_l0s_l1_en | 0x0100; + if (CHECK_PID(chip, 0x5288)) + rtsx_write_cfg_dw(chip, 2, 0xC0, + 0xFFFF, val); + else + rtsx_write_cfg_dw(chip, 1, 0xC0, + 0xFFFF, val); + } + } + } + + return; +} + +void rtsx_disable_aspm(struct rtsx_chip *chip) +{ + if (CHECK_PID(chip, 0x5208)) + rtsx_monitor_aspm_config(chip); + + if (chip->aspm_l0s_l1_en && chip->dynamic_aspm) { + if (chip->aspm_enabled) { + RTSX_DEBUGP("Try to disable ASPM\n"); + chip->aspm_enabled = 0; + + if (chip->asic_code && CHECK_PID(chip, 0x5208)) + rtsx_write_phy_register(chip, 0x07, 0x0129); + if (CHECK_PID(chip, 0x5208)) + rtsx_write_register(chip, ASPM_FORCE_CTL, + 0xF3, 0x30); + else + rtsx_write_config_byte(chip, LCTLR, 0x00); + + wait_timeout(1); + } + } + + return; +} + +int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) +{ + int retval; + int i, j; + u16 reg_addr; + u8 *ptr; + + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + ptr = buf; + reg_addr = PPBUF_BASE2; + for (i = 0; i < buf_len/256; i++) { + rtsx_init_cmd(chip); + + for (j = 0; j < 256; j++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); + + retval = rtsx_send_cmd(chip, 0, 250); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + memcpy(ptr, rtsx_get_cmd_data(chip), 256); + ptr += 256; + } + + if (buf_len%256) { + rtsx_init_cmd(chip); + + for (j = 0; j < buf_len%256; j++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); + + retval = rtsx_send_cmd(chip, 0, 250); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + } + + memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256); + + return STATUS_SUCCESS; +} + +int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) +{ + int retval; + int i, j; + u16 reg_addr; + u8 *ptr; + + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + ptr = buf; + reg_addr = PPBUF_BASE2; + for (i = 0; i < buf_len/256; i++) { + rtsx_init_cmd(chip); + + for (j = 0; j < 256; j++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, + *ptr); + ptr++; + } + + retval = rtsx_send_cmd(chip, 0, 250); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + } + + if (buf_len%256) { + rtsx_init_cmd(chip); + + for (j = 0; j < buf_len%256; j++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, + *ptr); + ptr++; + } + + retval = rtsx_send_cmd(chip, 0, 250); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int rtsx_check_chip_exist(struct rtsx_chip *chip) +{ + if (rtsx_readl(chip, 0) == 0xFFFFFFFF) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl) +{ + int retval; + u8 mask = 0; + + if (ctl & SSC_PDCTL) + mask |= SSC_POWER_DOWN; + +#ifdef SUPPORT_OCP + if (ctl & OC_PDCTL) { + mask |= SD_OC_POWER_DOWN; + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + mask |= MS_OC_POWER_DOWN; + } +#endif + + if (mask) { + retval = rtsx_write_register(chip, FPDCTL, mask, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHECK_PID(chip, 0x5288)) + wait_timeout(200); + } + + return STATUS_SUCCESS; +} + +int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl) +{ + int retval; + u8 mask = 0, val = 0; + + if (ctl & SSC_PDCTL) + mask |= SSC_POWER_DOWN; + +#ifdef SUPPORT_OCP + if (ctl & OC_PDCTL) { + mask |= SD_OC_POWER_DOWN; + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + mask |= MS_OC_POWER_DOWN; + } +#endif + + if (mask) { + val = mask; + retval = rtsx_write_register(chip, FPDCTL, mask, val); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h new file mode 100644 index 000000000000..c25efcc3f3aa --- /dev/null +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -0,0 +1,1002 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_CHIP_H +#define __REALTEK_RTSX_CHIP_H + +#include "rtsx.h" + +#define SUPPORT_CPRM +#define SUPPORT_OCP +#define SUPPORT_SDIO_ASPM +#define SUPPORT_MAGIC_GATE +#define SUPPORT_MSXC +#define SUPPORT_SD_LOCK +/* Hardware switch bus_ctl and cd_ctl automatically */ +#define HW_AUTO_SWITCH_SD_BUS +/* Enable hardware interrupt write clear */ +#define HW_INT_WRITE_CLR +/* #define LED_AUTO_BLINK */ +/* #define DISABLE_CARD_INT */ + +#ifdef SUPPORT_MAGIC_GATE + /* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */ + #define MG_SET_ICV_SLOW + /* HW may miss ERR/CMDNK signal when sampling INT status. */ + #define MS_SAMPLE_INT_ERR + /* HW DO NOT support Wait_INT function during READ_BYTES + * transfer mode */ + #define READ_BYTES_WAIT_INT +#endif + +#ifdef SUPPORT_MSXC +#define XC_POWERCLASS +#define SUPPORT_PCGL_1P18 +#endif + +#ifndef LED_AUTO_BLINK +#define REGULAR_BLINK +#endif + +#define LED_BLINK_SPEED 5 +#define LED_TOGGLE_INTERVAL 6 +#define GPIO_TOGGLE_THRESHOLD 1024 +#define LED_GPIO 0 + +#define POLLING_INTERVAL 30 + +#define TRACE_ITEM_CNT 64 + +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS 0 +#endif +#ifndef STATUS_FAIL +#define STATUS_FAIL 1 +#endif +#ifndef STATUS_TIMEDOUT +#define STATUS_TIMEDOUT 2 +#endif +#ifndef STATUS_NOMEM +#define STATUS_NOMEM 3 +#endif +#ifndef STATUS_READ_FAIL +#define STATUS_READ_FAIL 4 +#endif +#ifndef STATUS_WRITE_FAIL +#define STATUS_WRITE_FAIL 5 +#endif +#ifndef STATUS_ERROR +#define STATUS_ERROR 10 +#endif + +#define PM_S1 1 +#define PM_S3 3 + +/* + * Transport return codes + */ + +#define TRANSPORT_GOOD 0 /* Transport good, command good */ +#define TRANSPORT_FAILED 1 /* Transport good, command failed */ +#define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */ +#define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */ + + +/*----------------------------------- + Start-Stop-Unit +-----------------------------------*/ +#define STOP_MEDIUM 0x00 /* access disable */ +#define MAKE_MEDIUM_READY 0x01 /* access enable */ +#define UNLOAD_MEDIUM 0x02 /* unload */ +#define LOAD_MEDIUM 0x03 /* load */ + +/*----------------------------------- + STANDARD_INQUIRY +-----------------------------------*/ +#define QULIFIRE 0x00 +#define AENC_FNC 0x00 +#define TRML_IOP 0x00 +#define REL_ADR 0x00 +#define WBUS_32 0x00 +#define WBUS_16 0x00 +#define SYNC 0x00 +#define LINKED 0x00 +#define CMD_QUE 0x00 +#define SFT_RE 0x00 + +#define VEN_ID_LEN 8 /* Vendor ID Length */ +#define PRDCT_ID_LEN 16 /* Product ID Length */ +#define PRDCT_REV_LEN 4 /* Product LOT Length */ + +/* Dynamic flag definitions: used in set_bit() etc. */ +#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */ +#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in + * progress */ +#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect + * in progress */ +#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ + (1UL << US_FLIDX_DISCONNECTING)) +#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset + * in progress */ +#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI + * midlayer timed out */ + +#define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */ +#define RMB_DISC 0x80 /* The Device is Removable */ +#define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */ + +#define SCSI 0x00 /* Interface ID */ + +#define WRITE_PROTECTED_MEDIA 0x07 + +/*---- sense key ----*/ +#define ILI 0x20 /* ILI bit is on */ + +#define NO_SENSE 0x00 /* not exist sense key */ +#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */ +#define NOT_READY 0x02 /* Logical unit is not ready */ +#define MEDIA_ERR 0x03 /* medium/data error */ +#define HARDWARE_ERR 0x04 /* hardware error */ +#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */ +#define UNIT_ATTENTION 0x06 /* unit attention condition occur */ +#define DAT_PRTCT 0x07 /* read/write is desable */ +#define BLNC_CHK 0x08 /* find blank/DOF in read */ + /* write to unblank area */ +#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illgal */ +#define ABRT_CMD 0x0b /* Target make the command in error */ +#define EQUAL 0x0c /* Search Data end with Equal */ +#define VLM_OVRFLW 0x0d /* Some data are left in buffer */ +#define MISCMP 0x0e /* find inequality */ + +#define READ_ERR -1 +#define WRITE_ERR -2 + +#define FIRST_RESET 0x01 +#define USED_EXIST 0x02 + +/*----------------------------------- + SENSE_DATA +-----------------------------------*/ +/*---- valid ----*/ +#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */ +#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */ + +/*---- error code ----*/ +#define CUR_ERR 0x70 /* current error */ +#define DEF_ERR 0x71 /* specific command error */ + +/*---- sense key Information ----*/ +#define SNSKEYINFO_LEN 3 /* length of sense key information */ + +#define SKSV 0x80 +#define CDB_ILLEGAL 0x40 +#define DAT_ILLEGAL 0x00 +#define BPV 0x08 +#define BIT_ILLEGAL0 0 /* bit0 is illegal */ +#define BIT_ILLEGAL1 1 /* bit1 is illegal */ +#define BIT_ILLEGAL2 2 /* bit2 is illegal */ +#define BIT_ILLEGAL3 3 /* bit3 is illegal */ +#define BIT_ILLEGAL4 4 /* bit4 is illegal */ +#define BIT_ILLEGAL5 5 /* bit5 is illegal */ +#define BIT_ILLEGAL6 6 /* bit6 is illegal */ +#define BIT_ILLEGAL7 7 /* bit7 is illegal */ + +/*---- ASC ----*/ +#define ASC_NO_INFO 0x00 +#define ASC_MISCMP 0x1d +#define ASC_INVLD_CDB 0x24 +#define ASC_INVLD_PARA 0x26 +#define ASC_LU_NOT_READY 0x04 +#define ASC_WRITE_ERR 0x0c +#define ASC_READ_ERR 0x11 +#define ASC_LOAD_EJCT_ERR 0x53 +#define ASC_MEDIA_NOT_PRESENT 0x3A +#define ASC_MEDIA_CHANGED 0x28 +#define ASC_MEDIA_IN_PROCESS 0x04 +#define ASC_WRITE_PROTECT 0x27 +#define ASC_LUN_NOT_SUPPORTED 0x25 + +/*---- ASQC ----*/ +#define ASCQ_NO_INFO 0x00 +#define ASCQ_MEDIA_IN_PROCESS 0x01 +#define ASCQ_MISCMP 0x00 +#define ASCQ_INVLD_CDB 0x00 +#define ASCQ_INVLD_PARA 0x02 +#define ASCQ_LU_NOT_READY 0x02 +#define ASCQ_WRITE_ERR 0x02 +#define ASCQ_READ_ERR 0x00 +#define ASCQ_LOAD_EJCT_ERR 0x00 +#define ASCQ_WRITE_PROTECT 0x00 + + +struct sense_data_t { + unsigned char err_code; /* error code */ + /* bit7 : valid */ + /* (1 : SCSI2) */ + /* (0 : Vendor * specific) */ + /* bit6-0 : error * code */ + /* (0x70 : current * error) */ + /* (0x71 : specific command error) */ + unsigned char seg_no; /* segment No. */ + unsigned char sense_key; /* byte5 : ILI */ + /* bit3-0 : sense key */ + unsigned char info[4]; /* information */ + unsigned char ad_sense_len; /* additional sense data length */ + unsigned char cmd_info[4]; /* command specific information */ + unsigned char asc; /* ASC */ + unsigned char ascq; /* ASCQ */ + unsigned char rfu; /* FRU */ + unsigned char sns_key_info[3];/* sense key specific information */ +}; + +/* PCI Operation Register Address */ +#define RTSX_HCBAR 0x00 +#define RTSX_HCBCTLR 0x04 +#define RTSX_HDBAR 0x08 +#define RTSX_HDBCTLR 0x0C +#define RTSX_HAIMR 0x10 +#define RTSX_BIPR 0x14 +#define RTSX_BIER 0x18 + +/* Host command buffer control register */ +#define STOP_CMD (0x01 << 28) + +/* Host data buffer control register */ +#define SDMA_MODE 0x00 +#define ADMA_MODE (0x02 << 26) +#define STOP_DMA (0x01 << 28) +#define TRIG_DMA (0x01 << 31) + +/* Bus interrupt pending register */ +#define CMD_DONE_INT (1 << 31) +#define DATA_DONE_INT (1 << 30) +#define TRANS_OK_INT (1 << 29) +#define TRANS_FAIL_INT (1 << 28) +#define XD_INT (1 << 27) +#define MS_INT (1 << 26) +#define SD_INT (1 << 25) +#define GPIO0_INT (1 << 24) +#define OC_INT (1 << 23) +#define SD_WRITE_PROTECT (1 << 19) +#define XD_EXIST (1 << 18) +#define MS_EXIST (1 << 17) +#define SD_EXIST (1 << 16) +#define DELINK_INT GPIO0_INT +#define MS_OC_INT (1 << 23) +#define SD_OC_INT (1 << 22) + +#define CARD_INT (XD_INT | MS_INT | SD_INT) +#define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT) +#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | GPIO0_INT | OC_INT) + +#define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST) + +/* Bus interrupt enable register */ +#define CMD_DONE_INT_EN (1 << 31) +#define DATA_DONE_INT_EN (1 << 30) +#define TRANS_OK_INT_EN (1 << 29) +#define TRANS_FAIL_INT_EN (1 << 28) +#define XD_INT_EN (1 << 27) +#define MS_INT_EN (1 << 26) +#define SD_INT_EN (1 << 25) +#define GPIO0_INT_EN (1 << 24) +#define OC_INT_EN (1 << 23) +#define DELINK_INT_EN GPIO0_INT_EN +#define MS_OC_INT_EN (1 << 23) +#define SD_OC_INT_EN (1 << 22) + + +#define READ_REG_CMD 0 +#define WRITE_REG_CMD 1 +#define CHECK_REG_CMD 2 + +#define HOST_TO_DEVICE 0 +#define DEVICE_TO_HOST 1 + + +#define RTSX_RESV_BUF_LEN 4096 +#define HOST_CMDS_BUF_LEN 1024 +#define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN) + +#define SD_NR 2 +#define MS_NR 3 +#define XD_NR 4 +#define SPI_NR 7 +#define SD_CARD (1 << SD_NR) +#define MS_CARD (1 << MS_NR) +#define XD_CARD (1 << XD_NR) +#define SPI_CARD (1 << SPI_NR) + +#define MAX_ALLOWED_LUN_CNT 8 + +#define XD_FREE_TABLE_CNT 1200 +#define MS_FREE_TABLE_CNT 512 + + +/* Bit Operation */ +#define SET_BIT(data, idx) ((data) |= 1 << (idx)) +#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx))) +#define CHK_BIT(data, idx) ((data) & (1 << (idx))) + +/* SG descriptor */ +#define SG_INT 0x04 +#define SG_END 0x02 +#define SG_VALID 0x01 + +#define SG_NO_OP 0x00 +#define SG_TRANS_DATA (0x02 << 4) +#define SG_LINK_DESC (0x03 << 4) + +struct rtsx_chip; + +typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 sec_addr, u16 sec_cnt); + +/* Supported Clock */ +enum card_clock {CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60, + CLK_80, CLK_100, CLK_120, CLK_150, CLK_200}; + +enum RTSX_STAT {RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS, + RTSX_STAT_DELINK, RTSX_STAT_SUSPEND, + RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT}; +enum IC_VER {IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3}; + +#define MAX_RESET_CNT 3 + +/* For MS Card */ +#define MAX_DEFECTIVE_BLOCK 10 + +struct zone_entry { + u16 *l2p_table; + u16 *free_table; + u16 defect_list[MAX_DEFECTIVE_BLOCK]; /* For MS card only */ + int set_index; + int get_index; + int unused_blk_cnt; + int disable_count; + /* To indicate whether the L2P table of this zone has been built. */ + int build_flag; +}; + +#define TYPE_SD 0x0000 +#define TYPE_MMC 0x0001 + +/* TYPE_SD */ +#define SD_HS 0x0100 +#define SD_SDR50 0x0200 +#define SD_DDR50 0x0400 +#define SD_SDR104 0x0800 +#define SD_HCXC 0x1000 + +/* TYPE_MMC */ +#define MMC_26M 0x0100 +#define MMC_52M 0x0200 +#define MMC_4BIT 0x0400 +#define MMC_8BIT 0x0800 +#define MMC_SECTOR_MODE 0x1000 +#define MMC_DDR52 0x2000 + +/* SD card */ +#define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD) +#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HS)) +#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR50)) +#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_DDR50)) +#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR104)) +#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HCXC)) +#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && ((sd_card)->capacity <= 0x4000000)) +#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && ((sd_card)->capacity > 0x4000000)) +#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || CHK_SD_DDR50(sd_card) || CHK_SD_SDR104(sd_card)) + +#define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD) +#define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS) +#define SET_SD_SDR50(sd_card) ((sd_card)->sd_type |= SD_SDR50) +#define SET_SD_DDR50(sd_card) ((sd_card)->sd_type |= SD_DDR50) +#define SET_SD_SDR104(sd_card) ((sd_card)->sd_type |= SD_SDR104) +#define SET_SD_HCXC(sd_card) ((sd_card)->sd_type |= SD_HCXC) + +#define CLR_SD_HS(sd_card) ((sd_card)->sd_type &= ~SD_HS) +#define CLR_SD_SDR50(sd_card) ((sd_card)->sd_type &= ~SD_SDR50) +#define CLR_SD_DDR50(sd_card) ((sd_card)->sd_type &= ~SD_DDR50) +#define CLR_SD_SDR104(sd_card) ((sd_card)->sd_type &= ~SD_SDR104) +#define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC) + +/* MMC card */ +#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_MMC) +#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_26M)) +#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_52M)) +#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_4BIT)) +#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_8BIT)) +#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_SECTOR_MODE)) +#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_DDR52)) + +#define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC) +#define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M) +#define SET_MMC_52M(sd_card) ((sd_card)->sd_type |= MMC_52M) +#define SET_MMC_4BIT(sd_card) ((sd_card)->sd_type |= MMC_4BIT) +#define SET_MMC_8BIT(sd_card) ((sd_card)->sd_type |= MMC_8BIT) +#define SET_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type |= MMC_SECTOR_MODE) +#define SET_MMC_DDR52(sd_card) ((sd_card)->sd_type |= MMC_DDR52) + +#define CLR_MMC_26M(sd_card) ((sd_card)->sd_type &= ~MMC_26M) +#define CLR_MMC_52M(sd_card) ((sd_card)->sd_type &= ~MMC_52M) +#define CLR_MMC_4BIT(sd_card) ((sd_card)->sd_type &= ~MMC_4BIT) +#define CLR_MMC_8BIT(sd_card) ((sd_card)->sd_type &= ~MMC_8BIT) +#define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE) +#define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52) + +#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && CHK_MMC_26M(sd_card)) +#define CLR_MMC_HS(sd_card) \ +do { \ + CLR_MMC_DDR52(sd_card); \ + CLR_MMC_52M(sd_card); \ + CLR_MMC_26M(sd_card); \ +} while (0) + +#define SD_SUPPORT_CLASS_TEN 0x01 +#define SD_SUPPORT_1V8 0x02 + +#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= SD_SUPPORT_CLASS_TEN) +#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & SD_SUPPORT_CLASS_TEN) +#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= ~SD_SUPPORT_CLASS_TEN) +#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= SD_SUPPORT_1V8) +#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & SD_SUPPORT_1V8) +#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= ~SD_SUPPORT_1V8) + +struct sd_info { + u16 sd_type; + u8 err_code; + u8 sd_data_buf_ready; + u32 sd_addr; + u32 capacity; + + u8 raw_csd[16]; + u8 raw_scr[8]; + + /* Sequential RW */ + int seq_mode; + enum dma_data_direction pre_dir; + u32 pre_sec_addr; + u16 pre_sec_cnt; + + int cleanup_counter; + + int sd_clock; + + int mmc_dont_switch_bus; + +#ifdef SUPPORT_CPRM + int sd_pass_thru_en; + int pre_cmd_err; + u8 last_rsp_type; + u8 rsp[17]; +#endif + + u8 func_group1_mask; + u8 func_group2_mask; + u8 func_group3_mask; + u8 func_group4_mask; + + u8 sd_switch_fail; + u8 sd_read_phase; + +#ifdef SUPPORT_SD_LOCK + u8 sd_lock_status; + u8 sd_erase_status; + u8 sd_lock_notify; +#endif + int need_retune; +}; + +struct xd_delay_write_tag { + u32 old_phyblock; + u32 new_phyblock; + u32 logblock; + u8 pageoff; + u8 delay_write_flag; +}; + +struct xd_info { + u8 maker_code; + u8 device_code; + u8 block_shift; + u8 page_off; + u8 addr_cycle; + u16 cis_block; + u8 multi_flag; + u8 err_code; + u32 capacity; + + struct zone_entry *zone; + int zone_cnt; + + struct xd_delay_write_tag delay_write; + int cleanup_counter; + + int xd_clock; +}; + +#define MODE_512_SEQ 0x01 +#define MODE_2K_SEQ 0x02 + +#define TYPE_MS 0x0000 +#define TYPE_MSPRO 0x0001 + +#define MS_4BIT 0x0100 +#define MS_8BIT 0x0200 +#define MS_HG 0x0400 +#define MS_XC 0x0800 + +#define HG8BIT (MS_HG | MS_8BIT) + +#define CHK_MSPRO(ms_card) (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO) +#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && (((ms_card)->ms_type & HG8BIT) == HG8BIT)) +#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_XC)) +#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_HG)) + +#define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT)) +#define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT)) + +struct ms_delay_write_tag { + u16 old_phyblock; + u16 new_phyblock; + u16 logblock; + u8 pageoff; + u8 delay_write_flag; +}; + +struct ms_info { + u16 ms_type; + u8 block_shift; + u8 page_off; + u16 total_block; + u16 boot_block; + u32 capacity; + + u8 check_ms_flow; + u8 switch_8bit_fail; + u8 err_code; + + struct zone_entry *segment; + int segment_cnt; + + int pro_under_formatting; + int format_status; + u16 progress; + u8 raw_sys_info[96]; +#ifdef SUPPORT_PCGL_1P18 + u8 raw_model_name[48]; +#endif + + u8 multi_flag; + + /* Sequential RW */ + u8 seq_mode; + enum dma_data_direction pre_dir; + u32 pre_sec_addr; + u16 pre_sec_cnt; + u32 total_sec_cnt; + + struct ms_delay_write_tag delay_write; + + int cleanup_counter; + + int ms_clock; + +#ifdef SUPPORT_MAGIC_GATE + u8 magic_gate_id[16]; + u8 mg_entry_num; + int mg_auth; /* flag to indicate authentication process */ +#endif +}; + +struct spi_info { + u8 use_clk; + u8 write_en; + u16 clk_div; + u8 err_code; + + int spi_clock; +}; + + +#ifdef _MSG_TRACE +struct trace_msg_t { + u16 line; +#define MSG_FUNC_LEN 64 + char func[MSG_FUNC_LEN]; +#define MSG_FILE_LEN 32 + char file[MSG_FILE_LEN]; +#define TIME_VAL_LEN 16 + u8 timeval_buf[TIME_VAL_LEN]; + u8 valid; +}; +#endif + +/************/ +/* LUN mode */ +/************/ +/* Single LUN, support xD/SD/MS */ +#define DEFAULT_SINGLE 0 +/* 2 LUN mode, support SD/MS */ +#define SD_MS_2LUN 1 +/* Single LUN, but only support SD/MS, for Barossa LQFP */ +#define SD_MS_1LUN 2 + +#define LAST_LUN_MODE 2 + +/* Barossa package */ +#define QFN 0 +#define LQFP 1 + +/******************/ +/* sd_ctl bit map */ +/******************/ +/* SD push point control, bit 0, 1 */ +#define SD_PUSH_POINT_CTL_MASK 0x03 +#define SD_PUSH_POINT_DELAY 0x01 +#define SD_PUSH_POINT_AUTO 0x02 +/* SD sample point control, bit 2, 3 */ +#define SD_SAMPLE_POINT_CTL_MASK 0x0C +#define SD_SAMPLE_POINT_DELAY 0x04 +#define SD_SAMPLE_POINT_AUTO 0x08 +/* SD DDR Tx phase set by user, bit 4 */ +#define SD_DDR_TX_PHASE_SET_BY_USER 0x10 +/* MMC DDR Tx phase set by user, bit 5 */ +#define MMC_DDR_TX_PHASE_SET_BY_USER 0x20 +/* Support MMC DDR mode, bit 6 */ +#define SUPPORT_MMC_DDR_MODE 0x40 +/* Reset MMC at first */ +#define RESET_MMC_FIRST 0x80 + +#define SEQ_START_CRITERIA 0x20 + +/* MS Power Class En */ +#define POWER_CLASS_2_EN 0x02 +#define POWER_CLASS_1_EN 0x01 + +#define MAX_SHOW_CNT 10 +#define MAX_RESET_CNT 3 + +#define SDIO_EXIST 0x01 +#define SDIO_IGNORED 0x02 + +#define CHK_SDIO_EXIST(chip) ((chip)->sdio_func_exist & SDIO_EXIST) +#define SET_SDIO_EXIST(chip) ((chip)->sdio_func_exist |= SDIO_EXIST) +#define CLR_SDIO_EXIST(chip) ((chip)->sdio_func_exist &= ~SDIO_EXIST) + +#define CHK_SDIO_IGNORED(chip) ((chip)->sdio_func_exist & SDIO_IGNORED) +#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= SDIO_IGNORED) +#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= ~SDIO_IGNORED) + +struct rtsx_chip { + rtsx_dev_t *rtsx; + + u32 int_reg; /* Bus interrupt pending register */ + char max_lun; + void *context; + + void *host_cmds_ptr; /* host commands buffer pointer */ + dma_addr_t host_cmds_addr; + int ci; /* Command Index */ + + void *host_sg_tbl_ptr; /* SG descriptor table */ + dma_addr_t host_sg_tbl_addr; + int sgi; /* SG entry index */ + + struct scsi_cmnd *srb; /* current srb */ + struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT]; + + int cur_clk; /* current card clock */ + + /* Current accessed card */ + int cur_card; + + unsigned long need_release; /* need release bit map */ + unsigned long need_reset; /* need reset + * bit map */ + /* Flag to indicate that this card is just resumed from SS state, + * and need released before being resetted + */ + unsigned long need_reinit; + + int rw_need_retry; + +#ifdef SUPPORT_OCP + u32 ocp_int; + u8 ocp_stat; +#endif + + u8 card_exist; /* card exist bit map (physical exist) */ + u8 card_ready; /* card ready bit map (reset successfully) */ + u8 card_fail; /* card reset fail bit map */ + u8 card_ejected; /* card ejected bit map */ + u8 card_wp; /* card write protected bit map */ + + u8 lun_mc; /* flag to indicate whether to answer + * MediaChange */ + +#ifndef LED_AUTO_BLINK + int led_toggle_counter; +#endif + + int sd_reset_counter; + int xd_reset_counter; + int ms_reset_counter; + + /* card bus width */ + u8 card_bus_width[MAX_ALLOWED_LUN_CNT]; + /* card capacity */ + u32 capacity[MAX_ALLOWED_LUN_CNT]; + /* read/write card function pointer */ + card_rw_func rw_card[MAX_ALLOWED_LUN_CNT]; + /* read/write capacity, used for GPIO Toggle */ + u32 rw_cap[MAX_ALLOWED_LUN_CNT]; + /* card to lun mapping table */ + u8 card2lun[32]; + /* lun to card mapping table */ + u8 lun2card[MAX_ALLOWED_LUN_CNT]; + + int rw_fail_cnt[MAX_ALLOWED_LUN_CNT]; + + int sd_show_cnt; + int xd_show_cnt; + int ms_show_cnt; + + /* card information */ + struct sd_info sd_card; + struct xd_info xd_card; + struct ms_info ms_card; + + struct spi_info spi; + +#ifdef _MSG_TRACE + struct trace_msg_t trace_msg[TRACE_ITEM_CNT]; + int msg_idx; +#endif + + int auto_delink_cnt; + int auto_delink_allowed; + + int aspm_enabled; + + int sdio_aspm; + int sdio_idle; + int sdio_counter; + u8 sdio_raw_data[12]; + + u8 sd_io; + u8 sd_int; + + u8 rtsx_flag; + + int ss_counter; + int idle_counter; + enum RTSX_STAT rtsx_stat; + + u16 vendor_id; + u16 product_id; + u8 ic_version; + + int driver_first_load; + +#ifdef HW_AUTO_SWITCH_SD_BUS + int sdio_in_charge; +#endif + + u8 aspm_level[2]; + + int chip_insert_with_sdio; + + /* Options */ + + int adma_mode; + + int auto_delink_en; + int ss_en; + u8 lun_mode; + u8 aspm_l0s_l1_en; + + int power_down_in_ss; + + int sdr104_en; + int ddr50_en; + int sdr50_en; + + int baro_pkg; + + int asic_code; + int phy_debug_mode; + int hw_bypass_sd; + int sdio_func_exist; + int aux_pwr_exist; + u8 ms_power_class_en; + + int mspro_formatter_enable; + + int remote_wakeup_en; + + int ignore_sd; + int use_hw_setting; + + int ss_idle_period; + + int dynamic_aspm; + + int fpga_sd_sdr104_clk; + int fpga_sd_ddr50_clk; + int fpga_sd_sdr50_clk; + int fpga_sd_hs_clk; + int fpga_mmc_52m_clk; + int fpga_ms_hg_clk; + int fpga_ms_4bit_clk; + int fpga_ms_1bit_clk; + + int asic_sd_sdr104_clk; + int asic_sd_ddr50_clk; + int asic_sd_sdr50_clk; + int asic_sd_hs_clk; + int asic_mmc_52m_clk; + int asic_ms_hg_clk; + int asic_ms_4bit_clk; + int asic_ms_1bit_clk; + + u8 ssc_depth_sd_sdr104; + u8 ssc_depth_sd_ddr50; + u8 ssc_depth_sd_sdr50; + u8 ssc_depth_sd_hs; + u8 ssc_depth_mmc_52m; + u8 ssc_depth_ms_hg; + u8 ssc_depth_ms_4bit; + u8 ssc_depth_low_speed; + + u8 card_drive_sel; + u8 sd30_drive_sel_1v8; + u8 sd30_drive_sel_3v3; + + u8 sd_400mA_ocp_thd; + u8 sd_800mA_ocp_thd; + u8 ms_ocp_thd; + + int ssc_en; + int msi_en; + + int xd_timeout; + int sd_timeout; + int ms_timeout; + int mspro_timeout; + + int auto_power_down; + + int sd_ddr_tx_phase; + int mmc_ddr_tx_phase; + int sd_default_tx_phase; + int sd_default_rx_phase; + + int pmos_pwr_on_interval; + int sd_voltage_switch_delay; + int s3_pwr_off_delay; + + int force_clkreq_0; + int ft2_fast_mode; + + int do_delink_before_power_down; + int polling_config; + int sdio_retry_cnt; + + int delink_stage1_step; + int delink_stage2_step; + int delink_stage3_step; + + int auto_delink_in_L1; + int hp_watch_bios_hotplug; + int support_ms_8bit; + + u8 blink_led; + u8 phy_voltage; + u8 max_payload; + + u32 sd_speed_prior; + u32 sd_current_prior; + u32 sd_ctl; +}; + +#define rtsx_set_stat(chip, stat) \ +do { \ + if ((stat) != RTSX_STAT_IDLE) { \ + (chip)->idle_counter = 0; \ + } \ + (chip)->rtsx_stat = (enum RTSX_STAT)(stat); \ +} while (0) +#define rtsx_get_stat(chip) ((chip)->rtsx_stat) +#define rtsx_chk_stat(chip, stat) ((chip)->rtsx_stat == (stat)) + +#define RTSX_SET_DELINK(chip) ((chip)->rtsx_flag |= 0x01) +#define RTSX_CLR_DELINK(chip) ((chip)->rtsx_flag &= 0xFE) +#define RTSX_TST_DELINK(chip) ((chip)->rtsx_flag & 0x01) + +#define CHECK_PID(chip, pid) ((chip)->product_id == (pid)) +#define CHECK_BARO_PKG(chip, pkg) ((chip)->baro_pkg == (pkg)) +#define CHECK_LUN_MODE(chip, mode) ((chip)->lun_mode == (mode)) + +/* Power down control */ +#define SSC_PDCTL 0x01 +#define OC_PDCTL 0x02 + +int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl); +int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl); + +void rtsx_disable_card_int(struct rtsx_chip *chip); +void rtsx_enable_card_int(struct rtsx_chip *chip); +void rtsx_enable_bus_int(struct rtsx_chip *chip); +void rtsx_disable_bus_int(struct rtsx_chip *chip); +int rtsx_reset_chip(struct rtsx_chip *chip); +int rtsx_init_chip(struct rtsx_chip *chip); +void rtsx_release_chip(struct rtsx_chip *chip); +void rtsx_polling_func(struct rtsx_chip *chip); +void rtsx_undo_delink(struct rtsx_chip *chip); +void rtsx_stop_cmd(struct rtsx_chip *chip, int card); +int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data); +int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data); +int rtsx_write_cfg_dw(struct rtsx_chip *chip, + u8 func_no, u16 addr, u32 mask, u32 val); +int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val); +int rtsx_write_cfg_seq(struct rtsx_chip *chip, + u8 func, u16 addr, u8 *buf, int len); +int rtsx_read_cfg_seq(struct rtsx_chip *chip, + u8 func, u16 addr, u8 *buf, int len); +int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val); +int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val); +int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val); +int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val); +int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit); +int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit); +int rtsx_check_link_ready(struct rtsx_chip *chip); +void rtsx_enter_ss(struct rtsx_chip *chip); +void rtsx_exit_ss(struct rtsx_chip *chip); +int rtsx_pre_handle_interrupt(struct rtsx_chip *chip); +void rtsx_enter_L1(struct rtsx_chip *chip); +void rtsx_exit_L1(struct rtsx_chip *chip); +void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat); +void rtsx_enable_aspm(struct rtsx_chip *chip); +void rtsx_disable_aspm(struct rtsx_chip *chip); +int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len); +int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len); +int rtsx_check_chip_exist(struct rtsx_chip *chip); + +#define RTSX_WRITE_REG(chip, addr, mask, data) \ + do { \ + int retval = rtsx_write_register((chip), (addr), (mask), (data)); \ + if (retval != STATUS_SUCCESS) { \ + TRACE_RET((chip), retval); \ + } \ + } while (0) + +#define RTSX_READ_REG(chip, addr, data) \ + do { \ + int retval = rtsx_read_register((chip), (addr), (data)); \ + if (retval != STATUS_SUCCESS) { \ + TRACE_RET((chip), retval); \ + } \ + } while (0) + +#endif /* __REALTEK_RTSX_CHIP_H */ diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c new file mode 100644 index 000000000000..382e73a54f4d --- /dev/null +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -0,0 +1,3370 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_sys.h" +#include "rtsx_card.h" +#include "rtsx_chip.h" +#include "rtsx_scsi.h" +#include "sd.h" +#include "ms.h" +#include "spi.h" + +void scsi_show_command(struct scsi_cmnd *srb) +{ + char *what = NULL; + int i, unknown_cmd = 0; + + switch (srb->cmnd[0]) { + case TEST_UNIT_READY: + what = "TEST_UNIT_READY"; + break; + case REZERO_UNIT: + what = "REZERO_UNIT"; + break; + case REQUEST_SENSE: + what = "REQUEST_SENSE"; + break; + case FORMAT_UNIT: + what = "FORMAT_UNIT"; + break; + case READ_BLOCK_LIMITS: + what = "READ_BLOCK_LIMITS"; + break; + case REASSIGN_BLOCKS: + what = "REASSIGN_BLOCKS"; + break; + case READ_6: + what = "READ_6"; + break; + case WRITE_6: + what = "WRITE_6"; + break; + case SEEK_6: + what = "SEEK_6"; + break; + case READ_REVERSE: + what = "READ_REVERSE"; + break; + case WRITE_FILEMARKS: + what = "WRITE_FILEMARKS"; + break; + case SPACE: + what = "SPACE"; + break; + case INQUIRY: + what = "INQUIRY"; + break; + case RECOVER_BUFFERED_DATA: + what = "RECOVER_BUFFERED_DATA"; + break; + case MODE_SELECT: + what = "MODE_SELECT"; + break; + case RESERVE: + what = "RESERVE"; + break; + case RELEASE: + what = "RELEASE"; + break; + case COPY: + what = "COPY"; + break; + case ERASE: + what = "ERASE"; + break; + case MODE_SENSE: + what = "MODE_SENSE"; + break; + case START_STOP: + what = "START_STOP"; + break; + case RECEIVE_DIAGNOSTIC: + what = "RECEIVE_DIAGNOSTIC"; + break; + case SEND_DIAGNOSTIC: + what = "SEND_DIAGNOSTIC"; + break; + case ALLOW_MEDIUM_REMOVAL: + what = "ALLOW_MEDIUM_REMOVAL"; + break; + case SET_WINDOW: + what = "SET_WINDOW"; + break; + case READ_CAPACITY: + what = "READ_CAPACITY"; + break; + case READ_10: + what = "READ_10"; + break; + case WRITE_10: + what = "WRITE_10"; + break; + case SEEK_10: + what = "SEEK_10"; + break; + case WRITE_VERIFY: + what = "WRITE_VERIFY"; + break; + case VERIFY: + what = "VERIFY"; + break; + case SEARCH_HIGH: + what = "SEARCH_HIGH"; + break; + case SEARCH_EQUAL: + what = "SEARCH_EQUAL"; + break; + case SEARCH_LOW: + what = "SEARCH_LOW"; + break; + case SET_LIMITS: + what = "SET_LIMITS"; + break; + case READ_POSITION: + what = "READ_POSITION"; + break; + case SYNCHRONIZE_CACHE: + what = "SYNCHRONIZE_CACHE"; + break; + case LOCK_UNLOCK_CACHE: + what = "LOCK_UNLOCK_CACHE"; + break; + case READ_DEFECT_DATA: + what = "READ_DEFECT_DATA"; + break; + case MEDIUM_SCAN: + what = "MEDIUM_SCAN"; + break; + case COMPARE: + what = "COMPARE"; + break; + case COPY_VERIFY: + what = "COPY_VERIFY"; + break; + case WRITE_BUFFER: + what = "WRITE_BUFFER"; + break; + case READ_BUFFER: + what = "READ_BUFFER"; + break; + case UPDATE_BLOCK: + what = "UPDATE_BLOCK"; + break; + case READ_LONG: + what = "READ_LONG"; + break; + case WRITE_LONG: + what = "WRITE_LONG"; + break; + case CHANGE_DEFINITION: + what = "CHANGE_DEFINITION"; + break; + case WRITE_SAME: + what = "WRITE_SAME"; + break; + case GPCMD_READ_SUBCHANNEL: + what = "READ SUBCHANNEL"; + break; + case READ_TOC: + what = "READ_TOC"; + break; + case GPCMD_READ_HEADER: + what = "READ HEADER"; + break; + case GPCMD_PLAY_AUDIO_10: + what = "PLAY AUDIO (10)"; + break; + case GPCMD_PLAY_AUDIO_MSF: + what = "PLAY AUDIO MSF"; + break; + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + what = "GET EVENT/STATUS NOTIFICATION"; + break; + case GPCMD_PAUSE_RESUME: + what = "PAUSE/RESUME"; + break; + case LOG_SELECT: + what = "LOG_SELECT"; + break; + case LOG_SENSE: + what = "LOG_SENSE"; + break; + case GPCMD_STOP_PLAY_SCAN: + what = "STOP PLAY/SCAN"; + break; + case GPCMD_READ_DISC_INFO: + what = "READ DISC INFORMATION"; + break; + case GPCMD_READ_TRACK_RZONE_INFO: + what = "READ TRACK INFORMATION"; + break; + case GPCMD_RESERVE_RZONE_TRACK: + what = "RESERVE TRACK"; + break; + case GPCMD_SEND_OPC: + what = "SEND OPC"; + break; + case MODE_SELECT_10: + what = "MODE_SELECT_10"; + break; + case GPCMD_REPAIR_RZONE_TRACK: + what = "REPAIR TRACK"; + break; + case 0x59: + what = "READ MASTER CUE"; + break; + case MODE_SENSE_10: + what = "MODE_SENSE_10"; + break; + case GPCMD_CLOSE_TRACK: + what = "CLOSE TRACK/SESSION"; + break; + case 0x5C: + what = "READ BUFFER CAPACITY"; + break; + case 0x5D: + what = "SEND CUE SHEET"; + break; + case GPCMD_BLANK: + what = "BLANK"; + break; + case REPORT_LUNS: + what = "REPORT LUNS"; + break; + case MOVE_MEDIUM: + what = "MOVE_MEDIUM or PLAY AUDIO (12)"; + break; + case READ_12: + what = "READ_12"; + break; + case WRITE_12: + what = "WRITE_12"; + break; + case WRITE_VERIFY_12: + what = "WRITE_VERIFY_12"; + break; + case SEARCH_HIGH_12: + what = "SEARCH_HIGH_12"; + break; + case SEARCH_EQUAL_12: + what = "SEARCH_EQUAL_12"; + break; + case SEARCH_LOW_12: + what = "SEARCH_LOW_12"; + break; + case SEND_VOLUME_TAG: + what = "SEND_VOLUME_TAG"; + break; + case READ_ELEMENT_STATUS: + what = "READ_ELEMENT_STATUS"; + break; + case GPCMD_READ_CD_MSF: + what = "READ CD MSF"; + break; + case GPCMD_SCAN: + what = "SCAN"; + break; + case GPCMD_SET_SPEED: + what = "SET CD SPEED"; + break; + case GPCMD_MECHANISM_STATUS: + what = "MECHANISM STATUS"; + break; + case GPCMD_READ_CD: + what = "READ CD"; + break; + case 0xE1: + what = "WRITE CONTINUE"; + break; + case WRITE_LONG_2: + what = "WRITE_LONG_2"; + break; + case VENDOR_CMND: + what = "Realtek's vendor command"; + break; + default: + what = "(unknown command)"; unknown_cmd = 1; + break; + } + + if (srb->cmnd[0] != TEST_UNIT_READY) + RTSX_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); + + if (unknown_cmd) { + RTSX_DEBUGP(""); + for (i = 0; i < srb->cmd_len && i < 16; i++) + RTSX_DEBUGPN(" %02x", srb->cmnd[i]); + RTSX_DEBUGPN("\n"); + } +} + +void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type) +{ + switch (sense_type) { + case SENSE_TYPE_MEDIA_CHANGE: + set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0); + break; + + case SENSE_TYPE_MEDIA_NOT_PRESENT: + set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0); + break; + + case SENSE_TYPE_MEDIA_LBA_OVER_RANGE: + set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0); + break; + + case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT: + set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0); + break; + + case SENSE_TYPE_MEDIA_WRITE_PROTECT: + set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0); + break; + + case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR: + set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0); + break; + + case SENSE_TYPE_MEDIA_WRITE_ERR: + set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0); + break; + + case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD: + set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0, + ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); + break; + + case SENSE_TYPE_FORMAT_IN_PROGRESS: + set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0); + break; + + case SENSE_TYPE_FORMAT_CMD_FAILED: + set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0); + break; + +#ifdef SUPPORT_MAGIC_GATE + case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB: + set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0); + break; + + case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN: + set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0); + break; + + case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM: + set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0); + break; + + case SENSE_TYPE_MG_WRITE_ERR: + set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0); + break; +#endif + +#ifdef SUPPORT_SD_LOCK + case SENSE_TYPE_MEDIA_READ_FORBIDDEN: + set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0); + break; +#endif + + case SENSE_TYPE_NO_SENSE: + default: + set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0); + break; + } +} + +void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, + u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, + u16 sns_key_info1) +{ + struct sense_data_t *sense = &(chip->sense_buffer[lun]); + + sense->err_code = err_code; + sense->sense_key = sense_key; + sense->info[0] = (u8)(info >> 24); + sense->info[1] = (u8)(info >> 16); + sense->info[2] = (u8)(info >> 8); + sense->info[3] = (u8)info; + + sense->ad_sense_len = sizeof(struct sense_data_t) - 8; + sense->asc = asc; + sense->ascq = ascq; + if (sns_key_info0 != 0) { + sense->sns_key_info[0] = SKSV | sns_key_info0; + sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8; + sense->sns_key_info[2] = sns_key_info1 & 0x0f; + } +} + +static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + return TRANSPORT_FAILED; + } + + if (!(CHK_BIT(chip->lun_mc, lun))) { + SET_BIT(chip->lun_mc, lun); + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + return TRANSPORT_FAILED; + } + +#ifdef SUPPORT_SD_LOCK + if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) { + struct sd_info *sd_card = &(chip->sd_card); + if (sd_card->sd_lock_notify) { + sd_card->sd_lock_notify = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + return TRANSPORT_FAILED; + } else if (sd_card->sd_lock_status & SD_LOCKED) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_READ_FORBIDDEN); + return TRANSPORT_FAILED; + } + } +#endif + + return TRANSPORT_GOOD; +} + +static unsigned char formatter_inquiry_str[20] = { + 'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K', +#ifdef SUPPORT_MAGIC_GATE + '-', 'M', 'G', /* Byte[47:49] */ +#else + 0x20, 0x20, 0x20, /* Byte[47:49] */ +#endif + +#ifdef SUPPORT_MAGIC_GATE + 0x0B, /* Byte[50]: MG, MS, MSPro, MSXC */ +#else + 0x09, /* Byte[50]: MS, MSPro, MSXC */ +#endif + 0x00, /* Byte[51]: Category Specific Commands */ + 0x00, /* Byte[52]: Access Control and feature */ + 0x20, 0x20, 0x20, /* Byte[53:55] */ +}; + +static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + char *inquiry_default = (char *)"Generic-xD/SD/M.S. 1.00 "; + char *inquiry_sdms = (char *)"Generic-SD/MemoryStick 1.00 "; + char *inquiry_sd = (char *)"Generic-SD/MMC 1.00 "; + char *inquiry_ms = (char *)"Generic-MemoryStick 1.00 "; + char *inquiry_string; + unsigned char sendbytes; + unsigned char *buf; + u8 card = get_lun_card(chip, lun); + int pro_formatter_flag = 0; + unsigned char inquiry_buf[] = { + QULIFIRE|DRCT_ACCESS_DEV, + RMB_DISC|0x0D, + 0x00, + 0x01, + 0x1f, + 0x02, + 0, + REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE, + }; + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { + if (chip->lun2card[lun] == SD_CARD) + inquiry_string = inquiry_sd; + else + inquiry_string = inquiry_ms; + + } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) { + inquiry_string = inquiry_sdms; + } else { + inquiry_string = inquiry_default; + } + + buf = vmalloc(scsi_bufflen(srb)); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + +#ifdef SUPPORT_MAGIC_GATE + if ((chip->mspro_formatter_enable) && + (chip->lun2card[lun] & MS_CARD)) +#else + if (chip->mspro_formatter_enable) +#endif + { + if (!card || (card == MS_CARD)) + pro_formatter_flag = 1; + } + + if (pro_formatter_flag) { + if (scsi_bufflen(srb) < 56) + sendbytes = (unsigned char)(scsi_bufflen(srb)); + else + sendbytes = 56; + + } else { + if (scsi_bufflen(srb) < 36) + sendbytes = (unsigned char)(scsi_bufflen(srb)); + else + sendbytes = 36; + } + + if (sendbytes > 8) { + memcpy(buf, inquiry_buf, 8); + memcpy(buf + 8, inquiry_string, sendbytes - 8); + if (pro_formatter_flag) { + /* Additional Length */ + buf[4] = 0x33; + } + } else { + memcpy(buf, inquiry_buf, sendbytes); + } + + if (pro_formatter_flag) { + if (sendbytes > 36) + memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36); + } + + scsi_set_resid(srb, 0); + + rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); + vfree(buf); + + return TRANSPORT_GOOD; +} + + +static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + + scsi_set_resid(srb, scsi_bufflen(srb)); + + if (srb->cmnd[1] == 1) + return TRANSPORT_GOOD; + + switch (srb->cmnd[0x4]) { + case STOP_MEDIUM: + /* Media disabled */ + return TRANSPORT_GOOD; + + case UNLOAD_MEDIUM: + /* Media shall be unload */ + if (check_card_ready(chip, lun)) + eject_card(chip, lun); + return TRANSPORT_GOOD; + + case MAKE_MEDIUM_READY: + case LOAD_MEDIUM: + if (check_card_ready(chip, lun)) { + return TRANSPORT_GOOD; + } else { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + break; + } + + TRACE_RET(chip, TRANSPORT_ERROR); +} + + +static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int prevent; + + prevent = srb->cmnd[4] & 0x1; + + scsi_set_resid(srb, 0); + + if (prevent) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return TRANSPORT_GOOD; +} + + +static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sense_data_t *sense; + unsigned int lun = SCSI_LUN(srb); + struct ms_info *ms_card = &(chip->ms_card); + unsigned char *tmp, *buf; + + sense = &(chip->sense_buffer[lun]); + + if ((get_lun_card(chip, lun) == MS_CARD) && + ms_card->pro_under_formatting) { + if (ms_card->format_status == FORMAT_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); + ms_card->pro_under_formatting = 0; + ms_card->progress = 0; + } else if (ms_card->format_status == FORMAT_IN_PROGRESS) { + /* Logical Unit Not Ready Format in Progress */ + set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, + 0, (u16)(ms_card->progress)); + } else { + /* Format Command Failed */ + set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); + ms_card->pro_under_formatting = 0; + ms_card->progress = 0; + } + + rtsx_set_stat(chip, RTSX_STAT_RUN); + } + + buf = vmalloc(scsi_bufflen(srb)); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + tmp = (unsigned char *)sense; + memcpy(buf, tmp, scsi_bufflen(srb)); + + rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); + vfree(buf); + + scsi_set_resid(srb, 0); + /* Reset Sense Data */ + set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); + return TRANSPORT_GOOD; +} + +static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, + int lun, u8 *buf, int buf_len) +{ + struct ms_info *ms_card = &(chip->ms_card); + int sys_info_offset; + int data_size = buf_len; + int support_format = 0; + int i = 0; + + if (cmd == MODE_SENSE) { + sys_info_offset = 8; + if (data_size > 0x68) + data_size = 0x68; + + buf[i++] = 0x67; /* Mode Data Length */ + } else { + sys_info_offset = 12; + if (data_size > 0x6C) + data_size = 0x6C; + + buf[i++] = 0x00; /* Mode Data Length (MSB) */ + buf[i++] = 0x6A; /* Mode Data Length (LSB) */ + } + + /* Medium Type Code */ + if (check_card_ready(chip, lun)) { + if (CHK_MSXC(ms_card)) { + support_format = 1; + buf[i++] = 0x40; + } else if (CHK_MSPRO(ms_card)) { + support_format = 1; + buf[i++] = 0x20; + } else { + buf[i++] = 0x10; + } + + /* WP */ + if (check_card_wp(chip, lun)) + buf[i++] = 0x80; + else + buf[i++] = 0x00; + + } else { + buf[i++] = 0x00; /* MediaType */ + buf[i++] = 0x00; /* WP */ + } + + buf[i++] = 0x00; /* Reserved */ + + if (cmd == MODE_SENSE_10) { + buf[i++] = 0x00; /* Reserved */ + buf[i++] = 0x00; /* Block descriptor length(MSB) */ + buf[i++] = 0x00; /* Block descriptor length(LSB) */ + + /* The Following Data is the content of "Page 0x20" */ + if (data_size >= 9) + buf[i++] = 0x20; /* Page Code */ + if (data_size >= 10) + buf[i++] = 0x62; /* Page Length */ + if (data_size >= 11) + buf[i++] = 0x00; /* No Access Control */ + if (data_size >= 12) { + if (support_format) + buf[i++] = 0xC0; /* SF, SGM */ + else + buf[i++] = 0x00; + } + } else { + /* The Following Data is the content of "Page 0x20" */ + if (data_size >= 5) + buf[i++] = 0x20; /* Page Code */ + if (data_size >= 6) + buf[i++] = 0x62; /* Page Length */ + if (data_size >= 7) + buf[i++] = 0x00; /* No Access Control */ + if (data_size >= 8) { + if (support_format) + buf[i++] = 0xC0; /* SF, SGM */ + else + buf[i++] = 0x00; + } + } + + if (data_size > sys_info_offset) { + /* 96 Bytes Attribute Data */ + int len = data_size - sys_info_offset; + len = (len < 96) ? len : 96; + + memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len); + } +} + +static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + unsigned int dataSize; + int status; + int pro_formatter_flag; + unsigned char pageCode, *buf; + u8 card = get_lun_card(chip, lun); + +#ifndef SUPPORT_MAGIC_GATE + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + scsi_set_resid(srb, scsi_bufflen(srb)); + TRACE_RET(chip, TRANSPORT_FAILED); + } +#endif + + pro_formatter_flag = 0; + dataSize = 8; +#ifdef SUPPORT_MAGIC_GATE + if ((chip->lun2card[lun] & MS_CARD)) { + if (!card || (card == MS_CARD)) { + dataSize = 108; + if (chip->mspro_formatter_enable) + pro_formatter_flag = 1; + } + } +#else + if (card == MS_CARD) { + if (chip->mspro_formatter_enable) { + pro_formatter_flag = 1; + dataSize = 108; + } + } +#endif + + buf = kmalloc(dataSize, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + pageCode = srb->cmnd[2] & 0x3f; + + if ((pageCode == 0x3F) || (pageCode == 0x1C) || + (pageCode == 0x00) || + (pro_formatter_flag && (pageCode == 0x20))) { + if (srb->cmnd[0] == MODE_SENSE) { + if ((pageCode == 0x3F) || (pageCode == 0x20)) { + ms_mode_sense(chip, srb->cmnd[0], + lun, buf, dataSize); + } else { + dataSize = 4; + buf[0] = 0x03; + buf[1] = 0x00; + if (check_card_wp(chip, lun)) + buf[2] = 0x80; + else + buf[2] = 0x00; + + buf[3] = 0x00; + } + } else { + if ((pageCode == 0x3F) || (pageCode == 0x20)) { + ms_mode_sense(chip, srb->cmnd[0], + lun, buf, dataSize); + } else { + dataSize = 8; + buf[0] = 0x00; + buf[1] = 0x06; + buf[2] = 0x00; + if (check_card_wp(chip, lun)) + buf[3] = 0x80; + else + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x00; + buf[7] = 0x00; + } + } + status = TRANSPORT_GOOD; + } else { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + scsi_set_resid(srb, scsi_bufflen(srb)); + status = TRANSPORT_FAILED; + } + + if (status == TRANSPORT_GOOD) { + unsigned int len = min_t(unsigned int, scsi_bufflen(srb), + dataSize); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + } + kfree(buf); + + return status; +} + +static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ +#ifdef SUPPORT_SD_LOCK + struct sd_info *sd_card = &(chip->sd_card); +#endif + unsigned int lun = SCSI_LUN(srb); + int retval; + u32 start_sec; + u16 sec_cnt; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (!(CHK_BIT(chip->lun_mc, lun))) { + SET_BIT(chip->lun_mc, lun); + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + return TRANSPORT_FAILED; + } + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_erase_status) { + /* Accessing to any card is forbidden + * until the erase procedure of SD is completed + */ + RTSX_DEBUGP("SD card being erased!\n"); + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (get_lun_card(chip, lun) == SD_CARD) { + if (sd_card->sd_lock_status & SD_LOCKED) { + RTSX_DEBUGP("SD card locked!\n"); + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_READ_FORBIDDEN); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } +#endif + + if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) { + start_sec = ((u32)srb->cmnd[2] << 24) | + ((u32)srb->cmnd[3] << 16) | + ((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]); + sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; + } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { + start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) | + ((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]); + sec_cnt = srb->cmnd[4]; + } else if ((srb->cmnd[0] == VENDOR_CMND) && + (srb->cmnd[1] == SCSI_APP_CMD) && + ((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) { + start_sec = ((u32)srb->cmnd[4] << 24) | + ((u32)srb->cmnd[5] << 16) | + ((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]); + sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10]; + } else { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + /* In some test, we will receive a start_sec like 0xFFFFFFFF. + * In this situation, start_sec + sec_cnt will overflow, so we + * need to judge start_sec at first + */ + if ((start_sec > get_card_size(chip, lun)) || + ((start_sec + sec_cnt) > get_card_size(chip, lun))) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (sec_cnt == 0) { + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; + } + + if (chip->rw_fail_cnt[lun] == 3) { + RTSX_DEBUGP("read/write fail three times in succession\n"); + if (srb->sc_data_direction == DMA_FROM_DEVICE) + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + else + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); + + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { + if (check_card_wp(chip, lun)) { + RTSX_DEBUGP("Write protected card!\n"); + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_PROTECT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + retval = card_rw(srb, chip, start_sec, sec_cnt); + if (retval != STATUS_SUCCESS) { + if (chip->need_release & chip->lun2card[lun]) { + chip->rw_fail_cnt[lun] = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + } else { + chip->rw_fail_cnt[lun]++; + if (srb->sc_data_direction == DMA_FROM_DEVICE) + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + else + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + } + retval = TRANSPORT_FAILED; + TRACE_GOTO(chip, Exit); + } else { + chip->rw_fail_cnt[lun] = 0; + retval = TRANSPORT_GOOD; + } + + scsi_set_resid(srb, 0); + +Exit: + return retval; +} + +static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned char *buf; + unsigned int lun = SCSI_LUN(srb); + unsigned int buf_len; + u8 card = get_lun_card(chip, lun); + u32 card_size; + int desc_cnt; + int i = 0; + + if (!check_card_ready(chip, lun)) { + if (!chip->mspro_formatter_enable) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12; + + buf = kmalloc(buf_len, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + buf[i++] = 0; + buf[i++] = 0; + buf[i++] = 0; + + /* Capacity List Length */ + if ((buf_len > 12) && chip->mspro_formatter_enable && + (chip->lun2card[lun] & MS_CARD) && + (!card || (card == MS_CARD))) { + buf[i++] = 0x10; + desc_cnt = 2; + } else { + buf[i++] = 0x08; + desc_cnt = 1; + } + + while (desc_cnt) { + if (check_card_ready(chip, lun)) { + card_size = get_card_size(chip, lun); + buf[i++] = (unsigned char)(card_size >> 24); + buf[i++] = (unsigned char)(card_size >> 16); + buf[i++] = (unsigned char)(card_size >> 8); + buf[i++] = (unsigned char)card_size; + + if (desc_cnt == 2) + buf[i++] = 2; + else + buf[i++] = 0; + } else { + buf[i++] = 0xFF; + buf[i++] = 0xFF; + buf[i++] = 0xFF; + buf[i++] = 0xFF; + + if (desc_cnt == 2) + buf[i++] = 3; + else + buf[i++] = 0; + } + + buf[i++] = 0x00; + buf[i++] = 0x02; + buf[i++] = 0x00; + + desc_cnt--; + } + + buf_len = min_t(unsigned int, scsi_bufflen(srb), buf_len); + rtsx_stor_set_xfer_buf(buf, buf_len, srb); + kfree(buf); + + scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); + + return TRANSPORT_GOOD; +} + +static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned char *buf; + unsigned int lun = SCSI_LUN(srb); + u32 card_size; + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (!(CHK_BIT(chip->lun_mc, lun))) { + SET_BIT(chip->lun_mc, lun); + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + return TRANSPORT_FAILED; + } + + buf = kmalloc(8, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + card_size = get_card_size(chip, lun); + buf[0] = (unsigned char)((card_size - 1) >> 24); + buf[1] = (unsigned char)((card_size - 1) >> 16); + buf[2] = (unsigned char)((card_size - 1) >> 8); + buf[3] = (unsigned char)(card_size - 1); + + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x02; + buf[7] = 0x00; + + rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); + kfree(buf); + + scsi_set_resid(srb, 0); + + return TRANSPORT_GOOD; +} + +static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short len, i; + int retval; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len; i++) { + retval = spi_read_eeprom(chip, i, buf + i); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short len, i; + int retval; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (len == 511) { + retval = spi_erase_eeprom_chip(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } else { + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), + len); + buf = vmalloc(len); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + for (i = 0; i < len; i++) { + retval = spi_write_eeprom(chip, i, buf[i]); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + vfree(buf); + } + + return TRANSPORT_GOOD; +} + +static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr, len, i; + int retval; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3]; + len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + + if (addr < 0xFC00) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len; i++) { + retval = rtsx_read_register(chip, addr + i, buf + i); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr, len, i; + int retval; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3]; + len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + + if (addr < 0xFC00) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); + buf = vmalloc(len); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len; i++) { + retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (get_lun_card(chip, lun) != SD_CARD) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + scsi_set_resid(srb, 0); + rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb); + + return TRANSPORT_GOOD; +} + +static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + u8 gpio = srb->cmnd[2]; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + if (gpio > 3) + gpio = 1; + toggle_gpio(chip, gpio); + + return TRANSPORT_GOOD; +} + +#ifdef _MSG_TRACE +static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned char *ptr, *buf = NULL; + int i, msg_cnt; + u8 clear; + unsigned int buf_len; + + buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * + TRACE_ITEM_CNT); + + if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + clear = srb->cmnd[2]; + + buf = vmalloc(scsi_bufflen(srb)); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + ptr = buf; + + if (chip->trace_msg[chip->msg_idx].valid) + msg_cnt = TRACE_ITEM_CNT; + else + msg_cnt = chip->msg_idx; + + *(ptr++) = (u8)(msg_cnt >> 24); + *(ptr++) = (u8)(msg_cnt >> 16); + *(ptr++) = (u8)(msg_cnt >> 8); + *(ptr++) = (u8)msg_cnt; + RTSX_DEBUGP("Trace message count is %d\n", msg_cnt); + + for (i = 1; i <= msg_cnt; i++) { + int j, idx; + + idx = chip->msg_idx - i; + if (idx < 0) + idx += TRACE_ITEM_CNT; + + *(ptr++) = (u8)(chip->trace_msg[idx].line >> 8); + *(ptr++) = (u8)(chip->trace_msg[idx].line); + for (j = 0; j < MSG_FUNC_LEN; j++) + *(ptr++) = chip->trace_msg[idx].func[j]; + + for (j = 0; j < MSG_FILE_LEN; j++) + *(ptr++) = chip->trace_msg[idx].file[j]; + + for (j = 0; j < TIME_VAL_LEN; j++) + *(ptr++) = chip->trace_msg[idx].timeval_buf[j]; + } + + rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); + vfree(buf); + + if (clear) { + chip->msg_idx = 0; + for (i = 0; i < TRACE_ITEM_CNT; i++) + chip->trace_msg[i].valid = 0; + } + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; +} +#endif + +static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + u8 addr, buf[4]; + u32 val; + unsigned int len; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = srb->cmnd[4]; + + val = rtsx_readl(chip, addr); + RTSX_DEBUGP("Host register (0x%x): 0x%x\n", addr, val); + + buf[0] = (u8)(val >> 24); + buf[1] = (u8)(val >> 16); + buf[2] = (u8)(val >> 8); + buf[3] = (u8)val; + + len = min_t(unsigned int, scsi_bufflen(srb), 4); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + return TRANSPORT_GOOD; +} + +static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + u8 addr, buf[4]; + u32 val; + unsigned int len; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = srb->cmnd[4]; + + len = min_t(unsigned int, scsi_bufflen(srb), 4); + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2] + << 8) | buf[3]; + + rtsx_writel(chip, addr, val); + + return TRANSPORT_GOOD; +} + +static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned lun = SCSI_LUN(srb); + + if (srb->cmnd[3] == 1) { + /* Variable Clock */ + struct xd_info *xd_card = &(chip->xd_card); + struct sd_info *sd_card = &(chip->sd_card); + struct ms_info *ms_card = &(chip->ms_card); + + switch (srb->cmnd[4]) { + case XD_CARD: + xd_card->xd_clock = srb->cmnd[5]; + break; + + case SD_CARD: + sd_card->sd_clock = srb->cmnd[5]; + break; + + case MS_CARD: + ms_card->ms_clock = srb->cmnd[5]; + break; + + default: + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } else if (srb->cmnd[3] == 2) { + if (srb->cmnd[4]) { + chip->blink_led = 1; + } else { + int retval; + + chip->blink_led = 0; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && + (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + turn_off_led(chip, LED_GPIO); + } + } else { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return TRANSPORT_GOOD; +} + +static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + + if (srb->cmnd[3] == 1) { + struct xd_info *xd_card = &(chip->xd_card); + struct sd_info *sd_card = &(chip->sd_card); + struct ms_info *ms_card = &(chip->ms_card); + u8 tmp; + + switch (srb->cmnd[4]) { + case XD_CARD: + tmp = (u8)(xd_card->xd_clock); + break; + + case SD_CARD: + tmp = (u8)(sd_card->sd_clock); + break; + + case MS_CARD: + tmp = (u8)(ms_card->ms_clock); + break; + + default: + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + rtsx_stor_set_xfer_buf(&tmp, 1, srb); + } else if (srb->cmnd[3] == 2) { + u8 tmp = chip->blink_led; + rtsx_stor_set_xfer_buf(&tmp, 1, srb); + } else { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return TRANSPORT_GOOD; +} + +static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + unsigned int lun = SCSI_LUN(srb); + u16 len; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; + len = min_t(u16, len, scsi_bufflen(srb)); + + if (srb->sc_data_direction == DMA_FROM_DEVICE) + RTSX_DEBUGP("Read from device\n"); + else + RTSX_DEBUGP("Write to device\n"); + + retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len, + scsi_sg_count(srb), srb->sc_data_direction, 1000); + if (retval < 0) { + if (srb->sc_data_direction == DMA_FROM_DEVICE) + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + else + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + + TRACE_RET(chip, TRANSPORT_FAILED); + } + scsi_set_resid(srb, 0); + + return TRANSPORT_GOOD; +} + +static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + struct ms_info *ms_card = &(chip->ms_card); + int buf_len; + unsigned int lun = SCSI_LUN(srb); + u8 card = get_lun_card(chip, lun); + u8 status[32]; +#ifdef SUPPORT_OCP + u8 oc_now_mask = 0, oc_ever_mask = 0; +#endif + + memset(status, 0, 32); + + status[0] = (u8)(chip->product_id); + status[1] = chip->ic_version; + + if (chip->auto_delink_en) + status[2] = 0x10; + else + status[2] = 0x00; + + status[3] = 20; + status[4] = 10; + status[5] = 05; + status[6] = 21; + + if (chip->card_wp) + status[7] = 0x20; + else + status[7] = 0x00; + +#ifdef SUPPORT_OCP + status[8] = 0; + if (CHECK_LUN_MODE(chip, + SD_MS_2LUN) && (chip->lun2card[lun] == MS_CARD)) { + oc_now_mask = MS_OC_NOW; + oc_ever_mask = MS_OC_EVER; + } else { + oc_now_mask = SD_OC_NOW; + oc_ever_mask = SD_OC_EVER; + } + + if (chip->ocp_stat & oc_now_mask) + status[8] |= 0x02; + + if (chip->ocp_stat & oc_ever_mask) + status[8] |= 0x01; +#endif + + if (card == SD_CARD) { + if (CHK_SD(sd_card)) { + if (CHK_SD_HCXC(sd_card)) { + if (sd_card->capacity > 0x4000000) + status[0x0E] = 0x02; + else + status[0x0E] = 0x01; + } else { + status[0x0E] = 0x00; + } + + if (CHK_SD_SDR104(sd_card)) + status[0x0F] = 0x03; + else if (CHK_SD_DDR50(sd_card)) + status[0x0F] = 0x04; + else if (CHK_SD_SDR50(sd_card)) + status[0x0F] = 0x02; + else if (CHK_SD_HS(sd_card)) + status[0x0F] = 0x01; + else + status[0x0F] = 0x00; + } else { + if (CHK_MMC_SECTOR_MODE(sd_card)) + status[0x0E] = 0x01; + else + status[0x0E] = 0x00; + + if (CHK_MMC_DDR52(sd_card)) + status[0x0F] = 0x03; + else if (CHK_MMC_52M(sd_card)) + status[0x0F] = 0x02; + else if (CHK_MMC_26M(sd_card)) + status[0x0F] = 0x01; + else + status[0x0F] = 0x00; + } + } else if (card == MS_CARD) { + if (CHK_MSPRO(ms_card)) { + if (CHK_MSXC(ms_card)) + status[0x0E] = 0x01; + else + status[0x0E] = 0x00; + + if (CHK_HG8BIT(ms_card)) + status[0x0F] = 0x01; + else + status[0x0F] = 0x00; + } + } + +#ifdef SUPPORT_SD_LOCK + if (card == SD_CARD) { + status[0x17] = 0x80; + if (sd_card->sd_erase_status) + status[0x17] |= 0x01; + if (sd_card->sd_lock_status & SD_LOCKED) { + status[0x17] |= 0x02; + status[0x07] |= 0x40; + } + if (sd_card->sd_lock_status & SD_PWD_EXIST) + status[0x17] |= 0x04; + } else { + status[0x17] = 0x00; + } + + RTSX_DEBUGP("status[0x17] = 0x%x\n", status[0x17]); +#endif + + status[0x18] = 0x8A; + status[0x1A] = 0x28; +#ifdef SUPPORT_SD_LOCK + status[0x1F] = 0x01; +#endif + + buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status)); + rtsx_stor_set_xfer_buf(status, buf_len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); + + return TRANSPORT_GOOD; +} + +static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int phy_debug_mode; + int retval; + u16 reg; + + if (!CHECK_PID(chip, 0x5208)) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + phy_debug_mode = (int)(srb->cmnd[3]); + + if (phy_debug_mode) { + chip->phy_debug_mode = 1; + retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + rtsx_disable_bus_int(chip); + + retval = rtsx_read_phy_register(chip, 0x1C, ®); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + reg |= 0x0001; + retval = rtsx_write_phy_register(chip, 0x1C, reg); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + } else { + chip->phy_debug_mode = 0; + retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + rtsx_enable_bus_int(chip); + + retval = rtsx_read_phy_register(chip, 0x1C, ®); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + reg &= 0xFFFE; + retval = rtsx_write_phy_register(chip, 0x1C, reg); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return TRANSPORT_GOOD; +} + +static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval = STATUS_SUCCESS; + unsigned int lun = SCSI_LUN(srb); + u8 cmd_type, mask, value, idx; + u16 addr; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + switch (srb->cmnd[3]) { + case INIT_BATCHCMD: + rtsx_init_cmd(chip); + break; + + case ADD_BATCHCMD: + cmd_type = srb->cmnd[4]; + if (cmd_type > 2) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + addr = (srb->cmnd[5] << 8) | srb->cmnd[6]; + mask = srb->cmnd[7]; + value = srb->cmnd[8]; + rtsx_add_cmd(chip, cmd_type, addr, mask, value); + break; + + case SEND_BATCHCMD: + retval = rtsx_send_cmd(chip, 0, 1000); + break; + + case GET_BATCHRSP: + idx = srb->cmnd[4]; + value = *(rtsx_get_cmd_data(chip) + idx); + if (scsi_bufflen(srb) < 1) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + rtsx_stor_set_xfer_buf(&value, 1, srb); + scsi_set_resid(srb, 0); + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return TRANSPORT_GOOD; +} + +static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int result; + + switch (srb->cmnd[3]) { + case INIT_BATCHCMD: + case ADD_BATCHCMD: + case SEND_BATCHCMD: + case GET_BATCHRSP: + result = rw_mem_cmd_buf(srb, chip); + break; + default: + result = TRANSPORT_ERROR; + } + + return result; +} + +static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr, len, i; + int retval; + u8 *buf; + u16 val; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; + + if (len % 2) + len -= len % 2; + + if (len) { + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len / 2; i++) { + retval = rtsx_read_phy_register(chip, addr + i, &val); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + buf[2*i] = (u8)(val >> 8); + buf[2*i+1] = (u8)val; + } + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), + len); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + vfree(buf); + } + + return TRANSPORT_GOOD; +} + +static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr, len, i; + int retval; + u8 *buf; + u16 val; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; + + if (len % 2) + len -= len % 2; + + if (len) { + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), + len); + + buf = vmalloc(len); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len / 2; i++) { + val = ((u16)buf[2*i] << 8) | buf[2*i+1]; + retval = rtsx_write_phy_register(chip, addr + i, val); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + vfree(buf); + } + + return TRANSPORT_GOOD; +} + +static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr; + int retval; + u8 mode; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + mode = srb->cmnd[3]; + addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + + if (mode == 0) { + retval = spi_erase_eeprom_chip(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } else if (mode == 1) { + retval = spi_erase_eeprom_byte(chip, addr); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } else { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return TRANSPORT_GOOD; +} + +static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr, len, i; + int retval; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; + + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len; i++) { + retval = spi_read_eeprom(chip, addr + i, buf + i); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned short addr, len, i; + int retval; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; + len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); + buf = vmalloc(len); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len; i++) { + retval = spi_write_eeprom(chip, addr + i, buf[i]); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u8 addr, len, i; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = srb->cmnd[4]; + len = srb->cmnd[5]; + + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + for (i = 0; i < len; i++) { + retval = rtsx_read_efuse(chip, addr + i, buf + i); + if (retval != STATUS_SUCCESS) { + vfree(buf); + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + len = (u8)min_t(unsigned int, scsi_bufflen(srb), len); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval, result = TRANSPORT_GOOD; + u16 val; + u8 addr, len, i; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + addr = srb->cmnd[4]; + len = srb->cmnd[5]; + + len = (u8)min_t(unsigned int, scsi_bufflen(srb), len); + buf = vmalloc(len); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + retval = rtsx_force_power_on(chip, SSC_PDCTL); + if (retval != STATUS_SUCCESS) { + vfree(buf); + TRACE_RET(chip, TRANSPORT_ERROR); + } + + if (chip->asic_code) { + retval = rtsx_read_phy_register(chip, 0x08, &val); + if (retval != STATUS_SUCCESS) { + vfree(buf); + TRACE_RET(chip, TRANSPORT_ERROR); + } + + retval = rtsx_write_register(chip, PWR_GATE_CTRL, + LDO3318_PWR_MASK, LDO_OFF); + if (retval != STATUS_SUCCESS) { + vfree(buf); + TRACE_RET(chip, TRANSPORT_ERROR); + } + + wait_timeout(600); + + retval = rtsx_write_phy_register(chip, 0x08, + 0x4C00 | chip->phy_voltage); + if (retval != STATUS_SUCCESS) { + vfree(buf); + TRACE_RET(chip, TRANSPORT_ERROR); + } + + retval = rtsx_write_register(chip, PWR_GATE_CTRL, + LDO3318_PWR_MASK, LDO_ON); + if (retval != STATUS_SUCCESS) { + vfree(buf); + TRACE_RET(chip, TRANSPORT_ERROR); + } + + wait_timeout(600); + } + + retval = card_power_on(chip, SPI_CARD); + if (retval != STATUS_SUCCESS) { + vfree(buf); + TRACE_RET(chip, TRANSPORT_ERROR); + } + + wait_timeout(50); + + for (i = 0; i < len; i++) { + retval = rtsx_write_efuse(chip, addr + i, buf[i]); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_WRITE_ERR); + result = TRANSPORT_FAILED; + TRACE_GOTO(chip, Exit); + } + } + +Exit: + vfree(buf); + + retval = card_power_off(chip, SPI_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_ERROR); + + if (chip->asic_code) { + retval = rtsx_write_register(chip, PWR_GATE_CTRL, + LDO3318_PWR_MASK, LDO_OFF); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_ERROR); + + wait_timeout(600); + + retval = rtsx_write_phy_register(chip, 0x08, val); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_write_register(chip, PWR_GATE_CTRL, + LDO3318_PWR_MASK, LDO_ON); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_ERROR); + } + + return result; +} + +static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u8 func, func_max; + u16 addr, len; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + func = srb->cmnd[3]; + addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; + len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7]; + + RTSX_DEBUGP("%s: func = %d, addr = 0x%x, len = %d\n", __func__, func, + addr, len); + + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) + func_max = 1; + else + func_max = 0; + + if (func > func_max) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = rtsx_read_cfg_seq(chip, func, addr, buf, len); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + vfree(buf); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + len = (u16)min_t(unsigned int, scsi_bufflen(srb), len); + rtsx_stor_set_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u8 func, func_max; + u16 addr, len; + u8 *buf; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + func = srb->cmnd[3]; + addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; + len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7]; + + RTSX_DEBUGP("%s: func = %d, addr = 0x%x\n", __func__, func, addr); + + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) + func_max = 1; + else + func_max = 0; + + if (func > func_max) { + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); + buf = vmalloc(len); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - len); + + retval = rtsx_write_cfg_seq(chip, func, addr, buf, len); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); + vfree(buf); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + vfree(buf); + + return TRANSPORT_GOOD; +} + +static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int result; + + switch (srb->cmnd[2]) { + case PP_READ10: + case PP_WRITE10: + result = read_write(srb, chip); + break; + + case READ_HOST_REG: + result = read_host_reg(srb, chip); + break; + + case WRITE_HOST_REG: + result = write_host_reg(srb, chip); + break; + + case GET_VAR: + result = get_variable(srb, chip); + break; + + case SET_VAR: + result = set_variable(srb, chip); + break; + + case DMA_READ: + case DMA_WRITE: + result = dma_access_ring_buffer(srb, chip); + break; + + case READ_PHY: + result = read_phy_register(srb, chip); + break; + + case WRITE_PHY: + result = write_phy_register(srb, chip); + break; + + case ERASE_EEPROM2: + result = erase_eeprom2(srb, chip); + break; + + case READ_EEPROM2: + result = read_eeprom2(srb, chip); + break; + + case WRITE_EEPROM2: + result = write_eeprom2(srb, chip); + break; + + case READ_EFUSE: + result = read_efuse(srb, chip); + break; + + case WRITE_EFUSE: + result = write_efuse(srb, chip); + break; + + case READ_CFG: + result = read_cfg_byte(srb, chip); + break; + + case WRITE_CFG: + result = write_cfg_byte(srb, chip); + break; + + case SET_CHIP_MODE: + result = set_chip_mode(srb, chip); + break; + + case SUIT_CMD: + result = suit_cmd(srb, chip); + break; + + case GET_DEV_STATUS: + result = get_dev_status(srb, chip); + break; + + default: + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return result; +} + + +static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + u8 rtsx_status[16]; + int buf_len; + unsigned int lun = SCSI_LUN(srb); + + rtsx_status[0] = (u8)(chip->vendor_id >> 8); + rtsx_status[1] = (u8)(chip->vendor_id); + + rtsx_status[2] = (u8)(chip->product_id >> 8); + rtsx_status[3] = (u8)(chip->product_id); + + rtsx_status[4] = (u8)lun; + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { + if (chip->lun2card[lun] == SD_CARD) + rtsx_status[5] = 2; + else + rtsx_status[5] = 3; + } else { + if (chip->card_exist) { + if (chip->card_exist & XD_CARD) + rtsx_status[5] = 4; + else if (chip->card_exist & SD_CARD) + rtsx_status[5] = 2; + else if (chip->card_exist & MS_CARD) + rtsx_status[5] = 3; + else + rtsx_status[5] = 7; + } else { + rtsx_status[5] = 7; + } + } + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + rtsx_status[6] = 2; + else + rtsx_status[6] = 1; + + rtsx_status[7] = (u8)(chip->product_id); + rtsx_status[8] = chip->ic_version; + + if (check_card_exist(chip, lun)) + rtsx_status[9] = 1; + else + rtsx_status[9] = 0; + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) + rtsx_status[10] = 0; + else + rtsx_status[10] = 1; + + if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { + if (chip->lun2card[lun] == SD_CARD) + rtsx_status[11] = SD_CARD; + else + rtsx_status[11] = MS_CARD; + } else { + rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD; + } + + if (check_card_ready(chip, lun)) + rtsx_status[12] = 1; + else + rtsx_status[12] = 0; + + if (get_lun_card(chip, lun) == XD_CARD) { + rtsx_status[13] = 0x40; + } else if (get_lun_card(chip, lun) == SD_CARD) { + struct sd_info *sd_card = &(chip->sd_card); + + rtsx_status[13] = 0x20; + if (CHK_SD(sd_card)) { + if (CHK_SD_HCXC(sd_card)) + rtsx_status[13] |= 0x04; + if (CHK_SD_HS(sd_card)) + rtsx_status[13] |= 0x02; + } else { + rtsx_status[13] |= 0x08; + if (CHK_MMC_52M(sd_card)) + rtsx_status[13] |= 0x02; + if (CHK_MMC_SECTOR_MODE(sd_card)) + rtsx_status[13] |= 0x04; + } + } else if (get_lun_card(chip, lun) == MS_CARD) { + struct ms_info *ms_card = &(chip->ms_card); + + if (CHK_MSPRO(ms_card)) { + rtsx_status[13] = 0x38; + if (CHK_HG8BIT(ms_card)) + rtsx_status[13] |= 0x04; +#ifdef SUPPORT_MSXC + if (CHK_MSXC(ms_card)) + rtsx_status[13] |= 0x01; +#endif + } else { + rtsx_status[13] = 0x30; + } + } else { + if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) { +#ifdef SUPPORT_SDIO + if (chip->sd_io && chip->sd_int) + rtsx_status[13] = 0x60; + else + rtsx_status[13] = 0x70; +#else + rtsx_status[13] = 0x70; +#endif + } else { + if (chip->lun2card[lun] == SD_CARD) + rtsx_status[13] = 0x20; + else + rtsx_status[13] = 0x30; + } + } + + rtsx_status[14] = 0x78; + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) + rtsx_status[15] = 0x83; + else + rtsx_status[15] = 0x82; + + buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rtsx_status)); + rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb); + scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); + + return TRANSPORT_GOOD; +} + +static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + u8 card, bus_width; + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + card = get_lun_card(chip, lun); + if ((card == SD_CARD) || (card == MS_CARD)) { + bus_width = chip->card_bus_width[lun]; + } else { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + scsi_set_resid(srb, 0); + rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb); + + return TRANSPORT_GOOD; +} + +static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int result; + unsigned int lun = SCSI_LUN(srb); + u8 gpio_dir; + + if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + rtsx_force_power_on(chip, SSC_PDCTL); + + rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir); + rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06); + + switch (srb->cmnd[2]) { + case SCSI_SPI_GETSTATUS: + result = spi_get_status(srb, chip); + break; + + case SCSI_SPI_SETPARAMETER: + result = spi_set_parameter(srb, chip); + break; + + case SCSI_SPI_READFALSHID: + result = spi_read_flash_id(srb, chip); + break; + + case SCSI_SPI_READFLASH: + result = spi_read_flash(srb, chip); + break; + + case SCSI_SPI_WRITEFLASH: + result = spi_write_flash(srb, chip); + break; + + case SCSI_SPI_WRITEFLASHSTATUS: + result = spi_write_flash_status(srb, chip); + break; + + case SCSI_SPI_ERASEFLASH: + result = spi_erase_flash(srb, chip); + break; + + default: + rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir); + + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir); + + if (result != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + return TRANSPORT_GOOD; +} + +static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int result; + + switch (srb->cmnd[1]) { + case READ_STATUS: + result = read_status(srb, chip); + break; + + case READ_MEM: + result = read_mem(srb, chip); + break; + + case WRITE_MEM: + result = write_mem(srb, chip); + break; + + case READ_EEPROM: + result = read_eeprom(srb, chip); + break; + + case WRITE_EEPROM: + result = write_eeprom(srb, chip); + break; + + case TOGGLE_GPIO: + result = toggle_gpio_cmd(srb, chip); + break; + + case GET_SD_CSD: + result = get_sd_csd(srb, chip); + break; + + case GET_BUS_WIDTH: + result = get_card_bus_width(srb, chip); + break; + +#ifdef _MSG_TRACE + case TRACE_MSG: + result = trace_msg_cmd(srb, chip); + break; +#endif + + case SCSI_APP_CMD: + result = app_cmd(srb, chip); + break; + + case SPI_VENDOR_COMMAND: + result = spi_vendor_cmd(srb, chip); + break; + + default: + set_sense_type(chip, SCSI_LUN(srb), + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return result; +} + +#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK) +void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + u16 sec_cnt; + + if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) + sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; + else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) + sec_cnt = srb->cmnd[4]; + else + return; + + if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) { + toggle_gpio(chip, LED_GPIO); + chip->rw_cap[lun] = 0; + } else { + chip->rw_cap[lun] += sec_cnt; + } +} +#endif + +static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + unsigned int lun = SCSI_LUN(srb); + int retval, quick_format; + + if (get_lun_card(chip, lun) != MS_CARD) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) || + (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) || + (srb->cmnd[7] != 0x74)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + + if (!check_card_ready(chip, lun) || + (get_card_size(chip, lun) == 0)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + if (srb->cmnd[8] & 0x01) + quick_format = 0; + else + quick_format = 1; + + if (!(chip->card_ready & MS_CARD)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (chip->card_wp & MS_CARD) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (!CHK_MSPRO(ms_card)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; +} + +#ifdef SUPPORT_PCGL_1P18 +static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + unsigned int lun = SCSI_LUN(srb); + u8 dev_info_id, data_len; + u8 *buf; + unsigned int buf_len; + int i; + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + if ((get_lun_card(chip, lun) != MS_CARD)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) || + (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) || + (srb->cmnd[7] != 0x44)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + dev_info_id = srb->cmnd[3]; + if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) || + (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) || + !CHK_MSPRO(ms_card)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (dev_info_id == 0x15) + buf_len = data_len = 0x3A; + else + buf_len = data_len = 0x6A; + + buf = kmalloc(buf_len, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, TRANSPORT_ERROR); + + i = 0; + /* GET Memory Stick Media Information Response Header */ + buf[i++] = 0x00; /* Data length MSB */ + buf[i++] = data_len; /* Data length LSB */ + /* Device Information Type Code */ + if (CHK_MSXC(ms_card)) + buf[i++] = 0x03; + else + buf[i++] = 0x02; + + /* SGM bit */ + buf[i++] = 0x01; + /* Reserved */ + buf[i++] = 0x00; + buf[i++] = 0x00; + buf[i++] = 0x00; + /* Number of Device Information */ + buf[i++] = 0x01; + + /* Device Information Body */ + + /* Device Information ID Number */ + buf[i++] = dev_info_id; + /* Device Information Length */ + if (dev_info_id == 0x15) + data_len = 0x31; + else + data_len = 0x61; + + buf[i++] = 0x00; /* Data length MSB */ + buf[i++] = data_len; /* Data length LSB */ + /* Valid Bit */ + buf[i++] = 0x80; + if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) { + /* System Information */ + memcpy(buf+i, ms_card->raw_sys_info, 96); + } else { + /* Model Name */ + memcpy(buf+i, ms_card->raw_model_name, 48); + } + + rtsx_stor_set_xfer_buf(buf, buf_len, srb); + + if (dev_info_id == 0x15) + scsi_set_resid(srb, scsi_bufflen(srb)-0x3C); + else + scsi_set_resid(srb, scsi_bufflen(srb)-0x6C); + + kfree(buf); + return STATUS_SUCCESS; +} +#endif + +static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval = TRANSPORT_ERROR; + + if (srb->cmnd[2] == MS_FORMAT) + retval = ms_format_cmnd(srb, chip); +#ifdef SUPPORT_PCGL_1P18 + else if (srb->cmnd[2] == GET_MS_INFORMATION) + retval = get_ms_information(srb, chip); +#endif + + return retval; +} + +#ifdef SUPPORT_CPRM +static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + unsigned int lun = SCSI_LUN(srb); + int result; + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + sd_cleanup_work(chip); + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + if ((get_lun_card(chip, lun) != SD_CARD)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + switch (srb->cmnd[0]) { + case SD_PASS_THRU_MODE: + result = sd_pass_thru_mode(srb, chip); + break; + + case SD_EXECUTE_NO_DATA: + result = sd_execute_no_data(srb, chip); + break; + + case SD_EXECUTE_READ: + result = sd_execute_read_data(srb, chip); + break; + + case SD_EXECUTE_WRITE: + result = sd_execute_write_data(srb, chip); + break; + + case SD_GET_RSP: + result = sd_get_cmd_rsp(srb, chip); + break; + + case SD_HW_RST: + result = sd_hw_rst(srb, chip); + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + return result; +} +#endif + +#ifdef SUPPORT_MAGIC_GATE +static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + unsigned int lun = SCSI_LUN(srb); + int retval; + u8 key_format; + + RTSX_DEBUGP("--%s--\n", __func__); + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + ms_cleanup_work(chip); + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + if ((get_lun_card(chip, lun) != MS_CARD)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (srb->cmnd[7] != KC_MG_R_PRO) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (!CHK_MSPRO(ms_card)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + key_format = srb->cmnd[10] & 0x3F; + RTSX_DEBUGP("key_format = 0x%x\n", key_format); + + switch (key_format) { + case KF_GET_LOC_EKB: + if ((scsi_bufflen(srb) == 0x41C) && + (srb->cmnd[8] == 0x04) && + (srb->cmnd[9] == 0x1C)) { + retval = mg_get_local_EKB(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + case KF_RSP_CHG: + if ((scsi_bufflen(srb) == 0x24) && + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x24)) { + retval = mg_get_rsp_chg(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + case KF_GET_ICV: + ms_card->mg_entry_num = srb->cmnd[5]; + if ((scsi_bufflen(srb) == 0x404) && + (srb->cmnd[8] == 0x04) && + (srb->cmnd[9] == 0x04) && + (srb->cmnd[2] == 0x00) && + (srb->cmnd[3] == 0x00) && + (srb->cmnd[4] == 0x00) && + (srb->cmnd[5] < 32)) { + retval = mg_get_ICV(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; +} + +static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct ms_info *ms_card = &(chip->ms_card); + unsigned int lun = SCSI_LUN(srb); + int retval; + u8 key_format; + + RTSX_DEBUGP("--%s--\n", __func__); + + rtsx_disable_aspm(chip); + + if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { + rtsx_exit_ss(chip); + wait_timeout(100); + } + rtsx_set_stat(chip, RTSX_STAT_RUN); + + ms_cleanup_work(chip); + + if (!check_card_ready(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + if (check_card_wp(chip, lun)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + if ((get_lun_card(chip, lun) != MS_CARD)) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (srb->cmnd[7] != KC_MG_R_PRO) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (!CHK_MSPRO(ms_card)) { + set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + key_format = srb->cmnd[10] & 0x3F; + RTSX_DEBUGP("key_format = 0x%x\n", key_format); + + switch (key_format) { + case KF_SET_LEAF_ID: + if ((scsi_bufflen(srb) == 0x0C) && + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x0C)) { + retval = mg_set_leaf_id(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + case KF_CHG_HOST: + if ((scsi_bufflen(srb) == 0x0C) && + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x0C)) { + retval = mg_chg(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + case KF_RSP_HOST: + if ((scsi_bufflen(srb) == 0x0C) && + (srb->cmnd[8] == 0x00) && + (srb->cmnd[9] == 0x0C)) { + retval = mg_rsp(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + case KF_SET_ICV: + ms_card->mg_entry_num = srb->cmnd[5]; + if ((scsi_bufflen(srb) == 0x404) && + (srb->cmnd[8] == 0x04) && + (srb->cmnd[9] == 0x04) && + (srb->cmnd[2] == 0x00) && + (srb->cmnd[3] == 0x00) && + (srb->cmnd[4] == 0x00) && + (srb->cmnd[5] < 32)) { + retval = mg_set_ICV(srb, chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; +} +#endif + +int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ +#ifdef SUPPORT_SD_LOCK + struct sd_info *sd_card = &(chip->sd_card); +#endif + struct ms_info *ms_card = &(chip->ms_card); + unsigned int lun = SCSI_LUN(srb); + int result; + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_erase_status) { + /* Block all SCSI command except for + * REQUEST_SENSE and rs_ppstatus + */ + if (!((srb->cmnd[0] == VENDOR_CMND) && + (srb->cmnd[1] == SCSI_APP_CMD) && + (srb->cmnd[2] == GET_DEV_STATUS)) && + (srb->cmnd[0] != REQUEST_SENSE)) { + /* Logical Unit Not Ready Format in Progress */ + set_sense_data(chip, lun, CUR_ERR, + 0x02, 0, 0x04, 0x04, 0, 0); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } +#endif + + if ((get_lun_card(chip, lun) == MS_CARD) && + (ms_card->format_status == FORMAT_IN_PROGRESS)) { + if ((srb->cmnd[0] != REQUEST_SENSE) && + (srb->cmnd[0] != INQUIRY)) { + /* Logical Unit Not Ready Format in Progress */ + set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, + 0, (u16)(ms_card->progress)); + TRACE_RET(chip, TRANSPORT_FAILED); + } + } + + switch (srb->cmnd[0]) { + case READ_10: + case WRITE_10: + case READ_6: + case WRITE_6: + result = read_write(srb, chip); +#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK) + led_shine(srb, chip); +#endif + break; + + case TEST_UNIT_READY: + result = test_unit_ready(srb, chip); + break; + + case INQUIRY: + result = inquiry(srb, chip); + break; + + case READ_CAPACITY: + result = read_capacity(srb, chip); + break; + + case START_STOP: + result = start_stop_unit(srb, chip); + break; + + case ALLOW_MEDIUM_REMOVAL: + result = allow_medium_removal(srb, chip); + break; + + case REQUEST_SENSE: + result = request_sense(srb, chip); + break; + + case MODE_SENSE: + case MODE_SENSE_10: + result = mode_sense(srb, chip); + break; + + case 0x23: + result = read_format_capacity(srb, chip); + break; + + case VENDOR_CMND: + result = vendor_cmnd(srb, chip); + break; + + case MS_SP_CMND: + result = ms_sp_cmnd(srb, chip); + break; + +#ifdef SUPPORT_CPRM + case SD_PASS_THRU_MODE: + case SD_EXECUTE_NO_DATA: + case SD_EXECUTE_READ: + case SD_EXECUTE_WRITE: + case SD_GET_RSP: + case SD_HW_RST: + result = sd_extention_cmnd(srb, chip); + break; +#endif + +#ifdef SUPPORT_MAGIC_GATE + case CMD_MSPRO_MG_RKEY: + result = mg_report_key(srb, chip); + break; + + case CMD_MSPRO_MG_SKEY: + result = mg_send_key(srb, chip); + break; +#endif + + case FORMAT_UNIT: + case MODE_SELECT: + case VERIFY: + result = TRANSPORT_GOOD; + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + result = TRANSPORT_FAILED; + } + + return result; +} diff --git a/drivers/staging/rts5208/rtsx_scsi.h b/drivers/staging/rts5208/rtsx_scsi.h new file mode 100644 index 000000000000..d1750570dd38 --- /dev/null +++ b/drivers/staging/rts5208/rtsx_scsi.h @@ -0,0 +1,143 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_SCSI_H +#define __REALTEK_RTSX_SCSI_H + +#include "rtsx.h" +#include "rtsx_chip.h" + +#define MS_SP_CMND 0xFA +#define MS_FORMAT 0xA0 +#define GET_MS_INFORMATION 0xB0 + +#define VENDOR_CMND 0xF0 + +#define READ_STATUS 0x09 + +#define READ_EEPROM 0x04 +#define WRITE_EEPROM 0x05 +#define READ_MEM 0x0D +#define WRITE_MEM 0x0E +#define GET_BUS_WIDTH 0x13 +#define GET_SD_CSD 0x14 +#define TOGGLE_GPIO 0x15 +#define TRACE_MSG 0x18 + +#define SCSI_APP_CMD 0x10 + +#define PP_READ10 0x1A +#define PP_WRITE10 0x0A +#define READ_HOST_REG 0x1D +#define WRITE_HOST_REG 0x0D +#define SET_VAR 0x05 +#define GET_VAR 0x15 +#define DMA_READ 0x16 +#define DMA_WRITE 0x06 +#define GET_DEV_STATUS 0x10 +#define SET_CHIP_MODE 0x27 +#define SUIT_CMD 0xE0 +#define WRITE_PHY 0x07 +#define READ_PHY 0x17 +#define WRITE_EEPROM2 0x03 +#define READ_EEPROM2 0x13 +#define ERASE_EEPROM2 0x23 +#define WRITE_EFUSE 0x04 +#define READ_EFUSE 0x14 +#define WRITE_CFG 0x0E +#define READ_CFG 0x1E + +#define SPI_VENDOR_COMMAND 0x1C + +#define SCSI_SPI_GETSTATUS 0x00 +#define SCSI_SPI_SETPARAMETER 0x01 +#define SCSI_SPI_READFALSHID 0x02 +#define SCSI_SPI_READFLASH 0x03 +#define SCSI_SPI_WRITEFLASH 0x04 +#define SCSI_SPI_WRITEFLASHSTATUS 0x05 +#define SCSI_SPI_ERASEFLASH 0x06 + +#define INIT_BATCHCMD 0x41 +#define ADD_BATCHCMD 0x42 +#define SEND_BATCHCMD 0x43 +#define GET_BATCHRSP 0x44 + +#define CHIP_NORMALMODE 0x00 +#define CHIP_DEBUGMODE 0x01 + +/* SD Pass Through Command Extension */ +#define SD_PASS_THRU_MODE 0xD0 +#define SD_EXECUTE_NO_DATA 0xD1 +#define SD_EXECUTE_READ 0xD2 +#define SD_EXECUTE_WRITE 0xD3 +#define SD_GET_RSP 0xD4 +#define SD_HW_RST 0xD6 + +#ifdef SUPPORT_MAGIC_GATE +#define CMD_MSPRO_MG_RKEY 0xA4 /* Report Key Command */ +#define CMD_MSPRO_MG_SKEY 0xA3 /* Send Key Command */ + +/* CBWCB field: key class */ +#define KC_MG_R_PRO 0xBE /* MG-R PRO*/ + +/* CBWCB field: key format */ +#define KF_SET_LEAF_ID 0x31 /* Set Leaf ID */ +#define KF_GET_LOC_EKB 0x32 /* Get Local EKB */ +#define KF_CHG_HOST 0x33 /* Challenge (host) */ +#define KF_RSP_CHG 0x34 /* Response and Challenge (device) */ +#define KF_RSP_HOST 0x35 /* Response (host) */ +#define KF_GET_ICV 0x36 /* Get ICV */ +#define KF_SET_ICV 0x37 /* SSet ICV */ +#endif + +/* Sense type */ +#define SENSE_TYPE_NO_SENSE 0 +#define SENSE_TYPE_MEDIA_CHANGE 1 +#define SENSE_TYPE_MEDIA_NOT_PRESENT 2 +#define SENSE_TYPE_MEDIA_LBA_OVER_RANGE 3 +#define SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT 4 +#define SENSE_TYPE_MEDIA_WRITE_PROTECT 5 +#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6 +#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7 +#define SENSE_TYPE_MEDIA_WRITE_ERR 8 +#define SENSE_TYPE_FORMAT_IN_PROGRESS 9 +#define SENSE_TYPE_FORMAT_CMD_FAILED 10 +#ifdef SUPPORT_MAGIC_GATE +#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB 0x0b +#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN 0x0c +#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM 0x0d +#define SENSE_TYPE_MG_WRITE_ERR 0x0e +#endif +#ifdef SUPPORT_SD_LOCK +/* FOR Locked SD card*/ +#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10 +#endif + +void scsi_show_command(struct scsi_cmnd *srb); +void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type); +void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, + u8 sense_key, u32 info, u8 asc, u8 ascq, + u8 sns_key_info0, u16 sns_key_info1); +int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip); + +#endif /* __REALTEK_RTSX_SCSI_H */ diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h new file mode 100644 index 000000000000..0b6b4d4f1fea --- /dev/null +++ b/drivers/staging/rts5208/rtsx_sys.h @@ -0,0 +1,50 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __RTSX_SYS_H +#define __RTSX_SYS_H + +#include "rtsx.h" +#include "rtsx_chip.h" +#include "rtsx_card.h" + +typedef dma_addr_t ULONG_PTR; + +static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip) +{ + struct rtsx_dev *dev = chip->rtsx; + + spin_lock(&(dev->reg_lock)); + rtsx_enter_ss(chip); + spin_unlock(&(dev->reg_lock)); +} + +static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag) +{ + rtsx_reset_cards(chip); +} + +#define RTSX_MSG_IN_INT(x) + +#endif /* __RTSX_SYS_H */ + diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c new file mode 100644 index 000000000000..97b7b012983e --- /dev/null +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -0,0 +1,769 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_scsi.h" +#include "rtsx_transport.h" +#include "rtsx_chip.h" +#include "rtsx_card.h" +#include "debug.h" + +/*********************************************************************** + * Scatter-gather transfer buffer access routines + ***********************************************************************/ + +/* Copy a buffer of length buflen to/from the srb's transfer buffer. + * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer + * points to a list of s-g entries and we ignore srb->request_bufflen. + * For non-scatter-gather transfers, srb->request_buffer points to the + * transfer buffer itself and srb->request_bufflen is the buffer's length.) + * Update the *index and *offset variables so that the next copy will + * pick up from where this one left off. */ + +unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer, + unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, + unsigned int *offset, enum xfer_buf_dir dir) +{ + unsigned int cnt; + + /* If not using scatter-gather, just transfer the data directly. + * Make certain it will fit in the available buffer space. */ + if (scsi_sg_count(srb) == 0) { + if (*offset >= scsi_bufflen(srb)) + return 0; + cnt = min(buflen, scsi_bufflen(srb) - *offset); + if (dir == TO_XFER_BUF) + memcpy((unsigned char *) scsi_sglist(srb) + *offset, + buffer, cnt); + else + memcpy(buffer, (unsigned char *) scsi_sglist(srb) + + *offset, cnt); + *offset += cnt; + + /* Using scatter-gather. We have to go through the list one entry + * at a time. Each s-g entry contains some number of pages, and + * each page has to be kmap()'ed separately. If the page is already + * in kernel-addressable memory then kmap() will return its address. + * If the page is not directly accessible -- such as a user buffer + * located in high memory -- then kmap() will map it to a temporary + * position in the kernel's virtual address space. */ + } else { + struct scatterlist *sg = + (struct scatterlist *) scsi_sglist(srb) + + *index; + + /* This loop handles a single s-g list entry, which may + * include multiple pages. Find the initial page structure + * and the starting offset within the page, and update + * the *offset and *index values for the next loop. */ + cnt = 0; + while (cnt < buflen && *index < scsi_sg_count(srb)) { + struct page *page = sg_page(sg) + + ((sg->offset + *offset) >> PAGE_SHIFT); + unsigned int poff = + (sg->offset + *offset) & (PAGE_SIZE-1); + unsigned int sglen = sg->length - *offset; + + if (sglen > buflen - cnt) { + + /* Transfer ends within this s-g entry */ + sglen = buflen - cnt; + *offset += sglen; + } else { + + /* Transfer continues to next s-g entry */ + *offset = 0; + ++*index; + ++sg; + } + + /* Transfer the data for all the pages in this + * s-g entry. For each page: call kmap(), do the + * transfer, and call kunmap() immediately after. */ + while (sglen > 0) { + unsigned int plen = min(sglen, (unsigned int) + PAGE_SIZE - poff); + unsigned char *ptr = kmap(page); + + if (dir == TO_XFER_BUF) + memcpy(ptr + poff, buffer + cnt, plen); + else + memcpy(buffer + cnt, ptr + poff, plen); + kunmap(page); + + /* Start at the beginning of the next page */ + poff = 0; + ++page; + cnt += plen; + sglen -= plen; + } + } + } + + /* Return the amount actually transferred */ + return cnt; +} + +/* Store the contents of buffer into srb's transfer buffer and set the +* SCSI residue. */ +void rtsx_stor_set_xfer_buf(unsigned char *buffer, + unsigned int buflen, struct scsi_cmnd *srb) +{ + unsigned int index = 0, offset = 0; + + rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, + TO_XFER_BUF); + if (buflen < scsi_bufflen(srb)) + scsi_set_resid(srb, scsi_bufflen(srb) - buflen); +} + +void rtsx_stor_get_xfer_buf(unsigned char *buffer, + unsigned int buflen, struct scsi_cmnd *srb) +{ + unsigned int index = 0, offset = 0; + + rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, + FROM_XFER_BUF); + if (buflen < scsi_bufflen(srb)) + scsi_set_resid(srb, scsi_bufflen(srb) - buflen); +} + + +/*********************************************************************** + * Transport routines + ***********************************************************************/ + +/* Invoke the transport and basic error-handling/recovery methods + * + * This is used to send the message to the device and receive the response. + */ +void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int result; + + result = rtsx_scsi_handler(srb, chip); + + /* if the command gets aborted by the higher layers, we need to + * short-circuit all other processing + */ + if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { + RTSX_DEBUGP("-- command was aborted\n"); + srb->result = DID_ABORT << 16; + goto Handle_Errors; + } + + /* if there is a transport error, reset and don't auto-sense */ + if (result == TRANSPORT_ERROR) { + RTSX_DEBUGP("-- transport indicates error, resetting\n"); + srb->result = DID_ERROR << 16; + goto Handle_Errors; + } + + srb->result = SAM_STAT_GOOD; + + /* + * If we have a failure, we're going to do a REQUEST_SENSE + * automatically. Note that we differentiate between a command + * "failure" and an "error" in the transport mechanism. + */ + if (result == TRANSPORT_FAILED) { + /* set the result so the higher layers expect this data */ + srb->result = SAM_STAT_CHECK_CONDITION; + memcpy(srb->sense_buffer, + (unsigned char *)&(chip->sense_buffer[SCSI_LUN(srb)]), + sizeof(struct sense_data_t)); + } + + return; + + /* Error and abort processing: try to resynchronize with the device + * by issuing a port reset. If that fails, try a class-specific + * device reset. */ +Handle_Errors: + return; +} + +void rtsx_add_cmd(struct rtsx_chip *chip, + u8 cmd_type, u16 reg_addr, u8 mask, u8 data) +{ + u32 *cb = (u32 *)(chip->host_cmds_ptr); + u32 val = 0; + + val |= (u32)(cmd_type & 0x03) << 30; + val |= (u32)(reg_addr & 0x3FFF) << 16; + val |= (u32)mask << 8; + val |= (u32)data; + + spin_lock_irq(&chip->rtsx->reg_lock); + if (chip->ci < (HOST_CMDS_BUF_LEN / 4)) + cb[(chip->ci)++] = cpu_to_le32(val); + + spin_unlock_irq(&chip->rtsx->reg_lock); +} + +void rtsx_send_cmd_no_wait(struct rtsx_chip *chip) +{ + u32 val = 1 << 31; + + rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr); + + val |= (u32)(chip->ci * 4) & 0x00FFFFFF; + /* Hardware Auto Response */ + val |= 0x40000000; + rtsx_writel(chip, RTSX_HCBCTLR, val); +} + +int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout) +{ + struct rtsx_dev *rtsx = chip->rtsx; + struct completion trans_done; + u32 val = 1 << 31; + long timeleft; + int err = 0; + + if (card == SD_CARD) + rtsx->check_card_cd = SD_EXIST; + else if (card == MS_CARD) + rtsx->check_card_cd = MS_EXIST; + else if (card == XD_CARD) + rtsx->check_card_cd = XD_EXIST; + else + rtsx->check_card_cd = 0; + + spin_lock_irq(&rtsx->reg_lock); + + /* set up data structures for the wakeup system */ + rtsx->done = &trans_done; + rtsx->trans_result = TRANS_NOT_READY; + init_completion(&trans_done); + rtsx->trans_state = STATE_TRANS_CMD; + + rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr); + + val |= (u32)(chip->ci * 4) & 0x00FFFFFF; + /* Hardware Auto Response */ + val |= 0x40000000; + rtsx_writel(chip, RTSX_HCBCTLR, val); + + spin_unlock_irq(&rtsx->reg_lock); + + /* Wait for TRANS_OK_INT */ + timeleft = wait_for_completion_interruptible_timeout( + &trans_done, timeout * HZ / 1000); + if (timeleft <= 0) { + RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg); + err = -ETIMEDOUT; + TRACE_GOTO(chip, finish_send_cmd); + } + + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_RESULT_FAIL) + err = -EIO; + else if (rtsx->trans_result == TRANS_RESULT_OK) + err = 0; + + spin_unlock_irq(&rtsx->reg_lock); + +finish_send_cmd: + rtsx->done = NULL; + rtsx->trans_state = STATE_TRANS_NONE; + + if (err < 0) + rtsx_stop_cmd(chip, card); + + return err; +} + +static inline void rtsx_add_sg_tbl( + struct rtsx_chip *chip, u32 addr, u32 len, u8 option) +{ + u64 *sgb = (u64 *)(chip->host_sg_tbl_ptr); + u64 val = 0; + u32 temp_len = 0; + u8 temp_opt = 0; + + do { + if (len > 0x80000) { + temp_len = 0x80000; + temp_opt = option & (~SG_END); + } else { + temp_len = len; + temp_opt = option; + } + val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt; + + if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8)) + sgb[(chip->sgi)++] = cpu_to_le64(val); + + len -= temp_len; + addr += temp_len; + } while (len); +} + +static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, + struct scatterlist *sg, int num_sg, unsigned int *index, + unsigned int *offset, int size, + enum dma_data_direction dma_dir, int timeout) +{ + struct rtsx_dev *rtsx = chip->rtsx; + struct completion trans_done; + u8 dir; + int sg_cnt, i, resid; + int err = 0; + long timeleft; + struct scatterlist *sg_ptr; + u32 val = TRIG_DMA; + + if ((sg == NULL) || (num_sg <= 0) || !offset || !index) + return -EIO; + + if (dma_dir == DMA_TO_DEVICE) + dir = HOST_TO_DEVICE; + else if (dma_dir == DMA_FROM_DEVICE) + dir = DEVICE_TO_HOST; + else + return -ENXIO; + + if (card == SD_CARD) + rtsx->check_card_cd = SD_EXIST; + else if (card == MS_CARD) + rtsx->check_card_cd = MS_EXIST; + else if (card == XD_CARD) + rtsx->check_card_cd = XD_EXIST; + else + rtsx->check_card_cd = 0; + + spin_lock_irq(&rtsx->reg_lock); + + /* set up data structures for the wakeup system */ + rtsx->done = &trans_done; + + rtsx->trans_state = STATE_TRANS_SG; + rtsx->trans_result = TRANS_NOT_READY; + + spin_unlock_irq(&rtsx->reg_lock); + + sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir); + + resid = size; + sg_ptr = sg; + chip->sgi = 0; + /* Usually the next entry will be @sg@ + 1, but if this sg element + * is part of a chained scatterlist, it could jump to the start of + * a new scatterlist array. So here we use sg_next to move to + * the proper sg + */ + for (i = 0; i < *index; i++) + sg_ptr = sg_next(sg_ptr); + for (i = *index; i < sg_cnt; i++) { + dma_addr_t addr; + unsigned int len; + u8 option; + + addr = sg_dma_address(sg_ptr); + len = sg_dma_len(sg_ptr); + + RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n", + (unsigned int)addr, len); + RTSX_DEBUGP("*index = %d, *offset = %d\n", *index, *offset); + + addr += *offset; + + if ((len - *offset) > resid) { + *offset += resid; + len = resid; + resid = 0; + } else { + resid -= (len - *offset); + len -= *offset; + *offset = 0; + *index = *index + 1; + } + if ((i == (sg_cnt - 1)) || !resid) + option = SG_VALID | SG_END | SG_TRANS_DATA; + else + option = SG_VALID | SG_TRANS_DATA; + + rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); + + if (!resid) + break; + + sg_ptr = sg_next(sg_ptr); + } + + RTSX_DEBUGP("SG table count = %d\n", chip->sgi); + + val |= (u32)(dir & 0x01) << 29; + val |= ADMA_MODE; + + spin_lock_irq(&rtsx->reg_lock); + + init_completion(&trans_done); + + rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr); + rtsx_writel(chip, RTSX_HDBCTLR, val); + + spin_unlock_irq(&rtsx->reg_lock); + + timeleft = wait_for_completion_interruptible_timeout( + &trans_done, timeout * HZ / 1000); + if (timeleft <= 0) { + RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__); + RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg); + err = -ETIMEDOUT; + goto out; + } + + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_RESULT_FAIL) { + err = -EIO; + spin_unlock_irq(&rtsx->reg_lock); + goto out; + } + spin_unlock_irq(&rtsx->reg_lock); + + /* Wait for TRANS_OK_INT */ + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_NOT_READY) { + init_completion(&trans_done); + spin_unlock_irq(&rtsx->reg_lock); + timeleft = wait_for_completion_interruptible_timeout( + &trans_done, timeout * HZ / 1000); + if (timeleft <= 0) { + RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__); + RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg); + err = -ETIMEDOUT; + goto out; + } + } else { + spin_unlock_irq(&rtsx->reg_lock); + } + + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_RESULT_FAIL) + err = -EIO; + else if (rtsx->trans_result == TRANS_RESULT_OK) + err = 0; + + spin_unlock_irq(&rtsx->reg_lock); + +out: + rtsx->done = NULL; + rtsx->trans_state = STATE_TRANS_NONE; + dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir); + + if (err < 0) + rtsx_stop_cmd(chip, card); + + return err; +} + +static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, + struct scatterlist *sg, int num_sg, + enum dma_data_direction dma_dir, int timeout) +{ + struct rtsx_dev *rtsx = chip->rtsx; + struct completion trans_done; + u8 dir; + int buf_cnt, i; + int err = 0; + long timeleft; + struct scatterlist *sg_ptr; + + if ((sg == NULL) || (num_sg <= 0)) + return -EIO; + + if (dma_dir == DMA_TO_DEVICE) + dir = HOST_TO_DEVICE; + else if (dma_dir == DMA_FROM_DEVICE) + dir = DEVICE_TO_HOST; + else + return -ENXIO; + + if (card == SD_CARD) + rtsx->check_card_cd = SD_EXIST; + else if (card == MS_CARD) + rtsx->check_card_cd = MS_EXIST; + else if (card == XD_CARD) + rtsx->check_card_cd = XD_EXIST; + else + rtsx->check_card_cd = 0; + + spin_lock_irq(&rtsx->reg_lock); + + /* set up data structures for the wakeup system */ + rtsx->done = &trans_done; + + rtsx->trans_state = STATE_TRANS_SG; + rtsx->trans_result = TRANS_NOT_READY; + + spin_unlock_irq(&rtsx->reg_lock); + + buf_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir); + + sg_ptr = sg; + + for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) { + u32 val = TRIG_DMA; + int sg_cnt, j; + + if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8)) + sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8); + else + sg_cnt = (HOST_SG_TBL_BUF_LEN / 8); + + chip->sgi = 0; + for (j = 0; j < sg_cnt; j++) { + dma_addr_t addr = sg_dma_address(sg_ptr); + unsigned int len = sg_dma_len(sg_ptr); + u8 option; + + RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n", + (unsigned int)addr, len); + + if (j == (sg_cnt - 1)) + option = SG_VALID | SG_END | SG_TRANS_DATA; + else + option = SG_VALID | SG_TRANS_DATA; + + rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); + + sg_ptr = sg_next(sg_ptr); + } + + RTSX_DEBUGP("SG table count = %d\n", chip->sgi); + + val |= (u32)(dir & 0x01) << 29; + val |= ADMA_MODE; + + spin_lock_irq(&rtsx->reg_lock); + + init_completion(&trans_done); + + rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr); + rtsx_writel(chip, RTSX_HDBCTLR, val); + + spin_unlock_irq(&rtsx->reg_lock); + + timeleft = wait_for_completion_interruptible_timeout( + &trans_done, timeout * HZ / 1000); + if (timeleft <= 0) { + RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__); + RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg); + err = -ETIMEDOUT; + goto out; + } + + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_RESULT_FAIL) { + err = -EIO; + spin_unlock_irq(&rtsx->reg_lock); + goto out; + } + spin_unlock_irq(&rtsx->reg_lock); + + sg_ptr += sg_cnt; + } + + /* Wait for TRANS_OK_INT */ + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_NOT_READY) { + init_completion(&trans_done); + spin_unlock_irq(&rtsx->reg_lock); + timeleft = wait_for_completion_interruptible_timeout( + &trans_done, timeout * HZ / 1000); + if (timeleft <= 0) { + RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__); + RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg); + err = -ETIMEDOUT; + goto out; + } + } else { + spin_unlock_irq(&rtsx->reg_lock); + } + + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_RESULT_FAIL) + err = -EIO; + else if (rtsx->trans_result == TRANS_RESULT_OK) + err = 0; + + spin_unlock_irq(&rtsx->reg_lock); + +out: + rtsx->done = NULL; + rtsx->trans_state = STATE_TRANS_NONE; + dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir); + + if (err < 0) + rtsx_stop_cmd(chip, card); + + return err; +} + +static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, size_t len, + enum dma_data_direction dma_dir, int timeout) +{ + struct rtsx_dev *rtsx = chip->rtsx; + struct completion trans_done; + dma_addr_t addr; + u8 dir; + int err = 0; + u32 val = (1 << 31); + long timeleft; + + if ((buf == NULL) || (len <= 0)) + return -EIO; + + if (dma_dir == DMA_TO_DEVICE) + dir = HOST_TO_DEVICE; + else if (dma_dir == DMA_FROM_DEVICE) + dir = DEVICE_TO_HOST; + else + return -ENXIO; + + addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir); + if (!addr) + return -ENOMEM; + + if (card == SD_CARD) + rtsx->check_card_cd = SD_EXIST; + else if (card == MS_CARD) + rtsx->check_card_cd = MS_EXIST; + else if (card == XD_CARD) + rtsx->check_card_cd = XD_EXIST; + else + rtsx->check_card_cd = 0; + + val |= (u32)(dir & 0x01) << 29; + val |= (u32)(len & 0x00FFFFFF); + + spin_lock_irq(&rtsx->reg_lock); + + /* set up data structures for the wakeup system */ + rtsx->done = &trans_done; + + init_completion(&trans_done); + + rtsx->trans_state = STATE_TRANS_BUF; + rtsx->trans_result = TRANS_NOT_READY; + + rtsx_writel(chip, RTSX_HDBAR, addr); + rtsx_writel(chip, RTSX_HDBCTLR, val); + + spin_unlock_irq(&rtsx->reg_lock); + + /* Wait for TRANS_OK_INT */ + timeleft = wait_for_completion_interruptible_timeout( + &trans_done, timeout * HZ / 1000); + if (timeleft <= 0) { + RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__); + RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg); + err = -ETIMEDOUT; + goto out; + } + + spin_lock_irq(&rtsx->reg_lock); + if (rtsx->trans_result == TRANS_RESULT_FAIL) + err = -EIO; + else if (rtsx->trans_result == TRANS_RESULT_OK) + err = 0; + + spin_unlock_irq(&rtsx->reg_lock); + +out: + rtsx->done = NULL; + rtsx->trans_state = STATE_TRANS_NONE; + dma_unmap_single(&(rtsx->pci->dev), addr, len, dma_dir); + + if (err < 0) + rtsx_stop_cmd(chip, card); + + return err; +} + +int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, + void *buf, size_t len, int use_sg, unsigned int *index, + unsigned int *offset, enum dma_data_direction dma_dir, + int timeout) +{ + int err = 0; + + /* don't transfer data during abort processing */ + if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) + return -EIO; + + if (use_sg) { + err = rtsx_transfer_sglist_adma_partial(chip, card, + (struct scatterlist *)buf, use_sg, + index, offset, (int)len, dma_dir, timeout); + } else { + err = rtsx_transfer_buf(chip, card, + buf, len, dma_dir, timeout); + } + + if (err < 0) { + if (RTSX_TST_DELINK(chip)) { + RTSX_CLR_DELINK(chip); + chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; + rtsx_reinit_cards(chip, 1); + } + } + + return err; +} + +int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len, + int use_sg, enum dma_data_direction dma_dir, int timeout) +{ + int err = 0; + + RTSX_DEBUGP("use_sg = %d\n", use_sg); + + /* don't transfer data during abort processing */ + if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) + return -EIO; + + if (use_sg) { + err = rtsx_transfer_sglist_adma(chip, card, + (struct scatterlist *)buf, + use_sg, dma_dir, timeout); + } else { + err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout); + } + + if (err < 0) { + if (RTSX_TST_DELINK(chip)) { + RTSX_CLR_DELINK(chip); + chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; + rtsx_reinit_cards(chip, 1); + } + } + + return err; +} + diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h new file mode 100644 index 000000000000..b4b112372776 --- /dev/null +++ b/drivers/staging/rts5208/rtsx_transport.h @@ -0,0 +1,66 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_TRANSPORT_H +#define __REALTEK_RTSX_TRANSPORT_H + +#include "rtsx.h" +#include "rtsx_chip.h" + +#define WAIT_TIME 2000 + +unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer, + unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, + unsigned int *offset, enum xfer_buf_dir dir); +void rtsx_stor_set_xfer_buf(unsigned char *buffer, + unsigned int buflen, struct scsi_cmnd *srb); +void rtsx_stor_get_xfer_buf(unsigned char *buffer, + unsigned int buflen, struct scsi_cmnd *srb); +void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip); + + +#define rtsx_init_cmd(chip) ((chip)->ci = 0) + +void rtsx_add_cmd(struct rtsx_chip *chip, + u8 cmd_type, u16 reg_addr, u8 mask, u8 data); +void rtsx_send_cmd_no_wait(struct rtsx_chip *chip); +int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout); + +extern inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip) +{ +#ifdef CMD_USING_SG + return (u8 *)(chip->host_sg_tbl_ptr); +#else + return (u8 *)(chip->host_cmds_ptr); +#endif +} + +int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len, + int use_sg, enum dma_data_direction dma_dir, int timeout); + +int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, + void *buf, size_t len, + int use_sg, unsigned int *index, unsigned int *offset, + enum dma_data_direction dma_dir, int timeout); + +#endif /* __REALTEK_RTSX_TRANSPORT_H */ diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c new file mode 100644 index 000000000000..c7c1f5410430 --- /dev/null +++ b/drivers/staging/rts5208/sd.c @@ -0,0 +1,4525 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" +#include "sd.h" + +#define SD_MAX_RETRY_COUNT 3 + +static u16 REG_SD_CFG1; +static u16 REG_SD_CFG2; +static u16 REG_SD_CFG3; +static u16 REG_SD_STAT1; +static u16 REG_SD_STAT2; +static u16 REG_SD_BUS_STAT; +static u16 REG_SD_PAD_CTL; +static u16 REG_SD_SAMPLE_POINT_CTL; +static u16 REG_SD_PUSH_POINT_CTL; +static u16 REG_SD_CMD0; +static u16 REG_SD_CMD1; +static u16 REG_SD_CMD2; +static u16 REG_SD_CMD3; +static u16 REG_SD_CMD4; +static u16 REG_SD_CMD5; +static u16 REG_SD_BYTE_CNT_L; +static u16 REG_SD_BYTE_CNT_H; +static u16 REG_SD_BLOCK_CNT_L; +static u16 REG_SD_BLOCK_CNT_H; +static u16 REG_SD_TRANSFER; +static u16 REG_SD_VPCLK0_CTL; +static u16 REG_SD_VPCLK1_CTL; +static u16 REG_SD_DCMPS0_CTL; +static u16 REG_SD_DCMPS1_CTL; + +static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct sd_info *sd_card = &(chip->sd_card); + + sd_card->err_code |= err_code; +} + +static inline void sd_clr_err_code(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + + sd_card->err_code = 0; +} + +static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct sd_info *sd_card = &(chip->sd_card); + + return sd_card->err_code & err_code; +} + +static void sd_init_reg_addr(struct rtsx_chip *chip) +{ + REG_SD_CFG1 = 0xFD31; + REG_SD_CFG2 = 0xFD33; + REG_SD_CFG3 = 0xFD3E; + REG_SD_STAT1 = 0xFD30; + REG_SD_STAT2 = 0; + REG_SD_BUS_STAT = 0; + REG_SD_PAD_CTL = 0; + REG_SD_SAMPLE_POINT_CTL = 0; + REG_SD_PUSH_POINT_CTL = 0; + REG_SD_CMD0 = 0xFD34; + REG_SD_CMD1 = 0xFD35; + REG_SD_CMD2 = 0xFD36; + REG_SD_CMD3 = 0xFD37; + REG_SD_CMD4 = 0xFD38; + REG_SD_CMD5 = 0xFD5A; + REG_SD_BYTE_CNT_L = 0xFD39; + REG_SD_BYTE_CNT_H = 0xFD3A; + REG_SD_BLOCK_CNT_L = 0xFD3B; + REG_SD_BLOCK_CNT_H = 0xFD3C; + REG_SD_TRANSFER = 0xFD32; + REG_SD_VPCLK0_CTL = 0; + REG_SD_VPCLK1_CTL = 0; + REG_SD_DCMPS0_CTL = 0; + REG_SD_DCMPS1_CTL = 0; +} + +static int sd_check_data0_status(struct rtsx_chip *chip) +{ + u8 stat; + + RTSX_READ_REG(chip, REG_SD_STAT1, &stat); + + if (!(stat & SD_DAT0_STATUS)) { + sd_set_err_code(chip, SD_BUSY); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, + u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int timeout = 100; + u16 reg_addr; + u8 *ptr; + int stat_idx = 0; + int rty_cnt = 0; + + sd_clr_err_code(chip); + + RTSX_DEBUGP("SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg); + + if (rsp_type == SD_RSP_TYPE_R1b) + timeout = 3000; + +RTY_SEND_CMD: + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, + 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE); + + if (rsp_type == SD_RSP_TYPE_R2) { + for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + + stat_idx = 16; + } else if (rsp_type != SD_RSP_TYPE_R0) { + for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + + stat_idx = 5; + } + + rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0); + + retval = rtsx_send_cmd(chip, SD_CARD, timeout); + if (retval < 0) { + u8 val; + + rtsx_read_register(chip, REG_SD_STAT1, &val); + RTSX_DEBUGP("SD_STAT1: 0x%x\n", val); + + rtsx_read_register(chip, REG_SD_CFG3, &val); + RTSX_DEBUGP("SD_CFG3: 0x%x\n", val); + + if (retval == -ETIMEDOUT) { + if (rsp_type & SD_WAIT_BUSY_END) { + retval = sd_check_data0_status(chip); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + TRACE_RET(chip, retval); + } + } else { + sd_set_err_code(chip, SD_TO_ERR); + } + retval = STATUS_TIMEDOUT; + } else { + retval = STATUS_FAIL; + } + rtsx_clear_sd_error(chip); + + TRACE_RET(chip, retval); + } + + if (rsp_type == SD_RSP_TYPE_R0) + return STATUS_SUCCESS; + + ptr = rtsx_get_cmd_data(chip) + 1; + + if ((ptr[0] & 0xC0) != 0) { + sd_set_err_code(chip, SD_STS_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + if (!(rsp_type & SD_NO_CHECK_CRC7)) { + if (ptr[stat_idx] & SD_CRC7_ERR) { + if (cmd_idx == WRITE_MULTIPLE_BLOCK) { + sd_set_err_code(chip, SD_CRC_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + if (rty_cnt < SD_MAX_RETRY_COUNT) { + wait_timeout(20); + rty_cnt++; + goto RTY_SEND_CMD; + } else { + sd_set_err_code(chip, SD_CRC_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) { + if ((cmd_idx != SEND_RELATIVE_ADDR) && + (cmd_idx != SEND_IF_COND)) { + if (cmd_idx != STOP_TRANSMISSION) { + if (ptr[1] & 0x80) + TRACE_RET(chip, STATUS_FAIL); + } +#ifdef SUPPORT_SD_LOCK + if (ptr[1] & 0x7D) +#else + if (ptr[1] & 0x7F) +#endif + { + RTSX_DEBUGP("ptr[1]: 0x%02x\n", ptr[1]); + TRACE_RET(chip, STATUS_FAIL); + } + if (ptr[2] & 0xFF) { + RTSX_DEBUGP("ptr[2]: 0x%02x\n", ptr[2]); + TRACE_RET(chip, STATUS_FAIL); + } + if (ptr[3] & 0x80) { + RTSX_DEBUGP("ptr[3]: 0x%02x\n", ptr[3]); + TRACE_RET(chip, STATUS_FAIL); + } + if (ptr[3] & 0x01) + sd_card->sd_data_buf_ready = 1; + else + sd_card->sd_data_buf_ready = 0; + } + } + + if (rsp && rsp_len) + memcpy(rsp, ptr, rsp_len); + + return STATUS_SUCCESS; +} + +static int sd_read_data(struct rtsx_chip *chip, + u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt, + u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len, + int timeout) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i; + + sd_clr_err_code(chip); + + if (!buf) + buf_len = 0; + + if (buf_len > 512) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + if (cmd_len) { + RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); + for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, + 0xFF, cmd[i]); + } + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, + (u8)byte_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, + (u8)(byte_cnt >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, + (u8)blk_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, + (u8)(blk_cnt >> 8)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, + SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END| + SD_CHECK_CRC7 | SD_RSP_LEN_6); + if (trans_mode != SD_TM_AUTO_TUNING) + rtsx_add_cmd(chip, WRITE_REG_CMD, + CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + trans_mode | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, + SD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, SD_CARD, timeout); + if (retval < 0) { + if (retval == -ETIMEDOUT) { + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + } + + TRACE_RET(chip, STATUS_FAIL); + } + + if (buf && buf_len) { + retval = rtsx_read_ppbuf(chip, buf, buf_len); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, + u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width, + u8 *buf, int buf_len, int timeout) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i; + + sd_clr_err_code(chip); + + if (!buf) + buf_len = 0; + + if (buf_len > 512) { + /* This function can't write data more than one page */ + TRACE_RET(chip, STATUS_FAIL); + } + + if (buf && buf_len) { + retval = rtsx_write_ppbuf(chip, buf, buf_len); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_init_cmd(chip); + + if (cmd_len) { + RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); + for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + REG_SD_CMD0 + i, 0xFF, cmd[i]); + } + } + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, + (u8)byte_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, + (u8)(byte_cnt >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, + (u8)blk_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, + (u8)(blk_cnt >> 8)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, + SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | + SD_CHECK_CRC7 | SD_RSP_LEN_6); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + trans_mode | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, + SD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, SD_CARD, timeout); + if (retval < 0) { + if (retval == -ETIMEDOUT) { + sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + } + + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_check_csd(struct rtsx_chip *chip, char check_wp) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i; + u8 csd_ver, trans_speed; + u8 rsp[16]; + + for (i = 0; i < 6; i++) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, + SD_RSP_TYPE_R2, rsp, 16); + if (retval == STATUS_SUCCESS) + break; + } + + if (i == 6) + TRACE_RET(chip, STATUS_FAIL); + + memcpy(sd_card->raw_csd, rsp + 1, 15); + + RTSX_DEBUGP("CSD Response:\n"); + RTSX_DUMP(sd_card->raw_csd, 16); + + csd_ver = (rsp[1] & 0xc0) >> 6; + RTSX_DEBUGP("csd_ver = %d\n", csd_ver); + + trans_speed = rsp[4]; + if ((trans_speed & 0x07) == 0x02) { + if ((trans_speed & 0xf8) >= 0x30) { + if (chip->asic_code) + sd_card->sd_clock = 47; + else + sd_card->sd_clock = CLK_50; + + } else if ((trans_speed & 0xf8) == 0x28) { + if (chip->asic_code) + sd_card->sd_clock = 39; + else + sd_card->sd_clock = CLK_40; + + } else if ((trans_speed & 0xf8) == 0x20) { + if (chip->asic_code) + sd_card->sd_clock = 29; + else + sd_card->sd_clock = CLK_30; + + } else if ((trans_speed & 0xf8) >= 0x10) { + if (chip->asic_code) + sd_card->sd_clock = 23; + else + sd_card->sd_clock = CLK_20; + + } else if ((trans_speed & 0x08) >= 0x08) { + if (chip->asic_code) + sd_card->sd_clock = 19; + else + sd_card->sd_clock = CLK_20; + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + if (CHK_MMC_SECTOR_MODE(sd_card)) { + sd_card->capacity = 0; + } else { + if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) { + u8 blk_size, c_size_mult; + u16 c_size; + blk_size = rsp[6] & 0x0F; + c_size = ((u16)(rsp[7] & 0x03) << 10) + + ((u16)rsp[8] << 2) + + ((u16)(rsp[9] & 0xC0) >> 6); + c_size_mult = (u8)((rsp[10] & 0x03) << 1); + c_size_mult += (rsp[11] & 0x80) >> 7; + sd_card->capacity = (((u32)(c_size + 1)) * + (1 << (c_size_mult + 2))) + << (blk_size - 9); + } else { + u32 total_sector = 0; + total_sector = (((u32)rsp[8] & 0x3f) << 16) | + ((u32)rsp[9] << 8) | (u32)rsp[10]; + sd_card->capacity = (total_sector + 1) << 10; + } + } + + if (check_wp) { + if (rsp[15] & 0x30) + chip->card_wp |= SD_CARD; + + RTSX_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]); + } + + return STATUS_SUCCESS; +} + +static int sd_set_sample_push_timing(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + + u8 val = 0; + + if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) + val |= 0x10; + + if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) { + if (chip->asic_code) { + if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) { + if (val & 0x10) + val |= 0x04; + else + val |= 0x08; + } + } else { + if (val & 0x10) + val |= 0x04; + else + val |= 0x08; + } + } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == + SD_SAMPLE_POINT_DELAY) { + if (val & 0x10) + val |= 0x04; + else + val |= 0x08; + } + + RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val); + + return STATUS_SUCCESS; +} + +static void sd_choose_proper_clock(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + + if (CHK_SD_SDR104(sd_card)) { + if (chip->asic_code) + sd_card->sd_clock = chip->asic_sd_sdr104_clk; + else + sd_card->sd_clock = chip->fpga_sd_sdr104_clk; + + } else if (CHK_SD_DDR50(sd_card)) { + if (chip->asic_code) + sd_card->sd_clock = chip->asic_sd_ddr50_clk; + else + sd_card->sd_clock = chip->fpga_sd_ddr50_clk; + + } else if (CHK_SD_SDR50(sd_card)) { + if (chip->asic_code) + sd_card->sd_clock = chip->asic_sd_sdr50_clk; + else + sd_card->sd_clock = chip->fpga_sd_sdr50_clk; + + } else if (CHK_SD_HS(sd_card)) { + if (chip->asic_code) + sd_card->sd_clock = chip->asic_sd_hs_clk; + else + sd_card->sd_clock = chip->fpga_sd_hs_clk; + + } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { + if (chip->asic_code) + sd_card->sd_clock = chip->asic_mmc_52m_clk; + else + sd_card->sd_clock = chip->fpga_mmc_52m_clk; + + } else if (CHK_MMC_26M(sd_card)) { + if (chip->asic_code) + sd_card->sd_clock = 48; + else + sd_card->sd_clock = CLK_50; + } +} + +static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div) +{ + u8 mask = 0, val = 0; + + mask = 0x60; + if (clk_div == SD_CLK_DIVIDE_0) + val = 0x00; + else if (clk_div == SD_CLK_DIVIDE_128) + val = 0x40; + else if (clk_div == SD_CLK_DIVIDE_256) + val = 0x20; + + RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val); + + return STATUS_SUCCESS; +} + +static int sd_set_init_para(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + retval = sd_set_sample_push_timing(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + sd_choose_proper_clock(chip); + + retval = switch_clock(chip, sd_card->sd_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int sd_select_card(struct rtsx_chip *chip, int select) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd_idx, cmd_type; + u32 addr; + + if (select) { + cmd_idx = SELECT_CARD; + cmd_type = SD_RSP_TYPE_R1; + addr = sd_card->sd_addr; + } else { + cmd_idx = DESELECT_CARD; + cmd_type = SD_RSP_TYPE_R0; + addr = 0; + } + + retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +#ifdef SUPPORT_SD_LOCK +static int sd_update_lock_status(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 rsp[5]; + + retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, rsp, 5); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (rsp[1] & 0x02) + sd_card->sd_lock_status |= SD_LOCKED; + else + sd_card->sd_lock_status &= ~SD_LOCKED; + + RTSX_DEBUGP("sd_card->sd_lock_status = 0x%x\n", + sd_card->sd_lock_status); + + if (rsp[1] & 0x01) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} +#endif + +static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, + u8 data_ready, int polling_cnt) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval, i; + u8 rsp[5]; + + for (i = 0; i < polling_cnt; i++) { + retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, + 5); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (((rsp[3] & 0x1E) == state) && + ((rsp[3] & 0x01) == data_ready)) + return STATUS_SUCCESS; + } + + TRACE_RET(chip, STATUS_FAIL); +} + +static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage) +{ + int retval; + + if (voltage == SD_IO_3V3) { + if (chip->asic_code) { + retval = rtsx_write_phy_register(chip, 0x08, + 0x4FC0 | + chip->phy_voltage); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0); + } + } else if (voltage == SD_IO_1V8) { + if (chip->asic_code) { + retval = rtsx_write_phy_register(chip, 0x08, + 0x4C40 | + chip->phy_voltage); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, + SD_IO_USING_1V8); + } + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_voltage_switch(struct rtsx_chip *chip) +{ + int retval; + u8 stat; + + RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, + SD_CLK_TOGGLE_EN); + + retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + udelay(chip->sd_voltage_switch_delay); + + RTSX_READ_REG(chip, SD_BUS_STAT, &stat); + if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | + SD_DAT1_STATUS | SD_DAT0_STATUS)) { + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP); + retval = sd_change_bank_voltage(chip, SD_IO_1V8); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(50); + + RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); + wait_timeout(10); + + RTSX_READ_REG(chip, SD_BUS_STAT, &stat); + if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | + SD_DAT1_STATUS | SD_DAT0_STATUS)) != + (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | + SD_DAT1_STATUS | SD_DAT0_STATUS)) { + RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", stat); + rtsx_write_register(chip, SD_BUS_STAT, + SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); + rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, + 0); + + return STATUS_SUCCESS; +} + +static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir) +{ + if (tune_dir == TUNE_RX) { + RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_RX); + RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RX); + } else { + RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_TX); + RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_TX); + } + + return STATUS_SUCCESS; +} + +static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) +{ + struct sd_info *sd_card = &(chip->sd_card); + u16 SD_VP_CTL, SD_DCMPS_CTL; + u8 val; + int retval; + int ddr_rx = 0; + + RTSX_DEBUGP("sd_change_phase (sample_point = %d, tune_dir = %d)\n", + sample_point, tune_dir); + + if (tune_dir == TUNE_RX) { + SD_VP_CTL = SD_VPRX_CTL; + SD_DCMPS_CTL = SD_DCMPS_RX_CTL; + if (CHK_SD_DDR50(sd_card)) + ddr_rx = 1; + } else { + SD_VP_CTL = SD_VPTX_CTL; + SD_DCMPS_CTL = SD_DCMPS_TX_CTL; + } + + if (chip->asic_code) { + RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK); + RTSX_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point); + RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); + RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, + PHASE_NOT_RESET); + RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0); + } else { +#ifdef CONFIG_RTS5208_DEBUG + rtsx_read_register(chip, SD_VP_CTL, &val); + RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val); + rtsx_read_register(chip, SD_DCMPS_CTL, &val); + RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val); +#endif + + if (ddr_rx) { + RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, + PHASE_CHANGE); + udelay(50); + RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF, + PHASE_CHANGE | PHASE_NOT_RESET | sample_point); + } else { + RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK); + udelay(50); + RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF, + PHASE_NOT_RESET | sample_point); + } + udelay(100); + + rtsx_init_cmd(chip); + rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, + DCMPS_CHANGE); + rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, + DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); + retval = rtsx_send_cmd(chip, SD_CARD, 100); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, Fail); + + val = *rtsx_get_cmd_data(chip); + if (val & DCMPS_ERROR) + TRACE_GOTO(chip, Fail); + + if ((val & DCMPS_CURRENT_PHASE) != sample_point) + TRACE_GOTO(chip, Fail); + + RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); + if (ddr_rx) + RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0); + else + RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0); + + udelay(50); + } + + RTSX_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); + + return STATUS_SUCCESS; + +Fail: +#ifdef CONFIG_RTS5208_DEBUG + rtsx_read_register(chip, SD_VP_CTL, &val); + RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val); + rtsx_read_register(chip, SD_DCMPS_CTL, &val); + RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val); +#endif + + rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); + rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0); + wait_timeout(10); + sd_reset_dcm(chip, tune_dir); + return STATUS_FAIL; +} + +static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd[5], buf[8]; + + retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + cmd[0] = 0x40 | SEND_SCR; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, + buf, 8, 250); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + memcpy(sd_card->raw_scr, buf, 8); + + if ((buf[0] & 0x0F) == 0) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, + u8 func_to_switch, u8 *buf, int buf_len) +{ + u8 support_mask = 0, query_switch = 0, switch_busy = 0; + int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0; + + if (func_group == SD_FUNC_GROUP_1) { + support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET; + query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET; + check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET; + + switch (func_to_switch) { + case HS_SUPPORT: + support_mask = HS_SUPPORT_MASK; + query_switch = HS_QUERY_SWITCH_OK; + switch_busy = HS_SWITCH_BUSY; + break; + + case SDR50_SUPPORT: + support_mask = SDR50_SUPPORT_MASK; + query_switch = SDR50_QUERY_SWITCH_OK; + switch_busy = SDR50_SWITCH_BUSY; + break; + + case SDR104_SUPPORT: + support_mask = SDR104_SUPPORT_MASK; + query_switch = SDR104_QUERY_SWITCH_OK; + switch_busy = SDR104_SWITCH_BUSY; + break; + + case DDR50_SUPPORT: + support_mask = DDR50_SUPPORT_MASK; + query_switch = DDR50_QUERY_SWITCH_OK; + switch_busy = DDR50_SWITCH_BUSY; + break; + + default: + TRACE_RET(chip, STATUS_FAIL); + } + } else if (func_group == SD_FUNC_GROUP_3) { + support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET; + query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET; + check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET; + + switch (func_to_switch) { + case DRIVING_TYPE_A: + support_mask = DRIVING_TYPE_A_MASK; + query_switch = TYPE_A_QUERY_SWITCH_OK; + switch_busy = TYPE_A_SWITCH_BUSY; + break; + + case DRIVING_TYPE_C: + support_mask = DRIVING_TYPE_C_MASK; + query_switch = TYPE_C_QUERY_SWITCH_OK; + switch_busy = TYPE_C_SWITCH_BUSY; + break; + + case DRIVING_TYPE_D: + support_mask = DRIVING_TYPE_D_MASK; + query_switch = TYPE_D_QUERY_SWITCH_OK; + switch_busy = TYPE_D_SWITCH_BUSY; + break; + + default: + TRACE_RET(chip, STATUS_FAIL); + } + } else if (func_group == SD_FUNC_GROUP_4) { + support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET; + query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET; + check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET; + + switch (func_to_switch) { + case CURRENT_LIMIT_400: + support_mask = CURRENT_LIMIT_400_MASK; + query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK; + switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY; + break; + + case CURRENT_LIMIT_600: + support_mask = CURRENT_LIMIT_600_MASK; + query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK; + switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY; + break; + + case CURRENT_LIMIT_800: + support_mask = CURRENT_LIMIT_800_MASK; + query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK; + switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY; + break; + + default: + TRACE_RET(chip, STATUS_FAIL); + } + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + if (func_group == SD_FUNC_GROUP_1) { + if (!(buf[support_offset] & support_mask) || + ((buf[query_switch_offset] & 0x0F) != query_switch)) { + TRACE_RET(chip, STATUS_FAIL); + } + } + + /* Check 'Busy Status' */ + if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) && + ((buf[check_busy_offset] & switch_busy) == switch_busy)) { + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, + u8 func_group, u8 func_to_switch, u8 bus_width) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd[5], buf[64]; + + RTSX_DEBUGP("sd_check_switch_mode (mode = %d, func_group = %d, func_to_switch = %d)\n", + mode, func_group, func_to_switch); + + cmd[0] = 0x40 | SWITCH; + cmd[1] = mode; + + if (func_group == SD_FUNC_GROUP_1) { + cmd[2] = 0xFF; + cmd[3] = 0xFF; + cmd[4] = 0xF0 + func_to_switch; + } else if (func_group == SD_FUNC_GROUP_3) { + cmd[2] = 0xFF; + cmd[3] = 0xF0 + func_to_switch; + cmd[4] = 0xFF; + } else if (func_group == SD_FUNC_GROUP_4) { + cmd[2] = 0xFF; + cmd[3] = 0x0F + (func_to_switch << 4); + cmd[4] = 0xFF; + } else { + cmd[1] = SD_CHECK_MODE; + cmd[2] = 0xFF; + cmd[3] = 0xFF; + cmd[4] = 0xFF; + } + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, + buf, 64, 250); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_DUMP(buf, 64); + + if (func_group == NO_ARGUMENT) { + sd_card->func_group1_mask = buf[0x0D]; + sd_card->func_group2_mask = buf[0x0B]; + sd_card->func_group3_mask = buf[0x09]; + sd_card->func_group4_mask = buf[0x07]; + + RTSX_DEBUGP("func_group1_mask = 0x%02x\n", buf[0x0D]); + RTSX_DEBUGP("func_group2_mask = 0x%02x\n", buf[0x0B]); + RTSX_DEBUGP("func_group3_mask = 0x%02x\n", buf[0x09]); + RTSX_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]); + } else { + /* Maximum current consumption, check whether current is + * acceptable; bit[511:496] = 0x0000 means some error happened. + */ + u16 cc = ((u16)buf[0] << 8) | buf[1]; + RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc); + if ((cc == 0) || (cc > 800)) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_query_switch_result(chip, func_group, + func_to_switch, buf, 64); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) { + RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, + chip->sd_800mA_ocp_thd); + RTSX_WRITE_REG(chip, CARD_PWR_CTL, PMOS_STRG_MASK, + PMOS_STRG_800mA); + } + } + + return STATUS_SUCCESS; +} + +static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch) +{ + if (func_group == SD_FUNC_GROUP_1) { + if (func_to_switch > HS_SUPPORT) + func_to_switch--; + + } else if (func_group == SD_FUNC_GROUP_4) { + if (func_to_switch > CURRENT_LIMIT_200) + func_to_switch--; + } + + return func_to_switch; +} + +static int sd_check_switch(struct rtsx_chip *chip, + u8 func_group, u8 func_to_switch, u8 bus_width) +{ + int retval; + int i; + int switch_good = 0; + + for (i = 0; i < 3; i++) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group, + func_to_switch, bus_width); + if (retval == STATUS_SUCCESS) { + u8 stat; + + retval = sd_check_switch_mode(chip, SD_SWITCH_MODE, + func_group, func_to_switch, bus_width); + if (retval == STATUS_SUCCESS) { + switch_good = 1; + break; + } + + RTSX_READ_REG(chip, SD_STAT1, &stat); + if (stat & SD_CRC16_ERR) { + RTSX_DEBUGP("SD CRC16 error when switching mode\n"); + TRACE_RET(chip, STATUS_FAIL); + } + } + + func_to_switch = downgrade_switch_mode(func_group, + func_to_switch); + + wait_timeout(20); + } + + if (!switch_good) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i; + u8 func_to_switch = 0; + + /* Get supported functions */ + retval = sd_check_switch_mode(chip, SD_CHECK_MODE, + NO_ARGUMENT, NO_ARGUMENT, bus_width); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail); + + /* Function Group 1: Access Mode */ + for (i = 0; i < 4; i++) { + switch ((u8)(chip->sd_speed_prior >> (i*8))) { + case SDR104_SUPPORT: + if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) + && chip->sdr104_en) { + func_to_switch = SDR104_SUPPORT; + } + break; + + case DDR50_SUPPORT: + if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) + && chip->ddr50_en) { + func_to_switch = DDR50_SUPPORT; + } + break; + + case SDR50_SUPPORT: + if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) + && chip->sdr50_en) { + func_to_switch = SDR50_SUPPORT; + } + break; + + case HS_SUPPORT: + if (sd_card->func_group1_mask & HS_SUPPORT_MASK) + func_to_switch = HS_SUPPORT; + + break; + + default: + continue; + } + + + if (func_to_switch) + break; + + } + RTSX_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch); + +#ifdef SUPPORT_SD_LOCK + if ((sd_card->sd_lock_status & SD_SDR_RST) + && (DDR50_SUPPORT == func_to_switch) + && (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { + func_to_switch = SDR50_SUPPORT; + RTSX_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n"); + } +#endif + + if (func_to_switch) { + retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, + bus_width); + if (retval != STATUS_SUCCESS) { + if (func_to_switch == SDR104_SUPPORT) { + sd_card->sd_switch_fail = SDR104_SUPPORT_MASK; + } else if (func_to_switch == DDR50_SUPPORT) { + sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | + DDR50_SUPPORT_MASK; + } else if (func_to_switch == SDR50_SUPPORT) { + sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | + DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK; + } + TRACE_RET(chip, STATUS_FAIL); + } + + if (func_to_switch == SDR104_SUPPORT) + SET_SD_SDR104(sd_card); + else if (func_to_switch == DDR50_SUPPORT) + SET_SD_DDR50(sd_card); + else if (func_to_switch == SDR50_SUPPORT) + SET_SD_SDR50(sd_card); + else + SET_SD_HS(sd_card); + } + + if (CHK_SD_DDR50(sd_card)) { + RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04); + retval = sd_set_sample_push_timing(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + if (!func_to_switch || (func_to_switch == HS_SUPPORT)) { + /* Do not try to switch current limit if the card doesn't + * support UHS mode or we don't want it to support UHS mode + */ + return STATUS_SUCCESS; + } + + /* Function Group 4: Current Limit */ + func_to_switch = 0xFF; + + for (i = 0; i < 4; i++) { + switch ((u8)(chip->sd_current_prior >> (i*8))) { + case CURRENT_LIMIT_800: + if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) + func_to_switch = CURRENT_LIMIT_800; + + break; + + case CURRENT_LIMIT_600: + if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) + func_to_switch = CURRENT_LIMIT_600; + + break; + + case CURRENT_LIMIT_400: + if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) + func_to_switch = CURRENT_LIMIT_400; + + break; + + case CURRENT_LIMIT_200: + if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) + func_to_switch = CURRENT_LIMIT_200; + + break; + + default: + continue; + } + + if (func_to_switch != 0xFF) + break; + } + + RTSX_DEBUGP("SD_FUNC_GROUP_4: func_to_switch = 0x%02x", func_to_switch); + + if (func_to_switch <= CURRENT_LIMIT_800) { + retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, + bus_width); + if (retval != STATUS_SUCCESS) { + if (sd_check_err_code(chip, SD_NO_CARD)) + TRACE_RET(chip, STATUS_FAIL); + } + RTSX_DEBUGP("Switch current limit finished! (%d)\n", retval); + } + + if (CHK_SD_DDR50(sd_card)) + RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0); + + return STATUS_SUCCESS; +} + +static int sd_wait_data_idle(struct rtsx_chip *chip) +{ + int retval = STATUS_TIMEDOUT; + int i; + u8 val = 0; + + for (i = 0; i < 100; i++) { + RTSX_READ_REG(chip, SD_DATA_STATE, &val); + if (val & SD_DATA_IDLE) { + retval = STATUS_SUCCESS; + break; + } + udelay(100); + } + RTSX_DEBUGP("SD_DATA_STATE: 0x%02x\n", val); + + return retval; +} + +static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) +{ + int retval; + u8 cmd[5]; + + retval = sd_change_phase(chip, sample_point, TUNE_RX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + cmd[0] = 0x40 | SEND_TUNING_PATTERN; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + retval = sd_read_data(chip, SD_TM_AUTO_TUNING, + cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100); + if (retval != STATUS_SUCCESS) { + (void)sd_wait_data_idle(chip); + + rtsx_clear_sd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd[5]; + + retval = sd_change_phase(chip, sample_point, TUNE_RX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("sd ddr tuning rx\n"); + + retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + cmd[0] = 0x40 | SD_STATUS; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, + cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100); + if (retval != STATUS_SUCCESS) { + (void)sd_wait_data_idle(chip); + + rtsx_clear_sd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd[5], bus_width; + + if (CHK_MMC_8BIT(sd_card)) + bus_width = SD_BUS_WIDTH_8; + else if (CHK_MMC_4BIT(sd_card)) + bus_width = SD_BUS_WIDTH_4; + else + bus_width = SD_BUS_WIDTH_1; + + retval = sd_change_phase(chip, sample_point, TUNE_RX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("mmc ddr tuning rx\n"); + + cmd[0] = 0x40 | SEND_EXT_CSD; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, + cmd, 5, 0x200, 1, bus_width, NULL, 0, 100); + if (retval != STATUS_SUCCESS) { + (void)sd_wait_data_idle(chip); + + rtsx_clear_sd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + retval = sd_change_phase(chip, sample_point, TUNE_TX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, + SD_RSP_80CLK_TIMEOUT_EN); + + retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) { + if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) { + rtsx_write_register(chip, SD_CFG3, + SD_RSP_80CLK_TIMEOUT_EN, 0); + TRACE_RET(chip, STATUS_FAIL); + } + } + + RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); + + return STATUS_SUCCESS; +} + +static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd[5], bus_width; + + retval = sd_change_phase(chip, sample_point, TUNE_TX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_SD(sd_card)) { + bus_width = SD_BUS_WIDTH_4; + } else { + if (CHK_MMC_8BIT(sd_card)) + bus_width = SD_BUS_WIDTH_8; + else if (CHK_MMC_4BIT(sd_card)) + bus_width = SD_BUS_WIDTH_4; + else + bus_width = SD_BUS_WIDTH_1; + } + + retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, + SD_RSP_80CLK_TIMEOUT_EN); + + cmd[0] = 0x40 | PROGRAM_CSD; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, + cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); + + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, + NULL, 0); + + return STATUS_SUCCESS; +} + +static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, + u8 tune_dir) +{ + struct sd_info *sd_card = &(chip->sd_card); + struct timing_phase_path path[MAX_PHASE + 1]; + int i, j, cont_path_cnt; + int new_block, max_len, final_path_idx; + u8 final_phase = 0xFF; + + if (phase_map == 0xFFFFFFFF) { + if (tune_dir == TUNE_RX) + final_phase = (u8)chip->sd_default_rx_phase; + else + final_phase = (u8)chip->sd_default_tx_phase; + + goto Search_Finish; + } + + cont_path_cnt = 0; + new_block = 1; + j = 0; + for (i = 0; i < MAX_PHASE + 1; i++) { + if (phase_map & (1 << i)) { + if (new_block) { + new_block = 0; + j = cont_path_cnt++; + path[j].start = i; + path[j].end = i; + } else { + path[j].end = i; + } + } else { + new_block = 1; + if (cont_path_cnt) { + int idx = cont_path_cnt - 1; + path[idx].len = path[idx].end - + path[idx].start + 1; + path[idx].mid = path[idx].start + + path[idx].len / 2; + } + } + } + + if (cont_path_cnt == 0) { + RTSX_DEBUGP("No continuous phase path\n"); + goto Search_Finish; + } else { + int idx = cont_path_cnt - 1; + path[idx].len = path[idx].end - path[idx].start + 1; + path[idx].mid = path[idx].start + path[idx].len / 2; + } + + if ((path[0].start == 0) && + (path[cont_path_cnt - 1].end == MAX_PHASE)) { + path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; + path[0].len += path[cont_path_cnt - 1].len; + path[0].mid = path[0].start + path[0].len / 2; + if (path[0].mid < 0) + path[0].mid += MAX_PHASE + 1; + + cont_path_cnt--; + } + + max_len = 0; + final_phase = 0; + final_path_idx = 0; + for (i = 0; i < cont_path_cnt; i++) { + if (path[i].len > max_len) { + max_len = path[i].len; + final_phase = (u8)path[i].mid; + final_path_idx = i; + } + + RTSX_DEBUGP("path[%d].start = %d\n", i, path[i].start); + RTSX_DEBUGP("path[%d].end = %d\n", i, path[i].end); + RTSX_DEBUGP("path[%d].len = %d\n", i, path[i].len); + RTSX_DEBUGP("path[%d].mid = %d\n", i, path[i].mid); + RTSX_DEBUGP("\n"); + } + + if (tune_dir == TUNE_TX) { + if (CHK_SD_SDR104(sd_card)) { + if (max_len > 15) { + int temp_mid = (max_len - 16) / 2; + int temp_final_phase = + path[final_path_idx].end - + (max_len - (6 + temp_mid)); + + if (temp_final_phase < 0) + final_phase = (u8)(temp_final_phase + + MAX_PHASE + 1); + else + final_phase = (u8)temp_final_phase; + } + } else if (CHK_SD_SDR50(sd_card)) { + if (max_len > 12) { + int temp_mid = (max_len - 13) / 2; + int temp_final_phase = + path[final_path_idx].end - + (max_len - (3 + temp_mid)); + + if (temp_final_phase < 0) + final_phase = (u8)(temp_final_phase + + MAX_PHASE + 1); + else + final_phase = (u8)temp_final_phase; + } + } + } + +Search_Finish: + RTSX_DEBUGP("Final chosen phase: %d\n", final_phase); + return final_phase; +} + +static int sd_tuning_rx(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i, j; + u32 raw_phase_map[3], phase_map; + u8 final_phase; + int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); + + if (CHK_SD(sd_card)) { + if (CHK_SD_DDR50(sd_card)) + tuning_cmd = sd_ddr_tuning_rx_cmd; + else + tuning_cmd = sd_sdr_tuning_rx_cmd; + + } else { + if (CHK_MMC_DDR52(sd_card)) + tuning_cmd = mmc_ddr_tunning_rx_cmd; + else + TRACE_RET(chip, STATUS_FAIL); + } + + for (i = 0; i < 3; i++) { + raw_phase_map[i] = 0; + for (j = MAX_PHASE; j >= 0; j--) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = tuning_cmd(chip, (u8)j); + if (retval == STATUS_SUCCESS) + raw_phase_map[i] |= 1 << j; + } + } + + phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; + for (i = 0; i < 3; i++) + RTSX_DEBUGP("RX raw_phase_map[%d] = 0x%08x\n", i, + raw_phase_map[i]); + + RTSX_DEBUGP("RX phase_map = 0x%08x\n", phase_map); + + final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX); + if (final_phase == 0xFF) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_change_phase(chip, final_phase, TUNE_RX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i; + u32 phase_map; + u8 final_phase; + + RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, + SD_RSP_80CLK_TIMEOUT_EN); + + phase_map = 0; + for (i = MAX_PHASE; i >= 0; i--) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + rtsx_write_register(chip, SD_CFG3, + SD_RSP_80CLK_TIMEOUT_EN, 0); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_change_phase(chip, (u8)i, TUNE_TX); + if (retval != STATUS_SUCCESS) + continue; + + retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, + 0); + if ((retval == STATUS_SUCCESS) || + !sd_check_err_code(chip, SD_RSP_TIMEOUT)) + phase_map |= 1 << i; + } + + RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); + + RTSX_DEBUGP("DDR TX pre tune phase_map = 0x%08x\n", phase_map); + + final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); + if (final_phase == 0xFF) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_change_phase(chip, final_phase, TUNE_TX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("DDR TX pre tune phase: %d\n", (int)final_phase); + + return STATUS_SUCCESS; +} + +static int sd_tuning_tx(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int i, j; + u32 raw_phase_map[3], phase_map; + u8 final_phase; + int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); + + if (CHK_SD(sd_card)) { + if (CHK_SD_DDR50(sd_card)) + tuning_cmd = sd_ddr_tuning_tx_cmd; + else + tuning_cmd = sd_sdr_tuning_tx_cmd; + + } else { + if (CHK_MMC_DDR52(sd_card)) + tuning_cmd = sd_ddr_tuning_tx_cmd; + else + TRACE_RET(chip, STATUS_FAIL); + } + + for (i = 0; i < 3; i++) { + raw_phase_map[i] = 0; + for (j = MAX_PHASE; j >= 0; j--) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + rtsx_write_register(chip, SD_CFG3, + SD_RSP_80CLK_TIMEOUT_EN, 0); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = tuning_cmd(chip, (u8)j); + if (retval == STATUS_SUCCESS) + raw_phase_map[i] |= 1 << j; + } + } + + phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; + for (i = 0; i < 3; i++) + RTSX_DEBUGP("TX raw_phase_map[%d] = 0x%08x\n", + i, raw_phase_map[i]); + + RTSX_DEBUGP("TX phase_map = 0x%08x\n", phase_map); + + final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); + if (final_phase == 0xFF) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_change_phase(chip, final_phase, TUNE_TX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_sdr_tuning(struct rtsx_chip *chip) +{ + int retval; + + retval = sd_tuning_tx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_tuning_rx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_ddr_tuning(struct rtsx_chip *chip) +{ + int retval; + + if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { + retval = sd_ddr_pre_tuning_tx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, + TUNE_TX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_tuning_rx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { + retval = sd_tuning_tx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int mmc_ddr_tuning(struct rtsx_chip *chip) +{ + int retval; + + if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { + retval = sd_ddr_pre_tuning_tx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, + TUNE_TX); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_tuning_rx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { + retval = sd_tuning_tx(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int sd_switch_clock(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + int re_tuning = 0; + + retval = select_card(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = switch_clock(chip, sd_card->sd_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (re_tuning) { + if (CHK_SD(sd_card)) { + if (CHK_SD_DDR50(sd_card)) + retval = sd_ddr_tuning(chip); + else + retval = sd_sdr_tuning(chip); + } else { + if (CHK_MMC_DDR52(sd_card)) + retval = mmc_ddr_tuning(chip); + } + + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_prepare_reset(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + if (chip->asic_code) + sd_card->sd_clock = 29; + else + sd_card->sd_clock = CLK_30; + + sd_card->sd_type = 0; + sd_card->seq_mode = 0; + sd_card->sd_data_buf_ready = 0; + sd_card->capacity = 0; + +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status = 0; + sd_card->sd_erase_status = 0; +#endif + + chip->capacity[chip->card2lun[SD_CARD]] = 0; + chip->sd_io = 0; + + retval = sd_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, retval); + + RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, 0x40); + + RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, + SD_STOP | SD_CLR_ERR); + + retval = select_card(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_pull_ctl_disable(struct rtsx_chip *chip) +{ + if (CHECK_PID(chip, 0x5208)) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, + XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, + SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, + SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, + XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55); + RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55); + RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B); + RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69); + } + } + + return STATUS_SUCCESS; +} + +int sd_pull_ctl_enable(struct rtsx_chip *chip) +{ + int retval; + + rtsx_init_cmd(chip); + + if (CHECK_PID(chip, 0x5208)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, + XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, + SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, + SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, + XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, + MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, + 0xA8); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, + 0x5A); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, + 0x95); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, + 0xAA); + } + } + + retval = rtsx_send_cmd(chip, SD_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sd_init_power(struct rtsx_chip *chip) +{ + int retval; + + retval = sd_power_off_card3v3(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!chip->ft2_fast_mode) + wait_timeout(250); + + retval = enable_card_clock(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (chip->asic_code) { + retval = sd_pull_ctl_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, + 0); + } + + if (!chip->ft2_fast_mode) { + retval = card_power_on(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(260); + +#ifdef SUPPORT_OCP + if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { + RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", + chip->ocp_stat); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + } + + RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); + + return STATUS_SUCCESS; +} + +static int sd_dummy_clock(struct rtsx_chip *chip) +{ + RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0x01); + wait_timeout(5); + RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0); + + return STATUS_SUCCESS; +} + +static int sd_read_lba0(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 cmd[5], bus_width; + + cmd[0] = 0x40 | READ_SINGLE_BLOCK; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + if (CHK_SD(sd_card)) { + bus_width = SD_BUS_WIDTH_4; + } else { + if (CHK_MMC_8BIT(sd_card)) + bus_width = SD_BUS_WIDTH_8; + else if (CHK_MMC_4BIT(sd_card)) + bus_width = SD_BUS_WIDTH_4; + else + bus_width = SD_BUS_WIDTH_1; + } + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, + 5, 512, 1, bus_width, NULL, 0, 100); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sd_check_wp_state(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u32 val; + u16 sd_card_type; + u8 cmd[5], buf[64]; + + retval = sd_send_cmd_get_rsp(chip, APP_CMD, + sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + cmd[0] = 0x40 | SD_STATUS; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = 0; + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, + SD_BUS_WIDTH_4, buf, 64, 250); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_DEBUGP("ACMD13:\n"); + RTSX_DUMP(buf, 64); + + sd_card_type = ((u16)buf[2] << 8) | buf[3]; + RTSX_DEBUGP("sd_card_type = 0x%04x\n", sd_card_type); + if ((sd_card_type == 0x0001) || (sd_card_type == 0x0002)) { + /* ROM card or OTP */ + chip->card_wp |= SD_CARD; + } + + /* Check SD Machanical Write-Protect Switch */ + val = rtsx_readl(chip, RTSX_BIPR); + if (val & SD_WRITE_PROTECT) + chip->card_wp |= SD_CARD; + + return STATUS_SUCCESS; +} + +static int reset_sd(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0; + int sd_dont_switch = 0; + int support_1v8 = 0; + int try_sdio = 1; + u8 rsp[16]; + u8 switch_bus_width; + u32 voltage = 0; + int sd20_mode = 0; + + SET_SD(sd_card); + +Switch_Fail: + + i = 0; + j = 0; + k = 0; + hi_cap_flow = 0; + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) + goto SD_UNLOCK_ENTRY; +#endif + + retval = sd_prepare_reset(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_dummy_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { + int rty_cnt = 0; + + for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, + SD_RSP_TYPE_R4, rsp, 5); + if (retval == STATUS_SUCCESS) { + int func_num = (rsp[1] >> 4) & 0x07; + if (func_num) { + RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num); + chip->sd_io = 1; + TRACE_RET(chip, STATUS_FAIL); + } + + break; + } + + sd_init_power(chip); + + sd_dummy_clock(chip); + } + + RTSX_DEBUGP("Normal card!\n"); + } + + /* Start Initialization Process of SD Card */ +RTY_SD_RST: + retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(20); + + retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, + SD_RSP_TYPE_R7, rsp, 5); + if (retval == STATUS_SUCCESS) { + if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) { + hi_cap_flow = 1; + voltage = SUPPORT_VOLTAGE | 0x40000000; + } + } + + if (!hi_cap_flow) { + voltage = SUPPORT_VOLTAGE; + + retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, + SD_RSP_TYPE_R0, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(20); + } + + do { + retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, + NULL, 0); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + j++; + if (j < 3) + goto RTY_SD_RST; + else + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, + SD_RSP_TYPE_R3, rsp, 5); + if (retval != STATUS_SUCCESS) { + k++; + if (k < 3) + goto RTY_SD_RST; + else + TRACE_RET(chip, STATUS_FAIL); + } + + i++; + wait_timeout(20); + } while (!(rsp[1] & 0x80) && (i < 255)); + + if (i == 255) + TRACE_RET(chip, STATUS_FAIL); + + if (hi_cap_flow) { + if (rsp[1] & 0x40) + SET_SD_HCXC(sd_card); + else + CLR_SD_HCXC(sd_card); + + support_1v8 = 0; + } else { + CLR_SD_HCXC(sd_card); + support_1v8 = 0; + } + RTSX_DEBUGP("support_1v8 = %d\n", support_1v8); + + if (support_1v8) { + retval = sd_voltage_switch(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + for (i = 0; i < 3; i++) { + retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, + SD_RSP_TYPE_R6, rsp, 5); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + sd_card->sd_addr = (u32)rsp[1] << 24; + sd_card->sd_addr += (u32)rsp[2] << 16; + + if (sd_card->sd_addr) + break; + } + + retval = sd_check_csd(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_select_card(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + +#ifdef SUPPORT_SD_LOCK +SD_UNLOCK_ENTRY: + retval = sd_update_lock_status(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (sd_card->sd_lock_status & SD_LOCKED) { + sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); + return STATUS_SUCCESS; + } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) { + sd_card->sd_lock_status &= ~SD_PWD_EXIST; + } +#endif + + retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (support_1v8) { + retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + switch_bus_width = SD_BUS_WIDTH_4; + } else { + switch_bus_width = SD_BUS_WIDTH_1; + } + + retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (!(sd_card->raw_csd[4] & 0x40)) + sd_dont_switch = 1; + + if (!sd_dont_switch) { + if (sd20_mode) { + /* Set sd_switch_fail here, because we needn't + * switch to UHS mode + */ + sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | + DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK; + } + + /* Check the card whether follow SD1.1 spec or higher */ + retval = sd_check_spec(chip, switch_bus_width); + if (retval == STATUS_SUCCESS) { + retval = sd_switch_function(chip, switch_bus_width); + if (retval != STATUS_SUCCESS) { + sd_init_power(chip); + sd_dont_switch = 1; + try_sdio = 0; + + goto Switch_Fail; + } + } else { + if (support_1v8) { + sd_init_power(chip); + sd_dont_switch = 1; + try_sdio = 0; + + goto Switch_Fail; + } + } + } + + if (!support_1v8) { + retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, + SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; +#endif + + if (!sd20_mode && CHK_SD30_SPEED(sd_card)) { + int read_lba0 = 1; + + RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, + chip->sd30_drive_sel_1v8); + + retval = sd_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (CHK_SD_DDR50(sd_card)) + retval = sd_ddr_tuning(chip); + else + retval = sd_sdr_tuning(chip); + + if (retval != STATUS_SUCCESS) { + if (sd20_mode) { + TRACE_RET(chip, STATUS_FAIL); + } else { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + try_sdio = 0; + sd20_mode = 1; + goto Switch_Fail; + } + } + + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + + if (CHK_SD_DDR50(sd_card)) { + retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); + if (retval != STATUS_SUCCESS) + read_lba0 = 0; + } + + if (read_lba0) { + retval = sd_read_lba0(chip); + if (retval != STATUS_SUCCESS) { + if (sd20_mode) { + TRACE_RET(chip, STATUS_FAIL); + } else { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + try_sdio = 0; + sd20_mode = 1; + goto Switch_Fail; + } + } + } + } + + retval = sd_check_wp_state(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { + RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02); + RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00); + } +#endif + + return STATUS_SUCCESS; +} + + +static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 buf[8] = {0}, bus_width, *ptr; + u16 byte_cnt; + int len; + + retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, + 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, SWITCH_FAIL); + + if (width == MMC_8BIT_BUS) { + buf[0] = 0x55; + buf[1] = 0xAA; + len = 8; + byte_cnt = 8; + bus_width = SD_BUS_WIDTH_8; + } else { + buf[0] = 0x5A; + len = 4; + byte_cnt = 4; + bus_width = SD_BUS_WIDTH_4; + } + + retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, SWITCH_ERR); + + retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, + NULL, 0, byte_cnt, 1, bus_width, buf, len, 100); + if (retval != STATUS_SUCCESS) { + rtsx_clear_sd_error(chip); + rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); + TRACE_RET(chip, SWITCH_ERR); + } + + retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, SWITCH_ERR); + + RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R); + + if (width == MMC_8BIT_BUS) + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, + 0xFF, 0x08); + else + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, + 0xFF, 0x04); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, + SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END| + SD_CHECK_CRC7 | SD_RSP_LEN_6); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, + PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_NORMAL_READ | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, + SD_TRANSFER_END); + + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0); + if (width == MMC_8BIT_BUS) + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0); + + retval = rtsx_send_cmd(chip, SD_CARD, 100); + if (retval < 0) { + rtsx_clear_sd_error(chip); + TRACE_RET(chip, SWITCH_ERR); + } + + ptr = rtsx_get_cmd_data(chip) + 1; + + if (width == MMC_8BIT_BUS) { + RTSX_DEBUGP("BUSTEST_R [8bits]: 0x%02x 0x%02x\n", ptr[0], + ptr[1]); + if ((ptr[0] == 0xAA) && (ptr[1] == 0x55)) { + u8 rsp[5]; + u32 arg; + + if (CHK_MMC_DDR52(sd_card)) + arg = 0x03B70600; + else + arg = 0x03B70200; + + retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, + SD_RSP_TYPE_R1b, rsp, 5); + if ((retval == STATUS_SUCCESS) && + !(rsp[4] & MMC_SWITCH_ERR)) + return SWITCH_SUCCESS; + } + } else { + RTSX_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", ptr[0]); + if (ptr[0] == 0xA5) { + u8 rsp[5]; + u32 arg; + + if (CHK_MMC_DDR52(sd_card)) + arg = 0x03B70500; + else + arg = 0x03B70100; + + retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, + SD_RSP_TYPE_R1b, rsp, 5); + if ((retval == STATUS_SUCCESS) && + !(rsp[4] & MMC_SWITCH_ERR)) + return SWITCH_SUCCESS; + } + } + + TRACE_RET(chip, SWITCH_FAIL); +} + + +static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + u8 *ptr, card_type, card_type_mask = 0; + + CLR_MMC_HS(sd_card); + + RTSX_DEBUGP("SD/MMC CMD %d\n", SEND_EXT_CSD); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, + 0x40 | SEND_EXT_CSD); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, + SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END| + SD_CHECK_CRC7 | SD_RSP_LEN_6); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, + PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_NORMAL_READ | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, + SD_TRANSFER_END); + + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0); + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0); + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0); + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0); + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0); + + retval = rtsx_send_cmd(chip, SD_CARD, 1000); + if (retval < 0) { + if (retval == -ETIMEDOUT) { + rtsx_clear_sd_error(chip); + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + } + TRACE_RET(chip, STATUS_FAIL); + } + + ptr = rtsx_get_cmd_data(chip); + if (ptr[0] & SD_TRANSFER_ERR) { + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + TRACE_RET(chip, STATUS_FAIL); + } + + if (CHK_MMC_SECTOR_MODE(sd_card)) { + sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) | + ((u32)ptr[3] << 8) | ((u32)ptr[2]); + } + + card_type_mask = 0x03; + card_type = ptr[1] & card_type_mask; + if (card_type) { + u8 rsp[5]; + + if (card_type & 0x04) { + if (switch_ddr) + SET_MMC_DDR52(sd_card); + else + SET_MMC_52M(sd_card); + } else if (card_type & 0x02) { + SET_MMC_52M(sd_card); + } else { + SET_MMC_26M(sd_card); + } + + retval = sd_send_cmd_get_rsp(chip, SWITCH, + 0x03B90100, SD_RSP_TYPE_R1b, rsp, 5); + if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) + CLR_MMC_HS(sd_card); + } + + sd_choose_proper_clock(chip); + retval = switch_clock(chip, sd_card->sd_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + /* Test Bus Procedure */ + retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS); + if (retval == SWITCH_SUCCESS) { + SET_MMC_8BIT(sd_card); + chip->card_bus_width[chip->card2lun[SD_CARD]] = 8; +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; +#endif + } else if (retval == SWITCH_FAIL) { + retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS); + if (retval == SWITCH_SUCCESS) { + SET_MMC_4BIT(sd_card); + chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; +#endif + } else if (retval == SWITCH_FAIL) { + CLR_MMC_8BIT(sd_card); + CLR_MMC_4BIT(sd_card); + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } else { + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + + +static int reset_mmc(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval, i = 0, j = 0, k = 0; + int switch_ddr = 1; + u8 rsp[16]; + u8 spec_ver = 0; + u32 temp; + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) + goto MMC_UNLOCK_ENTRY; +#endif + +Switch_Fail: + retval = sd_prepare_reset(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, retval); + + SET_MMC(sd_card); + +RTY_MMC_RST: + retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + do { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND, + (SUPPORT_VOLTAGE | 0x40000000), + SD_RSP_TYPE_R3, rsp, 5); + if (retval != STATUS_SUCCESS) { + if (sd_check_err_code(chip, SD_BUSY) || + sd_check_err_code(chip, SD_TO_ERR)) { + k++; + if (k < 20) { + sd_clr_err_code(chip); + goto RTY_MMC_RST; + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } else { + j++; + if (j < 100) { + sd_clr_err_code(chip); + goto RTY_MMC_RST; + } else { + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + wait_timeout(20); + i++; + } while (!(rsp[1] & 0x80) && (i < 255)); + + if (i == 255) + TRACE_RET(chip, STATUS_FAIL); + + if ((rsp[1] & 0x60) == 0x40) + SET_MMC_SECTOR_MODE(sd_card); + else + CLR_MMC_SECTOR_MODE(sd_card); + + retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + sd_card->sd_addr = 0x00100000; + retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, + SD_RSP_TYPE_R6, rsp, 5); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_check_csd(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2; + + retval = sd_select_card(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, + NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + +#ifdef SUPPORT_SD_LOCK +MMC_UNLOCK_ENTRY: + retval = sd_update_lock_status(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); +#endif + + retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + chip->card_bus_width[chip->card2lun[SD_CARD]] = 1; + + if (!sd_card->mmc_dont_switch_bus) { + if (spec_ver == 4) { + /* MMC 4.x Cards */ + retval = mmc_switch_timing_bus(chip, switch_ddr); + if (retval != STATUS_SUCCESS) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + sd_card->mmc_dont_switch_bus = 1; + TRACE_GOTO(chip, Switch_Fail); + } + } + + if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) + TRACE_RET(chip, STATUS_FAIL); + + if (switch_ddr && CHK_MMC_DDR52(sd_card)) { + retval = sd_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = mmc_ddr_tuning(chip); + if (retval != STATUS_SUCCESS) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + switch_ddr = 0; + TRACE_GOTO(chip, Switch_Fail); + } + + retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); + if (retval == STATUS_SUCCESS) { + retval = sd_read_lba0(chip); + if (retval != STATUS_SUCCESS) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + switch_ddr = 0; + TRACE_GOTO(chip, Switch_Fail); + } + } + } + } + +#ifdef SUPPORT_SD_LOCK + if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { + RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02); + RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00); + } +#endif + + temp = rtsx_readl(chip, RTSX_BIPR); + if (temp & SD_WRITE_PROTECT) + chip->card_wp |= SD_CARD; + + return STATUS_SUCCESS; +} + +int reset_sd_card(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + sd_init_reg_addr(chip); + + memset(sd_card, 0, sizeof(struct sd_info)); + chip->capacity[chip->card2lun[SD_CARD]] = 0; + + retval = enable_card_clock(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && + !CHK_SDIO_IGNORED(chip)) { + if (chip->asic_code) { + retval = sd_pull_ctl_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + retval = rtsx_write_register(chip, FPGA_PULL_CTL, + FPGA_SD_PULL_CTL_BIT | 0x20, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + retval = card_share_mode(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + chip->sd_io = 1; + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (chip->sd_ctl & RESET_MMC_FIRST) { + retval = reset_mmc(chip); + if (retval != STATUS_SUCCESS) { + if (sd_check_err_code(chip, SD_NO_CARD)) + TRACE_RET(chip, STATUS_FAIL); + + retval = reset_sd(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + } else { + retval = reset_sd(chip); + if (retval != STATUS_SUCCESS) { + if (sd_check_err_code(chip, SD_NO_CARD)) + TRACE_RET(chip, STATUS_FAIL); + + if (chip->sd_io) { + TRACE_RET(chip, STATUS_FAIL); + } else { + retval = reset_mmc(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); + RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); + + chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; + + retval = sd_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type); + + return STATUS_SUCCESS; +} + +static int reset_mmc_only(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + sd_card->sd_type = 0; + sd_card->seq_mode = 0; + sd_card->sd_data_buf_ready = 0; + sd_card->capacity = 0; + sd_card->sd_switch_fail = 0; + +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status = 0; + sd_card->sd_erase_status = 0; +#endif + + chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0; + + retval = enable_card_clock(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = reset_mmc(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); + RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); + + chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; + + retval = sd_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("In reset_mmc_only, sd_card->sd_type = 0x%x\n", + sd_card->sd_type); + + return STATUS_SUCCESS; +} + +#define WAIT_DATA_READY_RTY_CNT 255 + +static int wait_data_buf_ready(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int i, retval; + + for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) { + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + sd_card->sd_data_buf_ready = 0; + + retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (sd_card->sd_data_buf_ready) { + return sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); + } + } + + sd_set_err_code(chip, SD_TO_ERR); + + TRACE_RET(chip, STATUS_FAIL); +} + +void sd_stop_seq_mode(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + if (sd_card->seq_mode) { + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + return; + + retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, + SD_RSP_TYPE_R1b, NULL, 0); + if (retval != STATUS_SUCCESS) + sd_set_err_code(chip, SD_STS_ERR); + + retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); + if (retval != STATUS_SUCCESS) + sd_set_err_code(chip, SD_STS_ERR); + + sd_card->seq_mode = 0; + + rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + } +} + +static inline int sd_auto_tune_clock(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + if (chip->asic_code) { + if (sd_card->sd_clock > 30) + sd_card->sd_clock -= 20; + } else { + switch (sd_card->sd_clock) { + case CLK_200: + sd_card->sd_clock = CLK_150; + break; + + case CLK_150: + sd_card->sd_clock = CLK_120; + break; + + case CLK_120: + sd_card->sd_clock = CLK_100; + break; + + case CLK_100: + sd_card->sd_clock = CLK_80; + break; + + case CLK_80: + sd_card->sd_clock = CLK_60; + break; + + case CLK_60: + sd_card->sd_clock = CLK_50; + break; + + default: + break; + } + } + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, + u16 sector_cnt) +{ + struct sd_info *sd_card = &(chip->sd_card); + u32 data_addr; + u8 cfg2; + int retval; + + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + RTSX_DEBUGP("sd_rw: Read %d %s from 0x%x\n", sector_cnt, + (sector_cnt > 1) ? "sectors" : "sector", start_sector); + } else { + RTSX_DEBUGP("sd_rw: Write %d %s to 0x%x\n", sector_cnt, + (sector_cnt > 1) ? "sectors" : "sector", start_sector); + } + + sd_card->cleanup_counter = 0; + + if (!(chip->card_ready & SD_CARD)) { + sd_card->seq_mode = 0; + + retval = reset_sd_card(chip); + if (retval == STATUS_SUCCESS) { + chip->card_ready |= SD_CARD; + chip->card_fail &= ~SD_CARD; + } else { + chip->card_ready &= ~SD_CARD; + chip->card_fail |= SD_CARD; + chip->capacity[chip->card2lun[SD_CARD]] = 0; + chip->rw_need_retry = 1; + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) + data_addr = start_sector << 9; + else + data_addr = start_sector; + + sd_clr_err_code(chip); + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_IO_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + if (sd_card->seq_mode && + ((sd_card->pre_dir != srb->sc_data_direction) || + ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != + start_sector))) { + if ((sd_card->pre_sec_cnt < 0x80) + && (sd_card->pre_dir == DMA_FROM_DEVICE) + && !CHK_SD30_SPEED(sd_card) + && !CHK_SD_HS(sd_card) + && !CHK_MMC_HS(sd_card)) { + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + } + + retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, + 0, SD_RSP_TYPE_R1b, NULL, 0); + if (retval != STATUS_SUCCESS) { + chip->rw_need_retry = 1; + sd_set_err_code(chip, SD_STS_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + sd_card->seq_mode = 0; + + retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); + if (retval != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_IO_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + if ((sd_card->pre_sec_cnt < 0x80) + && !CHK_SD30_SPEED(sd_card) + && !CHK_SD_HS(sd_card) + && !CHK_MMC_HS(sd_card)) { + sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0); + } + } + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, + (u8)sector_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, + (u8)(sector_cnt >> 8)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + + if (CHK_MMC_8BIT(sd_card)) + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, + 0x03, SD_BUS_WIDTH_8); + else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, + 0x03, SD_BUS_WIDTH_4); + else + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, + 0x03, SD_BUS_WIDTH_1); + + if (sd_card->seq_mode) { + cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16| + SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | + SD_RSP_LEN_0; + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); + + trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, + DMA_512); + + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_AUTO_READ_3 | SD_TRANSFER_START); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); + } + + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END, SD_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + } else { + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + RTSX_DEBUGP("SD/MMC CMD %d\n", READ_MULTIPLE_BLOCK); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, + 0x40 | READ_MULTIPLE_BLOCK); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, + (u8)(data_addr >> 24)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, + (u8)(data_addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, + (u8)(data_addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, + (u8)data_addr); + + cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | + SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | + SD_RSP_LEN_6; + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, + cfg2); + + trans_dma_enable(srb->sc_data_direction, chip, + sector_cnt * 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_AUTO_READ_2 | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END, SD_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + } else { + retval = rtsx_send_cmd(chip, SD_CARD, 50); + if (retval < 0) { + rtsx_clear_sd_error(chip); + + chip->rw_need_retry = 1; + sd_set_err_code(chip, SD_TO_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + retval = wait_data_buf_ready(chip); + if (retval != STATUS_SUCCESS) { + chip->rw_need_retry = 1; + sd_set_err_code(chip, SD_TO_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK, + data_addr, SD_RSP_TYPE_R1, NULL, 0); + if (retval != STATUS_SUCCESS) { + chip->rw_need_retry = 1; + TRACE_GOTO(chip, RW_FAIL); + } + + rtsx_init_cmd(chip); + + cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | + SD_NO_WAIT_BUSY_END | + SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, + cfg2); + + trans_dma_enable(srb->sc_data_direction, chip, + sector_cnt * 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END, SD_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + } + + sd_card->seq_mode = 1; + } + + retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), + scsi_bufflen(srb), scsi_sg_count(srb), + srb->sc_data_direction, chip->sd_timeout); + if (retval < 0) { + u8 stat = 0; + int err; + + sd_card->seq_mode = 0; + + if (retval == -ETIMEDOUT) + err = STATUS_TIMEDOUT; + else + err = STATUS_FAIL; + + rtsx_read_register(chip, REG_SD_STAT1, &stat); + rtsx_clear_sd_error(chip); + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + chip->rw_need_retry = 0; + RTSX_DEBUGP("No card exist, exit sd_rw\n"); + TRACE_RET(chip, STATUS_FAIL); + } + + chip->rw_need_retry = 1; + + retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, + SD_RSP_TYPE_R1b, NULL, 0); + if (retval != STATUS_SUCCESS) { + sd_set_err_code(chip, SD_STS_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) { + RTSX_DEBUGP("SD CRC error, tune clock!\n"); + sd_set_err_code(chip, SD_CRC_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + if (err == STATUS_TIMEDOUT) { + sd_set_err_code(chip, SD_TO_ERR); + TRACE_GOTO(chip, RW_FAIL); + } + + TRACE_RET(chip, err); + } + + sd_card->pre_sec_addr = start_sector; + sd_card->pre_sec_cnt = sector_cnt; + sd_card->pre_dir = srb->sc_data_direction; + + return STATUS_SUCCESS; + +RW_FAIL: + sd_card->seq_mode = 0; + + if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { + chip->rw_need_retry = 0; + RTSX_DEBUGP("No card exist, exit sd_rw\n"); + TRACE_RET(chip, STATUS_FAIL); + } + + if (sd_check_err_code(chip, SD_CRC_ERR)) { + if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) { + sd_card->mmc_dont_switch_bus = 1; + reset_mmc_only(chip); + sd_card->mmc_dont_switch_bus = 0; + } else { + sd_card->need_retune = 1; + sd_auto_tune_clock(chip); + } + } else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) { + retval = reset_sd_card(chip); + if (retval != STATUS_SUCCESS) { + chip->card_ready &= ~SD_CARD; + chip->card_fail |= SD_CARD; + chip->capacity[chip->card2lun[SD_CARD]] = 0; + } + } + + TRACE_RET(chip, STATUS_FAIL); +} + +#ifdef SUPPORT_CPRM +int soft_reset_sd_card(struct rtsx_chip *chip) +{ + return reset_sd(chip); +} + +int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, + u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check) +{ + int retval; + int timeout = 100; + u16 reg_addr; + u8 *ptr; + int stat_idx = 0; + int rty_cnt = 0; + + RTSX_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx); + + if (rsp_type == SD_RSP_TYPE_R1b) + timeout = 3000; + +RTY_SEND_CMD: + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, + 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, + SD_TRANSFER_END); + + if (rsp_type == SD_RSP_TYPE_R2) { + for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + + stat_idx = 17; + } else if (rsp_type != SD_RSP_TYPE_R0) { + for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); + + stat_idx = 6; + } + rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0); + + rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0); + + retval = rtsx_send_cmd(chip, SD_CARD, timeout); + if (retval < 0) { + if (retval == -ETIMEDOUT) { + rtsx_clear_sd_error(chip); + + if (rsp_type & SD_WAIT_BUSY_END) { + retval = sd_check_data0_status(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, retval); + } else { + sd_set_err_code(chip, SD_TO_ERR); + } + } + TRACE_RET(chip, STATUS_FAIL); + } + + if (rsp_type == SD_RSP_TYPE_R0) + return STATUS_SUCCESS; + + ptr = rtsx_get_cmd_data(chip) + 1; + + if ((ptr[0] & 0xC0) != 0) { + sd_set_err_code(chip, SD_STS_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + if (!(rsp_type & SD_NO_CHECK_CRC7)) { + if (ptr[stat_idx] & SD_CRC7_ERR) { + if (cmd_idx == WRITE_MULTIPLE_BLOCK) { + sd_set_err_code(chip, SD_CRC_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + if (rty_cnt < SD_MAX_RETRY_COUNT) { + wait_timeout(20); + rty_cnt++; + goto RTY_SEND_CMD; + } else { + sd_set_err_code(chip, SD_CRC_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) || + (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { + if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) { + if (ptr[1] & 0x80) + TRACE_RET(chip, STATUS_FAIL); + } +#ifdef SUPPORT_SD_LOCK + if (ptr[1] & 0x7D) +#else + if (ptr[1] & 0x7F) +#endif + { + TRACE_RET(chip, STATUS_FAIL); + } + if (ptr[2] & 0xF8) + TRACE_RET(chip, STATUS_FAIL); + + if (cmd_idx == SELECT_CARD) { + if (rsp_type == SD_RSP_TYPE_R2) { + if ((ptr[3] & 0x1E) != 0x04) + TRACE_RET(chip, STATUS_FAIL); + + } else if (rsp_type == SD_RSP_TYPE_R0) { + if ((ptr[3] & 0x1E) != 0x03) + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + if (rsp && rsp_len) + memcpy(rsp, ptr, rsp_len); + + return STATUS_SUCCESS; +} + +int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type) +{ + int retval, rsp_len; + u16 reg_addr; + + if (rsp_type == SD_RSP_TYPE_R0) + return STATUS_SUCCESS; + + rtsx_init_cmd(chip); + + if (rsp_type == SD_RSP_TYPE_R2) { + for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); + + rsp_len = 17; + } else if (rsp_type != SD_RSP_TYPE_R0) { + for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; + reg_addr++) + rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); + + rsp_len = 6; + } + rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0); + + retval = rtsx_send_cmd(chip, SD_CARD, 100); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (rsp) { + int min_len = (rsp_len < len) ? rsp_len : len; + + memcpy(rsp, rtsx_get_cmd_data(chip), min_len); + + RTSX_DEBUGP("min_len = %d\n", min_len); + RTSX_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n", + rsp[0], rsp[1], rsp[2], rsp[3]); + } + + return STATUS_SUCCESS; +} + +int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + int len; + u8 buf[18] = { + 0x00, + 0x00, + 0x00, + 0x0E, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x44, + 0x20, + 0x43, + 0x61, + 0x72, + 0x64, + 0x00, + 0x00, + 0x00, + }; + + sd_card->pre_cmd_err = 0; + + if (!(CHK_BIT(chip->lun_mc, lun))) { + SET_BIT(chip->lun_mc, lun); + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || + (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) || + (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) || + (0x64 != srb->cmnd[8])) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + switch (srb->cmnd[1] & 0x0F) { + case 0: + sd_card->sd_pass_thru_en = 0; + break; + + case 1: + sd_card->sd_pass_thru_en = 1; + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02; + if (chip->card_wp & SD_CARD) + buf[5] |= 0x80; + + buf[6] = (u8)(sd_card->sd_addr >> 16); + buf[7] = (u8)(sd_card->sd_addr >> 24); + + buf[15] = chip->max_lun; + + len = min_t(int, 18, scsi_bufflen(srb)); + rtsx_stor_set_xfer_buf(buf, len, srb); + + return TRANSPORT_GOOD; +} + +static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, + int *rsp_len) +{ + if (!rsp_type || !rsp_len) + return STATUS_FAIL; + + switch (srb->cmnd[10]) { + case 0x03: + *rsp_type = SD_RSP_TYPE_R0; + *rsp_len = 0; + break; + + case 0x04: + *rsp_type = SD_RSP_TYPE_R1; + *rsp_len = 6; + break; + + case 0x05: + *rsp_type = SD_RSP_TYPE_R1b; + *rsp_len = 6; + break; + + case 0x06: + *rsp_type = SD_RSP_TYPE_R2; + *rsp_len = 17; + break; + + case 0x07: + *rsp_type = SD_RSP_TYPE_R3; + *rsp_len = 6; + break; + + default: + return STATUS_FAIL; + } + + return STATUS_SUCCESS; +} + +int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + int retval, rsp_len; + u8 cmd_idx, rsp_type; + u8 standby = 0, acmd = 0; + u32 arg; + + if (!sd_card->sd_pass_thru_en) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + if (sd_card->pre_cmd_err) { + sd_card->pre_cmd_err = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + cmd_idx = srb->cmnd[2] & 0x3F; + if (srb->cmnd[1] & 0x02) + standby = 1; + + if (srb->cmnd[1] & 0x01) + acmd = 1; + + arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | + ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; + + retval = get_rsp_type(srb, &rsp_type, &rsp_len); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + sd_card->last_rsp_type = rsp_type; + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + +#ifdef SUPPORT_SD_LOCK + if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { + if (CHK_MMC_8BIT(sd_card)) { + retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, + SD_BUS_WIDTH_8); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { + retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, + SD_BUS_WIDTH_4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + } + } +#else + retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); +#endif + + if (standby) { + retval = sd_select_card(chip, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } + + if (acmd) { + retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } + + retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, + sd_card->rsp, rsp_len, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + + if (standby) { + retval = sd_select_card(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Cmd_Failed); + } + +#ifdef SUPPORT_SD_LOCK + retval = sd_update_lock_status(chip); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Cmd_Failed); +#endif + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; + +SD_Execute_Cmd_Failed: + sd_card->pre_cmd_err = 1; + set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); + release_sd_card(chip); + do_reset_sd_card(chip); + if (!(chip->card_ready & SD_CARD)) + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + + TRACE_RET(chip, TRANSPORT_FAILED); +} + +int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + int retval, rsp_len, i; + int cmd13_checkbit = 0, read_err = 0; + u8 cmd_idx, rsp_type, bus_width; + u8 send_cmd12 = 0, standby = 0, acmd = 0; + u32 data_len; + + if (!sd_card->sd_pass_thru_en) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (sd_card->pre_cmd_err) { + sd_card->pre_cmd_err = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + cmd_idx = srb->cmnd[2] & 0x3F; + if (srb->cmnd[1] & 0x04) + send_cmd12 = 1; + + if (srb->cmnd[1] & 0x02) + standby = 1; + + if (srb->cmnd[1] & 0x01) + acmd = 1; + + data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] + << 8) | srb->cmnd[9]; + + retval = get_rsp_type(srb, &rsp_type, &rsp_len); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + sd_card->last_rsp_type = rsp_type; + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + +#ifdef SUPPORT_SD_LOCK + if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { + if (CHK_MMC_8BIT(sd_card)) + bus_width = SD_BUS_WIDTH_8; + else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) + bus_width = SD_BUS_WIDTH_4; + else + bus_width = SD_BUS_WIDTH_1; + } else { + bus_width = SD_BUS_WIDTH_4; + } + RTSX_DEBUGP("bus_width = %d\n", bus_width); +#else + bus_width = SD_BUS_WIDTH_4; +#endif + + if (data_len < 512) { + retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + if (standby) { + retval = sd_select_card(chip, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + if (acmd) { + retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + if (data_len <= 512) { + int min_len; + u8 *buf; + u16 byte_cnt, blk_cnt; + u8 cmd[5]; + + byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9]; + blk_cnt = 1; + + cmd[0] = 0x40 | cmd_idx; + cmd[1] = srb->cmnd[3]; + cmd[2] = srb->cmnd[4]; + cmd[3] = srb->cmnd[5]; + cmd[4] = srb->cmnd[6]; + + buf = kmalloc(data_len, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, + blk_cnt, bus_width, buf, data_len, 2000); + if (retval != STATUS_SUCCESS) { + read_err = 1; + kfree(buf); + rtsx_clear_sd_error(chip); + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + min_len = min(data_len, scsi_bufflen(srb)); + rtsx_stor_set_xfer_buf(buf, min_len, srb); + + kfree(buf); + } else if (!(data_len & 0x1FF)) { + rtsx_init_cmd(chip); + + trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, + 0x02); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, + 0x00); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, + 0xFF, (srb->cmnd[7] & 0xFE) >> 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, + 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, + 0x40 | cmd_idx); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, + srb->cmnd[3]); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, + srb->cmnd[4]); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, + srb->cmnd[5]); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, + srb->cmnd[6]); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, + 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END, SD_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), + scsi_bufflen(srb), scsi_sg_count(srb), + DMA_FROM_DEVICE, 10000); + if (retval < 0) { + read_err = 1; + rtsx_clear_sd_error(chip); + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + } else { + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + + if (standby) { + retval = sd_select_card(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + if (send_cmd12) { + retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, + 0, SD_RSP_TYPE_R1b, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + if (data_len < 512) { + retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + + retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + + retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + } + + if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) + cmd13_checkbit = 1; + + for (i = 0; i < 3; i++) { + retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, + cmd13_checkbit); + if (retval == STATUS_SUCCESS) + break; + } + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; + +SD_Execute_Read_Cmd_Failed: + sd_card->pre_cmd_err = 1; + set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); + if (read_err) + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + + release_sd_card(chip); + do_reset_sd_card(chip); + if (!(chip->card_ready & SD_CARD)) + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + + TRACE_RET(chip, TRANSPORT_FAILED); +} + +int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + int retval, rsp_len, i; + int cmd13_checkbit = 0, write_err = 0; + u8 cmd_idx, rsp_type; + u8 send_cmd12 = 0, standby = 0, acmd = 0; + u32 data_len, arg; +#ifdef SUPPORT_SD_LOCK + int lock_cmd_fail = 0; + u8 sd_lock_state = 0; + u8 lock_cmd_type = 0; +#endif + + if (!sd_card->sd_pass_thru_en) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (sd_card->pre_cmd_err) { + sd_card->pre_cmd_err = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + cmd_idx = srb->cmnd[2] & 0x3F; + if (srb->cmnd[1] & 0x04) + send_cmd12 = 1; + + if (srb->cmnd[1] & 0x02) + standby = 1; + + if (srb->cmnd[1] & 0x01) + acmd = 1; + + data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] + << 8) | srb->cmnd[9]; + arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | + ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; + +#ifdef SUPPORT_SD_LOCK + if (cmd_idx == LOCK_UNLOCK) { + sd_lock_state = sd_card->sd_lock_status; + sd_lock_state &= SD_LOCKED; + } +#endif + + retval = get_rsp_type(srb, &rsp_type, &rsp_len); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + sd_card->last_rsp_type = rsp_type; + + retval = sd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + +#ifdef SUPPORT_SD_LOCK + if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { + if (CHK_MMC_8BIT(sd_card)) { + retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, + SD_BUS_WIDTH_8); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + + } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { + retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, + SD_BUS_WIDTH_4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); + } + } +#else + retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, TRANSPORT_FAILED); +#endif + + if (data_len < 512) { + retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + if (standby) { + retval = sd_select_card(chip, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + if (acmd) { + retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, + sd_card->rsp, rsp_len, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + + if (data_len <= 512) { + u16 i; + u8 *buf; + + buf = kmalloc(data_len, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, TRANSPORT_ERROR); + + rtsx_stor_get_xfer_buf(buf, data_len, srb); + +#ifdef SUPPORT_SD_LOCK + if (cmd_idx == LOCK_UNLOCK) + lock_cmd_type = buf[0] & 0x0F; +#endif + + if (data_len > 256) { + rtsx_init_cmd(chip); + for (i = 0; i < 256; i++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + PPBUF_BASE2 + i, 0xFF, buf[i]); + } + retval = rtsx_send_cmd(chip, 0, 250); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + rtsx_init_cmd(chip); + for (i = 256; i < data_len; i++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + PPBUF_BASE2 + i, 0xFF, buf[i]); + } + retval = rtsx_send_cmd(chip, 0, 250); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + } else { + rtsx_init_cmd(chip); + for (i = 0; i < data_len; i++) { + rtsx_add_cmd(chip, WRITE_REG_CMD, + PPBUF_BASE2 + i, 0xFF, buf[i]); + } + retval = rtsx_send_cmd(chip, 0, 250); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + } + + kfree(buf); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, + srb->cmnd[8] & 0x03); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, + srb->cmnd[9]); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, + 0x00); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, + 0x01); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, + PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END, SD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, SD_CARD, 250); + } else if (!(data_len & 0x1FF)) { + rtsx_init_cmd(chip); + + trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, + 0x02); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, + 0x00); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, + 0xFF, (srb->cmnd[7] & 0xFE) >> 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, + 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, + SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); + rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, + SD_TRANSFER_END, SD_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), + scsi_bufflen(srb), scsi_sg_count(srb), + DMA_TO_DEVICE, 10000); + + } else { + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + if (retval < 0) { + write_err = 1; + rtsx_clear_sd_error(chip); + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + +#ifdef SUPPORT_SD_LOCK + if (cmd_idx == LOCK_UNLOCK) { + if (lock_cmd_type == SD_ERASE) { + sd_card->sd_erase_status = SD_UNDER_ERASING; + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; + } + + rtsx_init_cmd(chip); + rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02); + + rtsx_send_cmd(chip, SD_CARD, 250); + + retval = sd_update_lock_status(chip); + if (retval != STATUS_SUCCESS) { + RTSX_DEBUGP("Lock command fail!\n"); + lock_cmd_fail = 1; + } + } +#endif /* SUPPORT_SD_LOCK */ + + if (standby) { + retval = sd_select_card(chip, 1); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + if (send_cmd12) { + retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, + 0, SD_RSP_TYPE_R1b, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + if (data_len < 512) { + retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, + SD_RSP_TYPE_R1, NULL, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + + retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + + rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + + if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) + cmd13_checkbit = 1; + + for (i = 0; i < 3; i++) { + retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, + sd_card->sd_addr, + SD_RSP_TYPE_R1, NULL, 0, + cmd13_checkbit); + if (retval == STATUS_SUCCESS) + break; + } + if (retval != STATUS_SUCCESS) + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + +#ifdef SUPPORT_SD_LOCK + if (cmd_idx == LOCK_UNLOCK) { + if (!lock_cmd_fail) { + RTSX_DEBUGP("lock_cmd_type = 0x%x\n", lock_cmd_type); + if (lock_cmd_type & SD_CLR_PWD) + sd_card->sd_lock_status &= ~SD_PWD_EXIST; + + if (lock_cmd_type & SD_SET_PWD) + sd_card->sd_lock_status |= SD_PWD_EXIST; + } + + RTSX_DEBUGP("sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n", + sd_lock_state, sd_card->sd_lock_status); + if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) { + sd_card->sd_lock_notify = 1; + if (sd_lock_state) { + if (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) { + sd_card->sd_lock_status |= ( + SD_UNLOCK_POW_ON | SD_SDR_RST); + if (CHK_SD(sd_card)) { + retval = reset_sd(chip); + if (retval != STATUS_SUCCESS) { + sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST); + TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); + } + } + + sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST); + } + } + } + } + + if (lock_cmd_fail) { + scsi_set_resid(srb, 0); + set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); + TRACE_RET(chip, TRANSPORT_FAILED); + } +#endif /* SUPPORT_SD_LOCK */ + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; + +SD_Execute_Write_Cmd_Failed: + sd_card->pre_cmd_err = 1; + set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); + if (write_err) + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); + + release_sd_card(chip); + do_reset_sd_card(chip); + if (!(chip->card_ready & SD_CARD)) + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + + TRACE_RET(chip, TRANSPORT_FAILED); +} + +int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + int count; + u16 data_len; + + if (!sd_card->sd_pass_thru_en) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (sd_card->pre_cmd_err) { + sd_card->pre_cmd_err = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8]; + + if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) { + count = (data_len < 17) ? data_len : 17; + } else { + count = (data_len < 6) ? data_len : 6; + } + rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb); + + RTSX_DEBUGP("Response length: %d\n", data_len); + RTSX_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n", sd_card->rsp[0], + sd_card->rsp[1], sd_card->rsp[2], sd_card->rsp[3]); + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; +} + +int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + unsigned int lun = SCSI_LUN(srb); + int retval; + + if (!sd_card->sd_pass_thru_en) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if (sd_card->pre_cmd_err) { + sd_card->pre_cmd_err = 0; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || + (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) || + (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) || + (0x64 != srb->cmnd[8])) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + switch (srb->cmnd[1] & 0x0F) { + case 0: +#ifdef SUPPORT_SD_LOCK + if (0x64 == srb->cmnd[9]) + sd_card->sd_lock_status |= SD_SDR_RST; +#endif + retval = reset_sd_card(chip); + if (retval != STATUS_SUCCESS) { +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status &= ~SD_SDR_RST; +#endif + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + sd_card->pre_cmd_err = 1; + TRACE_RET(chip, TRANSPORT_FAILED); + } +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status &= ~SD_SDR_RST; +#endif + break; + + case 1: + retval = soft_reset_sd_card(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + sd_card->pre_cmd_err = 1; + TRACE_RET(chip, TRANSPORT_FAILED); + } + break; + + default: + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); + TRACE_RET(chip, TRANSPORT_FAILED); + } + + scsi_set_resid(srb, 0); + return TRANSPORT_GOOD; +} +#endif + +void sd_cleanup_work(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + + if (sd_card->seq_mode) { + RTSX_DEBUGP("SD: stop transmission\n"); + sd_stop_seq_mode(chip); + sd_card->cleanup_counter = 0; + } +} + +int sd_power_off_card3v3(struct rtsx_chip *chip) +{ + int retval; + + retval = disable_card_clock(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0); + + if (!chip->ft2_fast_mode) { + retval = card_power_off(chip, SD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(50); + } + + if (chip->asic_code) { + retval = sd_pull_ctl_disable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, + FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT); + } + + return STATUS_SUCCESS; +} + +int release_sd_card(struct rtsx_chip *chip) +{ + struct sd_info *sd_card = &(chip->sd_card); + int retval; + + RTSX_DEBUGP("release_sd_card\n"); + + chip->card_ready &= ~SD_CARD; + chip->card_fail &= ~SD_CARD; + chip->card_wp &= ~SD_CARD; + + chip->sd_io = 0; + chip->sd_int = 0; + +#ifdef SUPPORT_SD_LOCK + sd_card->sd_lock_status = 0; + sd_card->sd_erase_status = 0; +#endif + + memset(sd_card->raw_csd, 0, 16); + memset(sd_card->raw_scr, 0, 8); + + retval = sd_power_off_card3v3(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} diff --git a/drivers/staging/rts5208/sd.h b/drivers/staging/rts5208/sd.h new file mode 100644 index 000000000000..735b2d0f5a78 --- /dev/null +++ b/drivers/staging/rts5208/sd.h @@ -0,0 +1,301 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_SD_H +#define __REALTEK_RTSX_SD_H + +#include "rtsx_chip.h" + +#define SUPPORT_VOLTAGE 0x003C0000 + +/* Error Code */ +#define SD_NO_ERROR 0x0 +#define SD_CRC_ERR 0x80 +#define SD_TO_ERR 0x40 +#define SD_NO_CARD 0x20 +#define SD_BUSY 0x10 +#define SD_STS_ERR 0x08 +#define SD_RSP_TIMEOUT 0x04 +#define SD_IO_ERR 0x02 + +/* Return code for MMC switch bus */ +#define SWITCH_SUCCESS 0 +#define SWITCH_ERR 1 +#define SWITCH_FAIL 2 + +/* MMC/SD Command Index */ +/* Basic command (class 0) */ +#define GO_IDLE_STATE 0 +#define SEND_OP_COND 1 +#define ALL_SEND_CID 2 +#define SET_RELATIVE_ADDR 3 +#define SEND_RELATIVE_ADDR 3 +#define SET_DSR 4 +#define IO_SEND_OP_COND 5 +#define SWITCH 6 +#define SELECT_CARD 7 +#define DESELECT_CARD 7 +/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec + * while is "SEND_IF_COND" for SD 2.0 + */ +#define SEND_EXT_CSD 8 +#define SEND_IF_COND 8 + +#define SEND_CSD 9 +#define SEND_CID 10 +#define VOLTAGE_SWITCH 11 +#define READ_DAT_UTIL_STOP 11 +#define STOP_TRANSMISSION 12 +#define SEND_STATUS 13 +#define GO_INACTIVE_STATE 15 + +#define SET_BLOCKLEN 16 +#define READ_SINGLE_BLOCK 17 +#define READ_MULTIPLE_BLOCK 18 +#define SEND_TUNING_PATTERN 19 + +#define BUSTEST_R 14 +#define BUSTEST_W 19 + +#define WRITE_BLOCK 24 +#define WRITE_MULTIPLE_BLOCK 25 +#define PROGRAM_CSD 27 + +#define ERASE_WR_BLK_START 32 +#define ERASE_WR_BLK_END 33 +#define ERASE_CMD 38 + +#define LOCK_UNLOCK 42 +#define IO_RW_DIRECT 52 + +#define APP_CMD 55 +#define GEN_CMD 56 + +#define SET_BUS_WIDTH 6 +#define SD_STATUS 13 +#define SEND_NUM_WR_BLOCKS 22 +#define SET_WR_BLK_ERASE_COUNT 23 +#define SD_APP_OP_COND 41 +#define SET_CLR_CARD_DETECT 42 +#define SEND_SCR 51 + +#define SD_READ_COMPLETE 0x00 +#define SD_READ_TO 0x01 +#define SD_READ_ADVENCE 0x02 + +#define SD_CHECK_MODE 0x00 +#define SD_SWITCH_MODE 0x80 +#define SD_FUNC_GROUP_1 0x01 +#define SD_FUNC_GROUP_2 0x02 +#define SD_FUNC_GROUP_3 0x03 +#define SD_FUNC_GROUP_4 0x04 +#define SD_CHECK_SPEC_V1_1 0xFF + +#define NO_ARGUMENT 0x00 +#define CHECK_PATTERN 0x000000AA +#define VOLTAGE_SUPPLY_RANGE 0x00000100 +#define SUPPORT_HIGH_AND_EXTENDED_CAPACITY 0x40000000 +#define SUPPORT_MAX_POWER_PERMANCE 0x10000000 +#define SUPPORT_1V8 0x01000000 + +#define SWTICH_NO_ERR 0x00 +#define CARD_NOT_EXIST 0x01 +#define SPEC_NOT_SUPPORT 0x02 +#define CHECK_MODE_ERR 0x03 +#define CHECK_NOT_READY 0x04 +#define SWITCH_CRC_ERR 0x05 +#define SWITCH_MODE_ERR 0x06 +#define SWITCH_PASS 0x07 + +#ifdef SUPPORT_SD_LOCK +#define SD_ERASE 0x08 +#define SD_LOCK 0x04 +#define SD_UNLOCK 0x00 +#define SD_CLR_PWD 0x02 +#define SD_SET_PWD 0x01 + +#define SD_PWD_LEN 0x10 + +#define SD_LOCKED 0x80 +#define SD_LOCK_1BIT_MODE 0x40 +#define SD_PWD_EXIST 0x20 +#define SD_UNLOCK_POW_ON 0x01 +#define SD_SDR_RST 0x02 + +#define SD_NOT_ERASE 0x00 +#define SD_UNDER_ERASING 0x01 +#define SD_COMPLETE_ERASE 0x02 + +#define SD_RW_FORBIDDEN 0x0F + +#endif + +#define HS_SUPPORT 0x01 +#define SDR50_SUPPORT 0x02 +#define SDR104_SUPPORT 0x03 +#define DDR50_SUPPORT 0x04 + +#define HS_SUPPORT_MASK 0x02 +#define SDR50_SUPPORT_MASK 0x04 +#define SDR104_SUPPORT_MASK 0x08 +#define DDR50_SUPPORT_MASK 0x10 + +#define HS_QUERY_SWITCH_OK 0x01 +#define SDR50_QUERY_SWITCH_OK 0x02 +#define SDR104_QUERY_SWITCH_OK 0x03 +#define DDR50_QUERY_SWITCH_OK 0x04 + +#define HS_SWITCH_BUSY 0x02 +#define SDR50_SWITCH_BUSY 0x04 +#define SDR104_SWITCH_BUSY 0x08 +#define DDR50_SWITCH_BUSY 0x10 + +#define FUNCTION_GROUP1_SUPPORT_OFFSET 0x0D +#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET 0x10 +#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET 0x1D + +#define DRIVING_TYPE_A 0x01 +#define DRIVING_TYPE_B 0x00 +#define DRIVING_TYPE_C 0x02 +#define DRIVING_TYPE_D 0x03 + +#define DRIVING_TYPE_A_MASK 0x02 +#define DRIVING_TYPE_B_MASK 0x01 +#define DRIVING_TYPE_C_MASK 0x04 +#define DRIVING_TYPE_D_MASK 0x08 + +#define TYPE_A_QUERY_SWITCH_OK 0x01 +#define TYPE_B_QUERY_SWITCH_OK 0x00 +#define TYPE_C_QUERY_SWITCH_OK 0x02 +#define TYPE_D_QUERY_SWITCH_OK 0x03 + +#define TYPE_A_SWITCH_BUSY 0x02 +#define TYPE_B_SWITCH_BUSY 0x01 +#define TYPE_C_SWITCH_BUSY 0x04 +#define TYPE_D_SWITCH_BUSY 0x08 + +#define FUNCTION_GROUP3_SUPPORT_OFFSET 0x09 +#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET 0x0F +#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET 0x19 + +#define CURRENT_LIMIT_200 0x00 +#define CURRENT_LIMIT_400 0x01 +#define CURRENT_LIMIT_600 0x02 +#define CURRENT_LIMIT_800 0x03 + +#define CURRENT_LIMIT_200_MASK 0x01 +#define CURRENT_LIMIT_400_MASK 0x02 +#define CURRENT_LIMIT_600_MASK 0x04 +#define CURRENT_LIMIT_800_MASK 0x08 + +#define CURRENT_LIMIT_200_QUERY_SWITCH_OK 0x00 +#define CURRENT_LIMIT_400_QUERY_SWITCH_OK 0x01 +#define CURRENT_LIMIT_600_QUERY_SWITCH_OK 0x02 +#define CURRENT_LIMIT_800_QUERY_SWITCH_OK 0x03 + +#define CURRENT_LIMIT_200_SWITCH_BUSY 0x01 +#define CURRENT_LIMIT_400_SWITCH_BUSY 0x02 +#define CURRENT_LIMIT_600_SWITCH_BUSY 0x04 +#define CURRENT_LIMIT_800_SWITCH_BUSY 0x08 + +#define FUNCTION_GROUP4_SUPPORT_OFFSET 0x07 +#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET 0x0F +#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET 0x17 + +#define DATA_STRUCTURE_VER_OFFSET 0x11 + +#define MAX_PHASE 31 + +#define MMC_8BIT_BUS 0x0010 +#define MMC_4BIT_BUS 0x0020 + +#define MMC_SWITCH_ERR 0x80 + +#define SD_IO_3V3 0 +#define SD_IO_1V8 1 + +#define TUNE_TX 0x00 +#define TUNE_RX 0x01 + +#define CHANGE_TX 0x00 +#define CHANGE_RX 0x01 + +#define DCM_HIGH_FREQUENCY_MODE 0x00 +#define DCM_LOW_FREQUENCY_MODE 0x01 + +#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C +#define DCM_Low_FREQUENCY_MODE_SET 0x00 + +#define MULTIPLY_BY_1 0x00 +#define MULTIPLY_BY_2 0x01 +#define MULTIPLY_BY_3 0x02 +#define MULTIPLY_BY_4 0x03 +#define MULTIPLY_BY_5 0x04 +#define MULTIPLY_BY_6 0x05 +#define MULTIPLY_BY_7 0x06 +#define MULTIPLY_BY_8 0x07 +#define MULTIPLY_BY_9 0x08 +#define MULTIPLY_BY_10 0x09 + +#define DIVIDE_BY_2 0x01 +#define DIVIDE_BY_3 0x02 +#define DIVIDE_BY_4 0x03 +#define DIVIDE_BY_5 0x04 +#define DIVIDE_BY_6 0x05 +#define DIVIDE_BY_7 0x06 +#define DIVIDE_BY_8 0x07 +#define DIVIDE_BY_9 0x08 +#define DIVIDE_BY_10 0x09 + +struct timing_phase_path { + int start; + int end; + int mid; + int len; +}; + +int sd_select_card(struct rtsx_chip *chip, int select); +int sd_pull_ctl_enable(struct rtsx_chip *chip); +int reset_sd_card(struct rtsx_chip *chip); +int sd_switch_clock(struct rtsx_chip *chip); +void sd_stop_seq_mode(struct rtsx_chip *chip); +int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 start_sector, u16 sector_cnt); +void sd_cleanup_work(struct rtsx_chip *chip); +int sd_power_off_card3v3(struct rtsx_chip *chip); +int release_sd_card(struct rtsx_chip *chip); +#ifdef SUPPORT_CPRM +int soft_reset_sd_card(struct rtsx_chip *chip); +int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, + u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check); +int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type); + +int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip); +#endif + +#endif /* __REALTEK_RTSX_SD_H */ diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c new file mode 100644 index 000000000000..312b9f9c6456 --- /dev/null +++ b/drivers/staging/rts5208/spi.c @@ -0,0 +1,877 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" +#include "spi.h" + +static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct spi_info *spi = &(chip->spi); + + spi->err_code = err_code; +} + +static int spi_init(struct rtsx_chip *chip) +{ + RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF, + CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | + SPI_AUTO); + RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF); + + return STATUS_SUCCESS; +} + +static int spi_set_init_para(struct rtsx_chip *chip) +{ + struct spi_info *spi = &(chip->spi); + int retval; + + RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8)); + RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div)); + + retval = switch_clock(chip, spi->spi_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = select_card(chip, SPI_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN); + RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN); + + wait_timeout(10); + + retval = spi_init(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int sf_polling_status(struct rtsx_chip *chip, int msec) +{ + int retval; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_POLLING_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, msec); + if (retval < 0) { + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_BUSY_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sf_enable_write(struct rtsx_chip *chip, u8 ins) +{ + struct spi_info *spi = &(chip->spi); + int retval; + + if (!spi->write_en) + return STATUS_SUCCESS; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_C_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) { + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int sf_disable_write(struct rtsx_chip *chip, u8 ins) +{ + struct spi_info *spi = &(chip->spi); + int retval; + + if (!spi->write_en) + return STATUS_SUCCESS; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_C_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) { + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr, + u16 len) +{ + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8)); + if (addr_mode) { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, + (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, + (u8)(addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CADO_MODE0); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CDO_MODE0); + } + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); +} + +static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr) +{ + int retval; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + if (addr_mode) { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, + (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, + (u8)(addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CA_MODE0); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_C_MODE0); + } + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) { + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int spi_init_eeprom(struct rtsx_chip *chip) +{ + int retval; + int clk; + + if (chip->asic_code) + clk = 30; + else + clk = CLK_30; + + RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00); + RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27); + + retval = switch_clock(chip, clk); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = select_card(chip, SPI_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN); + RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN); + + wait_timeout(10); + + RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF, + CS_POLARITY_HIGH | SPI_EEPROM_AUTO); + RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF); + + return STATUS_SUCCESS; +} + +static int spi_eeprom_program_enable(struct rtsx_chip *chip) +{ + int retval; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CA_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +int spi_erase_eeprom_chip(struct rtsx_chip *chip) +{ + int retval; + + retval = spi_init_eeprom(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = spi_eeprom_program_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CA_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01); + + return STATUS_SUCCESS; +} + +int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr) +{ + int retval; + + retval = spi_init_eeprom(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = spi_eeprom_program_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CA_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01); + + return STATUS_SUCCESS; +} + + +int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val) +{ + int retval; + u8 data; + + retval = spi_init_eeprom(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CADI_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(5); + RTSX_READ_REG(chip, SPI_DATA, &data); + + if (val) + *val = data; + + RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01); + + return STATUS_SUCCESS; +} + +int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val) +{ + int retval; + + retval = spi_init_eeprom(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = spi_eeprom_program_enable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CA_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01); + + return STATUS_SUCCESS; +} + + +int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct spi_info *spi = &(chip->spi); + + RTSX_DEBUGP("spi_get_status: err_code = 0x%x\n", spi->err_code); + rtsx_stor_set_xfer_buf(&(spi->err_code), + min_t(int, scsi_bufflen(srb), 1), srb); + scsi_set_resid(srb, scsi_bufflen(srb) - 1); + + return STATUS_SUCCESS; +} + +int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + struct spi_info *spi = &(chip->spi); + + spi_set_err_code(chip, SPI_NO_ERR); + + if (chip->asic_code) + spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9]; + else + spi->spi_clock = srb->cmnd[3]; + + spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; + spi->write_en = srb->cmnd[6]; + + RTSX_DEBUGP("spi_set_parameter: spi_clock = %d, clk_div = %d, write_en = %d\n", + spi->spi_clock, spi->clk_div, spi->write_en); + + return STATUS_SUCCESS; +} + +int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u16 len; + u8 *buf; + + spi_set_err_code(chip, SPI_NO_ERR); + + len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; + if (len > 512) { + spi_set_err_code(chip, SPI_INVALID_COMMAND); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = spi_set_init_para(chip); + if (retval != STATUS_SUCCESS) { + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, + PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]); + + if (len == 0) { + if (srb->cmnd[9]) { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, + 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, + 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0); + } + } else { + if (srb->cmnd[9]) { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CADI_MODE0); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CDI_MODE0); + } + } + + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) { + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + if (len) { + buf = kmalloc(len, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + retval = rtsx_read_ppbuf(chip, buf, len); + if (retval != STATUS_SUCCESS) { + spi_set_err_code(chip, SPI_READ_ERR); + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); + scsi_set_resid(srb, 0); + + kfree(buf); + } + + return STATUS_SUCCESS; +} + +int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + unsigned int index = 0, offset = 0; + u8 ins, slow_read; + u32 addr; + u16 len; + u8 *buf; + + spi_set_err_code(chip, SPI_NO_ERR); + + ins = srb->cmnd[3]; + addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) + << 8) | srb->cmnd[6]; + len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; + slow_read = srb->cmnd[9]; + + retval = spi_set_init_para(chip); + if (retval != STATUS_SUCCESS) { + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL); + if (buf == NULL) + TRACE_RET(chip, STATUS_ERROR); + + while (len) { + u16 pagelen = SF_PAGE_LEN - (u8)addr; + + if (pagelen > len) + pagelen = len; + + rtsx_init_cmd(chip); + + trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); + + if (slow_read) { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, + (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, + (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, + (u8)(addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, + (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, + (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF, + (u8)(addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32); + } + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, + (u8)(pagelen >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, + (u8)pagelen); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CADI_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, + SPI_TRANSFER0_END, SPI_TRANSFER0_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, + DMA_FROM_DEVICE, 10000); + if (retval < 0) { + kfree(buf); + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, + TO_XFER_BUF); + + addr += pagelen; + len -= pagelen; + } + + scsi_set_resid(srb, 0); + kfree(buf); + + return STATUS_SUCCESS; +} + +int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u8 ins, program_mode; + u32 addr; + u16 len; + u8 *buf; + unsigned int index = 0, offset = 0; + + spi_set_err_code(chip, SPI_NO_ERR); + + ins = srb->cmnd[3]; + addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) + << 8) | srb->cmnd[6]; + len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; + program_mode = srb->cmnd[9]; + + retval = spi_set_init_para(chip); + if (retval != STATUS_SUCCESS) { + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + if (program_mode == BYTE_PROGRAM) { + buf = kmalloc(4, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + while (len) { + retval = sf_enable_write(chip, SPI_WREN); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, + FROM_XFER_BUF); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, + buf[0]); + sf_program(chip, ins, 1, addr, 1); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) { + kfree(buf); + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sf_polling_status(chip, 100); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + addr++; + len--; + } + + kfree(buf); + + } else if (program_mode == AAI_PROGRAM) { + int first_byte = 1; + + retval = sf_enable_write(chip, SPI_WREN); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + buf = kmalloc(4, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_ERROR); + + while (len) { + rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, + FROM_XFER_BUF); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, + buf[0]); + if (first_byte) { + sf_program(chip, ins, 1, addr, 1); + first_byte = 0; + } else { + sf_program(chip, ins, 0, 0, 1); + } + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval < 0) { + kfree(buf); + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sf_polling_status(chip, 100); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + len--; + } + + kfree(buf); + + retval = sf_disable_write(chip, SPI_WRDI); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sf_polling_status(chip, 100); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else if (program_mode == PAGE_PROGRAM) { + buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL); + if (!buf) + TRACE_RET(chip, STATUS_NOMEM); + + while (len) { + u16 pagelen = SF_PAGE_LEN - (u8)addr; + + if (pagelen > len) + pagelen = len; + + retval = sf_enable_write(chip, SPI_WREN); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_init_cmd(chip); + + trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256); + sf_program(chip, ins, 1, addr, pagelen); + + rtsx_send_cmd_no_wait(chip); + + rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, + &offset, FROM_XFER_BUF); + + retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, + DMA_TO_DEVICE, 100); + if (retval < 0) { + kfree(buf); + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sf_polling_status(chip, 100); + if (retval != STATUS_SUCCESS) { + kfree(buf); + TRACE_RET(chip, STATUS_FAIL); + } + + addr += pagelen; + len -= pagelen; + } + + kfree(buf); + } else { + spi_set_err_code(chip, SPI_INVALID_COMMAND); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u8 ins, erase_mode; + u32 addr; + + spi_set_err_code(chip, SPI_NO_ERR); + + ins = srb->cmnd[3]; + addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) + << 8) | srb->cmnd[6]; + erase_mode = srb->cmnd[9]; + + retval = spi_set_init_para(chip); + if (retval != STATUS_SUCCESS) { + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + if (erase_mode == PAGE_ERASE) { + retval = sf_enable_write(chip, SPI_WREN); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sf_erase(chip, ins, 1, addr); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else if (erase_mode == CHIP_ERASE) { + retval = sf_enable_write(chip, SPI_WREN); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = sf_erase(chip, ins, 0, 0); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + spi_set_err_code(chip, SPI_INVALID_COMMAND); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) +{ + int retval; + u8 ins, status, ewsr; + + ins = srb->cmnd[3]; + status = srb->cmnd[4]; + ewsr = srb->cmnd[5]; + + retval = spi_set_init_para(chip); + if (retval != STATUS_SUCCESS) { + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = sf_enable_write(chip, ewsr); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, + PINGPONG_BUFFER); + + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, + SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status); + rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, + SPI_TRANSFER0_START | SPI_CDO_MODE0); + rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, + SPI_TRANSFER0_END); + + retval = rtsx_send_cmd(chip, 0, 100); + if (retval != STATUS_SUCCESS) { + rtsx_clear_spi_error(chip); + spi_set_err_code(chip, SPI_HW_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} diff --git a/drivers/staging/rts5208/spi.h b/drivers/staging/rts5208/spi.h new file mode 100644 index 000000000000..fc824b5d8d59 --- /dev/null +++ b/drivers/staging/rts5208/spi.h @@ -0,0 +1,65 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_SPI_H +#define __REALTEK_RTSX_SPI_H + +/* SPI operation error */ +#define SPI_NO_ERR 0x00 +#define SPI_HW_ERR 0x01 +#define SPI_INVALID_COMMAND 0x02 +#define SPI_READ_ERR 0x03 +#define SPI_WRITE_ERR 0x04 +#define SPI_ERASE_ERR 0x05 +#define SPI_BUSY_ERR 0x06 + +/* Serial flash instruction */ +#define SPI_READ 0x03 +#define SPI_FAST_READ 0x0B +#define SPI_WREN 0x06 +#define SPI_WRDI 0x04 +#define SPI_RDSR 0x05 + +#define SF_PAGE_LEN 256 + +#define BYTE_PROGRAM 0 +#define AAI_PROGRAM 1 +#define PAGE_PROGRAM 2 + +#define PAGE_ERASE 0 +#define CHIP_ERASE 1 + +int spi_erase_eeprom_chip(struct rtsx_chip *chip); +int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr); +int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val); +int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val); +int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); +int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip); + + +#endif /* __REALTEK_RTSX_SPI_H */ diff --git a/drivers/staging/rts5208/trace.h b/drivers/staging/rts5208/trace.h new file mode 100644 index 000000000000..0f177fbaaf1f --- /dev/null +++ b/drivers/staging/rts5208/trace.h @@ -0,0 +1,93 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_TRACE_H +#define __REALTEK_RTSX_TRACE_H + +#define _MSG_TRACE + +#ifdef _MSG_TRACE +static inline char *filename(char *path) +{ + char *ptr; + + if (path == NULL) + return NULL; + + ptr = path; + + while (*ptr != '\0') { + if ((*ptr == '\\') || (*ptr == '/')) + path = ptr + 1; + + ptr++; + } + + return path; +} + +#define TRACE_RET(chip, ret) \ + do { \ + char *_file = filename(__FILE__); \ + RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__); \ + (chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \ + strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1); \ + strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); \ + get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN); \ + (chip)->trace_msg[(chip)->msg_idx].valid = 1; \ + (chip)->msg_idx++; \ + if ((chip)->msg_idx >= TRACE_ITEM_CNT) { \ + (chip)->msg_idx = 0; \ + } \ + return ret; \ + } while (0) + +#define TRACE_GOTO(chip, label) \ + do { \ + char *_file = filename(__FILE__); \ + RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__); \ + (chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \ + strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1); \ + strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); \ + get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN); \ + (chip)->trace_msg[(chip)->msg_idx].valid = 1; \ + (chip)->msg_idx++; \ + if ((chip)->msg_idx >= TRACE_ITEM_CNT) { \ + (chip)->msg_idx = 0; \ + } \ + goto label; \ + } while (0) +#else +#define TRACE_RET(chip, ret) return ret +#define TRACE_GOTO(chip, label) goto label +#endif + +#ifdef CONFIG_RTS5208_DEBUG +#define RTSX_DUMP(buf, buf_len) \ + print_hex_dump(KERN_DEBUG, RTSX_STOR, DUMP_PREFIX_NONE, \ + 16, 1, (buf), (buf_len), false) +#else +#define RTSX_DUMP(buf, buf_len) +#endif + +#endif /* __REALTEK_RTSX_TRACE_H */ diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c new file mode 100644 index 000000000000..6aef53d14e31 --- /dev/null +++ b/drivers/staging/rts5208/xd.c @@ -0,0 +1,2088 @@ +/* Driver for Realtek PCI-Express card reader + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#include +#include +#include +#include + +#include "rtsx.h" +#include "rtsx_transport.h" +#include "rtsx_scsi.h" +#include "rtsx_card.h" +#include "xd.h" + +static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no); +static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, + u8 start_page, u8 end_page); + +static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct xd_info *xd_card = &(chip->xd_card); + + xd_card->err_code = err_code; +} + +static inline int xd_check_err_code(struct rtsx_chip *chip, u8 err_code) +{ + struct xd_info *xd_card = &(chip->xd_card); + + return (xd_card->err_code == err_code); +} + +static int xd_set_init_para(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval; + + if (chip->asic_code) + xd_card->xd_clock = 47; + else + xd_card->xd_clock = CLK_50; + + retval = switch_clock(chip, xd_card->xd_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int xd_switch_clock(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval; + + retval = select_card(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = switch_clock(chip, xd_card->xd_clock); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len) +{ + int retval, i; + u8 *ptr; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_READ_ID); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, + XD_TRANSFER_END); + + for (i = 0; i < 4; i++) + rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0); + + retval = rtsx_send_cmd(chip, XD_CARD, 20); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + ptr = rtsx_get_cmd_data(chip) + 1; + if (id_buf && buf_len) { + if (buf_len > 4) + buf_len = 4; + memcpy(id_buf, ptr, buf_len); + } + + return STATUS_SUCCESS; +} + +static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode) +{ + struct xd_info *xd_card = &(chip->xd_card); + + switch (mode) { + case XD_RW_ADDR: + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, + 0xFF, (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, + 0xFF, (u8)(addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, + xd_card->addr_cycle | XD_CALC_ECC | XD_BA_NO_TRANSFORM); + break; + + case XD_ERASE_ADDR: + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, + 0xFF, (u8)(addr >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, + 0xFF, (u8)(addr >> 16)); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, + (xd_card->addr_cycle - 1) | XD_CALC_ECC | + XD_BA_NO_TRANSFORM); + break; + + default: + break; + } +} + +static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, + u8 *buf, int buf_len) +{ + int retval, i; + + rtsx_init_cmd(chip); + + xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, + 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + for (i = 0; i < 6; i++) + rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i), + 0, 0); + for (i = 0; i < 4; i++) + rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i), + 0, 0); + rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0); + + retval = rtsx_send_cmd(chip, XD_CARD, 500); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + if (buf && buf_len) { + u8 *ptr = rtsx_get_cmd_data(chip) + 1; + + if (buf_len > 11) + buf_len = 11; + memcpy(buf, ptr, buf_len); + } + + return STATUS_SUCCESS; +} + +static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, + u8 *buf, int buf_len) +{ + int retval, i; + + if (!buf || (buf_len < 0)) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + for (i = 0; i < buf_len; i++) + rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, + 0, 0); + + retval = rtsx_send_cmd(chip, 0, 250); + if (retval < 0) { + rtsx_clear_xd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + memcpy(buf, rtsx_get_cmd_data(chip), buf_len); + + return STATUS_SUCCESS; +} + +static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf, + int buf_len) +{ + int retval; + u8 reg; + + if (!buf || (buf_len < 10)) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, + 0x01, PINGPONG_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, + XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_READ_PAGES); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, + XD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, XD_CARD, 250); + if (retval == -ETIMEDOUT) { + rtsx_clear_xd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_READ_REG(chip, XD_PAGE_STATUS, ®); + if (reg != XD_GPG) { + rtsx_clear_xd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + RTSX_READ_REG(chip, XD_CTL, ®); + if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) { + retval = xd_read_data_from_ppb(chip, 0, buf, buf_len); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + if (reg & XD_ECC1_ERROR) { + u8 ecc_bit, ecc_byte; + + RTSX_READ_REG(chip, XD_ECC_BIT1, &ecc_bit); + RTSX_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte); + + RTSX_DEBUGP("ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n", + ecc_bit, ecc_byte); + if (ecc_byte < buf_len) { + RTSX_DEBUGP("Before correct: 0x%x\n", + buf[ecc_byte]); + buf[ecc_byte] ^= (1 << ecc_bit); + RTSX_DEBUGP("After correct: 0x%x\n", + buf[ecc_byte]); + } + } + } else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) { + rtsx_clear_xd_error(chip); + + retval = xd_read_data_from_ppb(chip, 256, buf, buf_len); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + if (reg & XD_ECC2_ERROR) { + u8 ecc_bit, ecc_byte; + + RTSX_READ_REG(chip, XD_ECC_BIT2, &ecc_bit); + RTSX_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte); + + RTSX_DEBUGP("ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n", + ecc_bit, ecc_byte); + if (ecc_byte < buf_len) { + RTSX_DEBUGP("Before correct: 0x%x\n", + buf[ecc_byte]); + buf[ecc_byte] ^= (1 << ecc_bit); + RTSX_DEBUGP("After correct: 0x%x\n", + buf[ecc_byte]); + } + } + } else { + rtsx_clear_xd_error(chip); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip) +{ + if (CHECK_PID(chip, 0x5208)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, + XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, + XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, + XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, + XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, + MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, + 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, + 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, + 0xFF, 0x4B); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, + 0xFF, 0x69); + } + } +} + +static void xd_fill_pull_ctl_stage1_barossa(struct rtsx_chip *chip) +{ + if (CHECK_BARO_PKG(chip, QFN)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); + } +} + +static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip) +{ + if (CHECK_PID(chip, 0x5208)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, + XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, + XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, + XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, + XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, + MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, + 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, + 0xFF, 0x55); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, + 0xFF, 0x53); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, + 0xFF, 0xA9); + } + } +} + +static int xd_pull_ctl_disable(struct rtsx_chip *chip) +{ + if (CHECK_PID(chip, 0x5208)) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, + XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, + XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, + XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); + RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, + XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, + MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); + RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD); + } else if (CHECK_PID(chip, 0x5288)) { + if (CHECK_BARO_PKG(chip, QFN)) { + RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55); + RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55); + RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B); + RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69); + } + } + + return STATUS_SUCCESS; +} + +static int reset_xd(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval, i, j; + u8 *ptr, id_buf[4], redunt[11]; + + retval = select_card(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, + XD_PGSTS_NOT_FF); + if (chip->asic_code) { + if (!CHECK_PID(chip, 0x5288)) + xd_fill_pull_ctl_disable(chip); + else + xd_fill_pull_ctl_stage1_barossa(chip); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, + (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) | 0x20); + } + + if (!chip->ft2_fast_mode) + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT, + XD_NO_AUTO_PWR_OFF, 0); + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); + + retval = rtsx_send_cmd(chip, XD_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + if (!chip->ft2_fast_mode) { + retval = card_power_off(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(250); + + rtsx_init_cmd(chip); + + if (chip->asic_code) { + xd_fill_pull_ctl_enable(chip); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, + (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | + 0x20); + } + + retval = rtsx_send_cmd(chip, XD_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + retval = card_power_on(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + +#ifdef SUPPORT_OCP + wait_timeout(50); + if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { + RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", + chip->ocp_stat); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + } + + rtsx_init_cmd(chip); + + if (chip->ft2_fast_mode) { + if (chip->asic_code) { + xd_fill_pull_ctl_enable(chip); + } else { + rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, + (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | + 0x20); + } + } + + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, XD_OUTPUT_EN); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN); + + retval = rtsx_send_cmd(chip, XD_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + if (!chip->ft2_fast_mode) + wait_timeout(200); + + retval = xd_set_init_para(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + /* Read ID to check if the timing setting is right */ + for (i = 0; i < 4; i++) { + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF, + XD_TIME_SETUP_STEP * 3 + + XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF, + XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 + i) + + XD_TIME_RWN_STEP * (3 + i)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_RESET); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); + rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); + + retval = rtsx_send_cmd(chip, XD_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + ptr = rtsx_get_cmd_data(chip) + 1; + + RTSX_DEBUGP("XD_DAT: 0x%x, XD_CTL: 0x%x\n", ptr[0], ptr[1]); + + if (((ptr[0] & READY_FLAG) != READY_STATE) || + !(ptr[1] & XD_RDY)) + continue; + + retval = xd_read_id(chip, READ_ID, id_buf, 4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_DEBUGP("READ_ID: 0x%x 0x%x 0x%x 0x%x\n", + id_buf[0], id_buf[1], id_buf[2], id_buf[3]); + + xd_card->device_code = id_buf[1]; + + /* Check if the xD card is supported */ + switch (xd_card->device_code) { + case XD_4M_X8_512_1: + case XD_4M_X8_512_2: + xd_card->block_shift = 4; + xd_card->page_off = 0x0F; + xd_card->addr_cycle = 3; + xd_card->zone_cnt = 1; + xd_card->capacity = 8000; + XD_SET_4MB(xd_card); + break; + case XD_8M_X8_512: + xd_card->block_shift = 4; + xd_card->page_off = 0x0F; + xd_card->addr_cycle = 3; + xd_card->zone_cnt = 1; + xd_card->capacity = 16000; + break; + case XD_16M_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 3; + xd_card->zone_cnt = 1; + xd_card->capacity = 32000; + break; + case XD_32M_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 3; + xd_card->zone_cnt = 2; + xd_card->capacity = 64000; + break; + case XD_64M_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 4; + xd_card->zone_cnt = 4; + xd_card->capacity = 128000; + break; + case XD_128M_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 4; + xd_card->zone_cnt = 8; + xd_card->capacity = 256000; + break; + case XD_256M_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 4; + xd_card->zone_cnt = 16; + xd_card->capacity = 512000; + break; + case XD_512M_X8: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 4; + xd_card->zone_cnt = 32; + xd_card->capacity = 1024000; + break; + case xD_1G_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 4; + xd_card->zone_cnt = 64; + xd_card->capacity = 2048000; + break; + case xD_2G_X8_512: + XD_PAGE_512(xd_card); + xd_card->addr_cycle = 4; + xd_card->zone_cnt = 128; + xd_card->capacity = 4096000; + break; + default: + continue; + } + + /* Confirm timing setting */ + for (j = 0; j < 10; j++) { + retval = xd_read_id(chip, READ_ID, id_buf, 4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if (id_buf[1] != xd_card->device_code) + break; + } + + if (j == 10) + break; + } + + if (i == 4) { + xd_card->block_shift = 0; + xd_card->page_off = 0; + xd_card->addr_cycle = 0; + xd_card->capacity = 0; + + TRACE_RET(chip, STATUS_FAIL); + } + + retval = xd_read_id(chip, READ_xD_ID, id_buf, 4); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + RTSX_DEBUGP("READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n", + id_buf[0], id_buf[1], id_buf[2], id_buf[3]); + if (id_buf[2] != XD_ID_CODE) + TRACE_RET(chip, STATUS_FAIL); + + /* Search CIS block */ + for (i = 0; i < 24; i++) { + u32 page_addr; + + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + page_addr = (u32)i << xd_card->block_shift; + + for (j = 0; j < 3; j++) { + retval = xd_read_redundant(chip, page_addr, redunt, 11); + if (retval == STATUS_SUCCESS) + break; + } + if (j == 3) + continue; + + if (redunt[BLOCK_STATUS] != XD_GBLK) + continue; + + j = 0; + if (redunt[PAGE_STATUS] != XD_GPG) { + for (j = 1; j <= 8; j++) { + retval = xd_read_redundant(chip, page_addr + j, + redunt, 11); + if (retval == STATUS_SUCCESS) { + if (redunt[PAGE_STATUS] == XD_GPG) + break; + } + } + + if (j == 9) + break; + } + + /* Check CIS data */ + if ((redunt[BLOCK_STATUS] == XD_GBLK) && + (redunt[PARITY] & XD_BA1_ALL0)) { + u8 buf[10]; + + page_addr += j; + + retval = xd_read_cis(chip, page_addr, buf, 10); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + if ((buf[0] == 0x01) && (buf[1] == 0x03) && + (buf[2] == 0xD9) + && (buf[3] == 0x01) && (buf[4] == 0xFF) + && (buf[5] == 0x18) && (buf[6] == 0x02) + && (buf[7] == 0xDF) && (buf[8] == 0x01) + && (buf[9] == 0x20)) { + xd_card->cis_block = (u16)i; + } + } + + break; + } + + RTSX_DEBUGP("CIS block: 0x%x\n", xd_card->cis_block); + if (xd_card->cis_block == 0xFFFF) + TRACE_RET(chip, STATUS_FAIL); + + chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity; + + return STATUS_SUCCESS; +} + +static int xd_check_data_blank(u8 *redunt) +{ + int i; + + for (i = 0; i < 6; i++) { + if (redunt[PAGE_STATUS + i] != 0xFF) + return 0; + } + + if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) + != (XD_ECC1_ALL1 | XD_ECC2_ALL1)) + return 0; + + + for (i = 0; i < 4; i++) { + if (redunt[RESERVED0 + i] != 0xFF) + return 0; + } + + return 1; +} + +static u16 xd_load_log_block_addr(u8 *redunt) +{ + u16 addr = 0xFFFF; + + if (redunt[PARITY] & XD_BA1_BA2_EQL) + addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | + redunt[BLOCK_ADDR1_L]; + else if (redunt[PARITY] & XD_BA1_VALID) + addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | + redunt[BLOCK_ADDR1_L]; + else if (redunt[PARITY] & XD_BA2_VALID) + addr = ((u16)redunt[BLOCK_ADDR2_H] << 8) | + redunt[BLOCK_ADDR2_L]; + + return addr; +} + +static int xd_init_l2p_tbl(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int size, i; + + RTSX_DEBUGP("xd_init_l2p_tbl: zone_cnt = %d\n", xd_card->zone_cnt); + + if (xd_card->zone_cnt < 1) + TRACE_RET(chip, STATUS_FAIL); + + size = xd_card->zone_cnt * sizeof(struct zone_entry); + RTSX_DEBUGP("Buffer size for l2p table is %d\n", size); + + xd_card->zone = vmalloc(size); + if (!xd_card->zone) + TRACE_RET(chip, STATUS_ERROR); + + for (i = 0; i < xd_card->zone_cnt; i++) { + xd_card->zone[i].build_flag = 0; + xd_card->zone[i].l2p_table = NULL; + xd_card->zone[i].free_table = NULL; + xd_card->zone[i].get_index = 0; + xd_card->zone[i].set_index = 0; + xd_card->zone[i].unused_blk_cnt = 0; + } + + return STATUS_SUCCESS; +} + +static inline void free_zone(struct zone_entry *zone) +{ + RTSX_DEBUGP("free_zone\n"); + + if (!zone) + return; + + zone->build_flag = 0; + zone->set_index = 0; + zone->get_index = 0; + zone->unused_blk_cnt = 0; + if (zone->l2p_table) { + vfree(zone->l2p_table); + zone->l2p_table = NULL; + } + if (zone->free_table) { + vfree(zone->free_table); + zone->free_table = NULL; + } +} + +static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) +{ + struct xd_info *xd_card = &(chip->xd_card); + struct zone_entry *zone; + int zone_no; + + zone_no = (int)phy_blk >> 10; + if (zone_no >= xd_card->zone_cnt) { + RTSX_DEBUGP("Set unused block to invalid zone (zone_no = %d, zone_cnt = %d)\n", + zone_no, xd_card->zone_cnt); + return; + } + zone = &(xd_card->zone[zone_no]); + + if (zone->free_table == NULL) { + if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS) + return; + } + + if ((zone->set_index >= XD_FREE_TABLE_CNT) + || (zone->set_index < 0)) { + free_zone(zone); + RTSX_DEBUGP("Set unused block fail, invalid set_index\n"); + return; + } + + RTSX_DEBUGP("Set unused block to index %d\n", zone->set_index); + + zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff); + if (zone->set_index >= XD_FREE_TABLE_CNT) + zone->set_index = 0; + zone->unused_blk_cnt++; +} + +static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) +{ + struct xd_info *xd_card = &(chip->xd_card); + struct zone_entry *zone; + u32 phy_blk; + + if (zone_no >= xd_card->zone_cnt) { + RTSX_DEBUGP("Get unused block from invalid zone (zone_no = %d, zone_cnt = %d)\n", + zone_no, xd_card->zone_cnt); + return BLK_NOT_FOUND; + } + zone = &(xd_card->zone[zone_no]); + + if ((zone->unused_blk_cnt == 0) || + (zone->set_index == zone->get_index)) { + free_zone(zone); + RTSX_DEBUGP("Get unused block fail, no unused block available\n"); + return BLK_NOT_FOUND; + } + if ((zone->get_index >= XD_FREE_TABLE_CNT) || (zone->get_index < 0)) { + free_zone(zone); + RTSX_DEBUGP("Get unused block fail, invalid get_index\n"); + return BLK_NOT_FOUND; + } + + RTSX_DEBUGP("Get unused block from index %d\n", zone->get_index); + + phy_blk = zone->free_table[zone->get_index]; + zone->free_table[zone->get_index++] = 0xFFFF; + if (zone->get_index >= XD_FREE_TABLE_CNT) + zone->get_index = 0; + zone->unused_blk_cnt--; + + phy_blk += ((u32)(zone_no) << 10); + return phy_blk; +} + +static void xd_set_l2p_tbl(struct rtsx_chip *chip, + int zone_no, u16 log_off, u16 phy_off) +{ + struct xd_info *xd_card = &(chip->xd_card); + struct zone_entry *zone; + + zone = &(xd_card->zone[zone_no]); + zone->l2p_table[log_off] = phy_off; +} + +static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off) +{ + struct xd_info *xd_card = &(chip->xd_card); + struct zone_entry *zone; + int retval; + + zone = &(xd_card->zone[zone_no]); + if (zone->l2p_table[log_off] == 0xFFFF) { + u32 phy_blk = 0; + int i; + +#ifdef XD_DELAY_WRITE + retval = xd_delay_write(chip); + if (retval != STATUS_SUCCESS) { + RTSX_DEBUGP("In xd_get_l2p_tbl, delay write fail!\n"); + return BLK_NOT_FOUND; + } +#endif + + if (zone->unused_blk_cnt <= 0) { + RTSX_DEBUGP("No unused block!\n"); + return BLK_NOT_FOUND; + } + + for (i = 0; i < zone->unused_blk_cnt; i++) { + phy_blk = xd_get_unused_block(chip, zone_no); + if (phy_blk == BLK_NOT_FOUND) { + RTSX_DEBUGP("No unused block available!\n"); + return BLK_NOT_FOUND; + } + + retval = xd_init_page(chip, phy_blk, log_off, + 0, xd_card->page_off + 1); + if (retval == STATUS_SUCCESS) + break; + } + if (i >= zone->unused_blk_cnt) { + RTSX_DEBUGP("No good unused block available!\n"); + return BLK_NOT_FOUND; + } + + xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(phy_blk & 0x3FF)); + return phy_blk; + } + + return (u32)zone->l2p_table[log_off] + ((u32)(zone_no) << 10); +} + +int reset_xd_card(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval; + + memset(xd_card, 0, sizeof(struct xd_info)); + + xd_card->block_shift = 0; + xd_card->page_off = 0; + xd_card->addr_cycle = 0; + xd_card->capacity = 0; + xd_card->zone_cnt = 0; + xd_card->cis_block = 0xFFFF; + xd_card->delay_write.delay_write_flag = 0; + + retval = enable_card_clock(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = reset_xd(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + retval = xd_init_l2p_tbl(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval; + u32 page_addr; + u8 reg = 0; + + RTSX_DEBUGP("mark block 0x%x as bad block\n", phy_blk); + + if (phy_blk == BLK_NOT_FOUND) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_LATER_BBLK); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF); + + page_addr = phy_blk << xd_card->block_shift; + + xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, + xd_card->page_off + 1); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_WRITE_REDUNDANT); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, XD_CARD, 500); + if (retval < 0) { + rtsx_clear_xd_error(chip); + rtsx_read_register(chip, XD_DAT, ®); + if (reg & PROGRAM_ERROR) + xd_set_err_code(chip, XD_PRG_ERROR); + else + xd_set_err_code(chip, XD_TO_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, + u16 logoff, u8 start_page, u8 end_page) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval; + u32 page_addr; + u8 reg = 0; + + RTSX_DEBUGP("Init block 0x%x\n", phy_blk); + + if (start_page > end_page) + TRACE_RET(chip, STATUS_FAIL); + if (phy_blk == BLK_NOT_FOUND) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, + 0xFF, (u8)(logoff >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff); + + page_addr = (phy_blk << xd_card->block_shift) + start_page; + + xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, + XD_BA_TRANSFORM, XD_BA_TRANSFORM); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, + 0xFF, (end_page - start_page)); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, + 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, XD_CARD, 500); + if (retval < 0) { + rtsx_clear_xd_error(chip); + rtsx_read_register(chip, XD_DAT, ®); + if (reg & PROGRAM_ERROR) { + xd_mark_bad_block(chip, phy_blk); + xd_set_err_code(chip, XD_PRG_ERROR); + } else { + xd_set_err_code(chip, XD_TO_ERROR); + } + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + +static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, + u8 start_page, u8 end_page) +{ + struct xd_info *xd_card = &(chip->xd_card); + u32 old_page, new_page; + u8 i, reg = 0; + int retval; + + RTSX_DEBUGP("Copy page from block 0x%x to block 0x%x\n", + old_blk, new_blk); + + if (start_page > end_page) + TRACE_RET(chip, STATUS_FAIL); + + if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) + TRACE_RET(chip, STATUS_FAIL); + + old_page = (old_blk << xd_card->block_shift) + start_page; + new_page = (new_blk << xd_card->block_shift) + start_page; + + XD_CLR_BAD_NEWBLK(xd_card); + + RTSX_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); + + for (i = start_page; i < end_page; i++) { + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + rtsx_clear_xd_error(chip); + xd_set_err_code(chip, XD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + rtsx_init_cmd(chip); + + xd_assign_phy_addr(chip, old_page, XD_RW_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, + XD_AUTO_CHK_DATA_STATUS, 0); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_READ_PAGES); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, XD_CARD, 500); + if (retval < 0) { + rtsx_clear_xd_error(chip); + reg = 0; + rtsx_read_register(chip, XD_CTL, ®); + if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) { + wait_timeout(100); + + if (detect_card_cd(chip, + XD_CARD) != STATUS_SUCCESS) { + xd_set_err_code(chip, XD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + if (((reg & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) == + (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) + || ((reg & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) == + (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { + rtsx_write_register(chip, + XD_PAGE_STATUS, 0xFF, + XD_BPG); + rtsx_write_register(chip, + XD_BLOCK_STATUS, 0xFF, + XD_GBLK); + XD_SET_BAD_OLDBLK(xd_card); + RTSX_DEBUGP("old block 0x%x ecc error\n", old_blk); + } + } else { + xd_set_err_code(chip, XD_TO_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (XD_CHK_BAD_OLDBLK(xd_card)) + rtsx_clear_xd_error(chip); + + rtsx_init_cmd(chip); + + xd_assign_phy_addr(chip, new_page, XD_RW_ADDR); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_WRITE_PAGES); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, XD_CARD, 300); + if (retval < 0) { + rtsx_clear_xd_error(chip); + reg = 0; + rtsx_read_register(chip, XD_DAT, ®); + if (reg & PROGRAM_ERROR) { + xd_mark_bad_block(chip, new_blk); + xd_set_err_code(chip, XD_PRG_ERROR); + XD_SET_BAD_NEWBLK(xd_card); + } else { + xd_set_err_code(chip, XD_TO_ERROR); + } + TRACE_RET(chip, STATUS_FAIL); + } + + old_page++; + new_page++; + } + + return STATUS_SUCCESS; +} + +static int xd_reset_cmd(struct rtsx_chip *chip) +{ + int retval; + u8 *ptr; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, + 0xFF, XD_TRANSFER_START | XD_RESET); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); + rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); + + retval = rtsx_send_cmd(chip, XD_CARD, 100); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + ptr = rtsx_get_cmd_data(chip) + 1; + if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY)) + return STATUS_SUCCESS; + + TRACE_RET(chip, STATUS_FAIL); +} + +static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) +{ + struct xd_info *xd_card = &(chip->xd_card); + u32 page_addr; + u8 reg = 0, *ptr; + int i, retval; + + if (phy_blk == BLK_NOT_FOUND) + TRACE_RET(chip, STATUS_FAIL); + + page_addr = phy_blk << xd_card->block_shift; + + for (i = 0; i < 3; i++) { + rtsx_init_cmd(chip); + + xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_ERASE); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); + + retval = rtsx_send_cmd(chip, XD_CARD, 250); + if (retval < 0) { + rtsx_clear_xd_error(chip); + rtsx_read_register(chip, XD_DAT, ®); + if (reg & PROGRAM_ERROR) { + xd_mark_bad_block(chip, phy_blk); + xd_set_err_code(chip, XD_PRG_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } else { + xd_set_err_code(chip, XD_ERASE_FAIL); + } + retval = xd_reset_cmd(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + continue; + } + + ptr = rtsx_get_cmd_data(chip) + 1; + if (*ptr & PROGRAM_ERROR) { + xd_mark_bad_block(chip, phy_blk); + xd_set_err_code(chip, XD_PRG_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; + } + + xd_mark_bad_block(chip, phy_blk); + xd_set_err_code(chip, XD_ERASE_FAIL); + TRACE_RET(chip, STATUS_FAIL); +} + + +static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) +{ + struct xd_info *xd_card = &(chip->xd_card); + struct zone_entry *zone; + int retval; + u32 start, end, i; + u16 max_logoff, cur_fst_page_logoff; + u16 cur_lst_page_logoff, ent_lst_page_logoff; + u8 redunt[11]; + + RTSX_DEBUGP("xd_build_l2p_tbl: %d\n", zone_no); + + if (xd_card->zone == NULL) { + retval = xd_init_l2p_tbl(chip); + if (retval != STATUS_SUCCESS) + return retval; + } + + if (xd_card->zone[zone_no].build_flag) { + RTSX_DEBUGP("l2p table of zone %d has been built\n", zone_no); + return STATUS_SUCCESS; + } + + zone = &(xd_card->zone[zone_no]); + + if (zone->l2p_table == NULL) { + zone->l2p_table = vmalloc(2000); + if (zone->l2p_table == NULL) + TRACE_GOTO(chip, Build_Fail); + } + memset((u8 *)(zone->l2p_table), 0xff, 2000); + + if (zone->free_table == NULL) { + zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2); + if (zone->free_table == NULL) + TRACE_GOTO(chip, Build_Fail); + } + memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2); + + if (zone_no == 0) { + if (xd_card->cis_block == 0xFFFF) + start = 0; + else + start = xd_card->cis_block + 1; + if (XD_CHK_4MB(xd_card)) { + end = 0x200; + max_logoff = 499; + } else { + end = 0x400; + max_logoff = 999; + } + } else { + start = (u32)(zone_no) << 10; + end = (u32)(zone_no + 1) << 10; + max_logoff = 999; + } + + RTSX_DEBUGP("start block 0x%x, end block 0x%x\n", start, end); + + zone->set_index = zone->get_index = 0; + zone->unused_blk_cnt = 0; + + for (i = start; i < end; i++) { + u32 page_addr = i << xd_card->block_shift; + u32 phy_block; + + retval = xd_read_redundant(chip, page_addr, redunt, 11); + if (retval != STATUS_SUCCESS) + continue; + + if (redunt[BLOCK_STATUS] != 0xFF) { + RTSX_DEBUGP("bad block\n"); + continue; + } + + if (xd_check_data_blank(redunt)) { + RTSX_DEBUGP("blank block\n"); + xd_set_unused_block(chip, i); + continue; + } + + cur_fst_page_logoff = xd_load_log_block_addr(redunt); + if ((cur_fst_page_logoff == 0xFFFF) || + (cur_fst_page_logoff > max_logoff)) { + retval = xd_erase_block(chip, i); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, i); + continue; + } + + if ((zone_no == 0) && (cur_fst_page_logoff == 0) && + (redunt[PAGE_STATUS] != XD_GPG)) + XD_SET_MBR_FAIL(xd_card); + + if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) { + zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF); + continue; + } + + phy_block = zone->l2p_table[cur_fst_page_logoff] + + ((u32)((zone_no) << 10)); + + page_addr = ((i + 1) << xd_card->block_shift) - 1; + + retval = xd_read_redundant(chip, page_addr, redunt, 11); + if (retval != STATUS_SUCCESS) + continue; + + cur_lst_page_logoff = xd_load_log_block_addr(redunt); + if (cur_lst_page_logoff == cur_fst_page_logoff) { + int m; + + page_addr = ((phy_block + 1) << + xd_card->block_shift) - 1; + + for (m = 0; m < 3; m++) { + retval = xd_read_redundant(chip, page_addr, + redunt, 11); + if (retval == STATUS_SUCCESS) + break; + } + + if (m == 3) { + zone->l2p_table[cur_fst_page_logoff] = + (u16)(i & 0x3FF); + retval = xd_erase_block(chip, phy_block); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, phy_block); + continue; + } + + ent_lst_page_logoff = xd_load_log_block_addr(redunt); + if (ent_lst_page_logoff != cur_fst_page_logoff) { + zone->l2p_table[cur_fst_page_logoff] = + (u16)(i & 0x3FF); + retval = xd_erase_block(chip, phy_block); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, phy_block); + continue; + } else { + retval = xd_erase_block(chip, i); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, i); + } + } else { + retval = xd_erase_block(chip, i); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, i); + } + } + + if (XD_CHK_4MB(xd_card)) + end = 500; + else + end = 1000; + + i = 0; + for (start = 0; start < end; start++) { + if (zone->l2p_table[start] == 0xFFFF) + i++; + } + + RTSX_DEBUGP("Block count %d, invalid L2P entry %d\n", end, i); + RTSX_DEBUGP("Total unused block: %d\n", zone->unused_blk_cnt); + + if ((zone->unused_blk_cnt - i) < 1) + chip->card_wp |= XD_CARD; + + zone->build_flag = 1; + + return STATUS_SUCCESS; + +Build_Fail: + if (zone->l2p_table) { + vfree(zone->l2p_table); + zone->l2p_table = NULL; + } + if (zone->free_table) { + vfree(zone->free_table); + zone->free_table = NULL; + } + + return STATUS_FAIL; +} + +static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd) +{ + int retval; + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_SET_CMD); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + retval = rtsx_send_cmd(chip, XD_CARD, 200); + if (retval < 0) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} + +static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, + u32 log_blk, u8 start_page, u8 end_page, + u8 *buf, unsigned int *index, + unsigned int *offset) +{ + struct xd_info *xd_card = &(chip->xd_card); + u32 page_addr, new_blk; + u16 log_off; + u8 reg_val, page_cnt; + int zone_no, retval, i; + + if (start_page > end_page) + TRACE_RET(chip, STATUS_FAIL); + + page_cnt = end_page - start_page; + zone_no = (int)(log_blk / 1000); + log_off = (u16)(log_blk % 1000); + + if ((phy_blk & 0x3FF) == 0x3FF) { + for (i = 0; i < 256; i++) { + page_addr = ((u32)i) << xd_card->block_shift; + + retval = xd_read_redundant(chip, page_addr, NULL, 0); + if (retval == STATUS_SUCCESS) + break; + + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + xd_set_err_code(chip, XD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + } + } + + page_addr = (phy_blk << xd_card->block_shift) + start_page; + + rtsx_init_cmd(chip); + + xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, XD_PPB_TO_SIE); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, + XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); + + trans_dma_enable(chip->srb->sc_data_direction, chip, + page_cnt * 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, + XD_TRANSFER_START | XD_READ_PAGES); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END | XD_PPB_EMPTY, XD_TRANSFER_END | XD_PPB_EMPTY); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, + scsi_sg_count(chip->srb), + index, offset, DMA_FROM_DEVICE, + chip->xd_timeout); + if (retval < 0) { + rtsx_clear_xd_error(chip); + + if (retval == -ETIMEDOUT) { + xd_set_err_code(chip, XD_TO_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } else { + TRACE_GOTO(chip, Fail); + } + } + + return STATUS_SUCCESS; + +Fail: + RTSX_READ_REG(chip, XD_PAGE_STATUS, ®_val); + + if (reg_val != XD_GPG) + xd_set_err_code(chip, XD_PRG_ERROR); + + RTSX_READ_REG(chip, XD_CTL, ®_val); + + if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) + == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) + || ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) + == (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { + wait_timeout(100); + + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + xd_set_err_code(chip, XD_NO_CARD); + TRACE_RET(chip, STATUS_FAIL); + } + + xd_set_err_code(chip, XD_ECC_ERROR); + + new_blk = xd_get_unused_block(chip, zone_no); + if (new_blk == NO_NEW_BLK) { + XD_CLR_BAD_OLDBLK(xd_card); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = xd_copy_page(chip, phy_blk, new_blk, 0, + xd_card->page_off + 1); + if (retval != STATUS_SUCCESS) { + if (!XD_CHK_BAD_NEWBLK(xd_card)) { + retval = xd_erase_block(chip, new_blk); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, new_blk); + } else { + XD_CLR_BAD_NEWBLK(xd_card); + } + XD_CLR_BAD_OLDBLK(xd_card); + TRACE_RET(chip, STATUS_FAIL); + } + xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); + xd_erase_block(chip, phy_blk); + xd_mark_bad_block(chip, phy_blk); + XD_CLR_BAD_OLDBLK(xd_card); + } + + TRACE_RET(chip, STATUS_FAIL); +} + +static int xd_finish_write(struct rtsx_chip *chip, + u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval, zone_no; + u16 log_off; + + RTSX_DEBUGP("xd_finish_write, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n", + old_blk, new_blk, log_blk); + + if (page_off > xd_card->page_off) + TRACE_RET(chip, STATUS_FAIL); + + zone_no = (int)(log_blk / 1000); + log_off = (u16)(log_blk % 1000); + + if (old_blk == BLK_NOT_FOUND) { + retval = xd_init_page(chip, new_blk, log_off, + page_off, xd_card->page_off + 1); + if (retval != STATUS_SUCCESS) { + retval = xd_erase_block(chip, new_blk); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, new_blk); + TRACE_RET(chip, STATUS_FAIL); + } + } else { + retval = xd_copy_page(chip, old_blk, new_blk, + page_off, xd_card->page_off + 1); + if (retval != STATUS_SUCCESS) { + if (!XD_CHK_BAD_NEWBLK(xd_card)) { + retval = xd_erase_block(chip, new_blk); + if (retval == STATUS_SUCCESS) + xd_set_unused_block(chip, new_blk); + } + XD_CLR_BAD_NEWBLK(xd_card); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = xd_erase_block(chip, old_blk); + if (retval == STATUS_SUCCESS) { + if (XD_CHK_BAD_OLDBLK(xd_card)) { + xd_mark_bad_block(chip, old_blk); + XD_CLR_BAD_OLDBLK(xd_card); + } else { + xd_set_unused_block(chip, old_blk); + } + } else { + xd_set_err_code(chip, XD_NO_ERROR); + XD_CLR_BAD_OLDBLK(xd_card); + } + } + + xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); + + return STATUS_SUCCESS; +} + +static int xd_prepare_write(struct rtsx_chip *chip, + u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) +{ + int retval; + + RTSX_DEBUGP("%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x, page_off = %d\n", + __func__, old_blk, new_blk, log_blk, (int)page_off); + + if (page_off) { + retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} + + +static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, + u32 new_blk, u32 log_blk, u8 start_page, + u8 end_page, u8 *buf, unsigned int *index, + unsigned int *offset) +{ + struct xd_info *xd_card = &(chip->xd_card); + u32 page_addr; + int zone_no, retval; + u16 log_off; + u8 page_cnt, reg_val; + + RTSX_DEBUGP("%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n", + __func__, old_blk, new_blk, log_blk); + + if (start_page > end_page) + TRACE_RET(chip, STATUS_FAIL); + + page_cnt = end_page - start_page; + zone_no = (int)(log_blk / 1000); + log_off = (u16)(log_blk % 1000); + + page_addr = (new_blk << xd_card->block_shift) + start_page; + + retval = xd_send_cmd(chip, READ1_1); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + rtsx_init_cmd(chip); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, + 0xFF, (u8)(log_off >> 8)); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); + + xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, + XD_BA_TRANSFORM); + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); + rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); + + trans_dma_enable(chip->srb->sc_data_direction, chip, + page_cnt * 512, DMA_512); + + rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, + 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES); + rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, + XD_TRANSFER_END, XD_TRANSFER_END); + + rtsx_send_cmd_no_wait(chip); + + retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, + scsi_sg_count(chip->srb), + index, offset, DMA_TO_DEVICE, chip->xd_timeout); + if (retval < 0) { + rtsx_clear_xd_error(chip); + + if (retval == -ETIMEDOUT) { + xd_set_err_code(chip, XD_TO_ERROR); + TRACE_RET(chip, STATUS_FAIL); + } else { + TRACE_GOTO(chip, Fail); + } + } + + if (end_page == (xd_card->page_off + 1)) { + xd_card->delay_write.delay_write_flag = 0; + + if (old_blk != BLK_NOT_FOUND) { + retval = xd_erase_block(chip, old_blk); + if (retval == STATUS_SUCCESS) { + if (XD_CHK_BAD_OLDBLK(xd_card)) { + xd_mark_bad_block(chip, old_blk); + XD_CLR_BAD_OLDBLK(xd_card); + } else { + xd_set_unused_block(chip, old_blk); + } + } else { + xd_set_err_code(chip, XD_NO_ERROR); + XD_CLR_BAD_OLDBLK(xd_card); + } + } + xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); + } + + return STATUS_SUCCESS; + +Fail: + RTSX_READ_REG(chip, XD_DAT, ®_val); + if (reg_val & PROGRAM_ERROR) { + xd_set_err_code(chip, XD_PRG_ERROR); + xd_mark_bad_block(chip, new_blk); + } + + TRACE_RET(chip, STATUS_FAIL); +} + +#ifdef XD_DELAY_WRITE +int xd_delay_write(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); + int retval; + + if (delay_write->delay_write_flag) { + RTSX_DEBUGP("xd_delay_write\n"); + retval = xd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + delay_write->delay_write_flag = 0; + retval = xd_finish_write(chip, + delay_write->old_phyblock, + delay_write->new_phyblock, + delay_write->logblock, delay_write->pageoff); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } + + return STATUS_SUCCESS; +} +#endif + +int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 start_sector, u16 sector_cnt) +{ + struct xd_info *xd_card = &(chip->xd_card); + unsigned int lun = SCSI_LUN(srb); +#ifdef XD_DELAY_WRITE + struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); +#endif + int retval, zone_no; + unsigned int index = 0, offset = 0; + u32 log_blk, old_blk = 0, new_blk = 0; + u16 log_off, total_sec_cnt = sector_cnt; + u8 start_page, end_page = 0, page_cnt; + u8 *ptr; + + xd_set_err_code(chip, XD_NO_ERROR); + + xd_card->cleanup_counter = 0; + + RTSX_DEBUGP("xd_rw: scsi_sg_count = %d\n", scsi_sg_count(srb)); + + ptr = (u8 *)scsi_sglist(srb); + + retval = xd_switch_clock(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + chip->card_fail |= XD_CARD; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + + log_blk = start_sector >> xd_card->block_shift; + start_page = (u8)start_sector & xd_card->page_off; + zone_no = (int)(log_blk / 1000); + log_off = (u16)(log_blk % 1000); + + if (xd_card->zone[zone_no].build_flag == 0) { + retval = xd_build_l2p_tbl(chip, zone_no); + if (retval != STATUS_SUCCESS) { + chip->card_fail |= XD_CARD; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { +#ifdef XD_DELAY_WRITE + if (delay_write->delay_write_flag && + (delay_write->logblock == log_blk) && + (start_page > delay_write->pageoff)) { + delay_write->delay_write_flag = 0; + if (delay_write->old_phyblock != BLK_NOT_FOUND) { + retval = xd_copy_page(chip, + delay_write->old_phyblock, + delay_write->new_phyblock, + delay_write->pageoff, start_page); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + old_blk = delay_write->old_phyblock; + new_blk = delay_write->new_phyblock; + } else if (delay_write->delay_write_flag && + (delay_write->logblock == log_blk) && + (start_page == delay_write->pageoff)) { + delay_write->delay_write_flag = 0; + old_blk = delay_write->old_phyblock; + new_blk = delay_write->new_phyblock; + } else { + retval = xd_delay_write(chip); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); + new_blk = xd_get_unused_block(chip, zone_no); + if ((old_blk == BLK_NOT_FOUND) || + (new_blk == BLK_NOT_FOUND)) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = xd_prepare_write(chip, old_blk, new_blk, + log_blk, start_page); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, XD_CARD) != + STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#ifdef XD_DELAY_WRITE + } +#endif + } else { +#ifdef XD_DELAY_WRITE + retval = xd_delay_write(chip); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + + old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); + if (old_blk == BLK_NOT_FOUND) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + RTSX_DEBUGP("old_blk = 0x%x\n", old_blk); + + while (total_sec_cnt) { + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + chip->card_fail |= XD_CARD; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + + if ((start_page + total_sec_cnt) > (xd_card->page_off + 1)) + end_page = xd_card->page_off + 1; + else + end_page = start_page + (u8)total_sec_cnt; + + page_cnt = end_page - start_page; + if (srb->sc_data_direction == DMA_FROM_DEVICE) { + retval = xd_read_multiple_pages(chip, old_blk, log_blk, + start_page, end_page, ptr, + &index, &offset); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } else { + retval = xd_write_multiple_pages(chip, old_blk, + new_blk, log_blk, + start_page, end_page, ptr, + &index, &offset); + if (retval != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + total_sec_cnt -= page_cnt; + if (scsi_sg_count(srb) == 0) + ptr += page_cnt * 512; + + if (total_sec_cnt == 0) + break; + + log_blk++; + zone_no = (int)(log_blk / 1000); + log_off = (u16)(log_blk % 1000); + + if (xd_card->zone[zone_no].build_flag == 0) { + retval = xd_build_l2p_tbl(chip, zone_no); + if (retval != STATUS_SUCCESS) { + chip->card_fail |= XD_CARD; + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + } + + old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); + if (old_blk == BLK_NOT_FOUND) { + if (srb->sc_data_direction == DMA_FROM_DEVICE) + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); + else + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + + TRACE_RET(chip, STATUS_FAIL); + } + + if (srb->sc_data_direction == DMA_TO_DEVICE) { + new_blk = xd_get_unused_block(chip, zone_no); + if (new_blk == BLK_NOT_FOUND) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } + } + + start_page = 0; + } + + if ((srb->sc_data_direction == DMA_TO_DEVICE) && + (end_page != (xd_card->page_off + 1))) { +#ifdef XD_DELAY_WRITE + delay_write->delay_write_flag = 1; + delay_write->old_phyblock = old_blk; + delay_write->new_phyblock = new_blk; + delay_write->logblock = log_blk; + delay_write->pageoff = end_page; +#else + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + chip->card_fail |= XD_CARD; + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + + retval = xd_finish_write(chip, old_blk, new_blk, + log_blk, end_page); + if (retval != STATUS_SUCCESS) { + if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { + set_sense_type(chip, lun, + SENSE_TYPE_MEDIA_NOT_PRESENT); + TRACE_RET(chip, STATUS_FAIL); + } + set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); + TRACE_RET(chip, STATUS_FAIL); + } +#endif + } + + scsi_set_resid(srb, 0); + + return STATUS_SUCCESS; +} + +void xd_free_l2p_tbl(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int i = 0; + + if (xd_card->zone != NULL) { + for (i = 0; i < xd_card->zone_cnt; i++) { + if (xd_card->zone[i].l2p_table != NULL) { + vfree(xd_card->zone[i].l2p_table); + xd_card->zone[i].l2p_table = NULL; + } + if (xd_card->zone[i].free_table != NULL) { + vfree(xd_card->zone[i].free_table); + xd_card->zone[i].free_table = NULL; + } + } + vfree(xd_card->zone); + xd_card->zone = NULL; + } +} + +void xd_cleanup_work(struct rtsx_chip *chip) +{ +#ifdef XD_DELAY_WRITE + struct xd_info *xd_card = &(chip->xd_card); + + if (xd_card->delay_write.delay_write_flag) { + RTSX_DEBUGP("xD: delay write\n"); + xd_delay_write(chip); + xd_card->cleanup_counter = 0; + } +#endif +} + +int xd_power_off_card3v3(struct rtsx_chip *chip) +{ + int retval; + + retval = disable_card_clock(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + RTSX_WRITE_REG(chip, CARD_OE, XD_OUTPUT_EN, 0); + + if (!chip->ft2_fast_mode) { + retval = card_power_off(chip, XD_CARD); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + wait_timeout(50); + } + + if (chip->asic_code) { + retval = xd_pull_ctl_disable(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + } else { + RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, 0xDF); + } + + return STATUS_SUCCESS; +} + +int release_xd_card(struct rtsx_chip *chip) +{ + struct xd_info *xd_card = &(chip->xd_card); + int retval; + + RTSX_DEBUGP("release_xd_card\n"); + + chip->card_ready &= ~XD_CARD; + chip->card_fail &= ~XD_CARD; + chip->card_wp &= ~XD_CARD; + + xd_card->delay_write.delay_write_flag = 0; + + xd_free_l2p_tbl(chip); + + retval = xd_power_off_card3v3(chip); + if (retval != STATUS_SUCCESS) + TRACE_RET(chip, STATUS_FAIL); + + return STATUS_SUCCESS; +} diff --git a/drivers/staging/rts5208/xd.h b/drivers/staging/rts5208/xd.h new file mode 100644 index 000000000000..938138c50bb5 --- /dev/null +++ b/drivers/staging/rts5208/xd.h @@ -0,0 +1,188 @@ +/* Driver for Realtek PCI-Express card reader + * Header file + * + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, 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, see . + * + * Author: + * Wei WANG (wei_wang@realsil.com.cn) + * Micky Ching (micky_ching@realsil.com.cn) + */ + +#ifndef __REALTEK_RTSX_XD_H +#define __REALTEK_RTSX_XD_H + +#define XD_DELAY_WRITE + +/* Error Codes */ +#define XD_NO_ERROR 0x00 +#define XD_NO_MEMORY 0x80 +#define XD_PRG_ERROR 0x40 +#define XD_NO_CARD 0x20 +#define XD_READ_FAIL 0x10 +#define XD_ERASE_FAIL 0x08 +#define XD_WRITE_FAIL 0x04 +#define XD_ECC_ERROR 0x02 +#define XD_TO_ERROR 0x01 + +/* XD Commands */ +#define READ1_1 0x00 +#define READ1_2 0x01 +#define READ2 0x50 +#define READ_ID 0x90 +#define RESET 0xff +#define PAGE_PRG_1 0x80 +#define PAGE_PRG_2 0x10 +#define BLK_ERASE_1 0x60 +#define BLK_ERASE_2 0xD0 +#define READ_STS 0x70 +#define READ_xD_ID 0x9A +#define COPY_BACK_512 0x8A +#define COPY_BACK_2K 0x85 +#define READ1_1_2 0x30 +#define READ1_1_3 0x35 +#define CHG_DAT_OUT_1 0x05 +#define RDM_DAT_OUT_1 0x05 +#define CHG_DAT_OUT_2 0xE0 +#define RDM_DAT_OUT_2 0xE0 +#define CHG_DAT_OUT_2 0xE0 +#define CHG_DAT_IN_1 0x85 +#define CACHE_PRG 0x15 + +/* Redundant Area Related */ +#define XD_EXTRA_SIZE 0x10 +#define XD_2K_EXTRA_SIZE 0x40 + +#define NOT_WRITE_PROTECTED 0x80 +#define READY_STATE 0x40 +#define PROGRAM_ERROR 0x01 +#define PROGRAM_ERROR_N_1 0x02 +#define INTERNAL_READY 0x20 +#define READY_FLAG 0x5F + +#define XD_8M_X8_512 0xE6 +#define XD_16M_X8_512 0x73 +#define XD_32M_X8_512 0x75 +#define XD_64M_X8_512 0x76 +#define XD_128M_X8_512 0x79 +#define XD_256M_X8_512 0x71 +#define XD_128M_X8_2048 0xF1 +#define XD_256M_X8_2048 0xDA +#define XD_512M_X8 0xDC +#define XD_128M_X16_2048 0xC1 +#define XD_4M_X8_512_1 0xE3 +#define XD_4M_X8_512_2 0xE5 +#define xD_1G_X8_512 0xD3 +#define xD_2G_X8_512 0xD5 + +#define XD_ID_CODE 0xB5 + +#define VENDOR_BLOCK 0xEFFF +#define CIS_BLOCK 0xDFFF + +#define BLK_NOT_FOUND 0xFFFFFFFF + +#define NO_NEW_BLK 0xFFFFFFFF + +#define PAGE_CORRECTABLE 0x0 +#define PAGE_NOTCORRECTABLE 0x1 + +#define NO_OFFSET 0x0 +#define WITH_OFFSET 0x1 + +#define Sect_Per_Page 4 +#define XD_ADDR_MODE_2C XD_ADDR_MODE_2A + +#define ZONE0_BAD_BLOCK 23 +#define NOT_ZONE0_BAD_BLOCK 24 + +#define XD_RW_ADDR 0x01 +#define XD_ERASE_ADDR 0x02 + +#define XD_PAGE_512(xd_card) \ +do { \ + (xd_card)->block_shift = 5; \ + (xd_card)->page_off = 0x1F; \ +} while (0) + +#define XD_SET_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag |= 0x01) +#define XD_CLR_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag &= ~0x01) +#define XD_CHK_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag & 0x01) + +#define XD_SET_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag |= 0x02) +#define XD_CLR_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag &= ~0x02) +#define XD_CHK_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag & 0x02) + +#define XD_SET_MBR_FAIL(xd_card) ((xd_card)->multi_flag |= 0x04) +#define XD_CLR_MBR_FAIL(xd_card) ((xd_card)->multi_flag &= ~0x04) +#define XD_CHK_MBR_FAIL(xd_card) ((xd_card)->multi_flag & 0x04) + +#define XD_SET_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag |= 0x08) +#define XD_CLR_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag &= ~0x08) +#define XD_CHK_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag & 0x08) + +#define XD_SET_4MB(xd_card) ((xd_card)->multi_flag |= 0x10) +#define XD_CLR_4MB(xd_card) ((xd_card)->multi_flag &= ~0x10) +#define XD_CHK_4MB(xd_card) ((xd_card)->multi_flag & 0x10) + +#define XD_SET_ECC_ERR(xd_card) ((xd_card)->multi_flag |= 0x40) +#define XD_CLR_ECC_ERR(xd_card) ((xd_card)->multi_flag &= ~0x40) +#define XD_CHK_ECC_ERR(xd_card) ((xd_card)->multi_flag & 0x40) + +#define PAGE_STATUS 0 +#define BLOCK_STATUS 1 +#define BLOCK_ADDR1_L 2 +#define BLOCK_ADDR1_H 3 +#define BLOCK_ADDR2_L 4 +#define BLOCK_ADDR2_H 5 +#define RESERVED0 6 +#define RESERVED1 7 +#define RESERVED2 8 +#define RESERVED3 9 +#define PARITY 10 + +#define CIS0_0 0 +#define CIS0_1 1 +#define CIS0_2 2 +#define CIS0_3 3 +#define CIS0_4 4 +#define CIS0_5 5 +#define CIS0_6 6 +#define CIS0_7 7 +#define CIS0_8 8 +#define CIS0_9 9 +#define CIS1_0 256 +#define CIS1_1 (256 + 1) +#define CIS1_2 (256 + 2) +#define CIS1_3 (256 + 3) +#define CIS1_4 (256 + 4) +#define CIS1_5 (256 + 5) +#define CIS1_6 (256 + 6) +#define CIS1_7 (256 + 7) +#define CIS1_8 (256 + 8) +#define CIS1_9 (256 + 9) + +int reset_xd_card(struct rtsx_chip *chip); +#ifdef XD_DELAY_WRITE +int xd_delay_write(struct rtsx_chip *chip); +#endif +int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, + u32 start_sector, u16 sector_cnt); +void xd_free_l2p_tbl(struct rtsx_chip *chip); +void xd_cleanup_work(struct rtsx_chip *chip); +int xd_power_off_card3v3(struct rtsx_chip *chip); +int release_xd_card(struct rtsx_chip *chip); + +#endif /* __REALTEK_RTSX_XD_H */ -- cgit v1.2.3 From 9742e127cd0dd5783f8c11c62d07886003114499 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 12 Nov 2013 13:32:13 -0800 Subject: platform/chrome: Add pstore platform_device Add the ramoops pstore device so that we get logs of panics across reboots. Signed-off-by: Olof Johansson --- drivers/platform/chrome/Kconfig | 14 +++++ drivers/platform/chrome/Makefile | 1 + drivers/platform/chrome/chromeos_pstore.c | 101 ++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 drivers/platform/chrome/chromeos_pstore.c (limited to 'drivers') diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index b13303e75a34..440ed776efd4 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -25,4 +25,18 @@ config CHROMEOS_LAPTOP If you have a supported Chromebook, choose Y or M here. The module will be called chromeos_laptop. +config CHROMEOS_PSTORE + tristate "Chrome OS pstore support" + ---help--- + This module instantiates the persistent storage on x86 ChromeOS + devices. It can be used to store away console logs and crash + information across reboots. + + The range of memory used is 0xf00000-0x1000000, traditionally + the memory used to back VGA controller memory. + + If you have a supported Chromebook, choose Y or M here. + The module will be called chromeos_pstore. + + endif # CHROMEOS_PLATFORMS diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index 015e9195e226..2b860ca7450f 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o +obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c new file mode 100644 index 000000000000..e0e0e65cf442 --- /dev/null +++ b/drivers/platform/chrome/chromeos_pstore.c @@ -0,0 +1,101 @@ +/* + * chromeos_pstore.c - Driver to instantiate Chromebook ramoops device + * + * Copyright (C) 2013 Google, 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, version 2 of the License. + */ + +#include +#include +#include +#include + +static struct dmi_system_id chromeos_pstore_dmi_table[] __initdata = { + { + /* + * Today all Chromebooks/boxes ship with GOOGLE as vendor and + * coreboot as bios vendor. No other systems with this + * combination are known to date. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + }, + }, + { + /* + * The first Samsung Chromebox and Chromebook Series 5 550 use + * coreboot but with Samsung as the system vendor. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), + DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + }, + }, + { + /* x86-alex, the first Samsung Chromebook. */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), + }, + }, + { + /* x86-mario, the Cr-48 pilot device from Google. */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IEC"), + DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), + }, + }, + { + /* x86-zgb, the first Acer Chromebook. */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ACER"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), + }, + }, + { } +}; +MODULE_DEVICE_TABLE(dmi, chromeos_pstore_dmi_table); + +/* + * On x86 chromebooks/boxes, the firmware will keep the legacy VGA memory + * range untouched across reboots, so we use that to store our pstore + * contents for panic logs, etc. + */ +static struct ramoops_platform_data chromeos_ramoops_data = { + .mem_size = 0x100000, + .mem_address = 0xf00000, + .record_size = 0x20000, + .console_size = 0x20000, + .ftrace_size = 0x20000, + .dump_oops = 1, +}; + +static struct platform_device chromeos_ramoops = { + .name = "ramoops", + .dev = { + .platform_data = &chromeos_ramoops_data, + }, +}; + +static int __init chromeos_pstore_init(void) +{ + if (dmi_check_system(chromeos_pstore_dmi_table)) + return platform_device_register(&chromeos_ramoops); + + return -ENODEV; +} + +static void __exit chromeos_pstore_exit(void) +{ + platform_device_unregister(&chromeos_ramoops); +} + +module_init(chromeos_pstore_init); +module_exit(chromeos_pstore_exit); + +MODULE_DESCRIPTION("Chrome OS pstore module"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ec199dd57ef71858b53828283ac495ed82164933 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Sun, 20 Oct 2013 20:58:24 -0700 Subject: platform/chrome: chromeos_laptop - Restructure device associations The previous code had a single DMI matching entry for each device on a board. Instead provide a single DMI entry for each board which references a structure about each board that lists the associated peripherals. This allows for a lower number of DMI matching sequences as well making it easier to add new boards. Signed-off-by: Aaron Durbin Signed-off-by: Benson Leung Signed-off-by: Olof Johansson --- drivers/platform/chrome/chromeos_laptop.c | 197 +++++++++++++++++++----------- 1 file changed, 126 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 3e5b4497a1d0..5c69cfd97ff0 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -53,6 +53,17 @@ enum i2c_adapter_type { I2C_ADAPTER_PANEL, }; +struct i2c_peripheral { + void (*add)(enum i2c_adapter_type type); + enum i2c_adapter_type type; +}; + +#define MAX_I2C_PERIPHERALS 3 + +struct chromeos_laptop { + struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS]; +}; + static struct i2c_board_info __initdata cyapa_device = { I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), .flags = I2C_CLIENT_WAKE, @@ -233,149 +244,193 @@ static __init struct i2c_client *add_i2c_device(const char *name, addr_list); } - -static struct i2c_client __init *add_smbus_device(const char *name, - struct i2c_board_info *info) -{ - return add_i2c_device(name, I2C_ADAPTER_SMBUS, info); -} - -static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id) +static int __init setup_cyapa_tp(enum i2c_adapter_type type) { - /* add cyapa touchpad on smbus */ - tp = add_smbus_device("trackpad", &cyapa_device); + /* add cyapa touchpad */ + tp = add_i2c_device("trackpad", type, &cyapa_device); return 0; } -static int __init setup_atmel_224s_tp(const struct dmi_system_id *id) +static int __init setup_atmel_224s_tp(enum i2c_adapter_type type) { const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, ATMEL_TP_I2C_ADDR, I2C_CLIENT_END }; - /* add atmel mxt touchpad on VGA DDC GMBus */ - tp = add_probed_i2c_device("trackpad", I2C_ADAPTER_VGADDC, + /* add atmel mxt touchpad */ + tp = add_probed_i2c_device("trackpad", type, &atmel_224s_tp_device, addr_list); return 0; } -static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id) +static int __init setup_atmel_1664s_ts(enum i2c_adapter_type type) { const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, ATMEL_TS_I2C_ADDR, I2C_CLIENT_END }; - /* add atmel mxt touch device on PANEL GMBus */ - ts = add_probed_i2c_device("touchscreen", I2C_ADAPTER_PANEL, + /* add atmel mxt touch device */ + ts = add_probed_i2c_device("touchscreen", type, &atmel_1664s_device, addr_list); return 0; } - -static int __init setup_isl29018_als(const struct dmi_system_id *id) +static int __init setup_isl29018_als(enum i2c_adapter_type type) { /* add isl29018 light sensor */ - als = add_smbus_device("lightsensor", &isl_als_device); + als = add_i2c_device("lightsensor", type, &isl_als_device); return 0; } -static int __init setup_isl29023_als(const struct dmi_system_id *id) +static int __init setup_tsl2583_als(enum i2c_adapter_type type) { - /* add isl29023 light sensor on Panel GMBus */ - als = add_i2c_device("lightsensor", I2C_ADAPTER_PANEL, - &isl_als_device); + /* add tsl2583 light sensor */ + als = add_i2c_device(NULL, type, &tsl2583_als_device); return 0; } -static int __init setup_tsl2583_als(const struct dmi_system_id *id) +static int __init setup_tsl2563_als(enum i2c_adapter_type type) { - /* add tsl2583 light sensor on smbus */ - als = add_smbus_device(NULL, &tsl2583_als_device); + /* add tsl2563 light sensor */ + als = add_i2c_device(NULL, type, &tsl2563_als_device); return 0; } -static int __init setup_tsl2563_als(const struct dmi_system_id *id) +static int __init +chromeos_laptop_add_peripherals(const struct dmi_system_id *id) { - /* add tsl2563 light sensor on smbus */ - als = add_smbus_device(NULL, &tsl2563_als_device); - return 0; + int i; + struct chromeos_laptop *cros_laptop = (void *)id->driver_data; + + pr_debug("Adding peripherals for %s.\n", id->ident); + + for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + struct i2c_peripheral *i2c_dev; + + i2c_dev = &cros_laptop->i2c_peripherals[i]; + + /* No more peripherals. */ + if (i2c_dev->add == NULL) + break; + + /* Add the device. */ + i2c_dev->add(i2c_dev->type); + } + + /* Indicate to dmi_scan that processing is done. */ + return 1; } +static struct chromeos_laptop samsung_series_5_550 __initdata = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + /* Light Sensor. */ + { .add = setup_isl29018_als, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop samsung_series_5 __initdata = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop chromebook_pixel __initdata = { + .i2c_peripherals = { + /* Touch Screen. */ + { .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL }, + /* Touchpad. */ + { .add = setup_atmel_224s_tp, I2C_ADAPTER_VGADDC }, + /* Light Sensor. */ + { .add = setup_isl29018_als, I2C_ADAPTER_PANEL }, + }, +}; + +static struct chromeos_laptop acer_c7_chromebook __initdata = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop acer_ac700 __initdata = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop hp_pavilion_14_chromebook __initdata = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop cr48 __initdata = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, + }, +}; + +#define _CBDD(board_) \ + .callback = &chromeos_laptop_add_peripherals, \ + .driver_data = (void *)&board_ + static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { { - .ident = "Samsung Series 5 550 - Touchpad", + .ident = "Samsung Series 5 550", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), }, - .callback = setup_cyapa_smbus_tp, - }, - { - .ident = "Chromebook Pixel - Touchscreen", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), - DMI_MATCH(DMI_PRODUCT_NAME, "Link"), - }, - .callback = setup_atmel_1664s_ts, - }, - { - .ident = "Chromebook Pixel - Touchpad", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), - DMI_MATCH(DMI_PRODUCT_NAME, "Link"), - }, - .callback = setup_atmel_224s_tp, + _CBDD(samsung_series_5_550), }, { - .ident = "Samsung Series 5 550 - Light Sensor", + .ident = "Samsung Series 5", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), - DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), }, - .callback = setup_isl29018_als, + _CBDD(samsung_series_5), }, { - .ident = "Chromebook Pixel - Light Sensor", + .ident = "Chromebook Pixel", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Link"), }, - .callback = setup_isl29023_als, + _CBDD(chromebook_pixel), }, { - .ident = "Acer C7 Chromebook - Touchpad", + .ident = "Acer C7 Chromebook", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), }, - .callback = setup_cyapa_smbus_tp, + _CBDD(acer_c7_chromebook), }, { - .ident = "HP Pavilion 14 Chromebook - Touchpad", + .ident = "Acer AC700", .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), }, - .callback = setup_cyapa_smbus_tp, + _CBDD(acer_ac700), }, { - .ident = "Samsung Series 5 - Light Sensor", + .ident = "HP Pavilion 14 Chromebook", .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), + DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), }, - .callback = setup_tsl2583_als, + _CBDD(hp_pavilion_14_chromebook), }, { - .ident = "Cr-48 - Light Sensor", + .ident = "Cr-48", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), }, - .callback = setup_tsl2563_als, - }, - { - .ident = "Acer AC700 - Light Sensor", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), - }, - .callback = setup_tsl2563_als, + _CBDD(cr48), }, { } }; -- cgit v1.2.3 From 9ad3692458c387eb9537da73b2b75841ed7acdaf Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Sun, 20 Oct 2013 20:58:25 -0700 Subject: platform/chrome: chromeos_laptop - Use deferred probing Further refactor chromeos_laptop, adding a probe function. Init will call dmi_check_system, but will only use the match to select a chromeos_laptop structure of the current board. Probe will add the devices, and on errors return -EPROBE_DEFER. If i2c adapters are loaded after chromeos_laptop inits, the deferred probe will instantiate the peripherals when the bus appears. Signed-off-by: Benson Leung Reviewed-by: Aaron Durbin Signed-off-by: Olof Johansson --- drivers/platform/chrome/chromeos_laptop.c | 144 +++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 5c69cfd97ff0..e542330f8048 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -27,6 +27,7 @@ #include #include #include +#include #define ATMEL_TP_I2C_ADDR 0x4b #define ATMEL_TP_I2C_BL_ADDR 0x25 @@ -54,7 +55,7 @@ enum i2c_adapter_type { }; struct i2c_peripheral { - void (*add)(enum i2c_adapter_type type); + int (*add)(enum i2c_adapter_type type); enum i2c_adapter_type type; }; @@ -64,20 +65,22 @@ struct chromeos_laptop { struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS]; }; -static struct i2c_board_info __initdata cyapa_device = { +static struct chromeos_laptop *cros_laptop; + +static struct i2c_board_info cyapa_device = { I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), .flags = I2C_CLIENT_WAKE, }; -static struct i2c_board_info __initdata isl_als_device = { +static struct i2c_board_info isl_als_device = { I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }; -static struct i2c_board_info __initdata tsl2583_als_device = { +static struct i2c_board_info tsl2583_als_device = { I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), }; -static struct i2c_board_info __initdata tsl2563_als_device = { +static struct i2c_board_info tsl2563_als_device = { I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), }; @@ -100,7 +103,7 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = { .config_length = 0, }; -static struct i2c_board_info __initdata atmel_224s_tp_device = { +static struct i2c_board_info atmel_224s_tp_device = { I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), .platform_data = &atmel_224s_tp_platform_data, .flags = I2C_CLIENT_WAKE, @@ -121,13 +124,13 @@ static struct mxt_platform_data atmel_1664s_platform_data = { .config_length = 0, }; -static struct i2c_board_info __initdata atmel_1664s_device = { +static struct i2c_board_info atmel_1664s_device = { I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), .platform_data = &atmel_1664s_platform_data, .flags = I2C_CLIENT_WAKE, }; -static struct i2c_client __init *__add_probed_i2c_device( +static struct i2c_client *__add_probed_i2c_device( const char *name, int bus, struct i2c_board_info *info, @@ -180,7 +183,7 @@ static struct i2c_client __init *__add_probed_i2c_device( return client; } -static int __init __find_i2c_adap(struct device *dev, void *data) +static int __find_i2c_adap(struct device *dev, void *data) { const char *name = data; static const char *prefix = "i2c-"; @@ -191,7 +194,7 @@ static int __init __find_i2c_adap(struct device *dev, void *data) return (strncmp(adapter->name, name, strlen(name)) == 0); } -static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +static int find_i2c_adapter_num(enum i2c_adapter_type type) { struct device *dev = NULL; struct i2c_adapter *adapter; @@ -200,8 +203,9 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type) dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, __find_i2c_adap); if (!dev) { - pr_err("%s: i2c adapter %s not found on system.\n", __func__, - name); + /* Adapters may appear later. Deferred probing will retry */ + pr_notice("%s: i2c adapter %s not found on system.\n", __func__, + name); return -ENODEV; } adapter = to_i2c_adapter(dev); @@ -216,7 +220,7 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type) * Returns NULL if no devices found. * See Documentation/i2c/instantiating-devices for more information. */ -static __init struct i2c_client *add_probed_i2c_device( +static struct i2c_client *add_probed_i2c_device( const char *name, enum i2c_adapter_type type, struct i2c_board_info *info, @@ -233,7 +237,7 @@ static __init struct i2c_client *add_probed_i2c_device( * info->addr. * Returns NULL if no device found. */ -static __init struct i2c_client *add_i2c_device(const char *name, +static struct i2c_client *add_i2c_device(const char *name, enum i2c_adapter_type type, struct i2c_board_info *info) { @@ -244,65 +248,87 @@ static __init struct i2c_client *add_i2c_device(const char *name, addr_list); } -static int __init setup_cyapa_tp(enum i2c_adapter_type type) +static int setup_cyapa_tp(enum i2c_adapter_type type) { + if (tp) + return 0; + /* add cyapa touchpad */ tp = add_i2c_device("trackpad", type, &cyapa_device); - return 0; + return (!tp) ? -EAGAIN : 0; } -static int __init setup_atmel_224s_tp(enum i2c_adapter_type type) +static int setup_atmel_224s_tp(enum i2c_adapter_type type) { const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, ATMEL_TP_I2C_ADDR, I2C_CLIENT_END }; + if (tp) + return 0; /* add atmel mxt touchpad */ tp = add_probed_i2c_device("trackpad", type, &atmel_224s_tp_device, addr_list); - return 0; + return (!tp) ? -EAGAIN : 0; } -static int __init setup_atmel_1664s_ts(enum i2c_adapter_type type) +static int setup_atmel_1664s_ts(enum i2c_adapter_type type) { const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, ATMEL_TS_I2C_ADDR, I2C_CLIENT_END }; + if (ts) + return 0; /* add atmel mxt touch device */ ts = add_probed_i2c_device("touchscreen", type, &atmel_1664s_device, addr_list); - return 0; + return (!ts) ? -EAGAIN : 0; } -static int __init setup_isl29018_als(enum i2c_adapter_type type) +static int setup_isl29018_als(enum i2c_adapter_type type) { + if (als) + return 0; + /* add isl29018 light sensor */ als = add_i2c_device("lightsensor", type, &isl_als_device); - return 0; + return (!als) ? -EAGAIN : 0; } -static int __init setup_tsl2583_als(enum i2c_adapter_type type) +static int setup_tsl2583_als(enum i2c_adapter_type type) { + if (als) + return 0; + /* add tsl2583 light sensor */ als = add_i2c_device(NULL, type, &tsl2583_als_device); - return 0; + return (!als) ? -EAGAIN : 0; } -static int __init setup_tsl2563_als(enum i2c_adapter_type type) +static int setup_tsl2563_als(enum i2c_adapter_type type) { + if (als) + return 0; + /* add tsl2563 light sensor */ als = add_i2c_device(NULL, type, &tsl2563_als_device); - return 0; + return (!als) ? -EAGAIN : 0; } -static int __init -chromeos_laptop_add_peripherals(const struct dmi_system_id *id) +static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) { - int i; - struct chromeos_laptop *cros_laptop = (void *)id->driver_data; + cros_laptop = (void *)id->driver_data; + pr_debug("DMI Matched %s.\n", id->ident); - pr_debug("Adding peripherals for %s.\n", id->ident); + /* Indicate to dmi_scan that processing is done. */ + return 1; +} + +static int chromeos_laptop_probe(struct platform_device *pdev) +{ + int i; + int ret = 0; for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { struct i2c_peripheral *i2c_dev; @@ -313,15 +339,15 @@ chromeos_laptop_add_peripherals(const struct dmi_system_id *id) if (i2c_dev->add == NULL) break; - /* Add the device. */ - i2c_dev->add(i2c_dev->type); + /* Add the device. Set -EPROBE_DEFER on any failure */ + if (i2c_dev->add(i2c_dev->type)) + ret = -EPROBE_DEFER; } - /* Indicate to dmi_scan that processing is done. */ - return 1; + return ret; } -static struct chromeos_laptop samsung_series_5_550 __initdata = { +static struct chromeos_laptop samsung_series_5_550 = { .i2c_peripherals = { /* Touchpad. */ { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, @@ -330,14 +356,14 @@ static struct chromeos_laptop samsung_series_5_550 __initdata = { }, }; -static struct chromeos_laptop samsung_series_5 __initdata = { +static struct chromeos_laptop samsung_series_5 = { .i2c_peripherals = { /* Light Sensor. */ { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS }, }, }; -static struct chromeos_laptop chromebook_pixel __initdata = { +static struct chromeos_laptop chromebook_pixel = { .i2c_peripherals = { /* Touch Screen. */ { .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL }, @@ -348,28 +374,28 @@ static struct chromeos_laptop chromebook_pixel __initdata = { }, }; -static struct chromeos_laptop acer_c7_chromebook __initdata = { +static struct chromeos_laptop acer_c7_chromebook = { .i2c_peripherals = { /* Touchpad. */ { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, }, }; -static struct chromeos_laptop acer_ac700 __initdata = { +static struct chromeos_laptop acer_ac700 = { .i2c_peripherals = { /* Light Sensor. */ { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, }, }; -static struct chromeos_laptop hp_pavilion_14_chromebook __initdata = { +static struct chromeos_laptop hp_pavilion_14_chromebook = { .i2c_peripherals = { /* Touchpad. */ { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, }, }; -static struct chromeos_laptop cr48 __initdata = { +static struct chromeos_laptop cr48 = { .i2c_peripherals = { /* Light Sensor. */ { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, @@ -377,7 +403,7 @@ static struct chromeos_laptop cr48 __initdata = { }; #define _CBDD(board_) \ - .callback = &chromeos_laptop_add_peripherals, \ + .callback = chromeos_laptop_dmi_matched, \ .driver_data = (void *)&board_ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { @@ -436,13 +462,45 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { }; MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); +static struct platform_device *cros_platform_device; + +static struct platform_driver cros_platform_driver = { + .driver = { + .name = "chromeos_laptop", + .owner = THIS_MODULE, + }, + .probe = chromeos_laptop_probe, +}; + static int __init chromeos_laptop_init(void) { + int ret; if (!dmi_check_system(chromeos_laptop_dmi_table)) { pr_debug("%s unsupported system.\n", __func__); return -ENODEV; } + + ret = platform_driver_register(&cros_platform_driver); + if (ret) + return ret; + + cros_platform_device = platform_device_alloc("chromeos_laptop", -1); + if (!cros_platform_device) { + ret = -ENOMEM; + goto fail_platform_device1; + } + + ret = platform_device_add(cros_platform_device); + if (ret) + goto fail_platform_device2; + return 0; + +fail_platform_device2: + platform_device_put(cros_platform_device); +fail_platform_device1: + platform_driver_unregister(&cros_platform_driver); + return ret; } static void __exit chromeos_laptop_exit(void) -- cgit v1.2.3 From cdddd23fa2536cd4273e95d66b6ef83e67b747bf Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Sun, 20 Oct 2013 20:58:26 -0700 Subject: platform/chrome: chromeos_laptop - fix incorrect placement of __initdata tag __initdata tag should be placed between the variable name and equal sign for the variable to be placed in the intended .init.data section. Signed-off-by: Benson Leung Signed-off-by: Olof Johansson --- drivers/platform/chrome/chromeos_laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index e542330f8048..1c2747f119d1 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -406,7 +406,7 @@ static struct chromeos_laptop cr48 = { .callback = chromeos_laptop_dmi_matched, \ .driver_data = (void *)&board_ -static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { +static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = { { .ident = "Samsung Series 5 550", .matches = { -- cgit v1.2.3 From 3088f1085d1c08f31f02db26796555a66cdf7ca1 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 25 Nov 2013 15:31:21 +0530 Subject: usb: dwc3: invoke phy_resume after phy_init usb_phy_set_suspend(phy, 0) is called before usb_phy_init. Fix it. Reported-by: Roger Quadros Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 74f9cf02da07..4dd1f7e2edc8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -455,9 +455,6 @@ static int dwc3_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - usb_phy_set_suspend(dwc->usb2_phy, 0); - usb_phy_set_suspend(dwc->usb3_phy, 0); - spin_lock_init(&dwc->lock); platform_set_drvdata(pdev, dwc); @@ -488,6 +485,9 @@ static int dwc3_probe(struct platform_device *pdev) goto err0; } + usb_phy_set_suspend(dwc->usb2_phy, 0); + usb_phy_set_suspend(dwc->usb3_phy, 0); + ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); -- cgit v1.2.3 From 501fae512584e601d34945efccd35c5e5d759132 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 25 Nov 2013 15:31:22 +0530 Subject: usb: dwc3: power off usb phy in error path usb phy was power'ed on but was never power'ed off in the error path. Fix it. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 4dd1f7e2edc8..a49217ae3533 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -569,6 +569,8 @@ err2: dwc3_event_buffers_cleanup(dwc); err1: + usb_phy_set_suspend(dwc->usb2_phy, 1); + usb_phy_set_suspend(dwc->usb3_phy, 1); dwc3_core_exit(dwc); err0: -- cgit v1.2.3 From 6d3c1afe7367447c8f7d2fec7a132f723834efd1 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 25 Nov 2013 13:10:25 -0800 Subject: platform/chrome: Make i2c_adapter_names static Not used outside of the file, so declaration should be static. Picked up by sparse: drivers/platform/chrome/chromeos_laptop.c:44:12: warning: symbol 'i2c_adapter_names' was not declared. Should it be static? Signed-off-by: Olof Johansson Reviewed-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 1c2747f119d1..446ef0f9c256 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -41,7 +41,7 @@ static struct i2c_client *als; static struct i2c_client *tp; static struct i2c_client *ts; -const char *i2c_adapter_names[] = { +static const char *i2c_adapter_names[] = { "SMBus I801 adapter", "i915 gmbus vga", "i915 gmbus panel", -- cgit v1.2.3 From 0b55149033403d78f345fb613d8ad52d16c161fc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Nov 2013 01:43:17 -0800 Subject: usb: phy: twl6030-usb: signedness bug in twl6030_readb() "ret" needs to be signed for the error handling to work. Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl6030-usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 30e8a61552d4..bad57ce77ba5 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -127,7 +127,8 @@ static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module, static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) { - u8 data, ret = 0; + u8 data; + int ret; ret = twl_i2c_read_u8(module, &data, address); if (ret >= 0) -- cgit v1.2.3 From 94037efe81d8e734e28f12b98f76a6e8005495d6 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 13 Nov 2013 13:34:18 +0200 Subject: HID: i2c-hid: disable interrupt on suspend When an I2C HID device is powered of during system sleep, as a result of removing its power resources (by the ACPI core) the interrupt line might go low as well. This results inadvertent interrupt and wakes the system from sleep immediately. To prevent this we disable the device interrupt in the drivers suspend method and enable it on resume. The device can still wake the system up if it is wake capable (this also means that not all of its power will be removed to keep the interrupt line high). Reported-by: Jerome Blin Signed-off-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index ae48d18ee315..20ab6853950e 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1061,6 +1061,7 @@ static int i2c_hid_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + disable_irq(client->irq); if (device_may_wakeup(&client->dev)) enable_irq_wake(client->irq); @@ -1075,6 +1076,7 @@ static int i2c_hid_resume(struct device *dev) int ret; struct i2c_client *client = to_i2c_client(dev); + enable_irq(client->irq); ret = i2c_hid_hwreset(client); if (ret) return ret; -- cgit v1.2.3 From 07f9e5cf8e4154ad17b92ad288be0f04fa0cb94f Mon Sep 17 00:00:00 2001 From: Denis Carikli Date: Tue, 19 Nov 2013 11:56:04 -0800 Subject: Input: tsc2007 - add device tree support. Signed-off-by: Denis Carikli Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/tsc2007.txt | 41 +++++ arch/arm/mach-imx/mach-cpuimx35.c | 2 +- arch/arm/mach-imx/mach-cpuimx51sd.c | 2 +- arch/sh/boards/mach-ecovec24/setup.c | 2 +- drivers/input/touchscreen/tsc2007.c | 173 ++++++++++++++++----- include/linux/i2c/tsc2007.h | 6 +- 6 files changed, 180 insertions(+), 46 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt new file mode 100644 index 000000000000..ec365e172236 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt @@ -0,0 +1,41 @@ +* Texas Instruments tsc2007 touchscreen controller + +Required properties: +- compatible: must be "ti,tsc2007". +- reg: I2C address of the chip. +- ti,x-plate-ohms: X-plate resistance in ohms. + +Optional properties: +- gpios: the interrupt gpio the chip is connected to (trough the penirq pin). + The penirq pin goes to low when the panel is touched. + (see GPIO binding[1] for more details). +- interrupt-parent: the phandle for the gpio controller + (see interrupt binding[0]). +- interrupts: (gpio) interrupt to which the chip is connected + (see interrupt binding[0]). +- ti,max-rt: maximum pressure. +- ti,fuzzx: specifies the absolute input fuzz x value. + If set, it will permit noise in the data up to +- the value given to the fuzz + parameter, that is used to filter noise from the event stream. +- ti,fuzzy: specifies the absolute input fuzz y value. +- ti,fuzzz: specifies the absolute input fuzz z value. +- ti,poll-period: how much time to wait (in milliseconds) before reading again the + values from the tsc2007. + +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +[1]: Documentation/devicetree/bindings/gpio/gpio.txt + +Example: + &i2c1 { + /* ... */ + tsc2007@49 { + compatible = "ti,tsc2007"; + reg = <0x49>; + interrupt-parent = <&gpio4>; + interrupts = <0x0 0x8>; + gpios = <&gpio4 0 0>; + ti,x-plate-ohms = <180>; + }; + + /* ... */ + }; diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 771362d1fbee..65e4c53e1554 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -53,7 +53,7 @@ static const struct imxi2c_platform_data }; #define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2) -static int tsc2007_get_pendown_state(void) +static int tsc2007_get_pendown_state(struct device *dev) { return !gpio_get_value(TSC2007_IRQGPIO); } diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c index 9b5ddf5bbd33..1fba2b8e983f 100644 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c @@ -121,7 +121,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = { .flags = IMXUART_HAVE_RTSCTS, }; -static int tsc2007_get_pendown_state(void) +static int tsc2007_get_pendown_state(struct device *dev) { if (mx51_revision() < IMX_CHIP_REVISION_3_0) return !gpio_get_value(TSC2007_IRQGPIO_REV2); diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 1fa8be409771..23d7e45f9d14 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -501,7 +501,7 @@ static struct platform_device keysc_device = { /* TouchScreen */ #define IRQ0 evt2irq(0x600) -static int ts_get_pendown_state(void) +static int ts_get_pendown_state(struct device *dev) { int val = 0; gpio_free(GPIO_FN_INTC_IRQ0); diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 0b67ba476b4c..88b150a0b8ee 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #define TSC2007_MEASURE_TEMP0 (0x0 << 4) #define TSC2007_MEASURE_AUX (0x2 << 4) @@ -74,13 +77,17 @@ struct tsc2007 { u16 max_rt; unsigned long poll_delay; unsigned long poll_period; + int fuzzx; + int fuzzy; + int fuzzz; + unsigned gpio; int irq; wait_queue_head_t wait; bool stopped; - int (*get_pendown_state)(void); + int (*get_pendown_state)(struct device *); void (*clear_penirq)(void); }; @@ -161,7 +168,7 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts) if (!ts->get_pendown_state) return true; - return ts->get_pendown_state(); + return ts->get_pendown_state(&ts->client->dev); } static irqreturn_t tsc2007_soft_irq(int irq, void *handle) @@ -178,7 +185,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = tsc2007_calculate_pressure(ts, &tc); - if (rt == 0 && !ts->get_pendown_state) { + if (!rt && !ts->get_pendown_state) { /* * If pressure reported is 0 and we don't have * callback to check pendown state, we have to @@ -228,7 +235,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle) { struct tsc2007 *ts = handle; - if (!ts->get_pendown_state || likely(ts->get_pendown_state())) + if (tsc2007_is_pen_down(ts)) return IRQ_WAKE_THREAD; if (ts->clear_penirq) @@ -273,35 +280,74 @@ static void tsc2007_close(struct input_dev *input_dev) tsc2007_stop(ts); } -static int tsc2007_probe(struct i2c_client *client, - const struct i2c_device_id *id) +#ifdef CONFIG_OF +static int tsc2007_get_pendown_state_gpio(struct device *dev) { - struct tsc2007 *ts; - struct tsc2007_platform_data *pdata = client->dev.platform_data; - struct input_dev *input_dev; - int err; + struct i2c_client *client = to_i2c_client(dev); + struct tsc2007 *ts = i2c_get_clientdata(client); + + return !gpio_get_value(ts->gpio); +} + +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) +{ + struct device_node *np = client->dev.of_node; + u32 val32; + u64 val64; - if (!pdata) { - dev_err(&client->dev, "platform data is required!\n"); + if (!np) { + dev_err(&client->dev, "missing device tree data\n"); return -EINVAL; } - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -EIO; + if (!of_property_read_u32(np, "ti,max-rt", &val32)) + ts->max_rt = val32; + else + ts->max_rt = MAX_12BIT; - ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - err = -ENOMEM; - goto err_free_mem; + if (!of_property_read_u32(np, "ti,fuzzx", &val32)) + ts->fuzzx = val32; + + if (!of_property_read_u32(np, "ti,fuzzy", &val32)) + ts->fuzzy = val32; + + if (!of_property_read_u32(np, "ti,fuzzz", &val32)) + ts->fuzzz = val32; + + if (!of_property_read_u64(np, "ti,poll-period", &val64)) + ts->poll_period = val64; + else + ts->poll_period = 1; + + if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { + ts->x_plate_ohms = val32; + } else { + dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property."); + return -EINVAL; } - ts->client = client; - ts->irq = client->irq; - ts->input = input_dev; - init_waitqueue_head(&ts->wait); + ts->gpio = of_get_gpio(np, 0); + if (gpio_is_valid(ts->gpio)) + ts->get_pendown_state = tsc2007_get_pendown_state_gpio; + else + dev_warn(&client->dev, + "GPIO not specified in DT (of_get_gpio returned %d)\n", + ts->gpio); + return 0; +} +#else +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) +{ + dev_err(&client->dev, "platform data is required!\n"); + return -EINVAL; +} +#endif + +static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, + const struct tsc2007_platform_data *pdata, + const struct i2c_device_id *id) +{ ts->model = pdata->model; ts->x_plate_ohms = pdata->x_plate_ohms; ts->max_rt = pdata->max_rt ? : MAX_12BIT; @@ -309,13 +355,54 @@ static int tsc2007_probe(struct i2c_client *client, ts->poll_period = pdata->poll_period ? : 1; ts->get_pendown_state = pdata->get_pendown_state; ts->clear_penirq = pdata->clear_penirq; + ts->fuzzx = pdata->fuzzx; + ts->fuzzy = pdata->fuzzy; + ts->fuzzz = pdata->fuzzz; if (pdata->x_plate_ohms == 0) { dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); - err = -EINVAL; - goto err_free_mem; + return -EINVAL; } + return 0; +} + +static int tsc2007_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); + struct tsc2007 *ts; + struct input_dev *input_dev; + int err; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) + return -EIO; + + ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + if (pdata) + err = tsc2007_probe_pdev(client, ts, pdata, id); + else + err = tsc2007_probe_dt(client, ts); + if (err) + return err; + + input_dev = input_allocate_device(); + if (!input_dev) { + err = -ENOMEM; + goto err_free_input; + }; + + i2c_set_clientdata(client, ts); + + ts->client = client; + ts->irq = client->irq; + ts->input = input_dev; + init_waitqueue_head(&ts->wait); + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); @@ -331,19 +418,19 @@ static int tsc2007_probe(struct i2c_client *client, input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0); - input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0); + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, - pdata->fuzzz, 0); + ts->fuzzz, 0); - if (pdata->init_platform_hw) + if (pdata && pdata->init_platform_hw) pdata->init_platform_hw(); err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, IRQF_ONESHOT, client->dev.driver->name, ts); if (err < 0) { dev_err(&client->dev, "irq %d busy?\n", ts->irq); - goto err_free_mem; + goto err_free_input; } tsc2007_stop(ts); @@ -352,28 +439,25 @@ static int tsc2007_probe(struct i2c_client *client, if (err) goto err_free_irq; - i2c_set_clientdata(client, ts); - return 0; err_free_irq: free_irq(ts->irq, ts); - if (pdata->exit_platform_hw) + if (pdata && pdata->exit_platform_hw) pdata->exit_platform_hw(); - err_free_mem: + err_free_input: input_free_device(input_dev); - kfree(ts); return err; } static int tsc2007_remove(struct i2c_client *client) { - struct tsc2007 *ts = i2c_get_clientdata(client); - struct tsc2007_platform_data *pdata = client->dev.platform_data; + const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); + struct tsc2007 *ts = i2c_get_clientdata(client); free_irq(ts->irq, ts); - if (pdata->exit_platform_hw) + if (pdata && pdata->exit_platform_hw) pdata->exit_platform_hw(); input_unregister_device(ts->input); @@ -389,10 +473,19 @@ static const struct i2c_device_id tsc2007_idtable[] = { MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); +#ifdef CONFIG_OF +static const struct of_device_id tsc2007_of_match[] = { + { .compatible = "ti,tsc2007" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, tsc2007_of_match); +#endif + static struct i2c_driver tsc2007_driver = { .driver = { .owner = THIS_MODULE, - .name = "tsc2007" + .name = "tsc2007", + .of_match_table = of_match_ptr(tsc2007_of_match), }, .id_table = tsc2007_idtable, .probe = tsc2007_probe, diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h index 506a9f7af51e..041c8e823664 100644 --- a/include/linux/i2c/tsc2007.h +++ b/include/linux/i2c/tsc2007.h @@ -14,9 +14,9 @@ struct tsc2007_platform_data { int fuzzy; int fuzzz; - int (*get_pendown_state)(void); - void (*clear_penirq)(void); /* If needed, clear 2nd level - interrupt source */ + int (*get_pendown_state)(struct device *); + /* If needed, clear 2nd level interrupt source */ + void (*clear_penirq)(void); int (*init_platform_hw)(void); void (*exit_platform_hw)(void); }; -- cgit v1.2.3 From f261d46551275abc9e92b24773b15fbb82153b63 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 19 Nov 2013 12:51:26 -0800 Subject: Input: tsc2007 - remove unused poll_delay from platform data The driver does not use poll_delay parameter, so let's remove it. Tested-by: Denis Carikli Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2007.c | 2 -- include/linux/i2c/tsc2007.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 88b150a0b8ee..03fbdf1e8613 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -75,7 +75,6 @@ struct tsc2007 { u16 model; u16 x_plate_ohms; u16 max_rt; - unsigned long poll_delay; unsigned long poll_period; int fuzzx; int fuzzy; @@ -351,7 +350,6 @@ static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, ts->model = pdata->model; ts->x_plate_ohms = pdata->x_plate_ohms; ts->max_rt = pdata->max_rt ? : MAX_12BIT; - ts->poll_delay = pdata->poll_delay ? : 1; ts->poll_period = pdata->poll_period ? : 1; ts->get_pendown_state = pdata->get_pendown_state; ts->clear_penirq = pdata->clear_penirq; diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h index 041c8e823664..4f35b6ad3889 100644 --- a/include/linux/i2c/tsc2007.h +++ b/include/linux/i2c/tsc2007.h @@ -7,8 +7,6 @@ struct tsc2007_platform_data { u16 model; /* 2007. */ u16 x_plate_ohms; /* must be non-zero value */ u16 max_rt; /* max. resistance above which samples are ignored */ - unsigned long poll_delay; /* delay (in ms) after pen-down event - before polling starts */ unsigned long poll_period; /* time (in ms) between samples */ int fuzzx; /* fuzz factor for X, Y and pressure axes */ int fuzzy; -- cgit v1.2.3 From fd91a5f01373ebf672a6691f4dcd487af48be945 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 19 Nov 2013 12:52:29 -0800 Subject: Input: tsc2007 - convert to use devres-managed resources This simplifies error handling path and allows us get rid of tsc2007_remove(). Tested-by: Denis Carikli Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2007.c | 79 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 03fbdf1e8613..1bf9906b5a3f 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -365,6 +365,14 @@ static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, return 0; } +static void tsc2007_call_exit_platform_hw(void *data) +{ + struct device *dev = data; + const struct tsc2007_platform_data *pdata = dev_get_platdata(dev); + + pdata->exit_platform_hw(); +} + static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -388,11 +396,9 @@ static int tsc2007_probe(struct i2c_client *client, if (err) return err; - input_dev = input_allocate_device(); - if (!input_dev) { - err = -ENOMEM; - goto err_free_input; - }; + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) + return -ENOMEM; i2c_set_clientdata(client, ts); @@ -421,45 +427,41 @@ static int tsc2007_probe(struct i2c_client *client, input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, ts->fuzzz, 0); - if (pdata && pdata->init_platform_hw) - pdata->init_platform_hw(); + if (pdata) { + if (pdata->exit_platform_hw) { + err = devm_add_action(&client->dev, + tsc2007_call_exit_platform_hw, + &client->dev); + if (err) { + dev_err(&client->dev, + "Failed to register exit_platform_hw action, %d\n", + err); + return err; + } + } + + if (pdata->init_platform_hw) + pdata->init_platform_hw(); + } - err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, - IRQF_ONESHOT, client->dev.driver->name, ts); - if (err < 0) { - dev_err(&client->dev, "irq %d busy?\n", ts->irq); - goto err_free_input; + err = devm_request_threaded_irq(&client->dev, ts->irq, + tsc2007_hard_irq, tsc2007_soft_irq, + IRQF_ONESHOT, + client->dev.driver->name, ts); + if (err) { + dev_err(&client->dev, "Failed to request irq %d: %d\n", + ts->irq, err); + return err; } tsc2007_stop(ts); err = input_register_device(input_dev); - if (err) - goto err_free_irq; - - return 0; - - err_free_irq: - free_irq(ts->irq, ts); - if (pdata && pdata->exit_platform_hw) - pdata->exit_platform_hw(); - err_free_input: - input_free_device(input_dev); - return err; -} - -static int tsc2007_remove(struct i2c_client *client) -{ - const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); - struct tsc2007 *ts = i2c_get_clientdata(client); - - free_irq(ts->irq, ts); - - if (pdata && pdata->exit_platform_hw) - pdata->exit_platform_hw(); - - input_unregister_device(ts->input); - kfree(ts); + if (err) { + dev_err(&client->dev, + "Failed to register input device: %d\n", err); + return err; + } return 0; } @@ -487,7 +489,6 @@ static struct i2c_driver tsc2007_driver = { }, .id_table = tsc2007_idtable, .probe = tsc2007_probe, - .remove = tsc2007_remove, }; module_i2c_driver(tsc2007_driver); -- cgit v1.2.3 From c81e592696bbe1224506087eae8b4e02cd7186c3 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Tue, 19 Nov 2013 13:55:12 -0800 Subject: Input: twl4030-pwrbutton - add device tree support Add device tree support for twl4030 power button driver. Adding device tree support involved converting the driver to module_platform_driver(). Signed-off-by: Sebastian Reichel Acked-by: Kumar Gala Tested-by: Florian Vaussard Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/twl4030-pwrbutton.txt | 21 +++++++++++++++++++++ drivers/input/misc/twl4030-pwrbutton.c | 16 ++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt new file mode 100644 index 000000000000..c864a46cddcf --- /dev/null +++ b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt @@ -0,0 +1,21 @@ +Texas Instruments TWL family (twl4030) pwrbutton module + +This module is part of the TWL4030. For more details about the whole +chip see Documentation/devicetree/bindings/mfd/twl-familly.txt. + +This module provides a simple power button event via an Interrupt. + +Required properties: +- compatible: should be one of the following + - "ti,twl4030-pwrbutton": For controllers compatible with twl4030 +- interrupts: should be one of the following + - <8>: For controllers compatible with twl4030 + +Example: + +&twl { + twl_pwrbutton: pwrbutton { + compatible = "ti,twl4030-pwrbutton"; + interrupts = <8>; + }; +}; diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index b9a05fda03e4..412ef0ecb439 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -52,7 +52,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) return IRQ_HANDLED; } -static int __init twl4030_pwrbutton_probe(struct platform_device *pdev) +static int twl4030_pwrbutton_probe(struct platform_device *pdev) { struct input_dev *pwr; int irq = platform_get_irq(pdev, 0); @@ -106,16 +106,24 @@ static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { + { .compatible = "ti,twl4030-pwrbutton" }, + {}, +}; +MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); +#endif + static struct platform_driver twl4030_pwrbutton_driver = { + .probe = twl4030_pwrbutton_probe, .remove = __exit_p(twl4030_pwrbutton_remove), .driver = { .name = "twl4030_pwrbutton", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table), }, }; - -module_platform_driver_probe(twl4030_pwrbutton_driver, - twl4030_pwrbutton_probe); +module_platform_driver(twl4030_pwrbutton_driver); MODULE_ALIAS("platform:twl4030_pwrbutton"); MODULE_DESCRIPTION("Triton2 Power Button"); -- cgit v1.2.3 From 0330f93a7fac5e3e91b1fe2d85f5a6b63f9e9857 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Tue, 19 Nov 2013 13:53:31 -0800 Subject: Input: twl4030-pwrbutton - use dev_err for errors Use dev_err() to output errors instead of dev_dbg(). Signed-off-by: Sebastian Reichel Reviewed-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl4030-pwrbutton.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index 412ef0ecb439..88522d003ffe 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -60,7 +60,7 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) pwr = input_allocate_device(); if (!pwr) { - dev_dbg(&pdev->dev, "Can't allocate power button\n"); + dev_err(&pdev->dev, "Can't allocate power button\n"); return -ENOMEM; } @@ -74,13 +74,13 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "twl4030_pwrbutton", pwr); if (err < 0) { - dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); + dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); goto free_input_dev; } err = input_register_device(pwr); if (err) { - dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); + dev_err(&pdev->dev, "Can't register power button: %d\n", err); goto free_irq; } -- cgit v1.2.3 From 7f9ce649d2675103bbb71fe2c2bb4cd7fb362c37 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Tue, 19 Nov 2013 13:56:18 -0800 Subject: Input: twl4030-pwrbutton - simplify driver using devm_* Use managed irq resource to simplify the driver. Signed-off-by: Sebastian Reichel Reviewed-by: Aaro Koskinen Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl4030-pwrbutton.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index 88522d003ffe..fb3b63b2f85c 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -58,7 +58,7 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) int irq = platform_get_irq(pdev, 0); int err; - pwr = input_allocate_device(); + pwr = devm_input_allocate_device(&pdev->dev); if (!pwr) { dev_err(&pdev->dev, "Can't allocate power button\n"); return -ENOMEM; @@ -70,39 +70,22 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) pwr->phys = "twl4030_pwrbutton/input0"; pwr->dev.parent = &pdev->dev; - err = request_threaded_irq(irq, NULL, powerbutton_irq, + err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "twl4030_pwrbutton", pwr); if (err < 0) { dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); - goto free_input_dev; + return err; } err = input_register_device(pwr); if (err) { dev_err(&pdev->dev, "Can't register power button: %d\n", err); - goto free_irq; + return err; } platform_set_drvdata(pdev, pwr); - return 0; - -free_irq: - free_irq(irq, pwr); -free_input_dev: - input_free_device(pwr); - return err; -} - -static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev) -{ - struct input_dev *pwr = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - free_irq(irq, pwr); - input_unregister_device(pwr); - return 0; } @@ -116,7 +99,6 @@ MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); static struct platform_driver twl4030_pwrbutton_driver = { .probe = twl4030_pwrbutton_probe, - .remove = __exit_p(twl4030_pwrbutton_remove), .driver = { .name = "twl4030_pwrbutton", .owner = THIS_MODULE, -- cgit v1.2.3 From d0134e9fcfa393f64b4b406a6aac90d9b929a704 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 18:11:15 -0800 Subject: Input: serio - remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Dmitry Torokhov --- drivers/input/serio/pcips2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 76f83836fd5a..13062f667e82 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -181,7 +181,6 @@ static void pcips2_remove(struct pci_dev *dev) struct pcips2_data *ps2if = pci_get_drvdata(dev); serio_unregister_port(ps2if->io); - pci_set_drvdata(dev, NULL); kfree(ps2if); pci_release_regions(dev); pci_disable_device(dev); -- cgit v1.2.3 From 0b279da7af779fa515b70c0f4127001cab22ea86 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 25 Nov 2013 18:43:16 -0800 Subject: Input: wacom - scale up touch width and height values for Intuos Pro The width and height values reported by the Intuos Pro are not in surface units as required by the MT protocol. A simple multiplier of 100x corrects it. Signed-off-by: Jason Gerecke Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 9c8eded2e504..3f75f1d3b348 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1151,8 +1151,8 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) int width, height; if (features->type >= INTUOSPS && features->type <= INTUOSPL) { - width = data[5]; - height = data[6]; + width = data[5] * 100; + height = data[6] * 100; } else { /* * "a" is a scaled-down area which we assume is -- cgit v1.2.3 From 1d0d6df02750b4a6f466768cbfbf860e24f4c8d4 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 25 Nov 2013 18:43:45 -0800 Subject: Input: wacom - make sure touch_max is set for touch devices Old single touch Tablet PCs do not have touch_max set at wacom_features. Since touch device at lease supports one finger, assign touch_max to 1 when touch usage is defined in its HID Descriptor and touch_max is not pre-defined. Tested-by: Jason Gerecke Signed-off-by: Ping Cheng Reviewed-by: Chris Bagwell Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8a90da11365f..3d71b608330e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -304,7 +304,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); char limit = 0; /* result has to be defined as int for some devices */ - int result = 0; + int result = 0, touch_max = 0; int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; unsigned char *report; @@ -351,7 +351,8 @@ static int wacom_parse_hid(struct usb_interface *intf, if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; - + /* touch device at least supports one touch point */ + touch_max = 1; switch (features->type) { case TABLETPC2FG: features->pktlen = WACOM_PKGLEN_TPC2FG; @@ -504,6 +505,8 @@ static int wacom_parse_hid(struct usb_interface *intf, } out: + if (!features->touch_max && touch_max) + features->touch_max = touch_max; result = 0; kfree(report); return result; -- cgit v1.2.3 From b5fd2a3e92ca5c8c1f3c20d31ac5daed3ec4d604 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 25 Nov 2013 18:44:55 -0800 Subject: Input: wacom - add support for three new Intuos devices Two tablets in this series support both pen and touch. One (Intuos S) only supports pen. This patch also updates the driver to process wireless devices that do not support touch interface. Tested-by: Jason Gerecke Reviewed-by: Chris Bagwell Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 6 ++-- drivers/input/tablet/wacom_wac.c | 61 ++++++++++++++++++++++++++++++---------- drivers/input/tablet/wacom_wac.h | 2 ++ 3 files changed, 51 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 3d71b608330e..3a7d99c720cd 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1198,7 +1198,8 @@ static void wacom_wireless_work(struct work_struct *work) goto fail; /* Touch interface */ - if (wacom_wac1->features.touch_max) { + if (wacom_wac1->features.touch_max || + wacom_wac1->features.type == INTUOSHT) { wacom_wac2->features = *((struct wacom_features *)id->driver_info); wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; @@ -1321,7 +1322,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i * HID descriptor. If this is the touch interface (wMaxPacketSize * of WACOM_PKGLEN_BBTOUCH3), override the table values. */ - if (features->type >= INTUOS5S && features->type <= INTUOSPL) { + if (features->type >= INTUOS5S && features->type <= INTUOSHT) { if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; @@ -1391,7 +1392,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail5; } } - return 0; fail5: wacom_destroy_leds(wacom); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 3f75f1d3b348..eb60a284be05 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1176,10 +1176,16 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) { struct input_dev *input = wacom->input; + struct wacom_features *features = &wacom->features; - input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); + if (features->type == INTUOSHT) { + input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0); + input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0); + } else { + input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); + input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); + } input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); - input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0); input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0); } @@ -1217,7 +1223,7 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) unsigned char *data = wacom->data; int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; - if (data[0] != 0x02) + if (data[0] != WACOM_REPORT_PENABLED) return 0; prox = (data[1] & 0x20) == 0x20; @@ -1297,7 +1303,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) unsigned char *data = wacom->data; int connected; - if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80) + if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL) return 0; connected = data[1] & 0x01; @@ -1391,6 +1397,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case BAMBOO_PT: + case INTUOSHT: sync = wacom_bpt_irq(wacom_wac, len); break; @@ -1459,7 +1466,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOSPL) || + (features->type >= INTUOS5S && features->type <= INTUOSHT) || (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; @@ -1771,33 +1778,43 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case INTUOSHT: case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - if (features->device_type == BTN_TOOL_FINGER) { - unsigned int flags = INPUT_MT_POINTER; __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit); __set_bit(BTN_BACK, input_dev->keybit); __set_bit(BTN_RIGHT, input_dev->keybit); - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - input_set_abs_params(input_dev, + if (features->touch_max) { + /* touch interface */ + unsigned int flags = INPUT_MT_POINTER; + + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); + } else { + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + flags = 0; + } + input_mt_init_slots(input_dev, features->touch_max, flags); } else { - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - flags = 0; + /* buttons/keys only interface */ + __clear_bit(ABS_X, input_dev->absbit); + __clear_bit(ABS_Y, input_dev->absbit); + __clear_bit(BTN_TOUCH, input_dev->keybit); } - input_mt_init_slots(input_dev, features->touch_max, flags); } else if (features->device_type == BTN_TOOL_PEN) { + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); @@ -2194,6 +2211,17 @@ static const struct wacom_features wacom_features_0x300 = static const struct wacom_features wacom_features_0x301 = { "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x302 = + { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x303 = + { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x30E = + { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023, + 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2329,6 +2357,9 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x10D) }, { USB_DEVICE_WACOM(0x300) }, { USB_DEVICE_WACOM(0x301) }, + { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x304) }, { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) }, diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index fd23a3790605..854cceb6d6de 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -54,6 +54,7 @@ #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_TPC1FGE 18 #define WACOM_REPORT_24HDT 1 +#define WACOM_REPORT_WL 128 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -81,6 +82,7 @@ enum { INTUOSPS, INTUOSPM, INTUOSPL, + INTUOSHT, WACOM_21UX2, WACOM_22HD, DTK, -- cgit v1.2.3 From ac550511ad4be446847be94f86708ca0d3e4691d Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 26 Nov 2013 09:23:57 +0800 Subject: staging/lustre: fix build error on i386-randconfig kbuild test robot reported: All error/warnings: In file included from drivers/staging/lustre/lustre/llite/llite_internal.h:41:0, from drivers/staging/lustre/lustre/llite/dcache.c:48: >> drivers/staging/lustre/lustre/llite/../include/lustre_disk.h:499:28: error: field 'lsi_bdi' has incomplete type struct backing_dev_info lsi_bdi; /* each client mountpoint needs ^ -- In file included from drivers/staging/lustre/lustre/llite/llite_lib.c:51:0: >> drivers/staging/lustre/lustre/llite/../include/lustre_disk.h:499:28: error: field 'lsi_bdi' has incomplete type struct backing_dev_info lsi_bdi; /* each client mountpoint needs ^ drivers/staging/lustre/lustre/llite/llite_lib.c: In function 'll_bdi_register': >> drivers/staging/lustre/lustre/llite/llite_lib.c:953:5: error: dereferencing pointer to incomplete type bdi->name = "lustre"; ^ >> drivers/staging/lustre/lustre/llite/llite_lib.c:954:2: error: implicit declaration of function 'bdi_register' [-Werror=implicit-function-declaration] return bdi_register(bdi, NULL, "lustre-%d", ^ drivers/staging/lustre/lustre/llite/llite_lib.c: In function 'll_fill_super': >> drivers/staging/lustre/lustre/llite/llite_lib.c:990:2: error: implicit declaration of function 'bdi_init' [-Werror=implicit-function-declaration] err = bdi_init(&lsi->lsi_bdi); ^ >> drivers/staging/lustre/lustre/llite/llite_lib.c:994:30: error: 'BDI_CAP_MAP_COPY' undeclared (first use in this function) lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; ^ drivers/staging/lustre/lustre/llite/llite_lib.c:994:30: note: each undeclared identifier is reported only once for each function it appears in drivers/staging/lustre/lustre/llite/llite_lib.c: In function 'll_put_super': >> drivers/staging/lustre/lustre/llite/llite_lib.c:1101:3: error: implicit declaration of function 'bdi_destroy' [-Werror=implicit-function-declaration] bdi_destroy(&lsi->lsi_bdi); ^ cc1: some warnings being treated as errors Reported-by: Fengguang Wu Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_disk.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h index 9228b165b258..1de9a8bed497 100644 --- a/drivers/staging/lustre/lustre/include/lustre_disk.h +++ b/drivers/staging/lustre/lustre/include/lustre_disk.h @@ -50,6 +50,7 @@ #include #include +#include /****************** on-disk files *********************/ -- cgit v1.2.3 From 078d0cfdef9faf2416d68b990a2de6644a41006c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 25 Nov 2013 22:14:16 +0000 Subject: staging: vt6656: Remove unused variable bLongHeader Remove dead bLongHeader code. In s_vFillTxKey use ieee80211_has_a4 to detect long headers for future use. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 1 - drivers/staging/vt6656/rxtx.c | 24 ++++-------------------- 2 files changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index ec8acbd4abaa..9a4dfbcea8b7 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -598,7 +598,6 @@ struct vnt_private { int bCCK; int bEncryptionEnable; - int bLongHeader; int bShortSlotTime; int bProtectMode; int bNonERPPresent; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 723a8de3a466..aa71d39b1259 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -278,7 +278,7 @@ static void s_vFillTxKey(struct vnt_private *pDevice, mic_hdr->tsc_15_0 = cpu_to_be16(pTransmitKey->wTSC15_0); /* MICHDR1 */ - if (pDevice->bLongHeader) + if (ieee80211_has_a4(pMACHeader->frame_control)) mic_hdr->hlen = cpu_to_be16(28); else mic_hdr->hlen = cpu_to_be16(22); @@ -292,7 +292,7 @@ static void s_vFillTxKey(struct vnt_private *pDevice, & 0xc78f); mic_hdr->seq_ctrl = cpu_to_le16(pMACHeader->seq_ctrl & 0xf); - if (pDevice->bLongHeader) + if (ieee80211_has_a4(pMACHeader->frame_control)) memcpy(mic_hdr->addr4, pMACHeader->addr4, ETH_ALEN); } } @@ -790,7 +790,6 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice, { struct vnt_tx_fifo_head *pFifoHead = &tx_buffer->fifo_head; union vnt_tx_data_head *head = NULL; - u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */ u16 wFifoCtl; u8 byFBOption = AUTO_FB_NONE; @@ -805,9 +804,6 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice, if (!pFifoHead) return 0; - if (pDevice->bLongHeader) - cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (need_rts) { struct vnt_rrv_time_rts *pBuf = @@ -1007,16 +1003,9 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, pTxBufHead->wTimeStamp = DEFAULT_MSDU_LIFETIME_RES_64us; - //Set FIFOCTL_LHEAD - if (pDevice->bLongHeader) - pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD; - //Set FRAGCTL_MACHDCNT - if (pDevice->bLongHeader) { - cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; - } else { - cbMACHdLen = WLAN_HDR_ADDR3_LEN; - } + cbMACHdLen = WLAN_HDR_ADDR3_LEN; + pTxBufHead->wFragCtl |= (u16)(cbMACHdLen << 10); //Set FIFOCTL_GrpAckPolicy @@ -1336,11 +1325,6 @@ static void s_vGenerateMACHeader(struct vnt_private *pDevice, pMACHeader->duration_id = cpu_to_le16(wDuration); - if (pDevice->bLongHeader) { - PWLAN_80211HDR_A4 pMACA4Header = (PWLAN_80211HDR_A4) pbyBufferAddr; - pMACHeader->frame_control |= (FC_TODS | FC_FROMDS); - memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN); - } pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); //Set FragNumber in Sequence Control -- cgit v1.2.3 From 2474d74aaee59eebac6c2c458d7544a2a56d5650 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 25 Nov 2013 22:18:31 +0000 Subject: staging: vt6656: Remove unused variable bAES. bAES flips from false to true but doesn't do anything. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 2 -- drivers/staging/vt6656/rxtx.c | 4 ---- 2 files changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 9a4dfbcea8b7..82e1e6d695d1 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -667,8 +667,6 @@ struct vnt_private { u8 abyPRNG[WLAN_WEPMAX_KEYLEN+3]; u8 byKeyIndex; - int bAES; - u32 uKeyLength; u8 abyKey[WLAN_WEP232_KEYLEN]; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index aa71d39b1259..cc2302900989 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1462,7 +1462,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice, // Notes: // Although spec says MMPDU can be fragmented; In most case, // no one will send a MMPDU under fragmentation. With RTS may occur. - pDevice->bAES = false; //Set FRAGCTL_WEPTYP if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { @@ -1483,7 +1482,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice, cbIVlen = 8;//RSN Header cbICVlen = 8;//MIC pTxBufHead->wFragCtl |= FRAGCTL_AES; - pDevice->bAES = true; } //MAC Header should be padding 0 to DW alignment. uPadding = 4 - (cbMacHdLen%4); @@ -1858,7 +1856,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb) // Notes: // Although spec says MMPDU can be fragmented; In most case, // no one will send a MMPDU under fragmentation. With RTS may occur. - pDevice->bAES = false; //Set FRAGCTL_WEPTYP if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { @@ -1880,7 +1877,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb) cbICVlen = 8;//MIC cbMICHDR = sizeof(struct vnt_mic_hdr); pTxBufHead->wFragCtl |= FRAGCTL_AES; - pDevice->bAES = true; } //MAC Header should be padding 0 to DW alignment. uPadding = 4 - (cbMacHdLen%4); -- cgit v1.2.3 From 65f1c7816db85db02b2069f9d0e5111de52f5ee3 Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Tue, 26 Nov 2013 10:04:55 +0800 Subject: staging/lustre/server: use unified request handler for MGS - Unify request handler. It finds target for particular request and calls appropriate handler for it. Generic handlers are moved to the unified target code. The tgt_session_info is introduced to store all request-related data and passed to all handlers. - Pack reply in llog server functions early and use err_serious() - remove obsoleted llog_origin_handle_cancel(), it is not used anymore - remove push_ctxt/pop_ctxt from llog server function, it is based on OSD now. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2145 Lustre-change: http://review.whamcloud.com/4826 Signed-off-by: Mikhail Pershin Reviewed-by: Fan Yong Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_req_layout.h | 2 ++ drivers/staging/lustre/lustre/include/obd_support.h | 7 +++++++ drivers/staging/lustre/lustre/ptlrpc/layout.c | 7 ++++++- drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c | 4 ++-- 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index f4d3820865f1..28325693fc11 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -245,6 +245,8 @@ extern struct req_format RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK; extern struct req_format RQF_LLOG_ORIGIN_HANDLE_READ_HEADER; extern struct req_format RQF_LLOG_ORIGIN_CONNECT; +extern struct req_format RQF_CONNECT; + extern struct req_msg_field RMF_GENERIC_DATA; extern struct req_msg_field RMF_PTLRPC_BODY; extern struct req_msg_field RMF_MDT_BODY; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 9697e7faff2f..825a0c95c585 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -416,6 +416,13 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, #define OBD_FAIL_MGC_PAUSE_PROCESS_LOG 0x903 #define OBD_FAIL_MGS_PAUSE_REQ 0x904 #define OBD_FAIL_MGS_PAUSE_TARGET_REG 0x905 +#define OBD_FAIL_MGS_CONNECT_NET 0x906 +#define OBD_FAIL_MGS_DISCONNECT_NET 0x907 +#define OBD_FAIL_MGS_SET_INFO_NET 0x908 +#define OBD_FAIL_MGS_EXCEPTION_NET 0x909 +#define OBD_FAIL_MGS_TARGET_REG_NET 0x90a +#define OBD_FAIL_MGS_TARGET_DEL_NET 0x90b +#define OBD_FAIL_MGS_CONFIG_READ_NET 0x90c #define OBD_FAIL_QUOTA_DQACQ_NET 0xA01 #define OBD_FAIL_QUOTA_EDQUOT 0xA02 diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 504682d2eefa..4d6ac68676e0 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -738,7 +738,8 @@ static struct req_format *req_formats[] = { &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK, &RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK, &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER, - &RQF_LLOG_ORIGIN_CONNECT + &RQF_LLOG_ORIGIN_CONNECT, + &RQF_CONNECT, }; struct req_msg_field { @@ -1504,6 +1505,10 @@ struct req_format RQF_LLOG_ORIGIN_CONNECT = DEFINE_REQ_FMT0("LLOG_ORIGIN_CONNECT", llogd_conn_body_only, empty); EXPORT_SYMBOL(RQF_LLOG_ORIGIN_CONNECT); +struct req_format RQF_CONNECT = + DEFINE_REQ_FMT0("CONNECT", obd_connect_client, obd_connect_server); +EXPORT_SYMBOL(RQF_CONNECT); + struct req_format RQF_OST_CONNECT = DEFINE_REQ_FMT0("OST_CONNECT", obd_connect_client, obd_connect_server); diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 65451f77e782..1be978609c59 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -114,10 +114,10 @@ struct ll_rpc_opcode { { MGS_SET_INFO, "mgs_set_info" }, { MGS_CONFIG_READ, "mgs_config_read" }, { OBD_PING, "obd_ping" }, - { OBD_LOG_CANCEL, "llog_origin_handle_cancel" }, + { OBD_LOG_CANCEL, "llog_cancel" }, { OBD_QC_CALLBACK, "obd_quota_callback" }, { OBD_IDX_READ, "dt_index_read" }, - { LLOG_ORIGIN_HANDLE_CREATE, "llog_origin_handle_create" }, + { LLOG_ORIGIN_HANDLE_CREATE, "llog_origin_handle_open" }, { LLOG_ORIGIN_HANDLE_NEXT_BLOCK, "llog_origin_handle_next_block" }, { LLOG_ORIGIN_HANDLE_READ_HEADER,"llog_origin_handle_read_header" }, { LLOG_ORIGIN_HANDLE_WRITE_REC, "llog_origin_handle_write_rec" }, -- cgit v1.2.3 From ad8dbc93a464869f64365a2123b3491965df3b3e Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Tue, 26 Nov 2013 10:04:57 +0800 Subject: staging/lustre/nfs: writing to new files will return ENOENT This happend with SLES11SP2 Lustre client, which in turn acts as an NFS server, exporting a subtree of an Lustre fs through NFS. We detected that whenever we are writing to a new file using, fx, 'echo blah > newfile', it will return ENOENT error. We found out that this was caused by the anonymous dentry. In SLESS11SP2, anonymous dentries are assigned '/' as the name, instead of an empty string. When MDT handles the intent_open call, it will look up the obj by the name if it is not an empty string, and thus couldn't find it. As MDS_OPEN_BY_FID is always set on this request, we never need to send the name in this request. The fid is already available and should be used in case the file has been renamed. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3544 Lustre-change: http://review.whamcloud.com/6920 Signed-off-by: Cheng Shao Signed-off-by: Patrick Farrell Reviewed-by: Bob Glossman Reviewed-by: Alexey Shvetsov Reviewed-by: Lai Siyao Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 82248e9f6bff..f36c5d8dbae0 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -368,8 +368,6 @@ static int ll_intent_file_open(struct file *file, void *lmm, { struct ll_sb_info *sbi = ll_i2sbi(file->f_dentry->d_inode); struct dentry *parent = file->f_dentry->d_parent; - const char *name = file->f_dentry->d_name.name; - const int len = file->f_dentry->d_name.len; struct md_op_data *op_data; struct ptlrpc_request *req; __u32 opc = LUSTRE_OPC_ANY; @@ -394,8 +392,9 @@ static int ll_intent_file_open(struct file *file, void *lmm, } op_data = ll_prep_md_op_data(NULL, parent->d_inode, - file->f_dentry->d_inode, name, len, + file->f_dentry->d_inode, NULL, 0, O_RDWR, opc, NULL); + if (IS_ERR(op_data)) return PTR_ERR(op_data); -- cgit v1.2.3 From c1f3d689f9f510fcab6d33be2f1c03d00f5840b8 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 26 Nov 2013 10:04:59 +0800 Subject: staging/lustre/mdc: prevent fall through in mdc_iocontrol() In mdc_iocontrol() add a goto to the end of the LL_IOC_HSM_STATE_SET case, preventing fall through into the next case. In the same function, replace the return statement in OBD_IOC_QUOTACTL with a goto, so that a reference to the module is not leaked. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3576 Lustre-change: http://review.whamcloud.com/6962 Signed-off-by: John L. Hammond Reviewed-by: Aurelien Degremont Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_request.c | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index ed3a7a05557f..a09a5c3141aa 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1743,6 +1743,7 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, GOTO(out, rc); case LL_IOC_HSM_STATE_SET: rc = mdc_ioc_hsm_state_set(exp, karg); + GOTO(out, rc); case LL_IOC_HSM_ACTION: rc = mdc_ioc_hsm_current_action(exp, karg); GOTO(out, rc); @@ -1814,8 +1815,8 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, struct obd_quotactl *oqctl; OBD_ALLOC_PTR(oqctl); - if (!oqctl) - return -ENOMEM; + if (oqctl == NULL) + GOTO(out, rc = -ENOMEM); QCTL_COPY(oqctl, qctl); rc = obd_quotactl(exp, oqctl); @@ -1824,23 +1825,21 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, qctl->qc_valid = QC_MDTIDX; qctl->obd_uuid = obd->u.cli.cl_target_uuid; } + OBD_FREE_PTR(oqctl); - break; + GOTO(out, rc); } - case LL_IOC_GET_CONNECT_FLAGS: { - if (copy_to_user(uarg, - exp_connect_flags_ptr(exp), - sizeof(__u64))) + case LL_IOC_GET_CONNECT_FLAGS: + if (copy_to_user(uarg, exp_connect_flags_ptr(exp), + sizeof(*exp_connect_flags_ptr(exp)))) GOTO(out, rc = -EFAULT); - else - GOTO(out, rc = 0); - } - case LL_IOC_LOV_SWAP_LAYOUTS: { + + GOTO(out, rc = 0); + case LL_IOC_LOV_SWAP_LAYOUTS: rc = mdc_ioc_swap_layouts(exp, karg); - break; - } + GOTO(out, rc); default: - CERROR("mdc_ioctl(): unrecognised ioctl %#x\n", cmd); + CERROR("unrecognised ioctl: cmd = %#x\n", cmd); GOTO(out, rc = -ENOTTY); } out: -- cgit v1.2.3 From a0b58afa7df7c13d918bbddf75485346edfefe20 Mon Sep 17 00:00:00 2001 From: Andriy Skulysh Date: Tue, 26 Nov 2013 10:04:58 +0800 Subject: staging/lustre/ptlrpc: Fix race during exp_flock_hash creation During race exp_flock_hash can be created 2 times. It is created & assigned without any lock. Move hash initialization from ldlm_flock_blocking_link() to ldlm_init_export() Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2835 Lustre-change: http://review.whamcloud.com/5471 Signed-off-by: Andriy Skulysh Reviewed-by: Alexander Boyko Reviewed-by: Vitaly Fertman Tested-by: Kyrylo Shatskyy Reviewed-by: Keith Mannthey Reviewed-by: Prakash Surya Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 28 +++++++------------------ drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 8 +++++++ 2 files changed, 16 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 456d5aa76960..c9aae132f98a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -95,20 +95,12 @@ ldlm_flocks_overlap(struct ldlm_lock *lock, struct ldlm_lock *new) lock->l_policy_data.l_flock.start)); } -static inline int ldlm_flock_blocking_link(struct ldlm_lock *req, - struct ldlm_lock *lock) +static inline void ldlm_flock_blocking_link(struct ldlm_lock *req, + struct ldlm_lock *lock) { - int rc = 0; - /* For server only */ if (req->l_export == NULL) - return 0; - - if (unlikely(req->l_export->exp_flock_hash == NULL)) { - rc = ldlm_init_flock_export(req->l_export); - if (rc) - goto error; - } + return; LASSERT(hlist_unhashed(&req->l_exp_flock_hash)); @@ -121,8 +113,6 @@ static inline int ldlm_flock_blocking_link(struct ldlm_lock *req, cfs_hash_add(req->l_export->exp_flock_hash, &req->l_policy_data.l_flock.owner, &req->l_exp_flock_hash); -error: - return rc; } static inline void ldlm_flock_blocking_unlink(struct ldlm_lock *req) @@ -250,7 +240,6 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq, int overlaps = 0; int splitted = 0; const struct ldlm_callback_suite null_cbs = { NULL }; - int rc; CDEBUG(D_DLMTRACE, "flags %#llx owner "LPU64" pid %u mode %u start " LPU64" end "LPU64"\n", *flags, @@ -328,12 +317,8 @@ reprocess: /* add lock to blocking list before deadlock * check to prevent race */ - rc = ldlm_flock_blocking_link(req, lock); - if (rc) { - ldlm_flock_destroy(req, mode, *flags); - *err = rc; - return LDLM_ITER_STOP; - } + ldlm_flock_blocking_link(req, lock); + if (ldlm_flock_deadlock(req, lock)) { ldlm_flock_blocking_unlink(req); ldlm_flock_destroy(req, mode, *flags); @@ -813,6 +798,9 @@ static cfs_hash_ops_t ldlm_export_flock_ops = { int ldlm_init_flock_export(struct obd_export *exp) { + if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDT_NAME) != 0) + return 0; + exp->exp_flock_hash = cfs_hash_create(obd_uuid2str(&exp->exp_client_uuid), HASH_EXP_LOCK_CUR_BITS, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index bbf42914b765..85f5e7e42486 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -964,6 +964,7 @@ static cfs_hash_ops_t ldlm_export_lock_ops = { int ldlm_init_export(struct obd_export *exp) { + int rc; exp->exp_lock_hash = cfs_hash_create(obd_uuid2str(&exp->exp_client_uuid), HASH_EXP_LOCK_CUR_BITS, @@ -977,7 +978,14 @@ int ldlm_init_export(struct obd_export *exp) if (!exp->exp_lock_hash) return -ENOMEM; + rc = ldlm_init_flock_export(exp); + if (rc) + GOTO(err, rc); + return 0; +err: + ldlm_destroy_export(exp); + return rc; } EXPORT_SYMBOL(ldlm_init_export); -- cgit v1.2.3 From 7cd875d2b7bc61abdad75209b1ab63301a78f99c Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 26 Nov 2013 10:05:00 +0800 Subject: staging/lustre/lu: shrink lu_object by 8 bytes on x86_64 Remove the lo_depth member from struct lu_object. This field is never set and only read in lu_object_print(). Remove the lo_flags member. This field was only used in lu_object_alloc() and can be replaced with an on-stack mask to keep trace of which layers have been allocated. Lustre-change: http://review.whamcloud.com/5890 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3059 Signed-off-by: John L. Hammond Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lu_object.h | 19 ----------------- drivers/staging/lustre/lustre/obdclass/lu_object.c | 24 ++++++++++++++-------- 2 files changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index d5b8225ef1a7..6773bca1e0d8 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -397,17 +397,6 @@ static inline int lu_device_is_md(const struct lu_device *d) return ergo(d != NULL, d->ld_type->ldt_tags & LU_DEVICE_MD); } -/** - * Flags for the object layers. - */ -enum lu_object_flags { - /** - * this flags is set if lu_object_operations::loo_object_init() has - * been called for this layer. Used by lu_object_alloc(). - */ - LU_OBJECT_ALLOCATED = (1 << 0) -}; - /** * Common object attributes. */ @@ -485,14 +474,6 @@ struct lu_object { * Linkage into list of all layers. */ struct list_head lo_linkage; - /** - * Depth. Top level layer depth is 0. - */ - int lo_depth; - /** - * Flags from enum lu_object_flags. - */ - __u32 lo_flags; /** * Link to the device, for debugging. */ diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index d61b0dbe6ab6..1d6754bbace7 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -200,6 +200,8 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env, struct lu_object *scan; struct lu_object *top; struct list_head *layers; + unsigned int init_mask = 0; + unsigned int init_flag; int clean; int result; @@ -218,15 +220,17 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env, */ top->lo_header->loh_fid = *f; layers = &top->lo_header->loh_layers; + do { /* * Call ->loo_object_init() repeatedly, until no more new * object slices are created. */ clean = 1; + init_flag = 1; list_for_each_entry(scan, layers, lo_linkage) { - if (scan->lo_flags & LU_OBJECT_ALLOCATED) - continue; + if (init_mask & init_flag) + goto next; clean = 0; scan->lo_header = top->lo_header; result = scan->lo_ops->loo_object_init(env, scan, conf); @@ -234,7 +238,9 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env, lu_object_free(env, top); return ERR_PTR(result); } - scan->lo_flags |= LU_OBJECT_ALLOCATED; + init_mask |= init_flag; +next: + init_flag <<= 1; } } while (!clean); @@ -487,23 +493,25 @@ void lu_object_print(const struct lu_env *env, void *cookie, { static const char ruler[] = "........................................"; struct lu_object_header *top; - int depth; + int depth = 4; top = o->lo_header; lu_object_header_print(env, cookie, printer, top); - (*printer)(env, cookie, "{ \n"); - list_for_each_entry(o, &top->loh_layers, lo_linkage) { - depth = o->lo_depth + 4; + (*printer)(env, cookie, "{\n"); + list_for_each_entry(o, &top->loh_layers, lo_linkage) { /* * print `.' \a depth times followed by type name and address */ (*printer)(env, cookie, "%*.*s%s@%p", depth, depth, ruler, o->lo_dev->ld_type->ldt_name, o); + if (o->lo_ops->loo_object_print != NULL) - o->lo_ops->loo_object_print(env, cookie, printer, o); + (*o->lo_ops->loo_object_print)(env, cookie, printer, o); + (*printer)(env, cookie, "\n"); } + (*printer)(env, cookie, "} header@%p\n", top); } EXPORT_SYMBOL(lu_object_print); -- cgit v1.2.3 From 18dfaebfa8c5752b34c87a5269bb24bc3a571e5a Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Tue, 26 Nov 2013 10:05:01 +0800 Subject: staging/lustre/mdt: HSM coordinator client interface This patch implements the HSM coordinator methods used by client to add/remove/list HSM actions on FID. Lustre-change: http://review.whamcloud.com/6532 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3341 Signed-off-by: JC Lafoucriere Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_user.h | 7 +++---- drivers/staging/lustre/lustre/mdc/mdc_request.c | 4 +--- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 9fd1d3ba2a63..9436166c6ef2 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -1121,11 +1121,10 @@ static inline int hal_size(struct hsm_action_list *hal) sz = sizeof(*hal) + cfs_size_round(strlen(hal->hal_fsname)); hai = hai_zero(hal); - for (i = 0 ; i < hal->hal_count ; i++) { + for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) sz += cfs_size_round(hai->hai_len); - hai = hai_next(hai); - } - return(sz); + + return sz; } /* Copytool progress reporting */ diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index a09a5c3141aa..8373778c2e78 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1919,10 +1919,8 @@ static void lustre_swab_hal(struct hsm_action_list *h) __swab32s(&h->hal_archive_id); __swab64s(&h->hal_flags); hai = hai_zero(h); - for (i = 0; i < h->hal_count; i++) { + for (i = 0; i < h->hal_count; i++, hai = hai_next(hai)) lustre_swab_hai(hai); - hai = hai_next(hai); - } } static void lustre_swab_kuch(struct kuc_hdr *l) -- cgit v1.2.3 From d595bd4bbd853106e3926176fa8a677963337d38 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:32 -0800 Subject: drm/i915: Fix BDW PPGTT error path When we fail for some reason on loading the PDPs, it would be wise to disable the PPGTT in the ring registers. If we do not do this, we have undefined results. Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index efb5dab61c81..1a5272c172c8 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -238,10 +238,16 @@ static int gen8_ppgtt_enable(struct drm_device *dev) for_each_ring(ring, dev_priv, j) { ret = gen8_write_pdp(ring, i, addr); if (ret) - return ret; + goto err_out; } } return 0; + +err_out: + for_each_ring(ring, dev_priv, j) + I915_WRITE(RING_MODE_GEN7(ring), + _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE)); + return ret; } static void gen8_ppgtt_clear_range(struct i915_address_space *vm, -- cgit v1.2.3 From 686e1f6f87985bc05d38d90d483f3765d47780cc Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:34 -0800 Subject: drm/i915: Add a few missed bits to the mm This should really have been added in BDW integration, as well as: commit 93bd8649dba3155d1a0ba2a902d9c49f1c75a1da Author: Ben Widawsky Date: Tue Jul 16 16:50:06 2013 -0700 drm/i915: Put the mm in the parent address space It didn't really matter before, but it will in the future. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1a5272c172c8..c1d04a36688f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -322,6 +322,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) container_of(vm, struct i915_hw_ppgtt, base); int i, j; + drm_mm_takedown(&vm->mm); + for (i = 0; i < ppgtt->num_pd_pages ; i++) { if (ppgtt->pd_dma_addr[i]) { pci_unmap_page(ppgtt->base.dev->pdev, @@ -385,6 +387,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) ppgtt->base.clear_range = gen8_ppgtt_clear_range; ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; ppgtt->base.cleanup = gen8_ppgtt_cleanup; + ppgtt->base.start = 0; + ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE; BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS); @@ -636,6 +640,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->base.scratch = dev_priv->gtt.base.scratch; + ppgtt->base.start = 0; + ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE; ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *), GFP_KERNEL); if (!ppgtt->pt_pages) -- cgit v1.2.3 From ad52546e4336661c21b5ae927d8a9349e4a930cd Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:36 -0800 Subject: drm/i915: Disallow dynamic ppgtt param modification This would have never worked. Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 804a139901a2..13076db65eb9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -114,7 +114,7 @@ MODULE_PARM_DESC(enable_hangcheck, "(default: true)"); int i915_enable_ppgtt __read_mostly = -1; -module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600); +module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0400); MODULE_PARM_DESC(i915_enable_ppgtt, "Enable PPGTT (default: true)"); -- cgit v1.2.3 From 2f9fe5ff3e1f450f6ea7771d1d2645b522116c68 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:37 -0800 Subject: drm/i915: Demote drop_caches_set print Many tests call this ad naseum now (in an infinite loop, very often). It clutters the logs. Actually, I'd rather drop it completely... Cc: Daniel Vetter Cc: Chris Wilson Signed-off-by: Ben Widawsky Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 97c304ea4760..ee4d46593aae 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2744,7 +2744,7 @@ i915_drop_caches_set(void *data, u64 val) struct i915_vma *vma, *x; int ret; - DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val); + DRM_DEBUG("Dropping caches: 0x%08llx\n", val); /* No need to check and wait for gpu resets, only libdrm auto-restarts * on ioctls on -EAGAIN. */ -- cgit v1.2.3 From 17601cbc93bd8ee07181ac3e4456c86e94336990 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:38 -0800 Subject: drm/i915: Removed unused vm args i915_gem_execbuffer_relocate became defunct in: commit 27173f1f95db5e74ceb35fe9a2f2f348ea11bac9 Author: Ben Widawsky Date: Wed Aug 14 11:38:36 2013 +0200 drm/i915: Convert execbuf code to use vmas eb_create: never used? Signed-off-by: Ben Widawsky [danvet: The lingering vm parameter to eb_create might have been back from the days where we didn't yet keep both vmas and obj lists in the eb struct. But I didn't check really.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 885d595e0e02..740fc1da7f17 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -43,7 +43,7 @@ struct eb_vmas { }; static struct eb_vmas * -eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm) +eb_create(struct drm_i915_gem_execbuffer2 *args) { struct eb_vmas *eb = NULL; @@ -454,8 +454,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma, } static int -i915_gem_execbuffer_relocate(struct eb_vmas *eb, - struct i915_address_space *vm) +i915_gem_execbuffer_relocate(struct eb_vmas *eb) { struct i915_vma *vma; int ret = 0; @@ -1102,7 +1101,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto pre_mutex_err; } - eb = eb_create(args, vm); + eb = eb_create(args); if (eb == NULL) { mutex_unlock(&dev->struct_mutex); ret = -ENOMEM; @@ -1125,7 +1124,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, /* The objects are in their final locations, apply the relocations. */ if (need_relocs) - ret = i915_gem_execbuffer_relocate(eb, vm); + ret = i915_gem_execbuffer_relocate(eb); if (ret) { if (ret == -EFAULT) { ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring, -- cgit v1.2.3 From 2f88542607adcfe71e2d1fb6f134635e06f5d392 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:39 -0800 Subject: drm/i915: Remove defunct ctx switch comments Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2ec122a63406..41877045a1a0 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -492,8 +492,6 @@ static int do_switch(struct i915_hw_context *to) * @ring: ring for which we'll execute the context switch * @file_priv: file_priv associated with the context, may be NULL * @id: context id number - * @seqno: sequence number by which the new context will be switched to - * @flags: * * The context life cycle is simple. The context refcount is incremented and * decremented by 1 and create and destroy. If the context is in use by the GPU, -- cgit v1.2.3 From 5ce097254e71cd727687800bf15ca7af23a6bf08 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:40 -0800 Subject: drm/i915: Missed dropped VMA conversion This belonged in commit 07fe0b12800d4752d729d4122c01f41f80a5ba5a Author: Ben Widawsky Date: Wed Jul 31 17:00:10 2013 -0700 drm/i915: plumb VM into bind/unbind code But it was somehow missed along the way. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 740fc1da7f17..b800fe449530 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -307,7 +307,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, target_i915_obj = target_vma->obj; target_obj = &target_vma->obj->base; - target_offset = i915_gem_obj_ggtt_offset(target_i915_obj); + target_offset = target_vma->node.start; /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and * pipe_control writes because the gpu doesn't properly redirect them -- cgit v1.2.3 From 5ed1678206a392ac509cd1f6415df74b9008aa9a Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Nov 2013 09:54:43 -0800 Subject: drm/i915: Move the gtt mm takedown to cleanup Our VM code already has a cleanup function, and this is a nice place to put the drm_mm_takedown. This should have no functional impact, it just leaves the unload function a bit cleaer, and is more logical IMO Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 - drivers/gpu/drm/i915/i915_gem_gtt.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 25acbb5eca6e..5aeb103eae44 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1777,7 +1777,6 @@ int i915_driver_unload(struct drm_device *dev) list_del(&dev_priv->gtt.base.global_link); WARN_ON(!list_empty(&dev_priv->vm_list)); - drm_mm_takedown(&dev_priv->gtt.base.mm); drm_vblank_cleanup(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c1d04a36688f..056f1f0e2772 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1411,6 +1411,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm) { struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); + + drm_mm_takedown(&vm->mm); iounmap(gtt->gsm); teardown_scratch_page(vm->dev); } -- cgit v1.2.3 From 67e5871be82fec1451801d448b51d9a403d1ffac Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Nov 2013 20:35:24 +0000 Subject: drm/i915: Drop forcewake w/a for missed interrupts/seqno on Sandybridge I believe, and an evening of i-g-t, that our original workaround for the missed interrupts on Sandybridge, that of holding forcewake whilst we wait for an interrupts, is no longer required. This leaves us dependent on the second workaround of forcing an UC read of the ACTHD before reading back the seqno from the snooped HWS. Dropping the forcewake should allow us to conserve a little power, not much as the GPU is meant to be busy whilst we wait for it! Cc: Jesse Barnes Signed-off-by: Chris Wilson Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b65f4d77e3ed..69589e4f957f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1032,11 +1032,6 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) if (!dev->irq_enabled) return false; - /* It looks like we need to prevent the gt from suspending while waiting - * for an notifiy irq, otherwise irqs seem to get lost on at least the - * blt/bsd rings on ivb. */ - gen6_gt_force_wake_get(dev_priv); - spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { if (HAS_L3_DPF(dev) && ring->id == RCS) @@ -1068,8 +1063,6 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); - - gen6_gt_force_wake_put(dev_priv); } static bool -- cgit v1.2.3 From c293738e6d8dfb9c941759855b5161fde449644d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 29 Jun 2013 10:40:20 +0200 Subject: zorro: Do not allocate zorro_autocon[] statically Currently the array of Zorro devices is allocated statically, wasting up to 4.5 KiB when running an Amiga or multi-platform kernel on a machine with no or a handful of Zorro expansion cards. Convert it to conditional dynamic memory allocation to fix this. amiga_parse_bootinfo() still needs to store some information about the detected Zorro devices, at a time even the bootmem allocator is not yet available. This is now handled using a much smaller array (typically less than 0.5 KiB), which is __initdata and thus freed later. Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/config.c | 6 +++--- arch/m68k/amiga/platform.c | 4 ++-- drivers/zorro/zorro.c | 19 ++++++++++++++++--- include/linux/zorro.h | 18 +++++++++++++++++- 4 files changed, 38 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 93ab423758da..d956ddbfebe1 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -174,12 +174,12 @@ int __init amiga_parse_bootinfo(const struct bi_record *record) #ifdef CONFIG_ZORRO if (zorro_num_autocon < ZORRO_NUM_AUTO) { const struct ConfigDev *cd = (struct ConfigDev *)data; - struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++]; + struct zorro_dev_init *dev = &zorro_autocon_init[zorro_num_autocon++]; dev->rom = cd->cd_Rom; dev->slotaddr = cd->cd_SlotAddr; dev->slotsize = cd->cd_SlotSize; - dev->resource.start = (unsigned long)cd->cd_BoardAddr; - dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1; + dev->boardaddr = (u32)cd->cd_BoardAddr; + dev->boardsize = cd->cd_BoardSize; } else printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); #endif /* CONFIG_ZORRO */ diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index dacd9f911f71..7847b2b1b5b6 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -67,8 +67,8 @@ static int __init z_dev_present(zorro_id id) unsigned int i; for (i = 0; i < zorro_num_autocon; i++) - if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) && - zorro_autocon[i].rom.er_Product == ZORRO_PROD(id)) + if (zorro_autocon_init[i].rom.er_Manufacturer == ZORRO_MANUF(id) && + zorro_autocon_init[i].rom.er_Product == ZORRO_PROD(id)) return 1; return 0; diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 858c9714b2f3..10c7f77aec08 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -29,7 +29,8 @@ */ unsigned int zorro_num_autocon; -struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; +struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; +struct zorro_dev *zorro_autocon; /* @@ -38,6 +39,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; struct zorro_bus { struct device dev; + struct zorro_dev devices[0]; }; @@ -125,16 +127,20 @@ static struct resource __init *zorro_find_parent_resource( static int __init amiga_zorro_probe(struct platform_device *pdev) { struct zorro_bus *bus; + struct zorro_dev_init *zi; struct zorro_dev *z; struct resource *r; unsigned int i; int error; /* Initialize the Zorro bus */ - bus = kzalloc(sizeof(*bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus) + + zorro_num_autocon * sizeof(bus->devices[0]), + GFP_KERNEL); if (!bus) return -ENOMEM; + zorro_autocon = bus->devices; bus->dev.parent = &pdev->dev; dev_set_name(&bus->dev, "zorro"); error = device_register(&bus->dev); @@ -151,15 +157,22 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) /* First identify all devices ... */ for (i = 0; i < zorro_num_autocon; i++) { + zi = &zorro_autocon_init[i]; z = &zorro_autocon[i]; + + z->rom = zi->rom; z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); if (z->id == ZORRO_PROD_GVP_EPC_BASE) { /* GVP quirk */ - unsigned long magic = zorro_resource_start(z)+0x8000; + unsigned long magic = zi->boardaddr + 0x8000; z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; } + z->slotaddr = zi->slotaddr; + z->slotsize = zi->slotsize; sprintf(z->name, "Zorro device %08x", z->id); zorro_name_device(z); + z->resource.start = zi->boardaddr; + z->resource.end = zi->boardaddr + zi->boardsize - 1; z->resource.name = z->name; r = zorro_find_parent_resource(pdev, z); error = request_resource(r, &z->resource); diff --git a/include/linux/zorro.h b/include/linux/zorro.h index dff42025649b..661cbd2a86ee 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -175,7 +175,23 @@ static inline struct zorro_driver *zorro_dev_driver(const struct zorro_dev *z) extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */ -extern struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; +extern struct zorro_dev *zorro_autocon; + + + /* + * Minimal information about a Zorro device, passed from bootinfo + * Only available temporarily, i.e. until initmem has been freed! + */ + +struct zorro_dev_init { + struct ExpansionRom rom; + u16 slotaddr; + u16 slotsize; + u32 boardaddr; + u32 boardsize; +}; + +extern struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; /* -- cgit v1.2.3 From bd79014cd47b3a0fa59a7a17489d8ada56ecab9b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 30 Jun 2013 13:01:26 +0200 Subject: zorro: Don't fill in dummy names in zorro_name_device() If the device is not found in the database, it's not needed to fill in a dummy name. The caller of zorro_name_device() has already taken care of that to support CONFIG_ZORRO_NAMES=n. Signed-off-by: Geert Uytterhoeven --- drivers/zorro/names.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/zorro/names.c b/drivers/zorro/names.c index e8517c3d8e82..e44e04c4f29d 100644 --- a/drivers/zorro/names.c +++ b/drivers/zorro/names.c @@ -69,7 +69,6 @@ void __init zorro_name_device(struct zorro_dev *dev) } while (--i); /* Couldn't find either the manufacturer nor the product */ - sprintf(name, "Zorro device %08x", dev->id); return; match_manuf: { -- cgit v1.2.3 From 52182c758f7c9bc34dbee0dfdce13d356de50f03 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 17 May 2013 14:01:24 +0200 Subject: zorro: Refactor conditional handling of Zorro device name database Using an empty static inline function in the CONFIG_ZORRO_NAMES=n case allows to drop compilation of names.c. Signed-off-by: Geert Uytterhoeven --- drivers/zorro/Makefile | 3 ++- drivers/zorro/names.c | 10 ---------- drivers/zorro/zorro.h | 5 +++++ 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/zorro/Makefile b/drivers/zorro/Makefile index f62172603215..7dc5332ff984 100644 --- a/drivers/zorro/Makefile +++ b/drivers/zorro/Makefile @@ -2,8 +2,9 @@ # Makefile for the Zorro bus specific drivers. # -obj-$(CONFIG_ZORRO) += zorro.o zorro-driver.o zorro-sysfs.o names.o +obj-$(CONFIG_ZORRO) += zorro.o zorro-driver.o zorro-sysfs.o obj-$(CONFIG_PROC_FS) += proc.o +obj-$(CONFIG_ZORRO_NAMES) += names.o hostprogs-y := gen-devlist diff --git a/drivers/zorro/names.c b/drivers/zorro/names.c index e44e04c4f29d..6f3fd9903ac3 100644 --- a/drivers/zorro/names.c +++ b/drivers/zorro/names.c @@ -15,8 +15,6 @@ #include -#ifdef CONFIG_ZORRO_NAMES - struct zorro_prod_info { __u16 prod; unsigned short seen; @@ -97,11 +95,3 @@ void __init zorro_name_device(struct zorro_dev *dev) } } } - -#else - -void __init zorro_name_device(struct zorro_dev *dev) -{ -} - -#endif diff --git a/drivers/zorro/zorro.h b/drivers/zorro/zorro.h index b682d5ccd63f..34119fb4e560 100644 --- a/drivers/zorro/zorro.h +++ b/drivers/zorro/zorro.h @@ -1,4 +1,9 @@ +#ifdef CONFIG_ZORRO_NAMES extern void zorro_name_device(struct zorro_dev *z); +#else +static inline void zorro_name_device(struct zorro_dev *dev) { } +#endif + extern int zorro_create_sysfs_dev_files(struct zorro_dev *z); -- cgit v1.2.3 From 83b7bce3d390f15047e05a186bb4051536ee9dbc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 16 Oct 2013 11:28:54 +0200 Subject: zorro: Let the driver core handle device enumeration Filling in dev_name of the Zorro bus type and dev.id of each device allows the driver core to enumerate devices, so we don't have to do that ourselves. This changes the names of devices in sysfs from "%02x" to "zorro%u". Note that filling in dev.id is also needed to support MFD Zorro devices. Signed-off-by: Geert Uytterhoeven --- drivers/zorro/zorro-driver.c | 11 ++++++----- drivers/zorro/zorro.c | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index ac1db7f1bcab..eacae1434b73 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -161,11 +161,12 @@ static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) } struct bus_type zorro_bus_type = { - .name = "zorro", - .match = zorro_bus_match, - .uevent = zorro_uevent, - .probe = zorro_device_probe, - .remove = zorro_device_remove, + .name = "zorro", + .dev_name = "zorro", + .match = zorro_bus_match, + .uevent = zorro_uevent, + .probe = zorro_device_probe, + .remove = zorro_device_remove, }; EXPORT_SYMBOL(zorro_bus_type); diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 10c7f77aec08..450abf100f06 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -142,7 +142,7 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) zorro_autocon = bus->devices; bus->dev.parent = &pdev->dev; - dev_set_name(&bus->dev, "zorro"); + dev_set_name(&bus->dev, zorro_bus_type.name); error = device_register(&bus->dev); if (error) { pr_err("Zorro: Error registering zorro_bus\n"); @@ -180,9 +180,9 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) dev_err(&bus->dev, "Address space collision on device %s %pR\n", z->name, &z->resource); - dev_set_name(&z->dev, "%02x", i); z->dev.parent = &bus->dev; z->dev.bus = &zorro_bus_type; + z->dev.id = i; } /* ... then register them */ -- cgit v1.2.3 From 6112ea0862facaeaeab504ee01c0d04bcd22daaf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 9 Jan 2011 11:03:43 +0100 Subject: zorro: ZTWO_VADDR() should return "void __iomem *" ZTWO_VADDR() converts from physical to virtual I/O addresses, so it should return "void __iomem *" instead of "unsigned long". This allows to drop several casts, but requires adding a few casts to accomodate legacy driver frameworks that store "unsigned long" I/O addresses. Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/chipram.c | 2 +- arch/m68k/amiga/config.c | 2 +- arch/m68k/include/asm/amigahw.h | 2 +- drivers/block/z2ram.c | 4 ++-- drivers/ide/buddha.c | 2 +- drivers/net/ethernet/8390/hydra.c | 2 +- drivers/net/ethernet/8390/zorro8390.c | 4 ++-- drivers/net/ethernet/amd/a2065.c | 4 ++-- drivers/net/ethernet/amd/ariadne.c | 4 ++-- drivers/parport/parport_mfc3.c | 2 +- drivers/scsi/a2091.c | 2 +- drivers/scsi/a3000.c | 2 +- drivers/scsi/a4000t.c | 2 +- drivers/scsi/gvp11.c | 2 +- drivers/scsi/zorro7xx.c | 2 +- drivers/video/amifb.c | 2 +- drivers/video/cirrusfb.c | 4 ++-- 17 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c index 99449fbf9a72..ba03cec3f711 100644 --- a/arch/m68k/amiga/chipram.c +++ b/arch/m68k/amiga/chipram.c @@ -87,7 +87,7 @@ void *amiga_chip_alloc_res(unsigned long size, struct resource *res) atomic_sub(size, &chipavail); pr_debug("amiga_chip_alloc_res: returning %pR\n", res); - return (void *)ZTWO_VADDR(res->start); + return ZTWO_VADDR(res->start); } void amiga_chip_free(void *ptr) diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index d956ddbfebe1..acd9c1640cfc 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -618,7 +618,7 @@ static int __init amiga_savekmsg_setup(char *arg) /* Just steal the block, the chipram allocator isn't functional yet */ amiga_chip_size -= SAVEKMSG_MAXMEM; - savekmsg = (void *)ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size); + savekmsg = ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; savekmsg->magicptr = ZTWO_PADDR(savekmsg); diff --git a/arch/m68k/include/asm/amigahw.h b/arch/m68k/include/asm/amigahw.h index 7a19b5686a4a..3bef0b2ad945 100644 --- a/arch/m68k/include/asm/amigahw.h +++ b/arch/m68k/include/asm/amigahw.h @@ -266,7 +266,7 @@ struct CIA { #define zTwoBase (0x80000000) #define ZTWO_PADDR(x) (((unsigned long)(x))-zTwoBase) -#define ZTWO_VADDR(x) (((unsigned long)(x))+zTwoBase) +#define ZTWO_VADDR(x) ((void __iomem *)(((unsigned long)(x))+zTwoBase)) #define CUSTOM_PHYSADDR (0xdff000) #define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR))) diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 5a95baf4b104..8b2a60cee3a0 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -116,8 +116,8 @@ get_z2ram( void ) if ( test_bit( i, zorro_unused_z2ram ) ) { z2_count++; - z2ram_map[ z2ram_size++ ] = - ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT ); + z2ram_map[z2ram_size++] = (unsigned long)ZTWO_VADDR(Z2RAM_START) + + (i << Z2RAM_CHUNKSHIFT); clear_bit( i, zorro_unused_z2ram ); } } diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c index b1d38590ac01..46eaf58d881b 100644 --- a/drivers/ide/buddha.c +++ b/drivers/ide/buddha.c @@ -198,7 +198,7 @@ fail_base2: continue; } } - buddha_board = ZTWO_VADDR(board); + buddha_board = (unsigned long)ZTWO_VADDR(board); /* write to BUDDHA_IRQ_MR to enable the board IRQ */ /* X-Surf doesn't have this. IRQs are always on */ diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c index fb3dd4399cf3..f615fdec0f1b 100644 --- a/drivers/net/ethernet/8390/hydra.c +++ b/drivers/net/ethernet/8390/hydra.c @@ -113,7 +113,7 @@ static const struct net_device_ops hydra_netdev_ops = { static int hydra_init(struct zorro_dev *z) { struct net_device *dev; - unsigned long board = ZTWO_VADDR(z->resource.start); + unsigned long board = (unsigned long)ZTWO_VADDR(z->resource.start); unsigned long ioaddr = board+HYDRA_NIC_BASE; const char name[] = "NE2000"; int start_page, stop_page; diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c index 85ec4c2d2645..ae2a12b7db62 100644 --- a/drivers/net/ethernet/8390/zorro8390.c +++ b/drivers/net/ethernet/8390/zorro8390.c @@ -287,7 +287,7 @@ static const struct net_device_ops zorro8390_netdev_ops = { }; static int zorro8390_init(struct net_device *dev, unsigned long board, - const char *name, unsigned long ioaddr) + const char *name, void __iomem *ioaddr) { int i; int err; @@ -354,7 +354,7 @@ static int zorro8390_init(struct net_device *dev, unsigned long board, start_page = NESM_START_PG; stop_page = NESM_STOP_PG; - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long)ioaddr; dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index 0866e7627433..f492a19328e5 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -713,8 +713,8 @@ static int a2065_init_one(struct zorro_dev *z, dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; - dev->base_addr = ZTWO_VADDR(base_addr); - dev->mem_start = ZTWO_VADDR(mem_start); + dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr); + dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start); dev->mem_end = dev->mem_start + A2065_RAM_SIZE; priv->ll = (volatile struct lance_regs *)dev->base_addr; diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c index c178eb4c8166..33822cb69366 100644 --- a/drivers/net/ethernet/amd/ariadne.c +++ b/drivers/net/ethernet/amd/ariadne.c @@ -747,8 +747,8 @@ static int ariadne_init_one(struct zorro_dev *z, dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; - dev->base_addr = ZTWO_VADDR(base_addr); - dev->mem_start = ZTWO_VADDR(mem_start); + dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr); + dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start); dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE; dev->netdev_ops = &ariadne_netdev_ops; diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c index 7578d79b3688..2f650f68af14 100644 --- a/drivers/parport/parport_mfc3.c +++ b/drivers/parport/parport_mfc3.c @@ -300,7 +300,7 @@ static int __init parport_mfc3_init(void) if (!request_mem_region(piabase, sizeof(struct pia), "PIA")) continue; - pp = (struct pia *)ZTWO_VADDR(piabase); + pp = ZTWO_VADDR(piabase); pp->crb = 0; pp->pddrb = 255; /* all data pins output */ pp->crb = PIA_DDR|32|8; diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 30fa38a0ad39..9176bfbd5745 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -201,7 +201,7 @@ static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent) instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; - regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start); + regs = ZTWO_VADDR(z->resource.start); regs->DAWR = DAWR_A2091; wdregs.SASR = ®s->SASR; diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index c0f4f4290dd6..dd5b64726ddc 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -220,7 +220,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) instance->irq = IRQ_AMIGA_PORTS; - regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start); + regs = ZTWO_VADDR(res->start); regs->DAWR = DAWR_A3000; wdregs.SASR = ®s->SASR; diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 70c521f79f7c..f5a2ab41543b 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -56,7 +56,7 @@ static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev) scsi_addr = res->start + A4000T_SCSI_OFFSET; /* Fill in the required pieces of hostdata */ - hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr); + hostdata->base = ZTWO_VADDR(scsi_addr); hostdata->clock = 50; hostdata->chip710 = 1; hostdata->dmode_extra = DMODE_FC2; diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 2203ac281103..3b6f83ffddc4 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -310,7 +310,7 @@ static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent) if (!request_mem_region(address, 256, "wd33c93")) return -EBUSY; - regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); + regs = ZTWO_VADDR(address); error = check_wd33c93(regs); if (error) diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index cbf3476c68cd..aff31991aea9 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -104,7 +104,7 @@ static int zorro7xx_init_one(struct zorro_dev *z, if (ioaddr > 0x01000000) hostdata->base = ioremap(ioaddr, zorro_resource_len(z)); else - hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr); + hostdata->base = ZTWO_VADDR(ioaddr); hostdata->clock = 50; hostdata->chip710 = 1; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 0dac36ce09d6..518f790ef88a 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -3710,7 +3710,7 @@ default_chipset: if (!videomemory) { dev_warn(&pdev->dev, "Unable to map videomem cached writethrough\n"); - info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start); + info->screen_base = ZTWO_VADDR(info->fix.smem_start); } else info->screen_base = (char *)videomemory; diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 5aab9b9dc210..d992aa5eb3f0 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2256,7 +2256,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, info->fix.mmio_start = regbase; cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) - : (caddr_t)ZTWO_VADDR(regbase); + : ZTWO_VADDR(regbase); if (!cinfo->regbase) { dev_err(info->device, "Cannot map registers\n"); error = -EIO; @@ -2266,7 +2266,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, info->fix.smem_start = rambase; info->screen_size = ramsize; info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) - : (caddr_t)ZTWO_VADDR(rambase); + : ZTWO_VADDR(rambase); if (!info->screen_base) { dev_err(info->device, "Cannot map video RAM\n"); error = -EIO; -- cgit v1.2.3 From bd9ba8f40ee30edf31cc0845d8838bc43d172ef3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 4 Oct 2013 09:38:53 +0200 Subject: zorro/UAPI: Use proper types (endianness/size) in Fix member definitions for non-native userspace handling: - All multi-byte values are big-endian, hence use __be*, - All pointers are 32-bit pointers under AmigaOS, but unused (except for cd_BoardAddr) under Linux, hence use __be32. Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/config.c | 9 ++++---- arch/m68k/amiga/platform.c | 9 +++++--- drivers/net/ethernet/amd/a2065.c | 9 +++++--- drivers/net/ethernet/amd/ariadne.c | 9 +++++--- drivers/zorro/proc.c | 10 +++++---- drivers/zorro/zorro-sysfs.c | 22 +++++++++++++----- drivers/zorro/zorro.c | 4 +++- include/uapi/linux/zorro.h | 46 +++++++++++++++++++------------------- 8 files changed, 72 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index acd9c1640cfc..65b5e937ebba 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -176,10 +177,10 @@ int __init amiga_parse_bootinfo(const struct bi_record *record) const struct ConfigDev *cd = (struct ConfigDev *)data; struct zorro_dev_init *dev = &zorro_autocon_init[zorro_num_autocon++]; dev->rom = cd->cd_Rom; - dev->slotaddr = cd->cd_SlotAddr; - dev->slotsize = cd->cd_SlotSize; - dev->boardaddr = (u32)cd->cd_BoardAddr; - dev->boardsize = cd->cd_BoardSize; + dev->slotaddr = be16_to_cpu(cd->cd_SlotAddr); + dev->slotsize = be16_to_cpu(cd->cd_SlotSize); + dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr); + dev->boardsize = be32_to_cpu(cd->cd_BoardSize); } else printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); #endif /* CONFIG_ZORRO */ diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 7847b2b1b5b6..d34029d7b058 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -13,6 +13,7 @@ #include #include +#include #ifdef CONFIG_ZORRO @@ -66,10 +67,12 @@ static int __init z_dev_present(zorro_id id) { unsigned int i; - for (i = 0; i < zorro_num_autocon; i++) - if (zorro_autocon_init[i].rom.er_Manufacturer == ZORRO_MANUF(id) && - zorro_autocon_init[i].rom.er_Product == ZORRO_PROD(id)) + for (i = 0; i < zorro_num_autocon; i++) { + const struct ExpansionRom *rom = &zorro_autocon_init[i].rom; + if (be16_to_cpu(rom->er_Manufacturer) == ZORRO_MANUF(id) && + rom->er_Product == ZORRO_PROD(id)) return 1; + } return 0; } diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index f492a19328e5..56139184b801 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -57,6 +57,7 @@ #include #include +#include #include #include #include @@ -678,6 +679,7 @@ static int a2065_init_one(struct zorro_dev *z, unsigned long base_addr = board + A2065_LANCE; unsigned long mem_start = board + A2065_RAM; struct resource *r1, *r2; + u32 serial; int err; r1 = request_mem_region(base_addr, sizeof(struct lance_regs), @@ -702,6 +704,7 @@ static int a2065_init_one(struct zorro_dev *z, r1->name = dev->name; r2->name = dev->name; + serial = be32_to_cpu(z->rom.er_SerialNumber); dev->dev_addr[0] = 0x00; if (z->id != ZORRO_PROD_AMERISTAR_A2065) { /* Commodore */ dev->dev_addr[1] = 0x80; @@ -710,9 +713,9 @@ static int a2065_init_one(struct zorro_dev *z, dev->dev_addr[1] = 0x00; dev->dev_addr[2] = 0x9f; } - dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; - dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; - dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; + dev->dev_addr[3] = (serial >> 16) & 0xff; + dev->dev_addr[4] = (serial >> 8) & 0xff; + dev->dev_addr[5] = serial & 0xff; dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr); dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start); dev->mem_end = dev->mem_start + A2065_RAM_SIZE; diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c index 33822cb69366..b08101b31b8b 100644 --- a/drivers/net/ethernet/amd/ariadne.c +++ b/drivers/net/ethernet/amd/ariadne.c @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -718,6 +719,7 @@ static int ariadne_init_one(struct zorro_dev *z, struct resource *r1, *r2; struct net_device *dev; struct ariadne_private *priv; + u32 serial; int err; r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960"); @@ -741,12 +743,13 @@ static int ariadne_init_one(struct zorro_dev *z, r1->name = dev->name; r2->name = dev->name; + serial = be32_to_cpu(z->rom.er_SerialNumber); dev->dev_addr[0] = 0x00; dev->dev_addr[1] = 0x60; dev->dev_addr[2] = 0x30; - dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff; - dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff; - dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; + dev->dev_addr[3] = (serial >> 16) & 0xff; + dev->dev_addr[4] = (serial >> 8) & 0xff; + dev->dev_addr[5] = serial & 0xff; dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr); dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start); dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE; diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index ea1ce822a8e0..6ac2579da0eb 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -14,6 +14,8 @@ #include #include #include + +#include #include #include #include @@ -41,10 +43,10 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t * /* Construct a ConfigDev */ memset(&cd, 0, sizeof(cd)); cd.cd_Rom = z->rom; - cd.cd_SlotAddr = z->slotaddr; - cd.cd_SlotSize = z->slotsize; - cd.cd_BoardAddr = (void *)zorro_resource_start(z); - cd.cd_BoardSize = zorro_resource_len(z); + cd.cd_SlotAddr = cpu_to_be16(z->slotaddr); + cd.cd_SlotSize = cpu_to_be16(z->slotsize); + cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z)); + cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z)); if (copy_to_user(buf, (void *)&cd + pos, nbytes)) return -EFAULT; diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 26f7184ef9e1..36b210f9b6b2 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -16,6 +16,8 @@ #include #include +#include + #include "zorro.h" @@ -33,10 +35,20 @@ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); zorro_config_attr(id, id, "0x%08x\n"); zorro_config_attr(type, rom.er_Type, "0x%02x\n"); -zorro_config_attr(serial, rom.er_SerialNumber, "0x%08x\n"); zorro_config_attr(slotaddr, slotaddr, "0x%04x\n"); zorro_config_attr(slotsize, slotsize, "0x%04x\n"); +static ssize_t +show_serial(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct zorro_dev *z; + + z = to_zorro_dev(dev); + return sprintf(buf, "0x%08x\n", be32_to_cpu(z->rom.er_SerialNumber)); +} + +static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); + static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf) { struct zorro_dev *z = to_zorro_dev(dev); @@ -60,10 +72,10 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj, /* Construct a ConfigDev */ memset(&cd, 0, sizeof(cd)); cd.cd_Rom = z->rom; - cd.cd_SlotAddr = z->slotaddr; - cd.cd_SlotSize = z->slotsize; - cd.cd_BoardAddr = (void *)zorro_resource_start(z); - cd.cd_BoardSize = zorro_resource_len(z); + cd.cd_SlotAddr = cpu_to_be16(z->slotaddr); + cd.cd_SlotSize = cpu_to_be16(z->slotsize); + cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z)); + cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z)); return memory_read_from_buffer(buf, count, &off, &cd, sizeof(cd)); } diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 450abf100f06..707c1a5a0317 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -161,7 +162,8 @@ static int __init amiga_zorro_probe(struct platform_device *pdev) z = &zorro_autocon[i]; z->rom = zi->rom; - z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); + z->id = (be16_to_cpu(z->rom.er_Manufacturer) << 16) | + (z->rom.er_Product << 8); if (z->id == ZORRO_PROD_GVP_EPC_BASE) { /* GVP quirk */ unsigned long magic = zi->boardaddr + 0x8000; diff --git a/include/uapi/linux/zorro.h b/include/uapi/linux/zorro.h index 36a033e23d31..59d021b242ed 100644 --- a/include/uapi/linux/zorro.h +++ b/include/uapi/linux/zorro.h @@ -63,26 +63,26 @@ enum GVP_flags { struct Node { - struct Node *ln_Succ; /* Pointer to next (successor) */ - struct Node *ln_Pred; /* Pointer to previous (predecessor) */ - __u8 ln_Type; - __s8 ln_Pri; /* Priority, for sorting */ - __s8 *ln_Name; /* ID string, null terminated */ + __be32 ln_Succ; /* Pointer to next (successor) */ + __be32 ln_Pred; /* Pointer to previous (predecessor) */ + __u8 ln_Type; + __s8 ln_Pri; /* Priority, for sorting */ + __be32 ln_Name; /* ID string, null terminated */ } __packed; struct ExpansionRom { /* -First 16 bytes of the expansion ROM */ - __u8 er_Type; /* Board type, size and flags */ - __u8 er_Product; /* Product number, assigned by manufacturer */ - __u8 er_Flags; /* Flags */ - __u8 er_Reserved03; /* Must be zero ($ff inverted) */ - __u16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */ - __u32 er_SerialNumber; /* Available for use by manufacturer */ - __u16 er_InitDiagVec; /* Offset to optional "DiagArea" structure */ - __u8 er_Reserved0c; - __u8 er_Reserved0d; - __u8 er_Reserved0e; - __u8 er_Reserved0f; + __u8 er_Type; /* Board type, size and flags */ + __u8 er_Product; /* Product number, assigned by manufacturer */ + __u8 er_Flags; /* Flags */ + __u8 er_Reserved03; /* Must be zero ($ff inverted) */ + __be16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */ + __be32 er_SerialNumber; /* Available for use by manufacturer */ + __be16 er_InitDiagVec; /* Offset to optional "DiagArea" structure */ + __u8 er_Reserved0c; + __u8 er_Reserved0d; + __u8 er_Reserved0e; + __u8 er_Reserved0f; } __packed; /* er_Type board type bits */ @@ -99,13 +99,13 @@ struct ConfigDev { __u8 cd_Flags; /* (read/write) */ __u8 cd_Pad; /* reserved */ struct ExpansionRom cd_Rom; /* copy of board's expansion ROM */ - void *cd_BoardAddr; /* where in memory the board was placed */ - __u32 cd_BoardSize; /* size of board in bytes */ - __u16 cd_SlotAddr; /* which slot number (PRIVATE) */ - __u16 cd_SlotSize; /* number of slots (PRIVATE) */ - void *cd_Driver; /* pointer to node of driver */ - struct ConfigDev *cd_NextCD; /* linked list of drivers to config */ - __u32 cd_Unused[4]; /* for whatever the driver wants */ + __be32 cd_BoardAddr; /* where in memory the board was placed */ + __be32 cd_BoardSize; /* size of board in bytes */ + __be16 cd_SlotAddr; /* which slot number (PRIVATE) */ + __be16 cd_SlotSize; /* number of slots (PRIVATE) */ + __be32 cd_Driver; /* pointer to node of driver */ + __be32 cd_NextCD; /* linked list of drivers to config */ + __be32 cd_Unused[4]; /* for whatever the driver wants */ } __packed; #define ZORRO_NUM_AUTO 16 -- cgit v1.2.3 From b3ce71720560a9125aa0343bdbf501d887dbfb74 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 4 Oct 2013 12:38:23 +0200 Subject: block/z2ram: Remove duplicate external declarations Remove the external declarations for m68k_realnum_memory and m68k_memory, which are already provided by , to avoid conflicts later. Signed-off-by: Geert Uytterhoeven --- drivers/block/z2ram.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 8b2a60cee3a0..27de5046708a 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -43,9 +43,6 @@ #include -extern int m68k_realnum_memory; -extern struct mem_info m68k_memory[NUM_MEMINFO]; - #define Z2MINOR_COMBINED (0) #define Z2MINOR_Z2ONLY (1) #define Z2MINOR_CHIPONLY (2) -- cgit v1.2.3 From 371001e502e8cd3543f7b9907d398a112939dff7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 5 Oct 2013 21:14:22 +0200 Subject: m68k: Remove superfluous inclusions of Signed-off-by: Geert Uytterhoeven --- arch/m68k/mac/iop.c | 1 - arch/m68k/mac/misc.c | 1 - arch/m68k/mac/oss.c | 1 - arch/m68k/mac/psc.c | 1 - arch/m68k/mac/via.c | 1 - arch/m68k/sun3x/prom.c | 1 - drivers/net/ethernet/natsemi/macsonic.c | 1 - drivers/video/macfb.c | 1 - drivers/video/valkyriefb.c | 1 - 9 files changed, 9 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index ed0d9b0473ea..4d2adfb32a2a 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -111,7 +111,6 @@ #include #include -#include #include #include #include diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 3d02a3c3a93a..707b61aea203 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -25,7 +25,6 @@ #include #include -#include #include /* Offset between Unix time (1970-based) and Mac time (1904-based) */ diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index 6c4c882c126e..54037125ebf8 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index cc9f3f097be7..835fa04511c8 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 5d1458bb871b..e198dec868e4 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c index a7b7e818d627..0898c3f81508 100644 --- a/arch/m68k/sun3x/prom.c +++ b/arch/m68k/sun3x/prom.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 346a4e025c34..04b3ec1352f1 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -52,7 +52,6 @@ #include #include -#include #include #include #include diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 5bd2eb8d4f39..cda7587cbc86 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -34,7 +34,6 @@ #include #include -#include #include #include diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index e287ebc47817..97cb9bd1d1dd 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -56,7 +56,6 @@ #include #include #ifdef CONFIG_MAC -#include #include #else #include -- cgit v1.2.3 From 989c78dd56307c85f710533130a2a464f6f3c5ae Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 28 Oct 2013 23:49:26 +0100 Subject: usb: gadget: r8a66597-udc: convert to clk_prepare/unprepare Turn clk_enable() and clk_disable() calls into clk_prepare_enable() and clk_disable_unprepare() to get ready for the migration to the common clock framework. Cc: Felipe Balbi Cc: linux-usb@vger.kernel.org Signed-off-by: Laurent Pinchart Signed-off-by: Felipe Balbi --- drivers/usb/gadget/r8a66597-udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 68be48d33404..47287518bff3 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1833,7 +1833,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev) r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); if (r8a66597->pdata->on_chip) { - clk_disable(r8a66597->clk); + clk_disable_unprepare(r8a66597->clk); clk_put(r8a66597->clk); } @@ -1931,7 +1931,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) ret = PTR_ERR(r8a66597->clk); goto clean_up; } - clk_enable(r8a66597->clk); + clk_prepare_enable(r8a66597->clk); } if (r8a66597->pdata->sudmac) { @@ -1996,7 +1996,7 @@ clean_up3: free_irq(irq, r8a66597); clean_up2: if (r8a66597->pdata->on_chip) { - clk_disable(r8a66597->clk); + clk_disable_unprepare(r8a66597->clk); clk_put(r8a66597->clk); } clean_up: -- cgit v1.2.3 From 943c13971c08ddeb06f4cb9dea1addb76f6b4423 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 Oct 2013 12:17:16 -0500 Subject: usb: musb: dsps: implement ->set_mode() this will let us support broken designs such as AM335x EVM SK where ID pin isn't routed anywhere on a host port. With this we can toggle internal IDDIG signal and make sure MUSB goes into host mode as necessary. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1901f6fe5807..ce7ec014a125 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -106,6 +106,7 @@ struct dsps_musb_wrapper { /* bit positions for mode */ unsigned iddig:5; + unsigned iddig_mux:5; /* miscellaneous stuff */ u8 poll_seconds; }; @@ -406,6 +407,54 @@ static int dsps_musb_exit(struct musb *musb) return 0; } +static int dsps_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct dsps_glue *glue = dev_get_drvdata(dev->parent); + const struct dsps_musb_wrapper *wrp = glue->wrp; + void __iomem *ctrl_base = musb->ctrl_base; + void __iomem *base = musb->mregs; + u32 reg; + + reg = dsps_readl(base, wrp->mode); + + switch (mode) { + case MUSB_HOST: + reg &= ~(1 << wrp->iddig); + + /* + * if we're setting mode to host-only or device-only, we're + * going to ignore whatever the PHY sends us and just force + * ID pin status by SW + */ + reg |= (1 << wrp->iddig_mux); + + dsps_writel(base, wrp->mode, reg); + dsps_writel(ctrl_base, wrp->phy_utmi, 0x02); + break; + case MUSB_PERIPHERAL: + reg |= (1 << wrp->iddig); + + /* + * if we're setting mode to host-only or device-only, we're + * going to ignore whatever the PHY sends us and just force + * ID pin status by SW + */ + reg |= (1 << wrp->iddig_mux); + + dsps_writel(base, wrp->mode, reg); + break; + case MUSB_OTG: + dsps_writel(base, wrp->phy_utmi, 0x02); + break; + default: + dev_err(glue->dev, "unsupported mode %d\n", mode); + return -EINVAL; + } + + return 0; +} + static struct musb_platform_ops dsps_ops = { .init = dsps_musb_init, .exit = dsps_musb_exit, @@ -414,6 +463,7 @@ static struct musb_platform_ops dsps_ops = { .disable = dsps_musb_disable, .try_idle = dsps_musb_try_idle, + .set_mode = dsps_musb_set_mode, }; static u64 musb_dmamask = DMA_BIT_MASK(32); @@ -608,6 +658,7 @@ static const struct dsps_musb_wrapper am33xx_driver_data = { .reset = 0, .otg_disable = 21, .iddig = 8, + .iddig_mux = 7, .usb_shift = 0, .usb_mask = 0x1ff, .usb_bitmap = (0x1ff << 0), -- cgit v1.2.3 From 2df6761e5eca9a810050a15062ae8abce1bbae41 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 Oct 2013 12:17:17 -0500 Subject: usb: musb: core: call musb_platform_set_mode() during probe This will tell glue layer which mode we want port to be in. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0a43329569d1..377ef9b29c73 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1941,17 +1941,26 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) switch (musb->port_mode) { case MUSB_PORT_MODE_HOST: status = musb_host_setup(musb, plat->power); + if (status < 0) + goto fail3; + status = musb_platform_set_mode(musb, MUSB_HOST); break; case MUSB_PORT_MODE_GADGET: status = musb_gadget_setup(musb); + if (status < 0) + goto fail3; + status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); break; case MUSB_PORT_MODE_DUAL_ROLE: status = musb_host_setup(musb, plat->power); if (status < 0) goto fail3; status = musb_gadget_setup(musb); - if (status) + if (status) { musb_host_cleanup(musb); + goto fail3; + } + status = musb_platform_set_mode(musb, MUSB_OTG); break; default: dev_err(dev, "unsupported port mode %d\n", musb->port_mode); -- cgit v1.2.3 From e0a6104e066595bcf791381a23b568ab0a890707 Mon Sep 17 00:00:00 2001 From: George Cherian Date: Wed, 25 Sep 2013 11:59:43 +0530 Subject: usb: dwc3: dwc3-omap: return PROBE_DEFER if extcon is missing and found in dt Due to inter dependencies of I2C and extcon by the time dwc3 checks for extcon device its not registered especially in case of J6. In O5 the vbus regulator save us from getting to this point. So for tiime being return PROBE_DEFER if extcon is enabled in dt. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 7f7ea62e961b..daab0ad10b25 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -535,7 +535,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) edev = of_extcon_get_extcon_dev(dev, 0); if (IS_ERR(edev)) { dev_vdbg(dev, "couldn't get extcon device\n"); - ret = PTR_ERR(edev); + ret = -EPROBE_DEFER; goto err2; } -- cgit v1.2.3 From c338412b5dedf405d3f8ba3af1a61fa623319e1d Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 25 Nov 2013 22:26:40 +0100 Subject: usb: musb: unconditionally save and restore the context on suspend It appears not all platforms featuring a musb core need to save the musb core registers at suspend time and restore them on resume. The dsps platform does, however, and because it shouldn't cause any trouble on other platforms, do it unconditionally for all of them. Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 377ef9b29c73..ac96e4ce7e95 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2224,16 +2224,28 @@ static int musb_suspend(struct device *dev) */ } + musb_save_context(musb); + spin_unlock_irqrestore(&musb->lock, flags); return 0; } static int musb_resume_noirq(struct device *dev) { - /* for static cmos like DaVinci, register values were preserved + struct musb *musb = dev_to_musb(dev); + + /* + * For static cmos like DaVinci, register values were preserved * unless for some reason the whole soc powered down or the USB * module got reset through the PSC (vs just being disabled). + * + * For the DSPS glue layer though, a full register restore has to + * be done. As it shouldn't harm other platforms, we do it + * unconditionally. */ + + musb_restore_context(musb); + return 0; } -- cgit v1.2.3 From 94f72136a86141604bcab75a2548b6488e70128d Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 25 Nov 2013 22:26:41 +0100 Subject: usb: musb: call musb_port_suspend from musb_bus_suspend Make musb_port_suspend() externally available, and call it when to host goes into suspend. This allows the core to go into suspend while a device is connected. Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 2 ++ drivers/usb/musb/musb_host.h | 2 ++ drivers/usb/musb/musb_virthub.c | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 6582a20bec05..81caf9f4eb1a 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2433,6 +2433,8 @@ static int musb_bus_suspend(struct usb_hcd *hcd) struct musb *musb = hcd_to_musb(hcd); u8 devctl; + musb_port_suspend(musb, true); + if (!is_host_active(musb)) return 0; diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 960d73570b2f..e660af90272d 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -92,6 +92,7 @@ extern void musb_host_rx(struct musb *, u8); extern void musb_root_disconnect(struct musb *musb); extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_poke_root_hub(struct musb *musb); +extern void musb_port_suspend(struct musb *musb, bool do_suspend); #else static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) { @@ -121,6 +122,7 @@ static inline void musb_root_disconnect(struct musb *musb) {} static inline void musb_host_resume_root_hub(struct musb *musb) {} static inline void musb_host_poll_rh_status(struct musb *musb) {} static inline void musb_host_poke_root_hub(struct musb *musb) {} +static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {} #endif struct usb_hcd; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 9af6bba5eac9..e977441401ed 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -44,7 +44,7 @@ #include "musb_core.h" -static void musb_port_suspend(struct musb *musb, bool do_suspend) +void musb_port_suspend(struct musb *musb, bool do_suspend) { struct usb_otg *otg = musb->xceiv->otg; u8 power; -- cgit v1.2.3 From b991f9b77c029135f6e0d1d5d16869ebf755c4c0 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 25 Nov 2013 22:26:42 +0100 Subject: usb: musb: dsps: add {tx,rx}_mode to wrapper rx_mode and tx_mode need to be read at suspend time and restored on resume for dsps platforms. So add it to the wrapper struct first, and initialize the values. Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index ce7ec014a125..3f3724471667 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -83,6 +83,8 @@ struct dsps_musb_wrapper { u16 coreintr_status; u16 phy_utmi; u16 mode; + u16 tx_mode; + u16 rx_mode; /* bit positions for control */ unsigned reset:5; @@ -655,6 +657,8 @@ static const struct dsps_musb_wrapper am33xx_driver_data = { .coreintr_status = 0x34, .phy_utmi = 0xe0, .mode = 0xe8, + .tx_mode = 0x70, + .rx_mode = 0x74, .reset = 0, .otg_disable = 21, .iddig = 8, -- cgit v1.2.3 From 252d0d2bb07119296e215de7dc9afa8d12746b80 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Tue, 26 Nov 2013 13:48:09 +0200 Subject: clk: tegra: add TEGRA_DIVIDER_ROUND_UP for periph clks Perform upwards rounding when calculating dividers for periph clks on Tegra30 and Tegra114. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 53 ++++++++++++++++++++++------------------ drivers/clk/tegra/clk-tegra30.c | 19 +++++++------- 2 files changed, 39 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 76611289b8e6..e3904923005b 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -791,50 +791,53 @@ static unsigned long tegra114_input_freq[] = { #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id, \ - _parents##_idx, 0) + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ + _regs, _clk_num, periph_clk_enb_refcnt, _gate_flags,\ + _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id, \ - _parents##_idx, flags) + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ + _regs, _clk_num, periph_clk_enb_refcnt, _gate_flags,\ + _clk_id, _parents##_idx, flags) #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 29, MASK(3), 0, 0, 8, 1, 0, _regs, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id, \ - _parents##_idx, 0) + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ + _regs, _clk_num, periph_clk_enb_refcnt, _gate_flags,\ + _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id, _parents##_idx, flags) + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + periph_clk_enb_refcnt, _gate_flags, _clk_id, \ + _parents##_idx, flags) #define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id, _parents##_idx, 0) + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + periph_clk_enb_refcnt, _gate_flags, _clk_id, \ + _parents##_idx, 0) #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,\ - _clk_num, periph_clk_enb_refcnt, 0, _clk_id, \ - _parents##_idx, 0) + 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - 30, MASK(2), 0, 0, 16, 0, 0, _regs, _clk_num, \ - periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0) + 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ + _regs, _clk_num, periph_clk_enb_refcnt, 0, _clk_id,\ + _parents##_idx, 0) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_mask, _clk_num, _regs, \ @@ -847,14 +850,16 @@ static unsigned long tegra114_input_freq[] = { #define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \ - 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id, _parents##_idx, 0) + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + periph_clk_enb_refcnt, _gate_flags, _clk_id, \ + _parents##_idx, 0) #define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset, _clk_num,\ _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \ - _offset, 16, 0xE01F, 0, 0, 8, 1, 0, _regs, _clk_num, \ + _offset, 16, 0xE01F, 0, 0, 8, 1, \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ periph_clk_enb_refcnt, _gate_flags , _clk_id, \ mux_d_audio_clk_idx, 0) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index dbe7c8003c5c..147f5b9fed11 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -282,8 +282,8 @@ static DEFINE_SPINLOCK(sysrate_lock); #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 8, 1, 0, _regs, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id) + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, _regs, \ + _clk_num, periph_clk_enb_refcnt, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ @@ -295,21 +295,22 @@ static DEFINE_SPINLOCK(sysrate_lock); #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 29, 3, 0, 0, 8, 1, 0, _regs, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id) + 29, 3, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, _regs,\ + _clk_num, periph_clk_enb_refcnt, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id) + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + periph_clk_enb_refcnt, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _regs, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs, \ - _clk_num, periph_clk_enb_refcnt, 0, _clk_id) + 30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ + TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + periph_clk_enb_refcnt, 0, _clk_id) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_width, _clk_num, _regs, \ -- cgit v1.2.3 From 897e1dde1ec1571a28545594633624927fa0a76e Mon Sep 17 00:00:00 2001 From: Andrew Chew Date: Wed, 7 Aug 2013 19:25:09 +0800 Subject: clk: tegra: Set the clk parent of host1x to pll_p The power-on default parent for this clock is pll_m, which turns out to be wrong. Previously, bootloader reparented this clock. We'll do it in the kernel as well, so that there's one less thing that we depend on bootloader to initialize. Signed-off-by: Andrew Chew Signed-off-by: Mark Zhang --- drivers/clk/tegra/clk-tegra114.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index e3904923005b..9b8c938477de 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -2183,6 +2183,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, {TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, {TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0}, {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1}, {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1}, {TEGRA114_CLK_GR_2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, -- cgit v1.2.3 From 642fb0cf517173948684122403d73513c8c8b033 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 26 Sep 2013 18:30:01 +0300 Subject: clk: tegra: PLLE spread spectrum control Add spread spectrum control for PLLE in Tegra114. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-pll.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 197074a57754..c9d1e5c68dbc 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -77,7 +77,23 @@ #define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT) #define PLLE_SS_CTRL 0x68 -#define PLLE_SS_DISABLE (7 << 10) +#define PLLE_SS_CNTL_BYPASS_SS BIT(10) +#define PLLE_SS_CNTL_INTERP_RESET BIT(11) +#define PLLE_SS_CNTL_SSC_BYP BIT(12) +#define PLLE_SS_CNTL_CENTER BIT(14) +#define PLLE_SS_CNTL_INVERT BIT(15) +#define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\ + PLLE_SS_CNTL_SSC_BYP) +#define PLLE_SS_MAX_MASK 0x1ff +#define PLLE_SS_MAX_VAL 0x25 +#define PLLE_SS_INC_MASK (0xff << 16) +#define PLLE_SS_INC_VAL (0x1 << 16) +#define PLLE_SS_INCINTRV_MASK (0x3f << 24) +#define PLLE_SS_INCINTRV_VAL (0x20 << 24) +#define PLLE_SS_COEFFICIENTS_MASK \ + (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK) +#define PLLE_SS_COEFFICIENTS_VAL \ + (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL) #define PLLE_AUX_PLLP_SEL BIT(2) #define PLLE_AUX_ENABLE_SWCTL BIT(4) @@ -1217,6 +1233,18 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) if (ret < 0) goto out; + val = pll_readl(PLLE_SS_CTRL, pll); + val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); + val &= ~PLLE_SS_COEFFICIENTS_MASK; + val |= PLLE_SS_COEFFICIENTS_VAL; + pll_writel(val, PLLE_SS_CTRL, pll); + val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); + pll_writel(val, PLLE_SS_CTRL, pll); + udelay(1); + val &= ~PLLE_SS_CNTL_INTERP_RESET; + pll_writel(val, PLLE_SS_CTRL, pll); + udelay(1); + /* TODO: enable hw control of xusb brick pll */ out: -- cgit v1.2.3 From f67a8d21e63876a79f9f94b734049e789d594c7b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 2 Oct 2013 23:12:40 +0200 Subject: clk: tegra114: Rename gr_2d/gr_3d to gr2d/gr3d These clocks were named gr2d and gr3d on Tegra20 and Tegra30, so use the same names on Tegra114 for consistency. Signed-off-by: Thierry Reding Acked-by: Stephen Warren --- drivers/clk/tegra/clk-tegra114.c | 8 ++++---- include/dt-bindings/clock/tegra114-car.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 9b8c938477de..2471742d68de 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1846,8 +1846,8 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, TEGRA114_CLK_UARTB), TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, TEGRA114_CLK_UARTC), TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, TEGRA114_CLK_UARTD), - TEGRA_INIT_DATA_INT8("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, TEGRA114_CLK_GR_3D), - TEGRA_INIT_DATA_INT8("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, TEGRA114_CLK_GR_2D), + TEGRA_INIT_DATA_INT8("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, TEGRA114_CLK_GR3D), + TEGRA_INIT_DATA_INT8("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, TEGRA114_CLK_GR2D), TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, TEGRA114_CLK_VI), TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, TEGRA114_CLK_EPP), @@ -2186,8 +2186,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0}, {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1}, {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1}, - {TEGRA114_CLK_GR_2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, - {TEGRA114_CLK_GR_3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, + {TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, + {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, /* This MUST be the last entry. */ {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0}, diff --git a/include/dt-bindings/clock/tegra114-car.h b/include/dt-bindings/clock/tegra114-car.h index 5d4b90a2c023..6d0d8d8ef31e 100644 --- a/include/dt-bindings/clock/tegra114-car.h +++ b/include/dt-bindings/clock/tegra114-car.h @@ -37,10 +37,10 @@ #define TEGRA114_CLK_I2S2 18 #define TEGRA114_CLK_EPP 19 /* 20 (register bit affects vi and vi_sensor) */ -#define TEGRA114_CLK_GR_2D 21 +#define TEGRA114_CLK_GR2D 21 #define TEGRA114_CLK_USBD 22 #define TEGRA114_CLK_ISP 23 -#define TEGRA114_CLK_GR_3D 24 +#define TEGRA114_CLK_GR3D 24 /* 25 */ #define TEGRA114_CLK_DISP2 26 #define TEGRA114_CLK_DISP1 27 -- cgit v1.2.3 From 00c674e42c278e7af7b39b6c72dbbaa5e7ebd96c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 18 Nov 2013 16:11:35 +0100 Subject: clk: tegra: Fix clock rate computation The PLL output frequency is multiplied during the P-divider computation, so it needs to be divided by the P-divider again before returning. This fixes an issue where clk_round_rate() would return the multiplied frequency instead of the real one after the P-divider. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index c9d1e5c68dbc..25734348242f 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -411,6 +411,8 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, return -EINVAL; } + cfg->output_rate >>= p_div; + if (pll->params->pdiv_tohw) { ret = _p_div_to_hw(hw, 1 << p_div); if (ret < 0) -- cgit v1.2.3 From d5ff89a82a6d272d210db68a9487877682c94a24 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Thu, 22 Aug 2013 18:44:06 +0300 Subject: clk: tegra: simplify periph clock data This patch determines the register bank for clock enable/disable and reset based on the clock ID instead of hardcoding it in the tables describing the clocks. This results in less data to be maintained in the tables, making the code easier to understand. The full benefit of the change will be realized once also other clocktypes will be table based. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-periph-gate.c | 8 +- drivers/clk/tegra/clk-periph.c | 6 + drivers/clk/tegra/clk-tegra114.c | 376 ++++++++++++++---------------------- drivers/clk/tegra/clk-tegra20.c | 220 ++++++++------------- drivers/clk/tegra/clk-tegra30.c | 317 +++++++++++------------------- drivers/clk/tegra/clk.c | 104 ++++++++++ drivers/clk/tegra/clk.h | 17 +- 7 files changed, 464 insertions(+), 584 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index bafee9895a24..f38f33e3c65d 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -151,12 +151,16 @@ const struct clk_ops tegra_clk_periph_gate_ops = { struct clk *tegra_clk_register_periph_gate(const char *name, const char *parent_name, u8 gate_flags, void __iomem *clk_base, - unsigned long flags, int clk_num, - struct tegra_clk_periph_regs *pregs, int *enable_refcnt) + unsigned long flags, int clk_num, int *enable_refcnt) { struct tegra_clk_periph_gate *gate; struct clk *clk; struct clk_init_data init; + struct tegra_clk_periph_regs *pregs; + + pregs = get_reg_bank(clk_num); + if (!pregs) + return ERR_PTR(-EINVAL); gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) { diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index b2309d37a963..735b0243261c 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -178,6 +178,7 @@ static struct clk *_tegra_clk_register_periph(const char *name, { struct clk *clk; struct clk_init_data init; + struct tegra_clk_periph_regs *bank; init.name = name; init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; @@ -185,12 +186,17 @@ static struct clk *_tegra_clk_register_periph(const char *name, init.parent_names = parent_names; init.num_parents = num_parents; + bank = get_reg_bank(periph->gate.clk_num); + if (!bank) + return ERR_PTR(-EINVAL); + /* Data in .init is copied by clk_register(), so stack variable OK */ periph->hw.init = &init; periph->magic = TEGRA_CLK_PERIPH_MAGIC; periph->mux.reg = clk_base + offset; periph->divider.reg = div ? (clk_base + offset) : NULL; periph->gate.clk_base = clk_base; + periph->gate.regs = bank; clk = clk_register(NULL, &periph->hw); if (IS_ERR(clk)) diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 2471742d68de..8507067d5dd6 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -27,27 +27,10 @@ #include "clk.h" -#define RST_DEVICES_L 0x004 -#define RST_DEVICES_H 0x008 -#define RST_DEVICES_U 0x00C #define RST_DFLL_DVCO 0x2F4 -#define RST_DEVICES_V 0x358 -#define RST_DEVICES_W 0x35C -#define RST_DEVICES_X 0x28C -#define RST_DEVICES_SET_L 0x300 -#define RST_DEVICES_CLR_L 0x304 -#define RST_DEVICES_SET_H 0x308 -#define RST_DEVICES_CLR_H 0x30c -#define RST_DEVICES_SET_U 0x310 -#define RST_DEVICES_CLR_U 0x314 -#define RST_DEVICES_SET_V 0x430 -#define RST_DEVICES_CLR_V 0x434 -#define RST_DEVICES_SET_W 0x438 -#define RST_DEVICES_CLR_W 0x43c #define CPU_FINETRIM_SELECT 0x4d4 /* override default prop dlys */ #define CPU_FINETRIM_DR 0x4d8 /* rise->rise prop dly A */ #define CPU_FINETRIM_R 0x4e4 /* rise->rise prop dly inc A */ -#define RST_DEVICES_NUM 5 /* RST_DFLL_DVCO bitfields */ #define DVFS_DFLL_RESET_SHIFT 0 @@ -74,26 +57,10 @@ #define CPU_FINETRIM_R_FCPU_6_SHIFT 10 /* ftop */ #define CPU_FINETRIM_R_FCPU_6_MASK (0x3 << CPU_FINETRIM_R_FCPU_6_SHIFT) -#define CLK_OUT_ENB_L 0x010 -#define CLK_OUT_ENB_H 0x014 -#define CLK_OUT_ENB_U 0x018 -#define CLK_OUT_ENB_V 0x360 -#define CLK_OUT_ENB_W 0x364 -#define CLK_OUT_ENB_X 0x280 -#define CLK_OUT_ENB_SET_L 0x320 -#define CLK_OUT_ENB_CLR_L 0x324 -#define CLK_OUT_ENB_SET_H 0x328 -#define CLK_OUT_ENB_CLR_H 0x32c -#define CLK_OUT_ENB_SET_U 0x330 -#define CLK_OUT_ENB_CLR_U 0x334 -#define CLK_OUT_ENB_SET_V 0x440 -#define CLK_OUT_ENB_CLR_V 0x444 -#define CLK_OUT_ENB_SET_W 0x448 -#define CLK_OUT_ENB_CLR_W 0x44c -#define CLK_OUT_ENB_SET_X 0x284 -#define CLK_OUT_ENB_CLR_X 0x288 #define CLK_OUT_ENB_NUM 6 +#define TEGRA114_CLK_PERIPH_BANKS 5 + #define PLLC_BASE 0x80 #define PLLC_MISC2 0x88 #define PLLC_MISC 0x8c @@ -728,53 +695,6 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .div_nmp = &pllre_nmp, }; -/* Peripheral clock registers */ - -static struct tegra_clk_periph_regs periph_l_regs = { - .enb_reg = CLK_OUT_ENB_L, - .enb_set_reg = CLK_OUT_ENB_SET_L, - .enb_clr_reg = CLK_OUT_ENB_CLR_L, - .rst_reg = RST_DEVICES_L, - .rst_set_reg = RST_DEVICES_SET_L, - .rst_clr_reg = RST_DEVICES_CLR_L, -}; - -static struct tegra_clk_periph_regs periph_h_regs = { - .enb_reg = CLK_OUT_ENB_H, - .enb_set_reg = CLK_OUT_ENB_SET_H, - .enb_clr_reg = CLK_OUT_ENB_CLR_H, - .rst_reg = RST_DEVICES_H, - .rst_set_reg = RST_DEVICES_SET_H, - .rst_clr_reg = RST_DEVICES_CLR_H, -}; - -static struct tegra_clk_periph_regs periph_u_regs = { - .enb_reg = CLK_OUT_ENB_U, - .enb_set_reg = CLK_OUT_ENB_SET_U, - .enb_clr_reg = CLK_OUT_ENB_CLR_U, - .rst_reg = RST_DEVICES_U, - .rst_set_reg = RST_DEVICES_SET_U, - .rst_clr_reg = RST_DEVICES_CLR_U, -}; - -static struct tegra_clk_periph_regs periph_v_regs = { - .enb_reg = CLK_OUT_ENB_V, - .enb_set_reg = CLK_OUT_ENB_SET_V, - .enb_clr_reg = CLK_OUT_ENB_CLR_V, - .rst_reg = RST_DEVICES_V, - .rst_set_reg = RST_DEVICES_SET_V, - .rst_clr_reg = RST_DEVICES_CLR_V, -}; - -static struct tegra_clk_periph_regs periph_w_regs = { - .enb_reg = CLK_OUT_ENB_W, - .enb_set_reg = CLK_OUT_ENB_SET_W, - .enb_clr_reg = CLK_OUT_ENB_CLR_W, - .rst_reg = RST_DEVICES_W, - .rst_set_reg = RST_DEVICES_SET_W, - .rst_clr_reg = RST_DEVICES_CLR_W, -}; - /* possible OSC frequencies in Hz */ static unsigned long tegra114_input_freq[] = { [0] = 13000000, @@ -789,77 +709,77 @@ static unsigned long tegra114_input_freq[] = { #define MASK(x) (BIT(x) - 1) #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _regs, _clk_num, periph_clk_enb_refcnt, _gate_flags,\ + _clk_num, periph_clk_enb_refcnt, _gate_flags,\ _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _regs, _gate_flags, _clk_id, flags)\ + _clk_num, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _regs, _clk_num, periph_clk_enb_refcnt, _gate_flags,\ + _clk_num, periph_clk_enb_refcnt, _gate_flags,\ _clk_id, _parents##_idx, flags) #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _regs, _clk_num, periph_clk_enb_refcnt, _gate_flags,\ + _clk_num, periph_clk_enb_refcnt, _gate_flags,\ _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _regs, _gate_flags, _clk_id, flags)\ + _clk_num, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, _gate_flags, _clk_id, \ _parents##_idx, flags) #define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, _gate_flags, _clk_id, \ _parents##_idx, 0) #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _regs, _clk_id) \ + _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _regs, _clk_id) \ + _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ - _regs, _clk_num, periph_clk_enb_refcnt, 0, _clk_id,\ + _clk_num, periph_clk_enb_refcnt, 0, _clk_id,\ _parents##_idx, 0) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ - _mux_shift, _mux_mask, _clk_num, _regs, \ + _mux_shift, _mux_mask, _clk_num, \ _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ - _mux_shift, _mux_mask, 0, 0, 0, 0, 0, _regs, \ + _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, _gate_flags, _clk_id, \ _parents##_idx, 0) #define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset, _clk_num,\ - _regs, _gate_flags, _clk_id) \ + _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \ _offset, 16, 0xE01F, 0, 0, 8, 1, \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, _gate_flags , _clk_id, \ mux_d_audio_clk_idx, 0) @@ -1612,7 +1532,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) 0, &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 113, &periph_v_regs, + CLK_SET_RATE_PARENT, 113, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio0_2x", NULL); clks[TEGRA114_CLK_AUDIO0_2X] = clk; @@ -1625,7 +1545,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) 0, &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 114, &periph_v_regs, + CLK_SET_RATE_PARENT, 114, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio1_2x", NULL); clks[TEGRA114_CLK_AUDIO1_2X] = clk; @@ -1638,7 +1558,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) 0, &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 115, &periph_v_regs, + CLK_SET_RATE_PARENT, 115, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio2_2x", NULL); clks[TEGRA114_CLK_AUDIO2_2X] = clk; @@ -1651,7 +1571,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) 0, &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 116, &periph_v_regs, + CLK_SET_RATE_PARENT, 116, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio3_2x", NULL); clks[TEGRA114_CLK_AUDIO3_2X] = clk; @@ -1664,7 +1584,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) 0, &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 117, &periph_v_regs, + CLK_SET_RATE_PARENT, 117, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio4_2x", NULL); clks[TEGRA114_CLK_AUDIO4_2X] = clk; @@ -1678,7 +1598,7 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div", TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 118, - &periph_v_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "spdif_2x", NULL); clks[TEGRA114_CLK_SPDIF_2X] = clk; } @@ -1805,86 +1725,86 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) } static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S0), - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S2), - TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S3), - TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S4), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_OUT), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_IN), - TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_PWM), - TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_ADX), - TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), - TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), - TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), - TEGRA_INIT_DATA_MUX8("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), - TEGRA_INIT_DATA_MUX8("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), - TEGRA_INIT_DATA_MUX8("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), - TEGRA_INIT_DATA_MUX8("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), - TEGRA_INIT_DATA_MUX8("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), - TEGRA_INIT_DATA_MUX8("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), - TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), - TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, TEGRA114_CLK_SDMMC1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, TEGRA114_CLK_SDMMC2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, TEGRA114_CLK_SDMMC3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, TEGRA114_CLK_SDMMC4), - TEGRA_INIT_DATA_INT8("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, TEGRA114_CLK_VDE), - TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), - TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_OWR), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, TEGRA114_CLK_NOR), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_MIPI), - TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA114_CLK_I2C1), - TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA114_CLK_I2C2), - TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA114_CLK_I2C3), - TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, TEGRA114_CLK_I2C4), - TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, TEGRA114_CLK_I2C5), - TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, TEGRA114_CLK_UARTA), - TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, TEGRA114_CLK_UARTB), - TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, TEGRA114_CLK_UARTC), - TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, TEGRA114_CLK_UARTD), - TEGRA_INIT_DATA_INT8("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, TEGRA114_CLK_GR3D), - TEGRA_INIT_DATA_INT8("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, TEGRA114_CLK_GR2D), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), - TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, TEGRA114_CLK_VI), - TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, TEGRA114_CLK_EPP), - TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_u_regs, TEGRA_PERIPH_WAR_1005168, TEGRA114_CLK_MSENC), - TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, TEGRA114_CLK_TSEC), - TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, TEGRA114_CLK_HOST1X), - TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, TEGRA114_CLK_HDMI), - TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, TEGRA114_CLK_CILAB), - TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, TEGRA114_CLK_CILCD), - TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, TEGRA114_CLK_CILE), - TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, TEGRA114_CLK_DSIALP), - TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, TEGRA114_CLK_DSIBLP), - TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TSENSOR), - TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, TEGRA114_CLK_ACTMON), - TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, TEGRA114_CLK_EXTERN1), - TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, TEGRA114_CLK_EXTERN2), - TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, TEGRA114_CLK_EXTERN3), - TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2CSLOW), - TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SE), - TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, TEGRA114_CLK_MSELECT, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_REF), - TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_SOC), - TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SOC_THERM), - TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_HOST_SRC), - TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FALCON_SRC), - TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FS_SRC), - TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_SS_SRC), - TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_DEV_SRC), - TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_D_AUDIO), - TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM0), - TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM1), - TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM2), + TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S0), + TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S1), + TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S2), + TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S3), + TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S4), + TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_OUT), + TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_IN), + TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_PWM), + TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_ADX), + TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), + TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), + TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), + TEGRA_INIT_DATA_MUX8("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), + TEGRA_INIT_DATA_MUX8("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), + TEGRA_INIT_DATA_MUX8("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), + TEGRA_INIT_DATA_MUX8("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), + TEGRA_INIT_DATA_MUX8("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), + TEGRA_INIT_DATA_MUX8("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), + TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), + TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), + TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), + TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, TEGRA114_CLK_SDMMC1), + TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, TEGRA114_CLK_SDMMC2), + TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, TEGRA114_CLK_SDMMC3), + TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, TEGRA114_CLK_SDMMC4), + TEGRA_INIT_DATA_INT8("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, TEGRA114_CLK_VDE), + TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), + TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), + TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), + TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_OWR), + TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, TEGRA114_CLK_NOR), + TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_MIPI), + TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, TEGRA114_CLK_I2C1), + TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, TEGRA114_CLK_I2C2), + TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, TEGRA114_CLK_I2C3), + TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, TEGRA114_CLK_I2C4), + TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, TEGRA114_CLK_I2C5), + TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, TEGRA114_CLK_UARTA), + TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, TEGRA114_CLK_UARTB), + TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, TEGRA114_CLK_UARTC), + TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, TEGRA114_CLK_UARTD), + TEGRA_INIT_DATA_INT8("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, TEGRA114_CLK_GR3D), + TEGRA_INIT_DATA_INT8("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, TEGRA114_CLK_GR2D), + TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), + TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, TEGRA114_CLK_VI), + TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, TEGRA114_CLK_EPP), + TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, TEGRA114_CLK_MSENC), + TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, TEGRA114_CLK_TSEC), + TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, TEGRA114_CLK_HOST1X), + TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA114_CLK_HDMI), + TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, TEGRA114_CLK_CILAB), + TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, TEGRA114_CLK_CILCD), + TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, TEGRA114_CLK_CILE), + TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, TEGRA114_CLK_DSIALP), + TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, TEGRA114_CLK_DSIBLP), + TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TSENSOR), + TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, TEGRA114_CLK_ACTMON), + TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, TEGRA114_CLK_EXTERN1), + TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, TEGRA114_CLK_EXTERN2), + TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, TEGRA114_CLK_EXTERN3), + TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2CSLOW), + TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SE), + TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, TEGRA114_CLK_MSELECT, CLK_IGNORE_UNUSED), + TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_REF), + TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_SOC), + TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SOC_THERM), + TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_HOST_SRC), + TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FALCON_SRC), + TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FS_SRC), + TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_SS_SRC), + TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_DEV_SRC), + TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_D_AUDIO), + TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM0), + TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM1), + TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM2), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, &periph_l_regs, 0, TEGRA114_CLK_DISP1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, &periph_l_regs, 0, TEGRA114_CLK_DISP2), + TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, TEGRA114_CLK_DISP1), + TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, TEGRA114_CLK_DISP2), }; static __init void tegra114_periph_clk_init(void __iomem *clk_base) @@ -1896,16 +1816,14 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) /* apbdma */ clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, - 0, 34, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 34, periph_clk_enb_refcnt); clks[TEGRA114_CLK_APBDMA] = clk; /* rtc */ clk = tegra_clk_register_periph_gate("rtc", "clk_32k", TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, clk_base, - 0, 4, &periph_l_regs, - periph_clk_enb_refcnt); + 0, 4, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "rtc-tegra"); clks[TEGRA114_CLK_RTC] = clk; @@ -1913,123 +1831,112 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk = tegra_clk_register_periph_gate("kbc", "clk_32k", TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, clk_base, - 0, 36, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 36, periph_clk_enb_refcnt); clks[TEGRA114_CLK_KBC] = clk; /* timer */ clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, - 0, 5, &periph_l_regs, - periph_clk_enb_refcnt); + 0, 5, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "timer"); clks[TEGRA114_CLK_TIMER] = clk; /* kfuse */ clk = tegra_clk_register_periph_gate("kfuse", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 40, - &periph_h_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_KFUSE] = clk; /* fuse */ clk = tegra_clk_register_periph_gate("fuse", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 39, - &periph_h_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_FUSE] = clk; /* fuse_burn */ clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 39, - &periph_h_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_FUSE_BURN] = clk; /* apbif */ clk = tegra_clk_register_periph_gate("apbif", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 107, - &periph_v_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_APBIF] = clk; /* hda2hdmi */ clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 128, - &periph_w_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_HDA2HDMI] = clk; /* vcp */ clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, - 29, &periph_l_regs, - periph_clk_enb_refcnt); + 29, periph_clk_enb_refcnt); clks[TEGRA114_CLK_VCP] = clk; /* bsea */ clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, - 0, 62, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 62, periph_clk_enb_refcnt); clks[TEGRA114_CLK_BSEA] = clk; /* bsev */ clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, - 0, 63, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 63, periph_clk_enb_refcnt); clks[TEGRA114_CLK_BSEV] = clk; /* mipi-cal */ clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base, - 0, 56, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 56, periph_clk_enb_refcnt); clks[TEGRA114_CLK_MIPI_CAL] = clk; /* usbd */ clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, - 0, 22, &periph_l_regs, - periph_clk_enb_refcnt); + 0, 22, periph_clk_enb_refcnt); clks[TEGRA114_CLK_USBD] = clk; /* usb2 */ clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, - 0, 58, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 58, periph_clk_enb_refcnt); clks[TEGRA114_CLK_USB2] = clk; /* usb3 */ clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, - 0, 59, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 59, periph_clk_enb_refcnt); clks[TEGRA114_CLK_USB3] = clk; /* csi */ clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, - 0, 52, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 52, periph_clk_enb_refcnt); clks[TEGRA114_CLK_CSI] = clk; /* isp */ clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, - 23, &periph_l_regs, - periph_clk_enb_refcnt); + 23, periph_clk_enb_refcnt); clks[TEGRA114_CLK_ISP] = clk; /* csus */ clk = tegra_clk_register_periph_gate("csus", "clk_m", TEGRA_PERIPH_NO_RESET, clk_base, 0, 92, - &periph_u_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_CSUS] = clk; /* dds */ clk = tegra_clk_register_periph_gate("dds", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 150, - &periph_w_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_DDS] = clk; /* dp2 */ clk = tegra_clk_register_periph_gate("dp2", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 152, - &periph_w_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_DP2] = clk; /* dtv */ clk = tegra_clk_register_periph_gate("dtv", "clk_m", TEGRA_PERIPH_ON_APB, clk_base, 0, 79, - &periph_u_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clks[TEGRA114_CLK_DTV] = clk; /* dsia */ @@ -2039,8 +1946,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock); clks[TEGRA114_CLK_DSIA_MUX] = clk; clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base, - 0, 48, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 48, periph_clk_enb_refcnt); clks[TEGRA114_CLK_DSIA] = clk; /* dsib */ @@ -2050,8 +1956,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock); clks[TEGRA114_CLK_DSIB_MUX] = clk; clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base, - 0, 82, &periph_u_regs, - periph_clk_enb_refcnt); + 0, 82, periph_clk_enb_refcnt); clks[TEGRA114_CLK_DSIB] = clk; /* xusb_hs_src */ @@ -2065,20 +1970,17 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) /* xusb_host */ clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0, - clk_base, 0, 89, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 89, periph_clk_enb_refcnt); clks[TEGRA114_CLK_XUSB_HOST] = clk; /* xusb_ss */ clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0, - clk_base, 0, 156, &periph_w_regs, - periph_clk_enb_refcnt); + clk_base, 0, 156, periph_clk_enb_refcnt); clks[TEGRA114_CLK_XUSB_HOST] = clk; /* xusb_dev */ clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0, - clk_base, 0, 95, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 95, periph_clk_enb_refcnt); clks[TEGRA114_CLK_XUSB_DEV] = clk; /* emc */ @@ -2088,20 +1990,21 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) clk_base + CLK_SOURCE_EMC, 29, 3, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, - CLK_IGNORE_UNUSED, 57, &periph_h_regs, - periph_clk_enb_refcnt); + CLK_IGNORE_UNUSED, 57, periph_clk_enb_refcnt); clks[TEGRA114_CLK_EMC] = clk; for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->parent_names, - data->num_parents, &data->periph, - clk_base, data->offset, data->flags); + + clk = tegra_clk_register_periph(data->name, + data->parent_names, data->num_parents, &data->periph, + clk_base, data->offset, data->flags); clks[data->clk_id] = clk; } for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { data = &tegra_periph_nodiv_clk_list[i]; + clk = tegra_clk_register_periph_nodiv(data->name, data->parent_names, data->num_parents, &data->periph, clk_base, data->offset); @@ -2351,6 +2254,9 @@ static void __init tegra114_clock_init(struct device_node *np) if (tegra114_osc_clk_init(clk_base) < 0) return; + if (tegra_clk_set_periph_banks(TEGRA114_CLK_PERIPH_BANKS) < 0) + return; + tegra114_fixed_clk_init(clk_base); tegra114_pll_init(clk_base, pmc_base); tegra114_periph_clk_init(clk_base); diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 056f649d0d89..929a46278d83 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -25,26 +25,6 @@ #include "clk.h" -#define RST_DEVICES_L 0x004 -#define RST_DEVICES_H 0x008 -#define RST_DEVICES_U 0x00c -#define RST_DEVICES_SET_L 0x300 -#define RST_DEVICES_CLR_L 0x304 -#define RST_DEVICES_SET_H 0x308 -#define RST_DEVICES_CLR_H 0x30c -#define RST_DEVICES_SET_U 0x310 -#define RST_DEVICES_CLR_U 0x314 -#define RST_DEVICES_NUM 3 - -#define CLK_OUT_ENB_L 0x010 -#define CLK_OUT_ENB_H 0x014 -#define CLK_OUT_ENB_U 0x018 -#define CLK_OUT_ENB_SET_L 0x320 -#define CLK_OUT_ENB_CLR_L 0x324 -#define CLK_OUT_ENB_SET_H 0x328 -#define CLK_OUT_ENB_CLR_H 0x32c -#define CLK_OUT_ENB_SET_U 0x330 -#define CLK_OUT_ENB_CLR_U 0x334 #define CLK_OUT_ENB_NUM 3 #define OSC_CTRL 0x50 @@ -67,6 +47,8 @@ #define OSC_FREQ_DET_BUSY (1<<31) #define OSC_FREQ_DET_CNT_MASK 0xFFFF +#define TEGRA20_CLK_PERIPH_BANKS 3 + #define PLLS_BASE 0xf0 #define PLLS_MISC 0xf4 #define PLLC_BASE 0x80 @@ -197,31 +179,31 @@ static DEFINE_SPINLOCK(pll_div_lock); static DEFINE_SPINLOCK(sysrate_lock); #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _regs, _clk_num, periph_clk_enb_refcnt, \ + _clk_num, periph_clk_enb_refcnt, \ _gate_flags, _clk_id) #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ _clk_id) #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, _regs, \ + 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ _clk_id) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ - _mux_shift, _mux_width, _clk_num, _regs, \ + _mux_shift, _mux_width, _clk_num, \ _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs, \ + _mux_shift, _mux_width, 0, 0, 0, 0, 0, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ _clk_id) @@ -490,34 +472,6 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_delay = 0, }; -/* Peripheral clock registers */ -static struct tegra_clk_periph_regs periph_l_regs = { - .enb_reg = CLK_OUT_ENB_L, - .enb_set_reg = CLK_OUT_ENB_SET_L, - .enb_clr_reg = CLK_OUT_ENB_CLR_L, - .rst_reg = RST_DEVICES_L, - .rst_set_reg = RST_DEVICES_SET_L, - .rst_clr_reg = RST_DEVICES_CLR_L, -}; - -static struct tegra_clk_periph_regs periph_h_regs = { - .enb_reg = CLK_OUT_ENB_H, - .enb_set_reg = CLK_OUT_ENB_SET_H, - .enb_clr_reg = CLK_OUT_ENB_CLR_H, - .rst_reg = RST_DEVICES_H, - .rst_set_reg = RST_DEVICES_SET_H, - .rst_clr_reg = RST_DEVICES_CLR_H, -}; - -static struct tegra_clk_periph_regs periph_u_regs = { - .enb_reg = CLK_OUT_ENB_U, - .enb_set_reg = CLK_OUT_ENB_SET_U, - .enb_clr_reg = CLK_OUT_ENB_CLR_U, - .rst_reg = RST_DEVICES_U, - .rst_set_reg = RST_DEVICES_SET_U, - .rst_clr_reg = RST_DEVICES_CLR_U, -}; - static unsigned long tegra20_clk_measure_input_freq(void) { u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); @@ -792,7 +746,7 @@ static void __init tegra20_audio_clk_init(void) CLK_SET_RATE_PARENT, 2, 1); clk = tegra_clk_register_periph_gate("audio_2x", "audio_doubler", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 89, &periph_u_regs, + CLK_SET_RATE_PARENT, 89, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio_2x", NULL); clks[audio_2x] = clk; @@ -815,56 +769,56 @@ static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c", static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"}; static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra20-i2s.0", i2s1_parents, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra20-i2s.1", i2s2_parents, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra20-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), - TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), - TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), - TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), - TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), - TEGRA_INIT_DATA_MUX("spi", NULL, "spi", mux_pllpcm_clkm, CLK_SOURCE_SPI, 43, &periph_h_regs, TEGRA_PERIPH_ON_APB, spi), - TEGRA_INIT_DATA_MUX("xio", NULL, "xio", mux_pllpcm_clkm, CLK_SOURCE_XIO, 45, &periph_h_regs, 0, xio), - TEGRA_INIT_DATA_MUX("twc", NULL, "twc", mux_pllpcm_clkm, CLK_SOURCE_TWC, 16, &periph_l_regs, TEGRA_PERIPH_ON_APB, twc), - TEGRA_INIT_DATA_MUX("ide", NULL, "ide", mux_pllpcm_clkm, CLK_SOURCE_XIO, 25, &periph_l_regs, 0, ide), - TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_l_regs, 0, ndflash), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), - TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, 0, csite), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, 0, la), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), - TEGRA_INIT_DATA_MUX("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), - TEGRA_INIT_DATA_MUX("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), - TEGRA_INIT_DATA_MUX("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), - TEGRA_INIT_DATA_MUX("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, &periph_h_regs, 0, mpe), - TEGRA_INIT_DATA_MUX("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), - TEGRA_INIT_DATA_MUX("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d), - TEGRA_INIT_DATA_MUX("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr2d), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), - TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, &periph_h_regs, 0, cve), - TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, &periph_h_regs, 0, tvo), - TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, &periph_h_regs, 0, tvdac), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), - TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllpcm_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1), - TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllpcm_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2), - TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3), - TEGRA_INIT_DATA_DIV16("dvc", "div-clk", "tegra-i2c.3", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, &periph_h_regs, TEGRA_PERIPH_ON_APB, dvc), - TEGRA_INIT_DATA_MUX("hdmi", NULL, "hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), - TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm), + TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra20-i2s.0", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, i2s1), + TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra20-i2s.1", i2s2_parents, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, i2s2), + TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, spdif_out), + TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra20-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, spdif_in), + TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, sbc1), + TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, sbc2), + TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, sbc3), + TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, sbc4), + TEGRA_INIT_DATA_MUX("spi", NULL, "spi", mux_pllpcm_clkm, CLK_SOURCE_SPI, 43, TEGRA_PERIPH_ON_APB, spi), + TEGRA_INIT_DATA_MUX("xio", NULL, "xio", mux_pllpcm_clkm, CLK_SOURCE_XIO, 45, 0, xio), + TEGRA_INIT_DATA_MUX("twc", NULL, "twc", mux_pllpcm_clkm, CLK_SOURCE_TWC, 16, TEGRA_PERIPH_ON_APB, twc), + TEGRA_INIT_DATA_MUX("ide", NULL, "ide", mux_pllpcm_clkm, CLK_SOURCE_XIO, 25, 0, ide), + TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, 0, ndflash), + TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, vfir), + TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, 0, csite), + TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, 0, la), + TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, owr), + TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, mipi), + TEGRA_INIT_DATA_MUX("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, 0, vde), + TEGRA_INIT_DATA_MUX("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, 0, vi), + TEGRA_INIT_DATA_MUX("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, 0, epp), + TEGRA_INIT_DATA_MUX("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, 0, mpe), + TEGRA_INIT_DATA_MUX("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, 0, host1x), + TEGRA_INIT_DATA_MUX("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, TEGRA_PERIPH_MANUAL_RESET, gr3d), + TEGRA_INIT_DATA_MUX("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, 0, gr2d), + TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, 0, nor), + TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, 0, sdmmc1), + TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, 0, sdmmc2), + TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, 0, sdmmc3), + TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, 0, sdmmc4), + TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, 0, cve), + TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, 0, tvo), + TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, 0, tvdac), + TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, vi_sensor), + TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllpcm_clkm, CLK_SOURCE_I2C1, 12, TEGRA_PERIPH_ON_APB, i2c1), + TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllpcm_clkm, CLK_SOURCE_I2C2, 54, TEGRA_PERIPH_ON_APB, i2c2), + TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, TEGRA_PERIPH_ON_APB, i2c3), + TEGRA_INIT_DATA_DIV16("dvc", "div-clk", "tegra-i2c.3", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, TEGRA_PERIPH_ON_APB, dvc), + TEGRA_INIT_DATA_MUX("hdmi", NULL, "hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, 0, hdmi), + TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6, &periph_l_regs, TEGRA_PERIPH_ON_APB, uarta), - TEGRA_INIT_DATA_NODIV("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, uartb), - TEGRA_INIT_DATA_NODIV("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, &periph_h_regs, TEGRA_PERIPH_ON_APB, uartc), - TEGRA_INIT_DATA_NODIV("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, &periph_u_regs, TEGRA_PERIPH_ON_APB, uartd), - TEGRA_INIT_DATA_NODIV("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, &periph_u_regs, TEGRA_PERIPH_ON_APB, uarte), - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, &periph_l_regs, 0, disp1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, &periph_l_regs, 0, disp2), + TEGRA_INIT_DATA_NODIV("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6, TEGRA_PERIPH_ON_APB, uarta), + TEGRA_INIT_DATA_NODIV("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7, TEGRA_PERIPH_ON_APB, uartb), + TEGRA_INIT_DATA_NODIV("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, TEGRA_PERIPH_ON_APB, uartc), + TEGRA_INIT_DATA_NODIV("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, TEGRA_PERIPH_ON_APB, uartd), + TEGRA_INIT_DATA_NODIV("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, TEGRA_PERIPH_ON_APB, uarte), + TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, 0, disp1), + TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, 0, disp2), }; static void __init tegra20_periph_clk_init(void) @@ -876,67 +830,58 @@ static void __init tegra20_periph_clk_init(void) /* ac97 */ clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0", TEGRA_PERIPH_ON_APB, - clk_base, 0, 3, &periph_l_regs, - periph_clk_enb_refcnt); + clk_base, 0, 3, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra20-ac97"); clks[ac97] = clk; /* apbdma */ clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base, - 0, 34, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 34, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-apbdma"); clks[apbdma] = clk; /* rtc */ clk = tegra_clk_register_periph_gate("rtc", "clk_32k", TEGRA_PERIPH_NO_RESET, - clk_base, 0, 4, &periph_l_regs, - periph_clk_enb_refcnt); + clk_base, 0, 4, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "rtc-tegra"); clks[rtc] = clk; /* timer */ clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, - 0, 5, &periph_l_regs, - periph_clk_enb_refcnt); + 0, 5, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "timer"); clks[timer] = clk; /* kbc */ clk = tegra_clk_register_periph_gate("kbc", "clk_32k", TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 36, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 36, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-kbc"); clks[kbc] = clk; /* csus */ clk = tegra_clk_register_periph_gate("csus", "clk_m", TEGRA_PERIPH_NO_RESET, - clk_base, 0, 92, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 92, periph_clk_enb_refcnt); clk_register_clkdev(clk, "csus", "tengra_camera"); clks[csus] = clk; /* vcp */ clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, - clk_base, 0, 29, &periph_l_regs, - periph_clk_enb_refcnt); + clk_base, 0, 29, periph_clk_enb_refcnt); clk_register_clkdev(clk, "vcp", "tegra-avp"); clks[vcp] = clk; /* bsea */ clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, - clk_base, 0, 62, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 62, periph_clk_enb_refcnt); clk_register_clkdev(clk, "bsea", "tegra-avp"); clks[bsea] = clk; /* bsev */ clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, - clk_base, 0, 63, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 63, periph_clk_enb_refcnt); clk_register_clkdev(clk, "bsev", "tegra-aes"); clks[bsev] = clk; @@ -947,63 +892,61 @@ static void __init tegra20_periph_clk_init(void) clk_base + CLK_SOURCE_EMC, 30, 2, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, - 57, &periph_h_regs, periph_clk_enb_refcnt); + 57, periph_clk_enb_refcnt); clk_register_clkdev(clk, "emc", NULL); clks[emc] = clk; /* usbd */ clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, - 22, &periph_l_regs, periph_clk_enb_refcnt); + 22, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); clks[usbd] = clk; /* usb2 */ clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, - 58, &periph_h_regs, periph_clk_enb_refcnt); + 58, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-ehci.1"); clks[usb2] = clk; /* usb3 */ clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, - 59, &periph_h_regs, periph_clk_enb_refcnt); + 59, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-ehci.2"); clks[usb3] = clk; /* dsi */ clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0, - 48, &periph_h_regs, periph_clk_enb_refcnt); + 48, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "dsi"); clks[dsi] = clk; /* csi */ clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, - 0, 52, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 52, periph_clk_enb_refcnt); clk_register_clkdev(clk, "csi", "tegra_camera"); clks[csi] = clk; /* isp */ clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, - &periph_l_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "isp", "tegra_camera"); clks[isp] = clk; /* pex */ clk = tegra_clk_register_periph_gate("pex", "clk_m", 0, clk_base, 0, 70, - &periph_u_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "pex", NULL); clks[pex] = clk; /* afi */ clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, - &periph_u_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "afi", NULL); clks[afi] = clk; /* pcie_xclk */ clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base, - 0, 74, &periph_u_regs, - periph_clk_enb_refcnt); + 0, 74, periph_clk_enb_refcnt); clk_register_clkdev(clk, "pcie_xclk", NULL); clks[pcie_xclk] = clk; @@ -1011,8 +954,7 @@ static void __init tegra20_periph_clk_init(void) clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT, 26000000); clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0, - clk_base, 0, 94, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 94, periph_clk_enb_refcnt); clk_register_clkdev(clk, "cdev1", NULL); clks[cdev1] = clk; @@ -1020,8 +962,7 @@ static void __init tegra20_periph_clk_init(void) clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, CLK_IS_ROOT, 26000000); clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0, - clk_base, 0, 93, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 93, periph_clk_enb_refcnt); clk_register_clkdev(clk, "cdev2", NULL); clks[cdev2] = clk; @@ -1312,6 +1253,9 @@ static void __init tegra20_clock_init(struct device_node *np) BUG(); } + if (tegra_clk_set_periph_banks(TEGRA20_CLK_PERIPH_BANKS) < 0) + return; + tegra20_osc_clk_init(); tegra20_pmc_clk_init(); tegra20_fixed_clk_init(); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 147f5b9fed11..a66bdabb5c5c 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -26,38 +26,6 @@ #include "clk.h" -#define RST_DEVICES_L 0x004 -#define RST_DEVICES_H 0x008 -#define RST_DEVICES_U 0x00c -#define RST_DEVICES_V 0x358 -#define RST_DEVICES_W 0x35c -#define RST_DEVICES_SET_L 0x300 -#define RST_DEVICES_CLR_L 0x304 -#define RST_DEVICES_SET_H 0x308 -#define RST_DEVICES_CLR_H 0x30c -#define RST_DEVICES_SET_U 0x310 -#define RST_DEVICES_CLR_U 0x314 -#define RST_DEVICES_SET_V 0x430 -#define RST_DEVICES_CLR_V 0x434 -#define RST_DEVICES_SET_W 0x438 -#define RST_DEVICES_CLR_W 0x43c -#define RST_DEVICES_NUM 5 - -#define CLK_OUT_ENB_L 0x010 -#define CLK_OUT_ENB_H 0x014 -#define CLK_OUT_ENB_U 0x018 -#define CLK_OUT_ENB_V 0x360 -#define CLK_OUT_ENB_W 0x364 -#define CLK_OUT_ENB_SET_L 0x320 -#define CLK_OUT_ENB_CLR_L 0x324 -#define CLK_OUT_ENB_SET_H 0x328 -#define CLK_OUT_ENB_CLR_H 0x32c -#define CLK_OUT_ENB_SET_U 0x330 -#define CLK_OUT_ENB_CLR_U 0x334 -#define CLK_OUT_ENB_SET_V 0x440 -#define CLK_OUT_ENB_CLR_V 0x444 -#define CLK_OUT_ENB_SET_W 0x448 -#define CLK_OUT_ENB_CLR_W 0x44c #define CLK_OUT_ENB_NUM 5 #define OSC_CTRL 0x50 @@ -92,6 +60,8 @@ #define SYSTEM_CLK_RATE 0x030 +#define TEGRA30_CLK_PERIPH_BANKS 5 + #define PLLC_BASE 0x80 #define PLLC_MISC 0x8c #define PLLM_BASE 0x90 @@ -280,43 +250,43 @@ static DEFINE_SPINLOCK(pll_d_lock); static DEFINE_SPINLOCK(sysrate_lock); #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, _regs, \ + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ - _regs, _clk_num, periph_clk_enb_refcnt, \ + _clk_num, periph_clk_enb_refcnt, \ _gate_flags, _clk_id) #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 29, 3, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, _regs,\ + 29, 3, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _regs, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _regs, _clk_id) \ + _clk_num, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ - TEGRA_DIVIDER_ROUND_UP, _regs, _clk_num, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ periph_clk_enb_refcnt, 0, _clk_id) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ - _mux_shift, _mux_width, _clk_num, _regs, \ + _mux_shift, _mux_width, _clk_num, \ _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs, \ + _mux_shift, _mux_width, 0, 0, 0, 0, 0,\ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ _clk_id) @@ -695,52 +665,6 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_delay = 300, }; -/* Peripheral clock registers */ -static struct tegra_clk_periph_regs periph_l_regs = { - .enb_reg = CLK_OUT_ENB_L, - .enb_set_reg = CLK_OUT_ENB_SET_L, - .enb_clr_reg = CLK_OUT_ENB_CLR_L, - .rst_reg = RST_DEVICES_L, - .rst_set_reg = RST_DEVICES_SET_L, - .rst_clr_reg = RST_DEVICES_CLR_L, -}; - -static struct tegra_clk_periph_regs periph_h_regs = { - .enb_reg = CLK_OUT_ENB_H, - .enb_set_reg = CLK_OUT_ENB_SET_H, - .enb_clr_reg = CLK_OUT_ENB_CLR_H, - .rst_reg = RST_DEVICES_H, - .rst_set_reg = RST_DEVICES_SET_H, - .rst_clr_reg = RST_DEVICES_CLR_H, -}; - -static struct tegra_clk_periph_regs periph_u_regs = { - .enb_reg = CLK_OUT_ENB_U, - .enb_set_reg = CLK_OUT_ENB_SET_U, - .enb_clr_reg = CLK_OUT_ENB_CLR_U, - .rst_reg = RST_DEVICES_U, - .rst_set_reg = RST_DEVICES_SET_U, - .rst_clr_reg = RST_DEVICES_CLR_U, -}; - -static struct tegra_clk_periph_regs periph_v_regs = { - .enb_reg = CLK_OUT_ENB_V, - .enb_set_reg = CLK_OUT_ENB_SET_V, - .enb_clr_reg = CLK_OUT_ENB_CLR_V, - .rst_reg = RST_DEVICES_V, - .rst_set_reg = RST_DEVICES_SET_V, - .rst_clr_reg = RST_DEVICES_CLR_V, -}; - -static struct tegra_clk_periph_regs periph_w_regs = { - .enb_reg = CLK_OUT_ENB_W, - .enb_set_reg = CLK_OUT_ENB_SET_W, - .enb_clr_reg = CLK_OUT_ENB_CLR_W, - .rst_reg = RST_DEVICES_W, - .rst_set_reg = RST_DEVICES_SET_W, - .rst_clr_reg = RST_DEVICES_CLR_W, -}; - static void tegra30_clk_measure_input_freq(void) { u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); @@ -1160,7 +1084,7 @@ static void __init tegra30_audio_clk_init(void) &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 113, &periph_v_regs, + CLK_SET_RATE_PARENT, 113, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio0_2x", NULL); clks[audio0_2x] = clk; @@ -1173,7 +1097,7 @@ static void __init tegra30_audio_clk_init(void) &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 114, &periph_v_regs, + CLK_SET_RATE_PARENT, 114, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio1_2x", NULL); clks[audio1_2x] = clk; @@ -1186,7 +1110,7 @@ static void __init tegra30_audio_clk_init(void) &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 115, &periph_v_regs, + CLK_SET_RATE_PARENT, 115, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio2_2x", NULL); clks[audio2_2x] = clk; @@ -1199,7 +1123,7 @@ static void __init tegra30_audio_clk_init(void) &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 116, &periph_v_regs, + CLK_SET_RATE_PARENT, 116, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio3_2x", NULL); clks[audio3_2x] = clk; @@ -1212,7 +1136,7 @@ static void __init tegra30_audio_clk_init(void) &clk_doubler_lock); clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 117, &periph_v_regs, + CLK_SET_RATE_PARENT, 117, periph_clk_enb_refcnt); clk_register_clkdev(clk, "audio4_2x", NULL); clks[audio4_2x] = clk; @@ -1225,7 +1149,7 @@ static void __init tegra30_audio_clk_init(void) &clk_doubler_lock); clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div", TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 118, &periph_v_regs, + CLK_SET_RATE_PARENT, 118, periph_clk_enb_refcnt); clk_register_clkdev(clk, "spdif_2x", NULL); clks[spdif_2x] = clk; @@ -1444,77 +1368,77 @@ static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0", "pll_d2_out0" }; static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", i2s0_parents, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0), - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", i2s1_parents, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", i2s2_parents, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), - TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", i2s3_parents, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3), - TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", i2s4_parents, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), - TEGRA_INIT_DATA_MUX("d_audio", "d_audio", "tegra30-ahub", mux_pllacp_clkm, CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, 0, d_audio), - TEGRA_INIT_DATA_MUX("dam0", NULL, "tegra30-dam.0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, &periph_v_regs, 0, dam0), - TEGRA_INIT_DATA_MUX("dam1", NULL, "tegra30-dam.1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, &periph_v_regs, 0, dam1), - TEGRA_INIT_DATA_MUX("dam2", NULL, "tegra30-dam.2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, &periph_v_regs, 0, dam2), - TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, 0, hda), - TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, 0, hda2codec_2x), - TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), - TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), - TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), - TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), - TEGRA_INIT_DATA_MUX("sbc5", NULL, "spi_tegra.4", mux_pllpcm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5), - TEGRA_INIT_DATA_MUX("sbc6", NULL, "spi_tegra.5", mux_pllpcm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6), - TEGRA_INIT_DATA_MUX("sata_oob", NULL, "tegra_sata_oob", mux_pllpcm_clkm, CLK_SOURCE_SATA_OOB, 123, &periph_v_regs, TEGRA_PERIPH_ON_APB, sata_oob), - TEGRA_INIT_DATA_MUX("sata", NULL, "tegra_sata", mux_pllpcm_clkm, CLK_SOURCE_SATA, 124, &periph_v_regs, TEGRA_PERIPH_ON_APB, sata), - TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_l_regs, TEGRA_PERIPH_ON_APB, ndflash), - TEGRA_INIT_DATA_MUX("ndspeed", NULL, "tegra_nand_speed", mux_pllpcm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), - TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), - TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllpc_clkm_clk32k, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor), - TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllpc_clk32k_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow), - TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), - TEGRA_INIT_DATA_INT("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), - TEGRA_INIT_DATA_INT("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), - TEGRA_INIT_DATA_INT("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, &periph_h_regs, 0, mpe), - TEGRA_INIT_DATA_INT("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), - TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d), - TEGRA_INIT_DATA_INT("3d2", NULL, "3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, &periph_v_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d2), - TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr2d), - TEGRA_INIT_DATA_INT("se", NULL, "se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, 0, se), - TEGRA_INIT_DATA_MUX("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), - TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, &periph_h_regs, 0, cve), - TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, &periph_h_regs, 0, tvo), - TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, &periph_h_regs, 0, tvdac), - TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllpc_clk32k_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), - TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1), - TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2), - TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3), - TEGRA_INIT_DATA_DIV16("i2c4", "div-clk", "tegra-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2c4), - TEGRA_INIT_DATA_DIV16("i2c5", "div-clk", "tegra-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c5), - TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta), - TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb), - TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc), - TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd), - TEGRA_INIT_DATA_UART("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 66, &periph_u_regs, uarte), - TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), - TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1), - TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2), - TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3), - TEGRA_INIT_DATA("pwm", NULL, "pwm", mux_pllpc_clk32k_clkm, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, 0, pwm), + TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", i2s0_parents, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, i2s0), + TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, i2s1), + TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", i2s2_parents, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, i2s2), + TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", i2s3_parents, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, i2s3), + TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", i2s4_parents, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, i2s4), + TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, spdif_out), + TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, spdif_in), + TEGRA_INIT_DATA_MUX("d_audio", "d_audio", "tegra30-ahub", mux_pllacp_clkm, CLK_SOURCE_D_AUDIO, 106, 0, d_audio), + TEGRA_INIT_DATA_MUX("dam0", NULL, "tegra30-dam.0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, dam0), + TEGRA_INIT_DATA_MUX("dam1", NULL, "tegra30-dam.1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, dam1), + TEGRA_INIT_DATA_MUX("dam2", NULL, "tegra30-dam.2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, dam2), + TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA, 125, 0, hda), + TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, 0, hda2codec_2x), + TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, sbc1), + TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, sbc2), + TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, sbc3), + TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, sbc4), + TEGRA_INIT_DATA_MUX("sbc5", NULL, "spi_tegra.4", mux_pllpcm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, sbc5), + TEGRA_INIT_DATA_MUX("sbc6", NULL, "spi_tegra.5", mux_pllpcm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, sbc6), + TEGRA_INIT_DATA_MUX("sata_oob", NULL, "tegra_sata_oob", mux_pllpcm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, sata_oob), + TEGRA_INIT_DATA_MUX("sata", NULL, "tegra_sata", mux_pllpcm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, sata), + TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, ndflash), + TEGRA_INIT_DATA_MUX("ndspeed", NULL, "tegra_nand_speed", mux_pllpcm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, ndspeed), + TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, vfir), + TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, csite), + TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, la), + TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, owr), + TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, mipi), + TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllpc_clkm_clk32k, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, tsensor), + TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllpc_clk32k_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, i2cslow), + TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, 0, vde), + TEGRA_INIT_DATA_INT("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, 0, vi), + TEGRA_INIT_DATA_INT("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, 0, epp), + TEGRA_INIT_DATA_INT("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, 0, mpe), + TEGRA_INIT_DATA_INT("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, 0, host1x), + TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, TEGRA_PERIPH_MANUAL_RESET, gr3d), + TEGRA_INIT_DATA_INT("3d2", NULL, "3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, gr3d2), + TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, 0, gr2d), + TEGRA_INIT_DATA_INT("se", NULL, "se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, se), + TEGRA_INIT_DATA_MUX("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, mselect), + TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, 0, nor), + TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, 0, sdmmc1), + TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, 0, sdmmc2), + TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, 0, sdmmc3), + TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, 0, sdmmc4), + TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, 0, cve), + TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, 0, tvo), + TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, 0, tvdac), + TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllpc_clk32k_clkm, CLK_SOURCE_ACTMON, 119, 0, actmon), + TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, vi_sensor), + TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, TEGRA_PERIPH_ON_APB, i2c1), + TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, TEGRA_PERIPH_ON_APB, i2c2), + TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, TEGRA_PERIPH_ON_APB, i2c3), + TEGRA_INIT_DATA_DIV16("i2c4", "div-clk", "tegra-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, TEGRA_PERIPH_ON_APB, i2c4), + TEGRA_INIT_DATA_DIV16("i2c5", "div-clk", "tegra-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, TEGRA_PERIPH_ON_APB, i2c5), + TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 6, uarta), + TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 7, uartb), + TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 55, uartc), + TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 65, uartd), + TEGRA_INIT_DATA_UART("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 66, uarte), + TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, hdmi), + TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, extern1), + TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, extern2), + TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, extern3), + TEGRA_INIT_DATA("pwm", NULL, "pwm", mux_pllpc_clk32k_clkm, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, periph_clk_enb_refcnt, 0, pwm), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP1, 29, 3, 27, &periph_l_regs, 0, disp1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP2, 29, 3, 26, &periph_l_regs, 0, disp2), - TEGRA_INIT_DATA_NODIV("dsib", NULL, "tegradc.1", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB, 25, 1, 82, &periph_u_regs, 0, dsib), + TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP1, 29, 3, 27, 0, disp1), + TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP2, 29, 3, 26, 0, disp2), + TEGRA_INIT_DATA_NODIV("dsib", NULL, "tegradc.1", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB, 25, 1, 82, 0, dsib), }; static void __init tegra30_periph_clk_init(void) @@ -1525,166 +1449,154 @@ static void __init tegra30_periph_clk_init(void) /* apbdma */ clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, 0, 34, - &periph_h_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-apbdma"); clks[apbdma] = clk; /* rtc */ clk = tegra_clk_register_periph_gate("rtc", "clk_32k", TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 4, &periph_l_regs, - periph_clk_enb_refcnt); + clk_base, 0, 4, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "rtc-tegra"); clks[rtc] = clk; /* timer */ clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0, - 5, &periph_l_regs, periph_clk_enb_refcnt); + 5, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "timer"); clks[timer] = clk; /* kbc */ clk = tegra_clk_register_periph_gate("kbc", "clk_32k", TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 36, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 36, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-kbc"); clks[kbc] = clk; /* csus */ clk = tegra_clk_register_periph_gate("csus", "clk_m", TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 92, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 92, periph_clk_enb_refcnt); clk_register_clkdev(clk, "csus", "tengra_camera"); clks[csus] = clk; /* vcp */ clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, 29, - &periph_l_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "vcp", "tegra-avp"); clks[vcp] = clk; /* bsea */ clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, 0, - 62, &periph_h_regs, periph_clk_enb_refcnt); + 62, periph_clk_enb_refcnt); clk_register_clkdev(clk, "bsea", "tegra-avp"); clks[bsea] = clk; /* bsev */ clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, 0, - 63, &periph_h_regs, periph_clk_enb_refcnt); + 63, periph_clk_enb_refcnt); clk_register_clkdev(clk, "bsev", "tegra-aes"); clks[bsev] = clk; /* usbd */ clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, - 22, &periph_l_regs, periph_clk_enb_refcnt); + 22, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); clks[usbd] = clk; /* usb2 */ clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, - 58, &periph_h_regs, periph_clk_enb_refcnt); + 58, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-ehci.1"); clks[usb2] = clk; /* usb3 */ clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, - 59, &periph_h_regs, periph_clk_enb_refcnt); + 59, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra-ehci.2"); clks[usb3] = clk; /* dsia */ clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base, - 0, 48, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 48, periph_clk_enb_refcnt); clk_register_clkdev(clk, "dsia", "tegradc.0"); clks[dsia] = clk; /* csi */ clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, - 0, 52, &periph_h_regs, - periph_clk_enb_refcnt); + 0, 52, periph_clk_enb_refcnt); clk_register_clkdev(clk, "csi", "tegra_camera"); clks[csi] = clk; /* isp */ clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, - &periph_l_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "isp", "tegra_camera"); clks[isp] = clk; /* pcie */ clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0, - 70, &periph_u_regs, periph_clk_enb_refcnt); + 70, periph_clk_enb_refcnt); clk_register_clkdev(clk, "pcie", "tegra-pcie"); clks[pcie] = clk; /* afi */ clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, - &periph_u_regs, periph_clk_enb_refcnt); + periph_clk_enb_refcnt); clk_register_clkdev(clk, "afi", "tegra-pcie"); clks[afi] = clk; /* pciex */ clk = tegra_clk_register_periph_gate("pciex", "pll_e", 0, clk_base, 0, - 74, &periph_u_regs, periph_clk_enb_refcnt); + 74, periph_clk_enb_refcnt); clk_register_clkdev(clk, "pciex", "tegra-pcie"); clks[pciex] = clk; /* kfuse */ clk = tegra_clk_register_periph_gate("kfuse", "clk_m", TEGRA_PERIPH_ON_APB, - clk_base, 0, 40, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 40, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "kfuse-tegra"); clks[kfuse] = clk; /* fuse */ clk = tegra_clk_register_periph_gate("fuse", "clk_m", TEGRA_PERIPH_ON_APB, - clk_base, 0, 39, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 39, periph_clk_enb_refcnt); clk_register_clkdev(clk, "fuse", "fuse-tegra"); clks[fuse] = clk; /* fuse_burn */ clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", TEGRA_PERIPH_ON_APB, - clk_base, 0, 39, &periph_h_regs, - periph_clk_enb_refcnt); + clk_base, 0, 39, periph_clk_enb_refcnt); clk_register_clkdev(clk, "fuse_burn", "fuse-tegra"); clks[fuse_burn] = clk; /* apbif */ clk = tegra_clk_register_periph_gate("apbif", "clk_m", 0, - clk_base, 0, 107, &periph_v_regs, - periph_clk_enb_refcnt); + clk_base, 0, 107, periph_clk_enb_refcnt); clk_register_clkdev(clk, "apbif", "tegra30-ahub"); clks[apbif] = clk; /* hda2hdmi */ clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", TEGRA_PERIPH_ON_APB, - clk_base, 0, 128, &periph_w_regs, - periph_clk_enb_refcnt); + clk_base, 0, 128, periph_clk_enb_refcnt); clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda"); clks[hda2hdmi] = clk; /* sata_cold */ clk = tegra_clk_register_periph_gate("sata_cold", "clk_m", TEGRA_PERIPH_ON_APB, - clk_base, 0, 129, &periph_w_regs, - periph_clk_enb_refcnt); + clk_base, 0, 129, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "tegra_sata_cold"); clks[sata_cold] = clk; /* dtv */ clk = tegra_clk_register_periph_gate("dtv", "clk_m", TEGRA_PERIPH_ON_APB, - clk_base, 0, 79, &periph_u_regs, - periph_clk_enb_refcnt); + clk_base, 0, 79, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "dtv"); clks[dtv] = clk; @@ -1695,7 +1607,7 @@ static void __init tegra30_periph_clk_init(void) clk_base + CLK_SOURCE_EMC, 30, 2, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, - 57, &periph_h_regs, periph_clk_enb_refcnt); + 57, periph_clk_enb_refcnt); clk_register_clkdev(clk, "emc", NULL); clks[emc] = clk; @@ -2007,6 +1919,9 @@ static void __init tegra30_clock_init(struct device_node *np) BUG(); } + if (tegra_clk_set_periph_banks(TEGRA30_CLK_PERIPH_BANKS) < 0) + return; + tegra30_osc_clk_init(); tegra30_fixed_clk_init(); tegra30_pll_init(); diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index 86581ac1fd69..07f76df2583b 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -21,10 +21,114 @@ #include "clk.h" +#define CLK_OUT_ENB_L 0x010 +#define CLK_OUT_ENB_H 0x014 +#define CLK_OUT_ENB_U 0x018 +#define CLK_OUT_ENB_V 0x360 +#define CLK_OUT_ENB_W 0x364 +#define CLK_OUT_ENB_X 0x280 +#define CLK_OUT_ENB_SET_L 0x320 +#define CLK_OUT_ENB_CLR_L 0x324 +#define CLK_OUT_ENB_SET_H 0x328 +#define CLK_OUT_ENB_CLR_H 0x32c +#define CLK_OUT_ENB_SET_U 0x330 +#define CLK_OUT_ENB_CLR_U 0x334 +#define CLK_OUT_ENB_SET_V 0x440 +#define CLK_OUT_ENB_CLR_V 0x444 +#define CLK_OUT_ENB_SET_W 0x448 +#define CLK_OUT_ENB_CLR_W 0x44c +#define CLK_OUT_ENB_SET_X 0x284 +#define CLK_OUT_ENB_CLR_X 0x288 + +#define RST_DEVICES_L 0x004 +#define RST_DEVICES_H 0x008 +#define RST_DEVICES_U 0x00C +#define RST_DFLL_DVCO 0x2F4 +#define RST_DEVICES_V 0x358 +#define RST_DEVICES_W 0x35C +#define RST_DEVICES_X 0x28C +#define RST_DEVICES_SET_L 0x300 +#define RST_DEVICES_CLR_L 0x304 +#define RST_DEVICES_SET_H 0x308 +#define RST_DEVICES_CLR_H 0x30c +#define RST_DEVICES_SET_U 0x310 +#define RST_DEVICES_CLR_U 0x314 +#define RST_DEVICES_SET_V 0x430 +#define RST_DEVICES_CLR_V 0x434 +#define RST_DEVICES_SET_W 0x438 +#define RST_DEVICES_CLR_W 0x43c + /* Global data of Tegra CPU CAR ops */ static struct tegra_cpu_car_ops dummy_car_ops; struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops; +static int periph_banks; + +static struct tegra_clk_periph_regs periph_regs[] = { + [0] = { + .enb_reg = CLK_OUT_ENB_L, + .enb_set_reg = CLK_OUT_ENB_SET_L, + .enb_clr_reg = CLK_OUT_ENB_CLR_L, + .rst_reg = RST_DEVICES_L, + .rst_set_reg = RST_DEVICES_SET_L, + .rst_clr_reg = RST_DEVICES_CLR_L, + }, + [1] = { + .enb_reg = CLK_OUT_ENB_H, + .enb_set_reg = CLK_OUT_ENB_SET_H, + .enb_clr_reg = CLK_OUT_ENB_CLR_H, + .rst_reg = RST_DEVICES_H, + .rst_set_reg = RST_DEVICES_SET_H, + .rst_clr_reg = RST_DEVICES_CLR_H, + }, + [2] = { + .enb_reg = CLK_OUT_ENB_U, + .enb_set_reg = CLK_OUT_ENB_SET_U, + .enb_clr_reg = CLK_OUT_ENB_CLR_U, + .rst_reg = RST_DEVICES_U, + .rst_set_reg = RST_DEVICES_SET_U, + .rst_clr_reg = RST_DEVICES_CLR_U, + }, + [3] = { + .enb_reg = CLK_OUT_ENB_V, + .enb_set_reg = CLK_OUT_ENB_SET_V, + .enb_clr_reg = CLK_OUT_ENB_CLR_V, + .rst_reg = RST_DEVICES_V, + .rst_set_reg = RST_DEVICES_SET_V, + .rst_clr_reg = RST_DEVICES_CLR_V, + }, + [4] = { + .enb_reg = CLK_OUT_ENB_W, + .enb_set_reg = CLK_OUT_ENB_SET_W, + .enb_clr_reg = CLK_OUT_ENB_CLR_W, + .rst_reg = RST_DEVICES_W, + .rst_set_reg = RST_DEVICES_SET_W, + .rst_clr_reg = RST_DEVICES_CLR_W, + }, +}; + +struct tegra_clk_periph_regs *get_reg_bank(int clkid) +{ + int reg_bank = clkid / 32; + + if (reg_bank < periph_banks) + return &periph_regs[reg_bank]; + else { + WARN_ON(1); + return NULL; + } +} + +int __init tegra_clk_set_periph_banks(int num) +{ + if (num > ARRAY_SIZE(periph_regs)) + return -EINVAL; + + periph_banks = num; + + return 0; +} + void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, struct clk *clks[], int clk_max) { diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 07cfacd91686..730d37b39488 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -400,8 +400,7 @@ void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); extern const struct clk_ops tegra_clk_periph_gate_ops; struct clk *tegra_clk_register_periph_gate(const char *name, const char *parent_name, u8 gate_flags, void __iomem *clk_base, - unsigned long flags, int clk_num, - struct tegra_clk_periph_regs *pregs, int *enable_refcnt); + unsigned long flags, int clk_num, int *enable_refcnt); /** * struct clk-periph - peripheral clock @@ -443,7 +442,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ _div_shift, _div_width, _div_frac_width, \ - _div_flags, _clk_num, _enb_refcnt, _regs, \ + _div_flags, _clk_num, _enb_refcnt, \ _gate_flags, _table) \ { \ .mux = { \ @@ -462,7 +461,6 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, .flags = _gate_flags, \ .clk_num = _clk_num, \ .enable_refcnt = _enb_refcnt, \ - .regs = _regs, \ }, \ .mux_ops = &clk_mux_ops, \ .div_ops = &tegra_clk_frac_div_ops, \ @@ -483,7 +481,7 @@ struct tegra_periph_init_data { #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ _mux_shift, _mux_mask, _mux_flags, _div_shift, \ - _div_width, _div_frac_width, _div_flags, _regs, \ + _div_width, _div_frac_width, _div_flags, \ _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\ _flags) \ { \ @@ -495,7 +493,7 @@ struct tegra_periph_init_data { _mux_flags, _div_shift, \ _div_width, _div_frac_width, \ _div_flags, _clk_num, \ - _enb_refcnt, _regs, \ + _enb_refcnt, \ _gate_flags, _table), \ .offset = _offset, \ .con_id = _con_id, \ @@ -505,12 +503,12 @@ struct tegra_periph_init_data { #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\ _mux_shift, _mux_width, _mux_flags, _div_shift, \ - _div_width, _div_frac_width, _div_flags, _regs, \ + _div_width, _div_frac_width, _div_flags, \ _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ _div_shift, _div_width, _div_frac_width, _div_flags, \ - _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ + _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ NULL, 0) /** @@ -587,6 +585,9 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl, void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, struct clk *clks[], int clk_max); +struct tegra_clk_periph_regs *get_reg_bank(int clkid); +int tegra_clk_set_periph_banks(int num); + void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); void tegra114_clock_tune_cpu_trimmers_init(void); -- cgit v1.2.3 From 343a607cb79259429afbb9820bf524d33084e66c Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 2 Sep 2013 15:22:02 +0300 Subject: clk: tegra: common periph_clk_enb_refcnt and clks This patch makes periph_clk_enb_refcnt a global array, dynamically allocated at boottime. It simplifies the macros somewhat and allows clocks common to several Tegra SoCs to be defined in a separate files. Also the clks array becomes global and dynamically allocated which allows the DT registration to be moved to a generic funcion. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-periph.c | 1 + drivers/clk/tegra/clk-tegra114.c | 57 +++++++++++----------------------------- drivers/clk/tegra/clk-tegra20.c | 36 +++++++------------------ drivers/clk/tegra/clk-tegra30.c | 39 ++++++++------------------- drivers/clk/tegra/clk.c | 44 +++++++++++++++++++++++++++---- drivers/clk/tegra/clk.h | 16 ++++++----- 6 files changed, 85 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 735b0243261c..5102d5e58c04 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -197,6 +197,7 @@ static struct clk *_tegra_clk_register_periph(const char *name, periph->divider.reg = div ? (clk_base + offset) : NULL; periph->gate.clk_base = clk_base; periph->gate.regs = bank; + periph->gate.enable_refcnt = periph_clk_enb_refcnt; clk = clk_register(NULL, &periph->hw); if (IS_ERR(clk)) diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 8507067d5dd6..9729af823eaf 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -57,8 +57,6 @@ #define CPU_FINETRIM_R_FCPU_6_SHIFT 10 /* ftop */ #define CPU_FINETRIM_R_FCPU_6_MASK (0x3 << CPU_FINETRIM_R_FCPU_6_SHIFT) -#define CLK_OUT_ENB_NUM 6 - #define TEGRA114_CLK_PERIPH_BANKS 5 #define PLLC_BASE 0x80 @@ -266,8 +264,6 @@ static struct cpu_clk_suspend_context { } tegra114_cpu_clk_sctx; #endif -static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; - static void __iomem *clk_base; static void __iomem *pmc_base; @@ -712,59 +708,53 @@ static unsigned long tegra114_input_freq[] = { _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags,\ - _clk_id, _parents##_idx, 0) + _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags,\ - _clk_id, _parents##_idx, flags) + _clk_num, _gate_flags, _clk_id, _parents##_idx, flags) #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags,\ - _clk_id, _parents##_idx, 0) + _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id, \ - _parents##_idx, flags) + _gate_flags, _clk_id, _parents##_idx, flags) #define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id, \ - _parents##_idx, 0) + _gate_flags, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0) + 0, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, periph_clk_enb_refcnt, 0, _clk_id,\ - _parents##_idx, 0) + _clk_num, 0, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_mask, _clk_num, \ _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_num, _gate_flags, \ _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \ @@ -772,16 +762,14 @@ static unsigned long tegra114_input_freq[] = { TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id, \ - _parents##_idx, 0) + _gate_flags, _clk_id, _parents##_idx, 0) #define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset, _clk_num,\ _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \ _offset, 16, 0xE01F, 0, 0, 8, 1, \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags , _clk_id, \ - mux_d_audio_clk_idx, 0) + TEGRA_DIVIDER_ROUND_UP, _clk_num, \ + _gate_flags , _clk_id, mux_d_audio_clk_idx, 0) struct utmi_clk_param { /* Oscillator Frequency in KHz */ @@ -946,8 +934,7 @@ static const struct clk_div_table pll_re_div_table[] = { { .val = 0, .div = 0 }, }; -static struct clk *clks[TEGRA114_CLK_CLK_MAX]; -static struct clk_onecell_data clk_data; +static struct clk **clks; static unsigned long osc_freq; static unsigned long pll_ref_freq; @@ -2229,7 +2216,6 @@ EXPORT_SYMBOL(tegra114_clock_deassert_dfll_dvco_reset); static void __init tegra114_clock_init(struct device_node *np) { struct device_node *node; - int i; clk_base = of_iomap(np, 0); if (!clk_base) { @@ -2251,10 +2237,11 @@ static void __init tegra114_clock_init(struct device_node *np) return; } - if (tegra114_osc_clk_init(clk_base) < 0) + clks = tegra_clk_init(TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_PERIPH_BANKS); + if (!clks) return; - if (tegra_clk_set_periph_banks(TEGRA114_CLK_PERIPH_BANKS) < 0) + if (tegra114_osc_clk_init(clk_base) < 0) return; tegra114_fixed_clk_init(clk_base); @@ -2264,19 +2251,7 @@ static void __init tegra114_clock_init(struct device_node *np) tegra114_pmc_clk_init(pmc_base); tegra114_super_clk_init(clk_base); - for (i = 0; i < ARRAY_SIZE(clks); i++) { - if (IS_ERR(clks[i])) { - pr_err - ("Tegra114 clk %d: register failed with %ld\n", - i, PTR_ERR(clks[i])); - } - if (!clks[i]) - clks[i] = ERR_PTR(-EINVAL); - } - - clk_data.clks = clks; - clk_data.clk_num = ARRAY_SIZE(clks); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + tegra_add_of_provider(np); tegra_clk_apply_init_table = tegra114_clock_apply_init_table; diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 929a46278d83..6bf5c339ab43 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -25,8 +25,6 @@ #include "clk.h" -#define CLK_OUT_ENB_NUM 3 - #define OSC_CTRL 0x50 #define OSC_CTRL_OSC_FREQ_MASK (3<<30) #define OSC_CTRL_OSC_FREQ_13MHZ (0<<30) @@ -170,8 +168,6 @@ static struct cpu_clk_suspend_context { } tegra20_cpu_clk_sctx; #endif -static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; - static void __iomem *clk_base; static void __iomem *pmc_base; @@ -182,21 +178,21 @@ static DEFINE_SPINLOCK(sysrate_lock); _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, periph_clk_enb_refcnt, \ + _clk_num, \ _gate_flags, _clk_id) #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_num, _gate_flags, \ _clk_id) #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_num, _gate_flags, \ _clk_id) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ @@ -204,7 +200,7 @@ static DEFINE_SPINLOCK(sysrate_lock); _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_width, 0, 0, 0, 0, 0, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_num, _gate_flags, \ _clk_id) /* IDs assigned here must be in sync with DT bindings definition @@ -226,8 +222,7 @@ enum tegra20_clk { pll_x, cop, audio, pll_ref, twd, clk_max, }; -static struct clk *clks[clk_max]; -static struct clk_onecell_data clk_data; +static struct clk **clks; static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { { 12000000, 600000000, 600, 12, 0, 8 }, @@ -808,7 +803,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, TEGRA_PERIPH_ON_APB, i2c3), TEGRA_INIT_DATA_DIV16("dvc", "div-clk", "tegra-i2c.3", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, TEGRA_PERIPH_ON_APB, dvc), TEGRA_INIT_DATA_MUX("hdmi", NULL, "hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, 0, hdmi), - TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm), + TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, pwm), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { @@ -1232,7 +1227,6 @@ static const struct of_device_id pmc_match[] __initconst = { static void __init tegra20_clock_init(struct device_node *np) { - int i; struct device_node *node; clk_base = of_iomap(np, 0); @@ -1253,7 +1247,8 @@ static void __init tegra20_clock_init(struct device_node *np) BUG(); } - if (tegra_clk_set_periph_banks(TEGRA20_CLK_PERIPH_BANKS) < 0) + clks = tegra_clk_init(clk_max, TEGRA20_CLK_PERIPH_BANKS); + if (!clks) return; tegra20_osc_clk_init(); @@ -1264,22 +1259,9 @@ static void __init tegra20_clock_init(struct device_node *np) tegra20_periph_clk_init(); tegra20_audio_clk_init(); - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - if (IS_ERR(clks[i])) { - pr_err("Tegra20 clk %d: register failed with %ld\n", - i, PTR_ERR(clks[i])); - BUG(); - } - if (!clks[i]) - clks[i] = ERR_PTR(-EINVAL); - } - tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); - clk_data.clks = clks; - clk_data.clk_num = ARRAY_SIZE(clks); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + tegra_add_of_provider(np); tegra_clk_apply_init_table = tegra20_clock_apply_init_table; diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index a66bdabb5c5c..c5db42217ba8 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -26,8 +26,6 @@ #include "clk.h" -#define CLK_OUT_ENB_NUM 5 - #define OSC_CTRL 0x50 #define OSC_CTRL_OSC_FREQ_MASK (0xF<<28) #define OSC_CTRL_OSC_FREQ_13MHZ (0X0<<28) @@ -236,8 +234,6 @@ static struct cpu_clk_suspend_context { } tegra30_cpu_clk_sctx; #endif -static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; - static void __iomem *clk_base; static void __iomem *pmc_base; static unsigned long input_freq; @@ -253,41 +249,41 @@ static DEFINE_SPINLOCK(sysrate_lock); _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, _clk_id) + _clk_num, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, periph_clk_enb_refcnt, \ + _clk_num, \ _gate_flags, _clk_id) #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 29, 3, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, periph_clk_enb_refcnt, _gate_flags, _clk_id) + _clk_num, _gate_flags, _clk_id) #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, _gate_flags, _clk_id) + _gate_flags, _clk_id) #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ _clk_num, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - periph_clk_enb_refcnt, 0, _clk_id) + 0, _clk_id) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_width, _clk_num, \ _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_width, 0, 0, 0, 0, 0,\ - _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_num, _gate_flags, \ _clk_id) /* @@ -318,8 +314,7 @@ enum tegra30_clk { hclk, pclk, clk_out_1_mux = 300, clk_max }; -static struct clk *clks[clk_max]; -static struct clk_onecell_data clk_data; +static struct clk **clks; /* * Structure defining the fields for USB UTMI clocks Parameters. @@ -1432,7 +1427,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, extern1), TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, extern2), TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, extern3), - TEGRA_INIT_DATA("pwm", NULL, "pwm", mux_pllpc_clk32k_clkm, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, periph_clk_enb_refcnt, 0, pwm), + TEGRA_INIT_DATA("pwm", NULL, "pwm", mux_pllpc_clk32k_clkm, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, 0, pwm), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { @@ -1899,7 +1894,6 @@ static const struct of_device_id pmc_match[] __initconst = { static void __init tegra30_clock_init(struct device_node *np) { struct device_node *node; - int i; clk_base = of_iomap(np, 0); if (!clk_base) { @@ -1919,7 +1913,8 @@ static void __init tegra30_clock_init(struct device_node *np) BUG(); } - if (tegra_clk_set_periph_banks(TEGRA30_CLK_PERIPH_BANKS) < 0) + clks = tegra_clk_init(clk_max, TEGRA30_CLK_PERIPH_BANKS); + if (!clks) return; tegra30_osc_clk_init(); @@ -1930,21 +1925,9 @@ static void __init tegra30_clock_init(struct device_node *np) tegra30_audio_clk_init(); tegra30_pmc_clk_init(); - for (i = 0; i < ARRAY_SIZE(clks); i++) { - if (IS_ERR(clks[i])) { - pr_err("Tegra30 clk %d: register failed with %ld\n", - i, PTR_ERR(clks[i])); - BUG(); - } - if (!clks[i]) - clks[i] = ERR_PTR(-EINVAL); - } - tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); - clk_data.clks = clks; - clk_data.clk_num = ARRAY_SIZE(clks); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + tegra_add_of_provider(np); tegra_clk_apply_init_table = tegra30_clock_apply_init_table; diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index 07f76df2583b..3a95a8757ebc 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -62,7 +62,11 @@ static struct tegra_cpu_car_ops dummy_car_ops; struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops; +int *periph_clk_enb_refcnt; static int periph_banks; +static struct clk **clks; +static int clk_num; +static struct clk_onecell_data clk_data; static struct tegra_clk_periph_regs periph_regs[] = { [0] = { @@ -119,14 +123,25 @@ struct tegra_clk_periph_regs *get_reg_bank(int clkid) } } -int __init tegra_clk_set_periph_banks(int num) +struct clk ** __init tegra_clk_init(int num, int banks) { - if (num > ARRAY_SIZE(periph_regs)) - return -EINVAL; + if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) + return NULL; + + periph_clk_enb_refcnt = kzalloc(32 * banks * + sizeof(*periph_clk_enb_refcnt), GFP_KERNEL); + if (!periph_clk_enb_refcnt) + return NULL; - periph_banks = num; + periph_banks = banks; - return 0; + clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL); + if (!clks) + kfree(periph_clk_enb_refcnt); + + clk_num = num; + + return clks; } void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, @@ -178,6 +193,25 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, } } +void __init tegra_add_of_provider(struct device_node *np) +{ + int i; + + for (i = 0; i < clk_num; i++) { + if (IS_ERR(clks[i])) { + pr_err + ("Tegra clk %d: register failed with %ld\n", + i, PTR_ERR(clks[i])); + } + if (!clks[i]) + clks[i] = ERR_PTR(-EINVAL); + } + + clk_data.clks = clks; + clk_data.clk_num = clk_num; + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} + tegra_clk_apply_init_table_func tegra_clk_apply_init_table; void __init tegra_clocks_apply_init_table(void) diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 730d37b39488..997357ef059e 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -37,6 +37,8 @@ struct tegra_clk_sync_source { container_of(_hw, struct tegra_clk_sync_source, hw) extern const struct clk_ops tegra_clk_sync_source_ops; +extern int *periph_clk_enb_refcnt; + struct clk *tegra_clk_register_sync_source(const char *name, unsigned long fixed_rate, unsigned long max_rate); @@ -442,7 +444,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ _div_shift, _div_width, _div_frac_width, \ - _div_flags, _clk_num, _enb_refcnt, \ + _div_flags, _clk_num,\ _gate_flags, _table) \ { \ .mux = { \ @@ -460,7 +462,6 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, .gate = { \ .flags = _gate_flags, \ .clk_num = _clk_num, \ - .enable_refcnt = _enb_refcnt, \ }, \ .mux_ops = &clk_mux_ops, \ .div_ops = &tegra_clk_frac_div_ops, \ @@ -482,7 +483,7 @@ struct tegra_periph_init_data { #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ _mux_shift, _mux_mask, _mux_flags, _div_shift, \ _div_width, _div_frac_width, _div_flags, \ - _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\ + _clk_num, _gate_flags, _clk_id, _table, \ _flags) \ { \ .name = _name, \ @@ -493,7 +494,6 @@ struct tegra_periph_init_data { _mux_flags, _div_shift, \ _div_width, _div_frac_width, \ _div_flags, _clk_num, \ - _enb_refcnt, \ _gate_flags, _table), \ .offset = _offset, \ .con_id = _con_id, \ @@ -504,11 +504,11 @@ struct tegra_periph_init_data { #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\ _mux_shift, _mux_width, _mux_flags, _div_shift, \ _div_width, _div_frac_width, _div_flags, \ - _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ + _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ _div_shift, _div_width, _div_frac_width, _div_flags, \ - _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ + _clk_num, _gate_flags, _clk_id,\ NULL, 0) /** @@ -586,7 +586,9 @@ void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, struct clk *clks[], int clk_max); struct tegra_clk_periph_regs *get_reg_bank(int clkid); -int tegra_clk_set_periph_banks(int num); +struct clk **tegra_clk_init(int num, int periph_banks); + +void tegra_add_of_provider(struct device_node *np); void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); -- cgit v1.2.3 From 5bb9d26700c3db54d5a4346c3b6621b8889f3813 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 2 Sep 2013 18:43:56 +0300 Subject: clk: tegra: Add TEGRA_PERIPH_NO_DIV flag This flag indicates the peripheral clock does not have a divider. It will simplify the initialization tables and avoids some very similar code. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-periph.c | 11 ++++++++--- drivers/clk/tegra/clk.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 5102d5e58c04..b5feccca2f1e 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -173,12 +173,16 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = { static struct clk *_tegra_clk_register_periph(const char *name, const char **parent_names, int num_parents, struct tegra_clk_periph *periph, - void __iomem *clk_base, u32 offset, bool div, + void __iomem *clk_base, u32 offset, unsigned long flags) { struct clk *clk; struct clk_init_data init; struct tegra_clk_periph_regs *bank; + bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV); + + flags |= periph->gate.flags & TEGRA_PERIPH_NO_DIV ? + CLK_SET_RATE_PARENT : 0; init.name = name; init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; @@ -216,7 +220,7 @@ struct clk *tegra_clk_register_periph(const char *name, u32 offset, unsigned long flags) { return _tegra_clk_register_periph(name, parent_names, num_parents, - periph, clk_base, offset, true, flags); + periph, clk_base, offset, flags); } struct clk *tegra_clk_register_periph_nodiv(const char *name, @@ -224,6 +228,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, struct tegra_clk_periph *periph, void __iomem *clk_base, u32 offset) { + periph->gate.flags |= TEGRA_PERIPH_NO_DIV; return _tegra_clk_register_periph(name, parent_names, num_parents, - periph, clk_base, offset, false, CLK_SET_RATE_PARENT); + periph, clk_base, offset, CLK_SET_RATE_PARENT); } diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 997357ef059e..a82672084718 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -397,6 +397,7 @@ struct tegra_clk_periph_gate { #define TEGRA_PERIPH_MANUAL_RESET BIT(1) #define TEGRA_PERIPH_ON_APB BIT(2) #define TEGRA_PERIPH_WAR_1005168 BIT(3) +#define TEGRA_PERIPH_NO_DIV BIT(4) void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); extern const struct clk_ops tegra_clk_periph_gate_ops; -- cgit v1.2.3 From 04edb099a4a7e774a98b241dc016957922cbfb44 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 6 Sep 2013 14:37:37 +0300 Subject: clk: tegra: move some PLLC and PLLXC init to clk-pll.c VCO min clipping, dynamic ramp setup and IDDQ init can be done in the respective PLL clk_register functions if the parent is already registered. This is done for other some PLLs already. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-pll.c | 95 ++++++++++++++++++++++++++++++++-- drivers/clk/tegra/clk-tegra114.c | 109 +++++++-------------------------------- 2 files changed, 111 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 25734348242f..8f51147185db 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -773,6 +773,48 @@ static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, return 1; } +static unsigned long _clip_vco_min(unsigned long vco_min, + unsigned long parent_rate) +{ + return DIV_ROUND_UP(vco_min, parent_rate) * parent_rate; +} + +static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params, + void __iomem *clk_base, + unsigned long parent_rate) +{ + u32 val; + u32 step_a, step_b; + + switch (parent_rate) { + case 12000000: + case 13000000: + case 26000000: + step_a = 0x2B; + step_b = 0x0B; + break; + case 16800000: + step_a = 0x1A; + step_b = 0x09; + break; + case 19200000: + step_a = 0x12; + step_b = 0x08; + break; + default: + pr_err("%s: Unexpected reference rate %lu\n", + __func__, parent_rate); + WARN_ON(1); + return -EINVAL; + } + + val = step_a << pll_params->stepa_shift; + val |= step_b << pll_params->stepb_shift; + writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg); + + return 0; +} + static int clk_pll_iddq_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -1423,11 +1465,39 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, spinlock_t *lock) { struct tegra_clk_pll *pll; - struct clk *clk; + struct clk *clk, *parent; + unsigned long parent_rate; + int err; + u32 val, val_iddq; + + parent = __clk_lookup(parent_name); + if (IS_ERR(parent)) { + WARN(1, "parent clk %s of %s must be registered first\n", + name, parent_name); + return ERR_PTR(-EINVAL); + } if (!pll_params->pdiv_tohw) return ERR_PTR(-EINVAL); + parent_rate = __clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate); + if (err) + return ERR_PTR(err); + + val = readl_relaxed(clk_base + pll_params->base_reg); + val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg); + + if (val & PLL_BASE_ENABLE) + WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx)); + else { + val_iddq |= BIT(pll_params->iddq_bit_idx); + writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg); + } + pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, freq_table, lock); @@ -1455,6 +1525,9 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, struct clk *clk; pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC; + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, freq_table, lock); if (IS_ERR(pll)) @@ -1498,11 +1571,23 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, spinlock_t *lock) { struct tegra_clk_pll *pll; - struct clk *clk; + struct clk *clk, *parent; + unsigned long parent_rate; if (!pll_params->pdiv_tohw) return ERR_PTR(-EINVAL); + parent = __clk_lookup(parent_name); + if (IS_ERR(parent)) { + WARN(1, "parent clk %s of %s must be registered first\n", + name, parent_name); + return ERR_PTR(-EINVAL); + } + + parent_rate = __clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + pll_flags |= TEGRA_PLL_BYPASS; pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; pll_flags |= TEGRA_PLLM; @@ -1543,14 +1628,16 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, return ERR_PTR(-EINVAL); } + parent_rate = __clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + pll_flags |= TEGRA_PLL_BYPASS; pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, freq_table, lock); if (IS_ERR(pll)) return ERR_CAST(pll); - parent_rate = __clk_get_rate(parent); - /* * Most of PLLC register fields are shadowed, and can not be read * directly from PLL h/w. Hence, actual PLLC boot state is unknown. diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 9729af823eaf..fa562e3e8f19 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1077,63 +1077,6 @@ static __init void tegra114_utmi_param_configure(void __iomem *clk_base) writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); } -static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params) -{ - pll_params->vco_min = - DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq; -} - -static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params, - void __iomem *clk_base) -{ - u32 val; - u32 step_a, step_b; - - switch (pll_ref_freq) { - case 12000000: - case 13000000: - case 26000000: - step_a = 0x2B; - step_b = 0x0B; - break; - case 16800000: - step_a = 0x1A; - step_b = 0x09; - break; - case 19200000: - step_a = 0x12; - step_b = 0x08; - break; - default: - pr_err("%s: Unexpected reference rate %lu\n", - __func__, pll_ref_freq); - WARN_ON(1); - return -EINVAL; - } - - val = step_a << pll_params->stepa_shift; - val |= step_b << pll_params->stepb_shift; - writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg); - - return 0; -} - -static void __init _init_iddq(struct tegra_clk_pll_params *pll_params, - void __iomem *clk_base) -{ - u32 val, val_iddq; - - val = readl_relaxed(clk_base + pll_params->base_reg); - val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg); - - if (val & BIT(30)) - WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx)); - else { - val_iddq |= BIT(pll_params->iddq_bit_idx); - writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg); - } -} - static void __init tegra114_pll_init(void __iomem *clk_base, void __iomem *pmc) { @@ -1141,28 +1084,23 @@ static void __init tegra114_pll_init(void __iomem *clk_base, struct clk *clk; /* PLLC */ - _clip_vco_min(&pll_c_params); - if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) { - _init_iddq(&pll_c_params, clk_base); - clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base, - pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK, - pll_c_freq_table, NULL); - clk_register_clkdev(clk, "pll_c", NULL); - clks[TEGRA114_CLK_PLL_C] = clk; - - /* PLLC_OUT1 */ - clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", - clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, - 8, 8, 1, NULL); - clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", - clk_base + PLLC_OUT, 1, 0, - CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_c_out1", NULL); - clks[TEGRA114_CLK_PLL_C_OUT1] = clk; - } + clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base, + pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK, + pll_c_freq_table, NULL); + clk_register_clkdev(clk, "pll_c", NULL); + clks[TEGRA114_CLK_PLL_C] = clk; + + /* PLLC_OUT1 */ + clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", + clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", + clk_base + PLLC_OUT, 1, 0, + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_c_out1", NULL); + clks[TEGRA114_CLK_PLL_C_OUT1] = clk; /* PLLC2 */ - _clip_vco_min(&pll_c2_params); clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0, &pll_c2_params, TEGRA_PLL_USE_LOCK, pll_cx_freq_table, NULL); @@ -1170,7 +1108,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_C2] = clk; /* PLLC3 */ - _clip_vco_min(&pll_c3_params); clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0, &pll_c3_params, TEGRA_PLL_USE_LOCK, pll_cx_freq_table, NULL); @@ -1232,7 +1169,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_P_OUT4] = clk; /* PLLM */ - _clip_vco_min(&pll_m_params); clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, &pll_m_params, TEGRA_PLL_USE_LOCK, @@ -1255,15 +1191,11 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_SET_RATE_PARENT, 1, 1); /* PLLX */ - _clip_vco_min(&pll_x_params); - if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) { - _init_iddq(&pll_x_params, clk_base); - clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, - pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params, - TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL); - clk_register_clkdev(clk, "pll_x", NULL); - clks[TEGRA114_CLK_PLL_X] = clk; - } + clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, + pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params, + TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL); + clk_register_clkdev(clk, "pll_x", NULL); + clks[TEGRA114_CLK_PLL_X] = clk; /* PLLX_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", @@ -1356,7 +1288,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_A_OUT0] = clk; /* PLLRE */ - _clip_vco_min(&pll_re_vco_params); clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, 0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK, NULL, &pll_re_lock, pll_ref_freq); -- cgit v1.2.3 From 8e9cc80aa348938078c3c1a7ab55efb3c40990e3 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 25 Nov 2013 14:44:13 +0200 Subject: clk: tegra: use pll_ref as the pll_e parent Use pll_ref instead of pll_re_vco as the pll_e parent on Tegra114. Also add a 12Mhz pll_ref table entry for pll_e for Tegra114. This prevents the system from crashing at bootup because of an unsupported pll_re_vco rate. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-pll.c | 8 +++++--- drivers/clk/tegra/clk-tegra114.c | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 8f51147185db..48f6bffc1cee 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1704,11 +1704,13 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, val_aux = pll_readl(pll_params->aux_reg, pll); if (val & PLL_BASE_ENABLE) { - if (!(val_aux & PLLE_AUX_PLLRE_SEL)) + if ((val_aux & PLLE_AUX_PLLRE_SEL) || + (val_aux & PLLE_AUX_PLLP_SEL)) WARN(1, "pll_e enabled with unsupported parent %s\n", - (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref"); + (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : + "pll_re_vco"); } else { - val_aux |= PLLE_AUX_PLLRE_SEL; + val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL); pll_writel(val, pll_params->aux_reg, pll); } diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index fa562e3e8f19..e62e4764131c 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -637,6 +637,7 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { /* PLLE special case: use cpcon field to store cml divider value */ {336000000, 100000000, 100, 21, 16, 11}, {312000000, 100000000, 200, 26, 24, 13}, + {12000000, 100000000, 200, 1, 24, 13}, {0, 0, 0, 0, 0, 0}, }; @@ -1301,7 +1302,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_RE_OUT] = clk; /* PLLE */ - clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco", + clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_ref", clk_base, 0, 100000000, &pll_e_params, pll_e_freq_table, NULL); clk_register_clkdev(clk, "pll_e_out0", NULL); -- cgit v1.2.3 From ebe142b2ad35d5656caae35d5deefdbebe847d3b Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 4 Oct 2013 17:28:34 +0300 Subject: clk: tegra: move fields to tegra_clk_pll_params Move some fields related to the PLL HW description to the tegra_clk_pll_params. This allows some PLL code to be moved to common files later. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-pll.c | 138 +++++++++++++++++---------------------- drivers/clk/tegra/clk-tegra114.c | 74 ++++++++++++--------- drivers/clk/tegra/clk-tegra20.c | 44 ++++++++----- drivers/clk/tegra/clk-tegra30.c | 62 ++++++++++-------- drivers/clk/tegra/clk.h | 34 ++++------ 5 files changed, 175 insertions(+), 177 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 48f6bffc1cee..3aa85bf2f425 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -150,7 +150,7 @@ #define mask(w) ((1 << (w)) - 1) #define divm_mask(p) mask(p->params->div_nmp->divm_width) #define divn_mask(p) mask(p->params->div_nmp->divn_width) -#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \ +#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\ mask(p->params->div_nmp->divp_width)) #define divm_max(p) (divm_mask(p)) @@ -170,10 +170,10 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll) { u32 val; - if (!(pll->flags & TEGRA_PLL_USE_LOCK)) + if (!(pll->params->flags & TEGRA_PLL_USE_LOCK)) return; - if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE)) + if (!(pll->params->flags & TEGRA_PLL_HAS_LOCK_ENABLE)) return; val = pll_readl_misc(pll); @@ -187,13 +187,13 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll) u32 val, lock_mask; void __iomem *lock_addr; - if (!(pll->flags & TEGRA_PLL_USE_LOCK)) { + if (!(pll->params->flags & TEGRA_PLL_USE_LOCK)) { udelay(pll->params->lock_delay); return 0; } lock_addr = pll->clk_base; - if (pll->flags & TEGRA_PLL_LOCK_MISC) + if (pll->params->flags & TEGRA_PLL_LOCK_MISC) lock_addr += pll->params->misc_reg; else lock_addr += pll->params->base_reg; @@ -220,7 +220,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw) struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; - if (pll->flags & TEGRA_PLLM) { + if (pll->params->flags & TEGRA_PLLM) { val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0; @@ -239,12 +239,12 @@ static void _clk_pll_enable(struct clk_hw *hw) clk_pll_enable_lock(pll); val = pll_readl_base(pll); - if (pll->flags & TEGRA_PLL_BYPASS) + if (pll->params->flags & TEGRA_PLL_BYPASS) val &= ~PLL_BASE_BYPASS; val |= PLL_BASE_ENABLE; pll_writel_base(val, pll); - if (pll->flags & TEGRA_PLLM) { + if (pll->params->flags & TEGRA_PLLM) { val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); @@ -257,12 +257,12 @@ static void _clk_pll_disable(struct clk_hw *hw) u32 val; val = pll_readl_base(pll); - if (pll->flags & TEGRA_PLL_BYPASS) + if (pll->params->flags & TEGRA_PLL_BYPASS) val &= ~PLL_BASE_BYPASS; val &= ~PLL_BASE_ENABLE; pll_writel_base(val, pll); - if (pll->flags & TEGRA_PLLM) { + if (pll->params->flags & TEGRA_PLLM) { val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); @@ -342,7 +342,7 @@ static int _get_table_rate(struct clk_hw *hw, struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table *sel; - for (sel = pll->freq_table; sel->input_rate != 0; sel++) + for (sel = pll->params->freq_table; sel->input_rate != 0; sel++) if (sel->input_rate == parent_rate && sel->output_rate == rate) break; @@ -432,7 +432,7 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, struct tegra_clk_pll_params *params = pll->params; struct div_nmp *div_nmp = params->div_nmp; - if ((pll->flags & TEGRA_PLLM) && + if ((params->flags & TEGRA_PLLM) && (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { val = pll_override_readl(params->pmc_divp_reg, pll); @@ -468,7 +468,7 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, struct tegra_clk_pll_params *params = pll->params; struct div_nmp *div_nmp = params->div_nmp; - if ((pll->flags & TEGRA_PLLM) && + if ((params->flags & TEGRA_PLLM) && (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { val = pll_override_readl(params->pmc_divp_reg, pll); @@ -497,11 +497,11 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll, val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT); val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT; - if (pll->flags & TEGRA_PLL_SET_LFCON) { + if (pll->params->flags & TEGRA_PLL_SET_LFCON) { val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT); if (cfg->n >= PLLDU_LFCON_SET_DIVN) val |= 1 << PLL_MISC_LFCON_SHIFT; - } else if (pll->flags & TEGRA_PLL_SET_DCCON) { + } else if (pll->params->flags & TEGRA_PLL_SET_DCCON) { val &= ~(1 << PLL_MISC_DCCON_SHIFT); if (rate >= (pll->params->vco_max >> 1)) val |= 1 << PLL_MISC_DCCON_SHIFT; @@ -523,7 +523,7 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, _update_pll_mnp(pll, cfg); - if (pll->flags & TEGRA_PLL_HAS_CPCON) + if (pll->params->flags & TEGRA_PLL_HAS_CPCON) _update_pll_cpcon(pll, cfg, rate); if (state) { @@ -542,11 +542,11 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long flags = 0; int ret = 0; - if (pll->flags & TEGRA_PLL_FIXED) { - if (rate != pll->fixed_rate) { + if (pll->params->flags & TEGRA_PLL_FIXED) { + if (rate != pll->params->fixed_rate) { pr_err("%s: Can not change %s fixed rate %lu to %lu\n", __func__, __clk_get_name(hw->clk), - pll->fixed_rate, rate); + pll->params->fixed_rate, rate); return -EINVAL; } return 0; @@ -577,11 +577,11 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table cfg; - if (pll->flags & TEGRA_PLL_FIXED) - return pll->fixed_rate; + if (pll->params->flags & TEGRA_PLL_FIXED) + return pll->params->fixed_rate; /* PLLM is used for memory; we do not change rate */ - if (pll->flags & TEGRA_PLLM) + if (pll->params->flags & TEGRA_PLLM) return __clk_get_rate(hw->clk); if (_get_table_rate(hw, &cfg, rate, *prate) && @@ -604,17 +604,19 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, val = pll_readl_base(pll); - if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS)) + if ((pll->params->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS)) return parent_rate; - if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) { + if ((pll->params->flags & TEGRA_PLL_FIXED) && + !(val & PLL_BASE_OVERRIDE)) { struct tegra_clk_pll_freq_table sel; - if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) { + if (_get_table_rate(hw, &sel, pll->params->fixed_rate, + parent_rate)) { pr_err("Clock %s has unknown fixed frequency\n", __clk_get_name(hw->clk)); BUG(); } - return pll->fixed_rate; + return pll->params->fixed_rate; } _get_pll_mnp(pll, &cfg); @@ -682,7 +684,7 @@ static int clk_plle_enable(struct clk_hw *hw) u32 val; int err; - if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate)) + if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; clk_pll_disable(hw); @@ -698,7 +700,7 @@ static int clk_plle_enable(struct clk_hw *hw) return err; } - if (pll->flags & TEGRA_PLLE_CONFIGURE) { + if (pll->params->flags & TEGRA_PLLE_CONFIGURE) { /* configure dividers */ val = pll_readl_base(pll); val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); @@ -1233,7 +1235,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) unsigned long flags = 0; unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); - if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate)) + if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; if (pll->lock) @@ -1320,9 +1322,8 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw) #endif static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base, - void __iomem *pmc, unsigned long fixed_rate, - struct tegra_clk_pll_params *pll_params, u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) + void __iomem *pmc, struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) { struct tegra_clk_pll *pll; @@ -1333,10 +1334,7 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base, pll->clk_base = clk_base; pll->pmc = pmc; - pll->freq_table = freq_table; pll->params = pll_params; - pll->fixed_rate = fixed_rate; - pll->flags = pll_flags; pll->lock = lock; if (!pll_params->div_nmp) @@ -1365,17 +1363,15 @@ static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll, struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, - struct tegra_clk_pll_params *pll_params, u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) + unsigned long flags, struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) { struct tegra_clk_pll *pll; struct clk *clk; - pll_flags |= TEGRA_PLL_BYPASS; - pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; - pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, - freq_table, lock); + pll_params->flags |= TEGRA_PLL_BYPASS; + pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1389,17 +1385,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, - struct tegra_clk_pll_params *pll_params, u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) + unsigned long flags, struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) { struct tegra_clk_pll *pll; struct clk *clk; - pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS; - pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; - pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, - freq_table, lock); + pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS; + pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1458,10 +1452,8 @@ const struct clk_ops tegra_clk_plle_tegra114_ops = { struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) { struct tegra_clk_pll *pll; @@ -1498,9 +1490,8 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg); } - pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; - pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, - freq_table, lock); + pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1514,22 +1505,19 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock, unsigned long parent_rate) { u32 val; struct tegra_clk_pll *pll; struct clk *clk; - pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC; + pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC; pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); - pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, - freq_table, lock); + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1564,10 +1552,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) { struct tegra_clk_pll *pll; @@ -1588,11 +1574,10 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); - pll_flags |= TEGRA_PLL_BYPASS; - pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; - pll_flags |= TEGRA_PLLM; - pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, - freq_table, lock); + pll_params->flags |= TEGRA_PLL_BYPASS; + pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll_params->flags |= TEGRA_PLLM; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1606,10 +1591,8 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) { struct clk *parent, *clk; @@ -1632,9 +1615,8 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); - pll_flags |= TEGRA_PLL_BYPASS; - pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, - freq_table, lock); + pll_params->flags |= TEGRA_PLL_BYPASS; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1684,17 +1666,15 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, struct clk *tegra_clk_register_plle_tegra114(const char *name, const char *parent_name, void __iomem *clk_base, unsigned long flags, - unsigned long fixed_rate, struct tegra_clk_pll_params *pll_params, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) { struct tegra_clk_pll *pll; struct clk *clk; u32 val, val_aux; - pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params, - TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock); + pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index e62e4764131c..8f2ab376c53d 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -334,6 +334,8 @@ static struct tegra_clk_pll_params pll_c_params = { .stepb_shift = 9, .pdiv_tohw = pllxc_p, .div_nmp = &pllxc_nmp, + .freq_table = pll_c_freq_table, + .flags = TEGRA_PLL_USE_LOCK, }; static struct div_nmp pllcx_nmp = { @@ -381,6 +383,8 @@ static struct tegra_clk_pll_params pll_c2_params = { .ext_misc_reg[0] = 0x4f0, .ext_misc_reg[1] = 0x4f4, .ext_misc_reg[2] = 0x4f8, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_params pll_c3_params = { @@ -401,6 +405,8 @@ static struct tegra_clk_pll_params pll_c3_params = { .ext_misc_reg[0] = 0x504, .ext_misc_reg[1] = 0x508, .ext_misc_reg[2] = 0x50c, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, }; static struct div_nmp pllm_nmp = { @@ -447,6 +453,8 @@ static struct tegra_clk_pll_params pll_m_params = { .div_nmp = &pllm_nmp, .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2, + .freq_table = pll_m_freq_table, + .flags = TEGRA_PLL_USE_LOCK, }; static struct div_nmp pllp_nmp = { @@ -480,6 +488,9 @@ static struct tegra_clk_pll_params pll_p_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .div_nmp = &pllp_nmp, + .freq_table = pll_p_freq_table, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, + .fixed_rate = 408000000, }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { @@ -507,6 +518,8 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .div_nmp = &pllp_nmp, + .freq_table = pll_a_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { @@ -543,6 +556,9 @@ static struct tegra_clk_pll_params pll_d_params = { .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, .div_nmp = &pllp_nmp, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_params pll_d2_params = { @@ -558,6 +574,9 @@ static struct tegra_clk_pll_params pll_d2_params = { .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, .div_nmp = &pllp_nmp, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, }; static struct pdiv_map pllu_p[] = { @@ -598,6 +617,9 @@ static struct tegra_clk_pll_params pll_u_params = { .lock_delay = 1000, .pdiv_tohw = pllu_p, .div_nmp = &pllu_nmp, + .freq_table = pll_u_freq_table, + .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { @@ -631,6 +653,8 @@ static struct tegra_clk_pll_params pll_x_params = { .stepb_shift = 24, .pdiv_tohw = pllxc_p, .div_nmp = &pllxc_nmp, + .freq_table = pll_x_freq_table, + .flags = TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { @@ -664,6 +688,9 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 300, .div_nmp = &plle_nmp, + .freq_table = pll_e_freq_table, + .flags = TEGRA_PLL_FIXED, + .fixed_rate = 100000000, }; static struct div_nmp pllre_nmp = { @@ -690,6 +717,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .iddq_reg = PLLRE_MISC, .iddq_bit_idx = PLLRE_IDDQ_BIT, .div_nmp = &pllre_nmp, + .flags = TEGRA_PLL_USE_LOCK, }; /* possible OSC frequencies in Hz */ @@ -1086,8 +1114,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLC */ clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base, - pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK, - pll_c_freq_table, NULL); + pmc, 0, &pll_c_params, NULL); clk_register_clkdev(clk, "pll_c", NULL); clks[TEGRA114_CLK_PLL_C] = clk; @@ -1102,24 +1129,20 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_C_OUT1] = clk; /* PLLC2 */ - clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0, - &pll_c2_params, TEGRA_PLL_USE_LOCK, - pll_cx_freq_table, NULL); + clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, + &pll_c2_params, NULL); clk_register_clkdev(clk, "pll_c2", NULL); clks[TEGRA114_CLK_PLL_C2] = clk; /* PLLC3 */ - clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0, - &pll_c3_params, TEGRA_PLL_USE_LOCK, - pll_cx_freq_table, NULL); + clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, + &pll_c3_params, NULL); clk_register_clkdev(clk, "pll_c3", NULL); clks[TEGRA114_CLK_PLL_C3] = clk; /* PLLP */ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0, - 408000000, &pll_p_params, - TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, - pll_p_freq_table, NULL); + &pll_p_params, NULL); clk_register_clkdev(clk, "pll_p", NULL); clks[TEGRA114_CLK_PLL_P] = clk; @@ -1171,9 +1194,8 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLM */ clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, - &pll_m_params, TEGRA_PLL_USE_LOCK, - pll_m_freq_table, NULL); + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, + &pll_m_params, NULL); clk_register_clkdev(clk, "pll_m", NULL); clks[TEGRA114_CLK_PLL_M] = clk; @@ -1193,8 +1215,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLX */ clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, - pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params, - TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL); + pmc, CLK_IGNORE_UNUSED, &pll_x_params, NULL); clk_register_clkdev(clk, "pll_x", NULL); clks[TEGRA114_CLK_PLL_X] = clk; @@ -1210,9 +1231,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, writel(val, clk_base + pll_u_params.base_reg); clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0, - 0, &pll_u_params, TEGRA_PLLU | - TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock); + &pll_u_params, &pll_u_lock); clk_register_clkdev(clk, "pll_u", NULL); clks[TEGRA114_CLK_PLL_U] = clk; @@ -1245,9 +1264,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0, - 0, &pll_d_params, - TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock); + &pll_d_params, &pll_d_lock); clk_register_clkdev(clk, "pll_d", NULL); clks[TEGRA114_CLK_PLL_D] = clk; @@ -1259,9 +1276,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLD2 */ clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0, - 0, &pll_d2_params, - TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock); + &pll_d2_params, &pll_d2_lock); clk_register_clkdev(clk, "pll_d2", NULL); clks[TEGRA114_CLK_PLL_D2] = clk; @@ -1273,8 +1288,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLA */ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0, - 0, &pll_a_params, TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL); + &pll_a_params, NULL); clk_register_clkdev(clk, "pll_a", NULL); clks[TEGRA114_CLK_PLL_A] = clk; @@ -1290,8 +1304,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLRE */ clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, - 0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK, - NULL, &pll_re_lock, pll_ref_freq); + 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); clk_register_clkdev(clk, "pll_re_vco", NULL); clks[TEGRA114_CLK_PLL_RE_VCO] = clk; @@ -1303,8 +1316,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLE */ clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_ref", - clk_base, 0, 100000000, &pll_e_params, - pll_e_freq_table, NULL); + clk_base, 0, &pll_e_params, NULL); clk_register_clkdev(clk, "pll_e_out0", NULL); clks[TEGRA114_CLK_PLL_E_OUT0] = clk; } diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 6bf5c339ab43..31547fde92e4 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -360,6 +360,8 @@ static struct tegra_clk_pll_params pll_c_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_c_freq_table, + .flags = TEGRA_PLL_HAS_CPCON, }; static struct tegra_clk_pll_params pll_m_params = { @@ -374,6 +376,8 @@ static struct tegra_clk_pll_params pll_m_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_m_freq_table, + .flags = TEGRA_PLL_HAS_CPCON, }; static struct tegra_clk_pll_params pll_p_params = { @@ -388,6 +392,9 @@ static struct tegra_clk_pll_params pll_p_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_p_freq_table, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON, + .fixed_rate = 216000000, }; static struct tegra_clk_pll_params pll_a_params = { @@ -402,6 +409,8 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_a_freq_table, + .flags = TEGRA_PLL_HAS_CPCON, }; static struct tegra_clk_pll_params pll_d_params = { @@ -416,6 +425,8 @@ static struct tegra_clk_pll_params pll_d_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_HAS_CPCON, }; static struct pdiv_map pllu_p[] = { @@ -437,6 +448,8 @@ static struct tegra_clk_pll_params pll_u_params = { .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, .pdiv_tohw = pllu_p, + .freq_table = pll_u_freq_table, + .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON, }; static struct tegra_clk_pll_params pll_x_params = { @@ -451,6 +464,8 @@ static struct tegra_clk_pll_params pll_x_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_x_freq_table, + .flags = TEGRA_PLL_HAS_CPCON, }; static struct tegra_clk_pll_params pll_e_params = { @@ -465,6 +480,9 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_mask = PLLE_MISC_LOCK, .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 0, + .freq_table = pll_e_freq_table, + .flags = TEGRA_PLL_FIXED, + .fixed_rate = 100000000, }; static unsigned long tegra20_clk_measure_input_freq(void) @@ -526,8 +544,7 @@ static void tegra20_pll_init(void) /* PLLC */ clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, NULL, 0, - 0, &pll_c_params, TEGRA_PLL_HAS_CPCON, - pll_c_freq_table, NULL); + &pll_c_params, NULL); clk_register_clkdev(clk, "pll_c", NULL); clks[pll_c] = clk; @@ -543,8 +560,7 @@ static void tegra20_pll_init(void) /* PLLP */ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0, - 216000000, &pll_p_params, TEGRA_PLL_FIXED | - TEGRA_PLL_HAS_CPCON, pll_p_freq_table, NULL); + &pll_p_params, NULL); clk_register_clkdev(clk, "pll_p", NULL); clks[pll_p] = clk; @@ -598,9 +614,8 @@ static void tegra20_pll_init(void) /* PLLM */ clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, - &pll_m_params, TEGRA_PLL_HAS_CPCON, - pll_m_freq_table, NULL); + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, + &pll_m_params, NULL); clk_register_clkdev(clk, "pll_m", NULL); clks[pll_m] = clk; @@ -616,22 +631,19 @@ static void tegra20_pll_init(void) /* PLLX */ clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, NULL, 0, - 0, &pll_x_params, TEGRA_PLL_HAS_CPCON, - pll_x_freq_table, NULL); + &pll_x_params, NULL); clk_register_clkdev(clk, "pll_x", NULL); clks[pll_x] = clk; /* PLLU */ clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, NULL, 0, - 0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON, - pll_u_freq_table, NULL); + &pll_u_params, NULL); clk_register_clkdev(clk, "pll_u", NULL); clks[pll_u] = clk; /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, NULL, 0, - 0, &pll_d_params, TEGRA_PLL_HAS_CPCON, - pll_d_freq_table, NULL); + &pll_d_params, NULL); clk_register_clkdev(clk, "pll_d", NULL); clks[pll_d] = clk; @@ -643,8 +655,7 @@ static void tegra20_pll_init(void) /* PLLA */ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, NULL, 0, - 0, &pll_a_params, TEGRA_PLL_HAS_CPCON, - pll_a_freq_table, NULL); + &pll_a_params, NULL); clk_register_clkdev(clk, "pll_a", NULL); clks[pll_a] = clk; @@ -660,8 +671,7 @@ static void tegra20_pll_init(void) /* PLLE */ clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, pmc_base, - 0, 100000000, &pll_e_params, - 0, pll_e_freq_table, NULL); + 0, &pll_e_params, NULL); clk_register_clkdev(clk, "pll_e", NULL); clks[pll_e] = clk; } diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index c5db42217ba8..da540f6dc9c9 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -530,6 +530,8 @@ static struct tegra_clk_pll_params pll_c_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_c_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, }; static struct div_nmp pllm_nmp = { @@ -559,6 +561,9 @@ static struct tegra_clk_pll_params pll_m_params = { .div_nmp = &pllm_nmp, .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE, + .freq_table = pll_m_freq_table, + .flags = TEGRA_PLLM | TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_params pll_p_params = { @@ -573,6 +578,9 @@ static struct tegra_clk_pll_params pll_p_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_p_freq_table, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + .fixed_rate = 408000000, }; static struct tegra_clk_pll_params pll_a_params = { @@ -587,6 +595,8 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_a_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_params pll_d_params = { @@ -601,6 +611,10 @@ static struct tegra_clk_pll_params pll_d_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, + }; static struct tegra_clk_pll_params pll_d2_params = { @@ -615,6 +629,9 @@ static struct tegra_clk_pll_params pll_d2_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_params pll_u_params = { @@ -630,6 +647,8 @@ static struct tegra_clk_pll_params pll_u_params = { .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, .pdiv_tohw = pllu_p, + .freq_table = pll_u_freq_table, + .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON, }; static struct tegra_clk_pll_params pll_x_params = { @@ -644,6 +663,9 @@ static struct tegra_clk_pll_params pll_x_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_x_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_DCCON | + TEGRA_PLL_USE_LOCK, }; static struct tegra_clk_pll_params pll_e_params = { @@ -658,6 +680,9 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_mask = PLLE_MISC_LOCK, .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 300, + .freq_table = pll_e_freq_table, + .flags = TEGRA_PLLE_CONFIGURE | TEGRA_PLL_FIXED, + .fixed_rate = 100000000, }; static void tegra30_clk_measure_input_freq(void) @@ -783,9 +808,7 @@ static void __init tegra30_pll_init(void) /* PLLC */ clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0, - 0, &pll_c_params, - TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, - pll_c_freq_table, NULL); + &pll_c_params, NULL); clk_register_clkdev(clk, "pll_c", NULL); clks[pll_c] = clk; @@ -801,9 +824,7 @@ static void __init tegra30_pll_init(void) /* PLLP */ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc_base, 0, - 408000000, &pll_p_params, - TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_USE_LOCK, pll_p_freq_table, NULL); + &pll_p_params, NULL); clk_register_clkdev(clk, "pll_p", NULL); clks[pll_p] = clk; @@ -857,10 +878,8 @@ static void __init tegra30_pll_init(void) /* PLLM */ clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base, - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, - &pll_m_params, TEGRA_PLLM | TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK, - pll_m_freq_table, NULL); + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, + &pll_m_params, NULL); clk_register_clkdev(clk, "pll_m", NULL); clks[pll_m] = clk; @@ -876,9 +895,7 @@ static void __init tegra30_pll_init(void) /* PLLX */ clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, pmc_base, 0, - 0, &pll_x_params, TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK, - pll_x_freq_table, NULL); + &pll_x_params, NULL); clk_register_clkdev(clk, "pll_x", NULL); clks[pll_x] = clk; @@ -890,10 +907,7 @@ static void __init tegra30_pll_init(void) /* PLLU */ clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0, - 0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_LFCON, - pll_u_freq_table, - NULL); + &pll_u_params, NULL); clk_register_clkdev(clk, "pll_u", NULL); clks[pll_u] = clk; @@ -901,9 +915,7 @@ static void __init tegra30_pll_init(void) /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0, - 0, &pll_d_params, TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, - pll_d_freq_table, &pll_d_lock); + &pll_d_params, &pll_d_lock); clk_register_clkdev(clk, "pll_d", NULL); clks[pll_d] = clk; @@ -915,9 +927,7 @@ static void __init tegra30_pll_init(void) /* PLLD2 */ clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0, - 0, &pll_d2_params, TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, - pll_d_freq_table, NULL); + &pll_d2_params, NULL); clk_register_clkdev(clk, "pll_d2", NULL); clks[pll_d2] = clk; @@ -929,8 +939,7 @@ static void __init tegra30_pll_init(void) /* PLLA */ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc_base, - 0, 0, &pll_a_params, TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL); + 0, &pll_a_params, NULL); clk_register_clkdev(clk, "pll_a", NULL); clks[pll_a] = clk; @@ -950,8 +959,7 @@ static void __init tegra30_pll_init(void) CLK_SET_RATE_NO_REPARENT, clk_base + PLLE_AUX, 2, 1, 0, NULL); clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base, - CLK_GET_RATE_NOCACHE, 100000000, &pll_e_params, - TEGRA_PLLE_CONFIGURE, pll_e_freq_table, NULL); + CLK_GET_RATE_NOCACHE, &pll_e_params, NULL); clk_register_clkdev(clk, "pll_e", NULL); clks[pll_e] = clk; } diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index a82672084718..c49df4dc5ac6 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -190,12 +190,15 @@ struct tegra_clk_pll_params { u32 ext_misc_reg[3]; u32 pmc_divnm_reg; u32 pmc_divp_reg; + u32 flags; int stepa_shift; int stepb_shift; int lock_delay; int max_p; struct pdiv_map *pdiv_tohw; struct div_nmp *div_nmp; + struct tegra_clk_pll_freq_table *freq_table; + unsigned long fixed_rate; }; /** @@ -235,10 +238,7 @@ struct tegra_clk_pll { struct clk_hw hw; void __iomem *clk_base; void __iomem *pmc; - u32 flags; - unsigned long fixed_rate; spinlock_t *lock; - struct tegra_clk_pll_freq_table *freq_table; struct tegra_clk_pll_params *params; }; @@ -260,54 +260,42 @@ extern const struct clk_ops tegra_clk_pll_ops; extern const struct clk_ops tegra_clk_plle_ops; struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, - struct tegra_clk_pll_params *pll_params, u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); + unsigned long flags, struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, - struct tegra_clk_pll_params *pll_params, u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); + unsigned long flags, struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, - unsigned long flags, unsigned long fixed_rate, + unsigned long flags, struct tegra_clk_pll_params *pll_params, - u32 pll_flags, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock, unsigned long parent_rate); struct clk *tegra_clk_register_plle_tegra114(const char *name, const char *parent_name, void __iomem *clk_base, unsigned long flags, - unsigned long fixed_rate, struct tegra_clk_pll_params *pll_params, - struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); /** -- cgit v1.2.3 From a59ba9565ee20d162e858de03b9eebc0b9dbd8b6 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 2 Sep 2013 15:09:08 +0300 Subject: clk: tegra: add header for common tegra clock IDs Many clocks are common between several Tegra SoCs. Define an enum to list them so we can move them to separate files which can be shared between SoCs. Each SoC specific file will provide an array with the common clocks which are present on the SoC and their DT binding ID. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-id.h | 213 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 drivers/clk/tegra/clk-id.h (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h new file mode 100644 index 000000000000..22e2e8e67b2f --- /dev/null +++ b/drivers/clk/tegra/clk-id.h @@ -0,0 +1,213 @@ +/* + * This header provides IDs for clocks common between several Tegra SoCs + */ +#ifndef _TEGRA_CLK_ID_H +#define _TEGRA_CLK_ID_H + +enum clk_id { + tegra_clk_actmon, + tegra_clk_adx, + tegra_clk_afi, + tegra_clk_amx, + tegra_clk_apbdma, + tegra_clk_apbif, + tegra_clk_audio0, + tegra_clk_audio0_2x, + tegra_clk_audio0_mux, + tegra_clk_audio1, + tegra_clk_audio1_2x, + tegra_clk_audio1_mux, + tegra_clk_audio2, + tegra_clk_audio2_2x, + tegra_clk_audio2_mux, + tegra_clk_audio3, + tegra_clk_audio3_2x, + tegra_clk_audio3_mux, + tegra_clk_audio4, + tegra_clk_audio4_2x, + tegra_clk_audio4_mux, + tegra_clk_blink, + tegra_clk_bsea, + tegra_clk_bsev, + tegra_clk_cclk_g, + tegra_clk_cclk_lp, + tegra_clk_cilab, + tegra_clk_cilcd, + tegra_clk_cile, + tegra_clk_clk_32k, + tegra_clk_clk_m, + tegra_clk_clk_m_div2, + tegra_clk_clk_m_div4, + tegra_clk_clk_out_1, + tegra_clk_clk_out_1_mux, + tegra_clk_clk_out_2, + tegra_clk_clk_out_2_mux, + tegra_clk_clk_out_3, + tegra_clk_clk_out_3_mux, + tegra_clk_csi, + tegra_clk_csite, + tegra_clk_csus, + tegra_clk_cve, + tegra_clk_dam0, + tegra_clk_dam1, + tegra_clk_dam2, + tegra_clk_d_audio, + tegra_clk_dds, + tegra_clk_dfll_ref, + tegra_clk_dfll_soc, + tegra_clk_disp1, + tegra_clk_disp2, + tegra_clk_dp2, + tegra_clk_dsia, + tegra_clk_dsialp, + tegra_clk_dsia_mux, + tegra_clk_dsib, + tegra_clk_dsiblp, + tegra_clk_dsib_mux, + tegra_clk_dtv, + tegra_clk_emc, + tegra_clk_epp, + tegra_clk_epp_8, + tegra_clk_extern1, + tegra_clk_extern2, + tegra_clk_extern3, + tegra_clk_fuse, + tegra_clk_fuse_burn, + tegra_clk_gr2d, + tegra_clk_gr2d_8, + tegra_clk_gr3d, + tegra_clk_gr3d_8, + tegra_clk_hclk, + tegra_clk_hda, + tegra_clk_hda2codec_2x, + tegra_clk_hda2hdmi, + tegra_clk_hdmi, + tegra_clk_host1x, + tegra_clk_host1x_8, + tegra_clk_i2c1, + tegra_clk_i2c2, + tegra_clk_i2c3, + tegra_clk_i2c4, + tegra_clk_i2c5, + tegra_clk_i2cslow, + tegra_clk_i2s0, + tegra_clk_i2s0_sync, + tegra_clk_i2s1, + tegra_clk_i2s1_sync, + tegra_clk_i2s2, + tegra_clk_i2s2_sync, + tegra_clk_i2s3, + tegra_clk_i2s3_sync, + tegra_clk_i2s4, + tegra_clk_i2s4_sync, + tegra_clk_isp, + tegra_clk_kbc, + tegra_clk_kfuse, + tegra_clk_la, + tegra_clk_mipi, + tegra_clk_mipi_cal, + tegra_clk_mpe, + tegra_clk_mselect, + tegra_clk_msenc, + tegra_clk_ndflash, + tegra_clk_ndflash_8, + tegra_clk_ndspeed, + tegra_clk_ndspeed_8, + tegra_clk_nor, + tegra_clk_owr, + tegra_clk_pclk, + tegra_clk_pll_a, + tegra_clk_pll_a_out0, + tegra_clk_pll_c, + tegra_clk_pll_c2, + tegra_clk_pll_c3, + tegra_clk_pll_c_out1, + tegra_clk_pll_d, + tegra_clk_pll_d2, + tegra_clk_pll_d2_out0, + tegra_clk_pll_d_out0, + tegra_clk_pll_e_out0, + tegra_clk_pll_m, + tegra_clk_pll_m_out1, + tegra_clk_pll_p, + tegra_clk_pll_p_out1, + tegra_clk_pll_p_out2, + tegra_clk_pll_p_out2_int, + tegra_clk_pll_p_out3, + tegra_clk_pll_p_out4, + tegra_clk_pll_ref, + tegra_clk_pll_re_out, + tegra_clk_pll_re_vco, + tegra_clk_pll_u, + tegra_clk_pll_u_12m, + tegra_clk_pll_u_480m, + tegra_clk_pll_u_48m, + tegra_clk_pll_u_60m, + tegra_clk_pll_x, + tegra_clk_pll_x_out0, + tegra_clk_pwm, + tegra_clk_rtc, + tegra_clk_sata, + tegra_clk_sata_cold, + tegra_clk_sata_oob, + tegra_clk_sbc1, + tegra_clk_sbc1_8, + tegra_clk_sbc2, + tegra_clk_sbc2_8, + tegra_clk_sbc3, + tegra_clk_sbc3_8, + tegra_clk_sbc4, + tegra_clk_sbc4_8, + tegra_clk_sbc5, + tegra_clk_sbc5_8, + tegra_clk_sbc6, + tegra_clk_sbc6_8, + tegra_clk_sclk, + tegra_clk_sdmmc1, + tegra_clk_sdmmc2, + tegra_clk_sdmmc3, + tegra_clk_sdmmc4, + tegra_clk_se, + tegra_clk_soc_therm, + tegra_clk_spdif, + tegra_clk_spdif_2x, + tegra_clk_spdif_in, + tegra_clk_spdif_in_sync, + tegra_clk_spdif_mux, + tegra_clk_spdif_out, + tegra_clk_timer, + tegra_clk_trace, + tegra_clk_tsec, + tegra_clk_tsensor, + tegra_clk_tvdac, + tegra_clk_tvo, + tegra_clk_uarta, + tegra_clk_uartb, + tegra_clk_uartc, + tegra_clk_uartd, + tegra_clk_uarte, + tegra_clk_usb2, + tegra_clk_usb3, + tegra_clk_usbd, + tegra_clk_vcp, + tegra_clk_vde, + tegra_clk_vde_8, + tegra_clk_vfir, + tegra_clk_vi, + tegra_clk_vi_8, + tegra_clk_vimclk_sync, + tegra_clk_vi_sensor, + tegra_clk_vi_sensor_8, + tegra_clk_xusb_dev, + tegra_clk_xusb_dev_src, + tegra_clk_xusb_falcon_src, + tegra_clk_xusb_fs_src, + tegra_clk_xusb_host, + tegra_clk_xusb_host_src, + tegra_clk_xusb_hs_src, + tegra_clk_xusb_ss, + tegra_clk_xusb_ss_src, + tegra_clk_max, +}; + +#endif /* _TEGRA_CLK_ID_H */ -- cgit v1.2.3 From b8700d506ac4050fd96ce9305df04df811365326 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 14 Oct 2013 16:47:37 +0300 Subject: clk: tegra: add common infra for DT clocks Introduce a common infrastructure for sharing clock initialization between SoCs. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk.c | 9 +++++++++ drivers/clk/tegra/clk.h | 7 +++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index 3a95a8757ebc..a0430cd65d7c 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -212,6 +212,15 @@ void __init tegra_add_of_provider(struct device_node *np) of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } +struct clk ** __init tegra_lookup_dt_id(int clk_id, + struct tegra_clk *tegra_clk) +{ + if (tegra_clk[clk_id].present) + return &clks[tegra_clk[clk_id].dt_id]; + else + return NULL; +} + tegra_clk_apply_init_table_func tegra_clk_apply_init_table; void __init tegra_clocks_apply_init_table(void) diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index c49df4dc5ac6..489dad59d1d5 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -568,6 +568,11 @@ struct tegra_clk_duplicate { }, \ } +struct tegra_clk { + int dt_id; + bool present; +}; + void tegra_init_from_table(struct tegra_clk_init_table *tbl, struct clk *clks[], int clk_max); @@ -577,6 +582,8 @@ void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, struct tegra_clk_periph_regs *get_reg_bank(int clkid); struct clk **tegra_clk_init(int num, int periph_banks); +struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); + void tegra_add_of_provider(struct device_node *np); void tegra114_clock_tune_cpu_trimmers_high(void); -- cgit v1.2.3 From 73d37e4c7c4b9db26c9e4e1479e00996caa8e3f2 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Wed, 9 Oct 2013 14:47:57 +0300 Subject: clk: tegra: add clkdev registration infra Add a common infra for registering clkdev. This allows decoupling clk registration from clkdev registration. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 322 ++++++++++++++++++++------------------- drivers/clk/tegra/clk.c | 9 ++ drivers/clk/tegra/clk.h | 7 + 3 files changed, 179 insertions(+), 159 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 8f2ab376c53d..48d4381357bb 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -733,69 +733,69 @@ static unsigned long tegra114_input_freq[] = { #define MASK(x) (BIT(x) - 1) -#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ +#define TEGRA_INIT_DATA_MUX_FLAGS(_name, _parents, _offset,\ _clk_num, _gate_flags, _clk_id, flags)\ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ _clk_num, _gate_flags, _clk_id, _parents##_idx, flags) -#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_MUX8(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ +#define TEGRA_INIT_DATA_INT_FLAGS(_name, _parents, _offset,\ _clk_num, _gate_flags, _clk_id, flags)\ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ _gate_flags, _clk_id, _parents##_idx, flags) -#define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\ +#define TEGRA_INIT_DATA_INT8(_name, _parents, _offset,\ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ _gate_flags, _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ +#define TEGRA_INIT_DATA_UART(_name, _parents, _offset,\ _clk_num, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ 0, _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\ +#define TEGRA_INIT_DATA_I2C(_name, _parents, _offset,\ _clk_num, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ _clk_num, 0, _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_NODIV(_name, _parents, _offset, \ _mux_shift, _mux_mask, _clk_num, \ _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\ _clk_num, _gate_flags, \ _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_XUSB(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ _gate_flags, _clk_id, _parents##_idx, 0) -#define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset, _clk_num,\ +#define TEGRA_INIT_DATA_AUDIO(_name, _offset, _clk_num,\ _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk, \ _offset, 16, 0xE01F, 0, 0, 8, 1, \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ _gate_flags , _clk_id, mux_d_audio_clk_idx, 0) @@ -963,6 +963,71 @@ static const struct clk_div_table pll_re_div_table[] = { { .val = 0, .div = 0 }, }; +static struct tegra_devclk devclks[] __initdata = { + { .con_id = "clk_m", .dt_id = TEGRA114_CLK_CLK_M }, + { .con_id = "pll_ref", .dt_id = TEGRA114_CLK_PLL_REF }, + { .con_id = "clk_32k", .dt_id = TEGRA114_CLK_CLK_32K }, + { .con_id = "clk_m_div2", .dt_id = TEGRA114_CLK_CLK_M_DIV2 }, + { .con_id = "clk_m_div4", .dt_id = TEGRA114_CLK_CLK_M_DIV4 }, + { .con_id = "pll_c", .dt_id = TEGRA114_CLK_PLL_C }, + { .con_id = "pll_c_out1", .dt_id = TEGRA114_CLK_PLL_C_OUT1 }, + { .con_id = "pll_c2", .dt_id = TEGRA114_CLK_PLL_C2 }, + { .con_id = "pll_c3", .dt_id = TEGRA114_CLK_PLL_C3 }, + { .con_id = "pll_p", .dt_id = TEGRA114_CLK_PLL_P }, + { .con_id = "pll_p_out1", .dt_id = TEGRA114_CLK_PLL_P_OUT1 }, + { .con_id = "pll_p_out2", .dt_id = TEGRA114_CLK_PLL_P_OUT2 }, + { .con_id = "pll_p_out3", .dt_id = TEGRA114_CLK_PLL_P_OUT3 }, + { .con_id = "pll_p_out4", .dt_id = TEGRA114_CLK_PLL_P_OUT4 }, + { .con_id = "pll_m", .dt_id = TEGRA114_CLK_PLL_M }, + { .con_id = "pll_m_out1", .dt_id = TEGRA114_CLK_PLL_M_OUT1 }, + { .con_id = "pll_x", .dt_id = TEGRA114_CLK_PLL_X }, + { .con_id = "pll_x_out0", .dt_id = TEGRA114_CLK_PLL_X_OUT0 }, + { .con_id = "pll_u", .dt_id = TEGRA114_CLK_PLL_U }, + { .con_id = "pll_u_480M", .dt_id = TEGRA114_CLK_PLL_U_480M }, + { .con_id = "pll_u_60M", .dt_id = TEGRA114_CLK_PLL_U_60M }, + { .con_id = "pll_u_48M", .dt_id = TEGRA114_CLK_PLL_U_48M }, + { .con_id = "pll_u_12M", .dt_id = TEGRA114_CLK_PLL_U_12M }, + { .con_id = "pll_d", .dt_id = TEGRA114_CLK_PLL_D }, + { .con_id = "pll_d_out0", .dt_id = TEGRA114_CLK_PLL_D_OUT0 }, + { .con_id = "pll_d2", .dt_id = TEGRA114_CLK_PLL_D2 }, + { .con_id = "pll_d2_out0", .dt_id = TEGRA114_CLK_PLL_D2_OUT0 }, + { .con_id = "pll_a", .dt_id = TEGRA114_CLK_PLL_A }, + { .con_id = "pll_a_out0", .dt_id = TEGRA114_CLK_PLL_A_OUT0 }, + { .con_id = "pll_re_vco", .dt_id = TEGRA114_CLK_PLL_RE_VCO }, + { .con_id = "pll_re_out", .dt_id = TEGRA114_CLK_PLL_RE_OUT }, + { .con_id = "pll_e_out0", .dt_id = TEGRA114_CLK_PLL_E_OUT0 }, + { .con_id = "spdif_in_sync", .dt_id = TEGRA114_CLK_SPDIF_IN_SYNC }, + { .con_id = "i2s0_sync", .dt_id = TEGRA114_CLK_I2S0_SYNC }, + { .con_id = "i2s1_sync", .dt_id = TEGRA114_CLK_I2S1_SYNC }, + { .con_id = "i2s2_sync", .dt_id = TEGRA114_CLK_I2S2_SYNC }, + { .con_id = "i2s3_sync", .dt_id = TEGRA114_CLK_I2S3_SYNC }, + { .con_id = "i2s4_sync", .dt_id = TEGRA114_CLK_I2S4_SYNC }, + { .con_id = "vimclk_sync", .dt_id = TEGRA114_CLK_VIMCLK_SYNC }, + { .con_id = "audio0", .dt_id = TEGRA114_CLK_AUDIO0 }, + { .con_id = "audio1", .dt_id = TEGRA114_CLK_AUDIO1 }, + { .con_id = "audio2", .dt_id = TEGRA114_CLK_AUDIO2 }, + { .con_id = "audio3", .dt_id = TEGRA114_CLK_AUDIO3 }, + { .con_id = "audio4", .dt_id = TEGRA114_CLK_AUDIO4 }, + { .con_id = "spdif", .dt_id = TEGRA114_CLK_SPDIF }, + { .con_id = "audio0_2x", .dt_id = TEGRA114_CLK_AUDIO0_2X }, + { .con_id = "audio1_2x", .dt_id = TEGRA114_CLK_AUDIO1_2X }, + { .con_id = "audio2_2x", .dt_id = TEGRA114_CLK_AUDIO2_2X }, + { .con_id = "audio3_2x", .dt_id = TEGRA114_CLK_AUDIO3_2X }, + { .con_id = "audio4_2x", .dt_id = TEGRA114_CLK_AUDIO4_2X }, + { .con_id = "spdif_2x", .dt_id = TEGRA114_CLK_SPDIF_2X }, + { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA114_CLK_EXTERN1 }, + { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA114_CLK_EXTERN2 }, + { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA114_CLK_EXTERN3 }, + { .con_id = "blink", .dt_id = TEGRA114_CLK_BLINK }, + { .con_id = "cclk_g", .dt_id = TEGRA114_CLK_CCLK_G }, + { .con_id = "cclk_lp", .dt_id = TEGRA114_CLK_CCLK_LP }, + { .con_id = "sclk", .dt_id = TEGRA114_CLK_SCLK }, + { .con_id = "hclk", .dt_id = TEGRA114_CLK_HCLK }, + { .con_id = "pclk", .dt_id = TEGRA114_CLK_PCLK }, + { .dev_id = "rtc-tegra", .dt_id = TEGRA114_CLK_RTC }, + { .dev_id = "timer", .dt_id = TEGRA114_CLK_TIMER }, +}; + static struct clk **clks; static unsigned long osc_freq; @@ -984,7 +1049,6 @@ static int __init tegra114_osc_clk_init(void __iomem *clk_base) /* clk_m */ clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, osc_freq); - clk_register_clkdev(clk, "clk_m", NULL); clks[TEGRA114_CLK_CLK_M] = clk; /* pll_ref */ @@ -992,7 +1056,6 @@ static int __init tegra114_osc_clk_init(void __iomem *clk_base) pll_ref_div = 1 << val; clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", CLK_SET_RATE_PARENT, 1, pll_ref_div); - clk_register_clkdev(clk, "pll_ref", NULL); clks[TEGRA114_CLK_PLL_REF] = clk; pll_ref_freq = osc_freq / pll_ref_div; @@ -1007,19 +1070,16 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base) /* clk_32k */ clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, 32768); - clk_register_clkdev(clk, "clk_32k", NULL); clks[TEGRA114_CLK_CLK_32K] = clk; /* clk_m_div2 */ clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "clk_m_div2", NULL); clks[TEGRA114_CLK_CLK_M_DIV2] = clk; /* clk_m_div4 */ clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", CLK_SET_RATE_PARENT, 1, 4); - clk_register_clkdev(clk, "clk_m_div4", NULL); clks[TEGRA114_CLK_CLK_M_DIV4] = clk; } @@ -1115,7 +1175,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLC */ clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base, pmc, 0, &pll_c_params, NULL); - clk_register_clkdev(clk, "pll_c", NULL); clks[TEGRA114_CLK_PLL_C] = clk; /* PLLC_OUT1 */ @@ -1125,25 +1184,21 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_c_out1", NULL); clks[TEGRA114_CLK_PLL_C_OUT1] = clk; /* PLLC2 */ clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, &pll_c2_params, NULL); - clk_register_clkdev(clk, "pll_c2", NULL); clks[TEGRA114_CLK_PLL_C2] = clk; /* PLLC3 */ clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, &pll_c3_params, NULL); - clk_register_clkdev(clk, "pll_c3", NULL); clks[TEGRA114_CLK_PLL_C3] = clk; /* PLLP */ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0, &pll_p_params, NULL); - clk_register_clkdev(clk, "pll_p", NULL); clks[TEGRA114_CLK_PLL_P] = clk; /* PLLP_OUT1 */ @@ -1154,7 +1209,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLP_OUTA, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out1", NULL); clks[TEGRA114_CLK_PLL_P_OUT1] = clk; /* PLLP_OUT2 */ @@ -1166,7 +1220,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLP_OUTA, 17, 16, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out2", NULL); clks[TEGRA114_CLK_PLL_P_OUT2] = clk; /* PLLP_OUT3 */ @@ -1177,7 +1230,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLP_OUTB, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out3", NULL); clks[TEGRA114_CLK_PLL_P_OUT3] = clk; /* PLLP_OUT4 */ @@ -1189,14 +1241,12 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk_base + PLLP_OUTB, 17, 16, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out4", NULL); clks[TEGRA114_CLK_PLL_P_OUT4] = clk; /* PLLM */ clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, &pll_m_params, NULL); - clk_register_clkdev(clk, "pll_m", NULL); clks[TEGRA114_CLK_PLL_M] = clk; /* PLLM_OUT1 */ @@ -1206,7 +1256,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_m_out1", NULL); clks[TEGRA114_CLK_PLL_M_OUT1] = clk; /* PLLM_UD */ @@ -1216,13 +1265,11 @@ static void __init tegra114_pll_init(void __iomem *clk_base, /* PLLX */ clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, pmc, CLK_IGNORE_UNUSED, &pll_x_params, NULL); - clk_register_clkdev(clk, "pll_x", NULL); clks[TEGRA114_CLK_PLL_X] = clk; /* PLLX_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_x_out0", NULL); clks[TEGRA114_CLK_PLL_X_OUT0] = clk; /* PLLU */ @@ -1232,7 +1279,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0, &pll_u_params, &pll_u_lock); - clk_register_clkdev(clk, "pll_u", NULL); clks[TEGRA114_CLK_PLL_U] = clk; tegra114_utmi_param_configure(clk_base); @@ -1241,55 +1287,46 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk = clk_register_gate(NULL, "pll_u_480M", "pll_u", CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, 22, 0, &pll_u_lock); - clk_register_clkdev(clk, "pll_u_480M", NULL); clks[TEGRA114_CLK_PLL_U_480M] = clk; /* PLLU_60M */ clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u", CLK_SET_RATE_PARENT, 1, 8); - clk_register_clkdev(clk, "pll_u_60M", NULL); clks[TEGRA114_CLK_PLL_U_60M] = clk; /* PLLU_48M */ clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u", CLK_SET_RATE_PARENT, 1, 10); - clk_register_clkdev(clk, "pll_u_48M", NULL); clks[TEGRA114_CLK_PLL_U_48M] = clk; /* PLLU_12M */ clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u", CLK_SET_RATE_PARENT, 1, 40); - clk_register_clkdev(clk, "pll_u_12M", NULL); clks[TEGRA114_CLK_PLL_U_12M] = clk; /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0, &pll_d_params, &pll_d_lock); - clk_register_clkdev(clk, "pll_d", NULL); clks[TEGRA114_CLK_PLL_D] = clk; /* PLLD_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_d_out0", NULL); clks[TEGRA114_CLK_PLL_D_OUT0] = clk; /* PLLD2 */ clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0, &pll_d2_params, &pll_d2_lock); - clk_register_clkdev(clk, "pll_d2", NULL); clks[TEGRA114_CLK_PLL_D2] = clk; /* PLLD2_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_d2_out0", NULL); clks[TEGRA114_CLK_PLL_D2_OUT0] = clk; /* PLLA */ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0, &pll_a_params, NULL); - clk_register_clkdev(clk, "pll_a", NULL); clks[TEGRA114_CLK_PLL_A] = clk; /* PLLA_OUT0 */ @@ -1299,25 +1336,21 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_a_out0", NULL); clks[TEGRA114_CLK_PLL_A_OUT0] = clk; /* PLLRE */ clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); - clk_register_clkdev(clk, "pll_re_vco", NULL); clks[TEGRA114_CLK_PLL_RE_VCO] = clk; clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0, clk_base + PLLRE_BASE, 16, 4, 0, pll_re_div_table, &pll_re_lock); - clk_register_clkdev(clk, "pll_re_out", NULL); clks[TEGRA114_CLK_PLL_RE_OUT] = clk; /* PLLE */ clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_ref", clk_base, 0, &pll_e_params, NULL); - clk_register_clkdev(clk, "pll_e_out0", NULL); clks[TEGRA114_CLK_PLL_E_OUT0] = clk; } @@ -1344,37 +1377,30 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* spdif_in_sync */ clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000, 24000000); - clk_register_clkdev(clk, "spdif_in_sync", NULL); clks[TEGRA114_CLK_SPDIF_IN_SYNC] = clk; /* i2s0_sync */ clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s0_sync", NULL); clks[TEGRA114_CLK_I2S0_SYNC] = clk; /* i2s1_sync */ clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s1_sync", NULL); clks[TEGRA114_CLK_I2S1_SYNC] = clk; /* i2s2_sync */ clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s2_sync", NULL); clks[TEGRA114_CLK_I2S2_SYNC] = clk; /* i2s3_sync */ clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s3_sync", NULL); clks[TEGRA114_CLK_I2S3_SYNC] = clk; /* i2s4_sync */ clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s4_sync", NULL); clks[TEGRA114_CLK_I2S4_SYNC] = clk; /* vimclk_sync */ clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000); - clk_register_clkdev(clk, "vimclk_sync", NULL); clks[TEGRA114_CLK_VIMCLK_SYNC] = clk; /* audio0 */ @@ -1387,7 +1413,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S0, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio0", NULL); clks[TEGRA114_CLK_AUDIO0] = clk; /* audio1 */ @@ -1400,7 +1425,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S1, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio1", NULL); clks[TEGRA114_CLK_AUDIO1] = clk; /* audio2 */ @@ -1413,7 +1437,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S2, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio2", NULL); clks[TEGRA114_CLK_AUDIO2] = clk; /* audio3 */ @@ -1426,7 +1449,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S3, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio3", NULL); clks[TEGRA114_CLK_AUDIO3] = clk; /* audio4 */ @@ -1439,7 +1461,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S4, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio4", NULL); clks[TEGRA114_CLK_AUDIO4] = clk; /* spdif */ @@ -1452,7 +1473,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, clk_base + AUDIO_SYNC_CLK_SPDIF, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "spdif", NULL); clks[TEGRA114_CLK_SPDIF] = clk; /* audio0_2x */ @@ -1465,7 +1485,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 113, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio0_2x", NULL); clks[TEGRA114_CLK_AUDIO0_2X] = clk; /* audio1_2x */ @@ -1478,7 +1497,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 114, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio1_2x", NULL); clks[TEGRA114_CLK_AUDIO1_2X] = clk; /* audio2_2x */ @@ -1491,7 +1509,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 115, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio2_2x", NULL); clks[TEGRA114_CLK_AUDIO2_2X] = clk; /* audio3_2x */ @@ -1504,7 +1521,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 116, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio3_2x", NULL); clks[TEGRA114_CLK_AUDIO3_2X] = clk; /* audio4_2x */ @@ -1517,7 +1533,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 117, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio4_2x", NULL); clks[TEGRA114_CLK_AUDIO4_2X] = clk; /* spdif_2x */ @@ -1530,7 +1545,6 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 118, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "spdif_2x", NULL); clks[TEGRA114_CLK_SPDIF_2X] = clk; } @@ -1548,7 +1562,6 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, &clk_out_lock); - clk_register_clkdev(clk, "extern1", "clk_out_1"); clks[TEGRA114_CLK_CLK_OUT_1] = clk; /* clk_out_2 */ @@ -1561,7 +1574,6 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, &clk_out_lock); - clk_register_clkdev(clk, "extern2", "clk_out_2"); clks[TEGRA114_CLK_CLK_OUT_2] = clk; /* clk_out_3 */ @@ -1574,7 +1586,6 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, &clk_out_lock); - clk_register_clkdev(clk, "extern3", "clk_out_3"); clks[TEGRA114_CLK_CLK_OUT_3] = clk; /* blink */ @@ -1586,7 +1597,6 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) clk = clk_register_gate(NULL, "blink", "blink_override", 0, pmc_base + PMC_CTRL, PMC_CTRL_BLINK_ENB, 0, NULL); - clk_register_clkdev(clk, "blink", NULL); clks[TEGRA114_CLK_BLINK] = clk; } @@ -1613,7 +1623,6 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, clk_base + CCLKG_BURST_POLICY, 0, 4, 0, 0, NULL); - clk_register_clkdev(clk, "cclk_g", NULL); clks[TEGRA114_CLK_CCLK_G] = clk; /* CCLKLP */ @@ -1622,7 +1631,6 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, clk_base + CCLKLP_BURST_POLICY, 0, 4, 8, 9, NULL); - clk_register_clkdev(clk, "cclk_lp", NULL); clks[TEGRA114_CLK_CCLK_LP] = clk; /* SCLK */ @@ -1631,7 +1639,6 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) CLK_SET_RATE_PARENT, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); - clk_register_clkdev(clk, "sclk", NULL); clks[TEGRA114_CLK_SCLK] = clk; /* HCLK */ @@ -1641,7 +1648,6 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, 7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clk_register_clkdev(clk, "hclk", NULL); clks[TEGRA114_CLK_HCLK] = clk; /* PCLK */ @@ -1651,91 +1657,90 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clk_register_clkdev(clk, "pclk", NULL); clks[TEGRA114_CLK_PCLK] = clk; } static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S0), - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S2), - TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S3), - TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S4), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_OUT), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_IN), - TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_PWM), - TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_ADX), - TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), - TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), - TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), - TEGRA_INIT_DATA_MUX8("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), - TEGRA_INIT_DATA_MUX8("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), - TEGRA_INIT_DATA_MUX8("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), - TEGRA_INIT_DATA_MUX8("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), - TEGRA_INIT_DATA_MUX8("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), - TEGRA_INIT_DATA_MUX8("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), - TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), - TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, TEGRA114_CLK_SDMMC1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, TEGRA114_CLK_SDMMC2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, TEGRA114_CLK_SDMMC3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, TEGRA114_CLK_SDMMC4), - TEGRA_INIT_DATA_INT8("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, TEGRA114_CLK_VDE), - TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), - TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_OWR), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, TEGRA114_CLK_NOR), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_MIPI), - TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, TEGRA114_CLK_I2C1), - TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, TEGRA114_CLK_I2C2), - TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, TEGRA114_CLK_I2C3), - TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, TEGRA114_CLK_I2C4), - TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, TEGRA114_CLK_I2C5), - TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, TEGRA114_CLK_UARTA), - TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, TEGRA114_CLK_UARTB), - TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, TEGRA114_CLK_UARTC), - TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, TEGRA114_CLK_UARTD), - TEGRA_INIT_DATA_INT8("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, TEGRA114_CLK_GR3D), - TEGRA_INIT_DATA_INT8("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, TEGRA114_CLK_GR2D), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), - TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, TEGRA114_CLK_VI), - TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, TEGRA114_CLK_EPP), - TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, TEGRA114_CLK_MSENC), - TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, TEGRA114_CLK_TSEC), - TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, TEGRA114_CLK_HOST1X), - TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA114_CLK_HDMI), - TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, TEGRA114_CLK_CILAB), - TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, TEGRA114_CLK_CILCD), - TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, TEGRA114_CLK_CILE), - TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, TEGRA114_CLK_DSIALP), - TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, TEGRA114_CLK_DSIBLP), - TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TSENSOR), - TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, TEGRA114_CLK_ACTMON), - TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, TEGRA114_CLK_EXTERN1), - TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, TEGRA114_CLK_EXTERN2), - TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, TEGRA114_CLK_EXTERN3), - TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2CSLOW), - TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SE), - TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, TEGRA114_CLK_MSELECT, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_REF), - TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_SOC), - TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SOC_THERM), - TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_HOST_SRC), - TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FALCON_SRC), - TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FS_SRC), - TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_SS_SRC), - TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_DEV_SRC), - TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_D_AUDIO), - TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM0), - TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM1), - TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM2), + TEGRA_INIT_DATA_MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S0), + TEGRA_INIT_DATA_MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S1), + TEGRA_INIT_DATA_MUX("i2s2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S2), + TEGRA_INIT_DATA_MUX("i2s3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S3), + TEGRA_INIT_DATA_MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S4), + TEGRA_INIT_DATA_MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_OUT), + TEGRA_INIT_DATA_MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_IN), + TEGRA_INIT_DATA_MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_PWM), + TEGRA_INIT_DATA_MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_ADX), + TEGRA_INIT_DATA_MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), + TEGRA_INIT_DATA_MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), + TEGRA_INIT_DATA_MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), + TEGRA_INIT_DATA_MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), + TEGRA_INIT_DATA_MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), + TEGRA_INIT_DATA_MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), + TEGRA_INIT_DATA_MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), + TEGRA_INIT_DATA_MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), + TEGRA_INIT_DATA_MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), + TEGRA_INIT_DATA_MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), + TEGRA_INIT_DATA_MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), + TEGRA_INIT_DATA_MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), + TEGRA_INIT_DATA_MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, TEGRA114_CLK_SDMMC1), + TEGRA_INIT_DATA_MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, TEGRA114_CLK_SDMMC2), + TEGRA_INIT_DATA_MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, TEGRA114_CLK_SDMMC3), + TEGRA_INIT_DATA_MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, TEGRA114_CLK_SDMMC4), + TEGRA_INIT_DATA_INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, TEGRA114_CLK_VDE), + TEGRA_INIT_DATA_MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), + TEGRA_INIT_DATA_MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), + TEGRA_INIT_DATA_MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), + TEGRA_INIT_DATA_MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_OWR), + TEGRA_INIT_DATA_MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, TEGRA114_CLK_NOR), + TEGRA_INIT_DATA_MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_MIPI), + TEGRA_INIT_DATA_I2C("i2c1", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, TEGRA114_CLK_I2C1), + TEGRA_INIT_DATA_I2C("i2c2", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, TEGRA114_CLK_I2C2), + TEGRA_INIT_DATA_I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, TEGRA114_CLK_I2C3), + TEGRA_INIT_DATA_I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, TEGRA114_CLK_I2C4), + TEGRA_INIT_DATA_I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, TEGRA114_CLK_I2C5), + TEGRA_INIT_DATA_UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, TEGRA114_CLK_UARTA), + TEGRA_INIT_DATA_UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, TEGRA114_CLK_UARTB), + TEGRA_INIT_DATA_UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, TEGRA114_CLK_UARTC), + TEGRA_INIT_DATA_UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, TEGRA114_CLK_UARTD), + TEGRA_INIT_DATA_INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, TEGRA114_CLK_GR3D), + TEGRA_INIT_DATA_INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, TEGRA114_CLK_GR2D), + TEGRA_INIT_DATA_MUX("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), + TEGRA_INIT_DATA_INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, TEGRA114_CLK_VI), + TEGRA_INIT_DATA_INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, TEGRA114_CLK_EPP), + TEGRA_INIT_DATA_INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, TEGRA114_CLK_MSENC), + TEGRA_INIT_DATA_INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, TEGRA114_CLK_TSEC), + TEGRA_INIT_DATA_INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, TEGRA114_CLK_HOST1X), + TEGRA_INIT_DATA_MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA114_CLK_HDMI), + TEGRA_INIT_DATA_MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, TEGRA114_CLK_CILAB), + TEGRA_INIT_DATA_MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, TEGRA114_CLK_CILCD), + TEGRA_INIT_DATA_MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, TEGRA114_CLK_CILE), + TEGRA_INIT_DATA_MUX("dsialp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, TEGRA114_CLK_DSIALP), + TEGRA_INIT_DATA_MUX("dsiblp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, TEGRA114_CLK_DSIBLP), + TEGRA_INIT_DATA_MUX("tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TSENSOR), + TEGRA_INIT_DATA_MUX("actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, TEGRA114_CLK_ACTMON), + TEGRA_INIT_DATA_MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, TEGRA114_CLK_EXTERN1), + TEGRA_INIT_DATA_MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, TEGRA114_CLK_EXTERN2), + TEGRA_INIT_DATA_MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, TEGRA114_CLK_EXTERN3), + TEGRA_INIT_DATA_MUX("i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2CSLOW), + TEGRA_INIT_DATA_INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SE), + TEGRA_INIT_DATA_INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, TEGRA114_CLK_MSELECT, CLK_IGNORE_UNUSED), + TEGRA_INIT_DATA_MUX("dfll_ref", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_REF), + TEGRA_INIT_DATA_MUX("dfll_soc", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_SOC), + TEGRA_INIT_DATA_MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SOC_THERM), + TEGRA_INIT_DATA_XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_HOST_SRC), + TEGRA_INIT_DATA_XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FALCON_SRC), + TEGRA_INIT_DATA_XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FS_SRC), + TEGRA_INIT_DATA_XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_SS_SRC), + TEGRA_INIT_DATA_XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_DEV_SRC), + TEGRA_INIT_DATA_AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_D_AUDIO), + TEGRA_INIT_DATA_AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM0), + TEGRA_INIT_DATA_AUDIO("dam1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM1), + TEGRA_INIT_DATA_AUDIO("dam2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM2), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, TEGRA114_CLK_DISP1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, TEGRA114_CLK_DISP2), + TEGRA_INIT_DATA_NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, TEGRA114_CLK_DISP1), + TEGRA_INIT_DATA_NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, TEGRA114_CLK_DISP2), }; static __init void tegra114_periph_clk_init(void __iomem *clk_base) @@ -1755,7 +1760,6 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, clk_base, 0, 4, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "rtc-tegra"); clks[TEGRA114_CLK_RTC] = clk; /* kbc */ @@ -1768,7 +1772,6 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) /* timer */ clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0, 5, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "timer"); clks[TEGRA114_CLK_TIMER] = clk; /* kfuse */ @@ -2196,6 +2199,7 @@ static void __init tegra114_clock_init(struct device_node *np) tegra114_super_clk_init(clk_base); tegra_add_of_provider(np); + tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); tegra_clk_apply_init_table = tegra114_clock_apply_init_table; diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index a0430cd65d7c..14d25322aec5 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -212,6 +212,15 @@ void __init tegra_add_of_provider(struct device_node *np) of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } +void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) +{ + int i; + + for (i = 0; i < num; i++, dev_clks++) + clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id, + dev_clks->dev_id); +} + struct clk ** __init tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk) { diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 489dad59d1d5..f742c7dda4cc 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -573,6 +573,12 @@ struct tegra_clk { bool present; }; +struct tegra_devclk { + int dt_id; + char *dev_id; + char *con_id; +}; + void tegra_init_from_table(struct tegra_clk_init_table *tbl, struct clk *clks[], int clk_max); @@ -585,6 +591,7 @@ struct clk **tegra_clk_init(int num, int periph_banks); struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); void tegra_add_of_provider(struct device_node *np); +void tegra_register_devclks(struct tegra_devclk *dev_clks, int num); void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); -- cgit v1.2.3 From 6609dbe40e199ca8b1e99513d0e4bbc32b0d53b7 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Tue, 17 Sep 2013 15:42:24 +0300 Subject: clk: tegra: move audio clk to common file Move audio clocks and PLLA initialization to a common file so it can be used by multiple Tegra SoCs. Also a new array tegra114_clks is introduced for Tegra114 which specifies which common clocks are available on Tegra114 and what their DT IDs are. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/Makefile | 1 + drivers/clk/tegra/clk-tegra-audio.c | 215 ++++++++++++++++++++ drivers/clk/tegra/clk-tegra114.c | 390 +++++++++++++++++------------------- drivers/clk/tegra/clk.h | 4 + 4 files changed, 402 insertions(+), 208 deletions(-) create mode 100644 drivers/clk/tegra/clk-tegra-audio.c (limited to 'drivers') diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index f49fac2d193a..796ff9aa3899 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -6,6 +6,7 @@ obj-y += clk-periph-gate.o obj-y += clk-pll.o obj-y += clk-pll-out.o obj-y += clk-super.o +obj-y += clk-tegra-audio.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o diff --git a/drivers/clk/tegra/clk-tegra-audio.c b/drivers/clk/tegra/clk-tegra-audio.c new file mode 100644 index 000000000000..5c38aab2c5b8 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-audio.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "clk-id.h" + +#define AUDIO_SYNC_CLK_I2S0 0x4a0 +#define AUDIO_SYNC_CLK_I2S1 0x4a4 +#define AUDIO_SYNC_CLK_I2S2 0x4a8 +#define AUDIO_SYNC_CLK_I2S3 0x4ac +#define AUDIO_SYNC_CLK_I2S4 0x4b0 +#define AUDIO_SYNC_CLK_SPDIF 0x4b4 + +#define AUDIO_SYNC_DOUBLER 0x49c + +#define PLLA_OUT 0xb4 + +struct tegra_sync_source_initdata { + char *name; + unsigned long rate; + unsigned long max_rate; + int clk_id; +}; + +#define SYNC(_name) \ + {\ + .name = #_name,\ + .rate = 24000000,\ + .max_rate = 24000000,\ + .clk_id = tegra_clk_ ## _name,\ + } + +struct tegra_audio_clk_initdata { + char *gate_name; + char *mux_name; + u32 offset; + int gate_clk_id; + int mux_clk_id; +}; + +#define AUDIO(_name, _offset) \ + {\ + .gate_name = #_name,\ + .mux_name = #_name"_mux",\ + .offset = _offset,\ + .gate_clk_id = tegra_clk_ ## _name,\ + .mux_clk_id = tegra_clk_ ## _name ## _mux,\ + } + +struct tegra_audio2x_clk_initdata { + char *parent; + char *gate_name; + char *name_2x; + char *div_name; + int clk_id; + int clk_num; + u8 div_offset; +}; + +#define AUDIO2X(_name, _num, _offset) \ + {\ + .parent = #_name,\ + .gate_name = #_name"_2x",\ + .name_2x = #_name"_doubler",\ + .div_name = #_name"_div",\ + .clk_id = tegra_clk_ ## _name ## _2x,\ + .clk_num = _num,\ + .div_offset = _offset,\ + } + +static DEFINE_SPINLOCK(clk_doubler_lock); + +static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", + "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", +}; + +static struct tegra_sync_source_initdata sync_source_clks[] __initdata = { + SYNC(spdif_in_sync), + SYNC(i2s0_sync), + SYNC(i2s1_sync), + SYNC(i2s2_sync), + SYNC(i2s3_sync), + SYNC(i2s4_sync), + SYNC(vimclk_sync), +}; + +static struct tegra_audio_clk_initdata audio_clks[] = { + AUDIO(audio0, AUDIO_SYNC_CLK_I2S0), + AUDIO(audio1, AUDIO_SYNC_CLK_I2S1), + AUDIO(audio2, AUDIO_SYNC_CLK_I2S2), + AUDIO(audio3, AUDIO_SYNC_CLK_I2S3), + AUDIO(audio4, AUDIO_SYNC_CLK_I2S4), + AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF), +}; + +static struct tegra_audio2x_clk_initdata audio2x_clks[] = { + AUDIO2X(audio0, 113, 24), + AUDIO2X(audio1, 114, 25), + AUDIO2X(audio2, 115, 26), + AUDIO2X(audio3, 116, 27), + AUDIO2X(audio4, 117, 28), + AUDIO2X(spdif, 118, 29), +}; + +void __init tegra_audio_clk_init(void __iomem *clk_base, + void __iomem *pmc_base, struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_a_params) +{ + struct clk *clk; + struct clk **dt_clk; + int i; + + /* PLLA */ + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, + pmc_base, 0, pll_a_params, NULL); + *dt_clk = clk; + } + + /* PLLA_OUT0 */ + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", + clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", + clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, NULL); + *dt_clk = clk; + } + + for (i = 0; i < ARRAY_SIZE(sync_source_clks); i++) { + struct tegra_sync_source_initdata *data; + + data = &sync_source_clks[i]; + + dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = tegra_clk_register_sync_source(data->name, + data->rate, data->max_rate); + *dt_clk = clk; + } + + for (i = 0; i < ARRAY_SIZE(audio_clks); i++) { + struct tegra_audio_clk_initdata *data; + + data = &audio_clks[i]; + dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks); + + if (!dt_clk) + continue; + clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, + clk_base + data->offset, 0, 3, 0, + NULL); + *dt_clk = clk; + + dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = clk_register_gate(NULL, data->gate_name, data->mux_name, + 0, clk_base + data->offset, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + *dt_clk = clk; + } + + for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) { + struct tegra_audio2x_clk_initdata *data; + + data = &audio2x_clks[i]; + dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = clk_register_fixed_factor(NULL, data->name_2x, + data->parent, CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider(data->div_name, + data->name_2x, clk_base + AUDIO_SYNC_DOUBLER, + 0, 0, data->div_offset, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate(data->gate_name, + data->div_name, TEGRA_PERIPH_NO_RESET, + clk_base, CLK_SET_RATE_PARENT, data->clk_num, + periph_clk_enb_refcnt); + *dt_clk = clk; + } +} + diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 48d4381357bb..8bb9a226d05c 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -26,6 +26,7 @@ #include #include "clk.h" +#include "clk-id.h" #define RST_DFLL_DVCO 0x2F4 #define CPU_FINETRIM_SELECT 0x4d4 /* override default prop dlys */ @@ -107,16 +108,6 @@ #define PLLM_OUT 0x94 #define PLLP_OUTA 0xa4 #define PLLP_OUTB 0xa8 -#define PLLA_OUT 0xb4 - -#define AUDIO_SYNC_CLK_I2S0 0x4a0 -#define AUDIO_SYNC_CLK_I2S1 0x4a4 -#define AUDIO_SYNC_CLK_I2S2 0x4a8 -#define AUDIO_SYNC_CLK_I2S3 0x4ac -#define AUDIO_SYNC_CLK_I2S4 0x4b0 -#define AUDIO_SYNC_CLK_SPDIF 0x4b4 - -#define AUDIO_SYNC_DOUBLER 0x49c #define PMC_CLK_OUT_CNTRL 0x1a8 #define PMC_DPD_PADS_ORIDE 0x1c @@ -272,7 +263,6 @@ static DEFINE_SPINLOCK(pll_d2_lock); static DEFINE_SPINLOCK(pll_u_lock); static DEFINE_SPINLOCK(pll_div_lock); static DEFINE_SPINLOCK(pll_re_lock); -static DEFINE_SPINLOCK(clk_doubler_lock); static DEFINE_SPINLOCK(clk_out_lock); static DEFINE_SPINLOCK(sysrate_lock); @@ -963,6 +953,186 @@ static const struct clk_div_table pll_re_div_table[] = { { .val = 0, .div = 0 }, }; +static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { + [tegra_clk_rtc] = { .dt_id = TEGRA114_CLK_RTC, .present = true }, + [tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true }, + [tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true }, + [tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true }, + [tegra_clk_sdmmc2] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true }, + [tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true }, + [tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true }, + [tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true }, + [tegra_clk_sdmmc1] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc4] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true }, + [tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true }, + [tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true }, + [tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true }, + [tegra_clk_epp_8] = { .dt_id = TEGRA114_CLK_EPP, .present = true }, + [tegra_clk_gr2d_8] = { .dt_id = TEGRA114_CLK_GR2D, .present = true }, + [tegra_clk_usbd] = { .dt_id = TEGRA114_CLK_USBD, .present = true }, + [tegra_clk_isp] = { .dt_id = TEGRA114_CLK_ISP, .present = true }, + [tegra_clk_gr3d_8] = { .dt_id = TEGRA114_CLK_GR3D, .present = true }, + [tegra_clk_disp2] = { .dt_id = TEGRA114_CLK_DISP2, .present = true }, + [tegra_clk_disp1] = { .dt_id = TEGRA114_CLK_DISP1, .present = true }, + [tegra_clk_host1x_8] = { .dt_id = TEGRA114_CLK_HOST1X, .present = true }, + [tegra_clk_vcp] = { .dt_id = TEGRA114_CLK_VCP, .present = true }, + [tegra_clk_apbdma] = { .dt_id = TEGRA114_CLK_APBDMA, .present = true }, + [tegra_clk_kbc] = { .dt_id = TEGRA114_CLK_KBC, .present = true }, + [tegra_clk_kfuse] = { .dt_id = TEGRA114_CLK_KFUSE, .present = true }, + [tegra_clk_sbc1_8] = { .dt_id = TEGRA114_CLK_SBC1, .present = true }, + [tegra_clk_nor] = { .dt_id = TEGRA114_CLK_NOR, .present = true }, + [tegra_clk_sbc2_8] = { .dt_id = TEGRA114_CLK_SBC2, .present = true }, + [tegra_clk_sbc3_8] = { .dt_id = TEGRA114_CLK_SBC3, .present = true }, + [tegra_clk_i2c5] = { .dt_id = TEGRA114_CLK_I2C5, .present = true }, + [tegra_clk_dsia] = { .dt_id = TEGRA114_CLK_DSIA, .present = true }, + [tegra_clk_mipi] = { .dt_id = TEGRA114_CLK_MIPI, .present = true }, + [tegra_clk_hdmi] = { .dt_id = TEGRA114_CLK_HDMI, .present = true }, + [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true }, + [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true }, + [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true }, + [tegra_clk_mipi_cal] = { .dt_id = TEGRA114_CLK_MIPI_CAL, .present = true }, + [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true }, + [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true }, + [tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true }, + [tegra_clk_vde_8] = { .dt_id = TEGRA114_CLK_VDE, .present = true }, + [tegra_clk_bsea] = { .dt_id = TEGRA114_CLK_BSEA, .present = true }, + [tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true }, + [tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true }, + [tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true }, + [tegra_clk_sdmmc3] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true }, + [tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true }, + [tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true }, + [tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true }, + [tegra_clk_trace] = { .dt_id = TEGRA114_CLK_TRACE, .present = true }, + [tegra_clk_soc_therm] = { .dt_id = TEGRA114_CLK_SOC_THERM, .present = true }, + [tegra_clk_dtv] = { .dt_id = TEGRA114_CLK_DTV, .present = true }, + [tegra_clk_ndspeed] = { .dt_id = TEGRA114_CLK_NDSPEED, .present = true }, + [tegra_clk_i2cslow] = { .dt_id = TEGRA114_CLK_I2CSLOW, .present = true }, + [tegra_clk_dsib] = { .dt_id = TEGRA114_CLK_DSIB, .present = true }, + [tegra_clk_tsec] = { .dt_id = TEGRA114_CLK_TSEC, .present = true }, + [tegra_clk_xusb_host] = { .dt_id = TEGRA114_CLK_XUSB_HOST, .present = true }, + [tegra_clk_msenc] = { .dt_id = TEGRA114_CLK_MSENC, .present = true }, + [tegra_clk_csus] = { .dt_id = TEGRA114_CLK_CSUS, .present = true }, + [tegra_clk_mselect] = { .dt_id = TEGRA114_CLK_MSELECT, .present = true }, + [tegra_clk_tsensor] = { .dt_id = TEGRA114_CLK_TSENSOR, .present = true }, + [tegra_clk_i2s3] = { .dt_id = TEGRA114_CLK_I2S3, .present = true }, + [tegra_clk_i2s4] = { .dt_id = TEGRA114_CLK_I2S4, .present = true }, + [tegra_clk_i2c4] = { .dt_id = TEGRA114_CLK_I2C4, .present = true }, + [tegra_clk_sbc5_8] = { .dt_id = TEGRA114_CLK_SBC5, .present = true }, + [tegra_clk_sbc6_8] = { .dt_id = TEGRA114_CLK_SBC6, .present = true }, + [tegra_clk_d_audio] = { .dt_id = TEGRA114_CLK_D_AUDIO, .present = true }, + [tegra_clk_apbif] = { .dt_id = TEGRA114_CLK_APBIF, .present = true }, + [tegra_clk_dam0] = { .dt_id = TEGRA114_CLK_DAM0, .present = true }, + [tegra_clk_dam1] = { .dt_id = TEGRA114_CLK_DAM1, .present = true }, + [tegra_clk_dam2] = { .dt_id = TEGRA114_CLK_DAM2, .present = true }, + [tegra_clk_hda2codec_2x] = { .dt_id = TEGRA114_CLK_HDA2CODEC_2X, .present = true }, + [tegra_clk_audio0_2x] = { .dt_id = TEGRA114_CLK_AUDIO0_2X, .present = true }, + [tegra_clk_audio1_2x] = { .dt_id = TEGRA114_CLK_AUDIO1_2X, .present = true }, + [tegra_clk_audio2_2x] = { .dt_id = TEGRA114_CLK_AUDIO2_2X, .present = true }, + [tegra_clk_audio3_2x] = { .dt_id = TEGRA114_CLK_AUDIO3_2X, .present = true }, + [tegra_clk_audio4_2x] = { .dt_id = TEGRA114_CLK_AUDIO4_2X, .present = true }, + [tegra_clk_spdif_2x] = { .dt_id = TEGRA114_CLK_SPDIF_2X, .present = true }, + [tegra_clk_actmon] = { .dt_id = TEGRA114_CLK_ACTMON, .present = true }, + [tegra_clk_extern1] = { .dt_id = TEGRA114_CLK_EXTERN1, .present = true }, + [tegra_clk_extern2] = { .dt_id = TEGRA114_CLK_EXTERN2, .present = true }, + [tegra_clk_extern3] = { .dt_id = TEGRA114_CLK_EXTERN3, .present = true }, + [tegra_clk_hda] = { .dt_id = TEGRA114_CLK_HDA, .present = true }, + [tegra_clk_se] = { .dt_id = TEGRA114_CLK_SE, .present = true }, + [tegra_clk_hda2hdmi] = { .dt_id = TEGRA114_CLK_HDA2HDMI, .present = true }, + [tegra_clk_cilab] = { .dt_id = TEGRA114_CLK_CILAB, .present = true }, + [tegra_clk_cilcd] = { .dt_id = TEGRA114_CLK_CILCD, .present = true }, + [tegra_clk_cile] = { .dt_id = TEGRA114_CLK_CILE, .present = true }, + [tegra_clk_dsialp] = { .dt_id = TEGRA114_CLK_DSIALP, .present = true }, + [tegra_clk_dsiblp] = { .dt_id = TEGRA114_CLK_DSIBLP, .present = true }, + [tegra_clk_dds] = { .dt_id = TEGRA114_CLK_DDS, .present = true }, + [tegra_clk_dp2] = { .dt_id = TEGRA114_CLK_DP2, .present = true }, + [tegra_clk_amx] = { .dt_id = TEGRA114_CLK_AMX, .present = true }, + [tegra_clk_adx] = { .dt_id = TEGRA114_CLK_ADX, .present = true }, + [tegra_clk_xusb_ss] = { .dt_id = TEGRA114_CLK_XUSB_SS, .present = true }, + [tegra_clk_uartb] = { .dt_id = TEGRA114_CLK_UARTB, .present = true }, + [tegra_clk_vfir] = { .dt_id = TEGRA114_CLK_VFIR, .present = true }, + [tegra_clk_spdif_in] = { .dt_id = TEGRA114_CLK_SPDIF_IN, .present = true }, + [tegra_clk_spdif_out] = { .dt_id = TEGRA114_CLK_SPDIF_OUT, .present = true }, + [tegra_clk_vi_8] = { .dt_id = TEGRA114_CLK_VI, .present = true }, + [tegra_clk_vi_sensor_8] = { .dt_id = TEGRA114_CLK_VI_SENSOR, .present = true }, + [tegra_clk_fuse] = { .dt_id = TEGRA114_CLK_FUSE, .present = true }, + [tegra_clk_fuse_burn] = { .dt_id = TEGRA114_CLK_FUSE_BURN, .present = true }, + [tegra_clk_clk_32k] = { .dt_id = TEGRA114_CLK_CLK_32K, .present = true }, + [tegra_clk_clk_m] = { .dt_id = TEGRA114_CLK_CLK_M, .present = true }, + [tegra_clk_clk_m_div2] = { .dt_id = TEGRA114_CLK_CLK_M_DIV2, .present = true }, + [tegra_clk_clk_m_div4] = { .dt_id = TEGRA114_CLK_CLK_M_DIV4, .present = true }, + [tegra_clk_pll_ref] = { .dt_id = TEGRA114_CLK_PLL_REF, .present = true }, + [tegra_clk_pll_c] = { .dt_id = TEGRA114_CLK_PLL_C, .present = true }, + [tegra_clk_pll_c_out1] = { .dt_id = TEGRA114_CLK_PLL_C_OUT1, .present = true }, + [tegra_clk_pll_c2] = { .dt_id = TEGRA114_CLK_PLL_C2, .present = true }, + [tegra_clk_pll_c3] = { .dt_id = TEGRA114_CLK_PLL_C3, .present = true }, + [tegra_clk_pll_m] = { .dt_id = TEGRA114_CLK_PLL_M, .present = true }, + [tegra_clk_pll_m_out1] = { .dt_id = TEGRA114_CLK_PLL_M_OUT1, .present = true }, + [tegra_clk_pll_p] = { .dt_id = TEGRA114_CLK_PLL_P, .present = true }, + [tegra_clk_pll_p_out1] = { .dt_id = TEGRA114_CLK_PLL_P_OUT1, .present = true }, + [tegra_clk_pll_p_out2_int] = { .dt_id = TEGRA114_CLK_PLL_P_OUT2, .present = true }, + [tegra_clk_pll_p_out3] = { .dt_id = TEGRA114_CLK_PLL_P_OUT3, .present = true }, + [tegra_clk_pll_p_out4] = { .dt_id = TEGRA114_CLK_PLL_P_OUT4, .present = true }, + [tegra_clk_pll_a] = { .dt_id = TEGRA114_CLK_PLL_A, .present = true }, + [tegra_clk_pll_a_out0] = { .dt_id = TEGRA114_CLK_PLL_A_OUT0, .present = true }, + [tegra_clk_pll_d] = { .dt_id = TEGRA114_CLK_PLL_D, .present = true }, + [tegra_clk_pll_d_out0] = { .dt_id = TEGRA114_CLK_PLL_D_OUT0, .present = true }, + [tegra_clk_pll_d2] = { .dt_id = TEGRA114_CLK_PLL_D2, .present = true }, + [tegra_clk_pll_d2_out0] = { .dt_id = TEGRA114_CLK_PLL_D2_OUT0, .present = true }, + [tegra_clk_pll_u] = { .dt_id = TEGRA114_CLK_PLL_U, .present = true }, + [tegra_clk_pll_u_480m] = { .dt_id = TEGRA114_CLK_PLL_U_480M, .present = true }, + [tegra_clk_pll_u_60m] = { .dt_id = TEGRA114_CLK_PLL_U_60M, .present = true }, + [tegra_clk_pll_u_48m] = { .dt_id = TEGRA114_CLK_PLL_U_48M, .present = true }, + [tegra_clk_pll_u_12m] = { .dt_id = TEGRA114_CLK_PLL_U_12M, .present = true }, + [tegra_clk_pll_x] = { .dt_id = TEGRA114_CLK_PLL_X, .present = true }, + [tegra_clk_pll_x_out0] = { .dt_id = TEGRA114_CLK_PLL_X_OUT0, .present = true }, + [tegra_clk_pll_re_vco] = { .dt_id = TEGRA114_CLK_PLL_RE_VCO, .present = true }, + [tegra_clk_pll_re_out] = { .dt_id = TEGRA114_CLK_PLL_RE_OUT, .present = true }, + [tegra_clk_pll_e_out0] = { .dt_id = TEGRA114_CLK_PLL_E_OUT0, .present = true }, + [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA114_CLK_SPDIF_IN_SYNC, .present = true }, + [tegra_clk_i2s0_sync] = { .dt_id = TEGRA114_CLK_I2S0_SYNC, .present = true }, + [tegra_clk_i2s1_sync] = { .dt_id = TEGRA114_CLK_I2S1_SYNC, .present = true }, + [tegra_clk_i2s2_sync] = { .dt_id = TEGRA114_CLK_I2S2_SYNC, .present = true }, + [tegra_clk_i2s3_sync] = { .dt_id = TEGRA114_CLK_I2S3_SYNC, .present = true }, + [tegra_clk_i2s4_sync] = { .dt_id = TEGRA114_CLK_I2S4_SYNC, .present = true }, + [tegra_clk_vimclk_sync] = { .dt_id = TEGRA114_CLK_VIMCLK_SYNC, .present = true }, + [tegra_clk_audio0] = { .dt_id = TEGRA114_CLK_AUDIO0, .present = true }, + [tegra_clk_audio1] = { .dt_id = TEGRA114_CLK_AUDIO1, .present = true }, + [tegra_clk_audio2] = { .dt_id = TEGRA114_CLK_AUDIO2, .present = true }, + [tegra_clk_audio3] = { .dt_id = TEGRA114_CLK_AUDIO3, .present = true }, + [tegra_clk_audio4] = { .dt_id = TEGRA114_CLK_AUDIO4, .present = true }, + [tegra_clk_spdif] = { .dt_id = TEGRA114_CLK_SPDIF, .present = true }, + [tegra_clk_clk_out_1] = { .dt_id = TEGRA114_CLK_CLK_OUT_1, .present = true }, + [tegra_clk_clk_out_2] = { .dt_id = TEGRA114_CLK_CLK_OUT_2, .present = true }, + [tegra_clk_clk_out_3] = { .dt_id = TEGRA114_CLK_CLK_OUT_3, .present = true }, + [tegra_clk_blink] = { .dt_id = TEGRA114_CLK_BLINK, .present = true }, + [tegra_clk_xusb_host_src] = { .dt_id = TEGRA114_CLK_XUSB_HOST_SRC, .present = true }, + [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA114_CLK_XUSB_FALCON_SRC, .present = true }, + [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA114_CLK_XUSB_FS_SRC, .present = true }, + [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA114_CLK_XUSB_SS_SRC, .present = true }, + [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA114_CLK_XUSB_DEV_SRC, .present = true }, + [tegra_clk_xusb_dev] = { .dt_id = TEGRA114_CLK_XUSB_DEV, .present = true }, + [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA114_CLK_XUSB_HS_SRC, .present = true }, + [tegra_clk_sclk] = { .dt_id = TEGRA114_CLK_SCLK, .present = true }, + [tegra_clk_hclk] = { .dt_id = TEGRA114_CLK_HCLK, .present = true }, + [tegra_clk_pclk] = { .dt_id = TEGRA114_CLK_PCLK, .present = true }, + [tegra_clk_cclk_g] = { .dt_id = TEGRA114_CLK_CCLK_G, .present = true }, + [tegra_clk_cclk_lp] = { .dt_id = TEGRA114_CLK_CCLK_LP, .present = true }, + [tegra_clk_dfll_ref] = { .dt_id = TEGRA114_CLK_DFLL_REF, .present = true }, + [tegra_clk_dfll_soc] = { .dt_id = TEGRA114_CLK_DFLL_SOC, .present = true }, + [tegra_clk_audio0_mux] = { .dt_id = TEGRA114_CLK_AUDIO0_MUX, .present = true }, + [tegra_clk_audio1_mux] = { .dt_id = TEGRA114_CLK_AUDIO1_MUX, .present = true }, + [tegra_clk_audio2_mux] = { .dt_id = TEGRA114_CLK_AUDIO2_MUX, .present = true }, + [tegra_clk_audio3_mux] = { .dt_id = TEGRA114_CLK_AUDIO3_MUX, .present = true }, + [tegra_clk_audio4_mux] = { .dt_id = TEGRA114_CLK_AUDIO4_MUX, .present = true }, + [tegra_clk_spdif_mux] = { .dt_id = TEGRA114_CLK_SPDIF_MUX, .present = true }, + [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_1_MUX, .present = true }, + [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_2_MUX, .present = true }, + [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_3_MUX, .present = true }, + [tegra_clk_dsia_mux] = { .dt_id = TEGRA114_CLK_DSIA_MUX, .present = true }, + [tegra_clk_dsib_mux] = { .dt_id = TEGRA114_CLK_DSIB_MUX, .present = true }, +}; + static struct tegra_devclk devclks[] __initdata = { { .con_id = "clk_m", .dt_id = TEGRA114_CLK_CLK_M }, { .con_id = "pll_ref", .dt_id = TEGRA114_CLK_PLL_REF }, @@ -1324,20 +1494,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_SET_RATE_PARENT, 1, 2); clks[TEGRA114_CLK_PLL_D2_OUT0] = clk; - /* PLLA */ - clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0, - &pll_a_params, NULL); - clks[TEGRA114_CLK_PLL_A] = clk; - - /* PLLA_OUT0 */ - clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", - clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, - 8, 8, 1, NULL); - clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", - clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | - CLK_SET_RATE_PARENT, 0, NULL); - clks[TEGRA114_CLK_PLL_A_OUT0] = clk; - /* PLLRE */ clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); @@ -1354,10 +1510,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_E_OUT0] = clk; } -static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", - "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", -}; - static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", "clk_m_div4", "extern1", }; @@ -1370,184 +1522,6 @@ static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", "clk_m_div4", "extern3", }; -static void __init tegra114_audio_clk_init(void __iomem *clk_base) -{ - struct clk *clk; - - /* spdif_in_sync */ - clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000, - 24000000); - clks[TEGRA114_CLK_SPDIF_IN_SYNC] = clk; - - /* i2s0_sync */ - clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000); - clks[TEGRA114_CLK_I2S0_SYNC] = clk; - - /* i2s1_sync */ - clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000); - clks[TEGRA114_CLK_I2S1_SYNC] = clk; - - /* i2s2_sync */ - clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000); - clks[TEGRA114_CLK_I2S2_SYNC] = clk; - - /* i2s3_sync */ - clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000); - clks[TEGRA114_CLK_I2S3_SYNC] = clk; - - /* i2s4_sync */ - clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000); - clks[TEGRA114_CLK_I2S4_SYNC] = clk; - - /* vimclk_sync */ - clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000); - clks[TEGRA114_CLK_VIMCLK_SYNC] = clk; - - /* audio0 */ - clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, - NULL); - clks[TEGRA114_CLK_AUDIO0_MUX] = clk; - clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S0, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clks[TEGRA114_CLK_AUDIO0] = clk; - - /* audio1 */ - clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, - NULL); - clks[TEGRA114_CLK_AUDIO1_MUX] = clk; - clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S1, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clks[TEGRA114_CLK_AUDIO1] = clk; - - /* audio2 */ - clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, - NULL); - clks[TEGRA114_CLK_AUDIO2_MUX] = clk; - clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S2, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clks[TEGRA114_CLK_AUDIO2] = clk; - - /* audio3 */ - clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, - NULL); - clks[TEGRA114_CLK_AUDIO3_MUX] = clk; - clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S3, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clks[TEGRA114_CLK_AUDIO3] = clk; - - /* audio4 */ - clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, - NULL); - clks[TEGRA114_CLK_AUDIO4_MUX] = clk; - clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S4, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clks[TEGRA114_CLK_AUDIO4] = clk; - - /* spdif */ - clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, - NULL); - clks[TEGRA114_CLK_SPDIF_MUX] = clk; - clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, - clk_base + AUDIO_SYNC_CLK_SPDIF, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clks[TEGRA114_CLK_SPDIF] = clk; - - /* audio0_2x */ - clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio0_div", "audio0_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1, - 0, &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 113, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_AUDIO0_2X] = clk; - - /* audio1_2x */ - clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio1_div", "audio1_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1, - 0, &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 114, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_AUDIO1_2X] = clk; - - /* audio2_2x */ - clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio2_div", "audio2_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1, - 0, &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 115, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_AUDIO2_2X] = clk; - - /* audio3_2x */ - clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio3_div", "audio3_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1, - 0, &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 116, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_AUDIO3_2X] = clk; - - /* audio4_2x */ - clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio4_div", "audio4_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1, - 0, &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 117, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_AUDIO4_2X] = clk; - - /* spdif_2x */ - clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("spdif_div", "spdif_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1, - 0, &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 118, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_SPDIF_2X] = clk; -} - static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) { struct clk *clk; @@ -2194,7 +2168,7 @@ static void __init tegra114_clock_init(struct device_node *np) tegra114_fixed_clk_init(clk_base); tegra114_pll_init(clk_base, pmc_base); tegra114_periph_clk_init(clk_base); - tegra114_audio_clk_init(clk_base); + tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); tegra114_pmc_clk_init(pmc_base); tegra114_super_clk_init(clk_base); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index f742c7dda4cc..3306e41e6270 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -593,6 +593,10 @@ struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); void tegra_add_of_provider(struct device_node *np); void tegra_register_devclks(struct tegra_devclk *dev_clks, int num); +void tegra_audio_clk_init(void __iomem *clk_base, + void __iomem *pmc_base, struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_params); + void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); void tegra114_clock_tune_cpu_trimmers_init(void); -- cgit v1.2.3 From 76ebc134d45d7e6e1dc29fdcef4e539c5bc76eb8 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Wed, 4 Sep 2013 17:04:19 +0300 Subject: clk: tegra: move periph clocks to common file Introduce a new file for peripheral clocks common between several Tegra SoCs and move Tegra114 to this new infrastructure. Also PLLP and the PLLP_OUT clocks will be initialized here. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/Makefile | 2 +- drivers/clk/tegra/clk-tegra-periph.c | 596 +++++++++++++++++++++++++++++++++++ drivers/clk/tegra/clk-tegra114.c | 591 +--------------------------------- drivers/clk/tegra/clk-tegra20.c | 4 +- drivers/clk/tegra/clk-tegra30.c | 4 +- drivers/clk/tegra/clk.h | 11 +- 6 files changed, 627 insertions(+), 581 deletions(-) create mode 100644 drivers/clk/tegra/clk-tegra-periph.c (limited to 'drivers') diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 796ff9aa3899..304ea5df63eb 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -7,7 +7,7 @@ obj-y += clk-pll.o obj-y += clk-pll-out.o obj-y += clk-super.o obj-y += clk-tegra-audio.o - +obj-y += clk-tegra-periph.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c new file mode 100644 index 000000000000..9b04139f331d --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "clk-id.h" + +#define CLK_SOURCE_I2S0 0x1d8 +#define CLK_SOURCE_I2S1 0x100 +#define CLK_SOURCE_I2S2 0x104 +#define CLK_SOURCE_NDFLASH 0x160 +#define CLK_SOURCE_I2S3 0x3bc +#define CLK_SOURCE_I2S4 0x3c0 +#define CLK_SOURCE_SPDIF_OUT 0x108 +#define CLK_SOURCE_SPDIF_IN 0x10c +#define CLK_SOURCE_PWM 0x110 +#define CLK_SOURCE_ADX 0x638 +#define CLK_SOURCE_AMX 0x63c +#define CLK_SOURCE_HDA 0x428 +#define CLK_SOURCE_HDA2CODEC_2X 0x3e4 +#define CLK_SOURCE_SBC1 0x134 +#define CLK_SOURCE_SBC2 0x118 +#define CLK_SOURCE_SBC3 0x11c +#define CLK_SOURCE_SBC4 0x1b4 +#define CLK_SOURCE_SBC5 0x3c8 +#define CLK_SOURCE_SBC6 0x3cc +#define CLK_SOURCE_SATA_OOB 0x420 +#define CLK_SOURCE_SATA 0x424 +#define CLK_SOURCE_NDSPEED 0x3f8 +#define CLK_SOURCE_VFIR 0x168 +#define CLK_SOURCE_SDMMC1 0x150 +#define CLK_SOURCE_SDMMC2 0x154 +#define CLK_SOURCE_SDMMC3 0x1bc +#define CLK_SOURCE_SDMMC4 0x164 +#define CLK_SOURCE_CVE 0x140 +#define CLK_SOURCE_TVO 0x188 +#define CLK_SOURCE_TVDAC 0x194 +#define CLK_SOURCE_VDE 0x1c8 +#define CLK_SOURCE_CSITE 0x1d4 +#define CLK_SOURCE_LA 0x1f8 +#define CLK_SOURCE_TRACE 0x634 +#define CLK_SOURCE_OWR 0x1cc +#define CLK_SOURCE_NOR 0x1d0 +#define CLK_SOURCE_MIPI 0x174 +#define CLK_SOURCE_I2C1 0x124 +#define CLK_SOURCE_I2C2 0x198 +#define CLK_SOURCE_I2C3 0x1b8 +#define CLK_SOURCE_I2C4 0x3c4 +#define CLK_SOURCE_I2C5 0x128 +#define CLK_SOURCE_UARTA 0x178 +#define CLK_SOURCE_UARTB 0x17c +#define CLK_SOURCE_UARTC 0x1a0 +#define CLK_SOURCE_UARTD 0x1c0 +#define CLK_SOURCE_UARTE 0x1c4 +#define CLK_SOURCE_3D 0x158 +#define CLK_SOURCE_2D 0x15c +#define CLK_SOURCE_MPE 0x170 +#define CLK_SOURCE_VI_SENSOR 0x1a8 +#define CLK_SOURCE_VI 0x148 +#define CLK_SOURCE_EPP 0x16c +#define CLK_SOURCE_MSENC 0x1f0 +#define CLK_SOURCE_TSEC 0x1f4 +#define CLK_SOURCE_HOST1X 0x180 +#define CLK_SOURCE_HDMI 0x18c +#define CLK_SOURCE_DISP1 0x138 +#define CLK_SOURCE_DISP2 0x13c +#define CLK_SOURCE_CILAB 0x614 +#define CLK_SOURCE_CILCD 0x618 +#define CLK_SOURCE_CILE 0x61c +#define CLK_SOURCE_DSIALP 0x620 +#define CLK_SOURCE_DSIBLP 0x624 +#define CLK_SOURCE_TSENSOR 0x3b8 +#define CLK_SOURCE_D_AUDIO 0x3d0 +#define CLK_SOURCE_DAM0 0x3d8 +#define CLK_SOURCE_DAM1 0x3dc +#define CLK_SOURCE_DAM2 0x3e0 +#define CLK_SOURCE_ACTMON 0x3e8 +#define CLK_SOURCE_EXTERN1 0x3ec +#define CLK_SOURCE_EXTERN2 0x3f0 +#define CLK_SOURCE_EXTERN3 0x3f4 +#define CLK_SOURCE_I2CSLOW 0x3fc +#define CLK_SOURCE_SE 0x42c +#define CLK_SOURCE_MSELECT 0x3b4 +#define CLK_SOURCE_DFLL_REF 0x62c +#define CLK_SOURCE_DFLL_SOC 0x630 +#define CLK_SOURCE_SOC_THERM 0x644 +#define CLK_SOURCE_XUSB_HOST_SRC 0x600 +#define CLK_SOURCE_XUSB_FALCON_SRC 0x604 +#define CLK_SOURCE_XUSB_FS_SRC 0x608 +#define CLK_SOURCE_XUSB_SS_SRC 0x610 +#define CLK_SOURCE_XUSB_DEV_SRC 0x60c + +#define MASK(x) (BIT(x) - 1) + +#define MUX(_name, _parents, _offset, \ + _clk_num, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ + _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) + +#define MUX_FLAGS(_name, _parents, _offset,\ + _clk_num, _gate_flags, _clk_id, flags)\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ + _clk_num, _gate_flags, _clk_id, _parents##_idx, flags) + +#define MUX8(_name, _parents, _offset, \ + _clk_num, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ + _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) + +#define INT(_name, _parents, _offset, \ + _clk_num, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ + _clk_id, _parents##_idx, 0) + +#define INT_FLAGS(_name, _parents, _offset,\ + _clk_num, _gate_flags, _clk_id, flags)\ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ + _clk_id, _parents##_idx, flags) + +#define INT8(_name, _parents, _offset,\ + _clk_num, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ + _clk_id, _parents##_idx, 0) + +#define UART(_name, _parents, _offset,\ + _clk_num, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\ + _parents##_idx, 0) + +#define I2C(_name, _parents, _offset,\ + _clk_num, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ + _clk_num, 0, _clk_id, _parents##_idx, 0) + +#define XUSB(_name, _parents, _offset, \ + _clk_num, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \ + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ + _clk_id, _parents##_idx, 0) + +#define AUDIO(_name, _offset, _clk_num,\ + _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk, \ + _offset, 16, 0xE01F, 0, 0, 8, 1, \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags, \ + _clk_id, mux_d_audio_clk_idx, 0) + +#define NODIV(_name, _parents, _offset, \ + _mux_shift, _mux_mask, _clk_num, \ + _gate_flags, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\ + _clk_num, (_gate_flags) | TEGRA_PERIPH_NO_DIV,\ + _clk_id, _parents##_idx, 0) + +#define GATE(_name, _parent_name, \ + _clk_num, _gate_flags, _clk_id, _flags) \ + { \ + .name = _name, \ + .clk_id = _clk_id, \ + .p.parent_name = _parent_name, \ + .periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 0, 0, 0, \ + _clk_num, _gate_flags, 0), \ + .flags = _flags \ + } + +#define PLLP_BASE 0xa0 +#define PLLP_MISC 0xac +#define PLLP_OUTA 0xa4 +#define PLLP_OUTB 0xa8 + +#define PLL_BASE_LOCK BIT(27) +#define PLL_MISC_LOCK_ENABLE 18 + +static DEFINE_SPINLOCK(PLLP_OUTA_lock); +static DEFINE_SPINLOCK(PLLP_OUTB_lock); + +#define MUX_I2S_SPDIF(_id) \ +static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ + #_id, "pll_p",\ + "clk_m"}; +MUX_I2S_SPDIF(audio0) +MUX_I2S_SPDIF(audio1) +MUX_I2S_SPDIF(audio2) +MUX_I2S_SPDIF(audio3) +MUX_I2S_SPDIF(audio4) +MUX_I2S_SPDIF(audio) + +#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL +#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL +#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL +#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL +#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL +#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL + +static const char *mux_pllp_pllc_pllm_clkm[] = { + "pll_p", "pll_c", "pll_m", "clk_m" +}; +#define mux_pllp_pllc_pllm_clkm_idx NULL + +static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" }; +#define mux_pllp_pllc_pllm_idx NULL + +static const char *mux_pllp_pllc_clk32_clkm[] = { + "pll_p", "pll_c", "clk_32k", "clk_m" +}; +#define mux_pllp_pllc_clk32_clkm_idx NULL + +static const char *mux_plla_pllc_pllp_clkm[] = { + "pll_a_out0", "pll_c", "pll_p", "clk_m" +}; +#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx + +static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = { + "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m" +}; +static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = { + [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, +}; + +static const char *mux_pllp_clkm[] = { + "pll_p", "clk_m" +}; +static u32 mux_pllp_clkm_idx[] = { + [0] = 0, [1] = 3, +}; + +static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = { + "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0" +}; +#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx + +static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = { + "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c", + "pll_d2_out0", "clk_m" +}; +#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL + +static const char *mux_pllm_pllc_pllp_plla[] = { + "pll_m", "pll_c", "pll_p", "pll_a_out0" +}; +#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx + +static const char *mux_pllp_pllc_clkm[] = { + "pll_p", "pll_c", "pll_m" +}; +static u32 mux_pllp_pllc_clkm_idx[] = { + [0] = 0, [1] = 1, [2] = 3, +}; + +static const char *mux_pllp_pllc_clkm_clk32[] = { + "pll_p", "pll_c", "clk_m", "clk_32k" +}; +#define mux_pllp_pllc_clkm_clk32_idx NULL + +static const char *mux_plla_clk32_pllp_clkm_plle[] = { + "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0" +}; +#define mux_plla_clk32_pllp_clkm_plle_idx NULL + +static const char *mux_clkm_pllp_pllc_pllre[] = { + "clk_m", "pll_p", "pll_c", "pll_re_out" +}; +static u32 mux_clkm_pllp_pllc_pllre_idx[] = { + [0] = 0, [1] = 1, [2] = 3, [3] = 5, +}; + +static const char *mux_clkm_48M_pllp_480M[] = { + "clk_m", "pll_u_48M", "pll_p", "pll_u_480M" +}; +#define mux_clkm_48M_pllp_480M_idx NULL + +static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = { + "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref" +}; +static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = { + [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7, +}; + +static const char *mux_d_audio_clk[] = { + "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync", + "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", +}; +static u32 mux_d_audio_clk_idx[] = { + [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001, + [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007, +}; + +static const char *mux_pllp_plld_pllc_clkm[] = { + "pll_p", "pll_d_out0", "pll_c", "clk_m" +}; +#define mux_pllp_plld_pllc_clkm_idx NULL + +static struct tegra_periph_init_data periph_clks[] = { + AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio), + AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0), + AUDIO("dam1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, tegra_clk_dam1), + AUDIO("dam2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, tegra_clk_dam2), + I2C("i2c1", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, tegra_clk_i2c1), + I2C("i2c2", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, tegra_clk_i2c2), + I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3), + I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4), + I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5), + INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde), + INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi), + INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp), + INT("host1x", mux_pllm_pllc_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x), + INT("mpe", mux_pllm_pllc_pllp_plla, CLK_SOURCE_MPE, 60, 0, tegra_clk_mpe), + INT("2d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d), + INT("3d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d), + INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8), + INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8), + INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8), + INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc), + INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec), + INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8), + INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se), + INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8), + INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8), + INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED), + MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0), + MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1), + MUX("i2s2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, tegra_clk_i2s2), + MUX("i2s3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, tegra_clk_i2s3), + MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4), + MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out), + MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in), + MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm), + MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx), + MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx), + MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda), + MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x), + MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir), + MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1), + MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2), + MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3), + MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4), + MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la), + MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace), + MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr), + MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor), + MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi), + MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor), + MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab), + MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd), + MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile), + MUX("dsialp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, tegra_clk_dsialp), + MUX("dsiblp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, tegra_clk_dsiblp), + MUX("tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, tegra_clk_tsensor), + MUX("actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, tegra_clk_actmon), + MUX("dfll_ref", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_ref), + MUX("dfll_soc", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_soc), + MUX("i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, tegra_clk_i2cslow), + MUX("sbc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1), + MUX("sbc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2), + MUX("sbc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3), + MUX("sbc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4), + MUX("sbc5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5), + MUX("sbc6", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6), + MUX("cve", mux_pllp_plld_pllc_clkm, CLK_SOURCE_CVE, 49, 0, tegra_clk_cve), + MUX("tvo", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVO, 49, 0, tegra_clk_tvo), + MUX("tvdac", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVDAC, 53, 0, tegra_clk_tvdac), + MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash), + MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed), + MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob), + MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata), + MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8), + MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8), + MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8), + MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8), + MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8), + MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8), + MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8), + MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8), + MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi), + MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1), + MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2), + MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3), + MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm), + MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8), + MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED), + NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1), + NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2), + UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta), + UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), + UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), + UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd), + UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte), + XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src), + XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), + XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), + XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src), + XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src), +}; + +static struct tegra_periph_init_data gate_clks[] = { + GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0), + GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0), + GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), + GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), + GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), + GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), + GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), + GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0), + GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0), + GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0), + GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0), + GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0), + GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0), + GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0), + GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0), + GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0), + GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0), + GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0), + GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0), + GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0), + GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0), + GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0), + GATE("dtv", "clk_m", 79, TEGRA_PERIPH_ON_APB, tegra_clk_dtv, 0), + GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0), + GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0), + GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0), + GATE("dsia", "dsia_mux", 48, 0, tegra_clk_dsia, 0), + GATE("dsib", "dsib_mux", 82, 0, tegra_clk_dsib, 0), + GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED), + GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0), +}; + +struct pll_out_data { + char *div_name; + char *pll_out_name; + u32 offset; + int clk_id; + u8 div_shift; + u8 div_flags; + u8 rst_shift; + spinlock_t *lock; +}; + +#define PLL_OUT(_num, _offset, _div_shift, _div_flags, _rst_shift, _id) \ + {\ + .div_name = "pll_p_out" #_num "_div",\ + .pll_out_name = "pll_p_out" #_num,\ + .offset = _offset,\ + .div_shift = _div_shift,\ + .div_flags = _div_flags | TEGRA_DIVIDER_FIXED |\ + TEGRA_DIVIDER_ROUND_UP,\ + .rst_shift = _rst_shift,\ + .clk_id = tegra_clk_ ## _id,\ + .lock = &_offset ##_lock,\ + } + +static struct pll_out_data pllp_out_clks[] = { + PLL_OUT(1, PLLP_OUTA, 8, 0, 0, pll_p_out1), + PLL_OUT(2, PLLP_OUTA, 24, 0, 16, pll_p_out2), + PLL_OUT(2, PLLP_OUTA, 24, TEGRA_DIVIDER_INT, 16, pll_p_out2_int), + PLL_OUT(3, PLLP_OUTB, 8, 0, 0, pll_p_out3), + PLL_OUT(4, PLLP_OUTB, 24, 0, 16, pll_p_out4), +}; + +static void __init periph_clk_init(void __iomem *clk_base, + struct tegra_clk *tegra_clks) +{ + int i; + struct clk *clk; + struct clk **dt_clk; + + for (i = 0; i < ARRAY_SIZE(periph_clks); i++) { + struct tegra_clk_periph_regs *bank; + struct tegra_periph_init_data *data; + + data = periph_clks + i; + + dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); + if (!dt_clk) + continue; + + bank = get_reg_bank(data->periph.gate.clk_num); + if (!bank) + continue; + + data->periph.gate.regs = bank; + clk = tegra_clk_register_periph(data->name, + data->p.parent_names, data->num_parents, + &data->periph, clk_base, data->offset, + data->flags); + *dt_clk = clk; + } +} + +static void __init gate_clk_init(void __iomem *clk_base, + struct tegra_clk *tegra_clks) +{ + int i; + struct clk *clk; + struct clk **dt_clk; + + for (i = 0; i < ARRAY_SIZE(gate_clks); i++) { + struct tegra_periph_init_data *data; + + data = gate_clks + i; + + dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = tegra_clk_register_periph_gate(data->name, + data->p.parent_name, data->periph.gate.flags, + clk_base, data->flags, + data->periph.gate.clk_num, + periph_clk_enb_refcnt); + *dt_clk = clk; + } +} + +static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base, + struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_params) +{ + struct clk *clk; + struct clk **dt_clk; + int i; + + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p, tegra_clks); + if (dt_clk) { + /* PLLP */ + clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, + pmc_base, 0, pll_params, NULL); + clk_register_clkdev(clk, "pll_p", NULL); + *dt_clk = clk; + } + + for (i = 0; i < ARRAY_SIZE(pllp_out_clks); i++) { + struct pll_out_data *data; + + data = pllp_out_clks + i; + + dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = tegra_clk_register_divider(data->div_name, "pll_p", + clk_base + data->offset, 0, data->div_flags, + data->div_shift, 8, 1, data->lock); + clk = tegra_clk_register_pll_out(data->pll_out_name, + data->div_name, clk_base + data->offset, + data->rst_shift + 1, data->rst_shift, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + data->lock); + *dt_clk = clk; + } +} + +void __init tegra_periph_clk_init(void __iomem *clk_base, + void __iomem *pmc_base, struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_params) +{ + init_pllp(clk_base, pmc_base, tegra_clks, pll_params); + periph_clk_init(clk_base, tegra_clks); + gate_clk_init(clk_base, tegra_clks); +} diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 8bb9a226d05c..07098597db53 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -106,8 +106,6 @@ #define PLLE_AUX 0x48c #define PLLC_OUT 0x84 #define PLLM_OUT 0x94 -#define PLLP_OUTA 0xa4 -#define PLLP_OUTB 0xa8 #define PMC_CLK_OUT_CNTRL 0x1a8 #define PMC_DPD_PADS_ORIDE 0x1c @@ -153,91 +151,8 @@ #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) -#define CLK_SOURCE_I2S0 0x1d8 -#define CLK_SOURCE_I2S1 0x100 -#define CLK_SOURCE_I2S2 0x104 -#define CLK_SOURCE_NDFLASH 0x160 -#define CLK_SOURCE_I2S3 0x3bc -#define CLK_SOURCE_I2S4 0x3c0 -#define CLK_SOURCE_SPDIF_OUT 0x108 -#define CLK_SOURCE_SPDIF_IN 0x10c -#define CLK_SOURCE_PWM 0x110 -#define CLK_SOURCE_ADX 0x638 -#define CLK_SOURCE_AMX 0x63c -#define CLK_SOURCE_HDA 0x428 -#define CLK_SOURCE_HDA2CODEC_2X 0x3e4 -#define CLK_SOURCE_SBC1 0x134 -#define CLK_SOURCE_SBC2 0x118 -#define CLK_SOURCE_SBC3 0x11c -#define CLK_SOURCE_SBC4 0x1b4 -#define CLK_SOURCE_SBC5 0x3c8 -#define CLK_SOURCE_SBC6 0x3cc -#define CLK_SOURCE_SATA_OOB 0x420 -#define CLK_SOURCE_SATA 0x424 -#define CLK_SOURCE_NDSPEED 0x3f8 -#define CLK_SOURCE_VFIR 0x168 -#define CLK_SOURCE_SDMMC1 0x150 -#define CLK_SOURCE_SDMMC2 0x154 -#define CLK_SOURCE_SDMMC3 0x1bc -#define CLK_SOURCE_SDMMC4 0x164 -#define CLK_SOURCE_VDE 0x1c8 #define CLK_SOURCE_CSITE 0x1d4 -#define CLK_SOURCE_LA 0x1f8 -#define CLK_SOURCE_TRACE 0x634 -#define CLK_SOURCE_OWR 0x1cc -#define CLK_SOURCE_NOR 0x1d0 -#define CLK_SOURCE_MIPI 0x174 -#define CLK_SOURCE_I2C1 0x124 -#define CLK_SOURCE_I2C2 0x198 -#define CLK_SOURCE_I2C3 0x1b8 -#define CLK_SOURCE_I2C4 0x3c4 -#define CLK_SOURCE_I2C5 0x128 -#define CLK_SOURCE_UARTA 0x178 -#define CLK_SOURCE_UARTB 0x17c -#define CLK_SOURCE_UARTC 0x1a0 -#define CLK_SOURCE_UARTD 0x1c0 -#define CLK_SOURCE_UARTE 0x1c4 -#define CLK_SOURCE_UARTA_DBG 0x178 -#define CLK_SOURCE_UARTB_DBG 0x17c -#define CLK_SOURCE_UARTC_DBG 0x1a0 -#define CLK_SOURCE_UARTD_DBG 0x1c0 -#define CLK_SOURCE_UARTE_DBG 0x1c4 -#define CLK_SOURCE_3D 0x158 -#define CLK_SOURCE_2D 0x15c -#define CLK_SOURCE_VI_SENSOR 0x1a8 -#define CLK_SOURCE_VI 0x148 -#define CLK_SOURCE_EPP 0x16c -#define CLK_SOURCE_MSENC 0x1f0 -#define CLK_SOURCE_TSEC 0x1f4 -#define CLK_SOURCE_HOST1X 0x180 -#define CLK_SOURCE_HDMI 0x18c -#define CLK_SOURCE_DISP1 0x138 -#define CLK_SOURCE_DISP2 0x13c -#define CLK_SOURCE_CILAB 0x614 -#define CLK_SOURCE_CILCD 0x618 -#define CLK_SOURCE_CILE 0x61c -#define CLK_SOURCE_DSIALP 0x620 -#define CLK_SOURCE_DSIBLP 0x624 -#define CLK_SOURCE_TSENSOR 0x3b8 -#define CLK_SOURCE_D_AUDIO 0x3d0 -#define CLK_SOURCE_DAM0 0x3d8 -#define CLK_SOURCE_DAM1 0x3dc -#define CLK_SOURCE_DAM2 0x3e0 -#define CLK_SOURCE_ACTMON 0x3e8 -#define CLK_SOURCE_EXTERN1 0x3ec -#define CLK_SOURCE_EXTERN2 0x3f0 -#define CLK_SOURCE_EXTERN3 0x3f4 -#define CLK_SOURCE_I2CSLOW 0x3fc -#define CLK_SOURCE_SE 0x42c -#define CLK_SOURCE_MSELECT 0x3b4 -#define CLK_SOURCE_DFLL_REF 0x62c -#define CLK_SOURCE_DFLL_SOC 0x630 -#define CLK_SOURCE_SOC_THERM 0x644 -#define CLK_SOURCE_XUSB_HOST_SRC 0x600 -#define CLK_SOURCE_XUSB_FALCON_SRC 0x604 -#define CLK_SOURCE_XUSB_FS_SRC 0x608 #define CLK_SOURCE_XUSB_SS_SRC 0x610 -#define CLK_SOURCE_XUSB_DEV_SRC 0x60c #define CLK_SOURCE_EMC 0x19c /* PLLM override registers */ @@ -261,7 +176,6 @@ static void __iomem *pmc_base; static DEFINE_SPINLOCK(pll_d_lock); static DEFINE_SPINLOCK(pll_d2_lock); static DEFINE_SPINLOCK(pll_u_lock); -static DEFINE_SPINLOCK(pll_div_lock); static DEFINE_SPINLOCK(pll_re_lock); static DEFINE_SPINLOCK(clk_out_lock); static DEFINE_SPINLOCK(sysrate_lock); @@ -723,73 +637,6 @@ static unsigned long tegra114_input_freq[] = { #define MASK(x) (BIT(x) - 1) -#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \ - _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_MUX_FLAGS(_name, _parents, _offset,\ - _clk_num, _gate_flags, _clk_id, flags)\ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, _gate_flags, _clk_id, _parents##_idx, flags) - -#define TEGRA_INIT_DATA_MUX8(_name, _parents, _offset, \ - _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_INT_FLAGS(_name, _parents, _offset,\ - _clk_num, _gate_flags, _clk_id, flags)\ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - _gate_flags, _clk_id, _parents##_idx, flags) - -#define TEGRA_INIT_DATA_INT8(_name, _parents, _offset,\ - _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - _gate_flags, _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_UART(_name, _parents, _offset,\ - _clk_num, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - 0, _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_I2C(_name, _parents, _offset,\ - _clk_num, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, 0, _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_NODIV(_name, _parents, _offset, \ - _mux_shift, _mux_mask, _clk_num, \ - _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ - _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\ - _clk_num, _gate_flags, \ - _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_XUSB(_name, _parents, _offset, \ - _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \ - 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - _gate_flags, _clk_id, _parents##_idx, 0) - -#define TEGRA_INIT_DATA_AUDIO(_name, _offset, _clk_num,\ - _gate_flags, _clk_id) \ - TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk, \ - _offset, 16, 0xE01F, 0, 0, 8, 1, \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - _gate_flags , _clk_id, mux_d_audio_clk_idx, 0) - struct utmi_clk_param { /* Oscillator Frequency in KHz */ u32 osc_frequency; @@ -823,122 +670,11 @@ static const struct utmi_clk_param utmi_parameters[] = { /* peripheral mux definitions */ -#define MUX_I2S_SPDIF(_id) \ -static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ - #_id, "pll_p",\ - "clk_m"}; -MUX_I2S_SPDIF(audio0) -MUX_I2S_SPDIF(audio1) -MUX_I2S_SPDIF(audio2) -MUX_I2S_SPDIF(audio3) -MUX_I2S_SPDIF(audio4) -MUX_I2S_SPDIF(audio) - -#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL -#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL -#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL -#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL -#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL -#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL - -static const char *mux_pllp_pllc_pllm_clkm[] = { - "pll_p", "pll_c", "pll_m", "clk_m" -}; -#define mux_pllp_pllc_pllm_clkm_idx NULL - -static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" }; -#define mux_pllp_pllc_pllm_idx NULL - -static const char *mux_pllp_pllc_clk32_clkm[] = { - "pll_p", "pll_c", "clk_32k", "clk_m" -}; -#define mux_pllp_pllc_clk32_clkm_idx NULL - -static const char *mux_plla_pllc_pllp_clkm[] = { - "pll_a_out0", "pll_c", "pll_p", "clk_m" -}; -#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx - -static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = { - "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m" -}; -static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = { - [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, -}; - -static const char *mux_pllp_clkm[] = { - "pll_p", "clk_m" -}; -static u32 mux_pllp_clkm_idx[] = { - [0] = 0, [1] = 3, -}; - -static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = { - "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0" -}; -#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx - -static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = { - "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c", - "pll_d2_out0", "clk_m" -}; -#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL - -static const char *mux_pllm_pllc_pllp_plla[] = { - "pll_m", "pll_c", "pll_p", "pll_a_out0" -}; -#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx - -static const char *mux_pllp_pllc_clkm[] = { - "pll_p", "pll_c", "pll_m" -}; -static u32 mux_pllp_pllc_clkm_idx[] = { - [0] = 0, [1] = 1, [2] = 3, -}; - -static const char *mux_pllp_pllc_clkm_clk32[] = { - "pll_p", "pll_c", "clk_m", "clk_32k" -}; -#define mux_pllp_pllc_clkm_clk32_idx NULL - -static const char *mux_plla_clk32_pllp_clkm_plle[] = { - "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0" -}; -#define mux_plla_clk32_pllp_clkm_plle_idx NULL - -static const char *mux_clkm_pllp_pllc_pllre[] = { - "clk_m", "pll_p", "pll_c", "pll_re_out" -}; -static u32 mux_clkm_pllp_pllc_pllre_idx[] = { - [0] = 0, [1] = 1, [2] = 3, [3] = 5, -}; - -static const char *mux_clkm_48M_pllp_480M[] = { - "clk_m", "pll_u_48M", "pll_p", "pll_u_480M" -}; -#define mux_clkm_48M_pllp_480M_idx NULL - -static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = { - "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref" -}; -static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = { - [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7, -}; - static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0", "pll_d2_out0", }; #define mux_plld_out0_plld2_out0_idx NULL -static const char *mux_d_audio_clk[] = { - "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync", - "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", -}; -static u32 mux_d_audio_clk_idx[] = { - [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001, - [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007, -}; - static const char *mux_pllmcp_clkm[] = { "pll_m_out0", "pll_c_out0", "pll_p_out0", "clk_m", "pll_m_ud", }; @@ -1366,53 +1102,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, &pll_c3_params, NULL); clks[TEGRA114_CLK_PLL_C3] = clk; - /* PLLP */ - clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0, - &pll_p_params, NULL); - clks[TEGRA114_CLK_PLL_P] = clk; - - /* PLLP_OUT1 */ - clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", - clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", - clk_base + PLLP_OUTA, 1, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clks[TEGRA114_CLK_PLL_P_OUT1] = clk; - - /* PLLP_OUT2 */ - clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", - clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP | TEGRA_DIVIDER_INT, 24, - 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", - clk_base + PLLP_OUTA, 17, 16, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clks[TEGRA114_CLK_PLL_P_OUT2] = clk; - - /* PLLP_OUT3 */ - clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", - clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", - clk_base + PLLP_OUTB, 1, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clks[TEGRA114_CLK_PLL_P_OUT3] = clk; - - /* PLLP_OUT4 */ - clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", - clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, - &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", - clk_base + PLLP_OUTB, 17, 16, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clks[TEGRA114_CLK_PLL_P_OUT4] = clk; - /* PLLM */ clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, @@ -1634,290 +1323,44 @@ static void __init tegra114_super_clk_init(void __iomem *clk_base) clks[TEGRA114_CLK_PCLK] = clk; } -static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S0), - TEGRA_INIT_DATA_MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S1), - TEGRA_INIT_DATA_MUX("i2s2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S2), - TEGRA_INIT_DATA_MUX("i2s3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S3), - TEGRA_INIT_DATA_MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2S4), - TEGRA_INIT_DATA_MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_OUT), - TEGRA_INIT_DATA_MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SPDIF_IN), - TEGRA_INIT_DATA_MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_PWM), - TEGRA_INIT_DATA_MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_ADX), - TEGRA_INIT_DATA_MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_AMX), - TEGRA_INIT_DATA_MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA), - TEGRA_INIT_DATA_MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_HDA2CODEC_2X), - TEGRA_INIT_DATA_MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC1), - TEGRA_INIT_DATA_MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC2), - TEGRA_INIT_DATA_MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC3), - TEGRA_INIT_DATA_MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC4), - TEGRA_INIT_DATA_MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC5), - TEGRA_INIT_DATA_MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SBC6), - TEGRA_INIT_DATA_MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), - TEGRA_INIT_DATA_MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_NDSPEED), - TEGRA_INIT_DATA_MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_VFIR), - TEGRA_INIT_DATA_MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, TEGRA114_CLK_SDMMC1), - TEGRA_INIT_DATA_MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, TEGRA114_CLK_SDMMC2), - TEGRA_INIT_DATA_MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, TEGRA114_CLK_SDMMC3), - TEGRA_INIT_DATA_MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, TEGRA114_CLK_SDMMC4), - TEGRA_INIT_DATA_INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, TEGRA114_CLK_VDE), - TEGRA_INIT_DATA_MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_CSITE, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_LA), - TEGRA_INIT_DATA_MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TRACE), - TEGRA_INIT_DATA_MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_OWR), - TEGRA_INIT_DATA_MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, TEGRA114_CLK_NOR), - TEGRA_INIT_DATA_MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_MIPI), - TEGRA_INIT_DATA_I2C("i2c1", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, TEGRA114_CLK_I2C1), - TEGRA_INIT_DATA_I2C("i2c2", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, TEGRA114_CLK_I2C2), - TEGRA_INIT_DATA_I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, TEGRA114_CLK_I2C3), - TEGRA_INIT_DATA_I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, TEGRA114_CLK_I2C4), - TEGRA_INIT_DATA_I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, TEGRA114_CLK_I2C5), - TEGRA_INIT_DATA_UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, TEGRA114_CLK_UARTA), - TEGRA_INIT_DATA_UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, TEGRA114_CLK_UARTB), - TEGRA_INIT_DATA_UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, TEGRA114_CLK_UARTC), - TEGRA_INIT_DATA_UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, TEGRA114_CLK_UARTD), - TEGRA_INIT_DATA_INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, TEGRA114_CLK_GR3D), - TEGRA_INIT_DATA_INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, TEGRA114_CLK_GR2D), - TEGRA_INIT_DATA_MUX("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR), - TEGRA_INIT_DATA_INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, TEGRA114_CLK_VI), - TEGRA_INIT_DATA_INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, TEGRA114_CLK_EPP), - TEGRA_INIT_DATA_INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, TEGRA114_CLK_MSENC), - TEGRA_INIT_DATA_INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, TEGRA114_CLK_TSEC), - TEGRA_INIT_DATA_INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, TEGRA114_CLK_HOST1X), - TEGRA_INIT_DATA_MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA114_CLK_HDMI), - TEGRA_INIT_DATA_MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, TEGRA114_CLK_CILAB), - TEGRA_INIT_DATA_MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, TEGRA114_CLK_CILCD), - TEGRA_INIT_DATA_MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, TEGRA114_CLK_CILE), - TEGRA_INIT_DATA_MUX("dsialp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, TEGRA114_CLK_DSIALP), - TEGRA_INIT_DATA_MUX("dsiblp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, TEGRA114_CLK_DSIBLP), - TEGRA_INIT_DATA_MUX("tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_TSENSOR), - TEGRA_INIT_DATA_MUX("actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, TEGRA114_CLK_ACTMON), - TEGRA_INIT_DATA_MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, TEGRA114_CLK_EXTERN1), - TEGRA_INIT_DATA_MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, TEGRA114_CLK_EXTERN2), - TEGRA_INIT_DATA_MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, TEGRA114_CLK_EXTERN3), - TEGRA_INIT_DATA_MUX("i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_I2CSLOW), - TEGRA_INIT_DATA_INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SE), - TEGRA_INIT_DATA_INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, TEGRA114_CLK_MSELECT, CLK_IGNORE_UNUSED), - TEGRA_INIT_DATA_MUX("dfll_ref", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_REF), - TEGRA_INIT_DATA_MUX("dfll_soc", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DFLL_SOC), - TEGRA_INIT_DATA_MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_SOC_THERM), - TEGRA_INIT_DATA_XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_HOST_SRC), - TEGRA_INIT_DATA_XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FALCON_SRC), - TEGRA_INIT_DATA_XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_FS_SRC), - TEGRA_INIT_DATA_XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_SS_SRC), - TEGRA_INIT_DATA_XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_XUSB_DEV_SRC), - TEGRA_INIT_DATA_AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_D_AUDIO), - TEGRA_INIT_DATA_AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM0), - TEGRA_INIT_DATA_AUDIO("dam1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM1), - TEGRA_INIT_DATA_AUDIO("dam2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, TEGRA114_CLK_DAM2), -}; - -static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, TEGRA114_CLK_DISP1), - TEGRA_INIT_DATA_NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, TEGRA114_CLK_DISP2), -}; - -static __init void tegra114_periph_clk_init(void __iomem *clk_base) +static __init void tegra114_periph_clk_init(void __iomem *clk_base, + void __iomem *pmc_base) { - struct tegra_periph_init_data *data; struct clk *clk; - int i; u32 val; - /* apbdma */ - clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, - 0, 34, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_APBDMA] = clk; - - /* rtc */ - clk = tegra_clk_register_periph_gate("rtc", "clk_32k", - TEGRA_PERIPH_ON_APB | - TEGRA_PERIPH_NO_RESET, clk_base, - 0, 4, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_RTC] = clk; - - /* kbc */ - clk = tegra_clk_register_periph_gate("kbc", "clk_32k", - TEGRA_PERIPH_ON_APB | - TEGRA_PERIPH_NO_RESET, clk_base, - 0, 36, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_KBC] = clk; - - /* timer */ - clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, - 0, 5, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_TIMER] = clk; - - /* kfuse */ - clk = tegra_clk_register_periph_gate("kfuse", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 40, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_KFUSE] = clk; - - /* fuse */ - clk = tegra_clk_register_periph_gate("fuse", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 39, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_FUSE] = clk; - - /* fuse_burn */ - clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 39, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_FUSE_BURN] = clk; - - /* apbif */ - clk = tegra_clk_register_periph_gate("apbif", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 107, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_APBIF] = clk; - - /* hda2hdmi */ - clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 128, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_HDA2HDMI] = clk; - - /* vcp */ - clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, - 29, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_VCP] = clk; - - /* bsea */ - clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, - 0, 62, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_BSEA] = clk; - - /* bsev */ - clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, - 0, 63, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_BSEV] = clk; - - /* mipi-cal */ - clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base, - 0, 56, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_MIPI_CAL] = clk; - - /* usbd */ - clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, - 0, 22, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_USBD] = clk; - - /* usb2 */ - clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, - 0, 58, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_USB2] = clk; - - /* usb3 */ - clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, - 0, 59, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_USB3] = clk; - - /* csi */ - clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, - 0, 52, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_CSI] = clk; - - /* isp */ - clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, - 23, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_ISP] = clk; - - /* csus */ - clk = tegra_clk_register_periph_gate("csus", "clk_m", - TEGRA_PERIPH_NO_RESET, clk_base, 0, 92, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_CSUS] = clk; - - /* dds */ - clk = tegra_clk_register_periph_gate("dds", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 150, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_DDS] = clk; - - /* dp2 */ - clk = tegra_clk_register_periph_gate("dp2", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 152, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_DP2] = clk; - - /* dtv */ - clk = tegra_clk_register_periph_gate("dtv", "clk_m", - TEGRA_PERIPH_ON_APB, clk_base, 0, 79, - periph_clk_enb_refcnt); - clks[TEGRA114_CLK_DTV] = clk; - - /* dsia */ + /* xusb_hs_src */ + val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC); + val |= BIT(25); /* always select PLLU_60M */ + writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC); + + clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, + 1, 1); + clks[TEGRA114_CLK_XUSB_HS_SRC] = clk; + + /* dsia mux */ clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, ARRAY_SIZE(mux_plld_out0_plld2_out0), CLK_SET_RATE_NO_REPARENT, clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock); clks[TEGRA114_CLK_DSIA_MUX] = clk; - clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base, - 0, 48, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_DSIA] = clk; - /* dsib */ + /* dsib mux */ clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0, ARRAY_SIZE(mux_plld_out0_plld2_out0), CLK_SET_RATE_NO_REPARENT, clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock); clks[TEGRA114_CLK_DSIB_MUX] = clk; - clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base, - 0, 82, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_DSIB] = clk; - /* xusb_hs_src */ - val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC); - val |= BIT(25); /* always select PLLU_60M */ - writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC); - - clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, - 1, 1); - clks[TEGRA114_CLK_XUSB_HS_SRC] = clk; - - /* xusb_host */ - clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0, - clk_base, 0, 89, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_XUSB_HOST] = clk; - - /* xusb_ss */ - clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0, - clk_base, 0, 156, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_XUSB_HOST] = clk; - - /* xusb_dev */ - clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0, - clk_base, 0, 95, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_XUSB_DEV] = clk; - - /* emc */ + /* emc mux */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, ARRAY_SIZE(mux_pllmcp_clkm), CLK_SET_RATE_NO_REPARENT, clk_base + CLK_SOURCE_EMC, 29, 3, 0, NULL); - clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, - CLK_IGNORE_UNUSED, 57, periph_clk_enb_refcnt); - clks[TEGRA114_CLK_EMC] = clk; - - for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { - data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, - data->parent_names, data->num_parents, &data->periph, - clk_base, data->offset, data->flags); - clks[data->clk_id] = clk; - } - - for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { - data = &tegra_periph_nodiv_clk_list[i]; - - clk = tegra_clk_register_periph_nodiv(data->name, - data->parent_names, data->num_parents, - &data->periph, clk_base, data->offset); - clks[data->clk_id] = clk; - } + tegra_periph_clk_init(clk_base, pmc_base, tegra114_clks, + &pll_p_params); } /* Tegra114 CPU clock and reset control functions */ @@ -2167,7 +1610,7 @@ static void __init tegra114_clock_init(struct device_node *np) tegra114_fixed_clk_init(clk_base); tegra114_pll_init(clk_base, pmc_base); - tegra114_periph_clk_init(clk_base); + tegra114_periph_clk_init(clk_base, pmc_base); tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); tegra114_pmc_clk_init(pmc_base); tegra114_super_clk_init(clk_base); diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 31547fde92e4..7c9af8e2c33b 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -973,7 +973,7 @@ static void __init tegra20_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->parent_names, + clk = tegra_clk_register_periph(data->name, data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset, data->flags); clk_register_clkdev(clk, data->con_id, data->dev_id); @@ -983,7 +983,7 @@ static void __init tegra20_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { data = &tegra_periph_nodiv_clk_list[i]; clk = tegra_clk_register_periph_nodiv(data->name, - data->parent_names, + data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset); clk_register_clkdev(clk, data->con_id, data->dev_id); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index da540f6dc9c9..c75db196728c 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1616,7 +1616,7 @@ static void __init tegra30_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->parent_names, + clk = tegra_clk_register_periph(data->name, data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset, data->flags); clk_register_clkdev(clk, data->con_id, data->dev_id); @@ -1626,7 +1626,7 @@ static void __init tegra30_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { data = &tegra_periph_nodiv_clk_list[i]; clk = tegra_clk_register_periph_nodiv(data->name, - data->parent_names, + data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset); clk_register_clkdev(clk, data->con_id, data->dev_id); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 3306e41e6270..9ec6118e9b99 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -460,7 +460,10 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, struct tegra_periph_init_data { const char *name; int clk_id; - const char **parent_names; + union { + const char **parent_names; + const char *parent_name; + } p; int num_parents; struct tegra_clk_periph periph; u32 offset; @@ -477,7 +480,7 @@ struct tegra_periph_init_data { { \ .name = _name, \ .clk_id = _clk_id, \ - .parent_names = _parent_names, \ + .p.parent_names = _parent_names, \ .num_parents = ARRAY_SIZE(_parent_names), \ .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \ _mux_flags, _div_shift, \ @@ -597,6 +600,10 @@ void tegra_audio_clk_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *pll_params); +void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base, + struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_params); + void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); void tegra114_clock_tune_cpu_trimmers_init(void); -- cgit v1.2.3 From de4f30fd8403cd67449fbb9dc06a3d898fb9f10c Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Tue, 15 Oct 2013 17:19:13 +0300 Subject: clk: tegra: move PMC, fixed clocks to common files Introduce new files for fixed and PMC clocks common between several Tegra SoCs and move Tegra114 to this new infrastructure. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/Makefile | 2 + drivers/clk/tegra/clk-tegra-fixed.c | 111 ++++++++++++++++++++++++++++++ drivers/clk/tegra/clk-tegra-pmc.c | 132 ++++++++++++++++++++++++++++++++++++ drivers/clk/tegra/clk-tegra114.c | 75 +------------------- drivers/clk/tegra/clk.h | 7 ++ 5 files changed, 253 insertions(+), 74 deletions(-) create mode 100644 drivers/clk/tegra/clk-tegra-fixed.c create mode 100644 drivers/clk/tegra/clk-tegra-pmc.c (limited to 'drivers') diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 304ea5df63eb..a02e9a95a4cb 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -8,6 +8,8 @@ obj-y += clk-pll-out.o obj-y += clk-super.o obj-y += clk-tegra-audio.o obj-y += clk-tegra-periph.o +obj-y += clk-tegra-pmc.o +obj-y += clk-tegra-fixed.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c new file mode 100644 index 000000000000..f3b773833429 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-fixed.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "clk-id.h" + +#define OSC_CTRL 0x50 +#define OSC_CTRL_OSC_FREQ_SHIFT 28 +#define OSC_CTRL_PLL_REF_DIV_SHIFT 26 + +int __init tegra_osc_clk_init(void __iomem *clk_base, + struct tegra_clk *tegra_clks, + unsigned long *input_freqs, int num, + unsigned long *osc_freq, + unsigned long *pll_ref_freq) +{ + struct clk *clk; + struct clk **dt_clk; + u32 val, pll_ref_div; + unsigned osc_idx; + + val = readl_relaxed(clk_base + OSC_CTRL); + osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT; + + if (osc_idx < num) + *osc_freq = input_freqs[osc_idx]; + else + *osc_freq = 0; + + if (!*osc_freq) { + WARN_ON(1); + return -EINVAL; + } + + dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks); + if (!dt_clk) + return 0; + + clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, + *osc_freq); + *dt_clk = clk; + + /* pll_ref */ + val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3; + pll_ref_div = 1 << val; + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks); + if (!dt_clk) + return 0; + + clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", + 0, 1, pll_ref_div); + *dt_clk = clk; + + if (pll_ref_freq) + *pll_ref_freq = *osc_freq / pll_ref_div; + + return 0; +} + +void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks) +{ + struct clk *clk; + struct clk **dt_clk; + + /* clk_32k */ + dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks); + if (dt_clk) { + clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, + CLK_IS_ROOT, 32768); + *dt_clk = clk; + } + + /* clk_m_div2 */ + dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks); + if (dt_clk) { + clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", + CLK_SET_RATE_PARENT, 1, 2); + *dt_clk = clk; + } + + /* clk_m_div4 */ + dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks); + if (dt_clk) { + clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", + CLK_SET_RATE_PARENT, 1, 4); + *dt_clk = clk; + } +} + diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c new file mode 100644 index 000000000000..08b21c1ee867 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-pmc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "clk-id.h" + +#define PMC_CLK_OUT_CNTRL 0x1a8 +#define PMC_DPD_PADS_ORIDE 0x1c +#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 +#define PMC_CTRL 0 +#define PMC_CTRL_BLINK_ENB 7 +#define PMC_BLINK_TIMER 0x40 + +struct pmc_clk_init_data { + char *mux_name; + char *gate_name; + const char **parents; + int num_parents; + int mux_id; + int gate_id; + char *dev_name; + u8 mux_shift; + u8 gate_shift; +}; + +#define PMC_CLK(_num, _mux_shift, _gate_shift)\ + {\ + .mux_name = "clk_out_" #_num "_mux",\ + .gate_name = "clk_out_" #_num,\ + .parents = clk_out ##_num ##_parents,\ + .num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\ + .mux_id = tegra_clk_clk_out_ ##_num ##_mux,\ + .gate_id = tegra_clk_clk_out_ ##_num,\ + .dev_name = "extern" #_num,\ + .mux_shift = _mux_shift,\ + .gate_shift = _gate_shift,\ + } + +static DEFINE_SPINLOCK(clk_out_lock); + +static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", + "clk_m_div4", "extern1", +}; + +static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", + "clk_m_div4", "extern2", +}; + +static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", + "clk_m_div4", "extern3", +}; + +static struct pmc_clk_init_data pmc_clks[] = { + PMC_CLK(1, 6, 2), + PMC_CLK(2, 14, 10), + PMC_CLK(3, 22, 18), +}; + +void __init tegra_pmc_clk_init(void __iomem *pmc_base, + struct tegra_clk *tegra_clks) +{ + struct clk *clk; + struct clk **dt_clk; + int i; + + for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) { + struct pmc_clk_init_data *data; + + data = pmc_clks + i; + + dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks); + if (!dt_clk) + continue; + + clk = clk_register_mux(NULL, data->mux_name, data->parents, + data->num_parents, CLK_SET_RATE_NO_REPARENT, + pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift, + 3, 0, &clk_out_lock); + *dt_clk = clk; + + + dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks); + if (!dt_clk) + continue; + + clk = clk_register_gate(NULL, data->gate_name, data->mux_name, + 0, pmc_base + PMC_CLK_OUT_CNTRL, + data->gate_shift, 0, &clk_out_lock); + *dt_clk = clk; + clk_register_clkdev(clk, data->dev_name, data->gate_name); + } + + /* blink */ + writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); + clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, + pmc_base + PMC_DPD_PADS_ORIDE, + PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); + + dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks); + if (!dt_clk) + return; + + clk = clk_register_gate(NULL, "blink", "blink_override", 0, + pmc_base + PMC_CTRL, + PMC_CTRL_BLINK_ENB, 0, NULL); + clk_register_clkdev(clk, "blink", NULL); + *dt_clk = clk; +} + diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 07098597db53..046dbed0c2c5 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -107,13 +107,6 @@ #define PLLC_OUT 0x84 #define PLLM_OUT 0x94 -#define PMC_CLK_OUT_CNTRL 0x1a8 -#define PMC_DPD_PADS_ORIDE 0x1c -#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 -#define PMC_CTRL 0 -#define PMC_CTRL_BLINK_ENB 7 -#define PMC_BLINK_TIMER 0x40 - #define OSC_CTRL 0x50 #define OSC_CTRL_OSC_FREQ_SHIFT 28 #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 @@ -177,7 +170,6 @@ static DEFINE_SPINLOCK(pll_d_lock); static DEFINE_SPINLOCK(pll_d2_lock); static DEFINE_SPINLOCK(pll_u_lock); static DEFINE_SPINLOCK(pll_re_lock); -static DEFINE_SPINLOCK(clk_out_lock); static DEFINE_SPINLOCK(sysrate_lock); static struct div_nmp pllxc_nmp = { @@ -1199,71 +1191,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_E_OUT0] = clk; } -static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", - "clk_m_div4", "extern1", -}; - -static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", - "clk_m_div4", "extern2", -}; - -static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", - "clk_m_div4", "extern3", -}; - -static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) -{ - struct clk *clk; - - /* clk_out_1 */ - clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, - ARRAY_SIZE(clk_out1_parents), - CLK_SET_RATE_NO_REPARENT, - pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, - &clk_out_lock); - clks[TEGRA114_CLK_CLK_OUT_1_MUX] = clk; - clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, - pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, - &clk_out_lock); - clks[TEGRA114_CLK_CLK_OUT_1] = clk; - - /* clk_out_2 */ - clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, - ARRAY_SIZE(clk_out2_parents), - CLK_SET_RATE_NO_REPARENT, - pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, - &clk_out_lock); - clks[TEGRA114_CLK_CLK_OUT_2_MUX] = clk; - clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, - pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, - &clk_out_lock); - clks[TEGRA114_CLK_CLK_OUT_2] = clk; - - /* clk_out_3 */ - clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, - ARRAY_SIZE(clk_out3_parents), - CLK_SET_RATE_NO_REPARENT, - pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, - &clk_out_lock); - clks[TEGRA114_CLK_CLK_OUT_3_MUX] = clk; - clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, - pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, - &clk_out_lock); - clks[TEGRA114_CLK_CLK_OUT_3] = clk; - - /* blink */ - /* clear the blink timer register to directly output clk_32k */ - writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); - clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, - pmc_base + PMC_DPD_PADS_ORIDE, - PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); - clk = clk_register_gate(NULL, "blink", "blink_override", 0, - pmc_base + PMC_CTRL, - PMC_CTRL_BLINK_ENB, 0, NULL); - clks[TEGRA114_CLK_BLINK] = clk; - -} - static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", "pll_p", "pll_p_out2", "unused", "clk_32k", "pll_m_out1" }; @@ -1612,7 +1539,7 @@ static void __init tegra114_clock_init(struct device_node *np) tegra114_pll_init(clk_base, pmc_base); tegra114_periph_clk_init(clk_base, pmc_base); tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); - tegra114_pmc_clk_init(pmc_base); + tegra_pmc_clk_init(pmc_base, tegra114_clks); tegra114_super_clk_init(clk_base); tegra_add_of_provider(np); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 9ec6118e9b99..2d4881763902 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -604,6 +604,13 @@ void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *pll_params); +void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks); +void tegra_fixed_clk_init(struct tegra_clk *tegra_clks); +int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks, + unsigned long *input_freqs, int num, + unsigned long *osc_freq, + unsigned long *pll_ref_freq); + void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); void tegra114_clock_tune_cpu_trimmers_init(void); -- cgit v1.2.3 From a7c8485a0ebbdce303c6709e208bb4fd08aff8ad Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Tue, 3 Sep 2013 15:46:01 +0300 Subject: clk: tegra: introduce common gen4 super clock Introduce a common function which performs super clock initialization for Tegra114 and beyond. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/Makefile | 1 + drivers/clk/tegra/clk-tegra-super-gen4.c | 149 +++++++++++++++++++++++++++++++ drivers/clk/tegra/clk-tegra114.c | 76 +--------------- drivers/clk/tegra/clk.h | 3 + 4 files changed, 155 insertions(+), 74 deletions(-) create mode 100644 drivers/clk/tegra/clk-tegra-super-gen4.c (limited to 'drivers') diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index a02e9a95a4cb..2d837411dfed 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -10,6 +10,7 @@ obj-y += clk-tegra-audio.o obj-y += clk-tegra-periph.o obj-y += clk-tegra-pmc.o obj-y += clk-tegra-fixed.o +obj-y += clk-tegra-super-gen4.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c new file mode 100644 index 000000000000..05dce4aa2c11 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "clk-id.h" + +#define PLLX_BASE 0xe0 +#define PLLX_MISC 0xe4 +#define PLLX_MISC2 0x514 +#define PLLX_MISC3 0x518 + +#define CCLKG_BURST_POLICY 0x368 +#define CCLKLP_BURST_POLICY 0x370 +#define SCLK_BURST_POLICY 0x028 +#define SYSTEM_CLK_RATE 0x030 + +static DEFINE_SPINLOCK(sysrate_lock); + +static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", + "pll_p", "pll_p_out2", "unused", + "clk_32k", "pll_m_out1" }; + +static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", + "pll_p", "pll_p_out4", "unused", + "unused", "pll_x" }; + +static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", + "pll_p", "pll_p_out4", "unused", + "unused", "pll_x", "pll_x_out0" }; + +static void __init tegra_sclk_init(void __iomem *clk_base, + struct tegra_clk *tegra_clks) +{ + struct clk *clk; + struct clk **dt_clk; + + /* SCLK */ + dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_super_mux("sclk", sclk_parents, + ARRAY_SIZE(sclk_parents), + CLK_SET_RATE_PARENT, + clk_base + SCLK_BURST_POLICY, + 0, 4, 0, 0, NULL); + *dt_clk = clk; + } + + /* HCLK */ + dt_clk = tegra_lookup_dt_id(tegra_clk_hclk, tegra_clks); + if (dt_clk) { + clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, + clk_base + SYSTEM_CLK_RATE, 4, 2, 0, + &sysrate_lock); + clk = clk_register_gate(NULL, "hclk", "hclk_div", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + clk_base + SYSTEM_CLK_RATE, + 7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); + *dt_clk = clk; + } + + /* PCLK */ + dt_clk = tegra_lookup_dt_id(tegra_clk_pclk, tegra_clks); + if (!dt_clk) + return; + + clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, + clk_base + SYSTEM_CLK_RATE, 0, 2, 0, + &sysrate_lock); + clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT | + CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, + 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); + *dt_clk = clk; +} + +void __init tegra_super_clk_gen4_init(void __iomem *clk_base, + void __iomem *pmc_base, + struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *params) +{ + struct clk *clk; + struct clk **dt_clk; + + /* CCLKG */ + dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents, + ARRAY_SIZE(cclk_g_parents), + CLK_SET_RATE_PARENT, + clk_base + CCLKG_BURST_POLICY, + 0, 4, 0, 0, NULL); + *dt_clk = clk; + } + + /* CCLKLP */ + dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents, + ARRAY_SIZE(cclk_lp_parents), + CLK_SET_RATE_PARENT, + clk_base + CCLKLP_BURST_POLICY, + 0, 4, 8, 9, NULL); + *dt_clk = clk; + } + + tegra_sclk_init(clk_base, tegra_clks); + +#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC) + /* PLLX */ + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks); + if (!dt_clk) + return; + + clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, + pmc_base, CLK_IGNORE_UNUSED, params, NULL); + *dt_clk = clk; + + /* PLLX_OUT0 */ + + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks); + if (!dt_clk) + return; + clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", + CLK_SET_RATE_PARENT, 1, 2); + *dt_clk = clk; +#endif +} + diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 046dbed0c2c5..0b8c9af5bff3 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -114,9 +114,6 @@ #define PLLXC_SW_MAX_P 6 #define CCLKG_BURST_POLICY 0x368 -#define CCLKLP_BURST_POLICY 0x370 -#define SCLK_BURST_POLICY 0x028 -#define SYSTEM_CLK_RATE 0x030 #define UTMIP_PLL_CFG2 0x488 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) @@ -170,7 +167,6 @@ static DEFINE_SPINLOCK(pll_d_lock); static DEFINE_SPINLOCK(pll_d2_lock); static DEFINE_SPINLOCK(pll_u_lock); static DEFINE_SPINLOCK(pll_re_lock); -static DEFINE_SPINLOCK(sysrate_lock); static struct div_nmp pllxc_nmp = { .divm_shift = 0, @@ -1113,16 +1109,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", CLK_SET_RATE_PARENT, 1, 1); - /* PLLX */ - clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, - pmc, CLK_IGNORE_UNUSED, &pll_x_params, NULL); - clks[TEGRA114_CLK_PLL_X] = clk; - - /* PLLX_OUT0 */ - clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", - CLK_SET_RATE_PARENT, 1, 2); - clks[TEGRA114_CLK_PLL_X_OUT0] = clk; - /* PLLU */ val = readl(clk_base + pll_u_params.base_reg); val &= ~BIT(24); /* disable PLLU_OVERRIDE */ @@ -1191,65 +1177,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base, clks[TEGRA114_CLK_PLL_E_OUT0] = clk; } -static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", - "pll_p", "pll_p_out2", "unused", - "clk_32k", "pll_m_out1" }; - -static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", - "pll_p", "pll_p_out4", "unused", - "unused", "pll_x" }; - -static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", - "pll_p", "pll_p_out4", "unused", - "unused", "pll_x", "pll_x_out0" }; - -static void __init tegra114_super_clk_init(void __iomem *clk_base) -{ - struct clk *clk; - - /* CCLKG */ - clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents, - ARRAY_SIZE(cclk_g_parents), - CLK_SET_RATE_PARENT, - clk_base + CCLKG_BURST_POLICY, - 0, 4, 0, 0, NULL); - clks[TEGRA114_CLK_CCLK_G] = clk; - - /* CCLKLP */ - clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents, - ARRAY_SIZE(cclk_lp_parents), - CLK_SET_RATE_PARENT, - clk_base + CCLKLP_BURST_POLICY, - 0, 4, 8, 9, NULL); - clks[TEGRA114_CLK_CCLK_LP] = clk; - - /* SCLK */ - clk = tegra_clk_register_super_mux("sclk", sclk_parents, - ARRAY_SIZE(sclk_parents), - CLK_SET_RATE_PARENT, - clk_base + SCLK_BURST_POLICY, - 0, 4, 0, 0, NULL); - clks[TEGRA114_CLK_SCLK] = clk; - - /* HCLK */ - clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, - clk_base + SYSTEM_CLK_RATE, 4, 2, 0, - &sysrate_lock); - clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT | - CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, - 7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clks[TEGRA114_CLK_HCLK] = clk; - - /* PCLK */ - clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, - clk_base + SYSTEM_CLK_RATE, 0, 2, 0, - &sysrate_lock); - clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT | - CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, - 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clks[TEGRA114_CLK_PCLK] = clk; -} - static __init void tegra114_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { @@ -1540,7 +1467,8 @@ static void __init tegra114_clock_init(struct device_node *np) tegra114_periph_clk_init(clk_base, pmc_base); tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); tegra_pmc_clk_init(pmc_base, tegra114_clks); - tegra114_super_clk_init(clk_base); + tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks, + &pll_x_params); tegra_add_of_provider(np); tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 2d4881763902..05abfc5fdff8 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -610,6 +610,9 @@ int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks, unsigned long *input_freqs, int num, unsigned long *osc_freq, unsigned long *pll_ref_freq); +void tegra_super_clk_gen4_init(void __iomem *clk_base, + void __iomem *pmc_base, struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_params); void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_low(void); -- cgit v1.2.3 From 1bf409159b90804d5e36e4034abc0641555a292f Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 7 Oct 2013 14:49:04 +0300 Subject: clk: tegra: move tegra30 to common infra Move tegra30 to common tegra clock infrastructure. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra30.c | 1298 ++++++++++++--------------------------- 1 file changed, 403 insertions(+), 895 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index c75db196728c..f7ebf2bacdd9 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -23,8 +23,9 @@ #include #include #include - +#include #include "clk.h" +#include "clk-id.h" #define OSC_CTRL 0x50 #define OSC_CTRL_OSC_FREQ_MASK (0xF<<28) @@ -100,88 +101,20 @@ #define AUDIO_SYNC_CLK_I2S4 0x4b0 #define AUDIO_SYNC_CLK_SPDIF 0x4b4 -#define PMC_CLK_OUT_CNTRL 0x1a8 - -#define CLK_SOURCE_I2S0 0x1d8 -#define CLK_SOURCE_I2S1 0x100 -#define CLK_SOURCE_I2S2 0x104 -#define CLK_SOURCE_I2S3 0x3bc -#define CLK_SOURCE_I2S4 0x3c0 #define CLK_SOURCE_SPDIF_OUT 0x108 -#define CLK_SOURCE_SPDIF_IN 0x10c -#define CLK_SOURCE_PWM 0x110 #define CLK_SOURCE_D_AUDIO 0x3d0 #define CLK_SOURCE_DAM0 0x3d8 #define CLK_SOURCE_DAM1 0x3dc #define CLK_SOURCE_DAM2 0x3e0 -#define CLK_SOURCE_HDA 0x428 -#define CLK_SOURCE_HDA2CODEC_2X 0x3e4 -#define CLK_SOURCE_SBC1 0x134 -#define CLK_SOURCE_SBC2 0x118 -#define CLK_SOURCE_SBC3 0x11c -#define CLK_SOURCE_SBC4 0x1b4 -#define CLK_SOURCE_SBC5 0x3c8 -#define CLK_SOURCE_SBC6 0x3cc -#define CLK_SOURCE_SATA_OOB 0x420 -#define CLK_SOURCE_SATA 0x424 -#define CLK_SOURCE_NDFLASH 0x160 -#define CLK_SOURCE_NDSPEED 0x3f8 -#define CLK_SOURCE_VFIR 0x168 -#define CLK_SOURCE_SDMMC1 0x150 -#define CLK_SOURCE_SDMMC2 0x154 -#define CLK_SOURCE_SDMMC3 0x1bc -#define CLK_SOURCE_SDMMC4 0x164 -#define CLK_SOURCE_VDE 0x1c8 -#define CLK_SOURCE_CSITE 0x1d4 -#define CLK_SOURCE_LA 0x1f8 -#define CLK_SOURCE_OWR 0x1cc -#define CLK_SOURCE_NOR 0x1d0 -#define CLK_SOURCE_MIPI 0x174 -#define CLK_SOURCE_I2C1 0x124 -#define CLK_SOURCE_I2C2 0x198 -#define CLK_SOURCE_I2C3 0x1b8 -#define CLK_SOURCE_I2C4 0x3c4 -#define CLK_SOURCE_I2C5 0x128 -#define CLK_SOURCE_UARTA 0x178 -#define CLK_SOURCE_UARTB 0x17c -#define CLK_SOURCE_UARTC 0x1a0 -#define CLK_SOURCE_UARTD 0x1c0 -#define CLK_SOURCE_UARTE 0x1c4 -#define CLK_SOURCE_VI 0x148 -#define CLK_SOURCE_VI_SENSOR 0x1a8 -#define CLK_SOURCE_3D 0x158 #define CLK_SOURCE_3D2 0x3b0 #define CLK_SOURCE_2D 0x15c -#define CLK_SOURCE_EPP 0x16c -#define CLK_SOURCE_MPE 0x170 -#define CLK_SOURCE_HOST1X 0x180 -#define CLK_SOURCE_CVE 0x140 -#define CLK_SOURCE_TVO 0x188 -#define CLK_SOURCE_DTV 0x1dc #define CLK_SOURCE_HDMI 0x18c -#define CLK_SOURCE_TVDAC 0x194 -#define CLK_SOURCE_DISP1 0x138 -#define CLK_SOURCE_DISP2 0x13c #define CLK_SOURCE_DSIB 0xd0 -#define CLK_SOURCE_TSENSOR 0x3b8 -#define CLK_SOURCE_ACTMON 0x3e8 -#define CLK_SOURCE_EXTERN1 0x3ec -#define CLK_SOURCE_EXTERN2 0x3f0 -#define CLK_SOURCE_EXTERN3 0x3f4 -#define CLK_SOURCE_I2CSLOW 0x3fc #define CLK_SOURCE_SE 0x42c -#define CLK_SOURCE_MSELECT 0x3b4 #define CLK_SOURCE_EMC 0x19c #define AUDIO_SYNC_DOUBLER 0x49c -#define PMC_CTRL 0 -#define PMC_CTRL_BLINK_ENB 7 - -#define PMC_DPD_PADS_ORIDE 0x1c -#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 -#define PMC_BLINK_TIMER 0x40 - #define UTMIP_PLL_CFG2 0x488 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) @@ -238,82 +171,36 @@ static void __iomem *clk_base; static void __iomem *pmc_base; static unsigned long input_freq; -static DEFINE_SPINLOCK(clk_doubler_lock); -static DEFINE_SPINLOCK(clk_out_lock); -static DEFINE_SPINLOCK(pll_div_lock); static DEFINE_SPINLOCK(cml_lock); static DEFINE_SPINLOCK(pll_d_lock); -static DEFINE_SPINLOCK(sysrate_lock); -#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, _gate_flags, _clk_id) -#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, \ - _gate_flags, _clk_id) - -#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_MUX8(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ 29, 3, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, _gate_flags, _clk_id) -#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_INT(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT | \ TEGRA_DIVIDER_ROUND_UP, _clk_num, \ _gate_flags, _clk_id) -#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ - _clk_num, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART | \ - TEGRA_DIVIDER_ROUND_UP, _clk_num, \ - 0, _clk_id) - -#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_NODIV(_name, _parents, _offset, \ _mux_shift, _mux_width, _clk_num, \ _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ _mux_shift, _mux_width, 0, 0, 0, 0, 0,\ _clk_num, _gate_flags, \ _clk_id) -/* - * IDs assigned here must be in sync with DT bindings definition - * for Tegra30 clocks. - */ -enum tegra30_clk { - cpu, rtc = 4, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, ndflash, - sdmmc1, sdmmc4, pwm = 17, i2s2, epp, gr2d = 21, usbd, isp, gr3d, - disp2 = 26, disp1, host1x, vcp, i2s0, cop_cache, mc, ahbdma, apbdma, - kbc = 36, statmon, pmc, kfuse = 40, sbc1, nor, sbc2 = 44, sbc3 = 46, - i2c5, dsia, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, - usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, - pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2cslow, - dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92, - cdev2, cdev1, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4, - i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x, - atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x, - spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda, - se = 127, hda2hdmi, sata_cold, uartb = 160, vfir, spdif_in, spdif_out, - vi, vi_sensor, fuse, fuse_burn, cve, tvo, clk_32k, clk_m, clk_m_div2, - clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_m, pll_m_out1, pll_p, - pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_a, pll_a_out0, - pll_d, pll_d_out0, pll_d2, pll_d2_out0, pll_u, pll_x, pll_x_out0, pll_e, - spdif_in_sync, i2s0_sync, i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, - vimclk_sync, audio0, audio1, audio2, audio3, audio4, spdif, clk_out_1, - clk_out_2, clk_out_3, sclk, blink, cclk_g, cclk_lp, twd, cml0, cml1, - hclk, pclk, clk_out_1_mux = 300, clk_max -}; - static struct clk **clks; /* @@ -685,67 +572,295 @@ static struct tegra_clk_pll_params pll_e_params = { .fixed_rate = 100000000, }; -static void tegra30_clk_measure_input_freq(void) -{ - u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); - u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK; - u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK; - - switch (auto_clk_control) { - case OSC_CTRL_OSC_FREQ_12MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - input_freq = 12000000; - break; - case OSC_CTRL_OSC_FREQ_13MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - input_freq = 13000000; - break; - case OSC_CTRL_OSC_FREQ_19_2MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - input_freq = 19200000; - break; - case OSC_CTRL_OSC_FREQ_26MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - input_freq = 26000000; - break; - case OSC_CTRL_OSC_FREQ_16_8MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - input_freq = 16800000; - break; - case OSC_CTRL_OSC_FREQ_38_4MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2); - input_freq = 38400000; - break; - case OSC_CTRL_OSC_FREQ_48MHZ: - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4); - input_freq = 48000000; - break; - default: - pr_err("Unexpected auto clock control value %d", - auto_clk_control); - BUG(); - return; - } -} +static unsigned long tegra30_input_freq[] = { + [0] = 13000000, + [1] = 16800000, + [4] = 19200000, + [5] = 38400000, + [8] = 12000000, + [9] = 48000000, + [12] = 260000000, +}; -static unsigned int tegra30_get_pll_ref_div(void) -{ - u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) & - OSC_CTRL_PLL_REF_DIV_MASK; - - switch (pll_ref_div) { - case OSC_CTRL_PLL_REF_DIV_1: - return 1; - case OSC_CTRL_PLL_REF_DIV_2: - return 2; - case OSC_CTRL_PLL_REF_DIV_4: - return 4; - default: - pr_err("Invalid pll ref divider %d", pll_ref_div); - BUG(); - } - return 0; -} +static struct tegra_devclk devclks[] __initdata = { + { .con_id = "pll_c", .dt_id = TEGRA30_CLK_PLL_C }, + { .con_id = "pll_c_out1", .dt_id = TEGRA30_CLK_PLL_C_OUT1 }, + { .con_id = "pll_p", .dt_id = TEGRA30_CLK_PLL_P }, + { .con_id = "pll_p_out1", .dt_id = TEGRA30_CLK_PLL_P_OUT1 }, + { .con_id = "pll_p_out2", .dt_id = TEGRA30_CLK_PLL_P_OUT2 }, + { .con_id = "pll_p_out3", .dt_id = TEGRA30_CLK_PLL_P_OUT3 }, + { .con_id = "pll_p_out4", .dt_id = TEGRA30_CLK_PLL_P_OUT4 }, + { .con_id = "pll_m", .dt_id = TEGRA30_CLK_PLL_M }, + { .con_id = "pll_m_out1", .dt_id = TEGRA30_CLK_PLL_M_OUT1 }, + { .con_id = "pll_x", .dt_id = TEGRA30_CLK_PLL_X }, + { .con_id = "pll_x_out0", .dt_id = TEGRA30_CLK_PLL_X_OUT0 }, + { .con_id = "pll_u", .dt_id = TEGRA30_CLK_PLL_U }, + { .con_id = "pll_d", .dt_id = TEGRA30_CLK_PLL_D }, + { .con_id = "pll_d_out0", .dt_id = TEGRA30_CLK_PLL_D_OUT0 }, + { .con_id = "pll_d2", .dt_id = TEGRA30_CLK_PLL_D2 }, + { .con_id = "pll_d2_out0", .dt_id = TEGRA30_CLK_PLL_D2_OUT0 }, + { .con_id = "pll_a", .dt_id = TEGRA30_CLK_PLL_A }, + { .con_id = "pll_a_out0", .dt_id = TEGRA30_CLK_PLL_A_OUT0 }, + { .con_id = "pll_e", .dt_id = TEGRA30_CLK_PLL_E }, + { .con_id = "spdif_in_sync", .dt_id = TEGRA30_CLK_SPDIF_IN_SYNC }, + { .con_id = "i2s0_sync", .dt_id = TEGRA30_CLK_I2S0_SYNC }, + { .con_id = "i2s1_sync", .dt_id = TEGRA30_CLK_I2S1_SYNC }, + { .con_id = "i2s2_sync", .dt_id = TEGRA30_CLK_I2S2_SYNC }, + { .con_id = "i2s3_sync", .dt_id = TEGRA30_CLK_I2S3_SYNC }, + { .con_id = "i2s4_sync", .dt_id = TEGRA30_CLK_I2S4_SYNC }, + { .con_id = "vimclk_sync", .dt_id = TEGRA30_CLK_VIMCLK_SYNC }, + { .con_id = "audio0", .dt_id = TEGRA30_CLK_AUDIO0 }, + { .con_id = "audio1", .dt_id = TEGRA30_CLK_AUDIO1 }, + { .con_id = "audio2", .dt_id = TEGRA30_CLK_AUDIO2 }, + { .con_id = "audio3", .dt_id = TEGRA30_CLK_AUDIO3 }, + { .con_id = "audio4", .dt_id = TEGRA30_CLK_AUDIO4 }, + { .con_id = "spdif", .dt_id = TEGRA30_CLK_SPDIF }, + { .con_id = "audio0_2x", .dt_id = TEGRA30_CLK_AUDIO0_2X }, + { .con_id = "audio1_2x", .dt_id = TEGRA30_CLK_AUDIO1_2X }, + { .con_id = "audio2_2x", .dt_id = TEGRA30_CLK_AUDIO2_2X }, + { .con_id = "audio3_2x", .dt_id = TEGRA30_CLK_AUDIO3_2X }, + { .con_id = "audio4_2x", .dt_id = TEGRA30_CLK_AUDIO4_2X }, + { .con_id = "spdif_2x", .dt_id = TEGRA30_CLK_SPDIF_2X }, + { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA30_CLK_EXTERN1 }, + { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA30_CLK_EXTERN2 }, + { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA30_CLK_EXTERN3 }, + { .con_id = "blink", .dt_id = TEGRA30_CLK_BLINK }, + { .con_id = "cclk_g", .dt_id = TEGRA30_CLK_CCLK_G }, + { .con_id = "cclk_lp", .dt_id = TEGRA30_CLK_CCLK_LP }, + { .con_id = "sclk", .dt_id = TEGRA30_CLK_SCLK }, + { .con_id = "hclk", .dt_id = TEGRA30_CLK_HCLK }, + { .con_id = "pclk", .dt_id = TEGRA30_CLK_PCLK }, + { .con_id = "twd", .dt_id = TEGRA30_CLK_TWD }, + { .con_id = "emc", .dt_id = TEGRA30_CLK_EMC }, + { .con_id = "clk_32k", .dt_id = TEGRA30_CLK_CLK_32K }, + { .con_id = "clk_m_div2", .dt_id = TEGRA30_CLK_CLK_M_DIV2 }, + { .con_id = "clk_m_div4", .dt_id = TEGRA30_CLK_CLK_M_DIV4 }, + { .con_id = "cml0", .dt_id = TEGRA30_CLK_CML0 }, + { .con_id = "cml1", .dt_id = TEGRA30_CLK_CML1 }, + { .con_id = "clk_m", .dt_id = TEGRA30_CLK_CLK_M }, + { .con_id = "pll_ref", .dt_id = TEGRA30_CLK_PLL_REF }, + { .con_id = "csus", .dev_id = "tengra_camera", .dt_id = TEGRA30_CLK_CSUS }, + { .con_id = "vcp", .dev_id = "tegra-avp", .dt_id = TEGRA30_CLK_VCP }, + { .con_id = "bsea", .dev_id = "tegra-avp", .dt_id = TEGRA30_CLK_BSEA }, + { .con_id = "bsev", .dev_id = "tegra-aes", .dt_id = TEGRA30_CLK_BSEV }, + { .con_id = "dsia", .dev_id = "tegradc.0", .dt_id = TEGRA30_CLK_DSIA }, + { .con_id = "csi", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_CSI }, + { .con_id = "isp", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_ISP }, + { .con_id = "pcie", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIE }, + { .con_id = "afi", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_AFI }, + { .con_id = "pciex", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIEX }, + { .con_id = "fuse", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE }, + { .con_id = "fuse_burn", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE_BURN }, + { .con_id = "apbif", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_APBIF }, + { .con_id = "hda2hdmi", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2HDMI }, + { .dev_id = "tegra-apbdma", .dt_id = TEGRA30_CLK_APBDMA }, + { .dev_id = "rtc-tegra", .dt_id = TEGRA30_CLK_RTC }, + { .dev_id = "timer", .dt_id = TEGRA30_CLK_TIMER }, + { .dev_id = "tegra-kbc", .dt_id = TEGRA30_CLK_KBC }, + { .dev_id = "fsl-tegra-udc", .dt_id = TEGRA30_CLK_USBD }, + { .dev_id = "tegra-ehci.1", .dt_id = TEGRA30_CLK_USB2 }, + { .dev_id = "tegra-ehci.2", .dt_id = TEGRA30_CLK_USB2 }, + { .dev_id = "kfuse-tegra", .dt_id = TEGRA30_CLK_KFUSE }, + { .dev_id = "tegra_sata_cold", .dt_id = TEGRA30_CLK_SATA_COLD }, + { .dev_id = "dtv", .dt_id = TEGRA30_CLK_DTV }, + { .dev_id = "tegra30-i2s.0", .dt_id = TEGRA30_CLK_I2S0 }, + { .dev_id = "tegra30-i2s.1", .dt_id = TEGRA30_CLK_I2S1 }, + { .dev_id = "tegra30-i2s.2", .dt_id = TEGRA30_CLK_I2S2 }, + { .dev_id = "tegra30-i2s.3", .dt_id = TEGRA30_CLK_I2S3 }, + { .dev_id = "tegra30-i2s.4", .dt_id = TEGRA30_CLK_I2S4 }, + { .con_id = "spdif_out", .dev_id = "tegra30-spdif", .dt_id = TEGRA30_CLK_SPDIF_OUT }, + { .con_id = "spdif_in", .dev_id = "tegra30-spdif", .dt_id = TEGRA30_CLK_SPDIF_IN }, + { .con_id = "d_audio", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_D_AUDIO }, + { .dev_id = "tegra30-dam.0", .dt_id = TEGRA30_CLK_DAM0 }, + { .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 }, + { .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 }, + { .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA }, + { .con_id = "hda2codec", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X }, + { .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 }, + { .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 }, + { .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 }, + { .dev_id = "spi_tegra.3", .dt_id = TEGRA30_CLK_SBC4 }, + { .dev_id = "spi_tegra.4", .dt_id = TEGRA30_CLK_SBC5 }, + { .dev_id = "spi_tegra.5", .dt_id = TEGRA30_CLK_SBC6 }, + { .dev_id = "tegra_sata_oob", .dt_id = TEGRA30_CLK_SATA_OOB }, + { .dev_id = "tegra_sata", .dt_id = TEGRA30_CLK_SATA }, + { .dev_id = "tegra_nand", .dt_id = TEGRA30_CLK_NDFLASH }, + { .dev_id = "tegra_nand_speed", .dt_id = TEGRA30_CLK_NDSPEED }, + { .dev_id = "vfir", .dt_id = TEGRA30_CLK_VFIR }, + { .dev_id = "csite", .dt_id = TEGRA30_CLK_CSITE }, + { .dev_id = "la", .dt_id = TEGRA30_CLK_LA }, + { .dev_id = "tegra_w1", .dt_id = TEGRA30_CLK_OWR }, + { .dev_id = "mipi", .dt_id = TEGRA30_CLK_MIPI }, + { .dev_id = "tegra-tsensor", .dt_id = TEGRA30_CLK_TSENSOR }, + { .dev_id = "i2cslow", .dt_id = TEGRA30_CLK_I2CSLOW }, + { .dev_id = "vde", .dt_id = TEGRA30_CLK_VDE }, + { .con_id = "vi", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_VI }, + { .dev_id = "epp", .dt_id = TEGRA30_CLK_EPP }, + { .dev_id = "mpe", .dt_id = TEGRA30_CLK_MPE }, + { .dev_id = "host1x", .dt_id = TEGRA30_CLK_HOST1X }, + { .dev_id = "3d", .dt_id = TEGRA30_CLK_GR3D }, + { .dev_id = "3d2", .dt_id = TEGRA30_CLK_GR3D2 }, + { .dev_id = "2d", .dt_id = TEGRA30_CLK_GR2D }, + { .dev_id = "se", .dt_id = TEGRA30_CLK_SE }, + { .dev_id = "mselect", .dt_id = TEGRA30_CLK_MSELECT }, + { .dev_id = "tegra-nor", .dt_id = TEGRA30_CLK_NOR }, + { .dev_id = "sdhci-tegra.0", .dt_id = TEGRA30_CLK_SDMMC1 }, + { .dev_id = "sdhci-tegra.1", .dt_id = TEGRA30_CLK_SDMMC2 }, + { .dev_id = "sdhci-tegra.2", .dt_id = TEGRA30_CLK_SDMMC3 }, + { .dev_id = "sdhci-tegra.3", .dt_id = TEGRA30_CLK_SDMMC4 }, + { .dev_id = "cve", .dt_id = TEGRA30_CLK_CVE }, + { .dev_id = "tvo", .dt_id = TEGRA30_CLK_TVO }, + { .dev_id = "tvdac", .dt_id = TEGRA30_CLK_TVDAC }, + { .dev_id = "actmon", .dt_id = TEGRA30_CLK_ACTMON }, + { .con_id = "vi_sensor", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_VI_SENSOR }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.0", .dt_id = TEGRA30_CLK_I2C1 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.1", .dt_id = TEGRA30_CLK_I2C2 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.2", .dt_id = TEGRA30_CLK_I2C3 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.3", .dt_id = TEGRA30_CLK_I2C4 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.4", .dt_id = TEGRA30_CLK_I2C5 }, + { .dev_id = "tegra_uart.0", .dt_id = TEGRA30_CLK_UARTA }, + { .dev_id = "tegra_uart.1", .dt_id = TEGRA30_CLK_UARTB }, + { .dev_id = "tegra_uart.2", .dt_id = TEGRA30_CLK_UARTC }, + { .dev_id = "tegra_uart.3", .dt_id = TEGRA30_CLK_UARTD }, + { .dev_id = "tegra_uart.4", .dt_id = TEGRA30_CLK_UARTE }, + { .dev_id = "hdmi", .dt_id = TEGRA30_CLK_HDMI }, + { .dev_id = "extern1", .dt_id = TEGRA30_CLK_EXTERN1 }, + { .dev_id = "extern2", .dt_id = TEGRA30_CLK_EXTERN2 }, + { .dev_id = "extern3", .dt_id = TEGRA30_CLK_EXTERN3 }, + { .dev_id = "pwm", .dt_id = TEGRA30_CLK_PWM }, + { .dev_id = "tegradc.0", .dt_id = TEGRA30_CLK_DISP1 }, + { .dev_id = "tegradc.1", .dt_id = TEGRA30_CLK_DISP2 }, + { .dev_id = "tegradc.1", .dt_id = TEGRA30_CLK_DSIB }, +}; + +static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { + [tegra_clk_clk_32k] = { .dt_id = TEGRA30_CLK_CLK_32K, .present = true }, + [tegra_clk_clk_m] = { .dt_id = TEGRA30_CLK_CLK_M, .present = true }, + [tegra_clk_clk_m_div2] = { .dt_id = TEGRA30_CLK_CLK_M_DIV2, .present = true }, + [tegra_clk_clk_m_div4] = { .dt_id = TEGRA30_CLK_CLK_M_DIV4, .present = true }, + [tegra_clk_pll_ref] = { .dt_id = TEGRA30_CLK_PLL_REF, .present = true }, + [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA30_CLK_SPDIF_IN_SYNC, .present = true }, + [tegra_clk_i2s0_sync] = { .dt_id = TEGRA30_CLK_I2S0_SYNC, .present = true }, + [tegra_clk_i2s1_sync] = { .dt_id = TEGRA30_CLK_I2S1_SYNC, .present = true }, + [tegra_clk_i2s2_sync] = { .dt_id = TEGRA30_CLK_I2S2_SYNC, .present = true }, + [tegra_clk_i2s3_sync] = { .dt_id = TEGRA30_CLK_I2S3_SYNC, .present = true }, + [tegra_clk_i2s4_sync] = { .dt_id = TEGRA30_CLK_I2S4_SYNC, .present = true }, + [tegra_clk_vimclk_sync] = { .dt_id = TEGRA30_CLK_VIMCLK_SYNC, .present = true }, + [tegra_clk_audio0] = { .dt_id = TEGRA30_CLK_AUDIO0, .present = true }, + [tegra_clk_audio1] = { .dt_id = TEGRA30_CLK_AUDIO1, .present = true }, + [tegra_clk_audio2] = { .dt_id = TEGRA30_CLK_AUDIO2, .present = true }, + [tegra_clk_audio3] = { .dt_id = TEGRA30_CLK_AUDIO3, .present = true }, + [tegra_clk_audio4] = { .dt_id = TEGRA30_CLK_AUDIO4, .present = true }, + [tegra_clk_spdif] = { .dt_id = TEGRA30_CLK_SPDIF, .present = true }, + [tegra_clk_audio0_mux] = { .dt_id = TEGRA30_CLK_AUDIO0_MUX, .present = true }, + [tegra_clk_audio1_mux] = { .dt_id = TEGRA30_CLK_AUDIO1_MUX, .present = true }, + [tegra_clk_audio2_mux] = { .dt_id = TEGRA30_CLK_AUDIO2_MUX, .present = true }, + [tegra_clk_audio3_mux] = { .dt_id = TEGRA30_CLK_AUDIO3_MUX, .present = true }, + [tegra_clk_audio4_mux] = { .dt_id = TEGRA30_CLK_AUDIO4_MUX, .present = true }, + [tegra_clk_spdif_mux] = { .dt_id = TEGRA30_CLK_SPDIF_MUX, .present = true }, + [tegra_clk_audio0_2x] = { .dt_id = TEGRA30_CLK_AUDIO0_2X, .present = true }, + [tegra_clk_audio1_2x] = { .dt_id = TEGRA30_CLK_AUDIO1_2X, .present = true }, + [tegra_clk_audio2_2x] = { .dt_id = TEGRA30_CLK_AUDIO2_2X, .present = true }, + [tegra_clk_audio3_2x] = { .dt_id = TEGRA30_CLK_AUDIO3_2X, .present = true }, + [tegra_clk_audio4_2x] = { .dt_id = TEGRA30_CLK_AUDIO4_2X, .present = true }, + [tegra_clk_spdif_2x] = { .dt_id = TEGRA30_CLK_SPDIF_2X, .present = true }, + [tegra_clk_clk_out_1] = { .dt_id = TEGRA30_CLK_CLK_OUT_1, .present = true }, + [tegra_clk_clk_out_2] = { .dt_id = TEGRA30_CLK_CLK_OUT_2, .present = true }, + [tegra_clk_clk_out_3] = { .dt_id = TEGRA30_CLK_CLK_OUT_3, .present = true }, + [tegra_clk_blink] = { .dt_id = TEGRA30_CLK_BLINK, .present = true }, + [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_1_MUX, .present = true }, + [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_2_MUX, .present = true }, + [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_3_MUX, .present = true }, + [tegra_clk_hclk] = { .dt_id = TEGRA30_CLK_HCLK, .present = true }, + [tegra_clk_pclk] = { .dt_id = TEGRA30_CLK_PCLK, .present = true }, + [tegra_clk_i2s0] = { .dt_id = TEGRA30_CLK_I2S0, .present = true }, + [tegra_clk_i2s1] = { .dt_id = TEGRA30_CLK_I2S1, .present = true }, + [tegra_clk_i2s2] = { .dt_id = TEGRA30_CLK_I2S2, .present = true }, + [tegra_clk_i2s3] = { .dt_id = TEGRA30_CLK_I2S3, .present = true }, + [tegra_clk_i2s4] = { .dt_id = TEGRA30_CLK_I2S4, .present = true }, + [tegra_clk_spdif_in] = { .dt_id = TEGRA30_CLK_SPDIF_IN, .present = true }, + [tegra_clk_hda] = { .dt_id = TEGRA30_CLK_HDA, .present = true }, + [tegra_clk_hda2codec_2x] = { .dt_id = TEGRA30_CLK_HDA2CODEC_2X, .present = true }, + [tegra_clk_sbc1] = { .dt_id = TEGRA30_CLK_SBC1, .present = true }, + [tegra_clk_sbc2] = { .dt_id = TEGRA30_CLK_SBC2, .present = true }, + [tegra_clk_sbc3] = { .dt_id = TEGRA30_CLK_SBC3, .present = true }, + [tegra_clk_sbc4] = { .dt_id = TEGRA30_CLK_SBC4, .present = true }, + [tegra_clk_sbc5] = { .dt_id = TEGRA30_CLK_SBC5, .present = true }, + [tegra_clk_sbc6] = { .dt_id = TEGRA30_CLK_SBC6, .present = true }, + [tegra_clk_ndflash] = { .dt_id = TEGRA30_CLK_NDFLASH, .present = true }, + [tegra_clk_ndspeed] = { .dt_id = TEGRA30_CLK_NDSPEED, .present = true }, + [tegra_clk_vfir] = { .dt_id = TEGRA30_CLK_VFIR, .present = true }, + [tegra_clk_la] = { .dt_id = TEGRA30_CLK_LA, .present = true }, + [tegra_clk_csite] = { .dt_id = TEGRA30_CLK_CSITE, .present = true }, + [tegra_clk_owr] = { .dt_id = TEGRA30_CLK_OWR, .present = true }, + [tegra_clk_mipi] = { .dt_id = TEGRA30_CLK_MIPI, .present = true }, + [tegra_clk_tsensor] = { .dt_id = TEGRA30_CLK_TSENSOR, .present = true }, + [tegra_clk_i2cslow] = { .dt_id = TEGRA30_CLK_I2CSLOW, .present = true }, + [tegra_clk_vde] = { .dt_id = TEGRA30_CLK_VDE, .present = true }, + [tegra_clk_vi] = { .dt_id = TEGRA30_CLK_VI, .present = true }, + [tegra_clk_epp] = { .dt_id = TEGRA30_CLK_EPP, .present = true }, + [tegra_clk_mpe] = { .dt_id = TEGRA30_CLK_MPE, .present = true }, + [tegra_clk_host1x] = { .dt_id = TEGRA30_CLK_HOST1X, .present = true }, + [tegra_clk_gr2d] = { .dt_id = TEGRA30_CLK_GR2D, .present = true }, + [tegra_clk_gr3d] = { .dt_id = TEGRA30_CLK_GR3D, .present = true }, + [tegra_clk_mselect] = { .dt_id = TEGRA30_CLK_MSELECT, .present = true }, + [tegra_clk_nor] = { .dt_id = TEGRA30_CLK_NOR, .present = true }, + [tegra_clk_sdmmc1] = { .dt_id = TEGRA30_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc2] = { .dt_id = TEGRA30_CLK_SDMMC2, .present = true }, + [tegra_clk_sdmmc3] = { .dt_id = TEGRA30_CLK_SDMMC3, .present = true }, + [tegra_clk_sdmmc4] = { .dt_id = TEGRA30_CLK_SDMMC4, .present = true }, + [tegra_clk_cve] = { .dt_id = TEGRA30_CLK_CVE, .present = true }, + [tegra_clk_tvo] = { .dt_id = TEGRA30_CLK_TVO, .present = true }, + [tegra_clk_tvdac] = { .dt_id = TEGRA30_CLK_TVDAC, .present = true }, + [tegra_clk_actmon] = { .dt_id = TEGRA30_CLK_ACTMON, .present = true }, + [tegra_clk_vi_sensor] = { .dt_id = TEGRA30_CLK_VI_SENSOR, .present = true }, + [tegra_clk_i2c1] = { .dt_id = TEGRA30_CLK_I2C1, .present = true }, + [tegra_clk_i2c2] = { .dt_id = TEGRA30_CLK_I2C2, .present = true }, + [tegra_clk_i2c3] = { .dt_id = TEGRA30_CLK_I2C3, .present = true }, + [tegra_clk_i2c4] = { .dt_id = TEGRA30_CLK_I2C4, .present = true }, + [tegra_clk_i2c5] = { .dt_id = TEGRA30_CLK_I2C5, .present = true }, + [tegra_clk_uarta] = { .dt_id = TEGRA30_CLK_UARTA, .present = true }, + [tegra_clk_uartb] = { .dt_id = TEGRA30_CLK_UARTB, .present = true }, + [tegra_clk_uartc] = { .dt_id = TEGRA30_CLK_UARTC, .present = true }, + [tegra_clk_uartd] = { .dt_id = TEGRA30_CLK_UARTD, .present = true }, + [tegra_clk_uarte] = { .dt_id = TEGRA30_CLK_UARTE, .present = true }, + [tegra_clk_extern1] = { .dt_id = TEGRA30_CLK_EXTERN1, .present = true }, + [tegra_clk_extern2] = { .dt_id = TEGRA30_CLK_EXTERN2, .present = true }, + [tegra_clk_extern3] = { .dt_id = TEGRA30_CLK_EXTERN3, .present = true }, + [tegra_clk_pwm] = { .dt_id = TEGRA30_CLK_PWM, .present = true }, + [tegra_clk_disp1] = { .dt_id = TEGRA30_CLK_DISP1, .present = true }, + [tegra_clk_disp2] = { .dt_id = TEGRA30_CLK_DISP2, .present = true }, + [tegra_clk_apbdma] = { .dt_id = TEGRA30_CLK_APBDMA, .present = true }, + [tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true }, + [tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true }, + [tegra_clk_kbc] = { .dt_id = TEGRA30_CLK_KBC, .present = true }, + [tegra_clk_csus] = { .dt_id = TEGRA30_CLK_CSUS, .present = true }, + [tegra_clk_vcp] = { .dt_id = TEGRA30_CLK_VCP, .present = true }, + [tegra_clk_bsea] = { .dt_id = TEGRA30_CLK_BSEA, .present = true }, + [tegra_clk_bsev] = { .dt_id = TEGRA30_CLK_BSEV, .present = true }, + [tegra_clk_usbd] = { .dt_id = TEGRA30_CLK_USBD, .present = true }, + [tegra_clk_usb2] = { .dt_id = TEGRA30_CLK_USB2, .present = true }, + [tegra_clk_usb3] = { .dt_id = TEGRA30_CLK_USB3, .present = true }, + [tegra_clk_csi] = { .dt_id = TEGRA30_CLK_CSI, .present = true }, + [tegra_clk_isp] = { .dt_id = TEGRA30_CLK_ISP, .present = true }, + [tegra_clk_kfuse] = { .dt_id = TEGRA30_CLK_KFUSE, .present = true }, + [tegra_clk_fuse] = { .dt_id = TEGRA30_CLK_FUSE, .present = true }, + [tegra_clk_fuse_burn] = { .dt_id = TEGRA30_CLK_FUSE_BURN, .present = true }, + [tegra_clk_apbif] = { .dt_id = TEGRA30_CLK_APBIF, .present = true }, + [tegra_clk_hda2hdmi] = { .dt_id = TEGRA30_CLK_HDA2HDMI, .present = true }, + [tegra_clk_sata_cold] = { .dt_id = TEGRA30_CLK_SATA_COLD, .present = true }, + [tegra_clk_sata_oob] = { .dt_id = TEGRA30_CLK_SATA_OOB, .present = true }, + [tegra_clk_sata] = { .dt_id = TEGRA30_CLK_SATA, .present = true }, + [tegra_clk_dtv] = { .dt_id = TEGRA30_CLK_DTV, .present = true }, + [tegra_clk_pll_p] = { .dt_id = TEGRA30_CLK_PLL_P, .present = true }, + [tegra_clk_pll_p_out1] = { .dt_id = TEGRA30_CLK_PLL_P_OUT1, .present = true }, + [tegra_clk_pll_p_out2] = { .dt_id = TEGRA30_CLK_PLL_P_OUT2, .present = true }, + [tegra_clk_pll_p_out3] = { .dt_id = TEGRA30_CLK_PLL_P_OUT3, .present = true }, + [tegra_clk_pll_p_out4] = { .dt_id = TEGRA30_CLK_PLL_P_OUT4, .present = true }, + [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true }, + [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true }, + +}; static void tegra30_utmi_param_configure(void) { @@ -809,8 +924,7 @@ static void __init tegra30_pll_init(void) /* PLLC */ clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0, &pll_c_params, NULL); - clk_register_clkdev(clk, "pll_c", NULL); - clks[pll_c] = clk; + clks[TEGRA30_CLK_PLL_C] = clk; /* PLLC_OUT1 */ clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", @@ -819,69 +933,13 @@ static void __init tegra30_pll_init(void) clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_c_out1", NULL); - clks[pll_c_out1] = clk; - - /* PLLP */ - clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc_base, 0, - &pll_p_params, NULL); - clk_register_clkdev(clk, "pll_p", NULL); - clks[pll_p] = clk; - - /* PLLP_OUT1 */ - clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", - clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, - &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", - clk_base + PLLP_OUTA, 1, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out1", NULL); - clks[pll_p_out1] = clk; - - /* PLLP_OUT2 */ - clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", - clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, - &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", - clk_base + PLLP_OUTA, 17, 16, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out2", NULL); - clks[pll_p_out2] = clk; - - /* PLLP_OUT3 */ - clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", - clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, - &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", - clk_base + PLLP_OUTB, 1, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out3", NULL); - clks[pll_p_out3] = clk; - - /* PLLP_OUT4 */ - clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", - clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | - TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, - &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", - clk_base + PLLP_OUTB, 17, 16, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out4", NULL); - clks[pll_p_out4] = clk; + clks[TEGRA30_CLK_PLL_C_OUT1] = clk; /* PLLM */ clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base, CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, &pll_m_params, NULL); - clk_register_clkdev(clk, "pll_m", NULL); - clks[pll_m] = clk; + clks[TEGRA30_CLK_PLL_M] = clk; /* PLLM_OUT1 */ clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", @@ -890,68 +948,44 @@ static void __init tegra30_pll_init(void) clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_m_out1", NULL); - clks[pll_m_out1] = clk; + clks[TEGRA30_CLK_PLL_M_OUT1] = clk; /* PLLX */ clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, pmc_base, 0, &pll_x_params, NULL); - clk_register_clkdev(clk, "pll_x", NULL); - clks[pll_x] = clk; + clks[TEGRA30_CLK_PLL_X] = clk; /* PLLX_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_x_out0", NULL); - clks[pll_x_out0] = clk; + clks[TEGRA30_CLK_PLL_X_OUT0] = clk; /* PLLU */ clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0, &pll_u_params, NULL); - clk_register_clkdev(clk, "pll_u", NULL); - clks[pll_u] = clk; + clks[TEGRA30_CLK_PLL_U] = clk; tegra30_utmi_param_configure(); /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0, &pll_d_params, &pll_d_lock); - clk_register_clkdev(clk, "pll_d", NULL); - clks[pll_d] = clk; + clks[TEGRA30_CLK_PLL_D] = clk; /* PLLD_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_d_out0", NULL); - clks[pll_d_out0] = clk; + clks[TEGRA30_CLK_PLL_D_OUT0] = clk; /* PLLD2 */ clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0, &pll_d2_params, NULL); - clk_register_clkdev(clk, "pll_d2", NULL); - clks[pll_d2] = clk; + clks[TEGRA30_CLK_PLL_D2] = clk; /* PLLD2_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_d2_out0", NULL); - clks[pll_d2_out0] = clk; - - /* PLLA */ - clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc_base, - 0, &pll_a_params, NULL); - clk_register_clkdev(clk, "pll_a", NULL); - clks[pll_a] = clk; - - /* PLLA_OUT0 */ - clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", - clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, - 8, 8, 1, NULL); - clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", - clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | - CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_a_out0", NULL); - clks[pll_a_out0] = clk; + clks[TEGRA30_CLK_PLL_D2_OUT0] = clk; /* PLLE */ clk = clk_register_mux(NULL, "pll_e_mux", pll_e_parents, @@ -960,256 +994,7 @@ static void __init tegra30_pll_init(void) clk_base + PLLE_AUX, 2, 1, 0, NULL); clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base, CLK_GET_RATE_NOCACHE, &pll_e_params, NULL); - clk_register_clkdev(clk, "pll_e", NULL); - clks[pll_e] = clk; -} - -static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", - "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",}; -static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", - "clk_m_div4", "extern1", }; -static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", - "clk_m_div4", "extern2", }; -static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", - "clk_m_div4", "extern3", }; - -static void __init tegra30_audio_clk_init(void) -{ - struct clk *clk; - - /* spdif_in_sync */ - clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000, - 24000000); - clk_register_clkdev(clk, "spdif_in_sync", NULL); - clks[spdif_in_sync] = clk; - - /* i2s0_sync */ - clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s0_sync", NULL); - clks[i2s0_sync] = clk; - - /* i2s1_sync */ - clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s1_sync", NULL); - clks[i2s1_sync] = clk; - - /* i2s2_sync */ - clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s2_sync", NULL); - clks[i2s2_sync] = clk; - - /* i2s3_sync */ - clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s3_sync", NULL); - clks[i2s3_sync] = clk; - - /* i2s4_sync */ - clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000); - clk_register_clkdev(clk, "i2s4_sync", NULL); - clks[i2s4_sync] = clk; - - /* vimclk_sync */ - clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000); - clk_register_clkdev(clk, "vimclk_sync", NULL); - clks[vimclk_sync] = clk; - - /* audio0 */ - clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL); - clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S0, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio0", NULL); - clks[audio0] = clk; - - /* audio1 */ - clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL); - clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S1, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio1", NULL); - clks[audio1] = clk; - - /* audio2 */ - clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL); - clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S2, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio2", NULL); - clks[audio2] = clk; - - /* audio3 */ - clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL); - clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S3, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio3", NULL); - clks[audio3] = clk; - - /* audio4 */ - clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL); - clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, - clk_base + AUDIO_SYNC_CLK_I2S4, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio4", NULL); - clks[audio4] = clk; - - /* spdif */ - clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL); - clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, - clk_base + AUDIO_SYNC_CLK_SPDIF, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "spdif", NULL); - clks[spdif] = clk; - - /* audio0_2x */ - clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio0_div", "audio0_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1, 0, - &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 113, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio0_2x", NULL); - clks[audio0_2x] = clk; - - /* audio1_2x */ - clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio1_div", "audio1_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1, 0, - &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 114, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio1_2x", NULL); - clks[audio1_2x] = clk; - - /* audio2_2x */ - clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio2_div", "audio2_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1, 0, - &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 115, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio2_2x", NULL); - clks[audio2_2x] = clk; - - /* audio3_2x */ - clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio3_div", "audio3_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1, 0, - &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 116, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio3_2x", NULL); - clks[audio3_2x] = clk; - - /* audio4_2x */ - clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("audio4_div", "audio4_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1, 0, - &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 117, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio4_2x", NULL); - clks[audio4_2x] = clk; - - /* spdif_2x */ - clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif", - CLK_SET_RATE_PARENT, 2, 1); - clk = tegra_clk_register_divider("spdif_div", "spdif_doubler", - clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1, 0, - &clk_doubler_lock); - clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div", - TEGRA_PERIPH_NO_RESET, clk_base, - CLK_SET_RATE_PARENT, 118, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "spdif_2x", NULL); - clks[spdif_2x] = clk; -} - -static void __init tegra30_pmc_clk_init(void) -{ - struct clk *clk; - - /* clk_out_1 */ - clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, - ARRAY_SIZE(clk_out1_parents), - CLK_SET_RATE_NO_REPARENT, - pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, - &clk_out_lock); - clks[clk_out_1_mux] = clk; - clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, - pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, - &clk_out_lock); - clk_register_clkdev(clk, "extern1", "clk_out_1"); - clks[clk_out_1] = clk; - - /* clk_out_2 */ - clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, - ARRAY_SIZE(clk_out2_parents), - CLK_SET_RATE_NO_REPARENT, - pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, - &clk_out_lock); - clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, - pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, - &clk_out_lock); - clk_register_clkdev(clk, "extern2", "clk_out_2"); - clks[clk_out_2] = clk; - - /* clk_out_3 */ - clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, - ARRAY_SIZE(clk_out3_parents), - CLK_SET_RATE_NO_REPARENT, - pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, - &clk_out_lock); - clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, - pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, - &clk_out_lock); - clk_register_clkdev(clk, "extern3", "clk_out_3"); - clks[clk_out_3] = clk; - - /* blink */ - writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); - clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, - pmc_base + PMC_DPD_PADS_ORIDE, - PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); - clk = clk_register_gate(NULL, "blink", "blink_override", 0, - pmc_base + PMC_CTRL, - PMC_CTRL_BLINK_ENB, 0, NULL); - clk_register_clkdev(clk, "blink", NULL); - clks[blink] = clk; - + clks[TEGRA30_CLK_PLL_E] = clk; } static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", @@ -1260,8 +1045,7 @@ static void __init tegra30_super_clk_init(void) CLK_SET_RATE_PARENT, clk_base + CCLKG_BURST_POLICY, 0, 4, 0, 0, NULL); - clk_register_clkdev(clk, "cclk_g", NULL); - clks[cclk_g] = clk; + clks[TEGRA30_CLK_CCLK_G] = clk; /* * Clock input to cclk_lp divided from pll_p using @@ -1297,8 +1081,7 @@ static void __init tegra30_super_clk_init(void) clk_base + CCLKLP_BURST_POLICY, TEGRA_DIVIDER_2, 4, 8, 9, NULL); - clk_register_clkdev(clk, "cclk_lp", NULL); - clks[cclk_lp] = clk; + clks[TEGRA30_CLK_CCLK_LP] = clk; /* SCLK */ clk = tegra_clk_register_super_mux("sclk", sclk_parents, @@ -1306,142 +1089,42 @@ static void __init tegra30_super_clk_init(void) CLK_SET_RATE_PARENT, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); - clk_register_clkdev(clk, "sclk", NULL); - clks[sclk] = clk; - - /* HCLK */ - clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, - clk_base + SYSTEM_CLK_RATE, 4, 2, 0, - &sysrate_lock); - clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT, - clk_base + SYSTEM_CLK_RATE, 7, - CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clk_register_clkdev(clk, "hclk", NULL); - clks[hclk] = clk; - - /* PCLK */ - clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, - clk_base + SYSTEM_CLK_RATE, 0, 2, 0, - &sysrate_lock); - clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT, - clk_base + SYSTEM_CLK_RATE, 3, - CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clk_register_clkdev(clk, "pclk", NULL); - clks[pclk] = clk; + clks[TEGRA30_CLK_SCLK] = clk; /* twd */ clk = clk_register_fixed_factor(NULL, "twd", "cclk_g", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "twd", NULL); - clks[twd] = clk; + clks[TEGRA30_CLK_TWD] = clk; + + tegra_super_clk_gen4_init(clk_base, pmc_base, tegra30_clks, NULL); } static const char *mux_pllacp_clkm[] = { "pll_a_out0", "unused", "pll_p", "clk_m" }; static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" }; static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" }; -static const char *i2s0_parents[] = { "pll_a_out0", "audio0_2x", "pll_p", - "clk_m" }; -static const char *i2s1_parents[] = { "pll_a_out0", "audio1_2x", "pll_p", - "clk_m" }; -static const char *i2s2_parents[] = { "pll_a_out0", "audio2_2x", "pll_p", - "clk_m" }; -static const char *i2s3_parents[] = { "pll_a_out0", "audio3_2x", "pll_p", - "clk_m" }; -static const char *i2s4_parents[] = { "pll_a_out0", "audio4_2x", "pll_p", - "clk_m" }; static const char *spdif_out_parents[] = { "pll_a_out0", "spdif_2x", "pll_p", "clk_m" }; -static const char *spdif_in_parents[] = { "pll_p", "pll_c", "pll_m" }; -static const char *mux_pllpc_clk32k_clkm[] = { "pll_p", "pll_c", "clk_32k", - "clk_m" }; -static const char *mux_pllpc_clkm_clk32k[] = { "pll_p", "pll_c", "clk_m", - "clk_32k" }; static const char *mux_pllmcpa[] = { "pll_m", "pll_c", "pll_p", "pll_a_out0" }; -static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c", - "clk_m" }; -static const char *mux_pllp_clkm[] = { "pll_p", "unused", "unused", "clk_m" }; static const char *mux_pllpmdacd2_clkm[] = { "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c", "pll_d2_out0", "clk_m" }; -static const char *mux_plla_clk32k_pllp_clkm_plle[] = { "pll_a_out0", - "clk_32k", "pll_p", - "clk_m", "pll_e" }; static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0", "pll_d2_out0" }; static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", i2s0_parents, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, i2s0), - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, i2s1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", i2s2_parents, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, i2s2), - TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", i2s3_parents, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, i2s3), - TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", i2s4_parents, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, i2s4), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, spdif_out), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, spdif_in), - TEGRA_INIT_DATA_MUX("d_audio", "d_audio", "tegra30-ahub", mux_pllacp_clkm, CLK_SOURCE_D_AUDIO, 106, 0, d_audio), - TEGRA_INIT_DATA_MUX("dam0", NULL, "tegra30-dam.0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, dam0), - TEGRA_INIT_DATA_MUX("dam1", NULL, "tegra30-dam.1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, dam1), - TEGRA_INIT_DATA_MUX("dam2", NULL, "tegra30-dam.2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, dam2), - TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA, 125, 0, hda), - TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, 0, hda2codec_2x), - TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, sbc1), - TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, sbc2), - TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, sbc3), - TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, sbc4), - TEGRA_INIT_DATA_MUX("sbc5", NULL, "spi_tegra.4", mux_pllpcm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, sbc5), - TEGRA_INIT_DATA_MUX("sbc6", NULL, "spi_tegra.5", mux_pllpcm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, sbc6), - TEGRA_INIT_DATA_MUX("sata_oob", NULL, "tegra_sata_oob", mux_pllpcm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, sata_oob), - TEGRA_INIT_DATA_MUX("sata", NULL, "tegra_sata", mux_pllpcm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, sata), - TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, ndflash), - TEGRA_INIT_DATA_MUX("ndspeed", NULL, "tegra_nand_speed", mux_pllpcm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, ndspeed), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, vfir), - TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, csite), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, la), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, owr), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, mipi), - TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllpc_clkm_clk32k, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, tsensor), - TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllpc_clk32k_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, i2cslow), - TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, 0, vde), - TEGRA_INIT_DATA_INT("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, 0, vi), - TEGRA_INIT_DATA_INT("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, 0, epp), - TEGRA_INIT_DATA_INT("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, 0, mpe), - TEGRA_INIT_DATA_INT("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, 0, host1x), - TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, TEGRA_PERIPH_MANUAL_RESET, gr3d), - TEGRA_INIT_DATA_INT("3d2", NULL, "3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, gr3d2), - TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, 0, gr2d), - TEGRA_INIT_DATA_INT("se", NULL, "se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, se), - TEGRA_INIT_DATA_MUX("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, mselect), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, 0, nor), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, 0, sdmmc1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, 0, sdmmc2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, 0, sdmmc3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, 0, sdmmc4), - TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, 0, cve), - TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, 0, tvo), - TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, 0, tvdac), - TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllpc_clk32k_clkm, CLK_SOURCE_ACTMON, 119, 0, actmon), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, vi_sensor), - TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, TEGRA_PERIPH_ON_APB, i2c1), - TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, TEGRA_PERIPH_ON_APB, i2c2), - TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, TEGRA_PERIPH_ON_APB, i2c3), - TEGRA_INIT_DATA_DIV16("i2c4", "div-clk", "tegra-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, TEGRA_PERIPH_ON_APB, i2c4), - TEGRA_INIT_DATA_DIV16("i2c5", "div-clk", "tegra-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, TEGRA_PERIPH_ON_APB, i2c5), - TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 6, uarta), - TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 7, uartb), - TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 55, uartc), - TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 65, uartd), - TEGRA_INIT_DATA_UART("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 66, uarte), - TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, hdmi), - TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, extern1), - TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, extern2), - TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, extern3), - TEGRA_INIT_DATA("pwm", NULL, "pwm", mux_pllpc_clk32k_clkm, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, 0, pwm), + TEGRA_INIT_DATA_MUX("spdif_out", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_SPDIF_OUT), + TEGRA_INIT_DATA_MUX("d_audio", mux_pllacp_clkm, CLK_SOURCE_D_AUDIO, 106, 0, TEGRA30_CLK_D_AUDIO), + TEGRA_INIT_DATA_MUX("dam0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, TEGRA30_CLK_DAM0), + TEGRA_INIT_DATA_MUX("dam1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, TEGRA30_CLK_DAM1), + TEGRA_INIT_DATA_MUX("dam2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, TEGRA30_CLK_DAM2), + TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, TEGRA30_CLK_GR3D2), + TEGRA_INIT_DATA_INT("se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, TEGRA30_CLK_SE), + TEGRA_INIT_DATA_MUX8("hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA30_CLK_HDMI), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP1, 29, 3, 27, 0, disp1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP2, 29, 3, 26, 0, disp2), - TEGRA_INIT_DATA_NODIV("dsib", NULL, "tegradc.1", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB, 25, 1, 82, 0, dsib), + TEGRA_INIT_DATA_NODIV("dsib", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB, 25, 1, 82, 0, TEGRA30_CLK_DSIB), }; static void __init tegra30_periph_clk_init(void) @@ -1450,158 +1133,25 @@ static void __init tegra30_periph_clk_init(void) struct clk *clk; int i; - /* apbdma */ - clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, 0, 34, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-apbdma"); - clks[apbdma] = clk; - - /* rtc */ - clk = tegra_clk_register_periph_gate("rtc", "clk_32k", - TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 4, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "rtc-tegra"); - clks[rtc] = clk; - - /* timer */ - clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0, - 5, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "timer"); - clks[timer] = clk; - - /* kbc */ - clk = tegra_clk_register_periph_gate("kbc", "clk_32k", - TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 36, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-kbc"); - clks[kbc] = clk; - - /* csus */ - clk = tegra_clk_register_periph_gate("csus", "clk_m", - TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 92, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "csus", "tengra_camera"); - clks[csus] = clk; - - /* vcp */ - clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, 29, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "vcp", "tegra-avp"); - clks[vcp] = clk; - - /* bsea */ - clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, 0, - 62, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "bsea", "tegra-avp"); - clks[bsea] = clk; - - /* bsev */ - clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, 0, - 63, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "bsev", "tegra-aes"); - clks[bsev] = clk; - - /* usbd */ - clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, - 22, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); - clks[usbd] = clk; - - /* usb2 */ - clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, - 58, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-ehci.1"); - clks[usb2] = clk; - - /* usb3 */ - clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, - 59, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-ehci.2"); - clks[usb3] = clk; - /* dsia */ clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base, 0, 48, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "dsia", "tegradc.0"); - clks[dsia] = clk; - - /* csi */ - clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, - 0, 52, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "csi", "tegra_camera"); - clks[csi] = clk; - - /* isp */ - clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "isp", "tegra_camera"); - clks[isp] = clk; + clks[TEGRA30_CLK_DSIA] = clk; /* pcie */ clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0, 70, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "pcie", "tegra-pcie"); - clks[pcie] = clk; + clks[TEGRA30_CLK_PCIE] = clk; /* afi */ clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "afi", "tegra-pcie"); - clks[afi] = clk; + clks[TEGRA30_CLK_AFI] = clk; /* pciex */ clk = tegra_clk_register_periph_gate("pciex", "pll_e", 0, clk_base, 0, 74, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "pciex", "tegra-pcie"); - clks[pciex] = clk; - - /* kfuse */ - clk = tegra_clk_register_periph_gate("kfuse", "clk_m", - TEGRA_PERIPH_ON_APB, - clk_base, 0, 40, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "kfuse-tegra"); - clks[kfuse] = clk; - - /* fuse */ - clk = tegra_clk_register_periph_gate("fuse", "clk_m", - TEGRA_PERIPH_ON_APB, - clk_base, 0, 39, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "fuse", "fuse-tegra"); - clks[fuse] = clk; - - /* fuse_burn */ - clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", - TEGRA_PERIPH_ON_APB, - clk_base, 0, 39, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "fuse_burn", "fuse-tegra"); - clks[fuse_burn] = clk; - - /* apbif */ - clk = tegra_clk_register_periph_gate("apbif", "clk_m", 0, - clk_base, 0, 107, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "apbif", "tegra30-ahub"); - clks[apbif] = clk; - - /* hda2hdmi */ - clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", - TEGRA_PERIPH_ON_APB, - clk_base, 0, 128, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda"); - clks[hda2hdmi] = clk; - - /* sata_cold */ - clk = tegra_clk_register_periph_gate("sata_cold", "clk_m", - TEGRA_PERIPH_ON_APB, - clk_base, 0, 129, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra_sata_cold"); - clks[sata_cold] = clk; - - /* dtv */ - clk = tegra_clk_register_periph_gate("dtv", "clk_m", - TEGRA_PERIPH_ON_APB, - clk_base, 0, 79, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "dtv"); - clks[dtv] = clk; + clks[TEGRA30_CLK_PCIEX] = clk; /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, @@ -1611,15 +1161,23 @@ static void __init tegra30_periph_clk_init(void) 30, 2, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, 57, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "emc", NULL); - clks[emc] = clk; + clks[TEGRA30_CLK_EMC] = clk; + + /* cml0 */ + clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX, + 0, 0, &cml_lock); + clks[TEGRA30_CLK_CML0] = clk; + + /* cml1 */ + clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX, + 1, 0, &cml_lock); + clks[TEGRA30_CLK_CML1] = clk; for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; clk = tegra_clk_register_periph(data->name, data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset, data->flags); - clk_register_clkdev(clk, data->con_id, data->dev_id); clks[data->clk_id] = clk; } @@ -1629,65 +1187,10 @@ static void __init tegra30_periph_clk_init(void) data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset); - clk_register_clkdev(clk, data->con_id, data->dev_id); clks[data->clk_id] = clk; } -} - -static void __init tegra30_fixed_clk_init(void) -{ - struct clk *clk; - - /* clk_32k */ - clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, - 32768); - clk_register_clkdev(clk, "clk_32k", NULL); - clks[clk_32k] = clk; - - /* clk_m_div2 */ - clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", - CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "clk_m_div2", NULL); - clks[clk_m_div2] = clk; - - /* clk_m_div4 */ - clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", - CLK_SET_RATE_PARENT, 1, 4); - clk_register_clkdev(clk, "clk_m_div4", NULL); - clks[clk_m_div4] = clk; - - /* cml0 */ - clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX, - 0, 0, &cml_lock); - clk_register_clkdev(clk, "cml0", NULL); - clks[cml0] = clk; - /* cml1 */ - clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX, - 1, 0, &cml_lock); - clk_register_clkdev(clk, "cml1", NULL); - clks[cml1] = clk; -} - -static void __init tegra30_osc_clk_init(void) -{ - struct clk *clk; - unsigned int pll_ref_div; - - tegra30_clk_measure_input_freq(); - - /* clk_m */ - clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, - input_freq); - clk_register_clkdev(clk, "clk_m", NULL); - clks[clk_m] = clk; - - /* pll_ref */ - pll_ref_div = tegra30_get_pll_ref_div(); - clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", - CLK_SET_RATE_PARENT, 1, pll_ref_div); - clk_register_clkdev(clk, "pll_ref", NULL); - clks[pll_ref] = clk; + tegra_periph_clk_init(clk_base, pmc_base, tegra30_clks, &pll_p_params); } /* Tegra30 CPU clock and reset control functions */ @@ -1829,48 +1332,48 @@ static struct tegra_cpu_car_ops tegra30_cpu_car_ops = { }; static struct tegra_clk_init_table init_table[] __initdata = { - {uarta, pll_p, 408000000, 0}, - {uartb, pll_p, 408000000, 0}, - {uartc, pll_p, 408000000, 0}, - {uartd, pll_p, 408000000, 0}, - {uarte, pll_p, 408000000, 0}, - {pll_a, clk_max, 564480000, 1}, - {pll_a_out0, clk_max, 11289600, 1}, - {extern1, pll_a_out0, 0, 1}, - {clk_out_1_mux, extern1, 0, 0}, - {clk_out_1, clk_max, 0, 1}, - {blink, clk_max, 0, 1}, - {i2s0, pll_a_out0, 11289600, 0}, - {i2s1, pll_a_out0, 11289600, 0}, - {i2s2, pll_a_out0, 11289600, 0}, - {i2s3, pll_a_out0, 11289600, 0}, - {i2s4, pll_a_out0, 11289600, 0}, - {sdmmc1, pll_p, 48000000, 0}, - {sdmmc2, pll_p, 48000000, 0}, - {sdmmc3, pll_p, 48000000, 0}, - {pll_m, clk_max, 0, 1}, - {pclk, clk_max, 0, 1}, - {csite, clk_max, 0, 1}, - {emc, clk_max, 0, 1}, - {mselect, clk_max, 0, 1}, - {sbc1, pll_p, 100000000, 0}, - {sbc2, pll_p, 100000000, 0}, - {sbc3, pll_p, 100000000, 0}, - {sbc4, pll_p, 100000000, 0}, - {sbc5, pll_p, 100000000, 0}, - {sbc6, pll_p, 100000000, 0}, - {host1x, pll_c, 150000000, 0}, - {disp1, pll_p, 600000000, 0}, - {disp2, pll_p, 600000000, 0}, - {twd, clk_max, 0, 1}, - {gr2d, pll_c, 300000000, 0}, - {gr3d, pll_c, 300000000, 0}, - {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ + {TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 408000000, 0}, + {TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 408000000, 0}, + {TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0}, + {TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0}, + {TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0}, + {TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1}, + {TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1}, + {TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1}, + {TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0}, + {TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA30_CLK_I2S3, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA30_CLK_I2S4, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0}, + {TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0}, + {TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0}, + {TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0}, + {TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0}, + {TEGRA30_CLK_SBC3, TEGRA30_CLK_PLL_P, 100000000, 0}, + {TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0}, + {TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0}, + {TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0}, + {TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0}, + {TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0}, + {TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0}, + {TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1}, + {TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0}, + {TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0}, + {TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry. */ }; static void __init tegra30_clock_apply_init_table(void) { - tegra_init_from_table(init_table, clks, clk_max); + tegra_init_from_table(init_table, clks, TEGRA30_CLK_CLK_MAX); } /* @@ -1879,19 +1382,19 @@ static void __init tegra30_clock_apply_init_table(void) * table under two names. */ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { - TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL), - TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), - TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), - TEGRA_CLK_DUPLICATE(bsev, "tegra-avp", "bsev"), - TEGRA_CLK_DUPLICATE(bsev, "nvavp", "bsev"), - TEGRA_CLK_DUPLICATE(vde, "tegra-aes", "vde"), - TEGRA_CLK_DUPLICATE(bsea, "tegra-aes", "bsea"), - TEGRA_CLK_DUPLICATE(bsea, "nvavp", "bsea"), - TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL), - TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"), - TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"), - TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"), - TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */ + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_USBD, "utmip-pad", NULL), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_USBD, "tegra-ehci.0", NULL), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_USBD, "tegra-otg", NULL), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEV, "tegra-avp", "bsev"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEV, "nvavp", "bsev"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VDE, "tegra-aes", "vde"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEA, "tegra-aes", "bsea"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEA, "nvavp", "bsea"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML1, "tegra_sata_cml", NULL), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML0, "tegra_pcie", "cml"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_PCIEX, "tegra_pcie", "pciex"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VCP, "nvavp", "vcp"), + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL), /* MUST be the last entry */ }; static const struct of_device_id pmc_match[] __initconst = { @@ -1921,21 +1424,26 @@ static void __init tegra30_clock_init(struct device_node *np) BUG(); } - clks = tegra_clk_init(clk_max, TEGRA30_CLK_PERIPH_BANKS); + clks = tegra_clk_init(TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_PERIPH_BANKS); if (!clks) return; - tegra30_osc_clk_init(); - tegra30_fixed_clk_init(); + if (tegra_osc_clk_init(clk_base, tegra30_clks, tegra30_input_freq, + ARRAY_SIZE(tegra30_input_freq), &input_freq, NULL) < 0) + return; + + + tegra_fixed_clk_init(tegra30_clks); tegra30_pll_init(); tegra30_super_clk_init(); tegra30_periph_clk_init(); - tegra30_audio_clk_init(); - tegra30_pmc_clk_init(); + tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks, &pll_a_params); + tegra_pmc_clk_init(pmc_base, tegra30_clks); - tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); + tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX); tegra_add_of_provider(np); + tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); tegra_clk_apply_init_table = tegra30_clock_apply_init_table; -- cgit v1.2.3 From 540fc26a02a950a523a62a16d75b87f0e2103584 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 7 Oct 2013 14:49:10 +0300 Subject: clk: tegra: move tegra20 to common infra Move tegra20 to common tegra clock infrastructure. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra20.c | 657 ++++++++++++++++------------------------ 1 file changed, 255 insertions(+), 402 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 7c9af8e2c33b..be5bdbab78a6 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -22,8 +22,10 @@ #include #include #include +#include #include "clk.h" +#include "clk-id.h" #define OSC_CTRL 0x50 #define OSC_CTRL_OSC_FREQ_MASK (3<<30) @@ -94,34 +96,15 @@ #define CLK_SOURCE_I2S1 0x100 #define CLK_SOURCE_I2S2 0x104 -#define CLK_SOURCE_SPDIF_OUT 0x108 -#define CLK_SOURCE_SPDIF_IN 0x10c #define CLK_SOURCE_PWM 0x110 #define CLK_SOURCE_SPI 0x114 -#define CLK_SOURCE_SBC1 0x134 -#define CLK_SOURCE_SBC2 0x118 -#define CLK_SOURCE_SBC3 0x11c -#define CLK_SOURCE_SBC4 0x1b4 #define CLK_SOURCE_XIO 0x120 #define CLK_SOURCE_TWC 0x12c #define CLK_SOURCE_IDE 0x144 -#define CLK_SOURCE_NDFLASH 0x160 -#define CLK_SOURCE_VFIR 0x168 -#define CLK_SOURCE_SDMMC1 0x150 -#define CLK_SOURCE_SDMMC2 0x154 -#define CLK_SOURCE_SDMMC3 0x1bc -#define CLK_SOURCE_SDMMC4 0x164 -#define CLK_SOURCE_CVE 0x140 -#define CLK_SOURCE_TVO 0x188 -#define CLK_SOURCE_TVDAC 0x194 #define CLK_SOURCE_HDMI 0x18c #define CLK_SOURCE_DISP1 0x138 #define CLK_SOURCE_DISP2 0x13c #define CLK_SOURCE_CSITE 0x1d4 -#define CLK_SOURCE_LA 0x1f8 -#define CLK_SOURCE_OWR 0x1cc -#define CLK_SOURCE_NOR 0x1d0 -#define CLK_SOURCE_MIPI 0x174 #define CLK_SOURCE_I2C1 0x124 #define CLK_SOURCE_I2C2 0x198 #define CLK_SOURCE_I2C3 0x1b8 @@ -131,24 +114,10 @@ #define CLK_SOURCE_UARTC 0x1a0 #define CLK_SOURCE_UARTD 0x1c0 #define CLK_SOURCE_UARTE 0x1c4 -#define CLK_SOURCE_3D 0x158 -#define CLK_SOURCE_2D 0x15c -#define CLK_SOURCE_MPE 0x170 -#define CLK_SOURCE_EPP 0x16c -#define CLK_SOURCE_HOST1X 0x180 -#define CLK_SOURCE_VDE 0x1c8 -#define CLK_SOURCE_VI 0x148 -#define CLK_SOURCE_VI_SENSOR 0x1a8 #define CLK_SOURCE_EMC 0x19c #define AUDIO_SYNC_CLK 0x38 -#define PMC_CTRL 0x0 -#define PMC_CTRL_BLINK_ENB 7 -#define PMC_DPD_PADS_ORIDE 0x1c -#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 -#define PMC_BLINK_TIMER 0x40 - /* Tegra CPU clock and reset control regs */ #define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c #define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 @@ -171,57 +140,28 @@ static struct cpu_clk_suspend_context { static void __iomem *clk_base; static void __iomem *pmc_base; -static DEFINE_SPINLOCK(pll_div_lock); -static DEFINE_SPINLOCK(sysrate_lock); - -#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, \ _gate_flags, _clk_id) -#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ - _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ - 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, \ - _clk_num, _gate_flags, \ - _clk_id) - -#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_DIV16(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ _clk_num, _gate_flags, \ _clk_id) -#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ +#define TEGRA_INIT_DATA_NODIV(_name, _parents, _offset, \ _mux_shift, _mux_width, _clk_num, \ _gate_flags, _clk_id) \ - TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \ _mux_shift, _mux_width, 0, 0, 0, 0, 0, \ _clk_num, _gate_flags, \ _clk_id) -/* IDs assigned here must be in sync with DT bindings definition - * for Tegra20 clocks . - */ -enum tegra20_clk { - cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, - ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp, - gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma, - kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3, - dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, - usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, - pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb, - iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev2, cdev1, - uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve, - osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0, - pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1, - pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_s, pll_u, - pll_x, cop, audio, pll_ref, twd, clk_max, -}; - static struct clk **clks; static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { @@ -485,6 +425,157 @@ static struct tegra_clk_pll_params pll_e_params = { .fixed_rate = 100000000, }; +static struct tegra_devclk devclks[] __initdata = { + { .con_id = "pll_c", .dt_id = TEGRA20_CLK_PLL_C }, + { .con_id = "pll_c_out1", .dt_id = TEGRA20_CLK_PLL_C_OUT1 }, + { .con_id = "pll_p", .dt_id = TEGRA20_CLK_PLL_P }, + { .con_id = "pll_p_out1", .dt_id = TEGRA20_CLK_PLL_P_OUT1 }, + { .con_id = "pll_p_out2", .dt_id = TEGRA20_CLK_PLL_P_OUT2 }, + { .con_id = "pll_p_out3", .dt_id = TEGRA20_CLK_PLL_P_OUT3 }, + { .con_id = "pll_p_out4", .dt_id = TEGRA20_CLK_PLL_P_OUT4 }, + { .con_id = "pll_m", .dt_id = TEGRA20_CLK_PLL_M }, + { .con_id = "pll_m_out1", .dt_id = TEGRA20_CLK_PLL_M_OUT1 }, + { .con_id = "pll_x", .dt_id = TEGRA20_CLK_PLL_X }, + { .con_id = "pll_u", .dt_id = TEGRA20_CLK_PLL_U }, + { .con_id = "pll_d", .dt_id = TEGRA20_CLK_PLL_D }, + { .con_id = "pll_d_out0", .dt_id = TEGRA20_CLK_PLL_D_OUT0 }, + { .con_id = "pll_a", .dt_id = TEGRA20_CLK_PLL_A }, + { .con_id = "pll_a_out0", .dt_id = TEGRA20_CLK_PLL_A_OUT0 }, + { .con_id = "pll_e", .dt_id = TEGRA20_CLK_PLL_E }, + { .con_id = "cclk", .dt_id = TEGRA20_CLK_CCLK }, + { .con_id = "sclk", .dt_id = TEGRA20_CLK_SCLK }, + { .con_id = "hclk", .dt_id = TEGRA20_CLK_HCLK }, + { .con_id = "pclk", .dt_id = TEGRA20_CLK_PCLK }, + { .con_id = "twd", .dt_id = TEGRA20_CLK_TWD }, + { .con_id = "audio", .dt_id = TEGRA20_CLK_AUDIO }, + { .con_id = "audio_2x", .dt_id = TEGRA20_CLK_AUDIO_2X }, + { .dev_id = "tegra20-ac97", .dt_id = TEGRA20_CLK_AC97 }, + { .dev_id = "tegra-apbdma", .dt_id = TEGRA20_CLK_APBDMA }, + { .dev_id = "rtc-tegra", .dt_id = TEGRA20_CLK_RTC }, + { .dev_id = "timer", .dt_id = TEGRA20_CLK_TIMER }, + { .dev_id = "tegra-kbc", .dt_id = TEGRA20_CLK_KBC }, + { .con_id = "csus", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_CSUS }, + { .con_id = "vcp", .dev_id = "tegra-avp", .dt_id = TEGRA20_CLK_VCP }, + { .con_id = "bsea", .dev_id = "tegra-avp", .dt_id = TEGRA20_CLK_BSEA }, + { .con_id = "bsev", .dev_id = "tegra-aes", .dt_id = TEGRA20_CLK_BSEV }, + { .con_id = "emc", .dt_id = TEGRA20_CLK_EMC }, + { .dev_id = "fsl-tegra-udc", .dt_id = TEGRA20_CLK_USBD }, + { .dev_id = "tegra-ehci.1", .dt_id = TEGRA20_CLK_USB2 }, + { .dev_id = "tegra-ehci.2", .dt_id = TEGRA20_CLK_USB3 }, + { .dev_id = "dsi", .dt_id = TEGRA20_CLK_DSI }, + { .con_id = "csi", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_CSI }, + { .con_id = "isp", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_ISP }, + { .con_id = "pex", .dt_id = TEGRA20_CLK_PEX }, + { .con_id = "afi", .dt_id = TEGRA20_CLK_AFI }, + { .con_id = "pcie_xclk", .dt_id = TEGRA20_CLK_PCIE_XCLK }, + { .con_id = "cdev1", .dt_id = TEGRA20_CLK_CDEV1 }, + { .con_id = "cdev2", .dt_id = TEGRA20_CLK_CDEV2 }, + { .con_id = "clk_32k", .dt_id = TEGRA20_CLK_CLK_32K }, + { .con_id = "blink", .dt_id = TEGRA20_CLK_BLINK }, + { .con_id = "clk_m", .dt_id = TEGRA20_CLK_CLK_M }, + { .con_id = "pll_ref", .dt_id = TEGRA20_CLK_PLL_REF }, + { .dev_id = "tegra20-i2s.0", .dt_id = TEGRA20_CLK_I2S1 }, + { .dev_id = "tegra20-i2s.1", .dt_id = TEGRA20_CLK_I2S2 }, + { .con_id = "spdif_out", .dev_id = "tegra20-spdif", .dt_id = TEGRA20_CLK_SPDIF_OUT }, + { .con_id = "spdif_in", .dev_id = "tegra20-spdif", .dt_id = TEGRA20_CLK_SPDIF_IN }, + { .dev_id = "spi_tegra.0", .dt_id = TEGRA20_CLK_SBC1 }, + { .dev_id = "spi_tegra.1", .dt_id = TEGRA20_CLK_SBC2 }, + { .dev_id = "spi_tegra.2", .dt_id = TEGRA20_CLK_SBC3 }, + { .dev_id = "spi_tegra.3", .dt_id = TEGRA20_CLK_SBC4 }, + { .dev_id = "spi", .dt_id = TEGRA20_CLK_SPI }, + { .dev_id = "xio", .dt_id = TEGRA20_CLK_XIO }, + { .dev_id = "twc", .dt_id = TEGRA20_CLK_TWC }, + { .dev_id = "ide", .dt_id = TEGRA20_CLK_IDE }, + { .dev_id = "tegra_nand", .dt_id = TEGRA20_CLK_NDFLASH }, + { .dev_id = "vfir", .dt_id = TEGRA20_CLK_VFIR }, + { .dev_id = "csite", .dt_id = TEGRA20_CLK_CSITE }, + { .dev_id = "la", .dt_id = TEGRA20_CLK_LA }, + { .dev_id = "tegra_w1", .dt_id = TEGRA20_CLK_OWR }, + { .dev_id = "mipi", .dt_id = TEGRA20_CLK_MIPI }, + { .dev_id = "vde", .dt_id = TEGRA20_CLK_VDE }, + { .con_id = "vi", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_VI }, + { .dev_id = "epp", .dt_id = TEGRA20_CLK_EPP }, + { .dev_id = "mpe", .dt_id = TEGRA20_CLK_MPE }, + { .dev_id = "host1x", .dt_id = TEGRA20_CLK_HOST1X }, + { .dev_id = "3d", .dt_id = TEGRA20_CLK_GR3D }, + { .dev_id = "2d", .dt_id = TEGRA20_CLK_GR2D }, + { .dev_id = "tegra-nor", .dt_id = TEGRA20_CLK_NOR }, + { .dev_id = "sdhci-tegra.0", .dt_id = TEGRA20_CLK_SDMMC1 }, + { .dev_id = "sdhci-tegra.1", .dt_id = TEGRA20_CLK_SDMMC2 }, + { .dev_id = "sdhci-tegra.2", .dt_id = TEGRA20_CLK_SDMMC3 }, + { .dev_id = "sdhci-tegra.3", .dt_id = TEGRA20_CLK_SDMMC4 }, + { .dev_id = "cve", .dt_id = TEGRA20_CLK_CVE }, + { .dev_id = "tvo", .dt_id = TEGRA20_CLK_TVO }, + { .dev_id = "tvdac", .dt_id = TEGRA20_CLK_TVDAC }, + { .con_id = "vi_sensor", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_VI_SENSOR }, + { .dev_id = "hdmi", .dt_id = TEGRA20_CLK_HDMI }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.0", .dt_id = TEGRA20_CLK_I2C1 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.1", .dt_id = TEGRA20_CLK_I2C2 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.2", .dt_id = TEGRA20_CLK_I2C3 }, + { .con_id = "div-clk", .dev_id = "tegra-i2c.3", .dt_id = TEGRA20_CLK_DVC }, + { .dev_id = "tegra-pwm", .dt_id = TEGRA20_CLK_PWM }, + { .dev_id = "tegra_uart.0", .dt_id = TEGRA20_CLK_UARTA }, + { .dev_id = "tegra_uart.1", .dt_id = TEGRA20_CLK_UARTB }, + { .dev_id = "tegra_uart.2", .dt_id = TEGRA20_CLK_UARTC }, + { .dev_id = "tegra_uart.3", .dt_id = TEGRA20_CLK_UARTD }, + { .dev_id = "tegra_uart.4", .dt_id = TEGRA20_CLK_UARTE }, + { .dev_id = "tegradc.0", .dt_id = TEGRA20_CLK_DISP1 }, + { .dev_id = "tegradc.1", .dt_id = TEGRA20_CLK_DISP2 }, +}; + +static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { + [tegra_clk_spdif_out] = { .dt_id = TEGRA20_CLK_SPDIF_OUT, .present = true }, + [tegra_clk_spdif_in] = { .dt_id = TEGRA20_CLK_SPDIF_IN, .present = true }, + [tegra_clk_sdmmc1] = { .dt_id = TEGRA20_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc2] = { .dt_id = TEGRA20_CLK_SDMMC2, .present = true }, + [tegra_clk_sdmmc3] = { .dt_id = TEGRA20_CLK_SDMMC3, .present = true }, + [tegra_clk_sdmmc4] = { .dt_id = TEGRA20_CLK_SDMMC4, .present = true }, + [tegra_clk_la] = { .dt_id = TEGRA20_CLK_LA, .present = true }, + [tegra_clk_csite] = { .dt_id = TEGRA20_CLK_CSITE, .present = true }, + [tegra_clk_vfir] = { .dt_id = TEGRA20_CLK_VFIR, .present = true }, + [tegra_clk_mipi] = { .dt_id = TEGRA20_CLK_MIPI, .present = true }, + [tegra_clk_nor] = { .dt_id = TEGRA20_CLK_NOR, .present = true }, + [tegra_clk_rtc] = { .dt_id = TEGRA20_CLK_RTC, .present = true }, + [tegra_clk_timer] = { .dt_id = TEGRA20_CLK_TIMER, .present = true }, + [tegra_clk_kbc] = { .dt_id = TEGRA20_CLK_KBC, .present = true }, + [tegra_clk_csus] = { .dt_id = TEGRA20_CLK_CSUS, .present = true }, + [tegra_clk_vcp] = { .dt_id = TEGRA20_CLK_VCP, .present = true }, + [tegra_clk_bsea] = { .dt_id = TEGRA20_CLK_BSEA, .present = true }, + [tegra_clk_bsev] = { .dt_id = TEGRA20_CLK_BSEV, .present = true }, + [tegra_clk_usbd] = { .dt_id = TEGRA20_CLK_USBD, .present = true }, + [tegra_clk_usb2] = { .dt_id = TEGRA20_CLK_USB2, .present = true }, + [tegra_clk_usb3] = { .dt_id = TEGRA20_CLK_USB3, .present = true }, + [tegra_clk_csi] = { .dt_id = TEGRA20_CLK_CSI, .present = true }, + [tegra_clk_isp] = { .dt_id = TEGRA20_CLK_ISP, .present = true }, + [tegra_clk_clk_32k] = { .dt_id = TEGRA20_CLK_CLK_32K, .present = true }, + [tegra_clk_blink] = { .dt_id = TEGRA20_CLK_BLINK, .present = true }, + [tegra_clk_hclk] = { .dt_id = TEGRA20_CLK_HCLK, .present = true }, + [tegra_clk_pclk] = { .dt_id = TEGRA20_CLK_PCLK, .present = true }, + [tegra_clk_pll_p_out1] = { .dt_id = TEGRA20_CLK_PLL_P_OUT1, .present = true }, + [tegra_clk_pll_p_out2] = { .dt_id = TEGRA20_CLK_PLL_P_OUT2, .present = true }, + [tegra_clk_pll_p_out3] = { .dt_id = TEGRA20_CLK_PLL_P_OUT3, .present = true }, + [tegra_clk_pll_p_out4] = { .dt_id = TEGRA20_CLK_PLL_P_OUT4, .present = true }, + [tegra_clk_pll_p] = { .dt_id = TEGRA20_CLK_PLL_P, .present = true }, + [tegra_clk_owr] = { .dt_id = TEGRA20_CLK_OWR, .present = true }, + [tegra_clk_sbc1] = { .dt_id = TEGRA20_CLK_SBC1, .present = true }, + [tegra_clk_sbc2] = { .dt_id = TEGRA20_CLK_SBC2, .present = true }, + [tegra_clk_sbc3] = { .dt_id = TEGRA20_CLK_SBC3, .present = true }, + [tegra_clk_sbc4] = { .dt_id = TEGRA20_CLK_SBC4, .present = true }, + [tegra_clk_vde] = { .dt_id = TEGRA20_CLK_VDE, .present = true }, + [tegra_clk_vi] = { .dt_id = TEGRA20_CLK_VI, .present = true }, + [tegra_clk_epp] = { .dt_id = TEGRA20_CLK_EPP, .present = true }, + [tegra_clk_mpe] = { .dt_id = TEGRA20_CLK_MPE, .present = true }, + [tegra_clk_host1x] = { .dt_id = TEGRA20_CLK_HOST1X, .present = true }, + [tegra_clk_gr2d] = { .dt_id = TEGRA20_CLK_GR2D, .present = true }, + [tegra_clk_gr3d] = { .dt_id = TEGRA20_CLK_GR3D, .present = true }, + [tegra_clk_ndflash] = { .dt_id = TEGRA20_CLK_NDFLASH, .present = true }, + [tegra_clk_cve] = { .dt_id = TEGRA20_CLK_CVE, .present = true }, + [tegra_clk_tvo] = { .dt_id = TEGRA20_CLK_TVO, .present = true }, + [tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true }, + [tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true }, + [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true }, +}; + static unsigned long tegra20_clk_measure_input_freq(void) { u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); @@ -545,8 +636,7 @@ static void tegra20_pll_init(void) /* PLLC */ clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, NULL, 0, &pll_c_params, NULL); - clk_register_clkdev(clk, "pll_c", NULL); - clks[pll_c] = clk; + clks[TEGRA20_CLK_PLL_C] = clk; /* PLLC_OUT1 */ clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", @@ -555,69 +645,13 @@ static void tegra20_pll_init(void) clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_c_out1", NULL); - clks[pll_c_out1] = clk; - - /* PLLP */ - clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0, - &pll_p_params, NULL); - clk_register_clkdev(clk, "pll_p", NULL); - clks[pll_p] = clk; - - /* PLLP_OUT1 */ - clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", - clk_base + PLLP_OUTA, 0, - TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, - 8, 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", - clk_base + PLLP_OUTA, 1, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out1", NULL); - clks[pll_p_out1] = clk; - - /* PLLP_OUT2 */ - clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", - clk_base + PLLP_OUTA, 0, - TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, - 24, 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", - clk_base + PLLP_OUTA, 17, 16, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out2", NULL); - clks[pll_p_out2] = clk; - - /* PLLP_OUT3 */ - clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", - clk_base + PLLP_OUTB, 0, - TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, - 8, 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", - clk_base + PLLP_OUTB, 1, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out3", NULL); - clks[pll_p_out3] = clk; - - /* PLLP_OUT4 */ - clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", - clk_base + PLLP_OUTB, 0, - TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, - 24, 8, 1, &pll_div_lock); - clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", - clk_base + PLLP_OUTB, 17, 16, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, - &pll_div_lock); - clk_register_clkdev(clk, "pll_p_out4", NULL); - clks[pll_p_out4] = clk; + clks[TEGRA20_CLK_PLL_C_OUT1] = clk; /* PLLM */ clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL, CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, &pll_m_params, NULL); - clk_register_clkdev(clk, "pll_m", NULL); - clks[pll_m] = clk; + clks[TEGRA20_CLK_PLL_M] = clk; /* PLLM_OUT1 */ clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", @@ -626,38 +660,32 @@ static void tegra20_pll_init(void) clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_m_out1", NULL); - clks[pll_m_out1] = clk; + clks[TEGRA20_CLK_PLL_M_OUT1] = clk; /* PLLX */ clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, NULL, 0, &pll_x_params, NULL); - clk_register_clkdev(clk, "pll_x", NULL); - clks[pll_x] = clk; + clks[TEGRA20_CLK_PLL_X] = clk; /* PLLU */ clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, NULL, 0, &pll_u_params, NULL); - clk_register_clkdev(clk, "pll_u", NULL); - clks[pll_u] = clk; + clks[TEGRA20_CLK_PLL_U] = clk; /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, NULL, 0, &pll_d_params, NULL); - clk_register_clkdev(clk, "pll_d", NULL); - clks[pll_d] = clk; + clks[TEGRA20_CLK_PLL_D] = clk; /* PLLD_OUT0 */ clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", CLK_SET_RATE_PARENT, 1, 2); - clk_register_clkdev(clk, "pll_d_out0", NULL); - clks[pll_d_out0] = clk; + clks[TEGRA20_CLK_PLL_D_OUT0] = clk; /* PLLA */ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, NULL, 0, &pll_a_params, NULL); - clk_register_clkdev(clk, "pll_a", NULL); - clks[pll_a] = clk; + clks[TEGRA20_CLK_PLL_A] = clk; /* PLLA_OUT0 */ clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", @@ -666,14 +694,12 @@ static void tegra20_pll_init(void) clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, NULL); - clk_register_clkdev(clk, "pll_a_out0", NULL); - clks[pll_a_out0] = clk; + clks[TEGRA20_CLK_PLL_A_OUT0] = clk; /* PLLE */ clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, pmc_base, 0, &pll_e_params, NULL); - clk_register_clkdev(clk, "pll_e", NULL); - clks[pll_e] = clk; + clks[TEGRA20_CLK_PLL_E] = clk; } static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", @@ -691,40 +717,17 @@ static void tegra20_super_clk_init(void) clk = tegra_clk_register_super_mux("cclk", cclk_parents, ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT, clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL); - clk_register_clkdev(clk, "cclk", NULL); - clks[cclk] = clk; + clks[TEGRA20_CLK_CCLK] = clk; /* SCLK */ clk = tegra_clk_register_super_mux("sclk", sclk_parents, ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); - clk_register_clkdev(clk, "sclk", NULL); - clks[sclk] = clk; - - /* HCLK */ - clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, - clk_base + CLK_SYSTEM_RATE, 4, 2, 0, - &sysrate_lock); - clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT, - clk_base + CLK_SYSTEM_RATE, 7, - CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clk_register_clkdev(clk, "hclk", NULL); - clks[hclk] = clk; - - /* PCLK */ - clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, - clk_base + CLK_SYSTEM_RATE, 0, 2, 0, - &sysrate_lock); - clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT, - clk_base + CLK_SYSTEM_RATE, 3, - CLK_GATE_SET_TO_DISABLE, &sysrate_lock); - clk_register_clkdev(clk, "pclk", NULL); - clks[pclk] = clk; + clks[TEGRA20_CLK_SCLK] = clk; /* twd */ clk = clk_register_fixed_factor(NULL, "twd", "cclk", 0, 1, 4); - clk_register_clkdev(clk, "twd", NULL); - clks[twd] = clk; + clks[TEGRA20_CLK_TWD] = clk; } static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused", @@ -743,8 +746,7 @@ static void __init tegra20_audio_clk_init(void) clk = clk_register_gate(NULL, "audio", "audio_mux", 0, clk_base + AUDIO_SYNC_CLK, 4, CLK_GATE_SET_TO_DISABLE, NULL); - clk_register_clkdev(clk, "audio", NULL); - clks[audio] = clk; + clks[TEGRA20_CLK_AUDIO] = clk; /* audio_2x */ clk = clk_register_fixed_factor(NULL, "audio_doubler", "audio", @@ -753,8 +755,7 @@ static void __init tegra20_audio_clk_init(void) TEGRA_PERIPH_NO_RESET, clk_base, CLK_SET_RATE_PARENT, 89, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "audio_2x", NULL); - clks[audio_2x] = clk; + clks[TEGRA20_CLK_AUDIO_2X] = clk; } @@ -762,68 +763,36 @@ static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p", "clk_m"}; static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p", "clk_m"}; -static const char *spdif_out_parents[] = {"pll_a_out0", "audio_2x", "pll_p", - "clk_m"}; -static const char *spdif_in_parents[] = {"pll_p", "pll_c", "pll_m"}; static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m", "clk_32k"}; static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"}; -static const char *mux_pllmcpa[] = {"pll_m", "pll_c", "pll_c", "pll_a"}; static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c", "clk_m"}; static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"}; static struct tegra_periph_init_data tegra_periph_clk_list[] = { - TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra20-i2s.0", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, i2s1), - TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra20-i2s.1", i2s2_parents, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, i2s2), - TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, spdif_out), - TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra20-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, spdif_in), - TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, sbc1), - TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, sbc2), - TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, sbc3), - TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, sbc4), - TEGRA_INIT_DATA_MUX("spi", NULL, "spi", mux_pllpcm_clkm, CLK_SOURCE_SPI, 43, TEGRA_PERIPH_ON_APB, spi), - TEGRA_INIT_DATA_MUX("xio", NULL, "xio", mux_pllpcm_clkm, CLK_SOURCE_XIO, 45, 0, xio), - TEGRA_INIT_DATA_MUX("twc", NULL, "twc", mux_pllpcm_clkm, CLK_SOURCE_TWC, 16, TEGRA_PERIPH_ON_APB, twc), - TEGRA_INIT_DATA_MUX("ide", NULL, "ide", mux_pllpcm_clkm, CLK_SOURCE_XIO, 25, 0, ide), - TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, 0, ndflash), - TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, vfir), - TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, 0, csite), - TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, 0, la), - TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, owr), - TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, mipi), - TEGRA_INIT_DATA_MUX("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, 0, vde), - TEGRA_INIT_DATA_MUX("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, 0, vi), - TEGRA_INIT_DATA_MUX("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, 0, epp), - TEGRA_INIT_DATA_MUX("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, 0, mpe), - TEGRA_INIT_DATA_MUX("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, 0, host1x), - TEGRA_INIT_DATA_MUX("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, TEGRA_PERIPH_MANUAL_RESET, gr3d), - TEGRA_INIT_DATA_MUX("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, 0, gr2d), - TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, 0, nor), - TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, 0, sdmmc1), - TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, 0, sdmmc2), - TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, 0, sdmmc3), - TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, 0, sdmmc4), - TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, 0, cve), - TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, 0, tvo), - TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, 0, tvdac), - TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, vi_sensor), - TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllpcm_clkm, CLK_SOURCE_I2C1, 12, TEGRA_PERIPH_ON_APB, i2c1), - TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllpcm_clkm, CLK_SOURCE_I2C2, 54, TEGRA_PERIPH_ON_APB, i2c2), - TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, TEGRA_PERIPH_ON_APB, i2c3), - TEGRA_INIT_DATA_DIV16("dvc", "div-clk", "tegra-i2c.3", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, TEGRA_PERIPH_ON_APB, dvc), - TEGRA_INIT_DATA_MUX("hdmi", NULL, "hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, 0, hdmi), - TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, pwm), + TEGRA_INIT_DATA_MUX("i2s1", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S1), + TEGRA_INIT_DATA_MUX("i2s2", i2s2_parents, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S2), + TEGRA_INIT_DATA_MUX("spi", mux_pllpcm_clkm, CLK_SOURCE_SPI, 43, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_SPI), + TEGRA_INIT_DATA_MUX("xio", mux_pllpcm_clkm, CLK_SOURCE_XIO, 45, 0, TEGRA20_CLK_XIO), + TEGRA_INIT_DATA_MUX("twc", mux_pllpcm_clkm, CLK_SOURCE_TWC, 16, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_TWC), + TEGRA_INIT_DATA_MUX("ide", mux_pllpcm_clkm, CLK_SOURCE_XIO, 25, 0, TEGRA20_CLK_IDE), + TEGRA_INIT_DATA_DIV16("dvc", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_DVC), + TEGRA_INIT_DATA_DIV16("i2c1", mux_pllpcm_clkm, CLK_SOURCE_I2C1, 12, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2C1), + TEGRA_INIT_DATA_DIV16("i2c2", mux_pllpcm_clkm, CLK_SOURCE_I2C2, 54, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2C2), + TEGRA_INIT_DATA_DIV16("i2c3", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2C3), + TEGRA_INIT_DATA_MUX("hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA20_CLK_HDMI), + TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_PWM), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { - TEGRA_INIT_DATA_NODIV("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6, TEGRA_PERIPH_ON_APB, uarta), - TEGRA_INIT_DATA_NODIV("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7, TEGRA_PERIPH_ON_APB, uartb), - TEGRA_INIT_DATA_NODIV("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, TEGRA_PERIPH_ON_APB, uartc), - TEGRA_INIT_DATA_NODIV("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, TEGRA_PERIPH_ON_APB, uartd), - TEGRA_INIT_DATA_NODIV("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, TEGRA_PERIPH_ON_APB, uarte), - TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, 0, disp1), - TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, 0, disp2), + TEGRA_INIT_DATA_NODIV("uarta", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTA), + TEGRA_INIT_DATA_NODIV("uartb", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTB), + TEGRA_INIT_DATA_NODIV("uartc", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTC), + TEGRA_INIT_DATA_NODIV("uartd", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTD), + TEGRA_INIT_DATA_NODIV("uarte", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_UARTE), + TEGRA_INIT_DATA_NODIV("disp1", mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, 0, TEGRA20_CLK_DISP1), + TEGRA_INIT_DATA_NODIV("disp2", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, 0, TEGRA20_CLK_DISP2), }; static void __init tegra20_periph_clk_init(void) @@ -836,59 +805,12 @@ static void __init tegra20_periph_clk_init(void) clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0", TEGRA_PERIPH_ON_APB, clk_base, 0, 3, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra20-ac97"); - clks[ac97] = clk; + clks[TEGRA20_CLK_AC97] = clk; /* apbdma */ clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base, 0, 34, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-apbdma"); - clks[apbdma] = clk; - - /* rtc */ - clk = tegra_clk_register_periph_gate("rtc", "clk_32k", - TEGRA_PERIPH_NO_RESET, - clk_base, 0, 4, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "rtc-tegra"); - clks[rtc] = clk; - - /* timer */ - clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, - 0, 5, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "timer"); - clks[timer] = clk; - - /* kbc */ - clk = tegra_clk_register_periph_gate("kbc", "clk_32k", - TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, - clk_base, 0, 36, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-kbc"); - clks[kbc] = clk; - - /* csus */ - clk = tegra_clk_register_periph_gate("csus", "clk_m", - TEGRA_PERIPH_NO_RESET, - clk_base, 0, 92, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "csus", "tengra_camera"); - clks[csus] = clk; - - /* vcp */ - clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, - clk_base, 0, 29, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "vcp", "tegra-avp"); - clks[vcp] = clk; - - /* bsea */ - clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, - clk_base, 0, 62, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "bsea", "tegra-avp"); - clks[bsea] = clk; - - /* bsev */ - clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, - clk_base, 0, 63, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "bsev", "tegra-aes"); - clks[bsev] = clk; + clks[TEGRA20_CLK_APBDMA] = clk; /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, @@ -898,85 +820,43 @@ static void __init tegra20_periph_clk_init(void) 30, 2, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, 57, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "emc", NULL); - clks[emc] = clk; - - /* usbd */ - clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, - 22, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); - clks[usbd] = clk; - - /* usb2 */ - clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, - 58, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-ehci.1"); - clks[usb2] = clk; - - /* usb3 */ - clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, - 59, periph_clk_enb_refcnt); - clk_register_clkdev(clk, NULL, "tegra-ehci.2"); - clks[usb3] = clk; + clks[TEGRA20_CLK_EMC] = clk; /* dsi */ clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0, 48, periph_clk_enb_refcnt); clk_register_clkdev(clk, NULL, "dsi"); - clks[dsi] = clk; - - /* csi */ - clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, - 0, 52, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "csi", "tegra_camera"); - clks[csi] = clk; - - /* isp */ - clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "isp", "tegra_camera"); - clks[isp] = clk; + clks[TEGRA20_CLK_DSI] = clk; /* pex */ clk = tegra_clk_register_periph_gate("pex", "clk_m", 0, clk_base, 0, 70, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "pex", NULL); - clks[pex] = clk; - - /* afi */ - clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, - periph_clk_enb_refcnt); - clk_register_clkdev(clk, "afi", NULL); - clks[afi] = clk; + clks[TEGRA20_CLK_PEX] = clk; /* pcie_xclk */ clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base, 0, 74, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "pcie_xclk", NULL); - clks[pcie_xclk] = clk; + clks[TEGRA20_CLK_PCIE_XCLK] = clk; /* cdev1 */ clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT, 26000000); clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0, clk_base, 0, 94, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "cdev1", NULL); - clks[cdev1] = clk; + clks[TEGRA20_CLK_CDEV1] = clk; /* cdev2 */ clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, CLK_IS_ROOT, 26000000); clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0, clk_base, 0, 93, periph_clk_enb_refcnt); - clk_register_clkdev(clk, "cdev2", NULL); - clks[cdev2] = clk; + clks[TEGRA20_CLK_CDEV2] = clk; for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; clk = tegra_clk_register_periph(data->name, data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset, data->flags); - clk_register_clkdev(clk, data->con_id, data->dev_id); clks[data->clk_id] = clk; } @@ -986,37 +866,10 @@ static void __init tegra20_periph_clk_init(void) data->p.parent_names, data->num_parents, &data->periph, clk_base, data->offset); - clk_register_clkdev(clk, data->con_id, data->dev_id); clks[data->clk_id] = clk; } -} - - -static void __init tegra20_fixed_clk_init(void) -{ - struct clk *clk; - - /* clk_32k */ - clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, - 32768); - clk_register_clkdev(clk, "clk_32k", NULL); - clks[clk_32k] = clk; -} - -static void __init tegra20_pmc_clk_init(void) -{ - struct clk *clk; - /* blink */ - writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); - clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, - pmc_base + PMC_DPD_PADS_ORIDE, - PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); - clk = clk_register_gate(NULL, "blink", "blink_override", 0, - pmc_base + PMC_CTRL, - PMC_CTRL_BLINK_ENB, 0, NULL); - clk_register_clkdev(clk, "blink", NULL); - clks[blink] = clk; + tegra_periph_clk_init(clk_base, pmc_base, tegra20_clks, &pll_p_params); } static void __init tegra20_osc_clk_init(void) @@ -1030,15 +883,13 @@ static void __init tegra20_osc_clk_init(void) /* clk_m */ clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT | CLK_IGNORE_UNUSED, input_freq); - clk_register_clkdev(clk, "clk_m", NULL); - clks[clk_m] = clk; + clks[TEGRA20_CLK_CLK_M] = clk; /* pll_ref */ pll_ref_div = tegra20_get_pll_ref_div(); clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", CLK_SET_RATE_PARENT, 1, pll_ref_div); - clk_register_clkdev(clk, "pll_ref", NULL); - clks[pll_ref] = clk; + clks[TEGRA20_CLK_PLL_REF] = clk; } /* Tegra20 CPU clock and reset control functions */ @@ -1172,49 +1023,49 @@ static struct tegra_cpu_car_ops tegra20_cpu_car_ops = { }; static struct tegra_clk_init_table init_table[] __initdata = { - {pll_p, clk_max, 216000000, 1}, - {pll_p_out1, clk_max, 28800000, 1}, - {pll_p_out2, clk_max, 48000000, 1}, - {pll_p_out3, clk_max, 72000000, 1}, - {pll_p_out4, clk_max, 24000000, 1}, - {pll_c, clk_max, 600000000, 1}, - {pll_c_out1, clk_max, 120000000, 1}, - {sclk, pll_c_out1, 0, 1}, - {hclk, clk_max, 0, 1}, - {pclk, clk_max, 60000000, 1}, - {csite, clk_max, 0, 1}, - {emc, clk_max, 0, 1}, - {cclk, clk_max, 0, 1}, - {uarta, pll_p, 0, 0}, - {uartb, pll_p, 0, 0}, - {uartc, pll_p, 0, 0}, - {uartd, pll_p, 0, 0}, - {uarte, pll_p, 0, 0}, - {pll_a, clk_max, 56448000, 1}, - {pll_a_out0, clk_max, 11289600, 1}, - {cdev1, clk_max, 0, 1}, - {blink, clk_max, 32768, 1}, - {i2s1, pll_a_out0, 11289600, 0}, - {i2s2, pll_a_out0, 11289600, 0}, - {sdmmc1, pll_p, 48000000, 0}, - {sdmmc3, pll_p, 48000000, 0}, - {sdmmc4, pll_p, 48000000, 0}, - {spi, pll_p, 20000000, 0}, - {sbc1, pll_p, 100000000, 0}, - {sbc2, pll_p, 100000000, 0}, - {sbc3, pll_p, 100000000, 0}, - {sbc4, pll_p, 100000000, 0}, - {host1x, pll_c, 150000000, 0}, - {disp1, pll_p, 600000000, 0}, - {disp2, pll_p, 600000000, 0}, - {gr2d, pll_c, 300000000, 0}, - {gr3d, pll_c, 300000000, 0}, - {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */ + {TEGRA20_CLK_PLL_P, TEGRA20_CLK_CLK_MAX, 216000000, 1}, + {TEGRA20_CLK_PLL_P_OUT1, TEGRA20_CLK_CLK_MAX, 28800000, 1}, + {TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1}, + {TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1}, + {TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1}, + {TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1}, + {TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1}, + {TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1}, + {TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1}, + {TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1}, + {TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1}, + {TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1}, + {TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1}, + {TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0}, + {TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0}, + {TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0}, + {TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0}, + {TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0}, + {TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1}, + {TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1}, + {TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1}, + {TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1}, + {TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0}, + {TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0}, + {TEGRA20_CLK_SDMMC4, TEGRA20_CLK_PLL_P, 48000000, 0}, + {TEGRA20_CLK_SPI, TEGRA20_CLK_PLL_P, 20000000, 0}, + {TEGRA20_CLK_SBC1, TEGRA20_CLK_PLL_P, 100000000, 0}, + {TEGRA20_CLK_SBC2, TEGRA20_CLK_PLL_P, 100000000, 0}, + {TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0}, + {TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0}, + {TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0}, + {TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0}, + {TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0}, + {TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0}, + {TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0}, + {TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry */ }; static void __init tegra20_clock_apply_init_table(void) { - tegra_init_from_table(init_table, clks, clk_max); + tegra_init_from_table(init_table, clks, TEGRA20_CLK_CLK_MAX); } /* @@ -1223,11 +1074,11 @@ static void __init tegra20_clock_apply_init_table(void) * table under two names. */ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { - TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL), - TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), - TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), - TEGRA_CLK_DUPLICATE(cclk, NULL, "cpu"), - TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */ + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "utmip-pad", NULL), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-ehci.0", NULL), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-otg", NULL), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK, NULL, "cpu"), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL), /* Must be the last entry */ }; static const struct of_device_id pmc_match[] __initconst = { @@ -1257,21 +1108,23 @@ static void __init tegra20_clock_init(struct device_node *np) BUG(); } - clks = tegra_clk_init(clk_max, TEGRA20_CLK_PERIPH_BANKS); + clks = tegra_clk_init(TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_PERIPH_BANKS); if (!clks) return; tegra20_osc_clk_init(); - tegra20_pmc_clk_init(); - tegra20_fixed_clk_init(); + tegra_fixed_clk_init(tegra20_clks); tegra20_pll_init(); tegra20_super_clk_init(); + tegra_super_clk_gen4_init(clk_base, pmc_base, tegra20_clks, NULL); tegra20_periph_clk_init(); tegra20_audio_clk_init(); + tegra_pmc_clk_init(pmc_base, tegra20_clks); - tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); + tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA20_CLK_CLK_MAX); tegra_add_of_provider(np); + tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); tegra_clk_apply_init_table = tegra20_clock_apply_init_table; -- cgit v1.2.3 From 798e910bee3f9ad69a8b16d7e705086852d9f2de Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 9 Sep 2013 13:22:55 +0300 Subject: clk: tegra: Add support for PLLSS Tegra124 introduces a new PLL type, PLLSS. Add support for it. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-pll.c | 123 +++++++++++++++++++++++++++++++++++++++++++- drivers/clk/tegra/clk.h | 5 ++ 2 files changed, 126 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 3aa85bf2f425..689c468aca2f 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -137,6 +137,36 @@ #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) +#define PLLSS_MISC_KCP 0 +#define PLLSS_MISC_KVCO 0 +#define PLLSS_MISC_SETUP 0 +#define PLLSS_EN_SDM 0 +#define PLLSS_EN_SSC 0 +#define PLLSS_EN_DITHER2 0 +#define PLLSS_EN_DITHER 1 +#define PLLSS_SDM_RESET 0 +#define PLLSS_CLAMP 0 +#define PLLSS_SDM_SSC_MAX 0 +#define PLLSS_SDM_SSC_MIN 0 +#define PLLSS_SDM_SSC_STEP 0 +#define PLLSS_SDM_DIN 0 +#define PLLSS_MISC_DEFAULT ((PLLSS_MISC_KCP << 25) | \ + (PLLSS_MISC_KVCO << 24) | \ + PLLSS_MISC_SETUP) +#define PLLSS_CFG_DEFAULT ((PLLSS_EN_SDM << 31) | \ + (PLLSS_EN_SSC << 30) | \ + (PLLSS_EN_DITHER2 << 29) | \ + (PLLSS_EN_DITHER << 28) | \ + (PLLSS_SDM_RESET) << 27 | \ + (PLLSS_CLAMP << 22)) +#define PLLSS_CTRL1_DEFAULT \ + ((PLLSS_SDM_SSC_MAX << 16) | PLLSS_SDM_SSC_MIN) +#define PLLSS_CTRL2_DEFAULT \ + ((PLLSS_SDM_SSC_STEP << 16) | PLLSS_SDM_DIN) +#define PLLSS_LOCK_OVERRIDE BIT(24) +#define PLLSS_REF_SRC_SEL_SHIFT 25 +#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT) + #define pll_readl(offset, p) readl_relaxed(p->clk_base + offset) #define pll_readl_base(p) pll_readl(p->params->base_reg, p) #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) @@ -764,7 +794,7 @@ const struct clk_ops tegra_clk_plle_ops = { .enable = clk_plle_enable, }; -#ifdef CONFIG_ARCH_TEGRA_114_SOC +#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC) static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, unsigned long parent_rate) @@ -1405,7 +1435,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, return clk; } -#ifdef CONFIG_ARCH_TEGRA_114_SOC +#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC) const struct clk_ops tegra_clk_pllxc_ops = { .is_enabled = clk_pll_is_enabled, .enable = clk_pll_iddq_enable, @@ -1702,3 +1732,92 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, return clk; } #endif + +#ifdef CONFIG_ARCH_TEGRA_124_SOC +const struct clk_ops tegra_clk_pllss_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pll_iddq_enable, + .disable = clk_pll_iddq_disable, + .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_ramp_round_rate, + .set_rate = clk_pllxc_set_rate, +}; + +struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) +{ + struct tegra_clk_pll *pll; + struct clk *clk, *parent; + struct tegra_clk_pll_freq_table cfg; + unsigned long parent_rate; + u32 val; + int i; + + if (!pll_params->div_nmp) + return ERR_PTR(-EINVAL); + + parent = __clk_lookup(parent_name); + if (IS_ERR(parent)) { + WARN(1, "parent clk %s of %s must be registered first\n", + name, parent_name); + return ERR_PTR(-EINVAL); + } + + pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK; + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + val = pll_readl_base(pll); + val &= ~PLLSS_REF_SRC_SEL_MASK; + pll_writel_base(val, pll); + + parent_rate = __clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + /* initialize PLL to minimum rate */ + + cfg.m = _pll_fixed_mdiv(pll_params, parent_rate); + cfg.n = cfg.m * pll_params->vco_min / parent_rate; + + for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++) + ; + if (!i) { + kfree(pll); + return ERR_PTR(-EINVAL); + } + + cfg.p = pll_params->pdiv_tohw[i-1].hw_val; + + _update_pll_mnp(pll, &cfg); + + pll_writel_misc(PLLSS_MISC_DEFAULT, pll); + pll_writel(PLLSS_CFG_DEFAULT, pll_params->ext_misc_reg[0], pll); + pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[1], pll); + pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll); + + val = pll_readl_base(pll); + if (val & PLL_BASE_ENABLE) { + if (val & BIT(pll_params->iddq_bit_idx)) { + WARN(1, "%s is on but IDDQ set\n", name); + kfree(pll); + return ERR_PTR(-EINVAL); + } + } else + val |= BIT(pll_params->iddq_bit_idx); + + val &= ~PLLSS_LOCK_OVERRIDE; + pll_writel_base(val, pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pllss_ops); + + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} +#endif diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 05abfc5fdff8..7f110acfe2a1 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -298,6 +298,11 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, struct tegra_clk_pll_params *pll_params, spinlock_t *lock); +struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + /** * struct tegra_clk_pll_out - PLL divider down clock * -- cgit v1.2.3 From 2b239077d1e2061c65763dcf57ab978ae5261559 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Wed, 11 Sep 2013 17:57:37 +0300 Subject: clk: tegra: Add periph regs bank X Tegra124 has an extra bank of peripheral clock registers. Add it to the generic peripheral clock code. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index 14d25322aec5..a12a5f5107ec 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -57,6 +57,8 @@ #define RST_DEVICES_CLR_V 0x434 #define RST_DEVICES_SET_W 0x438 #define RST_DEVICES_CLR_W 0x43c +#define RST_DEVICES_SET_X 0x290 +#define RST_DEVICES_CLR_X 0x294 /* Global data of Tegra CPU CAR ops */ static struct tegra_cpu_car_ops dummy_car_ops; @@ -109,6 +111,14 @@ static struct tegra_clk_periph_regs periph_regs[] = { .rst_set_reg = RST_DEVICES_SET_W, .rst_clr_reg = RST_DEVICES_CLR_W, }, + [5] = { + .enb_reg = CLK_OUT_ENB_X, + .enb_set_reg = CLK_OUT_ENB_SET_X, + .enb_clr_reg = CLK_OUT_ENB_CLR_X, + .rst_reg = RST_DEVICES_X, + .rst_set_reg = RST_DEVICES_SET_X, + .rst_clr_reg = RST_DEVICES_CLR_X, + }, }; struct tegra_clk_periph_regs *get_reg_bank(int clkid) -- cgit v1.2.3 From bc44275b8ea2df7c77658b08955ec545a37560ab Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 18 Nov 2013 16:11:37 +0100 Subject: clk: tegra: add locking to periph clks Tegra124 has periph clocks which share the hw register. Hence locking is required. Signed-off-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 33 ++++++++++++++++++--------------- drivers/clk/tegra/clk.h | 10 ++++++---- 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 9b04139f331d..e8d6f2f20141 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -118,75 +118,78 @@ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ - _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) + _clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\ + NULL) #define MUX_FLAGS(_name, _parents, _offset,\ _clk_num, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, _gate_flags, _clk_id, _parents##_idx, flags) + _clk_num, _gate_flags, _clk_id, _parents##_idx, flags,\ + NULL) #define MUX8(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, _gate_flags, _clk_id, _parents##_idx, 0) + _clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\ + NULL) #define INT(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ - _clk_id, _parents##_idx, 0) + _clk_id, _parents##_idx, 0, NULL) #define INT_FLAGS(_name, _parents, _offset,\ _clk_num, _gate_flags, _clk_id, flags)\ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ - _clk_id, _parents##_idx, flags) + _clk_id, _parents##_idx, flags, NULL) #define INT8(_name, _parents, _offset,\ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ - _clk_id, _parents##_idx, 0) + _clk_id, _parents##_idx, 0, NULL) #define UART(_name, _parents, _offset,\ _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \ TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\ - _parents##_idx, 0) + _parents##_idx, 0, NULL) #define I2C(_name, _parents, _offset,\ _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ - _clk_num, 0, _clk_id, _parents##_idx, 0) + _clk_num, 0, _clk_id, _parents##_idx, 0, NULL) #define XUSB(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \ TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\ - _clk_id, _parents##_idx, 0) + _clk_id, _parents##_idx, 0, NULL) #define AUDIO(_name, _offset, _clk_num,\ _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk, \ _offset, 16, 0xE01F, 0, 0, 8, 1, \ TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags, \ - _clk_id, mux_d_audio_clk_idx, 0) + _clk_id, mux_d_audio_clk_idx, 0, NULL) #define NODIV(_name, _parents, _offset, \ _mux_shift, _mux_mask, _clk_num, \ - _gate_flags, _clk_id) \ + _gate_flags, _clk_id, _lock) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ _mux_shift, _mux_mask, 0, 0, 0, 0, 0,\ _clk_num, (_gate_flags) | TEGRA_PERIPH_NO_DIV,\ - _clk_id, _parents##_idx, 0) + _clk_id, _parents##_idx, 0, _lock) #define GATE(_name, _parent_name, \ _clk_num, _gate_flags, _clk_id, _flags) \ @@ -195,7 +198,7 @@ .clk_id = _clk_id, \ .p.parent_name = _parent_name, \ .periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 0, 0, 0, \ - _clk_num, _gate_flags, 0), \ + _clk_num, _gate_flags, 0, NULL), \ .flags = _flags \ } @@ -414,8 +417,8 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm), MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8), MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED), - NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1), - NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2), + NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL), + NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL), UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta), UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 7f110acfe2a1..f984ebed9f1f 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -439,19 +439,21 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ _div_shift, _div_width, _div_frac_width, \ _div_flags, _clk_num,\ - _gate_flags, _table) \ + _gate_flags, _table, _lock) \ { \ .mux = { \ .flags = _mux_flags, \ .shift = _mux_shift, \ .mask = _mux_mask, \ .table = _table, \ + .lock = _lock, \ }, \ .divider = { \ .flags = _div_flags, \ .shift = _div_shift, \ .width = _div_width, \ .frac_width = _div_frac_width, \ + .lock = _lock, \ }, \ .gate = { \ .flags = _gate_flags, \ @@ -481,7 +483,7 @@ struct tegra_periph_init_data { _mux_shift, _mux_mask, _mux_flags, _div_shift, \ _div_width, _div_frac_width, _div_flags, \ _clk_num, _gate_flags, _clk_id, _table, \ - _flags) \ + _flags, _lock) \ { \ .name = _name, \ .clk_id = _clk_id, \ @@ -491,7 +493,7 @@ struct tegra_periph_init_data { _mux_flags, _div_shift, \ _div_width, _div_frac_width, \ _div_flags, _clk_num, \ - _gate_flags, _table), \ + _gate_flags, _table, _lock), \ .offset = _offset, \ .con_id = _con_id, \ .dev_id = _dev_id, \ @@ -506,7 +508,7 @@ struct tegra_periph_init_data { _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ _div_shift, _div_width, _div_frac_width, _div_flags, \ _clk_num, _gate_flags, _clk_id,\ - NULL, 0) + NULL, 0, NULL) /** * struct clk_super_mux - super clock -- cgit v1.2.3 From b29f9e926442c35bd42ebd283aaed0de2c4f1477 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 18 Nov 2013 16:11:38 +0100 Subject: clk: tegra: add TEGRA_PERIPH_NO_GATE Tegra124 has a clock which consists of a mux and a fractional divider. Add support for this. Signed-off-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-periph.c | 18 +++++++++++++++--- drivers/clk/tegra/clk-tegra-periph.c | 6 ++++++ drivers/clk/tegra/clk.h | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index b5feccca2f1e..d62b396863c1 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -170,6 +170,14 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = { .disable = clk_periph_disable, }; +const struct clk_ops tegra_clk_periph_no_gate_ops = { + .get_parent = clk_periph_get_parent, + .set_parent = clk_periph_set_parent, + .recalc_rate = clk_periph_recalc_rate, + .round_rate = clk_periph_round_rate, + .set_rate = clk_periph_set_rate, +}; + static struct clk *_tegra_clk_register_periph(const char *name, const char **parent_names, int num_parents, struct tegra_clk_periph *periph, @@ -181,11 +189,15 @@ static struct clk *_tegra_clk_register_periph(const char *name, struct tegra_clk_periph_regs *bank; bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV); - flags |= periph->gate.flags & TEGRA_PERIPH_NO_DIV ? - CLK_SET_RATE_PARENT : 0; + if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) { + flags |= CLK_SET_RATE_PARENT; + init.ops = &tegra_clk_periph_nodiv_ops; + } else if (periph->gate.flags & TEGRA_PERIPH_NO_GATE) + init.ops = &tegra_clk_periph_no_gate_ops; + else + init.ops = &tegra_clk_periph_ops; init.name = name; - init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; init.flags = flags; init.parent_names = parent_names; init.num_parents = num_parents; diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index e8d6f2f20141..958d4f4fe91f 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -135,6 +135,12 @@ _clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\ NULL) +#define MUX8_NOGATE_LOCK(_name, _parents, _offset, _clk_id, _lock) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \ + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ + 0, TEGRA_PERIPH_NO_GATE, _clk_id,\ + _parents##_idx, 0, _lock) + #define INT(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index f984ebed9f1f..40fb011233c0 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -391,6 +391,7 @@ struct tegra_clk_periph_gate { #define TEGRA_PERIPH_ON_APB BIT(2) #define TEGRA_PERIPH_WAR_1005168 BIT(3) #define TEGRA_PERIPH_NO_DIV BIT(4) +#define TEGRA_PERIPH_NO_GATE BIT(5) void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); extern const struct clk_ops tegra_clk_periph_gate_ops; -- cgit v1.2.3 From 6d11632db44169a7b12a98da4853a8e9c96c3c7c Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 14 Oct 2013 18:52:25 +0300 Subject: clk: tegra124: Add common clk IDs to clk-id.h Tegra124 introduces a number of a new clocks. Introduce the corresponding the IDs for them. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-id.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 22e2e8e67b2f..cf0c323f2c36 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -7,8 +7,10 @@ enum clk_id { tegra_clk_actmon, tegra_clk_adx, + tegra_clk_adx1, tegra_clk_afi, tegra_clk_amx, + tegra_clk_amx1, tegra_clk_apbdma, tegra_clk_apbif, tegra_clk_audio0, @@ -35,6 +37,7 @@ enum clk_id { tegra_clk_cilcd, tegra_clk_cile, tegra_clk_clk_32k, + tegra_clk_clk72Mhz, tegra_clk_clk_m, tegra_clk_clk_m_div2, tegra_clk_clk_m_div4, @@ -44,6 +47,8 @@ enum clk_id { tegra_clk_clk_out_2_mux, tegra_clk_clk_out_3, tegra_clk_clk_out_3_mux, + tegra_clk_cml0, + tegra_clk_cml1, tegra_clk_csi, tegra_clk_csite, tegra_clk_csus, @@ -58,6 +63,7 @@ enum clk_id { tegra_clk_disp1, tegra_clk_disp2, tegra_clk_dp2, + tegra_clk_dpaux, tegra_clk_dsia, tegra_clk_dsialp, tegra_clk_dsia_mux, @@ -66,6 +72,7 @@ enum clk_id { tegra_clk_dsib_mux, tegra_clk_dtv, tegra_clk_emc, + tegra_clk_entropy, tegra_clk_epp, tegra_clk_epp_8, tegra_clk_extern1, @@ -73,6 +80,7 @@ enum clk_id { tegra_clk_extern3, tegra_clk_fuse, tegra_clk_fuse_burn, + tegra_clk_gpu, tegra_clk_gr2d, tegra_clk_gr2d_8, tegra_clk_gr3d, @@ -82,6 +90,7 @@ enum clk_id { tegra_clk_hda2codec_2x, tegra_clk_hda2hdmi, tegra_clk_hdmi, + tegra_clk_hdmi_audio, tegra_clk_host1x, tegra_clk_host1x_8, tegra_clk_i2c1, @@ -89,6 +98,7 @@ enum clk_id { tegra_clk_i2c3, tegra_clk_i2c4, tegra_clk_i2c5, + tegra_clk_i2c6, tegra_clk_i2cslow, tegra_clk_i2s0, tegra_clk_i2s0_sync, @@ -101,6 +111,8 @@ enum clk_id { tegra_clk_i2s4, tegra_clk_i2s4_sync, tegra_clk_isp, + tegra_clk_isp_8, + tegra_clk_ispb, tegra_clk_kbc, tegra_clk_kfuse, tegra_clk_la, @@ -115,17 +127,20 @@ enum clk_id { tegra_clk_ndspeed_8, tegra_clk_nor, tegra_clk_owr, + tegra_clk_pcie, tegra_clk_pclk, tegra_clk_pll_a, tegra_clk_pll_a_out0, tegra_clk_pll_c, tegra_clk_pll_c2, tegra_clk_pll_c3, + tegra_clk_pll_c4, tegra_clk_pll_c_out1, tegra_clk_pll_d, tegra_clk_pll_d2, tegra_clk_pll_d2_out0, tegra_clk_pll_d_out0, + tegra_clk_pll_dp, tegra_clk_pll_e_out0, tegra_clk_pll_m, tegra_clk_pll_m_out1, @@ -135,6 +150,7 @@ enum clk_id { tegra_clk_pll_p_out2_int, tegra_clk_pll_p_out3, tegra_clk_pll_p_out4, + tegra_clk_pll_p_out5, tegra_clk_pll_ref, tegra_clk_pll_re_out, tegra_clk_pll_re_vco, @@ -169,6 +185,8 @@ enum clk_id { tegra_clk_sdmmc4, tegra_clk_se, tegra_clk_soc_therm, + tegra_clk_sor0, + tegra_clk_sor0_lvds, tegra_clk_spdif, tegra_clk_spdif_2x, tegra_clk_spdif_in, @@ -195,8 +213,12 @@ enum clk_id { tegra_clk_vfir, tegra_clk_vi, tegra_clk_vi_8, + tegra_clk_vi_9, + tegra_clk_vic03, + tegra_clk_vim2_clk, tegra_clk_vimclk_sync, tegra_clk_vi_sensor, + tegra_clk_vi_sensor2, tegra_clk_vi_sensor_8, tegra_clk_xusb_dev, tegra_clk_xusb_dev_src, -- cgit v1.2.3 From 3b34d8214dce9bfeef9049de3fe1e8bfbbbb2709 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 14 Oct 2013 18:53:10 +0300 Subject: clk: tegra124: Add new peripheral clocks Tegra124 introduces a number of new peripheral clocks. This patch adds those to the common peripheral clock code. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-tegra-periph.c | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 958d4f4fe91f..5c35885f4a7c 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -37,7 +37,9 @@ #define CLK_SOURCE_SPDIF_IN 0x10c #define CLK_SOURCE_PWM 0x110 #define CLK_SOURCE_ADX 0x638 +#define CLK_SOURCE_ADX1 0x670 #define CLK_SOURCE_AMX 0x63c +#define CLK_SOURCE_AMX1 0x674 #define CLK_SOURCE_HDA 0x428 #define CLK_SOURCE_HDA2CODEC_2X 0x3e4 #define CLK_SOURCE_SBC1 0x134 @@ -69,6 +71,7 @@ #define CLK_SOURCE_I2C3 0x1b8 #define CLK_SOURCE_I2C4 0x3c4 #define CLK_SOURCE_I2C5 0x128 +#define CLK_SOURCE_I2C6 0x65c #define CLK_SOURCE_UARTA 0x178 #define CLK_SOURCE_UARTB 0x17c #define CLK_SOURCE_UARTC 0x1a0 @@ -77,6 +80,7 @@ #define CLK_SOURCE_3D 0x158 #define CLK_SOURCE_2D 0x15c #define CLK_SOURCE_MPE 0x170 +#define CLK_SOURCE_UARTE 0x1c4 #define CLK_SOURCE_VI_SENSOR 0x1a8 #define CLK_SOURCE_VI 0x148 #define CLK_SOURCE_EPP 0x16c @@ -111,6 +115,16 @@ #define CLK_SOURCE_XUSB_FS_SRC 0x608 #define CLK_SOURCE_XUSB_SS_SRC 0x610 #define CLK_SOURCE_XUSB_DEV_SRC 0x60c +#define CLK_SOURCE_ISP 0x144 +#define CLK_SOURCE_SOR0 0x414 +#define CLK_SOURCE_DPAUX 0x418 +#define CLK_SOURCE_SATA_OOB 0x420 +#define CLK_SOURCE_SATA 0x424 +#define CLK_SOURCE_ENTROPY 0x628 +#define CLK_SOURCE_VI_SENSOR2 0x658 +#define CLK_SOURCE_HDMI_AUDIO 0x668 +#define CLK_SOURCE_VIC03 0x678 +#define CLK_SOURCE_CLK72MHZ 0x66c #define MASK(x) (BIT(x) - 1) @@ -212,12 +226,15 @@ #define PLLP_MISC 0xac #define PLLP_OUTA 0xa4 #define PLLP_OUTB 0xa8 +#define PLLP_OUTC 0x67c #define PLL_BASE_LOCK BIT(27) #define PLL_MISC_LOCK_ENABLE 18 static DEFINE_SPINLOCK(PLLP_OUTA_lock); static DEFINE_SPINLOCK(PLLP_OUTB_lock); +static DEFINE_SPINLOCK(PLLP_OUTC_lock); +static DEFINE_SPINLOCK(sor0_lock); #define MUX_I2S_SPDIF(_id) \ static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ @@ -334,6 +351,41 @@ static const char *mux_pllp_plld_pllc_clkm[] = { "pll_p", "pll_d_out0", "pll_c", "clk_m" }; #define mux_pllp_plld_pllc_clkm_idx NULL +static const char *mux_pllm_pllc_pllp_plla_clkm_pllc4[] = { + "pll_m", "pll_c", "pll_p", "pll_a_out0", "clk_m", "pll_c4", +}; +static u32 mux_pllm_pllc_pllp_plla_clkm_pllc4_idx[] = { + [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 6, [5] = 7, +}; + +static const char *mux_pllp_clkm1[] = { + "pll_p", "clk_m", +}; +#define mux_pllp_clkm1_idx NULL + +static const char *mux_pllp3_pllc_clkm[] = { + "pll_p_out3", "pll_c", "pll_c2", "clk_m", +}; +#define mux_pllp3_pllc_clkm_idx NULL + +static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = { + "pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m" +}; +static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = { + [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, +}; + +static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = { + "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4", +}; +static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = { + [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7, +}; + +static const char *mux_clkm_plldp_sor0lvds[] = { + "clk_m", "pll_dp", "sor0_lvds", +}; +#define mux_clkm_plldp_sor0lvds_idx NULL static struct tegra_periph_init_data periph_clks[] = { AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio), @@ -354,6 +406,7 @@ static struct tegra_periph_init_data periph_clks[] = { INT("3d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d), INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8), INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8), + INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9), INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8), INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc), INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec), @@ -361,6 +414,7 @@ static struct tegra_periph_init_data periph_clks[] = { INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se), INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8), INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8), + INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03), INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED), MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0), MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1), @@ -408,6 +462,9 @@ static struct tegra_periph_init_data periph_clks[] = { MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed), MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob), MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata), + MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1), + MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1), + MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2), MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8), MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8), MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8), @@ -422,9 +479,15 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3), MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm), MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8), + MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8), + MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy), + MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio), + MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz), + MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock), MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED), NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL), NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL), + NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock), UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta), UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), @@ -468,6 +531,11 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("dsib", "dsib_mux", 82, 0, tegra_clk_dsib, 0), GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED), GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0), + GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0), + GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0), + GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), + GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0), + GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), }; struct pll_out_data { @@ -500,6 +568,7 @@ static struct pll_out_data pllp_out_clks[] = { PLL_OUT(2, PLLP_OUTA, 24, TEGRA_DIVIDER_INT, 16, pll_p_out2_int), PLL_OUT(3, PLLP_OUTB, 8, 0, 0, pll_p_out3), PLL_OUT(4, PLLP_OUTB, 24, 0, 16, pll_p_out4), + PLL_OUT(5, PLLP_OUTC, 24, 0, 16, pll_p_out5), }; static void __init periph_clk_init(void __iomem *clk_base, -- cgit v1.2.3 From 76da314df603a08ebc463853030752251b260ab8 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 9 Sep 2013 13:23:56 +0300 Subject: clk: tegra124: Add support for Tegra124 clocks Implement clock support for Tegra124. Signed-off-by: Peter De Schrijver --- .../bindings/clock/nvidia,tegra124-car.txt | 59 + drivers/clk/tegra/Makefile | 1 + drivers/clk/tegra/clk-tegra124.c | 1370 ++++++++++++++++++++ include/dt-bindings/clock/tegra124-car.h | 341 +++++ 4 files changed, 1771 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt create mode 100644 drivers/clk/tegra/clk-tegra124.c create mode 100644 include/dt-bindings/clock/tegra124-car.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt new file mode 100644 index 000000000000..1a91ec60dee5 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt @@ -0,0 +1,59 @@ +NVIDIA Tegra124 Clock And Reset Controller + +This binding uses the common clock binding: +Documentation/devicetree/bindings/clock/clock-bindings.txt + +The CAR (Clock And Reset) Controller on Tegra is the HW module responsible +for muxing and gating Tegra's clocks, and setting their rates. + +Required properties : +- compatible : Should be "nvidia,tegra124-car" +- reg : Should contain CAR registers location and length +- clocks : Should contain phandle and clock specifiers for two clocks: + the 32 KHz "32k_in", and the board-specific oscillator "osc". +- #clock-cells : Should be 1. + In clock consumers, this cell represents the clock ID exposed by the + CAR. The assignments may be found in header file + . + +Example SoC include file: + +/ { + tegra_car: clock { + compatible = "nvidia,tegra124-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + usb@c5004000 { + clocks = <&tegra_car TEGRA124_CLK_USB2>; + }; +}; + +Example board file: + +/ { + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + osc: clock@0 { + compatible = "fixed-clock"; + reg = <0>; + #clock-cells = <0>; + clock-frequency = <112400000>; + }; + + clk_32k: clock@1 { + compatible = "fixed-clock"; + reg = <1>; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + }; + + &tegra_car { + clocks = <&clk_32k> <&osc>; + }; +}; diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 2d837411dfed..f7dfb72884a4 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -14,3 +14,4 @@ obj-y += clk-tegra-super-gen4.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o +obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c new file mode 100644 index 000000000000..f69367a14777 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra124.c @@ -0,0 +1,1370 @@ +/* + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "clk-id.h" + +#define CLK_SOURCE_EMC 0x19c +#define CLK_SOURCE_XUSB_SS_SRC 0x610 + +#define PLLC_BASE 0x80 +#define PLLC_OUT 0x84 +#define PLLC_MISC2 0x88 +#define PLLC_MISC 0x8c +#define PLLC2_BASE 0x4e8 +#define PLLC2_MISC 0x4ec +#define PLLC3_BASE 0x4fc +#define PLLC3_MISC 0x500 +#define PLLM_BASE 0x90 +#define PLLM_OUT 0x94 +#define PLLM_MISC 0x9c +#define PLLP_BASE 0xa0 +#define PLLP_MISC 0xac +#define PLLA_BASE 0xb0 +#define PLLA_MISC 0xbc +#define PLLD_BASE 0xd0 +#define PLLD_MISC 0xdc +#define PLLU_BASE 0xc0 +#define PLLU_MISC 0xcc +#define PLLX_BASE 0xe0 +#define PLLX_MISC 0xe4 +#define PLLX_MISC2 0x514 +#define PLLX_MISC3 0x518 +#define PLLE_BASE 0xe8 +#define PLLE_MISC 0xec +#define PLLD2_BASE 0x4b8 +#define PLLD2_MISC 0x4bc +#define PLLE_AUX 0x48c +#define PLLRE_BASE 0x4c4 +#define PLLRE_MISC 0x4c8 +#define PLLDP_BASE 0x590 +#define PLLDP_MISC 0x594 +#define PLLC4_BASE 0x5a4 +#define PLLC4_MISC 0x5a8 + +#define PLLC_IDDQ_BIT 26 +#define PLLRE_IDDQ_BIT 16 +#define PLLSS_IDDQ_BIT 19 + +#define PLL_BASE_LOCK BIT(27) +#define PLLE_MISC_LOCK BIT(11) +#define PLLRE_MISC_LOCK BIT(24) + +#define PLL_MISC_LOCK_ENABLE 18 +#define PLLC_MISC_LOCK_ENABLE 24 +#define PLLDU_MISC_LOCK_ENABLE 22 +#define PLLE_MISC_LOCK_ENABLE 9 +#define PLLRE_MISC_LOCK_ENABLE 30 +#define PLLSS_MISC_LOCK_ENABLE 30 + +#define PLLXC_SW_MAX_P 6 + +#define PMC_PLLM_WB0_OVERRIDE 0x1dc +#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0 + +#define UTMIP_PLL_CFG2 0x488 +#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) +#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) + +#define UTMIP_PLL_CFG1 0x484 +#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) +#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) +#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) + +#define UTMIPLL_HW_PWRDN_CFG0 0x52c +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) +#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4) +#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) + +static void __iomem *clk_base; +static void __iomem *pmc_base; + +static unsigned long osc_freq; +static unsigned long pll_ref_freq; + +static DEFINE_SPINLOCK(pll_d_lock); +static DEFINE_SPINLOCK(pll_d2_lock); +static DEFINE_SPINLOCK(pll_e_lock); +static DEFINE_SPINLOCK(pll_re_lock); +static DEFINE_SPINLOCK(pll_u_lock); + +/* possible OSC frequencies in Hz */ +static unsigned long tegra124_input_freq[] = { + [0] = 13000000, + [1] = 16800000, + [4] = 19200000, + [5] = 38400000, + [8] = 12000000, + [9] = 48000000, + [12] = 260000000, +}; + +static const char *mux_plld_out0_plld2_out0[] = { + "pll_d_out0", "pll_d2_out0", +}; +#define mux_plld_out0_plld2_out0_idx NULL + +static const char *mux_pllmcp_clkm[] = { + "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3", +}; +#define mux_pllmcp_clkm_idx NULL + +static struct div_nmp pllxc_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 4, +}; + +static struct pdiv_map pllxc_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, + { .pdiv = 12, .hw_val = 10 }, + { .pdiv = 16, .hw_val = 11 }, + { .pdiv = 20, .hw_val = 12 }, + { .pdiv = 24, .hw_val = 13 }, + { .pdiv = 32, .hw_val = 14 }, + { .pdiv = 0, .hw_val = 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { + /* 1 GHz */ + {12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */ + {13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */ + {16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */ + {19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */ + {26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */ + {0, 0, 0, 0, 0, 0}, +}; + +static struct tegra_clk_pll_params pll_x_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .vco_min = 700000000, + .vco_max = 3000000000UL, + .base_reg = PLLX_BASE, + .misc_reg = PLLX_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLX_MISC3, + .iddq_bit_idx = 3, + .max_p = 6, + .dyn_ramp_reg = PLLX_MISC2, + .stepa_shift = 16, + .stepb_shift = 24, + .pdiv_tohw = pllxc_p, + .div_nmp = &pllxc_nmp, + .freq_table = pll_x_freq_table, + .flags = TEGRA_PLL_USE_LOCK, +}; + +static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { + { 12000000, 624000000, 104, 1, 2}, + { 12000000, 600000000, 100, 1, 2}, + { 13000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2}, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2}, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2}, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_c_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .vco_min = 600000000, + .vco_max = 1400000000, + .base_reg = PLLC_BASE, + .misc_reg = PLLC_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLC_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLC_MISC, + .iddq_bit_idx = PLLC_IDDQ_BIT, + .max_p = PLLXC_SW_MAX_P, + .dyn_ramp_reg = PLLC_MISC2, + .stepa_shift = 17, + .stepb_shift = 9, + .pdiv_tohw = pllxc_p, + .div_nmp = &pllxc_nmp, + .freq_table = pll_c_freq_table, + .flags = TEGRA_PLL_USE_LOCK, +}; + +static struct div_nmp pllcx_nmp = { + .divm_shift = 0, + .divm_width = 2, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 3, +}; + +static struct pdiv_map pllc_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 6, .hw_val = 4 }, + { .pdiv = 8, .hw_val = 5 }, + { .pdiv = 12, .hw_val = 6 }, + { .pdiv = 16, .hw_val = 7 }, + { .pdiv = 0, .hw_val = 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { + {12000000, 600000000, 100, 1, 2}, + {13000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ + {16800000, 600000000, 71, 1, 2}, /* actual: 596.4 MHz */ + {19200000, 600000000, 62, 1, 2}, /* actual: 595.2 MHz */ + {26000000, 600000000, 92, 2, 2}, /* actual: 598.0 MHz */ + {0, 0, 0, 0, 0, 0}, +}; + +static struct tegra_clk_pll_params pll_c2_params = { + .input_min = 12000000, + .input_max = 48000000, + .cf_min = 12000000, + .cf_max = 19200000, + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLC2_BASE, + .misc_reg = PLLC2_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .pdiv_tohw = pllc_p, + .div_nmp = &pllcx_nmp, + .max_p = 7, + .ext_misc_reg[0] = 0x4f0, + .ext_misc_reg[1] = 0x4f4, + .ext_misc_reg[2] = 0x4f8, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, +}; + +static struct tegra_clk_pll_params pll_c3_params = { + .input_min = 12000000, + .input_max = 48000000, + .cf_min = 12000000, + .cf_max = 19200000, + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLC3_BASE, + .misc_reg = PLLC3_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .pdiv_tohw = pllc_p, + .div_nmp = &pllcx_nmp, + .max_p = 7, + .ext_misc_reg[0] = 0x504, + .ext_misc_reg[1] = 0x508, + .ext_misc_reg[2] = 0x50c, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, +}; + +static struct div_nmp pllss_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 4, +}; + +static struct pdiv_map pll12g_ssd_esd_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, + { .pdiv = 12, .hw_val = 10 }, + { .pdiv = 16, .hw_val = 11 }, + { .pdiv = 20, .hw_val = 12 }, + { .pdiv = 24, .hw_val = 13 }, + { .pdiv = 32, .hw_val = 14 }, + { .pdiv = 0, .hw_val = 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_c4_freq_table[] = { + { 12000000, 600000000, 100, 1, 1}, + { 13000000, 600000000, 92, 1, 1}, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 1}, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 1}, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 1}, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_c4_params = { + .input_min = 12000000, + .input_max = 1000000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */ + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLC4_BASE, + .misc_reg = PLLC4_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLC4_BASE, + .iddq_bit_idx = PLLSS_IDDQ_BIT, + .pdiv_tohw = pll12g_ssd_esd_p, + .div_nmp = &pllss_nmp, + .ext_misc_reg[0] = 0x5ac, + .ext_misc_reg[1] = 0x5b0, + .ext_misc_reg[2] = 0x5b4, + .freq_table = pll_c4_freq_table, +}; + +static struct pdiv_map pllm_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 0, .hw_val = 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { + {12000000, 800000000, 66, 1, 1}, /* actual: 792.0 MHz */ + {13000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */ + {16800000, 800000000, 47, 1, 1}, /* actual: 789.6 MHz */ + {19200000, 800000000, 41, 1, 1}, /* actual: 787.2 MHz */ + {26000000, 800000000, 61, 2, 1}, /* actual: 793.0 MHz */ + {0, 0, 0, 0, 0, 0}, +}; + +static struct div_nmp pllm_nmp = { + .divm_shift = 0, + .divm_width = 8, + .override_divm_shift = 0, + .divn_shift = 8, + .divn_width = 8, + .override_divn_shift = 8, + .divp_shift = 20, + .divp_width = 1, + .override_divp_shift = 27, +}; + +static struct tegra_clk_pll_params pll_m_params = { + .input_min = 12000000, + .input_max = 500000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .vco_min = 400000000, + .vco_max = 1066000000, + .base_reg = PLLM_BASE, + .misc_reg = PLLM_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .max_p = 2, + .pdiv_tohw = pllm_p, + .div_nmp = &pllm_nmp, + .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, + .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2, + .freq_table = pll_m_freq_table, + .flags = TEGRA_PLL_USE_LOCK, +}; + +static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { + /* PLLE special case: use cpcon field to store cml divider value */ + {336000000, 100000000, 100, 21, 16, 11}, + {312000000, 100000000, 200, 26, 24, 13}, + {13000000, 100000000, 200, 1, 26, 13}, + {12000000, 100000000, 200, 1, 24, 13}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct div_nmp plle_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 24, + .divp_width = 4, +}; + +static struct tegra_clk_pll_params pll_e_params = { + .input_min = 12000000, + .input_max = 1000000000, + .cf_min = 12000000, + .cf_max = 75000000, + .vco_min = 1600000000, + .vco_max = 2400000000U, + .base_reg = PLLE_BASE, + .misc_reg = PLLE_MISC, + .aux_reg = PLLE_AUX, + .lock_mask = PLLE_MISC_LOCK, + .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, + .lock_delay = 300, + .div_nmp = &plle_nmp, + .freq_table = pll_e_freq_table, + .flags = TEGRA_PLL_FIXED, + .fixed_rate = 100000000, +}; + +static const struct clk_div_table pll_re_div_table[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 4, .div = 5 }, + { .val = 5, .div = 6 }, + { .val = 0, .div = 0 }, +}; + +static struct div_nmp pllre_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 16, + .divp_width = 4, +}; + +static struct tegra_clk_pll_params pll_re_vco_params = { + .input_min = 12000000, + .input_max = 1000000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */ + .vco_min = 300000000, + .vco_max = 600000000, + .base_reg = PLLRE_BASE, + .misc_reg = PLLRE_MISC, + .lock_mask = PLLRE_MISC_LOCK, + .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLRE_MISC, + .iddq_bit_idx = PLLRE_IDDQ_BIT, + .div_nmp = &pllre_nmp, + .flags = TEGRA_PLL_USE_LOCK, +}; + +static struct div_nmp pllp_nmp = { + .divm_shift = 0, + .divm_width = 5, + .divn_shift = 8, + .divn_width = 10, + .divp_shift = 20, + .divp_width = 3, +}; + +static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { + {12000000, 216000000, 432, 12, 1, 8}, + {13000000, 216000000, 432, 13, 1, 8}, + {16800000, 216000000, 360, 14, 1, 8}, + {19200000, 216000000, 360, 16, 1, 8}, + {26000000, 216000000, 432, 26, 1, 8}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct tegra_clk_pll_params pll_p_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 200000000, + .vco_max = 700000000, + .base_reg = PLLP_BASE, + .misc_reg = PLLP_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .div_nmp = &pllp_nmp, + .freq_table = pll_p_freq_table, + .fixed_rate = 408000000, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, +}; + +static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { + {9600000, 282240000, 147, 5, 0, 4}, + {9600000, 368640000, 192, 5, 0, 4}, + {9600000, 240000000, 200, 8, 0, 8}, + + {28800000, 282240000, 245, 25, 0, 8}, + {28800000, 368640000, 320, 25, 0, 8}, + {28800000, 240000000, 200, 24, 0, 8}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct tegra_clk_pll_params pll_a_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 200000000, + .vco_max = 700000000, + .base_reg = PLLA_BASE, + .misc_reg = PLLA_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .div_nmp = &pllp_nmp, + .freq_table = pll_a_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, +}; + +static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { + {12000000, 216000000, 864, 12, 4, 12}, + {13000000, 216000000, 864, 13, 4, 12}, + {16800000, 216000000, 720, 14, 4, 12}, + {19200000, 216000000, 720, 16, 4, 12}, + {26000000, 216000000, 864, 26, 4, 12}, + + {12000000, 594000000, 594, 12, 1, 12}, + {13000000, 594000000, 594, 13, 1, 12}, + {16800000, 594000000, 495, 14, 1, 12}, + {19200000, 594000000, 495, 16, 1, 12}, + {26000000, 594000000, 594, 26, 1, 12}, + + {12000000, 1000000000, 1000, 12, 1, 12}, + {13000000, 1000000000, 1000, 13, 1, 12}, + {19200000, 1000000000, 625, 12, 1, 12}, + {26000000, 1000000000, 1000, 26, 1, 12}, + + {0, 0, 0, 0, 0, 0}, +}; + +static struct tegra_clk_pll_params pll_d_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 500000000, + .vco_max = 1000000000, + .base_reg = PLLD_BASE, + .misc_reg = PLLD_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, + .div_nmp = &pllp_nmp, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, +}; + +static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = { + { 12000000, 148500000, 99, 1, 8}, + { 12000000, 594000000, 99, 1, 1}, + { 13000000, 594000000, 91, 1, 1}, /* actual: 591.5 MHz */ + { 16800000, 594000000, 71, 1, 1}, /* actual: 596.4 MHz */ + { 19200000, 594000000, 62, 1, 1}, /* actual: 595.2 MHz */ + { 26000000, 594000000, 91, 2, 1}, /* actual: 591.5 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params tegra124_pll_d2_params = { + .input_min = 12000000, + .input_max = 1000000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */ + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLD2_BASE, + .misc_reg = PLLD2_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLD2_BASE, + .iddq_bit_idx = PLLSS_IDDQ_BIT, + .pdiv_tohw = pll12g_ssd_esd_p, + .div_nmp = &pllss_nmp, + .ext_misc_reg[0] = 0x570, + .ext_misc_reg[1] = 0x574, + .ext_misc_reg[2] = 0x578, + .max_p = 15, + .freq_table = tegra124_pll_d2_freq_table, +}; + +static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = { + { 12000000, 600000000, 100, 1, 1}, + { 13000000, 600000000, 92, 1, 1}, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 1}, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 1}, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 1}, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_dp_params = { + .input_min = 12000000, + .input_max = 1000000000, + .cf_min = 12000000, + .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */ + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLDP_BASE, + .misc_reg = PLLDP_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLDP_BASE, + .iddq_bit_idx = PLLSS_IDDQ_BIT, + .pdiv_tohw = pll12g_ssd_esd_p, + .div_nmp = &pllss_nmp, + .ext_misc_reg[0] = 0x598, + .ext_misc_reg[1] = 0x59c, + .ext_misc_reg[2] = 0x5a0, + .max_p = 5, + .freq_table = pll_dp_freq_table, +}; + +static struct pdiv_map pllu_p[] = { + { .pdiv = 1, .hw_val = 1 }, + { .pdiv = 2, .hw_val = 0 }, + { .pdiv = 0, .hw_val = 0 }, +}; + +static struct div_nmp pllu_nmp = { + .divm_shift = 0, + .divm_width = 5, + .divn_shift = 8, + .divn_width = 10, + .divp_shift = 20, + .divp_width = 1, +}; + +static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { + {12000000, 480000000, 960, 12, 2, 12}, + {13000000, 480000000, 960, 13, 2, 12}, + {16800000, 480000000, 400, 7, 2, 5}, + {19200000, 480000000, 200, 4, 2, 3}, + {26000000, 480000000, 960, 26, 2, 12}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct tegra_clk_pll_params pll_u_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 480000000, + .vco_max = 960000000, + .base_reg = PLLU_BASE, + .misc_reg = PLLU_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, + .pdiv_tohw = pllu_p, + .div_nmp = &pllu_nmp, + .freq_table = pll_u_freq_table, + .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_USE_LOCK, +}; + +struct utmi_clk_param { + /* Oscillator Frequency in KHz */ + u32 osc_frequency; + /* UTMIP PLL Enable Delay Count */ + u8 enable_delay_count; + /* UTMIP PLL Stable count */ + u8 stable_count; + /* UTMIP PLL Active delay count */ + u8 active_delay_count; + /* UTMIP PLL Xtal frequency count */ + u8 xtal_freq_count; +}; + +static const struct utmi_clk_param utmi_parameters[] = { + {.osc_frequency = 13000000, .enable_delay_count = 0x02, + .stable_count = 0x33, .active_delay_count = 0x05, + .xtal_freq_count = 0x7F}, + {.osc_frequency = 19200000, .enable_delay_count = 0x03, + .stable_count = 0x4B, .active_delay_count = 0x06, + .xtal_freq_count = 0xBB}, + {.osc_frequency = 12000000, .enable_delay_count = 0x02, + .stable_count = 0x2F, .active_delay_count = 0x04, + .xtal_freq_count = 0x76}, + {.osc_frequency = 26000000, .enable_delay_count = 0x04, + .stable_count = 0x66, .active_delay_count = 0x09, + .xtal_freq_count = 0xFE}, + {.osc_frequency = 16800000, .enable_delay_count = 0x03, + .stable_count = 0x41, .active_delay_count = 0x0A, + .xtal_freq_count = 0xA4}, +}; + +static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { + [tegra_clk_ispb] = { .dt_id = TEGRA124_CLK_ISPB, .present = true }, + [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true }, + [tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true }, + [tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true }, + [tegra_clk_sdmmc2] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true }, + [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true }, + [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true }, + [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true }, + [tegra_clk_sdmmc1] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc4] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true }, + [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true }, + [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true }, + [tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true }, + [tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true }, + [tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true }, + [tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true }, + [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true }, + [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true }, + [tegra_clk_host1x] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true }, + [tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true }, + [tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true }, + [tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true }, + [tegra_clk_kbc] = { .dt_id = TEGRA124_CLK_KBC, .present = true }, + [tegra_clk_kfuse] = { .dt_id = TEGRA124_CLK_KFUSE, .present = true }, + [tegra_clk_sbc1] = { .dt_id = TEGRA124_CLK_SBC1, .present = true }, + [tegra_clk_nor] = { .dt_id = TEGRA124_CLK_NOR, .present = true }, + [tegra_clk_sbc2] = { .dt_id = TEGRA124_CLK_SBC2, .present = true }, + [tegra_clk_sbc3] = { .dt_id = TEGRA124_CLK_SBC3, .present = true }, + [tegra_clk_i2c5] = { .dt_id = TEGRA124_CLK_I2C5, .present = true }, + [tegra_clk_dsia] = { .dt_id = TEGRA124_CLK_DSIA, .present = true }, + [tegra_clk_mipi] = { .dt_id = TEGRA124_CLK_MIPI, .present = true }, + [tegra_clk_hdmi] = { .dt_id = TEGRA124_CLK_HDMI, .present = true }, + [tegra_clk_csi] = { .dt_id = TEGRA124_CLK_CSI, .present = true }, + [tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true }, + [tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true }, + [tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true }, + [tegra_clk_emc] = { .dt_id = TEGRA124_CLK_EMC, .present = true }, + [tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true }, + [tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true }, + [tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true }, + [tegra_clk_bsea] = { .dt_id = TEGRA124_CLK_BSEA, .present = true }, + [tegra_clk_bsev] = { .dt_id = TEGRA124_CLK_BSEV, .present = true }, + [tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true }, + [tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true }, + [tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true }, + [tegra_clk_sdmmc3] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true }, + [tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true }, + [tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true }, + [tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true }, + [tegra_clk_csite] = { .dt_id = TEGRA124_CLK_CSITE, .present = true }, + [tegra_clk_la] = { .dt_id = TEGRA124_CLK_LA, .present = true }, + [tegra_clk_trace] = { .dt_id = TEGRA124_CLK_TRACE, .present = true }, + [tegra_clk_soc_therm] = { .dt_id = TEGRA124_CLK_SOC_THERM, .present = true }, + [tegra_clk_dtv] = { .dt_id = TEGRA124_CLK_DTV, .present = true }, + [tegra_clk_ndspeed] = { .dt_id = TEGRA124_CLK_NDSPEED, .present = true }, + [tegra_clk_i2cslow] = { .dt_id = TEGRA124_CLK_I2CSLOW, .present = true }, + [tegra_clk_dsib] = { .dt_id = TEGRA124_CLK_DSIB, .present = true }, + [tegra_clk_tsec] = { .dt_id = TEGRA124_CLK_TSEC, .present = true }, + [tegra_clk_xusb_host] = { .dt_id = TEGRA124_CLK_XUSB_HOST, .present = true }, + [tegra_clk_msenc] = { .dt_id = TEGRA124_CLK_MSENC, .present = true }, + [tegra_clk_csus] = { .dt_id = TEGRA124_CLK_CSUS, .present = true }, + [tegra_clk_mselect] = { .dt_id = TEGRA124_CLK_MSELECT, .present = true }, + [tegra_clk_tsensor] = { .dt_id = TEGRA124_CLK_TSENSOR, .present = true }, + [tegra_clk_i2s3] = { .dt_id = TEGRA124_CLK_I2S3, .present = true }, + [tegra_clk_i2s4] = { .dt_id = TEGRA124_CLK_I2S4, .present = true }, + [tegra_clk_i2c4] = { .dt_id = TEGRA124_CLK_I2C4, .present = true }, + [tegra_clk_sbc5] = { .dt_id = TEGRA124_CLK_SBC5, .present = true }, + [tegra_clk_sbc6] = { .dt_id = TEGRA124_CLK_SBC6, .present = true }, + [tegra_clk_d_audio] = { .dt_id = TEGRA124_CLK_D_AUDIO, .present = true }, + [tegra_clk_apbif] = { .dt_id = TEGRA124_CLK_APBIF, .present = true }, + [tegra_clk_dam0] = { .dt_id = TEGRA124_CLK_DAM0, .present = true }, + [tegra_clk_dam1] = { .dt_id = TEGRA124_CLK_DAM1, .present = true }, + [tegra_clk_dam2] = { .dt_id = TEGRA124_CLK_DAM2, .present = true }, + [tegra_clk_hda2codec_2x] = { .dt_id = TEGRA124_CLK_HDA2CODEC_2X, .present = true }, + [tegra_clk_audio0_2x] = { .dt_id = TEGRA124_CLK_AUDIO0_2X, .present = true }, + [tegra_clk_audio1_2x] = { .dt_id = TEGRA124_CLK_AUDIO1_2X, .present = true }, + [tegra_clk_audio2_2x] = { .dt_id = TEGRA124_CLK_AUDIO2_2X, .present = true }, + [tegra_clk_audio3_2x] = { .dt_id = TEGRA124_CLK_AUDIO3_2X, .present = true }, + [tegra_clk_audio4_2x] = { .dt_id = TEGRA124_CLK_AUDIO4_2X, .present = true }, + [tegra_clk_spdif_2x] = { .dt_id = TEGRA124_CLK_SPDIF_2X, .present = true }, + [tegra_clk_actmon] = { .dt_id = TEGRA124_CLK_ACTMON, .present = true }, + [tegra_clk_extern1] = { .dt_id = TEGRA124_CLK_EXTERN1, .present = true }, + [tegra_clk_extern2] = { .dt_id = TEGRA124_CLK_EXTERN2, .present = true }, + [tegra_clk_extern3] = { .dt_id = TEGRA124_CLK_EXTERN3, .present = true }, + [tegra_clk_sata_oob] = { .dt_id = TEGRA124_CLK_SATA_OOB, .present = true }, + [tegra_clk_sata] = { .dt_id = TEGRA124_CLK_SATA, .present = true }, + [tegra_clk_hda] = { .dt_id = TEGRA124_CLK_HDA, .present = true }, + [tegra_clk_se] = { .dt_id = TEGRA124_CLK_SE, .present = true }, + [tegra_clk_hda2hdmi] = { .dt_id = TEGRA124_CLK_HDA2HDMI, .present = true }, + [tegra_clk_sata_cold] = { .dt_id = TEGRA124_CLK_SATA_COLD, .present = true }, + [tegra_clk_cilab] = { .dt_id = TEGRA124_CLK_CILAB, .present = true }, + [tegra_clk_cilcd] = { .dt_id = TEGRA124_CLK_CILCD, .present = true }, + [tegra_clk_cile] = { .dt_id = TEGRA124_CLK_CILE, .present = true }, + [tegra_clk_dsialp] = { .dt_id = TEGRA124_CLK_DSIALP, .present = true }, + [tegra_clk_dsiblp] = { .dt_id = TEGRA124_CLK_DSIBLP, .present = true }, + [tegra_clk_entropy] = { .dt_id = TEGRA124_CLK_ENTROPY, .present = true }, + [tegra_clk_dds] = { .dt_id = TEGRA124_CLK_DDS, .present = true }, + [tegra_clk_dp2] = { .dt_id = TEGRA124_CLK_DP2, .present = true }, + [tegra_clk_amx] = { .dt_id = TEGRA124_CLK_AMX, .present = true }, + [tegra_clk_adx] = { .dt_id = TEGRA124_CLK_ADX, .present = true }, + [tegra_clk_xusb_ss] = { .dt_id = TEGRA124_CLK_XUSB_SS, .present = true }, + [tegra_clk_i2c6] = { .dt_id = TEGRA124_CLK_I2C6, .present = true }, + [tegra_clk_vim2_clk] = { .dt_id = TEGRA124_CLK_VIM2_CLK, .present = true }, + [tegra_clk_hdmi_audio] = { .dt_id = TEGRA124_CLK_HDMI_AUDIO, .present = true }, + [tegra_clk_clk72Mhz] = { .dt_id = TEGRA124_CLK_CLK72MHZ, .present = true }, + [tegra_clk_vic03] = { .dt_id = TEGRA124_CLK_VIC03, .present = true }, + [tegra_clk_adx1] = { .dt_id = TEGRA124_CLK_ADX1, .present = true }, + [tegra_clk_dpaux] = { .dt_id = TEGRA124_CLK_DPAUX, .present = true }, + [tegra_clk_sor0] = { .dt_id = TEGRA124_CLK_SOR0, .present = true }, + [tegra_clk_sor0_lvds] = { .dt_id = TEGRA124_CLK_SOR0_LVDS, .present = true }, + [tegra_clk_gpu] = { .dt_id = TEGRA124_CLK_GPU, .present = true }, + [tegra_clk_amx1] = { .dt_id = TEGRA124_CLK_AMX1, .present = true }, + [tegra_clk_uartb] = { .dt_id = TEGRA124_CLK_UARTB, .present = true }, + [tegra_clk_vfir] = { .dt_id = TEGRA124_CLK_VFIR, .present = true }, + [tegra_clk_spdif_in] = { .dt_id = TEGRA124_CLK_SPDIF_IN, .present = true }, + [tegra_clk_spdif_out] = { .dt_id = TEGRA124_CLK_SPDIF_OUT, .present = true }, + [tegra_clk_vi_9] = { .dt_id = TEGRA124_CLK_VI, .present = true }, + [tegra_clk_vi_sensor] = { .dt_id = TEGRA124_CLK_VI_SENSOR, .present = true }, + [tegra_clk_fuse] = { .dt_id = TEGRA124_CLK_FUSE, .present = true }, + [tegra_clk_fuse_burn] = { .dt_id = TEGRA124_CLK_FUSE_BURN, .present = true }, + [tegra_clk_clk_32k] = { .dt_id = TEGRA124_CLK_CLK_32K, .present = true }, + [tegra_clk_clk_m] = { .dt_id = TEGRA124_CLK_CLK_M, .present = true }, + [tegra_clk_clk_m_div2] = { .dt_id = TEGRA124_CLK_CLK_M_DIV2, .present = true }, + [tegra_clk_clk_m_div4] = { .dt_id = TEGRA124_CLK_CLK_M_DIV4, .present = true }, + [tegra_clk_pll_ref] = { .dt_id = TEGRA124_CLK_PLL_REF, .present = true }, + [tegra_clk_pll_c] = { .dt_id = TEGRA124_CLK_PLL_C, .present = true }, + [tegra_clk_pll_c_out1] = { .dt_id = TEGRA124_CLK_PLL_C_OUT1, .present = true }, + [tegra_clk_pll_c2] = { .dt_id = TEGRA124_CLK_PLL_C2, .present = true }, + [tegra_clk_pll_c3] = { .dt_id = TEGRA124_CLK_PLL_C3, .present = true }, + [tegra_clk_pll_m] = { .dt_id = TEGRA124_CLK_PLL_M, .present = true }, + [tegra_clk_pll_m_out1] = { .dt_id = TEGRA124_CLK_PLL_M_OUT1, .present = true }, + [tegra_clk_pll_p] = { .dt_id = TEGRA124_CLK_PLL_P, .present = true }, + [tegra_clk_pll_p_out1] = { .dt_id = TEGRA124_CLK_PLL_P_OUT1, .present = true }, + [tegra_clk_pll_p_out2] = { .dt_id = TEGRA124_CLK_PLL_P_OUT2, .present = true }, + [tegra_clk_pll_p_out3] = { .dt_id = TEGRA124_CLK_PLL_P_OUT3, .present = true }, + [tegra_clk_pll_p_out4] = { .dt_id = TEGRA124_CLK_PLL_P_OUT4, .present = true }, + [tegra_clk_pll_a] = { .dt_id = TEGRA124_CLK_PLL_A, .present = true }, + [tegra_clk_pll_a_out0] = { .dt_id = TEGRA124_CLK_PLL_A_OUT0, .present = true }, + [tegra_clk_pll_d] = { .dt_id = TEGRA124_CLK_PLL_D, .present = true }, + [tegra_clk_pll_d_out0] = { .dt_id = TEGRA124_CLK_PLL_D_OUT0, .present = true }, + [tegra_clk_pll_d2] = { .dt_id = TEGRA124_CLK_PLL_D2, .present = true }, + [tegra_clk_pll_d2_out0] = { .dt_id = TEGRA124_CLK_PLL_D2_OUT0, .present = true }, + [tegra_clk_pll_u] = { .dt_id = TEGRA124_CLK_PLL_U, .present = true }, + [tegra_clk_pll_u_480m] = { .dt_id = TEGRA124_CLK_PLL_U_480M, .present = true }, + [tegra_clk_pll_u_60m] = { .dt_id = TEGRA124_CLK_PLL_U_60M, .present = true }, + [tegra_clk_pll_u_48m] = { .dt_id = TEGRA124_CLK_PLL_U_48M, .present = true }, + [tegra_clk_pll_u_12m] = { .dt_id = TEGRA124_CLK_PLL_U_12M, .present = true }, + [tegra_clk_pll_x] = { .dt_id = TEGRA124_CLK_PLL_X, .present = true }, + [tegra_clk_pll_x_out0] = { .dt_id = TEGRA124_CLK_PLL_X_OUT0, .present = true }, + [tegra_clk_pll_re_vco] = { .dt_id = TEGRA124_CLK_PLL_RE_VCO, .present = true }, + [tegra_clk_pll_re_out] = { .dt_id = TEGRA124_CLK_PLL_RE_OUT, .present = true }, + [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA124_CLK_SPDIF_IN_SYNC, .present = true }, + [tegra_clk_i2s0_sync] = { .dt_id = TEGRA124_CLK_I2S0_SYNC, .present = true }, + [tegra_clk_i2s1_sync] = { .dt_id = TEGRA124_CLK_I2S1_SYNC, .present = true }, + [tegra_clk_i2s2_sync] = { .dt_id = TEGRA124_CLK_I2S2_SYNC, .present = true }, + [tegra_clk_i2s3_sync] = { .dt_id = TEGRA124_CLK_I2S3_SYNC, .present = true }, + [tegra_clk_i2s4_sync] = { .dt_id = TEGRA124_CLK_I2S4_SYNC, .present = true }, + [tegra_clk_vimclk_sync] = { .dt_id = TEGRA124_CLK_VIMCLK_SYNC, .present = true }, + [tegra_clk_audio0] = { .dt_id = TEGRA124_CLK_AUDIO0, .present = true }, + [tegra_clk_audio1] = { .dt_id = TEGRA124_CLK_AUDIO1, .present = true }, + [tegra_clk_audio2] = { .dt_id = TEGRA124_CLK_AUDIO2, .present = true }, + [tegra_clk_audio3] = { .dt_id = TEGRA124_CLK_AUDIO3, .present = true }, + [tegra_clk_audio4] = { .dt_id = TEGRA124_CLK_AUDIO4, .present = true }, + [tegra_clk_spdif] = { .dt_id = TEGRA124_CLK_SPDIF, .present = true }, + [tegra_clk_clk_out_1] = { .dt_id = TEGRA124_CLK_CLK_OUT_1, .present = true }, + [tegra_clk_clk_out_2] = { .dt_id = TEGRA124_CLK_CLK_OUT_2, .present = true }, + [tegra_clk_clk_out_3] = { .dt_id = TEGRA124_CLK_CLK_OUT_3, .present = true }, + [tegra_clk_blink] = { .dt_id = TEGRA124_CLK_BLINK, .present = true }, + [tegra_clk_xusb_host_src] = { .dt_id = TEGRA124_CLK_XUSB_HOST_SRC, .present = true }, + [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA124_CLK_XUSB_FALCON_SRC, .present = true }, + [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA124_CLK_XUSB_FS_SRC, .present = true }, + [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA124_CLK_XUSB_SS_SRC, .present = true }, + [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA124_CLK_XUSB_DEV_SRC, .present = true }, + [tegra_clk_xusb_dev] = { .dt_id = TEGRA124_CLK_XUSB_DEV, .present = true }, + [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA124_CLK_XUSB_HS_SRC, .present = true }, + [tegra_clk_sclk] = { .dt_id = TEGRA124_CLK_SCLK, .present = true }, + [tegra_clk_hclk] = { .dt_id = TEGRA124_CLK_HCLK, .present = true }, + [tegra_clk_pclk] = { .dt_id = TEGRA124_CLK_PCLK, .present = true }, + [tegra_clk_cclk_g] = { .dt_id = TEGRA124_CLK_CCLK_G, .present = true }, + [tegra_clk_cclk_lp] = { .dt_id = TEGRA124_CLK_CCLK_LP, .present = true }, + [tegra_clk_dfll_ref] = { .dt_id = TEGRA124_CLK_DFLL_REF, .present = true }, + [tegra_clk_dfll_soc] = { .dt_id = TEGRA124_CLK_DFLL_SOC, .present = true }, + [tegra_clk_vi_sensor2] = { .dt_id = TEGRA124_CLK_VI_SENSOR2, .present = true }, + [tegra_clk_pll_p_out5] = { .dt_id = TEGRA124_CLK_PLL_P_OUT5, .present = true }, + [tegra_clk_pll_c4] = { .dt_id = TEGRA124_CLK_PLL_C4, .present = true }, + [tegra_clk_pll_dp] = { .dt_id = TEGRA124_CLK_PLL_DP, .present = true }, + [tegra_clk_audio0_mux] = { .dt_id = TEGRA124_CLK_AUDIO0_MUX, .present = true }, + [tegra_clk_audio1_mux] = { .dt_id = TEGRA124_CLK_AUDIO1_MUX, .present = true }, + [tegra_clk_audio2_mux] = { .dt_id = TEGRA124_CLK_AUDIO2_MUX, .present = true }, + [tegra_clk_audio3_mux] = { .dt_id = TEGRA124_CLK_AUDIO3_MUX, .present = true }, + [tegra_clk_audio4_mux] = { .dt_id = TEGRA124_CLK_AUDIO4_MUX, .present = true }, + [tegra_clk_spdif_mux] = { .dt_id = TEGRA124_CLK_SPDIF_MUX, .present = true }, + [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true }, + [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true }, + [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true }, + [tegra_clk_dsia_mux] = { .dt_id = TEGRA124_CLK_DSIA_MUX, .present = true }, + [tegra_clk_dsib_mux] = { .dt_id = TEGRA124_CLK_DSIB_MUX, .present = true }, + [tegra_clk_uarte] = { .dt_id = TEGRA124_CLK_UARTE, .present = true }, +}; + +static struct tegra_devclk devclks[] __initdata = { + { .con_id = "clk_m", .dt_id = TEGRA124_CLK_CLK_M }, + { .con_id = "pll_ref", .dt_id = TEGRA124_CLK_PLL_REF }, + { .con_id = "clk_32k", .dt_id = TEGRA124_CLK_CLK_32K }, + { .con_id = "clk_m_div2", .dt_id = TEGRA124_CLK_CLK_M_DIV2 }, + { .con_id = "clk_m_div4", .dt_id = TEGRA124_CLK_CLK_M_DIV4 }, + { .con_id = "pll_c", .dt_id = TEGRA124_CLK_PLL_C }, + { .con_id = "pll_c_out1", .dt_id = TEGRA124_CLK_PLL_C_OUT1 }, + { .con_id = "pll_c2", .dt_id = TEGRA124_CLK_PLL_C2 }, + { .con_id = "pll_c3", .dt_id = TEGRA124_CLK_PLL_C3 }, + { .con_id = "pll_p", .dt_id = TEGRA124_CLK_PLL_P }, + { .con_id = "pll_p_out1", .dt_id = TEGRA124_CLK_PLL_P_OUT1 }, + { .con_id = "pll_p_out2", .dt_id = TEGRA124_CLK_PLL_P_OUT2 }, + { .con_id = "pll_p_out3", .dt_id = TEGRA124_CLK_PLL_P_OUT3 }, + { .con_id = "pll_p_out4", .dt_id = TEGRA124_CLK_PLL_P_OUT4 }, + { .con_id = "pll_m", .dt_id = TEGRA124_CLK_PLL_M }, + { .con_id = "pll_m_out1", .dt_id = TEGRA124_CLK_PLL_M_OUT1 }, + { .con_id = "pll_x", .dt_id = TEGRA124_CLK_PLL_X }, + { .con_id = "pll_x_out0", .dt_id = TEGRA124_CLK_PLL_X_OUT0 }, + { .con_id = "pll_u", .dt_id = TEGRA124_CLK_PLL_U }, + { .con_id = "pll_u_480M", .dt_id = TEGRA124_CLK_PLL_U_480M }, + { .con_id = "pll_u_60M", .dt_id = TEGRA124_CLK_PLL_U_60M }, + { .con_id = "pll_u_48M", .dt_id = TEGRA124_CLK_PLL_U_48M }, + { .con_id = "pll_u_12M", .dt_id = TEGRA124_CLK_PLL_U_12M }, + { .con_id = "pll_d", .dt_id = TEGRA124_CLK_PLL_D }, + { .con_id = "pll_d_out0", .dt_id = TEGRA124_CLK_PLL_D_OUT0 }, + { .con_id = "pll_d2", .dt_id = TEGRA124_CLK_PLL_D2 }, + { .con_id = "pll_d2_out0", .dt_id = TEGRA124_CLK_PLL_D2_OUT0 }, + { .con_id = "pll_a", .dt_id = TEGRA124_CLK_PLL_A }, + { .con_id = "pll_a_out0", .dt_id = TEGRA124_CLK_PLL_A_OUT0 }, + { .con_id = "pll_re_vco", .dt_id = TEGRA124_CLK_PLL_RE_VCO }, + { .con_id = "pll_re_out", .dt_id = TEGRA124_CLK_PLL_RE_OUT }, + { .con_id = "spdif_in_sync", .dt_id = TEGRA124_CLK_SPDIF_IN_SYNC }, + { .con_id = "i2s0_sync", .dt_id = TEGRA124_CLK_I2S0_SYNC }, + { .con_id = "i2s1_sync", .dt_id = TEGRA124_CLK_I2S1_SYNC }, + { .con_id = "i2s2_sync", .dt_id = TEGRA124_CLK_I2S2_SYNC }, + { .con_id = "i2s3_sync", .dt_id = TEGRA124_CLK_I2S3_SYNC }, + { .con_id = "i2s4_sync", .dt_id = TEGRA124_CLK_I2S4_SYNC }, + { .con_id = "vimclk_sync", .dt_id = TEGRA124_CLK_VIMCLK_SYNC }, + { .con_id = "audio0", .dt_id = TEGRA124_CLK_AUDIO0 }, + { .con_id = "audio1", .dt_id = TEGRA124_CLK_AUDIO1 }, + { .con_id = "audio2", .dt_id = TEGRA124_CLK_AUDIO2 }, + { .con_id = "audio3", .dt_id = TEGRA124_CLK_AUDIO3 }, + { .con_id = "audio4", .dt_id = TEGRA124_CLK_AUDIO4 }, + { .con_id = "spdif", .dt_id = TEGRA124_CLK_SPDIF }, + { .con_id = "audio0_2x", .dt_id = TEGRA124_CLK_AUDIO0_2X }, + { .con_id = "audio1_2x", .dt_id = TEGRA124_CLK_AUDIO1_2X }, + { .con_id = "audio2_2x", .dt_id = TEGRA124_CLK_AUDIO2_2X }, + { .con_id = "audio3_2x", .dt_id = TEGRA124_CLK_AUDIO3_2X }, + { .con_id = "audio4_2x", .dt_id = TEGRA124_CLK_AUDIO4_2X }, + { .con_id = "spdif_2x", .dt_id = TEGRA124_CLK_SPDIF_2X }, + { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA124_CLK_EXTERN1 }, + { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA124_CLK_EXTERN2 }, + { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA124_CLK_EXTERN3 }, + { .con_id = "blink", .dt_id = TEGRA124_CLK_BLINK }, + { .con_id = "cclk_g", .dt_id = TEGRA124_CLK_CCLK_G }, + { .con_id = "cclk_lp", .dt_id = TEGRA124_CLK_CCLK_LP }, + { .con_id = "sclk", .dt_id = TEGRA124_CLK_SCLK }, + { .con_id = "hclk", .dt_id = TEGRA124_CLK_HCLK }, + { .con_id = "pclk", .dt_id = TEGRA124_CLK_PCLK }, + { .dev_id = "rtc-tegra", .dt_id = TEGRA124_CLK_RTC }, + { .dev_id = "timer", .dt_id = TEGRA124_CLK_TIMER }, +}; + +static struct clk **clks; + +static void tegra124_utmi_param_configure(void __iomem *clk_base) +{ + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { + if (osc_freq == utmi_parameters[i].osc_frequency) + break; + } + + if (i >= ARRAY_SIZE(utmi_parameters)) { + pr_err("%s: Unexpected oscillator freq %lu\n", __func__, + osc_freq); + return; + } + + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL stable and active counts */ + /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ + reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); + reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); + + reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); + + reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i]. + active_delay_count); + + /* Remove power downs from UTMIP PLL control bits */ + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; + + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL delay and oscillator frequency counts */ + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); + reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); + + reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i]. + enable_delay_count); + + reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); + reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i]. + xtal_freq_count); + + /* Remove power downs from UTMIP PLL control bits */ + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); + + /* Setup HW control of UTMIPLL */ + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; + reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; + reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); + + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); + + udelay(1); + + /* Setup SW override of UTMIPLL assuming USB2.0 + ports are assigned to USB2 */ + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL; + reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); + + udelay(1); + + /* Enable HW control UTMIPLL */ + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); +} + +static __init void tegra124_periph_clk_init(void __iomem *clk_base, + void __iomem *pmc_base) +{ + struct clk *clk; + u32 val; + + /* xusb_hs_src */ + val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC); + val |= BIT(25); /* always select PLLU_60M */ + writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC); + + clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, + 1, 1); + clks[TEGRA124_CLK_XUSB_HS_SRC] = clk; + + /* dsia mux */ + clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0, + clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock); + clks[TEGRA124_CLK_DSIA_MUX] = clk; + + /* dsib mux */ + clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0, + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0, + clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock); + clks[TEGRA124_CLK_DSIB_MUX] = clk; + + /* emc mux */ + clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, + ARRAY_SIZE(mux_pllmcp_clkm), 0, + clk_base + CLK_SOURCE_EMC, + 29, 3, 0, NULL); + + /* cml0 */ + clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX, + 0, 0, &pll_e_lock); + clk_register_clkdev(clk, "cml0", NULL); + clks[TEGRA124_CLK_CML0] = clk; + + /* cml1 */ + clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX, + 1, 0, &pll_e_lock); + clk_register_clkdev(clk, "cml1", NULL); + clks[TEGRA124_CLK_CML1] = clk; + + tegra_periph_clk_init(clk_base, pmc_base, tegra124_clks, &pll_p_params); +} + +static void __init tegra124_pll_init(void __iomem *clk_base, + void __iomem *pmc) +{ + u32 val; + struct clk *clk; + + /* PLLC */ + clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base, + pmc, 0, &pll_c_params, NULL); + clk_register_clkdev(clk, "pll_c", NULL); + clks[TEGRA124_CLK_PLL_C] = clk; + + /* PLLC_OUT1 */ + clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", + clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", + clk_base + PLLC_OUT, 1, 0, + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_c_out1", NULL); + clks[TEGRA124_CLK_PLL_C_OUT1] = clk; + + /* PLLC2 */ + clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, + &pll_c2_params, NULL); + clk_register_clkdev(clk, "pll_c2", NULL); + clks[TEGRA124_CLK_PLL_C2] = clk; + + /* PLLC3 */ + clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, + &pll_c3_params, NULL); + clk_register_clkdev(clk, "pll_c3", NULL); + clks[TEGRA124_CLK_PLL_C3] = clk; + + /* PLLM */ + clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, + &pll_m_params, NULL); + clk_register_clkdev(clk, "pll_m", NULL); + clks[TEGRA124_CLK_PLL_M] = clk; + + /* PLLM_OUT1 */ + clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", + clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", + clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_m_out1", NULL); + clks[TEGRA124_CLK_PLL_M_OUT1] = clk; + + /* PLLM_UD */ + clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", + CLK_SET_RATE_PARENT, 1, 1); + + /* PLLU */ + val = readl(clk_base + pll_u_params.base_reg); + val &= ~BIT(24); /* disable PLLU_OVERRIDE */ + writel(val, clk_base + pll_u_params.base_reg); + + clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0, + &pll_u_params, &pll_u_lock); + clk_register_clkdev(clk, "pll_u", NULL); + clks[TEGRA124_CLK_PLL_U] = clk; + + tegra124_utmi_param_configure(clk_base); + + /* PLLU_480M */ + clk = clk_register_gate(NULL, "pll_u_480M", "pll_u", + CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, + 22, 0, &pll_u_lock); + clk_register_clkdev(clk, "pll_u_480M", NULL); + clks[TEGRA124_CLK_PLL_U_480M] = clk; + + /* PLLU_60M */ + clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u", + CLK_SET_RATE_PARENT, 1, 8); + clk_register_clkdev(clk, "pll_u_60M", NULL); + clks[TEGRA124_CLK_PLL_U_60M] = clk; + + /* PLLU_48M */ + clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u", + CLK_SET_RATE_PARENT, 1, 10); + clk_register_clkdev(clk, "pll_u_48M", NULL); + clks[TEGRA124_CLK_PLL_U_48M] = clk; + + /* PLLU_12M */ + clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u", + CLK_SET_RATE_PARENT, 1, 40); + clk_register_clkdev(clk, "pll_u_12M", NULL); + clks[TEGRA124_CLK_PLL_U_12M] = clk; + + /* PLLD */ + clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0, + &pll_d_params, &pll_d_lock); + clk_register_clkdev(clk, "pll_d", NULL); + clks[TEGRA124_CLK_PLL_D] = clk; + + /* PLLD_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_d_out0", NULL); + clks[TEGRA124_CLK_PLL_D_OUT0] = clk; + + /* PLLRE */ + clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, + 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); + clk_register_clkdev(clk, "pll_re_vco", NULL); + clks[TEGRA124_CLK_PLL_RE_VCO] = clk; + + clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0, + clk_base + PLLRE_BASE, 16, 4, 0, + pll_re_div_table, &pll_re_lock); + clk_register_clkdev(clk, "pll_re_out", NULL); + clks[TEGRA124_CLK_PLL_RE_OUT] = clk; + + /* PLLE */ + clk = tegra_clk_register_plle_tegra114("pll_e", "pll_ref", + clk_base, 0, &pll_e_params, NULL); + clk_register_clkdev(clk, "pll_e", NULL); + clks[TEGRA124_CLK_PLL_E] = clk; + + /* PLLC4 */ + clk = tegra_clk_register_pllss("pll_c4", "pll_ref", clk_base, 0, + &pll_c4_params, NULL); + clk_register_clkdev(clk, "pll_c4", NULL); + clks[TEGRA124_CLK_PLL_C4] = clk; + + /* PLLDP */ + clk = tegra_clk_register_pllss("pll_dp", "pll_ref", clk_base, 0, + &pll_dp_params, NULL); + clk_register_clkdev(clk, "pll_dp", NULL); + clks[TEGRA124_CLK_PLL_DP] = clk; + + /* PLLD2 */ + clk = tegra_clk_register_pllss("pll_d2", "pll_ref", clk_base, 0, + &tegra124_pll_d2_params, NULL); + clk_register_clkdev(clk, "pll_d2", NULL); + clks[TEGRA124_CLK_PLL_D2] = clk; + + /* PLLD2_OUT0 ?? */ + clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_d2_out0", NULL); + clks[TEGRA124_CLK_PLL_D2_OUT0] = clk; + +} + +static const struct of_device_id pmc_match[] __initconst = { + { .compatible = "nvidia,tegra124-pmc" }, + {}, +}; + +static struct tegra_clk_init_table init_table[] __initdata = { + {TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0}, + {TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0}, + {TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0}, + {TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0}, + {TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1}, + {TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1}, + {TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1}, + {TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1}, + {TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1}, + {TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, + {TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0}, + {TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1}, + {TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1}, + {TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1}, + {TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1}, + {TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0}, + {TEGRA124_CLK_PLL_C_OUT1, TEGRA124_CLK_CLK_MAX, 100000000, 0}, + {TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1}, + {TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0}, + {TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0}, + /* This MUST be the last entry. */ + {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, +}; + +static void __init tegra124_clock_apply_init_table(void) +{ + tegra_init_from_table(init_table, clks, TEGRA124_CLK_CLK_MAX); +} + +static void __init tegra124_clock_init(struct device_node *np) +{ + struct device_node *node; + + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("ioremap tegra124 CAR failed\n"); + return; + } + + node = of_find_matching_node(NULL, pmc_match); + if (!node) { + pr_err("Failed to find pmc node\n"); + WARN_ON(1); + return; + } + + pmc_base = of_iomap(node, 0); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + WARN_ON(1); + return; + } + + clks = tegra_clk_init(TEGRA124_CLK_CLK_MAX, 6); + if (!clks) + return; + + if (tegra_osc_clk_init(clk_base, tegra124_clks, tegra124_input_freq, + ARRAY_SIZE(tegra124_input_freq), &osc_freq, &pll_ref_freq) < 0) + return; + + tegra_fixed_clk_init(tegra124_clks); + tegra124_pll_init(clk_base, pmc_base); + tegra124_periph_clk_init(clk_base, pmc_base); + tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks, &pll_a_params); + tegra_pmc_clk_init(pmc_base, tegra124_clks); + + tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks, + &pll_x_params); + tegra_add_of_provider(np); + tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); + + tegra_clk_apply_init_table = tegra124_clock_apply_init_table; +} +CLK_OF_DECLARE(tegra124, "nvidia,tegra124-car", tegra124_clock_init); diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h new file mode 100644 index 000000000000..a1116a3b54ef --- /dev/null +++ b/include/dt-bindings/clock/tegra124-car.h @@ -0,0 +1,341 @@ +/* + * This header provides constants for binding nvidia,tegra124-car. + * + * The first 192 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + * registers. These IDs often match those in the CAR's RST_DEVICES registers, + * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + * this case, those clocks are assigned IDs above 185 in order to highlight + * this issue. Implementations that interpret these clock IDs as bit values + * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + * explicitly handle these special cases. + * + * The balance of the clocks controlled by the CAR are assigned IDs of 185 and + * above. + */ + +#ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_H +#define _DT_BINDINGS_CLOCK_TEGRA124_CAR_H + +/* 0 */ +/* 1 */ +/* 2 */ +#define TEGRA124_CLK_ISPB 3 +#define TEGRA124_CLK_RTC 4 +#define TEGRA124_CLK_TIMER 5 +#define TEGRA124_CLK_UARTA 6 +/* 7 (register bit affects uartb and vfir) */ +/* 8 */ +#define TEGRA124_CLK_SDMMC2 9 +/* 10 (register bit affects spdif_in and spdif_out) */ +#define TEGRA124_CLK_I2S1 11 +#define TEGRA124_CLK_I2C1 12 +#define TEGRA124_CLK_NDFLASH 13 +#define TEGRA124_CLK_SDMMC1 14 +#define TEGRA124_CLK_SDMMC4 15 +/* 16 */ +#define TEGRA124_CLK_PWM 17 +#define TEGRA124_CLK_I2S2 18 +/* 20 (register bit affects vi and vi_sensor) */ +#define TEGRA124_CLK_GR_2D 21 +#define TEGRA124_CLK_USBD 22 +#define TEGRA124_CLK_ISP 23 +#define TEGRA124_CLK_GR_3D 24 +/* 25 */ +#define TEGRA124_CLK_DISP2 26 +#define TEGRA124_CLK_DISP1 27 +#define TEGRA124_CLK_HOST1X 28 +#define TEGRA124_CLK_VCP 29 +#define TEGRA124_CLK_I2S0 30 +/* 31 */ + +/* 32 */ +/* 33 */ +#define TEGRA124_CLK_APBDMA 34 +/* 35 */ +#define TEGRA124_CLK_KBC 36 +/* 37 */ +/* 38 */ +/* 39 (register bit affects fuse and fuse_burn) */ +#define TEGRA124_CLK_KFUSE 40 +#define TEGRA124_CLK_SBC1 41 +#define TEGRA124_CLK_NOR 42 +/* 43 */ +#define TEGRA124_CLK_SBC2 44 +/* 45 */ +#define TEGRA124_CLK_SBC3 46 +#define TEGRA124_CLK_I2C5 47 +#define TEGRA124_CLK_DSIA 48 +/* 49 */ +#define TEGRA124_CLK_MIPI 50 +#define TEGRA124_CLK_HDMI 51 +#define TEGRA124_CLK_CSI 52 +/* 53 */ +#define TEGRA124_CLK_I2C2 54 +#define TEGRA124_CLK_UARTC 55 +#define TEGRA124_CLK_MIPI_CAL 56 +#define TEGRA124_CLK_EMC 57 +#define TEGRA124_CLK_USB2 58 +#define TEGRA124_CLK_USB3 59 +/* 60 */ +#define TEGRA124_CLK_VDE 61 +#define TEGRA124_CLK_BSEA 62 +#define TEGRA124_CLK_BSEV 63 + +/* 64 */ +#define TEGRA124_CLK_UARTD 65 +#define TEGRA124_CLK_UARTE 66 +#define TEGRA124_CLK_I2C3 67 +#define TEGRA124_CLK_SBC4 68 +#define TEGRA124_CLK_SDMMC3 69 +#define TEGRA124_CLK_PCIE 70 +#define TEGRA124_CLK_OWR 71 +#define TEGRA124_CLK_AFI 72 +#define TEGRA124_CLK_CSITE 73 +/* 74 */ +/* 75 */ +#define TEGRA124_CLK_LA 76 +#define TEGRA124_CLK_TRACE 77 +#define TEGRA124_CLK_SOC_THERM 78 +#define TEGRA124_CLK_DTV 79 +#define TEGRA124_CLK_NDSPEED 80 +#define TEGRA124_CLK_I2CSLOW 81 +#define TEGRA124_CLK_DSIB 82 +#define TEGRA124_CLK_TSEC 83 +/* 84 */ +/* 85 */ +/* 86 */ +/* 87 */ +/* 88 */ +#define TEGRA124_CLK_XUSB_HOST 89 +/* 90 */ +#define TEGRA124_CLK_MSENC 91 +#define TEGRA124_CLK_CSUS 92 +/* 93 */ +/* 94 */ +/* 95 (bit affects xusb_dev and xusb_dev_src) */ + +/* 96 */ +/* 97 */ +/* 98 */ +#define TEGRA124_CLK_MSELECT 99 +#define TEGRA124_CLK_TSENSOR 100 +#define TEGRA124_CLK_I2S3 101 +#define TEGRA124_CLK_I2S4 102 +#define TEGRA124_CLK_I2C4 103 +#define TEGRA124_CLK_SBC5 104 +#define TEGRA124_CLK_SBC6 105 +#define TEGRA124_CLK_D_AUDIO 106 +#define TEGRA124_CLK_APBIF 107 +#define TEGRA124_CLK_DAM0 108 +#define TEGRA124_CLK_DAM1 109 +#define TEGRA124_CLK_DAM2 110 +#define TEGRA124_CLK_HDA2CODEC_2X 111 +/* 112 */ +#define TEGRA124_CLK_AUDIO0_2X 113 +#define TEGRA124_CLK_AUDIO1_2X 114 +#define TEGRA124_CLK_AUDIO2_2X 115 +#define TEGRA124_CLK_AUDIO3_2X 116 +#define TEGRA124_CLK_AUDIO4_2X 117 +#define TEGRA124_CLK_SPDIF_2X 118 +#define TEGRA124_CLK_ACTMON 119 +#define TEGRA124_CLK_EXTERN1 120 +#define TEGRA124_CLK_EXTERN2 121 +#define TEGRA124_CLK_EXTERN3 122 +#define TEGRA124_CLK_SATA_OOB 123 +#define TEGRA124_CLK_SATA 124 +#define TEGRA124_CLK_HDA 125 +/* 126 */ +#define TEGRA124_CLK_SE 127 + +#define TEGRA124_CLK_HDA2HDMI 128 +#define TEGRA124_CLK_SATA_COLD 129 +/* 130 */ +/* 131 */ +/* 132 */ +/* 133 */ +/* 134 */ +/* 135 */ +/* 136 */ +/* 137 */ +/* 138 */ +/* 139 */ +/* 140 */ +/* 141 */ +/* 142 */ +/* 143 (bit affects xusb_falcon_src, xusb_fs_src, */ +/* xusb_host_src and xusb_ss_src) */ +#define TEGRA124_CLK_CILAB 144 +#define TEGRA124_CLK_CILCD 145 +#define TEGRA124_CLK_CILE 146 +#define TEGRA124_CLK_DSIALP 147 +#define TEGRA124_CLK_DSIBLP 148 +#define TEGRA124_CLK_ENTROPY 149 +#define TEGRA124_CLK_DDS 150 +/* 151 */ +#define TEGRA124_CLK_DP2 152 +#define TEGRA124_CLK_AMX 153 +#define TEGRA124_CLK_ADX 154 +/* 155 (bit affects dfll_ref and dfll_soc) */ +#define TEGRA124_CLK_XUSB_SS 156 +/* 157 */ +/* 158 */ +/* 159 */ + +/* 160 */ +/* 161 */ +/* 162 */ +/* 163 */ +/* 164 */ +/* 165 */ +#define TEGRA124_CLK_I2C6 166 +/* 167 */ +/* 168 */ +/* 169 */ +/* 170 */ +#define TEGRA124_CLK_VIM2_CLK 171 +/* 172 */ +/* 173 */ +/* 174 */ +/* 175 */ +#define TEGRA124_CLK_HDMI_AUDIO 176 +#define TEGRA124_CLK_CLK72MHZ 177 +#define TEGRA124_CLK_VIC03 178 +/* 179 */ +#define TEGRA124_CLK_ADX1 180 +#define TEGRA124_CLK_DPAUX 181 +#define TEGRA124_CLK_SOR0 182 +/* 183 */ +#define TEGRA124_CLK_GPU 184 +#define TEGRA124_CLK_AMX1 185 +/* 186 */ +/* 187 */ +/* 188 */ +/* 189 */ +/* 190 */ +/* 191 */ +#define TEGRA124_CLK_UARTB 192 +#define TEGRA124_CLK_VFIR 193 +#define TEGRA124_CLK_SPDIF_IN 194 +#define TEGRA124_CLK_SPDIF_OUT 195 +#define TEGRA124_CLK_VI 196 +#define TEGRA124_CLK_VI_SENSOR 197 +#define TEGRA124_CLK_FUSE 198 +#define TEGRA124_CLK_FUSE_BURN 199 +#define TEGRA124_CLK_CLK_32K 200 +#define TEGRA124_CLK_CLK_M 201 +#define TEGRA124_CLK_CLK_M_DIV2 202 +#define TEGRA124_CLK_CLK_M_DIV4 203 +#define TEGRA124_CLK_PLL_REF 204 +#define TEGRA124_CLK_PLL_C 205 +#define TEGRA124_CLK_PLL_C_OUT1 206 +#define TEGRA124_CLK_PLL_C2 207 +#define TEGRA124_CLK_PLL_C3 208 +#define TEGRA124_CLK_PLL_M 209 +#define TEGRA124_CLK_PLL_M_OUT1 210 +#define TEGRA124_CLK_PLL_P 211 +#define TEGRA124_CLK_PLL_P_OUT1 212 +#define TEGRA124_CLK_PLL_P_OUT2 213 +#define TEGRA124_CLK_PLL_P_OUT3 214 +#define TEGRA124_CLK_PLL_P_OUT4 215 +#define TEGRA124_CLK_PLL_A 216 +#define TEGRA124_CLK_PLL_A_OUT0 217 +#define TEGRA124_CLK_PLL_D 218 +#define TEGRA124_CLK_PLL_D_OUT0 219 +#define TEGRA124_CLK_PLL_D2 220 +#define TEGRA124_CLK_PLL_D2_OUT0 221 +#define TEGRA124_CLK_PLL_U 222 +#define TEGRA124_CLK_PLL_U_480M 223 + +#define TEGRA124_CLK_PLL_U_60M 224 +#define TEGRA124_CLK_PLL_U_48M 225 +#define TEGRA124_CLK_PLL_U_12M 226 +#define TEGRA124_CLK_PLL_X 227 +#define TEGRA124_CLK_PLL_X_OUT0 228 +#define TEGRA124_CLK_PLL_RE_VCO 229 +#define TEGRA124_CLK_PLL_RE_OUT 230 +#define TEGRA124_CLK_PLL_E 231 +#define TEGRA124_CLK_SPDIF_IN_SYNC 232 +#define TEGRA124_CLK_I2S0_SYNC 233 +#define TEGRA124_CLK_I2S1_SYNC 234 +#define TEGRA124_CLK_I2S2_SYNC 235 +#define TEGRA124_CLK_I2S3_SYNC 236 +#define TEGRA124_CLK_I2S4_SYNC 237 +#define TEGRA124_CLK_VIMCLK_SYNC 238 +#define TEGRA124_CLK_AUDIO0 239 +#define TEGRA124_CLK_AUDIO1 240 +#define TEGRA124_CLK_AUDIO2 241 +#define TEGRA124_CLK_AUDIO3 242 +#define TEGRA124_CLK_AUDIO4 243 +#define TEGRA124_CLK_SPDIF 244 +#define TEGRA124_CLK_CLK_OUT_1 245 +#define TEGRA124_CLK_CLK_OUT_2 246 +#define TEGRA124_CLK_CLK_OUT_3 247 +#define TEGRA124_CLK_BLINK 248 +/* 249 */ +/* 250 */ +/* 251 */ +#define TEGRA124_CLK_XUSB_HOST_SRC 252 +#define TEGRA124_CLK_XUSB_FALCON_SRC 253 +#define TEGRA124_CLK_XUSB_FS_SRC 254 +#define TEGRA124_CLK_XUSB_SS_SRC 255 + +#define TEGRA124_CLK_XUSB_DEV_SRC 256 +#define TEGRA124_CLK_XUSB_DEV 257 +#define TEGRA124_CLK_XUSB_HS_SRC 258 +#define TEGRA124_CLK_SCLK 259 +#define TEGRA124_CLK_HCLK 260 +#define TEGRA124_CLK_PCLK 261 +#define TEGRA124_CLK_CCLK_G 262 +#define TEGRA124_CLK_CCLK_LP 263 +#define TEGRA124_CLK_DFLL_REF 264 +#define TEGRA124_CLK_DFLL_SOC 265 +#define TEGRA124_CLK_VI_SENSOR2 266 +#define TEGRA124_CLK_PLL_P_OUT5 267 +#define TEGRA124_CLK_CML0 268 +#define TEGRA124_CLK_CML1 269 +#define TEGRA124_CLK_PLL_C4 270 +#define TEGRA124_CLK_PLL_DP 271 +#define TEGRA124_CLK_PLL_E_MUX 272 +/* 273 */ +/* 274 */ +/* 275 */ +/* 276 */ +/* 277 */ +/* 278 */ +/* 279 */ +/* 280 */ +/* 281 */ +/* 282 */ +/* 283 */ +/* 284 */ +/* 285 */ +/* 286 */ +/* 287 */ + +/* 288 */ +/* 289 */ +/* 290 */ +/* 291 */ +/* 292 */ +/* 293 */ +/* 294 */ +/* 295 */ +/* 296 */ +/* 297 */ +/* 298 */ +/* 299 */ +#define TEGRA124_CLK_AUDIO0_MUX 300 +#define TEGRA124_CLK_AUDIO1_MUX 301 +#define TEGRA124_CLK_AUDIO2_MUX 302 +#define TEGRA124_CLK_AUDIO3_MUX 303 +#define TEGRA124_CLK_AUDIO4_MUX 304 +#define TEGRA124_CLK_SPDIF_MUX 305 +#define TEGRA124_CLK_CLK_OUT_1_MUX 306 +#define TEGRA124_CLK_CLK_OUT_2_MUX 307 +#define TEGRA124_CLK_CLK_OUT_3_MUX 308 +#define TEGRA124_CLK_DSIA_MUX 309 +#define TEGRA124_CLK_DSIB_MUX 310 +#define TEGRA124_CLK_SOR0_LVDS 311 +#define TEGRA124_CLK_CLK_MAX 312 + +#endif /* _DT_BINDINGS_CLOCK_TEGRA124_CAR_H */ -- cgit v1.2.3 From 9e036d3ef0b9fcb34acce5a89d1f2157f4f7b4ab Mon Sep 17 00:00:00 2001 From: Joseph Lo Date: Wed, 25 Sep 2013 17:27:51 +0800 Subject: clk: tegra124: add wait_for_reset and disable_clock for tegra_cpu_car_ops Hook the functions for CPU hotplug support. After the CPU is hot unplugged, the flow controller will handle to clock gate the CPU clock. But still need to implement an empty function to avoid warning message. Cc: Mike Turquette Signed-off-by: Joseph Lo --- drivers/clk/tegra/clk-tegra124.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index f69367a14777..345192233871 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -112,6 +112,9 @@ #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) +/* Tegra CPU clock and reset control regs */ +#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 + static void __iomem *clk_base; static void __iomem *pmc_base; @@ -1283,6 +1286,27 @@ static void __init tegra124_pll_init(void __iomem *clk_base, } +/* Tegra124 CPU clock and reset control functions */ +static void tegra124_wait_cpu_in_reset(u32 cpu) +{ + unsigned int reg; + + do { + reg = readl(clk_base + CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); + cpu_relax(); + } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ +} + +static void tegra124_disable_cpu_clock(u32 cpu) +{ + /* flow controller would take care in the power sequence. */ +} + +static struct tegra_cpu_car_ops tegra124_cpu_car_ops = { + .wait_for_reset = tegra124_wait_cpu_in_reset, + .disable_clock = tegra124_disable_cpu_clock, +}; + static const struct of_device_id pmc_match[] __initconst = { { .compatible = "nvidia,tegra124-pmc" }, {}, @@ -1366,5 +1390,7 @@ static void __init tegra124_clock_init(struct device_node *np) tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); tegra_clk_apply_init_table = tegra124_clock_apply_init_table; + + tegra_cpu_car_ops = &tegra124_cpu_car_ops; } CLK_OF_DECLARE(tegra124, "nvidia,tegra124-car", tegra124_clock_init); -- cgit v1.2.3 From 61792e40ca008d60331bb55df5faaa8fe220ac24 Mon Sep 17 00:00:00 2001 From: Joseph Lo Date: Thu, 26 Sep 2013 17:46:23 +0800 Subject: clk: tegra124: add suspend/resume function for tegra_cpu_car_ops Adding suspend/resume function for tegra_cpu_car_ops. We only save and restore the setting of the clock of CoreSight. Other clocks still need to be taken care by clock driver. Cc: Mike Turquette Signed-off-by: Joseph Lo Acked-by: Stephen Warren --- drivers/clk/tegra/clk-tegra124.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 345192233871..8af9d3929016 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -28,6 +28,7 @@ #include "clk.h" #include "clk-id.h" +#define CLK_SOURCE_CSITE 0x1d4 #define CLK_SOURCE_EMC 0x19c #define CLK_SOURCE_XUSB_SS_SRC 0x610 @@ -115,6 +116,12 @@ /* Tegra CPU clock and reset control regs */ #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 +#ifdef CONFIG_PM_SLEEP +static struct cpu_clk_suspend_context { + u32 clk_csite_src; +} tegra124_cpu_clk_sctx; +#endif + static void __iomem *clk_base; static void __iomem *pmc_base; @@ -1302,9 +1309,29 @@ static void tegra124_disable_cpu_clock(u32 cpu) /* flow controller would take care in the power sequence. */ } +#ifdef CONFIG_PM_SLEEP +static void tegra124_cpu_clock_suspend(void) +{ + /* switch coresite to clk_m, save off original source */ + tegra124_cpu_clk_sctx.clk_csite_src = + readl(clk_base + CLK_SOURCE_CSITE); + writel(3 << 30, clk_base + CLK_SOURCE_CSITE); +} + +static void tegra124_cpu_clock_resume(void) +{ + writel(tegra124_cpu_clk_sctx.clk_csite_src, + clk_base + CLK_SOURCE_CSITE); +} +#endif + static struct tegra_cpu_car_ops tegra124_cpu_car_ops = { .wait_for_reset = tegra124_wait_cpu_in_reset, .disable_clock = tegra124_disable_cpu_clock, +#ifdef CONFIG_PM_SLEEP + .suspend = tegra124_cpu_clock_suspend, + .resume = tegra124_cpu_clock_resume, +#endif }; static const struct of_device_id pmc_match[] __initconst = { -- cgit v1.2.3 From 77f71730341e9072766eabc5bbd001aa286e7a23 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Tue, 29 Oct 2013 16:51:10 +0100 Subject: clk: tegra114: Initialize clocks needed for HDMI Add disp1 and disp2 clocks to the clock initialization table. These clocks are required for display and HDMI support. Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra114.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 0b8c9af5bff3..875859d9ab5f 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1294,6 +1294,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0}, {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1}, {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1}, + {TEGRA114_CLK_DISP1, TEGRA114_CLK_PLL_P, 0, 0}, + {TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0}, {TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, -- cgit v1.2.3 From 43e36a9646ec7d0180d638c095cca36484cc6f82 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Oct 2013 16:51:11 +0100 Subject: clk: tegra: Initialize secondary gr3d clock on Tegra30 There are two GPUs on Tegra30 and each of them uses a separate clock, so the secondary clock needs to be initialized in order for the gr3d module to work properly. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index f7ebf2bacdd9..153ae1acd2fa 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1368,6 +1368,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1}, {TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0}, {TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0}, + {TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0}, {TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry. */ }; -- cgit v1.2.3 From c04bf559264de4f986463c639fabef2028542924 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Oct 2013 16:51:12 +0100 Subject: clk: tegra: Properly setup PWM clock on Tegra30 The clock for the PWM controller is slightly different from other peripheral clocks on Tegra30. The clock source mux field start at bit position 28 rather than 30. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 153ae1acd2fa..3afa09761bb3 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -102,6 +102,7 @@ #define AUDIO_SYNC_CLK_SPDIF 0x4b4 #define CLK_SOURCE_SPDIF_OUT 0x108 +#define CLK_SOURCE_PWM 0x110 #define CLK_SOURCE_D_AUDIO 0x3d0 #define CLK_SOURCE_DAM0 0x3d8 #define CLK_SOURCE_DAM1 0x3dc @@ -827,7 +828,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { [tegra_clk_extern1] = { .dt_id = TEGRA30_CLK_EXTERN1, .present = true }, [tegra_clk_extern2] = { .dt_id = TEGRA30_CLK_EXTERN2, .present = true }, [tegra_clk_extern3] = { .dt_id = TEGRA30_CLK_EXTERN3, .present = true }, - [tegra_clk_pwm] = { .dt_id = TEGRA30_CLK_PWM, .present = true }, [tegra_clk_disp1] = { .dt_id = TEGRA30_CLK_DISP1, .present = true }, [tegra_clk_disp2] = { .dt_id = TEGRA30_CLK_DISP2, .present = true }, [tegra_clk_apbdma] = { .dt_id = TEGRA30_CLK_APBDMA, .present = true }, @@ -1111,6 +1111,7 @@ static const char *mux_pllpmdacd2_clkm[] = { "pll_p", "pll_m", "pll_d_out0", "pll_d2_out0", "clk_m" }; static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0", "pll_d2_out0" }; +static const char *pwm_parents[] = { "pll_p", "pll_c", "clk_32k", "clk_m" }; static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX("spdif_out", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_SPDIF_OUT), @@ -1121,6 +1122,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, TEGRA30_CLK_GR3D2), TEGRA_INIT_DATA_INT("se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, TEGRA30_CLK_SE), TEGRA_INIT_DATA_MUX8("hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA30_CLK_HDMI), + TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_PWM), }; static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { -- cgit v1.2.3 From 5ab5d4048e6ed8811245a4ea45264456c180545e Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Thu, 21 Nov 2013 03:38:10 +0100 Subject: clk: tegra: add FUSE clock device This clock is needed to ensure the FUSE registers can be accessed without freezing the system. Signed-off-by: Alexandre Courbot --- drivers/clk/tegra/clk-tegra114.c | 1 + drivers/clk/tegra/clk-tegra124.c | 1 + drivers/clk/tegra/clk-tegra20.c | 1 + drivers/clk/tegra/clk-tegra30.c | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 875859d9ab5f..2a1b0b82462a 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -918,6 +918,7 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "sclk", .dt_id = TEGRA114_CLK_SCLK }, { .con_id = "hclk", .dt_id = TEGRA114_CLK_HCLK }, { .con_id = "pclk", .dt_id = TEGRA114_CLK_PCLK }, + { .con_id = "fuse", .dt_id = TEGRA114_CLK_FUSE }, { .dev_id = "rtc-tegra", .dt_id = TEGRA114_CLK_RTC }, { .dev_id = "timer", .dt_id = TEGRA114_CLK_TIMER }, }; diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 8af9d3929016..0ef4485e9b0a 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1009,6 +1009,7 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "sclk", .dt_id = TEGRA124_CLK_SCLK }, { .con_id = "hclk", .dt_id = TEGRA124_CLK_HCLK }, { .con_id = "pclk", .dt_id = TEGRA124_CLK_PCLK }, + { .con_id = "fuse", .dt_id = TEGRA124_CLK_FUSE }, { .dev_id = "rtc-tegra", .dt_id = TEGRA124_CLK_RTC }, { .dev_id = "timer", .dt_id = TEGRA124_CLK_TIMER }, }; diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index be5bdbab78a6..b3b7204acfe7 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -446,6 +446,7 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "sclk", .dt_id = TEGRA20_CLK_SCLK }, { .con_id = "hclk", .dt_id = TEGRA20_CLK_HCLK }, { .con_id = "pclk", .dt_id = TEGRA20_CLK_PCLK }, + { .con_id = "fuse", .dt_id = TEGRA20_CLK_FUSE }, { .con_id = "twd", .dt_id = TEGRA20_CLK_TWD }, { .con_id = "audio", .dt_id = TEGRA20_CLK_AUDIO }, { .con_id = "audio_2x", .dt_id = TEGRA20_CLK_AUDIO_2X }, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 3afa09761bb3..dcb6843b3a89 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -650,7 +650,7 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "pcie", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIE }, { .con_id = "afi", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_AFI }, { .con_id = "pciex", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIEX }, - { .con_id = "fuse", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE }, + { .con_id = "fuse", .dt_id = TEGRA30_CLK_FUSE }, { .con_id = "fuse_burn", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE_BURN }, { .con_id = "apbif", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_APBIF }, { .con_id = "hda2hdmi", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2HDMI }, -- cgit v1.2.3 From 39409aa4244f22eae3fa8f8db4b0cf9466b73c44 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 18 Nov 2013 16:11:36 +0100 Subject: clk: tegra: Initialize DSI low-power clocks The low-power DSI clocks are used during host-driven transactions on the DSI bus. Documentation recommends that they be children of PLLP and run at a frequency of at least 52 MHz. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra114.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 2a1b0b82462a..29b912582e3d 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1299,6 +1299,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0}, {TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, + {TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0}, + {TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0}, /* This MUST be the last entry. */ {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0}, -- cgit v1.2.3 From 869c597829817af4b9f85c5e4181c622918dc781 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 26 Nov 2013 13:31:14 +0100 Subject: usb: musb: dsps: add support for suspend and resume The dsps platform needs to save save some registers at suspend time and restore them after resume. This patch adds a struct for these registers, and also lets the musb core know that the core registers need to be saved as well. We also have to explicitly de-assert the port reset upon resume on this platform, but musb_port_reset() should not be called from glue layers. Hence, introduce a flag in struct musb_hdrc_config for this. Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 57 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/musb/musb_host.c | 7 ++++- drivers/usb/musb/musb_host.h | 2 ++ drivers/usb/musb/musb_virthub.c | 2 +- include/linux/usb/musb.h | 3 +++ 5 files changed, 69 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 3f3724471667..7cfa6e80ad60 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -113,6 +113,19 @@ struct dsps_musb_wrapper { u8 poll_seconds; }; +/* + * register shadow for suspend + */ +struct dsps_context { + u32 control; + u32 epintr; + u32 coreintr; + u32 phy_utmi; + u32 mode; + u32 tx_mode; + u32 rx_mode; +}; + /** * DSPS glue structure. */ @@ -122,6 +135,8 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer; /* otg_workaround timer */ unsigned long last_timer; /* last timer data for each instance */ + + struct dsps_context context; }; static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) @@ -559,6 +574,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, config->num_eps = get_int_prop(dn, "mentor,num-eps"); config->ram_bits = get_int_prop(dn, "mentor,ram-bits"); + config->host_port_deassert_reset_at_resume = 1; pdata.mode = get_musb_port_mode(dev); /* DT keeps this entry in mA, musb expects it as per USB spec */ pdata.power = get_int_prop(dn, "mentor,power") / 2; @@ -683,11 +699,52 @@ static const struct of_device_id musb_dsps_of_match[] = { }; MODULE_DEVICE_TABLE(of, musb_dsps_of_match); +#ifdef CONFIG_PM +static int dsps_suspend(struct device *dev) +{ + struct dsps_glue *glue = dev_get_drvdata(dev); + const struct dsps_musb_wrapper *wrp = glue->wrp; + struct musb *musb = platform_get_drvdata(glue->musb); + void __iomem *mbase = musb->ctrl_base; + + glue->context.control = dsps_readl(mbase, wrp->control); + glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); + glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); + glue->context.phy_utmi = dsps_readl(mbase, wrp->phy_utmi); + glue->context.mode = dsps_readl(mbase, wrp->mode); + glue->context.tx_mode = dsps_readl(mbase, wrp->tx_mode); + glue->context.rx_mode = dsps_readl(mbase, wrp->rx_mode); + + return 0; +} + +static int dsps_resume(struct device *dev) +{ + struct dsps_glue *glue = dev_get_drvdata(dev); + const struct dsps_musb_wrapper *wrp = glue->wrp; + struct musb *musb = platform_get_drvdata(glue->musb); + void __iomem *mbase = musb->ctrl_base; + + dsps_writel(mbase, wrp->control, glue->context.control); + dsps_writel(mbase, wrp->epintr_set, glue->context.epintr); + dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr); + dsps_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi); + dsps_writel(mbase, wrp->mode, glue->context.mode); + dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode); + dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); + static struct platform_driver dsps_usbss_driver = { .probe = dsps_probe, .remove = dsps_remove, .driver = { .name = "musb-dsps", + .pm = &dsps_pm_ops, .of_match_table = musb_dsps_of_match, }, }; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 81caf9f4eb1a..822413899260 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2464,7 +2464,12 @@ static int musb_bus_suspend(struct usb_hcd *hcd) static int musb_bus_resume(struct usb_hcd *hcd) { - /* resuming child port does the work */ + struct musb *musb = hcd_to_musb(hcd); + + if (musb->config && + musb->config->host_port_deassert_reset_at_resume) + musb_port_reset(musb, false); + return 0; } diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index e660af90272d..7436c24af0ff 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -93,6 +93,7 @@ extern void musb_root_disconnect(struct musb *musb); extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_poke_root_hub(struct musb *musb); extern void musb_port_suspend(struct musb *musb, bool do_suspend); +extern void musb_port_reset(struct musb *musb, bool do_reset); #else static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) { @@ -123,6 +124,7 @@ static inline void musb_host_resume_root_hub(struct musb *musb) {} static inline void musb_host_poll_rh_status(struct musb *musb) {} static inline void musb_host_poke_root_hub(struct musb *musb) {} static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {} +static inline void musb_port_reset(struct musb *musb) {} #endif struct usb_hcd; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index e977441401ed..24e46c0c84b5 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -109,7 +109,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) } } -static void musb_port_reset(struct musb *musb, bool do_reset) +void musb_port_reset(struct musb *musb, bool do_reset) { u8 power; void __iomem *mbase = musb->mregs; diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index eb505250940a..a4ee1b582183 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h @@ -76,6 +76,9 @@ struct musb_hdrc_config { unsigned dma:1 __deprecated; /* supports DMA */ unsigned vendor_req:1 __deprecated; /* vendor registers required */ + /* need to explicitly de-assert the port reset after resume? */ + unsigned host_port_deassert_reset_at_resume:1; + u8 num_eps; /* number of endpoints _with_ ep0 */ u8 dma_channels __deprecated; /* number of dma channels */ u8 dyn_fifo_size; /* dynamic size in bytes */ -- cgit v1.2.3 From c3505f04582f3fee1452613c7d36a1811e524ab4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Nov 2013 12:39:29 -0600 Subject: usb: gadget: epautoconf: switch over to usb_endpoint_type() we have a helper to fetch endpoint type out of a descriptor, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index a777f7bd11b4..feaaa7b72ee3 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -58,7 +58,7 @@ ep_matches ( return 0; /* only support ep0 for portable CONTROL traffic */ - type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + type = usb_endpoint_type(desc); if (USB_ENDPOINT_XFER_CONTROL == type) return 0; -- cgit v1.2.3 From 4fbc5566c8b9b8e1c927583b89f3ff9e27ebad09 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 10 Nov 2013 20:35:55 +0100 Subject: usb: gadget: goku: remove unused argument The stop_activity function never uses driver argument (even though it modifies it) and thus it is safe to remove it. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index f82768015715..7eda9fd6528e 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1350,16 +1350,12 @@ static int goku_udc_start(struct usb_gadget *g, return 0; } -static void -stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver) +static void stop_activity(struct goku_udc *dev) { unsigned i; DBG (dev, "%s\n", __func__); - if (dev->gadget.speed == USB_SPEED_UNKNOWN) - driver = NULL; - /* disconnect gadget driver after quiesceing hw and the driver */ udc_reset (dev); for (i = 0; i < 4; i++) @@ -1377,7 +1373,7 @@ static int goku_udc_stop(struct usb_gadget *g, spin_lock_irqsave(&dev->lock, flags); dev->driver = NULL; - stop_activity(dev, driver); + stop_activity(dev); spin_unlock_irqrestore(&dev->lock, flags); return 0; @@ -1521,7 +1517,7 @@ rescan: if (unlikely(stat & INT_DEVWIDE)) { if (stat & INT_SYSERROR) { ERROR(dev, "system error\n"); - stop_activity(dev, dev->driver); + stop_activity(dev); stat = 0; handled = 1; // FIXME have a neater way to prevent re-enumeration @@ -1536,7 +1532,7 @@ rescan: } else { DBG(dev, "disconnect\n"); if (dev->gadget.speed == USB_SPEED_FULL) - stop_activity(dev, dev->driver); + stop_activity(dev); dev->ep0state = EP0_DISCONNECT; dev->int_enable = INT_DEVWIDE; writel(dev->int_enable, &dev->regs->int_enable); -- cgit v1.2.3 From 7de7174aa36f548a53c26d6841f3f7aeb449513b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:24 +0100 Subject: usb: gadget: remove superfluous name casts device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Cc: linux-usb@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_qe_udc.c | 2 +- drivers/usb/gadget/fsl_udc_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 807127d56fa3..6315ee698d4d 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2717,7 +2717,7 @@ MODULE_DEVICE_TABLE(of, qe_udc_match); static struct platform_driver udc_driver = { .driver = { - .name = (char *)driver_name, + .name = driver_name, .owner = THIS_MODULE, .of_match_table = qe_udc_match, }, diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 36ac7cfba91d..b7dea4eec32c 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2666,7 +2666,7 @@ static struct platform_driver udc_driver = { .suspend = fsl_udc_suspend, .resume = fsl_udc_resume, .driver = { - .name = (char *)driver_name, + .name = driver_name, .owner = THIS_MODULE, /* udc suspend/resume called from OTG driver */ .suspend = fsl_udc_otg_suspend, -- cgit v1.2.3 From 574f24f797718937b48befb97d13850d5bebb72c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Nov 2013 11:42:11 +0300 Subject: usb: gadget: update some out of date comments These functions used to return negative errror codes but now they return ERR_PTRs. Signed-off-by: Dan Carpenter Acked-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/u_ether.c | 2 +- drivers/usb/gadget/u_ether.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 2aae0d61bb19..b7d4f82872b7 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -753,7 +753,7 @@ static struct device_type gadget_type = { * gadget driver using this framework. The link layer addresses are * set up using module parameters. * - * Returns negative errno, or zero on success + * Returns an eth_dev pointer on success, or an ERR_PTR on failure. */ struct eth_dev *gether_setup_name(struct usb_gadget *g, const char *dev_addr, const char *host_addr, diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index fb23d1fde8eb..a32b41e27450 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -106,7 +106,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, * gadget driver using this framework. The link layer addresses are * set up using module parameters. * - * Returns negative errno, or zero on success + * Returns a eth_dev pointer on success, or an ERR_PTR on failure */ static inline struct eth_dev *gether_setup(struct usb_gadget *g, const char *dev_addr, const char *host_addr, -- cgit v1.2.3 From cc9d9ccf2a1e8c9f36a436805317180003ba9719 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Nov 2013 10:06:00 -0600 Subject: usb: phy: fsm: don't depend on indirect includes this header uses spinlocks and errno values, so we must include and to avoid build errors. Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-fsm-usb.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h index 7441b46a27f1..32f86a36ba50 100644 --- a/drivers/usb/phy/phy-fsm-usb.h +++ b/drivers/usb/phy/phy-fsm-usb.h @@ -15,6 +15,9 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include + #undef VERBOSE #ifdef VERBOSE -- cgit v1.2.3 From d49dd788840ff802421ed7412e967b659fe9ca58 Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 26 Nov 2013 10:08:58 -0600 Subject: usb: phy: fsm: protect against multiple inclusions if this header is included twice, we would have redefinition build errors. Fix this. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-fsm-usb.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h index 32f86a36ba50..200f4d156020 100644 --- a/drivers/usb/phy/phy-fsm-usb.h +++ b/drivers/usb/phy/phy-fsm-usb.h @@ -15,6 +15,9 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef __LINUX_USB_OTG_FSM_H +#define __LINUX_USB_OTG_FSM_H + #include #include @@ -237,3 +240,5 @@ static inline int otg_start_gadget(struct otg_fsm *fsm, int on) } int otg_statemachine(struct otg_fsm *fsm); + +#endif /* __LINUX_USB_OTG_FSM_H */ -- cgit v1.2.3 From 16e569e9661ea2b964b8abb607a51e5285254021 Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 26 Nov 2013 11:46:05 +0900 Subject: usb: phy: replace spinlock with mutex in OTG FSM OTG Final State Machine calls functions which may sleep. For example, start_gadget callback implementation can use usb_gadget_vbus_connect(), whose context: can sleep. If so, mutex should be used instead of spinlock. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-fsl-usb.c | 7 +++---- drivers/usb/phy/phy-fsm-usb.c | 7 +++---- drivers/usb/phy/phy-fsm-usb.h | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index 7f3c73b967ce..62d5af22efaf 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -848,7 +848,7 @@ static int fsl_otg_conf(struct platform_device *pdev) pr_info("Couldn't init OTG timers\n"); goto err; } - spin_lock_init(&fsl_otg_tc->fsm.lock); + mutex_init(&fsl_otg_tc->fsm.lock); /* Set OTG state machine operations */ fsl_otg_tc->fsm.ops = &fsl_otg_ops; @@ -1017,10 +1017,9 @@ static int show_fsl_usb2_otg_state(struct device *dev, struct otg_fsm *fsm = &fsl_otg_dev->fsm; char *next = buf; unsigned size = PAGE_SIZE; - unsigned long flags; int t; - spin_lock_irqsave(&fsm->lock, flags); + mutex_lock(&fsm->lock); /* basic driver infomation */ t = scnprintf(next, size, @@ -1088,7 +1087,7 @@ static int show_fsl_usb2_otg_state(struct device *dev, size -= t; next += t; - spin_unlock_irqrestore(&fsm->lock, flags); + mutex_unlock(&fsm->lock); return PAGE_SIZE - size; } diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c index 329c2d2f8595..2817b04a6c47 100644 --- a/drivers/usb/phy/phy-fsm-usb.c +++ b/drivers/usb/phy/phy-fsm-usb.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include @@ -245,9 +245,8 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) int otg_statemachine(struct otg_fsm *fsm) { enum usb_otg_state state; - unsigned long flags; - spin_lock_irqsave(&fsm->lock, flags); + mutex_lock(&fsm->lock); state = fsm->otg->phy->state; state_changed = 0; @@ -359,7 +358,7 @@ int otg_statemachine(struct otg_fsm *fsm) default: break; } - spin_unlock_irqrestore(&fsm->lock, flags); + mutex_lock(&fsm->lock); VDBG("quit statemachine, changed = %d\n", state_changed); return state_changed; diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h index 200f4d156020..b6ba1bfb86f2 100644 --- a/drivers/usb/phy/phy-fsm-usb.h +++ b/drivers/usb/phy/phy-fsm-usb.h @@ -18,7 +18,7 @@ #ifndef __LINUX_USB_OTG_FSM_H #define __LINUX_USB_OTG_FSM_H -#include +#include #include #undef VERBOSE @@ -116,7 +116,7 @@ struct otg_fsm { /* Current usb protocol used: 0:undefine; 1:host; 2:client */ int protocol; - spinlock_t lock; + struct mutex lock; }; struct otg_fsm_ops { -- cgit v1.2.3 From 5653668c9585441926dd2575791f6b5bb84bb254 Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 26 Nov 2013 11:47:02 +0900 Subject: usb: phy: move OTG FSM header Other USB drivers may want to use OTG final state machine implementation, so make this header available for them. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-fsl-usb.h | 2 +- drivers/usb/phy/phy-fsm-usb.c | 3 +- drivers/usb/phy/phy-fsm-usb.h | 244 ------------------------------------------ include/linux/usb/otg-fsm.h | 244 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+), 247 deletions(-) delete mode 100644 drivers/usb/phy/phy-fsm-usb.h create mode 100644 include/linux/usb/otg-fsm.h (limited to 'drivers') diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h index 7365170a2f23..5986c96354df 100644 --- a/drivers/usb/phy/phy-fsl-usb.h +++ b/drivers/usb/phy/phy-fsl-usb.h @@ -15,7 +15,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "phy-fsm-usb.h" +#include #include #include diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c index 2817b04a6c47..62238726fb1c 100644 --- a/drivers/usb/phy/phy-fsm-usb.c +++ b/drivers/usb/phy/phy-fsm-usb.c @@ -28,8 +28,7 @@ #include #include #include - -#include "phy-fsm-usb.h" +#include /* Change USB protocol when there is a protocol change */ static int otg_set_protocol(struct otg_fsm *fsm, int protocol) diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h deleted file mode 100644 index b6ba1bfb86f2..000000000000 --- a/drivers/usb/phy/phy-fsm-usb.h +++ /dev/null @@ -1,244 +0,0 @@ -/* Copyright (C) 2007,2008 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. - * - * This program is distributed in the hope that it will be useful, 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __LINUX_USB_OTG_FSM_H -#define __LINUX_USB_OTG_FSM_H - -#include -#include - -#undef VERBOSE - -#ifdef VERBOSE -#define VDBG(fmt, args...) pr_debug("[%s] " fmt , \ - __func__, ## args) -#else -#define VDBG(stuff...) do {} while (0) -#endif - -#ifdef VERBOSE -#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) -#else -#define MPC_LOC do {} while (0) -#endif - -#define PROTO_UNDEF (0) -#define PROTO_HOST (1) -#define PROTO_GADGET (2) - -enum otg_fsm_timer { - /* Standard OTG timers */ - A_WAIT_VRISE, - A_WAIT_VFALL, - A_WAIT_BCON, - A_AIDL_BDIS, - B_ASE0_BRST, - A_BIDL_ADIS, - - /* Auxiliary timers */ - B_SE0_SRP, - B_SRP_FAIL, - A_WAIT_ENUM, - - NUM_OTG_FSM_TIMERS, -}; - -/* OTG state machine according to the OTG spec */ -struct otg_fsm { - /* Input */ - int id; - int adp_change; - int power_up; - int test_device; - int a_bus_drop; - int a_bus_req; - int a_srp_det; - int a_vbus_vld; - int b_conn; - int a_bus_resume; - int a_bus_suspend; - int a_conn; - int b_bus_req; - int b_se0_srp; - int b_ssend_srp; - int b_sess_vld; - /* Auxilary inputs */ - int a_sess_vld; - int b_bus_resume; - int b_bus_suspend; - - /* Output */ - int data_pulse; - int drv_vbus; - int loc_conn; - int loc_sof; - int adp_prb; - int adp_sns; - - /* Internal variables */ - int a_set_b_hnp_en; - int b_srp_done; - int b_hnp_enable; - int a_clr_err; - - /* Informative variables */ - int a_bus_drop_inf; - int a_bus_req_inf; - int a_clr_err_inf; - int b_bus_req_inf; - /* Auxilary informative variables */ - int a_suspend_req_inf; - - /* Timeout indicator for timers */ - int a_wait_vrise_tmout; - int a_wait_vfall_tmout; - int a_wait_bcon_tmout; - int a_aidl_bdis_tmout; - int b_ase0_brst_tmout; - int a_bidl_adis_tmout; - - struct otg_fsm_ops *ops; - struct usb_otg *otg; - - /* Current usb protocol used: 0:undefine; 1:host; 2:client */ - int protocol; - struct mutex lock; -}; - -struct otg_fsm_ops { - void (*chrg_vbus)(struct otg_fsm *fsm, int on); - void (*drv_vbus)(struct otg_fsm *fsm, int on); - void (*loc_conn)(struct otg_fsm *fsm, int on); - void (*loc_sof)(struct otg_fsm *fsm, int on); - void (*start_pulse)(struct otg_fsm *fsm); - void (*start_adp_prb)(struct otg_fsm *fsm); - void (*start_adp_sns)(struct otg_fsm *fsm); - void (*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); - void (*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); - int (*start_host)(struct otg_fsm *fsm, int on); - int (*start_gadget)(struct otg_fsm *fsm, int on); -}; - - -static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on) -{ - if (!fsm->ops->chrg_vbus) - return -EOPNOTSUPP; - fsm->ops->chrg_vbus(fsm, on); - return 0; -} - -static inline int otg_drv_vbus(struct otg_fsm *fsm, int on) -{ - if (!fsm->ops->drv_vbus) - return -EOPNOTSUPP; - if (fsm->drv_vbus != on) { - fsm->drv_vbus = on; - fsm->ops->drv_vbus(fsm, on); - } - return 0; -} - -static inline int otg_loc_conn(struct otg_fsm *fsm, int on) -{ - if (!fsm->ops->loc_conn) - return -EOPNOTSUPP; - if (fsm->loc_conn != on) { - fsm->loc_conn = on; - fsm->ops->loc_conn(fsm, on); - } - return 0; -} - -static inline int otg_loc_sof(struct otg_fsm *fsm, int on) -{ - if (!fsm->ops->loc_sof) - return -EOPNOTSUPP; - if (fsm->loc_sof != on) { - fsm->loc_sof = on; - fsm->ops->loc_sof(fsm, on); - } - return 0; -} - -static inline int otg_start_pulse(struct otg_fsm *fsm) -{ - if (!fsm->ops->start_pulse) - return -EOPNOTSUPP; - if (!fsm->data_pulse) { - fsm->data_pulse = 1; - fsm->ops->start_pulse(fsm); - } - return 0; -} - -static inline int otg_start_adp_prb(struct otg_fsm *fsm) -{ - if (!fsm->ops->start_adp_prb) - return -EOPNOTSUPP; - if (!fsm->adp_prb) { - fsm->adp_sns = 0; - fsm->adp_prb = 1; - fsm->ops->start_adp_prb(fsm); - } - return 0; -} - -static inline int otg_start_adp_sns(struct otg_fsm *fsm) -{ - if (!fsm->ops->start_adp_sns) - return -EOPNOTSUPP; - if (!fsm->adp_sns) { - fsm->adp_sns = 1; - fsm->ops->start_adp_sns(fsm); - } - return 0; -} - -static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) -{ - if (!fsm->ops->add_timer) - return -EOPNOTSUPP; - fsm->ops->add_timer(fsm, timer); - return 0; -} - -static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) -{ - if (!fsm->ops->del_timer) - return -EOPNOTSUPP; - fsm->ops->del_timer(fsm, timer); - return 0; -} - -static inline int otg_start_host(struct otg_fsm *fsm, int on) -{ - if (!fsm->ops->start_host) - return -EOPNOTSUPP; - return fsm->ops->start_host(fsm, on); -} - -static inline int otg_start_gadget(struct otg_fsm *fsm, int on) -{ - if (!fsm->ops->start_gadget) - return -EOPNOTSUPP; - return fsm->ops->start_gadget(fsm, on); -} - -int otg_statemachine(struct otg_fsm *fsm); - -#endif /* __LINUX_USB_OTG_FSM_H */ diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h new file mode 100644 index 000000000000..b6ba1bfb86f2 --- /dev/null +++ b/include/linux/usb/otg-fsm.h @@ -0,0 +1,244 @@ +/* Copyright (C) 2007,2008 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. + * + * This program is distributed in the hope that it will be useful, 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_USB_OTG_FSM_H +#define __LINUX_USB_OTG_FSM_H + +#include +#include + +#undef VERBOSE + +#ifdef VERBOSE +#define VDBG(fmt, args...) pr_debug("[%s] " fmt , \ + __func__, ## args) +#else +#define VDBG(stuff...) do {} while (0) +#endif + +#ifdef VERBOSE +#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) +#else +#define MPC_LOC do {} while (0) +#endif + +#define PROTO_UNDEF (0) +#define PROTO_HOST (1) +#define PROTO_GADGET (2) + +enum otg_fsm_timer { + /* Standard OTG timers */ + A_WAIT_VRISE, + A_WAIT_VFALL, + A_WAIT_BCON, + A_AIDL_BDIS, + B_ASE0_BRST, + A_BIDL_ADIS, + + /* Auxiliary timers */ + B_SE0_SRP, + B_SRP_FAIL, + A_WAIT_ENUM, + + NUM_OTG_FSM_TIMERS, +}; + +/* OTG state machine according to the OTG spec */ +struct otg_fsm { + /* Input */ + int id; + int adp_change; + int power_up; + int test_device; + int a_bus_drop; + int a_bus_req; + int a_srp_det; + int a_vbus_vld; + int b_conn; + int a_bus_resume; + int a_bus_suspend; + int a_conn; + int b_bus_req; + int b_se0_srp; + int b_ssend_srp; + int b_sess_vld; + /* Auxilary inputs */ + int a_sess_vld; + int b_bus_resume; + int b_bus_suspend; + + /* Output */ + int data_pulse; + int drv_vbus; + int loc_conn; + int loc_sof; + int adp_prb; + int adp_sns; + + /* Internal variables */ + int a_set_b_hnp_en; + int b_srp_done; + int b_hnp_enable; + int a_clr_err; + + /* Informative variables */ + int a_bus_drop_inf; + int a_bus_req_inf; + int a_clr_err_inf; + int b_bus_req_inf; + /* Auxilary informative variables */ + int a_suspend_req_inf; + + /* Timeout indicator for timers */ + int a_wait_vrise_tmout; + int a_wait_vfall_tmout; + int a_wait_bcon_tmout; + int a_aidl_bdis_tmout; + int b_ase0_brst_tmout; + int a_bidl_adis_tmout; + + struct otg_fsm_ops *ops; + struct usb_otg *otg; + + /* Current usb protocol used: 0:undefine; 1:host; 2:client */ + int protocol; + struct mutex lock; +}; + +struct otg_fsm_ops { + void (*chrg_vbus)(struct otg_fsm *fsm, int on); + void (*drv_vbus)(struct otg_fsm *fsm, int on); + void (*loc_conn)(struct otg_fsm *fsm, int on); + void (*loc_sof)(struct otg_fsm *fsm, int on); + void (*start_pulse)(struct otg_fsm *fsm); + void (*start_adp_prb)(struct otg_fsm *fsm); + void (*start_adp_sns)(struct otg_fsm *fsm); + void (*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); + void (*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); + int (*start_host)(struct otg_fsm *fsm, int on); + int (*start_gadget)(struct otg_fsm *fsm, int on); +}; + + +static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on) +{ + if (!fsm->ops->chrg_vbus) + return -EOPNOTSUPP; + fsm->ops->chrg_vbus(fsm, on); + return 0; +} + +static inline int otg_drv_vbus(struct otg_fsm *fsm, int on) +{ + if (!fsm->ops->drv_vbus) + return -EOPNOTSUPP; + if (fsm->drv_vbus != on) { + fsm->drv_vbus = on; + fsm->ops->drv_vbus(fsm, on); + } + return 0; +} + +static inline int otg_loc_conn(struct otg_fsm *fsm, int on) +{ + if (!fsm->ops->loc_conn) + return -EOPNOTSUPP; + if (fsm->loc_conn != on) { + fsm->loc_conn = on; + fsm->ops->loc_conn(fsm, on); + } + return 0; +} + +static inline int otg_loc_sof(struct otg_fsm *fsm, int on) +{ + if (!fsm->ops->loc_sof) + return -EOPNOTSUPP; + if (fsm->loc_sof != on) { + fsm->loc_sof = on; + fsm->ops->loc_sof(fsm, on); + } + return 0; +} + +static inline int otg_start_pulse(struct otg_fsm *fsm) +{ + if (!fsm->ops->start_pulse) + return -EOPNOTSUPP; + if (!fsm->data_pulse) { + fsm->data_pulse = 1; + fsm->ops->start_pulse(fsm); + } + return 0; +} + +static inline int otg_start_adp_prb(struct otg_fsm *fsm) +{ + if (!fsm->ops->start_adp_prb) + return -EOPNOTSUPP; + if (!fsm->adp_prb) { + fsm->adp_sns = 0; + fsm->adp_prb = 1; + fsm->ops->start_adp_prb(fsm); + } + return 0; +} + +static inline int otg_start_adp_sns(struct otg_fsm *fsm) +{ + if (!fsm->ops->start_adp_sns) + return -EOPNOTSUPP; + if (!fsm->adp_sns) { + fsm->adp_sns = 1; + fsm->ops->start_adp_sns(fsm); + } + return 0; +} + +static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) +{ + if (!fsm->ops->add_timer) + return -EOPNOTSUPP; + fsm->ops->add_timer(fsm, timer); + return 0; +} + +static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) +{ + if (!fsm->ops->del_timer) + return -EOPNOTSUPP; + fsm->ops->del_timer(fsm, timer); + return 0; +} + +static inline int otg_start_host(struct otg_fsm *fsm, int on) +{ + if (!fsm->ops->start_host) + return -EOPNOTSUPP; + return fsm->ops->start_host(fsm, on); +} + +static inline int otg_start_gadget(struct otg_fsm *fsm, int on) +{ + if (!fsm->ops->start_gadget) + return -EOPNOTSUPP; + return fsm->ops->start_gadget(fsm, on); +} + +int otg_statemachine(struct otg_fsm *fsm); + +#endif /* __LINUX_USB_OTG_FSM_H */ -- cgit v1.2.3 From e1d2e31975e1e3a31ac592d5b1c5cb5d655b3f4e Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 26 Nov 2013 11:47:53 +0900 Subject: usb: phy: Add OTG FSM configuration option This patch removes dependency on Freescale USB UTG Transceiver driver and makes OTG FSM implementation selectable. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/phy/Kconfig | 10 +++++++++- drivers/usb/phy/Makefile | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 08e2f39027ec..921a9f43e309 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -6,6 +6,14 @@ menu "USB Physical Layer drivers" config USB_PHY def_bool n +config USB_OTG_FSM + bool "USB 2.0 OTG FSM implementation" + select USB_OTG + select USB_PHY + help + Implements OTG Final State Machine as specified in On-The-Go + and Embedded Host Supplement to the USB Revision 2.0 Specification. + # # USB Transceiver Drivers # @@ -20,7 +28,7 @@ config AB8500_USB config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME + depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM_RUNTIME select USB_OTG select USB_PHY help diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 022c1da7fb78..1bf6c083a36e 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -3,12 +3,12 @@ # obj-$(CONFIG_USB_PHY) += phy.o obj-$(CONFIG_OF) += of.o +obj-$(CONFIG_USB_OTG_FSM) += phy-fsm-usb.o # transceiver drivers, keep the list sorted obj-$(CONFIG_AB8500_USB) += phy-ab8500-usb.o -phy-fsl-usb2-objs := phy-fsl-usb.o phy-fsm-usb.o -obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o +obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb.o obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o -- cgit v1.2.3 From 5ace3d00fa11bb9ec5e1cc02805ac27201f27e61 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Wed, 30 Oct 2013 09:38:23 -0500 Subject: usb: musb: dsps: polling ID pin status only in otg mode Only start the otg_timer in dual role mode; otherwise in peripheral mode when musb is disconnected from the host port, otg_timer starts and continuously toggles the session, which causes VBUS pulse. Signed-off-by: Bin Liu Acked-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 7cfa6e80ad60..593d3c962565 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -359,8 +359,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); - /* Poll for ID change */ - if (musb->xceiv->state == OTG_STATE_B_IDLE) + /* Poll for ID change in OTG port mode */ + if (musb->xceiv->state == OTG_STATE_B_IDLE && + musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); out: spin_unlock_irqrestore(&musb->lock, flags); -- cgit v1.2.3 From 272850f07c47ab1bef4386e41d006a0e6c1654a9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:11 -0700 Subject: staging: comedi: comedi_fops: remove use of DPRINTK Use dev_dbg(), or pr_debug() when dev is not valid, instead of the DPRINTK macro to output the comedi debugging information. Remove the debug messages for allocation failures. The failure will have already generated a message. Reword the messages that include the dev->minor number. This number will already be displayed as part of the dev_dbg() output. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 119 +++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 1071c9601d1a..cdaef09c8993 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -250,11 +250,13 @@ static int resize_async_buffer(struct comedi_device *dev, return -EPERM; if (s->busy) { - DPRINTK("subdevice is busy, cannot resize buffer\n"); + dev_dbg(dev->class_dev, + "subdevice is busy, cannot resize buffer\n"); return -EBUSY; } if (comedi_buf_is_mmapped(async)) { - DPRINTK("subdevice is mmapped, cannot resize buffer\n"); + dev_dbg(dev->class_dev, + "subdevice is mmapped, cannot resize buffer\n"); return -EBUSY; } @@ -272,8 +274,8 @@ static int resize_async_buffer(struct comedi_device *dev, return retval; } - DPRINTK("comedi%i subd %d buffer resized to %i bytes\n", - dev->minor, s->index, async->prealloc_bufsz); + dev_dbg(dev->class_dev, "subd %d buffer resized to %i bytes\n", + s->index, async->prealloc_bufsz); return 0; } @@ -726,7 +728,8 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, async = s->async; if (!async) { - DPRINTK("subdevice does not have async capability\n"); + dev_dbg(dev->class_dev, + "subdevice does not have async capability\n"); bc.size = 0; bc.maximum_size = 0; goto copyback; @@ -973,7 +976,8 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, async = s->async; if (!async) { - DPRINTK("subdevice does not have async capability\n"); + dev_dbg(dev->class_dev, + "subdevice does not have async capability\n"); bi.buf_write_ptr = 0; bi.buf_read_ptr = 0; bi.buf_write_count = 0; @@ -1125,19 +1129,20 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, break; } if (insn->subdev >= dev->n_subdevices) { - DPRINTK("%d not usable subdevice\n", + dev_dbg(dev->class_dev, + "%d not usable subdevice\n", insn->subdev); ret = -EINVAL; break; } s = &dev->subdevices[insn->subdev]; if (!s->async) { - DPRINTK("no async\n"); + dev_dbg(dev->class_dev, "no async\n"); ret = -EINVAL; break; } if (!s->async->inttrig) { - DPRINTK("no inttrig\n"); + dev_dbg(dev->class_dev, "no inttrig\n"); ret = -EAGAIN; break; } @@ -1146,7 +1151,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = 1; break; default: - DPRINTK("invalid insn\n"); + dev_dbg(dev->class_dev, "invalid insn\n"); ret = -EINVAL; break; } @@ -1155,21 +1160,23 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int maxdata; if (insn->subdev >= dev->n_subdevices) { - DPRINTK("subdevice %d out of range\n", insn->subdev); + dev_dbg(dev->class_dev, "subdevice %d out of range\n", + insn->subdev); ret = -EINVAL; goto out; } s = &dev->subdevices[insn->subdev]; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not usable subdevice\n", insn->subdev); + dev_dbg(dev->class_dev, "%d not usable subdevice\n", + insn->subdev); ret = -EIO; goto out; } /* are we locked? (ioctl lock) */ if (s->lock && s->lock != file) { - DPRINTK("device locked\n"); + dev_dbg(dev->class_dev, "device locked\n"); ret = -EACCES; goto out; } @@ -1177,7 +1184,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = comedi_check_chanlist(s, 1, &insn->chanspec); if (ret < 0) { ret = -EINVAL; - DPRINTK("bad chanspec\n"); + dev_dbg(dev->class_dev, "bad chanspec\n"); goto out; } @@ -1198,7 +1205,8 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, for (i = 0; i < insn->n; ++i) { if (data[i] > maxdata) { ret = -EINVAL; - DPRINTK("bad data value(s)\n"); + dev_dbg(dev->class_dev, + "bad data value(s)\n"); break; } } @@ -1280,35 +1288,35 @@ static int do_insnlist_ioctl(struct comedi_device *dev, data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); if (!data) { - DPRINTK("kmalloc failed\n"); ret = -ENOMEM; goto error; } insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL); if (!insns) { - DPRINTK("kmalloc failed\n"); ret = -ENOMEM; goto error; } if (copy_from_user(insns, insnlist.insns, sizeof(*insns) * insnlist.n_insns)) { - DPRINTK("copy_from_user failed\n"); + dev_dbg(dev->class_dev, "copy_from_user failed\n"); ret = -EFAULT; goto error; } for (i = 0; i < insnlist.n_insns; i++) { if (insns[i].n > MAX_SAMPLES) { - DPRINTK("number of samples too large\n"); + dev_dbg(dev->class_dev, + "number of samples too large\n"); ret = -EINVAL; goto error; } if (insns[i].insn & INSN_MASK_WRITE) { if (copy_from_user(data, insns[i].data, insns[i].n * sizeof(unsigned int))) { - DPRINTK("copy_from_user failed\n"); + dev_dbg(dev->class_dev, + "copy_from_user failed\n"); ret = -EFAULT; goto error; } @@ -1319,7 +1327,8 @@ static int do_insnlist_ioctl(struct comedi_device *dev, if (insns[i].insn & INSN_MASK_READ) { if (copy_to_user(insns[i].data, data, insns[i].n * sizeof(unsigned int))) { - DPRINTK("copy_to_user failed\n"); + dev_dbg(dev->class_dev, + "copy_to_user failed\n"); ret = -EFAULT; goto error; } @@ -1409,14 +1418,14 @@ static int do_cmd_ioctl(struct comedi_device *dev, unsigned int __user *user_chanlist; if (copy_from_user(&cmd, arg, sizeof(cmd))) { - DPRINTK("bad cmd address\n"); + dev_dbg(dev->class_dev, "bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ user_chanlist = (unsigned int __user *)cmd.chanlist; if (cmd.subdev >= dev->n_subdevices) { - DPRINTK("%d no such subdevice\n", cmd.subdev); + dev_dbg(dev->class_dev, "%d no such subdevice\n", cmd.subdev); return -ENODEV; } @@ -1424,38 +1433,38 @@ static int do_cmd_ioctl(struct comedi_device *dev, async = s->async; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not valid subdevice\n", cmd.subdev); + dev_dbg(dev->class_dev, "%d not valid subdevice\n", cmd.subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest || !s->async) { - DPRINTK("subdevice %i does not support commands\n", - cmd.subdev); + dev_dbg(dev->class_dev, + "subdevice %i does not support commands\n", cmd.subdev); return -EIO; } /* are we locked? (ioctl lock) */ if (s->lock && s->lock != file) { - DPRINTK("subdevice locked\n"); + dev_dbg(dev->class_dev, "subdevice locked\n"); return -EACCES; } /* are we busy? */ if (s->busy) { - DPRINTK("subdevice busy\n"); + dev_dbg(dev->class_dev, "subdevice busy\n"); return -EBUSY; } /* make sure channel/gain list isn't too long */ if (cmd.chanlist_len > s->len_chanlist) { - DPRINTK("channel/gain list too long %u > %d\n", + dev_dbg(dev->class_dev, "channel/gain list too long %u > %d\n", cmd.chanlist_len, s->len_chanlist); return -EINVAL; } /* make sure channel/gain list isn't too short */ if (cmd.chanlist_len < 1) { - DPRINTK("channel/gain list too short %u < 1\n", + dev_dbg(dev->class_dev, "channel/gain list too short %u < 1\n", cmd.chanlist_len); return -EINVAL; } @@ -1467,7 +1476,8 @@ static int do_cmd_ioctl(struct comedi_device *dev, async->cmd.chanlist_len * sizeof(int)); if (IS_ERR(async->cmd.chanlist)) { ret = PTR_ERR(async->cmd.chanlist); - DPRINTK("memdup_user failed with code %d\n", ret); + dev_dbg(dev->class_dev, "memdup_user failed with code %d\n", + ret); goto cleanup; } @@ -1476,20 +1486,20 @@ static int do_cmd_ioctl(struct comedi_device *dev, async->cmd.chanlist_len, async->cmd.chanlist); if (ret < 0) { - DPRINTK("bad chanlist\n"); + dev_dbg(dev->class_dev, "bad chanlist\n"); goto cleanup; } ret = s->do_cmdtest(dev, s, &async->cmd); if (async->cmd.flags & TRIG_BOGUS || ret) { - DPRINTK("test returned %d\n", ret); + dev_dbg(dev->class_dev, "test returned %d\n", ret); cmd = async->cmd; /* restore chanlist pointer before copying back */ cmd.chanlist = (unsigned int __force *)user_chanlist; cmd.data = NULL; if (copy_to_user(arg, &cmd, sizeof(cmd))) { - DPRINTK("fault writing cmd\n"); + dev_dbg(dev->class_dev, "fault writing cmd\n"); ret = -EFAULT; goto cleanup; } @@ -1499,7 +1509,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (!async->prealloc_bufsz) { ret = -ENOMEM; - DPRINTK("no buffer (?)\n"); + dev_dbg(dev->class_dev, "no buffer (?)\n"); goto cleanup; } @@ -1551,32 +1561,32 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, unsigned int __user *user_chanlist; if (copy_from_user(&cmd, arg, sizeof(cmd))) { - DPRINTK("bad cmd address\n"); + dev_dbg(dev->class_dev, "bad cmd address\n"); return -EFAULT; } /* save user's chanlist pointer so it can be restored later */ user_chanlist = (unsigned int __user *)cmd.chanlist; if (cmd.subdev >= dev->n_subdevices) { - DPRINTK("%d no such subdevice\n", cmd.subdev); + dev_dbg(dev->class_dev, "%d no such subdevice\n", cmd.subdev); return -ENODEV; } s = &dev->subdevices[cmd.subdev]; if (s->type == COMEDI_SUBD_UNUSED) { - DPRINTK("%d not valid subdevice\n", cmd.subdev); + dev_dbg(dev->class_dev, "%d not valid subdevice\n", cmd.subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest) { - DPRINTK("subdevice %i does not support commands\n", - cmd.subdev); + dev_dbg(dev->class_dev, + "subdevice %i does not support commands\n", cmd.subdev); return -EIO; } /* make sure channel/gain list isn't too long */ if (cmd.chanlist_len > s->len_chanlist) { - DPRINTK("channel/gain list too long %d > %d\n", + dev_dbg(dev->class_dev, "channel/gain list too long %d > %d\n", cmd.chanlist_len, s->len_chanlist); ret = -EINVAL; goto cleanup; @@ -1588,14 +1598,15 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, cmd.chanlist_len * sizeof(int)); if (IS_ERR(chanlist)) { ret = PTR_ERR(chanlist); - DPRINTK("memdup_user exited with code %d", ret); + dev_dbg(dev->class_dev, + "memdup_user exited with code %d", ret); goto cleanup; } /* make sure each element in channel/gain list is valid */ ret = comedi_check_chanlist(s, cmd.chanlist_len, chanlist); if (ret < 0) { - DPRINTK("bad chanlist\n"); + dev_dbg(dev->class_dev, "bad chanlist\n"); goto cleanup; } @@ -1608,7 +1619,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, cmd.chanlist = (unsigned int __force *)user_chanlist; if (copy_to_user(arg, &cmd, sizeof(cmd))) { - DPRINTK("bad cmd address\n"); + dev_dbg(dev->class_dev, "bad cmd address\n"); ret = -EFAULT; goto cleanup; } @@ -1818,7 +1829,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, } if (!dev->attached) { - DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor); + dev_dbg(dev->class_dev, "no driver attached\n"); rc = -ENODEV; goto done; } @@ -1923,7 +1934,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) mutex_lock(&dev->mutex); if (!dev->attached) { - DPRINTK("no driver configured on comedi%i\n", dev->minor); + dev_dbg(dev->class_dev, "no driver attached\n"); retval = -ENODEV; goto done; } @@ -1944,7 +1955,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) } if (vma->vm_pgoff != 0) { - DPRINTK("comedi: mmap() offset must be 0.\n"); + dev_dbg(dev->class_dev, "mmap() offset must be 0.\n"); retval = -EINVAL; goto done; } @@ -1998,7 +2009,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) mutex_lock(&dev->mutex); if (!dev->attached) { - DPRINTK("no driver configured on comedi%i\n", dev->minor); + dev_dbg(dev->class_dev, "no driver attached\n"); goto done; } @@ -2045,7 +2056,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, old_detach_count = dev->detach_count; if (!dev->attached) { - DPRINTK("no driver configured on comedi%i\n", dev->minor); + dev_dbg(dev->class_dev, "no driver attached\n"); retval = -ENODEV; goto out; } @@ -2181,7 +2192,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, old_detach_count = dev->detach_count; if (!dev->attached) { - DPRINTK("no driver configured on comedi%i\n", dev->minor); + dev_dbg(dev->class_dev, "no driver attached\n"); retval = -ENODEV; goto out; } @@ -2300,7 +2311,7 @@ static int comedi_open(struct inode *inode, struct file *file) int rc; if (!dev) { - DPRINTK("invalid minor number\n"); + pr_debug("invalid minor number\n"); return -ENODEV; } @@ -2321,7 +2332,7 @@ static int comedi_open(struct inode *inode, struct file *file) if (dev->attached) goto ok; if (!capable(CAP_NET_ADMIN) && dev->in_request_module) { - DPRINTK("in request module\n"); + dev_dbg(dev->class_dev, "in request module\n"); rc = -ENODEV; goto out; } @@ -2339,7 +2350,7 @@ static int comedi_open(struct inode *inode, struct file *file) dev->in_request_module = false; if (!dev->attached && !capable(CAP_NET_ADMIN)) { - DPRINTK("not attached and not CAP_NET_ADMIN\n"); + dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n"); rc = -ENODEV; goto out; } @@ -2440,8 +2451,6 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) unsigned runflags = 0; unsigned runflags_mask = 0; - /* DPRINTK("comedi_event 0x%x\n",mask); */ - if (!comedi_is_subdevice_running(s)) return; -- cgit v1.2.3 From 055ace5e26d2459e472419c5785b88564b7df79a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:12 -0700 Subject: staging: comedi: ni_pcidio: remove DEBUG_FLAGS define and code The DEBUG_FLAGS define enables some development code that outputs interrupt flags and status information in the interrupt handler. This information is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 60 ------------------------------ 1 file changed, 60 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 75da358b7a32..c04ec2954a0a 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -47,7 +47,6 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org */ #define USE_DMA -/* #define DEBUG_FLAGS */ #include #include @@ -311,14 +310,6 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode); static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s); -#ifdef DEBUG_FLAGS -static void ni_pcidio_print_flags(unsigned int flags); -static void ni_pcidio_print_status(unsigned int status); -#else -#define ni_pcidio_print_flags(x) -#define ni_pcidio_print_status(x) -#endif - static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev) { struct nidio96_private *devpriv = dev->private; @@ -421,8 +412,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n", status, flags); - ni_pcidio_print_flags(flags); - ni_pcidio_print_status(status); spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) @@ -488,8 +477,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) async->buf_int_count); */ /* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n", IntEn,flags,status); */ - /* ni_pcidio_print_flags(flags); */ - /* ni_pcidio_print_status(status); */ async->events |= COMEDI_CB_BLOCK; } @@ -536,8 +523,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) Interrupt_And_Window_Status); /* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x," "status=0x%02x\n", IntEn, flags, status); */ - /* ni_pcidio_print_flags(flags); */ - /* ni_pcidio_print_status(status); */ } out: @@ -554,51 +539,6 @@ out: return IRQ_HANDLED; } -#ifdef DEBUG_FLAGS -static const char *bit_set_string(unsigned int bits, unsigned int bit, - const char *const strings[]) -{ - return (bits & (1U << bit)) ? strings[bit] : ""; -} - -static const char *const flags_strings[] = { - " TransferReady", " CountExpired", " 2", " 3", - " 4", " Waited", " PrimaryTC", " SecondaryTC", -}; - - -static void ni_pcidio_print_flags(unsigned int flags) -{ - pr_debug("group_1_flags:%s%s%s%s%s%s%s%s\n", - bit_set_string(flags, 7, flags_strings), - bit_set_string(flags, 6, flags_strings), - bit_set_string(flags, 5, flags_strings), - bit_set_string(flags, 4, flags_strings), - bit_set_string(flags, 3, flags_strings), - bit_set_string(flags, 2, flags_strings), - bit_set_string(flags, 1, flags_strings), - bit_set_string(flags, 0, flags_strings)); -} - -static const char *const status_strings[] = { - " DataLeft1", " Reserved1", " Req1", " StopTrig1", - " DataLeft2", " Reserved2", " Req2", " StopTrig2", -}; - -static void ni_pcidio_print_status(unsigned int flags) -{ - pr_debug("group_status:%s%s%s%s%s%s%s%s\n", - bit_set_string(flags, 7, status_strings), - bit_set_string(flags, 6, status_strings), - bit_set_string(flags, 5, status_strings), - bit_set_string(flags, 4, status_strings), - bit_set_string(flags, 3, status_strings), - bit_set_string(flags, 2, status_strings), - bit_set_string(flags, 1, status_strings), - bit_set_string(flags, 0, status_strings)); -} -#endif - #ifdef unused static void debug_int(struct comedi_device *dev) { -- cgit v1.2.3 From 52cdd1205f4aa1e7f861eab8353740665f078106 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:13 -0700 Subject: staging: comedi: ni_pcidio: remove debug_int() This function is not used by the driver. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 31 ------------------------------ 1 file changed, 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index c04ec2954a0a..933aabec86e8 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -539,37 +539,6 @@ out: return IRQ_HANDLED; } -#ifdef unused -static void debug_int(struct comedi_device *dev) -{ - struct nidio96_private *devpriv = dev->private; - int a, b; - static int n_int; - struct timeval tv; - - do_gettimeofday(&tv); - a = readb(devpriv->mite->daq_io_addr + Group_Status); - b = readb(devpriv->mite->daq_io_addr + Group_1_Flags); - - if (n_int < 10) { - DPRINTK("status 0x%02x flags 0x%02x time %06d\n", a, b, - (int)tv.tv_usec); - } - - while (b & 1) { - writew(0xff, devpriv->mite->daq_io_addr + Group_1_FIFO); - b = readb(devpriv->mite->daq_io_addr + Group_1_Flags); - } - - b = readb(devpriv->mite->daq_io_addr + Group_1_Flags); - - if (n_int < 10) { - DPRINTK("new status 0x%02x\n", b); - n_int++; - } -} -#endif - static int ni_pcidio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, -- cgit v1.2.3 From 20dad98dfedd2c3d8905e03b19ed4a6a2c1d73f3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:14 -0700 Subject: staging: comedi: ni_pcidio: remove use of DPRINTK Remove the DPRINTK messages that are just function trace noise. Use dev_dbg() instead of the DPRINTK macro to output the comedi debugging information. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 34 ++++++------------------------ 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 933aabec86e8..b2af28096b32 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -410,9 +410,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) Interrupt_And_Window_Status); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); - DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n", - status, flags); - spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) m_status = mite_get_status(devpriv->di_mite_chan); @@ -431,7 +428,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d) } if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | CHSR_DRQ1 | CHSR_MRDY)) { - DPRINTK("unknown mite interrupt, disabling IRQ\n"); + dev_dbg(dev->class_dev, + "unknown mite interrupt, disabling IRQ\n"); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; disable_irq(dev->irq); } @@ -441,7 +439,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) while (status & DataLeft) { work++; if (work > 20) { - DPRINTK("too much work in interrupt\n"); + dev_dbg(dev->class_dev, "too much work in interrupt\n"); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); @@ -451,11 +449,11 @@ static irqreturn_t nidio_interrupt(int irq, void *d) flags &= IntEn; if (flags & TransferReady) { - /* DPRINTK("TransferReady\n"); */ while (flags & TransferReady) { work++; if (work > 100) { - DPRINTK("too much work in interrupt\n"); + dev_dbg(dev->class_dev, + "too much work in interrupt\n"); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control @@ -469,19 +467,13 @@ static irqreturn_t nidio_interrupt(int irq, void *d) data2 = (auxdata & 0xffff0000) >> 16; comedi_buf_put(async, data1); comedi_buf_put(async, data2); - /* DPRINTK("read:%d, %d\n",data1,data2); */ flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); } - /* DPRINTK("buf_int_count: %d\n", - async->buf_int_count); */ - /* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n", - IntEn,flags,status); */ async->events |= COMEDI_CB_BLOCK; } if (flags & CountExpired) { - DPRINTK("CountExpired\n"); writeb(ClearExpired, devpriv->mite->daq_io_addr + Group_1_Second_Clear); @@ -490,39 +482,26 @@ static irqreturn_t nidio_interrupt(int irq, void *d) writeb(0x00, devpriv->mite->daq_io_addr + OpMode); break; } else if (flags & Waited) { - DPRINTK("Waited\n"); writeb(ClearWaited, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; break; } else if (flags & PrimaryTC) { - DPRINTK("PrimaryTC\n"); writeb(ClearPrimaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } else if (flags & SecondaryTC) { - DPRINTK("SecondaryTC\n"); writeb(ClearSecondaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } -#if 0 - else { - DPRINTK("ni_pcidio: unknown interrupt\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - writeb(0x00, - devpriv->mite->daq_io_addr + - Master_DMA_And_Interrupt_Control); - } -#endif + flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); - /* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x," - "status=0x%02x\n", IntEn, flags, status); */ } out: @@ -784,7 +763,6 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) s->async->inttrig = ni_pcidio_inttrig; } - DPRINTK("ni_pcidio: command started\n"); return 0; } -- cgit v1.2.3 From 26901032089ecc6bba0ea9c04841e333e2ac8622 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:15 -0700 Subject: staging: comedi: remove DPRINTK macro All users of this macro have been converted to use dev_dbg(). Remove the unused macro. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 3c6329bed508..f00b43c955f4 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -27,8 +27,6 @@ #include "comedi.h" -#define DPRINTK(format, args...) pr_debug("comedi: " format, ## args); - #define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) #define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, \ COMEDI_MINORVERSION, COMEDI_MICROVERSION) -- cgit v1.2.3 From a7866a6ef70f657a54bbdfc2bd19fd8b70f72fd3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:16 -0700 Subject: staging: comedi: mite: remove MDPRINTK macro This macro is used by the comedi drivers that usee the mite module to output development function trace messages. These are just added noise. Remove the messages as well as the macro. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mite.c | 9 --------- drivers/staging/comedi/drivers/mite.h | 7 ------- drivers/staging/comedi/drivers/ni_mio_common.c | 18 ++---------------- 3 files changed, 2 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 1a2191699351..447047faf6bf 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -288,7 +288,6 @@ void mite_dma_arm(struct mite_channel *mite_chan) int chor; unsigned long flags; - MDPRINTK("mite_dma_arm ch%i\n", mite_chan->channel); /* * memory barrier is intended to insure any twiddling with the buffer * is done before writing to the mite to arm dma transfer @@ -329,8 +328,6 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, n_links = async->prealloc_bufsz >> PAGE_SHIFT; - MDPRINTK("ring->hw_dev=%p, n_links=0x%04x\n", ring->hw_dev, n_links); - ring->descriptors = dma_alloc_coherent(ring->hw_dev, n_links * sizeof(struct mite_dma_descriptor), @@ -368,8 +365,6 @@ void mite_prep_dma(struct mite_channel *mite_chan, unsigned int chor, chcr, mcr, dcr, lkcr; struct mite_struct *mite = mite_chan->mite; - MDPRINTK("mite_prep_dma ch%i\n", mite_chan->channel); - /* reset DMA and FIFO */ chor = CHOR_DMARESET | CHOR_FRESET; writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); @@ -448,8 +443,6 @@ void mite_prep_dma(struct mite_channel *mite_chan, /* starting address for link chaining */ writel(mite_chan->ring->descriptors_dma_addr, mite->mite_io_addr + MITE_LKAR(mite_chan->channel)); - - MDPRINTK("exit mite_prep_dma\n"); } EXPORT_SYMBOL_GPL(mite_prep_dma); @@ -515,8 +508,6 @@ unsigned mite_dma_tcr(struct mite_channel *mite_chan) lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel)); tcr = readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel)); - MDPRINTK("mite_dma_tcr ch%i, lkar=0x%08x tcr=%d\n", mite_chan->channel, - lkar, tcr); return tcr; } diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 8423b8bf3384..1d72149db918 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -24,15 +24,8 @@ #include #include "../comedidev.h" -/* #define DEBUG_MITE */ #define PCIMIO_COMPAT -#ifdef DEBUG_MITE -#define MDPRINTK(format, args...) pr_debug(format , ## args) -#else -#define MDPRINTK(format, args...) do { } while (0) -#endif - #define MAX_MITE_DMA_CHANNELS 8 struct mite_dma_descriptor { diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 5113397bfecf..058185292b0d 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -63,10 +63,6 @@ #include "mite.h" #include "comedi_fc.h" -#ifndef MDPRINTK -#define MDPRINTK(format, args...) -#endif - /* A timeout count */ #define NI_TIMEOUT 1000 static const unsigned old_RTSI_clock_channel = 7; @@ -1214,12 +1210,9 @@ static void handle_b_interrupt(struct comedi_device *dev, s->async->events |= COMEDI_CB_OVERFLOW; } - if (b_status & AO_BC_TC_St) { - MDPRINTK - ("ni_mio_common: AO BC_TC status=0x%04x status2=0x%04x\n", - b_status, devpriv->stc_readw(dev, AO_Status_2_Register)); + if (b_status & AO_BC_TC_St) s->async->events |= COMEDI_CB_EOA; - } + #ifndef PCIDMA if (b_status & AO_FIFO_Request_St) { int ret; @@ -2392,7 +2385,6 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int stop_count; int interrupt_a_enable = 0; - MDPRINTK("ni_ai_cmd\n"); if (dev->irq == 0) { comedi_error(dev, "cannot run command without an irq"); return -EIO; @@ -2630,15 +2622,11 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_set_bits(dev, Interrupt_A_Enable_Register, interrupt_a_enable, 1); - - MDPRINTK("Interrupt_A_Enable_Register = 0x%04x\n", - devpriv->int_a_enable_reg); } else { /* interrupt on nothing */ ni_set_bits(dev, Interrupt_A_Enable_Register, ~0, 0); /* XXX start polling if necessary */ - MDPRINTK("interrupting on nothing\n"); } /* end configuration */ @@ -2682,8 +2670,6 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; } - MDPRINTK("exit ni_ai_cmd\n"); - return 0; } -- cgit v1.2.3 From 096669a8301478641abf16bbc02db786e26165bd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:17 -0700 Subject: staging: comedi: mite: remove DEBUG_MITE code The code protected by the DEBUG_MITE define outputs some development debug information. This information is just added noise in the final driver. Remove the code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mite.c | 134 ------------------------- drivers/staging/comedi/drivers/mite.h | 5 - drivers/staging/comedi/drivers/ni_mio_common.c | 3 - drivers/staging/comedi/drivers/ni_pcidio.c | 4 - 4 files changed, 146 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 447047faf6bf..9c9a0ee432cf 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -633,140 +633,6 @@ int mite_done(struct mite_channel *mite_chan) } EXPORT_SYMBOL_GPL(mite_done); -#ifdef DEBUG_MITE - -/* names of bits in mite registers */ - -static const char *const mite_CHOR_strings[] = { - "start", "cont", "stop", "abort", - "freset", "clrlc", "clrrb", "clrdone", - "clr_lpause", "set_lpause", "clr_send_tc", - "set_send_tc", "12", "13", "14", - "15", "16", "17", "18", - "19", "20", "21", "22", - "23", "24", "25", "26", - "27", "28", "29", "30", - "dmareset", -}; - -static const char *const mite_CHCR_strings[] = { - "continue", "ringbuff", "2", "3", - "4", "5", "6", "7", - "8", "9", "10", "11", - "12", "13", "bursten", "fifodis", - "clr_cont_rb_ie", "set_cont_rb_ie", "clr_lc_ie", "set_lc_ie", - "clr_drdy_ie", "set_drdy_ie", "clr_mrdy_ie", "set_mrdy_ie", - "clr_done_ie", "set_done_ie", "clr_sar_ie", "set_sar_ie", - "clr_linkp_ie", "set_linkp_ie", "clr_dma_ie", "set_dma_ie", -}; - -static const char *const mite_MCR_strings[] = { - "amdevice", "1", "2", "3", - "4", "5", "portio", "portvxi", - "psizebyte", "psizehalf (byte & half = word)", "aseqxp1", "11", - "12", "13", "blocken", "berhand", - "reqsintlim/reqs0", "reqs1", "reqs2", "rd32", - "rd512", "rl1", "rl2", "rl8", - "24", "25", "26", "27", - "28", "29", "30", "stopen", -}; - -static const char *const mite_DCR_strings[] = { - "amdevice", "1", "2", "3", - "4", "5", "portio", "portvxi", - "psizebyte", "psizehalf (byte & half = word)", "aseqxp1", "aseqxp2", - "aseqxp8", "13", "blocken", "berhand", - "reqsintlim", "reqs1", "reqs2", "rd32", - "rd512", "rl1", "rl2", "rl8", - "23", "24", "25", "27", - "28", "wsdevc", "wsdevs", "rwdevpack", -}; - -static const char *const mite_LKCR_strings[] = { - "amdevice", "1", "2", "3", - "4", "5", "portio", "portvxi", - "psizebyte", "psizehalf (byte & half = word)", "asequp", "aseqdown", - "12", "13", "14", "berhand", - "16", "17", "18", "rd32", - "rd512", "rl1", "rl2", "rl8", - "24", "25", "26", "27", - "28", "29", "30", "chngend", -}; - -static const char *const mite_CHSR_strings[] = { - "d.err0", "d.err1", "m.err0", "m.err1", - "l.err0", "l.err1", "drq0", "drq1", - "end", "xferr", "operr0", "operr1", - "stops", "habort", "sabort", "error", - "16", "conts_rb", "18", "linkc", - "20", "drdy", "22", "mrdy", - "24", "done", "26", "sars", - "28", "lpauses", "30", "int", -}; - -static void mite_decode(const char *const *bit_str, unsigned int bits) -{ - int i; - - for (i = 31; i >= 0; i--) { - if (bits & (1 << i)) - pr_debug(" %s\n", bit_str[i]); - } -} - -void mite_dump_regs(struct mite_channel *mite_chan) -{ - void __iomem *mite_io_addr = mite_chan->mite->mite_io_addr; - unsigned int offset; - unsigned int value; - int channel = mite_chan->channel; - - pr_debug("mite_dump_regs ch%i\n", channel); - pr_debug("mite address is =%p\n", mite_io_addr); - - offset = MITE_CHOR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[CHOR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_CHOR_strings, value); - offset = MITE_CHCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[CHCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_CHCR_strings, value); - offset = MITE_TCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[TCR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_MCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[MCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_MCR_strings, value); - offset = MITE_MAR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[MAR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_DCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[DCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_DCR_strings, value); - offset = MITE_DAR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[DAR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_LKCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[LKCR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_LKCR_strings, value); - offset = MITE_LKAR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[LKAR] at 0x%08x =0x%08x\n", offset, value); - offset = MITE_CHSR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[CHSR] at 0x%08x =0x%08x\n", offset, value); - mite_decode(mite_CHSR_strings, value); - offset = MITE_FCR(channel); - value = readl(mite_io_addr + offset); - pr_debug("mite status[FCR] at 0x%08x =0x%08x\n", offset, value); -} -EXPORT_SYMBOL_GPL(mite_dump_regs); -#endif - static int __init mite_module_init(void) { return 0; diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 1d72149db918..bcf2f972376e 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -122,11 +122,6 @@ void mite_prep_dma(struct mite_channel *mite_chan, int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_async *async); -#ifdef DEBUG_MITE -void mite_print_chsr(unsigned int chsr); -void mite_dump_regs(struct mite_channel *mite_chan); -#endif - static inline int CHAN_OFFSET(int channel) { return 0x500 + 0x100 * channel; diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 058185292b0d..866e99394b0c 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1063,7 +1063,6 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, printk ("unknown mite interrupt, ack! (ai_mite_status=%08x)\n", ai_mite_status); - /* mite_print_chsr(ai_mite_status); */ s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; /* disable_irq(dev->irq); */ } @@ -1196,7 +1195,6 @@ static void handle_b_interrupt(struct comedi_device *dev, printk ("unknown mite interrupt, ack! (ao_mite_status=%08x)\n", ao_mite_status); - /* mite_print_chsr(ao_mite_status); */ s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; } #endif @@ -2652,7 +2650,6 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (retval) return retval; } - /* mite_dump_regs(devpriv->mite); */ #endif switch (cmd->start_src) { diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index b2af28096b32..c7bc23044568 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -413,11 +413,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) m_status = mite_get_status(devpriv->di_mite_chan); -#ifdef MITE_DEBUG - mite_print_chsr(m_status); -#endif - /* mite_dump_regs(mite); */ if (m_status & CHSR_INT) { if (m_status & CHSR_LINKC) { writel(CHOR_CLRLC, -- cgit v1.2.3 From 220edb916680102048fdc6a2eda980240bda9cac Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:18 -0700 Subject: staging: comedi: cb_pcidas64: remove DEBUG_PRINT The DEBUG_PRINT macro in this driver is used to output development debug tracing messages. These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcidas64.c | 126 +-------------------------- 1 file changed, 3 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index ff5206536be3..a0053bbb2ede 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -94,15 +94,6 @@ TODO: #include "plx9080.h" #include "comedi_fc.h" -#undef PCIDAS64_DEBUG /* disable debugging code */ -/* #define PCIDAS64_DEBUG enable debugging code */ - -#ifdef PCIDAS64_DEBUG -#define DEBUG_PRINT(format, args...) pr_debug(format, ## args) -#else -#define DEBUG_PRINT(format, args...) no_printk(format, ## args) -#endif - #define TIMER_BASE 25 /* 40MHz master clock */ /* 100kHz 'prescaled' clock for slow acquisition, * maybe I'll support this someday */ @@ -1252,8 +1243,6 @@ static void disable_ai_interrupts(struct comedi_device *dev) writew(devpriv->intr_enable_bits, devpriv->main_iobase + INTR_ENABLE_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - - DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits); } static void enable_ai_interrupts(struct comedi_device *dev, @@ -1277,7 +1266,6 @@ static void enable_ai_interrupts(struct comedi_device *dev, devpriv->intr_enable_bits |= bits; writew(devpriv->intr_enable_bits, devpriv->main_iobase + INTR_ENABLE_REG); - DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits); spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -1292,38 +1280,6 @@ static void init_plx9080(struct comedi_device *dev) devpriv->plx_control_bits = readl(devpriv->plx9080_iobase + PLX_CONTROL_REG); - /* plx9080 dump */ - DEBUG_PRINT(" plx interrupt status 0x%x\n", - readl(plx_iobase + PLX_INTRCS_REG)); - DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG)); - DEBUG_PRINT(" plx control reg 0x%x\n", devpriv->plx_control_bits); - DEBUG_PRINT(" plx mode/arbitration reg 0x%x\n", - readl(plx_iobase + PLX_MARB_REG)); - DEBUG_PRINT(" plx region0 reg 0x%x\n", - readl(plx_iobase + PLX_REGION0_REG)); - DEBUG_PRINT(" plx region1 reg 0x%x\n", - readl(plx_iobase + PLX_REGION1_REG)); - - DEBUG_PRINT(" plx revision 0x%x\n", - readl(plx_iobase + PLX_REVISION_REG)); - DEBUG_PRINT(" plx dma channel 0 mode 0x%x\n", - readl(plx_iobase + PLX_DMA0_MODE_REG)); - DEBUG_PRINT(" plx dma channel 1 mode 0x%x\n", - readl(plx_iobase + PLX_DMA1_MODE_REG)); - DEBUG_PRINT(" plx dma channel 0 pci address 0x%x\n", - readl(plx_iobase + PLX_DMA0_PCI_ADDRESS_REG)); - DEBUG_PRINT(" plx dma channel 0 local address 0x%x\n", - readl(plx_iobase + PLX_DMA0_LOCAL_ADDRESS_REG)); - DEBUG_PRINT(" plx dma channel 0 transfer size 0x%x\n", - readl(plx_iobase + PLX_DMA0_TRANSFER_SIZE_REG)); - DEBUG_PRINT(" plx dma channel 0 descriptor 0x%x\n", - readl(plx_iobase + PLX_DMA0_DESCRIPTOR_REG)); - DEBUG_PRINT(" plx dma channel 0 command status 0x%x\n", - readb(plx_iobase + PLX_DMA0_CS_REG)); - DEBUG_PRINT(" plx dma channel 0 threshold 0x%x\n", - readl(plx_iobase + PLX_DMA0_THRESHOLD_REG)); - DEBUG_PRINT(" plx bigend 0x%x\n", readl(plx_iobase + PLX_BIGEND_REG)); - #ifdef __BIG_ENDIAN bits = BIGEND_DMA0 | BIGEND_DMA1; #else @@ -1417,9 +1373,6 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev, devpriv->ai_fifo_segment_length = num_increments * increment_size; - DEBUG_PRINT("set hardware fifo segment length to %i\n", - devpriv->ai_fifo_segment_length); - return devpriv->ai_fifo_segment_length; } @@ -1441,8 +1394,6 @@ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) num_samples = retval * fifo->num_segments * fifo->sample_packing_ratio; - DEBUG_PRINT("set hardware fifo size to %i\n", num_samples); - return num_samples; } @@ -1538,8 +1489,6 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) if (devpriv->ai_dma_desc == NULL) return -ENOMEM; - DEBUG_PRINT("ai dma descriptors start at bus addr 0x%llx\n", - (unsigned long long)devpriv->ai_dma_desc_bus_addr); if (ao_cmd_is_supported(thisboard)) { devpriv->ao_dma_desc = pci_alloc_consistent(pcidev, @@ -1548,9 +1497,6 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) &devpriv->ao_dma_desc_bus_addr); if (devpriv->ao_dma_desc == NULL) return -ENOMEM; - - DEBUG_PRINT("ao dma descriptors start at bus addr 0x%llx\n", - (unsigned long long)devpriv->ao_dma_desc_bus_addr); } /* initialize dma descriptors */ for (i = 0; i < ai_dma_ring_count(thisboard); i++) { @@ -1650,8 +1596,6 @@ static void i2c_write_byte(struct comedi_device *dev, uint8_t byte) uint8_t bit; unsigned int num_bits = 8; - DEBUG_PRINT("writing to i2c byte 0x%x\n", byte); - for (bit = 1 << (num_bits - 1); bit; bit >>= 1) { i2c_set_scl(dev, 0); if ((byte & bit)) @@ -1738,7 +1682,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long flags; static const int timeout = 100; - DEBUG_PRINT("chanspec 0x%x\n", insn->chanspec); channel = CR_CHAN(insn->chanspec); range = CR_RANGE(insn->chanspec); aref = CR_AREF(insn->chanspec); @@ -1766,7 +1709,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, if (insn->chanspec & CR_ALT_SOURCE) { unsigned int cal_en_bit; - DEBUG_PRINT("reading calibration source\n"); if (thisboard->layout == LAYOUT_60XX) cal_en_bit = CAL_EN_60XX_BIT; else @@ -1800,7 +1742,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK; if (insn->chanspec & CR_ALT_SOURCE) { - DEBUG_PRINT("reading calibration source\n"); devpriv->i2c_cal_range_bits |= adc_src_4020_bits(devpriv->calibration_source); } else { /* select BNC inputs */ @@ -1839,7 +1780,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, /* wait for data */ for (i = 0; i < timeout; i++) { bits = readw(devpriv->main_iobase + HW_STATUS_REG); - DEBUG_PRINT(" pipe bits 0x%x\n", pipe_full_bits(bits)); if (thisboard->layout == LAYOUT_4020) { if (readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG)) @@ -1850,7 +1790,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } udelay(1); } - DEBUG_PRINT(" looped %i times waiting for data\n", i); if (i == timeout) { comedi_error(dev, " analog input read insn timed out"); dev_info(dev->class_dev, "status 0x%x\n", bits); @@ -1884,7 +1823,6 @@ static int ai_config_calibration_source(struct comedi_device *dev, return -EINVAL; } - DEBUG_PRINT("setting calibration source to %i\n", source); devpriv->calibration_source = source; return 2; @@ -2368,7 +2306,6 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) /* load lower 16 bits of convert interval */ writew(convert_counter & 0xffff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); - DEBUG_PRINT("convert counter 0x%x\n", convert_counter); /* load upper 8 bits of convert interval */ writew((convert_counter >> 16) & 0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); @@ -2378,7 +2315,6 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) /* load upper 8 bits of scan delay */ writew((scan_counter >> 16) & 0xff, devpriv->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG); - DEBUG_PRINT("scan counter 0x%x\n", scan_counter); } static int use_internal_queue_6xxx(const struct comedi_cmd *cmd) @@ -2469,9 +2405,6 @@ static int setup_channel_queue(struct comedi_device *dev, writew(bits, devpriv->main_iobase + ADC_QUEUE_FIFO_REG); - DEBUG_PRINT( - "wrote 0x%x to external channel queue\n", - bits); } /* doing a queue clear is not specified in board docs, * but required for reliable operation */ @@ -2593,7 +2526,6 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } writew(devpriv->adc_control1_bits, devpriv->main_iobase + ADC_CONTROL1_REG); - DEBUG_PRINT("control1 bits 0x%x\n", devpriv->adc_control1_bits); spin_unlock_irqrestore(&dev->spinlock, flags); /* clear adc buffer */ @@ -2645,17 +2577,14 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (use_hw_sample_counter(cmd)) bits |= ADC_SAMPLE_COUNTER_EN_BIT; writew(bits, devpriv->main_iobase + ADC_CONTROL0_REG); - DEBUG_PRINT("control0 bits 0x%x\n", bits); devpriv->ai_cmd_running = 1; spin_unlock_irqrestore(&dev->spinlock, flags); /* start acquisition */ - if (cmd->start_src == TRIG_NOW) { + if (cmd->start_src == TRIG_NOW) writew(0, devpriv->main_iobase + ADC_START_REG); - DEBUG_PRINT("soft trig\n"); - } return 0; } @@ -2690,10 +2619,6 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) read_segment = adc_upper_read_ptr_code(prepost_bits); write_segment = adc_upper_write_ptr_code(prepost_bits); - DEBUG_PRINT(" rd seg %i, wrt seg %i, rd idx %i, wrt idx %i\n", - read_segment, write_segment, read_index, - write_index); - if (read_segment != write_segment) num_samples = devpriv->ai_fifo_segment_length - read_index; @@ -2715,8 +2640,6 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) break; } - DEBUG_PRINT(" read %i samples from fifo\n", num_samples); - for (i = 0; i < num_samples; i++) { cfc_write_to_buffer(s, readw(devpriv->main_iobase + @@ -2812,11 +2735,6 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) num_samples * sizeof(uint16_t)); devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) % ai_dma_ring_count(thisboard); - - DEBUG_PRINT("next buffer addr 0x%lx\n", - (unsigned long)devpriv-> - ai_buffer_bus_addr[devpriv->ai_dma_index]); - DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr); } /* XXX check for dma ring buffer overrun * (use end-of-chain bit to mark last unused buffer) */ @@ -2845,24 +2763,17 @@ static void handle_ai_interrupt(struct comedi_device *dev, if (plx_status & ICS_DMA1_A) { /* dma chan 1 interrupt */ writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_iobase + PLX_DMA1_CS_REG); - DEBUG_PRINT("dma1 status 0x%x\n", dma1_status); if (dma1_status & PLX_DMA_EN_BIT) drain_dma_buffers(dev, 1); - - DEBUG_PRINT(" cleared dma ch1 interrupt\n"); } spin_unlock_irqrestore(&dev->spinlock, flags); - if (status & ADC_DONE_BIT) - DEBUG_PRINT("adc done interrupt\n"); - /* drain fifo with pio */ if ((status & ADC_DONE_BIT) || ((cmd->flags & TRIG_WAKE_EOS) && (status & ADC_INTR_PENDING_BIT) && (thisboard->layout != LAYOUT_4020))) { - DEBUG_PRINT("pio fifo drain\n"); spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->ai_cmd_running) { spin_unlock_irqrestore(&dev->spinlock, flags); @@ -2947,7 +2858,6 @@ static void restart_ao_dma(struct comedi_device *dev) dma_desc_bits = readl(devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG); dma_desc_bits &= ~PLX_END_OF_CHAIN_BIT; - DEBUG_PRINT("restarting ao dma, descriptor reg 0x%x\n", dma_desc_bits); load_first_dma_descriptor(dev, 0, dma_desc_bits); dma_start_sync(dev, 0); @@ -2963,10 +2873,6 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev, buffer_index = devpriv->ao_dma_index; prev_buffer_index = prev_ao_dma_index(dev); - DEBUG_PRINT("attempting to load ao buffer %i (0x%llx)\n", buffer_index, - (unsigned long long)devpriv->ao_buffer_bus_addr[ - buffer_index]); - num_bytes = comedi_buf_read_n_available(dev->write_subdev->async); if (num_bytes > DMA_BUFFER_SIZE) num_bytes = DMA_BUFFER_SIZE; @@ -2977,8 +2883,6 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev, if (num_bytes == 0) return 0; - DEBUG_PRINT("loading %i bytes\n", num_bytes); - num_bytes = cfc_read_array_from_buffer(dev->write_subdev, devpriv-> ao_buffer[buffer_index], @@ -3052,14 +2956,12 @@ static void handle_ao_interrupt(struct comedi_device *dev, writeb(PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_iobase + PLX_DMA0_CS_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - DEBUG_PRINT("dma0 status 0x%x\n", dma0_status); if (dma0_status & PLX_DMA_EN_BIT) { load_ao_dma(dev, cmd); /* try to recover from dma end-of-chain event */ if (ao_dma_needs_restart(dev, dma0_status)) restart_ao_dma(dev); } - DEBUG_PRINT(" cleared dma ch0 interrupt\n"); } else { spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -3068,12 +2970,6 @@ static void handle_ao_interrupt(struct comedi_device *dev, async->events |= COMEDI_CB_EOA; if (ao_stopped_by_error(dev, cmd)) async->events |= COMEDI_CB_ERROR; - DEBUG_PRINT("plx dma0 desc reg 0x%x\n", - readl(devpriv->plx9080_iobase + - PLX_DMA0_DESCRIPTOR_REG)); - DEBUG_PRINT("plx dma0 address reg 0x%x\n", - readl(devpriv->plx9080_iobase + - PLX_DMA0_PCI_ADDRESS_REG)); } cfc_handle_events(dev, s); } @@ -3089,15 +2985,12 @@ static irqreturn_t handle_interrupt(int irq, void *d) plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG); status = readw(devpriv->main_iobase + HW_STATUS_REG); - DEBUG_PRINT("hw status 0x%x, plx status 0x%x\n", status, plx_status); - /* an interrupt before all the postconfig stuff gets done could * cause a NULL dereference if we continue through the * interrupt handler */ - if (!dev->attached) { - DEBUG_PRINT("premature interrupt, ignoring\n"); + if (!dev->attached) return IRQ_HANDLED; - } + handle_ai_interrupt(dev, status, plx_status); handle_ao_interrupt(dev, status, plx_status); @@ -3105,11 +2998,8 @@ static irqreturn_t handle_interrupt(int irq, void *d) if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */ plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG); writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG); - DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits); } - DEBUG_PRINT("exiting handler\n"); - return IRQ_HANDLED; } @@ -3130,7 +3020,6 @@ static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) abort_dma(dev, 1); - DEBUG_PRINT("ai canceled\n"); return 0; } @@ -3458,7 +3347,6 @@ static int dio_callback(int dir, int port, int data, unsigned long arg) void __iomem *iobase = (void __iomem *)arg; if (dir) { writeb(data, iobase + port); - DEBUG_PRINT("wrote 0x%x to port %i\n", data, port); return 0; } else { return readb(iobase + port); @@ -4046,11 +3934,6 @@ static int auto_attach(struct comedi_device *dev, return -ENOMEM; } - DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase); - DEBUG_PRINT(" main remapped to 0x%p\n", devpriv->main_iobase); - DEBUG_PRINT(" diocounter remapped to 0x%p\n", - devpriv->dio_counter_iobase); - /* figure out what local addresses are */ local_range = readl(devpriv->plx9080_iobase + PLX_LAS0RNG_REG) & LRNG_MEM_MASK; @@ -4065,9 +3948,6 @@ static int auto_attach(struct comedi_device *dev, devpriv->local1_iobase = ((uint32_t)devpriv->dio_counter_phys_iobase & ~local_range) | local_decode; - DEBUG_PRINT(" local 0 io addr 0x%x\n", devpriv->local0_iobase); - DEBUG_PRINT(" local 1 io addr 0x%x\n", devpriv->local1_iobase); - retval = alloc_and_init_dma_members(dev); if (retval < 0) return retval; -- cgit v1.2.3 From f1bea9cf516135b40d3e9d71310a832cd7069868 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:19 -0700 Subject: staging: comedi: gsc_hpdi: remove DEBUG_PRINT The DEBUG_PRINT macro in this driver is used to output development debug tracing messages. These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/gsc_hpdi.c | 78 ------------------------------- 1 file changed, 78 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 559bf5583530..4fcf3c876ac9 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -60,15 +60,6 @@ static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static irqreturn_t handle_interrupt(int irq, void *d); static int dio_config_block_size(struct comedi_device *dev, unsigned int *data); -#undef HPDI_DEBUG /* disable debugging messages */ -/* #define HPDI_DEBUG enable debugging code */ - -#ifdef HPDI_DEBUG -#define DEBUG_PRINT(format, args...) pr_debug(format , ## args) -#else -#define DEBUG_PRINT(format, args...) no_printk(pr_fmt(format), ## args) -#endif - #define TIMER_BASE 50 /* 20MHz master clock */ #define DMA_BUFFER_SIZE 0x10000 #define NUM_DMA_BUFFERS 4 @@ -260,32 +251,6 @@ static void init_plx9080(struct comedi_device *dev) uint32_t bits; void __iomem *plx_iobase = devpriv->plx9080_iobase; - /* plx9080 dump */ - DEBUG_PRINT(" plx interrupt status 0x%x\n", - readl(plx_iobase + PLX_INTRCS_REG)); - DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG)); - DEBUG_PRINT(" plx control reg 0x%x\n", - readl(devpriv->plx9080_iobase + PLX_CONTROL_REG)); - - DEBUG_PRINT(" plx revision 0x%x\n", - readl(plx_iobase + PLX_REVISION_REG)); - DEBUG_PRINT(" plx dma channel 0 mode 0x%x\n", - readl(plx_iobase + PLX_DMA0_MODE_REG)); - DEBUG_PRINT(" plx dma channel 1 mode 0x%x\n", - readl(plx_iobase + PLX_DMA1_MODE_REG)); - DEBUG_PRINT(" plx dma channel 0 pci address 0x%x\n", - readl(plx_iobase + PLX_DMA0_PCI_ADDRESS_REG)); - DEBUG_PRINT(" plx dma channel 0 local address 0x%x\n", - readl(plx_iobase + PLX_DMA0_LOCAL_ADDRESS_REG)); - DEBUG_PRINT(" plx dma channel 0 transfer size 0x%x\n", - readl(plx_iobase + PLX_DMA0_TRANSFER_SIZE_REG)); - DEBUG_PRINT(" plx dma channel 0 descriptor 0x%x\n", - readl(plx_iobase + PLX_DMA0_DESCRIPTOR_REG)); - DEBUG_PRINT(" plx dma channel 0 command status 0x%x\n", - readb(plx_iobase + PLX_DMA0_CS_REG)); - DEBUG_PRINT(" plx dma channel 0 threshold 0x%x\n", - readl(plx_iobase + PLX_DMA0_THRESHOLD_REG)); - DEBUG_PRINT(" plx bigend 0x%x\n", readl(plx_iobase + PLX_BIGEND_REG)); #ifdef __BIG_ENDIAN bits = BIGEND_DMA0 | BIGEND_DMA1; #else @@ -395,10 +360,6 @@ static int setup_dma_descriptors(struct comedi_device *dev, if (transfer_size == 0) return -1; - DEBUG_PRINT(" transfer_size %i\n", transfer_size); - DEBUG_PRINT(" descriptors at 0x%lx\n", - (unsigned long)devpriv->dma_desc_phys_addr); - buffer_offset = 0; buffer_index = 0; for (i = 0; i < NUM_DMA_DESCRIPTORS && @@ -423,21 +384,11 @@ static int setup_dma_descriptors(struct comedi_device *dev, buffer_offset = 0; buffer_index++; } - - DEBUG_PRINT(" desc %i\n", i); - DEBUG_PRINT(" start addr virt 0x%p, phys 0x%lx\n", - devpriv->desc_dio_buffer[i], - (unsigned long)devpriv->dma_desc[i]. - pci_start_addr); - DEBUG_PRINT(" next 0x%lx\n", - (unsigned long)devpriv->dma_desc[i].next); } devpriv->num_dma_descriptors = i; /* fix last descriptor to point back to first */ devpriv->dma_desc[i - 1].next = cpu_to_le32(devpriv->dma_desc_phys_addr | next_bits); - DEBUG_PRINT(" desc %i next fixup 0x%lx\n", i - 1, - (unsigned long)devpriv->dma_desc[i - 1].next); devpriv->block_size = transfer_size; @@ -489,9 +440,6 @@ static int hpdi_auto_attach(struct comedi_device *dev, return -ENOMEM; } - DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase); - DEBUG_PRINT(" hpdi remapped to 0x%p\n", devpriv->hpdi_iobase); - init_plx9080(dev); /* get irq */ @@ -510,9 +458,6 @@ static int hpdi_auto_attach(struct comedi_device *dev, devpriv->dio_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, &devpriv->dio_buffer_phys_addr[i]); - DEBUG_PRINT("dio_buffer at virt 0x%p, phys 0x%lx\n", - devpriv->dio_buffer[i], - (unsigned long)devpriv->dio_buffer_phys_addr[i]); } /* allocate dma descriptors */ devpriv->dma_desc = pci_alloc_consistent(pcidev, @@ -687,8 +632,6 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s) hpdi_writel(dev, RX_FIFO_RESET_BIT, BOARD_CONTROL_REG); - DEBUG_PRINT("hpdi: in di_cmd\n"); - abort_dma(dev, 0); devpriv->dma_desc_index = 0; @@ -725,7 +668,6 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writel(intr_bit(RX_FULL_INTR), devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG); - DEBUG_PRINT("hpdi: starting rx\n"); hpdi_writel(dev, RX_ENABLE_BIT, BOARD_CONTROL_REG); return 0; @@ -778,11 +720,6 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) num_samples * sizeof(uint32_t)); devpriv->dma_desc_index++; devpriv->dma_desc_index %= devpriv->num_dma_descriptors; - - DEBUG_PRINT("next desc addr 0x%lx\n", (unsigned long) - devpriv->dma_desc[devpriv->dma_desc_index]. - next); - DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr); } /* XXX check for buffer overrun somehow */ } @@ -812,7 +749,6 @@ static irqreturn_t handle_interrupt(int irq, void *d) async->events = 0; if (hpdi_intr_status) { - DEBUG_PRINT("hpdi: intr status 0x%x, ", hpdi_intr_status); writel(hpdi_intr_status, devpriv->hpdi_iobase + INTERRUPT_STATUS_REG); } @@ -823,10 +759,8 @@ static irqreturn_t handle_interrupt(int irq, void *d) writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_iobase + PLX_DMA0_CS_REG); - DEBUG_PRINT("dma0 status 0x%x\n", dma0_status); if (dma0_status & PLX_DMA_EN_BIT) drain_dma_buffers(dev, 0); - DEBUG_PRINT(" cleared dma ch0 interrupt\n"); } spin_unlock_irqrestore(&dev->spinlock, flags); @@ -836,9 +770,6 @@ static irqreturn_t handle_interrupt(int irq, void *d) if (plx_status & ICS_DMA1_A) { /* XXX *//* dma chan 1 interrupt */ writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_iobase + PLX_DMA1_CS_REG); - DEBUG_PRINT("dma1 status 0x%x\n", dma1_status); - - DEBUG_PRINT(" cleared dma ch1 interrupt\n"); } spin_unlock_irqrestore(&dev->spinlock, flags); @@ -846,15 +777,11 @@ static irqreturn_t handle_interrupt(int irq, void *d) if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */ plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG); writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG); - DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits); } if (hpdi_board_status & RX_OVERRUN_BIT) { comedi_error(dev, "rx fifo overrun"); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - DEBUG_PRINT("dma0_status 0x%x\n", - (int)readb(devpriv->plx9080_iobase + - PLX_DMA0_CS_REG)); } if (hpdi_board_status & RX_UNDERRUN_BIT) { @@ -865,11 +792,6 @@ static irqreturn_t handle_interrupt(int irq, void *d) if (devpriv->dio_count == 0) async->events |= COMEDI_CB_EOA; - DEBUG_PRINT("board status 0x%x, ", hpdi_board_status); - DEBUG_PRINT("plx status 0x%x\n", plx_status); - if (async->events) - DEBUG_PRINT(" events 0x%x\n", async->events); - cfc_handle_events(dev, s); return IRQ_HANDLED; -- cgit v1.2.3 From 05d701b169411c32c89d4bea92c876d5c63f2e04 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:20 -0700 Subject: staging: comedi: ni_at_a2150: remove A2150_DEBUG The A2150_DEBUG define enables some development messages, specifically the ni_dum_regs() function. These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_at_a2150.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 63c847932eb8..cc69ddef0a67 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -74,9 +74,6 @@ TRIG_WAKE_EOS #define A2150_SIZE 28 #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */ -/* #define A2150_DEBUG enable debugging code */ -#undef A2150_DEBUG /* disable debugging code */ - /* Registers and bits */ #define CONFIG_REG 0x0 #define CHANNEL_BITS(x) ((x) & 0x7) @@ -167,19 +164,6 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, static int a2150_set_chanlist(struct comedi_device *dev, unsigned int start_channel, unsigned int num_channels); -#ifdef A2150_DEBUG - -static void ni_dump_regs(struct comedi_device *dev) -{ - struct a2150_private *devpriv = dev->private; - - printk("config bits 0x%x\n", devpriv->config_bits); - printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits); - printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG)); -} - -#endif - /* interrupt service routine */ static irqreturn_t a2150_interrupt(int irq, void *d) { @@ -506,9 +490,6 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* start acquisition for soft trigger */ if (cmd->start_src == TRIG_NOW) outw(0, dev->iobase + FIFO_START_REG); -#ifdef A2150_DEBUG - ni_dump_regs(dev); -#endif return 0; } @@ -573,13 +554,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, comedi_error(dev, "timeout"); return -ETIME; } -#ifdef A2150_DEBUG - ni_dump_regs(dev); -#endif data[n] = inw(dev->iobase + FIFO_DATA_REG); -#ifdef A2150_DEBUG - printk(" data is %i\n", data[n]); -#endif data[n] ^= 0x8000; } -- cgit v1.2.3 From f80f0999316ed037bd5691c3f7631c9d0e32171a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:21 -0700 Subject: staging: comedi: cb_pcimdas: remove CBPCIMDAS_DEBUG This define is not used in the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcimdas.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 30520d4c16a6..b25fa5d6e1e8 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -44,9 +44,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details. #include "plx9052.h" #include "8255.h" -/* #define CBPCIMDAS_DEBUG */ -#undef CBPCIMDAS_DEBUG - /* Registers for the PCIM-DAS1602/16 */ /* sizes of io regions (bytes) */ -- cgit v1.2.3 From f27fc3406bd8f8148b6eb838f5ee2a8841024229 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:22 -0700 Subject: staging: comedi: ni_pcimio: remove PCI_DEBUG This define is not used in the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcimio.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 536be83af549..aa002b275458 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -116,8 +116,6 @@ Bugs: #include "ni_stc.h" #include "mite.h" -/* #define PCI_DEBUG */ - #define PCIDMA #define PCIMIO 1 -- cgit v1.2.3 From 4bb82d647dad7be06341ffdb9f07a56a387e213f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:23 -0700 Subject: staging: comedi: pcmmio: remove DAMMIT_ITS_BROKEN debug These debug messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmmio.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 14cee3ac92c5..1ebc9d2df67d 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -250,11 +250,6 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ -#ifdef DAMMIT_ITS_BROKEN - /* DEBUG */ - printk(KERN_DEBUG "write mask: %08x data: %08x\n", data[0], data[1]); -#endif - s->state = 0; for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { @@ -271,14 +266,6 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, byte = inb(ioaddr); /* read all 8-bits for this port */ -#ifdef DAMMIT_ITS_BROKEN - /* DEBUG */ - printk - (KERN_DEBUG "byte %d wmb %02x db %02x offset %02d io %04x," - " data_in %02x ", byte_no, (unsigned)write_mask_byte, - (unsigned)data_byte, offset, ioaddr, (unsigned)byte); -#endif - if (write_mask_byte) { /* * this byte has some write_bits @@ -291,10 +278,6 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, /* Write out the new digital output state */ outb(byte, ioaddr); } -#ifdef DAMMIT_ITS_BROKEN - /* DEBUG */ - printk(KERN_DEBUG "data_out_byte %02x\n", (unsigned)byte); -#endif /* save the digital input lines for this byte.. */ s->state |= ((unsigned int)byte) << offset; } @@ -302,11 +285,6 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, /* now return the DIO lines to data[1] - note they came inverted! */ data[1] = ~s->state; -#ifdef DAMMIT_ITS_BROKEN - /* DEBUG */ - printk(KERN_DEBUG "s->state %08x data_out %08x\n", s->state, data[1]); -#endif - return insn->n; } -- cgit v1.2.3 From 733cde0ef1c2b8a44ab32c27b9f0c508a2e6c67f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:24 -0700 Subject: staging: comedi: pcmmio: remove commented out debug code Remove the commented out code in init_asics() that enables the rising edge interrupts on port0 of both asics. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmmio.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 1ebc9d2df67d..6da836e8caf1 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -357,13 +357,6 @@ static void init_asics(struct comedi_device *dev) outb(0, baseaddr + reg); } - /* DEBUG set rising edge interrupts on port0 of both asics */ - /*switch_page(dev, asic, PAGE_POL); - outb(0xff, baseaddr + REG_POL0); - switch_page(dev, asic, PAGE_ENAB); - outb(0xff, baseaddr + REG_ENAB0); */ - /* END DEBUG */ - /* switch back to default page 0 */ switch_page(dev, asic, 0); } -- cgit v1.2.3 From 4ced969ac63118fa4efdc367aef08215488f1eb0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:25 -0700 Subject: staging: comedi: dyna_pci10xx: convert a KERN_DEBUG message to dev_dbg() Convert a printk(KERN_DEBUG ... message to dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dyna_pci10xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index f2a9f1c2f3b6..9b1f196dbbc8 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -90,8 +90,7 @@ static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev, goto conv_finish; } data[n] = 0; - printk(KERN_DEBUG "comedi: dyna_pci10xx: " - "timeout reading analog input\n"); + dev_dbg(dev->class_dev, "timeout reading analog input\n"); continue; conv_finish: /* mask the first 4 bits - EOC bits */ -- cgit v1.2.3 From c4815b3d2cf43b9136e356839ed71847ad042b65 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:26 -0700 Subject: staging: comedi: pcmmio: convert a KERN_DEBUG message to dev_dbg() Convert a printk(KERN_DEBUG ... message to dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmmio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 6da836e8caf1..063496d6c00e 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -476,9 +476,9 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) * TODO here: dispatch io lines to subdevs * with commands.. */ - printk - (KERN_DEBUG "got edge detect interrupt %d asic %d which_chans: %06x\n", - irq, asic, triggered); + dev_dbg(dev->class_dev, + "got edge detect interrupt %d asic %d which_chans: %06x\n", + irq, asic, triggered); for (i = 2; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; /* -- cgit v1.2.3 From d59e3c2473fd451577aea192be741e1a2bdb4c2b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:27 -0700 Subject: staging: comedi: c6xdigio: remove unnecessary c6xdigio_pwmo_insn_read() The pwm subdevice in this driver sets the subdev_flags to SDF_WRITEABLE so the s->insn_read callback is not needed. Since this callback simply outputs a printk(KERN_DEBUG ... message jsut remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/c6xdigio.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 217aa19cdc32..a85b9493071f 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -322,14 +322,6 @@ static void C6X_encResetAll(unsigned long baseAddr) } } -static int c6xdigio_pwmo_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - printk(KERN_DEBUG "c6xdigio_pwmo_insn_read %x\n", insn->n); - return insn->n; -} - static int c6xdigio_pwmo_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -426,7 +418,6 @@ static int c6xdigio_attach(struct comedi_device *dev, s->subdev_flags = SDF_WRITEABLE; s->n_chan = 2; /* s->trig[0] = c6xdigio_pwmo; */ - s->insn_read = c6xdigio_pwmo_insn_read; s->insn_write = c6xdigio_pwmo_insn_write; s->maxdata = 500; s->range_table = &range_bipolar10; /* A suitable lie */ -- cgit v1.2.3 From c9001543fbaf04787324dd1f63444c6507da2d60 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:28 -0700 Subject: staging: comedi: dt2814: remove disabled irq probe code The irq probe code in dt2814_attach() is disabled by an #if 0 block. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2814.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 6514b9e00552..4b4147833843 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -256,26 +256,6 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) i = inb(dev->iobase + DT2814_DATA); irq = it->options[1]; -#if 0 - if (irq < 0) { - save_flags(flags); - sti(); - irqs = probe_irq_on(); - - outb(0, dev->iobase + DT2814_CSR); - - udelay(100); - - irq = probe_irq_off(irqs); - restore_flags(flags); - if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) - printk(KERN_DEBUG "error probing irq (bad)\n"); - - - i = inb(dev->iobase + DT2814_DATA); - i = inb(dev->iobase + DT2814_DATA); - } -#endif dev->irq = 0; if (irq > 0) { if (request_irq(irq, dt2814_interrupt, 0, "dt2814", dev)) { @@ -286,12 +266,6 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } else if (irq == 0) { printk(KERN_WARNING "(no irq)\n"); - } else { -#if 0 - printk(KERN_DEBUG "(probe returned multiple irqs--bad)\n"); -#else - printk(KERN_WARNING "(irq probe not implemented)\n"); -#endif } ret = comedi_alloc_subdevices(dev, 1); -- cgit v1.2.3 From 7567e83039598af34b867a9b4abef1a0d90f7381 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:29 -0700 Subject: staging: comedi: pcl818: remove an unnecessary printk(KERN_DEBUG ... This debug message is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 8b5e9c097349..be9cb8df877d 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1257,8 +1257,6 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) (", unable to allocate IRQ %u, DISABLING IT", irq); irq = 0; /* Can't use IRQ */ - } else { - printk(KERN_DEBUG "irq=%u", irq); } } } -- cgit v1.2.3 From 7f95741d6f627a5af0e97b4924de9c85877ac458 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:30 -0700 Subject: staging: comedi: dmm32at: remove some unnecessary printk(KERN_DEBUG ... These debug messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index b04a5633f754..cac83585ef86 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -723,12 +723,6 @@ static int dmm32at_attach(struct comedi_device *dev, intstat = inb(dev->iobase + DMM32AT_INTCLOCK); airback = inb(dev->iobase + DMM32AT_AIRBACK); - printk(KERN_DEBUG "dmm32at: lo=0x%02x hi=0x%02x fifostat=0x%02x\n", - ailo, aihi, fifostat); - printk(KERN_DEBUG - "dmm32at: aistat=0x%02x intstat=0x%02x airback=0x%02x\n", - aistat, intstat, airback); - if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) || (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) { printk(KERN_ERR "dmmat32: board detection failed\n"); -- cgit v1.2.3 From d316d2aba099b455c30894eb78344e59b23a1367 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:31 -0700 Subject: staging: comedi: ni_mio_common: remove unused NI_CS5529_DEBUG code The code blocked by #ifdef NI_CS5529_DEBUG is not used by the driver. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 30 -------------------------- 1 file changed, 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 866e99394b0c..f44013c8097b 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -318,10 +318,6 @@ static int cs5529_do_conversion(struct comedi_device *dev, static int cs5529_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -#ifdef NI_CS5529_DEBUG -static unsigned int cs5529_config_read(struct comedi_device *dev, - unsigned int reg_select_bits); -#endif static void cs5529_config_write(struct comedi_device *dev, unsigned int value, unsigned int reg_select_bits); @@ -5856,25 +5852,6 @@ static void cs5529_config_write(struct comedi_device *dev, unsigned int value, comedi_error(dev, "time or signal in cs5529_config_write()"); } -#ifdef NI_CS5529_DEBUG -/* read from cs5529 register */ -static unsigned int cs5529_config_read(struct comedi_device *dev, - unsigned int reg_select_bits) -{ - unsigned int value; - - reg_select_bits &= CSCMD_REGISTER_SELECT_MASK; - cs5529_command(dev, CSCMD_COMMAND | CSCMD_READ | reg_select_bits); - if (cs5529_wait_for_idle(dev)) - comedi_error(dev, "timeout or signal in cs5529_config_read()"); - value = (ni_ao_win_inw(dev, - CAL_ADC_Config_Data_High_Word_67xx) << 16) & - 0xff0000; - value |= ni_ao_win_inw(dev, CAL_ADC_Config_Data_Low_Word_67xx) & 0xffff; - return value; -} -#endif - static int cs5529_do_conversion(struct comedi_device *dev, unsigned short *data) { int retval; @@ -5950,13 +5927,6 @@ static int init_cs5529(struct comedi_device *dev) CSCMD_CONFIG_REGISTER); if (cs5529_wait_for_idle(dev)) comedi_error(dev, "timeout or signal in init_cs5529()\n"); -#endif -#ifdef NI_CS5529_DEBUG - printk("config: 0x%x\n", cs5529_config_read(dev, - CSCMD_CONFIG_REGISTER)); - printk("gain: 0x%x\n", cs5529_config_read(dev, CSCMD_GAIN_REGISTER)); - printk("offset: 0x%x\n", cs5529_config_read(dev, - CSCMD_OFFSET_REGISTER)); #endif return 0; } -- cgit v1.2.3 From 9d6a0f6abe05ee1f7d98adcb06758a0d121bc69a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:32 -0700 Subject: staging: comedi: ni_mio_common: remove DEBUG_DIO messages Defining DEBUG_DIO simply enables some function trace messages. These are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index f44013c8097b..4bf0ef2b93d7 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3798,10 +3798,6 @@ static int ni_serial_insn_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_SERIAL_CLOCK: - -#ifdef DEBUG_DIO - printk("SPI serial clock Config cd\n", data[1]); -#endif devpriv->serial_hw_mode = 1; devpriv->dio_control |= DIO_HW_Serial_Enable; @@ -3890,10 +3886,6 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, unsigned int status1; int err = 0, count = 20; -#ifdef DEBUG_DIO - printk("ni_serial_hw_readwrite8: outputting 0x%x\n", data_out); -#endif - devpriv->dio_output &= ~DIO_Serial_Data_Mask; devpriv->dio_output |= DIO_Serial_Data_Out(data_out); devpriv->stc_writew(dev, devpriv->dio_output, DIO_Output_Register); @@ -3927,12 +3919,8 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, DIO_Serial_IO_In_Progress_St goes high one bit too early. */ udelay((devpriv->serial_interval_ns + 999) / 1000); - if (data_in != NULL) { + if (data_in != NULL) *data_in = devpriv->stc_readw(dev, DIO_Serial_Input_Register); -#ifdef DEBUG_DIO - printk("ni_serial_hw_readwrite8: inputted 0x%x\n", *data_in); -#endif - } Error: devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); @@ -3948,10 +3936,6 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, struct ni_private *devpriv = dev->private; unsigned char mask, input = 0; -#ifdef DEBUG_DIO - printk("ni_serial_sw_readwrite8: outputting 0x%x\n", data_out); -#endif - /* Wait for one bit before transfer */ udelay((devpriv->serial_interval_ns + 999) / 1000); @@ -3988,9 +3972,7 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, input |= mask; } } -#ifdef DEBUG_DIO - printk("ni_serial_sw_readwrite8: inputted 0x%x\n", input); -#endif + if (data_in) *data_in = input; -- cgit v1.2.3 From 9af01ca9b91e142958f1f20bee68c272e7ac0ccd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:33 -0700 Subject: staging: comedi: ni_mio_common: remove DEBUG_STATUS_B messages Defining DEBUG_STATUS_B enables dumping of a status register during the interrupt. These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 29 -------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 4bf0ef2b93d7..1ae8f97f07f2 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -54,7 +54,6 @@ /* #define DEBUG_INTERRUPT */ /* #define DEBUG_STATUS_A */ -/* #define DEBUG_STATUS_B */ #include #include @@ -267,11 +266,6 @@ static void ni_mio_print_status_a(int status); #else #define ni_mio_print_status_a(a) #endif -#ifdef DEBUG_STATUS_B -static void ni_mio_print_status_b(int status); -#else -#define ni_mio_print_status_b(a) -#endif static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s); #ifndef PCIDMA @@ -1176,7 +1170,6 @@ static void handle_b_interrupt(struct comedi_device *dev, #ifdef DEBUG_INTERRUPT printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n", b_status, ao_mite_status); - ni_mio_print_status_b(b_status); #endif #ifdef PCIDMA @@ -1247,28 +1240,6 @@ static void ni_mio_print_status_a(int status) } #endif -#ifdef DEBUG_STATUS_B -static const char *const status_b_strings[] = { - "passthru1", "fifo", "G1_gate", "G1_TC", - "UI2_TC", "UPDATE", "UC_TC", "BC_TC", - "start1", "overrun", "start", "bc_tc_error", - "fifo_empty", "fifo_half_full", "fifo_full", "interrupt_b" -}; - -static void ni_mio_print_status_b(int status) -{ - int i; - - printk("B status:"); - for (i = 15; i >= 0; i--) { - if (status & (1 << i)) { - printk(" %s", status_b_strings[i]); - } - } - printk("\n"); -} -#endif - #ifndef PCIDMA static void ni_ao_fifo_load(struct comedi_device *dev, -- cgit v1.2.3 From 957a91418669d84de66f72f470972073992d6d7b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:34 -0700 Subject: staging: comedi: ni_mio_common: remove DEBUG_STATUS_A messages Defining DEBUG_STATUS_A enables dumping of a status register during the interrupt. These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 31 -------------------------- 1 file changed, 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1ae8f97f07f2..2ca37b611a91 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -53,7 +53,6 @@ */ /* #define DEBUG_INTERRUPT */ -/* #define DEBUG_STATUS_A */ #include #include @@ -261,12 +260,6 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s); static int ni_read_eeprom(struct comedi_device *dev, int addr); -#ifdef DEBUG_STATUS_A -static void ni_mio_print_status_a(int status); -#else -#define ni_mio_print_status_a(a) -#endif - static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s); #ifndef PCIDMA static void ni_handle_fifo_half_full(struct comedi_device *dev); @@ -1040,7 +1033,6 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, printk ("ni_mio_common: interrupt: a_status=%04x ai_mite_status=%08x\n", status, ai_mite_status); - ni_mio_print_status_a(status); #endif #ifdef PCIDMA if (ai_mite_status & CHSR_LINKC) { @@ -1077,7 +1069,6 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, AI_SC_TC_Error_St)) { printk("ni_mio_common: ai error a_status=%04x\n", status); - ni_mio_print_status_a(status); shutdown_ai_command(dev); @@ -1218,28 +1209,6 @@ static void handle_b_interrupt(struct comedi_device *dev, ni_event(dev, s); } -#ifdef DEBUG_STATUS_A -static const char *const status_a_strings[] = { - "passthru0", "fifo", "G0_gate", "G0_TC", - "stop", "start", "sc_tc", "start1", - "start2", "sc_tc_error", "overflow", "overrun", - "fifo_empty", "fifo_half_full", "fifo_full", "interrupt_a" -}; - -static void ni_mio_print_status_a(int status) -{ - int i; - - printk("A status:"); - for (i = 15; i >= 0; i--) { - if (status & (1 << i)) { - printk(" %s", status_a_strings[i]); - } - } - printk("\n"); -} -#endif - #ifndef PCIDMA static void ni_ao_fifo_load(struct comedi_device *dev, -- cgit v1.2.3 From d8e1f9619b039fab3405add5cc66d8916b7f7194 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:35 -0700 Subject: staging: comedi: ni_mio_common: remove DEBUG_INTERRUPT messages Defining DEBUG_INTERRUPT enables some function trace messages during the interrupt. These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 2ca37b611a91..65db6add0a68 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -52,8 +52,6 @@ fully tested as yet. Terry Barnaby, BEAM Ltd. */ -/* #define DEBUG_INTERRUPT */ - #include #include #include @@ -1029,11 +1027,6 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, if (s->type == COMEDI_SUBD_UNUSED) return; -#ifdef DEBUG_INTERRUPT - printk - ("ni_mio_common: interrupt: a_status=%04x ai_mite_status=%08x\n", - status, ai_mite_status); -#endif #ifdef PCIDMA if (ai_mite_status & CHSR_LINKC) { ni_sync_ai_dma(dev); @@ -1081,9 +1074,6 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, return; } if (status & AI_SC_TC_St) { -#ifdef DEBUG_INTERRUPT - printk("ni_mio_common: SC_TC interrupt\n"); -#endif if (!devpriv->ai_continuous) { shutdown_ai_command(dev); } @@ -1110,15 +1100,6 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, } ni_event(dev, s); - -#ifdef DEBUG_INTERRUPT - status = devpriv->stc_readw(dev, AI_Status_1_Register); - if (status & Interrupt_A_St) { - printk - ("handle_a_interrupt: didn't clear interrupt? status=0x%x\n", - status); - } -#endif } static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status) @@ -1158,11 +1139,6 @@ static void handle_b_interrupt(struct comedi_device *dev, struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; /* unsigned short ack=0; */ -#ifdef DEBUG_INTERRUPT - printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n", - b_status, ao_mite_status); -#endif - #ifdef PCIDMA /* Currently, mite.c requires us to handle LINKC */ if (ao_mite_status & CHSR_LINKC) { -- cgit v1.2.3 From 931cf48d2db64c67d0e917f55d7db7ab7b9fefa3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 10:21:36 -0700 Subject: staging: comedi: unionxx5: tidy up some dev_{level} messages Remove the "comedi%d:" prefix from the dev_{level} messages. This previx will already be displayed. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/unioxx5.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index d6b75d68a36a..adf7cb7086cc 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -146,8 +146,8 @@ static int __unioxx5_digital_read(struct comedi_subdevice *s, channel_offset = __unioxx5_define_chan_offset(channel); if (channel_offset < 0) { dev_err(csdev, - "comedi%d: undefined channel %d. channel range is 0 .. 23\n", - minor, channel); + "undefined channel %d. channel range is 0 .. 23\n", + channel); return 0; } @@ -174,8 +174,9 @@ static int __unioxx5_analog_read(struct comedi_subdevice *s, /* defining if given module can work on input */ if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) { - dev_err(csdev, "comedi%d: module in position %d with id 0x%02x is for output only", - minor, module_no, usp->usp_module_type[module_no]); + dev_err(csdev, + "module in position %d with id 0x%02x is for output only", + module_no, usp->usp_module_type[module_no]); return 0; } @@ -191,8 +192,7 @@ static int __unioxx5_analog_read(struct comedi_subdevice *s, /* if four bytes readding error occurs - return 0(false) */ if ((control & Rx4CA_ERR_MASK)) { - dev_err(csdev, - "comedi%d: 4 bytes error\n", minor); + dev_err(csdev, "4 bytes error\n"); return 0; } @@ -214,8 +214,9 @@ static int __unioxx5_digital_write(struct comedi_subdevice *s, channel_offset = __unioxx5_define_chan_offset(channel); if (channel_offset < 0) { - dev_err(csdev, "comedi%d: undefined channel %d. channel range is 0 .. 23\n", - minor, channel); + dev_err(csdev, + "undefined channel %d. channel range is 0 .. 23\n", + channel); return 0; } @@ -246,8 +247,9 @@ static int __unioxx5_analog_write(struct comedi_subdevice *s, /* defining if given module can work on output */ if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) { - dev_err(csdev, "comedi%d: module in position %d with id 0x%0x is for input only!\n", - minor, module, usp->usp_module_type[module]); + dev_err(csdev, + "module in position %d with id 0x%0x is for input only!\n", + module, usp->usp_module_type[module]); return 0; } @@ -329,16 +331,15 @@ static int unioxx5_insn_config(struct comedi_device *dev, if (type != MODULE_DIGITAL) { dev_err(dev->class_dev, - "comedi%d: channel configuration accessible only for digital modules\n", - dev->minor); + "channel configuration accessible only for digital modules\n"); return -1; } channel_offset = __unioxx5_define_chan_offset(channel); if (channel_offset < 0) { dev_err(dev->class_dev, - "comedi%d: undefined channel %d. channel range is 0 .. 23\n", - dev->minor, channel); + "undefined channel %d. channel range is 0 .. 23\n", + channel); return -1; } @@ -353,8 +354,7 @@ static int unioxx5_insn_config(struct comedi_device *dev, flags |= mask; break; default: - dev_err(dev->class_dev, - "comedi%d: unknown flag\n", dev->minor); + dev_err(dev->class_dev, "unknown flag\n"); return -1; } -- cgit v1.2.3 From 8b4f49e03901e82898540bd1189333edf9588d74 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 25 Nov 2013 15:51:16 -0800 Subject: drm/i915: split fb allocation and initialization v2 If we use a stolen buffer, our probe callback shouldn't allocate a new buffer; we should re-use the one from the BIOS instead if possible. v2: fix locking (Jesse) Reviewed-by: Chris Wilson Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbdev.c | 62 ++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 895fcb4fbd94..fdb6dc92a7ab 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -57,18 +57,14 @@ static struct fb_ops intelfb_ops = { .fb_debug_leave = drm_fb_helper_debug_leave, }; -static int intelfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) +static int intelfb_alloc(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) { struct intel_fbdev *ifbdev = container_of(helper, struct intel_fbdev, helper); struct drm_device *dev = helper->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct fb_info *info; - struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj; - struct device *device = &dev->pdev->dev; int size, ret; /* we don't do packed 24bpp */ @@ -94,8 +90,6 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out; } - mutex_lock(&dev->struct_mutex); - /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); if (ret) { @@ -103,7 +97,49 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out_unref; } - info = framebuffer_alloc(0, device); + ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); + if (ret) + goto out_unpin; + + return 0; + +out_unpin: + i915_gem_object_unpin(obj); +out_unref: + drm_gem_object_unreference(&obj->base); +out: + return ret; +} + +static int intelfb_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct intel_fbdev *ifbdev = + container_of(helper, struct intel_fbdev, helper); + struct intel_framebuffer *intel_fb = &ifbdev->ifb; + struct drm_device *dev = helper->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct fb_info *info; + struct drm_framebuffer *fb; + struct drm_i915_gem_object *obj; + int size, ret; + + mutex_lock(&dev->struct_mutex); + + if (!intel_fb->obj) { + DRM_ERROR("no BIOS fb, allocating a new one\n"); + ret = intelfb_alloc(helper, sizes); + if (ret) + goto out_unlock; + } else { + sizes->fb_width = intel_fb->base.width; + sizes->fb_height = intel_fb->base.height; + } + + obj = intel_fb->obj; + size = obj->base.size; + + info = framebuffer_alloc(0, &dev->pdev->dev); if (!info) { ret = -ENOMEM; goto out_unpin; @@ -111,10 +147,6 @@ static int intelfb_create(struct drm_fb_helper *helper, info->par = helper; - ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); - if (ret) - goto out_unpin; - fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; @@ -170,17 +202,15 @@ static int intelfb_create(struct drm_fb_helper *helper, fb->width, fb->height, i915_gem_obj_ggtt_offset(obj), obj); - mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unpin: i915_gem_object_unpin(obj); -out_unref: drm_gem_object_unreference(&obj->base); +out_unlock: mutex_unlock(&dev->struct_mutex); -out: return ret; } -- cgit v1.2.3 From 2850b05c9644d0f4c9df6cc77d628d7e0598a0cc Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 26 Nov 2013 11:02:52 -0700 Subject: PCI: mvebu: Drop writes to bridge Secondary Status register There are no writable bits in the secondary status register, only RO and RW1C (write-1-to-clear) bits. The driver never sets any of the RW1C bits, so the status register should always be 0, just remove the set from the write path. Someday the RW1C bits should be copied/cleared directly from registers in the HW. [bhelgaas: changelog tweaks] Signed-off-by: Jason Gunthorpe Signed-off-by: Bjorn Helgaas Acked-by: Jason Cooper --- drivers/pci/host/pci-mvebu.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index c269e430c760..6f5a20f3cdf6 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -500,7 +500,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, */ bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32; bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32; - bridge->secondary_status = value >> 16; mvebu_pcie_handle_iobase_change(port); break; -- cgit v1.2.3 From 43a16f94445310800e39d54aaa534f2ce7dbe0a2 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 26 Nov 2013 11:02:54 -0700 Subject: PCI: mvebu: Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits When PCI_COMMAND_MEMORY/PCI_COMMAND_IO are cleared, the bridge should not allocate windows or even look at the window limit/base registers. Otherwise we may set up bogus windows while the PCI core code performs discovery. The core will leave PCI_COMMAND_IO cleared if it doesn't need an IO window. Have mvebu_pcie_handle_*_change respect the bits, and call the change function whenever the bits changes. Tested-by: Thomas Petazzoni Signed-off-by: Jason Gunthorpe Signed-off-by: Bjorn Helgaas Acked-by: Jason Cooper --- drivers/pci/host/pci-mvebu.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 6f5a20f3cdf6..94294123e7bd 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -300,7 +300,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) /* Are the new iobase/iolimit values invalid? */ if (port->bridge.iolimit < port->bridge.iobase || - port->bridge.iolimitupper < port->bridge.iobaseupper) { + port->bridge.iolimitupper < port->bridge.iobaseupper || + !(port->bridge.command & PCI_COMMAND_IO)) { /* If a window was configured, remove it */ if (port->iowin_base) { @@ -337,7 +338,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) { /* Are the new membase/memlimit values invalid? */ - if (port->bridge.memlimit < port->bridge.membase) { + if (port->bridge.memlimit < port->bridge.membase || + !(port->bridge.command & PCI_COMMAND_MEMORY)) { /* If a window was configured, remove it */ if (port->memwin_base) { @@ -485,8 +487,16 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, switch (where & ~3) { case PCI_COMMAND: + { + u32 old = bridge->command; + bridge->command = value & 0xffff; + if ((old ^ bridge->command) & PCI_COMMAND_IO) + mvebu_pcie_handle_iobase_change(port); + if ((old ^ bridge->command) & PCI_COMMAND_MEMORY) + mvebu_pcie_handle_membase_change(port); break; + } case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value; -- cgit v1.2.3 From 641e674d6c0f974162c4c8cc0081c7ffc50b3911 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 26 Nov 2013 11:02:55 -0700 Subject: PCI: mvebu: Support a bridge with no IO port window Make pcie-io-aperture and the IO port MBUS ID in ranges optional. If not provided the bridge reports to Linux that IO space mapping is not supported and refuses to configure an IO MBUS window. This allows both complete disable (do not specify pcie-io-aperture) and per-port disable (do not specify a IO target ranges entry for the port). Most PCIe devices these days do not require IO support to function, so having an option to disable it in the driver is useful. Tested-by: Thomas Petazzoni Signed-off-by: Jason Gunthorpe Signed-off-by: Bjorn Helgaas Acked-by: Jason Cooper --- drivers/pci/host/pci-mvebu.c | 63 ++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 94294123e7bd..abd560e46757 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -150,6 +150,11 @@ static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg) return readl(port->base + reg); } +static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port) +{ + return port->io_target != -1 && port->io_attr != -1; +} + static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) { return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); @@ -314,6 +319,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) return; } + if (!mvebu_has_ioport(port)) { + dev_WARN(&port->pcie->pdev->dev, + "Attempt to set IO when IO is disabled\n"); + return; + } + /* * We read the PCI-to-PCI bridge emulated registers, and * calculate the base address and size of the address decoding @@ -428,9 +439,12 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, break; case PCI_IO_BASE: - *value = (bridge->secondary_status << 16 | - bridge->iolimit << 8 | - bridge->iobase); + if (!mvebu_has_ioport(port)) + *value = bridge->secondary_status << 16; + else + *value = (bridge->secondary_status << 16 | + bridge->iolimit << 8 | + bridge->iobase); break; case PCI_MEMORY_BASE: @@ -490,6 +504,9 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, { u32 old = bridge->command; + if (!mvebu_has_ioport(port)) + value &= ~PCI_COMMAND_IO; + bridge->command = value & 0xffff; if ((old ^ bridge->command) & PCI_COMMAND_IO) mvebu_pcie_handle_iobase_change(port); @@ -660,7 +677,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) struct mvebu_pcie *pcie = sys_to_pcie(sys); int i; - pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset); + if (resource_size(&pcie->realio) != 0) + pci_add_resource_offset(&sys->resources, &pcie->realio, + sys->io_offset); pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); pci_add_resource(&sys->resources, &pcie->busn); @@ -761,12 +780,17 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) static int mvebu_get_tgt_attr(struct device_node *np, int devfn, - unsigned long type, int *tgt, int *attr) + unsigned long type, + unsigned int *tgt, + unsigned int *attr) { const int na = 3, ns = 2; const __be32 *range; int rlen, nranges, rangesz, pna, i; + *tgt = -1; + *attr = -1; + range = of_get_property(np, "ranges", &rlen); if (!range) return -EINVAL; @@ -836,16 +860,15 @@ static int mvebu_pcie_probe(struct platform_device *pdev) } mvebu_mbus_get_pcie_io_aperture(&pcie->io); - if (resource_size(&pcie->io) == 0) { - dev_err(&pdev->dev, "invalid I/O aperture size\n"); - return -EINVAL; - } - pcie->realio.flags = pcie->io.flags; - pcie->realio.start = PCIBIOS_MIN_IO; - pcie->realio.end = min_t(resource_size_t, - IO_SPACE_LIMIT, - resource_size(&pcie->io)); + if (resource_size(&pcie->io) != 0) { + pcie->realio.flags = pcie->io.flags; + pcie->realio.start = PCIBIOS_MIN_IO; + pcie->realio.end = min_t(resource_size_t, + IO_SPACE_LIMIT, + resource_size(&pcie->io)); + } else + pcie->realio = pcie->io; /* Get the bus range */ ret = of_pci_parse_bus_range(np, &pcie->busn); @@ -904,12 +927,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev) continue; } - ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, - &port->io_target, &port->io_attr); - if (ret < 0) { - dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", - port->port, port->lane); - continue; + if (resource_size(&pcie->io) != 0) + mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, + &port->io_target, &port->io_attr); + else { + port->io_target = -1; + port->io_attr = -1; } port->reset_gpio = of_get_named_gpio_flags(child, -- cgit v1.2.3 From fbeeaa2306fcff7614c8b41b420a400503b6d28e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:28 +0200 Subject: drm/i915: add audio power domain This way the code is simpler and can also be used for other platforms where the audio power domain->power well mapping is different. Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 18ff544670d8..4ef8e81f5393 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -113,6 +113,7 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, + POWER_DOMAIN_AUDIO, POWER_DOMAIN_INIT, POWER_DOMAIN_NUM, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index de4cf565ec4c..8f472daa2793 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5775,10 +5775,7 @@ void i915_request_power_well(void) dev_priv = container_of(hsw_pwr, struct drm_i915_private, power_domains); - - mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]); - mutex_unlock(&hsw_pwr->lock); + intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5792,10 +5789,7 @@ void i915_release_power_well(void) dev_priv = container_of(hsw_pwr, struct drm_i915_private, power_domains); - - mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]); - mutex_unlock(&hsw_pwr->lock); + intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO); } EXPORT_SYMBOL_GPL(i915_release_power_well); -- cgit v1.2.3 From c1ca727f89450cbc560af93045d57a186b83b0dc Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:29 +0200 Subject: drm/i915: support for multiple power wells HW generations so far had only one always-on power well and optionally one dynamic power well. Upcoming HW gens may have multiple dynamic power wells, so add some infrastructure to support them. The idea is to keep the existing power domain API used by the rest of the driver and create a mapping between these power domains and the underlying power wells. This mapping can differ from one HW to another but high level driver code doesn't need to know about this. Through the existing get/put API it would just ask for a given power domain and the power domain framework would make sure the relevant power wells get enabled in the right order. Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 12 +++-- drivers/gpu/drm/i915/intel_pm.c | 116 ++++++++++++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4ef8e81f5393..bb09dbf65fe8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -950,21 +950,27 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { + const char *name; /* power well enable/disable usage count */ int count; + unsigned long domains; + void *data; + void (*set)(struct drm_device *dev, struct i915_power_well *power_well, + bool enable); + bool (*is_enabled)(struct drm_device *dev, + struct i915_power_well *power_well); }; -#define I915_MAX_POWER_WELLS 1 - struct i915_power_domains { /* * Power wells needed for initialization at driver init and suspend * time are on. They are kept on until after the first modeset. */ bool init_power_on; + int power_well_count; struct mutex lock; - struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; + struct i915_power_well *power_wells; }; struct i915_dri1_state { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8f472daa2793..2b3173415212 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5627,15 +5627,41 @@ static bool is_always_on_power_domain(struct drm_device *dev, return BIT(domain) & always_on_domains; } +#define for_each_power_well(i, power_well, domain_mask, power_domains) \ + for (i = 0; \ + i < (power_domains)->power_well_count && \ + ((power_well) = &(power_domains)->power_wells[i]); \ + i++) \ + if ((power_well)->domains & (domain_mask)) + +#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \ + for (i = (power_domains)->power_well_count - 1; \ + i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\ + i--) \ + if ((power_well)->domains & (domain_mask)) + /** * We should only use the power well if we explicitly asked the hardware to * enable it, so check if it's enabled and also check if we've requested it to * be enabled. */ +static bool hsw_power_well_enabled(struct drm_device *dev, + struct i915_power_well *power_well) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(HSW_PWR_WELL_DRIVER) == + (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); +} + bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain) { struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains; + struct i915_power_well *power_well; + bool is_enabled; + int i; if (!HAS_POWER_WELL(dev)) return true; @@ -5643,11 +5669,24 @@ bool intel_display_power_enabled(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return true; - return I915_READ(HSW_PWR_WELL_DRIVER) == - (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); + power_domains = &dev_priv->power_domains; + + is_enabled = true; + + mutex_lock(&power_domains->lock); + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { + if (!power_well->is_enabled(dev, power_well)) { + is_enabled = false; + break; + } + } + mutex_unlock(&power_domains->lock); + + return is_enabled; } -static void __intel_set_power_well(struct drm_device *dev, bool enable) +static void hsw_set_power_well(struct drm_device *dev, + struct i915_power_well *power_well, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; bool is_enabled, enable_requested; @@ -5713,16 +5752,17 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) static void __intel_power_well_get(struct drm_device *dev, struct i915_power_well *power_well) { - if (!power_well->count++) - __intel_set_power_well(dev, true); + if (!power_well->count++ && power_well->set) + power_well->set(dev, power_well, true); } static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { WARN_ON(!power_well->count); - if (!--power_well->count && i915_disable_power_well) - __intel_set_power_well(dev, false); + + if (!--power_well->count && power_well->set && i915_disable_power_well) + power_well->set(dev, power_well, false); } void intel_display_power_get(struct drm_device *dev, @@ -5730,6 +5770,8 @@ void intel_display_power_get(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains; + struct i915_power_well *power_well; + int i; if (!HAS_POWER_WELL(dev)) return; @@ -5740,7 +5782,8 @@ void intel_display_power_get(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_get(dev, &power_domains->power_wells[0]); + for_each_power_well(i, power_well, BIT(domain), power_domains) + __intel_power_well_get(dev, power_well); mutex_unlock(&power_domains->lock); } @@ -5749,6 +5792,8 @@ void intel_display_power_put(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains; + struct i915_power_well *power_well; + int i; if (!HAS_POWER_WELL(dev)) return; @@ -5759,7 +5804,8 @@ void intel_display_power_put(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_put(dev, &power_domains->power_wells[0]); + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) + __intel_power_well_put(dev, power_well); mutex_unlock(&power_domains->lock); } @@ -5793,17 +5839,52 @@ void i915_release_power_well(void) } EXPORT_SYMBOL_GPL(i915_release_power_well); +static struct i915_power_well hsw_power_wells[] = { + { + .name = "display", + .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS, + .is_enabled = hsw_power_well_enabled, + .set = hsw_set_power_well, + }, +}; + +static struct i915_power_well bdw_power_wells[] = { + { + .name = "display", + .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS, + .is_enabled = hsw_power_well_enabled, + .set = hsw_set_power_well, + }, +}; + +#define set_power_wells(power_domains, __power_wells) ({ \ + (power_domains)->power_wells = (__power_wells); \ + (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \ +}) + int intel_power_domains_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; + + if (!HAS_POWER_WELL(dev)) + return 0; mutex_init(&power_domains->lock); - hsw_pwr = power_domains; - power_well = &power_domains->power_wells[0]; - power_well->count = 0; + /* + * The enabling order will be from lower to higher indexed wells, + * the disabling order is reversed. + */ + if (IS_HASWELL(dev)) { + set_power_wells(power_domains, hsw_power_wells); + hsw_pwr = power_domains; + } else if (IS_BROADWELL(dev)) { + set_power_wells(power_domains, bdw_power_wells); + hsw_pwr = power_domains; + } else { + WARN_ON(1); + } return 0; } @@ -5818,15 +5899,16 @@ static void intel_power_domains_resume(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; struct i915_power_well *power_well; + int i; if (!HAS_POWER_WELL(dev)) return; mutex_lock(&power_domains->lock); - - power_well = &power_domains->power_wells[0]; - __intel_set_power_well(dev, power_well->count > 0); - + for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { + if (power_well->set) + power_well->set(dev, power_well, power_well->count > 0); + } mutex_unlock(&power_domains->lock); } -- cgit v1.2.3 From 6f3ef5ddabc0ad321678ee091c75b1f082a42707 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:30 +0200 Subject: drm/i915: add always-on power wells instead of special casing them Instead of using a separate function to check whether a power domain is is always on, add an always-on power well covering all these power domains and do the usual get/put on these unconditionally. Since we don't assign a .set handler for these the get/put won't have any effect besides the adjusted refcount. This makes the code more readable and provides debug info also on the use of always-on power wells (once the relevant debugfs entry is added.) v3: make is_always_on to be bool instead of a bit field (Paulo) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 41 +++++++++++++---------------------------- 2 files changed, 14 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bb09dbf65fe8..e3e732bd832c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -951,6 +951,7 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { const char *name; + bool always_on; /* power well enable/disable usage count */ int count; unsigned long domains; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2b3173415212..9230781824e5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5608,25 +5608,6 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } -static bool is_always_on_power_domain(struct drm_device *dev, - enum intel_display_power_domain domain) -{ - unsigned long always_on_domains; - - BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); - - if (IS_BROADWELL(dev)) { - always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS; - } else if (IS_HASWELL(dev)) { - always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; - } else { - WARN_ON(1); - return true; - } - - return BIT(domain) & always_on_domains; -} - #define for_each_power_well(i, power_well, domain_mask, power_domains) \ for (i = 0; \ i < (power_domains)->power_well_count && \ @@ -5666,15 +5647,15 @@ bool intel_display_power_enabled(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return true; - if (is_always_on_power_domain(dev, domain)) - return true; - power_domains = &dev_priv->power_domains; is_enabled = true; mutex_lock(&power_domains->lock); for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { + if (power_well->always_on) + continue; + if (!power_well->is_enabled(dev, power_well)) { is_enabled = false; break; @@ -5776,9 +5757,6 @@ void intel_display_power_get(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return; - if (is_always_on_power_domain(dev, domain)) - return; - power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); @@ -5798,9 +5776,6 @@ void intel_display_power_put(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return; - if (is_always_on_power_domain(dev, domain)) - return; - power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); @@ -5840,6 +5815,11 @@ void i915_release_power_well(void) EXPORT_SYMBOL_GPL(i915_release_power_well); static struct i915_power_well hsw_power_wells[] = { + { + .name = "always-on", + .always_on = 1, + .domains = HSW_ALWAYS_ON_POWER_DOMAINS, + }, { .name = "display", .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS, @@ -5849,6 +5829,11 @@ static struct i915_power_well hsw_power_wells[] = { }; static struct i915_power_well bdw_power_wells[] = { + { + .name = "always-on", + .always_on = 1, + .domains = BDW_ALWAYS_ON_POWER_DOMAINS, + }, { .name = "display", .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS, -- cgit v1.2.3 From 190be112fc02f6efcf954a82bd49e2c19b3673e8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:31 +0200 Subject: drm/i915: use IS_HASWELL/BROADWELL instead of HAS_POWER_WELL In intel_display_capture_error_state we use HAS_POWER_WELL to check if we are running on Haswell/Broadwell when accessing HSW_PWR_WELL_DRIVER which is specific to these platforms. Future platforms with power wells don't have this register, so HAS_POWER_WELL won't work there any more. Use IS_HASWELL/IS_BROADWELL instead. v3: fix using logical || instead of bitwise | (Paulo) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 54e7fa6d9628..aa1a6c1e90ea 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11359,7 +11359,7 @@ intel_display_capture_error_state(struct drm_device *dev) if (error == NULL) return NULL; - if (HAS_POWER_WELL(dev)) + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); for_each_pipe(i) { @@ -11430,7 +11430,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, return; err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); - if (HAS_POWER_WELL(dev)) + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) err_printf(m, "PWR_WELL_CTL2: %08x\n", error->power_well_driver); for_each_pipe(i) { -- cgit v1.2.3 From f9e711e92825d4c71791794c944dd685c63c1a59 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 25 Nov 2013 17:15:32 +0200 Subject: drm/i915: protect HSW power well check with IS_HASWELL in redisable_vga This may need work if other platforms do the same thing, but in the meantime we should avoid looking at HSW specific bits in this generic function. Signed-off-by: Jesse Barnes Reviewed-by: Paulo Zanoni [added IS_BROADWELL too as that needs the same handling (Imre)] Signed-off-by: Imre Deak [danvet: Add Imre's missing sob.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index aa1a6c1e90ea..22b7b141a22f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11032,7 +11032,7 @@ void i915_redisable_vga(struct drm_device *dev) * level, just check if the power well is enabled instead of trying to * follow the "don't touch the power well if we don't need it" policy * the rest of the driver uses. */ - if (HAS_POWER_WELL(dev) && + if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0) return; -- cgit v1.2.3 From f7243ac9a25810140f5910c69821d5fa1e3e2387 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:33 +0200 Subject: drm/i915: don't do BDW/HSW specific powerdomains init on other platforms Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9230781824e5..5331925e37fa 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5914,6 +5914,9 @@ void intel_power_domains_init_hw(struct drm_device *dev) intel_display_set_init_power(dev, true); intel_power_domains_resume(dev); + if (!(IS_HASWELL(dev) || IS_BROADWELL(dev))) + return; + /* We're taking over the BIOS, so clear any requests made by it since * the driver is in charge now. */ if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST) -- cgit v1.2.3 From 1c2256df26f697bcd20016c271ddc8fd44653919 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:34 +0200 Subject: drm/i915: add a default always-on power well So far we distinguished platforms without a dynamic power well with the HAS_POWER_WELL macro and for such platforms we didn't call any power domain functions. Instead of doing this check we can add an always-on power well for these platforms and call the power domain functions unconditionally. For always-on power wells we only increase/decrease their refcounts, otherwise they are nop. This makes high level driver code more readable and as a bonus provides some idea of the current power domains state for all platforms (once the relevant debugfs entry is added). v3: rename intel_power_wells to i9xx_always_on_power_well (Paulo) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 18 +++++++----------- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 28 +++++++++------------------- 3 files changed, 16 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5aeb103eae44..89e4cf1bb073 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1639,8 +1639,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_gem_unload; } - if (HAS_POWER_WELL(dev)) - intel_power_domains_init(dev); + intel_power_domains_init(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); @@ -1667,8 +1666,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; out_power_well: - if (HAS_POWER_WELL(dev)) - intel_power_domains_remove(dev); + intel_power_domains_remove(dev); drm_vblank_cleanup(dev); out_gem_unload: if (dev_priv->mm.inactive_shrinker.scan_objects) @@ -1706,13 +1704,11 @@ int i915_driver_unload(struct drm_device *dev) intel_gpu_ips_teardown(); - if (HAS_POWER_WELL(dev)) { - /* The i915.ko module is still not prepared to be loaded when - * the power well is not enabled, so just enable it in case - * we're going to unload/reload. */ - intel_display_set_init_power(dev, true); - intel_power_domains_remove(dev); - } + /* The i915.ko module is still not prepared to be loaded when + * the power well is not enabled, so just enable it in case + * we're going to unload/reload. */ + intel_display_set_init_power(dev, true); + intel_power_domains_remove(dev); i915_teardown_sysfs(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e3e732bd832c..0f7bc14208a3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1834,7 +1834,6 @@ struct drm_i915_file_private { #define HAS_IPS(dev) (IS_ULT(dev) || IS_BROADWELL(dev)) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) -#define HAS_POWER_WELL(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5331925e37fa..6b4f91ee486c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5644,9 +5644,6 @@ bool intel_display_power_enabled(struct drm_device *dev, bool is_enabled; int i; - if (!HAS_POWER_WELL(dev)) - return true; - power_domains = &dev_priv->power_domains; is_enabled = true; @@ -5754,9 +5751,6 @@ void intel_display_power_get(struct drm_device *dev, struct i915_power_well *power_well; int i; - if (!HAS_POWER_WELL(dev)) - return; - power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); @@ -5773,9 +5767,6 @@ void intel_display_power_put(struct drm_device *dev, struct i915_power_well *power_well; int i; - if (!HAS_POWER_WELL(dev)) - return; - power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); @@ -5814,6 +5805,14 @@ void i915_release_power_well(void) } EXPORT_SYMBOL_GPL(i915_release_power_well); +static struct i915_power_well i9xx_always_on_power_well[] = { + { + .name = "always-on", + .always_on = 1, + .domains = POWER_DOMAIN_MASK, + }, +}; + static struct i915_power_well hsw_power_wells[] = { { .name = "always-on", @@ -5852,9 +5851,6 @@ int intel_power_domains_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; - if (!HAS_POWER_WELL(dev)) - return 0; - mutex_init(&power_domains->lock); /* @@ -5868,7 +5864,7 @@ int intel_power_domains_init(struct drm_device *dev) set_power_wells(power_domains, bdw_power_wells); hsw_pwr = power_domains; } else { - WARN_ON(1); + set_power_wells(power_domains, i9xx_always_on_power_well); } return 0; @@ -5886,9 +5882,6 @@ static void intel_power_domains_resume(struct drm_device *dev) struct i915_power_well *power_well; int i; - if (!HAS_POWER_WELL(dev)) - return; - mutex_lock(&power_domains->lock); for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { if (power_well->set) @@ -5907,9 +5900,6 @@ void intel_power_domains_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (!HAS_POWER_WELL(dev)) - return; - /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev, true); intel_power_domains_resume(dev); -- cgit v1.2.3 From 1da51581b00b3fc3ac72156e2a69c6bab71f7794 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 25 Nov 2013 17:15:35 +0200 Subject: drm/i915: add a debugfs entry for power domain info Add a debugfs entry showing the use-count for all power domains of each power well. v3: address comments from Paulo: - simplify power_domain_str() by using a switch table - move power_well::domain_count to power_domains - WARN_ON decrementing a 0 refcount Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 71 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/intel_pm.c | 12 +++++++ 3 files changed, 86 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ee4d46593aae..6600447ad0d5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1844,6 +1844,76 @@ static int i915_pc8_status(struct seq_file *m, void *unused) return 0; } +static const char *power_domain_str(enum intel_display_power_domain domain) +{ + switch (domain) { + case POWER_DOMAIN_PIPE_A: + return "PIPE_A"; + case POWER_DOMAIN_PIPE_B: + return "PIPE_B"; + case POWER_DOMAIN_PIPE_C: + return "PIPE_C"; + case POWER_DOMAIN_PIPE_A_PANEL_FITTER: + return "PIPE_A_PANEL_FITTER"; + case POWER_DOMAIN_PIPE_B_PANEL_FITTER: + return "PIPE_B_PANEL_FITTER"; + case POWER_DOMAIN_PIPE_C_PANEL_FITTER: + return "PIPE_C_PANEL_FITTER"; + case POWER_DOMAIN_TRANSCODER_A: + return "TRANSCODER_A"; + case POWER_DOMAIN_TRANSCODER_B: + return "TRANSCODER_B"; + case POWER_DOMAIN_TRANSCODER_C: + return "TRANSCODER_C"; + case POWER_DOMAIN_TRANSCODER_EDP: + return "TRANSCODER_EDP"; + case POWER_DOMAIN_VGA: + return "VGA"; + case POWER_DOMAIN_AUDIO: + return "AUDIO"; + case POWER_DOMAIN_INIT: + return "INIT"; + default: + WARN_ON(1); + return "?"; + } +} + +static int i915_power_domain_info(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + int i; + + mutex_lock(&power_domains->lock); + + seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count"); + for (i = 0; i < power_domains->power_well_count; i++) { + struct i915_power_well *power_well; + enum intel_display_power_domain power_domain; + + power_well = &power_domains->power_wells[i]; + seq_printf(m, "%-25s %d\n", power_well->name, + power_well->count); + + for (power_domain = 0; power_domain < POWER_DOMAIN_NUM; + power_domain++) { + if (!(BIT(power_domain) & power_well->domains)) + continue; + + seq_printf(m, " %-23s %d\n", + power_domain_str(power_domain), + power_domains->domain_use_count[power_domain]); + } + } + + mutex_unlock(&power_domains->lock); + + return 0; +} + struct pipe_crc_info { const char *name; struct drm_device *dev; @@ -3079,6 +3149,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_edp_psr_status", i915_edp_psr_status, 0}, {"i915_energy_uJ", i915_energy_uJ, 0}, {"i915_pc8_status", i915_pc8_status, 0}, + {"i915_power_domain_info", i915_power_domain_info, 0}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0f7bc14208a3..49dfac9028e3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -971,6 +971,9 @@ struct i915_power_domains { int power_well_count; struct mutex lock; +#if IS_ENABLED(CONFIG_DEBUG_FS) + int domain_use_count[POWER_DOMAIN_NUM]; +#endif struct i915_power_well *power_wells; }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6b4f91ee486c..2f8399c347ee 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5754,8 +5754,13 @@ void intel_display_power_get(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); + +#if IS_ENABLED(CONFIG_DEBUG_FS) + power_domains->domain_use_count[domain]++; +#endif for_each_power_well(i, power_well, BIT(domain), power_domains) __intel_power_well_get(dev, power_well); + mutex_unlock(&power_domains->lock); } @@ -5770,8 +5775,15 @@ void intel_display_power_put(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) __intel_power_well_put(dev, power_well); + +#if IS_ENABLED(CONFIG_DEBUG_FS) + WARN_ON(!power_domains->domain_use_count[domain]); + power_domains->domain_use_count[domain]--; +#endif + mutex_unlock(&power_domains->lock); } -- cgit v1.2.3 From a01091e5ce866562ea2638a80f2241d8d6bde164 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 7 Nov 2013 08:41:25 +0100 Subject: usb: gadget: composite: redirect setup requests If there are setup requests not directed to an endpont or an interface, current config's setup() has been attempted so far. This patch, in case the above fails, adds code which tries the setup() of configuration's function if there is only one function in the configuration. This behavior is required to provide equivalent of gadget zero with configfs. The gadget zero has a "config driver" for sourcesink, but all it does is delegating the request to the function proper. So when the equivalent gadget is set up with configfs it needs to handle requests directed to "config driver", but with configfs it is not possible to specify "config drivers". Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 3e7ae707f691..611fe89c3a8b 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1451,8 +1451,22 @@ unknown: struct usb_configuration *c; c = cdev->config; - if (c && c->setup) + if (!c) + goto done; + + /* try current config's setup */ + if (c->setup) { value = c->setup(c, ctrl); + goto done; + } + + /* try the only function in the current config */ + if (!list_is_singular(&c->functions)) + goto done; + f = list_first_entry(&c->functions, struct usb_function, + list); + if (f->setup) + value = f->setup(f, ctrl); } goto done; -- cgit v1.2.3 From 1efd54eab2b60c68c2ce75ea635306cef847d751 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 7 Nov 2013 08:41:26 +0100 Subject: usb: gadget: factor out alloc_ep_req alloc_ep_req() is a function repeated in several modules. Make a common implementation and use it. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Makefile | 2 +- drivers/usb/gadget/f_hid.c | 18 +++++------------- drivers/usb/gadget/f_loopback.c | 8 +++++++- drivers/usb/gadget/f_midi.c | 22 +++++++--------------- drivers/usb/gadget/f_sourcesink.c | 23 +++++------------------ drivers/usb/gadget/g_zero.h | 1 - drivers/usb/gadget/u_f.c | 32 ++++++++++++++++++++++++++++++++ drivers/usb/gadget/u_f.h | 26 ++++++++++++++++++++++++++ 8 files changed, 83 insertions(+), 49 deletions(-) create mode 100644 drivers/usb/gadget/u_f.c create mode 100644 drivers/usb/gadget/u_f.h (limited to 'drivers') diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index f1af39603d4d..40bd0f80b5ad 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -7,7 +7,7 @@ ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o libcomposite-y := usbstring.o config.o epautoconf.o -libcomposite-y += composite.o functions.o configfs.o +libcomposite-y += composite.o functions.o configfs.o u_f.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 6e69a8e8d22a..a95290a1289f 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -20,6 +20,8 @@ #include #include +#include "u_f.h" + static int major, minors; static struct class *hidg_class; @@ -334,20 +336,10 @@ static int f_hidg_open(struct inode *inode, struct file *fd) /*-------------------------------------------------------------------------*/ /* usb_function */ -static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length) +static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, + unsigned length) { - struct usb_request *req; - - req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (req) { - req->length = length; - req->buf = kmalloc(length, GFP_ATOMIC); - if (!req->buf) { - usb_ep_free_request(ep, req); - req = NULL; - } - } - return req; + return alloc_ep_req(ep, length, length); } static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 4a3873a0f2d0..b79065376a16 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -20,6 +20,7 @@ #include #include "g_zero.h" +#include "u_f.h" /* * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals, @@ -293,6 +294,11 @@ static void disable_loopback(struct f_loopback *loop) VDBG(cdev, "%s disabled\n", loop->function.name); } +static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len) +{ + return alloc_ep_req(ep, len, buflen); +} + static int enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) { @@ -332,7 +338,7 @@ fail0: * than 'buflen' bytes each. */ for (i = 0; i < qlen && result == 0; i++) { - req = alloc_ep_req(ep, 0); + req = lb_alloc_ep_req(ep, 0); if (req) { req->complete = loopback_complete; result = usb_ep_queue(ep, req, GFP_ATOMIC); diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 263e721c2694..36d4bb23087f 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -32,6 +32,8 @@ #include #include +#include "u_f.h" + MODULE_AUTHOR("Ben Williamson"); MODULE_LICENSE("GPL v2"); @@ -191,20 +193,10 @@ static struct usb_gadget_strings *midi_strings[] = { NULL, }; -static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) +static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep, + unsigned length) { - struct usb_request *req; - - req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (req) { - req->length = length; - req->buf = kmalloc(length, GFP_ATOMIC); - if (!req->buf) { - usb_ep_free_request(ep, req); - req = NULL; - } - } - return req; + return alloc_ep_req(ep, length, length); } static void free_ep_req(struct usb_ep *ep, struct usb_request *req) @@ -365,7 +357,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) /* allocate a bunch of read buffers and queue them all at once. */ for (i = 0; i < midi->qlen && err == 0; i++) { struct usb_request *req = - alloc_ep_req(midi->out_ep, midi->buflen); + midi_alloc_ep_req(midi->out_ep, midi->buflen); if (req == NULL) return -ENOMEM; @@ -546,7 +538,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req) return; if (!req) - req = alloc_ep_req(ep, midi->buflen); + req = midi_alloc_ep_req(ep, midi->buflen); if (!req) { ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n"); diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index a8895859a221..c5ad4a1fa3c7 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -21,6 +21,7 @@ #include "g_zero.h" #include "gadget_chips.h" +#include "u_f.h" /* * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral @@ -301,23 +302,9 @@ static struct usb_gadget_strings *sourcesink_strings[] = { /*-------------------------------------------------------------------------*/ -struct usb_request *alloc_ep_req(struct usb_ep *ep, int len) +static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len) { - struct usb_request *req; - - req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (req) { - if (len) - req->length = len; - else - req->length = buflen; - req->buf = kmalloc(req->length, GFP_ATOMIC); - if (!req->buf) { - usb_ep_free_request(ep, req); - req = NULL; - } - } - return req; + return alloc_ep_req(ep, len, buflen); } void free_ep_req(struct usb_ep *ep, struct usb_request *req) @@ -628,10 +615,10 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, break; } ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; - req = alloc_ep_req(ep, size); + req = ss_alloc_ep_req(ep, size); } else { ep = is_in ? ss->in_ep : ss->out_ep; - req = alloc_ep_req(ep, 0); + req = ss_alloc_ep_req(ep, 0); } if (!req) diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index ef3e8515272b..a1c1a978b5e9 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -36,7 +36,6 @@ void lb_modexit(void); int lb_modinit(void); /* common utilities */ -struct usb_request *alloc_ep_req(struct usb_ep *ep, int len); void free_ep_req(struct usb_ep *ep, struct usb_request *req); void disable_endpoints(struct usb_composite_dev *cdev, struct usb_ep *in, struct usb_ep *out, diff --git a/drivers/usb/gadget/u_f.c b/drivers/usb/gadget/u_f.c new file mode 100644 index 000000000000..63b6642c162b --- /dev/null +++ b/drivers/usb/gadget/u_f.c @@ -0,0 +1,32 @@ +/* + * u_f.c -- USB function utilities for Gadget stack + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "u_f.h" + +struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len) +{ + struct usb_request *req; + + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (req) { + req->length = len ?: default_len; + req->buf = kmalloc(req->length, GFP_ATOMIC); + if (!req->buf) { + usb_ep_free_request(ep, req); + req = NULL; + } + } + return req; +} +EXPORT_SYMBOL(alloc_ep_req); diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h new file mode 100644 index 000000000000..71034c061fca --- /dev/null +++ b/drivers/usb/gadget/u_f.h @@ -0,0 +1,26 @@ +/* + * u_f.h + * + * Utility definitions for USB functions + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __U_F_H__ +#define __U_F_H__ + +struct usb_ep; +struct usb_request; + +struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len); + +#endif /* __U_F_H__ */ + + -- cgit v1.2.3 From c0501f47c68997ea2933460b9908e6a049c59f21 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 7 Nov 2013 08:41:27 +0100 Subject: usb: gadget: f_loopback: add configfs support Add support for using the loopback USB function in gadgets composed with configfs. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- .../ABI/testing/configfs-usb-gadget-loopback | 8 ++ drivers/usb/gadget/Kconfig | 12 ++ drivers/usb/gadget/f_loopback.c | 132 +++++++++++++++++++++ drivers/usb/gadget/g_zero.h | 12 ++ drivers/usb/gadget/zero.c | 4 +- 5 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-loopback (limited to 'drivers') diff --git a/Documentation/ABI/testing/configfs-usb-gadget-loopback b/Documentation/ABI/testing/configfs-usb-gadget-loopback new file mode 100644 index 000000000000..852b2365a5b5 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-loopback @@ -0,0 +1,8 @@ +What: /config/usb-gadget/gadget/functions/Loopback.name +Date: Nov 2013 +KenelVersion: 3.13 +Description: + The attributes: + + qlen - depth of loopback queue + bulk_buflen - buffer length diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a91e6422f930..26fe8769be45 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -689,6 +689,18 @@ config USB_CONFIGFS_MASS_STORAGE device (in much the same way as the "loop" device driver), specified as a module parameter or sysfs option. +config USB_CONFIGFS_F_LB + boolean "Loopback function (for testing)" + depends on USB_CONFIGFS + select USB_F_SS_LB + help + It loops back a configurable number of transfers. + It also implements control requests, for "chapter 9" conformance. + Make this be the first driver you try using on top of any new + USB peripheral controller driver. Then you can use host-side + test software, like the "usbtest" driver, to put your hardware + and its driver through a basic set of functional tests. + config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" select USB_LIBCOMPOSITE diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index b79065376a16..c35bb40cabf2 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -231,6 +231,14 @@ autoconf_fail: static void lb_free_func(struct usb_function *f) { + struct f_lb_opts *opts; + + opts = container_of(f->fi, struct f_lb_opts, func_inst); + + mutex_lock(&opts->lock); + opts->refcnt--; + mutex_unlock(&opts->lock); + usb_free_all_descriptors(f); kfree(func_to_loop(f)); } @@ -386,6 +394,11 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi) return ERR_PTR(-ENOMEM); lb_opts = container_of(fi, struct f_lb_opts, func_inst); + + mutex_lock(&lb_opts->lock); + lb_opts->refcnt++; + mutex_unlock(&lb_opts->lock); + buflen = lb_opts->bulk_buflen; qlen = lb_opts->qlen; if (!qlen) @@ -402,6 +415,118 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi) return &loop->function; } +static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_lb_opts, + func_inst.group); +} + +CONFIGFS_ATTR_STRUCT(f_lb_opts); +CONFIGFS_ATTR_OPS(f_lb_opts); + +static void lb_attr_release(struct config_item *item) +{ + struct f_lb_opts *lb_opts = to_f_lb_opts(item); + + usb_put_function_instance(&lb_opts->func_inst); +} + +static struct configfs_item_operations lb_item_ops = { + .release = lb_attr_release, + .show_attribute = f_lb_opts_attr_show, + .store_attribute = f_lb_opts_attr_store, +}; + +static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->qlen); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts, + const char *page, size_t len) +{ + int ret; + u32 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou32(page, 0, &num); + if (ret) + goto end; + + opts->qlen = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_lb_opts_attribute f_lb_opts_qlen = + __CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR, + f_lb_opts_qlen_show, + f_lb_opts_qlen_store); + +static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->bulk_buflen); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts, + const char *page, size_t len) +{ + int ret; + u32 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou32(page, 0, &num); + if (ret) + goto end; + + opts->bulk_buflen = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_lb_opts_attribute f_lb_opts_bulk_buflen = + __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR, + f_lb_opts_bulk_buflen_show, + f_lb_opts_bulk_buflen_store); + +static struct configfs_attribute *lb_attrs[] = { + &f_lb_opts_qlen.attr, + &f_lb_opts_bulk_buflen.attr, + NULL, +}; + +static struct config_item_type lb_func_type = { + .ct_item_ops = &lb_item_ops, + .ct_attrs = lb_attrs, + .ct_owner = THIS_MODULE, +}; + static void lb_free_instance(struct usb_function_instance *fi) { struct f_lb_opts *lb_opts; @@ -417,7 +542,14 @@ static struct usb_function_instance *loopback_alloc_instance(void) lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL); if (!lb_opts) return ERR_PTR(-ENOMEM); + mutex_init(&lb_opts->lock); lb_opts->func_inst.free_func_inst = lb_free_instance; + lb_opts->bulk_buflen = GZERO_BULK_BUFLEN; + lb_opts->qlen = GZERO_QLEN; + + config_group_init_type_name(&lb_opts->func_inst.group, "", + &lb_func_type); + return &lb_opts->func_inst; } DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc); diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index a1c1a978b5e9..19ec50a42a74 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -6,6 +6,9 @@ #ifndef __G_ZERO_H #define __G_ZERO_H +#define GZERO_BULK_BUFLEN 4096 +#define GZERO_QLEN 32 + struct usb_zero_options { unsigned pattern; unsigned isoc_interval; @@ -30,6 +33,15 @@ struct f_lb_opts { struct usb_function_instance func_inst; unsigned bulk_buflen; unsigned qlen; + + /* + * Read/write access to configfs attributes is handled by configfs. + * + * This is to protect the data from concurrent access by read/write + * and create symlink/remove symlink. + */ + struct mutex lock; + int refcnt; }; void lb_modexit(void); diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 0dd07ae1555d..d954bba7b405 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -66,8 +66,8 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR); static struct usb_zero_options gzero_options = { .isoc_interval = 4, .isoc_maxpacket = 1024, - .bulk_buflen = 4096, - .qlen = 32, + .bulk_buflen = GZERO_BULK_BUFLEN, + .qlen = GZERO_QLEN, }; /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 25d8015177ae7baedb8bdc76dffc0884b0d785a3 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 7 Nov 2013 08:41:28 +0100 Subject: usb: gadget: f_sourcesink: add configfs support Add support for using the sourcesink function in gadgets composed with configfs. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- .../ABI/testing/configfs-usb-gadget-sourcesink | 12 + drivers/usb/gadget/Kconfig | 7 +- drivers/usb/gadget/f_sourcesink.c | 318 +++++++++++++++++++++ drivers/usb/gadget/g_zero.h | 11 + drivers/usb/gadget/zero.c | 4 +- 5 files changed, 347 insertions(+), 5 deletions(-) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-sourcesink (limited to 'drivers') diff --git a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink new file mode 100644 index 000000000000..a30f3093ef6c --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink @@ -0,0 +1,12 @@ +What: /config/usb-gadget/gadget/functions/SourceSink.name +Date: Nov 2013 +KenelVersion: 3.13 +Description: + The attributes: + + pattern - 0 (all zeros), 1 (mod63), 2 (none) + isoc_interval - 1..16 + isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss) + isoc_mult - 0..2 (hs/ss only) + isoc_maxburst - 0..15 (ss only) + qlen - buffer length diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 26fe8769be45..5f1d4443aa0c 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -689,12 +689,13 @@ config USB_CONFIGFS_MASS_STORAGE device (in much the same way as the "loop" device driver), specified as a module parameter or sysfs option. -config USB_CONFIGFS_F_LB - boolean "Loopback function (for testing)" +config USB_CONFIGFS_F_LB_SS + boolean "Loopback and sourcesink function (for testing)" depends on USB_CONFIGFS select USB_F_SS_LB help - It loops back a configurable number of transfers. + Loopback function loops back a configurable number of transfers. + Sourcesink function either sinks and sources bulk data. It also implements control requests, for "chapter 9" conformance. Make this be the first driver you try using on top of any new USB peripheral controller driver. Then you can use host-side diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index c5ad4a1fa3c7..5d4251e7a377 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -477,6 +477,14 @@ no_iso: static void sourcesink_free_func(struct usb_function *f) { + struct f_ss_opts *opts; + + opts = container_of(f->fi, struct f_ss_opts, func_inst); + + mutex_lock(&opts->lock); + opts->refcnt--; + mutex_unlock(&opts->lock); + usb_free_all_descriptors(f); kfree(func_to_ss(f)); } @@ -865,6 +873,11 @@ static struct usb_function *source_sink_alloc_func( return NULL; ss_opts = container_of(fi, struct f_ss_opts, func_inst); + + mutex_lock(&ss_opts->lock); + ss_opts->refcnt++; + mutex_unlock(&ss_opts->lock); + pattern = ss_opts->pattern; isoc_interval = ss_opts->isoc_interval; isoc_maxpacket = ss_opts->isoc_maxpacket; @@ -885,6 +898,303 @@ static struct usb_function *source_sink_alloc_func( return &ss->function; } +static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_ss_opts, + func_inst.group); +} + +CONFIGFS_ATTR_STRUCT(f_ss_opts); +CONFIGFS_ATTR_OPS(f_ss_opts); + +static void ss_attr_release(struct config_item *item) +{ + struct f_ss_opts *ss_opts = to_f_ss_opts(item); + + usb_put_function_instance(&ss_opts->func_inst); +} + +static struct configfs_item_operations ss_item_ops = { + .release = ss_attr_release, + .show_attribute = f_ss_opts_attr_show, + .store_attribute = f_ss_opts_attr_store, +}; + +static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->pattern); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts, + const char *page, size_t len) +{ + int ret; + u8 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou8(page, 0, &num); + if (ret) + goto end; + + if (num != 0 && num != 1 && num != 2) { + ret = -EINVAL; + goto end; + } + + opts->pattern = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_ss_opts_attribute f_ss_opts_pattern = + __CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR, + f_ss_opts_pattern_show, + f_ss_opts_pattern_store); + +static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->isoc_interval); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts, + const char *page, size_t len) +{ + int ret; + u8 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou8(page, 0, &num); + if (ret) + goto end; + + if (num > 16) { + ret = -EINVAL; + goto end; + } + + opts->isoc_interval = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_ss_opts_attribute f_ss_opts_isoc_interval = + __CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR, + f_ss_opts_isoc_interval_show, + f_ss_opts_isoc_interval_store); + +static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->isoc_maxpacket); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts, + const char *page, size_t len) +{ + int ret; + u16 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou16(page, 0, &num); + if (ret) + goto end; + + if (num > 1024) { + ret = -EINVAL; + goto end; + } + + opts->isoc_maxpacket = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket = + __CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR, + f_ss_opts_isoc_maxpacket_show, + f_ss_opts_isoc_maxpacket_store); + +static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->isoc_mult); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts, + const char *page, size_t len) +{ + int ret; + u8 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou8(page, 0, &num); + if (ret) + goto end; + + if (num > 2) { + ret = -EINVAL; + goto end; + } + + opts->isoc_mult = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_ss_opts_attribute f_ss_opts_isoc_mult = + __CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR, + f_ss_opts_isoc_mult_show, + f_ss_opts_isoc_mult_store); + +static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->isoc_maxburst); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts, + const char *page, size_t len) +{ + int ret; + u8 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou8(page, 0, &num); + if (ret) + goto end; + + if (num > 15) { + ret = -EINVAL; + goto end; + } + + opts->isoc_maxburst = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst = + __CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR, + f_ss_opts_isoc_maxburst_show, + f_ss_opts_isoc_maxburst_store); + +static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page) +{ + int result; + + mutex_lock(&opts->lock); + result = sprintf(page, "%d", opts->bulk_buflen); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts, + const char *page, size_t len) +{ + int ret; + u32 num; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = kstrtou32(page, 0, &num); + if (ret) + goto end; + + opts->bulk_buflen = num; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +static struct f_ss_opts_attribute f_ss_opts_bulk_buflen = + __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR, + f_ss_opts_bulk_buflen_show, + f_ss_opts_bulk_buflen_store); + +static struct configfs_attribute *ss_attrs[] = { + &f_ss_opts_pattern.attr, + &f_ss_opts_isoc_interval.attr, + &f_ss_opts_isoc_maxpacket.attr, + &f_ss_opts_isoc_mult.attr, + &f_ss_opts_isoc_maxburst.attr, + &f_ss_opts_bulk_buflen.attr, + NULL, +}; + +static struct config_item_type ss_func_type = { + .ct_item_ops = &ss_item_ops, + .ct_attrs = ss_attrs, + .ct_owner = THIS_MODULE, +}; + static void source_sink_free_instance(struct usb_function_instance *fi) { struct f_ss_opts *ss_opts; @@ -900,7 +1210,15 @@ static struct usb_function_instance *source_sink_alloc_inst(void) ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL); if (!ss_opts) return ERR_PTR(-ENOMEM); + mutex_init(&ss_opts->lock); ss_opts->func_inst.free_func_inst = source_sink_free_instance; + ss_opts->isoc_interval = GZERO_ISOC_INTERVAL; + ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET; + ss_opts->bulk_buflen = GZERO_BULK_BUFLEN; + + config_group_init_type_name(&ss_opts->func_inst.group, "", + &ss_func_type); + return &ss_opts->func_inst; } DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst, diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index 19ec50a42a74..15f180904f8a 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -8,6 +8,8 @@ #define GZERO_BULK_BUFLEN 4096 #define GZERO_QLEN 32 +#define GZERO_ISOC_INTERVAL 4 +#define GZERO_ISOC_MAXPACKET 1024 struct usb_zero_options { unsigned pattern; @@ -27,6 +29,15 @@ struct f_ss_opts { unsigned isoc_mult; unsigned isoc_maxburst; unsigned bulk_buflen; + + /* + * Read/write access to configfs attributes is handled by configfs. + * + * This is to protect the data from concurrent access by read/write + * and create symlink/remove symlink. + */ + struct mutex lock; + int refcnt; }; struct f_lb_opts { diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index d954bba7b405..00b401906a32 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -64,8 +64,8 @@ static bool loopdefault = 0; module_param(loopdefault, bool, S_IRUGO|S_IWUSR); static struct usb_zero_options gzero_options = { - .isoc_interval = 4, - .isoc_maxpacket = 1024, + .isoc_interval = GZERO_ISOC_INTERVAL, + .isoc_maxpacket = GZERO_ISOC_MAXPACKET, .bulk_buflen = GZERO_BULK_BUFLEN, .qlen = GZERO_QLEN, }; -- cgit v1.2.3 From 8d99339710ac9bd1eca8f04a356752c89dc7cf0b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Nov 2013 23:02:11 +0100 Subject: pinctrl: nomadik: move platform data handling into driver This decomissions the platform data header (which is no longer in use after the systems using this driver were switched to a pure device-tree config path) and merges the result into the driver file or local driver header. Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 216 ++++++++++++++++++++++- drivers/pinctrl/pinctrl-nomadik.h | 14 +- include/linux/platform_data/pinctrl-nomadik.h | 242 -------------------------- 3 files changed, 227 insertions(+), 245 deletions(-) delete mode 100644 include/linux/platform_data/pinctrl-nomadik.h (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 7111c3b59130..3895f1415ef9 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -33,7 +33,6 @@ #include /* Since we request GPIOs from ourself */ #include -#include #include "pinctrl-nomadik.h" #include "core.h" @@ -45,6 +44,221 @@ * Symbols in this file are called "nmk_gpio" for "nomadik gpio" */ +/* + * pin configurations are represented by 32-bit integers: + * + * bit 0.. 8 - Pin Number (512 Pins Maximum) + * bit 9..10 - Alternate Function Selection + * bit 11..12 - Pull up/down state + * bit 13 - Sleep mode behaviour + * bit 14 - Direction + * bit 15 - Value (if output) + * bit 16..18 - SLPM pull up/down state + * bit 19..20 - SLPM direction + * bit 21..22 - SLPM Value (if output) + * bit 23..25 - PDIS value (if input) + * bit 26 - Gpio mode + * bit 27 - Sleep mode + * + * to facilitate the definition, the following macros are provided + * + * PIN_CFG_DEFAULT - default config (0): + * pull up/down = disabled + * sleep mode = input/wakeup + * direction = input + * value = low + * SLPM direction = same as normal + * SLPM pull = same as normal + * SLPM value = same as normal + * + * PIN_CFG - default config with alternate function + */ + +typedef unsigned long pin_cfg_t; + +#define PIN_NUM_MASK 0x1ff +#define PIN_NUM(x) ((x) & PIN_NUM_MASK) + +#define PIN_ALT_SHIFT 9 +#define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT) +#define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT) +#define PIN_GPIO (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT) +#define PIN_ALT_A (NMK_GPIO_ALT_A << PIN_ALT_SHIFT) +#define PIN_ALT_B (NMK_GPIO_ALT_B << PIN_ALT_SHIFT) +#define PIN_ALT_C (NMK_GPIO_ALT_C << PIN_ALT_SHIFT) + +#define PIN_PULL_SHIFT 11 +#define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT) +#define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT) +#define PIN_PULL_NONE (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT) +#define PIN_PULL_UP (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT) +#define PIN_PULL_DOWN (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT) + +#define PIN_SLPM_SHIFT 13 +#define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) +#define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) +#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) +#define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) +/* These two replace the above in DB8500v2+ */ +#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE + +#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ +#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ + +#define PIN_DIR_SHIFT 14 +#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) +#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) +#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) +#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) + +#define PIN_VAL_SHIFT 15 +#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) +#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) +#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) +#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) + +#define PIN_SLPM_PULL_SHIFT 16 +#define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL(x) \ + (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_NONE \ + ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_UP \ + ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_DOWN \ + ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) + +#define PIN_SLPM_DIR_SHIFT 19 +#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR(x) \ + (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) + +#define PIN_SLPM_VAL_SHIFT 21 +#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL(x) \ + (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) + +#define PIN_SLPM_PDIS_SHIFT 23 +#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS(x) \ + (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) + +#define PIN_LOWEMI_SHIFT 25 +#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) + +#define PIN_GPIOMODE_SHIFT 26 +#define PIN_GPIOMODE_MASK (0x1 << PIN_GPIOMODE_SHIFT) +#define PIN_GPIOMODE(x) (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT) +#define PIN_GPIOMODE_DISABLED (0 << PIN_GPIOMODE_SHIFT) +#define PIN_GPIOMODE_ENABLED (1 << PIN_GPIOMODE_SHIFT) + +#define PIN_SLEEPMODE_SHIFT 27 +#define PIN_SLEEPMODE_MASK (0x1 << PIN_SLEEPMODE_SHIFT) +#define PIN_SLEEPMODE(x) (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT) +#define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT) +#define PIN_SLEEPMODE_ENABLED (1 << PIN_SLEEPMODE_SHIFT) + + +/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ +#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) +#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) +#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) +#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) +#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) + +#define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) +#define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) +#define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) +#define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) +#define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) + +#define PIN_CFG_DEFAULT (0) + +#define PIN_CFG(num, alt) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt)) + +#define PIN_CFG_INPUT(num, alt, pull) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) + +#define PIN_CFG_OUTPUT(num, alt, val) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +#define GPIO_BLOCK_SHIFT 5 +#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 +#define NMK_GPIO_LOWEMI 0x28 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 +/* These appear in DB8540 and later ASICs */ +#define NMK_GPIO_EDGELEVEL 0x5C +#define NMK_GPIO_LEVEL 0x60 + + +/* Pull up/down values */ +enum nmk_gpio_pull { + NMK_GPIO_PULL_NONE, + NMK_GPIO_PULL_UP, + NMK_GPIO_PULL_DOWN, +}; + +/* Sleep mode */ +enum nmk_gpio_slpm { + NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_NOCHANGE, + NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, +}; + +/* + * Platform data to register a block: only the initial gpio/irq number. + */ +struct nmk_gpio_platform_data { + char *name; + int first_gpio; + int first_irq; + int num_gpio; + u32 (*get_secondary_status)(unsigned int bank); + void (*set_ioforce)(bool enable); + bool supports_sleepmode; +}; + struct nmk_gpio_chip { struct gpio_chip chip; struct irq_domain *domain; diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h index bcd4191e10ea..d8215f1e70c7 100644 --- a/drivers/pinctrl/pinctrl-nomadik.h +++ b/drivers/pinctrl/pinctrl-nomadik.h @@ -1,13 +1,23 @@ #ifndef PINCTRL_PINCTRL_NOMADIK_H #define PINCTRL_PINCTRL_NOMADIK_H -#include - /* Package definitions */ #define PINCTRL_NMK_STN8815 0 #define PINCTRL_NMK_DB8500 1 #define PINCTRL_NMK_DB8540 2 +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +#define NMK_GPIO_ALT_CX_SHIFT 2 +#define NMK_GPIO_ALT_C1 ((1< - * Copyright (C) 2009 Alessandro Rubini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __PLAT_NOMADIK_GPIO -#define __PLAT_NOMADIK_GPIO - -/* - * pin configurations are represented by 32-bit integers: - * - * bit 0.. 8 - Pin Number (512 Pins Maximum) - * bit 9..10 - Alternate Function Selection - * bit 11..12 - Pull up/down state - * bit 13 - Sleep mode behaviour - * bit 14 - Direction - * bit 15 - Value (if output) - * bit 16..18 - SLPM pull up/down state - * bit 19..20 - SLPM direction - * bit 21..22 - SLPM Value (if output) - * bit 23..25 - PDIS value (if input) - * bit 26 - Gpio mode - * bit 27 - Sleep mode - * - * to facilitate the definition, the following macros are provided - * - * PIN_CFG_DEFAULT - default config (0): - * pull up/down = disabled - * sleep mode = input/wakeup - * direction = input - * value = low - * SLPM direction = same as normal - * SLPM pull = same as normal - * SLPM value = same as normal - * - * PIN_CFG - default config with alternate function - */ - -typedef unsigned long pin_cfg_t; - -#define PIN_NUM_MASK 0x1ff -#define PIN_NUM(x) ((x) & PIN_NUM_MASK) - -#define PIN_ALT_SHIFT 9 -#define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT) -#define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT) -#define PIN_GPIO (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT) -#define PIN_ALT_A (NMK_GPIO_ALT_A << PIN_ALT_SHIFT) -#define PIN_ALT_B (NMK_GPIO_ALT_B << PIN_ALT_SHIFT) -#define PIN_ALT_C (NMK_GPIO_ALT_C << PIN_ALT_SHIFT) - -#define PIN_PULL_SHIFT 11 -#define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT) -#define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT) -#define PIN_PULL_NONE (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT) -#define PIN_PULL_UP (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT) -#define PIN_PULL_DOWN (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT) - -#define PIN_SLPM_SHIFT 13 -#define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) -#define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) -#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) -#define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) -/* These two replace the above in DB8500v2+ */ -#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) -#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) -#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE - -#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ -#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ - -#define PIN_DIR_SHIFT 14 -#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) -#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) -#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) -#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) - -#define PIN_VAL_SHIFT 15 -#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) -#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) -#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) -#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) - -#define PIN_SLPM_PULL_SHIFT 16 -#define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) -#define PIN_SLPM_PULL(x) \ - (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) -#define PIN_SLPM_PULL_NONE \ - ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) -#define PIN_SLPM_PULL_UP \ - ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) -#define PIN_SLPM_PULL_DOWN \ - ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) - -#define PIN_SLPM_DIR_SHIFT 19 -#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) -#define PIN_SLPM_DIR(x) \ - (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) -#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) -#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) - -#define PIN_SLPM_VAL_SHIFT 21 -#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) -#define PIN_SLPM_VAL(x) \ - (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) -#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) -#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) - -#define PIN_SLPM_PDIS_SHIFT 23 -#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) -#define PIN_SLPM_PDIS(x) \ - (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) -#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) -#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) -#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) - -#define PIN_LOWEMI_SHIFT 25 -#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) -#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) -#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) -#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) - -#define PIN_GPIOMODE_SHIFT 26 -#define PIN_GPIOMODE_MASK (0x1 << PIN_GPIOMODE_SHIFT) -#define PIN_GPIOMODE(x) (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT) -#define PIN_GPIOMODE_DISABLED (0 << PIN_GPIOMODE_SHIFT) -#define PIN_GPIOMODE_ENABLED (1 << PIN_GPIOMODE_SHIFT) - -#define PIN_SLEEPMODE_SHIFT 27 -#define PIN_SLEEPMODE_MASK (0x1 << PIN_SLEEPMODE_SHIFT) -#define PIN_SLEEPMODE(x) (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT) -#define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT) -#define PIN_SLEEPMODE_ENABLED (1 << PIN_SLEEPMODE_SHIFT) - - -/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ -#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) -#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) -#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) -#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) -#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) - -#define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) -#define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) -#define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) -#define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) -#define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) - -#define PIN_CFG_DEFAULT (0) - -#define PIN_CFG(num, alt) \ - (PIN_CFG_DEFAULT |\ - (PIN_NUM(num) | PIN_##alt)) - -#define PIN_CFG_INPUT(num, alt, pull) \ - (PIN_CFG_DEFAULT |\ - (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) - -#define PIN_CFG_OUTPUT(num, alt, val) \ - (PIN_CFG_DEFAULT |\ - (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) - -/* - * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving - * the "gpio" namespace for generic and cross-machine functions - */ - -#define GPIO_BLOCK_SHIFT 5 -#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) - -/* Register in the logic block */ -#define NMK_GPIO_DAT 0x00 -#define NMK_GPIO_DATS 0x04 -#define NMK_GPIO_DATC 0x08 -#define NMK_GPIO_PDIS 0x0c -#define NMK_GPIO_DIR 0x10 -#define NMK_GPIO_DIRS 0x14 -#define NMK_GPIO_DIRC 0x18 -#define NMK_GPIO_SLPC 0x1c -#define NMK_GPIO_AFSLA 0x20 -#define NMK_GPIO_AFSLB 0x24 -#define NMK_GPIO_LOWEMI 0x28 - -#define NMK_GPIO_RIMSC 0x40 -#define NMK_GPIO_FIMSC 0x44 -#define NMK_GPIO_IS 0x48 -#define NMK_GPIO_IC 0x4c -#define NMK_GPIO_RWIMSC 0x50 -#define NMK_GPIO_FWIMSC 0x54 -#define NMK_GPIO_WKS 0x58 -/* These appear in DB8540 and later ASICs */ -#define NMK_GPIO_EDGELEVEL 0x5C -#define NMK_GPIO_LEVEL 0x60 - -/* Alternate functions: function C is set in hw by setting both A and B */ -#define NMK_GPIO_ALT_GPIO 0 -#define NMK_GPIO_ALT_A 1 -#define NMK_GPIO_ALT_B 2 -#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) - -#define NMK_GPIO_ALT_CX_SHIFT 2 -#define NMK_GPIO_ALT_C1 ((1< Date: Tue, 19 Nov 2013 23:21:04 +0100 Subject: pinctrl: nomadik: decomission non-DT boot path After the patches deleting the last board registering this pin controller as a platform device has been deleted, proceed to remove the non-DT boot patch and depend on OF being available and the device to be coming up by a DT node. Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-nomadik.c | 80 +++++++++++---------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 3895f1415ef9..983662e846a4 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -4,7 +4,7 @@ * Copyright (C) 2008,2009 STMicroelectronics * Copyright (C) 2009 Alessandro Rubini * Rewritten based on work by Prafulla WADASKAR - * Copyright (C) 2011 Linus Walleij + * Copyright (C) 2011-2013 Linus Walleij * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1240,7 +1240,7 @@ static const struct irq_domain_ops nmk_gpio_irq_simple_ops = { static int nmk_gpio_probe(struct platform_device *dev) { - struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; + struct nmk_gpio_platform_data *pdata; struct device_node *np = dev->dev.of_node; struct nmk_gpio_chip *nmk_chip; struct gpio_chip *chip; @@ -1248,32 +1248,24 @@ static int nmk_gpio_probe(struct platform_device *dev) struct clk *clk; int secondary_irq; void __iomem *base; - int irq_start = 0; int irq; int ret; - if (!pdata && !np) { - dev_err(&dev->dev, "No platform data or device tree found\n"); - return -ENODEV; - } - - if (np) { - pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - if (of_get_property(np, "st,supports-sleepmode", NULL)) - pdata->supports_sleepmode = true; + pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; - if (of_property_read_u32(np, "gpio-bank", &dev->id)) { - dev_err(&dev->dev, "gpio-bank property not found\n"); - return -EINVAL; - } + if (of_get_property(np, "st,supports-sleepmode", NULL)) + pdata->supports_sleepmode = true; - pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP; - pdata->num_gpio = NMK_GPIO_PER_CHIP; + if (of_property_read_u32(np, "gpio-bank", &dev->id)) { + dev_err(&dev->dev, "gpio-bank property not found\n"); + return -EINVAL; } + pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP; + pdata->num_gpio = NMK_GPIO_PER_CHIP; + irq = platform_get_irq(dev, 0); if (irq < 0) return irq; @@ -1321,10 +1313,7 @@ static int nmk_gpio_probe(struct platform_device *dev) clk_enable(nmk_chip->clk); nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); clk_disable(nmk_chip->clk); - -#ifdef CONFIG_OF_GPIO chip->of_node = np; -#endif ret = gpiochip_add(&nmk_chip->chip); if (ret) @@ -1336,10 +1325,8 @@ static int nmk_gpio_probe(struct platform_device *dev) platform_set_drvdata(dev, nmk_chip); - if (!np) - irq_start = pdata->first_irq; nmk_chip->domain = irq_domain_add_simple(np, - NMK_GPIO_PER_CHIP, irq_start, + NMK_GPIO_PER_CHIP, 0, &nmk_gpio_irq_simple_ops, nmk_chip); if (!nmk_chip->domain) { dev_err(&dev->dev, "failed to create irqdomain\n"); @@ -2072,11 +2059,10 @@ static int nmk_pinctrl_resume(struct platform_device *pdev) static int nmk_pinctrl_probe(struct platform_device *pdev) { - const struct platform_device_id *platid = platform_get_device_id(pdev); + const struct of_device_id *match; struct device_node *np = pdev->dev.of_node; struct device_node *prcm_np; struct nmk_pinctrl *npct; - struct resource *res; unsigned int version = 0; int i; @@ -2084,16 +2070,10 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) if (!npct) return -ENOMEM; - if (platid) - version = platid->driver_data; - else if (np) { - const struct of_device_id *match; - - match = of_match_device(nmk_pinctrl_match, &pdev->dev); - if (!match) - return -ENODEV; - version = (unsigned int) match->data; - } + match = of_match_device(nmk_pinctrl_match, &pdev->dev); + if (!match) + return -ENODEV; + version = (unsigned int) match->data; /* Poke in other ASIC variants here */ if (version == PINCTRL_NMK_STN8815) @@ -2103,17 +2083,9 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) if (version == PINCTRL_NMK_DB8540) nmk_pinctrl_db8540_init(&npct->soc); - if (np) { - prcm_np = of_parse_phandle(np, "prcm", 0); - if (prcm_np) - npct->prcm_base = of_iomap(prcm_np, 0); - } - - /* Allow platform passed information to over-write DT. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - npct->prcm_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + prcm_np = of_parse_phandle(np, "prcm", 0); + if (prcm_np) + npct->prcm_base = of_iomap(prcm_np, 0); if (!npct->prcm_base) { if (version == PINCTRL_NMK_STN8815) { dev_info(&pdev->dev, @@ -2172,13 +2144,6 @@ static struct platform_driver nmk_gpio_driver = { .probe = nmk_gpio_probe, }; -static const struct platform_device_id nmk_pinctrl_id[] = { - { "pinctrl-stn8815", PINCTRL_NMK_STN8815 }, - { "pinctrl-db8500", PINCTRL_NMK_DB8500 }, - { "pinctrl-db8540", PINCTRL_NMK_DB8540 }, - { } -}; - static struct platform_driver nmk_pinctrl_driver = { .driver = { .owner = THIS_MODULE, @@ -2186,7 +2151,6 @@ static struct platform_driver nmk_pinctrl_driver = { .of_match_table = nmk_pinctrl_match, }, .probe = nmk_pinctrl_probe, - .id_table = nmk_pinctrl_id, #ifdef CONFIG_PM .suspend = nmk_pinctrl_suspend, .resume = nmk_pinctrl_resume, -- cgit v1.2.3 From bddd5a2bb335b101dc75233aea313b01d3459603 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 19 Nov 2013 11:07:41 +0000 Subject: dma: ste_dma40: Parse flags property for new 'high priority channel' request This is used for MSP (audio) devices which is about to be fully DT:ed. Acked-by: Vinod Koul Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- drivers/dma/ste_dma40.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index b8c031b7de4e..00a2de957b23 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -2409,6 +2409,7 @@ static void d40_set_prio_realtime(struct d40_chan *d40c) #define D40_DT_FLAGS_DIR(flags) ((flags >> 1) & 0x1) #define D40_DT_FLAGS_BIG_ENDIAN(flags) ((flags >> 2) & 0x1) #define D40_DT_FLAGS_FIXED_CHAN(flags) ((flags >> 3) & 0x1) +#define D40_DT_FLAGS_HIGH_PRIO(flags) ((flags >> 4) & 0x1) static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) @@ -2446,6 +2447,9 @@ static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec, cfg.use_fixed_channel = true; } + if (D40_DT_FLAGS_HIGH_PRIO(flags)) + cfg.high_priority = true; + return dma_request_channel(cap, stedma40_filter, &cfg); } -- cgit v1.2.3 From 7172c19a2427da1d2507d19ca056157fd92490e7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Nov 2013 22:23:21 +0100 Subject: clksrc: delete nomadik MTU non-DT boot path Both platforms using the MTU (Nomadik and Ux500) have now been converted to use device tree exclusively, thus let us delete this platform data header and make this driver a fully self-contained DT-only driver. Cc: Thomas Gleixner Cc: Lee Jones Acked-by: Daniel Lezcano Signed-off-by: Linus Walleij --- drivers/clocksource/nomadik-mtu.c | 23 +++++----------------- .../linux/platform_data/clocksource-nomadik-mtu.h | 9 --------- 2 files changed, 5 insertions(+), 27 deletions(-) delete mode 100644 include/linux/platform_data/clocksource-nomadik-mtu.h (limited to 'drivers') diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index ed7b73b508e0..f00b5c9ce8b6 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -103,7 +102,7 @@ static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev) return 0; } -void nmdk_clkevt_reset(void) +static void nmdk_clkevt_reset(void) { if (clkevt_periodic) { /* Timer: configure load and background-load, and fire it up */ @@ -144,7 +143,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, } } -void nmdk_clksrc_reset(void) +static void nmdk_clksrc_reset(void) { /* Disable */ writel(0, mtu_base + MTU_CR(0)); @@ -192,8 +191,8 @@ static struct irqaction nmdk_timer_irq = { .dev_id = &nmdk_clkevt, }; -static void __init __nmdk_timer_init(void __iomem *base, int irq, - struct clk *pclk, struct clk *clk) +static void __init nmdk_timer_init(void __iomem *base, int irq, + struct clk *pclk, struct clk *clk) { unsigned long rate; @@ -245,18 +244,6 @@ static void __init __nmdk_timer_init(void __iomem *base, int irq, register_current_timer_delay(&mtu_delay_timer); } -void __init nmdk_timer_init(void __iomem *base, int irq) -{ - struct clk *clk0, *pclk0; - - pclk0 = clk_get_sys("mtu0", "apb_pclk"); - BUG_ON(IS_ERR(pclk0)); - clk0 = clk_get_sys("mtu0", NULL); - BUG_ON(IS_ERR(clk0)); - - __nmdk_timer_init(base, irq, pclk0, clk0); -} - static void __init nmdk_timer_of_init(struct device_node *node) { struct clk *pclk; @@ -280,7 +267,7 @@ static void __init nmdk_timer_of_init(struct device_node *node) if (irq <= 0) panic("Can't parse IRQ"); - __nmdk_timer_init(base, irq, pclk, clk); + nmdk_timer_init(base, irq, pclk, clk); } CLOCKSOURCE_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu", nmdk_timer_of_init); diff --git a/include/linux/platform_data/clocksource-nomadik-mtu.h b/include/linux/platform_data/clocksource-nomadik-mtu.h deleted file mode 100644 index 80088973b734..000000000000 --- a/include/linux/platform_data/clocksource-nomadik-mtu.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __PLAT_MTU_H -#define __PLAT_MTU_H - -void nmdk_timer_init(void __iomem *base, int irq); -void nmdk_clkevt_reset(void); -void nmdk_clksrc_reset(void); - -#endif /* __PLAT_MTU_H */ - -- cgit v1.2.3 From 2b558c13df82b2ede7a016f00bc9ebf534ddb301 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 30 Oct 2013 22:09:48 +0800 Subject: mmc: sdhci: clear auto cmd setting bits for no data cmds The auto cmd settings bits should be cleared before sending new commands or we may receive command timeout error for normal commands due to wrongly pre-sent auto cmd. e.g. we receive CMD13 timeout error due to ACMD23 is wrongly enabled by former data commands. mmc2: new high speed DDR MMC card at address 0001 mmcblk1: mmc2:0001 SEM08G 7.39 GiB mmcblk1boot0: mmc2:0001 SEM08G partition 1 2.00 MiB mmcblk1boot1: mmc2:0001 SEM08G partition 2 2.00 MiB mmcblk1rpmb: mmc2:0001 SEM08G partition 3 128 KiB mmcblk1: p1 p2 p3 p4 < p5 p6 p7 > mmc2: Timeout waiting for hardware interrupt. mmcblk1boot1: unknown partition table mmc2: Timeout waiting for hardware interrupt. mmcblk1boot0: unknown partition table Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bd8a0982aec3..6840322c12a0 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -898,8 +898,13 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, u16 mode; struct mmc_data *data = cmd->data; - if (data == NULL) + if (data == NULL) { + /* clear Auto CMD settings for no data CMDs */ + mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); + sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | + SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); return; + } WARN_ON(!host->data); -- cgit v1.2.3 From 7dd109ef4f58ca09c18809e981658ffeaca471f8 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 30 Oct 2013 22:09:49 +0800 Subject: mmc: sdhci-esdhc-imx: add SDHCI_TRANSFER_MODE read function Used to read out the correct value of SDHCI_TRANSFER_MODE register for upper layer. Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 461a4c3f4ef7..2be77e0dcc4e 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -385,6 +385,22 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) return ret; } + if (unlikely(reg == SDHCI_TRANSFER_MODE)) { + if (esdhc_is_usdhc(imx_data)) { + u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); + ret = m & ESDHC_MIX_CTRL_SDHCI_MASK; + /* Swap AC23 bit */ + if (m & ESDHC_MIX_CTRL_AC23EN) { + ret &= ~ESDHC_MIX_CTRL_AC23EN; + ret |= SDHCI_TRNS_AUTO_CMD23; + } + } else { + ret = readw(host->ioaddr + SDHCI_TRANSFER_MODE); + } + + return ret; + } + return readw(host->ioaddr + reg); } -- cgit v1.2.3 From 976358e2343566207fed2101ce62ff6fbad7f830 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Mon, 25 Nov 2013 19:17:09 -0800 Subject: Input: add a new driver for GPIO beeper This patch adds a new driver for the beeper controlled via GPIO pin. The driver does not depend on the architecture and is positioned as a replacement for the specific drivers that are used for this function. Signed-off-by: Alexander Shiyan Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/gpio-beeper.txt | 13 +++ drivers/input/misc/Kconfig | 9 ++ drivers/input/misc/Makefile | 1 + drivers/input/misc/gpio-beeper.c | 127 +++++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/gpio-beeper.txt create mode 100644 drivers/input/misc/gpio-beeper.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/input/gpio-beeper.txt b/Documentation/devicetree/bindings/input/gpio-beeper.txt new file mode 100644 index 000000000000..a5086e37fce6 --- /dev/null +++ b/Documentation/devicetree/bindings/input/gpio-beeper.txt @@ -0,0 +1,13 @@ +* GPIO beeper device tree bindings + +Register a beeper connected to GPIO pin. + +Required properties: +- compatible: Should be "gpio-beeper". +- gpios: From common gpio binding; gpio connection to beeper enable pin. + +Example: + beeper: beeper { + compatible = "gpio-beeper"; + gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>; + }; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 5f4967d01bc3..4ffc39732513 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -222,6 +222,15 @@ config INPUT_GP2A To compile this driver as a module, choose M here: the module will be called gp2ap002a00f. +config INPUT_GPIO_BEEPER + tristate "Generic GPIO Beeper support" + depends on OF_GPIO + help + Say Y here if you have a beeper connected to a GPIO pin. + + To compile this driver as a module, choose M here: the + module will be called gpio-beeper. + config INPUT_GPIO_TILT_POLLED tristate "Polled GPIO tilt switch" depends on GPIOLIB diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0ebfb6dbf0f7..cda71fc52fb3 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o +obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c new file mode 100644 index 000000000000..b757435e2b3d --- /dev/null +++ b/drivers/input/misc/gpio-beeper.c @@ -0,0 +1,127 @@ +/* + * Generic GPIO beeper driver + * + * Copyright (C) 2013 Alexander Shiyan + * + * 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 + +#define BEEPER_MODNAME "gpio-beeper" + +struct gpio_beeper { + struct work_struct work; + int gpio; + bool active_low; + bool beeping; +}; + +static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on) +{ + gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low); +} + +static void gpio_beeper_work(struct work_struct *work) +{ + struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work); + + gpio_beeper_toggle(beep, beep->beeping); +} + +static int gpio_beeper_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) +{ + struct gpio_beeper *beep = input_get_drvdata(dev); + + if (type != EV_SND || code != SND_BELL) + return -ENOTSUPP; + + if (value < 0) + return -EINVAL; + + beep->beeping = value; + /* Schedule work to actually turn the beeper on or off */ + schedule_work(&beep->work); + + return 0; +} + +static void gpio_beeper_close(struct input_dev *input) +{ + struct gpio_beeper *beep = input_get_drvdata(input); + + cancel_work_sync(&beep->work); + gpio_beeper_toggle(beep, false); +} + +static int gpio_beeper_probe(struct platform_device *pdev) +{ + struct gpio_beeper *beep; + enum of_gpio_flags flags; + struct input_dev *input; + unsigned long gflags; + int err; + + beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); + if (!beep) + return -ENOMEM; + + beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); + if (!gpio_is_valid(beep->gpio)) + return beep->gpio; + + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return -ENOMEM; + + INIT_WORK(&beep->work, gpio_beeper_work); + + input->name = pdev->name; + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; + input->close = gpio_beeper_close; + input->event = gpio_beeper_event; + + input_set_capability(input, EV_SND, SND_BELL); + + beep->active_low = flags & OF_GPIO_ACTIVE_LOW; + gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + + err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name); + if (err) + return err; + + input_set_drvdata(input, beep); + + return input_register_device(input); +} + +static struct of_device_id gpio_beeper_of_match[] = { + { .compatible = BEEPER_MODNAME, }, + { } +}; +MODULE_DEVICE_TABLE(of, gpio_beeper_of_match); + +static struct platform_driver gpio_beeper_platform_driver = { + .driver = { + .name = BEEPER_MODNAME, + .owner = THIS_MODULE, + .of_match_table = gpio_beeper_of_match, + }, + .probe = gpio_beeper_probe, +}; +module_platform_driver(gpio_beeper_platform_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Shiyan "); +MODULE_DESCRIPTION("Generic GPIO beeper driver"); -- cgit v1.2.3 From 2b8454a75b90d7cd1ac325a0baba77244733354f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 27 Nov 2013 11:34:58 +0800 Subject: platform/chrome: unregister platform driver/device when module exit We have registered platform driver and device when module init, and need unregister them when module exit. Signed-off-by: Wei Yongjun Signed-off-by: Olof Johansson --- drivers/platform/chrome/chromeos_laptop.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 446ef0f9c256..7f3aad0e115c 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -511,6 +511,9 @@ static void __exit chromeos_laptop_exit(void) i2c_unregister_device(tp); if (ts) i2c_unregister_device(ts); + + platform_device_unregister(cros_platform_device); + platform_driver_unregister(&cros_platform_driver); } module_init(chromeos_laptop_init); -- cgit v1.2.3 From 947fdaadf05480e567d3cd58d456240655063d03 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Nov 2013 12:01:32 +0000 Subject: drm/i915: Do not attempt to re-enable an unconnected primary plane Due to user fudging (for instance using video=VGA-1:e with FBDEV=n) we can attempt to reset an inconsistent CRTC that is marked as active but has no assigned fb. It would be wise to fix this earlier, but the long term plan is to have primary and secondary planes associated with a CRTC, in which crtc->fb being NULL will be expected. So for a quick short term fix with pretensions of grandeur, just check for a NULL fb during GPU reset and ignore the plane restoration. This fixes a potential hard hang (a panic in the panic handler) following a GPU hang. Signed-off-by: Chris Wilson Cc: Daniel Vetter [danvet: Add a corresponding fixme comment.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 22b7b141a22f..784ff70a95eb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2241,7 +2241,12 @@ void intel_display_handle_reset(struct drm_device *dev) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); mutex_lock(&crtc->mutex); - if (intel_crtc->active) + /* + * FIXME: Once we have proper support for primary planes (and + * disabling them without disabling the entire crtc) allow again + * a NULL crtc->fb. + */ + if (intel_crtc->active && crtc->fb) dev_priv->display.update_plane(crtc, crtc->fb, crtc->x, crtc->y); mutex_unlock(&crtc->mutex); -- cgit v1.2.3 From e539887b1521ed4aefce7387bc3f33814b11442d Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:20 +0100 Subject: ath10k: don't consume other's shared interrupts ath10k assumed all interrupts were directed to it. This isn't the case for legacy shared interrupts. ath10k consumed interrupts for other devices. Check device irq status and return IRQ_NONE when appropriate. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/hw.h | 1 + drivers/net/wireless/ath/ath10k/pci.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 8aeb46d9b534..9535eaa09f09 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -269,6 +269,7 @@ enum ath10k_mcast2ucast_mode { #define CORE_CTRL_CPU_INTR_MASK 0x00002000 #define CORE_CTRL_ADDRESS 0x0000 #define PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define PCIE_INTR_CAUSE_ADDRESS 0x000c #define PCIE_INTR_CLR_ADDRESS 0x0014 #define SCRATCH_3_ADDRESS 0x0030 diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 2457c8ba9017..12fb12ea2182 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -201,6 +201,19 @@ static const struct ce_pipe_config target_ce_config_wlan[] = { /* CE7 used only by Host */ }; +static bool ath10k_pci_irq_pending(struct ath10k *ar) +{ + u32 cause; + + /* Check if the shared legacy irq is for us */ + cause = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CAUSE_ADDRESS); + if (cause & (PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL)) + return true; + + return false; +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user @@ -2086,6 +2099,9 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); if (ar_pci->num_msi_intrs == 0) { + if (!ath10k_pci_irq_pending(ar)) + return IRQ_NONE; + /* * IMPORTANT: INTR_CLR regiser has to be set after * INTR_ENABLE is set to 0, otherwise interrupt can not be -- cgit v1.2.3 From fc15ca13a6c95e0d6af682af118c3c8e679a8152 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:21 +0100 Subject: ath10k: split up pci irq code Hardware waits until host signals whether it has chosen MSI(-X) or shared legacy interrupts. It is not required for the driver to register interrupt handlers immediately. This patch prepares the pci irq code for more changes. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 225 ++++++++++++++++++++-------------- 1 file changed, 131 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 12fb12ea2182..957fc59c2256 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -55,8 +55,10 @@ static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); static void ath10k_pci_stop_ce(struct ath10k *ar); static int ath10k_pci_device_reset(struct ath10k *ar); static int ath10k_pci_wait_for_target_init(struct ath10k *ar); -static int ath10k_pci_start_intr(struct ath10k *ar); -static void ath10k_pci_stop_intr(struct ath10k *ar); +static int ath10k_pci_init_irq(struct ath10k *ar); +static int ath10k_pci_deinit_irq(struct ath10k *ar); +static int ath10k_pci_request_irq(struct ath10k *ar); +static void ath10k_pci_free_irq(struct ath10k *ar); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -1354,7 +1356,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); /* Irqs are never explicitly re-enabled. They are implicitly re-enabled - * by ath10k_pci_start_intr(). */ + * by upon power_up. */ ath10k_pci_disable_irqs(ar); ath10k_pci_stop_ce(ar); @@ -1900,34 +1902,40 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) goto err_ce; } - ret = ath10k_pci_start_intr(ar); + ret = ath10k_pci_init_irq(ar); if (ret) { - ath10k_err("failed to start interrupt handling: %d\n", ret); + ath10k_err("failed to init irqs: %d\n", ret); goto err_ce; } + ret = ath10k_pci_request_irq(ar); + if (ret) { + ath10k_err("failed to request irqs: %d\n", ret); + goto err_deinit_irq; + } + ret = ath10k_pci_wait_for_target_init(ar); if (ret) { ath10k_err("failed to wait for target to init: %d\n", ret); - goto err_irq; + goto err_free_irq; } ret = ath10k_ce_enable_err_irq(ar); if (ret) { ath10k_err("failed to enable CE error irq: %d\n", ret); - goto err_irq; + goto err_free_irq; } ret = ath10k_pci_init_config(ar); if (ret) { ath10k_err("failed to setup init config: %d\n", ret); - goto err_irq; + goto err_free_irq; } ret = ath10k_pci_wake_target_cpu(ar); if (ret) { ath10k_err("could not wake up target CPU: %d\n", ret); - goto err_irq; + goto err_free_irq; } ath10k_pci_start_bmi(ar); @@ -1944,11 +1952,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) return 0; -err_irq: - ath10k_ce_disable_interrupts(ar); - ath10k_pci_stop_intr(ar); +err_free_irq: + ath10k_pci_free_irq(ar); ath10k_pci_kill_tasklet(ar); ath10k_pci_device_reset(ar); +err_deinit_irq: + ath10k_pci_deinit_irq(ar); err_ce: ath10k_pci_ce_deinit(ar); err_ps: @@ -1962,7 +1971,8 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - ath10k_pci_stop_intr(ar); + ath10k_pci_free_irq(ar); + ath10k_pci_deinit_irq(ar); ath10k_pci_device_reset(ar); ath10k_pci_ce_deinit(ar); @@ -2152,24 +2162,17 @@ static void ath10k_pci_tasklet(unsigned long data) } } -static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num) +static int ath10k_pci_request_irq_msix(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ret; - int i; - - ret = pci_enable_msi_block(ar_pci->pdev, num); - if (ret) - return ret; + int ret, i; ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ath10k_pci_msi_fw_handler, IRQF_SHARED, "ath10k_pci", ar); if (ret) { - ath10k_warn("request_irq(%d) failed %d\n", + ath10k_warn("failed to request MSI-X fw irq %d: %d\n", ar_pci->pdev->irq + MSI_ASSIGN_FW, ret); - - pci_disable_msi(ar_pci->pdev); return ret; } @@ -2178,45 +2181,38 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num) ath10k_pci_per_engine_handler, IRQF_SHARED, "ath10k_pci", ar); if (ret) { - ath10k_warn("request_irq(%d) failed %d\n", + ath10k_warn("failed to request MSI-X ce irq %d: %d\n", ar_pci->pdev->irq + i, ret); for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--) free_irq(ar_pci->pdev->irq + i, ar); free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar); - pci_disable_msi(ar_pci->pdev); return ret; } } - ath10k_dbg(ATH10K_DBG_BOOT, - "MSI-X interrupt handling (%d intrs)\n", num); return 0; } -static int ath10k_pci_start_intr_msi(struct ath10k *ar) +static int ath10k_pci_request_irq_msi(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - ret = pci_enable_msi(ar_pci->pdev); - if (ret < 0) - return ret; - ret = request_irq(ar_pci->pdev->irq, ath10k_pci_interrupt_handler, IRQF_SHARED, "ath10k_pci", ar); - if (ret < 0) { - pci_disable_msi(ar_pci->pdev); + if (ret) { + ath10k_warn("failed to request MSI irq %d: %d\n", + ar_pci->pdev->irq, ret); return ret; } - ath10k_dbg(ATH10K_DBG_BOOT, "MSI interrupt handling\n"); return 0; } -static int ath10k_pci_start_intr_legacy(struct ath10k *ar) +static int ath10k_pci_request_irq_legacy(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; @@ -2224,99 +2220,140 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) ret = request_irq(ar_pci->pdev->irq, ath10k_pci_interrupt_handler, IRQF_SHARED, "ath10k_pci", ar); - if (ret < 0) - return ret; - - ret = ath10k_pci_wake(ar); if (ret) { - free_irq(ar_pci->pdev->irq, ar); - ath10k_err("failed to wake up target: %d\n", ret); + ath10k_warn("failed to request legacy irq %d: %d\n", + ar_pci->pdev->irq, ret); return ret; } - /* - * A potential race occurs here: The CORE_BASE write - * depends on target correctly decoding AXI address but - * host won't know when target writes BAR to CORE_CTRL. - * This write might get lost if target has NOT written BAR. - * For now, fix the race by repeating the write in below - * synchronization checking. - */ - iowrite32(PCIE_INTR_FIRMWARE_MASK | - PCIE_INTR_CE_MASK_ALL, - ar_pci->mem + (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS)); - - ath10k_pci_sleep(ar); - ath10k_dbg(ATH10K_DBG_BOOT, "legacy interrupt handling\n"); return 0; } -static int ath10k_pci_start_intr(struct ath10k *ar) +static int ath10k_pci_request_irq(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + switch (ar_pci->num_msi_intrs) { + case 0: + return ath10k_pci_request_irq_legacy(ar); + case 1: + return ath10k_pci_request_irq_msi(ar); + case MSI_NUM_REQUEST: + return ath10k_pci_request_irq_msix(ar); + } + + ath10k_warn("unknown irq configuration upon request\n"); + return -EINVAL; +} + +static void ath10k_pci_free_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int num = MSI_NUM_REQUEST; - int ret; int i; - tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long) ar); + /* There's at least one interrupt irregardless whether its legacy INTR + * or MSI or MSI-X */ + for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) + free_irq(ar_pci->pdev->irq + i, ar); +} + +static void ath10k_pci_init_irq_tasklets(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int i; + + tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar); tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet, - (unsigned long) ar); + (unsigned long)ar); for (i = 0; i < CE_COUNT; i++) { ar_pci->pipe_info[i].ar_pci = ar_pci; - tasklet_init(&ar_pci->pipe_info[i].intr, - ath10k_pci_ce_tasklet, + tasklet_init(&ar_pci->pipe_info[i].intr, ath10k_pci_ce_tasklet, (unsigned long)&ar_pci->pipe_info[i]); } +} + +static int ath10k_pci_init_irq(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + ath10k_pci_init_irq_tasklets(ar); if (!test_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features)) - num = 1; + goto msi; - if (num > 1) { - ret = ath10k_pci_start_intr_msix(ar, num); - if (ret == 0) - goto exit; + /* Try MSI-X */ + ar_pci->num_msi_intrs = MSI_NUM_REQUEST; + ret = pci_enable_msi_block(ar_pci->pdev, ar_pci->num_msi_intrs); + if (ret == 0) + return 0; + if (ret > 0) + pci_disable_msi(ar_pci->pdev); - ath10k_dbg(ATH10K_DBG_BOOT, - "MSI-X didn't succeed (%d), trying MSI\n", ret); - num = 1; - } +msi: + /* Try MSI */ + ar_pci->num_msi_intrs = 1; + ret = pci_enable_msi(ar_pci->pdev); + if (ret == 0) + return 0; - if (num == 1) { - ret = ath10k_pci_start_intr_msi(ar); - if (ret == 0) - goto exit; + /* Try legacy irq + * + * A potential race occurs here: The CORE_BASE write + * depends on target correctly decoding AXI address but + * host won't know when target writes BAR to CORE_CTRL. + * This write might get lost if target has NOT written BAR. + * For now, fix the race by repeating the write in below + * synchronization checking. */ + ar_pci->num_msi_intrs = 0; - ath10k_dbg(ATH10K_DBG_BOOT, - "MSI didn't succeed (%d), trying legacy INTR\n", - ret); - num = 0; + ret = ath10k_pci_wake(ar); + if (ret) { + ath10k_warn("failed to wake target: %d\n", ret); + return ret; } - ret = ath10k_pci_start_intr_legacy(ar); + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + ath10k_pci_sleep(ar); + + return 0; +} + +static int ath10k_pci_deinit_irq_legacy(struct ath10k *ar) +{ + int ret; + + ret = ath10k_pci_wake(ar); if (ret) { - ath10k_warn("Failed to start legacy interrupts: %d\n", ret); + ath10k_warn("failed to wake target: %d\n", ret); return ret; } -exit: - ar_pci->num_msi_intrs = num; - return ret; + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, + 0); + ath10k_pci_sleep(ar); + + return 0; } -static void ath10k_pci_stop_intr(struct ath10k *ar) +static int ath10k_pci_deinit_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; - /* There's at least one interrupt irregardless whether its legacy INTR - * or MSI or MSI-X */ - for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) - free_irq(ar_pci->pdev->irq + i, ar); - - if (ar_pci->num_msi_intrs > 0) + switch (ar_pci->num_msi_intrs) { + case 0: + return ath10k_pci_deinit_irq_legacy(ar); + case 1: + /* fall-through */ + case MSI_NUM_REQUEST: pci_disable_msi(ar_pci->pdev); + return 0; + } + + ath10k_warn("unknown irq configuration upon deinit\n"); + return -EINVAL; } static int ath10k_pci_wait_for_target_init(struct ath10k *ar) -- cgit v1.2.3 From 85622cde05c18371c79a7f2a6a122271170f3ff1 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:22 +0100 Subject: ath10k: don't use interrupts for BMI It's not really necessary for interrupts to be used for BMI. BMI already assumes there's only one caller at a time and it works directly with CE. Make BMI poll for CE completions instead of waiting for interrupts. This makes disabling interrupts during early boot possible. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 50 ++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 957fc59c2256..327afbcd5692 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -59,6 +59,9 @@ static int ath10k_pci_init_irq(struct ath10k *ar); static int ath10k_pci_deinit_irq(struct ath10k *ar); static int ath10k_pci_request_irq(struct ath10k *ar); static void ath10k_pci_free_irq(struct ath10k *ar); +static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, + struct ath10k_ce_pipe *rx_pipe, + struct bmi_xfer *xfer); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -1394,6 +1397,8 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, void *treq, *tresp = NULL; int ret = 0; + might_sleep(); + if (resp && !resp_len) return -EINVAL; @@ -1434,14 +1439,12 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, if (ret) goto err_resp; - ret = wait_for_completion_timeout(&xfer.done, - BMI_COMMUNICATION_TIMEOUT_HZ); - if (ret <= 0) { + ret = ath10k_pci_bmi_wait(ce_tx, ce_rx, &xfer); + if (ret) { u32 unused_buffer; unsigned int unused_nbytes; unsigned int unused_id; - ret = -ETIMEDOUT; ath10k_ce_cancel_send_next(ce_tx, NULL, &unused_buffer, &unused_nbytes, &unused_id); } else { @@ -1509,6 +1512,25 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) complete(&xfer->done); } +static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, + struct ath10k_ce_pipe *rx_pipe, + struct bmi_xfer *xfer) +{ + unsigned long timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ; + + while (time_before_eq(jiffies, timeout)) { + ath10k_pci_bmi_send_done(tx_pipe); + ath10k_pci_bmi_recv_data(rx_pipe); + + if (completion_done(&xfer->done)) + return 0; + + schedule(); + } + + return -ETIMEDOUT; +} + /* * Map from service/endpoint to Copy Engine. * This table is derived from the CE_PCI TABLE, above. @@ -1846,24 +1868,6 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar) ath10k_pci_sleep(ar); } -static void ath10k_pci_start_bmi(struct ath10k *ar) -{ - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_pci_pipe *pipe; - - /* - * Initially, establish CE completion handlers for use with BMI. - * These are overwritten with generic handlers after we exit BMI phase. - */ - pipe = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; - ath10k_ce_send_cb_register(pipe->ce_hdl, ath10k_pci_bmi_send_done, 0); - - pipe = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST]; - ath10k_ce_recv_cb_register(pipe->ce_hdl, ath10k_pci_bmi_recv_data); - - ath10k_dbg(ATH10K_DBG_BOOT, "boot start bmi\n"); -} - static int ath10k_pci_hif_power_up(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1938,8 +1942,6 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) goto err_free_irq; } - ath10k_pci_start_bmi(ar); - if (ar_pci->num_msi_intrs > 1) irq_mode = "MSI-X"; else if (ar_pci->num_msi_intrs == 1) -- cgit v1.2.3 From c80de12b3e9bde0736f66feed8dd7b6fdc739d16 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:23 +0100 Subject: ath10k: decouple ath10k_pci_start_ce() The function did a couple of things: it allocated CE completions, registered CE callbacks and enabled CE interrupts through HW registers. This cannot be so. Split the function into one that allocates CE completions and the other one that starts off CE operation. This is required for future legacy shared interrupt handling. This also fixes possible memory leak if post rx failed. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 75 +++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 327afbcd5692..05e6f8b4f1b8 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -62,6 +62,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar); static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, struct ath10k_ce_pipe *rx_pipe, struct bmi_xfer *xfer); +static void ath10k_pci_cleanup_ce(struct ath10k *ar); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -824,14 +825,13 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar, sizeof(ar_pci->msg_callbacks_current)); } -static int ath10k_pci_start_ce(struct ath10k *ar) +static int ath10k_pci_alloc_compl(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_diag = ar_pci->ce_diag; const struct ce_attr *attr; struct ath10k_pci_pipe *pipe_info; struct ath10k_pci_compl *compl; - int i, pipe_num, completions, disable_interrupts; + int i, pipe_num, completions; spin_lock_init(&ar_pci->compl_lock); INIT_LIST_HEAD(&ar_pci->compl_process); @@ -843,34 +843,23 @@ static int ath10k_pci_start_ce(struct ath10k *ar) INIT_LIST_HEAD(&pipe_info->compl_free); /* Handle Diagnostic CE specially */ - if (pipe_info->ce_hdl == ce_diag) + if (pipe_info->ce_hdl == ar_pci->ce_diag) continue; attr = &host_ce_config_wlan[pipe_num]; completions = 0; - if (attr->src_nentries) { - disable_interrupts = attr->flags & CE_ATTR_DIS_INTR; - ath10k_ce_send_cb_register(pipe_info->ce_hdl, - ath10k_pci_ce_send_done, - disable_interrupts); + if (attr->src_nentries) completions += attr->src_nentries; - } - if (attr->dest_nentries) { - ath10k_ce_recv_cb_register(pipe_info->ce_hdl, - ath10k_pci_ce_recv_data); + if (attr->dest_nentries) completions += attr->dest_nentries; - } - - if (completions == 0) - continue; for (i = 0; i < completions; i++) { compl = kmalloc(sizeof(*compl), GFP_KERNEL); if (!compl) { ath10k_warn("No memory for completion state\n"); - ath10k_pci_stop_ce(ar); + ath10k_pci_cleanup_ce(ar); return -ENOMEM; } @@ -882,6 +871,37 @@ static int ath10k_pci_start_ce(struct ath10k *ar) return 0; } +static int ath10k_pci_setup_ce_irq(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + const struct ce_attr *attr; + struct ath10k_pci_pipe *pipe_info; + int pipe_num, disable_interrupts; + + for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + + /* Handle Diagnostic CE specially */ + if (pipe_info->ce_hdl == ar_pci->ce_diag) + continue; + + attr = &host_ce_config_wlan[pipe_num]; + + if (attr->src_nentries) { + disable_interrupts = attr->flags & CE_ATTR_DIS_INTR; + ath10k_ce_send_cb_register(pipe_info->ce_hdl, + ath10k_pci_ce_send_done, + disable_interrupts); + } + + if (attr->dest_nentries) + ath10k_ce_recv_cb_register(pipe_info->ce_hdl, + ath10k_pci_ce_recv_data); + } + + return 0; +} + static void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1210,22 +1230,35 @@ static int ath10k_pci_hif_start(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - ret = ath10k_pci_start_ce(ar); + ret = ath10k_pci_alloc_compl(ar); if (ret) { - ath10k_warn("failed to start CE: %d\n", ret); + ath10k_warn("failed to allocate CE completions: %d\n", ret); return ret; } + ret = ath10k_pci_setup_ce_irq(ar); + if (ret) { + ath10k_warn("failed to setup CE interrupts: %d\n", ret); + goto err_free_compl; + } + /* Post buffers once to start things off. */ ret = ath10k_pci_post_rx(ar); if (ret) { ath10k_warn("failed to post RX buffers for all pipes: %d\n", ret); - return ret; + goto err_stop_ce; } ar_pci->started = 1; return 0; + +err_stop_ce: + ath10k_pci_stop_ce(ar); + ath10k_pci_process_ce(ar); +err_free_compl: + ath10k_pci_cleanup_ce(ar); + return ret; } static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) -- cgit v1.2.3 From 5d1aa94680f1bf581a4cea2c7137a1423f676795 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:24 +0100 Subject: ath10k: defer irq registration until hif start() It's impossible to rely on disable_irq() and/or CE interrupt masking with legacy shared interrupts. Other devices sharing the same irq line may assert it while ath10k is doing something that requires no interrupts. Irq handlers are now registered after all preparations are complete so spurious/foreign interrupts won't do any harm. The handlers are unregistered when no interrupts are required (i.e. during driver teardown). This also removes the ability to receive FW early indication (since interrupts are not registered until early boot is complete). This is not mission critical (it's more of a hint that early boot failed due to unexpected FW crash) and will be re-added in a follow up patch. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 15 -------- drivers/net/wireless/ath/ath10k/ce.h | 1 - drivers/net/wireless/ath/ath10k/pci.c | 65 +++++++++++++---------------------- 3 files changed, 23 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 476928f2dadc..d44d618b05f9 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -792,21 +792,6 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, ath10k_pci_sleep(ar); } -int ath10k_ce_enable_err_irq(struct ath10k *ar) -{ - int i, ret; - - ret = ath10k_pci_wake(ar); - if (ret) - return ret; - - for (i = 0; i < CE_COUNT; i++) - ath10k_ce_error_intr_enable(ar, ath10k_ce_base_address(i)); - - ath10k_pci_sleep(ar); - return 0; -} - int ath10k_ce_disable_interrupts(struct ath10k *ar) { int ce_id, ret; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 8a58bac958a1..67dbde6a5c74 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -235,7 +235,6 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state); void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_disable_interrupts(struct ath10k *ar); -int ath10k_ce_enable_err_irq(struct ath10k *ar); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 05e6f8b4f1b8..bd673115ec32 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -919,13 +919,6 @@ static void ath10k_pci_stop_ce(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_compl *compl; struct sk_buff *skb; - int ret; - - ret = ath10k_ce_disable_interrupts(ar); - if (ret) - ath10k_warn("failed to disable CE interrupts: %d\n", ret); - - ath10k_pci_kill_tasklet(ar); /* Mark pending completions as aborted, so that upper layers free up * their associated resources */ @@ -1236,10 +1229,17 @@ static int ath10k_pci_hif_start(struct ath10k *ar) return ret; } + ret = ath10k_pci_request_irq(ar); + if (ret) { + ath10k_warn("failed to post RX buffers for all pipes: %d\n", + ret); + goto err_free_compl; + } + ret = ath10k_pci_setup_ce_irq(ar); if (ret) { ath10k_warn("failed to setup CE interrupts: %d\n", ret); - goto err_free_compl; + goto err_stop; } /* Post buffers once to start things off. */ @@ -1247,13 +1247,16 @@ static int ath10k_pci_hif_start(struct ath10k *ar) if (ret) { ath10k_warn("failed to post RX buffers for all pipes: %d\n", ret); - goto err_stop_ce; + goto err_stop; } ar_pci->started = 1; return 0; -err_stop_ce: +err_stop: + ath10k_ce_disable_interrupts(ar); + ath10k_pci_free_irq(ar); + ath10k_pci_kill_tasklet(ar); ath10k_pci_stop_ce(ar); ath10k_pci_process_ce(ar); err_free_compl: @@ -1376,25 +1379,19 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar) } } -static void ath10k_pci_disable_irqs(struct ath10k *ar) -{ - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; - - for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) - disable_irq(ar_pci->pdev->irq + i); -} - static void ath10k_pci_hif_stop(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); - /* Irqs are never explicitly re-enabled. They are implicitly re-enabled - * by upon power_up. */ - ath10k_pci_disable_irqs(ar); + ret = ath10k_ce_disable_interrupts(ar); + if (ret) + ath10k_warn("failed to disable CE interrupts: %d\n", ret); + ath10k_pci_free_irq(ar); + ath10k_pci_kill_tasklet(ar); ath10k_pci_stop_ce(ar); /* At this point, asynchronous threads are stopped, the target should @@ -1945,34 +1942,22 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) goto err_ce; } - ret = ath10k_pci_request_irq(ar); - if (ret) { - ath10k_err("failed to request irqs: %d\n", ret); - goto err_deinit_irq; - } - ret = ath10k_pci_wait_for_target_init(ar); if (ret) { ath10k_err("failed to wait for target to init: %d\n", ret); - goto err_free_irq; - } - - ret = ath10k_ce_enable_err_irq(ar); - if (ret) { - ath10k_err("failed to enable CE error irq: %d\n", ret); - goto err_free_irq; + goto err_deinit_irq; } ret = ath10k_pci_init_config(ar); if (ret) { ath10k_err("failed to setup init config: %d\n", ret); - goto err_free_irq; + goto err_deinit_irq; } ret = ath10k_pci_wake_target_cpu(ar); if (ret) { ath10k_err("could not wake up target CPU: %d\n", ret); - goto err_free_irq; + goto err_deinit_irq; } if (ar_pci->num_msi_intrs > 1) @@ -1987,14 +1972,11 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) return 0; -err_free_irq: - ath10k_pci_free_irq(ar); - ath10k_pci_kill_tasklet(ar); - ath10k_pci_device_reset(ar); err_deinit_irq: ath10k_pci_deinit_irq(ar); err_ce: ath10k_pci_ce_deinit(ar); + ath10k_pci_device_reset(ar); err_ps: if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) ath10k_do_pci_sleep(ar); @@ -2006,7 +1988,6 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - ath10k_pci_free_irq(ar); ath10k_pci_deinit_irq(ar); ath10k_pci_device_reset(ar); -- cgit v1.2.3 From 2685218b3f3dd2af1c9ac09d7b3800725bb34d9c Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:25 +0100 Subject: ath10k: extract functions for legacy irq handling Preparation for code re-use. Also use ioread/write wrappers. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 65 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index bd673115ec32..1d2939c35d9c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -220,6 +220,34 @@ static bool ath10k_pci_irq_pending(struct ath10k *ar) return false; } +static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) +{ + /* IMPORTANT: INTR_CLR register has to be set after + * INTR_ENABLE is set to 0, otherwise interrupt can not be + * really cleared. */ + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, + 0); + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_CLR_ADDRESS, + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + + /* IMPORTANT: this extra read transaction is required to + * flush the posted write buffer. */ + (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + PCIE_INTR_ENABLE_ADDRESS); +} + +static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) +{ + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + + PCIE_INTR_ENABLE_ADDRESS, + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + + /* IMPORTANT: this extra read transaction is required to + * flush the posted write buffer. */ + (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + PCIE_INTR_ENABLE_ADDRESS); +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user @@ -2128,25 +2156,7 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) if (!ath10k_pci_irq_pending(ar)) return IRQ_NONE; - /* - * IMPORTANT: INTR_CLR regiser has to be set after - * INTR_ENABLE is set to 0, otherwise interrupt can not be - * really cleared. - */ - iowrite32(0, ar_pci->mem + - (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS)); - iowrite32(PCIE_INTR_FIRMWARE_MASK | - PCIE_INTR_CE_MASK_ALL, - ar_pci->mem + (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_CLR_ADDRESS)); - /* - * IMPORTANT: this extra read transaction is required to - * flush the posted write buffer. - */ - (void) ioread32(ar_pci->mem + - (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS)); + ath10k_pci_disable_and_clear_legacy_irq(ar); } tasklet_schedule(&ar_pci->intr_tq); @@ -2162,20 +2172,9 @@ static void ath10k_pci_tasklet(unsigned long data) ath10k_pci_fw_interrupt_handler(ar); /* FIXME: Handle FW error */ ath10k_ce_per_engine_service_any(ar); - if (ar_pci->num_msi_intrs == 0) { - /* Enable Legacy PCI line interrupts */ - iowrite32(PCIE_INTR_FIRMWARE_MASK | - PCIE_INTR_CE_MASK_ALL, - ar_pci->mem + (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS)); - /* - * IMPORTANT: this extra read transaction is required to - * flush the posted write buffer - */ - (void) ioread32(ar_pci->mem + - (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS)); - } + /* Re-enable legacy irq that was disabled in the irq handler */ + if (ar_pci->num_msi_intrs == 0) + ath10k_pci_enable_legacy_irq(ar); } static int ath10k_pci_request_irq_msix(struct ath10k *ar) -- cgit v1.2.3 From ab977bd04bd56edf473e0317eb2370abba04356c Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:26 +0100 Subject: ath10k: re-add support for early fw indication It's possible for FW to panic during early boot. The patch re-introduces support to detect and print those crashes. This introduces an additional irq handler that is set for the duration of early boot and shutdown. The handler is then overriden with regular handlers upon hif start(). Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 106 ++++++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/pci.h | 1 + 2 files changed, 102 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 1d2939c35d9c..0a2d1c20e4df 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -248,6 +248,46 @@ static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) PCIE_INTR_ENABLE_ADDRESS); } +static irqreturn_t ath10k_pci_early_irq_handler(int irq, void *arg) +{ + struct ath10k *ar = arg; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (ar_pci->num_msi_intrs == 0) { + if (!ath10k_pci_irq_pending(ar)) + return IRQ_NONE; + + ath10k_pci_disable_and_clear_legacy_irq(ar); + } + + tasklet_schedule(&ar_pci->early_irq_tasklet); + + return IRQ_HANDLED; +} + +static int ath10k_pci_request_early_irq(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + /* Regardless whether MSI-X/MSI/legacy irqs have been set up the first + * interrupt from irq vector is triggered in all cases for FW + * indication/errors */ + ret = request_irq(ar_pci->pdev->irq, ath10k_pci_early_irq_handler, + IRQF_SHARED, "ath10k_pci (early)", ar); + if (ret) { + ath10k_warn("failed to request early irq: %d\n", ret); + return ret; + } + + return 0; +} + +static void ath10k_pci_free_early_irq(struct ath10k *ar) +{ + free_irq(ath10k_pci_priv(ar)->pdev->irq, ar); +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user @@ -937,6 +977,7 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) tasklet_kill(&ar_pci->intr_tq); tasklet_kill(&ar_pci->msi_fw_err); + tasklet_kill(&ar_pci->early_irq_tasklet); for (i = 0; i < CE_COUNT; i++) tasklet_kill(&ar_pci->pipe_info[i].intr); @@ -1249,12 +1290,15 @@ static int ath10k_pci_post_rx(struct ath10k *ar) static int ath10k_pci_hif_start(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ret; + int ret, ret_early; + + ath10k_pci_free_early_irq(ar); + ath10k_pci_kill_tasklet(ar); ret = ath10k_pci_alloc_compl(ar); if (ret) { ath10k_warn("failed to allocate CE completions: %d\n", ret); - return ret; + goto err_early_irq; } ret = ath10k_pci_request_irq(ar); @@ -1289,6 +1333,14 @@ err_stop: ath10k_pci_process_ce(ar); err_free_compl: ath10k_pci_cleanup_ce(ar); +err_early_irq: + /* Though there should be no interrupts (device was reset) + * power_down() expects the early IRQ to be installed as per the + * driver lifecycle. */ + ret_early = ath10k_pci_request_early_irq(ar); + if (ret_early) + ath10k_warn("failed to re-enable early irq: %d\n", ret_early); + return ret; } @@ -1422,6 +1474,10 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_pci_kill_tasklet(ar); ath10k_pci_stop_ce(ar); + ret = ath10k_pci_request_early_irq(ar); + if (ret) + ath10k_warn("failed to re-enable early irq: %d\n", ret); + /* At this point, asynchronous threads are stopped, the target should * not DMA nor interrupt. We process the leftovers and then free * everything else up. */ @@ -1970,22 +2026,28 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) goto err_ce; } + ret = ath10k_pci_request_early_irq(ar); + if (ret) { + ath10k_err("failed to request early irq: %d\n", ret); + goto err_deinit_irq; + } + ret = ath10k_pci_wait_for_target_init(ar); if (ret) { ath10k_err("failed to wait for target to init: %d\n", ret); - goto err_deinit_irq; + goto err_free_early_irq; } ret = ath10k_pci_init_config(ar); if (ret) { ath10k_err("failed to setup init config: %d\n", ret); - goto err_deinit_irq; + goto err_free_early_irq; } ret = ath10k_pci_wake_target_cpu(ar); if (ret) { ath10k_err("could not wake up target CPU: %d\n", ret); - goto err_deinit_irq; + goto err_free_early_irq; } if (ar_pci->num_msi_intrs > 1) @@ -2000,6 +2062,8 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) return 0; +err_free_early_irq: + ath10k_pci_free_early_irq(ar); err_deinit_irq: ath10k_pci_deinit_irq(ar); err_ce: @@ -2016,6 +2080,8 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + ath10k_pci_free_early_irq(ar); + ath10k_pci_kill_tasklet(ar); ath10k_pci_deinit_irq(ar); ath10k_pci_device_reset(ar); @@ -2164,6 +2230,34 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) return IRQ_HANDLED; } +static void ath10k_pci_early_irq_tasklet(unsigned long data) +{ + struct ath10k *ar = (struct ath10k *)data; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + u32 fw_ind; + int ret; + + ret = ath10k_pci_wake(ar); + if (ret) { + ath10k_warn("failed to wake target in early irq tasklet: %d\n", + ret); + return; + } + + fw_ind = ath10k_pci_read32(ar, ar_pci->fw_indicator_address); + if (fw_ind & FW_IND_EVENT_PENDING) { + ath10k_pci_write32(ar, ar_pci->fw_indicator_address, + fw_ind & ~FW_IND_EVENT_PENDING); + + /* Some structures are unavailable during early boot or at + * driver teardown so just print that the device has crashed. */ + ath10k_warn("device crashed - no diagnostics available\n"); + } + + ath10k_pci_sleep(ar); + ath10k_pci_enable_legacy_irq(ar); +} + static void ath10k_pci_tasklet(unsigned long data) { struct ath10k *ar = (struct ath10k *)data; @@ -2280,6 +2374,8 @@ static void ath10k_pci_init_irq_tasklets(struct ath10k *ar) tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar); tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet, (unsigned long)ar); + tasklet_init(&ar_pci->early_irq_tasklet, ath10k_pci_early_irq_tasklet, + (unsigned long)ar); for (i = 0; i < CE_COUNT; i++) { ar_pci->pipe_info[i].ar_pci = ar_pci; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 73a3d4ee6ebf..a4f32038c440 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -198,6 +198,7 @@ struct ath10k_pci { struct tasklet_struct intr_tq; struct tasklet_struct msi_fw_err; + struct tasklet_struct early_irq_tasklet; int started; -- cgit v1.2.3 From cfe9c45b21ce2649e31f7e5d997f9c26b56f29e9 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 25 Nov 2013 14:06:27 +0100 Subject: ath10k: allow explicit MSI/MSI-X disabling This can be useful for testing and debugging. This introduces new ath10k_pci module parameter `irq_mode`. By default it is 0, meaning automatic irq mode (MSI-X as long as both target HW and host platform supports it). The parameter works on a best effort basis. kvalo: fix typo "ayto" Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 47 +++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0a2d1c20e4df..1365b55e7cca 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -33,10 +33,21 @@ #include "ce.h" #include "pci.h" +enum ath10k_pci_irq_mode { + ATH10K_PCI_IRQ_AUTO = 0, + ATH10K_PCI_IRQ_LEGACY = 1, + ATH10K_PCI_IRQ_MSI = 2, +}; + static unsigned int ath10k_target_ps; +static unsigned int ath10k_pci_irq_mode = ATH10K_PCI_IRQ_AUTO; + module_param(ath10k_target_ps, uint, 0644); MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option"); +module_param_named(irq_mode, ath10k_pci_irq_mode, uint, 0644); +MODULE_PARM_DESC(irq_mode, "0: auto, 1: legacy, 2: msi (default: 0)"); + #define QCA988X_2_0_DEVICE_ID (0x003c) static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = { @@ -2387,27 +2398,37 @@ static void ath10k_pci_init_irq_tasklets(struct ath10k *ar) static int ath10k_pci_init_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + bool msix_supported = test_bit(ATH10K_PCI_FEATURE_MSI_X, + ar_pci->features); int ret; ath10k_pci_init_irq_tasklets(ar); - if (!test_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features)) - goto msi; + if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO && + !test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) + ath10k_info("limiting irq mode to: %d\n", ath10k_pci_irq_mode); /* Try MSI-X */ - ar_pci->num_msi_intrs = MSI_NUM_REQUEST; - ret = pci_enable_msi_block(ar_pci->pdev, ar_pci->num_msi_intrs); - if (ret == 0) - return 0; - if (ret > 0) - pci_disable_msi(ar_pci->pdev); + if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO && msix_supported) { + ar_pci->num_msi_intrs = MSI_NUM_REQUEST; + ret = pci_enable_msi_block(ar_pci->pdev, ar_pci->num_msi_intrs); + if (ret == 0) + return 0; + if (ret > 0) + pci_disable_msi(ar_pci->pdev); + + /* fall-through */ + } -msi: /* Try MSI */ - ar_pci->num_msi_intrs = 1; - ret = pci_enable_msi(ar_pci->pdev); - if (ret == 0) - return 0; + if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_LEGACY) { + ar_pci->num_msi_intrs = 1; + ret = pci_enable_msi(ar_pci->pdev); + if (ret == 0) + return 0; + + /* fall-through */ + } /* Try legacy irq * -- cgit v1.2.3 From 6d33a9a658f73e15ab41ddcfe36f4b774207ef1d Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 26 Nov 2013 14:57:40 +0100 Subject: ath10k: fix Tx status clearing Too much of tx info was being cleared. This caused issues in some setups with tx frame status reporting. This should fix some cases of stations not being able to associate to ath10k AP. Reported-By: Matti Laakso Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index d476b2cc9d78..22829803f087 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -75,7 +75,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ath10k_report_offchan_tx(htt->ar, msdu); info = IEEE80211_SKB_CB(msdu); - memset(info, 0, sizeof(*info)); + memset(&info->status, 0, sizeof(info->status)); if (tx_done->discard) { ieee80211_free_txskb(htt->ar->hw, msdu); -- cgit v1.2.3 From 3e6006e4aec37b6e0d524dad5c8f85f49f4507f5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 11:18:06 +0100 Subject: spi: sh-msiof: Fix warnings due to improper casts Cast pointers to uintptr_t instead of unsigned int. This fixes warnings on platforms where pointers have a different size than int. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index c74298cf70e2..86f822a656ef 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -421,7 +421,7 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on) } /* use spi->controller data for CS (same strategy as spi_gpio) */ - gpio_set_value((unsigned)spi->controller_data, value); + gpio_set_value((uintptr_t)spi->controller_data, value); if (is_on == BITBANG_CS_INACTIVE) { if (test_and_clear_bit(0, &p->flags)) { -- cgit v1.2.3 From 8e1c8096faae6b8ac788a1bbeeea126044cb485a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 01:41:44 +0100 Subject: spi: rcar: Fix uninitialized variable warning The transfer data length variable is set based on the desired access size, without a default case. This results in a compiler warning, even though the access size is always set to a supported value. Create a default case to silence the warning. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 58449ad4ad0d..a3dca1dfd8ab 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -268,7 +268,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size) spcmd = SPCMD_SPB_8BIT; else if (access_size == 16) spcmd = SPCMD_SPB_16BIT; - else if (access_size == 32) + else spcmd = SPCMD_SPB_32BIT; spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN; -- cgit v1.2.3 From 5ffbe2d90d81b8734eaf69ee4dad8507f318aad0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 01:41:45 +0100 Subject: spi: rcar: Fix pointer cast in the remove function The platform driver data is set to point to the rspi_data structure at probe time. Calling spi_master_get() on the pointer is just plain wrong and only works by chance. Fix it by using the platform driver data directly. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index a3dca1dfd8ab..621be5dbea31 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -885,14 +885,13 @@ static void rspi_release_dma(struct rspi_data *rspi) static int rspi_remove(struct platform_device *pdev) { - struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev)); + struct rspi_data *rspi = platform_get_drvdata(pdev); spi_unregister_master(rspi->master); rspi_release_dma(rspi); free_irq(platform_get_irq(pdev, 0), rspi); clk_put(rspi->clk); iounmap(rspi->addr); - spi_master_put(rspi->master); return 0; } -- cgit v1.2.3 From 5d79e9ac89b45643c98b68ea7ce62c80b3b4e160 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 01:41:46 +0100 Subject: spi: rcar: Use devm_* managed allocators This simplies error and cleanup code paths. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 621be5dbea31..19c65c43cbc5 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -889,9 +889,6 @@ static int rspi_remove(struct platform_device *pdev) spi_unregister_master(rspi->master); rspi_release_dma(rspi); - free_irq(platform_get_irq(pdev, 0), rspi); - clk_put(rspi->clk); - iounmap(rspi->addr); return 0; } @@ -913,12 +910,6 @@ static int rspi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "there is no set_config_register\n"); return -ENODEV; } - /* get base addr */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(res == NULL)) { - dev_err(&pdev->dev, "invalid resource\n"); - return -EINVAL; - } irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -936,19 +927,20 @@ static int rspi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rspi); rspi->ops = ops; rspi->master = master; - rspi->addr = ioremap(res->start, resource_size(res)); - if (rspi->addr == NULL) { - dev_err(&pdev->dev, "ioremap error.\n"); - ret = -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rspi->addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rspi->addr)) { + ret = PTR_ERR(rspi->addr); goto error1; } snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id); - rspi->clk = clk_get(&pdev->dev, clk_name); + rspi->clk = devm_clk_get(&pdev->dev, clk_name); if (IS_ERR(rspi->clk)) { dev_err(&pdev->dev, "cannot get clock\n"); ret = PTR_ERR(rspi->clk); - goto error2; + goto error1; } clk_enable(rspi->clk); @@ -966,36 +958,32 @@ static int rspi_probe(struct platform_device *pdev) master->transfer = rspi_transfer; master->cleanup = rspi_cleanup; - ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi); + ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0, + dev_name(&pdev->dev), rspi); if (ret < 0) { dev_err(&pdev->dev, "request_irq error\n"); - goto error3; + goto error1; } rspi->irq = irq; ret = rspi_request_dma(rspi, pdev); if (ret < 0) { dev_err(&pdev->dev, "rspi_request_dma failed.\n"); - goto error4; + goto error2; } ret = spi_register_master(master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master error.\n"); - goto error4; + goto error2; } dev_info(&pdev->dev, "probed\n"); return 0; -error4: - rspi_release_dma(rspi); - free_irq(irq, rspi); -error3: - clk_put(rspi->clk); error2: - iounmap(rspi->addr); + rspi_release_dma(rspi); error1: spi_master_put(master); -- cgit v1.2.3 From 7ad35442fc07689eea3e6357390ae7c8fd9ef53c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 02:18:36 +0100 Subject: spi: sh-msiof: Enable driver compilation with COMPILE_TEST This helps increasing build testing coverage. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index eb1f1ef5fa2e..51ae940adce2 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -407,7 +407,8 @@ config SPI_SC18IS602 config SPI_SH_MSIOF tristate "SuperH MSIOF SPI controller" - depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK + depends on HAVE_CLK + depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST select SPI_BITBANG help SPI driver for SuperH and SH Mobile MSIOF blocks. -- cgit v1.2.3 From dc844b0d99b8533d6174e5b9a369f7c2cdacfe66 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 11 Nov 2013 13:26:06 +0200 Subject: mei: remove flash_work_queue Cancel each work properly and remove flash_work_queue. Quoting documentation: In most situations flushing the entire workqueue is overkill; you merely need to know that a particular work item isn't queued and isn't running. In such cases you should use cancel_delayed_work_sync() or cancel_work_sync() instead. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/init.c | 17 ++++++++++++----- drivers/misc/mei/mei_dev.h | 3 ++- drivers/misc/mei/nfc.c | 6 +++++- drivers/misc/mei/pci-me.c | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index f7f3abbe12b6..83c879bf9967 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -131,6 +131,15 @@ err: } EXPORT_SYMBOL_GPL(mei_start); + +void mei_cancel_work(struct mei_device *dev) +{ + cancel_work_sync(&dev->init_work); + + cancel_delayed_work(&dev->timer_work); +} +EXPORT_SYMBOL_GPL(mei_cancel_work); + /** * mei_reset - resets host and fw. * @@ -215,16 +224,14 @@ void mei_stop(struct mei_device *dev) { dev_dbg(&dev->pdev->dev, "stopping the device.\n"); - flush_scheduled_work(); + mei_cancel_work(dev); - mutex_lock(&dev->device_lock); + mei_nfc_host_exit(dev); - cancel_delayed_work(&dev->timer_work); + mutex_lock(&dev->device_lock); mei_wd_stop(dev); - mei_nfc_host_exit(); - dev->dev_state = MEI_DEV_POWER_DOWN; mei_reset(dev, 0); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 406f68e05b4e..6f577bf5dc9d 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -463,6 +463,7 @@ void mei_device_init(struct mei_device *dev); void mei_reset(struct mei_device *dev, int interrupts); int mei_start(struct mei_device *dev); void mei_stop(struct mei_device *dev); +void mei_cancel_work(struct mei_device *dev); /* * MEI interrupt functions prototype @@ -510,7 +511,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); * NFC functions */ int mei_nfc_host_init(struct mei_device *dev); -void mei_nfc_host_exit(void); +void mei_nfc_host_exit(struct mei_device *dev); /* * NFC Client UUID diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c index 994ca4aff1a3..0a892205ce7e 100644 --- a/drivers/misc/mei/nfc.c +++ b/drivers/misc/mei/nfc.c @@ -547,12 +547,16 @@ err: return ret; } -void mei_nfc_host_exit(void) +void mei_nfc_host_exit(struct mei_device *dev) { struct mei_nfc_dev *ndev = &nfc_dev; + cancel_work_sync(&ndev->init_work); + + mutex_lock(&dev->device_lock); if (ndev->cl && ndev->cl->device) mei_cl_remove_device(ndev->cl->device); mei_nfc_free(ndev); + mutex_unlock(&dev->device_lock); } diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index b96205aece0c..3bfae3843d95 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -195,8 +195,8 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; release_irq: + mei_cancel_work(dev); mei_disable_interrupts(dev); - flush_scheduled_work(); free_irq(pdev->irq, dev); disable_msi: pci_disable_msi(pdev); -- cgit v1.2.3 From 0f1d4ce5d0d09de5db92df7f51cdf7163bbb61f9 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Mon, 11 Nov 2013 13:26:07 +0200 Subject: mei: drop redundant list_del_init list_del_init appears twice in row in mei_cl_unlink, drop one. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 87c96e4669e2..6184e854ae1e 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -344,8 +344,6 @@ int mei_cl_unlink(struct mei_cl *cl) cl->state = MEI_FILE_INITIALIZING; - list_del_init(&cl->link); - return 0; } -- cgit v1.2.3 From 10ee90743e99fb06a0881a35731263c1845275dd Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 11 Nov 2013 13:26:08 +0200 Subject: mei: cleanup mei_irq_read_handler 1. Simplify function flow 2. Display errors in error or warnings level instead of debug. 3. Remove excessive debug messages Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 79 ++++++++++++++++++++++---------------------- drivers/misc/mei/mei_dev.h | 10 ++++++ 2 files changed, 50 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 7a95c07e59a6..9c8225b945c3 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -301,13 +301,11 @@ int mei_irq_read_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list, s32 *slots) { struct mei_msg_hdr *mei_hdr; - struct mei_cl *cl_pos = NULL; - struct mei_cl *cl_next = NULL; - int ret = 0; + struct mei_cl *cl; + int ret; if (!dev->rd_msg_hdr) { dev->rd_msg_hdr = mei_read_hdr(dev); - dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); (*slots)--; dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); } @@ -315,61 +313,64 @@ int mei_irq_read_handler(struct mei_device *dev, dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); if (mei_hdr->reserved || !dev->rd_msg_hdr) { - dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); + dev_err(&dev->pdev->dev, "corrupted message header 0x%08X\n", + dev->rd_msg_hdr); ret = -EBADMSG; goto end; } - if (mei_hdr->host_addr || mei_hdr->me_addr) { - list_for_each_entry_safe(cl_pos, cl_next, - &dev->file_list, link) { - dev_dbg(&dev->pdev->dev, - "list_for_each_entry_safe read host" - " client = %d, ME client = %d\n", - cl_pos->host_client_id, - cl_pos->me_client_id); - if (mei_cl_hbm_equal(cl_pos, mei_hdr)) - break; - } - - if (&cl_pos->link == &dev->file_list) { - dev_dbg(&dev->pdev->dev, "corrupted message header\n"); - ret = -EBADMSG; - goto end; - } - } - if (((*slots) * sizeof(u32)) < mei_hdr->length) { - dev_err(&dev->pdev->dev, - "we can't read the message slots =%08x.\n", + if (mei_slots2data(*slots) < mei_hdr->length) { + dev_err(&dev->pdev->dev, "less data available than length=%08x.\n", *slots); /* we can't read the message */ ret = -ERANGE; goto end; } - /* decide where to read the message too */ - if (!mei_hdr->host_addr) { - dev_dbg(&dev->pdev->dev, "call mei_hbm_dispatch.\n"); + /* HBM message */ + if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) { mei_hbm_dispatch(dev, mei_hdr); - dev_dbg(&dev->pdev->dev, "end mei_hbm_dispatch.\n"); - } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && - (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && - (dev->iamthif_state == MEI_IAMTHIF_READING)) { + ret = 0; + dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch.\n"); + goto reset_slots; + } - dev_dbg(&dev->pdev->dev, "call mei_amthif_irq_read_msg.\n"); - dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); + /* find recepient cl */ + list_for_each_entry(cl, &dev->file_list, link) { + if (mei_cl_hbm_equal(cl, mei_hdr)) { + cl_dbg(dev, cl, "got a message\n"); + break; + } + } + + /* if no recepient cl was found we assume corrupted header\n */ + if (&cl->link == &dev->file_list) { + dev_err(&dev->pdev->dev, "no destination client found 0x%08X\n", + dev->rd_msg_hdr); + ret = -EBADMSG; + goto end; + } + + if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && + MEI_FILE_CONNECTED == dev->iamthif_cl.state && + dev->iamthif_state == MEI_IAMTHIF_READING) { ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list); - if (ret) + if (ret) { + dev_err(&dev->pdev->dev, "mei_amthif_irq_read_msg failed = %d\n", + ret); goto end; + } } else { - dev_dbg(&dev->pdev->dev, "call mei_cl_irq_read_msg.\n"); - dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list); - if (ret) + if (ret) { + dev_err(&dev->pdev->dev, "mei_cl_irq_read_msg failed = %d\n", + ret); goto end; + } } +reset_slots: /* reset the number of slots and header */ *slots = mei_count_full_read_slots(dev); dev->rd_msg_hdr = 0; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 6f577bf5dc9d..4a7ee815fab1 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -456,6 +456,16 @@ static inline u32 mei_data2slots(size_t length) return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); } +/** + * mei_slots2data- get data in slots - bytes from slots + * @slots - number of available slots + * returns - number of bytes in slots + */ +static inline u32 mei_slots2data(int slots) +{ + return slots * 4; +} + /* * mei init function prototypes */ -- cgit v1.2.3 From b5f98e65c0d887388eb9cbf55c76cb97fb4c2187 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 27 Nov 2013 09:39:49 -0600 Subject: clk: clean up everything on debugfs error [Maybe the third time will be the charm. -Alex] If CONFIG_COMMON_CLK_DEBUG is defined, clk_debug_create_one() is called to populate a debugfs directory with a few entries that are common for all clock types. If an error happens after creating the first one debugfs_remove() is called on the clock's directory. The problem with this is that no cleanup is done on the debugfs files already created in that directory, so the directory never actually gets removed. This problem is silently ignored. Fix this by calling debugfs_remove_recursive() instead. Reset the clk->dentry field to null afterward, to ensure it can't be mistaken as a valid pointer. Signed-off-by: Alex Elder Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2cf2ea6b77a1..77fcd069c64a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -272,7 +272,8 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) goto out; err_out: - debugfs_remove(clk->dentry); + debugfs_remove_recursive(clk->dentry); + clk->dentry = NULL; out: return ret; } -- cgit v1.2.3 From 4d04391cfe6446fb2f184d063b56a4dcce425334 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 24 Oct 2013 03:18:30 -0500 Subject: clk: socfpga: Remove check for "reg" property in socfpga_clk_init The function socfpga_clk_init() can support clocks that do not have a divider register, but a fixed-divider that can be read from DTS. Therefore, the "reg" property is not a failing condition for socfpga_clk_init(). Signed-off-by: Dinh Nguyen Signed-off-by: Mike Turquette --- drivers/clk/socfpga/clk.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index 81dd31a686df..c3784899f002 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c @@ -121,9 +121,7 @@ static __init struct clk *socfpga_clk_init(struct device_node *node, int rc; u32 fixed_div; - rc = of_property_read_u32(node, "reg", ®); - if (WARN_ON(rc)) - return NULL; + of_property_read_u32(node, "reg", ®); socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); if (WARN_ON(!socfpga_clk)) -- cgit v1.2.3 From c8d9a5905e45d856fb21cce2e20f186ce6719560 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 23 Nov 2013 14:55:42 +0530 Subject: drm/i915: Add power well arguments to force wake routines. Added power well arguments to all the force wake routines to help us individually control power well based on the scenario. Signed-off-by: Deepak S Reviewed-by: Jesse Barnes [danvet: Resolve conflict with the removed forcewake hack and drop one spurious hunk Jesse noticed.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 8 +++--- drivers/gpu/drm/i915/i915_drv.h | 15 ++++++++--- drivers/gpu/drm/i915/intel_display.c | 4 +-- drivers/gpu/drm/i915/intel_pm.c | 19 ++++++++------ drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +-- drivers/gpu/drm/i915/intel_uncore.c | 44 +++++++++++++++++++-------------- 6 files changed, 56 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6600447ad0d5..1a4c559a9689 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -947,7 +947,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) if (ret) return ret; - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); reqf = I915_READ(GEN6_RPNSWREQ); reqf &= ~GEN6_TURBO_DISABLE; @@ -970,7 +970,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; cagf *= GT_FREQUENCY_MULTIPLIER; - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); @@ -3053,7 +3053,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file) if (INTEL_INFO(dev)->gen < 6) return 0; - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); return 0; } @@ -3066,7 +3066,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file) if (INTEL_INFO(dev)->gen < 6) return 0; - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 49dfac9028e3..9b219d3bf233 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -437,8 +437,10 @@ struct drm_i915_display_funcs { }; struct intel_uncore_funcs { - void (*force_wake_get)(struct drm_i915_private *dev_priv); - void (*force_wake_put)(struct drm_i915_private *dev_priv); + void (*force_wake_get)(struct drm_i915_private *dev_priv, + int fw_engine); + void (*force_wake_put)(struct drm_i915_private *dev_priv, + int fw_engine); uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace); uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace); @@ -2438,8 +2440,8 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, * must be set to prevent GT core from power down and stale values being * returned. */ -void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); -void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine); +void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine); int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val); int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val); @@ -2468,6 +2470,11 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); +#define FORCEWAKE_RENDER (1 << 0) +#define FORCEWAKE_MEDIA (1 << 1) +#define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA) + + #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 784ff70a95eb..ca467cb3c1b4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6583,7 +6583,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) /* Make sure we're not on PC8 state before disabling PC8, otherwise * we'll hang the machine! */ - dev_priv->uncore.funcs.force_wake_get(dev_priv); + dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -6617,7 +6617,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) DRM_ERROR("Switching back to LCPLL failed\n"); } - dev_priv->uncore.funcs.force_wake_put(dev_priv); + dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); } void hsw_enable_pc8_work(struct work_struct *__work) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2f8399c347ee..fd2537d429f2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -191,7 +191,8 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) u32 blt_ecoskpd; /* Make sure blitter notifies FBC of writes */ - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << GEN6_BLITTER_LOCK_SHIFT; @@ -202,7 +203,8 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) GEN6_BLITTER_LOCK_SHIFT); I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); POSTING_READ(GEN6_BLITTER_ECOSKPD); - gen6_gt_force_wake_put(dev_priv); + + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) @@ -3739,7 +3741,7 @@ static void gen8_enable_rps(struct drm_device *dev) /* 1c & 1d: Get forcewake during program sequence. Although the driver * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); /* 2a: Disable RC states. */ I915_WRITE(GEN6_RC_CONTROL, 0); @@ -3796,7 +3798,7 @@ static void gen8_enable_rps(struct drm_device *dev) gen6_enable_rps_interrupts(dev); - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } static void gen6_enable_rps(struct drm_device *dev) @@ -3826,7 +3828,7 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GTFIFODBG, gtfifodbg); } - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); @@ -3918,7 +3920,7 @@ static void gen6_enable_rps(struct drm_device *dev) DRM_ERROR("Couldn't fix incorrect rc6 voltage\n"); } - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } void gen6_update_ring_freq(struct drm_device *dev) @@ -4080,7 +4082,8 @@ static void valleyview_enable_rps(struct drm_device *dev) valleyview_setup_pctx(dev); - gen6_gt_force_wake_get(dev_priv); + /* If VLV, Forcewake all wells, else re-direct to regular path */ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); @@ -4152,7 +4155,7 @@ static void valleyview_enable_rps(struct drm_device *dev) gen6_enable_rps_interrupts(dev); - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } void ironlake_teardown_rc6(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 69589e4f957f..e05a0216cd9b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -438,7 +438,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) int ret = 0; u32 head; - gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); if (I915_NEED_GFX_HWS(dev)) intel_ring_setup_status_page(ring); @@ -511,7 +511,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); out: - gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); return ret; } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 07c0ad0e1583..d7c3f5effc79 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -64,7 +64,8 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, ECOBUS); } -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, + int fw_engine) { if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0, FORCEWAKE_ACK_TIMEOUT_MS)) @@ -89,7 +90,8 @@ static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, ECOBUS); } -static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv, + int fw_engine) { u32 forcewake_ack; @@ -126,7 +128,8 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) __raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); } -static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, + int fw_engine) { __raw_i915_write32(dev_priv, FORCEWAKE, 0); /* something from same cacheline, but !FORCEWAKE */ @@ -134,7 +137,8 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) gen6_gt_check_fifodbg(dev_priv); } -static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv, + int fw_engine) { __raw_i915_write32(dev_priv, FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); @@ -171,7 +175,7 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV); } -static void vlv_force_wake_get(struct drm_i915_private *dev_priv) +static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) { if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0, FORCEWAKE_ACK_TIMEOUT_MS)) @@ -195,7 +199,7 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) __gen6_gt_wait_for_thread_c0(dev_priv); } -static void vlv_force_wake_put(struct drm_i915_private *dev_priv) +static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) { __raw_i915_write32(dev_priv, FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); @@ -213,7 +217,7 @@ static void gen6_force_wake_work(struct work_struct *work) spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (--dev_priv->uncore.forcewake_count == 0) - dev_priv->uncore.funcs.force_wake_put(dev_priv); + dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -279,7 +283,7 @@ void intel_uncore_sanitize(struct drm_device *dev) * be called at the beginning of the sequence followed by a call to * gen6_gt_force_wake_put() at the end of the sequence. */ -void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) { unsigned long irqflags; @@ -288,14 +292,14 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (dev_priv->uncore.forcewake_count++ == 0) - dev_priv->uncore.funcs.force_wake_get(dev_priv); + dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } /* * see gen6_gt_force_wake_get() */ -void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) { unsigned long irqflags; @@ -377,10 +381,12 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ REG_READ_HEADER(x); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ if (dev_priv->uncore.forcewake_count == 0) \ - dev_priv->uncore.funcs.force_wake_get(dev_priv); \ + dev_priv->uncore.funcs.force_wake_get(dev_priv, \ + FORCEWAKE_ALL); \ val = __raw_i915_read##x(dev_priv, reg); \ if (dev_priv->uncore.forcewake_count == 0) \ - dev_priv->uncore.funcs.force_wake_put(dev_priv); \ + dev_priv->uncore.funcs.force_wake_put(dev_priv, \ + FORCEWAKE_ALL); \ } else { \ val = __raw_i915_read##x(dev_priv, reg); \ } \ @@ -487,11 +493,13 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \ REG_WRITE_HEADER; \ if (__needs_put) { \ - dev_priv->uncore.funcs.force_wake_get(dev_priv); \ + dev_priv->uncore.funcs.force_wake_get(dev_priv, \ + FORCEWAKE_ALL); \ } \ __raw_i915_write##x(dev_priv, reg, val); \ if (__needs_put) { \ - dev_priv->uncore.funcs.force_wake_put(dev_priv); \ + dev_priv->uncore.funcs.force_wake_put(dev_priv, \ + FORCEWAKE_ALL); \ } \ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ } @@ -550,9 +558,9 @@ void intel_uncore_init(struct drm_device *dev) * forcewake being disabled. */ mutex_lock(&dev->struct_mutex); - __gen6_gt_force_wake_mt_get(dev_priv); + __gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL); ecobus = __raw_i915_read32(dev_priv, ECOBUS); - __gen6_gt_force_wake_mt_put(dev_priv); + __gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); if (ecobus & FORCEWAKE_MT_ENABLE) { @@ -805,9 +813,9 @@ static int gen6_do_reset(struct drm_device *dev) /* If reset with a user forcewake, try to restore, otherwise turn it off */ if (dev_priv->uncore.forcewake_count) - dev_priv->uncore.funcs.force_wake_get(dev_priv); + dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); else - dev_priv->uncore.funcs.force_wake_put(dev_priv); + dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); /* Restore fifo count */ dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); -- cgit v1.2.3 From 940aece471bd6656b86f5d77132b6670a3b88dc8 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 23 Nov 2013 14:55:43 +0530 Subject: drm/i915/vlv: Valleyview support for forcewake Individual power wells. Split vlv force wake routines to help individually control Media/Render well based on the register access. We've seen power savings in the lower sub-1W range on workloads that only need on of the power wells, e.g. glbenchmark, media playback Note: The same split isn't there for the forcewake queue, only the forcwake domains are split. Signed-off-by: Deepak S Reviewed-by: Jesse Barnes [danvet: Rebase on top of the removed forcewake hack in the ring irq get/put code and add a note to add Deepak's answer to Chris question.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 17 ++++ drivers/gpu/drm/i915/intel_pm.c | 7 +- drivers/gpu/drm/i915/intel_uncore.c | 183 ++++++++++++++++++++++++++++++------ 3 files changed, 176 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9b219d3bf233..6b18b4714d7e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -465,6 +465,9 @@ struct intel_uncore { unsigned fifo_count; unsigned forcewake_count; + unsigned fw_rendercount; + unsigned fw_mediacount; + struct delayed_work force_wake_work; }; @@ -2470,6 +2473,20 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); +void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine); +void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine); + +#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \ + (((reg) >= 0x2000 && (reg) < 0x4000) ||\ + ((reg) >= 0x5000 && (reg) < 0x8000) ||\ + ((reg) >= 0xB000 && (reg) < 0x12000) ||\ + ((reg) >= 0x2E000 && (reg) < 0x30000)) + +#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\ + (((reg) >= 0x12000 && (reg) < 0x14000) ||\ + ((reg) >= 0x22000 && (reg) < 0x24000) ||\ + ((reg) >= 0x30000 && (reg) < 0x40000)) + #define FORCEWAKE_RENDER (1 << 0) #define FORCEWAKE_MEDIA (1 << 1) #define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fd2537d429f2..1659265a7f7a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -191,7 +191,10 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) u32 blt_ecoskpd; /* Make sure blitter notifies FBC of writes */ - gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + + /* Blitter is part of Media powerwell on VLV. No impact of + * his param in other platforms for now */ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA); blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << @@ -204,7 +207,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); POSTING_READ(GEN6_BLITTER_ECOSKPD); - gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA); } static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d7c3f5effc79..d002e30aaae0 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -175,38 +175,112 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV); } -static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) -{ - if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0, - FORCEWAKE_ACK_TIMEOUT_MS)) - DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); - - __raw_i915_write32(dev_priv, FORCEWAKE_VLV, - _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, - _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - - if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL), - FORCEWAKE_ACK_TIMEOUT_MS)) - DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n"); +static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, + int fw_engine) +{ + /* Check for Render Engine */ + if (FORCEWAKE_RENDER & fw_engine) { + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_VLV) & + FORCEWAKE_KERNEL) == 0, + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: Render forcewake old ack to clear.\n"); + + __raw_i915_write32(dev_priv, FORCEWAKE_VLV, + _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); + + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_VLV) & + FORCEWAKE_KERNEL), + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: waiting for Render to ack.\n"); + } - if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_MEDIA_VLV) & - FORCEWAKE_KERNEL), - FORCEWAKE_ACK_TIMEOUT_MS)) - DRM_ERROR("Timed out waiting for media to ack forcewake request.\n"); + /* Check for Media Engine */ + if (FORCEWAKE_MEDIA & fw_engine) { + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_MEDIA_VLV) & + FORCEWAKE_KERNEL) == 0, + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: Media forcewake old ack to clear.\n"); + + __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, + _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); + + if (wait_for_atomic((__raw_i915_read32(dev_priv, + FORCEWAKE_ACK_MEDIA_VLV) & + FORCEWAKE_KERNEL), + FORCEWAKE_ACK_TIMEOUT_MS)) + DRM_ERROR("Timed out: waiting for media to ack.\n"); + } /* WaRsForcewakeWaitTC0:vlv */ __gen6_gt_wait_for_thread_c0(dev_priv); + } -static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) +static void __vlv_force_wake_put(struct drm_i915_private *dev_priv, + int fw_engine) { - __raw_i915_write32(dev_priv, FORCEWAKE_VLV, - _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, - _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); + + /* Check for Render Engine */ + if (FORCEWAKE_RENDER & fw_engine) + __raw_i915_write32(dev_priv, FORCEWAKE_VLV, + _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); + + + /* Check for Media Engine */ + if (FORCEWAKE_MEDIA & fw_engine) + __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, + _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); + /* The below doubles as a POSTING_READ */ gen6_gt_check_fifodbg(dev_priv); + +} + +void vlv_force_wake_get(struct drm_i915_private *dev_priv, + int fw_engine) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (FORCEWAKE_RENDER & fw_engine) { + if (dev_priv->uncore.fw_rendercount++ == 0) + dev_priv->uncore.funcs.force_wake_get(dev_priv, + FORCEWAKE_RENDER); + } + if (FORCEWAKE_MEDIA & fw_engine) { + if (dev_priv->uncore.fw_mediacount++ == 0) + dev_priv->uncore.funcs.force_wake_get(dev_priv, + FORCEWAKE_MEDIA); + } + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +void vlv_force_wake_put(struct drm_i915_private *dev_priv, + int fw_engine) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + if (FORCEWAKE_RENDER & fw_engine) { + WARN_ON(dev_priv->uncore.fw_rendercount == 0); + if (--dev_priv->uncore.fw_rendercount == 0) + dev_priv->uncore.funcs.force_wake_put(dev_priv, + FORCEWAKE_RENDER); + } + + if (FORCEWAKE_MEDIA & fw_engine) { + WARN_ON(dev_priv->uncore.fw_mediacount == 0); + if (--dev_priv->uncore.fw_mediacount == 0) + dev_priv->uncore.funcs.force_wake_put(dev_priv, + FORCEWAKE_MEDIA); + } + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void gen6_force_wake_work(struct work_struct *work) @@ -290,6 +364,10 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) if (!dev_priv->uncore.funcs.force_wake_get) return; + /* Redirect to VLV specific routine */ + if (IS_VALLEYVIEW(dev_priv->dev)) + return vlv_force_wake_get(dev_priv, fw_engine); + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (dev_priv->uncore.forcewake_count++ == 0) dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); @@ -306,6 +384,11 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) if (!dev_priv->uncore.funcs.force_wake_put) return; + /* Redirect to VLV specific routine */ + if (IS_VALLEYVIEW(dev_priv->dev)) + return vlv_force_wake_put(dev_priv, fw_engine); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (--dev_priv->uncore.forcewake_count == 0) { dev_priv->uncore.forcewake_count++; @@ -393,6 +476,39 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ REG_READ_FOOTER; \ } +#define __vlv_read(x) \ +static u##x \ +vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ + unsigned fwengine = 0; \ + unsigned *fwcount = 0; \ + REG_READ_HEADER(x); \ + if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) { \ + fwengine = FORCEWAKE_RENDER; \ + fwcount = &dev_priv->uncore.fw_rendercount; \ + } \ + else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) { \ + fwengine = FORCEWAKE_MEDIA; \ + fwcount = &dev_priv->uncore.fw_mediacount; \ + } \ + if (fwengine != 0) { \ + if ((*fwcount)++ == 0) \ + (dev_priv)->uncore.funcs.force_wake_get(dev_priv, \ + fwengine); \ + val = __raw_i915_read##x(dev_priv, reg); \ + if (--(*fwcount) == 0) \ + (dev_priv)->uncore.funcs.force_wake_put(dev_priv, \ + FORCEWAKE_ALL); \ + } else { \ + val = __raw_i915_read##x(dev_priv, reg); \ + } \ + REG_READ_FOOTER; \ +} + + +__vlv_read(8) +__vlv_read(16) +__vlv_read(32) +__vlv_read(64) __gen6_read(8) __gen6_read(16) __gen6_read(32) @@ -406,6 +522,7 @@ __gen4_read(16) __gen4_read(32) __gen4_read(64) +#undef __vlv_read #undef __gen6_read #undef __gen5_read #undef __gen4_read @@ -540,8 +657,8 @@ void intel_uncore_init(struct drm_device *dev) gen6_force_wake_work); if (IS_VALLEYVIEW(dev)) { - dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get; - dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put; + dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; + dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put; } else if (IS_HASWELL(dev) || IS_GEN8(dev)) { dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get; dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put; @@ -607,10 +724,18 @@ void intel_uncore_init(struct drm_device *dev) dev_priv->uncore.funcs.mmio_writel = gen6_write32; dev_priv->uncore.funcs.mmio_writeq = gen6_write64; } - dev_priv->uncore.funcs.mmio_readb = gen6_read8; - dev_priv->uncore.funcs.mmio_readw = gen6_read16; - dev_priv->uncore.funcs.mmio_readl = gen6_read32; - dev_priv->uncore.funcs.mmio_readq = gen6_read64; + + if (IS_VALLEYVIEW(dev)) { + dev_priv->uncore.funcs.mmio_readb = vlv_read8; + dev_priv->uncore.funcs.mmio_readw = vlv_read16; + dev_priv->uncore.funcs.mmio_readl = vlv_read32; + dev_priv->uncore.funcs.mmio_readq = vlv_read64; + } else { + dev_priv->uncore.funcs.mmio_readb = gen6_read8; + dev_priv->uncore.funcs.mmio_readw = gen6_read16; + dev_priv->uncore.funcs.mmio_readl = gen6_read32; + dev_priv->uncore.funcs.mmio_readq = gen6_read64; + } break; case 5: dev_priv->uncore.funcs.mmio_writeb = gen5_write8; -- cgit v1.2.3 From 43709ba0d828b3706ace6980d875b762f90ce472 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 23 Nov 2013 14:55:44 +0530 Subject: drm/i915: Enabling DebugFS for valleyview forcewake counts Forcewake counts for valleyview are not exposed throgh DebugFS. Exposing with this change. Signed-off-by: Deepak S Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1a4c559a9689..13accf795548 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1564,13 +1564,21 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - unsigned forcewake_count; + unsigned forcewake_count = 0, fw_rendercount = 0, fw_mediacount = 0; spin_lock_irq(&dev_priv->uncore.lock); - forcewake_count = dev_priv->uncore.forcewake_count; + if (IS_VALLEYVIEW(dev)) { + fw_rendercount = dev_priv->uncore.fw_rendercount; + fw_mediacount = dev_priv->uncore.fw_mediacount; + } else + forcewake_count = dev_priv->uncore.forcewake_count; spin_unlock_irq(&dev_priv->uncore.lock); - seq_printf(m, "forcewake count = %u\n", forcewake_count); + if (IS_VALLEYVIEW(dev)) { + seq_printf(m, "fw_rendercount = %u\n", fw_rendercount); + seq_printf(m, "fw_mediacount = %u\n", fw_mediacount); + } else + seq_printf(m, "forcewake count = %u\n", forcewake_count); return 0; } -- cgit v1.2.3 From 90f256b5bbdd5c69e5a7bbaec690bc4821bb2272 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Nov 2013 01:59:59 +0200 Subject: drm/i915: Report all GTFIFODBG errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On VLV GTFIFODBG has more bits. Just report them all. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 5 ++++- drivers/gpu/drm/i915/intel_uncore.c | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f2104f5e3af7..4f84573c5ad6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4857,7 +4857,10 @@ #define FORCEWAKE_MT_ENABLE (1<<5) #define GTFIFODBG 0x120000 -#define GT_FIFO_CPU_ERROR_MASK 7 +#define GT_FIFO_SBDROPERR (1<<6) +#define GT_FIFO_BLOBDROPERR (1<<5) +#define GT_FIFO_SB_READ_ABORTERR (1<<4) +#define GT_FIFO_DROPERR (1<<3) #define GT_FIFO_OVFERR (1<<2) #define GT_FIFO_IAWRERR (1<<1) #define GT_FIFO_IARDERR (1<<0) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d002e30aaae0..cff6610601f6 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -123,9 +123,8 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) u32 gtfifodbg; gtfifodbg = __raw_i915_read32(dev_priv, GTFIFODBG); - if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, - "MMIO read or write has been dropped %x\n", gtfifodbg)) - __raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); + if (WARN(gtfifodbg, "GT wake FIFO error 0x%x\n", gtfifodbg)) + __raw_i915_write32(dev_priv, GTFIFODBG, gtfifodbg); } static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From 46520e2baa861a02c14d3d590d5897092950c62a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Nov 2013 02:00:00 +0200 Subject: drm/i915: Fix GT wake FIFO free entries for VLV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On VLV the GTFIFOCTL register has other bits besides the number of free entries in the GT wake FIFO. Apply a mask when we read th register to make sure we don't misinterpret the number of free FIFO entries. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes [danvet: There's some unclarity about hsw, but brushed off as todays' Bspec just acting up a bit.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 ++- drivers/gpu/drm/i915/intel_uncore.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4f84573c5ad6..2658d975279b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4865,7 +4865,8 @@ #define GT_FIFO_IAWRERR (1<<1) #define GT_FIFO_IARDERR (1<<0) -#define GT_FIFO_FREE_ENTRIES 0x120008 +#define GTFIFOCTL 0x120008 +#define GT_FIFO_FREE_ENTRIES_MASK 0x7f #define GT_FIFO_NUM_RESERVED_ENTRIES 20 #define HSW_IDICR 0x9008 diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index cff6610601f6..97ae8bda7a1e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -152,10 +152,10 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { int loop = 500; - u32 fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); + u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { udelay(10); - fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); + fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; } if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) ++ret; @@ -942,7 +942,7 @@ static int gen6_do_reset(struct drm_device *dev) dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); /* Restore fifo count */ - dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES); + dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); return ret; -- cgit v1.2.3 From 084054fc05c7798ff7cf61e25c246f222f41db5b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Nov 2013 20:47:58 +0100 Subject: drm/i915: drop the right force-wake engine in the vlv mmio funcs This was fumbled in the conversion to per-engine forcewake. Cc: Deepak S Cc: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 97ae8bda7a1e..a7c6de7d6240 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -496,7 +496,7 @@ vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ val = __raw_i915_read##x(dev_priv, reg); \ if (--(*fwcount) == 0) \ (dev_priv)->uncore.funcs.force_wake_put(dev_priv, \ - FORCEWAKE_ALL); \ + fwengine); \ } else { \ val = __raw_i915_read##x(dev_priv, reg); \ } \ -- cgit v1.2.3 From 5bc0e85cc6207650535e579b0995aa9574a8ecba Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Nov 2013 20:52:23 +0100 Subject: drm/i915: make sparse happy for the new vlv mmio read function It doesn't like that we assign 0 to a pointer, it wants the real NULL. On closer look that initialization is actually bogus, and the compiler can easily see that we never use it unitialized. So let's just drop this. Cc: Deepak S Cc: Jesse Barnes Reported-by: kbuild test robot Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a7c6de7d6240..d511e00095ac 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -479,7 +479,7 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ static u##x \ vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ unsigned fwengine = 0; \ - unsigned *fwcount = 0; \ + unsigned *fwcount; \ REG_READ_HEADER(x); \ if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) { \ fwengine = FORCEWAKE_RENDER; \ -- cgit v1.2.3 From 84fcb46977e57bafba40bde32067bacc1e510f9c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Nov 2013 16:03:01 +0100 Subject: drm/i915/sdvo: Fix up debug output to not split lines It leads to a big mess when stuff interleaves. Especially with the new patch I've submitted for the drm core to no longer artificially split up debug messages. v2: The size parameter to snprintf includes the terminating 0, but the return value does not. Adjust the logic accordingly. Spotted by Mika. Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 55 ++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index a583e8f718a7..e4f9918ab859 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -413,23 +413,34 @@ static const struct _sdvo_cmd_name { static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, const void *args, int args_len) { - int i; + int i, pos = 0; +#define BUF_LEN 256 + char buffer[BUF_LEN]; + +#define BUF_PRINT(args...) \ + pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args) + - DRM_DEBUG_KMS("%s: W: %02X ", - SDVO_NAME(intel_sdvo), cmd); - for (i = 0; i < args_len; i++) - DRM_LOG_KMS("%02X ", ((u8 *)args)[i]); - for (; i < 8; i++) - DRM_LOG_KMS(" "); + for (i = 0; i < args_len; i++) { + BUF_PRINT("%02X ", ((u8 *)args)[i]); + } + for (; i < 8; i++) { + BUF_PRINT(" "); + } for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) { if (cmd == sdvo_cmd_names[i].cmd) { - DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name); + BUF_PRINT("(%s)", sdvo_cmd_names[i].name); break; } } - if (i == ARRAY_SIZE(sdvo_cmd_names)) - DRM_LOG_KMS("(%02X)", cmd); - DRM_LOG_KMS("\n"); + if (i == ARRAY_SIZE(sdvo_cmd_names)) { + BUF_PRINT("(%02X)", cmd); + } + BUG_ON(pos >= BUF_LEN - 1); +#undef BUF_PRINT +#undef BUF_LEN + + DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer); } static const char *cmd_status_names[] = { @@ -512,9 +523,10 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, { u8 retry = 15; /* 5 quick checks, followed by 10 long checks */ u8 status; - int i; + int i, pos = 0; +#define BUF_LEN 256 + char buffer[BUF_LEN]; - DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); /* * The documentation states that all commands will be @@ -551,10 +563,13 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, goto log_fail; } +#define BUF_PRINT(args...) \ + pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args) + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - DRM_LOG_KMS("(%s)", cmd_status_names[status]); + BUF_PRINT("(%s)", cmd_status_names[status]); else - DRM_LOG_KMS("(??? %d)", status); + BUF_PRINT("(??? %d)", status); if (status != SDVO_CMD_STATUS_SUCCESS) goto log_fail; @@ -565,13 +580,17 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, SDVO_I2C_RETURN_0 + i, &((u8 *)response)[i])) goto log_fail; - DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); + BUF_PRINT(" %02X", ((u8 *)response)[i]); } - DRM_LOG_KMS("\n"); + BUG_ON(pos >= BUF_LEN - 1); +#undef BUF_PRINT +#undef BUF_LEN + + DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer); return true; log_fail: - DRM_LOG_KMS("... failed\n"); + DRM_DEBUG_KMS("%s: R: ... failed\n", SDVO_NAME(intel_sdvo)); return false; } -- cgit v1.2.3 From 9b547a882e9ffec67bb41a4e66b4bcc0e91a2737 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 28 Oct 2013 23:49:27 +0100 Subject: usb: r8a66597-hcd: Convert to clk_prepare/unprepare Turn clk_enable() and clk_disable() calls into clk_prepare_enable() and clk_disable_unprepare() to get ready for the migration to the common clock framework. Cc: linux-usb@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Yoshihiro Shimoda Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/usb/host/r8a66597-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 2ad004ae747c..a2fdd85e0c91 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -95,7 +95,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) int i = 0; if (r8a66597->pdata->on_chip) { - clk_enable(r8a66597->clk); + clk_prepare_enable(r8a66597->clk); do { r8a66597_write(r8a66597, SCKE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); @@ -139,7 +139,7 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597) udelay(1); if (r8a66597->pdata->on_chip) { - clk_disable(r8a66597->clk); + clk_disable_unprepare(r8a66597->clk); } else { r8a66597_bclr(r8a66597, PLLC, SYSCFG0); r8a66597_bclr(r8a66597, XCKE, SYSCFG0); -- cgit v1.2.3 From 2f0aa30425414f3105bc29dd39bfdb40cb684393 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 15 Nov 2013 09:32:11 -0800 Subject: drm/i915/vlv: use a lower RC6 timeout on VLV We use timeout mode, and we need to lower the timeout to get good RC6 residency when loads are running. This gets me from 0% residency during glxgears to 77%, which is a pretty good improvement. This value also matches the current BWG recommentations. Tested-by: "Meng, Mengmeng" Signed-off-by: Jesse Barnes Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1659265a7f7a..2d74ae83b175 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4110,7 +4110,7 @@ static void valleyview_enable_rps(struct drm_device *dev) for_each_ring(ring, dev_priv, i) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); - I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350); + I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); /* allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, -- cgit v1.2.3 From 6b88f295690d3340fcbd01c1ff46991ea4f83c9f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 15 Nov 2013 09:32:12 -0800 Subject: drm/i915/vlv: use parallel context restore when coming out of RC6 Setting this bit restores all ring contexts in parallel rather than serially. Matches current BWG recommendations. Tested-by: "Meng, Mengmeng" Signed-off-by: Jesse Barnes Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2658d975279b..3be449d884a7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4900,6 +4900,7 @@ #define GEN6_RC_CTL_RC6_ENABLE (1<<18) #define GEN6_RC_CTL_RC1e_ENABLE (1<<20) #define GEN6_RC_CTL_RC7_ENABLE (1<<22) +#define VLV_RC_CTL_CTX_RST_PARALLEL (1<<24) #define GEN7_RC_CTL_TO_MODE (1<<28) #define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) #define GEN6_RC_CTL_HW_ENABLE (1<<31) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2d74ae83b175..eac7c4eb345c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4118,7 +4118,7 @@ static void valleyview_enable_rps(struct drm_device *dev) VLV_MEDIA_RC6_COUNT_EN | VLV_RENDER_RC6_COUNT_EN)); if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) - rc6_mode = GEN7_RC_CTL_TO_MODE; + rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; intel_print_rc6_info(dev, rc6_mode); -- cgit v1.2.3 From b4dd05de3d6fb93724b27921689fb3e95ba71845 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Nov 2013 02:39:42 +0100 Subject: spi: sh-msiof: Use devm_* managed allocators This simplifies error and cleanup code paths. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 86f822a656ef..7f2bb8572e5c 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -635,8 +635,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); if (master == NULL) { dev_err(&pdev->dev, "failed to allocate spi master\n"); - ret = -ENOMEM; - goto err0; + return -ENOMEM; } p = spi_master_get_devdata(master); @@ -655,32 +654,32 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) init_completion(&p->done); - p->clk = clk_get(&pdev->dev, NULL); + p->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(p->clk)) { dev_err(&pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); i = platform_get_irq(pdev, 0); - if (!r || i < 0) { - dev_err(&pdev->dev, "cannot get platform resources\n"); + if (i < 0) { + dev_err(&pdev->dev, "cannot get platform IRQ\n"); ret = -ENOENT; - goto err2; + goto err1; } - p->mapbase = ioremap_nocache(r->start, resource_size(r)); - if (!p->mapbase) { - dev_err(&pdev->dev, "unable to ioremap\n"); - ret = -ENXIO; - goto err2; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + p->mapbase = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(p->mapbase)) { + ret = PTR_ERR(p->mapbase); + goto err1; } - ret = request_irq(i, sh_msiof_spi_irq, 0, - dev_name(&pdev->dev), p); + ret = devm_request_irq(&pdev->dev, i, sh_msiof_spi_irq, 0, + dev_name(&pdev->dev), p); if (ret) { dev_err(&pdev->dev, "unable to request irq\n"); - goto err3; + goto err1; } p->pdev = pdev; @@ -719,13 +718,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) return 0; pm_runtime_disable(&pdev->dev); - err3: - iounmap(p->mapbase); - err2: - clk_put(p->clk); err1: spi_master_put(master); - err0: return ret; } @@ -737,9 +731,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) ret = spi_bitbang_stop(&p->bitbang); if (!ret) { pm_runtime_disable(&pdev->dev); - free_irq(platform_get_irq(pdev, 0), p); - iounmap(p->mapbase); - clk_put(p->clk); spi_master_put(p->bitbang.master); } return ret; -- cgit v1.2.3 From 5c32d29f13e9f7b94e0e82bf3ed7a1cf6b0c0dd3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Nov 2013 02:39:43 +0100 Subject: spi: sh-msiof: Convert to clk_prepare/unprepare Get the driver ready for the migration to the common clock framework by calling clk_prepare() and clk_unprepare(). The calls are added in the probe and remove handlers as the clk_enable() and clk_disable() calls are located in atomic context and there's no callback function in non-atomic context that can be used to prepare/unprepare the clock. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 7f2bb8572e5c..d96b047afcd2 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -682,6 +682,12 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) goto err1; } + ret = clk_prepare(p->clk); + if (ret < 0) { + dev_err(&pdev->dev, "unable to prepare clock\n"); + goto err1; + } + p->pdev = pdev; pm_runtime_enable(&pdev->dev); @@ -718,6 +724,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) return 0; pm_runtime_disable(&pdev->dev); + clk_unprepare(p->clk); err1: spi_master_put(master); return ret; @@ -731,6 +738,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) ret = spi_bitbang_stop(&p->bitbang); if (!ret) { pm_runtime_disable(&pdev->dev); + clk_unprepare(p->clk); spi_master_put(p->bitbang.master); } return ret; -- cgit v1.2.3 From 32a8fda90f52f547719b16dec07cce4abbd093e0 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 27 Nov 2013 12:51:17 +0000 Subject: mfd: wm5110: Give new AIF2 registers defaults and mark as readable The registers associated with the new channels on AIF2 were accidentally missing defaults and not marked as readable this patch fixes this. Signed-off-by: Charles Keepax Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/mfd/wm5110-tables.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index d433e285f1f1..338cfbe6727b 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -885,6 +885,38 @@ static const struct reg_default wm5110_reg_default[] = { { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ + { 0x00000750, 0x0000 }, /* R1872 - AIF2TX3MIX Input 1 Source */ + { 0x00000751, 0x0080 }, /* R1873 - AIF2TX3MIX Input 1 Volume */ + { 0x00000752, 0x0000 }, /* R1874 - AIF2TX3MIX Input 2 Source */ + { 0x00000753, 0x0080 }, /* R1875 - AIF2TX3MIX Input 2 Volume */ + { 0x00000754, 0x0000 }, /* R1876 - AIF2TX3MIX Input 3 Source */ + { 0x00000755, 0x0080 }, /* R1877 - AIF2TX3MIX Input 3 Volume */ + { 0x00000756, 0x0000 }, /* R1878 - AIF2TX3MIX Input 4 Source */ + { 0x00000757, 0x0080 }, /* R1879 - AIF2TX3MIX Input 4 Volume */ + { 0x00000758, 0x0000 }, /* R1880 - AIF2TX4MIX Input 1 Source */ + { 0x00000759, 0x0080 }, /* R1881 - AIF2TX4MIX Input 1 Volume */ + { 0x0000075A, 0x0000 }, /* R1882 - AIF2TX4MIX Input 2 Source */ + { 0x0000075B, 0x0080 }, /* R1883 - AIF2TX4MIX Input 2 Volume */ + { 0x0000075C, 0x0000 }, /* R1884 - AIF2TX4MIX Input 3 Source */ + { 0x0000075D, 0x0080 }, /* R1885 - AIF2TX4MIX Input 3 Volume */ + { 0x0000075E, 0x0000 }, /* R1886 - AIF2TX4MIX Input 4 Source */ + { 0x0000075F, 0x0080 }, /* R1887 - AIF2TX4MIX Input 4 Volume */ + { 0x00000760, 0x0000 }, /* R1888 - AIF2TX5MIX Input 1 Source */ + { 0x00000761, 0x0080 }, /* R1889 - AIF2TX5MIX Input 1 Volume */ + { 0x00000762, 0x0000 }, /* R1890 - AIF2TX5MIX Input 2 Source */ + { 0x00000763, 0x0080 }, /* R1891 - AIF2TX5MIX Input 2 Volume */ + { 0x00000764, 0x0000 }, /* R1892 - AIF2TX5MIX Input 3 Source */ + { 0x00000765, 0x0080 }, /* R1893 - AIF2TX5MIX Input 3 Volume */ + { 0x00000766, 0x0000 }, /* R1894 - AIF2TX5MIX Input 4 Source */ + { 0x00000767, 0x0080 }, /* R1895 - AIF2TX5MIX Input 4 Volume */ + { 0x00000768, 0x0000 }, /* R1896 - AIF2TX6MIX Input 1 Source */ + { 0x00000769, 0x0080 }, /* R1897 - AIF2TX6MIX Input 1 Volume */ + { 0x0000076A, 0x0000 }, /* R1898 - AIF2TX6MIX Input 2 Source */ + { 0x0000076B, 0x0080 }, /* R1899 - AIF2TX6MIX Input 2 Volume */ + { 0x0000076C, 0x0000 }, /* R1900 - AIF2TX6MIX Input 3 Source */ + { 0x0000076D, 0x0080 }, /* R1901 - AIF2TX6MIX Input 3 Volume */ + { 0x0000076E, 0x0000 }, /* R1902 - AIF2TX6MIX Input 4 Source */ + { 0x0000076F, 0x0080 }, /* R1903 - AIF2TX6MIX Input 4 Volume */ { 0x00000780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */ { 0x00000781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */ { 0x00000782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */ @@ -1883,6 +1915,38 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME: case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE: case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME: case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE: case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME: case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE: -- cgit v1.2.3 From 8ba4b3b9cc3d95714b31467614205fc26b91fb7c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 27 Nov 2013 17:26:03 +0100 Subject: clk: tegra: Do not print errors for clk_round_rate() clk_round_rate() can be used by drivers to determine whether or not a frequency is supported by the clock. The current Tegra clock driver outputs an error message and a stacktrace when the requested rate isn't supported. That's fine for clk_set_rate(), but it's confusing when all the driver does is query whether or not a frequency is supported. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 689c468aca2f..8eb2755c71b3 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -435,9 +435,6 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) || (1 << p_div) > divp_max(pll) || cfg->output_rate > pll->params->vco_max) { - pr_err("%s: Failed to set %s rate %lu\n", - __func__, __clk_get_name(hw->clk), rate); - WARN_ON(1); return -EINVAL; } @@ -584,6 +581,8 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (_get_table_rate(hw, &cfg, rate, parent_rate) && _calc_rate(hw, &cfg, rate, parent_rate)) { + pr_err("%s: Failed to set %s rate %lu\n", __func__, + __clk_get_name(hw->clk), rate); WARN_ON(1); return -EINVAL; } @@ -615,10 +614,8 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, return __clk_get_rate(hw->clk); if (_get_table_rate(hw, &cfg, rate, *prate) && - _calc_rate(hw, &cfg, rate, *prate)) { - WARN_ON(1); + _calc_rate(hw, &cfg, rate, *prate)) return -EINVAL; - } return cfg.output_rate; } -- cgit v1.2.3 From 62ce7cd62f534023224912dc9b909963f26a38da Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 29 Oct 2013 03:07:57 +0100 Subject: clk: tegra: fix __clk_lookup() return value checks In case of error, the function __clk_lookup() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-pll.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 8eb2755c71b3..2dd432266ef6 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1490,7 +1490,7 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, u32 val, val_iddq; parent = __clk_lookup(parent_name); - if (IS_ERR(parent)) { + if (!parent) { WARN(1, "parent clk %s of %s must be registered first\n", name, parent_name); return ERR_PTR(-EINVAL); @@ -1591,7 +1591,7 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, return ERR_PTR(-EINVAL); parent = __clk_lookup(parent_name); - if (IS_ERR(parent)) { + if (!parent) { WARN(1, "parent clk %s of %s must be registered first\n", name, parent_name); return ERR_PTR(-EINVAL); @@ -1632,7 +1632,7 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, return ERR_PTR(-EINVAL); parent = __clk_lookup(parent_name); - if (IS_ERR(parent)) { + if (!parent) { WARN(1, "parent clk %s of %s must be registered first\n", name, parent_name); return ERR_PTR(-EINVAL); @@ -1756,7 +1756,7 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, return ERR_PTR(-EINVAL); parent = __clk_lookup(parent_name); - if (IS_ERR(parent)) { + if (!parent) { WARN(1, "parent clk %s of %s must be registered first\n", name, parent_name); return ERR_PTR(-EINVAL); -- cgit v1.2.3 From f26ca1d699e8b54a50d9faf82327d3c2072aaedd Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 27 Nov 2013 13:33:09 -0700 Subject: ACPI / PCI / hotplug: Avoid warning when _ADR not present acpiphp_enumerate_slots() walks ACPI namenamespace under a PCI host bridge with callback register_slot(). register_slot() evaluates _ADR for all the device objects and emits a warning message for any error. Some platforms have _HID device objects (such as HPET and IPMI), which trigger unnecessary warning messages. This patch avoids emitting a warning message when a target device object does not have _ADR. Signed-off-by: Toshi Kani Cc: 3.12+ # 3.12+ Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1cf605f67673..438a4d09958b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); if (ACPI_FAILURE(status)) { - acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status); + if (status != AE_NOT_FOUND) + acpi_handle_warn(handle, + "can't evaluate _ADR (%#x)\n", status); return AE_OK; } -- cgit v1.2.3 From 48e9212021d920fe91046ad078e1070524844059 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 26 Nov 2013 11:25:54 -0800 Subject: drm/i915: drop DRM_ERROR in intel_fbdev init This should just be a debug. Add another debug msg to the inherit path while we're at it. Signed-off-by: Jesse Barnes Reviewed-by: Damien Lespiau Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=72098 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index fdb6dc92a7ab..284c3eb066f6 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -127,11 +127,12 @@ static int intelfb_create(struct drm_fb_helper *helper, mutex_lock(&dev->struct_mutex); if (!intel_fb->obj) { - DRM_ERROR("no BIOS fb, allocating a new one\n"); + DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); ret = intelfb_alloc(helper, sizes); if (ret) goto out_unlock; } else { + DRM_DEBUG_KMS("re-using BIOS fb\n"); sizes->fb_width = intel_fb->base.width; sizes->fb_height = intel_fb->base.height; } -- cgit v1.2.3 From ddf9c536295b9d7fcfd0bfc377593b41f2a4dc02 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Nov 2013 22:02:02 +0200 Subject: drm/i915: add intel_display_power_enabled_sw() for use in atomic ctx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atm we call intel_display_power_enabled() from i915_capture_error_state() in IRQ context and then take a mutex. To fix this add a new intel_display_power_enabled_sw() which returns the domain state based on software tracking as opposed to reading the actual HW state. Since we use domain_use_count for this without locking on the reader side make sure we increase the counter only after enabling all required power wells and decrease it before disabling any of these power wells. Regression introduced in commit 1b02383464b4a915627ef3b8fd0ad7f07168c54c Author: Imre Deak Date:   Tue Sep 24 16:17:09 2013 +0300     drm/i915: support for multiple power wells Note that atm we depend on the value returned by intel_display_power_enabled_sw() in i915_capture_error_state() to avoid unclaimed register access reports. This was never guaranteed though, since another thread can disable the power concurrently. If this is a problem we need another explicit way to disable the reporting during error captures. v2: - remove barriers as the caller can't depend on the value returned from i915_capture_error_state_sw() anyway (Ville) - dump the state of pipe/transcoder power domain state (Daniel) Reported-by: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 24 ++++++++++++++++-------- 4 files changed, 30 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6b18b4714d7e..64ed8f4d991f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -976,9 +976,7 @@ struct i915_power_domains { int power_well_count; struct mutex lock; -#if IS_ENABLED(CONFIG_DEBUG_FS) int domain_use_count[POWER_DOMAIN_NUM]; -#endif struct i915_power_well *power_wells; }; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ca467cb3c1b4..5a79088e6da1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11317,6 +11317,7 @@ struct intel_display_error_state { } cursor[I915_MAX_PIPES]; struct intel_pipe_error_state { + bool power_domain_on; u32 source; } pipe[I915_MAX_PIPES]; @@ -11331,6 +11332,7 @@ struct intel_display_error_state { } plane[I915_MAX_PIPES]; struct intel_transcoder_error_state { + bool power_domain_on; enum transcoder cpu_transcoder; u32 conf; @@ -11368,7 +11370,9 @@ intel_display_capture_error_state(struct drm_device *dev) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); for_each_pipe(i) { - if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i))) + error->pipe[i].power_domain_on = + intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i)); + if (!error->pipe[i].power_domain_on) continue; if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { @@ -11404,8 +11408,9 @@ intel_display_capture_error_state(struct drm_device *dev) for (i = 0; i < error->num_transcoders; i++) { enum transcoder cpu_transcoder = transcoders[i]; - if (!intel_display_power_enabled(dev, - POWER_DOMAIN_TRANSCODER(cpu_transcoder))) + error->transcoder[i].power_domain_on = + intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i)); + if (!error->transcoder[i].power_domain_on) continue; error->transcoder[i].cpu_transcoder = cpu_transcoder; @@ -11440,6 +11445,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, error->power_well_driver); for_each_pipe(i) { err_printf(m, "Pipe [%d]:\n", i); + err_printf(m, " Power: %s\n", + error->pipe[i].power_domain_on ? "on" : "off"); err_printf(m, " SRC: %08x\n", error->pipe[i].source); err_printf(m, "Plane [%d]:\n", i); @@ -11465,6 +11472,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, for (i = 0; i < error->num_transcoders; i++) { err_printf(m, "CPU transcoder: %c\n", transcoder_name(error->transcoder[i].cpu_transcoder)); + err_printf(m, " Power: %s\n", + error->transcoder[i].power_domain_on ? "on" : "off"); err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 02312810374d..5dea38967523 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -842,6 +842,8 @@ int intel_power_domains_init(struct drm_device *dev); void intel_power_domains_remove(struct drm_device *dev); bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain); +bool intel_display_power_enabled_sw(struct drm_device *dev, + enum intel_display_power_domain domain); void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain); void intel_display_power_put(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index eac7c4eb345c..ff47520f8d40 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5641,6 +5641,17 @@ static bool hsw_power_well_enabled(struct drm_device *dev, (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); } +bool intel_display_power_enabled_sw(struct drm_device *dev, + enum intel_display_power_domain domain) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains; + + power_domains = &dev_priv->power_domains; + + return power_domains->domain_use_count[domain]; +} + bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain) { @@ -5761,12 +5772,11 @@ void intel_display_power_get(struct drm_device *dev, mutex_lock(&power_domains->lock); -#if IS_ENABLED(CONFIG_DEBUG_FS) - power_domains->domain_use_count[domain]++; -#endif for_each_power_well(i, power_well, BIT(domain), power_domains) __intel_power_well_get(dev, power_well); + power_domains->domain_use_count[domain]++; + mutex_unlock(&power_domains->lock); } @@ -5782,13 +5792,11 @@ void intel_display_power_put(struct drm_device *dev, mutex_lock(&power_domains->lock); - for_each_power_well_rev(i, power_well, BIT(domain), power_domains) - __intel_power_well_put(dev, power_well); - -#if IS_ENABLED(CONFIG_DEBUG_FS) WARN_ON(!power_domains->domain_use_count[domain]); power_domains->domain_use_count[domain]--; -#endif + + for_each_power_well_rev(i, power_well, BIT(domain), power_domains) + __intel_power_well_put(dev, power_well); mutex_unlock(&power_domains->lock); } -- cgit v1.2.3 From c19de8eb67f745a7b16a7587ed002e6916ab2a5d Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 28 Nov 2013 15:29:18 +0000 Subject: drm/i915: Return a drm_mode_status enum in the mode_valid vfuncs We had some mode_valid() vfuncs returning an int, others the enum. Let's use the latter everywhere. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 5 +++-- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 5 +++-- drivers/gpu/drm/i915/intel_dvo.c | 5 +++-- drivers/gpu/drm/i915/intel_hdmi.c | 5 +++-- drivers/gpu/drm/i915/intel_lvds.c | 5 +++-- drivers/gpu/drm/i915/intel_sdvo.c | 5 +++-- 7 files changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index b5b1b9b23adf..e2e39e65f109 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -222,8 +222,9 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) intel_modeset_check_state(connector->dev); } -static int intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_crt_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3b22e726585e..82de200efa05 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -142,7 +142,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; } -static int +static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index d257b093ca68..7b9b350d29ae 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -251,8 +251,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, /* XXX: read flags, set to adjusted_mode */ } -static int intel_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_dsi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 3c7736546856..eeff998e52ef 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -234,8 +234,9 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) intel_modeset_check_state(connector->dev); } -static int intel_dvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_dvo_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index d0c81b170149..6a6ad0c78dc7 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -853,8 +853,9 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi) return 225000; } -static int intel_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_hdmi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector))) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index c3b4da7895ed..3deb58e2f394 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -256,8 +256,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder) POSTING_READ(lvds_encoder->reg); } -static int intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_lvds_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e4f9918ab859..2abeab09e883 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1536,8 +1536,9 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) intel_modeset_check_state(connector->dev); } -static int intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +intel_sdvo_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); -- cgit v1.2.3 From 08239ca2a053dbc3b082916bdfbd88e5a9ad9267 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 28 Nov 2013 10:31:35 +0800 Subject: bcache: fix sparse non static symbol warning Fixes the following sparse warning: drivers/md/bcache/btree.c:2220:5: warning: symbol 'btree_insert_fn' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Kent Overstreet --- drivers/md/bcache/btree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 5e2765aadce1..dc6e2be265b7 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -2217,7 +2217,7 @@ struct btree_insert_op { struct bkey *replace_key; }; -int btree_insert_fn(struct btree_op *b_op, struct btree *b) +static int btree_insert_fn(struct btree_op *b_op, struct btree *b) { struct btree_insert_op *op = container_of(b_op, struct btree_insert_op, op); -- cgit v1.2.3 From c6f8e5575511967a94c917c8934503253ebf6d5b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 28 Oct 2013 09:16:05 -0300 Subject: [media] radio-shark: Mark shark_resume_leds() inline to kill compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If SHARK_USE_LEDS=1, but CONFIG_PM=n: drivers/media/radio/radio-shark.c:275: warning: ‘shark_resume_leds’ defined but not used Instead of making the #ifdef logic even more complicated (there are already two definitions of shark_resume_leds()), mark shark_resume_leds() inline to kill the compiler warning. shark_resume_leds() is small and it has only one caller. Signed-off-by: Geert Uytterhoeven Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-shark.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 3db8a8cfe1a8..050b3bb96fec 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -271,8 +271,7 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } -#ifdef CONFIG_PM -static void shark_resume_leds(struct shark_device *shark) +static inline void shark_resume_leds(struct shark_device *shark) { if (test_bit(BLUE_IS_PULSE, &shark->brightness_new)) set_bit(BLUE_PULSE_LED, &shark->brightness_new); @@ -281,7 +280,6 @@ static void shark_resume_leds(struct shark_device *shark) set_bit(RED_LED, &shark->brightness_new); schedule_work(&shark->led_work); } -#endif #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { -- cgit v1.2.3 From be46ffd48ba34189336c6fe420ff3370dcd36c60 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2013 13:21:49 +0200 Subject: drm/i915: Fix port name in vlv_wait_port_ready() timeout warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're currently misprinting the port name when vlv_wait_port_ready() times out. Fix it by using port_name(). Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5a79088e6da1..0332d7ca892d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1513,7 +1513,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) WARN(1, "timed out waiting for port %c ready: 0x%08x\n", - 'B' + dport->port, I915_READ(DPLL(0))); + port_name(dport->port), I915_READ(DPLL(0))); } /** -- cgit v1.2.3 From d8eec74a229f4e3448bfdff9ff3cd3f61bb1e63d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 17 Nov 2013 10:48:29 -0300 Subject: [media] radio-shark2: Mark shark_resume_leds() inline to kill compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This mirrors the patch to the radio-shark driver by Geert Uytterhoeven. If SHARK_USE_LEDS=1, but CONFIG_PM=n: drivers/media/radio/radio-shark2.c:240: warning: ‘shark_resume_leds’ defined but not used Instead of making the #ifdef logic even more complicated (there are already two definitions of shark_resume_leds()), mark shark_resume_leds() inline to kill the compiler warning. shark_resume_leds() is small and it has only one caller. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-shark2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index d86d90dab8bf..8654e0dc5c95 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -237,8 +237,7 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } -#ifdef CONFIG_PM -static void shark_resume_leds(struct shark_device *shark) +static inline void shark_resume_leds(struct shark_device *shark) { int i; @@ -247,7 +246,6 @@ static void shark_resume_leds(struct shark_device *shark) schedule_work(&shark->led_work); } -#endif #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { -- cgit v1.2.3 From ea3aba8482be6f3e4815f4014fa7302fc77c9c3f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 21 May 2013 05:11:35 -0300 Subject: [media] videobuf2: Add support for file access mode flags for DMABUF exporting Currently it is not possible for userspace to map a DMABUF exported buffer with write permissions. This patch allows to also pass O_RDONLY/O_RDWR when exporting the buffer, so that userspace may map it with write permissions. Signed-off-by: Philipp Zabel Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-expbuf.xml | 8 +++++--- drivers/media/v4l2-core/videobuf2-core.c | 8 ++++---- drivers/media/v4l2-core/videobuf2-dma-contig.c | 4 ++-- include/media/videobuf2-core.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml index e287c8fc803b..4165e7bfa4ff 100644 --- a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml @@ -73,7 +73,8 @@ range from zero to the maximal number of valid planes for the currently active format. For the single-planar API, applications must set plane to zero. Additional flags may be posted in the flags field. Refer to a manual for open() for details. -Currently only O_CLOEXEC is supported. All other fields must be set to zero. +Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported. All +other fields must be set to zero. In the case of multi-planar API, every plane is exported separately using multiple VIDIOC_EXPBUF calls. @@ -170,8 +171,9 @@ multi-planar API. Otherwise this value must be set to zero. __u32 flags Flags for the newly created file, currently only -O_CLOEXEC is supported, refer to the manual of open() for more -details. +O_CLOEXEC , O_RDONLY, O_WRONLY +, and O_RDWR are supported, refer to the manual +of open() for more details. __s32 diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index b19b306c8f7f..57ba131f08ad 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1824,8 +1824,8 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) return -EINVAL; } - if (eb->flags & ~O_CLOEXEC) { - dprintk(1, "Queue does support only O_CLOEXEC flag\n"); + if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) { + dprintk(1, "Queue does support only O_CLOEXEC and access mode flags\n"); return -EINVAL; } @@ -1848,14 +1848,14 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) vb_plane = &vb->planes[eb->plane]; - dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv); + dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE); if (IS_ERR_OR_NULL(dbuf)) { dprintk(1, "Failed to export buffer %d, plane %d\n", eb->index, eb->plane); return -EINVAL; } - ret = dma_buf_fd(dbuf, eb->flags); + ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE); if (ret < 0) { dprintk(3, "buffer %d, plane %d failed to export (%d)\n", eb->index, eb->plane, ret); diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 646f08f4f504..33d3871d1e13 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -393,7 +393,7 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) return sgt; } -static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv) +static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) { struct vb2_dc_buf *buf = buf_priv; struct dma_buf *dbuf; @@ -404,7 +404,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv) if (WARN_ON(!buf->sgt_base)) return NULL; - dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0); + dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags); if (IS_ERR(dbuf)) return NULL; diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index bd8218b15009..941055e9d125 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -83,7 +83,7 @@ struct vb2_fileio_data; struct vb2_mem_ops { void *(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags); void (*put)(void *buf_priv); - struct dma_buf *(*get_dmabuf)(void *buf_priv); + struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags); void *(*get_userptr)(void *alloc_ctx, unsigned long vaddr, unsigned long size, int write); -- cgit v1.2.3 From 39c1cb2b191f56a963103d715797fca70f2fb26e Mon Sep 17 00:00:00 2001 From: Jonathan McCrohan Date: Sun, 20 Oct 2013 21:34:01 -0300 Subject: [media] media_tree: Fix spelling errors Fix various spelling errors in strings and comments throughout the media tree. The majority of these were found using Lucas De Marchi's codespell tool. [m.chehab@samsung.com: discard hunks with conflicts] Signed-off-by: Jonathan McCrohan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smscoreapi.h | 4 ++-- drivers/media/common/siano/smsdvb.h | 2 +- drivers/media/dvb-core/dvb_demux.c | 2 +- drivers/media/dvb-frontends/dib8000.c | 4 ++-- drivers/media/dvb-frontends/drxk_hard.c | 18 +++++++++--------- drivers/media/i2c/adv7183_regs.h | 6 +++--- drivers/media/i2c/adv7604.c | 2 +- drivers/media/i2c/adv7842.c | 2 +- drivers/media/i2c/ir-kbd-i2c.c | 2 +- drivers/media/i2c/m5mols/m5mols_controls.c | 2 +- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 2 +- drivers/media/i2c/s5c73m3/s5c73m3.h | 2 +- drivers/media/i2c/saa7115.c | 2 +- drivers/media/i2c/soc_camera/ov5642.c | 2 +- drivers/media/pci/cx18/cx18-driver.h | 2 +- drivers/media/pci/cx23885/cx23885-417.c | 2 +- drivers/media/pci/pluto2/pluto2.c | 2 +- drivers/media/platform/coda.c | 2 +- drivers/media/platform/exynos4-is/fimc-core.c | 2 +- drivers/media/platform/exynos4-is/media-dev.c | 2 +- drivers/media/platform/omap3isp/isp.c | 2 +- drivers/media/platform/s5p-mfc/regs-mfc.h | 2 +- drivers/media/platform/s5p-mfc/s5p_mfc.c | 12 ++++++------ drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 2 +- drivers/media/platform/s5p-tv/mixer.h | 2 +- drivers/media/platform/s5p-tv/mixer_video.c | 4 ++-- drivers/media/platform/soc_camera/omap1_camera.c | 2 +- drivers/media/platform/vivi.c | 4 ++-- drivers/media/platform/vsp1/vsp1_drv.c | 2 +- drivers/media/radio/radio-si476x.c | 4 ++-- drivers/media/rc/imon.c | 2 +- drivers/media/rc/redrat3.c | 2 +- drivers/media/tuners/mt2063.c | 4 ++-- drivers/media/tuners/tuner-xc2028-types.h | 2 +- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 4 ++-- drivers/media/usb/gspca/gl860/gl860.c | 2 +- drivers/media/usb/gspca/pac207.c | 2 +- drivers/media/usb/gspca/pac7302.c | 2 +- drivers/media/usb/gspca/stv0680.c | 2 +- drivers/media/usb/gspca/zc3xx.c | 2 +- drivers/media/usb/pwc/pwc-if.c | 2 +- drivers/media/usb/uvc/uvc_video.c | 2 +- drivers/media/v4l2-core/v4l2-ctrls.c | 2 +- 43 files changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index d0799e323364..9c9063cd3208 100644 --- a/drivers/media/common/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h @@ -955,7 +955,7 @@ struct sms_rx_stats { u32 modem_state; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ s32 SNR; /* dB */ u32 ber; /* Post Viterbi ber [1E-5] */ - u32 ber_error_count; /* Number of erronous SYNC bits. */ + u32 ber_error_count; /* Number of erroneous SYNC bits. */ u32 ber_bit_count; /* Total number of SYNC bits. */ u32 ts_per; /* Transport stream PER, 0xFFFFFFFF indicate N/A */ @@ -981,7 +981,7 @@ struct sms_rx_stats_ex { u32 modem_state; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ s32 SNR; /* dB */ u32 ber; /* Post Viterbi ber [1E-5] */ - u32 ber_error_count; /* Number of erronous SYNC bits. */ + u32 ber_error_count; /* Number of erroneous SYNC bits. */ u32 ber_bit_count; /* Total number of SYNC bits. */ u32 ts_per; /* Transport stream PER, 0xFFFFFFFF indicate N/A */ diff --git a/drivers/media/common/siano/smsdvb.h b/drivers/media/common/siano/smsdvb.h index 92c413ba0c79..ae36d0ae0fb1 100644 --- a/drivers/media/common/siano/smsdvb.h +++ b/drivers/media/common/siano/smsdvb.h @@ -95,7 +95,7 @@ struct RECEPTION_STATISTICS_PER_SLICES_S { u32 is_demod_locked; /* 0 - not locked, 1 - locked */ u32 ber_bit_count; /* Total number of SYNC bits. */ - u32 ber_error_count; /* Number of erronous SYNC bits. */ + u32 ber_error_count; /* Number of erroneous SYNC bits. */ s32 MRC_SNR; /* dB */ s32 mrc_in_band_pwr; /* In band power in dBM */ diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 58de4410c525..53ee319b79b2 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -435,7 +435,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) dprintk_tscheck("TEI detected. " "PID=0x%x data1=0x%x\n", pid, buf[1]); - /* data in this packet cant be trusted - drop it unless + /* data in this packet can't be trusted - drop it unless * module option dvb_demux_feed_err_pkts is set */ if (!dvb_demux_feed_err_pkts) return; diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 90536147bf04..6dbbee453ee1 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3048,7 +3048,7 @@ static int dib8000_tune(struct dvb_frontend *fe) dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */ - /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */ + /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */ *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON); *tune_state = CT_DEMOD_STEP_5; break; @@ -3115,7 +3115,7 @@ static int dib8000_tune(struct dvb_frontend *fe) case CT_DEMOD_STEP_9: /* 39 */ if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */ - /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */ + /* defines timeout for mpeg lock depending on interleaver length of longest layer */ for (i = 0; i < 3; i++) { if (c->layer[i].interleaving >= deeper_interleaver) { dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving); diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index d416c15691da..bf29a3f0e6f0 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -1191,7 +1191,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) goto error; if (state->m_enable_parallel == true) { - /* paralel -> enable MD1 to MD7 */ + /* parallel -> enable MD1 to MD7 */ status = write16(state, SIO_PDR_MD1_CFG__A, sio_pdr_mdx_cfg); if (status < 0) @@ -1428,7 +1428,7 @@ static int mpegts_stop(struct drxk_state *state) dprintk(1, "\n"); - /* Gracefull shutdown (byte boundaries) */ + /* Graceful shutdown (byte boundaries) */ status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error; @@ -2021,7 +2021,7 @@ static int mpegts_dto_setup(struct drxk_state *state, fec_oc_dto_burst_len = 204; } - /* Check serial or parrallel output */ + /* Check serial or parallel output */ fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); if (state->m_enable_parallel == false) { /* MPEG data output is serial -> set ipr_mode[0] */ @@ -2908,7 +2908,7 @@ static int adc_synchronization(struct drxk_state *state) goto error; if (count == 1) { - /* Try sampling on a diffrent edge */ + /* Try sampling on a different edge */ u16 clk_neg = 0; status = read16(state, IQM_AF_CLKNEG__A, &clk_neg); @@ -3306,7 +3306,7 @@ static int dvbt_sc_command(struct drxk_state *state, if (status < 0) goto error; - /* Retreive results parameters from SC */ + /* Retrieve results parameters from SC */ switch (cmd) { /* All commands yielding 5 results */ /* All commands yielding 4 results */ @@ -3849,7 +3849,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, break; } #if 0 - /* No hierachical channels support in BDA */ + /* No hierarchical channels support in BDA */ /* Priority (only for hierarchical channels) */ switch (channel->priority) { case DRX_PRIORITY_LOW: @@ -4081,7 +4081,7 @@ error: /*============================================================================*/ /** -* \brief Retreive lock status . +* \brief Retrieve lock status . * \param demod Pointer to demodulator instance. * \param lockStat Pointer to lock status structure. * \return DRXStatus_t. @@ -6174,7 +6174,7 @@ static int init_drxk(struct drxk_state *state) goto error; /* Stamp driver version number in SCU data RAM in BCD code - Done to enable field application engineers to retreive drxdriver version + Done to enable field application engineers to retrieve drxdriver version via I2C from SCU RAM. Not using SCU command interface for SCU register access since no microcode may be present. @@ -6399,7 +6399,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe) fe->ops.tuner_ops.get_if_frequency(fe, &IF); start(state, 0, IF); - /* After set_frontend, stats aren't avaliable */ + /* After set_frontend, stats aren't available */ p->strength.stat[0].scale = FE_SCALE_RELATIVE; p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; diff --git a/drivers/media/i2c/adv7183_regs.h b/drivers/media/i2c/adv7183_regs.h index 4a5b7d211d2f..b253d400e817 100644 --- a/drivers/media/i2c/adv7183_regs.h +++ b/drivers/media/i2c/adv7183_regs.h @@ -52,9 +52,9 @@ #define ADV7183_VS_FIELD_CTRL_1 0x31 /* Vsync field control 1 */ #define ADV7183_VS_FIELD_CTRL_2 0x32 /* Vsync field control 2 */ #define ADV7183_VS_FIELD_CTRL_3 0x33 /* Vsync field control 3 */ -#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync positon control 1 */ -#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync positon control 2 */ -#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync positon control 3 */ +#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync position control 1 */ +#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync position control 2 */ +#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync position control 3 */ #define ADV7183_POLARITY 0x37 /* Polarity */ #define ADV7183_NTSC_COMB_CTRL 0x38 /* NTSC comb control */ #define ADV7183_PAL_COMB_CTRL 0x39 /* PAL comb control */ diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index fbfdd2fc2a36..a324106b9f11 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -877,7 +877,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd, break; case ADV7604_MODE_HDMI: /* set default prim_mode/vid_std for HDMI - accoring to [REF_03, c. 4.2] */ + according to [REF_03, c. 4.2] */ io_write(sd, 0x00, 0x02); /* video std */ io_write(sd, 0x01, 0x06); /* prim mode */ break; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 22f729d66a96..b154f36740b4 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -1013,7 +1013,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd, break; case ADV7842_MODE_HDMI: /* set default prim_mode/vid_std for HDMI - accoring to [REF_03, c. 4.2] */ + according to [REF_03, c. 4.2] */ io_write(sd, 0x00, 0x02); /* video std */ io_write(sd, 0x01, 0x06); /* prim mode */ break; diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 82bf5679da30..99ee456700f4 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -394,7 +394,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!rc) { /* - * If platform_data doesn't specify rc_dev, initilize it + * If platform_data doesn't specify rc_dev, initialize it * internally */ rc = rc_allocate_device(); diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c index f34429e452ab..a60931e66312 100644 --- a/drivers/media/i2c/m5mols/m5mols_controls.c +++ b/drivers/media/i2c/m5mols/m5mols_controls.c @@ -544,7 +544,7 @@ int m5mols_init_controls(struct v4l2_subdev *sd) u16 zoom_step; int ret; - /* Determine the firmware dependant control range and step values */ + /* Determine the firmware dependent control range and step values */ ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max); if (ret < 0) return ret; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 6fec9384d86e..e7f555cc827a 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1460,7 +1460,7 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd) mutex_unlock(&state->lock); v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n", - __func__, ret ? "failed" : "succeded", ret); + __func__, ret ? "failed" : "succeeded", ret); return ret; } diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h index 9d2c08652246..9dfa516f6944 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3.h +++ b/drivers/media/i2c/s5c73m3/s5c73m3.h @@ -393,7 +393,7 @@ struct s5c73m3 { /* External master clock frequency */ u32 mclk_frequency; - /* Video bus type - MIPI-CSI2/paralell */ + /* Video bus type - MIPI-CSI2/parallel */ enum v4l2_mbus_type bus_type; const struct s5c73m3_frame_size *sensor_pix_size[2]; diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 637d02634527..afdbcb045cee 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1699,7 +1699,7 @@ static void saa711x_write_platform_data(struct saa711x_state *state, * the analog demod. * If the tuner is not found, it returns -ENODEV. * If auto-detection is disabled and the tuner doesn't match what it was - * requred, it returns -EINVAL and fills 'name'. + * required, it returns -EINVAL and fills 'name'. * If the chip is found, it returns the chip ID and fills 'name'. */ static int saa711x_detect_chip(struct i2c_client *client, diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index 0a5c5d4fedd6..d2daa6a8f272 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -642,7 +642,7 @@ static const struct ov5642_datafmt static int reg_read(struct i2c_client *client, u16 reg, u8 *val) { int ret; - /* We have 16-bit i2c addresses - care for endianess */ + /* We have 16-bit i2c addresses - care for endianness */ unsigned char data[2] = { reg >> 8, reg & 0xff }; ret = i2c_master_send(client, data, 2); diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index 2767c64df0c8..57f4688ea55b 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -262,7 +262,7 @@ struct cx18_options { }; /* per-mdl bit flags */ -#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianess swapped */ +#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianness swapped */ /* per-stream, s_flags */ #define CX18_F_S_CLAIMED 3 /* this stream is claimed */ diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index e3fc2c71808a..95666eee7b27 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -427,7 +427,7 @@ int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) cx_write(MC417_RWD, regval); /* Transition RD to effect read transaction across bus. - * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)? + * Transition 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)? * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its * input only...) */ diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 8164d74b46a4..655d6854a8d7 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -401,7 +401,7 @@ static int pluto_hw_init(struct pluto *pluto) /* set automatic LED control by FPGA */ pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED); - /* set data endianess */ + /* set data endianness */ #ifdef __LITTLE_ENDIAN pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END); #else diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index bd72fb97fea5..61f3dbcc259f 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1434,7 +1434,7 @@ static void coda_buf_queue(struct vb2_buffer *vb) if (q_data->fourcc == V4L2_PIX_FMT_H264 && vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* - * For backwards compatiblity, queuing an empty buffer marks + * For backwards compatibility, queuing an empty buffer marks * the stream end */ if (vb2_get_plane_payload(vb, 0) == 0) diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 3d66d88ea3a1..f7915695c907 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -1039,7 +1039,7 @@ static int fimc_runtime_resume(struct device *dev) dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state); - /* Enable clocks and perform basic initalization */ + /* Enable clocks and perform basic initialization */ clk_enable(fimc->clock[CLK_GATE]); fimc_hw_reset(fimc); diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 7a4ee4c0449d..c1bce170df6f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -759,7 +759,7 @@ static int fimc_md_register_platform_entity(struct fimc_md *fmd, goto dev_unlock; drvdata = dev_get_drvdata(dev); - /* Some subdev didn't probe succesfully id drvdata is NULL */ + /* Some subdev didn't probe successfully id drvdata is NULL */ if (drvdata) { switch (plat_entity) { case IDX_FIMC: diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1c3608039663..561bce8ffb1b 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1673,7 +1673,7 @@ void omap3isp_print_status(struct isp_device *isp) * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in * resume(), and the the pipelines are restarted in complete(). * - * TODO: PM dependencies between the ISP and sensors are not modeled explicitly + * TODO: PM dependencies between the ISP and sensors are not modelled explicitly * yet. */ static int isp_pm_prepare(struct device *dev) diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h index 9319e93599ae..6ccc3f8c122a 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h @@ -382,7 +382,7 @@ #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET 16 #define S5P_FIMV_R2H_CMD_ERR_RET 32 -/* Dummy definition for MFCv6 compatibilty */ +/* Dummy definition for MFCv6 compatibility */ #define S5P_FIMV_CODEC_H264_MVC_DEC -1 #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET -1 #define S5P_FIMV_MFC_RESET -1 diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 5f2c4ad6c2cb..e46067a57853 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -239,7 +239,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx) frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); /* Copy timestamp / timecode from decoded src to dst and set - appropraite flags */ + appropriate flags */ src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); list_for_each_entry(dst_buf, &ctx->dst_queue, list) { if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) { @@ -428,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, case MFCINST_FINISHING: case MFCINST_FINISHED: case MFCINST_RUNNING: - /* It is higly probable that an error occured + /* It is highly probable that an error occurred * while decoding a frame */ clear_work_bit(ctx); ctx->state = MFCINST_ERROR; @@ -611,7 +611,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err); switch (reason) { case S5P_MFC_R2H_CMD_ERR_RET: - /* An error has occured */ + /* An error has occurred */ if (ctx->state == MFCINST_RUNNING && s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >= dev->warn_start) @@ -840,7 +840,7 @@ static int s5p_mfc_open(struct file *file) mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; - /* Deinit when failure occured */ + /* Deinit when failure occurred */ err_queue_init: if (dev->num_inst == 1) s5p_mfc_deinit_hw(dev); @@ -881,14 +881,14 @@ static int s5p_mfc_release(struct file *file) /* Mark context as idle */ clear_work_bit_irqsave(ctx); /* If instance was initialised then - * return instance and free reosurces */ + * return instance and free resources */ if (ctx->inst_no != MFC_NO_INSTANCE_SET) { mfc_debug(2, "Has to free instance\n"); ctx->state = MFCINST_RETURN_INST; set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - /* Wait until instance is returned or timeout occured */ + /* Wait until instance is returned or timeout occurred */ if (s5p_mfc_wait_for_done_ctx (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) { s5p_mfc_clock_off(); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 7cab6849fb5b..2475a3c9a0a6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -69,7 +69,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) } else { /* In this case bank2 can point to the same address as bank1. - * Firmware will always occupy the beggining of this area so it is + * Firmware will always occupy the beginning of this area so it is * impossible having a video frame buffer with zero address. */ dev->bank2 = dev->bank1; } diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index 04e6490a45be..fb2acc53112a 100644 --- a/drivers/media/platform/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h @@ -65,7 +65,7 @@ struct mxr_format { int num_subframes; /** specifies to which subframe belong given plane */ int plane2subframe[MXR_MAX_PLANES]; - /** internal code, driver dependant */ + /** internal code, driver dependent */ unsigned long cookie; }; diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 641b1f071e06..81b97db111d8 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -528,7 +528,7 @@ static int mxr_s_dv_timings(struct file *file, void *fh, mutex_lock(&mdev->mutex); /* timings change cannot be done while there is an entity - * dependant on output configuration + * dependent on output configuration */ if (mdev->n_output > 0) { mutex_unlock(&mdev->mutex); @@ -585,7 +585,7 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id norm) mutex_lock(&mdev->mutex); /* standard change cannot be done while there is an entity - * dependant on output configuration + * dependent on output configuration */ if (mdev->n_output > 0) { mutex_unlock(&mdev->mutex); diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index 6769193c7c7b..74ce8b6b79fa 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -1495,7 +1495,7 @@ static int omap1_cam_set_bus_param(struct soc_camera_device *icd) if (ctrlclock & LCLK_EN) CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - /* select bus endianess */ + /* select bus endianness */ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); fmt = xlate->host_fmt; diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c index 1d3f11965196..2d4e73b45c5e 100644 --- a/drivers/media/platform/vivi.c +++ b/drivers/media/platform/vivi.c @@ -1108,7 +1108,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -/* timeperframe is arbitrary and continous */ +/* timeperframe is arbitrary and continuous */ static int vidioc_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival) { @@ -1125,7 +1125,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv, fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; - /* fill in stepwise (step=1.0 is requred by V4L2 spec) */ + /* fill in stepwise (step=1.0 is required by V4L2 spec) */ fival->stepwise.min = tpf_min; fival->stepwise.max = tpf_max; fival->stepwise.step = (struct v4l2_fract) {1, 1}; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 1c9e771aa15c..d16bf0f41e24 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -323,7 +323,7 @@ static void vsp1_clocks_disable(struct vsp1_device *vsp1) * Increment the VSP1 reference count and initialize the device if the first * reference is taken. * - * Return a pointer to the VSP1 device or NULL if an error occured. + * Return a pointer to the VSP1 device or NULL if an error occurred. */ struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) { diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9c9084cb99f7..2fd9009f8663 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -268,8 +268,8 @@ struct si476x_radio; * * @tune_freq: Tune chip to a specific frequency * @seek_start: Star station seeking - * @rsq_status: Get Recieved Signal Quality(RSQ) status - * @rds_blckcnt: Get recived RDS blocks count + * @rsq_status: Get Received Signal Quality(RSQ) status + * @rds_blckcnt: Get received RDS blocks count * @phase_diversity: Change phase diversity mode of the tuner * @phase_div_status: Get phase diversity mode status * @acf_status: Get the status of Automatically Controlled diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 72e3fa652481..f329485c6629 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1370,7 +1370,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates * 0x688301b7 and the right one 0x688481b7. All other keys generate * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with - * reversed endianess. Extract direction from buffer, rotate endianess, + * reversed endianness. Extract direction from buffer, rotate endianness, * adjust sign and feed the values into stabilize(). The resulting codes * will be 0x01008000, 0x01007F00, which match the newer devices. */ diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 094484fac94c..a5d4f883d053 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -118,7 +118,7 @@ static int debug; #define RR3_IR_IO_LENGTH_FUZZ 0x04 /* Timeout for end of signal detection */ #define RR3_IR_IO_SIG_TIMEOUT 0x05 -/* Minumum value for pause recognition. */ +/* Minimum value for pause recognition. */ #define RR3_IR_IO_MIN_PAUSE 0x06 /* Clock freq. of EZ-USB chip */ diff --git a/drivers/media/tuners/mt2063.c b/drivers/media/tuners/mt2063.c index 2e1a02e360ff..20cca405bf45 100644 --- a/drivers/media/tuners/mt2063.c +++ b/drivers/media/tuners/mt2063.c @@ -1195,7 +1195,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state, * DNC Output is selected, the other is always off) * * @state: ptr to mt2063_state structure - * @Mode: desired reciever delivery system + * @Mode: desired receiver delivery system * * Note: Register cache must be valid for it to work */ @@ -2119,7 +2119,7 @@ static int mt2063_set_analog_params(struct dvb_frontend *fe, /* * As defined on EN 300 429, the DVB-C roll-off factor is 0.15. - * So, the amount of the needed bandwith is given by: + * So, the amount of the needed bandwidth is given by: * Bw = Symbol_rate * (1 + 0.15) * As such, the maximum symbol rate supported by 6 MHz is given by: * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds diff --git a/drivers/media/tuners/tuner-xc2028-types.h b/drivers/media/tuners/tuner-xc2028-types.h index 74dc46a71f64..7e4798783db7 100644 --- a/drivers/media/tuners/tuner-xc2028-types.h +++ b/drivers/media/tuners/tuner-xc2028-types.h @@ -119,7 +119,7 @@ #define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B) #define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B) -/* To preserve backward compatibilty, +/* To preserve backward compatibility, (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported */ diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 2627553f7de1..08240e498451 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -266,7 +266,7 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int err; - /* exit if we didnt initialize the driver yet */ + /* exit if we didn't initialize the driver yet */ if (!state->chip_id) { mxl_debug("driver not yet initialized, exit."); goto fail; @@ -322,7 +322,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int err; - /* exit if we didnt initialize the driver yet */ + /* exit if we didn't initialize the driver yet */ if (!state->chip_id) { mxl_debug("driver not yet initialized, exit."); goto fail; diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c index cb1e64ca59c9..cea8d7f51c3c 100644 --- a/drivers/media/usb/gspca/gl860/gl860.c +++ b/drivers/media/usb/gspca/gl860/gl860.c @@ -438,7 +438,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, s32 nToSkip = sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1); - /* Test only against 0202h, so endianess does not matter */ + /* Test only against 0202h, so endianness does not matter */ switch (*(s16 *) data) { case 0x0202: /* End of frame, start a new one */ gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c index cd79c180f67b..07529e5a0c56 100644 --- a/drivers/media/usb/gspca/pac207.c +++ b/drivers/media/usb/gspca/pac207.c @@ -416,7 +416,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ + int len) /* interrupt packet length */ { int ret = -EINVAL; diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index a91509643563..2fd1c5e31a0f 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -874,7 +874,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ + int len) /* interrupt packet length */ { int ret = -EINVAL; u8 data0, data1; diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c index 9c0827631b9c..7f94ec74282e 100644 --- a/drivers/media/usb/gspca/stv0680.c +++ b/drivers/media/usb/gspca/stv0680.c @@ -139,7 +139,7 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; - /* Give the camera some time to settle, otherwise initalization will + /* Give the camera some time to settle, otherwise initialization will fail on hotplug, and yes it really needs a full second. */ msleep(1000); diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index 7b95d8e88a20..d3e1b6d8bf49 100644 --- a/drivers/media/usb/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c @@ -6905,7 +6905,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ + int len) /* interrupt packet length */ { if (len == 8 && data[4] == 1) { input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 77bbf7889659..78c9bc8e7f56 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -1039,7 +1039,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id /* Set the leds off */ pwc_set_leds(pdev, 0, 0); - /* Setup intial videomode */ + /* Setup initial videomode */ rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, V4L2_PIX_FMT_YUV420, 30, &compression, 1); if (rc) diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 899cb6d1c4a4..898c208889cd 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -556,7 +556,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample) * * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1) * - * to avoid loosing precision in the division. Similarly, the host timestamp is + * to avoid losing precision in the division. Similarly, the host timestamp is * computed with * * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 60dcc0f3b32e..fb46790d0eca 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -420,7 +420,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Advanced Simple", "Core", "Simple Scalable", - "Advanced Coding Efficency", + "Advanced Coding Efficiency", NULL, }; -- cgit v1.2.3 From 0e0fe3958fdd13dbf55c3a787acafde6efd04272 Mon Sep 17 00:00:00 2001 From: Georg Kaindl Date: Mon, 21 Oct 2013 12:01:36 -0300 Subject: [media] usbtv: Add support for PAL video source Signed-off-by: Georg Kaindl Tested-by: Lubomir Rintel Tested-by: Marcin Nowak Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv.c | 174 +++++++++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 8a505a90d318..6222a4ab1e00 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c @@ -50,13 +50,8 @@ #define USBTV_ISOC_TRANSFERS 16 #define USBTV_ISOC_PACKETS 8 -#define USBTV_WIDTH 720 -#define USBTV_HEIGHT 480 - #define USBTV_CHUNK_SIZE 256 #define USBTV_CHUNK 240 -#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ - / 4 / USBTV_CHUNK) /* Chunk header. */ #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ @@ -65,6 +60,27 @@ #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) +#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL) + +/* parameters for supported TV norms */ +struct usbtv_norm_params { + v4l2_std_id norm; + int cap_width, cap_height; +}; + +static struct usbtv_norm_params norm_params[] = { + { + .norm = V4L2_STD_525_60, + .cap_width = 720, + .cap_height = 480, + }, + { + .norm = V4L2_STD_PAL, + .cap_width = 720, + .cap_height = 576, + } +}; + /* A single videobuf2 frame buffer. */ struct usbtv_buf { struct vb2_buffer vb; @@ -94,11 +110,38 @@ struct usbtv { USBTV_COMPOSITE_INPUT, USBTV_SVIDEO_INPUT, } input; + v4l2_std_id norm; + int width, height; + int n_chunks; int iso_size; unsigned int sequence; struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; }; +static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm) +{ + int i, ret = 0; + struct usbtv_norm_params *params = NULL; + + for (i = 0; i < ARRAY_SIZE(norm_params); i++) { + if (norm_params[i].norm & norm) { + params = &norm_params[i]; + break; + } + } + + if (params) { + usbtv->width = params->cap_width; + usbtv->height = params->cap_height; + usbtv->n_chunks = usbtv->width * usbtv->height + / 4 / USBTV_CHUNK; + usbtv->norm = params->norm; + } else + ret = -EINVAL; + + return ret; +} + static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) { int ret; @@ -158,6 +201,57 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) return ret; } +static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) +{ + int ret; + static const u16 pal[][2] = { + { USBTV_BASE + 0x001a, 0x0068 }, + { USBTV_BASE + 0x010e, 0x0072 }, + { USBTV_BASE + 0x010f, 0x00a2 }, + { USBTV_BASE + 0x0112, 0x00b0 }, + { USBTV_BASE + 0x0117, 0x0001 }, + { USBTV_BASE + 0x0118, 0x002c }, + { USBTV_BASE + 0x012d, 0x0010 }, + { USBTV_BASE + 0x012f, 0x0020 }, + { USBTV_BASE + 0x024f, 0x0002 }, + { USBTV_BASE + 0x0254, 0x0059 }, + { USBTV_BASE + 0x025a, 0x0016 }, + { USBTV_BASE + 0x025b, 0x0035 }, + { USBTV_BASE + 0x0263, 0x0017 }, + { USBTV_BASE + 0x0266, 0x0016 }, + { USBTV_BASE + 0x0267, 0x0036 } + }; + + static const u16 ntsc[][2] = { + { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x010e, 0x0068 }, + { USBTV_BASE + 0x010f, 0x009c }, + { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0117, 0x0000 }, + { USBTV_BASE + 0x0118, 0x00fc }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x024f, 0x0001 }, + { USBTV_BASE + 0x0254, 0x005f }, + { USBTV_BASE + 0x025a, 0x0012 }, + { USBTV_BASE + 0x025b, 0x0001 }, + { USBTV_BASE + 0x0263, 0x001c }, + { USBTV_BASE + 0x0266, 0x0011 }, + { USBTV_BASE + 0x0267, 0x0005 } + }; + + ret = usbtv_configure_for_norm(usbtv, norm); + + if (!ret) { + if (norm & V4L2_STD_525_60) + ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); + else if (norm & V4L2_STD_PAL) + ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); + } + + return ret; +} + static int usbtv_setup_capture(struct usbtv *usbtv) { int ret; @@ -225,26 +319,11 @@ static int usbtv_setup_capture(struct usbtv *usbtv) { USBTV_BASE + 0x0284, 0x0088 }, { USBTV_BASE + 0x0003, 0x0004 }, - { USBTV_BASE + 0x001a, 0x0079 }, { USBTV_BASE + 0x0100, 0x00d3 }, - { USBTV_BASE + 0x010e, 0x0068 }, - { USBTV_BASE + 0x010f, 0x009c }, - { USBTV_BASE + 0x0112, 0x00f0 }, { USBTV_BASE + 0x0115, 0x0015 }, - { USBTV_BASE + 0x0117, 0x0000 }, - { USBTV_BASE + 0x0118, 0x00fc }, - { USBTV_BASE + 0x012d, 0x0004 }, - { USBTV_BASE + 0x012f, 0x0008 }, { USBTV_BASE + 0x0220, 0x002e }, { USBTV_BASE + 0x0225, 0x0008 }, { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024f, 0x0001 }, - { USBTV_BASE + 0x0254, 0x005f }, - { USBTV_BASE + 0x025a, 0x0012 }, - { USBTV_BASE + 0x025b, 0x0001 }, - { USBTV_BASE + 0x0263, 0x001c }, - { USBTV_BASE + 0x0266, 0x0011 }, - { USBTV_BASE + 0x0267, 0x0005 }, { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -253,6 +332,10 @@ static int usbtv_setup_capture(struct usbtv *usbtv) if (ret) return ret; + ret = usbtv_select_norm(usbtv, usbtv->norm); + if (ret) + return ret; + ret = usbtv_select_input(usbtv, usbtv->input); if (ret) return ret; @@ -296,7 +379,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) frame_id = USBTV_FRAME_ID(chunk); odd = USBTV_ODD(chunk); chunk_no = USBTV_CHUNK_NO(chunk); - if (chunk_no >= USBTV_CHUNKS) + if (chunk_no >= usbtv->n_chunks) return; /* Beginning of a frame. */ @@ -324,10 +407,10 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) usbtv->chunks_done++; /* Last chunk in a frame, signalling an end */ - if (odd && chunk_no == USBTV_CHUNKS-1) { + if (odd && chunk_no == usbtv->n_chunks-1) { int size = vb2_plane_size(&buf->vb, 0); enum vb2_buffer_state state = usbtv->chunks_done == - USBTV_CHUNKS ? + usbtv->n_chunks ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; @@ -500,6 +583,8 @@ static int usbtv_querycap(struct file *file, void *priv, static int usbtv_enum_input(struct file *file, void *priv, struct v4l2_input *i) { + struct usbtv *dev = video_drvdata(file); + switch (i->index) { case USBTV_COMPOSITE_INPUT: strlcpy(i->name, "Composite", sizeof(i->name)); @@ -512,7 +597,7 @@ static int usbtv_enum_input(struct file *file, void *priv, } i->type = V4L2_INPUT_TYPE_CAMERA; - i->std = V4L2_STD_525_60; + i->std = dev->vdev.tvnorms; return 0; } @@ -531,23 +616,37 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, static int usbtv_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - f->fmt.pix.width = USBTV_WIDTH; - f->fmt.pix.height = USBTV_HEIGHT; + struct usbtv *usbtv = video_drvdata(file); + + f->fmt.pix.width = usbtv->width; + f->fmt.pix.height = usbtv->height; f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.bytesperline = USBTV_WIDTH * 2; + f->fmt.pix.bytesperline = usbtv->width * 2; f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height); f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; + return 0; } static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - *norm = V4L2_STD_525_60; + struct usbtv *usbtv = video_drvdata(file); + *norm = usbtv->norm; return 0; } +static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) +{ + int ret = -EINVAL; + struct usbtv *usbtv = video_drvdata(file); + + if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL)) + ret = usbtv_select_norm(usbtv, norm); + + return ret; +} + static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) { struct usbtv *usbtv = video_drvdata(file); @@ -561,13 +660,6 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i) return usbtv_select_input(usbtv, i); } -static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) -{ - if (norm & V4L2_STD_525_60) - return 0; - return -EINVAL; -} - struct v4l2_ioctl_ops usbtv_ioctl_ops = { .vidioc_querycap = usbtv_querycap, .vidioc_enum_input = usbtv_enum_input, @@ -604,10 +696,12 @@ static int usbtv_queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { + struct usbtv *usbtv = vb2_get_drv_priv(vq); + if (*nbuffers < 2) *nbuffers = 2; *nplanes = 1; - sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32); + sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32); return 0; } @@ -690,7 +784,11 @@ static int usbtv_probe(struct usb_interface *intf, return -ENOMEM; usbtv->dev = dev; usbtv->udev = usb_get_dev(interface_to_usbdev(intf)); + usbtv->iso_size = size; + + (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60); + spin_lock_init(&usbtv->buflock); mutex_init(&usbtv->v4l2_lock); mutex_init(&usbtv->vb2q_lock); @@ -727,7 +825,7 @@ static int usbtv_probe(struct usb_interface *intf, usbtv->vdev.release = video_device_release_empty; usbtv->vdev.fops = &usbtv_fops; usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops; - usbtv->vdev.tvnorms = V4L2_STD_525_60; + usbtv->vdev.tvnorms = USBTV_TV_STD; usbtv->vdev.queue = &usbtv->vb2q; usbtv->vdev.lock = &usbtv->v4l2_lock; set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); -- cgit v1.2.3 From 98c24dcd6392784b1cd0dca462abe6f91f0cadc9 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 6 Nov 2013 05:39:35 -0300 Subject: [media] em28xx-video: Swap release order to avoid lock nesting vb2_fop_release might take the video queue mutex lock. In order to avoid nesting mutexes the private mutex is taken after the fop_release has finished. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index fc5d60efd4ab..dd19c9ff76e0 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1664,8 +1664,8 @@ static int em28xx_v4l2_close(struct file *filp) em28xx_videodbg("users=%d\n", dev->users); - mutex_lock(&dev->lock); vb2_fop_release(filp); + mutex_lock(&dev->lock); if (dev->users == 1) { /* the device is already disconnect, -- cgit v1.2.3 From a3d94dafbba04f498beacec68a32b063bbf62d08 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 6 Nov 2013 11:40:18 -0300 Subject: [media] ths7303: Declare as static a private function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git grep shows that the function is only called from ths7303.c Fix this build warning: CC drivers/media/i2c/ths7303.o drivers/media/i2c/ths7303.c:86:5: warning: no previous prototype for ‘ths7303_setval’ [-Wmissing-prototypes] int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode) ^ Signed-off-by: Ricardo Ribalda Delgado Acked-by: Laurent Pinchart Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ths7303.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 42276d93624c..ed9ae8875348 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -83,7 +83,8 @@ static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val) } /* following function is used to set ths7303 */ -int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode) +static int ths7303_setval(struct v4l2_subdev *sd, + enum ths7303_filter_mode mode) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ths7303_state *state = to_state(sd); -- cgit v1.2.3 From fe4a0f1c7d316734b4614ce626e6126bc302a4b6 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 4 Nov 2013 23:18:15 -0300 Subject: [media] marvell-ccic: drop resource free in driver remove The mmp-driver is using devm_* to allocate the resource. The old resource release methods are not appropriate here. Signed-off-by: Libin Yang Acked-by: Jonathan Corbet Signed-off-by: Hans Verkuil Cc: stable@vger.kernel.org # for v3.12 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/mmp-driver.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index 3458fa0e2fd5..70cb57f3adc2 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -478,18 +478,11 @@ out_deinit_clk: static int mmpcam_remove(struct mmp_camera *cam) { struct mcam_camera *mcam = &cam->mcam; - struct mmp_camera_platform_data *pdata; mmpcam_remove_device(cam); mccic_shutdown(mcam); mmpcam_power_down(mcam); - pdata = cam->pdev->dev.platform_data; - gpio_free(pdata->sensor_reset_gpio); - gpio_free(pdata->sensor_power_gpio); mcam_deinit_clk(mcam); - iounmap(cam->power_regs); - iounmap(mcam->regs); - kfree(cam); return 0; } -- cgit v1.2.3 From fa507e4d32bf6c35eb5fe7dbc0593ae3723c9575 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Tue, 5 Nov 2013 05:29:07 -0300 Subject: [media] media: marvell-ccic: use devm to release clk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch uses devm to release the clks instead of releasing manually. And it adds enable/disable mipi_clk when getting its rate. Signed-off-by: Libin Yang Acked-by: Jonathan Corbet Acked-by: Uwe Kleine-König Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/mmp-driver.c | 39 +++++------------------- 1 file changed, 8 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index 70cb57f3adc2..054507f16734 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -142,12 +142,6 @@ static int mmpcam_power_up(struct mcam_camera *mcam) struct mmp_camera *cam = mcam_to_cam(mcam); struct mmp_camera_platform_data *pdata; - if (mcam->bus_type == V4L2_MBUS_CSI2) { - cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); - if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) - return PTR_ERR(cam->mipi_clk); - } - /* * Turn on power and clocks to the controller. */ @@ -186,12 +180,6 @@ static void mmpcam_power_down(struct mcam_camera *mcam) gpio_set_value(pdata->sensor_power_gpio, 0); gpio_set_value(pdata->sensor_reset_gpio, 0); - if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) { - if (cam->mipi_clk) - devm_clk_put(mcam->dev, cam->mipi_clk); - cam->mipi_clk = NULL; - } - mcam_clk_disable(mcam); } @@ -292,8 +280,9 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam) return; /* get the escape clk, this is hard coded */ + clk_prepare_enable(cam->mipi_clk); tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12; - + clk_disable_unprepare(cam->mipi_clk); /* * dphy[2] - CSI2_DPHY6: * bit 0 ~ bit 7: CK Term Enable @@ -325,19 +314,6 @@ static irqreturn_t mmpcam_irq(int irq, void *data) return IRQ_RETVAL(handled); } -static void mcam_deinit_clk(struct mcam_camera *mcam) -{ - unsigned int i; - - for (i = 0; i < NR_MCAM_CLK; i++) { - if (!IS_ERR(mcam->clk[i])) { - if (mcam->clk[i]) - devm_clk_put(mcam->dev, mcam->clk[i]); - } - mcam->clk[i] = NULL; - } -} - static void mcam_init_clk(struct mcam_camera *mcam) { unsigned int i; @@ -371,7 +347,6 @@ static int mmpcam_probe(struct platform_device *pdev) if (cam == NULL) return -ENOMEM; cam->pdev = pdev; - cam->mipi_clk = NULL; INIT_LIST_HEAD(&cam->devlist); mcam = &cam->mcam; @@ -387,6 +362,11 @@ static int mmpcam_probe(struct platform_device *pdev) mcam->mclk_div = pdata->mclk_div; mcam->bus_type = pdata->bus_type; mcam->dphy = pdata->dphy; + if (mcam->bus_type == V4L2_MBUS_CSI2) { + cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); + if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) + return PTR_ERR(cam->mipi_clk); + } mcam->mipi_enabled = false; mcam->lane = pdata->lane; mcam->chip_id = MCAM_ARMADA610; @@ -444,7 +424,7 @@ static int mmpcam_probe(struct platform_device *pdev) */ ret = mmpcam_power_up(mcam); if (ret) - goto out_deinit_clk; + return ret; ret = mccic_register(mcam); if (ret) goto out_power_down; @@ -469,8 +449,6 @@ out_unregister: mccic_shutdown(mcam); out_power_down: mmpcam_power_down(mcam); -out_deinit_clk: - mcam_deinit_clk(mcam); return ret; } @@ -482,7 +460,6 @@ static int mmpcam_remove(struct mmp_camera *cam) mmpcam_remove_device(cam); mccic_shutdown(mcam); mmpcam_power_down(mcam); - mcam_deinit_clk(mcam); return 0; } -- cgit v1.2.3 From e67adb4e669db834c1f95cbdf99bb4e9ec8455b3 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Fri, 8 Nov 2013 16:09:29 +0400 Subject: sata_rcar: Add R-Car Gen2 SATA PHY support R-Car Gen2 SoCs have a different PHY which is not compatible with the older R-Car H1 (R8A7779) version. This adds OF/platform device id tables and PHY initialization callbacks for the following Gen2 SoCs: * R-Car H2: R8A7790; * R-Car M2: R8A7791. PHY initialization method is chosen based on the device id. Default PHY settings are applied for Gen2 SoCs, which should suit the Gen2 boards available. While at it, this also adds "sata-r8a7779" compatibility string for R8A7779 SATA, while keeping the old one for compatibility. Signed-off-by: Valentine Barshak Signed-off-by: Tejun Heo --- drivers/ata/sata_rcar.c | 118 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c index 1dae9a9009f7..2b25bd83fc9d 100644 --- a/drivers/ata/sata_rcar.c +++ b/drivers/ata/sata_rcar.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -123,12 +124,37 @@ #define SATA_RCAR_DMA_BOUNDARY 0x1FFFFFFEUL +/* Gen2 Physical Layer Control Registers */ +#define RCAR_GEN2_PHY_CTL1_REG 0x1704 +#define RCAR_GEN2_PHY_CTL1 0x34180002 +#define RCAR_GEN2_PHY_CTL1_SS 0xC180 /* Spread Spectrum */ + +#define RCAR_GEN2_PHY_CTL2_REG 0x170C +#define RCAR_GEN2_PHY_CTL2 0x00002303 + +#define RCAR_GEN2_PHY_CTL3_REG 0x171C +#define RCAR_GEN2_PHY_CTL3 0x000B0194 + +#define RCAR_GEN2_PHY_CTL4_REG 0x1724 +#define RCAR_GEN2_PHY_CTL4 0x00030994 + +#define RCAR_GEN2_PHY_CTL5_REG 0x1740 +#define RCAR_GEN2_PHY_CTL5 0x03004001 +#define RCAR_GEN2_PHY_CTL5_DC BIT(1) /* DC connection */ +#define RCAR_GEN2_PHY_CTL5_TR BIT(2) /* Termination Resistor */ + +enum sata_rcar_type { + RCAR_GEN1_SATA, + RCAR_GEN2_SATA, +}; + struct sata_rcar_priv { void __iomem *base; struct clk *clk; + enum sata_rcar_type type; }; -static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv) +static void sata_rcar_gen1_phy_preinit(struct sata_rcar_priv *priv) { void __iomem *base = priv->base; @@ -141,8 +167,8 @@ static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv) iowrite32(0, base + SATAPHYRESET_REG); } -static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val, - int group) +static void sata_rcar_gen1_phy_write(struct sata_rcar_priv *priv, u16 reg, + u32 val, int group) { void __iomem *base = priv->base; int timeout; @@ -170,6 +196,29 @@ static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val, iowrite32(0, base + SATAPHYADDR_REG); } +static void sata_rcar_gen1_phy_init(struct sata_rcar_priv *priv) +{ + sata_rcar_gen1_phy_preinit(priv); + sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0); + sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1); + sata_rcar_gen1_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0); + sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0); + sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1); + sata_rcar_gen1_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0); +} + +static void sata_rcar_gen2_phy_init(struct sata_rcar_priv *priv) +{ + void __iomem *base = priv->base; + + iowrite32(RCAR_GEN2_PHY_CTL1, base + RCAR_GEN2_PHY_CTL1_REG); + iowrite32(RCAR_GEN2_PHY_CTL2, base + RCAR_GEN2_PHY_CTL2_REG); + iowrite32(RCAR_GEN2_PHY_CTL3, base + RCAR_GEN2_PHY_CTL3_REG); + iowrite32(RCAR_GEN2_PHY_CTL4, base + RCAR_GEN2_PHY_CTL4_REG); + iowrite32(RCAR_GEN2_PHY_CTL5 | RCAR_GEN2_PHY_CTL5_DC | + RCAR_GEN2_PHY_CTL5_TR, base + RCAR_GEN2_PHY_CTL5_REG); +} + static void sata_rcar_freeze(struct ata_port *ap) { struct sata_rcar_priv *priv = ap->host->private_data; @@ -738,13 +787,17 @@ static void sata_rcar_init_controller(struct ata_host *host) u32 val; /* reset and setup phy */ - sata_rcar_phy_initialize(priv); - sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0); - sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1); - sata_rcar_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0); - sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0); - sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1); - sata_rcar_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0); + switch (priv->type) { + case RCAR_GEN1_SATA: + sata_rcar_gen1_phy_init(priv); + break; + case RCAR_GEN2_SATA: + sata_rcar_gen2_phy_init(priv); + break; + default: + dev_warn(host->dev, "SATA phy is not initialized\n"); + break; + } /* SATA-IP reset state */ val = ioread32(base + ATAPI_CONTROL1_REG); @@ -770,8 +823,40 @@ static void sata_rcar_init_controller(struct ata_host *host) iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG); } +static struct of_device_id sata_rcar_match[] = { + { + /* Deprecated by "renesas,sata-r8a7779" */ + .compatible = "renesas,rcar-sata", + .data = (void *)RCAR_GEN1_SATA, + }, + { + .compatible = "renesas,sata-r8a7779", + .data = (void *)RCAR_GEN1_SATA, + }, + { + .compatible = "renesas,sata-r8a7790", + .data = (void *)RCAR_GEN2_SATA + }, + { + .compatible = "renesas,sata-r8a7791", + .data = (void *)RCAR_GEN2_SATA + }, + { }, +}; +MODULE_DEVICE_TABLE(of, sata_rcar_match); + +static const struct platform_device_id sata_rcar_id_table[] = { + { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */ + { "sata-r8a7779", RCAR_GEN1_SATA }, + { "sata-r8a7790", RCAR_GEN2_SATA }, + { "sata-r8a7791", RCAR_GEN2_SATA }, + { }, +}; +MODULE_DEVICE_TABLE(platform, sata_rcar_id_table); + static int sata_rcar_probe(struct platform_device *pdev) { + const struct of_device_id *of_id; struct ata_host *host; struct sata_rcar_priv *priv; struct resource *mem; @@ -787,6 +872,12 @@ static int sata_rcar_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + of_id = of_match_device(sata_rcar_match, &pdev->dev); + if (of_id) + priv->type = (enum sata_rcar_type)of_id->data; + else + priv->type = platform_get_device_id(pdev)->driver_data; + priv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "failed to get access to sata clock\n"); @@ -892,15 +983,10 @@ static const struct dev_pm_ops sata_rcar_pm_ops = { }; #endif -static struct of_device_id sata_rcar_match[] = { - { .compatible = "renesas,rcar-sata", }, - {}, -}; -MODULE_DEVICE_TABLE(of, sata_rcar_match); - static struct platform_driver sata_rcar_driver = { .probe = sata_rcar_probe, .remove = sata_rcar_remove, + .id_table = sata_rcar_id_table, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, -- cgit v1.2.3 From 87809942d3fa60bafb7a58d0bdb1c79e90a6821d Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 25 Nov 2013 19:00:14 +0000 Subject: libata: add ATA_HORKAGE_BROKEN_FPDMA_AA quirk for Seagate Momentus SpinPoint M8 We've received multiple reports in Fedora via (BZ 907193) that the Seagate Momentus SpinPoint M8 errors out when enabling AA: [ 2.555905] ata2.00: failed to enable AA (error_mask=0x1) [ 2.568482] ata2.00: failed to enable AA (error_mask=0x1) Add the ATA_HORKAGE_BROKEN_FPDMA_AA for this specific harddisk. Reported-by: Nicholas Signed-off-by: Michele Baldessari Tested-by: Nicholas Acked-by: Alan Cox Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/libata-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 75b93678bbcd..dae73efe5dbf 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4156,6 +4156,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, + /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ + { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, -- cgit v1.2.3 From f6308b36c411dc5afd6a6f73e6454722bfde57b7 Mon Sep 17 00:00:00 2001 From: Paul Drews Date: Mon, 25 Nov 2013 14:15:55 -0800 Subject: ACPI: Add BayTrail SoC GPIO and LPSS ACPI IDs This adds the new ACPI ID (INT33FC) for the BayTrail GPIO banks as seen on a BayTrail M System-On-Chip platform. This ACPI ID is used by the BayTrail GPIO (pinctrl) driver to manage the Low Power Subsystem (LPSS). Signed-off-by: Paul Drews Acked-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 1 + drivers/pinctrl/pinctrl-baytrail.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 6745fe137b9e..e60390597372 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -162,6 +162,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "80860F14", (unsigned long)&byt_sdio_dev_desc }, { "80860F41", (unsigned long)&byt_i2c_dev_desc }, { "INT33B2", }, + { "INT33FC", }, { "INT3430", (unsigned long)&lpt_dev_desc }, { "INT3431", (unsigned long)&lpt_dev_desc }, diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 2832576d8b12..114f5ef4b73a 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -512,6 +512,7 @@ static const struct dev_pm_ops byt_gpio_pm_ops = { static const struct acpi_device_id byt_gpio_acpi_match[] = { { "INT33B2", 0 }, + { "INT33FC", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); -- cgit v1.2.3 From 80c6463e2fa3377febfc98a6672d92d07f3c26c1 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 22 Nov 2013 10:54:28 -0700 Subject: power_supply: Fix Oops from NULL pointer dereference from wakeup_source_activate power_supply_register() calls device_init_wakeup() to register a wakeup source before initializing dev_name. As a result, device_wakeup_enable() end up registering wakeup source with a null name when wakeup_source_register() gets called with dev_name(dev) which is null at the time. When kernel is booted with wakeup_source_activate enabled, it will panic when the trace point code tries to dereference ws->name. Fixed the problem by moving up the kobject_set_name() call prior to accesses to dev_name(). Replaced kobject_set_name() with dev_set_name() which is the right interface to be called from drivers. Fixed the call to device_del() prior to device_add() in for wakeup_init_failed error handling code. Trace after the change: bash-2143 [003] d... 132.280697: wakeup_source_activate: BAT1 state=0x20001 kworker/3:2-1169 [003] d... 132.281305: wakeup_source_deactivate: BAT1 state=0x30000 Oops message: [ 819.769934] device: 'BAT1': device_add [ 819.770078] PM: Adding info for No Bus:BAT1 [ 819.770235] BUG: unable to handle kernel NULL pointer dereference at (null) [ 819.770435] IP: [] skip_spaces+0x30/0x30 [ 819.770572] PGD 3efd90067 PUD 3eff61067 PMD 0 [ 819.770716] Oops: 0000 [#1] SMP [ 819.770829] Modules linked in: arc4 iwldvm mac80211 x86_pkg_temp_thermal coretemp kvm_intel joydev i915 kvm uvcvideo ghash_clmulni_intel videobuf2_vmalloc aesni_intel videobuf2_memops videobuf2_core aes_x86_64 ablk_helper cryptd videodev iwlwifi lrw rfcomm gf128mul glue_helper bnep btusb media bluetooth parport_pc hid_generic ppdev snd_hda_codec_hdmi drm_kms_helper snd_hda_codec_realtek cfg80211 drm tpm_infineon samsung_laptop snd_hda_intel usbhid snd_hda_codec hid snd_hwdep snd_pcm microcode snd_page_alloc snd_timer psmouse i2c_algo_bit lpc_ich tpm_tis video wmi mac_hid serio_raw ext2 lp parport r8169 mii [ 819.771802] CPU: 0 PID: 2167 Comm: bash Not tainted 3.12.0+ #25 [ 819.771876] Hardware name: SAMSUNG ELECTRONICS CO., LTD. 900X3C/900X3D/900X4C/900X4D/SAMSUNG_NP1234567890, BIOS P03AAC 07/12/2012 [ 819.772022] task: ffff88002e6ddcc0 ti: ffff8804015ca000 task.ti: ffff8804015ca000 [ 819.772119] RIP: 0010:[] [] skip_spaces+0x30/0x30 [ 819.772242] RSP: 0018:ffff8804015cbc70 EFLAGS: 00010046 [ 819.772310] RAX: 0000000000000003 RBX: ffff88040cfd6d40 RCX: 0000000000000018 [ 819.772397] RDX: 0000000000020001 RSI: 0000000000000000 RDI: 0000000000000000 [ 819.772484] RBP: ffff8804015cbcc0 R08: 0000000000000000 R09: ffff8803f0768d40 [ 819.772570] R10: ffffea001033b800 R11: 0000000000000000 R12: ffffffff81c519c0 [ 819.772656] R13: 0000000000020001 R14: 0000000000000000 R15: 0000000000020001 [ 819.772744] FS: 00007ff98309b740(0000) GS:ffff88041f200000(0000) knlGS:0000000000000000 [ 819.772845] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 819.772917] CR2: 0000000000000000 CR3: 00000003f59dc000 CR4: 00000000001407f0 [ 819.773001] Stack: [ 819.773030] ffffffff81114003 ffff8804015cbcb0 0000000000000000 0000000000000046 [ 819.773146] ffff880409757a18 ffff8803f065a160 0000000000000000 0000000000020001 [ 819.773273] 0000000000000000 0000000000000000 ffff8804015cbce8 ffffffff8143e388 [ 819.773387] Call Trace: [ 819.773434] [] ? ftrace_raw_event_wakeup_source+0x43/0xe0 [ 819.773520] [] wakeup_source_report_event+0xb8/0xd0 [ 819.773595] [] __pm_stay_awake+0x2d/0x50 [ 819.773724] [] power_supply_changed+0x3c/0x90 [ 819.773795] [] power_supply_register+0x18c/0x250 [ 819.773869] [] sysfs_add_battery+0x61/0x7b [ 819.773935] [] battery_notify+0x37/0x3f [ 819.774001] [] notifier_call_chain+0x4c/0x70 [ 819.774071] [] __blocking_notifier_call_chain+0x4d/0x70 [ 819.774149] [] blocking_notifier_call_chain+0x16/0x20 [ 819.774227] [] pm_notifier_call_chain+0x1a/0x40 [ 819.774316] [] hibernate+0x66/0x1c0 [ 819.774407] [] state_store+0x71/0xa0 [ 819.774507] [] kobj_attr_store+0xf/0x20 [ 819.774613] [] sysfs_write_file+0x128/0x1c0 [ 819.774735] [] vfs_write+0xbd/0x1e0 [ 819.774841] [] SyS_write+0x49/0xa0 [ 819.774939] [] system_call_fastpath+0x16/0x1b [ 819.775055] Code: 89 f8 48 89 e5 f6 82 c0 a6 84 81 20 74 15 0f 1f 44 00 00 48 83 c0 01 0f b6 10 f6 82 c0 a6 84 81 20 75 f0 5d c3 66 0f 1f 44 00 00 <80> 3f 00 55 48 89 e5 74 15 48 89 f8 0f 1f 40 00 48 83 c0 01 80 [ 819.775760] RIP [] skip_spaces+0x30/0x30 [ 819.775881] RSP [ 819.775949] CR2: 0000000000000000 [ 819.794175] ---[ end trace c4ef25127039952e ]--- Signed-off-by: Shuah Khan Acked-by: Anton Vorontsov Acked-by: Greg Kroah-Hartman Cc: stable@vger.kernel.org Signed-off-by: Anton Vorontsov --- drivers/power/power_supply_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 00e667296360..557af943b2f5 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -511,6 +511,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy) dev_set_drvdata(dev, psy); psy->dev = dev; + rc = dev_set_name(dev, "%s", psy->name); + if (rc) + goto dev_set_name_failed; + INIT_WORK(&psy->changed_work, power_supply_changed_work); rc = power_supply_check_supplies(psy); @@ -524,10 +528,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy) if (rc) goto wakeup_init_failed; - rc = kobject_set_name(&dev->kobj, "%s", psy->name); - if (rc) - goto kobject_set_name_failed; - rc = device_add(dev); if (rc) goto device_add_failed; @@ -553,11 +553,11 @@ create_triggers_failed: register_cooler_failed: psy_unregister_thermal(psy); register_thermal_failed: -wakeup_init_failed: device_del(dev); -kobject_set_name_failed: device_add_failed: +wakeup_init_failed: check_supplies_failed: +dev_set_name_failed: put_device(dev); success: return rc; -- cgit v1.2.3 From 9403ac88220d79f8822e22c875ad1ebd7ffbea6f Mon Sep 17 00:00:00 2001 From: Chander Kashyap Date: Mon, 21 Oct 2013 06:01:40 +0900 Subject: irqchip: exynos-combiner: remove hard-coded irq_base value Replace irq_domain_add_simple with "irq_domain_add_linear" in order to use linear irq domain, and to remove hardcoded irq_base_value. Signed-off-by: Chander Kashyap Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- drivers/irqchip/exynos-combiner.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index 868ed40cb6bf..40e6440348ff 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c @@ -171,8 +171,7 @@ static struct irq_domain_ops combiner_irq_domain_ops = { static void __init combiner_init(void __iomem *combiner_base, struct device_node *np, - unsigned int max_nr, - int irq_base) + unsigned int max_nr) { int i, irq; unsigned int nr_irq; @@ -186,7 +185,7 @@ static void __init combiner_init(void __iomem *combiner_base, return; } - combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base, + combiner_irq_domain = irq_domain_add_linear(np, nr_irq, &combiner_irq_domain_ops, combiner_data); if (WARN_ON(!combiner_irq_domain)) { pr_warning("%s: irq domain init failed\n", __func__); @@ -207,7 +206,6 @@ static int __init combiner_of_init(struct device_node *np, { void __iomem *combiner_base; unsigned int max_nr = 20; - int irq_base = -1; combiner_base = of_iomap(np, 0); if (!combiner_base) { @@ -221,14 +219,7 @@ static int __init combiner_of_init(struct device_node *np, __func__, max_nr); } - /* - * FIXME: This is a hardwired COMBINER_IRQ(0,0). Once all devices - * get their IRQ from DT, remove this in order to get dynamic - * allocation. - */ - irq_base = 160; - - combiner_init(combiner_base, np, max_nr, irq_base); + combiner_init(combiner_base, np, max_nr); return 0; } -- cgit v1.2.3 From 93353e8088057dd988362e6cae727af43734b494 Mon Sep 17 00:00:00 2001 From: Austin Boyle Date: Sun, 24 Nov 2013 21:41:49 +1100 Subject: max17042_battery: Fix build errors caused by missing REGMAP_I2C config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit max17042 now uses regmap interface but does not enable config option. This patch fixes the following build errors: drivers/power/max17042_battery.c:661:15: error: variable ‘max17042_regmap_config’ has initializer but incomplete type drivers/power/max17042_battery.c:662:2: error: unknown field ‘reg_bits’ specified in initializer drivers/power/max17042_battery.c:662:2: warning: excess elements in struct initializer drivers/power/max17042_battery.c:662:2: warning: (near initialization for ‘max17042_regmap_config’) drivers/power/max17042_battery.c:663:2: error: unknown field ‘val_bits’ specified in initializer drivers/power/max17042_battery.c:663:2: warning: excess elements in struct initializer drivers/power/max17042_battery.c:663:2: warning: (near initialization for ‘max17042_regmap_config’) drivers/power/max17042_battery.c:664:2: error: unknown field ‘val_format_endian’ specified in initializer drivers/power/max17042_battery.c:664:23: error: ‘REGMAP_ENDIAN_NATIVE’ undeclared here (not in a function) drivers/power/max17042_battery.c:664:2: warning: excess elements in struct initializer drivers/power/max17042_battery.c:664:2: warning: (near initialization for ‘max17042_regmap_config’) drivers/power/max17042_battery.c: In function ‘max17042_probe’: drivers/power/max17042_battery.c:684:2: error: implicit declaration of function ‘devm_regmap_init_i2c’ Signed-off-by: Austin Boyle Acked-by: Jonghwa Lee Signed-off-by: Anton Vorontsov --- drivers/power/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 5e2054afe840..85ad58c6da17 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -196,6 +196,7 @@ config BATTERY_MAX17040 config BATTERY_MAX17042 tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" depends on I2C + select REGMAP_I2C help MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries in handheld and portable equipment. The MAX17042 is configured -- cgit v1.2.3 From d36240d26025bec95f3499e2401a56db98d9f01c Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Tue, 19 Nov 2013 11:18:03 +0100 Subject: power_supply: Add power_supply notifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a notifier chain to the power_supply, this helps drivers in other subsystem to listen to changes in power supply subsystem. This would help to take some actions in those drivers on changing the power supply properties. One such scenario is to increase/decrease system performance based on the battery capacity/voltage. Another scenario is to adjust the h/w peak current detection voltage/current thresholds based on battery voltage/capacity. The notifier helps drivers to listen to changes in power_suppy susbystem without polling the power_supply properties Signed-off-by: Jenny TC Signed-off-by: Pali Rohár Acked-by: Jenny TC Signed-off-by: Anton Vorontsov --- drivers/power/power_supply_core.c | 18 ++++++++++++++++++ include/linux/power_supply.h | 8 ++++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 557af943b2f5..6aac23cc6566 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,9 @@ struct class *power_supply_class; EXPORT_SYMBOL_GPL(power_supply_class); +ATOMIC_NOTIFIER_HEAD(power_supply_notifier); +EXPORT_SYMBOL_GPL(power_supply_notifier); + static struct device_type power_supply_dev_type; static bool __power_supply_is_supplied_by(struct power_supply *supplier, @@ -80,6 +84,8 @@ static void power_supply_changed_work(struct work_struct *work) class_for_each_device(power_supply_class, NULL, psy, __power_supply_changed_work); power_supply_update_leds(psy); + atomic_notifier_call_chain(&power_supply_notifier, + PSY_EVENT_PROP_CHANGED, psy); kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); spin_lock_irqsave(&psy->changed_lock, flags); } @@ -347,6 +353,18 @@ static void power_supply_dev_release(struct device *dev) kfree(dev); } +int power_supply_reg_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&power_supply_notifier, nb); +} +EXPORT_SYMBOL_GPL(power_supply_reg_notifier); + +void power_supply_unreg_notifier(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&power_supply_notifier, nb); +} +EXPORT_SYMBOL_GPL(power_supply_unreg_notifier); + #ifdef CONFIG_THERMAL static int power_supply_read_temp(struct thermal_zone_device *tzd, unsigned long *temp) diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 5c2600630dc9..3e28fe188d17 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -16,6 +16,7 @@ #include #include #include +#include struct device; @@ -158,6 +159,10 @@ enum power_supply_type { POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */ }; +enum power_supply_notifier_events { + PSY_EVENT_PROP_CHANGED, +}; + union power_supply_propval { int intval; const char *strval; @@ -235,6 +240,9 @@ struct power_supply_info { int use_for_apm; }; +extern struct atomic_notifier_head power_supply_notifier; +extern int power_supply_reg_notifier(struct notifier_block *nb); +extern void power_supply_unreg_notifier(struct notifier_block *nb); extern struct power_supply *power_supply_get_by_name(const char *name); extern void power_supply_changed(struct power_supply *psy); extern int power_supply_am_i_supplied(struct power_supply *psy); -- cgit v1.2.3 From c8ca9d6aa676b7a26ae9dce6e50222519380e483 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 23 Aug 2013 10:21:21 +0800 Subject: drm/rcar-du: fix return value check in rcar_du_lvdsenc_get_resources() In case of error, the function devm_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Also remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c index a0f6a1781925..fe1f6f59f539 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c @@ -144,18 +144,9 @@ static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds, sprintf(name, "lvds.%u", lvds->index); mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (mem == NULL) { - dev_err(&pdev->dev, "failed to get memory resource for %s\n", - name); - return -EINVAL; - } - lvds->mmio = devm_ioremap_resource(&pdev->dev, mem); - if (lvds->mmio == NULL) { - dev_err(&pdev->dev, "failed to remap memory resource for %s\n", - name); - return -ENOMEM; - } + if (IS_ERR(lvds->mmio)) + return PTR_ERR(lvds->mmio); lvds->clock = devm_clk_get(&pdev->dev, name); if (IS_ERR(lvds->clock)) { -- cgit v1.2.3 From f5abcc4674c3aa9d745772bb3fd51db60c93161f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Nov 2013 14:38:03 +0100 Subject: drm/rcar-du: Don't cast crtc to rcrtc twice in the same function Reuse the previously cast variable instead. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index a9d24e4bf792..d2af2bcf3eae 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -413,7 +413,7 @@ static int rcar_du_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, rcrtc->plane->src_x = x; rcrtc->plane->src_y = y; - rcar_du_crtc_update_base(to_rcar_crtc(crtc)); + rcar_du_crtc_update_base(rcrtc); return 0; } -- cgit v1.2.3 From eb86301f293da3c362db729a9f40ddb25755902b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Nov 2013 14:26:01 +0100 Subject: drm/rcar-du: Update plane pitch in .mode_set_base() operation When setting a new frame buffer with the mode set base operation the pitch value might change. Set the hardware plane pitch register at the same time as the plane base address in the rcar_du_plane_update_base() function to make sure the pitch value always matches the frame buffer. Cc: stable@vger.kernel.org Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 1 - drivers/gpu/drm/rcar-du/rcar_du_plane.c | 21 +++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index d2af2bcf3eae..fbf4be316d0b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -371,7 +371,6 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc, goto error; rcrtc->plane->format = format; - rcrtc->plane->pitch = crtc->fb->pitches[0]; rcrtc->plane->src_x = x; rcrtc->plane->src_y = y; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 53000644733f..3fb69d9ae61b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -104,6 +104,15 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane) { struct rcar_du_group *rgrp = plane->group; unsigned int index = plane->hwindex; + u32 mwr; + + /* Memory pitch (expressed in pixels) */ + if (plane->format->planes == 2) + mwr = plane->pitch; + else + mwr = plane->pitch * 8 / plane->format->bpp; + + rcar_du_plane_write(rgrp, index, PnMWR, mwr); /* The Y position is expressed in raster line units and must be doubled * for 32bpp formats, according to the R8A7790 datasheet. No mention of @@ -133,6 +142,8 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane, { struct drm_gem_cma_object *gem; + plane->pitch = fb->pitches[0]; + gem = drm_fb_cma_get_gem_obj(fb, 0); plane->dma[0] = gem->paddr + fb->offsets[0]; @@ -209,7 +220,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, struct rcar_du_group *rgrp = plane->group; u32 ddcr2 = PnDDCR2_CODE; u32 ddcr4; - u32 mwr; /* Data format * @@ -240,14 +250,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2); rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4); - /* Memory pitch (expressed in pixels) */ - if (plane->format->planes == 2) - mwr = plane->pitch; - else - mwr = plane->pitch * 8 / plane->format->bpp; - - rcar_du_plane_write(rgrp, index, PnMWR, mwr); - /* Destination position and size */ rcar_du_plane_write(rgrp, index, PnDSXR, plane->width); rcar_du_plane_write(rgrp, index, PnDSYR, plane->height); @@ -309,7 +311,6 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, rplane->crtc = crtc; rplane->format = format; - rplane->pitch = fb->pitches[0]; rplane->src_x = src_x >> 16; rplane->src_y = src_y >> 16; -- cgit v1.2.3 From e8355e0dc48c966477e6b427e7043ea71698776a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Nov 2013 13:33:45 +0100 Subject: drm/rcar-du: Split features and quirks 128-byte pitch alignement is not a hardware feature, it's a hardware bug. Split it from the features field into a new quirks field. New quirks will be added to support the R8A7791 SoC. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 13 +++++++++++-- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0023f9719cf1..a0ffacb4b80b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -249,8 +249,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = { }; static const struct rcar_du_device_info rcar_du_r8a7790_info = { - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B - | RCAR_DU_FEATURE_DEFR8, + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, + .quirks = RCAR_DU_QUIRK_ALIGN_128B, .num_crtcs = 3, .routes = { /* R8A7790 has one RGB output, two LVDS outputs and one diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 65d2d636b002..7ca98f352479 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -28,8 +28,9 @@ struct rcar_du_device; struct rcar_du_lvdsenc; #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ -#define RCAR_DU_FEATURE_ALIGN_128B (1 << 1) /* Align pitches to 128 bytes */ -#define RCAR_DU_FEATURE_DEFR8 (1 << 2) /* Has DEFR8 register */ +#define RCAR_DU_FEATURE_DEFR8 (1 << 1) /* Has DEFR8 register */ + +#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */ /* * struct rcar_du_output_routing - Output routing specification @@ -48,12 +49,14 @@ struct rcar_du_output_routing { /* * struct rcar_du_device_info - DU model-specific information * @features: device features (RCAR_DU_FEATURE_*) + * @quirks: device quirks (RCAR_DU_QUIRK_*) * @num_crtcs: total number of CRTCs * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*) * @num_lvds: number of internal LVDS encoders */ struct rcar_du_device_info { unsigned int features; + unsigned int quirks; unsigned int num_crtcs; struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; unsigned int num_lvds; @@ -84,6 +87,12 @@ static inline bool rcar_du_has(struct rcar_du_device *rcdu, return rcdu->info->features & feature; } +static inline bool rcar_du_needs(struct rcar_du_device *rcdu, + unsigned int quirk) +{ + return rcdu->info->quirks & quirk; +} + static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg) { return ioread32(rcdu->mmio + reg); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index b31ac080c4a7..fbeabd9a281f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -119,7 +119,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev, /* The R8A7779 DU requires a 16 pixels pitch alignment as documented, * but the R8A7790 DU seems to require a 128 bytes pitch alignment. */ - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B)) + if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) align = 128; else align = 16 * args->bpp / 8; @@ -144,7 +144,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-EINVAL); } - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B)) + if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) align = 128; else align = 16 * format->bpp / 8; -- cgit v1.2.3 From 5cca30ebe089be23bc2588c4b76af69e89b3b639 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Nov 2013 13:35:15 +0100 Subject: drm/rcar-du: Add LVDS_LANES quirk LVDS lanes 1 and 3 are switched in ES1 hardware (R8A7790). The problem has been fixed in newer revisions, add a quirk to make the workaround selectable. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 15 ++++++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index a0ffacb4b80b..4eee02f89965 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -250,7 +250,7 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = { static const struct rcar_du_device_info rcar_du_r8a7790_info = { .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, - .quirks = RCAR_DU_QUIRK_ALIGN_128B, + .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES, .num_crtcs = 3, .routes = { /* R8A7790 has one RGB output, two LVDS outputs and one diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 7ca98f352479..e31b735d3f25 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -31,6 +31,7 @@ struct rcar_du_lvdsenc; #define RCAR_DU_FEATURE_DEFR8 (1 << 1) /* Has DEFR8 register */ #define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */ +#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */ /* * struct rcar_du_output_routing - Output routing specification diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c index fe1f6f59f539..df30a075d793 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c @@ -44,6 +44,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, const struct drm_display_mode *mode = &rcrtc->crtc.mode; unsigned int freq = mode->clock; u32 lvdcr0; + u32 lvdhcr; u32 pllcr; int ret; @@ -72,15 +73,19 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, * VSYNC -> CTRL1 * DISP -> CTRL2 * 0 -> CTRL3 - * - * Channels 1 and 3 are switched on ES1. */ rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO | LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC | LVDCTRCR_CTR0SEL_HSYNC); - rcar_lvds_write(lvds, LVDCHCR, - LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) | - LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1)); + + if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES)) + lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) + | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1); + else + lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1) + | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3); + + rcar_lvds_write(lvds, LVDCHCR, lvdhcr); /* Select the input, hardcode mode 0, enable LVDS operation and turn * bias circuitry on. -- cgit v1.2.3 From 29ee6469e6138115420236a71c6b89bf8af1788a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 11 Nov 2013 19:08:13 +0100 Subject: drm/rcar-du: Add support for the r8a7791 DU The r8a7791 DU is a stripped-down version of the r8a7790 DU with two CRTCs and a single LVDS output. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 4eee02f89965..5536811a8cbe 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -272,9 +272,29 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { .num_lvds = 2, }; +static const struct rcar_du_device_info rcar_du_r8a7791_info = { + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, + .num_crtcs = 2, + .routes = { + /* R8A7791 has one RGB output, one LVDS output and one + * (currently unsupported) TCON output. + */ + [RCAR_DU_OUTPUT_DPAD0] = { + .possible_crtcs = BIT(1), + .encoder_type = DRM_MODE_ENCODER_NONE, + }, + [RCAR_DU_OUTPUT_LVDS0] = { + .possible_crtcs = BIT(0), + .encoder_type = DRM_MODE_ENCODER_LVDS, + }, + }, + .num_lvds = 1, +}; + static const struct platform_device_id rcar_du_id_table[] = { { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info }, { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info }, + { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info }, { } }; -- cgit v1.2.3 From c52b4fc7817579c88db55b2029db7bf2e9d4c934 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 1 Dec 2013 22:11:26 -0800 Subject: Input: ads7846 - use IS_ENABLED() macro Using the IS_ENABLED() macro can make the code shorter and simpler Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index ea195360747e..569578638233 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -101,7 +101,7 @@ struct ads7846 { struct spi_device *spi; struct regulator *reg; -#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) +#if IS_ENABLED(CONFIG_HWMON) struct attribute_group *attr_group; struct device *hwmon; #endif @@ -421,7 +421,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command) return status; } -#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) +#if IS_ENABLED(CONFIG_HWMON) #define SHOW(name, var, adjust) static ssize_t \ name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ -- cgit v1.2.3 From 1d940aaab881b0ee62557ffbaad877ac5a1b51db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Nov 2013 17:23:26 +0100 Subject: mac80211_hwsim: use CLOCK_MONOTONIC_RAW The beacon timers really shouldn't use any clock that is subject to adjustments from userspace, particularly not CLOCK_REALTIME. Use CLOCK_MONOTONIC_RAW instead. Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index bcc7d8208f23..ab875566c744 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2580,7 +2580,7 @@ static int __init init_mac80211_hwsim(void) tasklet_hrtimer_init(&data->beacon_timer, mac80211_hwsim_beacon, - CLOCK_REALTIME, HRTIMER_MODE_ABS); + CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); list_add_tail(&data->list, &hwsim_radios); } -- cgit v1.2.3 From b176e629402f41f2b984d3aa842ddae23ed5562e Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Mon, 18 Nov 2013 19:06:49 +0200 Subject: cfg80211: aggregate mgmt_tx parameters into a struct Change cfg80211 and mac80211 to use cfg80211_mgmt_tx_params struct to aggregate parameters for mgmt_tx functions. This makes the functions' signatures less clumsy and allows less painful parameters extension. Signed-off-by: Andrei Otcheretianski [fix all other drivers] Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 9 ++++-- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 7 +++-- drivers/net/wireless/mwifiex/cfg80211.c | 6 ++-- include/net/cfg80211.h | 28 +++++++++++++++++-- net/mac80211/cfg.c | 29 ++++++++++---------- net/wireless/core.h | 5 ++-- net/wireless/mlme.c | 12 +++----- net/wireless/nl80211.c | 32 +++++++++++----------- net/wireless/rdev-ops.h | 12 +++----- net/wireless/trace.h | 15 +++++----- 10 files changed, 86 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 2437ad26949d..36dc61da8336 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3169,12 +3169,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len) } static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, u64 *cookie) { struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev); struct ath6kl *ar = ath6kl_priv(vif->ndev); + struct ieee80211_channel *chan = params->chan; + const u8 *buf = params->buf; + size_t len = params->len; + unsigned int wait = params->wait; + bool no_cck = params->no_cck; u32 id, freq; const struct ieee80211_mgmt *mgmt; bool more_data, queued; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 1850efa83cf8..f0bdfb120667 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3973,11 +3973,12 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy, static int brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, u64 *cookie) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct ieee80211_channel *chan = params->chan; + const u8 *buf = params->buf; + size_t len = params->len; const struct ieee80211_mgmt *mgmt; struct brcmf_cfg80211_vif *vif; s32 err = 0; diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index d6d1d91a26dc..1c8116d46845 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -184,10 +184,10 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) */ static int mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, u64 *cookie) { + const u8 *buf = params->buf; + size_t len = params->len; struct sk_buff *skb; u16 pkt_len; const struct ieee80211_mgmt *mgmt; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index bacc5033f0b6..6c2bc329a900 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1943,6 +1943,29 @@ struct cfg80211_update_ft_ies_params { size_t ie_len; }; +/** + * struct cfg80211_mgmt_tx_params - mgmt tx parameters + * + * This structure provides information needed to transmit a mgmt frame + * + * @chan: channel to use + * @offchan: indicates wether off channel operation is required + * @wait: duration for ROC + * @buf: buffer to transmit + * @len: buffer length + * @no_cck: don't use cck rates for this frame + * @dont_wait_for_ack: tells the low level not to wait for an ack + */ +struct cfg80211_mgmt_tx_params { + struct ieee80211_channel *chan; + bool offchan; + unsigned int wait; + const u8 *buf; + size_t len; + bool no_cck; + bool dont_wait_for_ack; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -2341,9 +2364,8 @@ struct cfg80211_ops { u64 cookie); int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie); + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c7b3e57aec04..267d3aca9947 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3167,26 +3167,25 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, } static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct sta_info *sta; - const struct ieee80211_mgmt *mgmt = (void *)buf; + const struct ieee80211_mgmt *mgmt = (void *)params->buf; bool need_offchan = false; u32 flags; int ret; - if (dont_wait_for_ack) + if (params->dont_wait_for_ack) flags = IEEE80211_TX_CTL_NO_ACK; else flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | IEEE80211_TX_CTL_REQ_TX_STATUS; - if (no_cck) + if (params->no_cck) flags |= IEEE80211_TX_CTL_NO_CCK_RATE; switch (sdata->vif.type) { @@ -3234,7 +3233,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, /* configurations requiring offchan cannot work if no channel has been * specified */ - if (need_offchan && !chan) + if (need_offchan && !params->chan) return -EINVAL; mutex_lock(&local->mtx); @@ -3247,8 +3246,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (chanctx_conf) { - need_offchan = chan && (chan != chanctx_conf->def.chan); - } else if (!chan) { + need_offchan = params->chan && + (params->chan != + chanctx_conf->def.chan); + } else if (!params->chan) { ret = -EINVAL; rcu_read_unlock(); goto out_unlock; @@ -3258,19 +3259,19 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, rcu_read_unlock(); } - if (need_offchan && !offchan) { + if (need_offchan && !params->offchan) { ret = -EBUSY; goto out_unlock; } - skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len); if (!skb) { ret = -ENOMEM; goto out_unlock; } skb_reserve(skb, local->hw.extra_tx_headroom); - memcpy(skb_put(skb, len), buf, len); + memcpy(skb_put(skb, params->len), params->buf, params->len); IEEE80211_SKB_CB(skb)->flags = flags; @@ -3290,8 +3291,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, local->hw.offchannel_tx_hw_queue; /* This will handle all kinds of coalescing and immediate TX */ - ret = ieee80211_start_roc_work(local, sdata, chan, - wait, cookie, skb, + ret = ieee80211_start_roc_work(local, sdata, params->chan, + params->wait, cookie, skb, IEEE80211_ROC_TYPE_MGMT_TX); if (ret) kfree_skb(skb); diff --git a/net/wireless/core.h b/net/wireless/core.h index 2888867ee7c5..6716c5c3f748 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -317,9 +317,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie); + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, const struct ieee80211_ht_cap *ht_capa_mask); void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 31f541f7e4ea..52cca05044a8 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -520,9 +520,7 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, u64 *cookie) { const struct ieee80211_mgmt *mgmt; u16 stype; @@ -533,10 +531,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, if (!rdev->ops->mgmt_tx) return -EOPNOTSUPP; - if (len < 24 + 1) + if (params->len < 24 + 1) return -EINVAL; - mgmt = (const struct ieee80211_mgmt *) buf; + mgmt = (const struct ieee80211_mgmt *)params->buf; if (!ieee80211_is_mgmt(mgmt->frame_control)) return -EINVAL; @@ -615,9 +613,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, return -EINVAL; /* Transmit the Action frame as requested by user space */ - return rdev_mgmt_tx(rdev, wdev, chan, offchan, - wait, buf, len, no_cck, dont_wait_for_ack, - cookie); + return rdev_mgmt_tx(rdev, wdev, params, cookie); } bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8c83fbb3824f..703155b1aa7a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7428,10 +7428,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) void *hdr = NULL; u64 cookie; struct sk_buff *msg = NULL; - unsigned int wait = 0; - bool offchan, no_cck, dont_wait_for_ack; - - dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; + struct cfg80211_mgmt_tx_params params = { + .dont_wait_for_ack = + info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK], + }; if (!info->attrs[NL80211_ATTR_FRAME]) return -EINVAL; @@ -7458,24 +7458,24 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_DURATION]) { if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) return -EINVAL; - wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); + params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); /* * We should wait on the channel for at least a minimum amount * of time (10ms) but no longer than the driver supports. */ - if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || - wait > rdev->wiphy.max_remain_on_channel_duration) + if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || + params.wait > rdev->wiphy.max_remain_on_channel_duration) return -EINVAL; } - offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; + params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; - if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) + if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) return -EINVAL; - no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); + params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); /* get the channel if any has been specified, otherwise pass NULL to * the driver. The latter will use the current one @@ -7487,10 +7487,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) return err; } - if (!chandef.chan && offchan) + if (!chandef.chan && params.offchan) return -EINVAL; - if (!dont_wait_for_ack) { + if (!params.dont_wait_for_ack) { msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -7503,10 +7503,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) } } - err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, - nla_data(info->attrs[NL80211_ATTR_FRAME]), - nla_len(info->attrs[NL80211_ATTR_FRAME]), - no_cck, dont_wait_for_ack, &cookie); + params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); + params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); + params.chan = chandef.chan; + err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie); if (err) goto free_msg; diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 37ce9fdfe934..a6c03ab14a0d 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -624,16 +624,12 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev, static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) { int ret; - trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, - wait, no_cck, dont_wait_for_ack); - ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan, - wait, buf, len, no_cck, - dont_wait_for_ack, cookie); + trace_rdev_mgmt_tx(&rdev->wiphy, wdev, params); + ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, params, cookie); trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); return ret; } diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ba5f0d6614d5..f7aa7a72d9bc 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1653,9 +1653,8 @@ TRACE_EVENT(rdev_cancel_remain_on_channel, TRACE_EVENT(rdev_mgmt_tx, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, bool no_cck, bool dont_wait_for_ack), - TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack), + struct cfg80211_mgmt_tx_params *params), + TP_ARGS(wiphy, wdev, params), TP_STRUCT__entry( WIPHY_ENTRY WDEV_ENTRY @@ -1668,11 +1667,11 @@ TRACE_EVENT(rdev_mgmt_tx, TP_fast_assign( WIPHY_ASSIGN; WDEV_ASSIGN; - CHAN_ASSIGN(chan); - __entry->offchan = offchan; - __entry->wait = wait; - __entry->no_cck = no_cck; - __entry->dont_wait_for_ack = dont_wait_for_ack; + CHAN_ASSIGN(params->chan); + __entry->offchan = params->offchan; + __entry->wait = params->wait; + __entry->no_cck = params->no_cck; + __entry->dont_wait_for_ack = params->dont_wait_for_ack; ), TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s," " wait: %u, no cck: %s, dont wait for ack: %s", -- cgit v1.2.3 From e487eaeb076a44c69dc61348cbc903151bb8fcbd Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 21 Nov 2013 18:19:51 +0100 Subject: cfg80211/mac80211/ath6kl: acquire wdev lock outside ch_switch_notify The channel switch notification should be sent under the wdev/sdata-lock, preferably in the same moment as the channel change happens, to avoid races by other callers (e.g. start/stop_ap). This also adds the previously missing sdata_lock protection in csa_finalize_work. Reported-by: Johannes Berg Signed-off-by: Simon Wunderlich Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 ++ include/net/cfg80211.h | 3 ++- net/mac80211/cfg.c | 21 +++++++++++++++------ net/wireless/nl80211.c | 9 +++------ 4 files changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 36dc61da8336..fd4c89df67e1 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT); + mutex_lock(&vif->wdev.mtx); cfg80211_ch_switch_notify(vif->ndev, &chandef); + mutex_unlock(&vif->wdev.mtx); } static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6c2bc329a900..e9abc7b536cd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4286,7 +4286,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, * @dev: the device which switched channels * @chandef: the new channel definition * - * Acquires wdev_lock, so must only be called from sleepable driver context! + * Caller must acquire wdev_lock, therefore must only be called from sleepable + * driver context! */ void cfg80211_ch_switch_notify(struct net_device *dev, struct cfg80211_chan_def *chandef); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4a5c21ed64d1..1d446ac97ab5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2988,13 +2988,18 @@ void ieee80211_csa_finalize_work(struct work_struct *work) struct ieee80211_local *local = sdata->local; int err, changed = 0; + sdata_lock(sdata); + /* AP might have been stopped while waiting for the lock. */ + if (!sdata->vif.csa_active) + goto unlock; + if (!ieee80211_sdata_running(sdata)) - return; + goto unlock; sdata->radar_required = sdata->csa_radar_required; err = ieee80211_vif_change_channel(sdata, &changed); if (WARN_ON(err < 0)) - return; + goto unlock; if (!local->use_chanctx) { local->_oper_chandef = sdata->csa_chandef; @@ -3003,11 +3008,13 @@ void ieee80211_csa_finalize_work(struct work_struct *work) ieee80211_bss_info_change_notify(sdata, changed); + sdata->vif.csa_active = false; switch (sdata->vif.type) { case NL80211_IFTYPE_AP: err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); if (err < 0) - return; + goto unlock; + changed |= err; kfree(sdata->u.ap.next_beacon); sdata->u.ap.next_beacon = NULL; @@ -3021,20 +3028,22 @@ void ieee80211_csa_finalize_work(struct work_struct *work) case NL80211_IFTYPE_MESH_POINT: err = ieee80211_mesh_finish_csa(sdata); if (err < 0) - return; + goto unlock; break; #endif default: WARN_ON(1); - return; + goto unlock; } - sdata->vif.csa_active = false; ieee80211_wake_queues_by_reason(&sdata->local->hw, IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA); cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); + +unlock: + sdata_unlock(sdata); } static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 398756c226c3..95882a788b5b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -10821,21 +10821,18 @@ void cfg80211_ch_switch_notify(struct net_device *dev, struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - trace_cfg80211_ch_switch_notify(dev, chandef); + ASSERT_WDEV_LOCK(wdev); - wdev_lock(wdev); + trace_cfg80211_ch_switch_notify(dev, chandef); if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && wdev->iftype != NL80211_IFTYPE_P2P_GO && wdev->iftype != NL80211_IFTYPE_ADHOC && wdev->iftype != NL80211_IFTYPE_MESH_POINT)) - goto out; + return; wdev->channel = chandef->chan; nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); -out: - wdev_unlock(wdev); - return; } EXPORT_SYMBOL(cfg80211_ch_switch_notify); -- cgit v1.2.3 From e4d313ff79a8b5622a8c4954ba37c6564fa922c4 Mon Sep 17 00:00:00 2001 From: Takashi Yoshii Date: Mon, 2 Dec 2013 03:19:13 +0900 Subject: spi: spi-sh-msiof: round up div to fix freq calculation Truncation on integer division in sh_msiof_spi_set_clk_regs() results in insufficient transfer frequency (> max_speed_freq). For example, source 52MHz, required max 6MHz 52/6 = 8.6 --> 8, then 1/8 table selected, and result in 52/8 = 6.5 MHz (>6MHz) Rounding it up is a simple solution. 52/6 = 8.6 --> 9, then 1/16 table selected, and result in 52/16 = 3.25 MHz Signed-off-by: Takashi Yoshii Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index c74298cf70e2..ac8795f2e700 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -152,7 +152,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, size_t k; if (!WARN_ON(!spi_hz || !parent_rate)) - div = parent_rate / spi_hz; + div = DIV_ROUND_UP(parent_rate, spi_hz); /* TODO: make more fine grained */ -- cgit v1.2.3 From 50a7799829835120950520231797642e19d4152f Mon Sep 17 00:00:00 2001 From: Takashi Yoshii Date: Mon, 2 Dec 2013 03:19:15 +0900 Subject: spi: spi-sh-msiof: set hi/low Active for HW CS Set hardware CS(CS control function on MSIOF <-> GPIO CS) polarity according to SPI_CS_HIGH flag on spi->mode. Signed-off-by: Takashi Yoshii Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index d96b047afcd2..a0c3e54b0003 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -169,7 +169,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 cpol, u32 cpha, - u32 tx_hi_z, u32 lsb_first) + u32 tx_hi_z, u32 lsb_first, u32 cs_high) { u32 tmp; int edge; @@ -182,8 +182,12 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, * 1 1 11 11 1 1 */ sh_msiof_write(p, FCTR, 0); - sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24)); - sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24)); + + tmp = 0; + tmp |= !cs_high << 25; + tmp |= lsb_first << 24; + sh_msiof_write(p, TMDR1, 0xe0000005 | tmp); + sh_msiof_write(p, RMDR1, 0x20000005 | tmp); tmp = 0xa0000000; tmp |= cpol << 30; /* TSCKIZ */ @@ -417,7 +421,8 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on) sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), !!(spi->mode & SPI_CPHA), !!(spi->mode & SPI_3WIRE), - !!(spi->mode & SPI_LSB_FIRST)); + !!(spi->mode & SPI_LSB_FIRST), + !!(spi->mode & SPI_CS_HIGH)); } /* use spi->controller data for CS (same strategy as spi_gpio) */ -- cgit v1.2.3 From 5be19d910b9fc40102af475b3d1e6f2e0e9770d5 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 9 Oct 2013 10:47:12 +0200 Subject: drm/i915/lvds: don't restore hw state in the lid notifier for pch platforms It's a pain for two reasons: - The vga plane redisablign requires actual legacy vgao i/o to pull of. The hw engineers really botched this one here :( - There seem to be some BIOS out there which send out lid events when unplugging. Together with our broken DP code, which disables the port when the cable is lost, this results in an immediate modeset call, which can hang on the wait for outstanding flips. - Also we don't want to force a modeset on machines where it's not really needed, see the referenced bug. We might want to extend this in general to also all machines that support opregion, since there the BIOS supposedly should manage the gfx hardware more cooperatively. v2: Pimp commit message a bit. Cc: Roland Dreier References: https://bugs.freedesktop.org/show_bug.cgi?id=65486 Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lvds.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 3deb58e2f394..4c8553ea82f7 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -447,9 +447,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, if (dev_priv->modeset_restore == MODESET_DONE) goto exit; - drm_modeset_lock_all(dev); - intel_modeset_setup_hw_state(dev, true); - drm_modeset_unlock_all(dev); + /* + * Some old platform's BIOS love to wreak havoc while the lid is closed. + * We try to detect this here and undo any damage. The split for PCH + * platforms is rather conservative and a bit arbitrary expect that on + * those platforms VGA disabling requires actual legacy VGA I/O access, + * and as part of the cleanup in the hw state restore we also redisable + * the vga plane. + */ + if (!HAS_PCH_SPLIT(dev)) { + drm_modeset_lock_all(dev); + intel_modeset_setup_hw_state(dev, true); + drm_modeset_unlock_all(dev); + } dev_priv->modeset_restore = MODESET_DONE; -- cgit v1.2.3 From 765e5fbd3e04ba753b2585e9f852fdcd34b95d10 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 27 Nov 2013 10:05:56 +0800 Subject: HID: usbhid: merge the sis quirk USB_VENDOR_ID_SIS and USB_VENDOR_ID_SIS2_TOUCH are identical, so refine the code and merge the quirks. Signed-off-by: AceLan Kao Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 5 ++--- drivers/hid/usbhid/hid-quirks.c | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 76559629568c..90e9806e864b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -755,9 +755,10 @@ #define USB_VENDOR_ID_SIGMATEL 0x066F #define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 -#define USB_VENDOR_ID_SIS2_TOUCH 0x0457 +#define USB_VENDOR_ID_SIS_TOUCH 0x0457 #define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 #define USB_DEVICE_ID_SIS817_TOUCH 0x0817 +#define USB_DEVICE_ID_SIS_TS 0x1013 #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 @@ -936,7 +937,5 @@ #define USB_VENDOR_ID_PRIMAX 0x0461 #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 -#define USB_VENDOR_ID_SIS 0x0457 -#define USB_DEVICE_ID_SIS_TS 0x1013 #endif diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0db9a67278ba..37307dc2d1f7 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -84,8 +84,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, @@ -114,7 +115,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SIS, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From d8e2e7581d2521910398c4c80d7a3b78e84da7d5 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 27 Nov 2013 10:05:57 +0800 Subject: HID: usbhid: quirk for Synaptics HD touchscreen Add Synaptics HD touchscreen(06cb:0ac3) to no init report quirk. Signed-off-by: AceLan Kao Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 90e9806e864b..56ed3a00ee2d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -810,6 +810,7 @@ #define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 #define USB_DEVICE_ID_SYNAPTICS_LTS1 0x0af8 #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 +#define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 37307dc2d1f7..11facfbadead 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -115,6 +115,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From 12f508aede4bda5d20a2dd3ff3deb16ef47a97e9 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 27 Nov 2013 10:05:58 +0800 Subject: HID: usbhid: quirk for Synaptics Quad HD touchscreen Add Synaptics HD touchscreen(06cb:1ac3) to no init report quirk Signed-off-by: AceLan Kao Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 56ed3a00ee2d..cb219dee5e64 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -811,6 +811,7 @@ #define USB_DEVICE_ID_SYNAPTICS_LTS1 0x0af8 #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 #define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 +#define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 11facfbadead..b3c7684e8706 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -116,6 +116,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From 2edb90ae421a0f65edcdef65ef9dd08e3228abbf Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 09:37:45 +0200 Subject: ARM: at91: move at91_pmc.h to include/linux/clk/at91_pmc.h This patch moves at91_pmc.h header from machine specific directory (arch/arm/mach-at91/include/mach/at91_pmc.h) to clk include directory (include/linux/clk/at91_pmc.h). We need this to avoid reference to machine specific headers in clk drivers. Signed-off-by: Boris BREZILLON Acked-by: Felipe Balbi Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91rm9200.c | 2 +- arch/arm/mach-at91/at91sam9260.c | 2 +- arch/arm/mach-at91/at91sam9261.c | 2 +- arch/arm/mach-at91/at91sam9263.c | 2 +- arch/arm/mach-at91/at91sam9g45.c | 2 +- arch/arm/mach-at91/at91sam9n12.c | 2 +- arch/arm/mach-at91/at91sam9rl.c | 2 +- arch/arm/mach-at91/at91sam9x5.c | 2 +- arch/arm/mach-at91/clock.c | 2 +- arch/arm/mach-at91/include/mach/at91_pmc.h | 190 ----------------------------- arch/arm/mach-at91/pm.c | 2 +- arch/arm/mach-at91/pm_slowclock.S | 2 +- arch/arm/mach-at91/sama5d3.c | 2 +- arch/arm/mach-at91/setup.c | 2 +- drivers/usb/gadget/atmel_usba_udc.c | 2 +- include/linux/clk/at91_pmc.h | 190 +++++++++++++++++++++++++++++ 16 files changed, 204 insertions(+), 204 deletions(-) delete mode 100644 arch/arm/mach-at91/include/mach/at91_pmc.h create mode 100644 include/linux/clk/at91_pmc.h (limited to 'drivers') diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 25805f2f6010..e47f5fd232f5 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -12,13 +12,13 @@ #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index d6a1fa85371d..6c821e562159 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -11,6 +11,7 @@ */ #include +#include #include #include @@ -20,7 +21,6 @@ #include #include #include -#include #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 23ba1d8a1531..6276b4c1acfe 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -11,6 +11,7 @@ */ #include +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 7eccb0fc57bc..37b90f4b990c 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -11,6 +11,7 @@ */ #include +#include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 9405aa08b104..2f455ce35268 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -12,13 +12,13 @@ #include #include +#include #include #include #include #include #include -#include #include #include "at91_aic.h" diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index 388ec3aec4b9..4ef088c62eab 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -8,12 +8,12 @@ #include #include +#include #include #include #include #include -#include #include #include "board.h" diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 0750ffb7e6b1..3651517abedf 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -10,6 +10,7 @@ */ #include +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index e8a2e075a1b8..3e8ec26e39dc 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -8,12 +8,12 @@ #include #include +#include #include #include #include #include -#include #include #include "board.h" diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 6b2630a92f71..5f02aea1021c 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -24,9 +24,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h deleted file mode 100644 index c604cc69acb5..000000000000 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * arch/arm/mach-at91/include/mach/at91_pmc.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * Power Management Controller (PMC) - System peripherals registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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 AT91_PMC_H -#define AT91_PMC_H - -#ifndef __ASSEMBLY__ -extern void __iomem *at91_pmc_base; - -#define at91_pmc_read(field) \ - __raw_readl(at91_pmc_base + field) - -#define at91_pmc_write(field, value) \ - __raw_writel(value, at91_pmc_base + field) -#else -.extern at91_pmc_base -#endif - -#define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ -#define AT91_PMC_SCDR 0x04 /* System Clock Disable Register */ - -#define AT91_PMC_SCSR 0x08 /* System Clock Status Register */ -#define AT91_PMC_PCK (1 << 0) /* Processor Clock */ -#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */ -#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */ -#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */ -#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */ -#define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */ -#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */ -#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ -#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ -#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ -#define AT91_PMC_PCK4 (1 << 12) /* Programmable Clock 4 [AT572D940HF only] */ -#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ -#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ - -#define AT91_PMC_PCER 0x10 /* Peripheral Clock Enable Register */ -#define AT91_PMC_PCDR 0x14 /* Peripheral Clock Disable Register */ -#define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */ - -#define AT91_CKGR_UCKR 0x1C /* UTMI Clock Register [some SAM9] */ -#define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */ -#define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */ -#define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */ -#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */ - -#define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */ -#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ -#define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass */ -#define AT91_PMC_MOSCRCEN (1 << 3) /* Main On-Chip RC Oscillator Enable [some SAM9] */ -#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ -#define AT91_PMC_KEY (0x37 << 16) /* MOR Writing Key */ -#define AT91_PMC_MOSCSEL (1 << 24) /* Main Oscillator Selection [some SAM9] */ -#define AT91_PMC_CFDEN (1 << 25) /* Clock Failure Detector Enable [some SAM9] */ - -#define AT91_CKGR_MCFR 0x24 /* Main Clock Frequency Register */ -#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */ -#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ - -#define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ -#define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ -#define AT91_PMC_DIV (0xff << 0) /* Divider */ -#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ -#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ -#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ -#define AT91_PMC_MUL_GET(n) ((n) >> 16 & 0x7ff) -#define AT91_PMC3_MUL (0x7f << 18) /* PLL Multiplier [SAMA5 only] */ -#define AT91_PMC3_MUL_GET(n) ((n) >> 18 & 0x7f) -#define AT91_PMC_USBDIV (3 << 28) /* USB Divisor (PLLB only) */ -#define AT91_PMC_USBDIV_1 (0 << 28) -#define AT91_PMC_USBDIV_2 (1 << 28) -#define AT91_PMC_USBDIV_4 (2 << 28) -#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ - -#define AT91_PMC_MCKR 0x30 /* Master Clock Register */ -#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ -#define AT91_PMC_CSS_SLOW (0 << 0) -#define AT91_PMC_CSS_MAIN (1 << 0) -#define AT91_PMC_CSS_PLLA (2 << 0) -#define AT91_PMC_CSS_PLLB (3 << 0) -#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */ -#define PMC_PRES_OFFSET 2 -#define AT91_PMC_PRES (7 << PMC_PRES_OFFSET) /* Master Clock Prescaler */ -#define AT91_PMC_PRES_1 (0 << PMC_PRES_OFFSET) -#define AT91_PMC_PRES_2 (1 << PMC_PRES_OFFSET) -#define AT91_PMC_PRES_4 (2 << PMC_PRES_OFFSET) -#define AT91_PMC_PRES_8 (3 << PMC_PRES_OFFSET) -#define AT91_PMC_PRES_16 (4 << PMC_PRES_OFFSET) -#define AT91_PMC_PRES_32 (5 << PMC_PRES_OFFSET) -#define AT91_PMC_PRES_64 (6 << PMC_PRES_OFFSET) -#define PMC_ALT_PRES_OFFSET 4 -#define AT91_PMC_ALT_PRES (7 << PMC_ALT_PRES_OFFSET) /* Master Clock Prescaler [alternate location] */ -#define AT91_PMC_ALT_PRES_1 (0 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_ALT_PRES_2 (1 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_ALT_PRES_4 (2 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_ALT_PRES_8 (3 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_ALT_PRES_16 (4 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_ALT_PRES_32 (5 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_ALT_PRES_64 (6 << PMC_ALT_PRES_OFFSET) -#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */ -#define AT91RM9200_PMC_MDIV_1 (0 << 8) /* [AT91RM9200 only] */ -#define AT91RM9200_PMC_MDIV_2 (1 << 8) -#define AT91RM9200_PMC_MDIV_3 (2 << 8) -#define AT91RM9200_PMC_MDIV_4 (3 << 8) -#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9 only] */ -#define AT91SAM9_PMC_MDIV_2 (1 << 8) -#define AT91SAM9_PMC_MDIV_4 (2 << 8) -#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */ -#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */ -#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */ -#define AT91_PMC_PDIV_1 (0 << 12) -#define AT91_PMC_PDIV_2 (1 << 12) -#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */ -#define AT91_PMC_PLLADIV2_OFF (0 << 12) -#define AT91_PMC_PLLADIV2_ON (1 << 12) - -#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */ -#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */ -#define AT91_PMC_USBS_PLLA (0 << 0) -#define AT91_PMC_USBS_UPLL (1 << 0) -#define AT91_PMC_USBS_PLLB (1 << 0) /* [AT91SAMN12 only] */ -#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */ -#define AT91_PMC_OHCIUSBDIV_1 (0x0 << 8) -#define AT91_PMC_OHCIUSBDIV_2 (0x1 << 8) - -#define AT91_PMC_SMD 0x3c /* Soft Modem Clock Register [some SAM9 only] */ -#define AT91_PMC_SMDS (0x1 << 0) /* SMD input clock selection */ -#define AT91_PMC_SMD_DIV (0x1f << 8) /* SMD input clock divider */ -#define AT91_PMC_SMDDIV(n) (((n) << 8) & AT91_PMC_SMD_DIV) - -#define AT91_PMC_PCKR(n) (0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */ -#define AT91_PMC_ALT_PCKR_CSS (0x7 << 0) /* Programmable Clock Source Selection [alternate length] */ -#define AT91_PMC_CSS_MASTER (4 << 0) /* [some SAM9 only] */ -#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */ -#define AT91_PMC_CSSMCK_CSS (0 << 8) -#define AT91_PMC_CSSMCK_MCK (1 << 8) - -#define AT91_PMC_IER 0x60 /* Interrupt Enable Register */ -#define AT91_PMC_IDR 0x64 /* Interrupt Disable Register */ -#define AT91_PMC_SR 0x68 /* Status Register */ -#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */ -#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */ -#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ -#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ -#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9] */ -#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ -#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ -#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ -#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ -#define AT91_PMC_MOSCSELS (1 << 16) /* Main Oscillator Selection [some SAM9] */ -#define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */ -#define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ -#define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ - -#define AT91_PMC_PROT 0xe4 /* Write Protect Mode Register [some SAM9] */ -#define AT91_PMC_WPEN (0x1 << 0) /* Write Protect Enable */ -#define AT91_PMC_WPKEY (0xffffff << 8) /* Write Protect Key */ -#define AT91_PMC_PROTKEY (0x504d43 << 8) /* Activation Code */ - -#define AT91_PMC_WPSR 0xe8 /* Write Protect Status Register [some SAM9] */ -#define AT91_PMC_WPVS (0x1 << 0) /* Write Protect Violation Status */ -#define AT91_PMC_WPVSRC (0xffff << 8) /* Write Protect Violation Source */ - -#define AT91_PMC_PCER1 0x100 /* Peripheral Clock Enable Register 1 [SAMA5 only]*/ -#define AT91_PMC_PCDR1 0x104 /* Peripheral Clock Enable Register 1 */ -#define AT91_PMC_PCSR1 0x108 /* Peripheral Clock Enable Register 1 */ - -#define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9 and SAMA5] */ -#define AT91_PMC_PCR_PID (0x3f << 0) /* Peripheral ID */ -#define AT91_PMC_PCR_CMD (0x1 << 12) /* Command (read=0, write=1) */ -#define AT91_PMC_PCR_DIV(n) ((n) << 16) /* Divisor Value */ -#define AT91_PMC_PCR_DIV0 0x0 /* Peripheral clock is MCK */ -#define AT91_PMC_PCR_DIV2 0x1 /* Peripheral clock is MCK/2 */ -#define AT91_PMC_PCR_DIV4 0x2 /* Peripheral clock is MCK/4 */ -#define AT91_PMC_PCR_DIV8 0x3 /* Peripheral clock is MCK/8 */ -#define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ - -#endif diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 9986542e8060..d43b79f56e94 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -19,13 +19,13 @@ #include #include #include +#include #include #include #include #include -#include #include #include "at91_aic.h" diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 098c28ddf025..20018779bae7 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -13,8 +13,8 @@ */ #include +#include #include -#include #include diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 3ea86428ee09..5c6dc24fafbd 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c @@ -9,12 +9,12 @@ #include #include +#include #include #include #include #include -#include #include #include "soc.h" diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 094b3459c288..ca542dee087d 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include "at91_shdwc.h" #include "soc.h" diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 2cb52e0438df..9f71d9fdcc14 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -326,7 +326,7 @@ static int vbus_is_present(struct usba_udc *udc) #if defined(CONFIG_ARCH_AT91SAM9RL) -#include +#include static void toggle_bias(int is_on) { diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h new file mode 100644 index 000000000000..00c45b3510bf --- /dev/null +++ b/include/linux/clk/at91_pmc.h @@ -0,0 +1,190 @@ +/* + * include/linux/clk/at91_pmc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Power Management Controller (PMC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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 AT91_PMC_H +#define AT91_PMC_H + +#ifndef __ASSEMBLY__ +extern void __iomem *at91_pmc_base; + +#define at91_pmc_read(field) \ + __raw_readl(at91_pmc_base + field) + +#define at91_pmc_write(field, value) \ + __raw_writel(value, at91_pmc_base + field) +#else +.extern at91_pmc_base +#endif + +#define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ +#define AT91_PMC_SCDR 0x04 /* System Clock Disable Register */ + +#define AT91_PMC_SCSR 0x08 /* System Clock Status Register */ +#define AT91_PMC_PCK (1 << 0) /* Processor Clock */ +#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */ +#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */ +#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */ +#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */ +#define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */ +#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_PCK4 (1 << 12) /* Programmable Clock 4 [AT572D940HF only] */ +#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ +#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ + +#define AT91_PMC_PCER 0x10 /* Peripheral Clock Enable Register */ +#define AT91_PMC_PCDR 0x14 /* Peripheral Clock Disable Register */ +#define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */ + +#define AT91_CKGR_UCKR 0x1C /* UTMI Clock Register [some SAM9] */ +#define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */ +#define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */ +#define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */ +#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */ + +#define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */ +#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ +#define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass */ +#define AT91_PMC_MOSCRCEN (1 << 3) /* Main On-Chip RC Oscillator Enable [some SAM9] */ +#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ +#define AT91_PMC_KEY (0x37 << 16) /* MOR Writing Key */ +#define AT91_PMC_MOSCSEL (1 << 24) /* Main Oscillator Selection [some SAM9] */ +#define AT91_PMC_CFDEN (1 << 25) /* Clock Failure Detector Enable [some SAM9] */ + +#define AT91_CKGR_MCFR 0x24 /* Main Clock Frequency Register */ +#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */ +#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ + +#define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ +#define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ +#define AT91_PMC_DIV (0xff << 0) /* Divider */ +#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ +#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ +#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ +#define AT91_PMC_MUL_GET(n) ((n) >> 16 & 0x7ff) +#define AT91_PMC3_MUL (0x7f << 18) /* PLL Multiplier [SAMA5 only] */ +#define AT91_PMC3_MUL_GET(n) ((n) >> 18 & 0x7f) +#define AT91_PMC_USBDIV (3 << 28) /* USB Divisor (PLLB only) */ +#define AT91_PMC_USBDIV_1 (0 << 28) +#define AT91_PMC_USBDIV_2 (1 << 28) +#define AT91_PMC_USBDIV_4 (2 << 28) +#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ + +#define AT91_PMC_MCKR 0x30 /* Master Clock Register */ +#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ +#define AT91_PMC_CSS_SLOW (0 << 0) +#define AT91_PMC_CSS_MAIN (1 << 0) +#define AT91_PMC_CSS_PLLA (2 << 0) +#define AT91_PMC_CSS_PLLB (3 << 0) +#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */ +#define PMC_PRES_OFFSET 2 +#define AT91_PMC_PRES (7 << PMC_PRES_OFFSET) /* Master Clock Prescaler */ +#define AT91_PMC_PRES_1 (0 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_2 (1 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_4 (2 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_8 (3 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_16 (4 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_32 (5 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_64 (6 << PMC_PRES_OFFSET) +#define PMC_ALT_PRES_OFFSET 4 +#define AT91_PMC_ALT_PRES (7 << PMC_ALT_PRES_OFFSET) /* Master Clock Prescaler [alternate location] */ +#define AT91_PMC_ALT_PRES_1 (0 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_2 (1 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_4 (2 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_8 (3 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_16 (4 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_32 (5 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_64 (6 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */ +#define AT91RM9200_PMC_MDIV_1 (0 << 8) /* [AT91RM9200 only] */ +#define AT91RM9200_PMC_MDIV_2 (1 << 8) +#define AT91RM9200_PMC_MDIV_3 (2 << 8) +#define AT91RM9200_PMC_MDIV_4 (3 << 8) +#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9 only] */ +#define AT91SAM9_PMC_MDIV_2 (1 << 8) +#define AT91SAM9_PMC_MDIV_4 (2 << 8) +#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */ +#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */ +#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */ +#define AT91_PMC_PDIV_1 (0 << 12) +#define AT91_PMC_PDIV_2 (1 << 12) +#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */ +#define AT91_PMC_PLLADIV2_OFF (0 << 12) +#define AT91_PMC_PLLADIV2_ON (1 << 12) + +#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */ +#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */ +#define AT91_PMC_USBS_PLLA (0 << 0) +#define AT91_PMC_USBS_UPLL (1 << 0) +#define AT91_PMC_USBS_PLLB (1 << 0) /* [AT91SAMN12 only] */ +#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */ +#define AT91_PMC_OHCIUSBDIV_1 (0x0 << 8) +#define AT91_PMC_OHCIUSBDIV_2 (0x1 << 8) + +#define AT91_PMC_SMD 0x3c /* Soft Modem Clock Register [some SAM9 only] */ +#define AT91_PMC_SMDS (0x1 << 0) /* SMD input clock selection */ +#define AT91_PMC_SMD_DIV (0x1f << 8) /* SMD input clock divider */ +#define AT91_PMC_SMDDIV(n) (((n) << 8) & AT91_PMC_SMD_DIV) + +#define AT91_PMC_PCKR(n) (0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */ +#define AT91_PMC_ALT_PCKR_CSS (0x7 << 0) /* Programmable Clock Source Selection [alternate length] */ +#define AT91_PMC_CSS_MASTER (4 << 0) /* [some SAM9 only] */ +#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */ +#define AT91_PMC_CSSMCK_CSS (0 << 8) +#define AT91_PMC_CSSMCK_MCK (1 << 8) + +#define AT91_PMC_IER 0x60 /* Interrupt Enable Register */ +#define AT91_PMC_IDR 0x64 /* Interrupt Disable Register */ +#define AT91_PMC_SR 0x68 /* Status Register */ +#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */ +#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */ +#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ +#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ +#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9] */ +#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_MOSCSELS (1 << 16) /* Main Oscillator Selection [some SAM9] */ +#define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */ +#define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ +#define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ + +#define AT91_PMC_PROT 0xe4 /* Write Protect Mode Register [some SAM9] */ +#define AT91_PMC_WPEN (0x1 << 0) /* Write Protect Enable */ +#define AT91_PMC_WPKEY (0xffffff << 8) /* Write Protect Key */ +#define AT91_PMC_PROTKEY (0x504d43 << 8) /* Activation Code */ + +#define AT91_PMC_WPSR 0xe8 /* Write Protect Status Register [some SAM9] */ +#define AT91_PMC_WPVS (0x1 << 0) /* Write Protect Violation Status */ +#define AT91_PMC_WPVSRC (0xffff << 8) /* Write Protect Violation Source */ + +#define AT91_PMC_PCER1 0x100 /* Peripheral Clock Enable Register 1 [SAMA5 only]*/ +#define AT91_PMC_PCDR1 0x104 /* Peripheral Clock Enable Register 1 */ +#define AT91_PMC_PCSR1 0x108 /* Peripheral Clock Enable Register 1 */ + +#define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9 and SAMA5] */ +#define AT91_PMC_PCR_PID (0x3f << 0) /* Peripheral ID */ +#define AT91_PMC_PCR_CMD (0x1 << 12) /* Command (read=0, write=1) */ +#define AT91_PMC_PCR_DIV(n) ((n) << 16) /* Divisor Value */ +#define AT91_PMC_PCR_DIV0 0x0 /* Peripheral clock is MCK */ +#define AT91_PMC_PCR_DIV2 0x1 /* Peripheral clock is MCK/2 */ +#define AT91_PMC_PCR_DIV4 0x2 /* Peripheral clock is MCK/4 */ +#define AT91_PMC_PCR_DIV8 0x3 /* Peripheral clock is MCK/8 */ +#define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ + +#endif -- cgit v1.2.3 From 0ad6125b1579cac8ccbd0f46ec6d33cf71b79f51 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 2 Dec 2013 15:07:02 +0100 Subject: clk: at91: add PMC base support This patch adds at91 PMC (Power Management Controller) base support. All at91 clocks managed by the PMC unit will use this framework. This framework provides the following fonctionalities: - define a new struct at91_pmc to hide PMC internals (lock, PMC memory mapping, irq domain, ...) - read/write helper functions (pmc_read/write) to access PMC registers - lock/unlock helper functions (pmc_lock/unlock) to lock/unlock access to pmc registers - a new irq domain and its associated irq chip to request PMC specific interrupts (useful for clk prepare callbacks) The PMC unit is declared as a dt clk provider (CLK_OF_DECLARE), and every clk using this framework will declare a table of of_at91_clk_init_cb_t and add it to the pmc_clk_ids table. When the pmc dt clock setup function is called (by of_clk_init function), it triggers the registration of every supported child clk (those matching the definitions in pmc_clk_ids). This patch copies at91_pmc_base (memory mapping) and at91sam9_idle (function) from arch/arm/mach-at91/clock.c (which is not compiled if COMMON_CLK_AT91 is enabled). Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/Makefile | 1 + drivers/clk/at91/Makefile | 5 + drivers/clk/at91/pmc.c | 304 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.h | 61 ++++++++++ 4 files changed, 371 insertions(+) create mode 100644 drivers/clk/at91/Makefile create mode 100644 drivers/clk/at91/pmc.c create mode 100644 drivers/clk/at91/pmc.h (limited to 'drivers') diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7a10bc9a23e7..ace7309c4369 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile new file mode 100644 index 000000000000..1d4fb214bbc4 --- /dev/null +++ b/drivers/clk/at91/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for at91 specific clk +# + +obj-y += pmc.o diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c new file mode 100644 index 000000000000..69c116a6ba4f --- /dev/null +++ b/drivers/clk/at91/pmc.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +void __iomem *at91_pmc_base; +EXPORT_SYMBOL_GPL(at91_pmc_base); + +void at91sam9_idle(void) +{ + at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); + cpu_do_idle(); +} + +int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range) +{ + u32 min, max; + int ret; + + ret = of_property_read_u32_index(np, propname, 0, &min); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, propname, 1, &max); + if (ret) + return ret; + + if (range) { + range->min = min; + range->max = max; + } + + return 0; +} +EXPORT_SYMBOL_GPL(of_at91_get_clk_range); + +static void pmc_irq_mask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq); +} + +static void pmc_irq_unmask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq); +} + +static int pmc_irq_set_type(struct irq_data *d, unsigned type) +{ + if (type != IRQ_TYPE_LEVEL_HIGH) { + pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n"); + return -EINVAL; + } + + return 0; +} + +static struct irq_chip pmc_irq = { + .name = "PMC", + .irq_disable = pmc_irq_mask, + .irq_mask = pmc_irq_mask, + .irq_unmask = pmc_irq_unmask, + .irq_set_type = pmc_irq_set_type, +}; + +static struct lock_class_key pmc_lock_class; + +static int pmc_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct at91_pmc *pmc = h->host_data; + + irq_set_lockdep_class(virq, &pmc_lock_class); + + irq_set_chip_and_handler(virq, &pmc_irq, + handle_level_irq); + set_irq_flags(virq, IRQF_VALID); + irq_set_chip_data(virq, pmc); + + return 0; +} + +static int pmc_irq_domain_xlate(struct irq_domain *d, + struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, + unsigned int *out_type) +{ + struct at91_pmc *pmc = d->host_data; + const struct at91_pmc_caps *caps = pmc->caps; + + if (WARN_ON(intsize < 1)) + return -EINVAL; + + *out_hwirq = intspec[0]; + + if (!(caps->available_irqs & (1 << *out_hwirq))) + return -EINVAL; + + *out_type = IRQ_TYPE_LEVEL_HIGH; + + return 0; +} + +static struct irq_domain_ops pmc_irq_ops = { + .map = pmc_irq_map, + .xlate = pmc_irq_domain_xlate, +}; + +static irqreturn_t pmc_irq_handler(int irq, void *data) +{ + struct at91_pmc *pmc = (struct at91_pmc *)data; + unsigned long sr; + int n; + + sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR); + if (!sr) + return IRQ_NONE; + + for_each_set_bit(n, &sr, BITS_PER_LONG) + generic_handle_irq(irq_find_mapping(pmc->irqdomain, n)); + + return IRQ_HANDLED; +} + +static const struct at91_pmc_caps at91rm9200_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | + AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | + AT91_PMC_PCK3RDY, +}; + +static const struct at91_pmc_caps at91sam9260_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | + AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY, +}; + +static const struct at91_pmc_caps at91sam9g45_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | + AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY, +}; + +static const struct at91_pmc_caps at91sam9n12_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | + AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | + AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, +}; + +static const struct at91_pmc_caps at91sam9x5_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | + AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | + AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, +}; + +static const struct at91_pmc_caps sama5d3_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | + AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | + AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS | + AT91_PMC_CFDEV, +}; + +static struct at91_pmc *__init at91_pmc_init(struct device_node *np, + void __iomem *regbase, int virq, + const struct at91_pmc_caps *caps) +{ + struct at91_pmc *pmc; + + if (!regbase || !virq || !caps) + return NULL; + + at91_pmc_base = regbase; + + pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); + if (!pmc) + return NULL; + + spin_lock_init(&pmc->lock); + pmc->regbase = regbase; + pmc->virq = virq; + pmc->caps = caps; + + pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc); + + if (!pmc->irqdomain) + goto out_free_pmc; + + pmc_write(pmc, AT91_PMC_IDR, 0xffffffff); + if (request_irq(pmc->virq, pmc_irq_handler, IRQF_SHARED, "pmc", pmc)) + goto out_remove_irqdomain; + + return pmc; + +out_remove_irqdomain: + irq_domain_remove(pmc->irqdomain); +out_free_pmc: + kfree(pmc); + + return NULL; +} + +static const struct of_device_id pmc_clk_ids[] __initdata = { + { /*sentinel*/ } +}; + +static void __init of_at91_pmc_setup(struct device_node *np, + const struct at91_pmc_caps *caps) +{ + struct at91_pmc *pmc; + struct device_node *childnp; + void (*clk_setup)(struct device_node *, struct at91_pmc *); + const struct of_device_id *clk_id; + void __iomem *regbase = of_iomap(np, 0); + int virq; + + if (!regbase) + return; + + virq = irq_of_parse_and_map(np, 0); + if (!virq) + return; + + pmc = at91_pmc_init(np, regbase, virq, caps); + if (!pmc) + return; + for_each_child_of_node(np, childnp) { + clk_id = of_match_node(pmc_clk_ids, childnp); + if (!clk_id) + continue; + clk_setup = clk_id->data; + clk_setup(childnp, pmc); + } +} + +static void __init of_at91rm9200_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91rm9200_caps); +} +CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc", + of_at91rm9200_pmc_setup); + +static void __init of_at91sam9260_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9260_caps); +} +CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc", + of_at91sam9260_pmc_setup); + +static void __init of_at91sam9g45_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9g45_caps); +} +CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc", + of_at91sam9g45_pmc_setup); + +static void __init of_at91sam9n12_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9n12_caps); +} +CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc", + of_at91sam9n12_pmc_setup); + +static void __init of_at91sam9x5_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9x5_caps); +} +CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc", + of_at91sam9x5_pmc_setup); + +static void __init of_sama5d3_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &sama5d3_caps); +} +CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc", + of_sama5d3_pmc_setup); diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h new file mode 100644 index 000000000000..d92b946cdc9e --- /dev/null +++ b/drivers/clk/at91/pmc.h @@ -0,0 +1,61 @@ +/* + * drivers/clk/at91/pmc.h + * + * Copyright (C) 2013 Boris BREZILLON + * + * 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 __PMC_H_ +#define __PMC_H_ + +#include +#include +#include + +struct clk_range { + unsigned long min; + unsigned long max; +}; + +#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} + +struct at91_pmc_caps { + u32 available_irqs; +}; + +struct at91_pmc { + void __iomem *regbase; + int virq; + spinlock_t lock; + const struct at91_pmc_caps *caps; + struct irq_domain *irqdomain; +}; + +static inline void pmc_lock(struct at91_pmc *pmc) +{ + spin_lock(&pmc->lock); +} + +static inline void pmc_unlock(struct at91_pmc *pmc) +{ + spin_unlock(&pmc->lock); +} + +static inline u32 pmc_read(struct at91_pmc *pmc, int offset) +{ + return readl(pmc->regbase + offset); +} + +static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) +{ + writel(value, pmc->regbase + offset); +} + +int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range); + +#endif /* __PMC_H_ */ -- cgit v1.2.3 From 38d34c3120b5588e2bd561baa4c5cfef1a4917bb Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 10:44:49 +0200 Subject: clk: at91: add PMC main clock This patch adds new at91 main oscillator clock implementation using common clk framework. If rate is not provided during clock registration it is calculated using the slow clock (main clk parent in this case) rate and MCFR register. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/at91/Makefile | 1 + drivers/clk/at91/clk-main.c | 187 ++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 5 ++ drivers/clk/at91/pmc.h | 3 + 4 files changed, 196 insertions(+) create mode 100644 drivers/clk/at91/clk-main.c (limited to 'drivers') diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 1d4fb214bbc4..44105bd44aa1 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,3 +3,4 @@ # obj-y += pmc.o +obj-y += clk-main.o diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c new file mode 100644 index 000000000000..8e9e8cc0412d --- /dev/null +++ b/drivers/clk/at91/clk-main.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define SLOW_CLOCK_FREQ 32768 +#define MAINF_DIV 16 +#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \ + SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT + +struct clk_main { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned long rate; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_main(hw) container_of(hw, struct clk_main, hw) + +static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) +{ + struct clk_main *clkmain = (struct clk_main *)dev_id; + + wake_up(&clkmain->wait); + disable_irq_nosync(clkmain->irq); + + return IRQ_HANDLED; +} + +static int clk_main_prepare(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain->pmc; + unsigned long halt_time, timeout; + u32 tmp; + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) { + enable_irq(clkmain->irq); + wait_event(clkmain->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); + } + + if (clkmain->rate) + return 0; + + timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); + do { + halt_time = jiffies; + tmp = pmc_read(pmc, AT91_CKGR_MCFR); + if (tmp & AT91_PMC_MAINRDY) + return 0; + usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); + } while (time_before(halt_time, timeout)); + + return 0; +} + +static int clk_main_is_prepared(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + + return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); +} + +static unsigned long clk_main_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain->pmc; + + if (clkmain->rate) + return clkmain->rate; + + tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF; + clkmain->rate = (tmp * parent_rate) / MAINF_DIV; + + return clkmain->rate; +} + +static const struct clk_ops main_ops = { + .prepare = clk_main_prepare, + .is_prepared = clk_main_is_prepared, + .recalc_rate = clk_main_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_main(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + const char *parent_name, + unsigned long rate) +{ + int ret; + struct clk_main *clkmain; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name) + return ERR_PTR(-EINVAL); + + if (!rate && !parent_name) + return ERR_PTR(-EINVAL); + + clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); + if (!clkmain) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &main_ops; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.flags = parent_name ? 0 : CLK_IS_ROOT; + + clkmain->hw.init = &init; + clkmain->rate = rate; + clkmain->pmc = pmc; + clkmain->irq = irq; + init_waitqueue_head(&clkmain->wait); + irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); + ret = request_irq(clkmain->irq, clk_main_irq_handler, + IRQF_TRIGGER_HIGH, "clk-main", clkmain); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &clkmain->hw); + if (IS_ERR(clk)) { + free_irq(clkmain->irq, clkmain); + kfree(clkmain); + } + + return clk; +} + + + +static void __init +of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc) +{ + struct clk *clk; + unsigned int irq; + const char *parent_name; + const char *name = np->name; + u32 rate = 0; + + parent_name = of_clk_get_parent_name(np, 0); + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "clock-frequency", &rate); + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_main(pmc, irq, name, parent_name, rate); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +void __init of_at91rm9200_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_main_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 69c116a6ba4f..3d35b7313868 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -229,6 +229,11 @@ out_free_pmc: } static const struct of_device_id pmc_clk_ids[] __initdata = { + /* Main clock */ + { + .compatible = "atmel,at91rm9200-clk-main", + .data = of_at91rm9200_clk_main_setup, + }, { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index d92b946cdc9e..729aa46c7289 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -58,4 +58,7 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) int of_at91_get_clk_range(struct device_node *np, const char *propname, struct clk_range *range); +extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc); + #endif /* __PMC_H_ */ -- cgit v1.2.3 From 1a748d2bc5061b72588013a720645661345c0e65 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 10:48:26 +0200 Subject: clk: at91: add PMC pll clocks This patch adds new at91 pll clock implementation using common clk framework. The pll clock layout describe the PLLX register layout. There are four pll clock layouts: - at91rm9200 - at91sam9g20 - at91sam9g45 - sama5d3 PLL clocks are given characteristics: - min/max clock source rate - ranges of valid clock output rates - values to set in out and icpll fields for each supported output range These characteristics are checked during rate change to avoid over/underclocking. These characteristics are described in atmel's SoC datasheet in "Electrical Characteristics" paragraph. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/at91/Makefile | 2 +- drivers/clk/at91/clk-pll.c | 537 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/clk-plldiv.c | 135 +++++++++++ drivers/clk/at91/pmc.c | 21 ++ drivers/clk/at91/pmc.h | 11 + include/linux/clk/at91_pmc.h | 2 + 6 files changed, 707 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-pll.c create mode 100644 drivers/clk/at91/clk-plldiv.c (limited to 'drivers') diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 44105bd44aa1..902bbf1fe584 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,4 +3,4 @@ # obj-y += pmc.o -obj-y += clk-main.o +obj-y += clk-main.o clk-pll.o clk-plldiv.o diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c new file mode 100644 index 000000000000..5e23ee4ce387 --- /dev/null +++ b/drivers/clk/at91/clk-pll.c @@ -0,0 +1,537 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define PLL_STATUS_MASK(id) (1 << (1 + (id))) +#define PLL_REG(id) (AT91_CKGR_PLLAR + ((id) * 4)) +#define PLL_DIV_MASK 0xff +#define PLL_DIV_MAX PLL_DIV_MASK +#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) +#define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \ + (layout)->mul_mask) +#define PLL_ICPR_SHIFT(id) ((id) * 16) +#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) +#define PLL_MAX_COUNT 0x3ff +#define PLL_COUNT_SHIFT 8 +#define PLL_OUT_SHIFT 14 +#define PLL_MAX_ID 1 + +struct clk_pll_characteristics { + struct clk_range input; + int num_output; + struct clk_range *output; + u16 *icpll; + u8 *out; +}; + +struct clk_pll_layout { + u32 pllr_mask; + u16 mul_mask; + u8 mul_shift; +}; + +#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw) + +struct clk_pll { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 div; + u8 range; + u16 mul; + const struct clk_pll_layout *layout; + const struct clk_pll_characteristics *characteristics; +}; + +static irqreturn_t clk_pll_irq_handler(int irq, void *dev_id) +{ + struct clk_pll *pll = (struct clk_pll *)dev_id; + + wake_up(&pll->wait); + disable_irq_nosync(pll->irq); + + return IRQ_HANDLED; +} + +static int clk_pll_prepare(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + const struct clk_pll_layout *layout = pll->layout; + u8 id = pll->id; + u32 mask = PLL_STATUS_MASK(id); + int offset = PLL_REG(id); + u8 out = 0; + u32 pllr, icpr; + u8 div; + u16 mul; + + pllr = pmc_read(pmc, offset); + div = PLL_DIV(pllr); + mul = PLL_MUL(pllr, layout); + + if ((pmc_read(pmc, AT91_PMC_SR) & mask) && + (div == pll->div && mul == pll->mul)) + return 0; + + if (characteristics->out) + out = characteristics->out[pll->range]; + if (characteristics->icpll) { + icpr = pmc_read(pmc, AT91_PMC_PLLICPR) & ~PLL_ICPR_MASK(id); + icpr |= (characteristics->icpll[pll->range] << + PLL_ICPR_SHIFT(id)); + pmc_write(pmc, AT91_PMC_PLLICPR, icpr); + } + + pllr &= ~layout->pllr_mask; + pllr |= layout->pllr_mask & + (pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | + (out << PLL_OUT_SHIFT) | + ((pll->mul & layout->mul_mask) << layout->mul_shift)); + pmc_write(pmc, offset, pllr); + + while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { + enable_irq(pll->irq); + wait_event(pll->wait, + pmc_read(pmc, AT91_PMC_SR) & mask); + } + + return 0; +} + +static int clk_pll_is_prepared(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) & + PLL_STATUS_MASK(pll->id)); +} + +static void clk_pll_unprepare(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + const struct clk_pll_layout *layout = pll->layout; + int offset = PLL_REG(pll->id); + u32 tmp = pmc_read(pmc, offset) & ~(layout->pllr_mask); + + pmc_write(pmc, offset, tmp); +} + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + const struct clk_pll_layout *layout = pll->layout; + struct at91_pmc *pmc = pll->pmc; + int offset = PLL_REG(pll->id); + u32 tmp = pmc_read(pmc, offset) & layout->pllr_mask; + u8 div = PLL_DIV(tmp); + u16 mul = PLL_MUL(tmp, layout); + if (!div || !mul) + return 0; + + return (parent_rate * (mul + 1)) / div; +} + +static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, + unsigned long parent_rate, + u32 *div, u32 *mul, + u32 *index) { + unsigned long maxrate; + unsigned long minrate; + unsigned long divrate; + unsigned long bestdiv = 1; + unsigned long bestmul; + unsigned long tmpdiv; + unsigned long roundup; + unsigned long rounddown; + unsigned long remainder; + unsigned long bestremainder; + unsigned long maxmul; + unsigned long maxdiv; + unsigned long mindiv; + int i = 0; + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_characteristics *characteristics = + pll->characteristics; + + /* Minimum divider = 1 */ + /* Maximum multiplier = max_mul */ + maxmul = layout->mul_mask + 1; + maxrate = (parent_rate * maxmul) / 1; + + /* Maximum divider = max_div */ + /* Minimum multiplier = 2 */ + maxdiv = PLL_DIV_MAX; + minrate = (parent_rate * 2) / maxdiv; + + if (parent_rate < characteristics->input.min || + parent_rate < characteristics->input.max) + return -ERANGE; + + if (parent_rate < minrate || parent_rate > maxrate) + return -ERANGE; + + for (i = 0; i < characteristics->num_output; i++) { + if (parent_rate >= characteristics->output[i].min && + parent_rate <= characteristics->output[i].max) + break; + } + + if (i >= characteristics->num_output) + return -ERANGE; + + bestmul = rate / parent_rate; + rounddown = parent_rate % rate; + roundup = rate - rounddown; + bestremainder = roundup < rounddown ? roundup : rounddown; + + if (!bestremainder) { + if (div) + *div = bestdiv; + if (mul) + *mul = bestmul; + if (index) + *index = i; + return rate; + } + + maxdiv = 255 / (bestmul + 1); + if (parent_rate / maxdiv < characteristics->input.min) + maxdiv = parent_rate / characteristics->input.min; + mindiv = parent_rate / characteristics->input.max; + if (parent_rate % characteristics->input.max) + mindiv++; + + for (tmpdiv = mindiv; tmpdiv < maxdiv; tmpdiv++) { + divrate = parent_rate / tmpdiv; + + rounddown = rate % divrate; + roundup = divrate - rounddown; + remainder = roundup < rounddown ? roundup : rounddown; + + if (remainder < bestremainder) { + bestremainder = remainder; + bestmul = rate / divrate; + bestdiv = tmpdiv; + } + + if (!remainder) + break; + } + + rate = (parent_rate / bestdiv) * bestmul; + + if (div) + *div = bestdiv; + if (mul) + *mul = bestmul; + if (index) + *index = i; + + return rate; +} + +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + + return clk_pll_get_best_div_mul(pll, rate, *parent_rate, + NULL, NULL, NULL); +} + +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_characteristics *characteristics = + pll->characteristics; + u8 id = pll->id; + int offset = PLL_REG(id); + long ret; + u32 div; + u32 mul; + u32 index; + u32 tmp; + u8 out = 0; + + ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, + &div, &mul, &index); + if (ret < 0) + return ret; + + pll->range = index; + pll->div = div; + pll->mul = mul; + + return 0; +} + +static const struct clk_ops pll_ops = { + .prepare = clk_pll_prepare, + .unprepare = clk_pll_unprepare, + .is_prepared = clk_pll_is_prepared, + .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_pll_set_rate, +}; + +static struct clk * __init +at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, + const char *parent_name, u8 id, + const struct clk_pll_layout *layout, + const struct clk_pll_characteristics *characteristics) +{ + struct clk_pll *pll; + struct clk *clk = NULL; + struct clk_init_data init; + int ret; + int offset = PLL_REG(id); + u32 tmp; + + if (id > PLL_MAX_ID) + return ERR_PTR(-EINVAL); + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &pll_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_GATE; + + pll->id = id; + pll->hw.init = &init; + pll->layout = layout; + pll->characteristics = characteristics; + pll->pmc = pmc; + pll->irq = irq; + tmp = pmc_read(pmc, offset) & layout->pllr_mask; + pll->div = PLL_DIV(tmp); + pll->mul = PLL_MUL(tmp, layout); + init_waitqueue_head(&pll->wait); + irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); + ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, + id ? "clk-pllb" : "clk-plla", pll); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + + +static const struct clk_pll_layout at91rm9200_pll_layout = { + .pllr_mask = 0x7FFFFFF, + .mul_shift = 16, + .mul_mask = 0x7FF, +}; + +static const struct clk_pll_layout at91sam9g45_pll_layout = { + .pllr_mask = 0xFFFFFF, + .mul_shift = 16, + .mul_mask = 0xFF, +}; + +static const struct clk_pll_layout at91sam9g20_pllb_layout = { + .pllr_mask = 0x3FFFFF, + .mul_shift = 16, + .mul_mask = 0x3F, +}; + +static const struct clk_pll_layout sama5d3_pll_layout = { + .pllr_mask = 0x1FFFFFF, + .mul_shift = 18, + .mul_mask = 0x7F, +}; + + +static struct clk_pll_characteristics * __init +of_at91_clk_pll_get_characteristics(struct device_node *np) +{ + int i; + int offset; + u32 tmp; + int num_output; + u32 num_cells; + struct clk_range input; + struct clk_range *output; + u8 *out = NULL; + u16 *icpll = NULL; + struct clk_pll_characteristics *characteristics; + + if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input)) + return NULL; + + if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells", + &num_cells)) + return NULL; + + if (num_cells < 2 || num_cells > 4) + return NULL; + + if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp)) + return NULL; + num_output = tmp / (sizeof(u32) * num_cells); + + characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); + if (!characteristics) + return NULL; + + output = kzalloc(sizeof(*output) * num_output, GFP_KERNEL); + if (!output) + goto out_free_characteristics; + + if (num_cells > 2) { + out = kzalloc(sizeof(*out) * num_output, GFP_KERNEL); + if (!out) + goto out_free_output; + } + + if (num_cells > 3) { + icpll = kzalloc(sizeof(*icpll) * num_output, GFP_KERNEL); + if (!icpll) + goto out_free_output; + } + + for (i = 0; i < num_output; i++) { + offset = i * num_cells; + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset, &tmp)) + goto out_free_output; + output[i].min = tmp; + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset + 1, &tmp)) + goto out_free_output; + output[i].max = tmp; + + if (num_cells == 2) + continue; + + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset + 2, &tmp)) + goto out_free_output; + out[i] = tmp; + + if (num_cells == 3) + continue; + + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset + 3, &tmp)) + goto out_free_output; + icpll[i] = tmp; + } + + characteristics->input = input; + characteristics->num_output = num_output; + characteristics->output = output; + characteristics->out = out; + characteristics->icpll = icpll; + return characteristics; + +out_free_output: + kfree(icpll); + kfree(out); + kfree(output); +out_free_characteristics: + kfree(characteristics); + return NULL; +} + +static void __init +of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, + const struct clk_pll_layout *layout) +{ + u32 id; + unsigned int irq; + struct clk *clk; + const char *parent_name; + const char *name = np->name; + struct clk_pll_characteristics *characteristics; + + if (of_property_read_u32(np, "reg", &id)) + return; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + + characteristics = of_at91_clk_pll_get_characteristics(np); + if (!characteristics) + return; + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_pll(pmc, irq, name, parent_name, id, layout, + characteristics); + if (IS_ERR(clk)) + goto out_free_characteristics; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; + +out_free_characteristics: + kfree(characteristics); +} + +void __init of_at91rm9200_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &at91rm9200_pll_layout); +} + +void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &at91sam9g45_pll_layout); +} + +void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &at91sam9g20_pllb_layout); +} + +void __init of_sama5d3_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &sama5d3_pll_layout); +} diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c new file mode 100644 index 000000000000..ea226562bb40 --- /dev/null +++ b/drivers/clk/at91/clk-plldiv.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define to_clk_plldiv(hw) container_of(hw, struct clk_plldiv, hw) + +struct clk_plldiv { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_plldiv *plldiv = to_clk_plldiv(hw); + struct at91_pmc *pmc = plldiv->pmc; + + if (pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_PLLADIV2) + return parent_rate / 2; + + return parent_rate; +} + +static long clk_plldiv_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + + if (rate > *parent_rate) + return *parent_rate; + div = *parent_rate / 2; + if (rate < div) + return div; + + if (rate - div < *parent_rate - rate) + return div; + + return *parent_rate; +} + +static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_plldiv *plldiv = to_clk_plldiv(hw); + struct at91_pmc *pmc = plldiv->pmc; + u32 tmp; + + if (parent_rate != rate && (parent_rate / 2) != rate) + return -EINVAL; + + pmc_lock(pmc); + tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_PLLADIV2; + if ((parent_rate / 2) == rate) + tmp |= AT91_PMC_PLLADIV2; + pmc_write(pmc, AT91_PMC_MCKR, tmp); + pmc_unlock(pmc); + + return 0; +} + +static const struct clk_ops plldiv_ops = { + .recalc_rate = clk_plldiv_recalc_rate, + .round_rate = clk_plldiv_round_rate, + .set_rate = clk_plldiv_set_rate, +}; + +static struct clk * __init +at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, + const char *parent_name) +{ + struct clk_plldiv *plldiv; + struct clk *clk = NULL; + struct clk_init_data init; + + plldiv = kzalloc(sizeof(*plldiv), GFP_KERNEL); + if (!plldiv) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &plldiv_ops; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.flags = CLK_SET_RATE_GATE; + + plldiv->hw.init = &init; + plldiv->pmc = pmc; + + clk = clk_register(NULL, &plldiv->hw); + + if (IS_ERR(clk)) + kfree(plldiv); + + return clk; +} + +static void __init +of_at91_clk_plldiv_setup(struct device_node *np, struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91_clk_register_plldiv(pmc, name, parent_name); + + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; +} + +void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_plldiv_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 3d35b7313868..5af3f2fbf45e 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -234,6 +234,27 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91rm9200-clk-main", .data = of_at91rm9200_clk_main_setup, }, + /* PLL clocks */ + { + .compatible = "atmel,at91rm9200-clk-pll", + .data = of_at91rm9200_clk_pll_setup, + }, + { + .compatible = "atmel,at91sam9g45-clk-pll", + .data = of_at91sam9g45_clk_pll_setup, + }, + { + .compatible = "atmel,at91sam9g20-clk-pllb", + .data = of_at91sam9g20_clk_pllb_setup, + }, + { + .compatible = "atmel,sama5d3-clk-pll", + .data = of_sama5d3_clk_pll_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-plldiv", + .data = of_at91sam9x5_clk_plldiv_setup, + }, { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 729aa46c7289..15aaf38e37c5 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -61,4 +61,15 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname, extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, struct at91_pmc *pmc); +extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_sama5d3_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, + struct at91_pmc *pmc); + #endif /* __PMC_H_ */ diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index 00c45b3510bf..a6911ebbd02a 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h @@ -164,6 +164,8 @@ extern void __iomem *at91_pmc_base; #define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ #define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ +#define AT91_PMC_PLLICPR 0x80 /* PLL Charge Pump Current Register */ + #define AT91_PMC_PROT 0xe4 /* Write Protect Mode Register [some SAM9] */ #define AT91_PMC_WPEN (0x1 << 0) /* Write Protect Enable */ #define AT91_PMC_WPKEY (0xffffff << 8) /* Write Protect Key */ -- cgit v1.2.3 From e442d234405ad75e2d3d2baf15b364ee2c3573c9 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 10:51:23 +0200 Subject: clk: at91: add PMC master clock This patch adds new at91 master clock implementation using common clk framework. The master clock layout describe the MCKR register layout. There are 2 master clock layouts: - at91rm9200 - at91sam9x5 Master clocks are given characteristics: - min/max clock output rate These characteristics are checked during rate change to avoid over/underclocking. These characteristics are described in atmel's SoC datasheet in "Electrical Characteristics" paragraph. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/at91/Makefile | 2 +- drivers/clk/at91/clk-master.c | 270 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/clk-pll.c | 10 +- drivers/clk/at91/pmc.c | 9 ++ drivers/clk/at91/pmc.h | 5 + 5 files changed, 287 insertions(+), 9 deletions(-) create mode 100644 drivers/clk/at91/clk-master.c (limited to 'drivers') diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 902bbf1fe584..e28fb2bbb198 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -3,4 +3,4 @@ # obj-y += pmc.o -obj-y += clk-main.o clk-pll.o clk-plldiv.o +obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c new file mode 100644 index 000000000000..bd313f7816a8 --- /dev/null +++ b/drivers/clk/at91/clk-master.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define MASTER_SOURCE_MAX 4 + +#define MASTER_PRES_MASK 0x7 +#define MASTER_PRES_MAX MASTER_PRES_MASK +#define MASTER_DIV_SHIFT 8 +#define MASTER_DIV_MASK 0x3 + +struct clk_master_characteristics { + struct clk_range output; + u32 divisors[4]; + u8 have_div3_pres; +}; + +struct clk_master_layout { + u32 mask; + u8 pres_shift; +}; + +#define to_clk_master(hw) container_of(hw, struct clk_master, hw) + +struct clk_master { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + const struct clk_master_layout *layout; + const struct clk_master_characteristics *characteristics; +}; + +static irqreturn_t clk_master_irq_handler(int irq, void *dev_id) +{ + struct clk_master *master = (struct clk_master *)dev_id; + + wake_up(&master->wait); + disable_irq_nosync(master->irq); + + return IRQ_HANDLED; +} +static int clk_master_prepare(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master->pmc; + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) { + enable_irq(master->irq); + wait_event(master->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); + } + + return 0; +} + +static int clk_master_is_prepared(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + + return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); +} + +static unsigned long clk_master_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u8 pres; + u8 div; + unsigned long rate = parent_rate; + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master->pmc; + const struct clk_master_layout *layout = master->layout; + const struct clk_master_characteristics *characteristics = + master->characteristics; + u32 tmp; + + pmc_lock(pmc); + tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask; + pmc_unlock(pmc); + + pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK; + div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; + + if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX) + rate /= 3; + else + rate >>= pres; + + rate /= characteristics->divisors[div]; + + if (rate < characteristics->output.min) + pr_warn("master clk is underclocked"); + else if (rate > characteristics->output.max) + pr_warn("master clk is overclocked"); + + return rate; +} + +static u8 clk_master_get_parent(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master->pmc; + + return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS; +} + +static const struct clk_ops master_ops = { + .prepare = clk_master_prepare, + .is_prepared = clk_master_is_prepared, + .recalc_rate = clk_master_recalc_rate, + .get_parent = clk_master_get_parent, +}; + +static struct clk * __init +at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, + const char *name, int num_parents, + const char **parent_names, + const struct clk_master_layout *layout, + const struct clk_master_characteristics *characteristics) +{ + int ret; + struct clk_master *master; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name || !num_parents || !parent_names) + return ERR_PTR(-EINVAL); + + master = kzalloc(sizeof(*master), GFP_KERNEL); + if (!master) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &master_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = 0; + + master->hw.init = &init; + master->layout = layout; + master->characteristics = characteristics; + master->pmc = pmc; + master->irq = irq; + init_waitqueue_head(&master->wait); + irq_set_status_flags(master->irq, IRQ_NOAUTOEN); + ret = request_irq(master->irq, clk_master_irq_handler, + IRQF_TRIGGER_HIGH, "clk-master", master); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &master->hw); + if (IS_ERR(clk)) + kfree(master); + + return clk; +} + + +static const struct clk_master_layout at91rm9200_master_layout = { + .mask = 0x31F, + .pres_shift = 2, +}; + +static const struct clk_master_layout at91sam9x5_master_layout = { + .mask = 0x373, + .pres_shift = 4, +}; + + +static struct clk_master_characteristics * __init +of_at91_clk_master_get_characteristics(struct device_node *np) +{ + struct clk_master_characteristics *characteristics; + + characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); + if (!characteristics) + return NULL; + + if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output)) + goto out_free_characteristics; + + of_property_read_u32_array(np, "atmel,clk-divisors", + characteristics->divisors, 4); + + characteristics->have_div3_pres = + of_property_read_bool(np, "atmel,master-clk-have-div3-pres"); + + return characteristics; + +out_free_characteristics: + kfree(characteristics); + return NULL; +} + +static void __init +of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, + const struct clk_master_layout *layout) +{ + struct clk *clk; + int num_parents; + int i; + unsigned int irq; + const char *parent_names[MASTER_SOURCE_MAX]; + const char *name = np->name; + struct clk_master_characteristics *characteristics; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + characteristics = of_at91_clk_master_get_characteristics(np); + if (!characteristics) + return; + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_master(pmc, irq, name, num_parents, + parent_names, layout, + characteristics); + if (IS_ERR(clk)) + goto out_free_characteristics; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; + +out_free_characteristics: + kfree(characteristics); +} + +void __init of_at91rm9200_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout); +} + +void __init of_at91sam9x5_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout); +} diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index 5e23ee4ce387..cf6ed023504c 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -80,6 +80,8 @@ static int clk_pll_prepare(struct clk_hw *hw) struct clk_pll *pll = to_clk_pll(hw); struct at91_pmc *pmc = pll->pmc; const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_characteristics *characteristics = + pll->characteristics; u8 id = pll->id; u32 mask = PLL_STATUS_MASK(id); int offset = PLL_REG(id); @@ -269,18 +271,10 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); - struct at91_pmc *pmc = pll->pmc; - const struct clk_pll_layout *layout = pll->layout; - const struct clk_pll_characteristics *characteristics = - pll->characteristics; - u8 id = pll->id; - int offset = PLL_REG(id); long ret; u32 div; u32 mul; u32 index; - u32 tmp; - u8 out = 0; ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, &div, &mul, &index); diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 5af3f2fbf45e..a311cf3d5358 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -255,6 +255,15 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9x5-clk-plldiv", .data = of_at91sam9x5_clk_plldiv_setup, }, + /* Master clock */ + { + .compatible = "atmel,at91rm9200-clk-master", + .data = of_at91rm9200_clk_master_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-master", + .data = of_at91sam9x5_clk_master_setup, + }, { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 15aaf38e37c5..be5c964accad 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -72,4 +72,9 @@ extern void __init of_sama5d3_clk_pll_setup(struct device_node *np, extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, struct at91_pmc *pmc); +extern void __init of_at91rm9200_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc); + #endif /* __PMC_H_ */ -- cgit v1.2.3 From 5fba62ea2648f89cbd7f0ed32069f03b179d05e9 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 11:41:41 +0200 Subject: clk: at91: add PMC system clocks This patch adds new at91 system clock implementation using common clk framework. Some peripherals need to enable a "system" clock in order to work properly. Each system clock is given an id based on the bit position in SCER/SCDR registers. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/at91/Makefile | 1 + drivers/clk/at91/clk-system.c | 135 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 5 ++ drivers/clk/at91/pmc.h | 3 + 4 files changed, 144 insertions(+) create mode 100644 drivers/clk/at91/clk-system.c (limited to 'drivers') diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index e28fb2bbb198..c2b70683e4e0 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,3 +4,4 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o +obj-y += clk-system.o diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c new file mode 100644 index 000000000000..8f7c0434a09f --- /dev/null +++ b/drivers/clk/at91/clk-system.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define SYSTEM_MAX_ID 31 + +#define SYSTEM_MAX_NAME_SZ 32 + +#define to_clk_system(hw) container_of(hw, struct clk_system, hw) +struct clk_system { + struct clk_hw hw; + struct at91_pmc *pmc; + u8 id; +}; + +static int clk_system_enable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys->pmc; + + pmc_write(pmc, AT91_PMC_SCER, 1 << sys->id); + return 0; +} + +static void clk_system_disable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys->pmc; + + pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); +} + +static int clk_system_is_enabled(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id)); +} + +static const struct clk_ops system_ops = { + .enable = clk_system_enable, + .disable = clk_system_disable, + .is_enabled = clk_system_is_enabled, +}; + +static struct clk * __init +at91_clk_register_system(struct at91_pmc *pmc, const char *name, + const char *parent_name, u8 id) +{ + struct clk_system *sys; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!parent_name || id > SYSTEM_MAX_ID) + return ERR_PTR(-EINVAL); + + sys = kzalloc(sizeof(*sys), GFP_KERNEL); + if (!sys) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &system_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + /* + * CLK_IGNORE_UNUSED is used to avoid ddrck switch off. + * TODO : we should implement a driver supporting at91 ddr controller + * (see drivers/memory) which would request and enable the ddrck clock. + * When this is done we will be able to remove CLK_IGNORE_UNUSED flag. + */ + init.flags = CLK_IGNORE_UNUSED; + + sys->id = id; + sys->hw.init = &init; + sys->pmc = pmc; + + clk = clk_register(NULL, &sys->hw); + if (IS_ERR(clk)) + kfree(sys); + + return clk; +} + +static void __init +of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) +{ + int num; + u32 id; + struct clk *clk; + const char *name; + struct device_node *sysclknp; + const char *parent_name; + + num = of_get_child_count(np); + if (num > (SYSTEM_MAX_ID + 1)) + return; + + for_each_child_of_node(np, sysclknp) { + if (of_property_read_u32(sysclknp, "reg", &id)) + continue; + + if (of_property_read_string(np, "clock-output-names", &name)) + name = sysclknp->name; + + parent_name = of_clk_get_parent_name(sysclknp, 0); + + clk = at91_clk_register_system(pmc, name, parent_name, id); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); + } +} + +void __init of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_sys_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index a311cf3d5358..a97554f943e4 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -264,6 +264,11 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9x5-clk-master", .data = of_at91sam9x5_clk_master_setup, }, + /* System clocks */ + { + .compatible = "atmel,at91rm9200-clk-system", + .data = of_at91rm9200_clk_sys_setup, + }, { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index be5c964accad..9c8a397cb850 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -77,4 +77,7 @@ extern void __init of_at91rm9200_clk_master_setup(struct device_node *np, extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np, struct at91_pmc *pmc); +extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc); + #endif /* __PMC_H_ */ -- cgit v1.2.3 From 6114067e437eb861a8e75741e3d8763475f75512 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 11:44:36 +0200 Subject: clk: at91: add PMC peripheral clocks This patch adds new at91 peripheral clock implementation using common clk framework. Almost all peripherals provided by at91 SoCs need a clock to work properly. This clock is enabled/disabled using PCER/PCDR resgisters. Each peripheral is given an id (see atmel's datasheets) which is used to define and reference peripheral clocks. Some new SoCs (at91sam9x5 and sama5d3) provide a new register (PCR) where you can configure the peripheral clock as a division of the master clock. This will help reducing the peripherals power comsumption. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/at91/Makefile | 2 +- drivers/clk/at91/clk-peripheral.c | 410 ++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 9 + drivers/clk/at91/pmc.h | 5 + 4 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/at91/clk-peripheral.c (limited to 'drivers') diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index c2b70683e4e0..04deba35893e 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,4 +4,4 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o -obj-y += clk-system.o +obj-y += clk-system.o clk-peripheral.o diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c new file mode 100644 index 000000000000..597fed423d7d --- /dev/null +++ b/drivers/clk/at91/clk-peripheral.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define PERIPHERAL_MAX 64 + +#define PERIPHERAL_AT91RM9200 0 +#define PERIPHERAL_AT91SAM9X5 1 + +#define PERIPHERAL_ID_MIN 2 +#define PERIPHERAL_ID_MAX 31 +#define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX)) + +#define PERIPHERAL_RSHIFT_MASK 0x3 +#define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK) + +#define PERIPHERAL_MAX_SHIFT 4 + +struct clk_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 id; +}; + +#define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw) + +struct clk_sam9x5_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + struct clk_range range; + u32 id; + u32 div; + bool auto_div; +}; + +#define to_clk_sam9x5_peripheral(hw) \ + container_of(hw, struct clk_sam9x5_peripheral, hw) + +static int clk_peripheral_enable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCER; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return 0; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCER1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); + return 0; +} + +static void clk_peripheral_disable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCDR; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCDR1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); +} + +static int clk_peripheral_is_enabled(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCSR; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return 1; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCSR1; + return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id)); +} + +static const struct clk_ops peripheral_ops = { + .enable = clk_peripheral_enable, + .disable = clk_peripheral_disable, + .is_enabled = clk_peripheral_is_enabled, +}; + +static struct clk * __init +at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, + const char *parent_name, u32 id) +{ + struct clk_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); + if (!periph) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &peripheral_ops; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + init.flags = 0; + + periph->id = id; + periph->hw.init = &init; + periph->pmc = pmc; + + clk = clk_register(NULL, &periph->hw); + if (IS_ERR(clk)) + kfree(periph); + + return clk; +} + +static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) +{ + struct clk *parent; + unsigned long parent_rate; + int shift = 0; + + if (!periph->auto_div) + return; + + if (periph->range.max) { + parent = clk_get_parent_by_index(periph->hw.clk, 0); + parent_rate = __clk_get_rate(parent); + if (!parent_rate) + return; + + for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { + if (parent_rate >> shift <= periph->range.max) + break; + } + } + + periph->auto_div = false; + periph->div = shift; +} + +static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + + if (periph->id < PERIPHERAL_ID_MIN) + return 0; + + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) | + AT91_PMC_PCR_CMD | + AT91_PMC_PCR_DIV(periph->div) | + AT91_PMC_PCR_EN); + return 0; +} + +static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + + if (periph->id < PERIPHERAL_ID_MIN) + return; + + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) | + AT91_PMC_PCR_CMD); +} + +static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int ret; + + if (periph->id < PERIPHERAL_ID_MIN) + return 1; + + pmc_lock(pmc); + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID)); + ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN); + pmc_unlock(pmc); + + return ret; +} + +static unsigned long +clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + u32 tmp; + + if (periph->id < PERIPHERAL_ID_MIN) + return parent_rate; + + pmc_lock(pmc); + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID)); + tmp = pmc_read(pmc, AT91_PMC_PCR); + pmc_unlock(pmc); + + if (tmp & AT91_PMC_PCR_EN) { + periph->div = PERIPHERAL_RSHIFT(tmp); + periph->auto_div = false; + } else { + clk_sam9x5_peripheral_autodiv(periph); + } + + return parent_rate >> periph->div; +} + +static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + int shift = 0; + unsigned long best_rate; + unsigned long best_diff; + unsigned long cur_rate = *parent_rate; + unsigned long cur_diff; + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + + if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) + return *parent_rate; + + if (periph->range.max) { + for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { + cur_rate = *parent_rate >> shift; + if (cur_rate <= periph->range.max) + break; + } + } + + if (rate >= cur_rate) + return cur_rate; + + best_diff = cur_rate - rate; + best_rate = cur_rate; + for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { + cur_rate = *parent_rate >> shift; + if (cur_rate < rate) + cur_diff = rate - cur_rate; + else + cur_diff = cur_rate - rate; + + if (cur_diff < best_diff) { + best_diff = cur_diff; + best_rate = cur_rate; + } + + if (!best_diff || cur_rate < rate) + break; + } + + return best_rate; +} + +static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + int shift; + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) { + if (parent_rate == rate) + return 0; + else + return -EINVAL; + } + + if (periph->range.max && rate > periph->range.max) + return -EINVAL; + + for (shift = 0; shift < PERIPHERAL_MAX_SHIFT; shift++) { + if (parent_rate >> shift == rate) { + periph->auto_div = false; + periph->div = shift; + return 0; + } + } + + return -EINVAL; +} + +static const struct clk_ops sam9x5_peripheral_ops = { + .enable = clk_sam9x5_peripheral_enable, + .disable = clk_sam9x5_peripheral_disable, + .is_enabled = clk_sam9x5_peripheral_is_enabled, + .recalc_rate = clk_sam9x5_peripheral_recalc_rate, + .round_rate = clk_sam9x5_peripheral_round_rate, + .set_rate = clk_sam9x5_peripheral_set_rate, +}; + +static struct clk * __init +at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, + const char *parent_name, u32 id, + const struct clk_range *range) +{ + struct clk_sam9x5_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name || !parent_name) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); + if (!periph) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &sam9x5_peripheral_ops; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + init.flags = 0; + + periph->id = id; + periph->hw.init = &init; + periph->div = 0; + periph->pmc = pmc; + periph->auto_div = true; + periph->range = *range; + + clk = clk_register(NULL, &periph->hw); + if (IS_ERR(clk)) + kfree(periph); + else + clk_sam9x5_peripheral_autodiv(periph); + + return clk; +} + +static void __init +of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) +{ + int num; + u32 id; + struct clk *clk; + const char *parent_name; + const char *name; + struct device_node *periphclknp; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) + return; + + num = of_get_child_count(np); + if (!num || num > PERIPHERAL_MAX) + return; + + for_each_child_of_node(np, periphclknp) { + if (of_property_read_u32(periphclknp, "reg", &id)) + continue; + + if (id >= PERIPHERAL_MAX) + continue; + + if (of_property_read_string(np, "clock-output-names", &name)) + name = periphclknp->name; + + if (type == PERIPHERAL_AT91RM9200) { + clk = at91_clk_register_peripheral(pmc, name, + parent_name, id); + } else { + struct clk_range range = CLK_RANGE(0, 0); + + of_at91_get_clk_range(periphclknp, + "atmel,clk-output-range", + &range); + + clk = at91_clk_register_sam9x5_peripheral(pmc, name, + parent_name, + id, &range); + } + + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(periphclknp, of_clk_src_simple_get, clk); + } +} + +void __init of_at91rm9200_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200); +} + +void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index a97554f943e4..afdfeb27acb8 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -269,6 +269,15 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91rm9200-clk-system", .data = of_at91rm9200_clk_sys_setup, }, + /* Peripheral clocks */ + { + .compatible = "atmel,at91rm9200-clk-peripheral", + .data = of_at91rm9200_clk_periph_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-peripheral", + .data = of_at91sam9x5_clk_periph_setup, + }, { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 9c8a397cb850..a09212bc6bc9 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -80,4 +80,9 @@ extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np, extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc); +extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc); + #endif /* __PMC_H_ */ -- cgit v1.2.3 From 1f22f8bb64b3619324020b48b03181914b1f5544 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 11:57:04 +0200 Subject: clk: at91: add PMC programmable clocks This patch adds new at91 programmable clocks implementation using common clk framework. A programmable clock is a clock which can be exported on a given pin to clock external devices. Each programmable clock is given an id (from 0 to 8). The number of available programmable clocks depends on the SoC you're using. Programmable clock driver only implements the clock setting (clock rate and parent setting). It must be chained to a system clock in order to enable/disable the generated clock. The PCKX pins used to output the clock signals must be assigned to the appropriate peripheral (see atmel's datasheets). Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- drivers/clk/at91/Makefile | 2 + drivers/clk/at91/clk-programmable.c | 366 ++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h | 9 + 4 files changed, 392 insertions(+) create mode 100644 drivers/clk/at91/clk-programmable.c (limited to 'drivers') diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 04deba35893e..3873b621768f 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -5,3 +5,5 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o + +obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c new file mode 100644 index 000000000000..fd792b203eaf --- /dev/null +++ b/drivers/clk/at91/clk-programmable.c @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define PROG_SOURCE_MAX 5 +#define PROG_ID_MAX 7 + +#define PROG_STATUS_MASK(id) (1 << ((id) + 8)) +#define PROG_PRES_MASK 0x7 +#define PROG_MAX_RM9200_CSS 3 + +struct clk_programmable_layout { + u8 pres_shift; + u8 css_mask; + u8 have_slck_mck; +}; + +struct clk_programmable { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 css; + u8 pres; + u8 slckmck; + const struct clk_programmable_layout *layout; +}; + +#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) + + +static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id) +{ + struct clk_programmable *prog = (struct clk_programmable *)dev_id; + + wake_up(&prog->wait); + + return IRQ_HANDLED; +} + +static int clk_programmable_prepare(struct clk_hw *hw) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + u8 id = prog->id; + u32 mask = PROG_STATUS_MASK(id); + + tmp = prog->css | (prog->pres << layout->pres_shift); + if (layout->have_slck_mck && prog->slckmck) + tmp |= AT91_PMC_CSSMCK_MCK; + + pmc_write(pmc, AT91_PMC_PCKR(id), tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) + wait_event(prog->wait, pmc_read(pmc, AT91_PMC_SR) & mask); + + return 0; +} + +static int clk_programmable_is_ready(struct clk_hw *hw) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_PCKR(prog->id)); +} + +static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + + tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); + prog->pres = (tmp >> layout->pres_shift) & PROG_PRES_MASK; + + return parent_rate >> prog->pres; +} + +static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long best_rate = *parent_rate; + unsigned long best_diff; + unsigned long new_diff; + unsigned long cur_rate; + int shift = shift; + + if (rate > *parent_rate) + return *parent_rate; + else + best_diff = *parent_rate - rate; + + if (!best_diff) + return best_rate; + + for (shift = 1; shift < PROG_PRES_MASK; shift++) { + cur_rate = *parent_rate >> shift; + + if (cur_rate > rate) + new_diff = cur_rate - rate; + else + new_diff = rate - cur_rate; + + if (!new_diff) + return cur_rate; + + if (new_diff < best_diff) { + best_diff = new_diff; + best_rate = cur_rate; + } + + if (rate > cur_rate) + break; + } + + return best_rate; +} + +static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + const struct clk_programmable_layout *layout = prog->layout; + if (index > layout->css_mask) { + if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { + prog->css = 0; + prog->slckmck = 1; + return 0; + } else { + return -EINVAL; + } + } + + prog->css = index; + return 0; +} + +static u8 clk_programmable_get_parent(struct clk_hw *hw) +{ + u32 tmp; + u8 ret; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + + tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); + prog->css = tmp & layout->css_mask; + ret = prog->css; + if (layout->have_slck_mck) { + prog->slckmck = !!(tmp & AT91_PMC_CSSMCK_MCK); + if (prog->slckmck && !ret) + ret = PROG_MAX_RM9200_CSS + 1; + } + + return ret; +} + +static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + unsigned long best_rate = parent_rate; + unsigned long best_diff; + unsigned long new_diff; + unsigned long cur_rate; + int shift = 0; + + if (rate > parent_rate) + return parent_rate; + else + best_diff = parent_rate - rate; + + if (!best_diff) { + prog->pres = shift; + return 0; + } + + for (shift = 1; shift < PROG_PRES_MASK; shift++) { + cur_rate = parent_rate >> shift; + + if (cur_rate > rate) + new_diff = cur_rate - rate; + else + new_diff = rate - cur_rate; + + if (!new_diff) + break; + + if (new_diff < best_diff) { + best_diff = new_diff; + best_rate = cur_rate; + } + + if (rate > cur_rate) + break; + } + + prog->pres = shift; + return 0; +} + +static const struct clk_ops programmable_ops = { + .prepare = clk_programmable_prepare, + .is_prepared = clk_programmable_is_ready, + .recalc_rate = clk_programmable_recalc_rate, + .round_rate = clk_programmable_round_rate, + .get_parent = clk_programmable_get_parent, + .set_parent = clk_programmable_set_parent, + .set_rate = clk_programmable_set_rate, +}; + +static struct clk * __init +at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq, + const char *name, const char **parent_names, + u8 num_parents, u8 id, + const struct clk_programmable_layout *layout) +{ + int ret; + struct clk_programmable *prog; + struct clk *clk = NULL; + struct clk_init_data init; + char irq_name[11]; + + if (id > PROG_ID_MAX) + return ERR_PTR(-EINVAL); + + prog = kzalloc(sizeof(*prog), GFP_KERNEL); + if (!prog) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &programmable_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + prog->id = id; + prog->layout = layout; + prog->hw.init = &init; + prog->pmc = pmc; + prog->irq = irq; + init_waitqueue_head(&prog->wait); + irq_set_status_flags(prog->irq, IRQ_NOAUTOEN); + snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id); + ret = request_irq(prog->irq, clk_programmable_irq_handler, + IRQF_TRIGGER_HIGH, irq_name, prog); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &prog->hw); + if (IS_ERR(clk)) + kfree(prog); + + return clk; +} + +static const struct clk_programmable_layout at91rm9200_programmable_layout = { + .pres_shift = 2, + .css_mask = 0x3, + .have_slck_mck = 0, +}; + +static const struct clk_programmable_layout at91sam9g45_programmable_layout = { + .pres_shift = 2, + .css_mask = 0x3, + .have_slck_mck = 1, +}; + +static const struct clk_programmable_layout at91sam9x5_programmable_layout = { + .pres_shift = 4, + .css_mask = 0x7, + .have_slck_mck = 0, +}; + +static void __init +of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, + const struct clk_programmable_layout *layout) +{ + int num; + u32 id; + int i; + unsigned int irq; + struct clk *clk; + int num_parents; + const char *parent_names[PROG_SOURCE_MAX]; + const char *name; + struct device_node *progclknp; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + num = of_get_child_count(np); + if (!num || num > (PROG_ID_MAX + 1)) + return; + + for_each_child_of_node(np, progclknp) { + if (of_property_read_u32(progclknp, "reg", &id)) + continue; + + if (of_property_read_string(np, "clock-output-names", &name)) + name = progclknp->name; + + irq = irq_of_parse_and_map(progclknp, 0); + if (!irq) + continue; + + clk = at91_clk_register_programmable(pmc, irq, name, + parent_names, num_parents, + id, layout); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(progclknp, of_clk_src_simple_get, clk); + } +} + + +void __init of_at91rm9200_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout); +} + +void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout); +} + +void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index afdfeb27acb8..d0a1f93500f0 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -278,6 +278,21 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9x5-clk-peripheral", .data = of_at91sam9x5_clk_periph_setup, }, + /* Programmable clocks */ +#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS) + { + .compatible = "atmel,at91rm9200-clk-programmable", + .data = of_at91rm9200_clk_prog_setup, + }, + { + .compatible = "atmel,at91sam9g45-clk-programmable", + .data = of_at91sam9g45_clk_prog_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-programmable", + .data = of_at91sam9x5_clk_prog_setup, + }, +#endif { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index a09212bc6bc9..6eeed491c94c 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -85,4 +85,13 @@ extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np, extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc); +#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS) +extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + #endif /* __PMC_H_ */ -- cgit v1.2.3 From f090fb37def3eb9ea49b71751dbe43f423f3a152 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 12:22:06 +0200 Subject: clk: at91: add PMC utmi clock This adds new at91 utmi clock implementation using common clk framework. This clock is a pll with a fixed factor (x40). It is used as a source for usb clock. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 7 ++ drivers/clk/at91/Makefile | 1 + drivers/clk/at91/clk-utmi.c | 159 ++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 7 ++ drivers/clk/at91/pmc.h | 5 ++ 5 files changed, 179 insertions(+) create mode 100644 drivers/clk/at91/clk-utmi.c (limited to 'drivers') diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 85b53a441459..6ad37daca971 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -1,5 +1,8 @@ if ARCH_AT91 +config HAVE_AT91_UTMI + bool + config HAVE_AT91_DBGU0 bool @@ -78,6 +81,7 @@ config SOC_SAMA5D3 select HAVE_FB_ATMEL select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -124,6 +128,7 @@ config SOC_AT91SAM9RL select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI config SOC_AT91SAM9G45 bool "AT91SAM9G45 or AT91SAM9M10 families" @@ -131,6 +136,7 @@ config SOC_AT91SAM9G45 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -141,6 +147,7 @@ config SOC_AT91SAM9X5 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 3873b621768f..a82488323ea4 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -7,3 +7,4 @@ obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o +obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c new file mode 100644 index 000000000000..ae3263bc1476 --- /dev/null +++ b/drivers/clk/at91/clk-utmi.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define UTMI_FIXED_MUL 40 + +struct clk_utmi { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) + +static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) +{ + struct clk_utmi *utmi = (struct clk_utmi *)dev_id; + + wake_up(&utmi->wait); + disable_irq_nosync(utmi->irq); + + return IRQ_HANDLED; +} + +static int clk_utmi_prepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi->pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | + AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU)) { + enable_irq(utmi->irq); + wait_event(utmi->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); + } + + return 0; +} + +static int clk_utmi_is_prepared(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); +} + +static void clk_utmi_unprepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi->pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); +} + +static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + /* UTMI clk is a fixed clk multiplier */ + return parent_rate * UTMI_FIXED_MUL; +} + +static const struct clk_ops utmi_ops = { + .prepare = clk_utmi_prepare, + .unprepare = clk_utmi_unprepare, + .is_prepared = clk_utmi_is_prepared, + .recalc_rate = clk_utmi_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, + const char *name, const char *parent_name) +{ + int ret; + struct clk_utmi *utmi; + struct clk *clk = NULL; + struct clk_init_data init; + + utmi = kzalloc(sizeof(*utmi), GFP_KERNEL); + if (!utmi) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &utmi_ops; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.flags = CLK_SET_RATE_GATE; + + utmi->hw.init = &init; + utmi->pmc = pmc; + utmi->irq = irq; + init_waitqueue_head(&utmi->wait); + irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); + ret = request_irq(utmi->irq, clk_utmi_irq_handler, + IRQF_TRIGGER_HIGH, "clk-utmi", utmi); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &utmi->hw); + if (IS_ERR(clk)) + kfree(utmi); + + return clk; +} + +static void __init +of_at91_clk_utmi_setup(struct device_node *np, struct at91_pmc *pmc) +{ + unsigned int irq; + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_utmi(pmc, irq, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; +} + +void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_utmi_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index d0a1f93500f0..0f667fd4e7fa 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -292,6 +292,13 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9x5-clk-programmable", .data = of_at91sam9x5_clk_prog_setup, }, +#endif + /* UTMI clock */ +#if defined(CONFIG_HAVE_AT91_UTMI) + { + .compatible = "atmel,at91sam9x5-clk-utmi", + .data = of_at91sam9x5_clk_utmi_setup, + }, #endif { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 6eeed491c94c..8e18ab0d8e22 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -94,4 +94,9 @@ extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc); #endif +#if defined(CONFIG_HAVE_AT91_UTMI) +extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + #endif /* __PMC_H_ */ -- cgit v1.2.3 From c84a61d87261f91d378cf26be4ffd3199ffd2493 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 17 Oct 2013 18:55:41 +0200 Subject: clk: at91: add PMC usb clock This patch adds new at91 usb clock implementation using common clk framework. This clock is used to clock usb ports (ohci, ehci and udc). Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 11 ++ drivers/clk/at91/Makefile | 1 + drivers/clk/at91/clk-usb.c | 398 +++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 15 ++ drivers/clk/at91/pmc.h | 9 + 5 files changed, 434 insertions(+) create mode 100644 drivers/clk/at91/clk-usb.c (limited to 'drivers') diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 6ad37daca971..b76dc4c62af9 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -3,6 +3,9 @@ if ARCH_AT91 config HAVE_AT91_UTMI bool +config HAVE_AT91_USB_CLK + bool + config HAVE_AT91_DBGU0 bool @@ -82,6 +85,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -96,12 +100,14 @@ config SOC_AT91RM9200 select MULTI_IRQ_HANDLER select SPARSE_IRQ select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9260 bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20" select HAVE_AT91_DBGU0 select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -112,6 +118,7 @@ config SOC_AT91SAM9261 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -121,6 +128,7 @@ config SOC_AT91SAM9263 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9RL bool "AT91SAM9RL" @@ -137,6 +145,7 @@ config SOC_AT91SAM9G45 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -148,6 +157,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -161,6 +171,7 @@ config SOC_AT91SAM9N12 select HAVE_FB_ATMEL select SOC_AT91SAM9 select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index a82488323ea4..61db058be0c0 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -8,3 +8,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000000000000..7d1d26a4bd04 --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define USB_SOURCE_MAX 2 + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_MAX_DIV 0xf + +#define RM9200_USB_DIV_SHIFT 28 +#define RM9200_USB_DIV_TAB_SIZE 4 + +struct at91sam9x5_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_usb(hw) \ + container_of(hw, struct at91sam9x5_clk_usb, hw) + +struct at91rm9200_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 divisors[4]; +}; + +#define to_at91rm9200_clk_usb(hw) \ + container_of(hw, struct at91rm9200_clk_usb, hw) + +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 usbdiv; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + tmp = pmc_read(pmc, AT91_PMC_USB); + usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; + return parent_rate / (usbdiv + 1); +} + +static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate >= *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div >= SAM9X5_USB_MAX_DIV) + return *parent_rate / (SAM9X5_USB_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate > rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + if (index > 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS; + if (index) + tmp |= AT91_PMC_USBS; + pmc_write(pmc, AT91_PMC_USB, tmp); + return 0; +} + +static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + return pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS; +} + +static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV) + return -EINVAL; + + tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; + tmp |= (div - 1) << SAM9X5_USB_DIV_SHIFT; + pmc_write(pmc, AT91_PMC_USB, tmp); + + return 0; +} + +static const struct clk_ops at91sam9x5_usb_ops = { + .recalc_rate = at91sam9x5_clk_usb_recalc_rate, + .round_rate = at91sam9x5_clk_usb_round_rate, + .get_parent = at91sam9x5_clk_usb_get_parent, + .set_parent = at91sam9x5_clk_usb_set_parent, + .set_rate = at91sam9x5_clk_usb_set_rate, +}; + +static int at91sam9n12_clk_usb_enable(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + pmc_write(pmc, AT91_PMC_USB, + pmc_read(pmc, AT91_PMC_USB) | AT91_PMC_USBS); + return 0; +} + +static void at91sam9n12_clk_usb_disable(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + pmc_write(pmc, AT91_PMC_USB, + pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS); +} + +static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + return !!(pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS); +} + +static const struct clk_ops at91sam9n12_usb_ops = { + .enable = at91sam9n12_clk_usb_enable, + .disable = at91sam9n12_clk_usb_disable, + .is_enabled = at91sam9n12_clk_usb_is_enabled, + .recalc_rate = at91sam9x5_clk_usb_recalc_rate, + .round_rate = at91sam9x5_clk_usb_round_rate, + .set_rate = at91sam9x5_clk_usb_set_rate, +}; + +static struct clk * __init +at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, + const char **parent_names, u8 num_parents) +{ + struct at91sam9x5_clk_usb *usb; + struct clk *clk = NULL; + struct clk_init_data init; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91sam9x5_usb_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + usb->hw.init = &init; + usb->pmc = pmc; + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) + kfree(usb); + + return clk; +} + +static struct clk * __init +at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name, + const char *parent_name) +{ + struct at91sam9x5_clk_usb *usb; + struct clk *clk = NULL; + struct clk_init_data init; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91sam9n12_usb_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_GATE; + + usb->hw.init = &init; + usb->pmc = pmc; + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) + kfree(usb); + + return clk; +} + +static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + u32 tmp; + u8 usbdiv; + + tmp = pmc_read(pmc, AT91_CKGR_PLLBR); + usbdiv = (tmp & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; + if (usb->divisors[usbdiv]) + return parent_rate / usb->divisors[usbdiv]; + + return 0; +} + +static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + unsigned long bestrate = 0; + int bestdiff = -1; + unsigned long tmprate; + int tmpdiff; + int i = 0; + + for (i = 0; i < 4; i++) { + if (!usb->divisors[i]) + continue; + tmprate = *parent_rate / usb->divisors[i]; + if (tmprate < rate) + tmpdiff = rate - tmprate; + else + tmpdiff = tmprate - rate; + + if (bestdiff < 0 || bestdiff > tmpdiff) { + bestrate = tmprate; + bestdiff = tmpdiff; + } + + if (!bestdiff) + break; + } + + return bestrate; +} + +static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + int i; + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate) + return -EINVAL; + for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { + if (usb->divisors[i] == div) { + tmp = pmc_read(pmc, AT91_CKGR_PLLBR) & + ~AT91_PMC_USBDIV; + tmp |= i << RM9200_USB_DIV_SHIFT; + pmc_write(pmc, AT91_CKGR_PLLBR, tmp); + return 0; + } + } + + return -EINVAL; +} + +static const struct clk_ops at91rm9200_usb_ops = { + .recalc_rate = at91rm9200_clk_usb_recalc_rate, + .round_rate = at91rm9200_clk_usb_round_rate, + .set_rate = at91rm9200_clk_usb_set_rate, +}; + +static struct clk * __init +at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, + const char *parent_name, const u32 *divisors) +{ + struct at91rm9200_clk_usb *usb; + struct clk *clk = NULL; + struct clk_init_data init; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91rm9200_usb_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = 0; + + usb->hw.init = &init; + usb->pmc = pmc; + memcpy(usb->divisors, divisors, sizeof(usb->divisors)); + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) + kfree(usb); + + return clk; +} + +void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + int i; + int num_parents; + const char *parent_names[USB_SOURCE_MAX]; + const char *name = np->name; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > USB_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91sam9x5_clk_register_usb(pmc, name, parent_names, num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) + return; + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91sam9n12_clk_register_usb(pmc, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +void __init of_at91rm9200_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + u32 divisors[4] = {0, 0, 0, 0}; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) + return; + + of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4); + if (!divisors[0]) + return; + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91rm9200_clk_register_usb(pmc, name, parent_name, divisors); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 0f667fd4e7fa..4fba500dec38 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -299,6 +299,21 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9x5-clk-utmi", .data = of_at91sam9x5_clk_utmi_setup, }, +#endif + /* USB clock */ +#if defined(CONFIG_HAVE_AT91_USB_CLK) + { + .compatible = "atmel,at91rm9200-clk-usb", + .data = of_at91rm9200_clk_usb_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-usb", + .data = of_at91sam9x5_clk_usb_setup, + }, + { + .compatible = "atmel,at91sam9n12-clk-usb", + .data = of_at91sam9n12_clk_usb_setup, + }, #endif { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 8e18ab0d8e22..2483ddc0868b 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -99,4 +99,13 @@ extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, struct at91_pmc *pmc); #endif +#if defined(CONFIG_HAVE_AT91_USB_CLK) +extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + #endif /* __PMC_H_ */ -- cgit v1.2.3 From a9c0688fde53c0a44cd75e9fe33b16db73187ba8 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Oct 2013 13:27:06 +0200 Subject: clk: at91: add PMC smd clock This patch adds at91 smd (Soft Modem) clock implementation using common clk framework. Not used by any driver right now. Signed-off-by: Boris BREZILLON Acked-by: Mike Turquette Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 5 ++ drivers/clk/at91/Makefile | 1 + drivers/clk/at91/clk-smd.c | 171 +++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/at91/pmc.c | 7 ++ drivers/clk/at91/pmc.h | 5 ++ 5 files changed, 189 insertions(+) create mode 100644 drivers/clk/at91/clk-smd.c (limited to 'drivers') diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b76dc4c62af9..97033f792eea 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -39,6 +39,9 @@ config AT91_SAM9G45_RESET config AT91_SAM9_TIME bool +config HAVE_AT91_SMD + bool + config SOC_AT91SAM9 bool select AT91_SAM9_TIME @@ -85,6 +88,7 @@ config SOC_SAMA5D3 select HAVE_AT91_DBGU1 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. @@ -157,6 +161,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select AT91_USE_OLD_CLK select HAVE_AT91_UTMI + select HAVE_AT91_SMD select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 61db058be0c0..0e92b716f934 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -9,3 +9,4 @@ obj-y += clk-system.o clk-peripheral.o obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o +obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c new file mode 100644 index 000000000000..144d47ecfe63 --- /dev/null +++ b/drivers/clk/at91/clk-smd.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2013 Boris BREZILLON + * + * 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 "pmc.h" + +#define SMD_SOURCE_MAX 2 + +#define SMD_DIV_SHIFT 8 +#define SMD_MAX_DIV 0xf + +struct at91sam9x5_clk_smd { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_smd(hw) \ + container_of(hw, struct at91sam9x5_clk_smd, hw) + +static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 smddiv; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + + tmp = pmc_read(pmc, AT91_PMC_SMD); + smddiv = (tmp & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT; + return parent_rate / (smddiv + 1); +} + +static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate >= *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div > SMD_MAX_DIV) + return *parent_rate / (SMD_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate > rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + + if (index > 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMDS; + if (index) + tmp |= AT91_PMC_SMDS; + pmc_write(pmc, AT91_PMC_SMD, tmp); + return 0; +} + +static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + + return pmc_read(pmc, AT91_PMC_SMD) & AT91_PMC_SMDS; +} + +static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1)) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMD_DIV; + tmp |= (div - 1) << SMD_DIV_SHIFT; + pmc_write(pmc, AT91_PMC_SMD, tmp); + + return 0; +} + +static const struct clk_ops at91sam9x5_smd_ops = { + .recalc_rate = at91sam9x5_clk_smd_recalc_rate, + .round_rate = at91sam9x5_clk_smd_round_rate, + .get_parent = at91sam9x5_clk_smd_get_parent, + .set_parent = at91sam9x5_clk_smd_set_parent, + .set_rate = at91sam9x5_clk_smd_set_rate, +}; + +static struct clk * __init +at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, + const char **parent_names, u8 num_parents) +{ + struct at91sam9x5_clk_smd *smd; + struct clk *clk = NULL; + struct clk_init_data init; + + smd = kzalloc(sizeof(*smd), GFP_KERNEL); + if (!smd) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91sam9x5_smd_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + smd->hw.init = &init; + smd->pmc = pmc; + + clk = clk_register(NULL, &smd->hw); + if (IS_ERR(clk)) + kfree(smd); + + return clk; +} + +void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + int i; + int num_parents; + const char *parent_names[SMD_SOURCE_MAX]; + const char *name = np->name; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91sam9x5_clk_register_smd(pmc, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 4fba500dec38..7b9db603b936 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -314,6 +314,13 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9n12-clk-usb", .data = of_at91sam9n12_clk_usb_setup, }, +#endif + /* SMD clock */ +#if defined(CONFIG_HAVE_AT91_SMD) + { + .compatible = "atmel,at91sam9x5-clk-smd", + .data = of_at91sam9x5_clk_smd_setup, + }, #endif { /*sentinel*/ } }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 2483ddc0868b..ba8d14233f80 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -108,4 +108,9 @@ extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, struct at91_pmc *pmc); #endif +#if defined(CONFIG_HAVE_AT91_SMD) +extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + #endif /* __PMC_H_ */ -- cgit v1.2.3 From 6d16e9c301290268b92ce3d48114f982e9c4b00a Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Mon, 2 Dec 2013 23:19:24 +0800 Subject: HID: usbhid: fix sis quirk Since commit 765e5fbd merged the sis quirk, then USB_VENDOR_ID_SIS2_TOUCH remains undefined. Reported-by: Fengguang Wu Signed-off-by: Wanlong Gao Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 ++-- drivers/hid/hid-multitouch.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8c10f2742233..36cb475b1934 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1822,8 +1822,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index a2cedb8ae1c0..9ce8e8b757db 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1301,10 +1301,10 @@ static const struct hid_device_id mt_devices[] = { /* SiS panels */ { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, /* Stantum panels */ -- cgit v1.2.3 From cfb27d29b61cc32c0bb75f741aeabb9c6e6af742 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Mon, 2 Dec 2013 09:06:36 +0100 Subject: ath10k: fix multi BSSID with WPA on FW 10.1 FW 10.1 seems to require the default key index to be updated to point to group key after it is installed. Otherwise Txed frames are corrupted. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b70a3b2f9f46..7d3d3ac2343a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2717,6 +2717,44 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw, mutex_unlock(&ar->conf_mutex); } +static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, + struct ath10k_vif *arvif, + enum set_key_cmd cmd, + struct ieee80211_key_conf *key) +{ + u32 vdev_param = arvif->ar->wmi.vdev_param->def_keyid; + int ret; + + /* 10.1 firmware branch requires default key index to be set to group + * key index after installing it. Otherwise FW/HW Txes corrupted + * frames with multi-vif APs. This is not required for main firmware + * branch (e.g. 636). + * + * FIXME: This has been tested only in AP. It remains unknown if this + * is required for multi-vif STA interfaces on 10.1 */ + + if (arvif->vdev_type != WMI_VDEV_TYPE_AP) + return; + + if (key->cipher == WLAN_CIPHER_SUITE_WEP40) + return; + + if (key->cipher == WLAN_CIPHER_SUITE_WEP104) + return; + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) + return; + + if (cmd != SET_KEY) + return; + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + key->keyidx); + if (ret) + ath10k_warn("failed to set group key as default key: %d\n", + ret); +} + static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) @@ -2778,6 +2816,8 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, goto exit; } + ath10k_set_key_h_def_keyidx(ar, arvif, cmd, key); + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find(ar, arvif->vdev_id, peer_addr); if (peer && cmd == SET_KEY) -- cgit v1.2.3 From 84acfd4340f9c7cef7286eb9d539e78fb3a15292 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 29 Nov 2013 18:09:07 +0100 Subject: spi: omap-100k: remove pointless _remove function Commit [8074cf06: use devm_spi_register_master()] removed the last bit of omap1_spi100k_remove function that had side effects. After call to spi_unregister_master was removed, the function consisted of: 2. call to platform_get_drvdata whose return value was only used in: 2. call to spi_master_get_devdata whose return value was not used, 3. an if statement checking if zero was not zero, and 4. call to platform_get_resource whose return value was not used. Ah, yes, and of course, final return 0. ;) Since omap1_spi100k_remove no longer does anything, it can be safely removed. Signed-off-by: Michal Nazarewicz Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index b6ed82beb01d..0d32054bfc0d 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -470,31 +470,12 @@ err: return status; } -static int omap1_spi100k_remove(struct platform_device *pdev) -{ - struct spi_master *master; - struct omap1_spi100k *spi100k; - struct resource *r; - int status = 0; - - master = platform_get_drvdata(pdev); - spi100k = spi_master_get_devdata(master); - - if (status != 0) - return status; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - return 0; -} - static struct platform_driver omap1_spi100k_driver = { .driver = { .name = "omap1_spi100k", .owner = THIS_MODULE, }, .probe = omap1_spi100k_probe, - .remove = omap1_spi100k_remove, }; module_platform_driver(omap1_spi100k_driver); @@ -502,4 +483,3 @@ module_platform_driver(omap1_spi100k_driver); MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); MODULE_AUTHOR("Fabrice Crohas "); MODULE_LICENSE("GPL"); - -- cgit v1.2.3 From 561427f5ea106d57a8a84113c89ecf23a5c865bb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 30 Nov 2013 12:21:03 +0800 Subject: mfd: pcf50633: Correct device name for pcf50633 regulator Change the device name of the regulator function to the one chosen for MODULE_ALIAS. This fixes kernel auto-module loading for the regulator function. Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/mfd/pcf50633-core.c | 2 +- drivers/regulator/pcf50633-regulator.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 6841d6805fd6..41ab5e34d2ac 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -245,7 +245,7 @@ static int pcf50633_probe(struct i2c_client *client, for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { struct platform_device *pdev; - pdev = platform_device_alloc("pcf50633-regltr", i); + pdev = platform_device_alloc("pcf50633-regulator", i); if (!pdev) { dev_err(pcf->dev, "Cannot create regulator %d\n", i); continue; diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index d7da1c15a6da..134f90ec9ca1 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -105,7 +105,7 @@ static int pcf50633_regulator_probe(struct platform_device *pdev) static struct platform_driver pcf50633_regulator_driver = { .driver = { - .name = "pcf50633-regltr", + .name = "pcf50633-regulator", }, .probe = pcf50633_regulator_probe, }; -- cgit v1.2.3 From 96581132423d71195b49fa7286dc1c0663ce21b5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 23 Oct 2013 13:53:28 +0530 Subject: ath9k: Add WB335 PCI IDs Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/pci.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b5656fce4ff5..44761bbb2ad4 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -446,6 +446,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { 0x11AD, /* LITEON */ 0x0662), .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0036, + 0x11AD, /* LITEON */ + 0x0682), + .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0036, PCI_VENDOR_ID_AZWAVE, @@ -456,6 +461,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { PCI_VENDOR_ID_LENOVO, 0x3026), .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0036, + PCI_VENDOR_ID_LENOVO, + 0x4026), + .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0036, PCI_VENDOR_ID_HP, @@ -466,6 +476,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { PCI_VENDOR_ID_HP, 0x217F), .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0036, + PCI_VENDOR_ID_HP, + 0x2005), + .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0036, PCI_VENDOR_ID_DELL, @@ -545,6 +560,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { 0x185F, /* WNC */ 0x3027), .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0036, + 0x185F, /* WNC */ + 0xA120), + .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0036, + PCI_VENDOR_ID_FOXCONN, + 0xE07F), + .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, /* PCI-E AR9565 (WB335) */ { PCI_VDEVICE(ATHEROS, 0x0036), -- cgit v1.2.3 From 4dd3564030020f8beb8dc7bbfea05781648836d0 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 23 Oct 2013 14:26:04 +0530 Subject: ath9k: Identify Killer Wireless cards Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 3 +++ drivers/net/wireless/ath/ath9k/pci.c | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 60a5da53668f..9cf412c6c32c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -642,6 +642,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); #define ATH9K_PCI_AR9565_1ANT 0x0080 #define ATH9K_PCI_AR9565_2ANT 0x0100 #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 +#define ATH9K_PCI_KILLER 0x0400 /* * Default cache line size, in bytes. diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 710192ed27ed..6ef4c0635b3d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -589,6 +589,9 @@ static void ath9k_init_platform(struct ath_softc *sc) if (sc->driver_data & ATH9K_PCI_AR9565_2ANT) ath_info(common, "WB335 2-ANT card detected\n"); + if (sc->driver_data & ATH9K_PCI_KILLER) + ath_info(common, "Killer Wireless card detected\n"); + /* * Some WB335 cards do not support antenna diversity. Since * we use a hardcoded value for AR9565 instead of using the diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 44761bbb2ad4..e9a585758941 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -87,6 +87,19 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ + + /* Killer Wireless (3x3) */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0030, + 0x1A56, + 0x2000), + .driver_data = ATH9K_PCI_KILLER }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0030, + 0x1A56, + 0x2001), + .driver_data = ATH9K_PCI_KILLER }, + { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ /* PCI-E CUS198 */ @@ -354,6 +367,13 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { 0x1783), .driver_data = ATH9K_PCI_WOW }, + /* Killer Wireless (2x2) */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0030, + 0x1A56, + 0x2003), + .driver_data = ATH9K_PCI_KILLER }, + { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ -- cgit v1.2.3 From ef6b19e40f525777a0052956bf7d9a1985f74993 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 24 Oct 2013 12:04:39 +0530 Subject: ath9k: Fix TX99 config option usage Use CONFIG_ATH9K_TX99 to properly enclose the tx99 code and make sure that it is not compiled as part of the driver when it is not selected. Move the tx99 code to a new file tx99.c and also add ATH9K_DEBUGFS as a dependency in Kconfig. This reduces the module size on platforms like OpenWrt where ATH9K_DEBUGFS is selected, but TX99 might be disabled. Cc: Luis R. Rodriguez Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 2 +- drivers/net/wireless/ath/ath9k/Makefile | 4 +- drivers/net/wireless/ath/ath9k/ath9k.h | 20 ++- drivers/net/wireless/ath/ath9k/debug.c | 115 +------------- drivers/net/wireless/ath/ath9k/main.c | 130 +--------------- drivers/net/wireless/ath/ath9k/tx99.c | 263 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 4 + 7 files changed, 290 insertions(+), 248 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/tx99.c (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 32f139e2e897..3ffa4ea8fcbc 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -86,7 +86,7 @@ config ATH9K_DFS_CERTIFIED config ATH9K_TX99 bool "Atheros ath9k TX99 testing support" - depends on CFG80211_CERTIFICATION_ONUS + depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS default n ---help--- Say N. This should only be enabled on systems undergoing diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 6205ef5a9321..f86a261e708a 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -13,9 +13,9 @@ ath9k-$(CONFIG_ATH9K_PCI) += pci.o ath9k-$(CONFIG_ATH9K_AHB) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o -ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ - dfs.o +ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o ath9k-$(CONFIG_PM_SLEEP) += wow.o +ath9k-$(CONFIG_ATH9K_TX99) += tx99.o obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 9cf412c6c32c..b39ffac3b93a 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -948,10 +948,25 @@ struct fft_sample_ht20_40 { u8 data[SPECTRAL_HT20_40_NUM_BINS]; } __packed; -int ath9k_tx99_init(struct ath_softc *sc); -void ath9k_tx99_deinit(struct ath_softc *sc); +/********/ +/* TX99 */ +/********/ + +#ifdef CONFIG_ATH9K_TX99 +void ath9k_tx99_init_debug(struct ath_softc *sc); int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, struct ath_tx_control *txctl); +#else +static inline void ath9k_tx99_init_debug(struct ath_softc *sc) +{ +} +static inline int ath9k_tx99_send(struct ath_softc *sc, + struct sk_buff *skb, + struct ath_tx_control *txctl) +{ + return 0; +} +#endif /* CONFIG_ATH9K_TX99 */ void ath9k_tasklet(unsigned long data); int ath_cabq_update(struct ath_softc *); @@ -968,6 +983,7 @@ extern bool is_ath9k_unloaded; u8 ath9k_parse_mpdudensity(u8 mpdudensity); irqreturn_t ath_isr(int irq, void *dev); +int ath_reset(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 83a2c59f680b..2f7dccfdb727 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1778,111 +1778,6 @@ void ath9k_deinit_debug(struct ath_softc *sc) } } -static ssize_t read_file_tx99(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[3]; - unsigned int len; - - len = sprintf(buf, "%d\n", sc->tx99_state); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - char buf[32]; - bool start; - ssize_t len; - int r; - - if (sc->nvifs > 1) - return -EOPNOTSUPP; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - if (strtobool(buf, &start)) - return -EINVAL; - - if (start == sc->tx99_state) { - if (!start) - return count; - ath_dbg(common, XMIT, "Resetting TX99\n"); - ath9k_tx99_deinit(sc); - } - - if (!start) { - ath9k_tx99_deinit(sc); - return count; - } - - r = ath9k_tx99_init(sc); - if (r) - return r; - - return count; -} - -static const struct file_operations fops_tx99 = { - .read = read_file_tx99, - .write = write_file_tx99, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_tx99_power(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[32]; - unsigned int len; - - len = sprintf(buf, "%d (%d dBm)\n", - sc->tx99_power, - sc->tx99_power / 2); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_tx99_power(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - int r; - u8 tx_power; - - r = kstrtou8_from_user(user_buf, count, 0, &tx_power); - if (r) - return r; - - if (tx_power > MAX_RATE_POWER) - return -EINVAL; - - sc->tx99_power = tx_power; - - ath9k_ps_wakeup(sc); - ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); - ath9k_ps_restore(sc); - - return count; -} - -static const struct file_operations fops_tx99_power = { - .read = read_file_tx99_power, - .write = write_file_tx99_power, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -1899,6 +1794,7 @@ int ath9k_init_debug(struct ath_hw *ah) #endif ath9k_dfs_init_debug(sc); + ath9k_tx99_init_debug(sc); debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dma); @@ -1974,15 +1870,6 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_btcoex); #endif - if (config_enabled(CONFIG_ATH9K_TX99) && - AR_SREV_9300_20_OR_LATER(ah)) { - debugfs_create_file("tx99", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, - &fops_tx99); - debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, - &fops_tx99_power); - } return 0; } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 74f452c7b166..3d1739864350 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -627,7 +627,7 @@ chip_reset: #undef SCHED_INTR } -static int ath_reset(struct ath_softc *sc) +int ath_reset(struct ath_softc *sc) { int r; @@ -2373,134 +2373,6 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, sc->csa_vif = vif; } -static void ath9k_tx99_stop(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - - ath_drain_all_txq(sc); - ath_startrecv(sc); - - ath9k_hw_set_interrupts(ah); - ath9k_hw_enable_interrupts(ah); - - ieee80211_wake_queues(sc->hw); - - kfree_skb(sc->tx99_skb); - sc->tx99_skb = NULL; - sc->tx99_state = false; - - ath9k_hw_tx99_stop(sc->sc_ah); - ath_dbg(common, XMIT, "TX99 stopped\n"); -} - -static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) -{ - static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, - 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, - 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, - 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, - 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, - 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, - 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, - 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; - u32 len = 1200; - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *tx_info; - struct sk_buff *skb; - - skb = alloc_skb(len, GFP_KERNEL); - if (!skb) - return NULL; - - skb_put(skb, len); - - memset(skb->data, 0, len); - - hdr = (struct ieee80211_hdr *)skb->data; - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); - hdr->duration_id = 0; - - memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); - memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); - memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); - - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - - tx_info = IEEE80211_SKB_CB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->band = hw->conf.chandef.chan->band; - tx_info->flags = IEEE80211_TX_CTL_NO_ACK; - tx_info->control.vif = sc->tx99_vif; - - memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); - - return skb; -} - -void ath9k_tx99_deinit(struct ath_softc *sc) -{ - ath_reset(sc); - - ath9k_ps_wakeup(sc); - ath9k_tx99_stop(sc); - ath9k_ps_restore(sc); -} - -int ath9k_tx99_init(struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath_tx_control txctl; - int r; - - if (sc->sc_flags & SC_OP_INVALID) { - ath_err(common, - "driver is in invalid state unable to use TX99"); - return -EINVAL; - } - - sc->tx99_skb = ath9k_build_tx99_skb(sc); - if (!sc->tx99_skb) - return -ENOMEM; - - memset(&txctl, 0, sizeof(txctl)); - txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; - - ath_reset(sc); - - ath9k_ps_wakeup(sc); - - ath9k_hw_disable_interrupts(ah); - atomic_set(&ah->intr_ref_cnt, -1); - ath_drain_all_txq(sc); - ath_stoprecv(sc); - - sc->tx99_state = true; - - ieee80211_stop_queues(hw); - - if (sc->tx99_power == MAX_RATE_POWER + 1) - sc->tx99_power = MAX_RATE_POWER; - - ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); - r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); - if (r) { - ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); - return r; - } - - ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", - sc->tx99_power, - sc->tx99_power / 2); - - /* We leave the harware awake as it will be chugging on */ - - return 0; -} - struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c new file mode 100644 index 000000000000..6668197c277c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ath9k.h" + +static void ath9k_tx99_stop(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + + ath_drain_all_txq(sc); + ath_startrecv(sc); + + ath9k_hw_set_interrupts(ah); + ath9k_hw_enable_interrupts(ah); + + ieee80211_wake_queues(sc->hw); + + kfree_skb(sc->tx99_skb); + sc->tx99_skb = NULL; + sc->tx99_state = false; + + ath9k_hw_tx99_stop(sc->sc_ah); + ath_dbg(common, XMIT, "TX99 stopped\n"); +} + +static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) +{ + static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, + 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, + 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, + 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, + 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, + 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, + 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, + 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; + u32 len = 1200; + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *tx_info; + struct sk_buff *skb; + + skb = alloc_skb(len, GFP_KERNEL); + if (!skb) + return NULL; + + skb_put(skb, len); + + memset(skb->data, 0, len); + + hdr = (struct ieee80211_hdr *)skb->data; + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); + hdr->duration_id = 0; + + memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); + memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); + memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); + + hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); + + tx_info = IEEE80211_SKB_CB(skb); + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->band = hw->conf.chandef.chan->band; + tx_info->flags = IEEE80211_TX_CTL_NO_ACK; + tx_info->control.vif = sc->tx99_vif; + + memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); + + return skb; +} + +static void ath9k_tx99_deinit(struct ath_softc *sc) +{ + ath_reset(sc); + + ath9k_ps_wakeup(sc); + ath9k_tx99_stop(sc); + ath9k_ps_restore(sc); +} + +static int ath9k_tx99_init(struct ath_softc *sc) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_tx_control txctl; + int r; + + if (sc->sc_flags & SC_OP_INVALID) { + ath_err(common, + "driver is in invalid state unable to use TX99"); + return -EINVAL; + } + + sc->tx99_skb = ath9k_build_tx99_skb(sc); + if (!sc->tx99_skb) + return -ENOMEM; + + memset(&txctl, 0, sizeof(txctl)); + txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; + + ath_reset(sc); + + ath9k_ps_wakeup(sc); + + ath9k_hw_disable_interrupts(ah); + atomic_set(&ah->intr_ref_cnt, -1); + ath_drain_all_txq(sc); + ath_stoprecv(sc); + + sc->tx99_state = true; + + ieee80211_stop_queues(hw); + + if (sc->tx99_power == MAX_RATE_POWER + 1) + sc->tx99_power = MAX_RATE_POWER; + + ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); + r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); + if (r) { + ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); + return r; + } + + ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", + sc->tx99_power, + sc->tx99_power / 2); + + /* We leave the harware awake as it will be chugging on */ + + return 0; +} + +static ssize_t read_file_tx99(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[3]; + unsigned int len; + + len = sprintf(buf, "%d\n", sc->tx99_state); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + char buf[32]; + bool start; + ssize_t len; + int r; + + if (sc->nvifs > 1) + return -EOPNOTSUPP; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + if (strtobool(buf, &start)) + return -EINVAL; + + if (start == sc->tx99_state) { + if (!start) + return count; + ath_dbg(common, XMIT, "Resetting TX99\n"); + ath9k_tx99_deinit(sc); + } + + if (!start) { + ath9k_tx99_deinit(sc); + return count; + } + + r = ath9k_tx99_init(sc); + if (r) + return r; + + return count; +} + +static const struct file_operations fops_tx99 = { + .read = read_file_tx99, + .write = write_file_tx99, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_tx99_power(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%d (%d dBm)\n", + sc->tx99_power, + sc->tx99_power / 2); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_tx99_power(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + int r; + u8 tx_power; + + r = kstrtou8_from_user(user_buf, count, 0, &tx_power); + if (r) + return r; + + if (tx_power > MAX_RATE_POWER) + return -EINVAL; + + sc->tx99_power = tx_power; + + ath9k_ps_wakeup(sc); + ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); + ath9k_ps_restore(sc); + + return count; +} + +static const struct file_operations fops_tx99_power = { + .read = read_file_tx99_power, + .write = write_file_tx99_power, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +void ath9k_tx99_init_debug(struct ath_softc *sc) +{ + if (!AR_SREV_9300_20_OR_LATER(sc->sc_ah)) + return; + + debugfs_create_file("tx99", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, + &fops_tx99); + debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, + &fops_tx99_power); +} diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 09cdbcd09739..95f6c5a8ee12 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2749,6 +2749,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) } } +#ifdef CONFIG_ATH9K_TX99 + int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, struct ath_tx_control *txctl) { @@ -2791,3 +2793,5 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, return 0; } + +#endif /* CONFIG_ATH9K_TX99 */ -- cgit v1.2.3 From 9c9cb10fcb500e52097f2535011cd5cf87b93f21 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 28 Oct 2013 11:47:43 +0530 Subject: ath9k: Fix wow.c compilation The HW routines to set various WoW registers are present in wow.c. For some reason, it has been compiled as part of the main ath9k.ko module all this time, when it should really be part of ath9k_hw.ko. This patch renames the file to ar9003_wow.ko and adds it to ath9k_hw.ko. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 3 +- drivers/net/wireless/ath/ath9k/ar9003_wow.c | 422 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/wow.c | 422 ---------------------------- 3 files changed, 424 insertions(+), 423 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_wow.c delete mode 100644 drivers/net/wireless/ath/ath9k/wow.c (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index f86a261e708a..796686a65b4c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -14,7 +14,6 @@ ath9k-$(CONFIG_ATH9K_AHB) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o -ath9k-$(CONFIG_PM_SLEEP) += wow.o ath9k-$(CONFIG_ATH9K_TX99) += tx99.o obj-$(CONFIG_ATH9K) += ath9k.o @@ -41,6 +40,8 @@ ath9k_hw-y:= \ ar9003_eeprom.o \ ar9003_paprd.o +ath9k_hw-$(CONFIG_PM_SLEEP) += ar9003_wow.o + ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ ar9003_mci.o obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c new file mode 100644 index 000000000000..81c88dd606dc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "ath9k.h" +#include "reg.h" +#include "hw-ops.h" + +const char *ath9k_hw_wow_event_to_string(u32 wow_event) +{ + if (wow_event & AH_WOW_MAGIC_PATTERN_EN) + return "Magic pattern"; + if (wow_event & AH_WOW_USER_PATTERN_EN) + return "User pattern"; + if (wow_event & AH_WOW_LINK_CHANGE) + return "Link change"; + if (wow_event & AH_WOW_BEACON_MISS) + return "Beacon miss"; + + return "unknown reason"; +} +EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); + +static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + + /* set rx disable bit */ + REG_WRITE(ah, AR_CR, AR_CR_RXD); + + if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { + ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", + REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); + return; + } + + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); +} + +static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN]; + u32 ctl[13] = {0}; + u32 data_word[KAL_NUM_DATA_WORDS]; + u8 i; + u32 wow_ka_data_word0; + + memcpy(sta_mac_addr, common->macaddr, ETH_ALEN); + memcpy(ap_mac_addr, common->curbssid, ETH_ALEN); + + /* set the transmit buffer */ + ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); + ctl[1] = 0; + ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ + ctl[4] = 0; + ctl[7] = (ah->txchainmask) << 2; + ctl[2] = 0xf << 16; /* tx_tries 0 */ + + for (i = 0; i < KAL_NUM_DESC_WORDS; i++) + REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); + + REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); + + data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | + (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); + data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | + (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); + data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) | + (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); + data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) | + (sta_mac_addr[3] << 8) | (sta_mac_addr[2]); + data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | + (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); + data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); + + if (AR_SREV_9462_20(ah)) { + /* AR9462 2.0 has an extra descriptor word (time based + * discard) compared to other chips */ + REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); + wow_ka_data_word0 = AR_WOW_TXBUF(13); + } else { + wow_ka_data_word0 = AR_WOW_TXBUF(12); + } + + for (i = 0; i < KAL_NUM_DATA_WORDS; i++) + REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]); + +} + +void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, + u8 *user_mask, int pattern_count, + int pattern_len) +{ + int i; + u32 pattern_val, mask_val; + u32 set, clr; + + /* FIXME: should check count by querying the hardware capability */ + if (pattern_count >= MAX_NUM_PATTERN) + return; + + REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); + + /* set the registers for pattern */ + for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { + memcpy(&pattern_val, user_pattern, 4); + REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), + pattern_val); + user_pattern += 4; + } + + /* set the registers for mask */ + for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { + memcpy(&mask_val, user_mask, 4); + REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); + user_mask += 4; + } + + /* set the pattern length to be matched + * + * AR_WOW_LENGTH1_REG1 + * bit 31:24 pattern 0 length + * bit 23:16 pattern 1 length + * bit 15:8 pattern 2 length + * bit 7:0 pattern 3 length + * + * AR_WOW_LENGTH1_REG2 + * bit 31:24 pattern 4 length + * bit 23:16 pattern 5 length + * bit 15:8 pattern 6 length + * bit 7:0 pattern 7 length + * + * the below logic writes out the new + * pattern length for the corresponding + * pattern_count, while masking out the + * other fields + */ + + ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); + + if (pattern_count < 4) { + /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ + set = (pattern_len & AR_WOW_LENGTH_MAX) << + AR_WOW_LEN1_SHIFT(pattern_count); + clr = AR_WOW_LENGTH1_MASK(pattern_count); + REG_RMW(ah, AR_WOW_LENGTH1, set, clr); + } else { + /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ + set = (pattern_len & AR_WOW_LENGTH_MAX) << + AR_WOW_LEN2_SHIFT(pattern_count); + clr = AR_WOW_LENGTH2_MASK(pattern_count); + REG_RMW(ah, AR_WOW_LENGTH2, set, clr); + } + +} +EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); + +u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) +{ + u32 wow_status = 0; + u32 val = 0, rval; + + /* + * read the WoW status register to know + * the wakeup reason + */ + rval = REG_READ(ah, AR_WOW_PATTERN); + val = AR_WOW_STATUS(rval); + + /* + * mask only the WoW events that we have enabled. Sometimes + * we have spurious WoW events from the AR_WOW_PATTERN + * register. This mask will clean it up. + */ + + val &= ah->wow_event_mask; + + if (val) { + if (val & AR_WOW_MAGIC_PAT_FOUND) + wow_status |= AH_WOW_MAGIC_PATTERN_EN; + if (AR_WOW_PATTERN_FOUND(val)) + wow_status |= AH_WOW_USER_PATTERN_EN; + if (val & AR_WOW_KEEP_ALIVE_FAIL) + wow_status |= AH_WOW_LINK_CHANGE; + if (val & AR_WOW_BEACON_FAIL) + wow_status |= AH_WOW_BEACON_MISS; + } + + /* + * set and clear WOW_PME_CLEAR registers for the chip to + * generate next wow signal. + * disable D3 before accessing other registers ? + */ + + /* do we need to check the bit value 0x01000000 (7-10) ?? */ + REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR, + AR_PMCTRL_PWR_STATE_D1D3); + + /* + * clear all events + */ + REG_WRITE(ah, AR_WOW_PATTERN, + AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); + + /* + * restore the beacon threshold to init value + */ + REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); + + /* + * Restore the way the PCI-E reset, Power-On-Reset, external + * PCIE_POR_SHORT pins are tied to its original value. + * Previously just before WoW sleep, we untie the PCI-E + * reset to our Chip's Power On Reset so that any PCI-E + * reset from the bus will not reset our chip + */ + if (ah->is_pciexpress) + ath9k_hw_configpcipowersave(ah, false); + + ah->wow_event_mask = 0; + + return wow_status; +} +EXPORT_SYMBOL(ath9k_hw_wow_wakeup); + +void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) +{ + u32 wow_event_mask; + u32 set, clr; + + /* + * wow_event_mask is a mask to the AR_WOW_PATTERN register to + * indicate which WoW events we have enabled. The WoW events + * are from the 'pattern_enable' in this function and + * 'pattern_count' of ath9k_hw_wow_apply_pattern() + */ + wow_event_mask = ah->wow_event_mask; + + /* + * Untie Power-on-Reset from the PCI-E-Reset. When we are in + * WOW sleep, we do want the Reset from the PCI-E to disturb + * our hw state + */ + if (ah->is_pciexpress) { + /* + * we need to untie the internal POR (power-on-reset) + * to the external PCI-E reset. We also need to tie + * the PCI-E Phy reset to the PCI-E reset. + */ + set = AR_WA_RESET_EN | AR_WA_POR_SHORT; + clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; + REG_RMW(ah, AR_WA, set, clr); + } + + /* + * set the power states appropriately and enable PME + */ + set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | + AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; + + /* + * set and clear WOW_PME_CLEAR registers for the chip + * to generate next wow signal. + */ + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); + clr = AR_PMCTRL_WOW_PME_CLR; + REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); + + /* + * Setup for: + * - beacon misses + * - magic pattern + * - keep alive timeout + * - pattern matching + */ + + /* + * Program default values for pattern backoff, aifs/slot/KAL count, + * beacon miss timeout, KAL timeout, etc. + */ + set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); + REG_SET_BIT(ah, AR_WOW_PATTERN, set); + + set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | + AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | + AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); + REG_SET_BIT(ah, AR_WOW_COUNT, set); + + if (pattern_enable & AH_WOW_BEACON_MISS) + set = AR_WOW_BEACON_TIMO; + /* We are not using beacon miss, program a large value */ + else + set = AR_WOW_BEACON_TIMO_MAX; + + REG_WRITE(ah, AR_WOW_BCN_TIMO, set); + + /* + * Keep alive timo in ms except AR9280 + */ + if (!pattern_enable) + set = AR_WOW_KEEP_ALIVE_NEVER; + else + set = KAL_TIMEOUT * 32; + + REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); + + /* + * Keep alive delay in us. based on 'power on clock', + * therefore in usec + */ + set = KAL_DELAY * 1000; + REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); + + /* + * Create keep alive pattern to respond to beacons + */ + ath9k_wow_create_keep_alive_pattern(ah); + + /* + * Configure MAC WoW Registers + */ + set = 0; + /* Send keep alive timeouts anyway */ + clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; + + if (pattern_enable & AH_WOW_LINK_CHANGE) + wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; + else + set = AR_WOW_KEEP_ALIVE_FAIL_DIS; + + set = AR_WOW_KEEP_ALIVE_FAIL_DIS; + REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); + + /* + * we are relying on a bmiss failure. ensure we have + * enough threshold to prevent false positives + */ + REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, + AR_WOW_BMISSTHRESHOLD); + + set = 0; + clr = 0; + + if (pattern_enable & AH_WOW_BEACON_MISS) { + set = AR_WOW_BEACON_FAIL_EN; + wow_event_mask |= AR_WOW_BEACON_FAIL; + } else { + clr = AR_WOW_BEACON_FAIL_EN; + } + + REG_RMW(ah, AR_WOW_BCN_EN, set, clr); + + set = 0; + clr = 0; + /* + * Enable the magic packet registers + */ + if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { + set = AR_WOW_MAGIC_EN; + wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; + } else { + clr = AR_WOW_MAGIC_EN; + } + set |= AR_WOW_MAC_INTR_EN; + REG_RMW(ah, AR_WOW_PATTERN, set, clr); + + REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, + AR_WOW_PATTERN_SUPPORTED); + + /* + * Set the power states appropriately and enable PME + */ + clr = 0; + set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | + AR_PMCTRL_PWR_PM_CTRL_ENA; + + clr = AR_PCIE_PM_CTRL_ENA; + REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); + + /* + * this is needed to prevent the chip waking up + * the host within 3-4 seconds with certain + * platform/BIOS. The fix is to enable + * D1 & D3 to match original definition and + * also match the OTP value. Anyway this + * is more related to SW WOW. + */ + clr = AR_PMCTRL_PWR_STATE_D1D3; + REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); + + set = AR_PMCTRL_PWR_STATE_D1D3_REAL; + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); + + REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); + + /* to bring down WOW power low margin */ + set = BIT(13); + REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); + /* HW WoW */ + clr = BIT(5); + REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); + + ath9k_hw_set_powermode_wow_sleep(ah); + ah->wow_event_mask = wow_event_mask; +} +EXPORT_SYMBOL(ath9k_hw_wow_enable); diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c deleted file mode 100644 index 81c88dd606dc..000000000000 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "ath9k.h" -#include "reg.h" -#include "hw-ops.h" - -const char *ath9k_hw_wow_event_to_string(u32 wow_event) -{ - if (wow_event & AH_WOW_MAGIC_PATTERN_EN) - return "Magic pattern"; - if (wow_event & AH_WOW_USER_PATTERN_EN) - return "User pattern"; - if (wow_event & AH_WOW_LINK_CHANGE) - return "Link change"; - if (wow_event & AH_WOW_BEACON_MISS) - return "Beacon miss"; - - return "unknown reason"; -} -EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); - -static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - - REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - - /* set rx disable bit */ - REG_WRITE(ah, AR_CR, AR_CR_RXD); - - if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { - ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", - REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); - return; - } - - REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); -} - -static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN]; - u32 ctl[13] = {0}; - u32 data_word[KAL_NUM_DATA_WORDS]; - u8 i; - u32 wow_ka_data_word0; - - memcpy(sta_mac_addr, common->macaddr, ETH_ALEN); - memcpy(ap_mac_addr, common->curbssid, ETH_ALEN); - - /* set the transmit buffer */ - ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); - ctl[1] = 0; - ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ - ctl[4] = 0; - ctl[7] = (ah->txchainmask) << 2; - ctl[2] = 0xf << 16; /* tx_tries 0 */ - - for (i = 0; i < KAL_NUM_DESC_WORDS; i++) - REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); - - REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); - - data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | - (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); - data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | - (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); - data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) | - (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); - data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) | - (sta_mac_addr[3] << 8) | (sta_mac_addr[2]); - data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | - (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); - data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); - - if (AR_SREV_9462_20(ah)) { - /* AR9462 2.0 has an extra descriptor word (time based - * discard) compared to other chips */ - REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); - wow_ka_data_word0 = AR_WOW_TXBUF(13); - } else { - wow_ka_data_word0 = AR_WOW_TXBUF(12); - } - - for (i = 0; i < KAL_NUM_DATA_WORDS; i++) - REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]); - -} - -void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, - u8 *user_mask, int pattern_count, - int pattern_len) -{ - int i; - u32 pattern_val, mask_val; - u32 set, clr; - - /* FIXME: should check count by querying the hardware capability */ - if (pattern_count >= MAX_NUM_PATTERN) - return; - - REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); - - /* set the registers for pattern */ - for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { - memcpy(&pattern_val, user_pattern, 4); - REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), - pattern_val); - user_pattern += 4; - } - - /* set the registers for mask */ - for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { - memcpy(&mask_val, user_mask, 4); - REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); - user_mask += 4; - } - - /* set the pattern length to be matched - * - * AR_WOW_LENGTH1_REG1 - * bit 31:24 pattern 0 length - * bit 23:16 pattern 1 length - * bit 15:8 pattern 2 length - * bit 7:0 pattern 3 length - * - * AR_WOW_LENGTH1_REG2 - * bit 31:24 pattern 4 length - * bit 23:16 pattern 5 length - * bit 15:8 pattern 6 length - * bit 7:0 pattern 7 length - * - * the below logic writes out the new - * pattern length for the corresponding - * pattern_count, while masking out the - * other fields - */ - - ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); - - if (pattern_count < 4) { - /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ - set = (pattern_len & AR_WOW_LENGTH_MAX) << - AR_WOW_LEN1_SHIFT(pattern_count); - clr = AR_WOW_LENGTH1_MASK(pattern_count); - REG_RMW(ah, AR_WOW_LENGTH1, set, clr); - } else { - /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ - set = (pattern_len & AR_WOW_LENGTH_MAX) << - AR_WOW_LEN2_SHIFT(pattern_count); - clr = AR_WOW_LENGTH2_MASK(pattern_count); - REG_RMW(ah, AR_WOW_LENGTH2, set, clr); - } - -} -EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); - -u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) -{ - u32 wow_status = 0; - u32 val = 0, rval; - - /* - * read the WoW status register to know - * the wakeup reason - */ - rval = REG_READ(ah, AR_WOW_PATTERN); - val = AR_WOW_STATUS(rval); - - /* - * mask only the WoW events that we have enabled. Sometimes - * we have spurious WoW events from the AR_WOW_PATTERN - * register. This mask will clean it up. - */ - - val &= ah->wow_event_mask; - - if (val) { - if (val & AR_WOW_MAGIC_PAT_FOUND) - wow_status |= AH_WOW_MAGIC_PATTERN_EN; - if (AR_WOW_PATTERN_FOUND(val)) - wow_status |= AH_WOW_USER_PATTERN_EN; - if (val & AR_WOW_KEEP_ALIVE_FAIL) - wow_status |= AH_WOW_LINK_CHANGE; - if (val & AR_WOW_BEACON_FAIL) - wow_status |= AH_WOW_BEACON_MISS; - } - - /* - * set and clear WOW_PME_CLEAR registers for the chip to - * generate next wow signal. - * disable D3 before accessing other registers ? - */ - - /* do we need to check the bit value 0x01000000 (7-10) ?? */ - REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR, - AR_PMCTRL_PWR_STATE_D1D3); - - /* - * clear all events - */ - REG_WRITE(ah, AR_WOW_PATTERN, - AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); - - /* - * restore the beacon threshold to init value - */ - REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - - /* - * Restore the way the PCI-E reset, Power-On-Reset, external - * PCIE_POR_SHORT pins are tied to its original value. - * Previously just before WoW sleep, we untie the PCI-E - * reset to our Chip's Power On Reset so that any PCI-E - * reset from the bus will not reset our chip - */ - if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, false); - - ah->wow_event_mask = 0; - - return wow_status; -} -EXPORT_SYMBOL(ath9k_hw_wow_wakeup); - -void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) -{ - u32 wow_event_mask; - u32 set, clr; - - /* - * wow_event_mask is a mask to the AR_WOW_PATTERN register to - * indicate which WoW events we have enabled. The WoW events - * are from the 'pattern_enable' in this function and - * 'pattern_count' of ath9k_hw_wow_apply_pattern() - */ - wow_event_mask = ah->wow_event_mask; - - /* - * Untie Power-on-Reset from the PCI-E-Reset. When we are in - * WOW sleep, we do want the Reset from the PCI-E to disturb - * our hw state - */ - if (ah->is_pciexpress) { - /* - * we need to untie the internal POR (power-on-reset) - * to the external PCI-E reset. We also need to tie - * the PCI-E Phy reset to the PCI-E reset. - */ - set = AR_WA_RESET_EN | AR_WA_POR_SHORT; - clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; - REG_RMW(ah, AR_WA, set, clr); - } - - /* - * set the power states appropriately and enable PME - */ - set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | - AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; - - /* - * set and clear WOW_PME_CLEAR registers for the chip - * to generate next wow signal. - */ - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); - clr = AR_PMCTRL_WOW_PME_CLR; - REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); - - /* - * Setup for: - * - beacon misses - * - magic pattern - * - keep alive timeout - * - pattern matching - */ - - /* - * Program default values for pattern backoff, aifs/slot/KAL count, - * beacon miss timeout, KAL timeout, etc. - */ - set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); - REG_SET_BIT(ah, AR_WOW_PATTERN, set); - - set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | - AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | - AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); - REG_SET_BIT(ah, AR_WOW_COUNT, set); - - if (pattern_enable & AH_WOW_BEACON_MISS) - set = AR_WOW_BEACON_TIMO; - /* We are not using beacon miss, program a large value */ - else - set = AR_WOW_BEACON_TIMO_MAX; - - REG_WRITE(ah, AR_WOW_BCN_TIMO, set); - - /* - * Keep alive timo in ms except AR9280 - */ - if (!pattern_enable) - set = AR_WOW_KEEP_ALIVE_NEVER; - else - set = KAL_TIMEOUT * 32; - - REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); - - /* - * Keep alive delay in us. based on 'power on clock', - * therefore in usec - */ - set = KAL_DELAY * 1000; - REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); - - /* - * Create keep alive pattern to respond to beacons - */ - ath9k_wow_create_keep_alive_pattern(ah); - - /* - * Configure MAC WoW Registers - */ - set = 0; - /* Send keep alive timeouts anyway */ - clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; - - if (pattern_enable & AH_WOW_LINK_CHANGE) - wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; - else - set = AR_WOW_KEEP_ALIVE_FAIL_DIS; - - set = AR_WOW_KEEP_ALIVE_FAIL_DIS; - REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); - - /* - * we are relying on a bmiss failure. ensure we have - * enough threshold to prevent false positives - */ - REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, - AR_WOW_BMISSTHRESHOLD); - - set = 0; - clr = 0; - - if (pattern_enable & AH_WOW_BEACON_MISS) { - set = AR_WOW_BEACON_FAIL_EN; - wow_event_mask |= AR_WOW_BEACON_FAIL; - } else { - clr = AR_WOW_BEACON_FAIL_EN; - } - - REG_RMW(ah, AR_WOW_BCN_EN, set, clr); - - set = 0; - clr = 0; - /* - * Enable the magic packet registers - */ - if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { - set = AR_WOW_MAGIC_EN; - wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; - } else { - clr = AR_WOW_MAGIC_EN; - } - set |= AR_WOW_MAC_INTR_EN; - REG_RMW(ah, AR_WOW_PATTERN, set, clr); - - REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, - AR_WOW_PATTERN_SUPPORTED); - - /* - * Set the power states appropriately and enable PME - */ - clr = 0; - set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | - AR_PMCTRL_PWR_PM_CTRL_ENA; - - clr = AR_PCIE_PM_CTRL_ENA; - REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); - - /* - * this is needed to prevent the chip waking up - * the host within 3-4 seconds with certain - * platform/BIOS. The fix is to enable - * D1 & D3 to match original definition and - * also match the OTP value. Anyway this - * is more related to SW WOW. - */ - clr = AR_PMCTRL_PWR_STATE_D1D3; - REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); - - set = AR_PMCTRL_PWR_STATE_D1D3_REAL; - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); - - REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); - - /* to bring down WOW power low margin */ - set = BIT(13); - REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); - /* HW WoW */ - clr = BIT(5); - REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); - - ath9k_hw_set_powermode_wow_sleep(ah); - ah->wow_event_mask = wow_event_mask; -} -EXPORT_SYMBOL(ath9k_hw_wow_enable); -- cgit v1.2.3 From bb00b1f786efc4c38d8e1e3e0e1996a59277a90e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 28 Oct 2013 11:33:19 +0530 Subject: ath9k: Add a config option for WoW Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 3ffa4ea8fcbc..30d273c61bff 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -104,6 +104,14 @@ config ATH9K_TX99 be evaluated to meet the RF exposure limits set forth in the governmental SAR regulations. +config ATH9K_WOW + bool "Wake on Wireless LAN support (EXPERIMENTAL)" + depends on ATH9K && PM + default n + ---help--- + This option enables Wake on Wireless LAN support for certain cards. + Currently, AR9462 is supported. + config ATH9K_LEGACY_RATE_CONTROL bool "Atheros ath9k rate control" depends on ATH9K -- cgit v1.2.3 From e60001e7167536d99bb2026367751704c623f9f8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 28 Oct 2013 12:22:04 +0530 Subject: ath9k: Use CONFIG_ATH9K_WOW Move the WoW code to wow.c and compile it conditionally based on CONFIG_ATH9K_WOW. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 3 +- drivers/net/wireless/ath/ath9k/ath9k.h | 28 ++- drivers/net/wireless/ath/ath9k/hw.h | 4 +- drivers/net/wireless/ath/ath9k/init.c | 4 +- drivers/net/wireless/ath/ath9k/main.c | 338 +------------------------------ drivers/net/wireless/ath/ath9k/wow.c | 341 ++++++++++++++++++++++++++++++++ 6 files changed, 381 insertions(+), 337 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/wow.c (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 796686a65b4c..337c459eda28 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -15,6 +15,7 @@ ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o ath9k-$(CONFIG_ATH9K_TX99) += tx99.o +ath9k-$(CONFIG_ATH9K_WOW) += wow.o obj-$(CONFIG_ATH9K) += ath9k.o @@ -40,7 +41,7 @@ ath9k_hw-y:= \ ar9003_eeprom.o \ ar9003_paprd.o -ath9k_hw-$(CONFIG_PM_SLEEP) += ar9003_wow.o +ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ ar9003_mci.o diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b39ffac3b93a..9927dcaa5593 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -570,6 +570,30 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) } #endif +/************************/ +/* Wake on Wireless LAN */ +/************************/ + +#ifdef CONFIG_ATH9K_WOW +int ath9k_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan); +int ath9k_resume(struct ieee80211_hw *hw); +void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); +#else +static inline int ath9k_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + return 0; +} +static inline int ath9k_resume(struct ieee80211_hw *hw) +{ + return 0; +} +static inline void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ +} +#endif /* CONFIG_ATH9K_WOW */ + /*******************************/ /* Antenna diversity/combining */ /*******************************/ @@ -785,7 +809,7 @@ struct ath_softc { bool tx99_state; s16 tx99_power; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ATH9K_WOW atomic_t wow_got_bmiss_intr; atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ u32 wow_intr_before_sleep; @@ -984,6 +1008,8 @@ extern bool is_ath9k_unloaded; u8 ath9k_parse_mpdudensity(u8 mpdudensity); irqreturn_t ath_isr(int irq, void *dev); int ath_reset(struct ath_softc *sc); +void ath_cancel_work(struct ath_softc *sc); +void ath_restart_work(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops); void ath9k_deinit_device(struct ath_softc *sc); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a2c9a5dbac6b..ecc3a4efe18a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -921,7 +921,7 @@ struct ath_hw { /* Enterprise mode cap */ u32 ent_mode; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ATH9K_WOW u32 wow_event_mask; #endif bool is_clk_25mhz; @@ -1127,7 +1127,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ATH9K_WOW const char *ath9k_hw_wow_event_to_string(u32 wow_event); void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, u8 *user_mask, int pattern_count, diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 6ef4c0635b3d..cc23436e3401 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -876,7 +876,7 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; -#ifdef CONFIG_PM +#ifdef CONFIG_ATH9K_WOW static const struct wiphy_wowlan_support ath9k_wowlan_support = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, .n_patterns = MAX_NUM_USER_PATTERN, @@ -934,7 +934,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ATH9K_WOW if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && (sc->driver_data & ATH9K_PCI_WOW) && device_can_wakeup(sc->dev)) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3d1739864350..e54ffdd36e21 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -163,13 +163,13 @@ static void __ath_cancel_work(struct ath_softc *sc) #endif } -static void ath_cancel_work(struct ath_softc *sc) +void ath_cancel_work(struct ath_softc *sc) { __ath_cancel_work(sc); cancel_work_sync(&sc->hw_reset_work); } -static void ath_restart_work(struct ath_softc *sc) +void ath_restart_work(struct ath_softc *sc) { ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); @@ -579,7 +579,8 @@ irqreturn_t ath_isr(int irq, void *dev) goto chip_reset; } -#ifdef CONFIG_PM_SLEEP + +#ifdef CONFIG_ATH9K_WOW if (status & ATH9K_INT_BMISS) { if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { ath_dbg(common, ANY, "during WoW we got a BMISS\n"); @@ -588,6 +589,8 @@ irqreturn_t ath_isr(int irq, void *dev) } } #endif + + if (status & ATH9K_INT_SWBA) tasklet_schedule(&sc->bcon_tasklet); @@ -2021,333 +2024,6 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) return 0; } -#ifdef CONFIG_PM_SLEEP - -static void ath9k_wow_map_triggers(struct ath_softc *sc, - struct cfg80211_wowlan *wowlan, - u32 *wow_triggers) -{ - if (wowlan->disconnect) - *wow_triggers |= AH_WOW_LINK_CHANGE | - AH_WOW_BEACON_MISS; - if (wowlan->magic_pkt) - *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; - - if (wowlan->n_patterns) - *wow_triggers |= AH_WOW_USER_PATTERN_EN; - - sc->wow_enabled = *wow_triggers; - -} - -static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - int pattern_count = 0; - int i, byte_cnt; - u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; - u8 dis_deauth_mask[MAX_PATTERN_SIZE]; - - memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); - memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); - - /* - * Create Dissassociate / Deauthenticate packet filter - * - * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes - * +--------------+----------+---------+--------+--------+---- - * + Frame Control+ Duration + DA + SA + BSSID + - * +--------------+----------+---------+--------+--------+---- - * - * The above is the management frame format for disassociate/ - * deauthenticate pattern, from this we need to match the first byte - * of 'Frame Control' and DA, SA, and BSSID fields - * (skipping 2nd byte of FC and Duration feild. - * - * Disassociate pattern - * -------------------- - * Frame control = 00 00 1010 - * DA, SA, BSSID = x:x:x:x:x:x - * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x - * | x:x:x:x:x:x -- 22 bytes - * - * Deauthenticate pattern - * ---------------------- - * Frame control = 00 00 1100 - * DA, SA, BSSID = x:x:x:x:x:x - * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x - * | x:x:x:x:x:x -- 22 bytes - */ - - /* Create Disassociate Pattern first */ - - byte_cnt = 0; - - /* Fill out the mask with all FF's */ - - for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) - dis_deauth_mask[i] = 0xff; - - /* copy the first byte of frame control field */ - dis_deauth_pattern[byte_cnt] = 0xa0; - byte_cnt++; - - /* skip 2nd byte of frame control and Duration field */ - byte_cnt += 3; - - /* - * need not match the destination mac address, it can be a broadcast - * mac address or an unicast to this station - */ - byte_cnt += 6; - - /* copy the source mac address */ - memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); - - byte_cnt += 6; - - /* copy the bssid, its same as the source mac address */ - - memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); - - /* Create Disassociate pattern mask */ - - dis_deauth_mask[0] = 0xfe; - dis_deauth_mask[1] = 0x03; - dis_deauth_mask[2] = 0xc0; - - ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); - - ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, - pattern_count, byte_cnt); - - pattern_count++; - /* - * for de-authenticate pattern, only the first byte of the frame - * control field gets changed from 0xA0 to 0xC0 - */ - dis_deauth_pattern[0] = 0xC0; - - ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, - pattern_count, byte_cnt); - -} - -static void ath9k_wow_add_pattern(struct ath_softc *sc, - struct cfg80211_wowlan *wowlan) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_wow_pattern *wow_pattern = NULL; - struct cfg80211_pkt_pattern *patterns = wowlan->patterns; - int mask_len; - s8 i = 0; - - if (!wowlan->n_patterns) - return; - - /* - * Add the new user configured patterns - */ - for (i = 0; i < wowlan->n_patterns; i++) { - - wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); - - if (!wow_pattern) - return; - - /* - * TODO: convert the generic user space pattern to - * appropriate chip specific/802.11 pattern. - */ - - mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); - memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); - memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); - memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, - patterns[i].pattern_len); - memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); - wow_pattern->pattern_len = patterns[i].pattern_len; - - /* - * just need to take care of deauth and disssoc pattern, - * make sure we don't overwrite them. - */ - - ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, - wow_pattern->mask_bytes, - i + 2, - wow_pattern->pattern_len); - kfree(wow_pattern); - - } - -} - -static int ath9k_suspend(struct ieee80211_hw *hw, - struct cfg80211_wowlan *wowlan) -{ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - u32 wow_triggers_enabled = 0; - int ret = 0; - - mutex_lock(&sc->mutex); - - ath_cancel_work(sc); - ath_stop_ani(sc); - del_timer_sync(&sc->rx_poll_timer); - - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { - ath_dbg(common, ANY, "Device not present\n"); - ret = -EINVAL; - goto fail_wow; - } - - if (WARN_ON(!wowlan)) { - ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); - ret = -EINVAL; - goto fail_wow; - } - - if (!device_can_wakeup(sc->dev)) { - ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); - ret = 1; - goto fail_wow; - } - - /* - * none of the sta vifs are associated - * and we are not currently handling multivif - * cases, for instance we have to seperately - * configure 'keep alive frame' for each - * STA. - */ - - if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { - ath_dbg(common, WOW, "None of the STA vifs are associated\n"); - ret = 1; - goto fail_wow; - } - - if (sc->nvifs > 1) { - ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); - ret = 1; - goto fail_wow; - } - - ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); - - ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", - wow_triggers_enabled); - - ath9k_ps_wakeup(sc); - - ath9k_stop_btcoex(sc); - - /* - * Enable wake up on recieving disassoc/deauth - * frame by default. - */ - ath9k_wow_add_disassoc_deauth_pattern(sc); - - if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) - ath9k_wow_add_pattern(sc, wowlan); - - spin_lock_bh(&sc->sc_pcu_lock); - /* - * To avoid false wake, we enable beacon miss interrupt only - * when we go to sleep. We save the current interrupt mask - * so we can restore it after the system wakes up - */ - sc->wow_intr_before_sleep = ah->imask; - ah->imask &= ~ATH9K_INT_GLOBAL; - ath9k_hw_disable_interrupts(ah); - ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; - ath9k_hw_set_interrupts(ah); - ath9k_hw_enable_interrupts(ah); - - spin_unlock_bh(&sc->sc_pcu_lock); - - /* - * we can now sync irq and kill any running tasklets, since we already - * disabled interrupts and not holding a spin lock - */ - synchronize_irq(sc->irq); - tasklet_kill(&sc->intr_tq); - - ath9k_hw_wow_enable(ah, wow_triggers_enabled); - - ath9k_ps_restore(sc); - ath_dbg(common, ANY, "WoW enabled in ath9k\n"); - atomic_inc(&sc->wow_sleep_proc_intr); - -fail_wow: - mutex_unlock(&sc->mutex); - return ret; -} - -static int ath9k_resume(struct ieee80211_hw *hw) -{ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - u32 wow_status; - - mutex_lock(&sc->mutex); - - ath9k_ps_wakeup(sc); - - spin_lock_bh(&sc->sc_pcu_lock); - - ath9k_hw_disable_interrupts(ah); - ah->imask = sc->wow_intr_before_sleep; - ath9k_hw_set_interrupts(ah); - ath9k_hw_enable_interrupts(ah); - - spin_unlock_bh(&sc->sc_pcu_lock); - - wow_status = ath9k_hw_wow_wakeup(ah); - - if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { - /* - * some devices may not pick beacon miss - * as the reason they woke up so we add - * that here for that shortcoming. - */ - wow_status |= AH_WOW_BEACON_MISS; - atomic_dec(&sc->wow_got_bmiss_intr); - ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); - } - - atomic_dec(&sc->wow_sleep_proc_intr); - - if (wow_status) { - ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", - ath9k_hw_wow_event_to_string(wow_status), wow_status); - } - - ath_restart_work(sc); - ath9k_start_btcoex(sc); - - ath9k_ps_restore(sc); - mutex_unlock(&sc->mutex); - - return 0; -} - -static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) -{ - struct ath_softc *sc = hw->priv; - - mutex_lock(&sc->mutex); - device_init_wakeup(sc->dev, 1); - device_set_wakeup_enable(sc->dev, enabled); - mutex_unlock(&sc->mutex); -} - -#endif static void ath9k_sw_scan_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; @@ -2403,7 +2079,7 @@ struct ieee80211_ops ath9k_ops = { .set_antenna = ath9k_set_antenna, .get_antenna = ath9k_get_antenna, -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ATH9K_WOW .suspend = ath9k_suspend, .resume = ath9k_resume, .set_wakeup = ath9k_set_wakeup, diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c new file mode 100644 index 000000000000..e161bbc04dbc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/wow.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ath9k.h" + +static void ath9k_wow_map_triggers(struct ath_softc *sc, + struct cfg80211_wowlan *wowlan, + u32 *wow_triggers) +{ + if (wowlan->disconnect) + *wow_triggers |= AH_WOW_LINK_CHANGE | + AH_WOW_BEACON_MISS; + if (wowlan->magic_pkt) + *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; + + if (wowlan->n_patterns) + *wow_triggers |= AH_WOW_USER_PATTERN_EN; + + sc->wow_enabled = *wow_triggers; + +} + +static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + int pattern_count = 0; + int i, byte_cnt; + u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; + u8 dis_deauth_mask[MAX_PATTERN_SIZE]; + + memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); + memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); + + /* + * Create Dissassociate / Deauthenticate packet filter + * + * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes + * +--------------+----------+---------+--------+--------+---- + * + Frame Control+ Duration + DA + SA + BSSID + + * +--------------+----------+---------+--------+--------+---- + * + * The above is the management frame format for disassociate/ + * deauthenticate pattern, from this we need to match the first byte + * of 'Frame Control' and DA, SA, and BSSID fields + * (skipping 2nd byte of FC and Duration feild. + * + * Disassociate pattern + * -------------------- + * Frame control = 00 00 1010 + * DA, SA, BSSID = x:x:x:x:x:x + * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x + * | x:x:x:x:x:x -- 22 bytes + * + * Deauthenticate pattern + * ---------------------- + * Frame control = 00 00 1100 + * DA, SA, BSSID = x:x:x:x:x:x + * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x + * | x:x:x:x:x:x -- 22 bytes + */ + + /* Create Disassociate Pattern first */ + + byte_cnt = 0; + + /* Fill out the mask with all FF's */ + + for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) + dis_deauth_mask[i] = 0xff; + + /* copy the first byte of frame control field */ + dis_deauth_pattern[byte_cnt] = 0xa0; + byte_cnt++; + + /* skip 2nd byte of frame control and Duration field */ + byte_cnt += 3; + + /* + * need not match the destination mac address, it can be a broadcast + * mac address or an unicast to this station + */ + byte_cnt += 6; + + /* copy the source mac address */ + memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); + + byte_cnt += 6; + + /* copy the bssid, its same as the source mac address */ + + memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); + + /* Create Disassociate pattern mask */ + + dis_deauth_mask[0] = 0xfe; + dis_deauth_mask[1] = 0x03; + dis_deauth_mask[2] = 0xc0; + + ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); + + ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, + pattern_count, byte_cnt); + + pattern_count++; + /* + * for de-authenticate pattern, only the first byte of the frame + * control field gets changed from 0xA0 to 0xC0 + */ + dis_deauth_pattern[0] = 0xC0; + + ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, + pattern_count, byte_cnt); + +} + +static void ath9k_wow_add_pattern(struct ath_softc *sc, + struct cfg80211_wowlan *wowlan) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_wow_pattern *wow_pattern = NULL; + struct cfg80211_pkt_pattern *patterns = wowlan->patterns; + int mask_len; + s8 i = 0; + + if (!wowlan->n_patterns) + return; + + /* + * Add the new user configured patterns + */ + for (i = 0; i < wowlan->n_patterns; i++) { + + wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); + + if (!wow_pattern) + return; + + /* + * TODO: convert the generic user space pattern to + * appropriate chip specific/802.11 pattern. + */ + + mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); + memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); + memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); + memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, + patterns[i].pattern_len); + memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); + wow_pattern->pattern_len = patterns[i].pattern_len; + + /* + * just need to take care of deauth and disssoc pattern, + * make sure we don't overwrite them. + */ + + ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, + wow_pattern->mask_bytes, + i + 2, + wow_pattern->pattern_len); + kfree(wow_pattern); + + } + +} + +int ath9k_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + u32 wow_triggers_enabled = 0; + int ret = 0; + + mutex_lock(&sc->mutex); + + ath_cancel_work(sc); + ath_stop_ani(sc); + del_timer_sync(&sc->rx_poll_timer); + + if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { + ath_dbg(common, ANY, "Device not present\n"); + ret = -EINVAL; + goto fail_wow; + } + + if (WARN_ON(!wowlan)) { + ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); + ret = -EINVAL; + goto fail_wow; + } + + if (!device_can_wakeup(sc->dev)) { + ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); + ret = 1; + goto fail_wow; + } + + /* + * none of the sta vifs are associated + * and we are not currently handling multivif + * cases, for instance we have to seperately + * configure 'keep alive frame' for each + * STA. + */ + + if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { + ath_dbg(common, WOW, "None of the STA vifs are associated\n"); + ret = 1; + goto fail_wow; + } + + if (sc->nvifs > 1) { + ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); + ret = 1; + goto fail_wow; + } + + ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); + + ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", + wow_triggers_enabled); + + ath9k_ps_wakeup(sc); + + ath9k_stop_btcoex(sc); + + /* + * Enable wake up on recieving disassoc/deauth + * frame by default. + */ + ath9k_wow_add_disassoc_deauth_pattern(sc); + + if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) + ath9k_wow_add_pattern(sc, wowlan); + + spin_lock_bh(&sc->sc_pcu_lock); + /* + * To avoid false wake, we enable beacon miss interrupt only + * when we go to sleep. We save the current interrupt mask + * so we can restore it after the system wakes up + */ + sc->wow_intr_before_sleep = ah->imask; + ah->imask &= ~ATH9K_INT_GLOBAL; + ath9k_hw_disable_interrupts(ah); + ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; + ath9k_hw_set_interrupts(ah); + ath9k_hw_enable_interrupts(ah); + + spin_unlock_bh(&sc->sc_pcu_lock); + + /* + * we can now sync irq and kill any running tasklets, since we already + * disabled interrupts and not holding a spin lock + */ + synchronize_irq(sc->irq); + tasklet_kill(&sc->intr_tq); + + ath9k_hw_wow_enable(ah, wow_triggers_enabled); + + ath9k_ps_restore(sc); + ath_dbg(common, ANY, "WoW enabled in ath9k\n"); + atomic_inc(&sc->wow_sleep_proc_intr); + +fail_wow: + mutex_unlock(&sc->mutex); + return ret; +} + +int ath9k_resume(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + u32 wow_status; + + mutex_lock(&sc->mutex); + + ath9k_ps_wakeup(sc); + + spin_lock_bh(&sc->sc_pcu_lock); + + ath9k_hw_disable_interrupts(ah); + ah->imask = sc->wow_intr_before_sleep; + ath9k_hw_set_interrupts(ah); + ath9k_hw_enable_interrupts(ah); + + spin_unlock_bh(&sc->sc_pcu_lock); + + wow_status = ath9k_hw_wow_wakeup(ah); + + if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { + /* + * some devices may not pick beacon miss + * as the reason they woke up so we add + * that here for that shortcoming. + */ + wow_status |= AH_WOW_BEACON_MISS; + atomic_dec(&sc->wow_got_bmiss_intr); + ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); + } + + atomic_dec(&sc->wow_sleep_proc_intr); + + if (wow_status) { + ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", + ath9k_hw_wow_event_to_string(wow_status), wow_status); + } + + ath_restart_work(sc); + ath9k_start_btcoex(sc); + + ath9k_ps_restore(sc); + mutex_unlock(&sc->mutex); + + return 0; +} + +void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ + struct ath_softc *sc = hw->priv; + + mutex_lock(&sc->mutex); + device_init_wakeup(sc->dev, 1); + device_set_wakeup_enable(sc->dev, enabled); + mutex_unlock(&sc->mutex); +} -- cgit v1.2.3 From babaa80ac567462a8abda067ec70181d559bbdff Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 28 Oct 2013 13:01:28 +0530 Subject: ath9k: Add an initialization routine for WoW Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++++ drivers/net/wireless/ath/ath9k/init.c | 20 +------------------- drivers/net/wireless/ath/ath9k/wow.c | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 9927dcaa5593..e1013425cc7f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -575,11 +575,15 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) /************************/ #ifdef CONFIG_ATH9K_WOW +void ath9k_init_wow(struct ieee80211_hw *hw); int ath9k_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); int ath9k_resume(struct ieee80211_hw *hw); void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); #else +static inline void ath9k_init_wow(struct ieee80211_hw *hw) +{ +} static inline int ath9k_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cc23436e3401..fb55302c958d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -876,15 +876,6 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; -#ifdef CONFIG_ATH9K_WOW -static const struct wiphy_wowlan_support ath9k_wowlan_support = { - .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, - .n_patterns = MAX_NUM_USER_PATTERN, - .pattern_min_len = 1, - .pattern_max_len = MAX_PATTERN_SIZE, -}; -#endif - void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; @@ -934,16 +925,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; -#ifdef CONFIG_ATH9K_WOW - if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && - (sc->driver_data & ATH9K_PCI_WOW) && - device_can_wakeup(sc->dev)) - hw->wiphy->wowlan = &ath9k_wowlan_support; - - atomic_set(&sc->wow_sleep_proc_intr, -1); - atomic_set(&sc->wow_got_bmiss_intr, -1); -#endif - hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; @@ -969,6 +950,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; + ath9k_init_wow(hw); ath9k_reload_chainmask_settings(sc); SET_IEEE80211_PERM_ADDR(hw, common->macaddr); diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index e161bbc04dbc..f1cde81bb7a2 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c @@ -16,6 +16,13 @@ #include "ath9k.h" +static const struct wiphy_wowlan_support ath9k_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .n_patterns = MAX_NUM_USER_PATTERN, + .pattern_min_len = 1, + .pattern_max_len = MAX_PATTERN_SIZE, +}; + static void ath9k_wow_map_triggers(struct ath_softc *sc, struct cfg80211_wowlan *wowlan, u32 *wow_triggers) @@ -339,3 +346,16 @@ void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) device_set_wakeup_enable(sc->dev, enabled); mutex_unlock(&sc->mutex); } + +void ath9k_init_wow(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && + (sc->driver_data & ATH9K_PCI_WOW) && + device_can_wakeup(sc->dev)) + hw->wiphy->wowlan = &ath9k_wowlan_support; + + atomic_set(&sc->wow_sleep_proc_intr, -1); + atomic_set(&sc->wow_got_bmiss_intr, -1); +} -- cgit v1.2.3 From f51ecd770cb975adbc7761b6167d2de596e421ea Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 29 Oct 2013 11:35:31 +0530 Subject: ath9k: Add SERDES initvals for AR9462 2.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 4 ++++ drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h | 7 +++++++ 2 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 20e49095db2a..84b83e1e7130 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -223,6 +223,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9462_2p1_modes_fast_clock); INIT_INI_ARRAY(&ah->iniCckfirJapan2484, ar9462_2p1_baseband_core_txfir_coeff_japan_2484); + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9462_2p1_pciephy_clkreq_disable_L1); + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9462_2p1_pciephy_clkreq_disable_L1); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h index 57fc5f459d0a..0fcce0739a4c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h @@ -1771,4 +1771,11 @@ static const u32 ar9462_2p1_baseband_core_txfir_coeff_japan_2484[][2] = { {0x0000a3a0, 0xca9228ee}, }; +static const u32 ar9462_2p1_pciephy_clkreq_disable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x18213ede}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0003780c}, +}; + #endif /* INITVALS_9462_2P1_H */ -- cgit v1.2.3 From 28148db74d69de3d2ed0c401ec6ee53bd603f959 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 29 Oct 2013 11:40:06 +0530 Subject: ath9k: Remove unused AR9462 2.0 initvals Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 092b9d412e7f..5a10dcf2adf5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -33,13 +33,6 @@ static const u32 ar9462_modes_fast_clock_2p0[][3] = { {0x0000a254, 0x00000898, 0x00001130}, }; -static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x18253ede}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0003780c}, -}; - static const u32 ar9462_2p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, @@ -366,13 +359,6 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = { {0x00018c08, 0x0003780c}, }; -static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x18212ede}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0003780c}, -}; - static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, -- cgit v1.2.3 From c6fc7e64e1a699b77681dd383d9a5a1ff9eb48e9 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 29 Oct 2013 11:52:06 +0530 Subject: ath9k: Remove pcieSerDesWrite This HW config option is always set to true and is not needed. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 20 +++++++++----------- drivers/net/wireless/ath/ath9k/hw.c | 1 - drivers/net/wireless/ath/ath9k/hw.h | 1 - 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 84b83e1e7130..8d453de979c9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -754,6 +754,9 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) static void ar9003_hw_configpcipowersave(struct ath_hw *ah, bool power_off) { + unsigned int i; + struct ar5416IniArray *array; + /* * Increase L1 Entry Latency. Some WB222 boards don't have * this change in eeprom/OTP. @@ -779,18 +782,13 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, * Configire PCIE after Ini init. SERDES values now come from ini file * This enables PCIe low power mode. */ - if (ah->config.pcieSerDesWrite) { - unsigned int i; - struct ar5416IniArray *array; - - array = power_off ? &ah->iniPcieSerdes : - &ah->iniPcieSerdesLowPower; + array = power_off ? &ah->iniPcieSerdes : + &ah->iniPcieSerdesLowPower; - for (i = 0; i < array->ia_rows; i++) { - REG_WRITE(ah, - INI_RA(array, i, 0), - INI_RA(array, i, 1)); - } + for (i = 0; i < array->ia_rows; i++) { + REG_WRITE(ah, + INI_RA(array, i, 0), + INI_RA(array, i, 1)); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 54b04155e43b..381fbe1d4894 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -454,7 +454,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) } ah->config.rx_intr_mitigation = true; - ah->config.pcieSerDesWrite = true; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ecc3a4efe18a..e50843600989 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -283,7 +283,6 @@ struct ath9k_ops_config { int additional_swba_backoff; int ack_6mb; u32 cwm_ignore_extcca; - bool pcieSerDesWrite; u8 pcie_clock_req; u32 pcie_waen; u8 analog_shiftreg; -- cgit v1.2.3 From 8fd007ac7c6ca63f7dbf7792cc1081855ef7fe4e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 5 Nov 2013 05:54:59 +0530 Subject: ath9k: Apply CUS227 specific TX gain values CUS227, which is an AR9340 based card used in Qualcomm's Allplay platforms requires a custom TX gain array, based on the index 7. Add suport for this. Cc: Michael Larson Cc: Stephen Collmeyer Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 8 ++ drivers/net/wireless/ath/ath9k/ar9340_initvals.h | 102 +++++++++++++++++++++++ 2 files changed, 110 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 8d453de979c9..33f63dc672e1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -585,6 +585,13 @@ static void ar9003_tx_gain_table_mode6(struct ath_hw *ah) ar9580_1p0_type6_tx_gain_table); } +static void ar9003_tx_gain_table_mode7(struct ath_hw *ah) +{ + if (AR_SREV_9340(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9340_cus227_tx_gain_table_1p0); +} + typedef void (*ath_txgain_tab)(struct ath_hw *ah); static void ar9003_tx_gain_table_apply(struct ath_hw *ah) @@ -597,6 +604,7 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) ar9003_tx_gain_table_mode4, ar9003_tx_gain_table_mode5, ar9003_tx_gain_table_mode6, + ar9003_tx_gain_table_mode7, }; int idx = ar9003_hw_get_tx_gain_idx(ah); diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index 25db9215985a..182bf90ab809 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h @@ -1447,4 +1447,106 @@ static const u32 ar9340_1p0_soc_preamble[][2] = { {0x00007038, 0x000004c2}, }; +static const u32 ar9340_cus227_tx_gain_table_1p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2c022220, 0x2c022220, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x30022222, 0x30022222, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x35022225, 0x35022225, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x3b02222a, 0x3b02222a, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x3f02222c, 0x3f02222c, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, + {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, + {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, + {0x00016048, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, + {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015}, + {0x00016288, 0x30318000, 0x30318000, 0x00318000, 0x00318000}, + {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, + {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, + {0x0000a3a4, 0x00000011, 0x00000011, 0x00000011, 0x00000011}, + {0x0000a3a8, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c}, + {0x0000a3ac, 0x30303030, 0x30303030, 0x30303030, 0x30303030}, +}; + #endif /* INITVALS_9340_H */ -- cgit v1.2.3 From 26f2a64abdeb44e488e2334d28a380a3ed5a504d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Nov 2013 15:31:18 +0530 Subject: ath9k: fix SC_OP_INVALID test in ath9k_tx99_init() SC_OP_INVALID is zero so the test is always false. We're supposed to be testing the lowest bit instead. Fixes: 89f927af7f33 ('ath9k: add TX99 support') Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/tx99.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 6668197c277c..c65c37fe1014 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -99,7 +99,7 @@ static int ath9k_tx99_init(struct ath_softc *sc) struct ath_tx_control txctl; int r; - if (sc->sc_flags & SC_OP_INVALID) { + if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { ath_err(common, "driver is in invalid state unable to use TX99"); return -EINVAL; -- cgit v1.2.3 From 3b06c1d7af98f2fbc0c136b668568c873017bd54 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 15 Nov 2013 10:46:21 +0530 Subject: ath9k: Separate routines for PCOEM and SoC calibration Though there is some overlap between the calibration mechanisms of PC-OEM cards and SoC chip families, dumping both of them into a single function makes things hard to understand. ar9003_hw_init_cal() is unreadable with chip-specific segments scattered around. To make the logic understandable, use different functions for client cards and SoC chips. Some code is duplicated, but in the long run, it makes the code more maintanable. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 198 +++++++++++++++++++++++++- 1 file changed, 195 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 22934d3ca544..9f54cb58053c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1040,8 +1040,196 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) } } -static bool ar9003_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan) +static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_cal_data *caldata = ah->caldata; + bool txiqcal_done = false; + bool is_reusable = true, status = true; + bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; + bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); + u32 rx_delay = 0; + u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | + AR_PHY_AGC_CONTROL_FLTR_CAL | + AR_PHY_AGC_CONTROL_PKDET_CAL; + + /* Use chip chainmask only for calibration */ + ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); + + if (rtt) { + if (!ar9003_hw_rtt_restore(ah, chan)) + run_rtt_cal = true; + + if (run_rtt_cal) + ath_dbg(common, CALIBRATE, "RTT calibration to be done\n"); + } + + run_agc_cal = run_rtt_cal; + + if (run_rtt_cal) { + ar9003_hw_rtt_enable(ah); + ar9003_hw_rtt_set_mask(ah, 0x00); + ar9003_hw_rtt_clear_hist(ah); + } + + if (rtt) { + if (!run_rtt_cal) { + agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL); + agc_supp_cals &= agc_ctrl; + agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL | + AR_PHY_AGC_CONTROL_FLTR_CAL | + AR_PHY_AGC_CONTROL_PKDET_CAL); + REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); + } else { + if (ah->ah_flags & AH_FASTCC) + run_agc_cal = true; + } + } + + if (ah->enabled_cals & TX_CL_CAL) { + if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags)) + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, + AR_PHY_CL_CAL_ENABLE); + else { + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, + AR_PHY_CL_CAL_ENABLE); + run_agc_cal = true; + } + } + + if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) || + !(ah->enabled_cals & TX_IQ_CAL)) + goto skip_tx_iqcal; + + /* Do Tx IQ Calibration */ + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, + AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, + DELPT); + + /* + * For AR9485 or later chips, TxIQ cal runs as part of + * AGC calibration + */ + if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { + if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) + REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, + AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); + else + REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, + AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); + txiqcal_done = run_agc_cal = true; + } else if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) { + run_agc_cal = true; + sep_iq_cal = true; + } + +skip_tx_iqcal: + if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) + ar9003_mci_init_cal_req(ah, &is_reusable); + + if (sep_iq_cal) { + txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); + udelay(5); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + } + + if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { + rx_delay = REG_READ(ah, AR_PHY_RX_DELAY); + /* Disable BB_active */ + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); + udelay(5); + REG_WRITE(ah, AR_PHY_RX_DELAY, AR_PHY_RX_DELAY_DELAY); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + } + + if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { + /* Calibrate the AGC */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); + + /* Poll for offset calibration complete */ + status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT); + + ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal); + } + + if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { + REG_WRITE(ah, AR_PHY_RX_DELAY, rx_delay); + udelay(5); + } + + if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) + ar9003_mci_init_cal_done(ah); + + if (rtt && !run_rtt_cal) { + agc_ctrl |= agc_supp_cals; + REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); + } + + if (!status) { + if (run_rtt_cal) + ar9003_hw_rtt_disable(ah); + + ath_dbg(common, CALIBRATE, + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); + return false; + } + + if (txiqcal_done) + ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); + else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) + ar9003_hw_tx_iq_cal_reload(ah); + + ar9003_hw_cl_cal_post_proc(ah, is_reusable); + + if (run_rtt_cal && caldata) { + if (is_reusable) { + if (!ath9k_hw_rfbus_req(ah)) { + ath_err(ath9k_hw_common(ah), + "Could not stop baseband\n"); + } else { + ar9003_hw_rtt_fill_hist(ah); + + if (test_bit(SW_PKDET_DONE, &caldata->cal_flags)) + ar9003_hw_rtt_load_hist(ah); + } + + ath9k_hw_rfbus_done(ah); + } + + ar9003_hw_rtt_disable(ah); + } + + /* Revert chainmask to runtime parameters */ + ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + + /* Initialize list pointers */ + ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); + + /* Initialize current pointer to first element in list */ + ah->cal_list_curr = ah->cal_list; + + if (ah->cal_list_curr) + ath9k_hw_reset_calibration(ah, ah->cal_list_curr); + + if (caldata) + caldata->CalValid = 0; + + return true; +} + +static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, + struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_cal_data *caldata = ah->caldata; @@ -1233,8 +1421,12 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_ops *ops = ath9k_hw_ops(ah); + if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah)) + priv_ops->init_cal = ar9003_hw_init_cal_pcoem; + else + priv_ops->init_cal = ar9003_hw_init_cal_soc; + priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; - priv_ops->init_cal = ar9003_hw_init_cal; priv_ops->setup_calibration = ar9003_hw_setup_calibration; ops->calibrate = ar9003_hw_calibrate; -- cgit v1.2.3 From a3640781d91334ba2a507b56cae18355fad8b479 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 15 Nov 2013 10:50:58 +0530 Subject: ath9k: Remove RTT/MCI code from SoC calibration RTT is enabled only for AR9462 and MCI for AR9462/AR9565. Also, manual peak calibration is not done for any of the SoC chips. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 70 +-------------------------- 1 file changed, 1 insertion(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 9f54cb58053c..28248248add2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1235,46 +1235,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, struct ath9k_hw_cal_data *caldata = ah->caldata; bool txiqcal_done = false; bool is_reusable = true, status = true; - bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; - bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); + bool run_agc_cal = false, sep_iq_cal = false; u32 rx_delay = 0; - u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | - AR_PHY_AGC_CONTROL_FLTR_CAL | - AR_PHY_AGC_CONTROL_PKDET_CAL; /* Use chip chainmask only for calibration */ ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); - if (rtt) { - if (!ar9003_hw_rtt_restore(ah, chan)) - run_rtt_cal = true; - - if (run_rtt_cal) - ath_dbg(common, CALIBRATE, "RTT calibration to be done\n"); - } - - run_agc_cal = run_rtt_cal; - - if (run_rtt_cal) { - ar9003_hw_rtt_enable(ah); - ar9003_hw_rtt_set_mask(ah, 0x00); - ar9003_hw_rtt_clear_hist(ah); - } - - if (rtt) { - if (!run_rtt_cal) { - agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL); - agc_supp_cals &= agc_ctrl; - agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL | - AR_PHY_AGC_CONTROL_FLTR_CAL | - AR_PHY_AGC_CONTROL_PKDET_CAL); - REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); - } else { - if (ah->ah_flags & AH_FASTCC) - run_agc_cal = true; - } - } - if (ah->enabled_cals & TX_CL_CAL) { if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags)) REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, @@ -1313,9 +1279,6 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, } skip_tx_iqcal: - if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) - ar9003_mci_init_cal_req(ah, &is_reusable); - if (sep_iq_cal) { txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); @@ -1342,8 +1305,6 @@ skip_tx_iqcal: status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT); - - ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal); } if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { @@ -1351,18 +1312,7 @@ skip_tx_iqcal: udelay(5); } - if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) - ar9003_mci_init_cal_done(ah); - - if (rtt && !run_rtt_cal) { - agc_ctrl |= agc_supp_cals; - REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); - } - if (!status) { - if (run_rtt_cal) - ar9003_hw_rtt_disable(ah); - ath_dbg(common, CALIBRATE, "offset calibration failed to complete in %d ms; noisy environment?\n", AH_WAIT_TIMEOUT / 1000); @@ -1376,24 +1326,6 @@ skip_tx_iqcal: ar9003_hw_cl_cal_post_proc(ah, is_reusable); - if (run_rtt_cal && caldata) { - if (is_reusable) { - if (!ath9k_hw_rfbus_req(ah)) { - ath_err(ath9k_hw_common(ah), - "Could not stop baseband\n"); - } else { - ar9003_hw_rtt_fill_hist(ah); - - if (test_bit(SW_PKDET_DONE, &caldata->cal_flags)) - ar9003_hw_rtt_load_hist(ah); - } - - ath9k_hw_rfbus_done(ah); - } - - ar9003_hw_rtt_disable(ah); - } - /* Revert chainmask to runtime parameters */ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); -- cgit v1.2.3 From c20a2c5912755e8cb6c643fa0aa87e93e1b2c893 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 15 Nov 2013 11:05:38 +0530 Subject: ath9k: Remove unnecessary check TX IQ calibration is always enabled for SoC chips. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 28248248add2..347b002938ed 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1252,8 +1252,7 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, } } - if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) || - !(ah->enabled_cals & TX_IQ_CAL)) + if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) goto skip_tx_iqcal; /* Do Tx IQ Calibration */ -- cgit v1.2.3 From 34d9b6893405c5afaf9d906062feae15ccfbcb28 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 15 Nov 2013 13:05:18 +0530 Subject: ath9k: Fix Carrier Leak calibration for SoC chips CL calibration is applicable for all chips and the enable/disable knob comes via the INI file. For PCOEM chips, the calibration data is reused when Fast Channel Change is used. Caldata reuse is not enabled for SoC chips, so remove the CL post processing code. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 27 ++------------------------- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 9 +++++---- 2 files changed, 7 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 347b002938ed..58eacf12db83 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1236,20 +1236,13 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, bool txiqcal_done = false; bool is_reusable = true, status = true; bool run_agc_cal = false, sep_iq_cal = false; - u32 rx_delay = 0; /* Use chip chainmask only for calibration */ ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); if (ah->enabled_cals & TX_CL_CAL) { - if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags)) - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, - AR_PHY_CL_CAL_ENABLE); - else { - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, - AR_PHY_CL_CAL_ENABLE); - run_agc_cal = true; - } + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + run_agc_cal = true; } if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) @@ -1285,15 +1278,6 @@ skip_tx_iqcal: REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); } - if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { - rx_delay = REG_READ(ah, AR_PHY_RX_DELAY); - /* Disable BB_active */ - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); - udelay(5); - REG_WRITE(ah, AR_PHY_RX_DELAY, AR_PHY_RX_DELAY_DELAY); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - } - if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, @@ -1306,11 +1290,6 @@ skip_tx_iqcal: 0, AH_WAIT_TIMEOUT); } - if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { - REG_WRITE(ah, AR_PHY_RX_DELAY, rx_delay); - udelay(5); - } - if (!status) { ath_dbg(common, CALIBRATE, "offset calibration failed to complete in %d ms; noisy environment?\n", @@ -1323,8 +1302,6 @@ skip_tx_iqcal: else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) ar9003_hw_tx_iq_cal_reload(ah); - ar9003_hw_cl_cal_post_proc(ah, is_reusable); - /* Revert chainmask to runtime parameters */ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index d39b79f5e841..39b71b3d6919 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -641,11 +641,12 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) else ah->enabled_cals &= ~TX_IQ_CAL; - if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) - ah->enabled_cals |= TX_CL_CAL; - else - ah->enabled_cals &= ~TX_CL_CAL; } + + if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) + ah->enabled_cals |= TX_CL_CAL; + else + ah->enabled_cals &= ~TX_CL_CAL; } static void ar9003_hw_prog_ini(struct ath_hw *ah, -- cgit v1.2.3 From f28c785f37a977cfd5879f4bfec99838053373f8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 15 Nov 2013 14:49:32 +0530 Subject: ath9k: Fix TX IQ calibration for SoC chips Since calibration data reuse is not enabled in SoC chips, simplify the IQ calibration code. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 58eacf12db83..a18c3dd01a1a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1255,22 +1255,19 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, /* * For AR9485 or later chips, TxIQ cal runs as part of - * AGC calibration + * AGC calibration. Specifically, AR9550 in SoC chips. */ if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { - if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) - REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, - AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); - else - REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, - AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); - txiqcal_done = run_agc_cal = true; - } else if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) { + txiqcal_done = true; run_agc_cal = true; + } else { sep_iq_cal = true; + run_agc_cal = true; } -skip_tx_iqcal: + /* + * In the SoC family, this will run for AR9300, AR9331 and AR9340. + */ if (sep_iq_cal) { txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); @@ -1278,6 +1275,7 @@ skip_tx_iqcal: REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); } +skip_tx_iqcal: if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, @@ -1299,8 +1297,6 @@ skip_tx_iqcal: if (txiqcal_done) ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); - else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) - ar9003_hw_tx_iq_cal_reload(ah); /* Revert chainmask to runtime parameters */ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); -- cgit v1.2.3 From bf3dac5a6fcf33a80c99e7b7406f8e5af99e2a70 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Nov 2013 22:23:33 +0100 Subject: ath9k: use a timer to put hardware into full sleep When operating in client mode, the short period of time between scanning and associating is often enough to put the hardware through several FULL-SLEEP <-> AWAKE transitions, each wakeup requiring a reset to fully recover the hardware. This is completely unnecessary and can easily be avoided by deferring the switch to full sleep. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath/ath9k/init.c | 2 ++ drivers/net/wireless/ath/ath9k/main.c | 27 ++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index e1013425cc7f..0783e50f44b2 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -459,6 +459,7 @@ void ath_check_ani(struct ath_softc *sc); int ath_update_survey_stats(struct ath_softc *sc); void ath_update_survey_nf(struct ath_softc *sc, int channel); void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); +void ath_ps_full_sleep(unsigned long data); /**********/ /* BTCOEX */ @@ -789,6 +790,7 @@ struct ath_softc { struct delayed_work tx_complete_work; struct delayed_work hw_pll_work; struct timer_list rx_poll_timer; + struct timer_list sleep_timer; #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT struct ath_btcoex btcoex; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fb55302c958d..65a2add3b676 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -738,6 +738,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, (unsigned long)sc); + setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc); INIT_WORK(&sc->hw_reset_work, ath_reset_work); INIT_WORK(&sc->hw_check_work, ath_hw_check); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); @@ -1049,6 +1050,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); + del_timer_sync(&sc->sleep_timer); ath9k_hw_deinit(sc->sc_ah); if (sc->dfs_detector != NULL) sc->dfs_detector->exit(sc->dfs_detector); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e54ffdd36e21..f86404a70a73 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -82,6 +82,22 @@ static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) return ret; } +void ath_ps_full_sleep(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *) data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + bool reset; + + spin_lock(&common->cc_lock); + ath_hw_cycle_counters_update(common); + spin_unlock(&common->cc_lock); + + ath9k_hw_setrxabort(sc->sc_ah, 1); + ath9k_hw_stopdmarecv(sc->sc_ah, &reset); + + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); +} + void ath9k_ps_wakeup(struct ath_softc *sc) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -92,6 +108,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc) if (++sc->ps_usecount != 1) goto unlock; + del_timer_sync(&sc->sleep_timer); power_mode = sc->sc_ah->power_mode; ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); @@ -117,17 +134,17 @@ void ath9k_ps_restore(struct ath_softc *sc) struct ath_common *common = ath9k_hw_common(sc->sc_ah); enum ath9k_power_mode mode; unsigned long flags; - bool reset; spin_lock_irqsave(&sc->sc_pm_lock, flags); if (--sc->ps_usecount != 0) goto unlock; if (sc->ps_idle) { - ath9k_hw_setrxabort(sc->sc_ah, 1); - ath9k_hw_stopdmarecv(sc->sc_ah, &reset); - mode = ATH9K_PM_FULL_SLEEP; - } else if (sc->ps_enabled && + mod_timer(&sc->sleep_timer, jiffies + HZ / 10); + goto unlock; + } + + if (sc->ps_enabled && !(sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | -- cgit v1.2.3 From 10ffb6a77e617a8f5ded84b504550759ec4a8df0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Nov 2013 22:23:34 +0100 Subject: ath9k: optimize ath_drain_all_txq If the software has processed all packets, checking the hardware queue is unnecessary. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 95f6c5a8ee12..24846d91554b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1786,6 +1786,9 @@ bool ath_drain_all_txq(struct ath_softc *sc) if (!ATH_TXQ_SETUP(sc, i)) continue; + if (!sc->tx.txq[i].axq_depth) + continue; + if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum)) npend |= BIT(i); } -- cgit v1.2.3 From 10e2318103f5941aa70c318afe34bc41f1b98529 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Nov 2013 22:23:35 +0100 Subject: ath9k: optimize ath9k_flush Instead of checking the queues in a loop with hardcoded sleep times inbetween, use a wait queue to trigger queue checks after the tx processing tasklet has run. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/main.c | 46 ++++++++++++++++++---------------- 3 files changed, 27 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0783e50f44b2..5e5d5cb2458c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -754,6 +754,7 @@ struct ath_softc { struct work_struct hw_check_work; struct work_struct hw_reset_work; struct completion paprd_complete; + wait_queue_head_t tx_wait; unsigned int hw_busy_count; unsigned long sc_flags; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 65a2add3b676..8f4c1674b76e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -691,6 +691,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common = ath9k_hw_common(ah); sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); sc->tx99_power = MAX_RATE_POWER + 1; + init_waitqueue_head(&sc->tx_wait); if (!pdata) { ah->ah_flags |= AH_USE_EEPROM; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f86404a70a73..b1dcf89138d3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -504,6 +504,8 @@ void ath9k_tasklet(unsigned long data) ath_tx_edma_tasklet(sc); else ath_tx_tasklet(sc); + + wake_up(&sc->tx_wait); } ath9k_btcoex_handle_interrupt(sc, status); @@ -1837,13 +1839,31 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) mutex_unlock(&sc->mutex); } +static bool ath9k_has_tx_pending(struct ath_softc *sc) +{ + int i, npend; + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (!ATH_TXQ_SETUP(sc, i)) + continue; + + if (!sc->tx.txq[i].axq_depth) + continue; + + npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); + if (npend) + break; + } + + return !!npend; +} + static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) { struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - int timeout = 200; /* ms */ - int i, j; + int timeout = HZ / 5; /* 200 ms */ bool drain_txq; mutex_lock(&sc->mutex); @@ -1861,25 +1881,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) return; } - for (j = 0; j < timeout; j++) { - bool npend = false; - - if (j) - usleep_range(1000, 2000); - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (!ATH_TXQ_SETUP(sc, i)) - continue; - - npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); - - if (npend) - break; - } - - if (!npend) - break; - } + if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), + timeout) > 0) + drop = false; if (drop) { ath9k_ps_wakeup(sc); -- cgit v1.2.3 From 09d8e315d90a70eb1096d68f27be04d6c43724f3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Nov 2013 20:14:43 +0100 Subject: ath9k_hw: fix TSF save/restore around chip reset A cold reset can be triggered because of DMA stop issues, and this leads to TSF being cleared on all chipsets. To properly deal with this, always save the TSF. Additionally, account for the time it takes to do the actual chip reset, which can be quite significant. On AR9344 it takes around 4.5 ms. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 381fbe1d4894..02eff2a8a280 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "hw.h" @@ -1855,10 +1856,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata, bool fastcc) { struct ath_common *common = ath9k_hw_common(ah); + struct timespec ts; u32 saveLedState; u32 saveDefAntenna; u32 macStaId1; u64 tsf = 0; + s64 usec = 0; int r; bool start_mci_reset = false; bool save_fullsleep = ah->chip_fullsleep; @@ -1901,10 +1904,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; - /* For chips on which RTC reset is done, save TSF before it gets cleared */ - if (AR_SREV_9100(ah) || - (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) - tsf = ath9k_hw_gettsf64(ah); + /* Save TSF before chip reset, a cold reset clears it */ + tsf = ath9k_hw_gettsf64(ah); + getrawmonotonic(&ts); + usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000; saveLedState = REG_READ(ah, AR_CFG_LED) & (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | @@ -1937,8 +1940,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, } /* Restore TSF */ - if (tsf) - ath9k_hw_settsf64(ah, tsf); + getrawmonotonic(&ts); + usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000 - usec; + ath9k_hw_settsf64(ah, tsf + usec); if (AR_SREV_9280_20_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); -- cgit v1.2.3 From af02efb32e34938aecce5362b0cdb70e4d18e846 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Nov 2013 20:14:44 +0100 Subject: ath9k_hw: allow fast channel change when only CHANNEL_HT changes The CHANNEL_HT flag is insignificant for fast channel change conditions, since it does not affect any important part of the hardware reset / channel setup. Scanning usually runs with HT disabled, so this change will slightly improve scan time on many chipsets. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 02eff2a8a280..fe3537f6ec58 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1502,8 +1502,9 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, int r; if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { - band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan); - mode_diff = (chan->channelFlags != ah->curchan->channelFlags); + u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags; + band_switch = !!(flags_diff & CHANNEL_5GHZ); + mode_diff = !!(flags_diff & ~CHANNEL_HT); } for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { @@ -1815,7 +1816,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) * If cross-band fcc is not supoprted, bail out if channelFlags differ. */ if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && - chan->channelFlags != ah->curchan->channelFlags) + ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT)) goto fail; if (!ath9k_hw_check_alive(ah)) -- cgit v1.2.3 From ffaa02fc1e5cec06e32a63e2dfdc7ce3555102ca Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 19 Nov 2013 09:15:01 +0530 Subject: ath9k: Cleanup IQ calibration for PCOEM chips Since IQ calibration is done as part of AGC calibration for AR9485 and above, remove the seperate IQ calibration code. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index a18c3dd01a1a..aa0127265746 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1047,7 +1047,7 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, struct ath9k_hw_cal_data *caldata = ah->caldata; bool txiqcal_done = false; bool is_reusable = true, status = true; - bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; + bool run_rtt_cal = false, run_agc_cal; bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); u32 rx_delay = 0; u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | @@ -1119,22 +1119,12 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); txiqcal_done = run_agc_cal = true; - } else if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) { - run_agc_cal = true; - sep_iq_cal = true; } skip_tx_iqcal: if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) ar9003_mci_init_cal_req(ah, &is_reusable); - if (sep_iq_cal) { - txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); - udelay(5); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - } - if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { rx_delay = REG_READ(ah, AR_PHY_RX_DELAY); /* Disable BB_active */ -- cgit v1.2.3 From ae4a9a1062d5d9d9a8121590544c01eb65ea760a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 19 Nov 2013 12:01:09 +0530 Subject: ath9k: Add initvals for AR9565 1.1 The initialization arrays for v1.1 AR9565 are mostly the same as v1.0/v1.0.1 except for radio_postamble. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9565_1p1_initvals.h | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h new file mode 100644 index 000000000000..56810539971e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * Copyright (c) 2011-2012 Qualcomm Atheros Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9565_1P1_H +#define INITVALS_9565_1P1_H + +/* AR9565 1.1 */ + +#define ar9565_1p1_mac_core ar9565_1p0_mac_core + +#define ar9565_1p1_mac_postamble ar9565_1p0_mac_postamble + +#define ar9565_1p1_baseband_core ar9565_1p0_baseband_core + +#define ar9565_1p1_baseband_postamble ar9565_1p0_baseband_postamble + +#define ar9565_1p1_radio_core ar9565_1p0_radio_core + +#define ar9565_1p1_soc_preamble ar9565_1p0_soc_preamble + +#define ar9565_1p1_soc_postamble ar9565_1p0_soc_postamble + +#define ar9565_1p1_Common_rx_gain_table ar9565_1p0_Common_rx_gain_table + +#define ar9565_1p1_Modes_lowest_ob_db_tx_gain_table ar9565_1p0_Modes_lowest_ob_db_tx_gain_table + +#define ar9565_1p1_pciephy_clkreq_disable_L1 ar9565_1p0_pciephy_clkreq_disable_L1 + +#define ar9565_1p1_modes_fast_clock ar9565_1p0_modes_fast_clock + +#define ar9565_1p1_common_wo_xlna_rx_gain_table ar9565_1p0_common_wo_xlna_rx_gain_table + +#define ar9565_1p1_modes_low_ob_db_tx_gain_table ar9565_1p0_modes_low_ob_db_tx_gain_table + +#define ar9565_1p1_modes_high_ob_db_tx_gain_table ar9565_1p0_modes_high_ob_db_tx_gain_table + +#define ar9565_1p1_modes_high_power_tx_gain_table ar9565_1p0_modes_high_power_tx_gain_table + +#define ar9565_1p1_baseband_core_txfir_coeff_japan_2484 ar9565_1p0_baseband_core_txfir_coeff_japan_2484 + +static const u32 ar9565_1p1_radio_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524}, + {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, + {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70}, + {0x0001610c, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, + {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +}; + +#endif /* INITVALS_9565_1P1_H */ -- cgit v1.2.3 From 8af45965932781c1e9736a0609c8ed229b534a64 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 19 Nov 2013 12:06:08 +0530 Subject: ath9k: Add version macros for AR9565 1.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index a13b2d143d9e..259a4b307707 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -809,6 +809,8 @@ #define AR_SREV_REVISION_9462_21 3 #define AR_SREV_VERSION_9565 0x2C0 #define AR_SREV_REVISION_9565_10 0 +#define AR_SREV_REVISION_9565_101 1 +#define AR_SREV_REVISION_9565_11 2 #define AR_SREV_VERSION_9550 0x400 #define AR_SREV_5416(_ah) \ @@ -927,10 +929,18 @@ #define AR_SREV_9565(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) - #define AR_SREV_9565_10(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10)) +#define AR_SREV_9565_101(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101)) +#define AR_SREV_9565_11(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11)) +#define AR_SREV_9565_11_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11)) #define AR_SREV_9550(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550)) -- cgit v1.2.3 From 3777f7d121ffb8f75d7e98862f73ae8c2f2fa09a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 19 Nov 2013 12:11:13 +0530 Subject: ath9k: Attach INI arrays for AR9565 v1.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 33f63dc672e1..568f3138188a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -26,6 +26,7 @@ #include "ar9462_2p0_initvals.h" #include "ar9462_2p1_initvals.h" #include "ar9565_1p0_initvals.h" +#include "ar9565_1p1_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -335,6 +336,41 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesFastClock, ar9580_1p0_modes_fast_clock); + } else if (AR_SREV_9565_11_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9565_1p1_mac_core); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9565_1p1_mac_postamble); + + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9565_1p1_baseband_core); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9565_1p1_baseband_postamble); + + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9565_1p1_radio_core); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9565_1p1_radio_postamble); + + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9565_1p1_soc_preamble); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9565_1p1_soc_postamble); + + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9565_1p1_Common_rx_gain_table); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9565_1p1_Modes_lowest_ob_db_tx_gain_table); + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9565_1p1_pciephy_clkreq_disable_L1); + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9565_1p1_pciephy_clkreq_disable_L1); + + INIT_INI_ARRAY(&ah->iniModesFastClock, + ar9565_1p1_modes_fast_clock); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9565_1p1_baseband_core_txfir_coeff_japan_2484); } else if (AR_SREV_9565(ah)) { INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9565_1p0_mac_core); @@ -445,6 +481,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9462_modes_low_ob_db_tx_gain_table_2p0); + else if (AR_SREV_9565_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9565_1p1_modes_low_ob_db_tx_gain_table); else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p0_modes_low_ob_db_tx_gain_table); @@ -479,6 +518,9 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9462_modes_high_ob_db_tx_gain_table_2p0); + else if (AR_SREV_9565_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9565_1p1_modes_high_ob_db_tx_gain_table); else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p0_modes_high_ob_db_tx_gain_table); @@ -504,6 +546,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_low_ob_db_tx_gain_table); + else if (AR_SREV_9565_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9565_1p1_modes_low_ob_db_tx_gain_table); else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p0_modes_low_ob_db_tx_gain_table); @@ -529,6 +574,9 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah) else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_high_power_tx_gain_table); + else if (AR_SREV_9565_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9565_1p1_modes_high_power_tx_gain_table); else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p0_modes_high_power_tx_gain_table); @@ -642,6 +690,9 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_common_rx_gain_table_2p0); + else if (AR_SREV_9565_11(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9565_1p1_Common_rx_gain_table); else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9565_1p0_Common_rx_gain_table); @@ -678,6 +729,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) } else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9580_1p0_wo_xlna_rx_gain_table); + else if (AR_SREV_9565_11(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9565_1p1_common_wo_xlna_rx_gain_table); else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9565_1p0_common_wo_xlna_rx_gain_table); -- cgit v1.2.3 From dbb3e2fb4ab59e1b2c1d4d3a9b0ed4034ee349b9 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 26 Nov 2013 15:04:55 +0530 Subject: ath9k: Remove duplicate initvals for AR9462 v2.1 The initvals for AR9462 v2.1 are very similar to v2.0. Identify duplicate arrays and reuse the values from v2.0 to reduce module size. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 24 +- .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 18 +- .../net/wireless/ath/ath9k/ar9462_2p1_initvals.h | 1566 +------------------- .../net/wireless/ath/ath9k/ar9580_1p0_initvals.h | 2 +- 4 files changed, 60 insertions(+), 1550 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 568f3138188a..d3eca0cec9cd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -252,18 +252,18 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9462_2p0_soc_postamble); INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9462_common_rx_gain_table_2p0); + ar9462_2p0_common_rx_gain); /* Awake -> Sleep Setting */ INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9462_pciephy_clkreq_disable_L1_2p0); + ar9462_2p0_pciephy_clkreq_disable_L1); /* Sleep -> Awake Setting */ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9462_pciephy_clkreq_disable_L1_2p0); + ar9462_2p0_pciephy_clkreq_disable_L1); /* Fast clock modal settings */ INIT_INI_ARRAY(&ah->iniModesFastClock, - ar9462_modes_fast_clock_2p0); + ar9462_2p0_modes_fast_clock); INIT_INI_ARRAY(&ah->iniCckfirJapan2484, ar9462_2p0_baseband_core_txfir_coeff_japan_2484); @@ -480,7 +480,7 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) ar9462_2p1_modes_low_ob_db_tx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9462_modes_low_ob_db_tx_gain_table_2p0); + ar9462_2p0_modes_low_ob_db_tx_gain); else if (AR_SREV_9565_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p1_modes_low_ob_db_tx_gain_table); @@ -517,7 +517,7 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) ar9462_2p1_modes_high_ob_db_tx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9462_modes_high_ob_db_tx_gain_table_2p0); + ar9462_2p0_modes_high_ob_db_tx_gain); else if (AR_SREV_9565_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p1_modes_high_ob_db_tx_gain_table); @@ -598,7 +598,7 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) ar9462_2p1_modes_mix_ob_db_tx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9462_modes_mix_ob_db_tx_gain_table_2p0); + ar9462_2p0_modes_mix_ob_db_tx_gain); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_mixed_ob_db_tx_gain_table_2p2); @@ -689,7 +689,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) ar9462_2p1_common_rx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9462_common_rx_gain_table_2p0); + ar9462_2p0_common_rx_gain); else if (AR_SREV_9565_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9565_1p1_Common_rx_gain_table); @@ -720,7 +720,7 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) ar9462_2p1_common_wo_xlna_rx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9462_common_wo_xlna_rx_gain_table_2p0); + ar9462_2p0_common_wo_xlna_rx_gain); else if (AR_SREV_9550(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar955x_1p0_common_wo_xlna_rx_gain_table); @@ -753,7 +753,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) ar9462_2p1_baseband_postamble_5g_xlna); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9462_common_mixed_rx_gain_table_2p0); + ar9462_2p0_common_mixed_rx_gain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, ar9462_2p0_baseband_core_mix_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, @@ -767,12 +767,12 @@ static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) { if (AR_SREV_9462_21(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9462_2p1_common_5g_xlna_only_rx_gain); + ar9462_2p1_common_5g_xlna_only_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, ar9462_2p1_baseband_postamble_5g_xlna); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9462_2p0_5g_xlna_only_rxgain); + ar9462_2p0_common_5g_xlna_only_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, ar9462_2p0_baseband_postamble_5g_xlna); } diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 5a10dcf2adf5..739094384369 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -20,7 +20,7 @@ /* AR9462 2.0 */ -static const u32 ar9462_modes_fast_clock_2p0[][3] = { +static const u32 ar9462_2p0_modes_fast_clock[][3] = { /* Addr 5G_HT20 5G_HT40 */ {0x00001030, 0x00000268, 0x000004d0}, {0x00001070, 0x0000018c, 0x00000318}, @@ -92,7 +92,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, }; -static const u32 ar9462_common_rx_gain_table_2p0[][2] = { +static const u32 ar9462_2p0_common_rx_gain[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -352,7 +352,7 @@ static const u32 ar9462_common_rx_gain_table_2p0[][2] = { {0x0000b1fc, 0x00000196}, }; -static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = { +static const u32 ar9462_2p0_pciephy_clkreq_disable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x18213ede}, {0x00018c04, 0x000801d8}, @@ -366,7 +366,7 @@ static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, }; -static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = { +static const u32 ar9462_2p0_common_wo_xlna_rx_gain[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -633,7 +633,7 @@ static const u32 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = { {0x0000a3a0, 0xca9228ee}, }; -static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = { +static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, @@ -865,7 +865,7 @@ static const u32 ar9462_2p0_radio_postamble[][5] = { {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, }; -static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = { +static const u32 ar9462_2p0_modes_mix_ob_db_tx_gain[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, @@ -928,7 +928,7 @@ static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = { {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, }; -static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { +static const u32 ar9462_2p0_modes_high_ob_db_tx_gain[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, @@ -1238,7 +1238,7 @@ static const u32 ar9462_2p0_mac_postamble[][5] = { {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, }; -static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = { +static const u32 ar9462_2p0_common_mixed_rx_gain[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -1503,7 +1503,7 @@ static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = { {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, }; -static const u32 ar9462_2p0_5g_xlna_only_rxgain[][2] = { +static const u32 ar9462_2p0_common_5g_xlna_only_rxgain[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h index 0fcce0739a4c..dc3adda46e8b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h @@ -20,6 +20,44 @@ /* AR9462 2.1 */ +#define ar9462_2p1_mac_postamble ar9462_2p0_mac_postamble + +#define ar9462_2p1_baseband_core ar9462_2p0_baseband_core + +#define ar9462_2p1_radio_core ar9462_2p0_radio_core + +#define ar9462_2p1_radio_postamble ar9462_2p0_radio_postamble + +#define ar9462_2p1_soc_postamble ar9462_2p0_soc_postamble + +#define ar9462_2p1_radio_postamble_sys2ant ar9462_2p0_radio_postamble_sys2ant + +#define ar9462_2p1_common_rx_gain ar9462_2p0_common_rx_gain + +#define ar9462_2p1_common_mixed_rx_gain ar9462_2p0_common_mixed_rx_gain + +#define ar9462_2p1_common_5g_xlna_only_rxgain ar9462_2p0_common_5g_xlna_only_rxgain + +#define ar9462_2p1_baseband_core_mix_rxgain ar9462_2p0_baseband_core_mix_rxgain + +#define ar9462_2p1_baseband_postamble_mix_rxgain ar9462_2p0_baseband_postamble_mix_rxgain + +#define ar9462_2p1_baseband_postamble_5g_xlna ar9462_2p0_baseband_postamble_5g_xlna + +#define ar9462_2p1_common_wo_xlna_rx_gain ar9462_2p0_common_wo_xlna_rx_gain + +#define ar9462_2p1_modes_low_ob_db_tx_gain ar9462_2p0_modes_low_ob_db_tx_gain + +#define ar9462_2p1_modes_high_ob_db_tx_gain ar9462_2p0_modes_high_ob_db_tx_gain + +#define ar9462_2p1_modes_mix_ob_db_tx_gain ar9462_2p0_modes_mix_ob_db_tx_gain + +#define ar9462_2p1_modes_fast_clock ar9462_2p0_modes_fast_clock + +#define ar9462_2p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 + +#define ar9462_2p1_pciephy_clkreq_disable_L1 ar9462_2p0_pciephy_clkreq_disable_L1 + static const u32 ar9462_2p1_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, @@ -183,168 +221,6 @@ static const u32 ar9462_2p1_mac_core[][2] = { {0x000083d0, 0x000301ff}, }; -static const u32 ar9462_2p1_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - -static const u32 ar9462_2p1_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, - {0x00009804, 0xfd14e000}, - {0x00009808, 0x9c0a9f6b}, - {0x0000980c, 0x04900000}, - {0x00009814, 0x9280c00a}, - {0x00009818, 0x00000000}, - {0x0000981c, 0x00020028}, - {0x00009834, 0x6400a290}, - {0x00009838, 0x0108ecff}, - {0x0000983c, 0x0d000600}, - {0x00009880, 0x201fff00}, - {0x00009884, 0x00001042}, - {0x000098a4, 0x00200400}, - {0x000098b0, 0x32440bbe}, - {0x000098d0, 0x004b6a8e}, - {0x000098d4, 0x00000820}, - {0x000098dc, 0x00000000}, - {0x000098e4, 0x01ffffff}, - {0x000098e8, 0x01ffffff}, - {0x000098ec, 0x01ffffff}, - {0x000098f0, 0x00000000}, - {0x000098f4, 0x00000000}, - {0x00009bf0, 0x80000000}, - {0x00009c04, 0xff55ff55}, - {0x00009c08, 0x0320ff55}, - {0x00009c0c, 0x00000000}, - {0x00009c10, 0x00000000}, - {0x00009c14, 0x00046384}, - {0x00009c18, 0x05b6b440}, - {0x00009c1c, 0x00b6b440}, - {0x00009d00, 0xc080a333}, - {0x00009d04, 0x40206c10}, - {0x00009d08, 0x009c4060}, - {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, - {0x00009d14, 0x00c0040b}, - {0x00009d18, 0x00000000}, - {0x00009e08, 0x0038230c}, - {0x00009e24, 0x990bb515}, - {0x00009e28, 0x0c6f0000}, - {0x00009e30, 0x06336f77}, - {0x00009e34, 0x6af6532f}, - {0x00009e38, 0x0cc80c00}, - {0x00009e40, 0x15262820}, - {0x00009e4c, 0x00001004}, - {0x00009e50, 0x00ff03f1}, - {0x00009e54, 0xe4c555c2}, - {0x00009e58, 0xfd857722}, - {0x00009e5c, 0xe9198724}, - {0x00009fc0, 0x803e4788}, - {0x00009fc4, 0x0001efb5}, - {0x00009fcc, 0x40000014}, - {0x00009fd0, 0x0a193b93}, - {0x0000a20c, 0x00000000}, - {0x0000a220, 0x00000000}, - {0x0000a224, 0x00000000}, - {0x0000a228, 0x10002310}, - {0x0000a23c, 0x00000000}, - {0x0000a244, 0x0c000000}, - {0x0000a2a0, 0x00000001}, - {0x0000a2c0, 0x00000001}, - {0x0000a2c8, 0x00000000}, - {0x0000a2cc, 0x18c43433}, - {0x0000a2d4, 0x00000000}, - {0x0000a2ec, 0x00000000}, - {0x0000a2f0, 0x00000000}, - {0x0000a2f4, 0x00000000}, - {0x0000a2f8, 0x00000000}, - {0x0000a344, 0x00000000}, - {0x0000a34c, 0x00000000}, - {0x0000a350, 0x0000a000}, - {0x0000a364, 0x00000000}, - {0x0000a370, 0x00000000}, - {0x0000a390, 0x00000001}, - {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, - {0x0000a3c0, 0x20202020}, - {0x0000a3c4, 0x22222220}, - {0x0000a3c8, 0x20200020}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3d8, 0x20202020}, - {0x0000a3dc, 0x20202020}, - {0x0000a3e0, 0x20202020}, - {0x0000a3e4, 0x20202020}, - {0x0000a3e8, 0x20202020}, - {0x0000a3ec, 0x20202020}, - {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000006}, - {0x0000a3f8, 0x0c9bd380}, - {0x0000a3fc, 0x000f0f01}, - {0x0000a400, 0x8fa91f01}, - {0x0000a404, 0x00000000}, - {0x0000a408, 0x0e79e5c6}, - {0x0000a40c, 0x00820820}, - {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x2d001dce}, - {0x0000a434, 0x00000000}, - {0x0000a438, 0x00001801}, - {0x0000a43c, 0x00100000}, - {0x0000a444, 0x00000000}, - {0x0000a448, 0x05000080}, - {0x0000a44c, 0x00000001}, - {0x0000a450, 0x00010000}, - {0x0000a454, 0x07000000}, - {0x0000a644, 0xbfad9d74}, - {0x0000a648, 0x0048060a}, - {0x0000a64c, 0x00002037}, - {0x0000a670, 0x03020100}, - {0x0000a674, 0x09080504}, - {0x0000a678, 0x0d0c0b0a}, - {0x0000a67c, 0x13121110}, - {0x0000a680, 0x31301514}, - {0x0000a684, 0x35343332}, - {0x0000a688, 0x00000036}, - {0x0000a690, 0x00000838}, - {0x0000a6b0, 0x0000000a}, - {0x0000a6b4, 0x00512c01}, - {0x0000a7c0, 0x00000000}, - {0x0000a7c4, 0xfffffffc}, - {0x0000a7c8, 0x00000000}, - {0x0000a7cc, 0x00000000}, - {0x0000a7d0, 0x00000000}, - {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000000}, - {0x0000a7f0, 0x80000000}, - {0x0000a8d0, 0x004b6a8e}, - {0x0000a8d4, 0x00000820}, - {0x0000a8dc, 0x00000000}, - {0x0000a8f0, 0x00000000}, - {0x0000a8f4, 0x00000000}, - {0x0000abf0, 0x80000000}, - {0x0000b2d0, 0x00000080}, - {0x0000b2d4, 0x00000000}, - {0x0000b2ec, 0x00000000}, - {0x0000b2f0, 0x00000000}, - {0x0000b2f4, 0x00000000}, - {0x0000b2f8, 0x00000000}, - {0x0000b408, 0x0e79e5c0}, - {0x0000b40c, 0x00820820}, - {0x0000b420, 0x00000000}, - {0x0000b6b0, 0x0000000a}, - {0x0000b6b4, 0x00000001}, -}; - static const u32 ar9462_2p1_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, @@ -404,72 +280,6 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = { {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, }; -static const u32 ar9462_2p1_radio_core[][2] = { - /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73f00000}, - {0x0001600c, 0x00000000}, - {0x00016010, 0x6d820001}, - {0x00016040, 0x7f80fff8}, - {0x0001604c, 0x2699e04f}, - {0x00016050, 0x6db6db6c}, - {0x00016058, 0x6c200000}, - {0x00016080, 0x000c0000}, - {0x00016084, 0x9a68048c}, - {0x00016088, 0x54214514}, - {0x0001608c, 0x1203040b}, - {0x00016090, 0x24926490}, - {0x00016098, 0xd2888888}, - {0x000160a0, 0x0a108ffe}, - {0x000160a4, 0x812fc491}, - {0x000160a8, 0x423c8000}, - {0x000160b4, 0x92000000}, - {0x000160b8, 0x0285dddc}, - {0x000160bc, 0x02908888}, - {0x000160c0, 0x00adb6d0}, - {0x000160c4, 0x6db6db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x0de6c1b0}, - {0x00016100, 0x3fffbe04}, - {0x00016104, 0xfff80000}, - {0x00016108, 0x00200400}, - {0x00016110, 0x00000000}, - {0x00016144, 0x02084080}, - {0x00016148, 0x000080c0}, - {0x00016280, 0x050a0001}, - {0x00016284, 0x3d841418}, - {0x00016288, 0x00000000}, - {0x0001628c, 0xe3000000}, - {0x00016290, 0xa1005080}, - {0x00016294, 0x00000020}, - {0x00016298, 0x54a82900}, - {0x00016340, 0x121e4276}, - {0x00016344, 0x00300000}, - {0x00016400, 0x36db6db6}, - {0x00016404, 0x6db6db40}, - {0x00016408, 0x73f00000}, - {0x0001640c, 0x00000000}, - {0x00016410, 0x6c800001}, - {0x00016440, 0x7f80fff8}, - {0x0001644c, 0x4699e04f}, - {0x00016450, 0x6db6db6c}, - {0x00016500, 0x3fffbe04}, - {0x00016504, 0xfff80000}, - {0x00016508, 0x00200400}, - {0x00016510, 0x00000000}, - {0x00016544, 0x02084080}, - {0x00016548, 0x000080c0}, -}; - -static const u32 ar9462_2p1_radio_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524}, - {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70}, - {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, - {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, -}; - static const u32 ar9462_2p1_soc_preamble[][2] = { /* Addr allmodes */ {0x000040a4, 0x00a0c9c9}, @@ -478,1304 +288,4 @@ static const u32 ar9462_2p1_soc_preamble[][2] = { {0x00007038, 0x000004c2}, }; -static const u32 ar9462_2p1_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033}, -}; - -static const u32 ar9462_2p1_radio_postamble_sys2ant[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, - {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, -}; - -static const u32 ar9462_2p1_common_rx_gain[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x2a2d2f32}, - {0x0000b084, 0x21232328}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9462_2p1_common_mixed_rx_gain[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x2a2d2f32}, - {0x0000b084, 0x21232328}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9462_2p1_baseband_core_mix_rxgain[][2] = { - /* Addr allmodes */ - {0x00009fd0, 0x0a2d6b93}, -}; - -static const u32 ar9462_2p1_baseband_postamble_mix_rxgain[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae}, - {0x00009824, 0x63c640de, 0x5ac640d0, 0x63c640da, 0x63c640da}, - {0x00009828, 0x0796be89, 0x0696b081, 0x0916be81, 0x0916be81}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000d8, 0x6c4000d8}, - {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec86d2e}, - {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32395c5e}, -}; - -static const u32 ar9462_2p1_baseband_postamble_5g_xlna[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, -}; - -static const u32 ar9462_2p1_common_wo_xlna_rx_gain[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9462_2p1_common_5g_xlna_only_rx_gain[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x2a2d2f32}, - {0x0000b084, 0x21232328}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9462_2p1_modes_low_ob_db_tx_gain[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, - {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060}, - {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, - {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, - {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000}, - {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, -}; - -static const u32 ar9462_2p1_modes_high_ob_db_tx_gain[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, - {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de}, - {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, - {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, - {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, - {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, - {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84}, - {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0}, - {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4}, - {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, - {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, - {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, - {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, - {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4}, - {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060}, - {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, - {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4}, - {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000}, - {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, -}; - -static const u32 ar9462_2p1_modes_mix_ob_db_tx_gain[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, - {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de}, - {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400}, - {0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402}, - {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, - {0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640}, - {0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec}, - {0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0}, - {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4}, - {0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, - {0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, - {0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, - {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, - {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, - {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, - {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, - {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, -}; - -static const u32 ar9462_2p1_modes_fast_clock[][3] = { - /* Addr 5G_HT20 5G_HT40 */ - {0x00001030, 0x00000268, 0x000004d0}, - {0x00001070, 0x0000018c, 0x00000318}, - {0x000010b0, 0x00000fd0, 0x00001fa0}, - {0x00008014, 0x044c044c, 0x08980898}, - {0x0000801c, 0x148ec02b, 0x148ec057}, - {0x00008318, 0x000044c0, 0x00008980}, - {0x00009e00, 0x0372131c, 0x0372131c}, - {0x0000a230, 0x0000400b, 0x00004016}, - {0x0000a254, 0x00000898, 0x00001130}, -}; - -static const u32 ar9462_2p1_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - -static const u32 ar9462_2p1_pciephy_clkreq_disable_L1[][2] = { - /* Addr allmodes */ - {0x00018c00, 0x18213ede}, - {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0003780c}, -}; - #endif /* INITVALS_9462_2P1_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index bdee2ed67219..d17b7ca72612 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -771,7 +771,7 @@ static const u32 ar9580_1p0_soc_preamble[][2] = { {0x00007048, 0x00000008}, }; -#define ar9580_1p0_rx_gain_table ar9462_common_rx_gain_table_2p0 +#define ar9580_1p0_rx_gain_table ar9462_2p0_common_rx_gain static const u32 ar9580_1p0_radio_core[][2] = { /* Addr allmodes */ -- cgit v1.2.3 From 879fb289ef8436a4672328cc81a1eafd7c9d622a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 27 Nov 2013 13:10:46 +0530 Subject: ath9k: Update initvals for AR9300 v2.2 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 7546b9a7dcbf..15533953e0a2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -352,7 +352,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, + {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, @@ -378,9 +378,9 @@ static const u32 ar9300_2p2_baseband_core[][2] = { {0x00009814, 0x9280c00a}, {0x00009818, 0x00000000}, {0x0000981c, 0x00020028}, - {0x00009834, 0x6400a290}, + {0x00009834, 0x6400a190}, {0x00009838, 0x0108ecff}, - {0x0000983c, 0x0d000600}, + {0x0000983c, 0x14000600}, {0x00009880, 0x201fff00}, {0x00009884, 0x00001042}, {0x000098a4, 0x00200400}, @@ -401,7 +401,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = { {0x00009d04, 0x40206c10}, {0x00009d08, 0x009c4060}, {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, + {0x00009d10, 0x01884061}, {0x00009d14, 0x00c0040b}, {0x00009d18, 0x00000000}, {0x00009e08, 0x0038230c}, @@ -459,7 +459,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = { {0x0000a3e8, 0x20202020}, {0x0000a3ec, 0x20202020}, {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000246}, + {0x0000a3f4, 0x00000000}, {0x0000a3f8, 0x0c9bd380}, {0x0000a3fc, 0x000f0f01}, {0x0000a400, 0x8fa91f01}, @@ -644,7 +644,7 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a410, 0x000050d4, 0x000050d4, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, @@ -1086,8 +1086,8 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { {0x0000b074, 0x00000000}, {0x0000b078, 0x00000000}, {0x0000b07c, 0x00000000}, - {0x0000b080, 0x2a2d2f32}, - {0x0000b084, 0x21232328}, + {0x0000b080, 0x23232323}, + {0x0000b084, 0x21232323}, {0x0000b088, 0x19191c1e}, {0x0000b08c, 0x12141417}, {0x0000b090, 0x07070e0e}, @@ -1385,9 +1385,9 @@ static const u32 ar9300_2p2_mac_core[][2] = { {0x000081f8, 0x00000000}, {0x000081fc, 0x00000000}, {0x00008240, 0x00100000}, - {0x00008244, 0x0010f424}, + {0x00008244, 0x0010f400}, {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e848}, + {0x0000824c, 0x0001e800}, {0x00008250, 0x00000000}, {0x00008254, 0x00000000}, {0x00008258, 0x00000000}, @@ -1726,14 +1726,14 @@ static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { /* Addr allmodes */ - {0x00004040, 0x08253e5e}, + {0x00004040, 0x0825365e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { /* Addr allmodes */ - {0x00004040, 0x08213e5e}, + {0x00004040, 0x0821365e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; -- cgit v1.2.3 From 2d9507c899ab196b3110abd380a417b126b87d5c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 26 Nov 2013 22:00:29 +0530 Subject: ath9k: Update initvals for AR9580 v1.0 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9580_1p0_initvals.h | 559 ++++++++++++++------- 1 file changed, 386 insertions(+), 173 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index d17b7ca72612..2ae380b70c02 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -20,18 +20,34 @@ /* AR9580 1.0 */ +#define ar9580_1p0_soc_preamble ar9300_2p2_soc_preamble + +#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble + +#define ar9580_1p0_radio_core ar9300_2p2_radio_core + +#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble + +#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 + +#define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2 + +#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2 + #define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 +#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 + static const u32 ar9580_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, - {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000}, {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000}, {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000}, {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, }; @@ -44,9 +60,9 @@ static const u32 ar9580_1p0_baseband_core[][2] = { {0x00009814, 0x3280c00a}, {0x00009818, 0x00000000}, {0x0000981c, 0x00020028}, - {0x00009834, 0x6400a290}, + {0x00009834, 0x6400a190}, {0x00009838, 0x0108ecff}, - {0x0000983c, 0x0d000600}, + {0x0000983c, 0x14000600}, {0x00009880, 0x201fff00}, {0x00009884, 0x00001042}, {0x000098a4, 0x00200400}, @@ -67,7 +83,7 @@ static const u32 ar9580_1p0_baseband_core[][2] = { {0x00009d04, 0x40206c10}, {0x00009d08, 0x009c4060}, {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, + {0x00009d10, 0x01884061}, {0x00009d14, 0x00c0040b}, {0x00009d18, 0x00000000}, {0x00009e08, 0x0038230c}, @@ -198,8 +214,6 @@ static const u32 ar9580_1p0_baseband_core[][2] = { {0x0000c420, 0x00000000}, }; -#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble - static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, @@ -306,7 +320,112 @@ static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -#define ar9580_1p0_high_power_tx_gain_table ar9580_1p0_low_ob_db_tx_gain_table +static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, + {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, + {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, + {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, + {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, + {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, + {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, + {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, + {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, + {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016288, 0x05a2040a, 0x05a2040a, 0x05a20408, 0x05a20408}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ @@ -414,8 +533,6 @@ static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 - static const u32 ar9580_1p0_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, @@ -679,14 +796,6 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 - -#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble - -#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2 - -#define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2 - static const u32 ar9580_1p0_type6_tx_gain_table[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, @@ -761,160 +870,264 @@ static const u32 ar9580_1p0_type6_tx_gain_table[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -static const u32 ar9580_1p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x000040a4, 0x00a0c1c9}, - {0x00007008, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00007048, 0x00000008}, -}; - -#define ar9580_1p0_rx_gain_table ar9462_2p0_common_rx_gain - -static const u32 ar9580_1p0_radio_core[][2] = { +static const u32 ar9580_1p0_rx_gain_table[][2] = { /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73f00000}, - {0x0001600c, 0x00000000}, - {0x00016040, 0x7f80fff8}, - {0x0001604c, 0x76d005b5}, - {0x00016050, 0x556cf031}, - {0x00016054, 0x13449440}, - {0x00016058, 0x0c51c92c}, - {0x0001605c, 0x3db7fffc}, - {0x00016060, 0xfffffffc}, - {0x00016064, 0x000f0278}, - {0x0001606c, 0x6db60000}, - {0x00016080, 0x00000000}, - {0x00016084, 0x0e48048c}, - {0x00016088, 0x54214514}, - {0x0001608c, 0x119f481e}, - {0x00016090, 0x24926490}, - {0x00016098, 0xd2888888}, - {0x000160a0, 0x0a108ffe}, - {0x000160a4, 0x812fc370}, - {0x000160a8, 0x423c8000}, - {0x000160b4, 0x92480080}, - {0x000160c0, 0x00adb6d0}, - {0x000160c4, 0x6db6db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x01e6c000}, - {0x00016100, 0x3fffbe01}, - {0x00016104, 0xfff80000}, - {0x00016108, 0x00080010}, - {0x00016144, 0x02084080}, - {0x00016148, 0x00000000}, - {0x00016280, 0x058a0001}, - {0x00016284, 0x3d840208}, - {0x00016288, 0x05a20408}, - {0x0001628c, 0x00038c07}, - {0x00016290, 0x00000004}, - {0x00016294, 0x458aa14f}, - {0x00016380, 0x00000000}, - {0x00016384, 0x00000000}, - {0x00016388, 0x00800700}, - {0x0001638c, 0x00800700}, - {0x00016390, 0x00800700}, - {0x00016394, 0x00000000}, - {0x00016398, 0x00000000}, - {0x0001639c, 0x00000000}, - {0x000163a0, 0x00000001}, - {0x000163a4, 0x00000001}, - {0x000163a8, 0x00000000}, - {0x000163ac, 0x00000000}, - {0x000163b0, 0x00000000}, - {0x000163b4, 0x00000000}, - {0x000163b8, 0x00000000}, - {0x000163bc, 0x00000000}, - {0x000163c0, 0x000000a0}, - {0x000163c4, 0x000c0000}, - {0x000163c8, 0x14021402}, - {0x000163cc, 0x00001402}, - {0x000163d0, 0x00000000}, - {0x000163d4, 0x00000000}, - {0x00016400, 0x36db6db6}, - {0x00016404, 0x6db6db40}, - {0x00016408, 0x73f00000}, - {0x0001640c, 0x00000000}, - {0x00016440, 0x7f80fff8}, - {0x0001644c, 0x76d005b5}, - {0x00016450, 0x556cf031}, - {0x00016454, 0x13449440}, - {0x00016458, 0x0c51c92c}, - {0x0001645c, 0x3db7fffc}, - {0x00016460, 0xfffffffc}, - {0x00016464, 0x000f0278}, - {0x0001646c, 0x6db60000}, - {0x00016500, 0x3fffbe01}, - {0x00016504, 0xfff80000}, - {0x00016508, 0x00080010}, - {0x00016544, 0x02084080}, - {0x00016548, 0x00000000}, - {0x00016780, 0x00000000}, - {0x00016784, 0x00000000}, - {0x00016788, 0x00800700}, - {0x0001678c, 0x00800700}, - {0x00016790, 0x00800700}, - {0x00016794, 0x00000000}, - {0x00016798, 0x00000000}, - {0x0001679c, 0x00000000}, - {0x000167a0, 0x00000001}, - {0x000167a4, 0x00000001}, - {0x000167a8, 0x00000000}, - {0x000167ac, 0x00000000}, - {0x000167b0, 0x00000000}, - {0x000167b4, 0x00000000}, - {0x000167b8, 0x00000000}, - {0x000167bc, 0x00000000}, - {0x000167c0, 0x000000a0}, - {0x000167c4, 0x000c0000}, - {0x000167c8, 0x14021402}, - {0x000167cc, 0x00001402}, - {0x000167d0, 0x00000000}, - {0x000167d4, 0x00000000}, - {0x00016800, 0x36db6db6}, - {0x00016804, 0x6db6db40}, - {0x00016808, 0x73f00000}, - {0x0001680c, 0x00000000}, - {0x00016840, 0x7f80fff8}, - {0x0001684c, 0x76d005b5}, - {0x00016850, 0x556cf031}, - {0x00016854, 0x13449440}, - {0x00016858, 0x0c51c92c}, - {0x0001685c, 0x3db7fffc}, - {0x00016860, 0xfffffffc}, - {0x00016864, 0x000f0278}, - {0x0001686c, 0x6db60000}, - {0x00016900, 0x3fffbe01}, - {0x00016904, 0xfff80000}, - {0x00016908, 0x00080010}, - {0x00016944, 0x02084080}, - {0x00016948, 0x00000000}, - {0x00016b80, 0x00000000}, - {0x00016b84, 0x00000000}, - {0x00016b88, 0x00800700}, - {0x00016b8c, 0x00800700}, - {0x00016b90, 0x00800700}, - {0x00016b94, 0x00000000}, - {0x00016b98, 0x00000000}, - {0x00016b9c, 0x00000000}, - {0x00016ba0, 0x00000001}, - {0x00016ba4, 0x00000001}, - {0x00016ba8, 0x00000000}, - {0x00016bac, 0x00000000}, - {0x00016bb0, 0x00000000}, - {0x00016bb4, 0x00000000}, - {0x00016bb8, 0x00000000}, - {0x00016bbc, 0x00000000}, - {0x00016bc0, 0x000000a0}, - {0x00016bc4, 0x000c0000}, - {0x00016bc8, 0x14021402}, - {0x00016bcc, 0x00001402}, - {0x00016bd0, 0x00000000}, - {0x00016bd4, 0x00000000}, + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x01910190}, + {0x0000a030, 0x01930192}, + {0x0000a034, 0x01950194}, + {0x0000a038, 0x038a0196}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x22222229}, + {0x0000a084, 0x1d1d1d1d}, + {0x0000a088, 0x1d1d1d1d}, + {0x0000a08c, 0x1d1d1d1d}, + {0x0000a090, 0x171d1d1d}, + {0x0000a094, 0x11111717}, + {0x0000a098, 0x00030311}, + {0x0000a09c, 0x00000000}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x23232323}, + {0x0000b084, 0x21232323}, + {0x0000b088, 0x19191c1e}, + {0x0000b08c, 0x12141417}, + {0x0000b090, 0x07070e0e}, + {0x0000b094, 0x03030305}, + {0x0000b098, 0x00000003}, + {0x0000b09c, 0x00000000}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, }; static const u32 ar9580_1p0_baseband_postamble[][5] = { @@ -956,7 +1169,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = { {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, + {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, -- cgit v1.2.3 From 40cc87de93ebb9122f6fcddd799ea18145f0bdab Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 2 Dec 2013 09:27:24 +0530 Subject: ath9k: Update AR9340 initvals * Baseband updates * Remove ar9340Common_rx_gain_table_1p0 since it is a duplicate. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9340_initvals.h | 286 ++--------------------- 1 file changed, 14 insertions(+), 272 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index 182bf90ab809..d2d789bdb7f8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h @@ -18,6 +18,16 @@ #ifndef INITVALS_9340_H #define INITVALS_9340_H +#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble + +#define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble + +#define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2 + +#define ar9340Common_rx_gain_table_1p0 ar9300Common_rx_gain_table_2p2 + +#define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2 + static const u32 ar9340_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, @@ -100,8 +110,6 @@ static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, }; -#define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2 - static const u32 ar9340_1p0_radio_core[][2] = { /* Addr allmodes */ {0x00016000, 0x36db6db6}, @@ -215,16 +223,12 @@ static const u32 ar9340_1p0_radio_core_40M[][2] = { {0x0000824c, 0x0001e800}, }; -#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble - -#define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble - static const u32 ar9340_1p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x00009828, 0x06903081, 0x06903081, 0x09103881, 0x09103881}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, @@ -340,9 +344,9 @@ static const u32 ar9340_1p0_baseband_core[][2] = { {0x0000a370, 0x00000000}, {0x0000a390, 0x00000001}, {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, + {0x0000a398, 0x00000000}, + {0x0000a39c, 0x210d0401}, + {0x0000a3a0, 0xab9a7144}, {0x0000a3a4, 0x00000000}, {0x0000a3a8, 0xaaaaaaaa}, {0x0000a3ac, 0x3c466478}, @@ -714,266 +718,6 @@ static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000}, }; -static const u32 ar9340Common_rx_gain_table_1p0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x23232323}, - {0x0000b084, 0x21232323}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, @@ -1437,8 +1181,6 @@ static const u32 ar9340_1p0_mac_core[][2] = { {0x000083d0, 0x000101ff}, }; -#define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2 - static const u32 ar9340_1p0_soc_preamble[][2] = { /* Addr allmodes */ {0x00007008, 0x00000000}, -- cgit v1.2.3 From 2c8672c13a206fdf1df1f9c5c57f361a7d3f5594 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 2 Dec 2013 09:56:31 +0530 Subject: ath9k: Fix initvals for freq 2484 This is missing for AR9300, AR9580 and AR9340. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 7 +++++++ drivers/net/wireless/ath/ath9k/ar9003_hw.c | 12 +++++++++--- drivers/net/wireless/ath/ath9k/ar9340_initvals.h | 2 ++ drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 15533953e0a2..e7cdf1100f56 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1738,4 +1738,11 @@ static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { {0x00004044, 0x00000000}, }; +static const u32 ar9300_2p2_baseband_core_txfir_coeff_japan_2484[][2] = { + /* Addr allmodes */ + {0x0000a398, 0x00000000}, + {0x0000a39c, 0x6f7f0301}, + {0x0000a3a0, 0xca9228ee}, +}; + #endif /* INITVALS_9003_2P2_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index d3eca0cec9cd..d8c1eee8ea53 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -149,7 +149,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9340Modes_high_ob_db_tx_gain_table_1p0); INIT_INI_ARRAY(&ah->iniModesFastClock, - ar9340Modes_fast_clock_1p0); + ar9340Modes_fast_clock_1p0); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9340_1p0_baseband_core_txfir_coeff_japan_2484); if (!ah->is_clk_25mhz) INIT_INI_ARRAY(&ah->iniAdditional, @@ -335,7 +337,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9580_1p0_low_ob_db_tx_gain_table); INIT_INI_ARRAY(&ah->iniModesFastClock, - ar9580_1p0_modes_fast_clock); + ar9580_1p0_modes_fast_clock); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9580_1p0_baseband_core_txfir_coeff_japan_2484); } else if (AR_SREV_9565_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9565_1p1_mac_core); @@ -451,7 +455,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) /* Fast clock modal settings */ INIT_INI_ARRAY(&ah->iniModesFastClock, - ar9300Modes_fast_clock_2p2); + ar9300Modes_fast_clock_2p2); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9300_2p2_baseband_core_txfir_coeff_japan_2484); } } diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index d2d789bdb7f8..7f22cb2a4941 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h @@ -28,6 +28,8 @@ #define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2 +#define ar9340_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 + static const u32 ar9340_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index 2ae380b70c02..75bef1179d0d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -36,7 +36,7 @@ #define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 -#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 +#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 static const u32 ar9580_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- cgit v1.2.3 From 1e86d69662d7d86360624f74bbe1b5fa1b8ffb13 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 29 Nov 2013 11:48:13 +0100 Subject: brcmfmac: Update fwsignal to fix out of order tx. When using fwsignal it is possible that tx packets get delivered out of order. This patch fixes that by reordering suppressed packets and tracking generation bit and sequence number per packet. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 167 ++++++++++++++++++--- 1 file changed, 146 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index d0cd0bf95c5a..784cf94072ea 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -105,6 +105,9 @@ static struct { }; #undef BRCMF_FWS_TLV_DEF +#define BRCMF_FWS_TYPE_SEQ_LEN 2 + + static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) { int i; @@ -147,8 +150,15 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01 #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02 -#define BRCMF_FWS_RET_OK_NOSCHEDULE 0 -#define BRCMF_FWS_RET_OK_SCHEDULE 1 +#define BRCMF_FWS_RET_OK_NOSCHEDULE 0 +#define BRCMF_FWS_RET_OK_SCHEDULE 1 + +#define BRCMF_FWS_MODE_REUSESEQ_SHIFT 3 /* seq reuse */ +#define BRCMF_FWS_MODE_SET_REUSESEQ(x, val) ((x) = \ + ((x) & ~(1 << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) | \ + (((val) & 1) << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) +#define BRCMF_FWS_MODE_GET_REUSESEQ(x) \ + (((x) >> BRCMF_FWS_MODE_REUSESEQ_SHIFT) & 1) /** * enum brcmf_fws_skb_state - indicates processing state of skb. @@ -171,6 +181,7 @@ enum brcmf_fws_skb_state { * @bus_flags: 2 bytes reserved for bus specific parameters * @if_flags: holds interface index and packet related flags. * @htod: host to device packet identifier (used in PKTTAG tlv). + * @htod_seq: this 16-bit is original seq number for every suppress packet. * @state: transmit state of the packet. * @mac: descriptor related to destination for this packet. * @@ -181,6 +192,7 @@ struct brcmf_skbuff_cb { u16 bus_flags; u16 if_flags; u32 htod; + u16 htod_seq; enum brcmf_fws_skb_state state; struct brcmf_fws_mac_descriptor *mac; }; @@ -257,6 +269,22 @@ struct brcmf_skbuff_cb { BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) +#define BRCMF_SKB_HTOD_SEQ_FROMFW_MASK 0x2000 +#define BRCMF_SKB_HTOD_SEQ_FROMFW_SHIFT 13 +#define BRCMF_SKB_HTOD_SEQ_FROMDRV_MASK 0x1000 +#define BRCMF_SKB_HTOD_SEQ_FROMDRV_SHIFT 12 +#define BRCMF_SKB_HTOD_SEQ_NR_MASK 0x0fff +#define BRCMF_SKB_HTOD_SEQ_NR_SHIFT 0 + +#define brcmf_skb_htod_seq_set_field(skb, field, value) \ + brcmu_maskset16(&(brcmf_skbcb(skb)->htod_seq), \ + BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \ + BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT, (value)) +#define brcmf_skb_htod_seq_get_field(skb, field) \ + brcmu_maskget16(brcmf_skbcb(skb)->htod_seq, \ + BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \ + BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT) + #define BRCMF_FWS_TXSTAT_GENERATION_MASK 0x80000000 #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT 31 #define BRCMF_FWS_TXSTAT_FLAGS_MASK 0x78000000 @@ -265,8 +293,8 @@ struct brcmf_skbuff_cb { #define BRCMF_FWS_TXSTAT_FIFO_SHIFT 24 #define BRCMF_FWS_TXSTAT_HSLOT_MASK 0x00FFFF00 #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT 8 -#define BRCMF_FWS_TXSTAT_PKTID_MASK 0x00FFFFFF -#define BRCMF_FWS_TXSTAT_PKTID_SHIFT 0 +#define BRCMF_FWS_TXSTAT_FREERUN_MASK 0x000000FF +#define BRCMF_FWS_TXSTAT_FREERUN_SHIFT 0 #define brcmf_txstatus_get_field(txs, field) \ brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \ @@ -443,6 +471,7 @@ struct brcmf_fws_info { unsigned long borrow_defer_timestamp; bool bus_flow_blocked; bool creditmap_received; + u8 mode; }; /* @@ -812,13 +841,16 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) u16 data_offset = 0; u8 fillers; __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); + __le16 pktseq = cpu_to_le16(brcmf_skbcb(skb)->htod_seq); - brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n", + brcmf_dbg(TRACE, "enter: %s, idx=%d hslot=%d htod %X seq %X\n", entry->name, brcmf_skb_if_flags_get_field(skb, INDEX), - le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff); + (le32_to_cpu(pkttag) >> 8) & 0xffff, + brcmf_skbcb(skb)->htod, brcmf_skbcb(skb)->htod_seq); if (entry->send_tim_signal) data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; - + if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) + data_offset += BRCMF_FWS_TYPE_SEQ_LEN; /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; fillers = round_up(data_offset, 4) - data_offset; @@ -830,7 +862,12 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) wlh[0] = BRCMF_FWS_TYPE_PKTTAG; wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; memcpy(&wlh[2], &pkttag, sizeof(pkttag)); - wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2; + if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) { + wlh[1] += BRCMF_FWS_TYPE_SEQ_LEN; + memcpy(&wlh[2 + BRCMF_FWS_TYPE_PKTTAG_LEN], &pktseq, + sizeof(pktseq)); + } + wlh += wlh[1] + 2; if (entry->send_tim_signal) { entry->send_tim_signal = 0; @@ -875,6 +912,7 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, /* create a dummy packet and sent that. The traffic */ /* bitmap info will automatically be attached to that packet */ len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 + + BRCMF_FWS_TYPE_SEQ_LEN + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 + 4 + fws->drvr->hdrlen; skb = brcmu_pkt_buf_get_skb(len); @@ -884,6 +922,8 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, skcb = brcmf_skbcb(skb); skcb->mac = entry; skcb->state = BRCMF_FWS_SKBSTATE_TIM; + skcb->htod = 0; + skcb->htod_seq = 0; bus = fws->drvr->bus_if; err = brcmf_fws_hdrpush(fws, skb); if (err == 0) { @@ -1172,8 +1212,13 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, { int prec = 2 * fifo; u32 *qfull_stat = &fws->stats.delayq_full_error; - struct brcmf_fws_mac_descriptor *entry; + struct pktq *pq; + struct sk_buff_head *queue; + struct sk_buff *p_head; + struct sk_buff *p_tail; + u32 fr_new; + u32 fr_compare; entry = brcmf_skbcb(p)->mac; if (entry == NULL) { @@ -1185,9 +1230,55 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { prec += 1; qfull_stat = &fws->stats.supprq_full_error; - } - if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) { + /* Fix out of order delivery of frames. Dont assume frame */ + /* can be inserted at the end, but look for correct position */ + pq = &entry->psq; + if (pktq_full(pq) || pktq_pfull(pq, prec)) { + *qfull_stat += 1; + return -ENFILE; + } + queue = &pq->q[prec].skblist; + + p_head = skb_peek(queue); + p_tail = skb_peek_tail(queue); + fr_new = brcmf_skb_htod_tag_get_field(p, FREERUN); + + while (p_head != p_tail) { + fr_compare = brcmf_skb_htod_tag_get_field(p_tail, + FREERUN); + /* be sure to handle wrap of 256 */ + if (((fr_new > fr_compare) && + ((fr_new - fr_compare) < 128)) || + ((fr_new < fr_compare) && + ((fr_compare - fr_new) > 128))) + break; + p_tail = skb_queue_prev(queue, p_tail); + } + /* Position found. Determine what to do */ + if (p_tail == NULL) { + /* empty list */ + __skb_queue_tail(queue, p); + } else { + fr_compare = brcmf_skb_htod_tag_get_field(p_tail, + FREERUN); + if (((fr_new > fr_compare) && + ((fr_new - fr_compare) < 128)) || + ((fr_new < fr_compare) && + ((fr_compare - fr_new) > 128))) { + /* After tail */ + __skb_queue_after(queue, p_tail, p); + } else { + /* Before tail */ + __skb_insert(p, p_tail->prev, p_tail, queue); + } + } + + /* Complete the counters and statistics */ + pq->len++; + if (pq->hi_prec < prec) + pq->hi_prec = (u8) prec; + } else if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) { *qfull_stat += 1; return -ENFILE; } @@ -1277,7 +1368,8 @@ done: } static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, - struct sk_buff *skb, u32 genbit) + struct sk_buff *skb, u32 genbit, + u16 seq) { struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; u32 hslot; @@ -1298,6 +1390,14 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); if (ret == 0) + brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); + brcmf_skbcb(skb)->htod_seq = seq; + if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { + brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1); + brcmf_skb_htod_seq_set_field(skb, FROMFW, 0); + } else { + brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0); + } ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb); if (ret != 0) { @@ -1317,7 +1417,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, static int brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, - u32 genbit) + u32 genbit, u16 seq) { u32 fifo; int ret; @@ -1360,8 +1460,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, if (entry->suppressed && entry->suppr_transit_count) entry->suppr_transit_count--; - brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, - skcb->htod); + brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags, + skcb->htod, seq); /* pick up the implicit credit from this packet */ fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); @@ -1374,7 +1474,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, brcmf_fws_macdesc_return_req_credit(skb); if (!remove_from_hanger) - ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); + ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit, + seq); if (remove_from_hanger || ret) brcmf_txfinalize(fws->drvr, skb, true); @@ -1406,10 +1507,12 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) { __le32 status_le; + __le16 seq_le; u32 status; u32 hslot; u32 genbit; u8 flags; + u16 seq; fws->stats.txs_indicate++; memcpy(&status_le, data, sizeof(status_le)); @@ -1417,9 +1520,16 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) flags = brcmf_txstatus_get_field(status, FLAGS); hslot = brcmf_txstatus_get_field(status, HSLOT); genbit = brcmf_txstatus_get_field(status, GENERATION); + if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) { + memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN], + sizeof(seq_le)); + seq = le16_to_cpu(seq_le); + } else { + seq = 0; + } brcmf_fws_lock(fws); - brcmf_fws_txs_process(fws, flags, hslot, genbit); + brcmf_fws_txs_process(fws, flags, hslot, genbit, seq); brcmf_fws_unlock(fws); return BRCMF_FWS_RET_OK_NOSCHEDULE; } @@ -1610,8 +1720,8 @@ static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, struct brcmf_fws_mac_descriptor *entry = skcb->mac; u8 flags; - brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); - brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); + if (skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED) + brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; if (brcmf_skb_if_flags_get_field(p, REQUESTED)) { /* @@ -1652,7 +1762,7 @@ static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, fws->stats.rollback_failed++; hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, - hslot, 0); + hslot, 0, 0); } else { fws->stats.rollback_success++; brcmf_fws_return_credits(fws, fifo, 1); @@ -1732,6 +1842,8 @@ static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p, struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); int rc, hslot; + skcb->htod = 0; + skcb->htod_seq = 0; hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]); @@ -1908,6 +2020,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr) struct brcmf_fws_info *fws; u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; int rc; + u32 mode; drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); if (!drvr->fws) { @@ -1966,6 +2079,18 @@ int brcmf_fws_init(struct brcmf_pub *drvr) if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); + /* Enable seq number reuse, if supported */ + if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) { + if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) { + mode = 0; + BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1); + if (brcmf_fil_iovar_int_set(drvr->iflist[0], + "wlfc_mode", mode) == 0) { + BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1); + } + } + } + brcmf_fws_hanger_init(&fws->hanger); brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0); brcmf_fws_macdesc_set_name(fws, &fws->desc.other); @@ -2022,7 +2147,7 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) } brcmf_fws_lock(fws); hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); - brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0); + brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0); brcmf_fws_unlock(fws); } -- cgit v1.2.3 From 8dee77bab2eda24b48bfb8aecf5ac1370e424416 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 11:48:14 +0100 Subject: brcmfmac: add separate function for passing bus tx overhead The common driver needs the packet overhead for the bus in order to reserve headroom for sk_buffs. For the SDIO driver this depends on firmware features so it is not possible to provide it in the brcmf_attach() call. Reviewed-by: Franky Lin Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 3 ++- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 14 ++++++++++++-- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 4 +++- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 4 ++-- 4 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index a6eb09e5d46f..a129d21498ff 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -139,7 +139,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); /* Indication from bus module regarding presence/insertion of dongle. */ -int brcmf_attach(uint bus_hdrlen, struct device *dev); +int brcmf_attach(struct device *dev); /* Indication from bus module regarding removal/absence of dongle */ void brcmf_detach(struct device *dev); /* Indication from bus module that dongle should be reset */ @@ -151,6 +151,7 @@ void brcmf_txflowblock(struct device *dev, bool state); void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); int brcmf_bus_start(struct device *dev); +void brcmf_bus_add_txhdrlen(struct device *dev, uint len); #ifdef CONFIG_BRCMFMAC_SDIO void brcmf_sdio_exit(void); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 64e9cff241b9..0c4c2306647d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -1016,7 +1016,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) } } -int brcmf_attach(uint bus_hdrlen, struct device *dev) +int brcmf_attach(struct device *dev) { struct brcmf_pub *drvr = NULL; int ret = 0; @@ -1031,7 +1031,7 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) mutex_init(&drvr->proto_block); /* Link to bus module */ - drvr->hdrlen = bus_hdrlen; + drvr->hdrlen = 0; drvr->bus_if = dev_get_drvdata(dev); drvr->bus_if->drvr = drvr; @@ -1138,6 +1138,16 @@ fail: return 0; } +void brcmf_bus_add_txhdrlen(struct device *dev, uint len) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; + + if (drvr) { + drvr->hdrlen += len; + } +} + static void brcmf_bus_detach(struct brcmf_pub *drvr) { brcmf_dbg(TRACE, "Enter\n"); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index b02953c4ade7..928983be800b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -3983,7 +3983,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; /* Attach to the common layer, reserve hdr space */ - ret = brcmf_attach(bus->tx_hdrlen, bus->sdiodev->dev); + ret = brcmf_attach(bus->sdiodev->dev); if (ret != 0) { brcmf_err("brcmf_attach failed\n"); goto fail; @@ -4027,6 +4027,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list); } + brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); + /* if firmware path present try to download and bring up bus */ ret = brcmf_bus_start(bus->sdiodev->dev); if (ret != 0) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 422f44c63175..51c4de054b15 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -1255,7 +1255,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) bus->chiprev = bus_pub->chiprev; /* Attach to the common driver interface */ - ret = brcmf_attach(0, dev); + ret = brcmf_attach(dev); if (ret) { brcmf_err("brcmf_attach failed\n"); goto fail; @@ -1454,7 +1454,7 @@ static int brcmf_usb_resume(struct usb_interface *intf) struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); brcmf_dbg(USB, "Enter\n"); - if (!brcmf_attach(0, devinfo->dev)) + if (!brcmf_attach(devinfo->dev)) return brcmf_bus_start(&usb->dev); return 0; -- cgit v1.2.3 From cf4582875a77c13adf8fec79b8ab3896d2b38e97 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 11:48:15 +0100 Subject: brcmfmac: replace dongle command list with .preinit() callback The bus-specific interface allowed a list of dongle commands to be provided to the common driver part. However, upcoming functionality requires a more dynamic behaviour. Hence the list is replaced by a new callback function so the bus-specific driver part can implement this behaviour. Reviewed-by: Franky Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 12 ++++- .../net/wireless/brcm80211/brcmfmac/dhd_common.c | 15 +----- .../net/wireless/brcm80211/brcmfmac/dhd_linux.c | 10 +++- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 58 +++++++++++----------- 4 files changed, 51 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index a129d21498ff..6a54905528be 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -34,6 +34,7 @@ struct brcmf_bus_dcmd { /** * struct brcmf_bus_ops - bus callback operations. * + * @preinit: execute bus/device specific dongle init commands (optional). * @init: prepare for communication with dongle. * @stop: clear pending frames, disable data flow. * @txdata: send a data frame to the dongle. When the data @@ -51,6 +52,7 @@ struct brcmf_bus_dcmd { * indicated otherwise these callbacks are mandatory. */ struct brcmf_bus_ops { + int (*preinit)(struct device *dev); int (*init)(struct device *dev); void (*stop)(struct device *dev); int (*txdata)(struct device *dev, struct sk_buff *skb); @@ -85,7 +87,6 @@ struct brcmf_bus { unsigned long tx_realloc; u32 chip; u32 chiprev; - struct list_head dcmd_list; struct brcmf_bus_ops *ops; }; @@ -93,6 +94,13 @@ struct brcmf_bus { /* * callback wrappers */ +static inline int brcmf_bus_preinit(struct brcmf_bus *bus) +{ + if (!bus->ops->preinit) + return 0; + return bus->ops->preinit(bus->dev); +} + static inline int brcmf_bus_init(struct brcmf_bus *bus) { return bus->ops->init(bus->dev); @@ -151,6 +159,8 @@ void brcmf_txflowblock(struct device *dev, bool state); void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); int brcmf_bus_start(struct device *dev); +s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, + u32 len); void brcmf_bus_add_txhdrlen(struct device *dev, uint len); #ifdef CONFIG_BRCMFMAC_SDIO diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 9431af2465f3..5c0c9191b794 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -257,8 +257,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) u8 buf[BRCMF_DCMD_SMLEN]; char *ptr; s32 err; - struct brcmf_bus_dcmd *cmdlst; - struct list_head *cur, *q; /* retreive mac address */ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, @@ -342,17 +340,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, 0, true); - /* set bus specific command if there is any */ - list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) { - cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); - if (cmdlst->name && cmdlst->param && cmdlst->param_len) { - brcmf_fil_iovar_data_set(ifp, cmdlst->name, - cmdlst->param, - cmdlst->param_len); - } - list_del(cur); - kfree(cmdlst); - } + /* do bus specific preinit here */ + err = brcmf_bus_preinit(ifp->drvr->bus_if); done: return err; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 0c4c2306647d..ab207e22e515 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -1048,8 +1048,6 @@ int brcmf_attach(struct device *dev) /* attach firmware event handler */ brcmf_fweh_attach(drvr); - INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); - return ret; fail: @@ -1206,6 +1204,14 @@ void brcmf_detach(struct device *dev) kfree(drvr); } +s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_if *ifp = bus_if->drvr->iflist[0]; + + return brcmf_fil_iovar_data_set(ifp, name, data, len); +} + static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) { return atomic_read(&ifp->pend_8021x_cnt); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 928983be800b..2597a534e694 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -3425,6 +3425,35 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) return ret; } +static int brcmf_sdbrcm_bus_preinit(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; + u32 value; + u8 idx; + int err; + + /* sdio bus core specific dcmd */ + idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); + if (bus->ci->c_inf[idx].rev < 12) { + /* for sdio core rev < 12, disable txgloming */ + value = 0; + err = brcmf_iovar_data_set(dev, "bus:txglom", &value, + sizeof(u32)); + } else { + /* otherwise, set txglomalign */ + value = 4; + if (sdiodev->pdata) + value = sdiodev->pdata->sd_sgentry_align; + /* SDIO ADMA requires at least 32 bit alignment */ + value = max_t(u32, value, 4); + err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, + sizeof(u32)); + } + return err; +} + static int brcmf_sdbrcm_bus_init(struct device *dev) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -3905,6 +3934,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) static struct brcmf_bus_ops brcmf_sdio_bus_ops = { .stop = brcmf_sdbrcm_bus_stop, + .preinit = brcmf_sdbrcm_bus_preinit, .init = brcmf_sdbrcm_bus_init, .txdata = brcmf_sdbrcm_bus_txdata, .txctl = brcmf_sdbrcm_bus_txctl, @@ -3916,10 +3946,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) { int ret; struct brcmf_sdio *bus; - struct brcmf_bus_dcmd *dlst; - u32 dngl_txglom; - u32 txglomalign = 0; - u8 idx; brcmf_dbg(TRACE, "Enter\n"); @@ -4003,30 +4029,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) brcmf_sdio_debugfs_create(bus); brcmf_dbg(INFO, "completed!!\n"); - /* sdio bus core specific dcmd */ - idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); - dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL); - if (dlst) { - if (bus->ci->c_inf[idx].rev < 12) { - /* for sdio core rev < 12, disable txgloming */ - dngl_txglom = 0; - dlst->name = "bus:txglom"; - dlst->param = (char *)&dngl_txglom; - dlst->param_len = sizeof(u32); - } else { - /* otherwise, set txglomalign */ - if (sdiodev->pdata) - txglomalign = sdiodev->pdata->sd_sgentry_align; - /* SDIO ADMA requires at least 32 bit alignment */ - if (txglomalign < 4) - txglomalign = 4; - dlst->name = "bus:txglomalign"; - dlst->param = (char *)&txglomalign; - dlst->param_len = sizeof(u32); - } - list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list); - } - brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); /* if firmware path present try to download and bring up bus */ -- cgit v1.2.3 From dcede4b8767dc4b12ce6324ac772776ae9f28569 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 11:48:16 +0100 Subject: brcmfmac: start netif queues only when setup is completed successful Moving the call to netif_start_queue() after brcmf_cfg80211_up() is completed successful. If not return -EIO instead of -1 as that results in 'Operation not permitted' which can put user on wrong track. Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index ab207e22e515..f4eeaa1b7319 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -769,7 +769,6 @@ static int brcmf_netdev_open(struct net_device *ndev) struct brcmf_pub *drvr = ifp->drvr; struct brcmf_bus *bus_if = drvr->bus_if; u32 toe_ol; - s32 ret = 0; brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); @@ -788,14 +787,14 @@ static int brcmf_netdev_open(struct net_device *ndev) else ndev->features &= ~NETIF_F_IP_CSUM; - /* Allow transmit calls */ - netif_start_queue(ndev); if (brcmf_cfg80211_up(ndev)) { brcmf_err("failed to bring up cfg80211\n"); - return -1; + return -EIO; } - return ret; + /* Allow transmit calls */ + netif_start_queue(ndev); + return 0; } static const struct net_device_ops brcmf_netdev_ops_pri = { -- cgit v1.2.3 From 15265f95c2020940350b2febbc513cbbeae0f77e Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Fri, 29 Nov 2013 11:48:17 +0100 Subject: brcmfmac: remove empty brcmf_proto_stop remove empty brcmf_proto_stop from protocol layer Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend Van Spriel Reviewed-by: Hante Meuleman Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | 5 ----- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 3 --- drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h | 3 --- 3 files changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index dd85401063cb..42aaf104cc44 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -385,8 +385,3 @@ void brcmf_proto_detach(struct brcmf_pub *drvr) kfree(drvr->prot); drvr->prot = NULL; } - -void brcmf_proto_stop(struct brcmf_pub *drvr) -{ - /* Nothing to do for CDC */ -} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index f4eeaa1b7319..c34ca703d2a3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -1150,9 +1150,6 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr) brcmf_dbg(TRACE, "Enter\n"); if (drvr) { - /* Stop the protocol module */ - brcmf_proto_stop(drvr); - /* Stop the bus module */ brcmf_bus_stop(drvr->bus_if); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h index 53c6e710f2cb..d633362a52d0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h @@ -27,9 +27,6 @@ int brcmf_proto_attach(struct brcmf_pub *drvr); /* Unlink, frees allocated protocol memory (including brcmf_proto) */ void brcmf_proto_detach(struct brcmf_pub *drvr); -/* Stop protocol: sync w/dongle state. */ -void brcmf_proto_stop(struct brcmf_pub *drvr); - /* Add any protocol-specific data header. * Caller must reserve prot_hdrlen prepend space. */ -- cgit v1.2.3 From b317d1d543fbafd768525db6fbc11ca4af9c921b Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 11:48:18 +0100 Subject: brcmfmac: reduce logging noise accessing SDIO SleepCSR register The SleepCSR register is accessed to wakeup the device from the host side. Depending on the state of the device this may take multiple attempts. The failed attempt are not real failures so reduce the log level specifically for this register. The calling function will scream when the multiple attempts all failed. Reviewed-by: Hante Meuleman Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 905704e335d7..009d2a021b87 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -156,10 +156,21 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, } } - if (err_ret) - brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", - rw ? "write" : "read", func, regaddr, *byte, err_ret); - + if (err_ret) { + /* + * SleepCSR register access can fail when + * waking up the device so reduce this noise + * in the logs. + */ + if (regaddr != SBSDIO_FUNC1_SLEEPCSR) + brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", + rw ? "write" : "read", func, regaddr, *byte, + err_ret); + else + brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", + rw ? "write" : "read", func, regaddr, *byte, + err_ret); + } return err_ret; } -- cgit v1.2.3 From 89eda3640cd4dfc00971406fb5ba2d614f61ac29 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 11:48:19 +0100 Subject: brcmsmac: select CONFIG_BCMA when possible The brcmsmac relies BCMA functionality to access the device. This patch selects CONFIG_BCMA when CONFIG_BCMA_POSSIBLE is set. This way the user does not need to be select BCMA to make the brcmsmac driver show up in his menuconfig. Reported-by: Dan Carpenter Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index b00a7e92225f..d9d85e93d098 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -4,7 +4,8 @@ config BRCMUTIL config BRCMSMAC tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" depends on MAC80211 - depends on BCMA + depends on BCMA_POSSIBLE + select BCMA select BRCMUTIL select FW_LOADER select CRC_CCITT -- cgit v1.2.3 From 4b776961a0d2099c684f4c2256896cb64e4fa9e7 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:06 +0100 Subject: brcmfmac: support hardware extension header in trace_brcmf_sdpcm_hdr() The SDPCM header can be traced, but it used a fixed header size. With txglom feature the SDPCM header will have additional 8 bytes of hardware extension header so SDIO core can properly handle the txglom packet. Reviewed-by: Franky Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 4 +-- .../net/wireless/brcm80211/brcmfmac/tracepoint.h | 29 +++++++++++++++------- 2 files changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 2597a534e694..510ab184efb5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -1147,7 +1147,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, u8 rx_seq, fc, tx_seq_max; u32 swheader; - trace_brcmf_sdpcm_hdr(false, header); + trace_brcmf_sdpcm_hdr(SDPCM_RX, header); /* hw header */ len = get_unaligned_le16(header); @@ -1271,7 +1271,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, SDPCM_DOFFSET_MASK; *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); *(((__le32 *)header) + 2) = 0; - trace_brcmf_sdpcm_hdr(true, header); + trace_brcmf_sdpcm_hdr(SDPCM_TX, header); } static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index 3c67529b9074..d229cda98aa7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h @@ -110,21 +110,32 @@ TRACE_EVENT(brcmf_bdchdr, TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) ); +#ifndef SDPCM_RX +#define SDPCM_RX 0 +#endif +#ifndef SDPCM_TX +#define SDPCM_TX 1 +#endif +#ifndef SDPCM_GLOM +#define SDPCM_GLOM 2 +#endif + TRACE_EVENT(brcmf_sdpcm_hdr, - TP_PROTO(bool tx, void *data), - TP_ARGS(tx, data), + TP_PROTO(u8 dir, void *data), + TP_ARGS(dir, data), TP_STRUCT__entry( - __field(u8, tx) + __field(u8, dir) __field(u16, len) - __array(u8, hdr, 12) + __dynamic_array(u8, hdr, dir == SDPCM_GLOM ? 20 : 12) ), TP_fast_assign( - memcpy(__entry->hdr, data, 12); - __entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8); - __entry->tx = tx ? 1 : 0; + memcpy(__get_dynamic_array(hdr), data, dir == SDPCM_GLOM ? 20 : 12); + __entry->len = *(u8 *)data | (*((u8 *)data + 1) << 8); + __entry->dir = dir; ), - TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX", - __entry->len, __entry->hdr[4]) + TP_printk("sdpcm: %s len %u, seq %d", + __entry->dir == SDPCM_RX ? "RX" : "TX", + __entry->len, ((u8 *)__get_dynamic_array(hdr))[4]) ); #ifdef CONFIG_BRCM_TRACING -- cgit v1.2.3 From 2f5f817f1aceca10b9fb7eaf8a07b2a67f8ad15c Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:07 +0100 Subject: brcmfmac: determine sd host controller related variable earlier The commit "eb9c174 brcmfmac: determine host controller related variables during probe" was not implemented correctly as the information is already needed in brcmf_sdbrcm_probe(). This patch moves it to brcmf_sdioh_attach() instead. Reviewed-by: Franky Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 009d2a021b87..225493aec72d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -278,6 +278,9 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) { int err_ret = 0; + struct mmc_host *host; + struct sdio_func *func; + uint max_blocks; brcmf_dbg(SDIO, "\n"); @@ -299,6 +302,20 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) brcmf_sdioh_enablefuncs(sdiodev); + /* + * determine host related variables after brcmf_sdio_probe() + * as func->cur_blksize is properly set and F2 init has been + * completed successfully. + */ + func = sdiodev->func[2]; + host = func->card->host; + sdiodev->sg_support = host->max_segs > 1; + max_blocks = min_t(uint, host->max_blk_count, 511u); + sdiodev->max_request_size = min_t(uint, host->max_req_size, + max_blocks * func->cur_blksize); + sdiodev->max_segment_count = min_t(uint, host->max_segs, + SG_MAX_SINGLE_ALLOC); + sdiodev->max_segment_size = host->max_seg_size; out: sdio_release_host(sdiodev->func[1]); brcmf_dbg(SDIO, "Done\n"); @@ -327,8 +344,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, int err; struct brcmf_sdio_dev *sdiodev; struct brcmf_bus *bus_if; - struct mmc_host *host; - uint max_blocks; brcmf_dbg(SDIO, "Enter\n"); brcmf_dbg(SDIO, "Class=%x\n", func->class); @@ -376,19 +391,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, goto fail; } - /* - * determine host related variables after brcmf_sdio_probe() - * as func->cur_blksize is properly set and F2 init has been - * completed successfully. - */ - host = func->card->host; - sdiodev->sg_support = host->max_segs > 1; - max_blocks = min_t(uint, host->max_blk_count, 511u); - sdiodev->max_request_size = min_t(uint, host->max_req_size, - max_blocks * func->cur_blksize); - sdiodev->max_segment_count = min_t(uint, host->max_segs, - SG_MAX_SINGLE_ALLOC); - sdiodev->max_segment_size = host->max_seg_size; brcmf_dbg(SDIO, "F2 init completed...\n"); return 0; -- cgit v1.2.3 From 9a9e405f95b8c28a76cc0711a603bac7b71dd6b4 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:08 +0100 Subject: brcmfmac: fix driver build issue when CONFIG_BRCMDBG is not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CONFIG_BRCMDBG is not set we get the following build issue: CC [M] drivers/net/wireless/brcm80211/brcmfmac/fwsignal.o drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c: In function ‘brcmf_fws_hdrpush’: drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c:852:18: error: ‘BRCMF_FWS_TYPE_SEQ_LEN’ undeclared The define BRCMF_FWS_TYPE_SEQ_LEN was introduced by: commit 6918f38e4ed4e0493a90a4331e0033bdfc806e00 Author: Hante Meuleman Date: Wed Oct 23 14:58:51 2013 +0200 brcmfmac: Update fwsignal to fix out of order tx. Unfortunately, it was put in conditional part of the source file under #ifdef DEBUG. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 784cf94072ea..296dbf1d1425 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -105,8 +105,6 @@ static struct { }; #undef BRCMF_FWS_TLV_DEF -#define BRCMF_FWS_TYPE_SEQ_LEN 2 - static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) { @@ -125,6 +123,12 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) } #endif /* DEBUG */ +/* + * The PKTTAG tlv has additional bytes when firmware-signalling + * mode has REUSESEQ flag set. + */ +#define BRCMF_FWS_TYPE_SEQ_LEN 2 + /* * flags used to enable tlv signalling from firmware. */ -- cgit v1.2.3 From bed89b64bcbc73a078028f04f64bc955a87ec8ad Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Fri, 29 Nov 2013 12:25:09 +0100 Subject: brcmfmac: add firmware and nvram file name for bcm4339 Add firmware/nvram file name for bcm4339 so fmac can actually be functional with the chip. Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 510ab184efb5..f017c92c731f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -499,6 +499,8 @@ enum brcmf_sdio_frmtype { #define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" #define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" #define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt" +#define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" +#define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); MODULE_FIRMWARE(BCM43143_NVRAM_NAME); @@ -514,6 +516,8 @@ MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME); MODULE_FIRMWARE(BCM4334_NVRAM_NAME); MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME); MODULE_FIRMWARE(BCM4335_NVRAM_NAME); +MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); +MODULE_FIRMWARE(BCM4339_NVRAM_NAME); struct brcmf_firmware_names { u32 chipid; @@ -537,7 +541,8 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = { { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, - { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) } + { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, + { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) } }; -- cgit v1.2.3 From 8da9d2c86888257c7874687467e9519405aa87d5 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Fri, 29 Nov 2013 12:25:10 +0100 Subject: brcmfmac: add host tx glomming support New WiFi full dongle supports receiving chained packets in one command through the SDIO bus. This patch adds the support on the host side to send chained packets. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 327 ++++++++++++++------- 1 file changed, 227 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index f017c92c731f..f5d3650659ec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,8 @@ struct rte_console { #define BRCMF_TXBOUND 20 /* Default for max tx frames in one scheduling */ +#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ + #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ #define MEMBLOCK 2048 /* Block size used for downloading @@ -360,6 +363,8 @@ struct brcmf_sdio_hdrinfo { u16 len_left; u16 len_nxtfrm; u8 dat_offset; + bool lastfrm; + u16 tail_pad; }; /* misc chip info needed by some of the routines */ @@ -455,6 +460,8 @@ struct brcmf_sdio { bool sleeping; /* SDIO bus sleeping */ u8 tx_hdrlen; /* sdio bus header length for tx packet */ + bool txglom; /* host tx glomming enable flag */ + struct sk_buff *txglom_sgpad; /* scatter-gather padding buffer */ }; /* clkstate */ @@ -479,6 +486,10 @@ static const uint max_roundup = 512; #define ALIGNMENT 4 +static int brcmf_sdio_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; +module_param_named(txglomsz, brcmf_sdio_txglomsz, int, 0); +MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]"); + enum brcmf_sdio_frmtype { BRCMF_SDIO_FT_NORMAL, BRCMF_SDIO_FT_SUPER, @@ -1102,10 +1113,18 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) * host and WiFi dongle which contains information needed for SDIO core and * firmware * - * It consists of 2 parts: hw header and software header + * It consists of 3 parts: hardware header, hardware extension header and + * software header * hardware header (frame tag) - 4 bytes * Byte 0~1: Frame length * Byte 2~3: Checksum, bit-wise inverse of frame length + * hardware extension header - 8 bytes + * Tx glom mode only, N/A for Rx or normal Tx + * Byte 0~1: Packet length excluding hw frame tag + * Byte 2: Reserved + * Byte 3: Frame flags, bit 0: last frame indication + * Byte 4~5: Reserved + * Byte 6~7: Tail padding length * software header - 8 bytes * Byte 0: Rx/Tx sequence number * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag @@ -1116,6 +1135,7 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) * Byte 6~7: Reserved */ #define SDPCM_HWHDR_LEN 4 +#define SDPCM_HWEXT_LEN 8 #define SDPCM_SWHDR_LEN 8 #define SDPCM_HDRLEN (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN) /* software header */ @@ -1265,18 +1285,28 @@ static inline void brcmf_sdio_update_hwhdr(u8 *header, u16 frm_length) static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, struct brcmf_sdio_hdrinfo *hd_info) { - u32 sw_header; + u32 hdrval; + u8 hdr_offset; brcmf_sdio_update_hwhdr(header, hd_info->len); - - sw_header = bus->tx_seq; - sw_header |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) & - SDPCM_CHANNEL_MASK; - sw_header |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) & - SDPCM_DOFFSET_MASK; - *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); - *(((__le32 *)header) + 2) = 0; - trace_brcmf_sdpcm_hdr(SDPCM_TX, header); + hdr_offset = SDPCM_HWHDR_LEN; + + if (bus->txglom) { + hdrval = (hd_info->len - hdr_offset) | (hd_info->lastfrm << 24); + *((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval); + hdrval = (u16)hd_info->tail_pad << 16; + *(((__le32 *)(header + hdr_offset)) + 1) = cpu_to_le32(hdrval); + hdr_offset += SDPCM_HWEXT_LEN; + } + + hdrval = hd_info->seq_num; + hdrval |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) & + SDPCM_CHANNEL_MASK; + hdrval |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) & + SDPCM_DOFFSET_MASK; + *((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval); + *(((__le32 *)(header + hdr_offset)) + 1) = 0; + trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header); } static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) @@ -1876,6 +1906,34 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) return; } +static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt) +{ + u16 head_align, head_pad; + u8 *dat_buf; + + /* SDIO ADMA requires at least 32 bit alignment */ + head_align = 4; + if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4) + head_align = bus->sdiodev->pdata->sd_head_align; + + dat_buf = (u8 *)(pkt->data); + + /* Check head padding */ + head_pad = ((unsigned long)dat_buf % head_align); + if (head_pad) { + if (skb_headroom(pkt) < head_pad) { + bus->sdiodev->bus_if->tx_realloc++; + head_pad = 0; + if (skb_cow(pkt, head_pad)) + return -ENOMEM; + } + skb_push(pkt, head_pad); + dat_buf = (u8 *)(pkt->data); + memset(dat_buf, 0, head_pad + bus->tx_hdrlen); + } + return head_pad; +} + /** * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for * bus layer usage. @@ -1885,16 +1943,18 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) /* bit mask of data length chopped from the previous packet */ #define ALIGN_SKB_CHOP_LEN_MASK 0x7fff -static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, +static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, struct sk_buff_head *pktq, - struct sk_buff *pkt, uint chan) + struct sk_buff *pkt, u16 total_len) { + struct brcmf_sdio_dev *sdiodev; struct sk_buff *pkt_pad; - u16 tail_pad, tail_chop, sg_align; + u16 tail_pad, tail_chop, sg_align, chain_pad; unsigned int blksize; - u8 *dat_buf; - int ntail; + bool lastfrm; + int ntail, ret; + sdiodev = bus->sdiodev; blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; sg_align = 4; if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4) @@ -1903,14 +1963,23 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, WARN_ON(blksize % sg_align); /* Check tail padding */ - pkt_pad = NULL; + lastfrm = skb_queue_is_last(pktq, pkt); + tail_pad = 0; tail_chop = pkt->len % sg_align; - tail_pad = sg_align - tail_chop; - tail_pad += blksize - (pkt->len + tail_pad) % blksize; + if (tail_chop) + tail_pad = sg_align - tail_chop; + chain_pad = (total_len + tail_pad) % blksize; + if (lastfrm && chain_pad) + tail_pad += blksize - chain_pad; if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { - pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop); + pkt_pad = bus->txglom_sgpad; + if (pkt_pad == NULL) + brcmu_pkt_buf_get_skb(tail_pad + tail_chop); if (pkt_pad == NULL) return -ENOMEM; + ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad); + if (unlikely(ret < 0)) + return ret; memcpy(pkt_pad->data, pkt->data + pkt->len - tail_chop, tail_chop); @@ -1925,14 +1994,10 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, return -ENOMEM; if (skb_linearize(pkt)) return -ENOMEM; - dat_buf = (u8 *)(pkt->data); __skb_put(pkt, tail_pad); } - if (pkt_pad) - return pkt->len + tail_chop; - else - return pkt->len - tail_pad; + return tail_pad; } /** @@ -1951,58 +2016,66 @@ static int brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, uint chan) { - u16 head_pad, head_align; + u16 head_pad, total_len; struct sk_buff *pkt_next; - u8 *dat_buf; - int err; + u8 txseq; + int ret; struct brcmf_sdio_hdrinfo hd_info = {0}; - /* SDIO ADMA requires at least 32 bit alignment */ - head_align = 4; - if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4) - head_align = bus->sdiodev->pdata->sd_head_align; + txseq = bus->tx_seq; + total_len = 0; + skb_queue_walk(pktq, pkt_next) { + /* alignment packet inserted in previous + * loop cycle can be skipped as it is + * already properly aligned and does not + * need an sdpcm header. + */ + if (*(u32 *)(pkt_next->cb) & ALIGN_SKB_FLAG) + continue; - pkt_next = pktq->next; - dat_buf = (u8 *)(pkt_next->data); + /* align packet data pointer */ + ret = brcmf_sdio_txpkt_hdalign(bus, pkt_next); + if (ret < 0) + return ret; + head_pad = (u16)ret; + if (head_pad) + memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen); - /* Check head padding */ - head_pad = ((unsigned long)dat_buf % head_align); - if (head_pad) { - if (skb_headroom(pkt_next) < head_pad) { - bus->sdiodev->bus_if->tx_realloc++; - head_pad = 0; - if (skb_cow(pkt_next, head_pad)) - return -ENOMEM; - } - skb_push(pkt_next, head_pad); - dat_buf = (u8 *)(pkt_next->data); - memset(dat_buf, 0, head_pad + bus->tx_hdrlen); - } + total_len += pkt_next->len; - if (bus->sdiodev->sg_support && pktq->qlen > 1) { - err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq, - pkt_next, chan); - if (err < 0) - return err; - hd_info.len = (u16)err; - } else { hd_info.len = pkt_next->len; - } - - hd_info.channel = chan; - hd_info.dat_offset = head_pad + bus->tx_hdrlen; - - /* Now fill the header */ - brcmf_sdio_hdpack(bus, dat_buf, &hd_info); - - if (BRCMF_BYTES_ON() && - ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || - (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL))) - brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, "Tx Frame:\n"); - else if (BRCMF_HDRS_ON()) - brcmf_dbg_hex_dump(true, pkt_next, head_pad + bus->tx_hdrlen, - "Tx Header:\n"); + hd_info.lastfrm = skb_queue_is_last(pktq, pkt_next); + if (bus->txglom && pktq->qlen > 1) { + ret = brcmf_sdio_txpkt_prep_sg(bus, pktq, + pkt_next, total_len); + if (ret < 0) + return ret; + hd_info.tail_pad = (u16)ret; + total_len += (u16)ret; + } + hd_info.channel = chan; + hd_info.dat_offset = head_pad + bus->tx_hdrlen; + hd_info.seq_num = txseq++; + + /* Now fill the header */ + brcmf_sdio_hdpack(bus, pkt_next->data, &hd_info); + + if (BRCMF_BYTES_ON() && + ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || + (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL))) + brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, + "Tx Frame:\n"); + else if (BRCMF_HDRS_ON()) + brcmf_dbg_hex_dump(true, pkt_next, + head_pad + bus->tx_hdrlen, + "Tx Header:\n"); + } + /* Hardware length tag of the first packet should be total + * length of the chain (including padding) + */ + if (bus->txglom) + brcmf_sdio_update_hwhdr(pktq->next->data, total_len); return 0; } @@ -2020,6 +2093,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) { u8 *hdr; u32 dat_offset; + u16 tail_pad; u32 dummy_flags, chop_len; struct sk_buff *pkt_next, *tmp, *pkt_prev; @@ -2029,42 +2103,42 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK; if (chop_len) { pkt_prev = pkt_next->prev; - memcpy(pkt_prev->data + pkt_prev->len, - pkt_next->data, chop_len); skb_put(pkt_prev, chop_len); } __skb_unlink(pkt_next, pktq); brcmu_pkt_buf_free_skb(pkt_next); } else { - hdr = pkt_next->data + SDPCM_HWHDR_LEN; + hdr = pkt_next->data + bus->tx_hdrlen - SDPCM_SWHDR_LEN; dat_offset = le32_to_cpu(*(__le32 *)hdr); dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT; skb_pull(pkt_next, dat_offset); + if (bus->txglom) { + tail_pad = le16_to_cpu(*(__le16 *)(hdr - 2)); + skb_trim(pkt_next, pkt_next->len - tail_pad); + } } } } /* Writes a HW/SW header into the packet and sends it. */ /* Assumes: (a) header space already there, (b) caller holds lock */ -static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, +static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq, uint chan) { int ret; int i; - struct sk_buff_head localq; + struct sk_buff *pkt_next, *tmp; brcmf_dbg(TRACE, "Enter\n"); - __skb_queue_head_init(&localq); - __skb_queue_tail(&localq, pkt); - ret = brcmf_sdio_txpkt_prep(bus, &localq, chan); + ret = brcmf_sdio_txpkt_prep(bus, pktq, chan); if (ret) goto done; sdio_claim_host(bus->sdiodev->func[1]); ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, &localq); + SDIO_FUNC_2, F2SYNC, pktq); bus->sdcnt.f2txdata++; if (ret < 0) { @@ -2088,42 +2162,56 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, if ((hi == 0) && (lo == 0)) break; } - } sdio_release_host(bus->sdiodev->func[1]); - if (ret == 0) - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; done: - brcmf_sdio_txpkt_postp(bus, &localq); - __skb_dequeue_tail(&localq); - brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0); + brcmf_sdio_txpkt_postp(bus, pktq); + if (ret == 0) + bus->tx_seq = (bus->tx_seq + pktq->qlen) % SDPCM_SEQ_WRAP; + skb_queue_walk_safe(pktq, pkt_next, tmp) { + __skb_unlink(pkt_next, pktq); + brcmf_txcomplete(bus->sdiodev->dev, pkt_next, ret == 0); + } return ret; } static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) { struct sk_buff *pkt; + struct sk_buff_head pktq; u32 intstatus = 0; - int ret = 0, prec_out; + int ret = 0, prec_out, i; uint cnt = 0; - u8 tx_prec_map; + u8 tx_prec_map, pkt_num; brcmf_dbg(TRACE, "Enter\n"); tx_prec_map = ~bus->flowcontrol; /* Send frames until the limit or some other event */ - for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) { + for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { + pkt_num = 1; + __skb_queue_head_init(&pktq); + if (bus->txglom) + pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, + brcmf_sdio_txglomsz); + pkt_num = min_t(u32, pkt_num, + brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)); spin_lock_bh(&bus->txqlock); - pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); - if (pkt == NULL) { - spin_unlock_bh(&bus->txqlock); - break; + for (i = 0; i < pkt_num; i++) { + pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, + &prec_out); + if (pkt == NULL) + break; + __skb_queue_tail(&pktq, pkt); } spin_unlock_bh(&bus->txqlock); + if (i == 0) + break; - ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL); + ret = brcmf_sdbrcm_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); + cnt += i; /* In poll mode, need to check for other events */ if (!bus->intr && cnt) { @@ -2670,7 +2758,7 @@ static int brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) { u8 *frame; - u16 len; + u16 len, pad; uint retries = 0; u8 doff = 0; int ret = -1; @@ -2697,13 +2785,15 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) doff += bus->tx_hdrlen; /* Round send length to next SDIO block */ + pad = 0; if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { - u16 pad = bus->blocksize - (len % bus->blocksize); - if ((pad <= bus->roundup) && (pad < bus->blocksize)) - len += pad; + pad = bus->blocksize - (len % bus->blocksize); + if ((pad > bus->roundup) || (pad >= bus->blocksize)) + pad = 0; } else if (len % BRCMF_SDALIGN) { - len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); + pad = BRCMF_SDALIGN - (len % BRCMF_SDALIGN); } + len += pad; /* Satisfy length-alignment requirements */ if (len & (ALIGNMENT - 1)) @@ -2719,8 +2809,16 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) hd_info.len = (u16)msglen; hd_info.channel = SDPCM_CONTROL_CHANNEL; hd_info.dat_offset = doff; + hd_info.seq_num = bus->tx_seq; + if (bus->txglom) { + hd_info.lastfrm = true; + hd_info.tail_pad = pad; + } brcmf_sdio_hdpack(bus, frame, &hd_info); + if (bus->txglom) + brcmf_sdio_update_hwhdr(frame, len); + if (!data_ok(bus)) { brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", bus->tx_max, bus->tx_seq); @@ -3435,11 +3533,15 @@ static int brcmf_sdbrcm_bus_preinit(struct device *dev) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; + uint pad_size; u32 value; u8 idx; int err; - /* sdio bus core specific dcmd */ + /* the commands below use the terms tx and rx from + * a device perspective, ie. bus:txglom affects the + * bus transfers from device to host. + */ idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); if (bus->ci->c_inf[idx].rev < 12) { /* for sdio core rev < 12, disable txgloming */ @@ -3456,6 +3558,32 @@ static int brcmf_sdbrcm_bus_preinit(struct device *dev) err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, sizeof(u32)); } + + if (err < 0) + goto done; + + bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; + if (sdiodev->sg_support) { + bus->txglom = false; + value = 1; + pad_size = bus->sdiodev->func[2]->cur_blksize << 1; + bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size); + if (!bus->txglom_sgpad) + brcmf_err("allocating txglom padding skb failed, reduced performance\n"); + + err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom", + &value, sizeof(u32)); + if (err < 0) { + /* bus:rxglom is allowed to fail */ + err = 0; + } else { + bus->txglom = true; + bus->tx_hdrlen += SDPCM_HWEXT_LEN; + } + } + brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); + +done: return err; } @@ -3929,6 +4057,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) brcmf_sdbrcm_release_dongle(bus); } + brcmu_pkt_buf_free_skb(bus->txglom_sgpad); brcmf_sdbrcm_release_malloc(bus); kfree(bus); @@ -4034,8 +4163,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) brcmf_sdio_debugfs_create(bus); brcmf_dbg(INFO, "completed!!\n"); - brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); - /* if firmware path present try to download and bring up bus */ ret = brcmf_bus_start(bus->sdiodev->dev); if (ret != 0) { -- cgit v1.2.3 From 5d406f8e03921b742fb549def43939254572dee9 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 29 Nov 2013 12:46:29 +0100 Subject: brcmfmac: rename dhd_cdc to bcdc dhd_cdc is renamed to bcdc. This is a step in cleaning and restructuring protocol layer. This is done so new protocols can be added in the future. This step only renames the source files. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman [arend@broadcom.com: use 'git mv' to do the rename] Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/Makefile | 2 +- drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 387 ++++++++++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | 387 ---------------------- 3 files changed, 388 insertions(+), 388 deletions(-) create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/bcdc.c delete mode 100644 drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 8e9b1221b32c..e15b61c26145 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -28,7 +28,7 @@ brcmfmac-objs += \ fweh.o \ fwsignal.o \ p2p.o \ - dhd_cdc.o \ + bcdc.o \ dhd_common.o \ dhd_linux.o \ btcoex.o diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c new file mode 100644 index 000000000000..42aaf104cc44 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2010 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/******************************************************************************* + * Communicates with the dongle by using dcmd codes. + * For certain dcmd codes, the dongle interprets string data from the host. + ******************************************************************************/ + +#include +#include + +#include +#include + +#include "dhd.h" +#include "dhd_proto.h" +#include "dhd_bus.h" +#include "fwsignal.h" +#include "dhd_dbg.h" +#include "tracepoint.h" + +struct brcmf_proto_cdc_dcmd { + __le32 cmd; /* dongle command value */ + __le32 len; /* lower 16: output buflen; + * upper 16: input buflen (excludes header) */ + __le32 flags; /* flag defns given below */ + __le32 status; /* status code returned from the device */ +}; + +/* Max valid buffer size that can be sent to the dongle */ +#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) + +/* CDC flag definitions */ +#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ +#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ +#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ +#define CDC_DCMD_IF_SHIFT 12 +#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ +#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ +#define CDC_DCMD_ID(flags) \ + (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) + +/* + * BDC header - Broadcom specific extension of CDC. + * Used on data packets to convey priority across USB. + */ +#define BDC_HEADER_LEN 4 +#define BDC_PROTO_VER 2 /* Protocol version */ +#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ +#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ +#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ +#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ +#define BDC_PRIORITY_MASK 0x7 +#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ +#define BDC_FLAG2_IF_SHIFT 0 + +#define BDC_GET_IF_IDX(hdr) \ + ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) +#define BDC_SET_IF_IDX(hdr, idx) \ + ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ + ((idx) << BDC_FLAG2_IF_SHIFT))) + +/** + * struct brcmf_proto_bdc_header - BDC header format + * + * @flags: flags contain protocol and checksum info. + * @priority: 802.1d priority and USB flow control info (bit 4:7). + * @flags2: additional flags containing dongle interface index. + * @data_offset: start of packet data. header is following by firmware signals. + */ +struct brcmf_proto_bdc_header { + u8 flags; + u8 priority; + u8 flags2; + u8 data_offset; +}; + +/* + * maximum length of firmware signal data between + * the BDC header and packet data in the tx path. + */ +#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 + +#define RETRIES 2 /* # of retries to retrieve matching dcmd response */ +#define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE + * (amount of header tha might be added) + * plus any space that might be needed + * for bus alignment padding. + */ +#define ROUND_UP_MARGIN 2048 /* Biggest bus block size possible for + * round off at the end of buffer + * Currently is SDIO + */ + +struct brcmf_proto { + u16 reqid; + u8 bus_header[BUS_HEADER_LEN]; + struct brcmf_proto_cdc_dcmd msg; + unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; +}; + +static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) +{ + struct brcmf_proto *prot = drvr->prot; + int len = le32_to_cpu(prot->msg.len) + + sizeof(struct brcmf_proto_cdc_dcmd); + + brcmf_dbg(CDC, "Enter\n"); + + /* NOTE : cdc->msg.len holds the desired length of the buffer to be + * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area + * is actually sent to the dongle + */ + if (len > CDC_MAX_MSG_SIZE) + len = CDC_MAX_MSG_SIZE; + + /* Send request */ + return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&prot->msg, len); +} + +static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) +{ + int ret; + struct brcmf_proto *prot = drvr->prot; + + brcmf_dbg(CDC, "Enter\n"); + len += sizeof(struct brcmf_proto_cdc_dcmd); + do { + ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, + len); + if (ret < 0) + break; + } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); + + return ret; +} + +int +brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, + void *buf, uint len) +{ + struct brcmf_proto *prot = drvr->prot; + struct brcmf_proto_cdc_dcmd *msg = &prot->msg; + void *info; + int ret = 0, retries = 0; + u32 id, flags; + + brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); + + memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); + + msg->cmd = cpu_to_le32(cmd); + msg->len = cpu_to_le32(len); + flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); + flags = (flags & ~CDC_DCMD_IF_MASK) | + (ifidx << CDC_DCMD_IF_SHIFT); + msg->flags = cpu_to_le32(flags); + + if (buf) + memcpy(prot->buf, buf, len); + + ret = brcmf_proto_cdc_msg(drvr); + if (ret < 0) { + brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n", + ret); + goto done; + } + +retry: + /* wait for interrupt and get first fragment */ + ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); + if (ret < 0) + goto done; + + flags = le32_to_cpu(msg->flags); + id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; + + if ((id < prot->reqid) && (++retries < RETRIES)) + goto retry; + if (id != prot->reqid) { + brcmf_err("%s: unexpected request id %d (expected %d)\n", + brcmf_ifname(drvr, ifidx), id, prot->reqid); + ret = -EINVAL; + goto done; + } + + /* Check info buffer */ + info = (void *)&msg[1]; + + /* Copy info buffer */ + if (buf) { + if (ret < (int)len) + len = ret; + memcpy(buf, info, len); + } + + /* Check the ERROR flag */ + if (flags & CDC_DCMD_ERROR) + ret = le32_to_cpu(msg->status); + +done: + return ret; +} + +int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, + void *buf, uint len) +{ + struct brcmf_proto *prot = drvr->prot; + struct brcmf_proto_cdc_dcmd *msg = &prot->msg; + int ret = 0; + u32 flags, id; + + brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); + + memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); + + msg->cmd = cpu_to_le32(cmd); + msg->len = cpu_to_le32(len); + flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; + flags = (flags & ~CDC_DCMD_IF_MASK) | + (ifidx << CDC_DCMD_IF_SHIFT); + msg->flags = cpu_to_le32(flags); + + if (buf) + memcpy(prot->buf, buf, len); + + ret = brcmf_proto_cdc_msg(drvr); + if (ret < 0) + goto done; + + ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); + if (ret < 0) + goto done; + + flags = le32_to_cpu(msg->flags); + id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; + + if (id != prot->reqid) { + brcmf_err("%s: unexpected request id %d (expected %d)\n", + brcmf_ifname(drvr, ifidx), id, prot->reqid); + ret = -EINVAL; + goto done; + } + + /* Check the ERROR flag */ + if (flags & CDC_DCMD_ERROR) + ret = le32_to_cpu(msg->status); + +done: + return ret; +} + +static bool pkt_sum_needed(struct sk_buff *skb) +{ + return skb->ip_summed == CHECKSUM_PARTIAL; +} + +static void pkt_set_sum_good(struct sk_buff *skb, bool x) +{ + skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); +} + +void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, + struct sk_buff *pktbuf) +{ + struct brcmf_proto_bdc_header *h; + + brcmf_dbg(CDC, "Enter\n"); + + /* Push BDC header used to convey priority for buses that don't */ + skb_push(pktbuf, BDC_HEADER_LEN); + + h = (struct brcmf_proto_bdc_header *)(pktbuf->data); + + h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); + if (pkt_sum_needed(pktbuf)) + h->flags |= BDC_FLAG_SUM_NEEDED; + + h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); + h->flags2 = 0; + h->data_offset = offset; + BDC_SET_IF_IDX(h, ifidx); + trace_brcmf_bdchdr(pktbuf->data); +} + +int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, + struct sk_buff *pktbuf) +{ + struct brcmf_proto_bdc_header *h; + + brcmf_dbg(CDC, "Enter\n"); + + /* Pop BDC header used to convey priority for buses that don't */ + + if (pktbuf->len <= BDC_HEADER_LEN) { + brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", + pktbuf->len, BDC_HEADER_LEN); + return -EBADE; + } + + trace_brcmf_bdchdr(pktbuf->data); + h = (struct brcmf_proto_bdc_header *)(pktbuf->data); + + *ifidx = BDC_GET_IF_IDX(h); + if (*ifidx >= BRCMF_MAX_IFS) { + brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); + return -EBADE; + } + /* The ifidx is the idx to map to matching netdev/ifp. When receiving + * events this is easy because it contains the bssidx which maps + * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. + * bssidx 1 is used for p2p0 and no data can be received or + * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 + */ + if (*ifidx) + (*ifidx)++; + + if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != + BDC_PROTO_VER) { + brcmf_err("%s: non-BDC packet received, flags 0x%x\n", + brcmf_ifname(drvr, *ifidx), h->flags); + return -EBADE; + } + + if (h->flags & BDC_FLAG_SUM_GOOD) { + brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n", + brcmf_ifname(drvr, *ifidx), h->flags); + pkt_set_sum_good(pktbuf, true); + } + + pktbuf->priority = h->priority & BDC_PRIORITY_MASK; + + skb_pull(pktbuf, BDC_HEADER_LEN); + if (do_fws) + brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); + else + skb_pull(pktbuf, h->data_offset << 2); + + if (pktbuf->len == 0) + return -ENODATA; + return 0; +} + +int brcmf_proto_attach(struct brcmf_pub *drvr) +{ + struct brcmf_proto *cdc; + + cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); + if (!cdc) + goto fail; + + /* ensure that the msg buf directly follows the cdc msg struct */ + if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { + brcmf_err("struct brcmf_proto is not correctly defined\n"); + goto fail; + } + + drvr->prot = cdc; + drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; + drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + + sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; + return 0; + +fail: + kfree(cdc); + return -ENOMEM; +} + +/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ +void brcmf_proto_detach(struct brcmf_pub *drvr) +{ + kfree(drvr->prot); + drvr->prot = NULL; +} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c deleted file mode 100644 index 42aaf104cc44..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2010 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/******************************************************************************* - * Communicates with the dongle by using dcmd codes. - * For certain dcmd codes, the dongle interprets string data from the host. - ******************************************************************************/ - -#include -#include - -#include -#include - -#include "dhd.h" -#include "dhd_proto.h" -#include "dhd_bus.h" -#include "fwsignal.h" -#include "dhd_dbg.h" -#include "tracepoint.h" - -struct brcmf_proto_cdc_dcmd { - __le32 cmd; /* dongle command value */ - __le32 len; /* lower 16: output buflen; - * upper 16: input buflen (excludes header) */ - __le32 flags; /* flag defns given below */ - __le32 status; /* status code returned from the device */ -}; - -/* Max valid buffer size that can be sent to the dongle */ -#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) - -/* CDC flag definitions */ -#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ -#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ -#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ -#define CDC_DCMD_IF_SHIFT 12 -#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ -#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ -#define CDC_DCMD_ID(flags) \ - (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) - -/* - * BDC header - Broadcom specific extension of CDC. - * Used on data packets to convey priority across USB. - */ -#define BDC_HEADER_LEN 4 -#define BDC_PROTO_VER 2 /* Protocol version */ -#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ -#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ -#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ -#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ -#define BDC_PRIORITY_MASK 0x7 -#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ -#define BDC_FLAG2_IF_SHIFT 0 - -#define BDC_GET_IF_IDX(hdr) \ - ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) -#define BDC_SET_IF_IDX(hdr, idx) \ - ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ - ((idx) << BDC_FLAG2_IF_SHIFT))) - -/** - * struct brcmf_proto_bdc_header - BDC header format - * - * @flags: flags contain protocol and checksum info. - * @priority: 802.1d priority and USB flow control info (bit 4:7). - * @flags2: additional flags containing dongle interface index. - * @data_offset: start of packet data. header is following by firmware signals. - */ -struct brcmf_proto_bdc_header { - u8 flags; - u8 priority; - u8 flags2; - u8 data_offset; -}; - -/* - * maximum length of firmware signal data between - * the BDC header and packet data in the tx path. - */ -#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 - -#define RETRIES 2 /* # of retries to retrieve matching dcmd response */ -#define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE - * (amount of header tha might be added) - * plus any space that might be needed - * for bus alignment padding. - */ -#define ROUND_UP_MARGIN 2048 /* Biggest bus block size possible for - * round off at the end of buffer - * Currently is SDIO - */ - -struct brcmf_proto { - u16 reqid; - u8 bus_header[BUS_HEADER_LEN]; - struct brcmf_proto_cdc_dcmd msg; - unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; -}; - -static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) -{ - struct brcmf_proto *prot = drvr->prot; - int len = le32_to_cpu(prot->msg.len) + - sizeof(struct brcmf_proto_cdc_dcmd); - - brcmf_dbg(CDC, "Enter\n"); - - /* NOTE : cdc->msg.len holds the desired length of the buffer to be - * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area - * is actually sent to the dongle - */ - if (len > CDC_MAX_MSG_SIZE) - len = CDC_MAX_MSG_SIZE; - - /* Send request */ - return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&prot->msg, len); -} - -static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) -{ - int ret; - struct brcmf_proto *prot = drvr->prot; - - brcmf_dbg(CDC, "Enter\n"); - len += sizeof(struct brcmf_proto_cdc_dcmd); - do { - ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, - len); - if (ret < 0) - break; - } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); - - return ret; -} - -int -brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len) -{ - struct brcmf_proto *prot = drvr->prot; - struct brcmf_proto_cdc_dcmd *msg = &prot->msg; - void *info; - int ret = 0, retries = 0; - u32 id, flags; - - brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); - - memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); - - msg->cmd = cpu_to_le32(cmd); - msg->len = cpu_to_le32(len); - flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); - flags = (flags & ~CDC_DCMD_IF_MASK) | - (ifidx << CDC_DCMD_IF_SHIFT); - msg->flags = cpu_to_le32(flags); - - if (buf) - memcpy(prot->buf, buf, len); - - ret = brcmf_proto_cdc_msg(drvr); - if (ret < 0) { - brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n", - ret); - goto done; - } - -retry: - /* wait for interrupt and get first fragment */ - ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); - if (ret < 0) - goto done; - - flags = le32_to_cpu(msg->flags); - id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; - - if ((id < prot->reqid) && (++retries < RETRIES)) - goto retry; - if (id != prot->reqid) { - brcmf_err("%s: unexpected request id %d (expected %d)\n", - brcmf_ifname(drvr, ifidx), id, prot->reqid); - ret = -EINVAL; - goto done; - } - - /* Check info buffer */ - info = (void *)&msg[1]; - - /* Copy info buffer */ - if (buf) { - if (ret < (int)len) - len = ret; - memcpy(buf, info, len); - } - - /* Check the ERROR flag */ - if (flags & CDC_DCMD_ERROR) - ret = le32_to_cpu(msg->status); - -done: - return ret; -} - -int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len) -{ - struct brcmf_proto *prot = drvr->prot; - struct brcmf_proto_cdc_dcmd *msg = &prot->msg; - int ret = 0; - u32 flags, id; - - brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); - - memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); - - msg->cmd = cpu_to_le32(cmd); - msg->len = cpu_to_le32(len); - flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; - flags = (flags & ~CDC_DCMD_IF_MASK) | - (ifidx << CDC_DCMD_IF_SHIFT); - msg->flags = cpu_to_le32(flags); - - if (buf) - memcpy(prot->buf, buf, len); - - ret = brcmf_proto_cdc_msg(drvr); - if (ret < 0) - goto done; - - ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); - if (ret < 0) - goto done; - - flags = le32_to_cpu(msg->flags); - id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; - - if (id != prot->reqid) { - brcmf_err("%s: unexpected request id %d (expected %d)\n", - brcmf_ifname(drvr, ifidx), id, prot->reqid); - ret = -EINVAL; - goto done; - } - - /* Check the ERROR flag */ - if (flags & CDC_DCMD_ERROR) - ret = le32_to_cpu(msg->status); - -done: - return ret; -} - -static bool pkt_sum_needed(struct sk_buff *skb) -{ - return skb->ip_summed == CHECKSUM_PARTIAL; -} - -static void pkt_set_sum_good(struct sk_buff *skb, bool x) -{ - skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); -} - -void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, - struct sk_buff *pktbuf) -{ - struct brcmf_proto_bdc_header *h; - - brcmf_dbg(CDC, "Enter\n"); - - /* Push BDC header used to convey priority for buses that don't */ - skb_push(pktbuf, BDC_HEADER_LEN); - - h = (struct brcmf_proto_bdc_header *)(pktbuf->data); - - h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); - if (pkt_sum_needed(pktbuf)) - h->flags |= BDC_FLAG_SUM_NEEDED; - - h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); - h->flags2 = 0; - h->data_offset = offset; - BDC_SET_IF_IDX(h, ifidx); - trace_brcmf_bdchdr(pktbuf->data); -} - -int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *pktbuf) -{ - struct brcmf_proto_bdc_header *h; - - brcmf_dbg(CDC, "Enter\n"); - - /* Pop BDC header used to convey priority for buses that don't */ - - if (pktbuf->len <= BDC_HEADER_LEN) { - brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", - pktbuf->len, BDC_HEADER_LEN); - return -EBADE; - } - - trace_brcmf_bdchdr(pktbuf->data); - h = (struct brcmf_proto_bdc_header *)(pktbuf->data); - - *ifidx = BDC_GET_IF_IDX(h); - if (*ifidx >= BRCMF_MAX_IFS) { - brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); - return -EBADE; - } - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (*ifidx) - (*ifidx)++; - - if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != - BDC_PROTO_VER) { - brcmf_err("%s: non-BDC packet received, flags 0x%x\n", - brcmf_ifname(drvr, *ifidx), h->flags); - return -EBADE; - } - - if (h->flags & BDC_FLAG_SUM_GOOD) { - brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n", - brcmf_ifname(drvr, *ifidx), h->flags); - pkt_set_sum_good(pktbuf, true); - } - - pktbuf->priority = h->priority & BDC_PRIORITY_MASK; - - skb_pull(pktbuf, BDC_HEADER_LEN); - if (do_fws) - brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); - else - skb_pull(pktbuf, h->data_offset << 2); - - if (pktbuf->len == 0) - return -ENODATA; - return 0; -} - -int brcmf_proto_attach(struct brcmf_pub *drvr) -{ - struct brcmf_proto *cdc; - - cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); - if (!cdc) - goto fail; - - /* ensure that the msg buf directly follows the cdc msg struct */ - if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { - brcmf_err("struct brcmf_proto is not correctly defined\n"); - goto fail; - } - - drvr->prot = cdc; - drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; - drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + - sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; - return 0; - -fail: - kfree(cdc); - return -ENOMEM; -} - -/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ -void brcmf_proto_detach(struct brcmf_pub *drvr) -{ - kfree(drvr->prot); - drvr->prot = NULL; -} -- cgit v1.2.3 From f931868d498ec4e7a1b8730e7173b5a17d36dd1a Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 29 Nov 2013 12:25:12 +0100 Subject: brcmfmac: removed dhd_proto.h. dhd_proto.h was cleaned up and prototypes were moved to dhd.h. dhd_proto.h was removed. This is a step in cleaning and restucturing protocol layer. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 1 - drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 15 +++++++++ .../net/wireless/brcm80211/brcmfmac/dhd_common.c | 1 - .../net/wireless/brcm80211/brcmfmac/dhd_linux.c | 1 - .../net/wireless/brcm80211/brcmfmac/dhd_proto.h | 39 ---------------------- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 1 - 6 files changed, 15 insertions(+), 43 deletions(-) delete mode 100644 drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 42aaf104cc44..59c6c054b113 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -26,7 +26,6 @@ #include #include "dhd.h" -#include "dhd_proto.h" #include "dhd_bus.h" #include "fwsignal.h" #include "dhd_dbg.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 899a2ada5b82..dc2ebefa4cac 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -635,6 +635,18 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev); /* Return pointer to interface name */ char *brcmf_ifname(struct brcmf_pub *drvr, int idx); +/* Linkage, sets prot link and updates hdrlen in pub */ +int brcmf_proto_attach(struct brcmf_pub *drvr); + +/* Unlink, frees allocated protocol memory (including brcmf_proto) */ +void brcmf_proto_detach(struct brcmf_pub *drvr); + +/* Add any protocol-specific data header. + * Caller must reserve prot_hdrlen prepend space. + */ +void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, + struct sk_buff *txp); + /* Query dongle */ int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len); @@ -655,4 +667,7 @@ u32 brcmf_get_chip_info(struct brcmf_if *ifp); void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, bool success); +/* Sets dongle media info (drv_version, mac address). */ +int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); + #endif /* _BRCMF_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 5c0c9191b794..601763393184 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -21,7 +21,6 @@ #include #include "dhd.h" #include "dhd_bus.h" -#include "dhd_proto.h" #include "dhd_dbg.h" #include "fwil.h" #include "tracepoint.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c34ca703d2a3..c626938665aa 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -24,7 +24,6 @@ #include "dhd.h" #include "dhd_bus.h" -#include "dhd_proto.h" #include "dhd_dbg.h" #include "fwil_types.h" #include "p2p.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h deleted file mode 100644 index d633362a52d0..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _BRCMF_PROTO_H_ -#define _BRCMF_PROTO_H_ - -/* - * Exported from the brcmf protocol module (brcmf_cdc) - */ - -/* Linkage, sets prot link and updates hdrlen in pub */ -int brcmf_proto_attach(struct brcmf_pub *drvr); - -/* Unlink, frees allocated protocol memory (including brcmf_proto) */ -void brcmf_proto_detach(struct brcmf_pub *drvr); - -/* Add any protocol-specific data header. - * Caller must reserve prot_hdrlen prepend space. - */ -void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, - struct sk_buff *txp); - -/* Sets dongle media info (drv_version, mac address). */ -int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); - -#endif /* _BRCMF_PROTO_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 296dbf1d1425..b96ee3a93a68 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -27,7 +27,6 @@ #include #include #include "dhd.h" -#include "dhd_proto.h" #include "dhd_dbg.h" #include "dhd_bus.h" #include "fwil.h" -- cgit v1.2.3 From e217d1c8bfbd97316f5a1d3845587284cc137291 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:13 +0100 Subject: brcmfmac: determine alignment values during probe The alignment values were being determined for each transmit and receive depending on platform data. Instead determine these once during the probe. Reviewed-by: Franky Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index f5d3650659ec..584ffb8ff4f8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -462,6 +462,8 @@ struct brcmf_sdio { u8 tx_hdrlen; /* sdio bus header length for tx packet */ bool txglom; /* host tx glomming enable flag */ struct sk_buff *txglom_sgpad; /* scatter-gather padding buffer */ + u16 head_align; /* buffer pointer alignment */ + u16 sgentry_align; /* scatter-gather buffer alignment */ }; /* clkstate */ @@ -1313,7 +1315,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) { u16 dlen, totlen; u8 *dptr, num = 0; - u32 align = 0; u16 sublen; struct sk_buff *pfirst, *pnext; @@ -1328,11 +1329,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) brcmf_dbg(SDIO, "start: glomd %p glom %p\n", bus->glomd, skb_peek(&bus->glom)); - if (bus->sdiodev->pdata) - align = bus->sdiodev->pdata->sd_sgentry_align; - if (align < 4) - align = 4; - /* If there's a descriptor, generate the packet chain */ if (bus->glomd) { pfirst = pnext = NULL; @@ -1356,9 +1352,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) pnext = NULL; break; } - if (sublen % align) { + if (sublen % bus->sgentry_align) { brcmf_err("sublen %d not multiple of %d\n", - sublen, align); + sublen, bus->sgentry_align); } totlen += sublen; @@ -1371,7 +1367,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } /* Allocate/chain packet for next subframe */ - pnext = brcmu_pkt_buf_get_skb(sublen + align); + pnext = brcmu_pkt_buf_get_skb(sublen + bus->sgentry_align); if (pnext == NULL) { brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n", num, sublen); @@ -1380,7 +1376,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) skb_queue_tail(&bus->glom, pnext); /* Adhere to start alignment requirements */ - pkt_align(pnext, sublen, align); + pkt_align(pnext, sublen, bus->sgentry_align); } /* If all allocations succeeded, save packet chain @@ -1908,18 +1904,13 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt) { - u16 head_align, head_pad; + u16 head_pad; u8 *dat_buf; - /* SDIO ADMA requires at least 32 bit alignment */ - head_align = 4; - if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4) - head_align = bus->sdiodev->pdata->sd_head_align; - dat_buf = (u8 *)(pkt->data); /* Check head padding */ - head_pad = ((unsigned long)dat_buf % head_align); + head_pad = ((unsigned long)dat_buf % bus->head_align); if (head_pad) { if (skb_headroom(pkt) < head_pad) { bus->sdiodev->bus_if->tx_realloc++; @@ -1949,25 +1940,22 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, { struct brcmf_sdio_dev *sdiodev; struct sk_buff *pkt_pad; - u16 tail_pad, tail_chop, sg_align, chain_pad; + u16 tail_pad, tail_chop, chain_pad; unsigned int blksize; bool lastfrm; int ntail, ret; sdiodev = bus->sdiodev; blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; - sg_align = 4; - if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4) - sg_align = sdiodev->pdata->sd_sgentry_align; /* sg entry alignment should be a divisor of block size */ - WARN_ON(blksize % sg_align); + WARN_ON(blksize % bus->sgentry_align); /* Check tail padding */ lastfrm = skb_queue_is_last(pktq, pkt); tail_pad = 0; - tail_chop = pkt->len % sg_align; + tail_chop = pkt->len % bus->sgentry_align; if (tail_chop) - tail_pad = sg_align - tail_chop; + tail_pad = bus->sgentry_align - tail_chop; chain_pad = (total_len + tail_pad) % blksize; if (lastfrm && chain_pad) tail_pad += blksize - chain_pad; @@ -4099,6 +4087,18 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->txminmax = BRCMF_TXMINMAX; bus->tx_seq = SDPCM_SEQ_WRAP - 1; + /* platform specific configuration: + * alignments must be at least 4 bytes for ADMA + */ + bus->head_align = ALIGNMENT; + bus->sgentry_align = ALIGNMENT; + if (sdiodev->pdata) { + if (sdiodev->pdata->sd_head_align > ALIGNMENT) + bus->head_align = sdiodev->pdata->sd_head_align; + if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT) + bus->sgentry_align = sdiodev->pdata->sd_sgentry_align; + } + INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); if (bus->brcmf_wq == NULL) { -- cgit v1.2.3 From 9b2d2f2a890847277371d953e2751c4224efa273 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:14 +0100 Subject: brcmfmac: use platform specific alignment in SDIO The SDIO part of the brcmfmac driver uses a static define BRCMF_SDALIGN to align buffers used for SDIO transfers. This patch replaces it by using alignment derived from the platform specific data. Reviewed-by: Franky Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 50 ++++++++++------------ 1 file changed, 22 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 584ffb8ff4f8..0f95f3e79c10 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -389,7 +389,7 @@ struct brcmf_sdio { u8 tx_seq; /* Transmit sequence number (next) */ u8 tx_max; /* Maximum transmit sequence allowed */ - u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; + u8 *hdrbuf; /* buffer for handling rx frame */ u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ u8 rx_seq; /* Receive sequence number (expected) */ struct brcmf_sdio_hdrinfo cur_read; @@ -1580,9 +1580,9 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) goto done; rbuf = bus->rxbuf; - pad = ((unsigned long)rbuf % BRCMF_SDALIGN); + pad = ((unsigned long)rbuf % bus->head_align); if (pad) - rbuf += (BRCMF_SDALIGN - pad); + rbuf += (bus->head_align - pad); /* Copy the already-read portion over */ memcpy(buf, hdr, BRCMF_FIRSTREAD); @@ -1596,14 +1596,10 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) if ((pad <= bus->roundup) && (pad < bus->blocksize) && ((len + pad) < bus->sdiodev->bus_if->maxctl)) rdlen += pad; - } else if (rdlen % BRCMF_SDALIGN) { - rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); + } else if (rdlen % bus->head_align) { + rdlen += bus->head_align - (rdlen % bus->head_align); } - /* Satisfy length-alignment requirements */ - if (rdlen & (ALIGNMENT - 1)) - rdlen = roundup(rdlen, ALIGNMENT); - /* Drop if the read is too big or it exceeds our maximum */ if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) { brcmf_err("%d-byte control read exceeds %d-byte buffer\n", @@ -1668,8 +1664,8 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) if (*pad <= bus->roundup && *pad < bus->blocksize && *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ) *rdlen += *pad; - } else if (*rdlen % BRCMF_SDALIGN) { - *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN); + } else if (*rdlen % bus->head_align) { + *rdlen += bus->head_align - (*rdlen % bus->head_align); } } @@ -1757,7 +1753,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) brcmf_pad(bus, &pad, &rd->len_left); pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + - BRCMF_SDALIGN); + bus->head_align); if (!pkt) { /* Give up on data, request rtx of events */ brcmf_err("brcmu_pkt_buf_get_skb failed\n"); @@ -1767,7 +1763,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) continue; } skb_pull(pkt, head_read); - pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); + pkt_align(pkt, rd->len_left, bus->head_align); ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, pkt); @@ -2762,14 +2758,14 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) len = (msglen += bus->tx_hdrlen); /* Add alignment padding (optional for ctl frames) */ - doff = ((unsigned long)frame % BRCMF_SDALIGN); + doff = ((unsigned long)frame % bus->head_align); if (doff) { frame -= doff; len += doff; msglen += doff; memset(frame, 0, doff + bus->tx_hdrlen); } - /* precondition: doff < BRCMF_SDALIGN */ + /* precondition: doff < bus->head_align */ doff += bus->tx_hdrlen; /* Round send length to next SDIO block */ @@ -2778,15 +2774,11 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) pad = bus->blocksize - (len % bus->blocksize); if ((pad > bus->roundup) || (pad >= bus->blocksize)) pad = 0; - } else if (len % BRCMF_SDALIGN) { - pad = BRCMF_SDALIGN - (len % BRCMF_SDALIGN); + } else if (len % bus->head_align) { + pad = bus->head_align - (len % bus->head_align); } len += pad; - /* Satisfy length-alignment requirements */ - if (len & (ALIGNMENT - 1)) - len = roundup(len, ALIGNMENT); - /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ /* Make sure backplane clock is on */ @@ -2798,10 +2790,8 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) hd_info.channel = SDPCM_CONTROL_CHANNEL; hd_info.dat_offset = doff; hd_info.seq_num = bus->tx_seq; - if (bus->txglom) { - hd_info.lastfrm = true; - hd_info.tail_pad = pad; - } + hd_info.lastfrm = true; + hd_info.tail_pad = pad; brcmf_sdio_hdpack(bus, frame, &hd_info); if (bus->txglom) @@ -3823,7 +3813,7 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) if (bus->sdiodev->bus_if->maxctl) { bus->rxblen = roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN), - ALIGNMENT) + BRCMF_SDALIGN; + ALIGNMENT) + bus->head_align; bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); if (!(bus->rxbuf)) return false; @@ -3924,9 +3914,13 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); + /* allocate header buffer */ + bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL); + if (!bus->hdrbuf) + return false; /* Locate an appropriately-aligned portion of hdrbuf */ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], - BRCMF_SDALIGN); + bus->head_align); /* Set the poll and/or interrupt flags */ bus->intr = true; @@ -4047,7 +4041,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) brcmu_pkt_buf_free_skb(bus->txglom_sgpad); brcmf_sdbrcm_release_malloc(bus); - + kfree(bus->hdrbuf); kfree(bus); } -- cgit v1.2.3 From e601fb37405af384781284f90125fd4da665a7b3 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:15 +0100 Subject: brcmfmac: remove redundant ioctl handlers The ioctl() entry points were empty except for handling SIOC_ETHTOOL but that has been obsoleted in favor of struct ethtool_ops. Cleaning up removing the ioctl() handlers. Reviewed-by: Hante Meuleman Reviewed-by: Franky Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/dhd_linux.c | 149 --------------------- 1 file changed, 149 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c626938665aa..9336f6dd3f83 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -591,28 +591,6 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) return &ifp->stats; } -/* - * Set current toe component enables in toe_ol iovar, - * and set toe global enable iovar - */ -static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol) -{ - s32 err; - - err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol); - if (err < 0) { - brcmf_err("Setting toe_ol failed, %d\n", err); - return err; - } - - err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0)); - if (err < 0) - brcmf_err("Setting toe failed, %d\n", err); - - return err; - -} - static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { @@ -630,124 +608,6 @@ static const struct ethtool_ops brcmf_ethtool_ops = { .get_drvinfo = brcmf_ethtool_get_drvinfo, }; -static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr) -{ - struct brcmf_pub *drvr = ifp->drvr; - struct ethtool_drvinfo info; - char drvname[sizeof(info.driver)]; - u32 cmd; - struct ethtool_value edata; - u32 toe_cmpnt, csum_dir; - int ret; - - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); - - /* all ethtool calls start with a cmd word */ - if (copy_from_user(&cmd, uaddr, sizeof(u32))) - return -EFAULT; - - switch (cmd) { - case ETHTOOL_GDRVINFO: - /* Copy out any request driver name */ - if (copy_from_user(&info, uaddr, sizeof(info))) - return -EFAULT; - strncpy(drvname, info.driver, sizeof(info.driver)); - drvname[sizeof(info.driver) - 1] = '\0'; - - /* clear struct for return */ - memset(&info, 0, sizeof(info)); - info.cmd = cmd; - - /* if requested, identify ourselves */ - if (strcmp(drvname, "?dhd") == 0) { - sprintf(info.driver, "dhd"); - strcpy(info.version, BRCMF_VERSION_STR); - } - /* report dongle driver type */ - else - sprintf(info.driver, "wl"); - - sprintf(info.version, "%lu", drvr->drv_version); - if (copy_to_user(uaddr, &info, sizeof(info))) - return -EFAULT; - brcmf_dbg(TRACE, "given %*s, returning %s\n", - (int)sizeof(drvname), drvname, info.driver); - break; - - /* Get toe offload components from dongle */ - case ETHTOOL_GRXCSUM: - case ETHTOOL_GTXCSUM: - ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt); - if (ret < 0) - return ret; - - csum_dir = - (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; - - edata.cmd = cmd; - edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; - - if (copy_to_user(uaddr, &edata, sizeof(edata))) - return -EFAULT; - break; - - /* Set toe offload components in dongle */ - case ETHTOOL_SRXCSUM: - case ETHTOOL_STXCSUM: - if (copy_from_user(&edata, uaddr, sizeof(edata))) - return -EFAULT; - - /* Read the current settings, update and write back */ - ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt); - if (ret < 0) - return ret; - - csum_dir = - (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; - - if (edata.data != 0) - toe_cmpnt |= csum_dir; - else - toe_cmpnt &= ~csum_dir; - - ret = brcmf_toe_set(ifp, toe_cmpnt); - if (ret < 0) - return ret; - - /* If setting TX checksum mode, tell Linux the new mode */ - if (cmd == ETHTOOL_STXCSUM) { - if (edata.data) - ifp->ndev->features |= NETIF_F_IP_CSUM; - else - ifp->ndev->features &= ~NETIF_F_IP_CSUM; - } - - break; - - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, - int cmd) -{ - struct brcmf_if *ifp = netdev_priv(ndev); - struct brcmf_pub *drvr = ifp->drvr; - - brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd); - - if (!drvr->iflist[ifp->bssidx]) - return -1; - - if (cmd == SIOCETHTOOL) - return brcmf_ethtool(ifp, ifr->ifr_data); - - return -EOPNOTSUPP; -} - static int brcmf_netdev_stop(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); @@ -800,7 +660,6 @@ static const struct net_device_ops brcmf_netdev_ops_pri = { .ndo_open = brcmf_netdev_open, .ndo_stop = brcmf_netdev_stop, .ndo_get_stats = brcmf_netdev_get_stats, - .ndo_do_ioctl = brcmf_netdev_ioctl_entry, .ndo_start_xmit = brcmf_netdev_start_xmit, .ndo_set_mac_address = brcmf_netdev_set_mac_address, .ndo_set_rx_mode = brcmf_netdev_set_multicast_list @@ -866,13 +725,6 @@ static int brcmf_net_p2p_stop(struct net_device *ndev) return brcmf_cfg80211_down(ndev); } -static int brcmf_net_p2p_do_ioctl(struct net_device *ndev, - struct ifreq *ifr, int cmd) -{ - brcmf_dbg(TRACE, "Enter\n"); - return 0; -} - static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -885,7 +737,6 @@ static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb, static const struct net_device_ops brcmf_netdev_ops_p2p = { .ndo_open = brcmf_net_p2p_open, .ndo_stop = brcmf_net_p2p_stop, - .ndo_do_ioctl = brcmf_net_p2p_do_ioctl, .ndo_start_xmit = brcmf_net_p2p_start_xmit }; -- cgit v1.2.3 From 85b8413371225e9bcbbb30cf3caa5889fed5f6a4 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 29 Nov 2013 12:25:16 +0100 Subject: brcmfmac: Dynamically register a protocol layer. BCDC is the default protocol layer and being called directly. This patch installs the functions for this layer dynamically. This allows new protocols to be added and selected dynamically depending on the hw capabilties. As currently only BCDC is supported this is always the installed protocol. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/Makefile | 1 + drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 93 ++++++++++++---------- drivers/net/wireless/brcm80211/brcmfmac/bcdc.h | 24 ++++++ drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 24 +----- .../net/wireless/brcm80211/brcmfmac/dhd_linux.c | 4 +- drivers/net/wireless/brcm80211/brcmfmac/fwil.c | 7 +- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 1 + drivers/net/wireless/brcm80211/brcmfmac/proto.c | 62 +++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/proto.h | 57 +++++++++++++ 9 files changed, 202 insertions(+), 71 deletions(-) create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/bcdc.h create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/proto.c create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/proto.h (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index e15b61c26145..2082402d4b63 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -28,6 +28,7 @@ brcmfmac-objs += \ fweh.o \ fwsignal.o \ p2p.o \ + proto.o \ bcdc.o \ dhd_common.o \ dhd_linux.o \ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 59c6c054b113..b5a252908777 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -30,6 +30,8 @@ #include "fwsignal.h" #include "dhd_dbg.h" #include "tracepoint.h" +#include "proto.h" +#include "bcdc.h" struct brcmf_proto_cdc_dcmd { __le32 cmd; /* dongle command value */ @@ -104,7 +106,7 @@ struct brcmf_proto_bdc_header { * Currently is SDIO */ -struct brcmf_proto { +struct brcmf_bcdc { u16 reqid; u8 bus_header[BUS_HEADER_LEN]; struct brcmf_proto_cdc_dcmd msg; @@ -113,8 +115,8 @@ struct brcmf_proto { static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) { - struct brcmf_proto *prot = drvr->prot; - int len = le32_to_cpu(prot->msg.len) + + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + int len = le32_to_cpu(bcdc->msg.len) + sizeof(struct brcmf_proto_cdc_dcmd); brcmf_dbg(CDC, "Enter\n"); @@ -127,32 +129,32 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) len = CDC_MAX_MSG_SIZE; /* Send request */ - return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&prot->msg, len); + return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); } static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) { int ret; - struct brcmf_proto *prot = drvr->prot; + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; brcmf_dbg(CDC, "Enter\n"); len += sizeof(struct brcmf_proto_cdc_dcmd); do { - ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, + ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); if (ret < 0) break; - } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); + } while (CDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id); return ret; } -int -brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len) +static int +brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, + void *buf, uint len) { - struct brcmf_proto *prot = drvr->prot; - struct brcmf_proto_cdc_dcmd *msg = &prot->msg; + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_cdc_dcmd *msg = &bcdc->msg; void *info; int ret = 0, retries = 0; u32 id, flags; @@ -163,13 +165,13 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, msg->cmd = cpu_to_le32(cmd); msg->len = cpu_to_le32(len); - flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); + flags = (++bcdc->reqid << CDC_DCMD_ID_SHIFT); flags = (flags & ~CDC_DCMD_IF_MASK) | (ifidx << CDC_DCMD_IF_SHIFT); msg->flags = cpu_to_le32(flags); if (buf) - memcpy(prot->buf, buf, len); + memcpy(bcdc->buf, buf, len); ret = brcmf_proto_cdc_msg(drvr); if (ret < 0) { @@ -180,18 +182,18 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, retry: /* wait for interrupt and get first fragment */ - ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); + ret = brcmf_proto_cdc_cmplt(drvr, bcdc->reqid, len); if (ret < 0) goto done; flags = le32_to_cpu(msg->flags); id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; - if ((id < prot->reqid) && (++retries < RETRIES)) + if ((id < bcdc->reqid) && (++retries < RETRIES)) goto retry; - if (id != prot->reqid) { + if (id != bcdc->reqid) { brcmf_err("%s: unexpected request id %d (expected %d)\n", - brcmf_ifname(drvr, ifidx), id, prot->reqid); + brcmf_ifname(drvr, ifidx), id, bcdc->reqid); ret = -EINVAL; goto done; } @@ -214,11 +216,12 @@ done: return ret; } -int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len) +static int +brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, + void *buf, uint len) { - struct brcmf_proto *prot = drvr->prot; - struct brcmf_proto_cdc_dcmd *msg = &prot->msg; + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_cdc_dcmd *msg = &bcdc->msg; int ret = 0; u32 flags, id; @@ -228,28 +231,28 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, msg->cmd = cpu_to_le32(cmd); msg->len = cpu_to_le32(len); - flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; + flags = (++bcdc->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; flags = (flags & ~CDC_DCMD_IF_MASK) | (ifidx << CDC_DCMD_IF_SHIFT); msg->flags = cpu_to_le32(flags); if (buf) - memcpy(prot->buf, buf, len); + memcpy(bcdc->buf, buf, len); ret = brcmf_proto_cdc_msg(drvr); if (ret < 0) goto done; - ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); + ret = brcmf_proto_cdc_cmplt(drvr, bcdc->reqid, len); if (ret < 0) goto done; flags = le32_to_cpu(msg->flags); id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; - if (id != prot->reqid) { + if (id != bcdc->reqid) { brcmf_err("%s: unexpected request id %d (expected %d)\n", - brcmf_ifname(drvr, ifidx), id, prot->reqid); + brcmf_ifname(drvr, ifidx), id, bcdc->reqid); ret = -EINVAL; goto done; } @@ -272,7 +275,8 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x) skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); } -void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, +static void +brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, struct sk_buff *pktbuf) { struct brcmf_proto_bdc_header *h; @@ -295,8 +299,9 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, trace_brcmf_bdchdr(pktbuf->data); } -int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *pktbuf) +static int +brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, + struct sk_buff *pktbuf) { struct brcmf_proto_bdc_header *h; @@ -353,34 +358,38 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, return 0; } -int brcmf_proto_attach(struct brcmf_pub *drvr) +int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { - struct brcmf_proto *cdc; + struct brcmf_bcdc *bcdc; - cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); - if (!cdc) + bcdc = kzalloc(sizeof(*bcdc), GFP_ATOMIC); + if (!bcdc) goto fail; /* ensure that the msg buf directly follows the cdc msg struct */ - if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { - brcmf_err("struct brcmf_proto is not correctly defined\n"); + if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) { + brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n"); goto fail; } - drvr->prot = cdc; + drvr->proto->hdrpush = brcmf_proto_bcdc_hdrpush; + drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull; + drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd; + drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd; + drvr->proto->pd = bcdc; + drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; return 0; fail: - kfree(cdc); + kfree(bcdc); return -ENOMEM; } -/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ -void brcmf_proto_detach(struct brcmf_pub *drvr) +void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) { - kfree(drvr->prot); - drvr->prot = NULL; + kfree(drvr->proto->pd); + drvr->proto->pd = NULL; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h new file mode 100644 index 000000000000..17e8c039ff32 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef BRCMFMAC_BCDC_H +#define BRCMFMAC_BCDC_H + + +int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); + + +#endif /* BRCMFMAC_BCDC_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index dc2ebefa4cac..4ed7a97bd190 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -535,7 +535,7 @@ struct brcmf_fws_info; /* firmware signalling info */ struct brcmf_pub { /* Linkage ponters */ struct brcmf_bus *bus_if; - struct brcmf_proto *prot; + struct brcmf_proto *proto; struct brcmf_cfg80211_info *config; /* Internal brcmf items */ @@ -635,28 +635,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev); /* Return pointer to interface name */ char *brcmf_ifname(struct brcmf_pub *drvr, int idx); -/* Linkage, sets prot link and updates hdrlen in pub */ -int brcmf_proto_attach(struct brcmf_pub *drvr); - -/* Unlink, frees allocated protocol memory (including brcmf_proto) */ -void brcmf_proto_detach(struct brcmf_pub *drvr); - -/* Add any protocol-specific data header. - * Caller must reserve prot_hdrlen prepend space. - */ -void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, - struct sk_buff *txp); - -/* Query dongle */ -int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len); -int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len); - -/* Remove any protocol-specific data header. */ -int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *rxp); - int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, char *name, u8 *mac_addr); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 9336f6dd3f83..644e62e1963c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -30,6 +30,7 @@ #include "wl_cfg80211.h" #include "fwil.h" #include "fwsignal.h" +#include "proto.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -1040,8 +1041,7 @@ void brcmf_detach(struct device *dev) brcmf_bus_detach(drvr); - if (drvr->prot) - brcmf_proto_detach(drvr); + brcmf_proto_detach(drvr); brcmf_fws_deinit(drvr); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 04f395930d86..b72d3395499a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c @@ -27,6 +27,7 @@ #include "dhd_dbg.h" #include "tracepoint.h" #include "fwil.h" +#include "proto.h" #define MAX_HEX_DUMP_LEN 64 @@ -46,11 +47,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) if (data != NULL) len = min_t(uint, len, BRCMF_DCMD_MAXLEN); if (set) - err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data, - len); + err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); else - err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data, - len); + err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); if (err >= 0) err = 0; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index b96ee3a93a68..e9bdfdb95d8f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -35,6 +35,7 @@ #include "fwsignal.h" #include "p2p.h" #include "wl_cfg80211.h" +#include "proto.h" /** * DOC: Firmware Signalling diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c new file mode 100644 index 000000000000..87eb2bd4c072 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + + #include +#include +#include + +#include +#include "dhd.h" +#include "dhd_dbg.h" +#include "proto.h" +#include "bcdc.h" + + +int brcmf_proto_attach(struct brcmf_pub *drvr) +{ + struct brcmf_proto *proto; + + proto = kzalloc(sizeof(*proto), GFP_ATOMIC); + if (!proto) + goto fail; + + drvr->proto = proto; + /* BCDC protocol is only protocol supported for the moment */ + if (brcmf_proto_bcdc_attach(drvr)) + goto fail; + + if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) || + (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) { + brcmf_err("Not all proto handlers have been installed\n"); + goto fail; + } + return 0; + +fail: + kfree(proto); + drvr->proto = NULL; + return -ENOMEM; +} + +void brcmf_proto_detach(struct brcmf_pub *drvr) +{ + if (drvr->proto) { + brcmf_proto_bcdc_detach(drvr); + kfree(drvr->proto); + drvr->proto = NULL; + } +} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h new file mode 100644 index 000000000000..8de1b3bce228 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef BRCMFMAC_PROTO_H +#define BRCMFMAC_PROTO_H + +struct brcmf_proto { + void (*hdrpush)(struct brcmf_pub *drvr, int ifidx, u8 offset, + struct sk_buff *skb); + int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, + struct sk_buff *skb); + int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, + void *buf, uint len); + int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, + uint len); + void *pd; +}; + + +int brcmf_proto_attach(struct brcmf_pub *drvr); +void brcmf_proto_detach(struct brcmf_pub *drvr); + +static inline void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, + u8 offset, struct sk_buff *skb) +{ + drvr->proto->hdrpush(drvr, ifidx, offset, skb); +} +static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, + u8 *ifidx, struct sk_buff *skb) +{ + return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb); +} +static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, + uint cmd, void *buf, uint len) +{ + return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len); +} +static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx, + uint cmd, void *buf, uint len) +{ + return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); +} + + +#endif /* BRCMFMAC_PROTO_H */ -- cgit v1.2.3 From 55685b8f2f9f419b1b1c5abf78a5c82f01ef0fe3 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:17 +0100 Subject: brcmfmac: provide firmware version in ethtool driver info Knowing the firmware version is pretty useful information when looking at issues. It is retrieved during initialization so store it in driver data structure to fill the ethtool driver info when requested. Reviewed-by: Hante Meuleman Reviewed-by: Franky Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 7 ++++++- drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | 5 +++++ drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 4ed7a97bd190..714194c16a9d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -211,6 +211,11 @@ #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS 256 +/* Length of firmware version string stored for + * ethtool driver info which uses 32 bytes as well. + */ +#define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32 + /* Pattern matching filter. Specifies an offset within received packets to * start matching, the pattern to match, the size of the pattern, and a bitmask * that indicates which bits within the pattern should be matched. @@ -544,7 +549,7 @@ struct brcmf_pub { u8 wme_dp; /* wme discard priority */ /* Dongle media info */ - unsigned long drv_version; /* Version of dongle-resident driver */ + char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN]; u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ /* Multicast data packets sent to dongle */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 601763393184..d5811a46a338 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -278,9 +278,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) } ptr = (char *)buf; strsep(&ptr, "\n"); + /* Print fw version info */ brcmf_err("Firmware version = %s\n", buf); + /* locate firmware version number for ethtool */ + ptr = strrchr(buf, ' ') + 1; + strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); + /* * Setup timeout if Beacons are lost and roam is off to report * link down diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 644e62e1963c..bce0b8e511fd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -599,8 +599,8 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, struct brcmf_pub *drvr = ifp->drvr; strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - snprintf(info->version, sizeof(info->version), "%lu", - drvr->drv_version); + snprintf(info->version, sizeof(info->version), "n/a"); + strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version)); strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), sizeof(info->bus_info)); } -- cgit v1.2.3 From 84c69fb164cb0713c3e95bd190611f196d24c5b5 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:18 +0100 Subject: brcmfmac: remove unnecessary EXPORT_SYMBOL() usage In bcmsdh.c the functions brcmf_sdio_probe() and brcmf_sdio_remove() were exported, but that is not needed. The functions are linked into the driver module, which is the only one needing to call these. Reviewed-by: Franky Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Daniel (Deognyoun) Kim Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 3e10b801eee8..91651ec7f13f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -774,7 +773,6 @@ out: return ret; } -EXPORT_SYMBOL(brcmf_sdio_probe); int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) { @@ -791,7 +789,6 @@ int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) return 0; } -EXPORT_SYMBOL(brcmf_sdio_remove); void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) { -- cgit v1.2.3 From 6f5838a48aad77defef5e2ed91608e862309e351 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:19 +0100 Subject: brcmfmac: move firmware related structures to fwil_types.h The firmware control interface is provided by fwil source file, but a number of structures used to communicate with the firmware still resided in dhd.h. The patch moves them to fwil_types.h. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 306 --------------------- .../net/wireless/brcm80211/brcmfmac/dhd_common.c | 1 + .../net/wireless/brcm80211/brcmfmac/fwil_types.h | 304 ++++++++++++++++++++ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 10 +- 4 files changed, 310 insertions(+), 311 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 714194c16a9d..780615577fa8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -100,31 +100,11 @@ #define TOE_TX_CSUM_OL 0x00000001 #define TOE_RX_CSUM_OL 0x00000002 -#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ - -/* size of brcmf_scan_params not including variable length array */ -#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 - -/* masks for channel and ssid count */ -#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff -#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 - -/* primary (ie tx) key */ -#define BRCMF_PRIMARY_KEY (1 << 1) - /* For supporting multiple interfaces */ #define BRCMF_MAX_IFS 16 -#define DOT11_BSSTYPE_ANY 2 #define DOT11_MAX_DEFAULT_KEYS 4 -#define BRCMF_ESCAN_REQ_VERSION 1 - -#define WLC_BSS_RSSI_ON_CHANNEL 0x0002 - -#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ -#define BRCMF_STA_ASSOC 0x10 /* Associated */ - #define BRCMF_E_STATUS_SUCCESS 0 #define BRCMF_E_STATUS_FAIL 1 #define BRCMF_E_STATUS_TIMEOUT 2 @@ -216,292 +196,6 @@ */ #define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32 -/* Pattern matching filter. Specifies an offset within received packets to - * start matching, the pattern to match, the size of the pattern, and a bitmask - * that indicates which bits within the pattern should be matched. - */ -struct brcmf_pkt_filter_pattern_le { - /* - * Offset within received packet to start pattern matching. - * Offset '0' is the first byte of the ethernet header. - */ - __le32 offset; - /* Size of the pattern. Bitmask must be the same size.*/ - __le32 size_bytes; - /* - * Variable length mask and pattern data. mask starts at offset 0. - * Pattern immediately follows mask. - */ - u8 mask_and_pattern[1]; -}; - -/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ -struct brcmf_pkt_filter_le { - __le32 id; /* Unique filter id, specified by app. */ - __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ - __le32 negate_match; /* Negate the result of filter matches */ - union { /* Filter definitions */ - struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ - } u; -}; - -/* IOVAR "pkt_filter_enable" parameter. */ -struct brcmf_pkt_filter_enable_le { - __le32 id; /* Unique filter id */ - __le32 enable; /* Enable/disable bool */ -}; - -/* BSS info structure - * Applications MUST CHECK ie_offset field and length field to access IEs and - * next bss_info structure in a vector (in struct brcmf_scan_results) - */ -struct brcmf_bss_info_le { - __le32 version; /* version field */ - __le32 length; /* byte length of data in this record, - * starting at version and including IEs - */ - u8 BSSID[ETH_ALEN]; - __le16 beacon_period; /* units are Kusec */ - __le16 capability; /* Capability information */ - u8 SSID_len; - u8 SSID[32]; - struct { - __le32 count; /* # rates in this set */ - u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ - } rateset; /* supported rates */ - __le16 chanspec; /* chanspec for bss */ - __le16 atim_window; /* units are Kusec */ - u8 dtim_period; /* DTIM period */ - __le16 RSSI; /* receive signal strength (in dBm) */ - s8 phy_noise; /* noise (in dBm) */ - - u8 n_cap; /* BSS is 802.11N Capable */ - /* 802.11N BSS Capabilities (based on HT_CAP_*): */ - __le32 nbss_cap; - u8 ctl_ch; /* 802.11N BSS control channel number */ - __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ - u8 flags; /* flags */ - u8 reserved[3]; /* Reserved for expansion of BSS properties */ - u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ - - __le16 ie_offset; /* offset at which IEs start, from beginning */ - __le32 ie_length; /* byte length of Information Elements */ - __le16 SNR; /* average SNR of during frame reception */ - /* Add new fields here */ - /* variable length Information Elements */ -}; - -struct brcm_rateset_le { - /* # rates in this set */ - __le32 count; - /* rates in 500kbps units w/hi bit set if basic */ - u8 rates[BRCMF_MAXRATES_IN_SET]; -}; - -struct brcmf_ssid { - u32 SSID_len; - unsigned char SSID[32]; -}; - -struct brcmf_ssid_le { - __le32 SSID_len; - unsigned char SSID[32]; -}; - -struct brcmf_scan_params_le { - struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ - u8 bssid[ETH_ALEN]; /* default: bcast */ - s8 bss_type; /* default: any, - * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT - */ - u8 scan_type; /* flags, 0 use default */ - __le32 nprobes; /* -1 use default, number of probes per channel */ - __le32 active_time; /* -1 use default, dwell time per channel for - * active scanning - */ - __le32 passive_time; /* -1 use default, dwell time per channel - * for passive scanning - */ - __le32 home_time; /* -1 use default, dwell time for the - * home channel between channel scans - */ - __le32 channel_num; /* count of channels and ssids that follow - * - * low half is count of channels in - * channel_list, 0 means default (use all - * available channels) - * - * high half is entries in struct brcmf_ssid - * array that follows channel_list, aligned for - * s32 (4 bytes) meaning an odd channel count - * implies a 2-byte pad between end of - * channel_list and first ssid - * - * if ssid count is zero, single ssid in the - * fixed parameter portion is assumed, otherwise - * ssid in the fixed portion is ignored - */ - __le16 channel_list[1]; /* list of chanspecs */ -}; - -struct brcmf_scan_results { - u32 buflen; - u32 version; - u32 count; - struct brcmf_bss_info_le bss_info_le[]; -}; - -struct brcmf_escan_params_le { - __le32 version; - __le16 action; - __le16 sync_id; - struct brcmf_scan_params_le params_le; -}; - -struct brcmf_escan_result_le { - __le32 buflen; - __le32 version; - __le16 sync_id; - __le16 bss_count; - struct brcmf_bss_info_le bss_info_le; -}; - -#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \ - sizeof(struct brcmf_bss_info_le)) - -/* used for association with a specific BSSID and chanspec list */ -struct brcmf_assoc_params_le { - /* 00:00:00:00:00:00: broadcast scan */ - u8 bssid[ETH_ALEN]; - /* 0: all available channels, otherwise count of chanspecs in - * chanspec_list */ - __le32 chanspec_num; - /* list of chanspecs */ - __le16 chanspec_list[1]; -}; - -/* used for join with or without a specific bssid and channel list */ -struct brcmf_join_params { - struct brcmf_ssid_le ssid_le; - struct brcmf_assoc_params_le params_le; -}; - -/* scan params for extended join */ -struct brcmf_join_scan_params_le { - u8 scan_type; /* 0 use default, active or passive scan */ - __le32 nprobes; /* -1 use default, nr of probes per channel */ - __le32 active_time; /* -1 use default, dwell time per channel for - * active scanning - */ - __le32 passive_time; /* -1 use default, dwell time per channel - * for passive scanning - */ - __le32 home_time; /* -1 use default, dwell time for the home - * channel between channel scans - */ -}; - -/* extended join params */ -struct brcmf_ext_join_params_le { - struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */ - struct brcmf_join_scan_params_le scan_le; - struct brcmf_assoc_params_le assoc_le; -}; - -struct brcmf_wsec_key { - u32 index; /* key index */ - u32 len; /* key length */ - u8 data[WLAN_MAX_KEY_LEN]; /* key data */ - u32 pad_1[18]; - u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ - u32 flags; /* misc flags */ - u32 pad_2[3]; - u32 iv_initialized; /* has IV been initialized already? */ - u32 pad_3; - /* Rx IV */ - struct { - u32 hi; /* upper 32 bits of IV */ - u16 lo; /* lower 16 bits of IV */ - } rxiv; - u32 pad_4[2]; - u8 ea[ETH_ALEN]; /* per station */ -}; - -/* - * dongle requires same struct as above but with fields in little endian order - */ -struct brcmf_wsec_key_le { - __le32 index; /* key index */ - __le32 len; /* key length */ - u8 data[WLAN_MAX_KEY_LEN]; /* key data */ - __le32 pad_1[18]; - __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ - __le32 flags; /* misc flags */ - __le32 pad_2[3]; - __le32 iv_initialized; /* has IV been initialized already? */ - __le32 pad_3; - /* Rx IV */ - struct { - __le32 hi; /* upper 32 bits of IV */ - __le16 lo; /* lower 16 bits of IV */ - } rxiv; - __le32 pad_4[2]; - u8 ea[ETH_ALEN]; /* per station */ -}; - -/* Used to get specific STA parameters */ -struct brcmf_scb_val_le { - __le32 val; - u8 ea[ETH_ALEN]; -}; - -/* channel encoding */ -struct brcmf_channel_info_le { - __le32 hw_channel; - __le32 target_channel; - __le32 scan_channel; -}; - -struct brcmf_sta_info_le { - __le16 ver; /* version of this struct */ - __le16 len; /* length in bytes of this structure */ - __le16 cap; /* sta's advertised capabilities */ - __le32 flags; /* flags defined below */ - __le32 idle; /* time since data pkt rx'd from sta */ - u8 ea[ETH_ALEN]; /* Station address */ - __le32 count; /* # rates in this set */ - u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ - /* w/hi bit set if basic */ - __le32 in; /* seconds elapsed since associated */ - __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ - __le32 tx_pkts; /* # of packets transmitted */ - __le32 tx_failures; /* # of packets failed */ - __le32 rx_ucast_pkts; /* # of unicast packets received */ - __le32 rx_mcast_pkts; /* # of multicast packets received */ - __le32 tx_rate; /* Rate of last successful tx frame */ - __le32 rx_rate; /* Rate of last successful rx frame */ - __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ - __le32 rx_decrypt_failures; /* # of packet decrypted failed */ -}; - -struct brcmf_chanspec_list { - __le32 count; /* # of entries */ - __le32 element[1]; /* variable length uint32 list */ -}; - -/* - * WLC_E_PROBRESP_MSG - * WLC_E_P2P_PROBREQ_MSG - * WLC_E_ACTION_FRAME_RX - */ -struct brcmf_rx_mgmt_data { - __be16 version; - __be16 chanspec; - __be32 rssi; - __be32 mactime; - __be32 rate; -}; - /* Bus independent dongle command */ struct brcmf_dcmd { uint cmd; /* common dongle cmd definition */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index d5811a46a338..548dbb5542c6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -23,6 +23,7 @@ #include "dhd_bus.h" #include "dhd_dbg.h" #include "fwil.h" +#include "fwil_types.h" #include "tracepoint.h" #define PKTFILTER_BUF_SIZE 128 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index ecabb04f33c3..af17a5bc8b83 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h @@ -29,6 +29,24 @@ #define BRCMF_ARP_OL_HOST_AUTO_REPLY 0x00000004 #define BRCMF_ARP_OL_PEER_AUTO_REPLY 0x00000008 +#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ +#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 + +#define BRCMF_STA_ASSOC 0x10 /* Associated */ + +/* size of brcmf_scan_params not including variable length array */ +#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 + +/* masks for channel and ssid count */ +#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff +#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 + +/* primary (ie tx) key */ +#define BRCMF_PRIMARY_KEY (1 << 1) +#define DOT11_BSSTYPE_ANY 2 +#define BRCMF_ESCAN_REQ_VERSION 1 + +#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ enum brcmf_fil_p2p_if_types { BRCMF_FIL_P2P_IF_CLIENT, @@ -90,4 +108,290 @@ enum brcmf_tdls_manual_ep_ops { BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6 }; +/* Pattern matching filter. Specifies an offset within received packets to + * start matching, the pattern to match, the size of the pattern, and a bitmask + * that indicates which bits within the pattern should be matched. + */ +struct brcmf_pkt_filter_pattern_le { + /* + * Offset within received packet to start pattern matching. + * Offset '0' is the first byte of the ethernet header. + */ + __le32 offset; + /* Size of the pattern. Bitmask must be the same size.*/ + __le32 size_bytes; + /* + * Variable length mask and pattern data. mask starts at offset 0. + * Pattern immediately follows mask. + */ + u8 mask_and_pattern[1]; +}; + +/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ +struct brcmf_pkt_filter_le { + __le32 id; /* Unique filter id, specified by app. */ + __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ + __le32 negate_match; /* Negate the result of filter matches */ + union { /* Filter definitions */ + struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ + } u; +}; + +/* IOVAR "pkt_filter_enable" parameter. */ +struct brcmf_pkt_filter_enable_le { + __le32 id; /* Unique filter id */ + __le32 enable; /* Enable/disable bool */ +}; + +/* BSS info structure + * Applications MUST CHECK ie_offset field and length field to access IEs and + * next bss_info structure in a vector (in struct brcmf_scan_results) + */ +struct brcmf_bss_info_le { + __le32 version; /* version field */ + __le32 length; /* byte length of data in this record, + * starting at version and including IEs + */ + u8 BSSID[ETH_ALEN]; + __le16 beacon_period; /* units are Kusec */ + __le16 capability; /* Capability information */ + u8 SSID_len; + u8 SSID[32]; + struct { + __le32 count; /* # rates in this set */ + u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ + } rateset; /* supported rates */ + __le16 chanspec; /* chanspec for bss */ + __le16 atim_window; /* units are Kusec */ + u8 dtim_period; /* DTIM period */ + __le16 RSSI; /* receive signal strength (in dBm) */ + s8 phy_noise; /* noise (in dBm) */ + + u8 n_cap; /* BSS is 802.11N Capable */ + /* 802.11N BSS Capabilities (based on HT_CAP_*): */ + __le32 nbss_cap; + u8 ctl_ch; /* 802.11N BSS control channel number */ + __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ + u8 flags; /* flags */ + u8 reserved[3]; /* Reserved for expansion of BSS properties */ + u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ + + __le16 ie_offset; /* offset at which IEs start, from beginning */ + __le32 ie_length; /* byte length of Information Elements */ + __le16 SNR; /* average SNR of during frame reception */ + /* Add new fields here */ + /* variable length Information Elements */ +}; + +struct brcm_rateset_le { + /* # rates in this set */ + __le32 count; + /* rates in 500kbps units w/hi bit set if basic */ + u8 rates[BRCMF_MAXRATES_IN_SET]; +}; + +struct brcmf_ssid { + u32 SSID_len; + unsigned char SSID[32]; +}; + +struct brcmf_ssid_le { + __le32 SSID_len; + unsigned char SSID[32]; +}; + +struct brcmf_scan_params_le { + struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ + u8 bssid[ETH_ALEN]; /* default: bcast */ + s8 bss_type; /* default: any, + * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT + */ + u8 scan_type; /* flags, 0 use default */ + __le32 nprobes; /* -1 use default, number of probes per channel */ + __le32 active_time; /* -1 use default, dwell time per channel for + * active scanning + */ + __le32 passive_time; /* -1 use default, dwell time per channel + * for passive scanning + */ + __le32 home_time; /* -1 use default, dwell time for the + * home channel between channel scans + */ + __le32 channel_num; /* count of channels and ssids that follow + * + * low half is count of channels in + * channel_list, 0 means default (use all + * available channels) + * + * high half is entries in struct brcmf_ssid + * array that follows channel_list, aligned for + * s32 (4 bytes) meaning an odd channel count + * implies a 2-byte pad between end of + * channel_list and first ssid + * + * if ssid count is zero, single ssid in the + * fixed parameter portion is assumed, otherwise + * ssid in the fixed portion is ignored + */ + __le16 channel_list[1]; /* list of chanspecs */ +}; + +struct brcmf_scan_results { + u32 buflen; + u32 version; + u32 count; + struct brcmf_bss_info_le bss_info_le[]; +}; + +struct brcmf_escan_params_le { + __le32 version; + __le16 action; + __le16 sync_id; + struct brcmf_scan_params_le params_le; +}; + +struct brcmf_escan_result_le { + __le32 buflen; + __le32 version; + __le16 sync_id; + __le16 bss_count; + struct brcmf_bss_info_le bss_info_le; +}; + +#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \ + sizeof(struct brcmf_bss_info_le)) + +/* used for association with a specific BSSID and chanspec list */ +struct brcmf_assoc_params_le { + /* 00:00:00:00:00:00: broadcast scan */ + u8 bssid[ETH_ALEN]; + /* 0: all available channels, otherwise count of chanspecs in + * chanspec_list */ + __le32 chanspec_num; + /* list of chanspecs */ + __le16 chanspec_list[1]; +}; + +/* used for join with or without a specific bssid and channel list */ +struct brcmf_join_params { + struct brcmf_ssid_le ssid_le; + struct brcmf_assoc_params_le params_le; +}; + +/* scan params for extended join */ +struct brcmf_join_scan_params_le { + u8 scan_type; /* 0 use default, active or passive scan */ + __le32 nprobes; /* -1 use default, nr of probes per channel */ + __le32 active_time; /* -1 use default, dwell time per channel for + * active scanning + */ + __le32 passive_time; /* -1 use default, dwell time per channel + * for passive scanning + */ + __le32 home_time; /* -1 use default, dwell time for the home + * channel between channel scans + */ +}; + +/* extended join params */ +struct brcmf_ext_join_params_le { + struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */ + struct brcmf_join_scan_params_le scan_le; + struct brcmf_assoc_params_le assoc_le; +}; + +struct brcmf_wsec_key { + u32 index; /* key index */ + u32 len; /* key length */ + u8 data[WLAN_MAX_KEY_LEN]; /* key data */ + u32 pad_1[18]; + u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ + u32 flags; /* misc flags */ + u32 pad_2[3]; + u32 iv_initialized; /* has IV been initialized already? */ + u32 pad_3; + /* Rx IV */ + struct { + u32 hi; /* upper 32 bits of IV */ + u16 lo; /* lower 16 bits of IV */ + } rxiv; + u32 pad_4[2]; + u8 ea[ETH_ALEN]; /* per station */ +}; + +/* + * dongle requires same struct as above but with fields in little endian order + */ +struct brcmf_wsec_key_le { + __le32 index; /* key index */ + __le32 len; /* key length */ + u8 data[WLAN_MAX_KEY_LEN]; /* key data */ + __le32 pad_1[18]; + __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ + __le32 flags; /* misc flags */ + __le32 pad_2[3]; + __le32 iv_initialized; /* has IV been initialized already? */ + __le32 pad_3; + /* Rx IV */ + struct { + __le32 hi; /* upper 32 bits of IV */ + __le16 lo; /* lower 16 bits of IV */ + } rxiv; + __le32 pad_4[2]; + u8 ea[ETH_ALEN]; /* per station */ +}; + +/* Used to get specific STA parameters */ +struct brcmf_scb_val_le { + __le32 val; + u8 ea[ETH_ALEN]; +}; + +/* channel encoding */ +struct brcmf_channel_info_le { + __le32 hw_channel; + __le32 target_channel; + __le32 scan_channel; +}; + +struct brcmf_sta_info_le { + __le16 ver; /* version of this struct */ + __le16 len; /* length in bytes of this structure */ + __le16 cap; /* sta's advertised capabilities */ + __le32 flags; /* flags defined below */ + __le32 idle; /* time since data pkt rx'd from sta */ + u8 ea[ETH_ALEN]; /* Station address */ + __le32 count; /* # rates in this set */ + u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ + /* w/hi bit set if basic */ + __le32 in; /* seconds elapsed since associated */ + __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ + __le32 tx_pkts; /* # of packets transmitted */ + __le32 tx_failures; /* # of packets failed */ + __le32 rx_ucast_pkts; /* # of unicast packets received */ + __le32 rx_mcast_pkts; /* # of multicast packets received */ + __le32 tx_rate; /* Rate of last successful tx frame */ + __le32 rx_rate; /* Rate of last successful rx frame */ + __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ + __le32 rx_decrypt_failures; /* # of packet decrypted failed */ +}; + +struct brcmf_chanspec_list { + __le32 count; /* # of entries */ + __le32 element[1]; /* variable length uint32 list */ +}; + +/* + * WLC_E_PROBRESP_MSG + * WLC_E_P2P_PROBREQ_MSG + * WLC_E_ACTION_FRAME_RX + */ +struct brcmf_rx_mgmt_data { + __be16 version; + __be16 chanspec; + __be32 rssi; + __be32 mactime; + __be32 rate; +}; + #endif /* FWIL_TYPES_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 571f013cebbb..470a47f2b384 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -2556,8 +2556,8 @@ brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg, ch_bss.band == ch_bss_info_le.band && bss_info_le->SSID_len == bss->SSID_len && !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { - if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == - (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) { + if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == + (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL)) { s16 bss_rssi = le16_to_cpu(bss->RSSI); s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI); @@ -2566,13 +2566,13 @@ brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg, */ if (bss_info_rssi > bss_rssi) bss->RSSI = bss_info_le->RSSI; - } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && - (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { + } else if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) && + (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == 0) { /* preserve the on-channel rssi measurement * if the new measurement is off channel */ bss->RSSI = bss_info_le->RSSI; - bss->flags |= WLC_BSS_RSSI_ON_CHANNEL; + bss->flags |= BRCMF_BSS_RSSI_ON_CHANNEL; } return 1; } -- cgit v1.2.3 From 5ca85216b173ebac0aa523e4dd826d82d530a465 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:20 +0100 Subject: brcmfmac: move firmware command code definitions Move the command codes to the firmware interface module as that makes a bit more sense. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 61 -------------------------- drivers/net/wireless/brcm80211/brcmfmac/fwil.h | 61 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 780615577fa8..a85f9db36285 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -25,67 +25,6 @@ #include "fweh.h" -/******************************************************************************* - * IO codes that are interpreted by dongle firmware - ******************************************************************************/ -#define BRCMF_C_GET_VERSION 1 -#define BRCMF_C_UP 2 -#define BRCMF_C_DOWN 3 -#define BRCMF_C_SET_PROMISC 10 -#define BRCMF_C_GET_RATE 12 -#define BRCMF_C_GET_INFRA 19 -#define BRCMF_C_SET_INFRA 20 -#define BRCMF_C_GET_AUTH 21 -#define BRCMF_C_SET_AUTH 22 -#define BRCMF_C_GET_BSSID 23 -#define BRCMF_C_GET_SSID 25 -#define BRCMF_C_SET_SSID 26 -#define BRCMF_C_TERMINATED 28 -#define BRCMF_C_GET_CHANNEL 29 -#define BRCMF_C_SET_CHANNEL 30 -#define BRCMF_C_GET_SRL 31 -#define BRCMF_C_SET_SRL 32 -#define BRCMF_C_GET_LRL 33 -#define BRCMF_C_SET_LRL 34 -#define BRCMF_C_GET_RADIO 37 -#define BRCMF_C_SET_RADIO 38 -#define BRCMF_C_GET_PHYTYPE 39 -#define BRCMF_C_SET_KEY 45 -#define BRCMF_C_SET_PASSIVE_SCAN 49 -#define BRCMF_C_SCAN 50 -#define BRCMF_C_SCAN_RESULTS 51 -#define BRCMF_C_DISASSOC 52 -#define BRCMF_C_REASSOC 53 -#define BRCMF_C_SET_ROAM_TRIGGER 55 -#define BRCMF_C_SET_ROAM_DELTA 57 -#define BRCMF_C_GET_BCNPRD 75 -#define BRCMF_C_SET_BCNPRD 76 -#define BRCMF_C_GET_DTIMPRD 77 -#define BRCMF_C_SET_DTIMPRD 78 -#define BRCMF_C_SET_COUNTRY 84 -#define BRCMF_C_GET_PM 85 -#define BRCMF_C_SET_PM 86 -#define BRCMF_C_GET_CURR_RATESET 114 -#define BRCMF_C_GET_AP 117 -#define BRCMF_C_SET_AP 118 -#define BRCMF_C_GET_RSSI 127 -#define BRCMF_C_GET_WSEC 133 -#define BRCMF_C_SET_WSEC 134 -#define BRCMF_C_GET_PHY_NOISE 135 -#define BRCMF_C_GET_BSS_INFO 136 -#define BRCMF_C_GET_BANDLIST 140 -#define BRCMF_C_SET_SCB_TIMEOUT 158 -#define BRCMF_C_GET_PHYLIST 180 -#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 -#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 -#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 -#define BRCMF_C_GET_VALID_CHANNELS 217 -#define BRCMF_C_GET_KEY_PRIMARY 235 -#define BRCMF_C_SET_KEY_PRIMARY 236 -#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 -#define BRCMF_C_GET_VAR 262 -#define BRCMF_C_SET_VAR 263 - /* phy types (returned by WLC_GET_PHYTPE) */ #define WLC_PHY_TYPE_A 0 #define WLC_PHY_TYPE_B 1 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 16eb8202fb1e..77eae86e55c2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h @@ -17,6 +17,67 @@ #ifndef _fwil_h_ #define _fwil_h_ +/******************************************************************************* + * Dongle command codes that are interpreted by firmware + ******************************************************************************/ +#define BRCMF_C_GET_VERSION 1 +#define BRCMF_C_UP 2 +#define BRCMF_C_DOWN 3 +#define BRCMF_C_SET_PROMISC 10 +#define BRCMF_C_GET_RATE 12 +#define BRCMF_C_GET_INFRA 19 +#define BRCMF_C_SET_INFRA 20 +#define BRCMF_C_GET_AUTH 21 +#define BRCMF_C_SET_AUTH 22 +#define BRCMF_C_GET_BSSID 23 +#define BRCMF_C_GET_SSID 25 +#define BRCMF_C_SET_SSID 26 +#define BRCMF_C_TERMINATED 28 +#define BRCMF_C_GET_CHANNEL 29 +#define BRCMF_C_SET_CHANNEL 30 +#define BRCMF_C_GET_SRL 31 +#define BRCMF_C_SET_SRL 32 +#define BRCMF_C_GET_LRL 33 +#define BRCMF_C_SET_LRL 34 +#define BRCMF_C_GET_RADIO 37 +#define BRCMF_C_SET_RADIO 38 +#define BRCMF_C_GET_PHYTYPE 39 +#define BRCMF_C_SET_KEY 45 +#define BRCMF_C_SET_PASSIVE_SCAN 49 +#define BRCMF_C_SCAN 50 +#define BRCMF_C_SCAN_RESULTS 51 +#define BRCMF_C_DISASSOC 52 +#define BRCMF_C_REASSOC 53 +#define BRCMF_C_SET_ROAM_TRIGGER 55 +#define BRCMF_C_SET_ROAM_DELTA 57 +#define BRCMF_C_GET_BCNPRD 75 +#define BRCMF_C_SET_BCNPRD 76 +#define BRCMF_C_GET_DTIMPRD 77 +#define BRCMF_C_SET_DTIMPRD 78 +#define BRCMF_C_SET_COUNTRY 84 +#define BRCMF_C_GET_PM 85 +#define BRCMF_C_SET_PM 86 +#define BRCMF_C_GET_CURR_RATESET 114 +#define BRCMF_C_GET_AP 117 +#define BRCMF_C_SET_AP 118 +#define BRCMF_C_GET_RSSI 127 +#define BRCMF_C_GET_WSEC 133 +#define BRCMF_C_SET_WSEC 134 +#define BRCMF_C_GET_PHY_NOISE 135 +#define BRCMF_C_GET_BSS_INFO 136 +#define BRCMF_C_GET_BANDLIST 140 +#define BRCMF_C_SET_SCB_TIMEOUT 158 +#define BRCMF_C_GET_PHYLIST 180 +#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 +#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 +#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 +#define BRCMF_C_GET_VALID_CHANNELS 217 +#define BRCMF_C_GET_KEY_PRIMARY 235 +#define BRCMF_C_SET_KEY_PRIMARY 236 +#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 +#define BRCMF_C_GET_VAR 262 +#define BRCMF_C_SET_VAR 263 + s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); -- cgit v1.2.3 From aec87ce2f38c54dc7ef9bff2038e3b102a4e6c0c Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 29 Nov 2013 12:25:21 +0100 Subject: brcmfmac: Use consistent naming for BCDC. The BCDC protocol layer is using a mix of naming of CDC, BDC and BCDC. Use the name BCDC consistenly over all functions, defines and variables. This patch does not change code functionality. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 195 ++++++++++----------- drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | 2 +- .../net/wireless/brcm80211/brcmfmac/tracepoint.h | 4 +- 3 files changed, 95 insertions(+), 106 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index b5a252908777..06848e426f9a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -33,7 +33,7 @@ #include "proto.h" #include "bcdc.h" -struct brcmf_proto_cdc_dcmd { +struct brcmf_proto_bcdc_dcmd { __le32 cmd; /* dongle command value */ __le32 len; /* lower 16: output buflen; * upper 16: input buflen (excludes header) */ @@ -42,47 +42,47 @@ struct brcmf_proto_cdc_dcmd { }; /* Max valid buffer size that can be sent to the dongle */ -#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) - -/* CDC flag definitions */ -#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ -#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ -#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ -#define CDC_DCMD_IF_SHIFT 12 -#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ -#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ -#define CDC_DCMD_ID(flags) \ - (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) +#define BCDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) + +/* BCDC flag definitions */ +#define BCDC_DCMD_ERROR 0x01 /* 1=cmd failed */ +#define BCDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ +#define BCDC_DCMD_IF_MASK 0xF000 /* I/F index */ +#define BCDC_DCMD_IF_SHIFT 12 +#define BCDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ +#define BCDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ +#define BCDC_DCMD_ID(flags) \ + (((flags) & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT) /* - * BDC header - Broadcom specific extension of CDC. + * BCDC header - Broadcom specific extension of CDC. * Used on data packets to convey priority across USB. */ -#define BDC_HEADER_LEN 4 -#define BDC_PROTO_VER 2 /* Protocol version */ -#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ -#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ -#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ -#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ -#define BDC_PRIORITY_MASK 0x7 -#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ -#define BDC_FLAG2_IF_SHIFT 0 - -#define BDC_GET_IF_IDX(hdr) \ - ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) -#define BDC_SET_IF_IDX(hdr, idx) \ - ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ - ((idx) << BDC_FLAG2_IF_SHIFT))) +#define BCDC_HEADER_LEN 4 +#define BCDC_PROTO_VER 2 /* Protocol version */ +#define BCDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ +#define BCDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ +#define BCDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ +#define BCDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ +#define BCDC_PRIORITY_MASK 0x7 +#define BCDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ +#define BCDC_FLAG2_IF_SHIFT 0 + +#define BCDC_GET_IF_IDX(hdr) \ + ((int)((((hdr)->flags2) & BCDC_FLAG2_IF_MASK) >> BCDC_FLAG2_IF_SHIFT)) +#define BCDC_SET_IF_IDX(hdr, idx) \ + ((hdr)->flags2 = (((hdr)->flags2 & ~BCDC_FLAG2_IF_MASK) | \ + ((idx) << BCDC_FLAG2_IF_SHIFT))) /** - * struct brcmf_proto_bdc_header - BDC header format + * struct brcmf_proto_bcdc_header - BCDC header format * * @flags: flags contain protocol and checksum info. * @priority: 802.1d priority and USB flow control info (bit 4:7). * @flags2: additional flags containing dongle interface index. * @data_offset: start of packet data. header is following by firmware signals. */ -struct brcmf_proto_bdc_header { +struct brcmf_proto_bcdc_header { u8 flags; u8 priority; u8 flags2; @@ -91,7 +91,7 @@ struct brcmf_proto_bdc_header { /* * maximum length of firmware signal data between - * the BDC header and packet data in the tx path. + * the BCDC header and packet data in the tx path. */ #define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 @@ -109,42 +109,42 @@ struct brcmf_proto_bdc_header { struct brcmf_bcdc { u16 reqid; u8 bus_header[BUS_HEADER_LEN]; - struct brcmf_proto_cdc_dcmd msg; + struct brcmf_proto_bcdc_dcmd msg; unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; }; -static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) +static int brcmf_proto_bcdc_msg(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; int len = le32_to_cpu(bcdc->msg.len) + - sizeof(struct brcmf_proto_cdc_dcmd); + sizeof(struct brcmf_proto_bcdc_dcmd); - brcmf_dbg(CDC, "Enter\n"); + brcmf_dbg(BCDC, "Enter\n"); - /* NOTE : cdc->msg.len holds the desired length of the buffer to be - * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area + /* NOTE : bcdc->msg.len holds the desired length of the buffer to be + * returned. Only up to BCDC_MAX_MSG_SIZE of this buffer area * is actually sent to the dongle */ - if (len > CDC_MAX_MSG_SIZE) - len = CDC_MAX_MSG_SIZE; + if (len > BCDC_MAX_MSG_SIZE) + len = BCDC_MAX_MSG_SIZE; /* Send request */ return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); } -static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) +static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) { int ret; struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; - brcmf_dbg(CDC, "Enter\n"); - len += sizeof(struct brcmf_proto_cdc_dcmd); + brcmf_dbg(BCDC, "Enter\n"); + len += sizeof(struct brcmf_proto_bcdc_dcmd); do { ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); if (ret < 0) break; - } while (CDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id); + } while (BCDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id); return ret; } @@ -154,40 +154,40 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len) { struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; - struct brcmf_proto_cdc_dcmd *msg = &bcdc->msg; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; void *info; int ret = 0, retries = 0; u32 id, flags; - brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); - memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); + memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); msg->cmd = cpu_to_le32(cmd); msg->len = cpu_to_le32(len); - flags = (++bcdc->reqid << CDC_DCMD_ID_SHIFT); - flags = (flags & ~CDC_DCMD_IF_MASK) | - (ifidx << CDC_DCMD_IF_SHIFT); + flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT); + flags = (flags & ~BCDC_DCMD_IF_MASK) | + (ifidx << BCDC_DCMD_IF_SHIFT); msg->flags = cpu_to_le32(flags); if (buf) memcpy(bcdc->buf, buf, len); - ret = brcmf_proto_cdc_msg(drvr); + ret = brcmf_proto_bcdc_msg(drvr); if (ret < 0) { - brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n", + brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", ret); goto done; } retry: /* wait for interrupt and get first fragment */ - ret = brcmf_proto_cdc_cmplt(drvr, bcdc->reqid, len); + ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len); if (ret < 0) goto done; flags = le32_to_cpu(msg->flags); - id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; + id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT; if ((id < bcdc->reqid) && (++retries < RETRIES)) goto retry; @@ -209,7 +209,7 @@ retry: } /* Check the ERROR flag */ - if (flags & CDC_DCMD_ERROR) + if (flags & BCDC_DCMD_ERROR) ret = le32_to_cpu(msg->status); done: @@ -221,34 +221,34 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len) { struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; - struct brcmf_proto_cdc_dcmd *msg = &bcdc->msg; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; int ret = 0; u32 flags, id; - brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); - memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); + memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); msg->cmd = cpu_to_le32(cmd); msg->len = cpu_to_le32(len); - flags = (++bcdc->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; - flags = (flags & ~CDC_DCMD_IF_MASK) | - (ifidx << CDC_DCMD_IF_SHIFT); + flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT) | BCDC_DCMD_SET; + flags = (flags & ~BCDC_DCMD_IF_MASK) | + (ifidx << BCDC_DCMD_IF_SHIFT); msg->flags = cpu_to_le32(flags); if (buf) memcpy(bcdc->buf, buf, len); - ret = brcmf_proto_cdc_msg(drvr); + ret = brcmf_proto_bcdc_msg(drvr); if (ret < 0) goto done; - ret = brcmf_proto_cdc_cmplt(drvr, bcdc->reqid, len); + ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len); if (ret < 0) goto done; flags = le32_to_cpu(msg->flags); - id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; + id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT; if (id != bcdc->reqid) { brcmf_err("%s: unexpected request id %d (expected %d)\n", @@ -258,67 +258,56 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, } /* Check the ERROR flag */ - if (flags & CDC_DCMD_ERROR) + if (flags & BCDC_DCMD_ERROR) ret = le32_to_cpu(msg->status); done: return ret; } -static bool pkt_sum_needed(struct sk_buff *skb) -{ - return skb->ip_summed == CHECKSUM_PARTIAL; -} - -static void pkt_set_sum_good(struct sk_buff *skb, bool x) -{ - skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); -} - static void brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, struct sk_buff *pktbuf) { - struct brcmf_proto_bdc_header *h; + struct brcmf_proto_bcdc_header *h; - brcmf_dbg(CDC, "Enter\n"); + brcmf_dbg(BCDC, "Enter\n"); /* Push BDC header used to convey priority for buses that don't */ - skb_push(pktbuf, BDC_HEADER_LEN); + skb_push(pktbuf, BCDC_HEADER_LEN); - h = (struct brcmf_proto_bdc_header *)(pktbuf->data); + h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); - h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); - if (pkt_sum_needed(pktbuf)) - h->flags |= BDC_FLAG_SUM_NEEDED; + h->flags = (BCDC_PROTO_VER << BCDC_FLAG_VER_SHIFT); + if (pktbuf->ip_summed == CHECKSUM_PARTIAL) + h->flags |= BCDC_FLAG_SUM_NEEDED; - h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); + h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK); h->flags2 = 0; h->data_offset = offset; - BDC_SET_IF_IDX(h, ifidx); - trace_brcmf_bdchdr(pktbuf->data); + BCDC_SET_IF_IDX(h, ifidx); + trace_brcmf_bcdchdr(pktbuf->data); } static int brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, struct sk_buff *pktbuf) { - struct brcmf_proto_bdc_header *h; - - brcmf_dbg(CDC, "Enter\n"); + struct brcmf_proto_bcdc_header *h; - /* Pop BDC header used to convey priority for buses that don't */ + brcmf_dbg(BCDC, "Enter\n"); - if (pktbuf->len <= BDC_HEADER_LEN) { + /* Pop BCDC header used to convey priority for buses that don't */ + if (pktbuf->len <= BCDC_HEADER_LEN) { brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", - pktbuf->len, BDC_HEADER_LEN); + pktbuf->len, BCDC_HEADER_LEN); return -EBADE; } - trace_brcmf_bdchdr(pktbuf->data); - h = (struct brcmf_proto_bdc_header *)(pktbuf->data); + trace_brcmf_bcdchdr(pktbuf->data); + h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); - *ifidx = BDC_GET_IF_IDX(h); + *ifidx = BCDC_GET_IF_IDX(h); if (*ifidx >= BRCMF_MAX_IFS) { brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); return -EBADE; @@ -332,22 +321,22 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, if (*ifidx) (*ifidx)++; - if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != - BDC_PROTO_VER) { - brcmf_err("%s: non-BDC packet received, flags 0x%x\n", + if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != + BCDC_PROTO_VER) { + brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", brcmf_ifname(drvr, *ifidx), h->flags); return -EBADE; } - if (h->flags & BDC_FLAG_SUM_GOOD) { - brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n", + if (h->flags & BCDC_FLAG_SUM_GOOD) { + brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", brcmf_ifname(drvr, *ifidx), h->flags); - pkt_set_sum_good(pktbuf, true); + pktbuf->ip_summed = CHECKSUM_UNNECESSARY; } - pktbuf->priority = h->priority & BDC_PRIORITY_MASK; + pktbuf->priority = h->priority & BCDC_PRIORITY_MASK; - skb_pull(pktbuf, BDC_HEADER_LEN); + skb_pull(pktbuf, BCDC_HEADER_LEN); if (do_fws) brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); else @@ -378,9 +367,9 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd; drvr->proto->pd = bcdc; - drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; + drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + - sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; + sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN; return 0; fail: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index 0af1f5dc583a..ef52ed7abc69 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -33,7 +33,7 @@ #define BRCMF_USB_VAL 0x00002000 #define BRCMF_SCAN_VAL 0x00004000 #define BRCMF_CONN_VAL 0x00008000 -#define BRCMF_CDC_VAL 0x00010000 +#define BRCMF_BCDC_VAL 0x00010000 #define BRCMF_SDIO_VAL 0x00020000 /* set default print format */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index d229cda98aa7..4d7d51f95716 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h @@ -89,7 +89,7 @@ TRACE_EVENT(brcmf_hexdump, TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len) ); -TRACE_EVENT(brcmf_bdchdr, +TRACE_EVENT(brcmf_bcdchdr, TP_PROTO(void *data), TP_ARGS(data), TP_STRUCT__entry( @@ -107,7 +107,7 @@ TRACE_EVENT(brcmf_bdchdr, memcpy(__get_dynamic_array(signal), (u8 *)data + 4, __entry->siglen); ), - TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) + TP_printk("bcdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) ); #ifndef SDPCM_RX -- cgit v1.2.3 From b881879dea8d4bbfc71534d9dc5c9cf8298127a9 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:22 +0100 Subject: brcmfmac: remove some unused definitions Removing WLC_PHY_TYPE and some BRCMF_E_.* definitions as these are not used in the driver sources. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 48 --------------------------- 1 file changed, 48 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index a85f9db36285..da5cf00ac09c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -25,17 +25,6 @@ #include "fweh.h" -/* phy types (returned by WLC_GET_PHYTPE) */ -#define WLC_PHY_TYPE_A 0 -#define WLC_PHY_TYPE_B 1 -#define WLC_PHY_TYPE_G 2 -#define WLC_PHY_TYPE_N 4 -#define WLC_PHY_TYPE_LP 5 -#define WLC_PHY_TYPE_SSN 6 -#define WLC_PHY_TYPE_HT 7 -#define WLC_PHY_TYPE_LCN 8 -#define WLC_PHY_TYPE_NULL 0xf - #define TOE_TX_CSUM_OL 0x00000001 #define TOE_RX_CSUM_OL 0x00000002 @@ -75,38 +64,6 @@ #define BRCMF_E_REASON_TSPEC_REJECTED 7 #define BRCMF_E_REASON_BETTER_AP 8 -#define BRCMF_E_PRUNE_ENCR_MISMATCH 1 -#define BRCMF_E_PRUNE_BCAST_BSSID 2 -#define BRCMF_E_PRUNE_MAC_DENY 3 -#define BRCMF_E_PRUNE_MAC_NA 4 -#define BRCMF_E_PRUNE_REG_PASSV 5 -#define BRCMF_E_PRUNE_SPCT_MGMT 6 -#define BRCMF_E_PRUNE_RADAR 7 -#define BRCMF_E_RSN_MISMATCH 8 -#define BRCMF_E_PRUNE_NO_COMMON_RATES 9 -#define BRCMF_E_PRUNE_BASIC_RATES 10 -#define BRCMF_E_PRUNE_CIPHER_NA 12 -#define BRCMF_E_PRUNE_KNOWN_STA 13 -#define BRCMF_E_PRUNE_WDS_PEER 15 -#define BRCMF_E_PRUNE_QBSS_LOAD 16 -#define BRCMF_E_PRUNE_HOME_AP 17 - -#define BRCMF_E_SUP_OTHER 0 -#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1 -#define BRCMF_E_SUP_BAD_UCAST_WEP128 2 -#define BRCMF_E_SUP_BAD_UCAST_WEP40 3 -#define BRCMF_E_SUP_UNSUP_KEY_LEN 4 -#define BRCMF_E_SUP_PW_KEY_CIPHER 5 -#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6 -#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7 -#define BRCMF_E_SUP_NO_INSTALL_FLAG 8 -#define BRCMF_E_SUP_MSG3_NO_GTK 9 -#define BRCMF_E_SUP_GRP_KEY_CIPHER 10 -#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11 -#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12 -#define BRCMF_E_SUP_SEND_FAIL 13 -#define BRCMF_E_SUP_DEAUTH 14 - #define BRCMF_E_IF_ADD 1 #define BRCMF_E_IF_DEL 2 #define BRCMF_E_IF_CHANGE 3 @@ -117,11 +74,6 @@ #define BRCMF_E_IF_ROLE_AP 1 #define BRCMF_E_IF_ROLE_WDS 2 -#define BRCMF_E_LINK_BCN_LOSS 1 -#define BRCMF_E_LINK_DISASSOC 2 -#define BRCMF_E_LINK_ASSOC_REC 3 -#define BRCMF_E_LINK_BSSCFG_DIS 4 - /* Small, medium and maximum buffer size for dcmd */ #define BRCMF_DCMD_SMLEN 256 -- cgit v1.2.3 From 01376a07bcf72fdad1ed5ed906025ca786d333dc Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:23 +0100 Subject: brcmfmac: move firmware event related defines to fweh.h The dhd.h file contained a number of definitions that are related to events received from the firmware. Those are processed and dispatched in the driver by fweh. Hence the definitions are moved to its include file. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 49 ----------------------- drivers/net/wireless/brcm80211/brcmfmac/fweh.h | 54 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index da5cf00ac09c..252024bcbc3b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -33,47 +33,6 @@ #define DOT11_MAX_DEFAULT_KEYS 4 -#define BRCMF_E_STATUS_SUCCESS 0 -#define BRCMF_E_STATUS_FAIL 1 -#define BRCMF_E_STATUS_TIMEOUT 2 -#define BRCMF_E_STATUS_NO_NETWORKS 3 -#define BRCMF_E_STATUS_ABORT 4 -#define BRCMF_E_STATUS_NO_ACK 5 -#define BRCMF_E_STATUS_UNSOLICITED 6 -#define BRCMF_E_STATUS_ATTEMPT 7 -#define BRCMF_E_STATUS_PARTIAL 8 -#define BRCMF_E_STATUS_NEWSCAN 9 -#define BRCMF_E_STATUS_NEWASSOC 10 -#define BRCMF_E_STATUS_11HQUIET 11 -#define BRCMF_E_STATUS_SUPPRESS 12 -#define BRCMF_E_STATUS_NOCHANS 13 -#define BRCMF_E_STATUS_CS_ABORT 15 -#define BRCMF_E_STATUS_ERROR 16 - -#define BRCMF_E_REASON_INITIAL_ASSOC 0 -#define BRCMF_E_REASON_LOW_RSSI 1 -#define BRCMF_E_REASON_DEAUTH 2 -#define BRCMF_E_REASON_DISASSOC 3 -#define BRCMF_E_REASON_BCNS_LOST 4 -#define BRCMF_E_REASON_MINTXRATE 9 -#define BRCMF_E_REASON_TXFAIL 10 - -#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4 -#define BRCMF_E_REASON_FAST_ROAM_FAILED 5 -#define BRCMF_E_REASON_DIRECTED_ROAM 6 -#define BRCMF_E_REASON_TSPEC_REJECTED 7 -#define BRCMF_E_REASON_BETTER_AP 8 - -#define BRCMF_E_IF_ADD 1 -#define BRCMF_E_IF_DEL 2 -#define BRCMF_E_IF_CHANGE 3 - -#define BRCMF_E_IF_FLAG_NOIF 1 - -#define BRCMF_E_IF_ROLE_STA 0 -#define BRCMF_E_IF_ROLE_AP 1 -#define BRCMF_E_IF_ROLE_WDS 2 - /* Small, medium and maximum buffer size for dcmd */ #define BRCMF_DCMD_SMLEN 256 @@ -156,14 +115,6 @@ struct brcmf_pub { #endif }; -struct brcmf_if_event { - u8 ifidx; - u8 action; - u8 flags; - u8 bssidx; - u8 role; -}; - /* forward declarations */ struct brcmf_cfg80211_vif; struct brcmf_fws_mac_descriptor; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 14bc24dc5bae..51b53a73d074 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -122,6 +122,52 @@ enum brcmf_fweh_event_code { #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 #define BRCMF_EVENT_MSG_GROUP 0x04 +/* status field values in struct brcmf_event_msg */ +#define BRCMF_E_STATUS_SUCCESS 0 +#define BRCMF_E_STATUS_FAIL 1 +#define BRCMF_E_STATUS_TIMEOUT 2 +#define BRCMF_E_STATUS_NO_NETWORKS 3 +#define BRCMF_E_STATUS_ABORT 4 +#define BRCMF_E_STATUS_NO_ACK 5 +#define BRCMF_E_STATUS_UNSOLICITED 6 +#define BRCMF_E_STATUS_ATTEMPT 7 +#define BRCMF_E_STATUS_PARTIAL 8 +#define BRCMF_E_STATUS_NEWSCAN 9 +#define BRCMF_E_STATUS_NEWASSOC 10 +#define BRCMF_E_STATUS_11HQUIET 11 +#define BRCMF_E_STATUS_SUPPRESS 12 +#define BRCMF_E_STATUS_NOCHANS 13 +#define BRCMF_E_STATUS_CS_ABORT 15 +#define BRCMF_E_STATUS_ERROR 16 + +/* reason field values in struct brcmf_event_msg */ +#define BRCMF_E_REASON_INITIAL_ASSOC 0 +#define BRCMF_E_REASON_LOW_RSSI 1 +#define BRCMF_E_REASON_DEAUTH 2 +#define BRCMF_E_REASON_DISASSOC 3 +#define BRCMF_E_REASON_BCNS_LOST 4 +#define BRCMF_E_REASON_MINTXRATE 9 +#define BRCMF_E_REASON_TXFAIL 10 + +#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4 +#define BRCMF_E_REASON_FAST_ROAM_FAILED 5 +#define BRCMF_E_REASON_DIRECTED_ROAM 6 +#define BRCMF_E_REASON_TSPEC_REJECTED 7 +#define BRCMF_E_REASON_BETTER_AP 8 + +/* action field values for brcmf_ifevent */ +#define BRCMF_E_IF_ADD 1 +#define BRCMF_E_IF_DEL 2 +#define BRCMF_E_IF_CHANGE 3 + +/* flag field values for brcmf_ifevent */ +#define BRCMF_E_IF_FLAG_NOIF 1 + +/* role field values for brcmf_ifevent */ +#define BRCMF_E_IF_ROLE_STA 0 +#define BRCMF_E_IF_ROLE_AP 1 +#define BRCMF_E_IF_ROLE_WDS 2 + /** * definitions for event packet validation. */ @@ -160,6 +206,14 @@ struct brcmf_event_msg { u8 bsscfgidx; }; +struct brcmf_if_event { + u8 ifidx; + u8 action; + u8 flags; + u8 bssidx; + u8 role; +}; + typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, const struct brcmf_event_msg *evtmsg, void *data); -- cgit v1.2.3 From 7d68849f40cd9169088249cc889d95c8998c3fb8 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 29 Nov 2013 12:25:24 +0100 Subject: brcmfmac: expose chip information through debugfs Adding the debugfs file /brcmfmac//chipinfo which contains the chip number and revision. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | 36 ++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 0f9e9057e7dd..03fe8aca4d32 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c @@ -22,7 +22,6 @@ #include "dhd.h" #include "dhd_bus.h" #include "dhd_dbg.h" -#include "tracepoint.h" static struct dentry *root_folder; @@ -42,6 +41,40 @@ void brcmf_debugfs_exit(void) root_folder = NULL; } +static +ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data, + size_t count, loff_t *ppos) +{ + struct brcmf_pub *drvr = f->private_data; + struct brcmf_bus *bus = drvr->bus_if; + char buf[40]; + int res; + + /* only allow read from start */ + if (*ppos > 0) + return 0; + + res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n", + bus->chip, bus->chip, bus->chiprev); + return simple_read_from_buffer(data, count, ppos, buf, res); +} + +static const struct file_operations brcmf_debugfs_chipinfo_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = brcmf_debugfs_chipinfo_read +}; + +static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr) +{ + struct dentry *dentry = drvr->dbgfs_dir; + + if (!IS_ERR_OR_NULL(dentry)) + debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr, + &brcmf_debugfs_chipinfo_ops); + return 0; +} + int brcmf_debugfs_attach(struct brcmf_pub *drvr) { struct device *dev = drvr->bus_if->dev; @@ -50,6 +83,7 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) return -ENODEV; drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); + brcmf_debugfs_create_chipinfo(drvr); return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); } -- cgit v1.2.3 From 587194873820a4a1b2eda260ac851394095afd77 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 9 Sep 2013 21:03:09 +0300 Subject: xhci: convert TRB_CYCLE to le32 before using it to set Link TRB's cycle bit This patch converts TRB_CYCLE to le32 to update correctly the Cycle Bit in 'control' field of the link TRB. This bug was found using sparse. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-mem.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 49b8bd063fab..90709cf45ee5 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -57,7 +57,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */ if (cycle_state == 0) { for (i = 0; i < TRBS_PER_SEGMENT; i++) - seg->trbs[i].link.control |= TRB_CYCLE; + seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE); } seg->dma = dma; seg->next = NULL; @@ -308,7 +308,8 @@ static void xhci_reinit_cached_ring(struct xhci_hcd *xhci, sizeof(union xhci_trb)*TRBS_PER_SEGMENT); if (cycle_state == 0) { for (i = 0; i < TRBS_PER_SEGMENT; i++) - seg->trbs[i].link.control |= TRB_CYCLE; + seg->trbs[i].link.control |= + cpu_to_le32(TRB_CYCLE); } /* All endpoint rings have link TRBs */ xhci_link_segments(xhci, seg, seg->next, type); -- cgit v1.2.3 From 7e76ad431545d013911ddc744843118b43d01e89 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 9 Sep 2013 21:03:10 +0300 Subject: xhci: fix incorrect type in assignment in handle_device_notification() This patch converts Event TRB's 3rd field, which has type le32, to CPU byteorder before using it to retrieve the Slot ID with TRB_TO_SLOT_ID macro. This bug was found using sparse. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1e2f3f495843..22da09388a74 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1655,7 +1655,7 @@ static void handle_device_notification(struct xhci_hcd *xhci, u32 slot_id; struct usb_device *udev; - slot_id = TRB_TO_SLOT_ID(event->generic.field[3]); + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->generic.field[3])); if (!xhci->devs[slot_id]) { xhci_warn(xhci, "Device Notification event for " "unused slot %u\n", slot_id); -- cgit v1.2.3 From f00466963817c8a240f022af864cdc39d482cdb7 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 9 Sep 2013 21:03:11 +0300 Subject: xhci: fix derivation of TRB's DMA address in xhci_log_event Trace Event Class This patch fixes the retrieval of the DMA address of the TRB that generated the event by converting the field[0] (low address bits) and field[1] (high address bits) to CPU byteorder and then typecasting field[1] to u64 so that the bitshift will not lead to overflow. In the original code, the typecasting of le32 to u64 was incorrect and the subsequent conversion to le64 reverts the low and high address parts. This bug was found using sparse. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 20364cc8d2fb..afe093340834 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -120,8 +120,8 @@ DECLARE_EVENT_CLASS(xhci_log_event, ), TP_fast_assign( __entry->va = trb_va; - __entry->dma = le64_to_cpu(((u64)ev->field[1]) << 32 | - ev->field[0]); + __entry->dma = ((u64)le32_to_cpu(ev->field[1])) << 32 | + le32_to_cpu(ev->field[0]); __entry->status = le32_to_cpu(ev->field[2]); __entry->flags = le32_to_cpu(ev->field[3]); memcpy(__get_dynamic_array(trb), trb_va, -- cgit v1.2.3 From d20c72256721411f55eb95beddf1d8a5d5da31eb Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 9 Sep 2013 21:03:12 +0300 Subject: xhci: fix sparse warning in xhci-trace.h This patch fixes the following sparse warnings: drivers/usb/host/./xhci-trace.h:116:1: warning: cast to restricted __le32 drivers/usb/host/./xhci-trace.h:116:1: warning: cast to restricted __le32 drivers/usb/host/./xhci-trace.h:116:1: warning: restricted __le32 degrades to integer drivers/usb/host/./xhci-trace.h:116:1: warning: restricted __le32 degrades to integer by converting the field 'trb' of the trace buffer entry structure from array with elements of type __le32 to an array with elements of type u8. Into the trb array are copied the contents of the TRB that generated the event. The trace-cmd tool with the help of plugin_xhci.py will use this field to parse the TRB contents in a human readable way. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index afe093340834..dde3959b7a33 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -116,7 +116,7 @@ DECLARE_EVENT_CLASS(xhci_log_event, __field(u64, dma) __field(u32, status) __field(u32, flags) - __dynamic_array(__le32, trb, 4) + __dynamic_array(u8, trb, sizeof(struct xhci_generic_trb)) ), TP_fast_assign( __entry->va = trb_va; -- cgit v1.2.3 From 0c052aabe66c495bf1248f301a8e745da66c6633 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Fri, 15 Nov 2013 03:18:07 +0200 Subject: xhci: fix incorrect type in assignment in xhci_address_device() The field 'dev_info' in struct xhci_slot_ctx has type __le32 and it needs to be converted to CPU byteorder for the correct retrieval of its subfield 'Context Entries'. This field is used by the trace event 'xhci_address_ctx' to trace only the contexts of valid endpoints. This bug was found using sparse. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4265b48856f6..a96b35cf4fa7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3771,7 +3771,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); trace_xhci_address_ctx(xhci, virt_dev->in_ctx, - slot_ctx->dev_info >> 27); + le32_to_cpu(slot_ctx->dev_info) >> 27); spin_lock_irqsave(&xhci->lock, flags); cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring); @@ -3850,7 +3850,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); trace_xhci_address_ctx(xhci, virt_dev->in_ctx, - slot_ctx->dev_info >> 27); + le32_to_cpu(slot_ctx->dev_info) >> 27); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); /* @@ -3859,7 +3859,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) */ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); trace_xhci_address_ctx(xhci, virt_dev->out_ctx, - slot_ctx->dev_info >> 27); + le32_to_cpu(slot_ctx->dev_info) >> 27); /* Zero the input context control for later use */ ctrl_ctx->add_flags = 0; ctrl_ctx->drop_flags = 0; -- cgit v1.2.3 From 64ba419b7a5acf5fc934bfad9cc46c7f17ab8026 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 26 Aug 2013 23:29:46 +0300 Subject: xhci: replace USB_MAXINTERFACES with config->desc.bNumInterface This patch replaces USB_MAXINTERFACES with config->desc.bNumInterface in the termination condition for the loop that updates the LPM timeout of the endpoints on the cofiguration's interfaces, in xhci_calculate_lpm_timeout(), to avoid unnecessary loop cycles since most configurations come with 1-2 interfaces while USB_MAXINTERFACES is 32. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a96b35cf4fa7..1798c5353102 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4455,7 +4455,7 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, if (!config) return timeout; - for (i = 0; i < USB_MAXINTERFACES; i++) { + for (i = 0; i < config->desc.bNumInterfaces; i++) { struct usb_driver *driver; struct usb_interface *intf = config->interface[i]; -- cgit v1.2.3 From 63a67a72d63dd077c2313cf19eb29d8e4bfa6963 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 26 Aug 2013 23:29:47 +0300 Subject: xhci: fix SCT_FOR_CTX(p) macro SCT_FOR_CTX(p) is defined as (((p) << 1) & 0x7) in which case if we want to set the stream context type to SCT_SSA_256 i.e 0x7 (although secondary stream arrays are not yet supported) using this macro definition we will get actually 0x6 which is not what we want. This patch fixes the above issue by defining the SCT_FOR_CTX(p) macro as (((p) & 0x7) << 1) Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 03c74b7965f8..a33e8b5bf7a2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -752,7 +752,7 @@ struct xhci_stream_ctx { }; /* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */ -#define SCT_FOR_CTX(p) (((p) << 1) & 0x7) +#define SCT_FOR_CTX(p) (((p) & 0x7) << 1) /* Secondary stream array type, dequeue pointer is to a transfer ring */ #define SCT_SEC_TR 0 /* Primary stream array type, dequeue pointer is to a transfer ring */ -- cgit v1.2.3 From 0d3703be3a671ca225a796f4ae6e904dd83c2e07 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 26 Aug 2013 23:29:48 +0300 Subject: xhci: remove unnecessary check in xhci_free_stream_info() This patch removes the unneccessary check 'if (stream_info)' because there is already a check few lines above which ensures that stream_info is not NULL. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-mem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 90709cf45ee5..1445e08819cf 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -722,8 +722,7 @@ void xhci_free_stream_info(struct xhci_hcd *xhci, stream_info->stream_ctx_array, stream_info->ctx_array_dma); - if (stream_info) - kfree(stream_info->stream_rings); + kfree(stream_info->stream_rings); kfree(stream_info); } -- cgit v1.2.3 From ef73400ca5d1ad695374988510b9977c41b81f3e Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 9 Sep 2013 21:03:06 +0300 Subject: xhci: fix incorrect type in assignment in xhci_count_num_new_endpoints() The fields 'add_flags' and 'drop_flags' in struct xhci_input_control_ctx have type __le32 and need to be converted to CPU byteorder before being used to derive the number of added endpoints. This bug was found using sparse. This patch is not suitable for stable, since the bug would only be triggered on big endian systems, and the code only runs for Intel xHCI host controllers, which are always integrated into little endian systems. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1798c5353102..b7289e9a44dd 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1892,8 +1892,8 @@ static u32 xhci_count_num_new_endpoints(struct xhci_hcd *xhci, * (bit 1). The default control endpoint is added during the Address * Device command and is never removed until the slot is disabled. */ - valid_add_flags = ctrl_ctx->add_flags >> 2; - valid_drop_flags = ctrl_ctx->drop_flags >> 2; + valid_add_flags = le32_to_cpu(ctrl_ctx->add_flags) >> 2; + valid_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags) >> 2; /* Use hweight32 to count the number of ones in the add flags, or * number of endpoints added. Don't count endpoints that are changed -- cgit v1.2.3 From 78d1ff025698e1a70e3fef38342648d4dc826cf6 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 9 Sep 2013 21:03:07 +0300 Subject: xhci: fix incorrect type in assignment in xhci_count_num_dropped_endpoints() The fields 'add_flags' and 'drop_flags' in struct xhci_input_control_ctx have type __le32 and need to be converted to CPU byteorder before being used to derive the number of dropped endpoints. This bug was found using sparse. This patch is not suitable for stable, since the bug would only be triggered on big endian systems, and the code only runs for Intel xHCI host controllers, which are always integrated into little endian systems. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b7289e9a44dd..900ba36ee2b8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1909,8 +1909,8 @@ static unsigned int xhci_count_num_dropped_endpoints(struct xhci_hcd *xhci, u32 valid_add_flags; u32 valid_drop_flags; - valid_add_flags = ctrl_ctx->add_flags >> 2; - valid_drop_flags = ctrl_ctx->drop_flags >> 2; + valid_add_flags = le32_to_cpu(ctrl_ctx->add_flags) >> 2; + valid_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags) >> 2; return hweight32(valid_drop_flags) - hweight32(valid_add_flags & valid_drop_flags); -- cgit v1.2.3 From 2a100047481a5c7430c72883b586eb6f2df34812 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Fri, 15 Nov 2013 03:18:08 +0200 Subject: xhci: remove conversion from generic to pci device in xhci_mem.c This patch removes the to_pci_dev() conversion performed to generic struct device since it is not actually useful (the pointer to the generic device can be used directly rather through a conversion to pci_dev) and it is pci bus specific. This isn't stable material because this code will produce harmless behavior on non-PCI xHCI hosts. The pci_device pointer is never dereferenced, only used to re-calculate the underlying device pointer. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-mem.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 1445e08819cf..99e7251c2b65 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -433,10 +433,10 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, struct xhci_stream_ctx *stream_ctx, dma_addr_t dma) { - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct device *dev = xhci_to_hcd(xhci)->self.controller; if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE) - dma_free_coherent(&pdev->dev, + dma_free_coherent(dev, sizeof(struct xhci_stream_ctx)*num_stream_ctxs, stream_ctx, dma); else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE) @@ -461,10 +461,10 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, dma_addr_t *dma, gfp_t mem_flags) { - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct device *dev = xhci_to_hcd(xhci)->self.controller; if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE) - return dma_alloc_coherent(&pdev->dev, + return dma_alloc_coherent(dev, sizeof(struct xhci_stream_ctx)*num_stream_ctxs, dma, mem_flags); else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE) @@ -1616,7 +1616,7 @@ static void scratchpad_free(struct xhci_hcd *xhci) { int num_sp; int i; - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct device *dev = xhci_to_hcd(xhci)->self.controller; if (!xhci->scratchpad) return; @@ -1624,13 +1624,13 @@ static void scratchpad_free(struct xhci_hcd *xhci) num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); for (i = 0; i < num_sp; i++) { - dma_free_coherent(&pdev->dev, xhci->page_size, + dma_free_coherent(dev, xhci->page_size, xhci->scratchpad->sp_buffers[i], xhci->scratchpad->sp_dma_buffers[i]); } kfree(xhci->scratchpad->sp_dma_buffers); kfree(xhci->scratchpad->sp_buffers); - dma_free_coherent(&pdev->dev, num_sp * sizeof(u64), + dma_free_coherent(dev, num_sp * sizeof(u64), xhci->scratchpad->sp_array, xhci->scratchpad->sp_dma); kfree(xhci->scratchpad); @@ -1692,7 +1692,7 @@ void xhci_free_command(struct xhci_hcd *xhci, void xhci_mem_cleanup(struct xhci_hcd *xhci) { - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct device *dev = xhci_to_hcd(xhci)->self.controller; struct xhci_cd *cur_cd, *next_cd; int size; int i, j, num_ports; @@ -1700,7 +1700,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) /* Free the Event Ring Segment Table and the actual Event Ring */ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); if (xhci->erst.entries) - dma_free_coherent(&pdev->dev, size, + dma_free_coherent(dev, size, xhci->erst.entries, xhci->erst.erst_dma_addr); xhci->erst.entries = NULL; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed ERST"); @@ -1748,7 +1748,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) "Freed medium stream array pool"); if (xhci->dcbaa) - dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa), + dma_free_coherent(dev, sizeof(*xhci->dcbaa), xhci->dcbaa, xhci->dcbaa->dma); xhci->dcbaa = NULL; -- cgit v1.2.3 From b0ba9720846c980d053b1ffcd766fddfbef95d4c Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Fri, 15 Nov 2013 05:34:06 +0200 Subject: xhci: replace xhci_readl() with readl() Function xhci_readl() is used to read 32bit xHC registers residing in MMIO address space. It takes as first argument a pointer to the xhci_hcd although it does not use it. xhci_readl() internally simply calls readl(). This creates an illusion that xhci_readl() is an xhci specific function that has to be called in a context where a pointer to xhci_hcd is available. Remove the unnecessary xhci_readl() wrapper function and replace its calls to with calls to readl() to make the code more straightforward. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-dbg.c | 36 +++++++++---------- drivers/usb/host/xhci-hub.c | 71 ++++++++++++++++++------------------ drivers/usb/host/xhci-mem.c | 20 +++++------ drivers/usb/host/xhci-ring.c | 12 +++---- drivers/usb/host/xhci.c | 86 ++++++++++++++++++++++---------------------- drivers/usb/host/xhci.h | 5 --- 6 files changed, 112 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 73503a81ee81..eb009a457fb5 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -32,7 +32,7 @@ void xhci_dbg_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, "// xHCI capability registers at %p:\n", xhci->cap_regs); - temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); + temp = readl(&xhci->cap_regs->hc_capbase); xhci_dbg(xhci, "// @%p = 0x%x (CAPLENGTH AND HCIVERSION)\n", &xhci->cap_regs->hc_capbase, temp); xhci_dbg(xhci, "// CAPLENGTH: 0x%x\n", @@ -44,13 +44,13 @@ void xhci_dbg_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, "// xHCI operational registers at %p:\n", xhci->op_regs); - temp = xhci_readl(xhci, &xhci->cap_regs->run_regs_off); + temp = readl(&xhci->cap_regs->run_regs_off); xhci_dbg(xhci, "// @%p = 0x%x RTSOFF\n", &xhci->cap_regs->run_regs_off, (unsigned int) temp & RTSOFF_MASK); xhci_dbg(xhci, "// xHCI runtime registers at %p:\n", xhci->run_regs); - temp = xhci_readl(xhci, &xhci->cap_regs->db_off); + temp = readl(&xhci->cap_regs->db_off); xhci_dbg(xhci, "// @%p = 0x%x DBOFF\n", &xhci->cap_regs->db_off, temp); xhci_dbg(xhci, "// Doorbell array at %p:\n", xhci->dba); } @@ -61,7 +61,7 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, "xHCI capability registers at %p:\n", xhci->cap_regs); - temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); + temp = readl(&xhci->cap_regs->hc_capbase); xhci_dbg(xhci, "CAPLENGTH AND HCIVERSION 0x%x:\n", (unsigned int) temp); xhci_dbg(xhci, "CAPLENGTH: 0x%x\n", @@ -69,7 +69,7 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, "HCIVERSION: 0x%x\n", (unsigned int) HC_VERSION(temp)); - temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params1); + temp = readl(&xhci->cap_regs->hcs_params1); xhci_dbg(xhci, "HCSPARAMS 1: 0x%x\n", (unsigned int) temp); xhci_dbg(xhci, " Max device slots: %u\n", @@ -79,7 +79,7 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, " Max ports: %u\n", (unsigned int) HCS_MAX_PORTS(temp)); - temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params2); + temp = readl(&xhci->cap_regs->hcs_params2); xhci_dbg(xhci, "HCSPARAMS 2: 0x%x\n", (unsigned int) temp); xhci_dbg(xhci, " Isoc scheduling threshold: %u\n", @@ -87,7 +87,7 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, " Maximum allowed segments in event ring: %u\n", (unsigned int) HCS_ERST_MAX(temp)); - temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); + temp = readl(&xhci->cap_regs->hcs_params3); xhci_dbg(xhci, "HCSPARAMS 3 0x%x:\n", (unsigned int) temp); xhci_dbg(xhci, " Worst case U1 device exit latency: %u\n", @@ -95,14 +95,14 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) xhci_dbg(xhci, " Worst case U2 device exit latency: %u\n", (unsigned int) HCS_U2_LATENCY(temp)); - temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); + temp = readl(&xhci->cap_regs->hcc_params); xhci_dbg(xhci, "HCC PARAMS 0x%x:\n", (unsigned int) temp); xhci_dbg(xhci, " HC generates %s bit addresses\n", HCC_64BIT_ADDR(temp) ? "64" : "32"); /* FIXME */ xhci_dbg(xhci, " FIXME: more HCCPARAMS debugging\n"); - temp = xhci_readl(xhci, &xhci->cap_regs->run_regs_off); + temp = readl(&xhci->cap_regs->run_regs_off); xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK); } @@ -110,7 +110,7 @@ static void xhci_print_command_reg(struct xhci_hcd *xhci) { u32 temp; - temp = xhci_readl(xhci, &xhci->op_regs->command); + temp = readl(&xhci->op_regs->command); xhci_dbg(xhci, "USBCMD 0x%x:\n", temp); xhci_dbg(xhci, " HC is %s\n", (temp & CMD_RUN) ? "running" : "being stopped"); @@ -128,7 +128,7 @@ static void xhci_print_status(struct xhci_hcd *xhci) { u32 temp; - temp = xhci_readl(xhci, &xhci->op_regs->status); + temp = readl(&xhci->op_regs->status); xhci_dbg(xhci, "USBSTS 0x%x:\n", temp); xhci_dbg(xhci, " Event ring is %sempty\n", (temp & STS_EINT) ? "not " : ""); @@ -163,7 +163,7 @@ static void xhci_print_ports(struct xhci_hcd *xhci) for (j = 0; j < NUM_PORT_REGS; ++j) { xhci_dbg(xhci, "%p port %s reg = 0x%x\n", addr, names[j], - (unsigned int) xhci_readl(xhci, addr)); + (unsigned int) readl(addr)); addr++; } } @@ -177,7 +177,7 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num) u64 temp_64; addr = &ir_set->irq_pending; - temp = xhci_readl(xhci, addr); + temp = readl(addr); if (temp == XHCI_INIT_VALUE) return; @@ -187,17 +187,17 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num) (unsigned int)temp); addr = &ir_set->irq_control; - temp = xhci_readl(xhci, addr); + temp = readl(addr); xhci_dbg(xhci, " %p: ir_set.control = 0x%x\n", addr, (unsigned int)temp); addr = &ir_set->erst_size; - temp = xhci_readl(xhci, addr); + temp = readl(addr); xhci_dbg(xhci, " %p: ir_set.erst_size = 0x%x\n", addr, (unsigned int)temp); addr = &ir_set->rsvd; - temp = xhci_readl(xhci, addr); + temp = readl(addr); if (temp != XHCI_INIT_VALUE) xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n", addr, (unsigned int)temp); @@ -219,12 +219,12 @@ void xhci_print_run_regs(struct xhci_hcd *xhci) int i; xhci_dbg(xhci, "xHCI runtime registers at %p:\n", xhci->run_regs); - temp = xhci_readl(xhci, &xhci->run_regs->microframe_index); + temp = readl(&xhci->run_regs->microframe_index); xhci_dbg(xhci, " %p: Microframe index = 0x%x\n", &xhci->run_regs->microframe_index, (unsigned int) temp); for (i = 0; i < 7; ++i) { - temp = xhci_readl(xhci, &xhci->run_regs->rsvd[i]); + temp = readl(&xhci->run_regs->rsvd[i]); if (temp != XHCI_INIT_VALUE) xhci_dbg(xhci, " WARN: %p: Rsvd[%i] = 0x%x\n", &xhci->run_regs->rsvd[i], diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 805f2348eeba..70ed7c94e917 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -94,7 +94,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, */ memset(port_removable, 0, sizeof(port_removable)); for (i = 0; i < ports; i++) { - portsc = xhci_readl(xhci, xhci->usb2_ports[i]); + portsc = readl(xhci->usb2_ports[i]); /* If a device is removable, PORTSC reports a 0, same as in the * hub descriptor DeviceRemovable bits. */ @@ -148,7 +148,7 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, port_removable = 0; /* bit 0 is reserved, bit 1 is for port 1, etc. */ for (i = 0; i < ports; i++) { - portsc = xhci_readl(xhci, xhci->usb3_ports[i]); + portsc = readl(xhci->usb3_ports[i]); if (portsc & PORT_DEV_REMOVE) port_removable |= 1 << (i + 1); } @@ -343,7 +343,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, /* Write 1 to disable the port */ xhci_writel(xhci, port_status | PORT_PE, addr); - port_status = xhci_readl(xhci, addr); + port_status = readl(addr); xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n", wIndex, port_status); } @@ -389,7 +389,7 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, } /* Change bits are all write 1 to clear */ xhci_writel(xhci, port_status | status, addr); - port_status = xhci_readl(xhci, addr); + port_status = readl(addr); xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n", port_change_bit, wIndex, port_status); } @@ -415,7 +415,7 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, { u32 temp; - temp = xhci_readl(xhci, port_array[port_id]); + temp = readl(port_array[port_id]); temp = xhci_port_state_to_neutral(temp); temp &= ~PORT_PLS_MASK; temp |= PORT_LINK_STROBE | link_state; @@ -427,7 +427,7 @@ static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, { u32 temp; - temp = xhci_readl(xhci, port_array[port_id]); + temp = readl(port_array[port_id]); temp = xhci_port_state_to_neutral(temp); if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) @@ -454,7 +454,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, { u32 temp; - temp = xhci_readl(xhci, port_array[port_id]); + temp = readl(port_array[port_id]); if (temp & port_bit) { temp = xhci_port_state_to_neutral(temp); temp |= port_bit; @@ -623,8 +623,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, } xhci_ring_device(xhci, slot_id); } else { - int port_status = xhci_readl(xhci, - port_array[wIndex]); + int port_status = readl(port_array[wIndex]); xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", XHCI_MAX_REXIT_TIMEOUT, port_status); @@ -733,12 +732,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Set the U1 and U2 exit latencies. */ memcpy(buf, &usb_bos_descriptor, USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE); - temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); + temp = readl(&xhci->cap_regs->hcs_params3); buf[12] = HCS_U1_LATENCY(temp); put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); /* Indicate whether the host has LTM support. */ - temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); + temp = readl(&xhci->cap_regs->hcc_params); if (HCC_LTC(temp)) buf[8] |= USB_LTM_SUPPORT; @@ -748,7 +747,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if (!wIndex || wIndex > max_ports) goto error; wIndex--; - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); if (temp == 0xffffffff) { retval = -ENODEV; break; @@ -775,7 +774,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if (!wIndex || wIndex > max_ports) goto error; wIndex--; - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); if (temp == 0xffffffff) { retval = -ENODEV; break; @@ -784,7 +783,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* FIXME: What new port features do we need to support? */ switch (wValue) { case USB_PORT_FEAT_SUSPEND: - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); if ((temp & PORT_PLS_MASK) != XDEV_U0) { /* Resume the port to U0 first */ xhci_set_link_state(xhci, port_array, wIndex, @@ -797,7 +796,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, * a port unless the port reports that it is in the * enabled (PED = ‘1’,PLS < ‘3’) state. */ - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) || (temp & PORT_PLS_MASK) >= XDEV_U3) { xhci_warn(xhci, "USB core suspending device " @@ -822,11 +821,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, msleep(10); /* wait device to enter */ spin_lock_irqsave(&xhci->lock, flags); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); bus_state->suspended_ports |= 1 << wIndex; break; case USB_PORT_FEAT_LINK_STATE: - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); /* Disable port */ if (link_state == USB_SS_PORT_LS_SS_DISABLED) { @@ -841,7 +840,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, PORT_CEC; xhci_writel(xhci, temp | PORT_PE, port_array[wIndex]); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); break; } @@ -850,7 +849,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_dbg(xhci, "Enable port %d\n", wIndex); xhci_set_link_state(xhci, port_array, wIndex, link_state); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); break; } @@ -884,7 +883,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, msleep(20); /* wait device to enter */ spin_lock_irqsave(&xhci->lock, flags); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); if (link_state == USB_SS_PORT_LS_U3) bus_state->suspended_ports |= 1 << wIndex; break; @@ -898,7 +897,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_writel(xhci, temp | PORT_POWER, port_array[wIndex]); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); spin_unlock_irqrestore(&xhci->lock, flags); @@ -913,13 +912,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = (temp | PORT_RESET); xhci_writel(xhci, temp, port_array[wIndex]); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); break; case USB_PORT_FEAT_REMOTE_WAKE_MASK: xhci_set_remote_wake_mask(xhci, port_array, wIndex, wake_mask); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); xhci_dbg(xhci, "set port remote wake mask, " "actual port %d status = 0x%x\n", wIndex, temp); @@ -928,12 +927,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp |= PORT_WR; xhci_writel(xhci, temp, port_array[wIndex]); - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); break; case USB_PORT_FEAT_U1_TIMEOUT: if (hcd->speed != HCD_USB3) goto error; - temp = xhci_readl(xhci, port_array[wIndex] + PORTPMSC); + temp = readl(port_array[wIndex] + PORTPMSC); temp &= ~PORT_U1_TIMEOUT_MASK; temp |= PORT_U1_TIMEOUT(timeout); xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC); @@ -941,7 +940,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_U2_TIMEOUT: if (hcd->speed != HCD_USB3) goto error; - temp = xhci_readl(xhci, port_array[wIndex] + PORTPMSC); + temp = readl(port_array[wIndex] + PORTPMSC); temp &= ~PORT_U2_TIMEOUT_MASK; temp |= PORT_U2_TIMEOUT(timeout); xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC); @@ -950,13 +949,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, goto error; } /* unblock any posted writes */ - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); break; case ClearPortFeature: if (!wIndex || wIndex > max_ports) goto error; wIndex--; - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); if (temp == 0xffffffff) { retval = -ENODEV; break; @@ -965,7 +964,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_port_state_to_neutral(temp); switch (wValue) { case USB_PORT_FEAT_SUSPEND: - temp = xhci_readl(xhci, port_array[wIndex]); + temp = readl(port_array[wIndex]); xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); xhci_dbg(xhci, "PORTSC %04x\n", temp); if (temp & PORT_RESET) @@ -1070,7 +1069,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) spin_lock_irqsave(&xhci->lock, flags); /* For each port, did anything change? If so, set that bit in buf. */ for (i = 0; i < max_ports; i++) { - temp = xhci_readl(xhci, port_array[i]); + temp = readl(port_array[i]); if (temp == 0xffffffff) { retval = -ENODEV; break; @@ -1124,7 +1123,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) u32 t1, t2; int slot_id; - t1 = xhci_readl(xhci, port_array[port_index]); + t1 = readl(port_array[port_index]); t2 = xhci_port_state_to_neutral(t1); if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { @@ -1187,7 +1186,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) } /* delay the irqs */ - temp = xhci_readl(xhci, &xhci->op_regs->command); + temp = readl(&xhci->op_regs->command); temp &= ~CMD_EIE; xhci_writel(xhci, temp, &xhci->op_regs->command); @@ -1198,7 +1197,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) u32 temp; int slot_id; - temp = xhci_readl(xhci, port_array[port_index]); + temp = readl(port_array[port_index]); if (DEV_SUPERSPEED(temp)) temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); else @@ -1238,14 +1237,14 @@ int xhci_bus_resume(struct usb_hcd *hcd) xhci_writel(xhci, temp, port_array[port_index]); } - (void) xhci_readl(xhci, &xhci->op_regs->command); + (void) readl(&xhci->op_regs->command); bus_state->next_statechange = jiffies + msecs_to_jiffies(5); /* re-enable irqs */ - temp = xhci_readl(xhci, &xhci->op_regs->command); + temp = readl(&xhci->op_regs->command); temp |= CMD_EIE; xhci_writel(xhci, temp, &xhci->op_regs->command); - temp = xhci_readl(xhci, &xhci->op_regs->command); + temp = readl(&xhci->op_regs->command); spin_unlock_irqrestore(&xhci->lock, flags); return 0; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 99e7251c2b65..3682a3b7e057 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1986,7 +1986,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, } /* Port offset and count in the third dword, see section 7.2 */ - temp = xhci_readl(xhci, addr + 2); + temp = readl(addr + 2); port_offset = XHCI_EXT_PORT_OFF(temp); port_count = XHCI_EXT_PORT_COUNT(temp); xhci_dbg_trace(xhci, trace_xhci_dbg_init, @@ -2069,7 +2069,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) int cap_count = 0; addr = &xhci->cap_regs->hcc_params; - offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); + offset = XHCI_HCC_EXT_CAPS(readl(addr)); if (offset == 0) { xhci_err(xhci, "No Extended Capability registers, " "unable to set up roothub.\n"); @@ -2106,7 +2106,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) /* count extended protocol capability entries for later caching */ do { u32 cap_id; - cap_id = xhci_readl(xhci, tmp_addr); + cap_id = readl(tmp_addr); if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) cap_count++; tmp_offset = XHCI_EXT_CAPS_NEXT(cap_id); @@ -2120,7 +2120,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) while (1) { u32 cap_id; - cap_id = xhci_readl(xhci, addr); + cap_id = readl(addr); if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) xhci_add_in_port(xhci, num_ports, addr, (u8) XHCI_EXT_PORT_MAJOR(cap_id), @@ -2224,7 +2224,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) INIT_LIST_HEAD(&xhci->cancel_cmd_list); - page_size = xhci_readl(xhci, &xhci->op_regs->page_size); + page_size = readl(&xhci->op_regs->page_size); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Supported page size register = 0x%x", page_size); for (i = 0; i < 16; i++) { @@ -2247,10 +2247,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * Program the Number of Device Slots Enabled field in the CONFIG * register with the max value of slots the HC can handle. */ - val = HCS_MAX_SLOTS(xhci_readl(xhci, &xhci->cap_regs->hcs_params1)); + val = HCS_MAX_SLOTS(readl(&xhci->cap_regs->hcs_params1)); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// xHC can handle at most %d device slots.", val); - val2 = xhci_readl(xhci, &xhci->op_regs->config_reg); + val2 = readl(&xhci->op_regs->config_reg); val |= (val2 & ~HCS_SLOTS_MASK); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Setting Max device slots reg = 0x%x.", val); @@ -2331,7 +2331,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) */ xhci->cmd_ring_reserved_trbs++; - val = xhci_readl(xhci, &xhci->cap_regs->db_off); + val = readl(&xhci->cap_regs->db_off); val &= DBOFF_MASK; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Doorbell array is located at offset 0x%x" @@ -2382,7 +2382,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) } /* set ERST count with the number of entries in the segment table */ - val = xhci_readl(xhci, &xhci->ir_set->erst_size); + val = readl(&xhci->ir_set->erst_size); val &= ERST_SIZE_MASK; val |= ERST_NUM_SEGS; xhci_dbg_trace(xhci, trace_xhci_dbg_init, @@ -2431,7 +2431,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * is necessary for allowing USB 3.0 devices to do remote wakeup from * U3 (device suspend). */ - temp = xhci_readl(xhci, &xhci->op_regs->dev_notification); + temp = readl(&xhci->op_regs->dev_notification); temp &= ~DEV_NOTE_MASK; temp |= DEV_NOTE_FWAKE; xhci_writel(xhci, temp, &xhci->op_regs->dev_notification); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 22da09388a74..9f2349b2aea5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -297,7 +297,7 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) xhci_dbg(xhci, "// Ding dong!\n"); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ - xhci_readl(xhci, &xhci->dba->doorbell[0]); + readl(&xhci->dba->doorbell[0]); } static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) @@ -1739,7 +1739,7 @@ static void handle_port_status(struct xhci_hcd *xhci, faked_port_index = find_faked_portnum_from_hw_portnum(hcd, xhci, port_id); - temp = xhci_readl(xhci, port_array[faked_port_index]); + temp = readl(port_array[faked_port_index]); if (hcd->state == HC_STATE_SUSPENDED) { xhci_dbg(xhci, "resume root hub\n"); usb_hcd_resume_root_hub(hcd); @@ -1748,7 +1748,7 @@ static void handle_port_status(struct xhci_hcd *xhci, if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { xhci_dbg(xhci, "port resume event for port %d\n", port_id); - temp1 = xhci_readl(xhci, &xhci->op_regs->command); + temp1 = readl(&xhci->op_regs->command); if (!(temp1 & CMD_RUN)) { xhci_warn(xhci, "xHC is not running.\n"); goto cleanup; @@ -2831,7 +2831,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) spin_lock(&xhci->lock); /* Check if the xHC generated the interrupt, or the irq is shared */ - status = xhci_readl(xhci, &xhci->op_regs->status); + status = readl(&xhci->op_regs->status); if (status == 0xffffffff) goto hw_died; @@ -2860,7 +2860,7 @@ hw_died: if (hcd->irq) { u32 irq_pending; /* Acknowledge the PCI interrupt */ - irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); + irq_pending = readl(&xhci->ir_set->irq_pending); irq_pending |= IMAN_IP; xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); } @@ -3931,7 +3931,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, if (ret) return ret; - start_frame = xhci_readl(xhci, &xhci->run_regs->microframe_index); + start_frame = readl(&xhci->run_regs->microframe_index); start_frame &= 0x3fff; urb->start_frame = start_frame; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 900ba36ee2b8..5e6a8651c2a8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -60,7 +60,7 @@ int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 result; do { - result = xhci_readl(xhci, ptr); + result = readl(ptr); if (result == ~(u32)0) /* card removed */ return -ENODEV; result &= mask; @@ -82,11 +82,11 @@ void xhci_quiesce(struct xhci_hcd *xhci) u32 mask; mask = ~(XHCI_IRQS); - halted = xhci_readl(xhci, &xhci->op_regs->status) & STS_HALT; + halted = readl(&xhci->op_regs->status) & STS_HALT; if (!halted) mask &= ~CMD_RUN; - cmd = xhci_readl(xhci, &xhci->op_regs->command); + cmd = readl(&xhci->op_regs->command); cmd &= mask; xhci_writel(xhci, cmd, &xhci->op_regs->command); } @@ -124,7 +124,7 @@ static int xhci_start(struct xhci_hcd *xhci) u32 temp; int ret; - temp = xhci_readl(xhci, &xhci->op_regs->command); + temp = readl(&xhci->op_regs->command); temp |= (CMD_RUN); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Turn on HC, cmd = 0x%x.", temp); @@ -158,14 +158,14 @@ int xhci_reset(struct xhci_hcd *xhci) u32 state; int ret, i; - state = xhci_readl(xhci, &xhci->op_regs->status); + state = readl(&xhci->op_regs->status); if ((state & STS_HALT) == 0) { xhci_warn(xhci, "Host controller not halted, aborting reset.\n"); return 0; } xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Reset the HC"); - command = xhci_readl(xhci, &xhci->op_regs->command); + command = readl(&xhci->op_regs->command); command |= CMD_RESET; xhci_writel(xhci, command, &xhci->op_regs->command); @@ -422,7 +422,7 @@ static void compliance_mode_recovery(unsigned long arg) xhci = (struct xhci_hcd *)arg; for (i = 0; i < xhci->num_usb3_ports; i++) { - temp = xhci_readl(xhci, xhci->usb3_ports[i]); + temp = readl(xhci->usb3_ports[i]); if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { /* * Compliance Mode Detected. Letting USB Core @@ -611,19 +611,19 @@ int xhci_run(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Set the interrupt modulation register"); - temp = xhci_readl(xhci, &xhci->ir_set->irq_control); + temp = readl(&xhci->ir_set->irq_control); temp &= ~ER_IRQ_INTERVAL_MASK; temp |= (u32) 160; xhci_writel(xhci, temp, &xhci->ir_set->irq_control); /* Set the HCD state before we enable the irqs */ - temp = xhci_readl(xhci, &xhci->op_regs->command); + temp = readl(&xhci->op_regs->command); temp |= (CMD_EIE); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Enable interrupts, cmd = 0x%x.", temp); xhci_writel(xhci, temp, &xhci->op_regs->command); - temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); + temp = readl(&xhci->ir_set->irq_pending); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Enabling event ring interrupter %p by writing 0x%x to irq_pending", xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp)); @@ -698,9 +698,9 @@ void xhci_stop(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Disabling event ring interrupts"); - temp = xhci_readl(xhci, &xhci->op_regs->status); + temp = readl(&xhci->op_regs->status); xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status); - temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); + temp = readl(&xhci->ir_set->irq_pending); xhci_writel(xhci, ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); xhci_print_ir_set(xhci, 0); @@ -709,7 +709,7 @@ void xhci_stop(struct usb_hcd *hcd) xhci_mem_cleanup(xhci); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_stop completed - status = %x", - xhci_readl(xhci, &xhci->op_regs->status)); + readl(&xhci->op_regs->status)); } /* @@ -739,7 +739,7 @@ void xhci_shutdown(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_shutdown completed - status = %x", - xhci_readl(xhci, &xhci->op_regs->status)); + readl(&xhci->op_regs->status)); /* Yet another workaround for spurious wakeups at shutdown with HSW */ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) @@ -749,15 +749,15 @@ void xhci_shutdown(struct usb_hcd *hcd) #ifdef CONFIG_PM static void xhci_save_registers(struct xhci_hcd *xhci) { - xhci->s3.command = xhci_readl(xhci, &xhci->op_regs->command); - xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification); + xhci->s3.command = readl(&xhci->op_regs->command); + xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification); xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); - xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg); - xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size); + xhci->s3.config_reg = readl(&xhci->op_regs->config_reg); + xhci->s3.erst_size = readl(&xhci->ir_set->erst_size); xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); - xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); - xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control); + xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending); + xhci->s3.irq_control = readl(&xhci->ir_set->irq_control); } static void xhci_restore_registers(struct xhci_hcd *xhci) @@ -866,7 +866,7 @@ int xhci_suspend(struct xhci_hcd *xhci) /* skipped assuming that port suspend has done */ /* step 2: clear Run/Stop bit */ - command = xhci_readl(xhci, &xhci->op_regs->command); + command = readl(&xhci->op_regs->command); command &= ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); @@ -885,7 +885,7 @@ int xhci_suspend(struct xhci_hcd *xhci) xhci_save_registers(xhci); /* step 4: set CSS flag */ - command = xhci_readl(xhci, &xhci->op_regs->command); + command = readl(&xhci->op_regs->command); command |= CMD_CSS; xhci_writel(xhci, command, &xhci->op_regs->command); if (xhci_handshake(xhci, &xhci->op_regs->status, @@ -951,7 +951,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_set_cmd_ring_deq(xhci); /* step 3: restore state and start state*/ /* step 3: set CRS flag */ - command = xhci_readl(xhci, &xhci->op_regs->command); + command = readl(&xhci->op_regs->command); command |= CMD_CRS; xhci_writel(xhci, command, &xhci->op_regs->command); if (xhci_handshake(xhci, &xhci->op_regs->status, @@ -960,7 +960,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } - temp = xhci_readl(xhci, &xhci->op_regs->status); + temp = readl(&xhci->op_regs->status); } /* If restore operation fails, re-initialize the HC during resume */ @@ -984,9 +984,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_cleanup_msix(xhci); xhci_dbg(xhci, "// Disabling event ring interrupts\n"); - temp = xhci_readl(xhci, &xhci->op_regs->status); + temp = readl(&xhci->op_regs->status); xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status); - temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); + temp = readl(&xhci->ir_set->irq_pending); xhci_writel(xhci, ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); xhci_print_ir_set(xhci, 0); @@ -994,7 +994,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "cleaning up memory\n"); xhci_mem_cleanup(xhci); xhci_dbg(xhci, "xhci_stop completed - status = %x\n", - xhci_readl(xhci, &xhci->op_regs->status)); + readl(&xhci->op_regs->status)); /* USB core calls the PCI reinit and start functions twice: * first with the primary HCD, and then with the secondary HCD. @@ -1023,7 +1023,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) } /* step 4: set Run/Stop bit */ - command = xhci_readl(xhci, &xhci->op_regs->command); + command = readl(&xhci->op_regs->command); command |= CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, @@ -1464,7 +1464,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ret = usb_hcd_check_unlink_urb(hcd, urb, status); if (ret || !urb->hcpriv) goto done; - temp = xhci_readl(xhci, &xhci->op_regs->status); + temp = readl(&xhci->op_regs->status); if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "HW died, freeing TD."); @@ -3585,7 +3585,7 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) spin_lock_irqsave(&xhci->lock, flags); /* Don't disable the slot if the host controller is dead. */ - state = xhci_readl(xhci, &xhci->op_regs->status); + state = readl(&xhci->op_regs->status); if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || (xhci->xhc_state & XHCI_STATE_HALTED)) { xhci_free_virt_device(xhci, udev->slot_id); @@ -4042,7 +4042,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, port_array = xhci->usb2_ports; port_num = udev->portnum - 1; pm_addr = port_array[port_num] + PORTPMSC; - pm_val = xhci_readl(xhci, pm_addr); + pm_val = readl(pm_addr); hlpm_addr = port_array[port_num] + PORTHLPMC; field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); @@ -4084,7 +4084,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, hlpm_val = xhci_calculate_usb2_hw_lpm_params(udev); xhci_writel(xhci, hlpm_val, hlpm_addr); /* flush write */ - xhci_readl(xhci, hlpm_addr); + readl(hlpm_addr); } else { hird = xhci_calculate_hird_besl(xhci, udev); } @@ -4092,16 +4092,16 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, pm_val &= ~PORT_HIRD_MASK; pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id); xhci_writel(xhci, pm_val, pm_addr); - pm_val = xhci_readl(xhci, pm_addr); + pm_val = readl(pm_addr); pm_val |= PORT_HLE; xhci_writel(xhci, pm_val, pm_addr); /* flush write */ - xhci_readl(xhci, pm_addr); + readl(pm_addr); } else { pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK | PORT_L1DS_MASK); xhci_writel(xhci, pm_val, pm_addr); /* flush write */ - xhci_readl(xhci, pm_addr); + readl(pm_addr); if (udev->usb2_hw_lpm_besl_capable) { spin_unlock_irqrestore(&xhci->lock, flags); mutex_lock(hcd->bandwidth_mutex); @@ -4704,7 +4704,7 @@ int xhci_get_frame(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); /* EHCI mods by the periodic size. Why? */ - return xhci_readl(xhci, &xhci->run_regs->microframe_index) >> 3; + return readl(&xhci->run_regs->microframe_index) >> 3; } int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) @@ -4748,16 +4748,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci->cap_regs = hcd->regs; xhci->op_regs = hcd->regs + - HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase)); + HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)); xhci->run_regs = hcd->regs + - (xhci_readl(xhci, &xhci->cap_regs->run_regs_off) & RTSOFF_MASK); + (readl(&xhci->cap_regs->run_regs_off) & RTSOFF_MASK); /* Cache read-only capability registers */ - xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1); - xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2); - xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); - xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); + xhci->hcs_params1 = readl(&xhci->cap_regs->hcs_params1); + xhci->hcs_params2 = readl(&xhci->cap_regs->hcs_params2); + xhci->hcs_params3 = readl(&xhci->cap_regs->hcs_params3); + xhci->hcc_params = readl(&xhci->cap_regs->hc_capbase); xhci->hci_version = HC_VERSION(xhci->hcc_params); - xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params); + xhci->hcc_params = readl(&xhci->cap_regs->hcc_params); xhci_print_registers(xhci); get_quirks(dev, xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a33e8b5bf7a2..c727f1edb37f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1597,11 +1597,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) /* TODO: copied from ehci.h - can be refactored? */ /* xHCI spec says all registers are little endian */ -static inline unsigned int xhci_readl(const struct xhci_hcd *xhci, - __le32 __iomem *regs) -{ - return readl(regs); -} static inline void xhci_writel(struct xhci_hcd *xhci, const unsigned int val, __le32 __iomem *regs) { -- cgit v1.2.3 From 204b7793f2a9935e9a08524d0b4bb51b990d518e Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Fri, 15 Nov 2013 05:34:07 +0200 Subject: xhci: replace xhci_writel() with writel() Function xhci_writel() is used to write a 32bit value in xHC registers residing in MMIO address space. It takes as first argument a pointer to the xhci_hcd although it does not use it. xhci_writel() internally simply calls writel(). This creates an illusion that xhci_writel() is an xhci specific function that has to be called in a context where a pointer to xhci_hcd is available. Remove xhci_writel() wrapper function and replace its calls with calls to writel() to make the code more straight-forward. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-hub.c | 35 ++++++++++++++---------------- drivers/usb/host/xhci-mem.c | 6 +++--- drivers/usb/host/xhci-ring.c | 8 +++---- drivers/usb/host/xhci.c | 51 +++++++++++++++++++++----------------------- drivers/usb/host/xhci.h | 8 ------- 5 files changed, 47 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 70ed7c94e917..9992fbfec85f 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -342,7 +342,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, } /* Write 1 to disable the port */ - xhci_writel(xhci, port_status | PORT_PE, addr); + writel(port_status | PORT_PE, addr); port_status = readl(addr); xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n", wIndex, port_status); @@ -388,7 +388,7 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, return; } /* Change bits are all write 1 to clear */ - xhci_writel(xhci, port_status | status, addr); + writel(port_status | status, addr); port_status = readl(addr); xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n", port_change_bit, wIndex, port_status); @@ -419,7 +419,7 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, temp = xhci_port_state_to_neutral(temp); temp &= ~PORT_PLS_MASK; temp |= PORT_LINK_STROBE | link_state; - xhci_writel(xhci, temp, port_array[port_id]); + writel(temp, port_array[port_id]); } static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, @@ -445,7 +445,7 @@ static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, else temp &= ~PORT_WKOC_E; - xhci_writel(xhci, temp, port_array[port_id]); + writel(temp, port_array[port_id]); } /* Test and clear port RWC bit */ @@ -458,7 +458,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, if (temp & port_bit) { temp = xhci_port_state_to_neutral(temp); temp |= port_bit; - xhci_writel(xhci, temp, port_array[port_id]); + writel(temp, port_array[port_id]); } } @@ -838,8 +838,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp |= PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | PORT_RC | PORT_PLC | PORT_CEC; - xhci_writel(xhci, temp | PORT_PE, - port_array[wIndex]); + writel(temp | PORT_PE, port_array[wIndex]); temp = readl(port_array[wIndex]); break; } @@ -894,8 +893,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, * However, khubd will ignore the roothub events until * the roothub is registered. */ - xhci_writel(xhci, temp | PORT_POWER, - port_array[wIndex]); + writel(temp | PORT_POWER, port_array[wIndex]); temp = readl(port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); @@ -910,7 +908,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); - xhci_writel(xhci, temp, port_array[wIndex]); + writel(temp, port_array[wIndex]); temp = readl(port_array[wIndex]); xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); @@ -925,7 +923,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_BH_PORT_RESET: temp |= PORT_WR; - xhci_writel(xhci, temp, port_array[wIndex]); + writel(temp, port_array[wIndex]); temp = readl(port_array[wIndex]); break; @@ -935,7 +933,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = readl(port_array[wIndex] + PORTPMSC); temp &= ~PORT_U1_TIMEOUT_MASK; temp |= PORT_U1_TIMEOUT(timeout); - xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC); + writel(temp, port_array[wIndex] + PORTPMSC); break; case USB_PORT_FEAT_U2_TIMEOUT: if (hcd->speed != HCD_USB3) @@ -943,7 +941,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = readl(port_array[wIndex] + PORTPMSC); temp &= ~PORT_U2_TIMEOUT_MASK; temp |= PORT_U2_TIMEOUT(timeout); - xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC); + writel(temp, port_array[wIndex] + PORTPMSC); break; default: goto error; @@ -1007,8 +1005,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, port_array[wIndex], temp); break; case USB_PORT_FEAT_POWER: - xhci_writel(xhci, temp & ~PORT_POWER, - port_array[wIndex]); + writel(temp & ~PORT_POWER, port_array[wIndex]); spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, @@ -1156,7 +1153,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) t1 = xhci_port_state_to_neutral(t1); if (t1 != t2) - xhci_writel(xhci, t2, port_array[port_index]); + writel(t2, port_array[port_index]); } hcd->state = HC_STATE_SUSPENDED; bus_state->next_statechange = jiffies + msecs_to_jiffies(10); @@ -1188,7 +1185,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) /* delay the irqs */ temp = readl(&xhci->op_regs->command); temp &= ~CMD_EIE; - xhci_writel(xhci, temp, &xhci->op_regs->command); + writel(temp, &xhci->op_regs->command); port_index = max_ports; while (port_index--) { @@ -1234,7 +1231,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) if (slot_id) xhci_ring_device(xhci, slot_id); } else - xhci_writel(xhci, temp, port_array[port_index]); + writel(temp, port_array[port_index]); } (void) readl(&xhci->op_regs->command); @@ -1243,7 +1240,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) /* re-enable irqs */ temp = readl(&xhci->op_regs->command); temp |= CMD_EIE; - xhci_writel(xhci, temp, &xhci->op_regs->command); + writel(temp, &xhci->op_regs->command); temp = readl(&xhci->op_regs->command); spin_unlock_irqrestore(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 3682a3b7e057..bce4391a0e7d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2254,7 +2254,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) val |= (val2 & ~HCS_SLOTS_MASK); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Setting Max device slots reg = 0x%x.", val); - xhci_writel(xhci, val, &xhci->op_regs->config_reg); + writel(val, &xhci->op_regs->config_reg); /* * Section 5.4.8 - doorbell array must be @@ -2388,7 +2388,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Write ERST size = %i to ir_set 0 (some bits preserved)", val); - xhci_writel(xhci, val, &xhci->ir_set->erst_size); + writel(val, &xhci->ir_set->erst_size); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Set ERST entries to point to event ring."); @@ -2434,7 +2434,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) temp = readl(&xhci->op_regs->dev_notification); temp &= ~DEV_NOTE_MASK; temp |= DEV_NOTE_FWAKE; - xhci_writel(xhci, temp, &xhci->op_regs->dev_notification); + writel(temp, &xhci->op_regs->dev_notification); return 0; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9f2349b2aea5..bc46cce46db8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -295,7 +295,7 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) return; xhci_dbg(xhci, "// Ding dong!\n"); - xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); + writel(DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ readl(&xhci->dba->doorbell[0]); } @@ -427,7 +427,7 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, if ((ep_state & EP_HALT_PENDING) || (ep_state & SET_DEQ_PENDING) || (ep_state & EP_HALTED)) return; - xhci_writel(xhci, DB_VALUE(ep_index, stream_id), db_addr); + writel(DB_VALUE(ep_index, stream_id), db_addr); /* The CPU has better things to do at this point than wait for a * write-posting flush. It'll get there soon enough. */ @@ -2853,7 +2853,7 @@ hw_died: * Write 1 to clear the interrupt status. */ status |= STS_EINT; - xhci_writel(xhci, status, &xhci->op_regs->status); + writel(status, &xhci->op_regs->status); /* FIXME when MSI-X is supported and there are multiple vectors */ /* Clear the MSI-X event interrupt status */ @@ -2862,7 +2862,7 @@ hw_died: /* Acknowledge the PCI interrupt */ irq_pending = readl(&xhci->ir_set->irq_pending); irq_pending |= IMAN_IP; - xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); + writel(irq_pending, &xhci->ir_set->irq_pending); } if (xhci->xhc_state & XHCI_STATE_DYING) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5e6a8651c2a8..7630b9ff56d4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -88,7 +88,7 @@ void xhci_quiesce(struct xhci_hcd *xhci) cmd = readl(&xhci->op_regs->command); cmd &= mask; - xhci_writel(xhci, cmd, &xhci->op_regs->command); + writel(cmd, &xhci->op_regs->command); } /* @@ -128,7 +128,7 @@ static int xhci_start(struct xhci_hcd *xhci) temp |= (CMD_RUN); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Turn on HC, cmd = 0x%x.", temp); - xhci_writel(xhci, temp, &xhci->op_regs->command); + writel(temp, &xhci->op_regs->command); /* * Wait for the HCHalted Status bit to be 0 to indicate the host is @@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Reset the HC"); command = readl(&xhci->op_regs->command); command |= CMD_RESET; - xhci_writel(xhci, command, &xhci->op_regs->command); + writel(command, &xhci->op_regs->command); ret = xhci_handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 10 * 1000 * 1000); @@ -614,21 +614,20 @@ int xhci_run(struct usb_hcd *hcd) temp = readl(&xhci->ir_set->irq_control); temp &= ~ER_IRQ_INTERVAL_MASK; temp |= (u32) 160; - xhci_writel(xhci, temp, &xhci->ir_set->irq_control); + writel(temp, &xhci->ir_set->irq_control); /* Set the HCD state before we enable the irqs */ temp = readl(&xhci->op_regs->command); temp |= (CMD_EIE); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Enable interrupts, cmd = 0x%x.", temp); - xhci_writel(xhci, temp, &xhci->op_regs->command); + writel(temp, &xhci->op_regs->command); temp = readl(&xhci->ir_set->irq_pending); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Enabling event ring interrupter %p by writing 0x%x to irq_pending", xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp)); - xhci_writel(xhci, ER_IRQ_ENABLE(temp), - &xhci->ir_set->irq_pending); + writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); xhci_print_ir_set(xhci, 0); if (xhci->quirks & XHCI_NEC_HOST) @@ -699,10 +698,9 @@ void xhci_stop(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Disabling event ring interrupts"); temp = readl(&xhci->op_regs->status); - xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status); + writel(temp & ~STS_EINT, &xhci->op_regs->status); temp = readl(&xhci->ir_set->irq_pending); - xhci_writel(xhci, ER_IRQ_DISABLE(temp), - &xhci->ir_set->irq_pending); + writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); xhci_print_ir_set(xhci, 0); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory"); @@ -762,15 +760,15 @@ static void xhci_save_registers(struct xhci_hcd *xhci) static void xhci_restore_registers(struct xhci_hcd *xhci) { - xhci_writel(xhci, xhci->s3.command, &xhci->op_regs->command); - xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification); + writel(xhci->s3.command, &xhci->op_regs->command); + writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification); xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); - xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg); - xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size); + writel(xhci->s3.config_reg, &xhci->op_regs->config_reg); + writel(xhci->s3.erst_size, &xhci->ir_set->erst_size); xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); - xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); - xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control); + writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending); + writel(xhci->s3.irq_control, &xhci->ir_set->irq_control); } static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) @@ -868,7 +866,7 @@ int xhci_suspend(struct xhci_hcd *xhci) /* step 2: clear Run/Stop bit */ command = readl(&xhci->op_regs->command); command &= ~CMD_RUN; - xhci_writel(xhci, command, &xhci->op_regs->command); + writel(command, &xhci->op_regs->command); /* Some chips from Fresco Logic need an extraordinary delay */ delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1; @@ -887,7 +885,7 @@ int xhci_suspend(struct xhci_hcd *xhci) /* step 4: set CSS flag */ command = readl(&xhci->op_regs->command); command |= CMD_CSS; - xhci_writel(xhci, command, &xhci->op_regs->command); + writel(command, &xhci->op_regs->command); if (xhci_handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { xhci_warn(xhci, "WARN: xHC save state timeout\n"); @@ -953,7 +951,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* step 3: set CRS flag */ command = readl(&xhci->op_regs->command); command |= CMD_CRS; - xhci_writel(xhci, command, &xhci->op_regs->command); + writel(command, &xhci->op_regs->command); if (xhci_handshake(xhci, &xhci->op_regs->status, STS_RESTORE, 0, 10 * 1000)) { xhci_warn(xhci, "WARN: xHC restore state timeout\n"); @@ -985,10 +983,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "// Disabling event ring interrupts\n"); temp = readl(&xhci->op_regs->status); - xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status); + writel(temp & ~STS_EINT, &xhci->op_regs->status); temp = readl(&xhci->ir_set->irq_pending); - xhci_writel(xhci, ER_IRQ_DISABLE(temp), - &xhci->ir_set->irq_pending); + writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); xhci_print_ir_set(xhci, 0); xhci_dbg(xhci, "cleaning up memory\n"); @@ -1025,7 +1022,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* step 4: set Run/Stop bit */ command = readl(&xhci->op_regs->command); command |= CMD_RUN; - xhci_writel(xhci, command, &xhci->op_regs->command); + writel(command, &xhci->op_regs->command); xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, 0, 250 * 1000); @@ -4082,7 +4079,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, spin_lock_irqsave(&xhci->lock, flags); hlpm_val = xhci_calculate_usb2_hw_lpm_params(udev); - xhci_writel(xhci, hlpm_val, hlpm_addr); + writel(hlpm_val, hlpm_addr); /* flush write */ readl(hlpm_addr); } else { @@ -4091,15 +4088,15 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, pm_val &= ~PORT_HIRD_MASK; pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id); - xhci_writel(xhci, pm_val, pm_addr); + writel(pm_val, pm_addr); pm_val = readl(pm_addr); pm_val |= PORT_HLE; - xhci_writel(xhci, pm_val, pm_addr); + writel(pm_val, pm_addr); /* flush write */ readl(pm_addr); } else { pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK | PORT_L1DS_MASK); - xhci_writel(xhci, pm_val, pm_addr); + writel(pm_val, pm_addr); /* flush write */ readl(pm_addr); if (udev->usb2_hw_lpm_besl_capable) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c727f1edb37f..402d8743d245 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1595,14 +1595,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) #define xhci_warn_ratelimited(xhci, fmt, args...) \ dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args) -/* TODO: copied from ehci.h - can be refactored? */ -/* xHCI spec says all registers are little endian */ -static inline void xhci_writel(struct xhci_hcd *xhci, - const unsigned int val, __le32 __iomem *regs) -{ - writel(val, regs); -} - /* * Registers should always be accessed with double word or quad word accesses. * -- cgit v1.2.3 From e8b373326d8efcaf9ec1da8b618556c89bd5ffc4 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Fri, 15 Nov 2013 05:34:08 +0200 Subject: xhci: replace xhci_read_64() with readq() Function xhci_read_64() is used to read 64bit xHC registers residing in MMIO. On 32bit systems, xHC registers need to be read with 32bit accesses by reading first the lower 32bits and then the higher 32bits. Replace all calls to xhci_read_64() with calls to readq() and include asm-generic/io-64-nonatomic-lo-hi.h header file, so that if the system is not 64bit, readq() will read registers in 32bit chunks with low-high order. This is done to reduce code duplication since 64bit low-high read logic is already implemented and to take advantage of inherent "atomic" 64bit read operations on 64bit systems. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-dbg.c | 6 +++--- drivers/usb/host/xhci-mem.c | 6 +++--- drivers/usb/host/xhci-ring.c | 6 +++--- drivers/usb/host/xhci.c | 12 ++++++------ drivers/usb/host/xhci.h | 10 ++-------- 5 files changed, 17 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index eb009a457fb5..b016d38199f2 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num) addr, (unsigned int)temp); addr = &ir_set->erst_base; - temp_64 = xhci_read_64(xhci, addr); + temp_64 = readq(addr); xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n", addr, temp_64); addr = &ir_set->erst_dequeue; - temp_64 = xhci_read_64(xhci, addr); + temp_64 = readq(addr); xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n", addr, temp_64); } @@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) { u64 val; - val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + val = readq(&xhci->op_regs->cmd_ring); xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n", lower_32_bits(val)); xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n", diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index bce4391a0e7d..4b87026f8a5a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1958,7 +1958,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) xhci_warn(xhci, "WARN something wrong with SW event ring " "dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ - temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp = readq(&xhci->ir_set->erst_dequeue); temp &= ERST_PTR_MASK; /* Don't clear the EHB bit (which is RW1C) because * there might be more events to service. @@ -2312,7 +2312,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) (unsigned long long)xhci->cmd_ring->first_seg->dma); /* Set the address in the Command Ring Control register */ - val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + val_64 = readq(&xhci->op_regs->cmd_ring); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | xhci->cmd_ring->cycle_state; @@ -2396,7 +2396,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Set ERST base address for ir_set 0 = 0x%llx", (unsigned long long)xhci->erst.erst_dma_addr); - val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base); + val_64 = readq(&xhci->ir_set->erst_base); val_64 &= ERST_PTR_MASK; val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bc46cce46db8..339733b8524a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -313,7 +313,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) return 0; } - temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + temp_64 = readq(&xhci->op_regs->cmd_ring); if (!(temp_64 & CMD_RING_RUNNING)) { xhci_dbg(xhci, "Command ring had been stopped\n"); return 0; @@ -2871,7 +2871,7 @@ hw_died: /* Clear the event handler busy flag (RW1C); * the event ring should be empty. */ - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 = readq(&xhci->ir_set->erst_dequeue); xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); @@ -2885,7 +2885,7 @@ hw_died: */ while (xhci_handle_event(xhci) > 0) {} - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 = readq(&xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7630b9ff56d4..858e992729c9 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -604,7 +604,7 @@ int xhci_run(struct usb_hcd *hcd) xhci_dbg(xhci, "Event ring:\n"); xhci_debug_ring(xhci, xhci->event_ring); xhci_dbg_ring_ptrs(xhci, xhci->event_ring); - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 = readq(&xhci->ir_set->erst_dequeue); temp_64 &= ~ERST_PTR_MASK; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "ERST deq = 64'h%0lx", (long unsigned int) temp_64); @@ -749,11 +749,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci) { xhci->s3.command = readl(&xhci->op_regs->command); xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification); - xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); + xhci->s3.dcbaa_ptr = readq(&xhci->op_regs->dcbaa_ptr); xhci->s3.config_reg = readl(&xhci->op_regs->config_reg); xhci->s3.erst_size = readl(&xhci->ir_set->erst_size); - xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); - xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + xhci->s3.erst_base = readq(&xhci->ir_set->erst_base); + xhci->s3.erst_dequeue = readq(&xhci->ir_set->erst_dequeue); xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending); xhci->s3.irq_control = readl(&xhci->ir_set->irq_control); } @@ -776,7 +776,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) u64 val_64; /* step 2: initialize command ring buffer */ - val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + val_64 = readq(&xhci->op_regs->cmd_ring); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, xhci->cmd_ring->dequeue) & @@ -3832,7 +3832,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (ret) { return ret; } - temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); + temp_64 = readq(&xhci->op_regs->dcbaa_ptr); xhci_dbg_trace(xhci, trace_xhci_dbg_address, "Op regs DCBAA ptr = %#016llx", temp_64); xhci_dbg_trace(xhci, trace_xhci_dbg_address, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 402d8743d245..5579b44379a4 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -28,6 +28,8 @@ #include #include +#include + /* Code sharing between pci-quirks and xhci hcd */ #include "xhci-ext-caps.h" #include "pci-quirks.h" @@ -1604,14 +1606,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) * xHCI implementations that do not support 64-bit address pointers will ignore * the high dword, and write order is irrelevant. */ -static inline u64 xhci_read_64(const struct xhci_hcd *xhci, - __le64 __iomem *regs) -{ - __u32 __iomem *ptr = (__u32 __iomem *) regs; - u64 val_lo = readl(ptr); - u64 val_hi = readl(ptr + 1); - return val_lo + (val_hi << 32); -} static inline void xhci_write_64(struct xhci_hcd *xhci, const u64 val, __le64 __iomem *regs) { -- cgit v1.2.3 From 7dd09a1af2c7150269350aaa567a11b06e831003 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Fri, 15 Nov 2013 05:34:09 +0200 Subject: xhci: replace xhci_write_64() with writeq() Function xhci_write_64() is used to write 64bit xHC registers residing in MMIO. On 32bit systems, xHC registers need to be written with 32bit accesses by writing first the lower 32bits and then the higher 32bits. The header file asm-generic/io-64-nonatomic-lo-hi.h ensures that on 32bit systems writeq() will will write 64bit registers in 32bit chunks with low-high order. Replace all calls to xhci_write_64() with calls to writeq(). This is done to reduce code duplication since 64bit low-high write logic is already implemented and to take advantage of inherent "atomic" 64bit write operations on 64bit systems. Signed-off-by: Xenia Ragiadakou Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-mem.c | 8 ++++---- drivers/usb/host/xhci-ring.c | 8 +++----- drivers/usb/host/xhci.c | 8 ++++---- drivers/usb/host/xhci.h | 29 +++++++++-------------------- 4 files changed, 20 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4b87026f8a5a..873c272b3ef5 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1967,7 +1967,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Write event ring dequeue pointer, " "preserving EHB bit"); - xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, + writeq(((u64) deq & (u64) ~ERST_PTR_MASK) | temp, &xhci->ir_set->erst_dequeue); } @@ -2269,7 +2269,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Device context base array address = 0x%llx (DMA), %p (virt)", (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa); - xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr); + writeq(dma, &xhci->op_regs->dcbaa_ptr); /* * Initialize the ring segment pool. The ring must be a contiguous @@ -2318,7 +2318,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring->cycle_state; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Setting command ring address to 0x%x", val); - xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); + writeq(val_64, &xhci->op_regs->cmd_ring); xhci_dbg_cmd_ptrs(xhci); xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags); @@ -2399,7 +2399,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) val_64 = readq(&xhci->ir_set->erst_base); val_64 &= ERST_PTR_MASK; val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); - xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); + writeq(val_64, &xhci->ir_set->erst_base); /* Set the event ring dequeue address */ xhci_set_hc_event_deq(xhci); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 339733b8524a..fe9208a5d103 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -319,8 +319,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) return 0; } xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; - xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, - &xhci->op_regs->cmd_ring); + writeq(temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); /* Section 4.6.1.2 of xHCI 1.0 spec says software should * time the completion od all xHCI commands, including @@ -2872,8 +2871,7 @@ hw_died: * the event ring should be empty. */ temp_64 = readq(&xhci->ir_set->erst_dequeue); - xhci_write_64(xhci, temp_64 | ERST_EHB, - &xhci->ir_set->erst_dequeue); + writeq(temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); return IRQ_HANDLED; @@ -2900,7 +2898,7 @@ hw_died: /* Clear the event handler busy flag (RW1C); event ring is empty. */ temp_64 |= ERST_EHB; - xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); + writeq(temp_64, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 858e992729c9..7fe6f664054f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -762,11 +762,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci) { writel(xhci->s3.command, &xhci->op_regs->command); writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification); - xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); + writeq(xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); writel(xhci->s3.config_reg, &xhci->op_regs->config_reg); writel(xhci->s3.erst_size, &xhci->ir_set->erst_size); - xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); - xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); + writeq(xhci->s3.erst_base, &xhci->ir_set->erst_base); + writeq(xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending); writel(xhci->s3.irq_control, &xhci->ir_set->irq_control); } @@ -785,7 +785,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Setting command ring address to 0x%llx", (long unsigned long) val_64); - xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); + writeq(val_64, &xhci->op_regs->cmd_ring); } /* diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 5579b44379a4..7807f621a713 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -28,6 +28,15 @@ #include #include +/* + * Registers should always be accessed with double word or quad word accesses. + * + * Some xHCI implementations may support 64-bit address pointers. Registers + * with 64-bit address pointers should be written to with dword accesses by + * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. + * xHCI implementations that do not support 64-bit address pointers will ignore + * the high dword, and write order is irrelevant. + */ #include /* Code sharing between pci-quirks and xhci hcd */ @@ -1597,26 +1606,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) #define xhci_warn_ratelimited(xhci, fmt, args...) \ dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args) -/* - * Registers should always be accessed with double word or quad word accesses. - * - * Some xHCI implementations may support 64-bit address pointers. Registers - * with 64-bit address pointers should be written to with dword accesses by - * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. - * xHCI implementations that do not support 64-bit address pointers will ignore - * the high dword, and write order is irrelevant. - */ -static inline void xhci_write_64(struct xhci_hcd *xhci, - const u64 val, __le64 __iomem *regs) -{ - __u32 __iomem *ptr = (__u32 __iomem *) regs; - u32 val_lo = lower_32_bits(val); - u32 val_hi = upper_32_bits(val); - - writel(val_lo, ptr); - writel(val_hi, ptr + 1); -} - static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci) { return xhci->quirks & XHCI_LINK_TRB_QUIRK; -- cgit v1.2.3 From 56d0c8b7c8fb63505a06b50364d12817ded88daa Mon Sep 17 00:00:00 2001 From: Vitaly Katraew Date: Sat, 30 Nov 2013 13:51:28 +0400 Subject: HID: add support for Logitech Dual Action gamepads I have two Logitech Dual Action gamepads, both have same Vendor/Device id pair. Newest gamepad (A) can switch between old mode (HID) and XBox gamepad emulation mode. Old gamepad (B) can only work in HID mode. In HID mode gamepad A sends many EPIPE errors during initialization and was disconnected immediately after connect to usb port. It works fine in Win and Mac. After adding NOGET quirk in driver, it was working properly. Gamepad B works fine before and after changes. I tested both gamepads with 3.8.0 and 3.11.6 kernels with modified driver. Follow patch can apply for current git kernel version. I can send pcap log from usb bus with both gamepads or any other additional information if it is needed Signed-off-by: Vitaly Katraew Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-lg.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index cb219dee5e64..92b2ddc83516 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -551,6 +551,7 @@ #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 +#define USB_DEVICE_ID_LOGITECH_DUAL_ACTION 0xc216 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 06eb45fa6331..9fe9d4ac3114 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -758,6 +758,8 @@ static const struct hid_device_id lg_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), .driver_data = LG_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION), + .driver_data = LG_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), .driver_data = LG_NOGET | LG_FF4 }, -- cgit v1.2.3 From 41e043fcfa2236bb2c4a8335eb09f4c8cee224b3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:26:00 +0900 Subject: staging: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255_pci.c | 2 +- drivers/staging/comedi/drivers/addi_apci_035.c | 2 +- drivers/staging/comedi/drivers/addi_apci_1032.c | 2 +- drivers/staging/comedi/drivers/addi_apci_1500.c | 2 +- drivers/staging/comedi/drivers/addi_apci_1516.c | 2 +- drivers/staging/comedi/drivers/addi_apci_1564.c | 2 +- drivers/staging/comedi/drivers/addi_apci_16xx.c | 2 +- drivers/staging/comedi/drivers/addi_apci_2032.c | 2 +- drivers/staging/comedi/drivers/addi_apci_2200.c | 2 +- drivers/staging/comedi/drivers/addi_apci_3120.c | 2 +- drivers/staging/comedi/drivers/addi_apci_3200.c | 2 +- drivers/staging/comedi/drivers/addi_apci_3501.c | 2 +- drivers/staging/comedi/drivers/addi_apci_3xxx.c | 2 +- drivers/staging/comedi/drivers/adl_pci6208.c | 2 +- drivers/staging/comedi/drivers/adl_pci7x3x.c | 2 +- drivers/staging/comedi/drivers/adl_pci8164.c | 2 +- drivers/staging/comedi/drivers/adl_pci9111.c | 2 +- drivers/staging/comedi/drivers/adl_pci9118.c | 2 +- drivers/staging/comedi/drivers/adv_pci1710.c | 2 +- drivers/staging/comedi/drivers/adv_pci1723.c | 2 +- drivers/staging/comedi/drivers/adv_pci1724.c | 2 +- drivers/staging/comedi/drivers/adv_pci_dio.c | 2 +- drivers/staging/comedi/drivers/amplc_dio200_pci.c | 2 +- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- drivers/staging/comedi/drivers/amplc_pci224.c | 2 +- drivers/staging/comedi/drivers/amplc_pci230.c | 2 +- drivers/staging/comedi/drivers/amplc_pci263.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas64.c | 2 +- drivers/staging/comedi/drivers/cb_pcidda.c | 2 +- drivers/staging/comedi/drivers/cb_pcimdas.c | 2 +- drivers/staging/comedi/drivers/cb_pcimdda.c | 2 +- drivers/staging/comedi/drivers/contec_pci_dio.c | 2 +- drivers/staging/comedi/drivers/daqboard2000.c | 2 +- drivers/staging/comedi/drivers/das08_pci.c | 2 +- drivers/staging/comedi/drivers/dt3000.c | 2 +- drivers/staging/comedi/drivers/dyna_pci10xx.c | 2 +- drivers/staging/comedi/drivers/gsc_hpdi.c | 2 +- drivers/staging/comedi/drivers/icp_multi.c | 2 +- drivers/staging/comedi/drivers/jr3_pci.c | 2 +- drivers/staging/comedi/drivers/ke_counter.c | 2 +- drivers/staging/comedi/drivers/me4000.c | 2 +- drivers/staging/comedi/drivers/me_daq.c | 2 +- drivers/staging/comedi/drivers/ni_6527.c | 2 +- drivers/staging/comedi/drivers/ni_65xx.c | 2 +- drivers/staging/comedi/drivers/ni_660x.c | 2 +- drivers/staging/comedi/drivers/ni_670x.c | 2 +- drivers/staging/comedi/drivers/ni_labpc_pci.c | 2 +- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- drivers/staging/comedi/drivers/ni_pcimio.c | 2 +- drivers/staging/comedi/drivers/rtd520.c | 2 +- drivers/staging/comedi/drivers/s626.c | 2 +- drivers/staging/comedi/drivers/skel.c | 2 +- drivers/staging/crystalhd/crystalhd_lnx.c | 2 +- drivers/staging/dwc2/pci.c | 2 +- drivers/staging/et131x/et131x.c | 2 +- drivers/staging/media/dt3155v4l/dt3155v4l.c | 2 +- drivers/staging/media/solo6x10/solo6x10-core.c | 2 +- drivers/staging/phison/phison.c | 2 +- drivers/staging/sep/sep_main.c | 2 +- drivers/staging/slicoss/slicoss.c | 2 +- drivers/staging/sm7xxfb/sm7xxfb.c | 2 +- drivers/staging/vt6655/device_main.c | 2 +- drivers/staging/xgifb/XGI_main.h | 2 +- drivers/staging/xillybus/xillybus_pcie.c | 2 +- 65 files changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 432e3f9c3301..ec14acb653c2 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -257,7 +257,7 @@ static int pci_8255_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &pci_8255_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = { +static const struct pci_device_id pci_8255_pci_table[] = { { PCI_VDEVICE(ADLINK, 0x7224), BOARD_ADLINK_PCI7224 }, { PCI_VDEVICE(ADLINK, 0x7248), BOARD_ADLINK_PCI7248 }, { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 }, diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c index 8d229b2f0973..ccd49211ea17 100644 --- a/drivers/staging/comedi/drivers/addi_apci_035.c +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -58,7 +58,7 @@ static int apci035_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci035_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci035_pci_table) = { +static const struct pci_device_id apci035_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x0300) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index 34ab0679e992..af2306c1b649 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -364,7 +364,7 @@ static int apci1032_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci1032_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci1032_pci_table) = { +static const struct pci_device_id apci1032_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1003) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index ae9ded63dcec..74f7ace8adbc 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -57,7 +57,7 @@ static int apci1500_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci1500_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci1500_pci_table) = { +static const struct pci_device_id apci1500_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80fc) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index 9d1b1425c60b..e9c5291c77cd 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -206,7 +206,7 @@ static int apci1516_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci1516_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci1516_pci_table) = { +static const struct pci_device_id apci1516_pci_table[] = { { PCI_VDEVICE(ADDIDATA, 0x1000), BOARD_APCI1016 }, { PCI_VDEVICE(ADDIDATA, 0x1001), BOARD_APCI1516 }, { PCI_VDEVICE(ADDIDATA, 0x1002), BOARD_APCI2016 }, diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index c5717d63e16a..6248284caaf5 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -55,7 +55,7 @@ static int apci1564_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci1564_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci1564_pci_table) = { +static const struct pci_device_id apci1564_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1006) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 5ee204bcbeef..28df4b50b87a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -168,7 +168,7 @@ static int apci16xx_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci16xx_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci16xx_pci_table) = { +static const struct pci_device_id apci16xx_pci_table[] = { { PCI_VDEVICE(ADDIDATA, 0x1009), BOARD_APCI1648 }, { PCI_VDEVICE(ADDIDATA, 0x100a), BOARD_APCI1696 }, { 0 } diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index c77ee8732d38..c9b933cb5987 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -359,7 +359,7 @@ static int apci2032_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci2032_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = { +static const struct pci_device_id apci2032_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1004) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index 7fb32e778d8b..e1a916546d18 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -134,7 +134,7 @@ static int apci2200_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci2200_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci2200_pci_table) = { +static const struct pci_device_id apci2200_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1005) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 67d09e8afb2e..1e6fa56c516e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -230,7 +230,7 @@ static int apci3120_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table) = { +static const struct pci_device_id apci3120_pci_table[] = { { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 }, { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 }, { 0 } diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c index 1213d5aa6bea..9868a5369aff 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3200.c +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -109,7 +109,7 @@ static int apci3200_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci3200_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci3200_pci_table) = { +static const struct pci_device_id apci3200_pci_table[] = { { PCI_VDEVICE(ADDIDATA, 0x3000), BOARD_APCI3200 }, { PCI_VDEVICE(ADDIDATA, 0x3007), BOARD_APCI3300 }, { 0 } diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 6138440b919e..4cb69ec54c9b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -428,7 +428,7 @@ static int apci3501_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci3501_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table) = { +static const struct pci_device_id apci3501_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 761cbf8f964b..ceadf8eff47f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -915,7 +915,7 @@ static int apci3xxx_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &apci3xxx_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(apci3xxx_pci_table) = { +static const struct pci_device_id apci3xxx_pci_table[] = { { PCI_VDEVICE(ADDIDATA, 0x3010), BOARD_APCI3000_16 }, { PCI_VDEVICE(ADDIDATA, 0x300f), BOARD_APCI3000_8 }, { PCI_VDEVICE(ADDIDATA, 0x300e), BOARD_APCI3000_4 }, diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index dd092c7954a9..5c1413abc52d 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -242,7 +242,7 @@ static int adl_pci6208_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = { +static const struct pci_device_id adl_pci6208_pci_table[] = { { PCI_VDEVICE(ADLINK, 0x6208), BOARD_PCI6208 }, { PCI_VDEVICE(ADLINK, 0x6216), BOARD_PCI6216 }, { 0 } diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index 5617f5ca384a..6f622b4de698 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -259,7 +259,7 @@ static int adl_pci7x3x_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adl_pci7x3x_pci_table) = { +static const struct pci_device_id adl_pci7x3x_pci_table[] = { { PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 }, { PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 }, { PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 }, diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index b3d009285ed4..300df55a2802 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -145,7 +145,7 @@ static int adl_pci8164_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = { +static const struct pci_device_id adl_pci8164_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x8164) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index eab8da2c3d66..03b38ea92cb0 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -938,7 +938,7 @@ static int pci9111_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { +static const struct pci_device_id pci9111_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) }, /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */ { 0 } diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 986489641ed7..97343cc40515 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -2217,7 +2217,7 @@ static int adl_pci9118_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = { +static const struct pci_device_id adl_pci9118_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index c3fdcabe9aec..bac5e0dcc685 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1374,7 +1374,7 @@ static int adv_pci1710_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = { +static const struct pci_device_id adv_pci1710_pci_table[] = { { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050), diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index bd4f781b4b24..72394267ddfe 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -306,7 +306,7 @@ static int adv_pci1723_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adv_pci1723_pci_table) = { +static const struct pci_device_id adv_pci1723_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index 009a3039fc4f..56f2d97b3a46 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -381,7 +381,7 @@ static int adv_pci1724_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(adv_pci1724_pci_table) = { +static const struct pci_device_id adv_pci1724_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1724) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 6bac665261f8..d4bd61d84daf 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1188,7 +1188,7 @@ static int adv_pci_dio_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype); } -static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = { +static const struct pci_device_id adv_pci_dio_pci_table[] = { { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 }, { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 }, { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 }, diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index a810a2416443..e0367380b37a 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -439,7 +439,7 @@ static struct comedi_driver dio200_pci_comedi_driver = { .detach = dio200_pci_detach, }; -static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { +static const struct pci_device_id dio200_pci_table[] = { { PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215), pci215_model diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 98075f999c9f..eaf21ce37ed5 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -567,7 +567,7 @@ static struct comedi_driver amplc_pc236_driver = { }; #if DO_PCI -static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { +static const struct pci_device_id pc236_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) }, {0} }; diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index dcccdce53c18..230a0103497b 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1496,7 +1496,7 @@ static int amplc_pci224_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = { +static const struct pci_device_id amplc_pci224_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) }, { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) }, { 0 } diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index e11d7cec11e6..58e7a43586e6 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2852,7 +2852,7 @@ static int amplc_pci230_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = { +static const struct pci_device_id amplc_pci230_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) }, { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) }, { 0 } diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index 4bd4ef8e88cd..be28e6cbea20 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -96,7 +96,7 @@ static struct comedi_driver amplc_pci263_driver = { .detach = comedi_pci_disable, }; -static DEFINE_PCI_DEVICE_TABLE(pci263_pci_table) = { +static const struct pci_device_id pci263_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, {0} }; diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index e72a403db17c..22c1623c048b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1614,7 +1614,7 @@ static int cb_pcidas_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = { +static const struct pci_device_id cb_pcidas_pci_table[] = { { PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 }, { PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 }, { PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 }, diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index a0053bbb2ede..0fcedd050425 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -4041,7 +4041,7 @@ static int cb_pcidas64_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = { +static const struct pci_device_id cb_pcidas64_pci_table[] = { { PCI_VDEVICE(CB, 0x001d), BOARD_PCIDAS6402_16 }, { PCI_VDEVICE(CB, 0x001e), BOARD_PCIDAS6402_12 }, { PCI_VDEVICE(CB, 0x0035), BOARD_PCIDAS64_M1_16 }, diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 94f115820279..8cca0518cfda 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -407,7 +407,7 @@ static int cb_pcidda_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = { +static const struct pci_device_id cb_pcidda_pci_table[] = { { PCI_VDEVICE(CB, 0x0020), BOARD_DDA02_12 }, { PCI_VDEVICE(CB, 0x0021), BOARD_DDA04_12 }, { PCI_VDEVICE(CB, 0x0022), BOARD_DDA08_12 }, diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index b25fa5d6e1e8..04dc2005454a 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -285,7 +285,7 @@ static int cb_pcimdas_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = { +static const struct pci_device_id cb_pcimdas_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0056) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index edf17b63096f..43a86630a66e 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -206,7 +206,7 @@ static int cb_pcimdda_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(cb_pcimdda_pci_table) = { +static const struct pci_device_id cb_pcimdda_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_ID_PCIM_DDA06_16) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 89836c0828d9..323a7f39cd97 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -111,7 +111,7 @@ static int contec_pci_dio_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = { +static const struct pci_device_id contec_pci_dio_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index de920ccff400..ce153fcb8b2a 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -772,7 +772,7 @@ static int daqboard2000_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = { +static const struct pci_device_id daqboard2000_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_IOTECH, 0x0409) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 3a6d3725b25f..d94af09151b0 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -89,7 +89,7 @@ static int das08_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { +static const struct pci_device_id das08_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_PCIDAS08) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 3073efd79248..1410943807b9 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -795,7 +795,7 @@ static int dt3000_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &dt3000_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = { +static const struct pci_device_id dt3000_pci_table[] = { { PCI_VDEVICE(DT, 0x0022), BOARD_DT3001 }, { PCI_VDEVICE(DT, 0x0023), BOARD_DT3002 }, { PCI_VDEVICE(DT, 0x0024), BOARD_DT3003 }, diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 9b1f196dbbc8..8fd705cb235b 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -259,7 +259,7 @@ static int dyna_pci10xx_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = { +static const struct pci_device_id dyna_pci10xx_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_PLX, 0x1050) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 4fcf3c876ac9..de60a2871d70 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -836,7 +836,7 @@ static int gsc_hpdi_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &gsc_hpdi_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(gsc_hpdi_pci_table) = { +static const struct pci_device_id gsc_hpdi_pci_table[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX, 0x2400, 0, 0, 0}, { 0 } diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 1e16641ec52d..e00aa9089e5f 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -597,7 +597,7 @@ static int icp_multi_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &icp_multi_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(icp_multi_pci_table) = { +static const struct pci_device_id icp_multi_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ICP, PCI_DEVICE_ID_ICP_MULTI) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index b52d58e5de27..6100c12c164f 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -807,7 +807,7 @@ static int jr3_pci_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &jr3_pci_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = { +static const struct pci_device_id jr3_pci_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL) }, { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW) }, { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL) }, diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 15589f62a619..6b9846fd8c48 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -139,7 +139,7 @@ static int ke_counter_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ke_counter_pci_table) = { +static const struct pci_device_id ke_counter_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 3d12e9135926..081a31004801 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1635,7 +1635,7 @@ static int me4000_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = { +static const struct pci_device_id me4000_pci_table[] = { { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 }, { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 }, { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I }, diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 24ec9ef9b1a0..7f6687896401 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -576,7 +576,7 @@ static int me_daq_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &me_daq_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(me_daq_pci_table) = { +static const struct pci_device_id me_daq_pci_table[] = { { PCI_VDEVICE(MEILHAUS, 0x2600), BOARD_ME2600 }, { PCI_VDEVICE(MEILHAUS, 0x2000), BOARD_ME2000 }, { 0 } diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 85aa9609d6a2..860fc81fb11c 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -455,7 +455,7 @@ static int ni6527_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &ni6527_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = { +static const struct pci_device_id ni6527_pci_table[] = { { PCI_VDEVICE(NI, 0x2b10), BOARD_PXI6527 }, { PCI_VDEVICE(NI, 0x2b20), BOARD_PCI6527 }, { 0 } diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index aae708bfbe15..effa12482c8d 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -738,7 +738,7 @@ static int ni_65xx_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &ni_65xx_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = { +static const struct pci_device_id ni_65xx_pci_table[] = { { PCI_VDEVICE(NI, 0x1710), BOARD_PXI6509 }, { PCI_VDEVICE(NI, 0x7085), BOARD_PCI6509 }, { PCI_VDEVICE(NI, 0x7086), BOARD_PXI6528 }, diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 8a991dcab24a..61c64a9e3c30 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1320,7 +1320,7 @@ static int ni_660x_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &ni_660x_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = { +static const struct pci_device_id ni_660x_pci_table[] = { { PCI_VDEVICE(NI, 0x1310), BOARD_PCI6602 }, { PCI_VDEVICE(NI, 0x1360), BOARD_PXI6602 }, { PCI_VDEVICE(NI, 0x2c60), BOARD_PCI6601 }, diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index e4414cf110e7..8550fdc4ccd3 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -282,7 +282,7 @@ static int ni_670x_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &ni_670x_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = { +static const struct pci_device_id ni_670x_pci_table[] = { { PCI_VDEVICE(NI, 0x1290), BOARD_PCI6704 }, { PCI_VDEVICE(NI, 0x1920), BOARD_PXI6704 }, { PCI_VDEVICE(NI, 0x2c90), BOARD_PCI6703 }, diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 8be681fca907..739597068297 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -107,7 +107,7 @@ static struct comedi_driver labpc_pci_comedi_driver = { .detach = labpc_pci_detach, }; -static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { +static const struct pci_device_id labpc_pci_table[] = { { PCI_VDEVICE(NI, 0x161), BOARD_NI_PCI1200 }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index c7bc23044568..313b436617bb 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1075,7 +1075,7 @@ static int ni_pcidio_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = { +static const struct pci_device_id ni_pcidio_pci_table[] = { { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS }, { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 }, { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 }, diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index aa002b275458..b0ed0413bd0f 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1637,7 +1637,7 @@ static int ni_pcimio_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &ni_pcimio_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(ni_pcimio_pci_table) = { +static const struct pci_device_id ni_pcimio_pci_table[] = { { PCI_VDEVICE(NI, 0x0162), BOARD_PCIMIO_16XE_50 }, /* 0x1620? */ { PCI_VDEVICE(NI, 0x1170), BOARD_PCIMIO_16XE_10 }, { PCI_VDEVICE(NI, 0x1180), BOARD_PCIMIO_16E_1 }, diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 44c8712ed9e0..a1e4892eac31 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1427,7 +1427,7 @@ static int rtd520_pci_probe(struct pci_dev *dev, return comedi_pci_auto_config(dev, &rtd520_driver, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = { +static const struct pci_device_id rtd520_pci_table[] = { { PCI_VDEVICE(RTD, 0x7520), BOARD_DM7520 }, { PCI_VDEVICE(RTD, 0x4520), BOARD_PCI4520 }, { 0 } diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index b486099b543d..6d266235ae4f 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2965,7 +2965,7 @@ static int s626_pci_probe(struct pci_dev *dev, * also subvendor:subdevice ids, because otherwise it will conflict with * Philips SAA7146 media/dvb based cards. */ -static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { +static const struct pci_device_id s626_pci_table[] = { { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x6000, 0x0272) }, { 0 } diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index daee2f42bde0..77e2059ff62e 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -698,7 +698,7 @@ static int skel_pci_probe(struct pci_dev *dev, * This is used by modprobe to translate PCI IDs to drivers. * Should only be used for PCI and ISA-PnP devices */ -static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = { +static const struct pci_device_id skel_pci_table[] = { { PCI_VDEVICE(SKEL, 0x0100), BOARD_SKEL100 }, { PCI_VDEVICE(SKEL, 0x0200), BOARD_SKEL200 }, { 0 } diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c index 190b9b924368..99eefd0291c3 100644 --- a/drivers/staging/crystalhd/crystalhd_lnx.c +++ b/drivers/staging/crystalhd/crystalhd_lnx.c @@ -703,7 +703,7 @@ static int chd_dec_pci_resume(struct pci_dev *pdev) } #endif -static DEFINE_PCI_DEVICE_TABLE(chd_dec_pci_id_table) = { +static const struct pci_device_id chd_dec_pci_id_table[] = { { PCI_VDEVICE(BROADCOM, 0x1612), 8 }, { 0, }, }; diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c index 3d14c8870fca..c291fca5d21f 100644 --- a/drivers/staging/dwc2/pci.c +++ b/drivers/staging/dwc2/pci.c @@ -152,7 +152,7 @@ static int dwc2_driver_probe(struct pci_dev *dev, return retval; } -static DEFINE_PCI_DEVICE_TABLE(dwc2_pci_ids) = { +static const struct pci_device_id dwc2_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_PRODUCT_ID_HAPS_HSOTG), }, diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index ab8b29d2cb26..ca36b04d3c1b 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -4930,7 +4930,7 @@ err_disable: goto out; } -static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = { +static const struct pci_device_id et131x_pci_table[] = { { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_GIG), 0UL}, { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_FAST), 0UL}, {0,} diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c index 081407be33ab..e729e52639c5 100644 --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c @@ -974,7 +974,7 @@ dt3155_remove(struct pci_dev *pdev) kfree(pd); } -static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { +static const struct pci_device_id pci_ids[] = { { PCI_DEVICE(DT3155_VENDOR_ID, DT3155_DEVICE_ID) }, { 0, /* zero marks the end */ }, }; diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/staging/media/solo6x10/solo6x10-core.c index 36750205d23f..480b7c4064cc 100644 --- a/drivers/staging/media/solo6x10/solo6x10-core.c +++ b/drivers/staging/media/solo6x10/solo6x10-core.c @@ -669,7 +669,7 @@ static void solo_pci_remove(struct pci_dev *pdev) free_solo_dev(solo_dev); } -static DEFINE_PCI_DEVICE_TABLE(solo_id_table) = { +static const struct pci_device_id solo_id_table[] = { /* 6010 based cards */ { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010), .driver_data = SOLO_DEV_6010 }, diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c index 919cb95236fc..57fc27958797 100644 --- a/drivers/staging/phison/phison.c +++ b/drivers/staging/phison/phison.c @@ -69,7 +69,7 @@ static int phison_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } -static DEFINE_PCI_DEVICE_TABLE(phison_pci_tbl) = { +static const struct pci_device_id phison_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000), PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 }, { 0, }, diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 1e80a4013b8c..dca838d043e5 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -4292,7 +4292,7 @@ static void sep_remove(struct pci_dev *pdev) } /* Initialize struct pci_device_id for our driver */ -static DEFINE_PCI_DEVICE_TABLE(sep_pci_id_tbl) = { +static const struct pci_device_id sep_pci_id_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0826)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08e9)}, {0} diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 652272b96a56..f340cb9a90ff 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -136,7 +136,7 @@ MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting"); module_param(intagg_delay, int, 0); MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay"); -static DEFINE_PCI_DEVICE_TABLE(slic_pci_tbl) = { +static const struct pci_device_id slic_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) }, { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) }, { 0 } diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index ba199ffff178..805c3fa36d8f 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -920,7 +920,7 @@ failed_free: * 0x712 (LynxEM+) * 0x720 (Lynx3DM, Lynx3DM+) */ -static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = { +static const struct pci_device_id smtcfb_pci_table[] = { { PCI_DEVICE(0x126f, 0x710), }, { PCI_DEVICE(0x126f, 0x712), }, { PCI_DEVICE(0x126f, 0x720), }, diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 68cbaee29775..a952df1bf9d6 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -267,7 +267,7 @@ static CHIP_INFO chip_info_table[] = { {0, NULL} }; -DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = { +const struct pci_device_id vt6655_pci_id_table[] = { { PCI_VDEVICE(VIA, 0x3253), (kernel_ulong_t)chip_info_table}, { 0, } }; diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index c033da408a58..95ce9708cec9 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -11,7 +11,7 @@ #define PCI_DEVICE_ID_XGI_27 0x027 #endif -static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = { +static const struct pci_device_id xgifb_pci_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_20)}, {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_27)}, {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_40)}, diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c index 1811aa764213..0564f97bdde4 100644 --- a/drivers/staging/xillybus/xillybus_pcie.c +++ b/drivers/staging/xillybus/xillybus_pcie.c @@ -30,7 +30,7 @@ MODULE_LICENSE("GPL v2"); static const char xillyname[] = "xillybus_pcie"; -static DEFINE_PCI_DEVICE_TABLE(xillyids) = { +static const struct pci_device_id xillyids[] = { {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)}, {PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)}, -- cgit v1.2.3 From a4d8d6da4820230a2e0e977fda44ced9345c41d4 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 22 Nov 2013 14:01:23 +0200 Subject: pinctrl-baytrail: show pin label with the reset of the gpio debug data The default gpiolib debug output shows pin labels. We want baytrail custom debug output to have the same functionality. Signed-off-by: Mathias Nyman Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-baytrail.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 2832576d8b12..1174ea86b6e9 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -286,13 +286,19 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) spin_lock_irqsave(&vg->lock, flags); for (i = 0; i < vg->chip.ngpio; i++) { + const char *label; offs = vg->range->pins[i] * 16; conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); val = readl(vg->reg_base + offs + BYT_VAL_REG); + label = gpiochip_is_requested(chip, i); + if (!label) + label = "Unrequested"; + seq_printf(s, - " gpio-%-3d %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n", + " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n", i, + label, val & BYT_INPUT_EN ? " " : "in", val & BYT_OUTPUT_EN ? " " : "out", val & BYT_LEVEL ? "hi" : "lo", -- cgit v1.2.3 From e5428a682ca726249a89201c79ddd0599669c484 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 26 Nov 2013 14:28:32 +0100 Subject: gpio: drop users of irq_set_chip_and_handler_name() Switch all users of irq_set_chip_and_handler_name() to simply use irq_set_chip_and_handler(), all just provide a boilerplate name like "demux" or "mux" - a fact which is anyway obvious from the hwirq number from the irqdomain now present in e.g. /proc/interrupts. Cc: Mathias Nyman Cc: Dan Carpenter Acked-by: David Cohen Acked-by: Mika Westerberg Tested-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpio-intel-mid.c | 3 +-- drivers/gpio/gpio-lynxpoint.c | 3 +-- drivers/gpio/gpio-msic.c | 7 +++---- drivers/gpio/gpio-timberdale.c | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index be803af658ac..17f135046c7f 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -358,8 +358,7 @@ static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq, { struct intel_mid_gpio *priv = d->host_data; - irq_set_chip_and_handler_name(irq, &intel_mid_irqchip, - handle_simple_irq, "demux"); + irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq); irq_set_chip_data(irq, priv); irq_set_irq_type(irq, IRQ_TYPE_NONE); diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index f1ca9d5880b6..89867ed7bd50 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -331,8 +331,7 @@ static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq, { struct lp_gpio *lg = d->host_data; - irq_set_chip_and_handler_name(irq, &lp_irqchip, handle_simple_irq, - "demux"); + irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq); irq_set_chip_data(irq, lg); irq_set_irq_type(irq, IRQ_TYPE_NONE); diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index d75eaa3a1dcc..69d60ab1d698 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -305,10 +305,9 @@ static int platform_msic_gpio_probe(struct platform_device *pdev) for (i = 0; i < mg->chip.ngpio; i++) { irq_set_chip_data(i + mg->irq_base, mg); - irq_set_chip_and_handler_name(i + mg->irq_base, - &msic_irqchip, - handle_simple_irq, - "demux"); + irq_set_chip_and_handler(i + mg->irq_base, + &msic_irqchip, + handle_simple_irq); } irq_set_chained_handler(mg->irq, msic_gpio_irq_handler); irq_set_handler_data(mg->irq, mg); diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 7a0e956ef1ed..521971e6a9f5 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -290,8 +290,8 @@ static int timbgpio_probe(struct platform_device *pdev) return 0; for (i = 0; i < pdata->nr_pins; i++) { - irq_set_chip_and_handler_name(tgpio->irq_base + i, - &timbgpio_irqchip, handle_simple_irq, "mux"); + irq_set_chip_and_handler(tgpio->irq_base + i, + &timbgpio_irqchip, handle_simple_irq); irq_set_chip_data(tgpio->irq_base + i, tgpio); #ifdef CONFIG_ARM set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); -- cgit v1.2.3 From eef80f333fe659b2a5782abcaae93848d3963b57 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 21 Nov 2013 13:55:14 +0100 Subject: ARM: lpc32xx: move custom GPIO header Move to . Acked-by: Roland Stigge Signed-off-by: Linus Walleij --- arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h | 50 ----------------------- arch/arm/mach-lpc32xx/phy3250.c | 2 +- drivers/gpio/gpio-lpc32xx.c | 2 +- include/linux/platform_data/gpio-lpc32xx.h | 50 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 52 deletions(-) delete mode 100644 arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h create mode 100644 include/linux/platform_data/gpio-lpc32xx.h (limited to 'drivers') diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h deleted file mode 100644 index a544e962a818..000000000000 --- a/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Author: Kevin Wells - * - * Copyright (C) 2010 NXP Semiconductors - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * 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. - */ - -#ifndef __MACH_GPIO_LPC32XX_H -#define __MACH_GPIO_LPC32XX_H - -/* - * Note! - * Muxed GP pins need to be setup to the GP state in the board level - * code prior to using this driver. - * GPI pins : 28xP3 group - * GPO pins : 24xP3 group - * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group - */ - -#define LPC32XX_GPIO_P0_MAX 8 -#define LPC32XX_GPIO_P1_MAX 24 -#define LPC32XX_GPIO_P2_MAX 13 -#define LPC32XX_GPIO_P3_MAX 6 -#define LPC32XX_GPI_P3_MAX 29 -#define LPC32XX_GPO_P3_MAX 24 - -#define LPC32XX_GPIO_P0_GRP 0 -#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX) -#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX) -#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX) -#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX) -#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) - -/* - * A specific GPIO can be selected with this macro - * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) - * See the LPC32x0 User's guide for GPIO group numbers - */ -#define LPC32XX_GPIO(x, y) ((x) + (y)) - -#endif /* __MACH_GPIO_LPC32XX_H */ diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index e54f87ec2e4a..34932e0e31fa 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,6 @@ #include #include #include -#include #include "common.h" /* diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 2d5555decf0c..a7093e010149 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -25,10 +25,10 @@ #include #include #include +#include #include #include -#include #include #define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) diff --git a/include/linux/platform_data/gpio-lpc32xx.h b/include/linux/platform_data/gpio-lpc32xx.h new file mode 100644 index 000000000000..a544e962a818 --- /dev/null +++ b/include/linux/platform_data/gpio-lpc32xx.h @@ -0,0 +1,50 @@ +/* + * Author: Kevin Wells + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#ifndef __MACH_GPIO_LPC32XX_H +#define __MACH_GPIO_LPC32XX_H + +/* + * Note! + * Muxed GP pins need to be setup to the GP state in the board level + * code prior to using this driver. + * GPI pins : 28xP3 group + * GPO pins : 24xP3 group + * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group + */ + +#define LPC32XX_GPIO_P0_MAX 8 +#define LPC32XX_GPIO_P1_MAX 24 +#define LPC32XX_GPIO_P2_MAX 13 +#define LPC32XX_GPIO_P3_MAX 6 +#define LPC32XX_GPI_P3_MAX 29 +#define LPC32XX_GPO_P3_MAX 24 + +#define LPC32XX_GPIO_P0_GRP 0 +#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX) +#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX) +#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX) +#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX) +#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) + +/* + * A specific GPIO can be selected with this macro + * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) + * See the LPC32x0 User's guide for GPIO group numbers + */ +#define LPC32XX_GPIO(x, y) ((x) + (y)) + +#endif /* __MACH_GPIO_LPC32XX_H */ -- cgit v1.2.3 From d463c6ff88108d187c73396280f5dae8b4a78e65 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 27 Nov 2013 15:46:06 +0100 Subject: gpio-lynxpoint: Allow building as a module Change CONFIG_GPIO_LYNXPOINT from bool to tristate so that the gpio-lynxpoint driver can be built as a module. Add the required glue: an exit function to unregister the driver, and module information. Signed-off-by: Jean Delvare Cc: Mathias Nyman Cc: Linus Walleij Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-lynxpoint.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0f0444475bf0..58d98dd9e4b9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -353,7 +353,7 @@ config GPIO_GE_FPGA board computers. config GPIO_LYNXPOINT - bool "Intel Lynxpoint GPIO support" + tristate "Intel Lynxpoint GPIO support" depends on ACPI && X86 select IRQ_DOMAIN help diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 89867ed7bd50..1a7443ee6016 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -469,4 +469,15 @@ static int __init lp_gpio_init(void) return platform_driver_register(&lp_gpio_driver); } +static void __exit lp_gpio_exit(void) +{ + platform_driver_unregister(&lp_gpio_driver); +} + subsys_initcall(lp_gpio_init); +module_exit(lp_gpio_exit); + +MODULE_AUTHOR("Mathias Nyman (Intel)"); +MODULE_DESCRIPTION("GPIO interface for Intel Lynxpoint"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lp_gpio"); -- cgit v1.2.3 From 850dfe17e3c467f50a0b9a527a65831873740c23 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 29 Nov 2013 14:48:00 +0100 Subject: gpio: rcar: Support both edge trigger with DT Some versions of the R-Car GPIO controller support triggering on both edges of the input signal. Whether this capability is supported is currently specified in platform data. R-Car GPIO devices instantiated from the device tree have the capability turned off even when the hardware supports it. To fix this, add DT match data support to the driver, initialize both edge trigger support from match data and enable both edge trigger in r8a7790 and r8a7791 match data. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 56 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d2c34da7b3bf..28fa94a316ff 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -284,7 +284,34 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = { .map = gpio_rcar_irq_domain_map, }; -static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) +struct gpio_rcar_info { + bool has_both_edge_trigger; +}; + +static const struct of_device_id gpio_rcar_of_table[] = { + { + .compatible = "renesas,gpio-r8a7790", + .data = (void *)&(const struct gpio_rcar_info) { + .has_both_edge_trigger = true, + }, + }, { + .compatible = "renesas,gpio-r8a7791", + .data = (void *)&(const struct gpio_rcar_info) { + .has_both_edge_trigger = true, + }, + }, { + .compatible = "renesas,gpio-rcar", + .data = (void *)&(const struct gpio_rcar_info) { + .has_both_edge_trigger = false, + }, + }, { + /* Terminator */ + }, +}; + +MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); + +static int gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) { struct gpio_rcar_config *pdata = dev_get_platdata(&p->pdev->dev); struct device_node *np = p->pdev->dev.of_node; @@ -294,11 +321,21 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) if (pdata) { p->config = *pdata; } else if (IS_ENABLED(CONFIG_OF) && np) { + const struct of_device_id *match; + const struct gpio_rcar_info *info; + + match = of_match_node(gpio_rcar_of_table, np); + if (!match) + return -EINVAL; + + info = match->data; + ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); p->config.number_of_pins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; p->config.gpio_base = -1; + p->config.has_both_edge_trigger = info->has_both_edge_trigger; } if (p->config.number_of_pins == 0 || @@ -308,6 +345,8 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK); p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK; } + + return 0; } static int gpio_rcar_probe(struct platform_device *pdev) @@ -330,7 +369,9 @@ static int gpio_rcar_probe(struct platform_device *pdev) spin_lock_init(&p->lock); /* Get device configuration from DT node or platform data. */ - gpio_rcar_parse_pdata(p); + ret = gpio_rcar_parse_pdata(p); + if (ret < 0) + return ret; platform_set_drvdata(pdev, p); @@ -434,17 +475,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF -static const struct of_device_id gpio_rcar_of_table[] = { - { - .compatible = "renesas,gpio-rcar", - }, - { }, -}; - -MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); -#endif - static struct platform_driver gpio_rcar_device_driver = { .probe = gpio_rcar_probe, .remove = gpio_rcar_remove, -- cgit v1.2.3 From 0299b77b44531ae0963fe86d8b9cb9b5ddb584b7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 29 Nov 2013 12:11:34 +0100 Subject: gpio: Add MOXA ART GPIO driver Add GPIO driver for MOXA ART SoCs. Signed-off-by: Jonas Jensen Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/moxa,moxart-gpio.txt | 19 +++ drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-moxart.c | 162 +++++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt create mode 100644 drivers/gpio/gpio-moxart.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt b/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt new file mode 100644 index 000000000000..f8e8f185a3db --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt @@ -0,0 +1,19 @@ +MOXA ART GPIO Controller + +Required properties: + +- #gpio-cells : Should be 2, The first cell is the pin number, + the second cell is used to specify polarity: + 0 = active high + 1 = active low +- compatible : Must be "moxa,moxart-gpio" +- reg : Should contain registers location and length + +Example: + + gpio: gpio@98700000 { + gpio-controller; + #gpio-cells = <2>; + compatible = "moxa,moxart-gpio"; + reg = <0x98700000 0xC>; + }; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 58d98dd9e4b9..ae3682d25a3c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -156,6 +156,13 @@ config GPIO_F7188X To compile this driver as a module, choose M here: the module will be called f7188x-gpio. +config GPIO_MOXART + bool "MOXART GPIO support" + depends on ARCH_MOXART + help + Select this option to enable GPIO driver for + MOXA ART SoC devices. + config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 7971e36b8b12..ee95154cb1d2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o +obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c new file mode 100644 index 000000000000..d662cdededac --- /dev/null +++ b/drivers/gpio/gpio-moxart.c @@ -0,0 +1,162 @@ +/* + * MOXA ART SoCs GPIO driver. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_DATA_OUT 0x00 +#define GPIO_DATA_IN 0x04 +#define GPIO_PIN_DIRECTION 0x08 + +struct moxart_gpio_chip { + struct gpio_chip gpio; + void __iomem *moxart_gpio_base; +}; + +static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct moxart_gpio_chip, gpio); +} + +static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_request_gpio(offset); +} + +static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + pinctrl_free_gpio(offset); +} + +static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + + writel(readl(ioaddr) & ~BIT(offset), ioaddr); + return 0; +} + +static int moxart_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + + writel(readl(ioaddr) | BIT(offset), ioaddr); + return 0; +} + +static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_DATA_OUT; + u32 reg = readl(ioaddr); + + if (value) + reg = reg | BIT(offset); + else + reg = reg & ~BIT(offset); + + + writel(reg, ioaddr); +} + +static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct moxart_gpio_chip *gc = to_moxart_gpio(chip); + u32 ret = readl(gc->moxart_gpio_base + GPIO_PIN_DIRECTION); + + if (ret & BIT(offset)) + return !!(readl(gc->moxart_gpio_base + GPIO_DATA_OUT) & + BIT(offset)); + else + return !!(readl(gc->moxart_gpio_base + GPIO_DATA_IN) & + BIT(offset)); +} + +static struct gpio_chip moxart_template_chip = { + .label = "moxart-gpio", + .request = moxart_gpio_request, + .free = moxart_gpio_free, + .direction_input = moxart_gpio_direction_input, + .direction_output = moxart_gpio_direction_output, + .set = moxart_gpio_set, + .get = moxart_gpio_get, + .base = 0, + .ngpio = 32, + .can_sleep = 0, +}; + +static int moxart_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct moxart_gpio_chip *mgc; + int ret; + + mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL); + if (!mgc) { + dev_err(dev, "can't allocate GPIO chip container\n"); + return -ENOMEM; + } + mgc->gpio = moxart_template_chip; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mgc->moxart_gpio_base = devm_ioremap_resource(dev, res); + if (IS_ERR(mgc->moxart_gpio_base)) { + dev_err(dev, "%s: devm_ioremap_resource res_gpio failed\n", + dev->of_node->full_name); + return PTR_ERR(mgc->moxart_gpio_base); + } + + mgc->gpio.dev = dev; + + ret = gpiochip_add(&mgc->gpio); + if (ret) { + dev_err(dev, "%s: gpiochip_add failed\n", + dev->of_node->full_name); + return ret; + } + + return 0; +} + +static const struct of_device_id moxart_gpio_match[] = { + { .compatible = "moxa,moxart-gpio" }, + { } +}; + +static struct platform_driver moxart_gpio_driver = { + .driver = { + .name = "moxart-gpio", + .owner = THIS_MODULE, + .of_match_table = moxart_gpio_match, + }, + .probe = moxart_gpio_probe, +}; +module_platform_driver(moxart_gpio_driver); + +MODULE_DESCRIPTION("MOXART GPIO chip driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonas Jensen "); -- cgit v1.2.3 From 14f4a8838acac0fe6bf710ec08fc4cce57c0011b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:08:45 +0900 Subject: gpio: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Linus Walleij --- drivers/gpio/gpio-amd8111.c | 2 +- drivers/gpio/gpio-bt8xx.c | 2 +- drivers/gpio/gpio-intel-mid.c | 2 +- drivers/gpio/gpio-ml-ioh.c | 2 +- drivers/gpio/gpio-pch.c | 2 +- drivers/gpio/gpio-sodaville.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c index 710fafcdd1b1..94e9992f8904 100644 --- a/drivers/gpio/gpio-amd8111.c +++ b/drivers/gpio/gpio-amd8111.c @@ -60,7 +60,7 @@ * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */ -static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { +static const struct pci_device_id pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 }, { 0, }, /* terminate list */ }; diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index 9dfe36fd8baf..c5c356b7f2ce 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -308,7 +308,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev) #define bt8xxgpio_resume NULL #endif /* CONFIG_PM */ -static DEFINE_PCI_DEVICE_TABLE(bt8xxgpio_pci_tbl) = { +static const struct pci_device_id bt8xxgpio_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) }, { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 17f135046c7f..f2035c01577f 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -275,7 +275,7 @@ static const struct intel_mid_gpio_ddata gpio_tangier = { .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, }; -static DEFINE_PCI_DEVICE_TABLE(intel_gpio_ids) = { +static const struct pci_device_id intel_gpio_ids[] = { { /* Lincroft */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 6da6d7667c6d..5c94af3c84e0 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -596,7 +596,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev) #define ioh_gpio_resume NULL #endif -static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { +static const struct pci_device_id ioh_gpio_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, { 0, } }; diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 0fec097e838d..ef7a756c9ded 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -518,7 +518,7 @@ static int pch_gpio_resume(struct pci_dev *pdev) #endif #define PCI_VENDOR_ID_ROHM 0x10DB -static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { +static const struct pci_device_id pch_gpio_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 88f374ac7753..5d171e0182db 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -270,7 +270,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev) kfree(sd); } -static DEFINE_PCI_DEVICE_TABLE(sdv_gpio_pci_ids) = { +static const struct pci_device_id sdv_gpio_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, { 0, }, }; -- cgit v1.2.3 From 10becdb402af4fd4808a0491a726b96128c41076 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 25 Nov 2013 09:47:00 +0100 Subject: ahci: imx: Explicitly clear IMX6Q_GPR13_SATA_MPLL_CLK_EN We must clear this IMX6Q_GPR13_SATA_MPLL_CLK_EN bit on i.MX6Q, otherwise Linux will fail to find the attached drive on some boards. This entire fix was: Reported-by: Eric Nelson Signed-off-by: Marek Vasut Reviewed-by: Shawn Guo Cc: Richard Zhu Cc: Linux-IDE Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/ahci_imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index ae2d73fe321e..3e23e9941dad 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -113,7 +113,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) /* * set PHY Paremeters, two steps to configure the GPR13, * one write for rest of parameters, mask of first write - * is 0x07fffffd, and the other one write for setting + * is 0x07ffffff, and the other one write for setting * the mpll_clk_en. */ regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK @@ -124,6 +124,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) | IMX6Q_GPR13_SATA_TX_ATTEN_MASK | IMX6Q_GPR13_SATA_TX_BOOST_MASK | IMX6Q_GPR13_SATA_TX_LVL_MASK + | IMX6Q_GPR13_SATA_MPLL_CLK_EN | IMX6Q_GPR13_SATA_TX_EDGE_RATE , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M -- cgit v1.2.3 From 8403e2ec8d4c759f821996d3bc43ca7c512ac9a0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 25 Nov 2013 09:47:01 +0100 Subject: ahci: imx: Pull out the clock enable/disable calls The same code for enabling and disabling SATA clock was found in multiple places in the driver. Implement functions that enable/disable the SATA clock and use them in such places instead of duplicating the code. Signed-off-by: Marek Vasut Reviewed-by: Shawn Guo Cc: Richard Zhu Cc: Linux-IDE Signed-off-by: Tejun Heo --- drivers/ata/ahci_imx.c | 143 ++++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 3e23e9941dad..6214411349de 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -47,6 +47,36 @@ static int ahci_imx_hotplug; module_param_named(hotplug, ahci_imx_hotplug, int, 0644); MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); +static int imx_sata_clock_enable(struct device *dev) +{ + struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + int ret; + + ret = clk_prepare_enable(imxpriv->sata_ref_clk); + if (ret < 0) { + dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); + return ret; + } + + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + IMX6Q_GPR13_SATA_MPLL_CLK_EN); + + usleep_range(1000, 2000); + + return 0; +} + +static void imx_sata_clock_disable(struct device *dev) +{ + struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + clk_disable_unprepare(imxpriv->sata_ref_clk); +} + static void ahci_imx_error_handler(struct ata_port *ap) { u32 reg_val; @@ -72,10 +102,7 @@ static void ahci_imx_error_handler(struct ata_port *ap) */ reg_val = readl(mmio + PORT_PHY_CTL); writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - !IMX6Q_GPR13_SATA_MPLL_CLK_EN); - clk_disable_unprepare(imxpriv->sata_ref_clk); + imx_sata_clock_disable(ap->dev); imxpriv->no_device = true; } @@ -97,46 +124,9 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) unsigned int reg_val; struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); - imxpriv->gpr = - syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); - if (IS_ERR(imxpriv->gpr)) { - dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); - return PTR_ERR(imxpriv->gpr); - } - - ret = clk_prepare_enable(imxpriv->sata_ref_clk); - if (ret < 0) { - dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); + ret = imx_sata_clock_enable(dev); + if (ret < 0) return ret; - } - - /* - * set PHY Paremeters, two steps to configure the GPR13, - * one write for rest of parameters, mask of first write - * is 0x07ffffff, and the other one write for setting - * the mpll_clk_en. - */ - regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK - | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK - | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK - | IMX6Q_GPR13_SATA_SPD_MODE_MASK - | IMX6Q_GPR13_SATA_MPLL_SS_EN - | IMX6Q_GPR13_SATA_TX_ATTEN_MASK - | IMX6Q_GPR13_SATA_TX_BOOST_MASK - | IMX6Q_GPR13_SATA_TX_LVL_MASK - | IMX6Q_GPR13_SATA_MPLL_CLK_EN - | IMX6Q_GPR13_SATA_TX_EDGE_RATE - , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB - | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M - | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F - | IMX6Q_GPR13_SATA_SPD_MODE_3P0G - | IMX6Q_GPR13_SATA_MPLL_SS_EN - | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 - | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB - | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); - regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, - IMX6Q_GPR13_SATA_MPLL_CLK_EN); - usleep_range(100, 200); /* * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, @@ -164,11 +154,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) static void imx6q_sata_exit(struct device *dev) { - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); - - regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, - !IMX6Q_GPR13_SATA_MPLL_CLK_EN); - clk_disable_unprepare(imxpriv->sata_ref_clk); + imx_sata_clock_disable(dev); } static int imx_ahci_suspend(struct device *dev) @@ -179,12 +165,8 @@ static int imx_ahci_suspend(struct device *dev) * If no_device is set, The CLKs had been gated off in the * initialization so don't do it again here. */ - if (!imxpriv->no_device) { - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - !IMX6Q_GPR13_SATA_MPLL_CLK_EN); - clk_disable_unprepare(imxpriv->sata_ref_clk); - } + if (!imxpriv->no_device) + imx_sata_clock_disable(dev); return 0; } @@ -192,22 +174,12 @@ static int imx_ahci_suspend(struct device *dev) static int imx_ahci_resume(struct device *dev) { struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); - int ret; + int ret = 0; - if (!imxpriv->no_device) { - ret = clk_prepare_enable(imxpriv->sata_ref_clk); - if (ret < 0) { - dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret); - return ret; - } - - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - IMX6Q_GPR13_SATA_MPLL_CLK_EN); - usleep_range(1000, 2000); - } + if (!imxpriv->no_device) + ret = imx_sata_clock_enable(dev); - return 0; + return ret; } static struct ahci_platform_data imx6q_sata_pdata = { @@ -290,6 +262,41 @@ static int imx_ahci_probe(struct platform_device *pdev) ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; ahci_dev->of_node = dev->of_node; + imxpriv->gpr = + syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + + if (IS_ERR(imxpriv->gpr)) { + dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); + ret = PTR_ERR(imxpriv->gpr); + goto err_out; + } + + /* + * Set PHY Paremeters, two steps to configure the GPR13, + * one write for rest of parameters, mask of first write + * is 0x07ffffff, and the other one write for setting + * the mpll_clk_en happens in imx_sata_clock_enable(). + */ + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | + IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | + IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | + IMX6Q_GPR13_SATA_SPD_MODE_MASK | + IMX6Q_GPR13_SATA_MPLL_SS_EN | + IMX6Q_GPR13_SATA_TX_ATTEN_MASK | + IMX6Q_GPR13_SATA_TX_BOOST_MASK | + IMX6Q_GPR13_SATA_TX_LVL_MASK | + IMX6Q_GPR13_SATA_MPLL_CLK_EN | + IMX6Q_GPR13_SATA_TX_EDGE_RATE, + IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | + IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | + IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | + IMX6Q_GPR13_SATA_SPD_MODE_3P0G | + IMX6Q_GPR13_SATA_MPLL_SS_EN | + IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | + IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | + IMX6Q_GPR13_SATA_TX_LVL_1_025_V); + ret = platform_device_add_resources(ahci_pdev, res, 2); if (ret) goto err_out; -- cgit v1.2.3 From 4a23d1793f8e268e5867eec6c20abe78ec28ba5f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 25 Nov 2013 09:47:02 +0100 Subject: ahci: imx: Add i.MX53 support Add minor adjustments to support i.MX53 SATA port as well as i.MX6Q one. The difference here is mostly the clock which need to be enabled and also the lack of need of programming IOMUXC registers on i.MX53. All of which is well handles in the clock enable/disable functions. Note that this patch also cleans up the names of the common functions, so they don't read imx6q_* but imx_* instead. Signed-off-by: Marek Vasut Reviewed-by: Shawn Guo Cc: Richard Zhu Cc: Linux-IDE Signed-off-by: Tejun Heo --- drivers/ata/ahci_imx.c | 180 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 6214411349de..8cb89655cf06 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -34,10 +34,21 @@ enum { HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ }; +enum ahci_imx_type { + AHCI_IMX53, + AHCI_IMX6Q, +}; + struct imx_ahci_priv { struct platform_device *ahci_pdev; + enum ahci_imx_type type; + + /* i.MX53 clock */ + struct clk *sata_gate_clk; + /* Common clock */ struct clk *sata_ref_clk; struct clk *ahb_clk; + struct regmap *gpr; bool no_device; bool first_time; @@ -52,29 +63,52 @@ static int imx_sata_clock_enable(struct device *dev) struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); int ret; + if (imxpriv->type == AHCI_IMX53) { + ret = clk_prepare_enable(imxpriv->sata_gate_clk); + if (ret < 0) { + dev_err(dev, "prepare-enable sata_gate clock err:%d\n", + ret); + return ret; + } + } + ret = clk_prepare_enable(imxpriv->sata_ref_clk); if (ret < 0) { - dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret); - return ret; + dev_err(dev, "prepare-enable sata_ref clock err:%d\n", + ret); + goto clk_err; } - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - IMX6Q_GPR13_SATA_MPLL_CLK_EN); + if (imxpriv->type == AHCI_IMX6Q) { + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + IMX6Q_GPR13_SATA_MPLL_CLK_EN); + } usleep_range(1000, 2000); return 0; + +clk_err: + if (imxpriv->type == AHCI_IMX53) + clk_disable_unprepare(imxpriv->sata_gate_clk); + return ret; } static void imx_sata_clock_disable(struct device *dev) { struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + if (imxpriv->type == AHCI_IMX6Q) { + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + } + clk_disable_unprepare(imxpriv->sata_ref_clk); + + if (imxpriv->type == AHCI_IMX53) + clk_disable_unprepare(imxpriv->sata_gate_clk); } static void ahci_imx_error_handler(struct ata_port *ap) @@ -106,9 +140,25 @@ static void ahci_imx_error_handler(struct ata_port *ap) imxpriv->no_device = true; } +int ahci_imx_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + struct ata_port *ap = link->ap; + struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); + int ret = -EIO; + + if (imxpriv->type == AHCI_IMX53) + ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline); + else if (imxpriv->type == AHCI_IMX6Q) + ret = ahci_ops.softreset(link, class, deadline); + + return ret; +} + static struct ata_port_operations ahci_imx_ops = { .inherits = &ahci_platform_ops, .error_handler = ahci_imx_error_handler, + .softreset = ahci_imx_softreset, }; static const struct ata_port_info ahci_imx_port_info = { @@ -118,7 +168,7 @@ static const struct ata_port_info ahci_imx_port_info = { .port_ops = &ahci_imx_ops, }; -static int imx6q_sata_init(struct device *dev, void __iomem *mmio) +static int imx_sata_init(struct device *dev, void __iomem *mmio) { int ret = 0; unsigned int reg_val; @@ -152,7 +202,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) return 0; } -static void imx6q_sata_exit(struct device *dev) +static void imx_sata_exit(struct device *dev) { imx_sata_clock_disable(dev); } @@ -182,16 +232,18 @@ static int imx_ahci_resume(struct device *dev) return ret; } -static struct ahci_platform_data imx6q_sata_pdata = { - .init = imx6q_sata_init, - .exit = imx6q_sata_exit, - .ata_port_info = &ahci_imx_port_info, - .suspend = imx_ahci_suspend, - .resume = imx_ahci_resume, +static struct ahci_platform_data imx_sata_pdata = { + .init = imx_sata_init, + .exit = imx_sata_exit, + .ata_port_info = &ahci_imx_port_info, + .suspend = imx_ahci_suspend, + .resume = imx_ahci_resume, + }; static const struct of_device_id imx_ahci_of_match[] = { - { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata}, + { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, + { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, {}, }; MODULE_DEVICE_TABLE(of, imx_ahci_of_match); @@ -201,12 +253,20 @@ static int imx_ahci_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *mem, *irq, res[2]; const struct of_device_id *of_id; + enum ahci_imx_type type; const struct ahci_platform_data *pdata = NULL; struct imx_ahci_priv *imxpriv; struct device *ahci_dev; struct platform_device *ahci_pdev; int ret; + of_id = of_match_device(imx_ahci_of_match, dev); + if (!of_id) + return -EINVAL; + + type = (enum ahci_imx_type)of_id->data; + pdata = &imx_sata_pdata; + imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); if (!imxpriv) { dev_err(dev, "can't alloc ahci_host_priv\n"); @@ -222,6 +282,8 @@ static int imx_ahci_probe(struct platform_device *pdev) imxpriv->no_device = false; imxpriv->first_time = true; + imxpriv->type = type; + imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); if (IS_ERR(imxpriv->ahb_clk)) { dev_err(dev, "can't get ahb clock.\n"); @@ -229,6 +291,15 @@ static int imx_ahci_probe(struct platform_device *pdev) goto err_out; } + if (type == AHCI_IMX53) { + imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate"); + if (IS_ERR(imxpriv->sata_gate_clk)) { + dev_err(dev, "can't get sata_gate clock.\n"); + ret = PTR_ERR(imxpriv->sata_gate_clk); + goto err_out; + } + } + imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); if (IS_ERR(imxpriv->sata_ref_clk)) { dev_err(dev, "can't get sata_ref clock.\n"); @@ -239,14 +310,6 @@ static int imx_ahci_probe(struct platform_device *pdev) imxpriv->ahci_pdev = ahci_pdev; platform_set_drvdata(pdev, imxpriv); - of_id = of_match_device(imx_ahci_of_match, dev); - if (of_id) { - pdata = of_id->data; - } else { - ret = -EINVAL; - goto err_out; - } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!mem || !irq) { @@ -262,41 +325,42 @@ static int imx_ahci_probe(struct platform_device *pdev) ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; ahci_dev->of_node = dev->of_node; - imxpriv->gpr = - syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); - - if (IS_ERR(imxpriv->gpr)) { - dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); - ret = PTR_ERR(imxpriv->gpr); - goto err_out; + if (type == AHCI_IMX6Q) { + imxpriv->gpr = syscon_regmap_lookup_by_compatible( + "fsl,imx6q-iomuxc-gpr"); + if (IS_ERR(imxpriv->gpr)) { + dev_err(dev, + "failed to find fsl,imx6q-iomux-gpr regmap\n"); + return PTR_ERR(imxpriv->gpr); + } + + /* + * Set PHY Paremeters, two steps to configure the GPR13, + * one write for rest of parameters, mask of first write + * is 0x07fffffe, and the other one write for setting + * the mpll_clk_en happens in imx_sata_clock_enable(). + */ + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | + IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | + IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | + IMX6Q_GPR13_SATA_SPD_MODE_MASK | + IMX6Q_GPR13_SATA_MPLL_SS_EN | + IMX6Q_GPR13_SATA_TX_ATTEN_MASK | + IMX6Q_GPR13_SATA_TX_BOOST_MASK | + IMX6Q_GPR13_SATA_TX_LVL_MASK | + IMX6Q_GPR13_SATA_MPLL_CLK_EN | + IMX6Q_GPR13_SATA_TX_EDGE_RATE, + IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | + IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | + IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | + IMX6Q_GPR13_SATA_SPD_MODE_3P0G | + IMX6Q_GPR13_SATA_MPLL_SS_EN | + IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | + IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | + IMX6Q_GPR13_SATA_TX_LVL_1_025_V); } - /* - * Set PHY Paremeters, two steps to configure the GPR13, - * one write for rest of parameters, mask of first write - * is 0x07ffffff, and the other one write for setting - * the mpll_clk_en happens in imx_sata_clock_enable(). - */ - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | - IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | - IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | - IMX6Q_GPR13_SATA_SPD_MODE_MASK | - IMX6Q_GPR13_SATA_MPLL_SS_EN | - IMX6Q_GPR13_SATA_TX_ATTEN_MASK | - IMX6Q_GPR13_SATA_TX_BOOST_MASK | - IMX6Q_GPR13_SATA_TX_LVL_MASK | - IMX6Q_GPR13_SATA_MPLL_CLK_EN | - IMX6Q_GPR13_SATA_TX_EDGE_RATE, - IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | - IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | - IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | - IMX6Q_GPR13_SATA_SPD_MODE_3P0G | - IMX6Q_GPR13_SATA_MPLL_SS_EN | - IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | - IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | - IMX6Q_GPR13_SATA_TX_LVL_1_025_V); - ret = platform_device_add_resources(ahci_pdev, res, 2); if (ret) goto err_out; -- cgit v1.2.3 From 68fd02d15bed4a680c23f0aaeee9bc871bf1630c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 21 Oct 2013 16:56:36 -0300 Subject: [media] rtl2830: add parent for I2C adapter i2c i2c-6: adapter [RTL2830 tuner I2C adapter] registered BUG: unable to handle kernel NULL pointer dereference at 0000000000000220 IP: [] i2c_register_adapter+0x130/0x390 [i2c_core] Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 7efb796c472c..50e8b63e5169 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -710,6 +710,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, sizeof(priv->tuner_i2c_adapter.name)); priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; priv->tuner_i2c_adapter.algo_data = NULL; + priv->tuner_i2c_adapter.dev.parent = &i2c->dev; i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { dev_err(&i2c->dev, -- cgit v1.2.3 From dcdc50e72b8b8c21aca598705192dcbf96f4fb64 Mon Sep 17 00:00:00 2001 From: Olivier Gay Date: Tue, 3 Dec 2013 00:17:24 +0100 Subject: HID: logitech-dj: add HIDRAW dependency in Kconfig hid-logitech-dj.c driver needs hidraw to work correctly. Without hidraw, hid-logitech-dj.c fails during probe() and Logitech Unifying devices HID reports aren't recognized. The unifying receiver has 3 usb interfaces. When hid-logitech-dj driver is loaded, interfaces 0 and 1 are discarded. Interface 2 consists of a hid class interface with 3 collections, each of which sports the 'vendor' usage, thus, there is no reason for hid_input to claim any of them. On the other hand, hidraw has no issue in claiming the collections, even if they are 'vendor'. As of today, hid-logitech-dj uses hidraw api to send configuration/control reports to interface 2 of the Unifying receiver. Without the hid-logitech-dj driver, interfaces 0 and 1 are claimed by hid-input, as they correspond to a keyboard and a mouse. But that is not relevant to the discussion. [jkosina@suse.cz: make the changelog more verbose, thanks to Nestor] Signed-off-by: Olivier Gay Signed-off-by: Nestor Lopez Casado Signed-off-by: Mathieu Meisser Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 329fbb9b5976..c8a66b94b6dd 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -344,6 +344,7 @@ config HID_LOGITECH config HID_LOGITECH_DJ tristate "Logitech Unifying receivers full support" + depends on HIDRAW depends on HID_LOGITECH ---help--- Say Y if you want support for Logitech Unifying receivers and devices. -- cgit v1.2.3 From 34c040ce1a9d9c13121c95101164383ce516ddd6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 3 Dec 2013 15:08:22 +0100 Subject: regulator: ab8500: delete non-devicetree probe path The Ux500 platform has been converted to do device-tree only boots, no longer supports platform data passing, so this probe path is unused. Delete it, simplifying the driver a whole lot. Signed-off-by: Linus Walleij Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 102 ++++----------------------------------------- 1 file changed, 8 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 603f192e84f1..0f86695b737a 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -2998,37 +2998,6 @@ static void abx500_get_regulator_info(struct ab8500 *ab8500) } } -static int ab8500_regulator_init_registers(struct platform_device *pdev, - int id, int mask, int value) -{ - struct ab8500_reg_init *reg_init = abx500_regulator.init; - int err; - - BUG_ON(value & ~mask); - BUG_ON(mask & ~reg_init[id].mask); - - /* initialize register */ - err = abx500_mask_and_set_register_interruptible( - &pdev->dev, - reg_init[id].bank, - reg_init[id].addr, - mask, value); - if (err < 0) { - dev_err(&pdev->dev, - "Failed to initialize 0x%02x, 0x%02x.\n", - reg_init[id].bank, - reg_init[id].addr); - return err; - } - dev_vdbg(&pdev->dev, - " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - reg_init[id].bank, - reg_init[id].addr, - mask, value); - - return 0; -} - static int ab8500_regulator_register(struct platform_device *pdev, struct regulator_init_data *init_data, int id, struct device_node *np) @@ -3095,9 +3064,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct device_node *np = pdev->dev.of_node; - struct ab8500_platform_data *ppdata; - struct ab8500_regulator_platform_data *pdata; - int i, err; + int err; if (!ab8500) { dev_err(&pdev->dev, "null mfd parent\n"); @@ -3106,68 +3073,15 @@ static int ab8500_regulator_probe(struct platform_device *pdev) abx500_get_regulator_info(ab8500); - if (np) { - err = of_regulator_match(&pdev->dev, np, - abx500_regulator.match, - abx500_regulator.match_size); - if (err < 0) { - dev_err(&pdev->dev, - "Error parsing regulator init data: %d\n", err); - return err; - } - - err = ab8500_regulator_of_probe(pdev, np); - return err; - } - - ppdata = dev_get_platdata(ab8500->dev); - if (!ppdata) { - dev_err(&pdev->dev, "null parent pdata\n"); - return -EINVAL; - } - - pdata = ppdata->regulator; - if (!pdata) { - dev_err(&pdev->dev, "null pdata\n"); - return -EINVAL; - } - - /* make sure the platform data has the correct size */ - if (pdata->num_regulator != abx500_regulator.info_size) { - dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); - return -EINVAL; - } - - /* initialize debug (initial state is recorded with this call) */ - err = ab8500_regulator_debug_init(pdev); - if (err) + err = of_regulator_match(&pdev->dev, np, + abx500_regulator.match, + abx500_regulator.match_size); + if (err < 0) { + dev_err(&pdev->dev, + "Error parsing regulator init data: %d\n", err); return err; - - /* initialize registers */ - for (i = 0; i < pdata->num_reg_init; i++) { - int id, mask, value; - - id = pdata->reg_init[i].id; - mask = pdata->reg_init[i].mask; - value = pdata->reg_init[i].value; - - /* check for configuration errors */ - BUG_ON(id >= abx500_regulator.init_size); - - err = ab8500_regulator_init_registers(pdev, id, mask, value); - if (err < 0) - return err; - } - - /* register all regulators */ - for (i = 0; i < abx500_regulator.info_size; i++) { - err = ab8500_regulator_register(pdev, &pdata->regulator[i], - i, NULL); - if (err < 0) - return err; } - - return 0; + return ab8500_regulator_of_probe(pdev, np); } static int ab8500_regulator_remove(struct platform_device *pdev) -- cgit v1.2.3 From ee4e5a9abf470908bb04feadec236c51e19fc413 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 3 Dec 2013 10:25:37 -0500 Subject: ahci: imx: ahci_imx_softreset() can be static Acked-by: Marek Vasut Signed-off-by: Fengguang Wu Signed-off-by: Tejun Heo --- drivers/ata/ahci_imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 8cb89655cf06..2daa28891b7f 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -140,7 +140,7 @@ static void ahci_imx_error_handler(struct ata_port *ap) imxpriv->no_device = true; } -int ahci_imx_softreset(struct ata_link *link, unsigned int *class, +static int ahci_imx_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { struct ata_port *ap = link->ap; -- cgit v1.2.3 From fff04e00f53645c6a1233591cc2d9f3abf7dfac4 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Mon, 25 Nov 2013 13:42:43 -0800 Subject: staging: dwc2: remove stale comment after changing function to void Remove stale comment after changing dwc2_set_parameters() to void function Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index c0b122a67996..f2708f95cea3 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -2687,7 +2687,7 @@ void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) /* * This function is called during module intialization to pass module parameters - * for the DWC_otg core. It returns non-0 if any parameters are invalid. + * for the DWC_otg core. */ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, const struct dwc2_core_params *params) -- cgit v1.2.3 From 54216acee5a408411ca23e727a5315ace5acf0c4 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Mon, 25 Nov 2013 13:42:44 -0800 Subject: staging: dwc2: fix screwup in checking return value Fix screwup in checking return value from dwc2_is_controller_alive() Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_intr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index e672e6db2943..50e6de54f0f0 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -2059,7 +2059,7 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg) u32 gintsts, dbg_gintsts; irqreturn_t retval = IRQ_NONE; - if (!dwc2_is_controller_alive(hsotg) < 0) { + if (!dwc2_is_controller_alive(hsotg)) { dev_warn(hsotg->dev, "Controller is dead\n"); return retval; } -- cgit v1.2.3 From 0b851be2737fa7533facfbf3be46678d180fee80 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Mon, 25 Nov 2013 13:42:45 -0800 Subject: staging: dwc2: fix thinko in dwc2_fill_host_dma_desc() The check against MAX_DMA_DESC_SIZE didn't make sense, fix it Reported-by: Dan Carpenter Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_ddma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c index 72e9788c1a13..3376177e4d3c 100644 --- a/drivers/staging/dwc2/hcd_ddma.c +++ b/drivers/staging/dwc2/hcd_ddma.c @@ -621,8 +621,8 @@ static void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_hcd_dma_desc *dma_desc = &qh->desc_list[n_desc]; int len = chan->xfer_len; - if (len > MAX_DMA_DESC_SIZE) - len = MAX_DMA_DESC_SIZE - chan->max_packet + 1; + if (len > MAX_DMA_DESC_SIZE - (chan->max_packet - 1)) + len = MAX_DMA_DESC_SIZE - (chan->max_packet - 1); if (chan->ep_is_in) { int num_packets; -- cgit v1.2.3 From e7e59e11700c04d822a309917c1b7520bb8578c3 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Mon, 25 Nov 2013 13:42:46 -0800 Subject: staging: dwc2: fix useless test for non-0 In dwc2_xfercomp_isoc_split_in(), the function has already exited if len == 0, so no need to test it again Reported-by: Dan Carpenter Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_intr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index 50e6de54f0f0..012f17ec1a37 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -935,7 +935,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, frame_desc->actual_length += len; - if (chan->align_buf && len) { + if (chan->align_buf) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, qtd->urb->dma, qtd->urb->length, DMA_FROM_DEVICE); -- cgit v1.2.3 From e8576e68d193c40fa6e4fae7c5d166d48ff78895 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Mon, 25 Nov 2013 13:42:47 -0800 Subject: staging: dwc2: move function to more logical place The function dwc2_get_hwparams() was in an awkward place, mixed in with the dwc2_set_param* functions. Move it down after those functions. Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 124 ++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index f2708f95cea3..8a71726a3566 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -2510,6 +2510,68 @@ void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) hsotg->core_params->otg_ver = val; } +void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) +{ + if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { + if (val >= 0) { + dev_err(hsotg->dev, + "'%d' invalid for parameter uframe_sched\n", + val); + dev_err(hsotg->dev, "uframe_sched must be 0 or 1\n"); + } + val = 1; + dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val); + } + + hsotg->core_params->uframe_sched = val; +} + +/* + * This function is called during module intialization to pass module parameters + * for the DWC_otg core. + */ +void dwc2_set_parameters(struct dwc2_hsotg *hsotg, + const struct dwc2_core_params *params) +{ + dev_dbg(hsotg->dev, "%s()\n", __func__); + + dwc2_set_param_otg_cap(hsotg, params->otg_cap); + dwc2_set_param_dma_enable(hsotg, params->dma_enable); + dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable); + dwc2_set_param_host_support_fs_ls_low_power(hsotg, + params->host_support_fs_ls_low_power); + dwc2_set_param_enable_dynamic_fifo(hsotg, + params->enable_dynamic_fifo); + dwc2_set_param_host_rx_fifo_size(hsotg, + params->host_rx_fifo_size); + dwc2_set_param_host_nperio_tx_fifo_size(hsotg, + params->host_nperio_tx_fifo_size); + dwc2_set_param_host_perio_tx_fifo_size(hsotg, + params->host_perio_tx_fifo_size); + dwc2_set_param_max_transfer_size(hsotg, + params->max_transfer_size); + dwc2_set_param_max_packet_count(hsotg, + params->max_packet_count); + dwc2_set_param_host_channels(hsotg, params->host_channels); + dwc2_set_param_phy_type(hsotg, params->phy_type); + dwc2_set_param_speed(hsotg, params->speed); + dwc2_set_param_host_ls_low_power_phy_clk(hsotg, + params->host_ls_low_power_phy_clk); + dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr); + dwc2_set_param_phy_ulpi_ext_vbus(hsotg, + params->phy_ulpi_ext_vbus); + dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width); + dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls); + dwc2_set_param_ts_dline(hsotg, params->ts_dline); + dwc2_set_param_i2c_enable(hsotg, params->i2c_enable); + dwc2_set_param_en_multiple_tx_fifo(hsotg, + params->en_multiple_tx_fifo); + dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); + dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); + dwc2_set_param_otg_ver(hsotg, params->otg_ver); + dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); +} + /** * During device initialization, read various hardware configuration * registers and interpret the contents. @@ -2669,68 +2731,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) return 0; } -void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter uframe_sched\n", - val); - dev_err(hsotg->dev, "uframe_sched must be 0 or 1\n"); - } - val = 1; - dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val); - } - - hsotg->core_params->uframe_sched = val; -} - -/* - * This function is called during module intialization to pass module parameters - * for the DWC_otg core. - */ -void dwc2_set_parameters(struct dwc2_hsotg *hsotg, - const struct dwc2_core_params *params) -{ - dev_dbg(hsotg->dev, "%s()\n", __func__); - - dwc2_set_param_otg_cap(hsotg, params->otg_cap); - dwc2_set_param_dma_enable(hsotg, params->dma_enable); - dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable); - dwc2_set_param_host_support_fs_ls_low_power(hsotg, - params->host_support_fs_ls_low_power); - dwc2_set_param_enable_dynamic_fifo(hsotg, - params->enable_dynamic_fifo); - dwc2_set_param_host_rx_fifo_size(hsotg, - params->host_rx_fifo_size); - dwc2_set_param_host_nperio_tx_fifo_size(hsotg, - params->host_nperio_tx_fifo_size); - dwc2_set_param_host_perio_tx_fifo_size(hsotg, - params->host_perio_tx_fifo_size); - dwc2_set_param_max_transfer_size(hsotg, - params->max_transfer_size); - dwc2_set_param_max_packet_count(hsotg, - params->max_packet_count); - dwc2_set_param_host_channels(hsotg, params->host_channels); - dwc2_set_param_phy_type(hsotg, params->phy_type); - dwc2_set_param_speed(hsotg, params->speed); - dwc2_set_param_host_ls_low_power_phy_clk(hsotg, - params->host_ls_low_power_phy_clk); - dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr); - dwc2_set_param_phy_ulpi_ext_vbus(hsotg, - params->phy_ulpi_ext_vbus); - dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width); - dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls); - dwc2_set_param_ts_dline(hsotg, params->ts_dline); - dwc2_set_param_i2c_enable(hsotg, params->i2c_enable); - dwc2_set_param_en_multiple_tx_fifo(hsotg, - params->en_multiple_tx_fifo); - dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); - dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); - dwc2_set_param_otg_ver(hsotg, params->otg_ver); - dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); -} - u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) { return hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103; -- cgit v1.2.3 From 646959059c56374896010fb245bec5338cbac44d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 18 Oct 2013 00:07:11 -0300 Subject: [media] mt9p031: Include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly to avoid build breakage in the future. Signed-off-by: Sachin Kamat Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9p031.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 4734836fe5a4..1c2303d18bf4 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From e8c794df021e3299ff315a0536cf65331b9117ea Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 26 Nov 2013 23:55:13 +0900 Subject: staging: sb105x: Fix typo in sb105x Correct spelling typo in staging/sb105x. Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sb105x/sb_mp_register.h | 8 ++++---- drivers/staging/sb105x/sb_pci_mp.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h index 16de497415ee..276c1bbcc18d 100644 --- a/drivers/staging/sb105x/sb_mp_register.h +++ b/drivers/staging/sb105x/sb_mp_register.h @@ -116,10 +116,10 @@ #define SB105X_FCR_TXFR 0x04 /* TX FIFO Reset */ #define SB105X_FCR_DMS 0x08 /* DMA Mode Select */ -#define SB105X_FCR_RTR08 0x00 /* Receice Trigger Level set at 8 */ -#define SB105X_FCR_RTR16 0x40 /* Receice Trigger Level set at 16 */ -#define SB105X_FCR_RTR56 0x80 /* Receice Trigger Level set at 56 */ -#define SB105X_FCR_RTR60 0xc0 /* Receice Trigger Level set at 60 */ +#define SB105X_FCR_RTR08 0x00 /* Receive Trigger Level set at 8 */ +#define SB105X_FCR_RTR16 0x40 /* Receive Trigger Level set at 16 */ +#define SB105X_FCR_RTR56 0x80 /* Receive Trigger Level set at 56 */ +#define SB105X_FCR_RTR60 0xc0 /* Receive Trigger Level set at 60 */ #define SB105X_FCR_TTR08 0x00 /* Transmit Trigger Level set at 8 */ #define SB105X_FCR_TTR16 0x10 /* Transmit Trigger Level set at 16 */ #define SB105X_FCR_TTR32 0x20 /* Transmit Trigger Level set at 32 */ diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c index 5cd3efff97d3..c9d6ee3903ad 100644 --- a/drivers/staging/sb105x/sb_pci_mp.c +++ b/drivers/staging/sb105x/sb_pci_mp.c @@ -182,7 +182,7 @@ static int sb1054_get_register(struct sb_uart_port *port, int page, int reg) if( page <= 0) { - printk(" page 0 can not use this fuction\n"); + printk(" page 0 can not use this function\n"); return -1; } @@ -243,7 +243,7 @@ static int sb1054_set_register(struct sb_uart_port *port, int page, int reg, int if( page <= 0) { - printk(" page 0 can not use this fuction\n"); + printk(" page 0 can not use this function\n"); return -1; } switch(page) -- cgit v1.2.3 From aceaf01891776585d94222f3d62b8e138e23d604 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 26 Nov 2013 19:06:35 +0000 Subject: staging: vt6656: remove void pointer from s_vGetFreeContext Replace with struct vnt_usb_send_context. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index cc2302900989..0e4b6fb2ec96 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -96,7 +96,8 @@ static const u16 wFB_Opt1[2][5] = { static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl); -static void *s_vGetFreeContext(struct vnt_private *pDevice); +static struct vnt_usb_send_context + *s_vGetFreeContext(struct vnt_private *pDevice); static u16 s_vGenerateTxParameter(struct vnt_private *pDevice, u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer, @@ -136,7 +137,8 @@ static u16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType, u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck, u8 byFBOption); -static void *s_vGetFreeContext(struct vnt_private *pDevice) +static struct vnt_usb_send_context + *s_vGetFreeContext(struct vnt_private *pDevice) { struct vnt_usb_send_context *pContext = NULL; struct vnt_usb_send_context *pReturnContext = NULL; @@ -158,7 +160,8 @@ static void *s_vGetFreeContext(struct vnt_private *pDevice) if ( ii == pDevice->cbTD ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); } - return (void *) pReturnContext; + + return pReturnContext; } static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, @@ -1377,7 +1380,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice, u32 cbMacHdLen; u16 wCurrentRate = RATE_1M; - pContext = (struct vnt_usb_send_context *)s_vGetFreeContext(pDevice); + pContext = s_vGetFreeContext(pDevice); if (NULL == pContext) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n"); @@ -1635,7 +1638,7 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, struct vnt_usb_send_context *pContext; CMD_STATUS status; - pContext = (struct vnt_usb_send_context *)s_vGetFreeContext(pDevice); + pContext = s_vGetFreeContext(pDevice); if (NULL == pContext) { status = CMD_STATUS_RESOURCES; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n"); @@ -1745,7 +1748,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb) } p80211Header = (PUWLAN_80211HDR)skb->data; - pContext = (struct vnt_usb_send_context *)s_vGetFreeContext(pDevice); + pContext = s_vGetFreeContext(pDevice); if (NULL == pContext) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0 TX...NO CONTEXT!\n"); @@ -2166,7 +2169,7 @@ int nsDMA_tx_packet(struct vnt_private *pDevice, } } - pContext = (struct vnt_usb_send_context *)s_vGetFreeContext(pDevice); + pContext = s_vGetFreeContext(pDevice); if (pContext == NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG" pContext == NULL\n"); @@ -2491,7 +2494,7 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen, u32 status; u16 wKeepRate = pDevice->wCurrentRate; - pContext = (struct vnt_usb_send_context *)s_vGetFreeContext(pDevice); + pContext = s_vGetFreeContext(pDevice); if (NULL == pContext) { return false; -- cgit v1.2.3 From 5c851383b5e5d43e2d24b9c22cdbbda9632dfa64 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 26 Nov 2013 19:12:38 +0000 Subject: staging: vt6656: s_vGetFreeContext remove pReturnContext Just return the context from for loop. Return NULL if end reached. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 0e4b6fb2ec96..6534f753296a 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -141,7 +141,6 @@ static struct vnt_usb_send_context *s_vGetFreeContext(struct vnt_private *pDevice) { struct vnt_usb_send_context *pContext = NULL; - struct vnt_usb_send_context *pReturnContext = NULL; int ii; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n"); @@ -153,15 +152,14 @@ static struct vnt_usb_send_context if (pContext->bBoolInUse == false) { pContext->bBoolInUse = true; memset(pContext->Data, 0, MAX_TOTAL_SIZE_WITH_ALL_HEADERS); - pReturnContext = pContext; - break; + return pContext; } } if ( ii == pDevice->cbTD ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); } - return pReturnContext; + return NULL; } static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, -- cgit v1.2.3 From b89f3b9460417758d5189caddab8a052d2dd19f4 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 26 Nov 2013 19:16:59 +0000 Subject: staging: vt6656: clean up s_vGetFreeContext Camel case clean up pDevice -> priv pContext -> context Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 6534f753296a..2db03d6d4c20 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -96,8 +96,7 @@ static const u16 wFB_Opt1[2][5] = { static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl); -static struct vnt_usb_send_context - *s_vGetFreeContext(struct vnt_private *pDevice); +static struct vnt_usb_send_context *s_vGetFreeContext(struct vnt_private *); static u16 s_vGenerateTxParameter(struct vnt_private *pDevice, u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer, @@ -138,26 +137,28 @@ static u16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, int bNeedAck, u8 byFBOption); static struct vnt_usb_send_context - *s_vGetFreeContext(struct vnt_private *pDevice) + *s_vGetFreeContext(struct vnt_private *priv) { - struct vnt_usb_send_context *pContext = NULL; + struct vnt_usb_send_context *context = NULL; int ii; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n"); - for (ii = 0; ii < pDevice->cbTD; ii++) { - if (!pDevice->apTD[ii]) - return NULL; - pContext = pDevice->apTD[ii]; - if (pContext->bBoolInUse == false) { - pContext->bBoolInUse = true; - memset(pContext->Data, 0, MAX_TOTAL_SIZE_WITH_ALL_HEADERS); - return pContext; - } - } - if ( ii == pDevice->cbTD ) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); - } + for (ii = 0; ii < priv->cbTD; ii++) { + if (!priv->apTD[ii]) + return NULL; + + context = priv->apTD[ii]; + if (context->bBoolInUse == false) { + context->bBoolInUse = true; + memset(context->Data, 0, + MAX_TOTAL_SIZE_WITH_ALL_HEADERS); + return context; + } + } + + if (ii == priv->cbTD) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); return NULL; } -- cgit v1.2.3 From 04eb2b7f3ff19685531945a484e78ab7b9376ccc Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:11:38 +0800 Subject: staging/lustre: fix build error when CONFIG_FS_POSIX_ACL is off We need to include regardless of CONFIG_FS_POSIX_ACL is set or not. Otherwise build fails as reported by kbuild robot: >> drivers/staging/lustre/lustre/llite/file.c:2965:2: error: implicit declaration of function 'posix_acl_dup' [-Werror=implicit-function-declaration] acl = posix_acl_dup(lli->lli_posix_acl); Reported-by: Fengguang Wu Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/linux/lustre_acl.h | 18 +++++++++--------- drivers/staging/lustre/lustre/include/lustre_mdc.h | 9 +++------ drivers/staging/lustre/lustre/llite/llite_internal.h | 1 + drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 6 ++---- 4 files changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_acl.h b/drivers/staging/lustre/lustre/include/linux/lustre_acl.h index ff4fc4ff2894..778b123ce31e 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_acl.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_acl.h @@ -47,17 +47,17 @@ #error Shoud not include direectly. use #include instead #endif -# include -# include -# ifdef CONFIG_FS_POSIX_ACL -# include -# define LUSTRE_POSIX_ACL_MAX_ENTRIES 32 -# define LUSTRE_POSIX_ACL_MAX_SIZE \ +#include +#include + +#include +#define LUSTRE_POSIX_ACL_MAX_ENTRIES 32 +#define LUSTRE_POSIX_ACL_MAX_SIZE \ (sizeof(posix_acl_xattr_header) + \ LUSTRE_POSIX_ACL_MAX_ENTRIES * sizeof(posix_acl_xattr_entry)) -# endif /* CONFIG_FS_POSIX_ACL */ -# include -# include /* XATTR_{REPLACE,CREATE} */ + +#include +#include /* XATTR_{REPLACE,CREATE} */ #ifndef LUSTRE_POSIX_ACL_MAX_SIZE # define LUSTRE_POSIX_ACL_MAX_SIZE 0 diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index 19000259a5e4..c1e02702b931 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -48,12 +48,9 @@ * @{ */ -# include -# include -# ifdef CONFIG_FS_POSIX_ACL -# include -# endif /* CONFIG_FS_POSIX_ACL */ -# include +#include +#include +#include #include #include #include diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index c326ff24410c..6d15e5c100fc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -47,6 +47,7 @@ #include #include #include +#include #ifndef FMODE_EXEC #define FMODE_EXEC 0 diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index e3f02c77f3b9..6cc0d6e61f12 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -36,10 +36,8 @@ #define DEBUG_SUBSYSTEM S_RPC -# ifdef CONFIG_FS_POSIX_ACL -# include -# include -# endif +#include +#include #include #include -- cgit v1.2.3 From 1183ddb6ec87e54e38573ca0e1d16fe3e0794564 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:11:39 +0800 Subject: staging/lustre: remove wirehdr.c It is not used. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/wirehdr.c | 47 -------------------------- 1 file changed, 47 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/ptlrpc/wirehdr.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/wirehdr.c b/drivers/staging/lustre/lustre/ptlrpc/wirehdr.c deleted file mode 100644 index 93bc40b422ee..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/wirehdr.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#define DEBUG_SUBSYSTEM S_RPC - -# ifdef CONFIG_FS_POSIX_ACL -# include -# include -# endif - -#include -#include -#include -#include -- cgit v1.2.3 From 8cc93bc357cae8ace3e223bd584c382bee61a053 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 21:58:39 +0800 Subject: Revert "staging/lustre/nfs: writing to new files will return ENOENT" This reverts commit ad8dbc93a464869f64365a2123b3491965df3b3e. The original commit was reverted in Lustre tree this due to interoperability problems with 2.1 servers. But I forgot to remove it from my patch queue. sorry for the noise. Cc: Patrick Farrell Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index f36c5d8dbae0..82248e9f6bff 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -368,6 +368,8 @@ static int ll_intent_file_open(struct file *file, void *lmm, { struct ll_sb_info *sbi = ll_i2sbi(file->f_dentry->d_inode); struct dentry *parent = file->f_dentry->d_parent; + const char *name = file->f_dentry->d_name.name; + const int len = file->f_dentry->d_name.len; struct md_op_data *op_data; struct ptlrpc_request *req; __u32 opc = LUSTRE_OPC_ANY; @@ -392,9 +394,8 @@ static int ll_intent_file_open(struct file *file, void *lmm, } op_data = ll_prep_md_op_data(NULL, parent->d_inode, - file->f_dentry->d_inode, NULL, 0, + file->f_dentry->d_inode, name, len, O_RDWR, opc, NULL); - if (IS_ERR(op_data)) return PTR_ERR(op_data); -- cgit v1.2.3 From aa4e3c8abc5c7b74d446d07cc99ca240c23a9723 Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Tue, 3 Dec 2013 21:58:40 +0800 Subject: staging/lustre/llog: MGC to use OSD API for backup logs MGC uses lvfs API to access local llogs blocking removal of old code - llog_is_empty() and llog_backup() are introduced Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2059 Lustre-change: http://review.whamcloud.com/5049 Cc: Levente Kurusa Signed-off-by: Mikhail Pershin Reviewed-by: Lai Siyao Reviewed-by: Alex Zhuravlev Reviewed-by: James Simmons Reviewed-by: Oleg Drokin [pick client side change only -- Peng Tao] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/dt_object.h | 2 +- drivers/staging/lustre/lustre/include/lustre_log.h | 13 +- drivers/staging/lustre/lustre/include/obd.h | 4 +- drivers/staging/lustre/lustre/mgc/libmgc.c | 3 - drivers/staging/lustre/lustre/mgc/mgc_request.c | 394 +++++++++++++-------- drivers/staging/lustre/lustre/obdclass/llog.c | 212 +++++++---- .../staging/lustre/lustre/obdclass/local_storage.c | 9 +- .../staging/lustre/lustre/obdclass/local_storage.h | 3 + drivers/staging/lustre/lustre/obdclass/lu_object.c | 2 +- drivers/staging/lustre/lustre/obdclass/obd_mount.c | 3 + 10 files changed, 407 insertions(+), 238 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/dt_object.h b/drivers/staging/lustre/lustre/include/dt_object.h index e116bb21b529..9304c269afa9 100644 --- a/drivers/staging/lustre/lustre/include/dt_object.h +++ b/drivers/staging/lustre/lustre/include/dt_object.h @@ -692,7 +692,7 @@ struct local_oid_storage { struct dt_object *los_obj; /* data used to generate new fids */ - struct mutex los_id_lock; + struct mutex los_id_lock; __u64 los_seq; __u32 los_last_oid; }; diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h index 721aa05dff3b..896c7576aa0f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_log.h +++ b/drivers/staging/lustre/lustre/include/lustre_log.h @@ -136,7 +136,11 @@ int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle **lgh, struct llog_logid *logid, char *name, enum llog_open_param open_param); int llog_close(const struct lu_env *env, struct llog_handle *cathandle); -int llog_get_size(struct llog_handle *loghandle); +int llog_is_empty(const struct lu_env *env, struct llog_ctxt *ctxt, + char *name); +int llog_backup(const struct lu_env *env, struct obd_device *obd, + struct llog_ctxt *ctxt, struct llog_ctxt *bak_ctxt, + char *name, char *backup); /* llog_process flags */ #define LLOG_FLAG_NODEAMON 0x0001 @@ -382,6 +386,13 @@ static inline int llog_data_len(int len) return cfs_size_round(len); } +static inline int llog_get_size(struct llog_handle *loghandle) +{ + if (loghandle && loghandle->lgh_hdr) + return loghandle->lgh_hdr->llh_count; + return 0; +} + static inline struct llog_ctxt *llog_ctxt_get(struct llog_ctxt *ctxt) { atomic_inc(&ctxt->loc_refcount); diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index d0aea15b7c39..f0c17736c334 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -399,8 +399,8 @@ struct client_obd { /* mgc datastruct */ struct semaphore cl_mgc_sem; - struct vfsmount *cl_mgc_vfsmnt; - struct dentry *cl_mgc_configs_dir; + struct local_oid_storage *cl_mgc_los; + struct dt_object *cl_mgc_configs_dir; atomic_t cl_mgc_refcount; struct obd_export *cl_mgc_mgsexp; diff --git a/drivers/staging/lustre/lustre/mgc/libmgc.c b/drivers/staging/lustre/lustre/mgc/libmgc.c index 7b4947cec3a8..9b40c57d3cd4 100644 --- a/drivers/staging/lustre/lustre/mgc/libmgc.c +++ b/drivers/staging/lustre/lustre/mgc/libmgc.c @@ -99,11 +99,8 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) static int mgc_cleanup(struct obd_device *obd) { - struct client_obd *cli = &obd->u.cli; int rc; - LASSERT(cli->cl_mgc_vfsmnt == NULL); - ptlrpcd_decref(); rc = client_obd_cleanup(obd); diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 93b601d1ff38..f6e4bacc3a15 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -41,17 +41,14 @@ #define DEBUG_SUBSYSTEM S_MGC #define D_MGC D_CONFIG /*|D_WARNING*/ -# include -# include -# include -# include - +#include #include #include #include #include -#include #include +#include + #include "mgc_internal.h" static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id, @@ -578,97 +575,175 @@ static void mgc_requeue_add(struct config_llog_data *cld) } /********************** class fns **********************/ +static int mgc_local_llog_init(const struct lu_env *env, + struct obd_device *obd, + struct obd_device *disk) +{ + struct llog_ctxt *ctxt; + int rc; + + rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CONFIG_ORIG_CTXT, disk, + &llog_osd_ops); + if (rc) + return rc; + + ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); + LASSERT(ctxt); + ctxt->loc_dir = obd->u.cli.cl_mgc_configs_dir; + llog_ctxt_put(ctxt); -static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, - struct vfsmount *mnt) + return 0; +} + +static int mgc_local_llog_fini(const struct lu_env *env, + struct obd_device *obd) { - struct lvfs_run_ctxt saved; - struct lustre_sb_info *lsi = s2lsi(sb); - struct client_obd *cli = &obd->u.cli; - struct dentry *dentry; - char *label; - int err = 0; + struct llog_ctxt *ctxt; + + ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); + llog_cleanup(env, ctxt); + + return 0; +} + +static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb) +{ + struct lustre_sb_info *lsi = s2lsi(sb); + struct client_obd *cli = &obd->u.cli; + struct lu_fid rfid, fid; + struct dt_object *root, *dto; + struct lu_env *env; + int rc = 0; LASSERT(lsi); - LASSERT(lsi->lsi_srv_mnt == mnt); + LASSERT(lsi->lsi_dt_dev); + + OBD_ALLOC_PTR(env); + if (env == NULL) + return -ENOMEM; /* The mgc fs exclusion sem. Only one fs can be setup at a time. */ down(&cli->cl_mgc_sem); cfs_cleanup_group_info(); - obd->obd_fsops = fsfilt_get_ops(lsi->lsi_fstype); - if (IS_ERR(obd->obd_fsops)) { - up(&cli->cl_mgc_sem); - CERROR("%s: No fstype %s: rc = %ld\n", lsi->lsi_fstype, - obd->obd_name, PTR_ERR(obd->obd_fsops)); - return PTR_ERR(obd->obd_fsops); - } + /* Setup the configs dir */ + rc = lu_env_init(env, LCT_MG_THREAD); + if (rc) + GOTO(out_err, rc); - cli->cl_mgc_vfsmnt = mnt; - err = fsfilt_setup(obd, mnt->mnt_sb); - if (err) - GOTO(err_ops, err); - - OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt); - obd->obd_lvfs_ctxt.pwdmnt = mnt; - obd->obd_lvfs_ctxt.pwd = mnt->mnt_root; - obd->obd_lvfs_ctxt.fs = get_ds(); - - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - dentry = ll_lookup_one_len(MOUNT_CONFIGS_DIR, cfs_fs_pwd(current->fs), - strlen(MOUNT_CONFIGS_DIR)); - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - if (IS_ERR(dentry)) { - err = PTR_ERR(dentry); - CERROR("cannot lookup %s directory: rc = %d\n", - MOUNT_CONFIGS_DIR, err); - GOTO(err_ops, err); - } - cli->cl_mgc_configs_dir = dentry; + fid.f_seq = FID_SEQ_LOCAL_NAME; + fid.f_oid = 1; + fid.f_ver = 0; + rc = local_oid_storage_init(env, lsi->lsi_dt_dev, &fid, + &cli->cl_mgc_los); + if (rc) + GOTO(out_env, rc); + + rc = dt_root_get(env, lsi->lsi_dt_dev, &rfid); + if (rc) + GOTO(out_env, rc); + + root = dt_locate_at(env, lsi->lsi_dt_dev, &rfid, + &cli->cl_mgc_los->los_dev->dd_lu_dev); + if (unlikely(IS_ERR(root))) + GOTO(out_los, rc = PTR_ERR(root)); + + dto = local_file_find_or_create(env, cli->cl_mgc_los, root, + MOUNT_CONFIGS_DIR, + S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); + lu_object_put_nocache(env, &root->do_lu); + if (IS_ERR(dto)) + GOTO(out_los, rc = PTR_ERR(dto)); + + cli->cl_mgc_configs_dir = dto; + + LASSERT(lsi->lsi_osd_exp->exp_obd->obd_lvfs_ctxt.dt); + rc = mgc_local_llog_init(env, obd, lsi->lsi_osd_exp->exp_obd); + if (rc) + GOTO(out_llog, rc); /* We take an obd ref to insure that we can't get to mgc_cleanup - without calling mgc_fs_cleanup first. */ + * without calling mgc_fs_cleanup first. */ class_incref(obd, "mgc_fs", obd); - label = fsfilt_get_label(obd, mnt->mnt_sb); - if (label) - CDEBUG(D_MGC, "MGC using disk labelled=%s\n", label); - /* We keep the cl_mgc_sem until mgc_fs_cleanup */ - return 0; - -err_ops: - fsfilt_put_ops(obd->obd_fsops); - obd->obd_fsops = NULL; - cli->cl_mgc_vfsmnt = NULL; - up(&cli->cl_mgc_sem); - return err; +out_llog: + if (rc) { + lu_object_put(env, &cli->cl_mgc_configs_dir->do_lu); + cli->cl_mgc_configs_dir = NULL; + } +out_los: + if (rc < 0) { + local_oid_storage_fini(env, cli->cl_mgc_los); + cli->cl_mgc_los = NULL; + up(&cli->cl_mgc_sem); + } +out_env: + lu_env_fini(env); +out_err: + OBD_FREE_PTR(env); + return rc; } static int mgc_fs_cleanup(struct obd_device *obd) { - struct client_obd *cli = &obd->u.cli; - int rc = 0; + struct lu_env env; + struct client_obd *cli = &obd->u.cli; + int rc; - LASSERT(cli->cl_mgc_vfsmnt != NULL); + LASSERT(cli->cl_mgc_los != NULL); - if (cli->cl_mgc_configs_dir != NULL) { - struct lvfs_run_ctxt saved; - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - l_dput(cli->cl_mgc_configs_dir); - cli->cl_mgc_configs_dir = NULL; - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - class_decref(obd, "mgc_fs", obd); - } + rc = lu_env_init(&env, LCT_MG_THREAD); + if (rc) + GOTO(unlock, rc); + + mgc_local_llog_fini(&env, obd); - cli->cl_mgc_vfsmnt = NULL; - if (obd->obd_fsops) - fsfilt_put_ops(obd->obd_fsops); + lu_object_put_nocache(&env, &cli->cl_mgc_configs_dir->do_lu); + cli->cl_mgc_configs_dir = NULL; + local_oid_storage_fini(&env, cli->cl_mgc_los); + cli->cl_mgc_los = NULL; + lu_env_fini(&env); + +unlock: + class_decref(obd, "mgc_fs", obd); up(&cli->cl_mgc_sem); - return rc; + return 0; +} + +static int mgc_llog_init(const struct lu_env *env, struct obd_device *obd) +{ + struct llog_ctxt *ctxt; + int rc; + + /* setup only remote ctxt, the local disk context is switched per each + * filesystem during mgc_fs_setup() */ + rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CONFIG_REPL_CTXT, obd, + &llog_client_ops); + if (rc) + return rc; + + ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); + LASSERT(ctxt); + + llog_initiator_connect(ctxt); + llog_ctxt_put(ctxt); + + return 0; +} + +static int mgc_llog_fini(const struct lu_env *env, struct obd_device *obd) +{ + struct llog_ctxt *ctxt; + + ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); + if (ctxt) + llog_cleanup(env, ctxt); + + return 0; } static atomic_t mgc_count = ATOMIC_INIT(0); @@ -694,7 +769,7 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) } } obd_cleanup_client_import(obd); - rc = obd_llog_finish(obd, 0); + rc = mgc_llog_fini(NULL, obd); if (rc != 0) CERROR("failed to cleanup llogging subsystems\n"); break; @@ -704,11 +779,8 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) static int mgc_cleanup(struct obd_device *obd) { - struct client_obd *cli = &obd->u.cli; int rc; - LASSERT(cli->cl_mgc_vfsmnt == NULL); - /* COMPAT_146 - old config logs may have added profiles we don't know about */ if (obd->obd_type->typ_refcnt <= 1) @@ -733,7 +805,7 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) if (rc) GOTO(err_decref, rc); - rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL); + rc = mgc_llog_init(NULL, obd); if (rc) { CERROR("failed to setup llogging subsystems\n"); GOTO(err_cleanup, rc); @@ -1011,11 +1083,11 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp, } if (KEY_IS(KEY_SET_FS)) { struct super_block *sb = (struct super_block *)val; - struct lustre_sb_info *lsi; + if (vallen != sizeof(struct super_block)) return -EINVAL; - lsi = s2lsi(sb); - rc = mgc_fs_setup(exp->exp_obd, sb, lsi->lsi_srv_mnt); + + rc = mgc_fs_setup(exp->exp_obd, sb); if (rc) { CERROR("set_fs got %d\n", rc); } @@ -1145,49 +1217,6 @@ static int mgc_import_event(struct obd_device *obd, return rc; } -static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg, - struct obd_device *tgt, int *index) -{ - struct llog_ctxt *ctxt; - int rc; - - LASSERT(olg == &obd->obd_olg); - - - rc = llog_setup(NULL, obd, olg, LLOG_CONFIG_REPL_CTXT, tgt, - &llog_client_ops); - if (rc) - GOTO(out, rc); - - ctxt = llog_group_get_ctxt(olg, LLOG_CONFIG_REPL_CTXT); - if (!ctxt) - GOTO(out, rc = -ENODEV); - - llog_initiator_connect(ctxt); - llog_ctxt_put(ctxt); - - return 0; -out: - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - if (ctxt) - llog_cleanup(NULL, ctxt); - return rc; -} - -static int mgc_llog_finish(struct obd_device *obd, int count) -{ - struct llog_ctxt *ctxt; - - ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); - if (ctxt) - llog_cleanup(NULL, ctxt); - - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - if (ctxt) - llog_cleanup(NULL, ctxt); - return 0; -} - enum { CONFIG_READ_NRPAGES_INIT = 1 << (20 - PAGE_CACHE_SHIFT), CONFIG_READ_NRPAGES = 4 @@ -1540,17 +1569,58 @@ out: return rc; } +static int mgc_llog_local_copy(const struct lu_env *env, + struct obd_device *obd, + struct llog_ctxt *rctxt, + struct llog_ctxt *lctxt, char *logname) +{ + char *temp_log; + int rc; + + + + /* + * - copy it to backup using llog_backup() + * - copy remote llog to logname using llog_backup() + * - if failed then move bakup to logname again + */ + + OBD_ALLOC(temp_log, strlen(logname) + 1); + if (!temp_log) + return -ENOMEM; + sprintf(temp_log, "%sT", logname); + + /* make a copy of local llog at first */ + rc = llog_backup(env, obd, lctxt, lctxt, logname, temp_log); + if (rc < 0 && rc != -ENOENT) + GOTO(out, rc); + /* copy remote llog to the local copy */ + rc = llog_backup(env, obd, rctxt, lctxt, logname, logname); + if (rc == -ENOENT) { + /* no remote llog, delete local one too */ + llog_erase(env, lctxt, NULL, logname); + } else if (rc < 0) { + /* error during backup, get local one back from the copy */ + llog_backup(env, obd, lctxt, lctxt, temp_log, logname); +out: + CERROR("%s: failed to copy remote log %s: rc = %d\n", + obd->obd_name, logname, rc); + } + llog_erase(env, lctxt, NULL, temp_log); + OBD_FREE(temp_log, strlen(logname) + 1); + return rc; +} /* local_only means it cannot get remote llogs */ static int mgc_process_cfg_log(struct obd_device *mgc, - struct config_llog_data *cld, - int local_only) + struct config_llog_data *cld, int local_only) { - struct llog_ctxt *ctxt, *lctxt = NULL; - struct lvfs_run_ctxt *saved_ctxt; - struct lustre_sb_info *lsi = NULL; - int rc = 0, must_pop = 0; - bool sptlrpc_started = false; + struct llog_ctxt *ctxt, *lctxt = NULL; + struct dt_object *cl_mgc_dir = mgc->u.cli.cl_mgc_configs_dir; + struct lustre_sb_info *lsi = NULL; + int rc = 0; + bool sptlrpc_started = false; + struct lu_env *env; LASSERT(cld); LASSERT(mutex_is_locked(&cld->cld_lock)); @@ -1565,20 +1635,48 @@ static int mgc_process_cfg_log(struct obd_device *mgc, if (cld->cld_cfg.cfg_sb) lsi = s2lsi(cld->cld_cfg.cfg_sb); - ctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT); - if (!ctxt) { - CERROR("missing llog context\n"); - return -EINVAL; - } - - OBD_ALLOC_PTR(saved_ctxt); - if (saved_ctxt == NULL) + OBD_ALLOC_PTR(env); + if (env == NULL) return -ENOMEM; + rc = lu_env_init(env, LCT_MG_THREAD); + if (rc) + GOTO(out_free, rc); + + ctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT); + LASSERT(ctxt); + lctxt = llog_get_context(mgc, LLOG_CONFIG_ORIG_CTXT); - if (local_only) { /* no local log at client side */ - GOTO(out_pop, rc = -EIO); + /* Copy the setup log locally if we can. Don't mess around if we're + * running an MGS though (logs are already local). */ + if (lctxt && lsi && IS_SERVER(lsi) && !IS_MGS(lsi) && + cl_mgc_dir != NULL && + lu2dt_dev(cl_mgc_dir->do_lu.lo_dev) == lsi->lsi_dt_dev) { + if (!local_only) + /* Only try to copy log if we have the lock. */ + rc = mgc_llog_local_copy(env, mgc, ctxt, lctxt, + cld->cld_logname); + if (local_only || rc) { + if (llog_is_empty(env, lctxt, cld->cld_logname)) { + LCONSOLE_ERROR_MSG(0x13a, + "Failed to get MGS log %s and no local copy.\n", + cld->cld_logname); + GOTO(out_pop, rc = -ENOTCONN); + } + CDEBUG(D_MGC, + "Failed to get MGS log %s, using local copy for now, will try to update later.\n", + cld->cld_logname); + } + /* Now, whether we copied or not, start using the local llog. + * If we failed to copy, we'll start using whatever the old + * log has. */ + llog_ctxt_put(ctxt); + ctxt = lctxt; + lctxt = NULL; + } else { + if (local_only) /* no local log at client side */ + GOTO(out_pop, rc = -EIO); } if (cld_is_sptlrpc(cld)) { @@ -1587,19 +1685,16 @@ static int mgc_process_cfg_log(struct obd_device *mgc, } /* logname and instance info should be the same, so use our - copy of the instance for the update. The cfg_last_idx will - be updated here. */ - rc = class_config_parse_llog(NULL, ctxt, cld->cld_logname, + * copy of the instance for the update. The cfg_last_idx will + * be updated here. */ + rc = class_config_parse_llog(env, ctxt, cld->cld_logname, &cld->cld_cfg); out_pop: - llog_ctxt_put(ctxt); + __llog_ctxt_put(env, ctxt); if (lctxt) - llog_ctxt_put(lctxt); - if (must_pop) - pop_ctxt(saved_ctxt, &mgc->obd_lvfs_ctxt, NULL); + __llog_ctxt_put(env, lctxt); - OBD_FREE_PTR(saved_ctxt); /* * update settings on existing OBDs. doing it inside * of llog_process_lock so no device is attaching/detaching @@ -1614,6 +1709,9 @@ out_pop: strlen("-sptlrpc")); } + lu_env_fini(env); +out_free: + OBD_FREE_PTR(env); return rc; } @@ -1801,8 +1899,6 @@ struct obd_ops mgc_obd_ops = { .o_set_info_async = mgc_set_info_async, .o_get_info = mgc_get_info, .o_import_event = mgc_import_event, - .o_llog_init = mgc_llog_init, - .o_llog_finish = mgc_llog_finish, .o_process_config = mgc_process_config, }; diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index b4dad344b72a..e0dfb089dd90 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -265,31 +265,6 @@ out: } EXPORT_SYMBOL(llog_init_handle); -int llog_copy_handler(const struct lu_env *env, - struct llog_handle *llh, - struct llog_rec_hdr *rec, - void *data) -{ - struct llog_rec_hdr local_rec = *rec; - struct llog_handle *local_llh = (struct llog_handle *)data; - char *cfg_buf = (char*) (rec + 1); - struct lustre_cfg *lcfg; - int rc = 0; - - /* Append all records */ - local_rec.lrh_len -= sizeof(*rec) + sizeof(struct llog_rec_tail); - rc = llog_write(env, local_llh, &local_rec, NULL, 0, - (void *)cfg_buf, -1); - - lcfg = (struct lustre_cfg *)cfg_buf; - CDEBUG(D_INFO, "idx=%d, rc=%d, len=%d, cmd %x %s %s\n", - rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command, - lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1)); - - return rc; -} -EXPORT_SYMBOL(llog_copy_handler); - static int llog_process_thread(void *arg) { struct llog_process_info *lpi = arg; @@ -493,14 +468,6 @@ int llog_process(const struct lu_env *env, struct llog_handle *loghandle, } EXPORT_SYMBOL(llog_process); -inline int llog_get_size(struct llog_handle *loghandle) -{ - if (loghandle && loghandle->lgh_hdr) - return loghandle->lgh_hdr->llh_count; - return 0; -} -EXPORT_SYMBOL(llog_get_size); - int llog_reverse_process(const struct lu_env *env, struct llog_handle *loghandle, llog_cb_t cb, void *data, void *catdata) @@ -767,8 +734,9 @@ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle **res, struct llog_logid *logid, char *name) { - struct thandle *th; - int rc; + struct dt_device *d; + struct thandle *th; + int rc; rc = llog_open(env, ctxt, res, logid, name, LLOG_OPEN_NEW); if (rc) @@ -777,27 +745,21 @@ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt, if (llog_exist(*res)) return 0; - if ((*res)->lgh_obj != NULL) { - struct dt_device *d; + LASSERT((*res)->lgh_obj != NULL); - d = lu2dt_dev((*res)->lgh_obj->do_lu.lo_dev); + d = lu2dt_dev((*res)->lgh_obj->do_lu.lo_dev); - th = dt_trans_create(env, d); - if (IS_ERR(th)) - GOTO(out, rc = PTR_ERR(th)); + th = dt_trans_create(env, d); + if (IS_ERR(th)) + GOTO(out, rc = PTR_ERR(th)); - rc = llog_declare_create(env, *res, th); - if (rc == 0) { - rc = dt_trans_start_local(env, d, th); - if (rc == 0) - rc = llog_create(env, *res, th); - } - dt_trans_stop(env, d, th); - } else { - /* lvfs compat code */ - LASSERT((*res)->lgh_file == NULL); - rc = llog_create(env, *res, NULL); + rc = llog_declare_create(env, *res, th); + if (rc == 0) { + rc = dt_trans_start_local(env, d, th); + if (rc == 0) + rc = llog_create(env, *res, th); } + dt_trans_stop(env, d, th); out: if (rc) llog_close(env, *res); @@ -842,41 +804,34 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle, struct llog_rec_hdr *rec, struct llog_cookie *reccookie, int cookiecount, void *buf, int idx) { - int rc; + struct dt_device *dt; + struct thandle *th; + int rc; LASSERT(loghandle); LASSERT(loghandle->lgh_ctxt); + LASSERT(loghandle->lgh_obj != NULL); - if (loghandle->lgh_obj != NULL) { - struct dt_device *dt; - struct thandle *th; - - dt = lu2dt_dev(loghandle->lgh_obj->do_lu.lo_dev); + dt = lu2dt_dev(loghandle->lgh_obj->do_lu.lo_dev); - th = dt_trans_create(env, dt); - if (IS_ERR(th)) - return PTR_ERR(th); + th = dt_trans_create(env, dt); + if (IS_ERR(th)) + return PTR_ERR(th); - rc = llog_declare_write_rec(env, loghandle, rec, idx, th); - if (rc) - GOTO(out_trans, rc); + rc = llog_declare_write_rec(env, loghandle, rec, idx, th); + if (rc) + GOTO(out_trans, rc); - rc = dt_trans_start_local(env, dt, th); - if (rc) - GOTO(out_trans, rc); + rc = dt_trans_start_local(env, dt, th); + if (rc) + GOTO(out_trans, rc); - down_write(&loghandle->lgh_lock); - rc = llog_write_rec(env, loghandle, rec, reccookie, - cookiecount, buf, idx, th); - up_write(&loghandle->lgh_lock); + down_write(&loghandle->lgh_lock); + rc = llog_write_rec(env, loghandle, rec, reccookie, + cookiecount, buf, idx, th); + up_write(&loghandle->lgh_lock); out_trans: - dt_trans_stop(env, dt, th); - } else { /* lvfs compatibility */ - down_write(&loghandle->lgh_lock); - rc = llog_write_rec(env, loghandle, rec, reccookie, - cookiecount, buf, idx, NULL); - up_write(&loghandle->lgh_lock); - } + dt_trans_stop(env, dt, th); return rc; } EXPORT_SYMBOL(llog_write); @@ -932,3 +887,104 @@ out: return rc; } EXPORT_SYMBOL(llog_close); + +int llog_is_empty(const struct lu_env *env, struct llog_ctxt *ctxt, + char *name) +{ + struct llog_handle *llh; + int rc = 0; + + rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); + if (rc < 0) { + if (likely(rc == -ENOENT)) + rc = 0; + GOTO(out, rc); + } + + rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out_close, rc); + rc = llog_get_size(llh); + +out_close: + llog_close(env, llh); +out: + /* header is record 1 */ + return rc <= 1; +} +EXPORT_SYMBOL(llog_is_empty); + +int llog_copy_handler(const struct lu_env *env, struct llog_handle *llh, + struct llog_rec_hdr *rec, void *data) +{ + struct llog_handle *copy_llh = data; + + /* Append all records */ + return llog_write(env, copy_llh, rec, NULL, 0, NULL, -1); +} +EXPORT_SYMBOL(llog_copy_handler); + +/* backup plain llog */ +int llog_backup(const struct lu_env *env, struct obd_device *obd, + struct llog_ctxt *ctxt, struct llog_ctxt *bctxt, + char *name, char *backup) +{ + struct llog_handle *llh, *bllh; + int rc; + + + + /* open original log */ + rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); + if (rc < 0) { + /* the -ENOENT case is also reported to the caller + * but silently so it should handle that if needed. + */ + if (rc != -ENOENT) + CERROR("%s: failed to open log %s: rc = %d\n", + obd->obd_name, name, rc); + return rc; + } + + rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out_close, rc); + + /* Make sure there's no old backup log */ + rc = llog_erase(env, bctxt, NULL, backup); + if (rc < 0 && rc != -ENOENT) + GOTO(out_close, rc); + + /* open backup log */ + rc = llog_open_create(env, bctxt, &bllh, NULL, backup); + if (rc) { + CERROR("%s: failed to open backup logfile %s: rc = %d\n", + obd->obd_name, backup, rc); + GOTO(out_close, rc); + } + + /* check that backup llog is not the same object as original one */ + if (llh->lgh_obj == bllh->lgh_obj) { + CERROR("%s: backup llog %s to itself (%s), objects %p/%p\n", + obd->obd_name, name, backup, llh->lgh_obj, + bllh->lgh_obj); + GOTO(out_backup, rc = -EEXIST); + } + + rc = llog_init_handle(env, bllh, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out_backup, rc); + + /* Copy log record by record */ + rc = llog_process_or_fork(env, llh, llog_copy_handler, (void *)bllh, + NULL, false); + if (rc) + CERROR("%s: failed to backup log %s: rc = %d\n", + obd->obd_name, name, rc); +out_backup: + llog_close(env, bllh); +out_close: + llog_close(env, llh); + return rc; +} +EXPORT_SYMBOL(llog_backup); diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.c b/drivers/staging/lustre/lustre/obdclass/local_storage.c index 51ab7f413004..e79e4beb3628 100644 --- a/drivers/staging/lustre/lustre/obdclass/local_storage.c +++ b/drivers/staging/lustre/lustre/obdclass/local_storage.c @@ -855,9 +855,12 @@ out_los: (*los)->los_seq = fid_seq(first_fid); (*los)->los_last_oid = le64_to_cpu(lastid); (*los)->los_obj = o; - /* read value should not be less than initial one */ - LASSERTF((*los)->los_last_oid >= first_oid, "%u < %u\n", - (*los)->los_last_oid, first_oid); + /* Read value should not be less than initial one + * but possible after upgrade from older fs. + * In this case just switch to the first_oid in memory and + * it will be updated on disk with first object generated */ + if ((*los)->los_last_oid < first_oid) + (*los)->los_last_oid = first_oid; } out: mutex_unlock(&ls->ls_los_mutex); diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.h b/drivers/staging/lustre/lustre/obdclass/local_storage.h index d553c3752703..0f63b8c073b4 100644 --- a/drivers/staging/lustre/lustre/obdclass/local_storage.h +++ b/drivers/staging/lustre/lustre/obdclass/local_storage.h @@ -29,6 +29,8 @@ * * Author: Mikhail Pershin */ +#ifndef __LOCAL_STORAGE_H +#define __LOCAL_STORAGE_H #include #include @@ -86,3 +88,4 @@ struct los_ondisk { }; #define LOS_MAGIC 0xdecafbee +#endif diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 1d6754bbace7..9887d8fffb6e 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -429,7 +429,7 @@ LU_KEY_INIT_FINI(lu_global, struct lu_cdebug_data); */ struct lu_context_key lu_global_key = { .lct_tags = LCT_MD_THREAD | LCT_DT_THREAD | - LCT_MG_THREAD | LCT_CL_THREAD, + LCT_MG_THREAD | LCT_CL_THREAD | LCT_LOCAL, .lct_init = lu_global_key_init, .lct_fini = lu_global_key_fini }; diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 68a4d6a0eb03..a69a630b596e 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -631,6 +631,9 @@ int lustre_put_lsi(struct super_block *sb) CDEBUG(D_MOUNT, "put %p %d\n", sb, atomic_read(&lsi->lsi_mounts)); if (atomic_dec_and_test(&lsi->lsi_mounts)) { if (IS_SERVER(lsi) && lsi->lsi_osd_exp) { + lu_device_put(&lsi->lsi_dt_dev->dd_lu_dev); + lsi->lsi_osd_exp->exp_obd->obd_lvfs_ctxt.dt = NULL; + lsi->lsi_dt_dev = NULL; obd_disconnect(lsi->lsi_osd_exp); /* wait till OSD is gone */ obd_zombie_barrier(); -- cgit v1.2.3 From 1ecc2061f608e9afb3f49c4b94e93013f5778efc Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Tue, 3 Dec 2013 21:58:41 +0800 Subject: staging/lustre: constify uuid argument of obd_uuid2str This is only part of the original Lustre tree commit. Main part of the original commit changes server code and is unneeded at client side. Lustre-change: http://review.whamcloud.com/6534 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3342 Signed-off-by: JC Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 9436166c6ef2..ff825d83daa7 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -446,7 +446,7 @@ static inline void obd_str2uuid(struct obd_uuid *uuid, const char *tmp) } /* For printf's only, make sure uuid is terminated */ -static inline char *obd_uuid2str(struct obd_uuid *uuid) +static inline char *obd_uuid2str(const struct obd_uuid *uuid) { if (uuid->uuid[sizeof(*uuid) - 1] != '\0') { /* Obviously not safe, but for printfs, no real harm done... -- cgit v1.2.3 From 211b316813023ab6a82926d90522c12069baebc1 Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Tue, 3 Dec 2013 21:58:42 +0800 Subject: staging/lustre: make obd_uuid_equals return bool This is only part of the original Lustre tree commit. Main part of the original commit changes server code and is unneeded at client side. Lustre-change: http://review.whamcloud.com/6534 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3342 Signed-off-by: JC Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_user.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index ff825d83daa7..631f0261c44d 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -428,8 +428,8 @@ struct obd_uuid { char uuid[UUID_MAX]; }; -static inline int obd_uuid_equals(const struct obd_uuid *u1, - const struct obd_uuid *u2) +static inline bool obd_uuid_equals(const struct obd_uuid *u1, + const struct obd_uuid *u2) { return strcmp((char *)u1->uuid, (char *)u2->uuid) == 0; } -- cgit v1.2.3 From c0ac76d9bc12d5485c899265ef1309a7dd00d854 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Tue, 3 Dec 2013 21:58:43 +0800 Subject: staging/lustre/scrub: OI scrub on OST Main part of original patch in Lustre tree (http://review.whamcloud.com/6669) changes server code and is unneeded by client. The patch only picks up common functions and data structures change. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3335 Lustre-change: http://review.whamcloud.com/6669 Signed-off-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_idl.h | 7 +++++-- drivers/staging/lustre/lustre/include/obd_support.h | 1 + drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 7dfb925a536b..08da4f331f23 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -321,8 +321,11 @@ static inline int range_compare_loc(const struct lu_seq_range *r1, * xattr. */ enum lma_compat { - LMAC_HSM = 0x00000001, - LMAC_SOM = 0x00000002, + LMAC_HSM = 0x00000001, + LMAC_SOM = 0x00000002, + LMAC_NOT_IN_OI = 0x00000004, /* the object does NOT need OI mapping */ + LMAC_FID_ON_OST = 0x00000008, /* For OST-object, its OI mapping is + * under /O//d. */ }; /** diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 825a0c95c585..1748985bb466 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -256,6 +256,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, #define OBD_FAIL_OSD_SCRUB_FATAL 0x192 #define OBD_FAIL_OSD_FID_MAPPING 0x193 #define OBD_FAIL_OSD_LMA_INCOMPAT 0x194 +#define OBD_FAIL_OSD_COMPAT_INVALID_ENTRY 0x195 #define OBD_FAIL_OST 0x200 #define OBD_FAIL_OST_CONNECT_NET 0x201 diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 6cc0d6e61f12..c2efd118ddf9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -431,6 +431,10 @@ void lustre_assert_wire_constants(void) (unsigned)LMAC_HSM); LASSERTF(LMAC_SOM == 0x00000002UL, "found 0x%.8xUL\n", (unsigned)LMAC_SOM); + LASSERTF(LMAC_NOT_IN_OI == 0x00000004UL, "found 0x%.8xUL\n", + (unsigned)LMAC_NOT_IN_OI); + LASSERTF(LMAC_FID_ON_OST == 0x00000008UL, "found 0x%.8xUL\n", + (unsigned)LMAC_FID_ON_OST); LASSERTF(OBJ_CREATE == 1, "found %lld\n", (long long)OBJ_CREATE); LASSERTF(OBJ_DESTROY == 2, "found %lld\n", -- cgit v1.2.3 From c03a98b4aa441dedcb994a829bbe7454945bdfef Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Tue, 3 Dec 2013 21:58:44 +0800 Subject: staging/lustre: make code align in lma_incompat This is the coding style part of the original Lustre commit. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3335 Lustre-change: http://review.whamcloud.com/6669 Signed-off-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_idl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 08da4f331f23..dd94dc81db80 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -334,10 +334,10 @@ enum lma_compat { * This information is stored in lustre_mdt_attrs::lma_incompat. */ enum lma_incompat { - LMAI_RELEASED = 0x0000001, /* file is released */ - LMAI_AGENT = 0x00000002, /* agent inode */ - LMAI_REMOTE_PARENT = 0x00000004, /* the parent of the object - is on the remote MDT */ + LMAI_RELEASED = 0x00000001, /* file is released */ + LMAI_AGENT = 0x00000002, /* agent inode */ + LMAI_REMOTE_PARENT = 0x00000004, /* the parent of the object + is on the remote MDT */ }; #define LMA_INCOMPAT_SUPP (LMAI_AGENT | LMAI_REMOTE_PARENT) -- cgit v1.2.3 From 1e8a576eb38f23e55ed88e4e8e2b35ccb43cfb7f Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 3 Dec 2013 21:58:45 +0800 Subject: staging/lustre/llite: don't check for O_CREAT in it_create_mode ll_lookup_it() checks for O_CREAT in struct lookup_intent's it_create_mode member which is nonsensical, as it_create_mode is used for file mode bits (S_IFREG, S_IRUSR, ...). Fix this by just checking for IT_CREATE in it_op. This will not affect the behavior of either function, since if O_CREATE (0100) is actually set in o_create_mode then IT_CREATE must have been set in it_op. In ll_atomic_open() check for O_CREAT in the open_flags parameter rather than testing mode. Lustre-change: http://review.whamcloud.com/6786 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3517 Signed-off-by: John L. Hammond Reviewed-by: Lai Siyao Reviewed-by: Peng Tao Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/namei.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 804451fabfbf..52422338a666 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -523,8 +523,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, icbd.icbd_childp = &dentry; icbd.icbd_parent = parent; - if (it->it_op & IT_CREAT || - (it->it_op & IT_OPEN && it->it_create_mode & O_CREAT)) + if (it->it_op & IT_CREAT) opc = LUSTRE_OPC_CREATE; else opc = LUSTRE_OPC_ANY; @@ -623,7 +622,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, return -ENOMEM; it->it_op = IT_OPEN; - if (mode) { + if (open_flags & O_CREAT) { it->it_op |= IT_CREAT; lookup_flags |= LOOKUP_CREATE; } -- cgit v1.2.3 From 56dba8cd9ac8cb59161b906a27b5a4260e6ee99f Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 3 Dec 2013 21:58:46 +0800 Subject: staging/lustre/build: fix compilation issue with is_compat_task After removing LIBCFS_HAVE_IS_COMPAT_TASK test we have a compilation issue with kernels configured without CONFIG_COMPAT. Lustre-change: http://review.whamcloud.com/7118 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2800 Signed-off-by: Dmitry Eremin Reviewed-by: James Simmons Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_internal.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 6d15e5c100fc..1aeadc13c7ec 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -651,7 +651,12 @@ static inline int ll_need_32bit_api(struct ll_sb_info *sbi) #if BITS_PER_LONG == 32 return 1; #else - return unlikely(is_compat_task() || (sbi->ll_flags & LL_SBI_32BIT_API)); + return unlikely( +#ifdef CONFIG_COMPAT + is_compat_task() || +#endif + (sbi->ll_flags & LL_SBI_32BIT_API) + ); #endif } -- cgit v1.2.3 From 3c92a0bf4d72737035a16c4fe357ccd439c9b7d2 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Tue, 3 Dec 2013 21:58:47 +0800 Subject: staging/lustre/ptlrpc: Fix a crash when dereferencing NULL pointer When a system runs out of memory and the function ptlrpc_register_bulk() is called from ptl_send_rpc() the call to LNetMEAttach() fails due to failure to allocate memory. This forces the code into an error path, which most probably previously went untested. The error path: if (rc != 0) { CERROR("%s: LNetMEAttach failed x"LPU64"/%d: rc = %dn", desc->bd_export->exp_obd->obd_name, xid, posted_md, rc); break; } This print assumes that desc->bd_export is not NULL. However, it is. In fact it is expected to be NULL. desc->bd_import is the correct structure to access in this case. Lustre-change: http://review.whamcloud.com/7121 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3585 Cc: stable # 3.12 Signed-off-by: Amir Shehata Reviewed-by: Liang Zhen Reviewed-by: Doug Oucharek Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 5f2aa7aa17ea..3c6bf23415f9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -180,7 +180,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) LNET_UNLINK, LNET_INS_AFTER, &me_h); if (rc != 0) { CERROR("%s: LNetMEAttach failed x"LPU64"/%d: rc = %d\n", - desc->bd_export->exp_obd->obd_name, xid, + desc->bd_import->imp_obd->obd_name, xid, posted_md, rc); break; } @@ -190,7 +190,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) &desc->bd_mds[posted_md]); if (rc != 0) { CERROR("%s: LNetMDAttach failed x"LPU64"/%d: rc = %d\n", - desc->bd_export->exp_obd->obd_name, xid, + desc->bd_import->imp_obd->obd_name, xid, posted_md, rc); rc2 = LNetMEUnlink(me_h); LASSERT(rc2 == 0); @@ -220,7 +220,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) /* Holler if peer manages to touch buffers before he knows the xid */ if (desc->bd_md_count != total_md) CWARN("%s: Peer %s touched %d buffers while I registered\n", - desc->bd_export->exp_obd->obd_name, libcfs_id2str(peer), + desc->bd_import->imp_obd->obd_name, libcfs_id2str(peer), total_md - desc->bd_md_count); spin_unlock(&desc->bd_lock); -- cgit v1.2.3 From 48d23e612721d7e08dd8b13f5b8fbd12c6f88181 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 3 Dec 2013 21:58:48 +0800 Subject: staging/lustre/hsm: Add hsm_release feature. HSM Release is one of the key feature of HSM. To perform HSM release, clients need to acquire the file lease exclusivelt and flush dirty cache from clients. A special close REQ will be sent to the MDT to release the lease and get rid of OST objects. Lustre-change: http://review.whamcloud.com/7028 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1333 Signed-off-by: Aurelien Degremont Signed-off-by: Jinshan Xiong Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 14 +++- .../lustre/lustre/include/lustre/lustre_user.h | 11 ++- .../lustre/lustre/include/lustre_req_layout.h | 2 + drivers/staging/lustre/lustre/include/obd.h | 6 +- .../staging/lustre/lustre/lclient/lcommon_misc.c | 4 +- drivers/staging/lustre/lustre/llite/dir.c | 24 +++++- drivers/staging/lustre/lustre/llite/file.c | 87 +++++++++++++++++++--- .../staging/lustre/lustre/llite/llite_internal.h | 3 +- drivers/staging/lustre/lustre/llite/vvp_object.c | 2 +- .../staging/lustre/lustre/lov/lov_cl_internal.h | 16 ++++ drivers/staging/lustre/lustre/lov/lov_object.c | 35 ++++++--- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 26 ++++++- drivers/staging/lustre/lustre/mdc/mdc_request.c | 23 +++++- drivers/staging/lustre/lustre/ptlrpc/layout.c | 19 +++++ .../staging/lustre/lustre/ptlrpc/pack_generic.c | 7 ++ 15 files changed, 242 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index dd94dc81db80..77edf7d965e4 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1761,6 +1761,7 @@ static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic) #define OBD_MD_FLRMTRGETFACL (0x0008000000000000ULL) /* lfs rgetfacl case */ #define OBD_MD_FLDATAVERSION (0x0010000000000000ULL) /* iversion sum */ +#define OBD_MD_FLRELEASED (0x0020000000000000ULL) /* file released */ #define OBD_MD_FLGETATTR (OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLMTIME | \ OBD_MD_FLCTIME | OBD_MD_FLSIZE | OBD_MD_FLBLKSZ | \ @@ -2397,6 +2398,7 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa); * delegation, succeed if it's not * being opened with conflict mode. */ +#define MDS_OPEN_RELEASE 02000000000000ULL /* Open the file for HSM release */ /* permission for create non-directory file */ #define MAY_CREATE (1 << 7) @@ -2415,7 +2417,7 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa); /* lfs rgetfacl permission check */ #define MAY_RGETFACL (1 << 14) -enum { +enum mds_op_bias { MDS_CHECK_SPLIT = 1 << 0, MDS_CROSS_REF = 1 << 1, MDS_VTX_BYPASS = 1 << 2, @@ -2428,6 +2430,7 @@ enum { MDS_DATA_MODIFIED = 1 << 9, MDS_CREATE_VOLATILE = 1 << 10, MDS_OWNEROVERRIDE = 1 << 11, + MDS_HSM_RELEASE = 1 << 12, }; /* instance of mdt_reint_rec */ @@ -3751,5 +3754,14 @@ struct mdc_swap_layouts { void lustre_swab_swap_layouts(struct mdc_swap_layouts *msl); +struct close_data { + struct lustre_handle cd_handle; + struct lu_fid cd_fid; + __u64 cd_data_version; + __u64 cd_reserved[8]; +}; + +void lustre_swab_close_data(struct close_data *data); + #endif /** @} lustreidl */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 631f0261c44d..c7abb802a789 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -623,10 +623,13 @@ struct if_quotactl { }; /* swap layout flags */ -#define SWAP_LAYOUTS_CHECK_DV1 (1 << 0) -#define SWAP_LAYOUTS_CHECK_DV2 (1 << 1) -#define SWAP_LAYOUTS_KEEP_MTIME (1 << 2) -#define SWAP_LAYOUTS_KEEP_ATIME (1 << 3) +#define SWAP_LAYOUTS_CHECK_DV1 (1 << 0) +#define SWAP_LAYOUTS_CHECK_DV2 (1 << 1) +#define SWAP_LAYOUTS_KEEP_MTIME (1 << 2) +#define SWAP_LAYOUTS_KEEP_ATIME (1 << 3) + +/* Swap XATTR_NAME_HSM as well, only on the MDT so far */ +#define SWAP_LAYOUTS_MDS_HSM (1 << 31) struct lustre_swap_layouts { __u64 sl_flags; __u32 sl_fd; diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index 28325693fc11..a75f4c608fbb 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -164,6 +164,7 @@ extern struct req_format RQF_UPDATE_OBJ; */ extern struct req_format RQF_MDS_GETATTR_NAME; extern struct req_format RQF_MDS_CLOSE; +extern struct req_format RQF_MDS_RELEASE_CLOSE; extern struct req_format RQF_MDS_PIN; extern struct req_format RQF_MDS_UNPIN; extern struct req_format RQF_MDS_CONNECT; @@ -262,6 +263,7 @@ extern struct req_msg_field RMF_GETINFO_VAL; extern struct req_msg_field RMF_GETINFO_VALLEN; extern struct req_msg_field RMF_GETINFO_KEY; extern struct req_msg_field RMF_IDX_INFO; +extern struct req_msg_field RMF_CLOSE_DATA; /* * connection handle received in MDS_CONNECT request. diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f0c17736c334..3247d1d3f342 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1070,7 +1070,7 @@ struct md_op_data { struct obd_capa *op_capa2; /* Various operation flags. */ - __u32 op_bias; + enum mds_op_bias op_bias; /* Operation type */ __u32 op_opc; @@ -1084,6 +1084,10 @@ struct md_op_data { /* used to transfer info between the stacks of MD client * see enum op_cli_flags */ __u32 op_cli_flags; + + /* File object data version for HSM release, on client */ + __u64 op_data_version; + struct lustre_handle op_lease_handle; }; enum op_cli_flags { diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c b/drivers/staging/lustre/lustre/lclient/lcommon_misc.c index 2b4dbeebcd5d..e04c2d37c249 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_misc.c @@ -140,7 +140,9 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock, rc = cl_io_init(env, io, CIT_MISC, io->ci_obj); if (rc) { - LASSERT(rc < 0); + /* Does not make sense to take GL for released layout */ + if (rc > 0) + rc = -ENOTSUPP; cl_env_put(env, &refcheck); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 1f079034bd8f..22d0acc95bc5 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1809,8 +1809,28 @@ out_rmdir: return -EFAULT; } - rc = obd_iocontrol(cmd, ll_i2mdexp(inode), totalsize, - hur, NULL); + if (hur->hur_request.hr_action == HUA_RELEASE) { + const struct lu_fid *fid; + struct inode *f; + int i; + + for (i = 0; i < hur->hur_request.hr_itemcount; i++) { + fid = &hur->hur_user_item[i].hui_fid; + f = search_inode_for_lustre(inode->i_sb, fid); + if (IS_ERR(f)) { + rc = PTR_ERR(f); + break; + } + + rc = ll_hsm_release(f); + iput(f); + if (rc != 0) + break; + } + } else { + rc = obd_iocontrol(cmd, ll_i2mdexp(inode), totalsize, + hur, NULL); + } OBD_FREE_LARGE(hur, totalsize); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 82248e9f6bff..95d736443b9b 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -115,7 +115,8 @@ out: static int ll_close_inode_openhandle(struct obd_export *md_exp, struct inode *inode, - struct obd_client_handle *och) + struct obd_client_handle *och, + const __u64 *data_version) { struct obd_export *exp = ll_i2mdexp(inode); struct md_op_data *op_data; @@ -139,6 +140,13 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, GOTO(out, rc = -ENOMEM); // XXX We leak openhandle and request here. ll_prepare_close(inode, op_data, och); + if (data_version != NULL) { + /* Pass in data_version implies release. */ + op_data->op_bias |= MDS_HSM_RELEASE; + op_data->op_data_version = *data_version; + op_data->op_lease_handle = och->och_lease_handle; + op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS; + } epoch_close = (op_data->op_flags & MF_EPOCH_CLOSE); rc = md_close(md_exp, op_data, och->och_mod, &req); if (rc == -EAGAIN) { @@ -167,14 +175,20 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, spin_unlock(&lli->lli_lock); } - ll_finish_md_op_data(op_data); - if (rc == 0) { rc = ll_objects_destroy(req, inode); if (rc) CERROR("inode %lu ll_objects destroy: rc = %d\n", inode->i_ino, rc); } + if (rc == 0 && op_data->op_bias & MDS_HSM_RELEASE) { + struct mdt_body *body; + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (!(body->valid & OBD_MD_FLRELEASED)) + rc = -EBUSY; + } + + ll_finish_md_op_data(op_data); out: if (exp_connect_som(exp) && !epoch_close && @@ -224,7 +238,7 @@ int ll_md_real_close(struct inode *inode, int flags) if (och) { /* There might be a race and somebody have freed this och already */ rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, - inode, och); + inode, och, NULL); } return rc; @@ -254,7 +268,7 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode, } if (fd->fd_och != NULL) { - rc = ll_close_inode_openhandle(md_exp, inode, fd->fd_och); + rc = ll_close_inode_openhandle(md_exp, inode, fd->fd_och, NULL); fd->fd_och = NULL; GOTO(out, rc); } @@ -719,7 +733,7 @@ static int ll_md_blocking_lease_ast(struct ldlm_lock *lock, * Acquire a lease and open the file. */ struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file, - fmode_t fmode) + fmode_t fmode, __u64 open_flags) { struct lookup_intent it = { .it_op = IT_OPEN }; struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -787,7 +801,8 @@ struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file, /* To tell the MDT this openhandle is from the same owner */ op_data->op_handle = old_handle; - it.it_flags = fmode | MDS_OPEN_LOCK | MDS_OPEN_BY_FID | MDS_OPEN_LEASE; + it.it_flags = fmode | open_flags; + it.it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID | MDS_OPEN_LEASE; rc = md_intent_lock(sbi->ll_md_exp, op_data, NULL, 0, &it, 0, &req, ll_md_blocking_lease_ast, /* LDLM_FL_NO_LRU: To not put the lease lock into LRU list, otherwise @@ -833,7 +848,7 @@ struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file, return och; out_close: - rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, inode, och); + rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, inode, och, NULL); if (rc2) CERROR("Close openhandle returned %d\n", rc2); @@ -878,7 +893,8 @@ int ll_lease_close(struct obd_client_handle *och, struct inode *inode, if (lease_broken != NULL) *lease_broken = cancelled; - rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och); + rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och, + NULL); return rc; } EXPORT_SYMBOL(ll_lease_close); @@ -1687,8 +1703,8 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it) ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och); rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, - inode, och); - out: + inode, och, NULL); +out: /* this one is in place of ll_file_open */ if (it_disposition(it, DISP_ENQ_OPEN_REF)) { ptlrpc_req_finished(it->d.lustre.it_data); @@ -1893,6 +1909,53 @@ out: return rc; } +/* + * Trigger a HSM release request for the provided inode. + */ +int ll_hsm_release(struct inode *inode) +{ + struct cl_env_nest nest; + struct lu_env *env; + struct obd_client_handle *och = NULL; + __u64 data_version = 0; + int rc; + + + CDEBUG(D_INODE, "%s: Releasing file "DFID".\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&ll_i2info(inode)->lli_fid)); + + och = ll_lease_open(inode, NULL, FMODE_WRITE, MDS_OPEN_RELEASE); + if (IS_ERR(och)) + GOTO(out, rc = PTR_ERR(och)); + + /* Grab latest data_version and [am]time values */ + rc = ll_data_version(inode, &data_version, 1); + if (rc != 0) + GOTO(out, rc); + + env = cl_env_nested_get(&nest); + if (IS_ERR(env)) + GOTO(out, rc = PTR_ERR(env)); + + ll_merge_lvb(env, inode); + cl_env_nested_put(&nest, env); + + /* Release the file. + * NB: lease lock handle is released in mdc_hsm_release_pack() because + * we still need it to pack l_remote_handle to MDT. */ + rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och, + &data_version); + och = NULL; + + +out: + if (och != NULL && !IS_ERR(och)) /* close the file */ + ll_lease_close(och, inode, NULL); + + return rc; +} + struct ll_swap_stack { struct iattr ia1, ia2; __u64 dv1, dv2; @@ -2320,7 +2383,7 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) CDEBUG(D_INODE, "Set lease with mode %d\n", mode); /* apply for lease */ - och = ll_lease_open(inode, file, mode); + och = ll_lease_open(inode, file, mode, 0); if (IS_ERR(och)) return PTR_ERR(och); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1aeadc13c7ec..33a3e9717115 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -788,9 +788,10 @@ int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg); int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg); int ll_fid2path(struct inode *inode, void *arg); int ll_data_version(struct inode *inode, __u64 *data_version, int extent_lock); +int ll_hsm_release(struct inode *inode); struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file, - fmode_t mode); + fmode_t mode, __u64 flags); int ll_lease_close(struct obd_client_handle *och, struct inode *inode, bool *lease_broken); diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 33173fce478f..25973dedd9a2 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -138,7 +138,7 @@ int vvp_conf_set(const struct lu_env *env, struct cl_object *obj, lli->lli_layout_gen, conf->u.coc_md->lsm->lsm_layout_gen); - lli->lli_has_smd = true; + lli->lli_has_smd = lsm_has_objects(conf->u.coc_md->lsm); lli->lli_layout_gen = conf->u.coc_md->lsm->lsm_layout_gen; } else { CDEBUG(D_VFSTRACE, "layout lock destroyed: %u.\n", diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 4276124d92e9..3965d5e4e725 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -168,6 +168,22 @@ enum lov_layout_type { LLT_NR }; +static inline char *llt2str(enum lov_layout_type llt) +{ + switch (llt) { + case LLT_EMPTY: + return "EMPTY"; + case LLT_RAID0: + return "RAID0"; + case LLT_RELEASED: + return "RELEASED"; + case LLT_NR: + LBUG(); + } + LBUG(); + return ""; +} + /** * lov-specific file state. * diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index cf2fa8abfb1d..df8b5b5b7cf4 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -393,13 +393,13 @@ static int lov_print_empty(const struct lu_env *env, void *cookie, static int lov_print_raid0(const struct lu_env *env, void *cookie, lu_printer_t p, const struct lu_object *o) { - struct lov_object *lov = lu2lov(o); - struct lov_layout_raid0 *r0 = lov_r0(lov); - struct lov_stripe_md *lsm = lov->lo_lsm; - int i; + struct lov_object *lov = lu2lov(o); + struct lov_layout_raid0 *r0 = lov_r0(lov); + struct lov_stripe_md *lsm = lov->lo_lsm; + int i; - (*p)(env, cookie, "stripes: %d, %svalid, lsm{%p 0x%08X %d %u %u}: \n", - r0->lo_nr, lov->lo_layout_invalid ? "in" : "", lsm, + (*p)(env, cookie, "stripes: %d, %s, lsm{%p 0x%08X %d %u %u}:\n", + r0->lo_nr, lov->lo_layout_invalid ? "invalid" : "valid", lsm, lsm->lsm_magic, atomic_read(&lsm->lsm_refc), lsm->lsm_stripe_count, lsm->lsm_layout_gen); for (i = 0; i < r0->lo_nr; ++i) { @@ -408,8 +408,9 @@ static int lov_print_raid0(const struct lu_env *env, void *cookie, if (r0->lo_sub[i] != NULL) { sub = lovsub2lu(r0->lo_sub[i]); lu_object_print(env, cookie, p, sub); - } else + } else { (*p)(env, cookie, "sub %d absent\n", i); + } } return 0; } @@ -417,7 +418,14 @@ static int lov_print_raid0(const struct lu_env *env, void *cookie, static int lov_print_released(const struct lu_env *env, void *cookie, lu_printer_t p, const struct lu_object *o) { - (*p)(env, cookie, "released\n"); + struct lov_object *lov = lu2lov(o); + struct lov_stripe_md *lsm = lov->lo_lsm; + + (*p)(env, cookie, + "released: %s, lsm{%p 0x%08X %d %u %u}:\n", + lov->lo_layout_invalid ? "invalid" : "valid", lsm, + lsm->lsm_magic, atomic_read(&lsm->lsm_refc), + lsm->lsm_stripe_count, lsm->lsm_layout_gen); return 0; } @@ -662,6 +670,10 @@ static int lov_layout_change(const struct lu_env *unused, return PTR_ERR(env); } + CDEBUG(D_INODE, DFID" from %s to %s\n", + PFID(lu_object_fid(lov2lu(lov))), + llt2str(lov->lo_type), llt2str(llt)); + old_ops = &lov_dispatch[lov->lo_type]; new_ops = &lov_dispatch[llt]; @@ -750,8 +762,9 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, if (conf->u.coc_md != NULL) lsm = conf->u.coc_md->lsm; if ((lsm == NULL && lov->lo_lsm == NULL) || - (lsm != NULL && lov->lo_lsm != NULL && - lov->lo_lsm->lsm_layout_gen == lsm->lsm_layout_gen)) { + ((lsm != NULL && lov->lo_lsm != NULL) && + (lov->lo_lsm->lsm_layout_gen == lsm->lsm_layout_gen) && + (lov->lo_lsm->lsm_pattern == lsm->lsm_pattern))) { /* same version of layout */ lov->lo_layout_invalid = false; GOTO(out, result = 0); @@ -767,6 +780,8 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, out: lov_conf_unlock(lov); + CDEBUG(D_INODE, DFID" lo_layout_invalid=%d\n", + PFID(lu_object_fid(lov2lu(lov))), lov->lo_layout_invalid); return result; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 3e7702075bf9..91f6876dac3f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -179,7 +179,8 @@ static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) __u64 cr_flags = (flags & (FMODE_READ | FMODE_WRITE | MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | - MDS_OPEN_BY_FID | MDS_OPEN_LEASE)); + MDS_OPEN_BY_FID | MDS_OPEN_LEASE | + MDS_OPEN_RELEASE)); if (flags & O_CREAT) cr_flags |= MDS_OPEN_CREAT; if (flags & O_EXCL) @@ -490,6 +491,28 @@ void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, } } +static void mdc_hsm_release_pack(struct ptlrpc_request *req, + struct md_op_data *op_data) +{ + if (op_data->op_bias & MDS_HSM_RELEASE) { + struct close_data *data; + struct ldlm_lock *lock; + + data = req_capsule_client_get(&req->rq_pill, &RMF_CLOSE_DATA); + LASSERT(data != NULL); + + lock = ldlm_handle2lock(&op_data->op_lease_handle); + if (lock != NULL) { + data->cd_handle = lock->l_remote_handle; + ldlm_lock_put(lock); + } + ldlm_cli_cancel(&op_data->op_lease_handle, LCF_LOCAL); + + data->cd_data_version = op_data->op_data_version; + data->cd_fid = op_data->op_fid2; + } +} + void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data) { struct mdt_ioepoch *epoch; @@ -501,6 +524,7 @@ void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data) mdc_setattr_pack_rec(rec, op_data); mdc_pack_capa(req, &RMF_CAPA1, op_data->op_capa1); mdc_ioepoch_pack(epoch, op_data); + mdc_hsm_release_pack(req, op_data); } static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 8373778c2e78..0b432517afaf 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -800,10 +800,27 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, { struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; - int rc; + struct req_format *req_fmt; + int rc; + int saved_rc = 0; + + + req_fmt = &RQF_MDS_CLOSE; + if (op_data->op_bias & MDS_HSM_RELEASE) { + req_fmt = &RQF_MDS_RELEASE_CLOSE; + + /* allocate a FID for volatile file */ + rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); + if (rc < 0) { + CERROR("%s: "DFID" failed to allocate FID: %d\n", + obd->obd_name, PFID(&op_data->op_fid1), rc); + /* save the errcode and proceed to close */ + saved_rc = rc; + } + } *request = NULL; - req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_CLOSE); + req = ptlrpc_request_alloc(class_exp2cliimp(exp), req_fmt); if (req == NULL) return -ENOMEM; @@ -893,7 +910,7 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, } *request = req; mdc_close_handle_reply(req, op_data, rc); - return rc; + return rc < 0 ? rc : saved_rc; } int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 4d6ac68676e0..c4381eb5e8dd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -145,6 +145,14 @@ static const struct req_msg_field *mdt_close_client[] = { &RMF_CAPA1 }; +static const struct req_msg_field *mdt_release_close_client[] = { + &RMF_PTLRPC_BODY, + &RMF_MDT_EPOCH, + &RMF_REC_REINT, + &RMF_CAPA1, + &RMF_CLOSE_DATA +}; + static const struct req_msg_field *obd_statfs_server[] = { &RMF_PTLRPC_BODY, &RMF_OBD_STATFS @@ -666,6 +674,7 @@ static struct req_format *req_formats[] = { &RQF_MDS_GETXATTR, &RQF_MDS_SYNC, &RQF_MDS_CLOSE, + &RQF_MDS_RELEASE_CLOSE, &RQF_MDS_PIN, &RQF_MDS_UNPIN, &RQF_MDS_READPAGE, @@ -885,6 +894,11 @@ struct req_msg_field RMF_PTLRPC_BODY = sizeof(struct ptlrpc_body), lustre_swab_ptlrpc_body, NULL); EXPORT_SYMBOL(RMF_PTLRPC_BODY); +struct req_msg_field RMF_CLOSE_DATA = + DEFINE_MSGF("data_version", 0, + sizeof(struct close_data), lustre_swab_close_data, NULL); +EXPORT_SYMBOL(RMF_CLOSE_DATA); + struct req_msg_field RMF_OBD_STATFS = DEFINE_MSGF("obd_statfs", 0, sizeof(struct obd_statfs), lustre_swab_obd_statfs, NULL); @@ -1412,6 +1426,11 @@ struct req_format RQF_MDS_CLOSE = mdt_close_client, mds_last_unlink_server); EXPORT_SYMBOL(RQF_MDS_CLOSE); +struct req_format RQF_MDS_RELEASE_CLOSE = + DEFINE_REQ_FMT0("MDS_CLOSE", + mdt_release_close_client, mds_last_unlink_server); +EXPORT_SYMBOL(RQF_MDS_RELEASE_CLOSE); + struct req_format RQF_MDS_PIN = DEFINE_REQ_FMT0("MDS_PIN", mdt_body_capa, mdt_body_only); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index d831bd7e8e08..464479c0f00b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -2565,3 +2565,10 @@ void lustre_swab_swap_layouts(struct mdc_swap_layouts *msl) __swab64s(&msl->msl_flags); } EXPORT_SYMBOL(lustre_swab_swap_layouts); + +void lustre_swab_close_data(struct close_data *cd) +{ + lustre_swab_lu_fid(&cd->cd_fid); + __swab64s(&cd->cd_data_version); +} +EXPORT_SYMBOL(lustre_swab_close_data); -- cgit v1.2.3 From 7fc1f831d83f5abfebab964a6bdbc057ff1205a6 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Tue, 3 Dec 2013 21:58:49 +0800 Subject: staging/lustre/llite: extended attribute cache This patch implements an extended attribute cache for a Lustre client. It is organized as a write-through cache: reads are performed from cache, updates are sent synchronously to the MDS. An additional inode bit MDS_INODELOCK_XATTR is added to protect the cache. Lustre-change: http://review.whamcloud.com/5537 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2869 Signed-off-by: Andrew Perepechko Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin [remove extra GPL notice in original patch as kernel already has one and it causes checkpatch error. -- Peng Tao] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/linux/lustre_lite.h | 1 + .../lustre/lustre/include/lustre/lustre_idl.h | 12 +- .../lustre/lustre/include/lustre_req_layout.h | 3 + drivers/staging/lustre/lustre/include/md_object.h | 4 +- drivers/staging/lustre/lustre/include/obd.h | 5 + .../staging/lustre/lustre/include/obd_support.h | 1 + drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 2 + drivers/staging/lustre/lustre/llite/Makefile | 2 +- drivers/staging/lustre/lustre/llite/file.c | 13 +- .../staging/lustre/lustre/llite/llite_internal.h | 36 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 23 +- drivers/staging/lustre/lustre/llite/lproc_llite.c | 37 ++ drivers/staging/lustre/lustre/llite/namei.c | 4 + drivers/staging/lustre/lustre/llite/super25.c | 4 + drivers/staging/lustre/lustre/llite/xattr.c | 102 ++-- drivers/staging/lustre/lustre/llite/xattr_cache.c | 617 +++++++++++++++++++++ drivers/staging/lustre/lustre/mdc/mdc_internal.h | 1 + drivers/staging/lustre/lustre/mdc/mdc_locks.c | 63 ++- drivers/staging/lustre/lustre/ptlrpc/layout.c | 34 ++ 19 files changed, 902 insertions(+), 62 deletions(-) create mode 100644 drivers/staging/lustre/lustre/llite/xattr_cache.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h index 9e5df8dabe80..df9391275617 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h @@ -88,6 +88,7 @@ enum { LPROC_LL_ALLOC_INODE, LPROC_LL_SETXATTR, LPROC_LL_GETXATTR, + LPROC_LL_GETXATTR_HITS, LPROC_LL_LISTXATTR, LPROC_LL_REMOVEXATTR, LPROC_LL_INODE_PERM, diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 77edf7d965e4..5da31c54924a 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1368,7 +1368,7 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); OBD_CONNECT_EINPROGRESS | \ OBD_CONNECT_LIGHTWEIGHT | OBD_CONNECT_UMASK | \ OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\ - OBD_CONNECT_PINGLESS) + OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE) #define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \ OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \ OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX | \ @@ -1752,7 +1752,9 @@ static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic) #define OBD_MD_FLCKSPLIT (0x0000080000000000ULL) /* Check split on server */ #define OBD_MD_FLCROSSREF (0x0000100000000000ULL) /* Cross-ref case */ #define OBD_MD_FLGETATTRLOCK (0x0000200000000000ULL) /* Get IOEpoch attributes - * under lock */ + * under lock; for xattr + * requests means the + * client holds the lock */ #define OBD_MD_FLOBJCOUNT (0x0000400000000000ULL) /* for multiple destroy */ #define OBD_MD_FLRMTLSETFACL (0x0001000000000000ULL) /* lfs lsetfacl case */ @@ -1769,6 +1771,9 @@ static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic) OBD_MD_FLGID | OBD_MD_FLFLAGS | OBD_MD_FLNLINK | \ OBD_MD_FLGENER | OBD_MD_FLRDEV | OBD_MD_FLGROUP) +#define OBD_MD_FLXATTRLOCKED OBD_MD_FLGETATTRLOCK +#define OBD_MD_FLXATTRALL (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS) + /* don't forget obdo_fid which is way down at the bottom so it can * come after the definition of llog_cookie */ @@ -2141,8 +2146,9 @@ extern void lustre_swab_generic_32s (__u32 *val); #define MDS_INODELOCK_OPEN 0x000004 /* For opened files */ #define MDS_INODELOCK_LAYOUT 0x000008 /* for layout */ #define MDS_INODELOCK_PERM 0x000010 /* for permission */ +#define MDS_INODELOCK_XATTR 0x000020 /* extended attributes */ -#define MDS_INODELOCK_MAXSHIFT 4 +#define MDS_INODELOCK_MAXSHIFT 5 /* This FULL lock is useful to take on unlink sort of operations */ #define MDS_INODELOCK_FULL ((1<<(MDS_INODELOCK_MAXSHIFT+1))-1) diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index a75f4c608fbb..a83db61a30be 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -230,6 +230,7 @@ extern struct req_format RQF_LDLM_INTENT_GETATTR; extern struct req_format RQF_LDLM_INTENT_OPEN; extern struct req_format RQF_LDLM_INTENT_CREATE; extern struct req_format RQF_LDLM_INTENT_UNLINK; +extern struct req_format RQF_LDLM_INTENT_GETXATTR; extern struct req_format RQF_LDLM_INTENT_QUOTA; extern struct req_format RQF_LDLM_CANCEL; extern struct req_format RQF_LDLM_CALLBACK; @@ -279,6 +280,8 @@ extern struct req_msg_field RMF_LAYOUT_INTENT; extern struct req_msg_field RMF_MDT_MD; extern struct req_msg_field RMF_REC_REINT; extern struct req_msg_field RMF_EADATA; +extern struct req_msg_field RMF_EAVALS; +extern struct req_msg_field RMF_EAVALS_LENS; extern struct req_msg_field RMF_ACL; extern struct req_msg_field RMF_LOGCOOKIES; extern struct req_msg_field RMF_CAPA1; diff --git a/drivers/staging/lustre/lustre/include/md_object.h b/drivers/staging/lustre/lustre/include/md_object.h index daf93afe3feb..7b45b47b48f9 100644 --- a/drivers/staging/lustre/lustre/include/md_object.h +++ b/drivers/staging/lustre/lustre/include/md_object.h @@ -352,8 +352,8 @@ struct md_device_operations { int (*mdo_root_get)(const struct lu_env *env, struct md_device *m, struct lu_fid *f); - int (*mdo_maxsize_get)(const struct lu_env *env, struct md_device *m, - int *md_size, int *cookie_size); + int (*mdo_maxeasize_get)(const struct lu_env *env, struct md_device *m, + int *easize); int (*mdo_statfs)(const struct lu_env *env, struct md_device *m, struct obd_statfs *sfs); diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 3247d1d3f342..c3470ce62cff 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1022,6 +1022,7 @@ struct lu_context; #define IT_LAYOUT (1 << 10) #define IT_QUOTA_DQACQ (1 << 11) #define IT_QUOTA_CONN (1 << 12) +#define IT_SETXATTR (1 << 13) static inline int it_to_lock_mode(struct lookup_intent *it) { @@ -1031,6 +1032,10 @@ static inline int it_to_lock_mode(struct lookup_intent *it) else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_LOOKUP | IT_LAYOUT)) return LCK_CR; + else if (it->it_op & IT_GETXATTR) + return LCK_PR; + else if (it->it_op & IT_SETXATTR) + return LCK_PW; LASSERTF(0, "Invalid it_op: %d\n", it->it_op); return -EINVAL; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 1748985bb466..2dc95de1059c 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -465,6 +465,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, #define OBD_FAIL_LOCK_STATE_WAIT_INTR 0x1402 #define OBD_FAIL_LOV_INIT 0x1403 #define OBD_FAIL_GLIMPSE_DELAY 0x1404 +#define OBD_FAIL_LLITE_XATTR_ENOMEM 0x1405 #define OBD_FAIL_FID_INDIR 0x1501 #define OBD_FAIL_FID_INLMA 0x1502 diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index ef826e90df03..95eff79d5752 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -145,6 +145,8 @@ char *ldlm_it2str(int it) return "getxattr"; case IT_LAYOUT: return "layout"; + case IT_SETXATTR: + return "setxattr"; default: CERROR("Unknown intent %d\n", it); return "UNKNOWN"; diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index f493e0740004..bb34b8b40645 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o obj-$(CONFIG_LUSTRE_LLITE_LLOOP) += llite_lloop.o lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ rw.o lproc_llite.o namei.o symlink.o llite_mmap.o \ - xattr.o remote_perm.o llite_rmtacl.o llite_capa.o \ + xattr.o xattr_cache.o remote_perm.o llite_rmtacl.o llite_capa.o \ rw26.o super25.o statahead.o \ ../lclient/glimpse.o ../lclient/lcommon_cl.o ../lclient/lcommon_misc.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 95d736443b9b..c1261357fd40 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2784,7 +2784,8 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, ldlm_mode_t l_req_mode) } ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits, - struct lustre_handle *lockh, __u64 flags) + struct lustre_handle *lockh, __u64 flags, + ldlm_mode_t mode) { ldlm_policy_data_t policy = { .l_inodebits = {bits}}; struct lu_fid *fid; @@ -2794,8 +2795,8 @@ ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits, CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid)); rc = md_lock_match(ll_i2mdexp(inode), LDLM_FL_BLOCK_GRANTED|flags, - fid, LDLM_IBITS, &policy, - LCK_CR|LCK_CW|LCK_PR|LCK_PW, lockh); + fid, LDLM_IBITS, &policy, mode, lockh); + return rc; } @@ -3471,7 +3472,8 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) /* mostly layout lock is caching on the local side, so try to match * it before grabbing layout lock mutex. */ - mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0); + mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0, + LCK_CR | LCK_CW | LCK_PR | LCK_PW); if (mode != 0) { /* hit cached lock */ rc = ll_layout_lock_set(&lockh, mode, inode, gen, false); if (rc == 0) @@ -3486,7 +3488,8 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) again: /* try again. Maybe somebody else has done this. */ - mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0); + mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0, + LCK_CR | LCK_CW | LCK_PR | LCK_PW); if (mode != 0) { /* hit cached lock */ rc = ll_layout_lock_set(&lockh, mode, inode, gen, true); if (rc == -EAGAIN) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 33a3e9717115..10ffaf62e9d3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -128,6 +128,8 @@ enum lli_flags { LLIF_DATA_MODIFIED = (1 << 6), /* File is being restored */ LLIF_FILE_RESTORING = (1 << 7), + /* Xattr cache is attached to the file */ + LLIF_XATTR_CACHE = (1 << 8), }; struct ll_inode_info { @@ -280,8 +282,27 @@ struct ll_inode_info { struct mutex lli_layout_mutex; /* valid only inside LAYOUT ibits lock, protected by lli_layout_mutex */ __u32 lli_layout_gen; + + struct rw_semaphore lli_xattrs_list_rwsem; + struct mutex lli_xattrs_enq_lock; + struct list_head lli_xattrs;/* ll_xattr_entry->xe_list */ }; +int ll_xattr_cache_destroy(struct inode *inode); + +int ll_xattr_cache_get(struct inode *inode, + const char *name, + char *buffer, + size_t size, + __u64 valid); + +int ll_xattr_cache_update(struct inode *inode, + const char *name, + const char *newval, + size_t size, + __u64 valid, + int flags); + /* * Locking to guarantee consistency of non-atomic updates to long long i_size, * consistency between file size and KMS. @@ -403,6 +424,7 @@ enum stats_track_type { #define LL_SBI_VERBOSE 0x10000 /* verbose mount/umount */ #define LL_SBI_LAYOUT_LOCK 0x20000 /* layout lock support */ #define LL_SBI_USER_FID2PATH 0x40000 /* allow fid2path by unprivileged users */ +#define LL_SBI_XATTR_CACHE 0x80000 /* support for xattr cache */ #define LL_SBI_FLAGS { \ "nolck", \ @@ -410,6 +432,7 @@ enum stats_track_type { "flock", \ "xattr", \ "acl", \ + "???", \ "rmt_client", \ "mds_capa", \ "oss_capa", \ @@ -422,7 +445,9 @@ enum stats_track_type { "agl", \ "verbose", \ "layout", \ - "user_fid2path" } + "user_fid2path",\ + "xattr", \ +} /* default value for ll_sb_info->contention_time */ #define SBI_DEFAULT_CONTENTION_SECONDS 60 @@ -462,7 +487,8 @@ struct ll_sb_info { struct lu_fid ll_root_fid; /* root object fid */ int ll_flags; - unsigned int ll_umounting:1; + unsigned int ll_umounting:1, + ll_xattr_cache_enabled:1; struct list_head ll_conn_chain; /* per-conn chain of SBs */ struct lustre_client_ocd ll_lco; @@ -733,7 +759,8 @@ extern int ll_inode_revalidate_it(struct dentry *, struct lookup_intent *, extern int ll_have_md_lock(struct inode *inode, __u64 *bits, ldlm_mode_t l_req_mode); extern ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits, - struct lustre_handle *lockh, __u64 flags); + struct lustre_handle *lockh, __u64 flags, + ldlm_mode_t mode); int __ll_inode_revalidate_it(struct dentry *, struct lookup_intent *, __u64 bits); int ll_revalidate_nd(struct dentry *dentry, unsigned int flags); @@ -1599,4 +1626,7 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf); int ll_layout_refresh(struct inode *inode, __u32 *gen); int ll_layout_restore(struct inode *inode); +int ll_xattr_init(void); +void ll_xattr_fini(void); + #endif /* LLITE_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index facc39158447..154bdb235655 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -209,7 +209,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH| OBD_CONNECT_EINPROGRESS | OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | - OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; + OBD_CONNECT_LAYOUTLOCK | + OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -383,6 +384,17 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; } + if (data->ocd_ibits_known & MDS_INODELOCK_XATTR) { + if (!(data->ocd_connect_flags & OBD_CONNECT_MAX_EASIZE)) { + LCONSOLE_INFO( + "%s: disabling xattr cache due to unknown maximum xattr size.\n", + dt); + } else { + sbi->ll_flags |= LL_SBI_XATTR_CACHE; + sbi->ll_xattr_cache_enabled = 1; + } + } + obd = class_name2obd(dt); if (!obd) { CERROR("DT %s: not setup or attached\n", dt); @@ -922,6 +934,9 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_layout_gen = LL_LAYOUT_GEN_NONE; lli->lli_clob = NULL; + init_rwsem(&lli->lli_xattrs_list_rwsem); + mutex_init(&lli->lli_xattrs_enq_lock); + LASSERT(lli->lli_vfs_inode.i_mode != 0); if (S_ISDIR(lli->lli_vfs_inode.i_mode)) { mutex_init(&lli->lli_readdir_mutex); @@ -1194,6 +1209,8 @@ void ll_clear_inode(struct inode *inode) lli->lli_symlink_name = NULL; } + ll_xattr_cache_destroy(inode); + if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { LASSERT(lli->lli_posix_acl == NULL); if (lli->lli_remote_perms) { @@ -1752,7 +1769,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) * lock on the client and set LLIF_MDS_SIZE_LOCK holding * it. */ mode = ll_take_md_lock(inode, MDS_INODELOCK_UPDATE, - &lockh, LDLM_FL_CBPENDING); + &lockh, LDLM_FL_CBPENDING, + LCK_CR | LCK_CW | + LCK_PR | LCK_PW); if (mode) { if (lli->lli_flags & (LLIF_DONE_WRITING | LLIF_EPOCH_PENDING | diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 4bf09c4a0c9d..1ded16a0586e 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -723,6 +723,41 @@ static int ll_sbi_flags_seq_show(struct seq_file *m, void *v) } LPROC_SEQ_FOPS_RO(ll_sbi_flags); +static int ll_xattr_cache_seq_show(struct seq_file *m, void *v) +{ + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + int rc; + + rc = seq_printf(m, "%u\n", sbi->ll_xattr_cache_enabled); + + return rc; +} + +static ssize_t ll_xattr_cache_seq_write(struct file *file, const char *buffer, + size_t count, loff_t *off) +{ + struct seq_file *seq = file->private_data; + struct super_block *sb = seq->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + int val, rc; + + rc = lprocfs_write_helper(buffer, count, &val); + if (rc) + return rc; + + if (val != 0 && val != 1) + return -ERANGE; + + if (val == 1 && !(sbi->ll_flags & LL_SBI_XATTR_CACHE)) + return -ENOTSUPP; + + sbi->ll_xattr_cache_enabled = val; + + return count; +} +LPROC_SEQ_FOPS(ll_xattr_cache); + static struct lprocfs_vars lprocfs_llite_obd_vars[] = { { "uuid", &ll_sb_uuid_fops, 0, 0 }, //{ "mntpt_path", ll_rd_path, 0, 0 }, @@ -751,6 +786,7 @@ static struct lprocfs_vars lprocfs_llite_obd_vars[] = { { "lazystatfs", &ll_lazystatfs_fops, 0 }, { "max_easize", &ll_maxea_size_fops, 0, 0 }, { "sbi_flags", &ll_sbi_flags_fops, 0, 0 }, + { "xattr_cache", &ll_xattr_cache_fops, 0, 0 }, { 0 } }; @@ -802,6 +838,7 @@ struct llite_file_opcode { { LPROC_LL_ALLOC_INODE, LPROCFS_TYPE_REGS, "alloc_inode" }, { LPROC_LL_SETXATTR, LPROCFS_TYPE_REGS, "setxattr" }, { LPROC_LL_GETXATTR, LPROCFS_TYPE_REGS, "getxattr" }, + { LPROC_LL_GETXATTR_HITS, LPROCFS_TYPE_REGS, "getxattr_hits" }, { LPROC_LL_LISTXATTR, LPROCFS_TYPE_REGS, "listxattr" }, { LPROC_LL_REMOVEXATTR, LPROCFS_TYPE_REGS, "removexattr" }, { LPROC_LL_INODE_PERM, LPROCFS_TYPE_REGS, "inode_permission" }, diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 52422338a666..fc8d264f6c9a 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -223,6 +223,10 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, break; LASSERT(lock->l_flags & LDLM_FL_CANCELING); + + if (bits & MDS_INODELOCK_XATTR) + ll_xattr_cache_destroy(inode); + /* For OPEN locks we differentiate between lock modes * LCK_CR, LCK_CW, LCK_PR - bug 22891 */ if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE | diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 0beaf4e76b4b..e21e1c760a8e 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -187,11 +187,15 @@ static int __init init_lustre_lite(void) if (rc == 0) rc = vvp_global_init(); + if (rc == 0) + rc = ll_xattr_init(); + return rc; } static void __exit exit_lustre_lite(void) { + ll_xattr_fini(); vvp_global_fini(); del_timer(&ll_capa_timer); ll_capa_thread_stop(); diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index bcf86bac30a9..ee95855a2cf3 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -109,7 +109,7 @@ int ll_setxattr_common(struct inode *inode, const char *name, int flags, __u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ptlrpc_request *req; + struct ptlrpc_request *req = NULL; int xattr_type, rc; struct obd_capa *oc; #ifdef CONFIG_FS_POSIX_ACL @@ -183,11 +183,17 @@ int ll_setxattr_common(struct inode *inode, const char *name, valid |= rce_ops2valid(rce->rce_ops); } #endif - oc = ll_mdscapa_get(inode); - rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, - valid, name, pv, size, 0, flags, ll_i2suppgid(inode), - &req); - capa_put(oc); + if (sbi->ll_xattr_cache_enabled && + (rce == NULL || rce->rce_ops == RMT_LSETFACL)) { + rc = ll_xattr_cache_update(inode, name, pv, size, valid, flags); + } else { + oc = ll_mdscapa_get(inode); + rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, + valid, name, pv, size, 0, flags, + ll_i2suppgid(inode), &req); + capa_put(oc); + } + #ifdef CONFIG_FS_POSIX_ACL if (new_value != NULL) lustre_posix_acl_xattr_free(new_value, size); @@ -352,48 +358,54 @@ int ll_getxattr_common(struct inode *inode, const char *name, #endif do_getxattr: - oc = ll_mdscapa_get(inode); - rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, - valid | (rce ? rce_ops2valid(rce->rce_ops) : 0), - name, NULL, 0, size, 0, &req); - capa_put(oc); - if (rc) { - if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { - LCONSOLE_INFO("Disabling user_xattr feature because " - "it is not supported on the server\n"); - sbi->ll_flags &= ~LL_SBI_USER_XATTR; - } - return rc; - } + if (sbi->ll_xattr_cache_enabled && (rce == NULL || + rce->rce_ops == RMT_LGETFACL || + rce->rce_ops == RMT_LSETFACL)) { + rc = ll_xattr_cache_get(inode, name, buffer, size, valid); + if (rc < 0) + GOTO(out_xattr, rc); + } else { + oc = ll_mdscapa_get(inode); + rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, + valid | (rce ? rce_ops2valid(rce->rce_ops) : 0), + name, NULL, 0, size, 0, &req); + capa_put(oc); - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - LASSERT(body); + if (rc < 0) + GOTO(out_xattr, rc); - /* only detect the xattr size */ - if (size == 0) - GOTO(out, rc = body->eadatasize); + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + LASSERT(body); - if (size < body->eadatasize) { - CERROR("server bug: replied size %u > %u\n", - body->eadatasize, (int)size); - GOTO(out, rc = -ERANGE); - } + /* only detect the xattr size */ + if (size == 0) + GOTO(out, rc = body->eadatasize); - if (body->eadatasize == 0) - GOTO(out, rc = -ENODATA); + if (size < body->eadatasize) { + CERROR("server bug: replied size %u > %u\n", + body->eadatasize, (int)size); + GOTO(out, rc = -ERANGE); + } + + if (body->eadatasize == 0) + GOTO(out, rc = -ENODATA); - /* do not need swab xattr data */ - xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, - body->eadatasize); - if (!xdata) - GOTO(out, rc = -EFAULT); + /* do not need swab xattr data */ + xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, + body->eadatasize); + if (!xdata) + GOTO(out, rc = -EFAULT); + + memcpy(buffer, xdata, body->eadatasize); + rc = body->eadatasize; + } #ifdef CONFIG_FS_POSIX_ACL - if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) { + if (rce && rce->rce_ops == RMT_LSETFACL) { ext_acl_xattr_header *acl; - acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata, - body->eadatasize); + acl = lustre_posix_acl_xattr_2ext( + (posix_acl_xattr_header *)buffer, rc); if (IS_ERR(acl)) GOTO(out, rc = PTR_ERR(acl)); @@ -406,12 +418,12 @@ do_getxattr: } #endif - if (body->eadatasize == 0) { - rc = -ENODATA; - } else { - LASSERT(buffer); - memcpy(buffer, xdata, body->eadatasize); - rc = body->eadatasize; +out_xattr: + if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { + LCONSOLE_INFO( + "%s: disabling user_xattr feature because it is not supported on the server: rc = %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), rc); + sbi->ll_flags &= ~LL_SBI_USER_XATTR; } out: ptlrpc_req_finished(req); diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c new file mode 100644 index 000000000000..3e3be1f13502 --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -0,0 +1,617 @@ +/* + * Copyright 2012 Xyratex Technology Limited + * + * Author: Andrew Perepechko + * + */ + +#define DEBUG_SUBSYSTEM S_LLITE + +#include +#include +#include +#include +#include +#include +#include +#include "llite_internal.h" + +/* If we ever have hundreds of extended attributes, we might want to consider + * using a hash or a tree structure instead of list for faster lookups. + */ +struct ll_xattr_entry { + struct list_head xe_list; /* protected with + * lli_xattrs_list_rwsem */ + char *xe_name; /* xattr name, \0-terminated */ + char *xe_value; /* xattr value */ + unsigned xe_namelen; /* strlen(xe_name) + 1 */ + unsigned xe_vallen; /* xattr value length */ +}; + +static struct kmem_cache *xattr_kmem; +static struct lu_kmem_descr xattr_caches[] = { + { + .ckd_cache = &xattr_kmem, + .ckd_name = "xattr_kmem", + .ckd_size = sizeof(struct ll_xattr_entry) + }, + { + .ckd_cache = NULL + } +}; + +int ll_xattr_init(void) +{ + return lu_kmem_init(xattr_caches); +} + +void ll_xattr_fini(void) +{ + lu_kmem_fini(xattr_caches); +} + +/** + * Initializes xattr cache for an inode. + * + * This initializes the xattr list and marks cache presence. + */ +static void ll_xattr_cache_init(struct ll_inode_info *lli) +{ + + + LASSERT(lli != NULL); + + INIT_LIST_HEAD(&lli->lli_xattrs); + lli->lli_flags |= LLIF_XATTR_CACHE; +} + +/** + * This looks for a specific extended attribute. + * + * Find in @cache and return @xattr_name attribute in @xattr, + * for the NULL @xattr_name return the first cached @xattr. + * + * \retval 0 success + * \retval -ENODATA if not found + */ +static int ll_xattr_cache_find(struct list_head *cache, + const char *xattr_name, + struct ll_xattr_entry **xattr) +{ + struct ll_xattr_entry *entry; + + + + list_for_each_entry(entry, cache, xe_list) { + /* xattr_name == NULL means look for any entry */ + if (xattr_name == NULL || + strcmp(xattr_name, entry->xe_name) == 0) { + *xattr = entry; + CDEBUG(D_CACHE, "find: [%s]=%.*s\n", + entry->xe_name, entry->xe_vallen, + entry->xe_value); + return 0; + } + } + + return -ENODATA; +} + +/** + * This adds or updates an xattr. + * + * Add @xattr_name attr with @xattr_val value and @xattr_val_len length, + * if the attribute already exists, then update its value. + * + * \retval 0 success + * \retval -ENOMEM if no memory could be allocated for the cached attr + */ +static int ll_xattr_cache_add(struct list_head *cache, + const char *xattr_name, + const char *xattr_val, + unsigned xattr_val_len) +{ + struct ll_xattr_entry *xattr; + + + + if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) { + /* Found a cached EA, update it */ + + if (xattr_val_len != xattr->xe_vallen) { + char *val; + OBD_ALLOC(val, xattr_val_len); + if (val == NULL) { + CDEBUG(D_CACHE, + "failed to allocate %u bytes for xattr %s update\n", + xattr_val_len, xattr_name); + return -ENOMEM; + } + OBD_FREE(xattr->xe_value, xattr->xe_vallen); + xattr->xe_value = val; + xattr->xe_vallen = xattr_val_len; + } + memcpy(xattr->xe_value, xattr_val, xattr_val_len); + + CDEBUG(D_CACHE, "update: [%s]=%.*s\n", xattr_name, + xattr_val_len, xattr_val); + + return 0; + } + + OBD_SLAB_ALLOC_PTR_GFP(xattr, xattr_kmem, __GFP_IO); + if (xattr == NULL) { + CDEBUG(D_CACHE, "failed to allocate xattr\n"); + return -ENOMEM; + } + + xattr->xe_namelen = strlen(xattr_name) + 1; + + OBD_ALLOC(xattr->xe_name, xattr->xe_namelen); + if (!xattr->xe_name) { + CDEBUG(D_CACHE, "failed to alloc xattr name %u\n", + xattr->xe_namelen); + goto err_name; + } + OBD_ALLOC(xattr->xe_value, xattr_val_len); + if (!xattr->xe_value) { + CDEBUG(D_CACHE, "failed to alloc xattr value %d\n", + xattr_val_len); + goto err_value; + } + + memcpy(xattr->xe_name, xattr_name, xattr->xe_namelen); + memcpy(xattr->xe_value, xattr_val, xattr_val_len); + xattr->xe_vallen = xattr_val_len; + list_add(&xattr->xe_list, cache); + + CDEBUG(D_CACHE, "set: [%s]=%.*s\n", xattr_name, + xattr_val_len, xattr_val); + + return 0; +err_value: + OBD_FREE(xattr->xe_name, xattr->xe_namelen); +err_name: + OBD_SLAB_FREE_PTR(xattr, xattr_kmem); + + return -ENOMEM; +} + +/** + * This removes an extended attribute from cache. + * + * Remove @xattr_name attribute from @cache. + * + * \retval 0 success + * \retval -ENODATA if @xattr_name is not cached + */ +static int ll_xattr_cache_del(struct list_head *cache, + const char *xattr_name) +{ + struct ll_xattr_entry *xattr; + + + + CDEBUG(D_CACHE, "del xattr: %s\n", xattr_name); + + if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) { + list_del(&xattr->xe_list); + OBD_FREE(xattr->xe_name, xattr->xe_namelen); + OBD_FREE(xattr->xe_value, xattr->xe_vallen); + OBD_SLAB_FREE_PTR(xattr, xattr_kmem); + + return 0; + } + + return -ENODATA; +} + +/** + * This iterates cached extended attributes. + * + * Walk over cached attributes in @cache and + * fill in @xld_buffer or only calculate buffer + * size if @xld_buffer is NULL. + * + * \retval >= 0 buffer list size + * \retval -ENODATA if the list cannot fit @xld_size buffer + */ +static int ll_xattr_cache_list(struct list_head *cache, + char *xld_buffer, + int xld_size) +{ + struct ll_xattr_entry *xattr, *tmp; + int xld_tail = 0; + + + + list_for_each_entry_safe(xattr, tmp, cache, xe_list) { + CDEBUG(D_CACHE, "list: buffer=%p[%d] name=%s\n", + xld_buffer, xld_tail, xattr->xe_name); + + if (xld_buffer) { + xld_size -= xattr->xe_namelen; + if (xld_size < 0) + break; + memcpy(&xld_buffer[xld_tail], + xattr->xe_name, xattr->xe_namelen); + } + xld_tail += xattr->xe_namelen; + } + + if (xld_size < 0) + return -ERANGE; + + return xld_tail; +} + +/** + * Check if the xattr cache is initialized (filled). + * + * \retval 0 @cache is not initialized + * \retval 1 @cache is initialized + */ +int ll_xattr_cache_valid(struct ll_inode_info *lli) +{ + return !!(lli->lli_flags & LLIF_XATTR_CACHE); +} + +/** + * This finalizes the xattr cache. + * + * Free all xattr memory. @lli is the inode info pointer. + * + * \retval 0 no error occured + */ +static int ll_xattr_cache_destroy_locked(struct ll_inode_info *lli) +{ + + + if (!ll_xattr_cache_valid(lli)) + return 0; + + while (ll_xattr_cache_del(&lli->lli_xattrs, NULL) == 0) + ; /* empty loop */ + lli->lli_flags &= ~LLIF_XATTR_CACHE; + + return 0; +} + +int ll_xattr_cache_destroy(struct inode *inode) +{ + struct ll_inode_info *lli = ll_i2info(inode); + int rc; + + + + down_write(&lli->lli_xattrs_list_rwsem); + rc = ll_xattr_cache_destroy_locked(lli); + up_write(&lli->lli_xattrs_list_rwsem); + + return rc; +} + +/** + * Match or enqueue a PR or PW LDLM lock. + * + * Find or request an LDLM lock with xattr data. + * Since LDLM does not provide API for atomic match_or_enqueue, + * the function handles it with a separate enq lock. + * If successful, the function exits with the list lock held. + * + * \retval 0 no error occured + * \retval -ENOMEM not enough memory + */ +static int ll_xattr_find_get_lock(struct inode *inode, + struct lookup_intent *oit, + struct ptlrpc_request **req) +{ + ldlm_mode_t mode; + struct lustre_handle lockh = { 0 }; + struct md_op_data *op_data; + struct ll_inode_info *lli = ll_i2info(inode); + struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, + .ei_mode = it_to_lock_mode(oit), + .ei_cb_bl = ll_md_blocking_ast, + .ei_cb_cp = ldlm_completion_ast }; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct obd_export *exp = sbi->ll_md_exp; + int rc; + + + + mutex_lock(&lli->lli_xattrs_enq_lock); + /* Try matching first. */ + mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0, + oit->it_op == IT_SETXATTR ? LCK_PW : + (LCK_PR | LCK_PW)); + if (mode != 0) { + /* fake oit in mdc_revalidate_lock() manner */ + oit->d.lustre.it_lock_handle = lockh.cookie; + oit->d.lustre.it_lock_mode = mode; + goto out; + } + + /* Enqueue if the lock isn't cached locally. */ + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) { + mutex_unlock(&lli->lli_xattrs_enq_lock); + return PTR_ERR(op_data); + } + + op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS | + OBD_MD_FLXATTRLOCKED; +#ifdef CONFIG_FS_POSIX_ACL + /* If working with ACLs, we would like to cache local ACLs */ + if (sbi->ll_flags & LL_SBI_RMT_CLIENT) + op_data->op_valid |= OBD_MD_FLRMTLGETFACL; +#endif + + rc = md_enqueue(exp, &einfo, oit, op_data, &lockh, NULL, 0, NULL, 0); + ll_finish_md_op_data(op_data); + + if (rc < 0) { + CDEBUG(D_CACHE, + "md_intent_lock failed with %d for fid "DFID"\n", + rc, PFID(ll_inode2fid(inode))); + mutex_unlock(&lli->lli_xattrs_enq_lock); + return rc; + } + + *req = (struct ptlrpc_request *)oit->d.lustre.it_data; +out: + down_write(&lli->lli_xattrs_list_rwsem); + mutex_unlock(&lli->lli_xattrs_enq_lock); + + return 0; +} + +/** + * Refill the xattr cache. + * + * Fetch and cache the whole of xattrs for @inode, acquiring + * a read or a write xattr lock depending on operation in @oit. + * Intent is dropped on exit unless the operation is setxattr. + * + * \retval 0 no error occured + * \retval -EPROTO network protocol error + * \retval -ENOMEM not enough memory for the cache + */ +static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit) +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ptlrpc_request *req = NULL; + const char *xdata, *xval, *xtail, *xvtail; + struct ll_inode_info *lli = ll_i2info(inode); + struct mdt_body *body; + __u32 *xsizes; + int rc = 0, i; + + + + rc = ll_xattr_find_get_lock(inode, oit, &req); + if (rc) + GOTO(out_no_unlock, rc); + + /* Do we have the data at this point? */ + if (ll_xattr_cache_valid(lli)) { + ll_stats_ops_tally(sbi, LPROC_LL_GETXATTR_HITS, 1); + GOTO(out_maybe_drop, rc = 0); + } + + /* Matched but no cache? Cancelled on error by a parallel refill. */ + if (unlikely(req == NULL)) { + CDEBUG(D_CACHE, "cancelled by a parallel getxattr\n"); + GOTO(out_maybe_drop, rc = -EIO); + } + + if (oit->d.lustre.it_status < 0) { + CDEBUG(D_CACHE, "getxattr intent returned %d for fid "DFID"\n", + oit->d.lustre.it_status, PFID(ll_inode2fid(inode))); + GOTO(out_destroy, rc = oit->d.lustre.it_status); + } + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (body == NULL) { + CERROR("no MDT BODY in the refill xattr reply\n"); + GOTO(out_destroy, rc = -EPROTO); + } + /* do not need swab xattr data */ + xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, + body->eadatasize); + xval = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS, + body->aclsize); + xsizes = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS_LENS, + body->max_mdsize * sizeof(__u32)); + if (xdata == NULL || xval == NULL || xsizes == NULL) { + CERROR("wrong setxattr reply\n"); + GOTO(out_destroy, rc = -EPROTO); + } + + xtail = xdata + body->eadatasize; + xvtail = xval + body->aclsize; + + CDEBUG(D_CACHE, "caching: xdata=%p xtail=%p\n", xdata, xtail); + + ll_xattr_cache_init(lli); + + for (i = 0; i < body->max_mdsize; i++) { + CDEBUG(D_CACHE, "caching [%s]=%.*s\n", xdata, *xsizes, xval); + /* Perform consistency checks: attr names and vals in pill */ + if (memchr(xdata, 0, xtail - xdata) == NULL) { + CERROR("xattr protocol violation (names are broken)\n"); + rc = -EPROTO; + } else if (xval + *xsizes > xvtail) { + CERROR("xattr protocol violation (vals are broken)\n"); + rc = -EPROTO; + } else if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_XATTR_ENOMEM)) { + rc = -ENOMEM; + } else { + rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval, + *xsizes); + } + if (rc < 0) { + ll_xattr_cache_destroy_locked(lli); + GOTO(out_destroy, rc); + } + xdata += strlen(xdata) + 1; + xval += *xsizes; + xsizes++; + } + + if (xdata != xtail || xval != xvtail) + CERROR("a hole in xattr data\n"); + + ll_set_lock_data(sbi->ll_md_exp, inode, oit, NULL); + + GOTO(out_maybe_drop, rc); +out_maybe_drop: + /* drop lock on error or getxattr */ + if (rc != 0 || oit->it_op != IT_SETXATTR) + ll_intent_drop_lock(oit); + + if (rc != 0) + up_write(&lli->lli_xattrs_list_rwsem); +out_no_unlock: + ptlrpc_req_finished(req); + + return rc; + +out_destroy: + up_write(&lli->lli_xattrs_list_rwsem); + + ldlm_lock_decref_and_cancel((struct lustre_handle *) + &oit->d.lustre.it_lock_handle, + oit->d.lustre.it_lock_mode); + + goto out_no_unlock; +} + +/** + * Get an xattr value or list xattrs using the write-through cache. + * + * Get the xattr value (@valid has OBD_MD_FLXATTR set) of @name or + * list xattr names (@valid has OBD_MD_FLXATTRLS set) for @inode. + * The resulting value/list is stored in @buffer if the former + * is not larger than @size. + * + * \retval 0 no error occured + * \retval -EPROTO network protocol error + * \retval -ENOMEM not enough memory for the cache + * \retval -ERANGE the buffer is not large enough + * \retval -ENODATA no such attr or the list is empty + */ +int ll_xattr_cache_get(struct inode *inode, + const char *name, + char *buffer, + size_t size, + __u64 valid) +{ + struct lookup_intent oit = { .it_op = IT_GETXATTR }; + struct ll_inode_info *lli = ll_i2info(inode); + int rc = 0; + + + + LASSERT(!!(valid & OBD_MD_FLXATTR) ^ !!(valid & OBD_MD_FLXATTRLS)); + + down_read(&lli->lli_xattrs_list_rwsem); + if (!ll_xattr_cache_valid(lli)) { + up_read(&lli->lli_xattrs_list_rwsem); + rc = ll_xattr_cache_refill(inode, &oit); + if (rc) + return rc; + downgrade_write(&lli->lli_xattrs_list_rwsem); + } else { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR_HITS, 1); + } + + if (valid & OBD_MD_FLXATTR) { + struct ll_xattr_entry *xattr; + + rc = ll_xattr_cache_find(&lli->lli_xattrs, name, &xattr); + if (rc == 0) { + rc = xattr->xe_vallen; + /* zero size means we are only requested size in rc */ + if (size != 0) { + if (size >= xattr->xe_vallen) + memcpy(buffer, xattr->xe_value, + xattr->xe_vallen); + else + rc = -ERANGE; + } + } + } else if (valid & OBD_MD_FLXATTRLS) { + rc = ll_xattr_cache_list(&lli->lli_xattrs, + size ? buffer : NULL, size); + } + + GOTO(out, rc); +out: + up_read(&lli->lli_xattrs_list_rwsem); + + return rc; +} + + +/** + * Set/update an xattr value or remove xattr using the write-through cache. + * + * Set/update the xattr value (if @valid has OBD_MD_FLXATTR) of @name to @newval + * or + * remove the xattr @name (@valid has OBD_MD_FLXATTRRM set) from @inode. + * @flags is either XATTR_CREATE or XATTR_REPLACE as defined by setxattr(2) + * + * \retval 0 no error occured + * \retval -EPROTO network protocol error + * \retval -ENOMEM not enough memory for the cache + * \retval -ERANGE the buffer is not large enough + * \retval -ENODATA no such attr (in the removal case) + */ +int ll_xattr_cache_update(struct inode *inode, + const char *name, + const char *newval, + size_t size, + __u64 valid, + int flags) +{ + struct lookup_intent oit = { .it_op = IT_SETXATTR }; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ptlrpc_request *req = NULL; + struct ll_inode_info *lli = ll_i2info(inode); + struct obd_capa *oc; + int rc; + + + + LASSERT(!!(valid & OBD_MD_FLXATTR) ^ !!(valid & OBD_MD_FLXATTRRM)); + + rc = ll_xattr_cache_refill(inode, &oit); + if (rc) + return rc; + + oc = ll_mdscapa_get(inode); + rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, + valid | OBD_MD_FLXATTRLOCKED, name, newval, + size, 0, flags, ll_i2suppgid(inode), &req); + capa_put(oc); + + if (rc) { + ll_intent_drop_lock(&oit); + GOTO(out, rc); + } + + if (valid & OBD_MD_FLXATTR) + rc = ll_xattr_cache_add(&lli->lli_xattrs, name, newval, size); + else if (valid & OBD_MD_FLXATTRRM) + rc = ll_xattr_cache_del(&lli->lli_xattrs, name); + + ll_intent_drop_lock(&oit); + GOTO(out, rc); +out: + up_write(&lli->lli_xattrs_list_rwsem); + ptlrpc_req_finished(req); + + return rc; +} diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index b995af6a2782..506982996c0e 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -72,6 +72,7 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, __u32 mode, __u64 rdev, __u64 flags, const void *data, int datalen); void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); +void mdc_getxattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, const char *old, int oldlen, const char *new, int newlen); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 09dee1120ed2..cc5490c3a603 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -360,6 +360,62 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, return req; } +static struct ptlrpc_request * +mdc_intent_getxattr_pack(struct obd_export *exp, + struct lookup_intent *it, + struct md_op_data *op_data) +{ + struct ptlrpc_request *req; + struct ldlm_intent *lit; + int rc, count = 0, maxdata; + LIST_HEAD(cancels); + + + + req = ptlrpc_request_alloc(class_exp2cliimp(exp), + &RQF_LDLM_INTENT_GETXATTR); + if (req == NULL) + return ERR_PTR(-ENOMEM); + + mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1); + + if (it->it_op == IT_SETXATTR) + /* If we want to upgrade to LCK_PW, let's cancel LCK_PR + * locks now. This avoids unnecessary ASTs. */ + count = mdc_resource_get_unused(exp, &op_data->op_fid1, + &cancels, LCK_PW, + MDS_INODELOCK_XATTR); + + rc = ldlm_prep_enqueue_req(exp, req, &cancels, count); + if (rc) { + ptlrpc_request_free(req); + return ERR_PTR(rc); + } + + /* pack the intent */ + lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT); + lit->opc = IT_GETXATTR; + + maxdata = class_exp2cliimp(exp)->imp_connect_data.ocd_max_easize; + + /* pack the intended request */ + mdc_pack_body(req, &op_data->op_fid1, op_data->op_capa1, + op_data->op_valid, maxdata, -1, 0); + + req_capsule_set_size(&req->rq_pill, &RMF_EADATA, + RCL_SERVER, maxdata); + + req_capsule_set_size(&req->rq_pill, &RMF_EAVALS, + RCL_SERVER, maxdata); + + req_capsule_set_size(&req->rq_pill, &RMF_EAVALS_LENS, + RCL_SERVER, maxdata); + + ptlrpc_request_set_replen(req); + + return req; +} + static struct ptlrpc_request *mdc_intent_unlink_pack(struct obd_export *exp, struct lookup_intent *it, struct md_op_data *op_data) @@ -735,6 +791,8 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, { .l_inodebits = { MDS_INODELOCK_UPDATE } }; static const ldlm_policy_data_t layout_policy = { .l_inodebits = { MDS_INODELOCK_LAYOUT } }; + static const ldlm_policy_data_t getxattr_policy = { + .l_inodebits = { MDS_INODELOCK_XATTR } }; ldlm_policy_data_t const *policy = &lookup_policy; int generation, resends = 0; struct ldlm_reply *lockrep; @@ -751,6 +809,8 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, policy = &update_policy; else if (it->it_op & IT_LAYOUT) policy = &layout_policy; + else if (it->it_op & (IT_GETXATTR | IT_SETXATTR)) + policy = &getxattr_policy; } LASSERT(reqp == NULL); @@ -781,9 +841,10 @@ resend: } else if (it->it_op & IT_LAYOUT) { if (!imp_connect_lvb_type(class_exp2cliimp(exp))) return -EOPNOTSUPP; - req = mdc_intent_layout_pack(exp, it, op_data); lvb_type = LVB_T_LAYOUT; + } else if (it->it_op & (IT_GETXATTR | IT_SETXATTR)) { + req = mdc_intent_getxattr_pack(exp, it, op_data); } else { LBUG(); return -EINVAL; diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index c4381eb5e8dd..eee88746e9d2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -462,6 +462,25 @@ static const struct req_msg_field *ldlm_intent_unlink_client[] = { &RMF_NAME }; +static const struct req_msg_field *ldlm_intent_getxattr_client[] = { + &RMF_PTLRPC_BODY, + &RMF_DLM_REQ, + &RMF_LDLM_INTENT, + &RMF_MDT_BODY, + &RMF_CAPA1, +}; + +static const struct req_msg_field *ldlm_intent_getxattr_server[] = { + &RMF_PTLRPC_BODY, + &RMF_DLM_REP, + &RMF_MDT_BODY, + &RMF_MDT_MD, + &RMF_ACL, /* for req_capsule_extend/mdt_intent_policy */ + &RMF_EADATA, + &RMF_EAVALS, + &RMF_EAVALS_LENS +}; + static const struct req_msg_field *mds_getxattr_client[] = { &RMF_PTLRPC_BODY, &RMF_MDT_BODY, @@ -739,6 +758,7 @@ static struct req_format *req_formats[] = { &RQF_LDLM_INTENT_OPEN, &RQF_LDLM_INTENT_CREATE, &RQF_LDLM_INTENT_UNLINK, + &RQF_LDLM_INTENT_GETXATTR, &RQF_LDLM_INTENT_QUOTA, &RQF_QUOTA_DQACQ, &RQF_LOG_CANCEL, @@ -1013,6 +1033,9 @@ struct req_msg_field RMF_EADATA = DEFINE_MSGF("eadata", 0, -1, NULL, NULL); EXPORT_SYMBOL(RMF_EADATA); +struct req_msg_field RMF_EAVALS = DEFINE_MSGF("eavals", 0, -1, NULL, NULL); +EXPORT_SYMBOL(RMF_EAVALS); + struct req_msg_field RMF_ACL = DEFINE_MSGF("acl", RMF_F_NO_SIZE_CHECK, LUSTRE_POSIX_ACL_MAX_SIZE, NULL, NULL); @@ -1064,6 +1087,11 @@ struct req_msg_field RMF_RCS = lustre_swab_generic_32s, dump_rcs); EXPORT_SYMBOL(RMF_RCS); +struct req_msg_field RMF_EAVALS_LENS = + DEFINE_MSGF("eavals_lens", RMF_F_STRUCT_ARRAY, sizeof(__u32), + lustre_swab_generic_32s, NULL); +EXPORT_SYMBOL(RMF_EAVALS_LENS); + struct req_msg_field RMF_OBD_ID = DEFINE_MSGF("obd_id", 0, sizeof(obd_id), lustre_swab_ost_last_id, NULL); @@ -1421,6 +1449,12 @@ struct req_format RQF_LDLM_INTENT_UNLINK = ldlm_intent_unlink_client, ldlm_intent_server); EXPORT_SYMBOL(RQF_LDLM_INTENT_UNLINK); +struct req_format RQF_LDLM_INTENT_GETXATTR = + DEFINE_REQ_FMT0("LDLM_INTENT_GETXATTR", + ldlm_intent_getxattr_client, + ldlm_intent_getxattr_server); +EXPORT_SYMBOL(RQF_LDLM_INTENT_GETXATTR); + struct req_format RQF_MDS_CLOSE = DEFINE_REQ_FMT0("MDS_CLOSE", mdt_close_client, mds_last_unlink_server); -- cgit v1.2.3 From 4504a3c11efad961f60888e8d81ef2c785dbf260 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 3 Dec 2013 21:58:50 +0800 Subject: staging/lustre: clean up SET_BUT_UNUSED/UNUSED macros This is SET_BUT_UNUSED/UNUSED macro cleaning up part of the original Lustre tree commit. Lustre-change: http://review.whamcloud.com/6139 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3204 Signed-off-by: Dmitry Eremin Signed-off-by: Ned Bass Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs.h | 2 -- drivers/staging/lustre/lnet/selftest/rpc.c | 2 -- drivers/staging/lustre/lnet/selftest/selftest.h | 3 -- drivers/staging/lustre/lnet/selftest/timer.c | 11 ++----- drivers/staging/lustre/lustre/llite/dcache.c | 34 +++++++++------------- 5 files changed, 17 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 687dbab2c4ec..4a6c7da72174 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -181,8 +181,6 @@ static inline void *__container_of(void *ptr, unsigned long shift) #define container_of0(ptr, type, member) \ ((type *)__container_of((void *)(ptr), offsetof(type, member))) -#define SET_BUT_UNUSED(a) do { } while(sizeof(a) - sizeof(a)) - #define _LIBCFS_H #endif /* _LIBCFS_H */ diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 7659a26676bb..5ae59d2a0dad 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -124,7 +124,6 @@ srpc_bulk_t * srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink) { srpc_bulk_t *bk; - struct page **pages; int i; LASSERT(bulk_npg > 0 && bulk_npg <= LNET_MAX_IOV); @@ -140,7 +139,6 @@ srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink) bk->bk_sink = sink; bk->bk_len = bulk_len; bk->bk_niov = bulk_npg; - UNUSED(pages); for (i = 0; i < bulk_npg; i++) { struct page *pg; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 8053b0563ff3..cd539263201a 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -572,9 +572,6 @@ swi_state2str (int state) #undef STATE2STR } -#define UNUSED(x) ( (void)(x) ) - - #define selftest_wait_events() cfs_pause(cfs_time_seconds(1) / 10) diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index 82fd363679cb..b8e50ef0bb4e 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -171,19 +171,14 @@ stt_check_timers(cfs_time_t *last) int stt_timer_main(void *arg) { - int rc = 0; - UNUSED(arg); - - SET_BUT_UNUSED(rc); - cfs_block_allsigs(); while (!stt_data.stt_shuttingdown) { stt_check_timers(&stt_data.stt_prev_slot); - rc = wait_event_timeout(stt_data.stt_waitq, - stt_data.stt_shuttingdown, - cfs_time_seconds(STTIMER_SLOTTIME)); + wait_event_timeout(stt_data.stt_waitq, + stt_data.stt_shuttingdown, + cfs_time_seconds(STTIMER_SLOTTIME)); } spin_lock(&stt_data.stt_lock); diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index e7629be39739..cbd663ed030c 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -404,7 +404,6 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, struct inode *inode = de->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct obd_client_handle **och_p; - __u64 *och_usecount; __u64 ibits; /* @@ -418,37 +417,32 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, */ - if (it->it_flags & FMODE_WRITE) { + if (it->it_flags & FMODE_WRITE) och_p = &lli->lli_mds_write_och; - och_usecount = &lli->lli_open_fd_write_count; - } else if (it->it_flags & FMODE_EXEC) { + else if (it->it_flags & FMODE_EXEC) och_p = &lli->lli_mds_exec_och; - och_usecount = &lli->lli_open_fd_exec_count; - } else { + else och_p = &lli->lli_mds_read_och; - och_usecount = &lli->lli_open_fd_read_count; - } + /* Check for the proper lock. */ ibits = MDS_INODELOCK_LOOKUP; if (!ll_have_md_lock(inode, &ibits, LCK_MINMODE)) goto do_lock; mutex_lock(&lli->lli_och_mutex); if (*och_p) { /* Everything is open already, do nothing */ - /*(*och_usecount)++; Do not let them steal our open - handle from under us */ - SET_BUT_UNUSED(och_usecount); - /* XXX The code above was my original idea, but in case - we have the handle, but we cannot use it due to later - checks (e.g. O_CREAT|O_EXCL flags set), nobody - would decrement counter increased here. So we just - hope the lock won't be invalidated in between. But - if it would be, we'll reopen the open request to - MDS later during file open path */ + /* Originally it was idea to do not let them steal our + * open handle from under us by (*och_usecount)++ here. + * But in case we have the handle, but we cannot use it + * due to later checks (e.g. O_CREAT|O_EXCL flags set), + * nobody would decrement counter increased here. So we + * just hope the lock won't be invalidated in between. + * But if it would be, we'll reopen the open request to + * MDS later during file open path. + */ mutex_unlock(&lli->lli_och_mutex); return 1; - } else { - mutex_unlock(&lli->lli_och_mutex); } + mutex_unlock(&lli->lli_och_mutex); } if (it->it_op == IT_GETATTR) { -- cgit v1.2.3 From f4420b2400c03beab7481328c63c8a7c30ee3df6 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 3 Dec 2013 21:58:51 +0800 Subject: staging/lustre/pinger: remove never implemented suspend timeouts functionality This is part of original Lustre tree commit. It removes never implemented suspend timeouts functionality from pinger.c which was commented out since 2007 and going to be replaced by adaptive timeouts. Also removed all references to this functionality from ldlm_lockd.c, ldlm_request.c and import.c which actually nevers executes or do nothing. Lustre-change: http://review.whamcloud.com/6139 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3204 Signed-off-by: Dmitry Eremin Signed-off-by: Ned Bass Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_ha.h | 3 - drivers/staging/lustre/lustre/include/lustre_net.h | 2 - drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 3 - drivers/staging/lustre/lustre/ptlrpc/import.c | 2 - drivers/staging/lustre/lustre/ptlrpc/pinger.c | 65 ---------------------- 5 files changed, 75 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_ha.h b/drivers/staging/lustre/lustre/include/lustre_ha.h index 105f6d61eef0..f3ae02b3eef3 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ha.h +++ b/drivers/staging/lustre/lustre/include/lustre_ha.h @@ -58,9 +58,6 @@ void ptlrpc_activate_import(struct obd_import *imp); void ptlrpc_deactivate_import(struct obd_import *imp); void ptlrpc_invalidate_import(struct obd_import *imp); void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt); -int ptlrpc_check_suspend(void); -void ptlrpc_activate_timeouts(struct obd_import *imp); -void ptlrpc_deactivate_timeouts(struct obd_import *imp); /** @} ha */ diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 91f28e363be2..6c5479b2d715 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -3403,10 +3403,8 @@ int ptlrpc_del_timeout_client(struct list_head *obd_list, enum timeout_event event); struct ptlrpc_request * ptlrpc_prep_ping(struct obd_import *imp); int ptlrpc_obd_ping(struct obd_device *obd); -cfs_time_t ptlrpc_suspend_wakeup_time(void); void ping_evictor_start(void); void ping_evictor_stop(void); -int ptlrpc_check_and_wait_suspend(struct ptlrpc_request *req); void ptlrpc_pinger_ir_up(void); void ptlrpc_pinger_ir_down(void); /** @} */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 4974becb3d9b..a8f8c1cace27 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -97,9 +97,6 @@ int ldlm_expired_completion_wait(void *data) if (lock->l_conn_export == NULL) { static cfs_time_t next_dump = 0, last_dump = 0; - if (ptlrpc_check_suspend()) - return 0; - LCONSOLE_WARN("lock timed out (enqueued at "CFS_TIME_T", " CFS_DURATION_T"s ago)\n", lock->l_last_activity, diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 283173a2fe23..f465547eb95e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -170,7 +170,6 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt) target_len, target_start, libcfs_nid2str(imp->imp_connection->c_peer.nid)); } - ptlrpc_deactivate_timeouts(imp); IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_DISCON); spin_unlock(&imp->imp_lock); @@ -383,7 +382,6 @@ void ptlrpc_activate_import(struct obd_import *imp) spin_lock(&imp->imp_lock); imp->imp_invalid = 0; - ptlrpc_activate_timeouts(imp); spin_unlock(&imp->imp_lock); obd_import_event(obd, imp, IMP_EVENT_ACTIVE); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index 4684b03c4a5f..6dff502ce23e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -141,9 +141,6 @@ static inline int ptlrpc_next_reconnect(struct obd_import *imp) return cfs_time_shift(obd_timeout); } -static atomic_t suspend_timeouts = ATOMIC_INIT(0); -static cfs_time_t suspend_wakeup_time = 0; - cfs_duration_t pinger_check_timeout(cfs_time_t time) { struct timeout_item *item; @@ -163,67 +160,6 @@ cfs_duration_t pinger_check_timeout(cfs_time_t time) cfs_time_current()); } -static wait_queue_head_t suspend_timeouts_waitq; - -cfs_time_t ptlrpc_suspend_wakeup_time(void) -{ - return suspend_wakeup_time; -} - -void ptlrpc_deactivate_timeouts(struct obd_import *imp) -{ - /*XXX: disabled for now, will be replaced by adaptive timeouts */ -#if 0 - if (imp->imp_no_timeout) - return; - imp->imp_no_timeout = 1; - atomic_inc(&suspend_timeouts); - CDEBUG(D_HA|D_WARNING, "deactivate timeouts %u\n", - atomic_read(&suspend_timeouts)); -#endif -} - -void ptlrpc_activate_timeouts(struct obd_import *imp) -{ - /*XXX: disabled for now, will be replaced by adaptive timeouts */ -#if 0 - if (!imp->imp_no_timeout) - return; - imp->imp_no_timeout = 0; - LASSERT(atomic_read(&suspend_timeouts) > 0); - if (atomic_dec_and_test(&suspend_timeouts)) { - suspend_wakeup_time = cfs_time_current(); - wake_up(&suspend_timeouts_waitq); - } - CDEBUG(D_HA|D_WARNING, "activate timeouts %u\n", - atomic_read(&suspend_timeouts)); -#endif -} - -int ptlrpc_check_suspend(void) -{ - if (atomic_read(&suspend_timeouts)) - return 1; - return 0; -} - -int ptlrpc_check_and_wait_suspend(struct ptlrpc_request *req) -{ - struct l_wait_info lwi; - - if (atomic_read(&suspend_timeouts)) { - DEBUG_REQ(D_NET, req, "-- suspend %d regular timeout", - atomic_read(&suspend_timeouts)); - lwi = LWI_INTR(NULL, NULL); - l_wait_event(suspend_timeouts_waitq, - atomic_read(&suspend_timeouts) == 0, &lwi); - DEBUG_REQ(D_NET, req, "-- recharge regular timeout"); - return 1; - } - return 0; -} - - static bool ir_up; void ptlrpc_pinger_ir_up(void) @@ -378,7 +314,6 @@ int ptlrpc_start_pinger(void) return -EALREADY; init_waitqueue_head(&pinger_thread.t_ctl_waitq); - init_waitqueue_head(&suspend_timeouts_waitq); strcpy(pinger_thread.t_name, "ll_ping"); -- cgit v1.2.3 From 645ae203b9f789f3c759c0c8a9f7f200f5beb8e6 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 3 Dec 2013 21:58:52 +0800 Subject: staging/lustre/obdclass: remove unuse variables from lprocfs_stats_collect/clear This is only part of the original Lustre tree commit splitted to follow the "one thing per patch" rule. Lustre-change: http://review.whamcloud.com/6139 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3204 Signed-off-by: Dmitry Eremin Signed-off-by: Ned Bass Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lprocfs_status.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 0f0750beab3b..882841923e5f 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -420,7 +420,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, { unsigned int num_entry; struct lprocfs_counter *percpu_cntr; - struct lprocfs_counter_header *cntr_header; int i; unsigned long flags = 0; @@ -439,7 +438,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, for (i = 0; i < num_entry; i++) { if (stats->ls_percpu[i] == NULL) continue; - cntr_header = &stats->ls_cnt_header[idx]; percpu_cntr = lprocfs_stats_counter_get(stats, i, idx); cnt->lc_count += percpu_cntr->lc_count; @@ -999,7 +997,6 @@ EXPORT_SYMBOL(lprocfs_free_stats); void lprocfs_clear_stats(struct lprocfs_stats *stats) { struct lprocfs_counter *percpu_cntr; - struct lprocfs_counter_header *header; int i; int j; unsigned int num_entry; @@ -1011,7 +1008,6 @@ void lprocfs_clear_stats(struct lprocfs_stats *stats) if (stats->ls_percpu[i] == NULL) continue; for (j = 0; j < stats->ls_num; j++) { - header = &stats->ls_cnt_header[j]; percpu_cntr = lprocfs_stats_counter_get(stats, i, j); percpu_cntr->lc_count = 0; percpu_cntr->lc_min = LC_MIN_INIT; -- cgit v1.2.3 From 87c7d31570076d73f1fe73ef8f01c1380b768a3b Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 3 Dec 2013 21:58:53 +0800 Subject: staging/lustre/ptlrpc: better error handling in ptlrpcd_start This is only part of the original Lustre tree commit. It cleans up ptlrpcd_start error handling a bit. Lustre-change: http://review.whamcloud.com/6139 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3204 Signed-off-by: Dmitry Eremin Signed-off-by: Ned Bass Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 2ebdb1b06dde..8a95fa5e1052 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -600,7 +600,6 @@ static int ptlrpcd_bind(int index, int max) int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) { int rc; - int env = 0; /* * Do not allow start second thread for one pc. @@ -619,6 +618,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) pc->pc_set = ptlrpc_prep_set(); if (pc->pc_set == NULL) GOTO(out, rc = -ENOMEM); + /* * So far only "client" ptlrpcd uses an environment. In the future, * ptlrpcd thread (or a thread-set) has to be given an argument, @@ -626,40 +626,40 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) */ rc = lu_context_init(&pc->pc_env.le_ctx, LCT_CL_THREAD|LCT_REMEMBER); if (rc != 0) - GOTO(out, rc); + GOTO(out_set, rc); - env = 1; { struct task_struct *task; - if (index >= 0) { rc = ptlrpcd_bind(index, max); if (rc < 0) - GOTO(out, rc); + GOTO(out_env, rc); } - task = kthread_run(ptlrpcd, pc, "%s", pc->pc_name); + task = kthread_run(ptlrpcd, pc, pc->pc_name); if (IS_ERR(task)) - GOTO(out, rc = PTR_ERR(task)); + GOTO(out_env, rc = PTR_ERR(task)); - rc = 0; wait_for_completion(&pc->pc_starting); } -out: - if (rc) { - if (pc->pc_set != NULL) { - struct ptlrpc_request_set *set = pc->pc_set; - - spin_lock(&pc->pc_lock); - pc->pc_set = NULL; - spin_unlock(&pc->pc_lock); - ptlrpc_set_destroy(set); - } - if (env != 0) - lu_context_fini(&pc->pc_env.le_ctx); - clear_bit(LIOD_BIND, &pc->pc_flags); - clear_bit(LIOD_START, &pc->pc_flags); + return 0; + +out_env: + lu_context_fini(&pc->pc_env.le_ctx); + +out_set: + if (pc->pc_set != NULL) { + struct ptlrpc_request_set *set = pc->pc_set; + + spin_lock(&pc->pc_lock); + pc->pc_set = NULL; + spin_unlock(&pc->pc_lock); + ptlrpc_set_destroy(set); } + clear_bit(LIOD_BIND, &pc->pc_flags); + +out: + clear_bit(LIOD_START, &pc->pc_flags); return rc; } -- cgit v1.2.3 From 52ee5b567c4cf3ee51af7836ff71d27c04491d2e Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:41:58 +0800 Subject: staging/lustre/obdclass: fix false used uninitialized warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Got below warning when building lustre with 4.7.3. drivers/staging/lustre/lustre/obdclass/llog_test.c: In function ‘ llog_test_init’: drivers/staging/lustre/lustre/obdclass/llog_test.c:1058:28: warning: ‘ lvars.module_vars’ is used uninitialized in this function [-Wuninitialized] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/llog_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/llog_test.c b/drivers/staging/lustre/lustre/obdclass/llog_test.c index 178f89eccab1..7427c125a3ab 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_test.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_test.c @@ -1048,7 +1048,7 @@ static struct obd_ops llog_obd_ops = { static int __init llog_test_init(void) { - struct lprocfs_static_vars lvars; + struct lprocfs_static_vars uninitialized_var(lvars); lprocfs_llog_test_init_vars(&lvars); return class_register_type(&llog_obd_ops, NULL, -- cgit v1.2.3 From 8cc420d057f2ed1941e76f0578b5b41dfe0bbc21 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:41:59 +0800 Subject: staging/lustre/obdclass: lprocfs_{alloc_stats,register} always defined No need to surround them with #ifdef LPROCFS. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/class_obd.c | 4 ++-- drivers/staging/lustre/lustre/obdclass/genops.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 4afd962cdb64..4fb1ecd08908 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -516,7 +516,7 @@ static int __init init_obdclass(void) spin_lock_init(&obd_types_lock); obd_zombie_impexp_init(); -#ifdef LPROCFS + obd_memory = lprocfs_alloc_stats(OBD_STATS_NUM, LPROCFS_STATS_FLAG_NONE | LPROCFS_STATS_FLAG_IRQ_SAFE); @@ -531,7 +531,7 @@ static int __init init_obdclass(void) lprocfs_counter_init(obd_memory, OBD_MEMORY_PAGES_STAT, LPROCFS_CNTR_AVGMINMAX, "pagesused", "pages"); -#endif + err = obd_init_checks(); if (err == -EOVERFLOW) return err; diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index f6fae16fc7f7..d9f750d42c80 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -193,7 +193,6 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, strcpy(type->typ_name, name); spin_lock_init(&type->obd_type_lock); -#ifdef LPROCFS type->typ_procroot = lprocfs_register(type->typ_name, proc_lustre_root, vars, type); if (IS_ERR(type->typ_procroot)) { @@ -201,7 +200,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, type->typ_procroot = NULL; GOTO (failed, rc); } -#endif + if (ldt != NULL) { type->typ_lu = ldt; rc = lu_device_type_init(ldt); -- cgit v1.2.3 From 0396ec9e93d68e140460bee7f3a5ae21abcf5d5e Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:42:01 +0800 Subject: staging/lustre/ldlm: inline ldlm_proc_setup Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_dlm.h | 3 ++- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index bc2b82ffae92..ec4bb5e3c13e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -1285,10 +1285,11 @@ void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client); void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client); void ldlm_namespace_get(struct ldlm_namespace *ns); void ldlm_namespace_put(struct ldlm_namespace *ns); -int ldlm_proc_setup(void); #ifdef LPROCFS +int ldlm_proc_setup(void); void ldlm_proc_cleanup(void); #else +static inline int ldlm_proc_setup(void) { return 0; } static inline void ldlm_proc_cleanup(void) {} #endif diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 85f5e7e42486..3ed020eb89c0 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -1012,11 +1012,9 @@ static int ldlm_setup(void) if (ldlm_state == NULL) return -ENOMEM; -#ifdef LPROCFS rc = ldlm_proc_setup(); if (rc != 0) GOTO(out, rc); -#endif memset(&conf, 0, sizeof(conf)); conf = (typeof(conf)) { -- cgit v1.2.3 From c7c5da015a4e142c4c7c77572a1e756136f7564b Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:42:02 +0800 Subject: staging/lustre/obdclass: move obd_sysctl_init out of class_procfs_init It is not strictly related to procfs. Besides, we already call obd_sysctl_clean outside of class_procfs_clean. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/class_obd.c | 3 +++ drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 4fb1ecd08908..7b1d1b685803 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -564,6 +564,9 @@ static int __init init_obdclass(void) err = obd_init_caches(); if (err) return err; + + obd_sysctl_init(); + err = class_procfs_init(); if (err) return err; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index d1a57ebfda95..2efc43720ecb 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -380,7 +380,6 @@ int class_procfs_init(void) { int rc = 0; - obd_sysctl_init(); proc_lustre_root = lprocfs_register("fs/lustre", NULL, lprocfs_base, NULL); if (IS_ERR(proc_lustre_root)) { -- cgit v1.2.3 From 62494681cdee38e7d2d6e3b485a3c8dc2a5f9ba9 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:42:04 +0800 Subject: staging/lustre: fix defined not used warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit register_sysctl_table/unregister_sysctl_table are defined regardless of CONFIG_SYSCTL true or false. so we don't need to surround them with #ifdef CONFIG_SYSCTL. Besides, current code got build warnings when CONFIG_SYSCTL is not set: drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c:368:20: warning: ‘lnet_table’ defined but not used [-Wunused-variable] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/router_proc.c | 4 ---- drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c | 8 -------- 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index daaa043ad118..e4fe7a116fb5 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -908,21 +908,17 @@ static ctl_table_t top_table[] = { void lnet_proc_init(void) { -#ifdef CONFIG_SYSCTL if (lnet_table_header == NULL) lnet_table_header = register_sysctl_table(top_table); -#endif } void lnet_proc_fini(void) { -#ifdef CONFIG_SYSCTL if (lnet_table_header != NULL) unregister_sysctl_table(lnet_table_header); lnet_table_header = NULL; -#endif } #else diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c index ef0ab106496f..e947b9128c58 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c @@ -65,9 +65,7 @@ #include #include "tracefile.h" -#ifdef CONFIG_SYSCTL static ctl_table_header_t *lnet_table_header = NULL; -#endif extern char lnet_upcall[1024]; /** * The path of debug log dump upcall script. @@ -518,7 +516,6 @@ static ctl_table_t lnet_table[] = { } }; -#ifdef CONFIG_SYSCTL static ctl_table_t top_table[] = { { .procname = "lnet", @@ -530,23 +527,18 @@ static ctl_table_t top_table[] = { { } }; -#endif int insert_proc(void) { -#ifdef CONFIG_SYSCTL if (lnet_table_header == NULL) lnet_table_header = register_sysctl_table(top_table); -#endif return 0; } void remove_proc(void) { -#ifdef CONFIG_SYSCTL if (lnet_table_header != NULL) unregister_sysctl_table(lnet_table_header); lnet_table_header = NULL; -#endif } -- cgit v1.2.3 From f4b406dc43af155715ad6bfd72d742db7d9c01ac Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 3 Dec 2013 22:42:05 +0800 Subject: staging/lustre/llite: fix used uninitialized warning Got below warning when building with sparc: drivers/staging/lustre/lustre/llite/file.c: In function 'll_file_aio_write': drivers/staging/lustre/lustre/llite/file.c:1247:9: warning: 'count' may be used uninitialized in this function [-Wuninitialized] drivers/staging/lustre/lustre/llite/file.c: In function 'll_file_aio_read': drivers/staging/lustre/lustre/llite/file.c:1188:9: warning: 'count' may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c1261357fd40..8f03eb0d2ff3 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1185,7 +1185,7 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, { struct lu_env *env; struct vvp_io_args *args; - size_t count; + size_t count = 0; ssize_t result; int refcheck; @@ -1244,7 +1244,7 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov, { struct lu_env *env; struct vvp_io_args *args; - size_t count; + size_t count = 0; ssize_t result; int refcheck; -- cgit v1.2.3 From e1b22732485396dda9b8eab90cdd1c636efc0a3e Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 3 Dec 2013 13:46:58 +0000 Subject: drm/i915: Fix copy/paste DP vs eDP error in comment It's all about tiny details. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e5eecfd5e47c..cc0a63349a9c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = { }; static const u32 bdw_ddi_translations_edp[] = { - 0x00FFFFFF, 0x00000012, /* DP parameters */ + 0x00FFFFFF, 0x00000012, /* eDP parameters */ 0x00EBAFFF, 0x00020011, 0x00C71FFF, 0x0006000F, 0x00FFFFFF, 0x00020011, -- cgit v1.2.3 From 7e11f9f4cacf71847716cec9d103b25d4c21e7a0 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 3 Dec 2013 13:47:00 +0000 Subject: drm/i915: Remove if 0'ed static arrays Sweeping some dead code away. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 82de200efa05..5f97be6f22ed 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1941,18 +1941,6 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ DP_LINK_STATUS_SIZE); } -#if 0 -static char *voltage_names[] = { - "0.4V", "0.6V", "0.8V", "1.2V" -}; -static char *pre_emph_names[] = { - "0dB", "3.5dB", "6dB", "9.5dB" -}; -static char *link_train_names[] = { - "pattern 1", "pattern 2", "idle", "off" -}; -#endif - /* * These are source-specific values; current Intel hardware supports * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB -- cgit v1.2.3 From 831eae69a855983099072e0c0e490bca6f02d54e Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 26 Nov 2013 18:58:01 -0700 Subject: staging: dwc2: set up all module params The DWC2 USB controller in the BCM2835 (Raspberry Pi) needs some non- default parameters. Select these based on the compatible value from the DT node. For all other HW, fall back to the default parameters currently in use. The values in params_bcm2835[] were posted to the mailing list by Paul quite some time ago. I made a couple of minor modifications since then; to set ahbcfg instead of ahb_single, and to set uframe_sched. Signed-off-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/staging/dwc2.txt | 4 +- drivers/staging/dwc2/platform.c | 58 ++++++++++++++++++---- 2 files changed, 51 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/staging/dwc2.txt b/Documentation/devicetree/bindings/staging/dwc2.txt index 1a1b7cfa4845..8b60e90efe33 100644 --- a/Documentation/devicetree/bindings/staging/dwc2.txt +++ b/Documentation/devicetree/bindings/staging/dwc2.txt @@ -2,7 +2,9 @@ Platform DesignWare HS OTG USB 2.0 controller ----------------------------------------------------- Required properties: -- compatible : "snps,dwc2" +- compatible : One of: + - brcm,bcm2835-usb: The DWC2 USB controller instance in the BCM2835 SoC. + - snps,dwc2: A generic DWC2 USB controller with default parameters. - reg : Should contain 1 register range (address and length) - interrupts : Should contain 1 interrupt diff --git a/drivers/staging/dwc2/platform.c b/drivers/staging/dwc2/platform.c index 4d9fac017044..28a78fe48453 100644 --- a/drivers/staging/dwc2/platform.c +++ b/drivers/staging/dwc2/platform.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "core.h" @@ -46,6 +47,34 @@ static const char dwc2_driver_name[] = "dwc2"; +static const struct dwc2_core_params params_bcm2835 = { + .otg_cap = 0, /* HNP/SRP capable */ + .otg_ver = 0, /* 1.3 */ + .dma_enable = 1, + .dma_desc_enable = 0, + .speed = 0, /* High Speed */ + .enable_dynamic_fifo = 1, + .en_multiple_tx_fifo = 1, + .host_rx_fifo_size = 774, /* 774 DWORDs */ + .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */ + .host_perio_tx_fifo_size = 512, /* 512 DWORDs */ + .max_transfer_size = 65535, + .max_packet_count = 511, + .host_channels = 8, + .phy_type = 1, /* UTMI */ + .phy_utmi_width = 8, /* 8 bits */ + .phy_ulpi_ddr = 0, /* Single */ + .phy_ulpi_ext_vbus = 0, + .i2c_enable = 0, + .ulpi_fs_ls = 0, + .host_support_fs_ls_low_power = 0, + .host_ls_low_power_phy_clk = 0, /* 48 MHz */ + .ts_dline = 0, + .reload_ctl = 0, + .ahbcfg = 0x10, + .uframe_sched = 1, +}; + /** * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the * DWC_otg driver @@ -66,6 +95,13 @@ static int dwc2_driver_remove(struct platform_device *dev) return 0; } +static const struct of_device_id dwc2_of_match_table[] = { + { .compatible = "brcm,bcm2835-usb", .data = ¶ms_bcm2835 }, + { .compatible = "snps,dwc2", .data = NULL }, + {}, +}; +MODULE_DEVICE_TABLE(of, dwc2_of_match_table); + /** * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg * driver @@ -80,14 +116,22 @@ static int dwc2_driver_remove(struct platform_device *dev) */ static int dwc2_driver_probe(struct platform_device *dev) { + const struct of_device_id *match; + const struct dwc2_core_params *params; + struct dwc2_core_params defparams; struct dwc2_hsotg *hsotg; struct resource *res; int retval; int irq; - struct dwc2_core_params params; - /* Default all params to autodetect */ - dwc2_set_all_params(¶ms, -1); + match = of_match_device(dwc2_of_match_table, &dev->dev); + if (match && match->data) { + params = match->data; + } else { + /* Default all params to autodetect */ + dwc2_set_all_params(&defparams, -1); + params = &defparams; + } hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); if (!hsotg) @@ -118,7 +162,7 @@ static int dwc2_driver_probe(struct platform_device *dev) dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); - retval = dwc2_hcd_init(hsotg, irq, ¶ms); + retval = dwc2_hcd_init(hsotg, irq, params); if (retval) return retval; @@ -127,12 +171,6 @@ static int dwc2_driver_probe(struct platform_device *dev) return retval; } -static const struct of_device_id dwc2_of_match_table[] = { - { .compatible = "snps,dwc2" }, - {}, -}; -MODULE_DEVICE_TABLE(of, dwc2_of_match_table); - static struct platform_driver dwc2_platform_driver = { .driver = { .name = dwc2_driver_name, -- cgit v1.2.3 From 6bf2e2a59769264f40c75a31b07603faab9460b5 Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Sat, 30 Nov 2013 19:33:57 +0200 Subject: Staging: dwc2: hcd.c: Fixed a coding style issue Fixed a coding style issue, specifically: Line 1798: Removed parentheses since return is not a function. Signed-off-by: Aldo Iljazi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 24a4efe874d6..24b57d7952c5 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -1795,7 +1795,7 @@ int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg) int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg) { - return (hsotg->op_state == OTG_STATE_B_HOST); + return hsotg->op_state == OTG_STATE_B_HOST; } static struct dwc2_hcd_urb *dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg, -- cgit v1.2.3 From ed5ca77ed7505cd389003a6d35ca1b7365429d71 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 2 Dec 2013 19:00:45 +0200 Subject: drm/i915: Avoid div-by-zero in clock calculation funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check that the N and P dividers don't cause a divide by zero. This shouldn't happen under normal circumstances, but can happen eg. under simulation. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0332d7ca892d..66b39dbaf12c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -329,6 +329,8 @@ static void vlv_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m1 * clock->m2; clock->p = clock->p1 * clock->p2; + if (WARN_ON(clock->n == 0 || clock->p == 0)) + return; clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); } @@ -430,6 +432,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m2 + 2; clock->p = clock->p1 * clock->p2; + if (WARN_ON(clock->n == 0 || clock->p == 0)) + return; clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); } @@ -443,6 +447,8 @@ static void i9xx_clock(int refclk, intel_clock_t *clock) { clock->m = i9xx_dpll_compute_m(clock); clock->p = clock->p1 * clock->p2; + if (WARN_ON(clock->n + 2 == 0 || clock->p == 0)) + return; clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); } -- cgit v1.2.3 From 7d4c0318f121bbba25d76fddd2f5ba3c01f318a6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 27 Nov 2013 08:38:19 +0800 Subject: staging: rts5208: fix error return code in rtsx_probe() Fix to return -ENOMEM instead of 0 when the memory alloc fail in probe error handling path. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 7882f578a8d9..8586ac5d2144 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -896,8 +896,10 @@ static int rtsx_probe(struct pci_dev *pci, memset(dev, 0, sizeof(struct rtsx_dev)); dev->chip = kzalloc(sizeof(struct rtsx_chip), GFP_KERNEL); - if (dev->chip == NULL) + if (dev->chip == NULL) { + err = -ENOMEM; goto errout; + } spin_lock_init(&dev->reg_lock); mutex_init(&(dev->dev_mutex)); -- cgit v1.2.3 From 5ba21c464b78e924ae74225e4080e42fea4560e8 Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Fri, 29 Nov 2013 14:55:37 +0200 Subject: Staging: dgnc: dgnc_trace.c: fixed coding style issues Fixed the following coding style issues: Lines 66-70: Replaced spaced with tabs. Lines 75, 98, 182: Inserted space before the open parenthesis. Line 89: Inserted spaces around that '=' Signed-off-by: Aldo Iljazi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_trace.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_trace.c b/drivers/staging/dgnc/dgnc_trace.c index a98b7d4255c8..e59b7813c355 100644 --- a/drivers/staging/dgnc/dgnc_trace.c +++ b/drivers/staging/dgnc/dgnc_trace.c @@ -63,16 +63,16 @@ void dgnc_tracef(const char *fmt, ...) void dgnc_tracef(const char *fmt, ...) { - va_list ap; - char buf[TRC_MAXMSG+1]; - size_t lenbuf; - int i; - static int failed = FALSE; + va_list ap; + char buf[TRC_MAXMSG+1]; + size_t lenbuf; + int i; + static int failed = FALSE; # if defined(TRC_TO_KMEM) unsigned long flags; #endif - if(failed) + if (failed) return; # if defined(TRC_TO_KMEM) DGNC_LOCK(dgnc_tracef_lock, flags); @@ -86,7 +86,7 @@ void dgnc_tracef(const char *fmt, ...) # if defined(TRC_TO_KMEM) { - static int initd=0; + static int initd = 0; /* * Now, in addition to (or instead of) printing this stuff out @@ -95,7 +95,7 @@ void dgnc_tracef(const char *fmt, ...) */ if (!initd) { dgnc_trcbuf = (char *) vmalloc(dgnc_trcbuf_size); - if(!dgnc_trcbuf) { + if (!dgnc_trcbuf) { failed = TRUE; printk("dgnc: tracing init failed!\n"); return; @@ -179,6 +179,6 @@ void dgnc_tracef(const char *fmt, ...) */ void dgnc_tracer_free(void) { - if(dgnc_trcbuf) + if (dgnc_trcbuf) vfree(dgnc_trcbuf); } -- cgit v1.2.3 From 14f4f4aa90473ece675df56062a9f14efbf00859 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 29 Nov 2013 18:05:01 +0100 Subject: staging: silicom: remove dead code bus_info field of struct ethtool_drvinfo is an array thus it always evaluates to true in a boolean context. Therefore operation depending on it being false will never be executed. Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bpctl_mod.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c index 39dc92a271ab..20325f53328e 100644 --- a/drivers/staging/silicom/bpctl_mod.c +++ b/drivers/staging/silicom/bpctl_mod.c @@ -135,8 +135,6 @@ static int bp_get_dev_idx_bsf(struct net_device *dev, int *index) else return -EOPNOTSUPP; - if (!drvinfo.bus_info) - return -ENODATA; if (!strcmp(drvinfo.bus_info, "N/A")) return -ENODATA; -- cgit v1.2.3 From 358bd68cbdf23797f7360948094b4920caf65877 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 29 Nov 2013 18:10:59 +0100 Subject: staging: lustre: fix potential NULL pointer dereference The rest of the code seem to imply that rmf_dumper may indeed be NULL. Change the code so that dumping is not even considered if rmf_dumper callback is not set. Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/layout.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index eee88746e9d2..dfcb410fe485 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -1882,8 +1882,11 @@ swabber_dumper_helper(struct req_capsule *pill, else do_swab = 0; + if (!field->rmf_dumper) + dump = 0; + if (!(field->rmf_flags & RMF_F_STRUCT_ARRAY)) { - if (dump && field->rmf_dumper) { + if (dump) { CDEBUG(D_RPCTRACE, "Dump of %sfield %s follows\n", do_swab ? "unswabbed " : "", field->rmf_name); field->rmf_dumper(value); @@ -1909,7 +1912,7 @@ swabber_dumper_helper(struct req_capsule *pill, for (p = value, i = 0, n = len / field->rmf_size; i < n; i++, p += field->rmf_size) { - if (dump && field->rmf_dumper) { + if (dump) { CDEBUG(D_RPCTRACE, "Dump of %sarray field %s, " "element %d follows\n", do_swab ? "unswabbed " : "", field->rmf_name, i); @@ -1918,7 +1921,7 @@ swabber_dumper_helper(struct req_capsule *pill, if (!do_swab) continue; swabber(p); - if (dump && field->rmf_dumper) { + if (dump) { CDEBUG(D_RPCTRACE, "Dump of swabbed array field %s, " "element %d follows\n", field->rmf_name, i); field->rmf_dumper(value); -- cgit v1.2.3 From 3229b869d14263c870ce0d3df18ce48fa02a40f2 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Wed, 27 Nov 2013 11:40:58 +0800 Subject: drivers: staging: ft1000: ft1000-usb: ft1000_debug.c: check return value of get_user() in ft1000_ioctl() get_user() may fail and cause 'msgsz' uninitialized, so need give a check. The related warning (with allmodconfig under hexagon): CC [M] drivers/staging/ft1000/ft1000-usb/ft1000_debug.o drivers/staging/ft1000/ft1000-usb/ft1000_debug.c: In function 'ft1000_ioctl': include/uapi/linux/swab.h:53:9: warning: 'msgsz' may be used uninitialized in this function [-Wuninitialized] drivers/staging/ft1000/ft1000-usb/ft1000_debug.c:533:17: note: 'msgsz' was declared here Signed-off-by: Chen Gang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-usb/ft1000_debug.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c index 68a55ce69200..ffdc7f597a96 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c @@ -560,6 +560,8 @@ static long ft1000_ioctl(struct file *file, unsigned int command, /* Get the length field to see how many bytes to copy */ result = get_user(msgsz, (__u16 __user *)argp); + if (result) + break; msgsz = ntohs(msgsz); /* DEBUG("FT1000:ft1000_ioctl: length of message = %d\n", msgsz); */ -- cgit v1.2.3 From 909cc6f9fa70bb8f4b183f62c6d095f2ad53deb8 Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Mon, 2 Dec 2013 15:22:29 +0200 Subject: Staging: usbip: vhci_hcd.c: removed a space Line 921: Removed the space before the semicolon. Signed-off-by: Aldo Iljazi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index aa22c631191c..72391ef87646 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -917,7 +917,7 @@ static void vhci_stop(struct usb_hcd *hcd) sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group); /* 2. shutdown all the ports of vhci_hcd */ - for (rhport = 0 ; rhport < VHCI_NPORTS; rhport++) { + for (rhport = 0; rhport < VHCI_NPORTS; rhport++) { struct vhci_device *vdev = &vhci->vdev[rhport]; usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED); -- cgit v1.2.3 From e445123975141a1f14b3c8f2aa96588f62a0c156 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 2 Dec 2013 11:26:09 -0200 Subject: drm/i915: use __packed instead of __attribute__((packed)) Checkpatch tells me WARNING: __packed is preferred over __attribute__((packed)) so switch over to __packed across the driver before adding new packed structs. Signed-off-by: Jani Nikula Signed-off-by: Rodrigo Vivi Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.h | 48 +++++++++++++++++----------------- drivers/gpu/drm/i915/intel_opregion.c | 8 +++--- drivers/gpu/drm/i915/intel_sdvo_regs.h | 40 ++++++++++++++-------------- 3 files changed, 48 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index f580a2b0ddd3..81ed58cb7b31 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -39,7 +39,7 @@ struct vbt_header { u8 reserved0; u32 bdb_offset; /**< from beginning of VBT */ u32 aim_offset[4]; /**< from beginning of VBT */ -} __attribute__((packed)); +} __packed; struct bdb_header { u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ @@ -65,7 +65,7 @@ struct vbios_data { u8 rsvd4; /* popup memory size */ u8 resize_pci_bios; u8 rsvd5; /* is crt already on ddc2 */ -} __attribute__((packed)); +} __packed; /* * There are several types of BIOS data blocks (BDBs), each block has @@ -142,7 +142,7 @@ struct bdb_general_features { u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */ u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */ u8 rsvd11:3; /* finish byte */ -} __attribute__((packed)); +} __packed; /* pre-915 */ #define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */ @@ -225,7 +225,7 @@ struct old_child_dev_config { u8 dvo2_wiring; u16 extended_type; u8 dvo_function; -} __attribute__((packed)); +} __packed; /* This one contains field offsets that are known to be common for all BDB * versions. Notice that the meaning of the contents contents may still change, @@ -238,7 +238,7 @@ struct common_child_dev_config { u8 not_common2[2]; u8 ddc_pin; u16 edid_ptr; -} __attribute__((packed)); +} __packed; /* This field changes depending on the BDB version, so the most reliable way to * read it is by checking the BDB version and reading the raw pointer. */ @@ -279,7 +279,7 @@ struct bdb_general_definitions { * sizeof(child_device_config); */ union child_device_config devices[0]; -} __attribute__((packed)); +} __packed; struct bdb_lvds_options { u8 panel_type; @@ -293,7 +293,7 @@ struct bdb_lvds_options { u8 lvds_edid:1; u8 rsvd2:1; u8 rsvd4; -} __attribute__((packed)); +} __packed; /* LFP pointer table contains entries to the struct below */ struct bdb_lvds_lfp_data_ptr { @@ -303,12 +303,12 @@ struct bdb_lvds_lfp_data_ptr { u8 dvo_table_size; u16 panel_pnp_id_offset; u8 pnp_table_size; -} __attribute__((packed)); +} __packed; struct bdb_lvds_lfp_data_ptrs { u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ struct bdb_lvds_lfp_data_ptr ptr[16]; -} __attribute__((packed)); +} __packed; /* LFP data has 3 blocks per entry */ struct lvds_fp_timing { @@ -325,7 +325,7 @@ struct lvds_fp_timing { u32 pfit_reg; u32 pfit_reg_val; u16 terminator; -} __attribute__((packed)); +} __packed; struct lvds_dvo_timing { u16 clock; /**< In 10khz */ @@ -353,7 +353,7 @@ struct lvds_dvo_timing { u8 vsync_positive:1; u8 hsync_positive:1; u8 rsvd2:1; -} __attribute__((packed)); +} __packed; struct lvds_pnp_id { u16 mfg_name; @@ -361,17 +361,17 @@ struct lvds_pnp_id { u32 serial; u8 mfg_week; u8 mfg_year; -} __attribute__((packed)); +} __packed; struct bdb_lvds_lfp_data_entry { struct lvds_fp_timing fp_timing; struct lvds_dvo_timing dvo_timing; struct lvds_pnp_id pnp_id; -} __attribute__((packed)); +} __packed; struct bdb_lvds_lfp_data { struct bdb_lvds_lfp_data_entry data[16]; -} __attribute__((packed)); +} __packed; struct aimdb_header { char signature[16]; @@ -379,12 +379,12 @@ struct aimdb_header { u16 aimdb_version; u16 aimdb_header_size; u16 aimdb_size; -} __attribute__((packed)); +} __packed; struct aimdb_block { u8 aimdb_id; u16 aimdb_size; -} __attribute__((packed)); +} __packed; struct vch_panel_data { u16 fp_timing_offset; @@ -395,12 +395,12 @@ struct vch_panel_data { u8 text_fitting_size; u16 graphics_fitting_offset; u8 graphics_fitting_size; -} __attribute__((packed)); +} __packed; struct vch_bdb_22 { struct aimdb_block aimdb_block; struct vch_panel_data panels[16]; -} __attribute__((packed)); +} __packed; struct bdb_sdvo_lvds_options { u8 panel_backlight; @@ -416,7 +416,7 @@ struct bdb_sdvo_lvds_options { u8 panel_misc_bits_2; u8 panel_misc_bits_3; u8 panel_misc_bits_4; -} __attribute__((packed)); +} __packed; #define BDB_DRIVER_FEATURE_NO_LVDS 0 @@ -462,7 +462,7 @@ struct bdb_driver_features { u8 hdmi_termination; u8 custom_vbt_version; -} __attribute__((packed)); +} __packed; #define EDP_18BPP 0 #define EDP_24BPP 1 @@ -487,14 +487,14 @@ struct edp_power_seq { u16 t9; u16 t10; u16 t11_t12; -} __attribute__ ((packed)); +} __packed; struct edp_link_params { u8 rate:4; u8 lanes:4; u8 preemphasis:4; u8 vswing:4; -} __attribute__ ((packed)); +} __packed; struct bdb_edp { struct edp_power_seq power_seqs[16]; @@ -505,7 +505,7 @@ struct bdb_edp { /* ith bit indicates enabled/disabled for (i+1)th panel */ u16 edp_s3d_feature; u16 edp_t3_optimization; -} __attribute__ ((packed)); +} __packed; void intel_setup_bios(struct drm_device *dev); int intel_parse_bios(struct drm_device *dev); @@ -733,6 +733,6 @@ struct bdb_mipi { u32 hl_switch_cnt; u32 lp_byte_clk; u32 clk_lane_switch_cnt; -} __attribute__((packed)); +} __packed; #endif /* _I830_BIOS_H_ */ diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 6506df26ac9e..853d13ea055f 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -64,7 +64,7 @@ struct opregion_header { u8 driver_ver[16]; u32 mboxes; u8 reserved[164]; -} __attribute__((packed)); +} __packed; /* OpRegion mailbox #1: public ACPI methods */ struct opregion_acpi { @@ -86,7 +86,7 @@ struct opregion_acpi { u32 cnot; /* current OS notification */ u32 nrdy; /* driver status */ u8 rsvd2[60]; -} __attribute__((packed)); +} __packed; /* OpRegion mailbox #2: SWSCI */ struct opregion_swsci { @@ -94,7 +94,7 @@ struct opregion_swsci { u32 parm; /* command parameters */ u32 dslp; /* driver sleep time-out */ u8 rsvd[244]; -} __attribute__((packed)); +} __packed; /* OpRegion mailbox #3: ASLE */ struct opregion_asle { @@ -115,7 +115,7 @@ struct opregion_asle { u32 srot; /* supported rotation angles */ u32 iuer; /* IUER events */ u8 rsvd[86]; -} __attribute__((packed)); +} __packed; /* Driver readiness indicator */ #define ASLE_ARDY_READY (1 << 0) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 770bdd6ecd9f..2e2d4eb4a00d 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -59,7 +59,7 @@ struct intel_sdvo_caps { unsigned int stall_support:1; unsigned int pad:1; u16 output_flags; -} __attribute__((packed)); +} __packed; /* Note: SDVO detailed timing flags match EDID misc flags. */ #define DTD_FLAG_HSYNC_POSITIVE (1 << 1) @@ -94,12 +94,12 @@ struct intel_sdvo_dtd { u8 v_sync_off_high; u8 reserved; } part2; -} __attribute__((packed)); +} __packed; struct intel_sdvo_pixel_clock_range { u16 min; /**< pixel clock, in 10kHz units */ u16 max; /**< pixel clock, in 10kHz units */ -} __attribute__((packed)); +} __packed; struct intel_sdvo_preferred_input_timing_args { u16 clock; @@ -108,7 +108,7 @@ struct intel_sdvo_preferred_input_timing_args { u8 interlace:1; u8 scaled:1; u8 pad:6; -} __attribute__((packed)); +} __packed; /* I2C registers for SDVO */ #define SDVO_I2C_ARG_0 0x07 @@ -162,7 +162,7 @@ struct intel_sdvo_get_trained_inputs_response { unsigned int input0_trained:1; unsigned int input1_trained:1; unsigned int pad:6; -} __attribute__((packed)); +} __packed; /** Returns a struct intel_sdvo_output_flags of active outputs. */ #define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 @@ -219,7 +219,7 @@ struct intel_sdvo_get_interrupt_event_source_response { unsigned int ambient_light_interrupt:1; unsigned int hdmi_audio_encrypt_change:1; unsigned int pad:6; -} __attribute__((packed)); +} __packed; /** * Selects which input is affected by future input commands. @@ -232,7 +232,7 @@ struct intel_sdvo_get_interrupt_event_source_response { struct intel_sdvo_set_target_input_args { unsigned int target_1:1; unsigned int pad:7; -} __attribute__((packed)); +} __packed; /** * Takes a struct intel_sdvo_output_flags of which outputs are targeted by @@ -370,7 +370,7 @@ struct intel_sdvo_tv_format { unsigned int hdtv_std_eia_7702a_480i_60:1; unsigned int hdtv_std_eia_7702a_480p_60:1; unsigned int pad:3; -} __attribute__((packed)); +} __packed; #define SDVO_CMD_GET_TV_FORMAT 0x28 @@ -401,7 +401,7 @@ struct intel_sdvo_sdtv_resolution_request { unsigned int secam_l:1; unsigned int secam_60:1; unsigned int pad:5; -} __attribute__((packed)); +} __packed; struct intel_sdvo_sdtv_resolution_reply { unsigned int res_320x200:1; @@ -426,7 +426,7 @@ struct intel_sdvo_sdtv_resolution_reply { unsigned int res_1024x768:1; unsigned int res_1280x1024:1; unsigned int pad:5; -} __attribute__((packed)); +} __packed; /* Get supported resolution with squire pixel aspect ratio that can be scaled for the requested HDTV format */ @@ -463,7 +463,7 @@ struct intel_sdvo_hdtv_resolution_request { unsigned int hdtv_std_eia_7702a_480i_60:1; unsigned int hdtv_std_eia_7702a_480p_60:1; unsigned int pad:6; -} __attribute__((packed)); +} __packed; struct intel_sdvo_hdtv_resolution_reply { unsigned int res_640x480:1; @@ -517,7 +517,7 @@ struct intel_sdvo_hdtv_resolution_reply { unsigned int res_1280x768:1; unsigned int pad5:7; -} __attribute__((packed)); +} __packed; /* Get supported power state returns info for encoder and monitor, rely on last SetTargetInput and SetTargetOutput calls */ @@ -557,13 +557,13 @@ struct sdvo_panel_power_sequencing { unsigned int t4_high:2; unsigned int pad:6; -} __attribute__((packed)); +} __packed; #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30 struct sdvo_max_backlight_reply { u8 max_value; u8 default_value; -} __attribute__((packed)); +} __packed; #define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31 #define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32 @@ -573,14 +573,14 @@ struct sdvo_get_ambient_light_reply { u16 trip_low; u16 trip_high; u16 value; -} __attribute__((packed)); +} __packed; #define SDVO_CMD_SET_AMBIENT_LIGHT 0x34 struct sdvo_set_ambient_light_reply { u16 trip_low; u16 trip_high; unsigned int enable:1; unsigned int pad:7; -} __attribute__((packed)); +} __packed; /* Set display power state */ #define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d @@ -608,7 +608,7 @@ struct intel_sdvo_enhancements_reply { unsigned int dither:1; unsigned int tv_chroma_filter:1; unsigned int tv_luma_filter:1; -} __attribute__((packed)); +} __packed; /* Picture enhancement limits below are dependent on the current TV format, * and thus need to be queried and set after it. @@ -630,7 +630,7 @@ struct intel_sdvo_enhancements_reply { struct intel_sdvo_enhancement_limits_reply { u16 max_value; u16 default_value; -} __attribute__((packed)); +} __packed; #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f #define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80 @@ -671,7 +671,7 @@ struct intel_sdvo_enhancement_limits_reply { #define SDVO_CMD_SET_TV_LUMA_FILTER 0x79 struct intel_sdvo_enhancements_arg { u16 value; -} __attribute__((packed)); +} __packed; #define SDVO_CMD_GET_DOT_CRAWL 0x70 #define SDVO_CMD_SET_DOT_CRAWL 0x71 @@ -727,4 +727,4 @@ struct intel_sdvo_enhancements_arg { struct intel_sdvo_encode { u8 dvi_rev; u8 hdmi_rev; -} __attribute__ ((packed)); +} __packed; -- cgit v1.2.3 From 54c136d4e525684a3310e3dd76de8ae81d7dbbf7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2013 09:57:16 +0000 Subject: drm/i915: Add a timing breadcrumb to panel waits When inspecting reports that boot/suspend/resume times are unusual it would be useful to clearly identify the time we must spend waiting for the hardware to complete its task. In this case we have a notification before we start waiting for the panel to change state, but none afterwards - which would be useful. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5f97be6f22ed..d45b311c1ab6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1037,6 +1037,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp, I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg)); } + + DRM_DEBUG_KMS("Wait complete\n"); } static void ironlake_wait_panel_on(struct intel_dp *intel_dp) -- cgit v1.2.3 From 15d2006970edfc580e1508f96bbbf788ffb991e4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:32 -0700 Subject: staging: comedi: pcmmio.c: remove kcalloc() failure message An allocation failure will have already displayed a message. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmmio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 063496d6c00e..ec098d883eb7 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -991,11 +991,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->sprivs = kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private), GFP_KERNEL); - if (!devpriv->sprivs) { - printk(KERN_ERR "comedi%d: cannot allocate subdevice private data structures\n", - dev->minor); + if (!devpriv->sprivs) return -ENOMEM; - } ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret) -- cgit v1.2.3 From 96a1f91ae2959e977e261528d4b0fb16a37f1d06 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:33 -0700 Subject: staging: comedi: adv_pci1710: convert some printk's to dev_dbg() Convert these debug messages to dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adv_pci1710.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index bac5e0dcc685..a1519c98022f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -740,16 +740,15 @@ static void interrupt_pci1710_every_sample(void *d) m = inw(dev->iobase + PCI171x_STATUS); if (m & Status_FE) { - printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m); + dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", m); pci171x_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); return; } if (m & Status_FF) { - printk - ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", - dev->minor, m); + dev_dbg(dev->class_dev, + "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); pci171x_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); @@ -825,12 +824,12 @@ static int move_block_from_fifo(struct comedi_device *dev, sampl = inw(dev->iobase + PCI171x_AD_DATA); if (this_board->cardtype != TYPE_PCI1713) if ((sampl & 0xf000) != devpriv->act_chanlist[j]) { - printk - ("comedi%d: A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n", - dev->minor, (sampl & 0xf000) >> 12, - (devpriv->act_chanlist[j] & 0xf000) >> 12, - i, j, devpriv->ai_act_scan, n, turn, - sampl); + dev_dbg(dev->class_dev, + "A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n", + (sampl & 0xf000) >> 12, + (devpriv->act_chanlist[j] & 0xf000) >> 12, + i, j, devpriv->ai_act_scan, n, turn, + sampl); pci171x_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; @@ -865,17 +864,15 @@ static void interrupt_pci1710_half_fifo(void *d) m = inw(dev->iobase + PCI171x_STATUS); if (!(m & Status_FH)) { - printk("comedi%d: A/D FIFO not half full! (%4x)\n", - dev->minor, m); + dev_dbg(dev->class_dev, "A/D FIFO not half full! (%4x)\n", m); pci171x_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); return; } if (m & Status_FF) { - printk - ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", - dev->minor, m); + dev_dbg(dev->class_dev, + "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); pci171x_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); -- cgit v1.2.3 From 9b35db028f7f5c375ab9cef095ea48250d4c15ff Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:34 -0700 Subject: staging: comedi: dmm32at: remove final attach noise and fix return value The "success" message after an attach is just added noise. Remove it. The normal return value for "success" is 0. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index cac83585ef86..bd192de319d3 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -793,11 +793,7 @@ static int dmm32at_attach(struct comedi_device *dev, s->insn_bits = dmm32at_dio_insn_bits; s->insn_config = dmm32at_dio_insn_config; - /* success */ - printk(KERN_INFO "comedi%d: dmm32at: attached\n", dev->minor); - - return 1; - + return 0; } static struct comedi_driver dmm32at_driver = { -- cgit v1.2.3 From 5adbc856a7e2ac5c710492afcfdfb48325d81653 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:35 -0700 Subject: staging: comedi: pcl812: convert some printk's to dev_dbg() Convert these debug messages to dev_dbg() and tidy them up a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 03315abcca19..e31cf44faa33 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -404,9 +404,7 @@ static int pcl812_ai_insn_read(struct comedi_device *dev, goto conv_finish; udelay(1); } - printk - ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n", - dev->minor, dev->board_name, dev->iobase); + dev_dbg(dev->class_dev, "A/D insn read timeout\n"); outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); return -ETIME; @@ -441,9 +439,7 @@ static int acl8216_ai_insn_read(struct comedi_device *dev, goto conv_finish; udelay(1); } - printk - ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n", - dev->minor, dev->board_name, dev->iobase); + dev_dbg(dev->class_dev, "A/D insn read timeout\n"); outb(0, dev->iobase + PCL812_MODE); return -ETIME; @@ -786,10 +782,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) } if (err) { - printk - ("comedi%d: pcl812: (%s at 0x%lx) " - "A/D cmd IRQ without DRDY!\n", - dev->minor, dev->board_name, dev->iobase); + dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n"); pcl812_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); -- cgit v1.2.3 From 5e1503aea7f46dcd5ebc2b929d7368a2f175bfb8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:36 -0700 Subject: staging: comedi: pcl816: convert some printk's to dev_dbg() Convert these warning messages to dev_dbg() to minimize the noise. Also, tidy them up a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 7b92aa50aa7f..8776c596bad2 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -800,12 +800,10 @@ check_channel_list(struct comedi_device *dev, (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ - printk(KERN_WARNING - "comedi%d: pcl816: channel list must " - "be continuous! chanlist[%i]=%d but " - "must be %d or %d!\n", dev->minor, - i, CR_CHAN(chanlist[i]), nowmustbechan, - CR_CHAN(chanlist[0])); + dev_dbg(dev->class_dev, + "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); return 0; } /* well, this is next correct channel in list */ @@ -815,16 +813,14 @@ check_channel_list(struct comedi_device *dev, /* check whole chanlist */ for (i = 0, segpos = 0; i < chanlen; i++) { if (chanlist[i] != chansegment[i % seglen]) { - printk(KERN_WARNING - "comedi%d: pcl816: bad channel or range" - " number! chanlist[%i]=%d,%d,%d and not" - " %d,%d,%d!\n", dev->minor, i, - CR_CHAN(chansegment[i]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); + dev_dbg(dev->class_dev, + "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); return 0; /* chan/gain list is strange */ } } -- cgit v1.2.3 From 84f03cf1d5912da90eca069a3458a3aea5d5fa8a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:37 -0700 Subject: staging: comedi: pcl818: convert some printk's to dev_dbg() Convert these messages to dev_dbg() and tidy them up a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index be9cb8df877d..def79c5b1a66 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -910,10 +910,10 @@ static int check_channel_list(struct comedi_device *dev, nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ - printk - ("comedi%d: pcl818: channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", - dev->minor, i, CR_CHAN(chanlist[i]), - nowmustbechan, CR_CHAN(chanlist[0])); + dev_dbg(dev->class_dev, + "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); return 0; } /* well, this is next correct channel in list */ @@ -924,14 +924,14 @@ static int check_channel_list(struct comedi_device *dev, for (i = 0, segpos = 0; i < n_chan; i++) { /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */ if (chanlist[i] != chansegment[i % seglen]) { - printk - ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", - dev->minor, i, CR_CHAN(chansegment[i]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); + dev_dbg(dev->class_dev, + "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); return 0; /* chan/gain list is strange */ } } -- cgit v1.2.3 From e9c76f3f67eb7d1187d8bc7c9165aabc5057103f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:38 -0700 Subject: staging: comedi: adq12b: remove commented out debug message Remove the commented out message, it would just be added noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adq12b.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 8150a67cd1fb..79e06b9b6bc9 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -162,8 +162,6 @@ static int adq12b_ai_rinsn(struct comedi_device *dev, hi = inb(dev->iobase + ADQ12B_ADHIG); lo = inb(dev->iobase + ADQ12B_ADLOW); - /* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", - channel, range, status, hi, lo); */ data[n] = (hi << 8) | lo; } -- cgit v1.2.3 From c89d6ea38819b5defb7d24584ed9cf87efe8366a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:39 -0700 Subject: staging: comedi: c6xdigio: remove commented out subdevice code The code to initialize subdevice[2] is commented out and incomplete. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/c6xdigio.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index a85b9493071f..7512eaf546a7 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -338,26 +338,6 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device *dev, return i; } -/* static int c6xdigio_ei_init_insn_read(struct comedi_device *dev, */ -/* struct comedi_subdevice *s, */ -/* struct comedi_insn *insn, */ -/* unsigned int *data) */ -/* { */ -/* printk("c6xdigio_ei_init_insn_read %x\n", insn->n); */ -/* return insn->n; */ -/* } */ - -/* static int c6xdigio_ei_init_insn_write(struct comedi_device *dev, */ -/* struct comedi_subdevice *s, */ -/* struct comedi_insn *insn, */ -/* unsigned int *data) */ -/* { */ -/* int i; */ -/* int chan = CR_CHAN(insn->chanspec); */ - /* *//* C6X_encResetAll( dev->iobase ); */ - /* *//* return insn->n; */ -/* } */ - static int c6xdigio_ei_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -432,17 +412,6 @@ static int c6xdigio_attach(struct comedi_device *dev, s->maxdata = 0xffffff; s->range_table = &range_unknown; - /* s = &dev->subdevices[2]; */ - /* pwm output subdevice */ - /* s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here */ - /* s->subdev_flags = SDF_WRITEABLE; */ - /* s->n_chan = 1; */ - /* s->trig[0] = c6xdigio_ei_init; */ - /* s->insn_read = c6xdigio_ei_init_insn_read; */ - /* s->insn_write = c6xdigio_ei_init_insn_write; */ - /* s->maxdata = 0xFFFF; // Really just a don't care */ - /* s->range_table = &range_unknown; // Not sure what to put here */ - /* I will call this init anyway but more than likely the DSP board */ /* will not be connected when device driver is loaded. */ board_init(dev); -- cgit v1.2.3 From 4dfe3df9b3fa1bb4d30ee5ae2e360cfe72026459 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:40 -0700 Subject: staging: comedi: c6xdigio: remove commented out function trace messages These commented out messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/c6xdigio.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 7512eaf546a7..5034f663eec9 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -94,8 +94,6 @@ static void C6X_pwmInit(unsigned long baseAddr) { int timeout = 0; -/* printk("Inside C6X_pwmInit\n"); */ - WriteByteToHwPort(baseAddr, 0x70); while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { @@ -132,8 +130,6 @@ static void C6X_pwmOutput(unsigned long baseAddr, unsigned channel, int value) int timeout = 0; unsigned tmp; - /* printk("Inside C6X_pwmOutput\n"); */ - pwm.cmd = value; if (pwm.cmd > 498) pwm.cmd = 498; @@ -200,8 +196,6 @@ static int C6X_encInput(unsigned long baseAddr, unsigned channel) int timeout = 0; int tmp; - /* printk("Inside C6X_encInput\n"); */ - enc.value = 0; if (channel == 0) ppcmd = 0x48; @@ -295,8 +289,6 @@ static void C6X_encResetAll(unsigned long baseAddr) { unsigned timeout = 0; -/* printk("Inside C6X_encResetAll\n"); */ - WriteByteToHwPort(baseAddr, 0x68); while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { @@ -330,7 +322,6 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device *dev, int i; int chan = CR_CHAN(insn->chanspec); - /* printk("c6xdigio_pwmo_insn_write %x\n", insn->n); */ for (i = 0; i < insn->n; i++) { C6X_pwmOutput(dev->iobase, chan, data[i]); /* devpriv->ao_readback[chan] = data[i]; */ @@ -342,7 +333,6 @@ static int c6xdigio_ei_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - /* printk("c6xdigio_ei__insn_read %x\n", insn->n); */ int n; int chan = CR_CHAN(insn->chanspec); @@ -354,12 +344,8 @@ static int c6xdigio_ei_insn_read(struct comedi_device *dev, static void board_init(struct comedi_device *dev) { - - /* printk("Inside board_init\n"); */ - C6X_pwmInit(dev->iobase); C6X_encResetAll(dev->iobase); - } static const struct pnp_device_id c6xdigio_pnp_tbl[] = { -- cgit v1.2.3 From 279579e40b0b2982cf9a2df10d999b6aecf43509 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:41 -0700 Subject: staging: comedi: cb_pcimdas: remove commented out irq init code This driver does not have interrupt support. Remove the commented out code that requests the irq. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcimdas.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 04dc2005454a..da669501b533 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -219,15 +219,6 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, devpriv->BADR3 = pci_resource_start(pcidev, 3); iobase_8255 = pci_resource_start(pcidev, 4); -/* Dont support IRQ yet */ -/* get irq */ -/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */ -/* { */ -/* printk(" unable to allocate irq %u\n", pcidev->irq); */ -/* return -EINVAL; */ -/* } */ -/* dev->irq = pcidev->irq; */ - ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; -- cgit v1.2.3 From b8cd7941a028891d2ca3d0927f9ed6ef4cf4c3e0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:42 -0700 Subject: staging: comedi: cb_pcimdas: remove unnecessary printk noise The ai read timeout will return -ETIMEDOUT. The printk is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcimdas.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index da669501b533..57295d189ff6 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -142,10 +142,9 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, if (!busy) break; } - if (i == TIMEOUT) { - printk("timeout\n"); + if (i == TIMEOUT) return -ETIMEDOUT; - } + /* read data */ data[n] = inw(dev->iobase + 0); } -- cgit v1.2.3 From 729988507680b2ce934bce61d9ce0ea7b235914c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:43 -0700 Subject: staging: comedi: das16m1: tidy up the irq support in das16m1_attach() An irq is only needed by this driver in order to support async commands. Since it is optional, modify the attach so that if an invalid irq is selected by the user, or the request_irq() fails, the attach does not fail. Remove all the printk noise about the irq. Only hookup the async command support if the request_irq() was successful. Tidy up das16m1_irq_bits() a bit. This helper returns the value that needs to be written to the DAS16M1_INTR_CONTROL register to setup the irq routing. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16m1.c | 78 +++++++++++--------------------- 1 file changed, 26 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index fce9acfe8084..0081ee4f4dc1 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -508,38 +508,26 @@ static irqreturn_t das16m1_interrupt(int irq, void *d) static int das16m1_irq_bits(unsigned int irq) { - int ret; - switch (irq) { case 10: - ret = 0x0; - break; + return 0x0; case 11: - ret = 0x1; - break; + return 0x1; case 12: - ret = 0x2; - break; + return 0x2; case 15: - ret = 0x3; - break; + return 0x3; case 2: - ret = 0x4; - break; + return 0x4; case 3: - ret = 0x5; - break; + return 0x5; case 5: - ret = 0x6; - break; + return 0x6; case 7: - ret = 0x7; - break; + return 0x7; default: - return -1; - break; + return 0x0; } - return ret << 4; } /* @@ -553,7 +541,6 @@ static int das16m1_attach(struct comedi_device *dev, struct das16m1_private_struct *devpriv; struct comedi_subdevice *s; int ret; - unsigned int irq; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -569,24 +556,12 @@ static int das16m1_attach(struct comedi_device *dev, return ret; devpriv->extra_iobase = dev->iobase + DAS16M1_82C55; - /* now for the irq */ - irq = it->options[1]; - /* make sure it is valid */ - if (das16m1_irq_bits(irq) >= 0) { - ret = request_irq(irq, das16m1_interrupt, 0, - dev->driver->driver_name, dev); - if (ret < 0) - return ret; - dev->irq = irq; - printk - ("irq %u\n", irq); - } else if (irq == 0) { - printk - (", no irq\n"); - } else { - comedi_error(dev, "invalid irq\n" - " valid irqs are 2, 3, 5, 7, 10, 11, 12, or 15\n"); - return -EINVAL; + /* only irqs 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, and 15 are valid */ + if ((1 << it->options[1]) & 0xdcfc) { + ret = request_irq(it->options[1], das16m1_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } ret = comedi_alloc_subdevices(dev, 4); @@ -594,20 +569,22 @@ static int das16m1_attach(struct comedi_device *dev, return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; /* ai */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_DIFF; s->n_chan = 8; - s->subdev_flags = SDF_DIFF; - s->len_chanlist = 256; s->maxdata = (1 << 12) - 1; s->range_table = &range_das16m1; s->insn_read = das16m1_ai_rinsn; - s->do_cmdtest = das16m1_cmd_test; - s->do_cmd = das16m1_cmd_exec; - s->cancel = das16m1_cancel; - s->poll = das16m1_poll; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 256; + s->do_cmdtest = das16m1_cmd_test; + s->do_cmd = das16m1_cmd_exec; + s->cancel = das16m1_cancel; + s->poll = das16m1_poll; + } s = &dev->subdevices[1]; /* di */ @@ -640,10 +617,7 @@ static int das16m1_attach(struct comedi_device *dev, outb(0, dev->iobase + DAS16M1_DIO); /* set the interrupt level */ - if (dev->irq) - devpriv->control_state = das16m1_irq_bits(dev->irq); - else - devpriv->control_state = 0; + devpriv->control_state = das16m1_irq_bits(dev->irq) << 4; outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); return 0; -- cgit v1.2.3 From 65e2618fd3bbe9c3776048212dc15ddc7fe61451 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:44 -0700 Subject: staging: comedi: dmm32at: remove unnecessary printk noise A timeout will return -ETIMEDOUT. The printks are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index bd192de319d3..f057d7995bad 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -199,10 +199,8 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, if ((status & DMM32AT_STATUS) == 0) break; } - if (i == 40000) { - printk(KERN_WARNING "dmm32at: timeout\n"); + if (i == 40000) return -ETIMEDOUT; - } /* convert n samples */ for (n = 0; n < insn->n; n++) { @@ -214,10 +212,8 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, if ((status & DMM32AT_STATUS) == 0) break; } - if (i == 40000) { - printk(KERN_WARNING "dmm32at: timeout\n"); + if (i == 40000) return -ETIMEDOUT; - } /* read data */ lsb = inb(dev->iobase + DMM32AT_AILSB); @@ -453,10 +449,8 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if ((status & DMM32AT_STATUS) == 0) break; } - if (i == 40000) { - printk(KERN_WARNING "dmm32at: timeout\n"); + if (i == 40000) return -ETIMEDOUT; - } if (devpriv->ai_scans_left > 1) { /* start the clock and enable the interrupts */ @@ -567,10 +561,9 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, if ((status & DMM32AT_DACBUSY) == 0) break; } - if (i == 40000) { - printk(KERN_WARNING "dmm32at: timeout\n"); + if (i == 40000) return -ETIMEDOUT; - } + /* dummy read to update trigger the output */ status = inb(dev->iobase + DMM32AT_DACMSB); -- cgit v1.2.3 From 49220f916d9a90e468b60d9dd8fde789e239c632 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:45 -0700 Subject: staging: comedi: dmm32at: remove commented out printk debug These printk messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index f057d7995bad..6fb8ce1d110c 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -182,8 +182,6 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, chan = CR_CHAN(insn->chanspec) & (s->n_chan - 1); range = CR_RANGE(insn->chanspec); - /* printk("channel=0x%02x, range=%d\n",chan,range); */ - /* zero scan and fifo control and reset fifo */ outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL); @@ -461,8 +459,6 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outb(0xff, dev->iobase + DMM32AT_CONV); } -/* printk("dmmat32 in command\n"); */ - /* for(i=0;ichanlist_len;i++) */ /* comedi_buf_put(s->async,i*100); */ @@ -550,7 +546,6 @@ static int dmm32at_ao_winsn(struct comedi_device *dev, lo = data[i] & 0x00ff; /* high byte also contains channel number */ hi = (data[i] >> 8) + chan * (1 << 6); - /* printk("writing 0x%02x 0x%02x\n",hi,lo); */ /* write the low and high values to the board */ outb(lo, dev->iobase + DMM32AT_DACLSB); outb(hi, dev->iobase + DMM32AT_DACMSB); -- cgit v1.2.3 From 0c2e55324199d89aaea816ce7a76571c3f88d158 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:46 -0700 Subject: staging: comedi: dmm32at: tidy up the irq support in dmm32at_attach() An irq is only needed by this driver in order to support async commands. Since it is optional, modify the attach so that if the request_irq() fails the attach does not fail. Remove the printk noise about the irq. Only hookup the async command support if the request_irq() was successful. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 6fb8ce1d110c..1831f3288ca8 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -670,9 +670,6 @@ static int dmm32at_attach(struct comedi_device *dev, int ret; struct comedi_subdevice *s; unsigned char aihi, ailo, fifostat, aistat, intstat, airback; - unsigned int irq; - - irq = it->options[1]; ret = comedi_request_region(dev, it->options[0], DMM32AT_MEMSIZE); if (ret) @@ -717,14 +714,11 @@ static int dmm32at_attach(struct comedi_device *dev, return -EIO; } - /* board is there, register interrupt */ - if (irq) { - ret = request_irq(irq, dmm32at_isr, 0, dev->board_name, dev); - if (ret < 0) { - printk(KERN_ERR "dmm32at: irq conflict\n"); - return ret; - } - dev->irq = irq; + if (it->options[1]) { + ret = request_irq(it->options[1], dmm32at_isr, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); @@ -736,20 +730,22 @@ static int dmm32at_attach(struct comedi_device *dev, return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; /* we support single-ended (ground) and differential */ - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = 32; s->maxdata = 0xffff; s->range_table = &dmm32at_airanges; - s->len_chanlist = 32; /* This is the maximum chanlist length that - the board can handle */ s->insn_read = dmm32at_ai_rinsn; - s->do_cmd = dmm32at_ai_cmd; - s->do_cmdtest = dmm32at_ai_cmdtest; - s->cancel = dmm32at_ai_cancel; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 32; + s->do_cmd = dmm32at_ai_cmd; + s->do_cmdtest = dmm32at_ai_cmdtest; + s->cancel = dmm32at_ai_cancel; + } s = &dev->subdevices[1]; /* analog output subdevice */ -- cgit v1.2.3 From 45d351031e1326a4d0a988c776f23673f7e1ffd2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:47 -0700 Subject: staging: comedi: dmm32at: convert a printk(KERN_ERR to a dev->err() Convert this printk message to a dev_err() message. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dmm32at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 1831f3288ca8..174735d37b51 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -710,7 +710,7 @@ static int dmm32at_attach(struct comedi_device *dev, if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) || (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) { - printk(KERN_ERR "dmmat32: board detection failed\n"); + dev_err(dev->class_dev, "board detection failed\n"); return -EIO; } -- cgit v1.2.3 From cd5afa443a6f120ef1003acd57be4bd7cc8b97bb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:48 -0700 Subject: staging: comedi: dt2801: remove disabled code in dt2801_writedata The code that checks the DT_S_READY status is disabled. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2801.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 1dd8190970e3..a1b022cfe712 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -289,13 +289,6 @@ static int dt2801_writedata(struct comedi_device *dev, unsigned int data) outb_p(data & 0xff, dev->iobase + DT2801_DATA); return 0; } -#if 0 - if (stat & DT_S_READY) { - printk - ("dt2801: ready flag set (bad!) in dt2801_writedata()\n"); - return -EIO; - } -#endif } while (--timeout > 0); return -ETIME; -- cgit v1.2.3 From 5fc517cd94f56d07c614d300d83289ce3977ee90 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:49 -0700 Subject: staging: comedi: dt2801: remove commented out printk() This printk is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2801.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index a1b022cfe712..065e78060935 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -372,7 +372,6 @@ static int dt2801_reset(struct comedi_device *dev) if (!timeout) printk("dt2801: timeout 1 status=0x%02x\n", stat); - /* printk("dt2801: reading dummy\n"); */ /* dt2801_readdata(dev,&board_code); */ outb_p(DT_C_RESET, dev->iobase + DT2801_CMD); -- cgit v1.2.3 From f3b672cf44ab1656098fbe3a8b087fd33d0e8a11 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:50 -0700 Subject: staging: comedi: dt2801: convert printk() messages to dev_dbg() Convert all the printk() messages in this driver to dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2801.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 065e78060935..4bf2c7f8f551 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -336,11 +336,11 @@ static int dt2801_writecmd(struct comedi_device *dev, int command) stat = inb_p(dev->iobase + DT2801_STATUS); if (stat & DT_S_COMPOSITE_ERROR) { - printk - ("dt2801: composite-error in dt2801_writecmd(), ignoring\n"); + dev_dbg(dev->class_dev, + "composite-error in %s, ignoring\n", __func__); } if (!(stat & DT_S_READY)) - printk("dt2801: !ready in dt2801_writecmd(), ignoring\n"); + dev_dbg(dev->class_dev, "!ready in %s, ignoring\n", __func__); outb_p(command, dev->iobase + DT2801_CMD); return 0; @@ -370,7 +370,7 @@ static int dt2801_reset(struct comedi_device *dev) break; } while (timeout--); if (!timeout) - printk("dt2801: timeout 1 status=0x%02x\n", stat); + dev_dbg(dev->class_dev, "timeout 1 status=0x%02x\n", stat); /* dt2801_readdata(dev,&board_code); */ @@ -385,7 +385,7 @@ static int dt2801_reset(struct comedi_device *dev) break; } while (timeout--); if (!timeout) - printk("dt2801: timeout 2 status=0x%02x\n", stat); + dev_dbg(dev->class_dev, "timeout 2 status=0x%02x\n", stat); dt2801_readdata(dev, &board_code); @@ -448,12 +448,12 @@ static int dt2801_error(struct comedi_device *dev, int stat) { if (stat < 0) { if (stat == -ETIME) - printk("dt2801: timeout\n"); + dev_dbg(dev->class_dev, "timeout\n"); else - printk("dt2801: error %d\n", stat); + dev_dbg(dev->class_dev, "error %d\n", stat); return stat; } - printk("dt2801: error status 0x%02x, resetting...\n", stat); + dev_dbg(dev->class_dev, "error status 0x%02x, resetting...\n", stat); dt2801_reset(dev); dt2801_reset(dev); @@ -584,8 +584,8 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (boardtypes[type].boardcode == board_code) goto havetype; } - printk("dt2801: unrecognized board code=0x%02x, contact author\n", - board_code); + dev_dbg(dev->class_dev, + "unrecognized board code=0x%02x, contact author\n", board_code); type = 0; havetype: -- cgit v1.2.3 From baa92cc0bfcb159ffae8f17a9a6971c2419fa2c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:51 -0700 Subject: staging: comedi: dt2811: remove disabled dt2811_adtrig() function This function is not used by the driver. It's also suffering from bitrot since COMEDI_MDEMAND and COMEDI_MCONTS are not defined anywhere. Just remove the code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2811.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 0ca02fa7ba1b..686d86c93faa 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -278,35 +278,6 @@ static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, return i; } -#if 0 -/* Wow. This is code from the Comedi stone age. But it hasn't been - * replaced, so I'll let it stay. */ -int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig) -{ - struct comedi_device *dev = comedi_devices + minor; - - if (adtrig->n < 1) - return 0; - dev->curadchan = adtrig->chan; - switch (dev->i_admode) { - case COMEDI_MDEMAND: - dev->ntrig = adtrig->n - 1; - /* not necessary */ - /*printk("dt2811: AD soft trigger\n"); */ - /*outb(DT2811_CLRERROR|DT2811_INTENB, - dev->iobase+DT2811_ADCSR); */ - outb(dev->curadchan, dev->iobase + DT2811_ADGCR); - do_gettimeofday(&trigtime); - break; - case COMEDI_MCONTS: - dev->ntrig = adtrig->n; - break; - } - - return 0; -} -#endif - static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { -- cgit v1.2.3 From d7bfe8e845ad03a48bc0e988cddedb536e296144 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:52 -0700 Subject: staging: comedi: dt2811: remove disabled interrupt support code The interrupt support in this driver is incomplete due to the missing comedi functions to support async commands. Since the interrupt code is already disable just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2811.c | 72 +-------------------------------- 1 file changed, 1 insertion(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 686d86c93faa..115eb0ad77ef 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -42,7 +42,6 @@ Configuration options: */ #include -#include #include "../comedidev.h" static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = { @@ -227,33 +226,6 @@ static const struct comedi_lrange *dac_range_types[] = { #define DT2811_TIMEOUT 5 -#if 0 -static irqreturn_t dt2811_interrupt(int irq, void *d) -{ - int lo, hi; - int data; - struct comedi_device *dev = d; - struct dt2811_private *devpriv = dev->private; - - if (!dev->attached) { - comedi_error(dev, "spurious interrupt"); - return IRQ_HANDLED; - } - - lo = inb(dev->iobase + DT2811_ADDATLO); - hi = inb(dev->iobase + DT2811_ADDATHI); - - data = lo + (hi << 8); - - if (!(--devpriv->ntrig)) { - /* how to turn off acquisition */ - s->async->events |= COMEDI_SB_EOA; - } - comedi_event(dev, s); - return IRQ_HANDLED; -} -#endif - static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { @@ -357,10 +329,7 @@ static int dt2811_do_insn_bits(struct comedi_device *dev, */ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - /* int i, irq; */ - /* unsigned long irqs; */ - /* long flags; */ - + /* int i; */ const struct dt2811_board *board = comedi_board(dev); struct dt2811_private *devpriv; int ret; @@ -377,45 +346,6 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) i = inb(dev->iobase + DT2811_ADDATHI); #endif -#if 0 - irq = it->options[1]; - if (irq < 0) { - save_flags(flags); - sti(); - irqs = probe_irq_on(); - - outb(DT2811_CLRERROR | DT2811_INTENB, - dev->iobase + DT2811_ADCSR); - outb(0, dev->iobase + DT2811_ADGCR); - - udelay(100); - - irq = probe_irq_off(irqs); - restore_flags(flags); - - /*outb(DT2811_CLRERROR|DT2811_INTENB, - dev->iobase+DT2811_ADCSR);*/ - - if (inb(dev->iobase + DT2811_ADCSR) & DT2811_ADERROR) - printk(KERN_ERR "error probing irq (bad)\n"); - dev->irq = 0; - if (irq > 0) { - i = inb(dev->iobase + DT2811_ADDATLO); - i = inb(dev->iobase + DT2811_ADDATHI); - printk(KERN_INFO "(irq = %d)\n", irq); - ret = request_irq(irq, dt2811_interrupt, 0, - dev->board_name, dev); - if (ret < 0) - return -EIO; - dev->irq = irq; - } else if (irq == 0) { - printk(KERN_INFO "(no irq)\n"); - } else { - printk(KERN_ERR "( multiple irq's -- this is bad! )\n"); - } - } -#endif - ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; -- cgit v1.2.3 From f0256161c234f2377f491b0b5e12b5d5f5d45892 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:53 -0700 Subject: staging: comedi: dt2814: remove unnecessary printk noise The ai read timeout will return -ETIMEDOUT. The printk is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2814.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 4b4147833843..90defd51c998 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -85,10 +85,8 @@ static int dt2814_ai_insn_read(struct comedi_device *dev, if (status & DT2814_FINISH) break; } - if (i >= DT2814_TIMEOUT) { - printk(KERN_INFO "dt2814: status: %02x\n", status); + if (i >= DT2814_TIMEOUT) return -ETIMEDOUT; - } hi = inb(dev->iobase + DT2814_DATA); lo = inb(dev->iobase + DT2814_DATA); -- cgit v1.2.3 From 1cb62c86ef1227edae33d4cd1b034d0cf257a9b8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:54 -0700 Subject: staging: comedi: dt2814: remove bad printk noise This printk could spew a lot of noise while waiting for the ai conversion to complete. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2814.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 90defd51c998..3a05588f722f 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -80,7 +80,6 @@ static int dt2814_ai_insn_read(struct comedi_device *dev, outb(chan, dev->iobase + DT2814_CSR); for (i = 0; i < DT2814_TIMEOUT; i++) { status = inb(dev->iobase + DT2814_CSR); - printk(KERN_INFO "dt2814: status: %02x\n", status); udelay(10); if (status & DT2814_FINISH) break; -- cgit v1.2.3 From 323cd3559f2443c3d5be511ea298cfadade71c17 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:55 -0700 Subject: staging: comedi: dt2814: convert a printk(KERN_ERR into a dev_err() Convert this printk message into a dev_dev(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2814.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 3a05588f722f..c3f82087ae10 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -246,7 +246,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) outb(0, dev->iobase + DT2814_CSR); udelay(100); if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) { - printk(KERN_ERR "reset error (fatal)\n"); + dev_err(dev->class_dev, "reset error (fatal)\n"); return -EIO; } i = inb(dev->iobase + DT2814_DATA); -- cgit v1.2.3 From c5a9595b2368eee2a4a92ffe30a57f3a45e478bf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:56 -0700 Subject: staging: comedi: dt2814: tidy up the irq support in dt2814_attach() An irq is only needed by this driver in order to support async commands. Since it is optional, modify the attach so that if the request_irq() fails the attach does not fail. Remove the printk noise about the irq. Only hookup the async command support if the request_irq() was successful. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2814.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index c3f82087ae10..e52d22e0ba63 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -235,9 +235,9 @@ static irqreturn_t dt2814_interrupt(int irq, void *d) static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct dt2814_private *devpriv; - int i, irq; - int ret; struct comedi_subdevice *s; + int ret; + int i; ret = comedi_request_region(dev, it->options[0], DT2814_SIZE); if (ret) @@ -252,17 +252,11 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) i = inb(dev->iobase + DT2814_DATA); i = inb(dev->iobase + DT2814_DATA); - irq = it->options[1]; - dev->irq = 0; - if (irq > 0) { - if (request_irq(irq, dt2814_interrupt, 0, "dt2814", dev)) { - printk(KERN_WARNING "(irq %d unavailable)\n", irq); - } else { - printk(KERN_INFO "( irq = %d )\n", irq); - dev->irq = irq; - } - } else if (irq == 0) { - printk(KERN_WARNING "(no irq)\n"); + if (it->options[1]) { + ret = request_irq(it->options[1], dt2814_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } ret = comedi_alloc_subdevices(dev, 1); @@ -274,16 +268,19 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; s = &dev->subdevices[0]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 16; /* XXX */ - s->len_chanlist = 1; s->insn_read = dt2814_ai_insn_read; - s->do_cmd = dt2814_ai_cmd; - s->do_cmdtest = dt2814_ai_cmdtest; s->maxdata = 0xfff; s->range_table = &range_unknown; /* XXX */ + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; + s->do_cmd = dt2814_ai_cmd; + s->do_cmdtest = dt2814_ai_cmdtest; + } return 0; } -- cgit v1.2.3 From 38fa4c4cfda77e58801a000112856ecdefe4335d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:57 -0700 Subject: staging: comedi: dt2815: convert printk's in dt2815_ao_insn() Convert the printk(KERN_WARNING messages in this function to dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2815.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 34040f0175e8..1a4caada5620 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -107,8 +107,9 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, status = dt2815_wait_for_status(dev, 0x00); if (status != 0) { - printk(KERN_WARNING "dt2815: failed to write low byte " - "on %d reason %x\n", chan, status); + dev_dbg(dev->class_dev, + "failed to write low byte on %d reason %x\n", + chan, status); return -EBUSY; } @@ -116,8 +117,9 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, status = dt2815_wait_for_status(dev, 0x10); if (status != 0x10) { - printk(KERN_WARNING "dt2815: failed to write high byte " - "on %d reason %x\n", chan, status); + dev_dbg(dev->class_dev, + "failed to write high byte on %d reason %x\n", + chan, status); return -EBUSY; } devpriv->ao_readback[chan] = data[i]; -- cgit v1.2.3 From 5b7b0eb2b208d3ecdaf946876f6c0f9cf292ddf2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:58 -0700 Subject: staging: comedi: dt2815: convert printk's in dt2815_attach() These messages don't appear to be important enough to warrent KERN_INFO and KERN_WARNING levels. Convert them dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2815.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 1a4caada5620..ee24717821e1 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -202,12 +202,13 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned int program; program = (it->options[4] & 0x3) << 3 | 0x7; outb(program, dev->iobase + DT2815_DATA); - printk(KERN_INFO ", program: 0x%x (@t=%d)\n", - program, i); + dev_dbg(dev->class_dev, "program: 0x%x (@t=%d)\n", + program, i); break; } else if (status != 0x00) { - printk(KERN_WARNING "dt2815: unexpected status 0x%x " - "(@t=%d)\n", status, i); + dev_dbg(dev->class_dev, + "unexpected status 0x%x (@t=%d)\n", + status, i); if (status & 0x60) outb(0x00, dev->iobase + DT2815_STATUS); } -- cgit v1.2.3 From 06551fda7e0f07250884c0cf47d1286da0a5651c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:41:59 -0700 Subject: staging: comedi: dt282x: tidy up the irq support in dt282x_attach() An irq is only needed by this driver in order to support async commands. Since it is optional, modify the attach so that if the request_irq() fails the attach does not fail. Remove the printk noise about the irq. Only hookup the async command support if the request_irq() was successful. Also, only call dt282x_grab_dma() if we have an irq since interrupt support is needed to support dma. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 84 ++++++++++++--------------------- 1 file changed, 30 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index c4ffedbdde21..d2f95bf94f44 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1118,9 +1118,9 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv; - int i, irq; - int ret; struct comedi_subdevice *s; + int ret; + int i; ret = comedi_request_region(dev, it->options[0], DT2821_SIZE); if (ret) @@ -1144,53 +1144,23 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* should do board test */ - irq = it->options[opt_irq]; -#if 0 - if (irq < 0) { - unsigned long flags; - int irqs; - - save_flags(flags); - sti(); - irqs = probe_irq_on(); - - /* trigger interrupt */ - - udelay(100); - - irq = probe_irq_off(irqs); - restore_flags(flags); - if (0 /* error */) - printk(KERN_ERR " error probing irq (bad)"); - } -#endif - if (irq > 0) { - printk(KERN_INFO " ( irq = %d )", irq); - ret = request_irq(irq, dt282x_interrupt, 0, + if (it->options[opt_irq] > 0) { + ret = request_irq(it->options[opt_irq], dt282x_interrupt, 0, dev->board_name, dev); - if (ret < 0) { - printk(KERN_ERR " failed to get irq\n"); - return -EIO; - } - dev->irq = irq; - } else if (irq == 0) { - printk(KERN_INFO " (no irq)"); - } else { -#if 0 - printk(KERN_INFO " (probe returned multiple irqs--bad)"); -#else - printk(KERN_INFO " (irq probe not implemented)"); -#endif + if (ret == 0) + dev->irq = it->options[opt_irq]; } devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - ret = dt282x_grab_dma(dev, it->options[opt_dma1], - it->options[opt_dma2]); - if (ret < 0) - return ret; + if (dev->irq) { + ret = dt282x_grab_dma(dev, it->options[opt_dma1], + it->options[opt_dma2]); + if (ret < 0) + return ret; + } ret = comedi_alloc_subdevices(dev, 3); if (ret) @@ -1198,22 +1168,25 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = &dev->subdevices[0]; - dev->read_subdev = s; /* ai subdevice */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ | + s->subdev_flags = SDF_READABLE | ((it->options[opt_diff]) ? SDF_DIFF : SDF_COMMON); s->n_chan = (it->options[opt_diff]) ? board->adchan_di : board->adchan_se; s->insn_read = dt282x_ai_insn_read; - s->do_cmdtest = dt282x_ai_cmdtest; - s->do_cmd = dt282x_ai_cmd; - s->cancel = dt282x_ai_cancel; s->maxdata = (1 << board->adbits) - 1; - s->len_chanlist = 16; s->range_table = opt_ai_range_lkup(board->ispgl, it->options[opt_ai_range]); devpriv->ad_2scomp = it->options[opt_ai_twos]; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 16; + s->do_cmdtest = dt282x_ai_cmdtest; + s->do_cmd = dt282x_ai_cmd; + s->cancel = dt282x_ai_cancel; + } s = &dev->subdevices[1]; @@ -1221,15 +1194,10 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (s->n_chan) { /* ao subsystem */ s->type = COMEDI_SUBD_AO; - dev->write_subdev = s; - s->subdev_flags = SDF_WRITABLE | SDF_CMD_WRITE; + s->subdev_flags = SDF_WRITABLE; s->insn_read = dt282x_ao_insn_read; s->insn_write = dt282x_ao_insn_write; - s->do_cmdtest = dt282x_ao_cmdtest; - s->do_cmd = dt282x_ao_cmd; - s->cancel = dt282x_ao_cancel; s->maxdata = (1 << board->dabits) - 1; - s->len_chanlist = 2; s->range_table_list = devpriv->darangelist; devpriv->darangelist[0] = opt_ao_range_lkup(it->options[opt_ao0_range]); @@ -1237,6 +1205,14 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) opt_ao_range_lkup(it->options[opt_ao1_range]); devpriv->da0_2scomp = it->options[opt_ao0_twos]; devpriv->da1_2scomp = it->options[opt_ao1_twos]; + if (dev->irq) { + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->len_chanlist = 2; + s->do_cmdtest = dt282x_ao_cmdtest; + s->do_cmd = dt282x_ao_cmd; + s->cancel = dt282x_ao_cancel; + } } else { s->type = COMEDI_SUBD_UNUSED; } -- cgit v1.2.3 From ab49581acebd6926842d261a74693e70564afe54 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:00 -0700 Subject: staging: comedi: dt282x: remove attach noise in dt282x_grab_dma() These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index d2f95bf94f44..7de9c4429920 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1060,10 +1060,8 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) devpriv->usedma = 0; - if (!dma1 && !dma2) { - printk(KERN_ERR " (no dma)"); + if (!dma1 && !dma2) return 0; - } if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7) return -EINVAL; @@ -1088,12 +1086,8 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) devpriv->dma_maxsize = PAGE_SIZE; devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) { - printk(KERN_ERR " can't get DMA memory"); + if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) return -ENOMEM; - } - - printk(KERN_INFO " (dma=%d,%d)", dma1, dma2); devpriv->usedma = 1; -- cgit v1.2.3 From 753b53d9b169043c6d2c30f7f990c2e4f7b23b14 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:01 -0700 Subject: staging: comedi: dt282x: convert printk() in dt282x_attach to a dev_err() Convert this printk message into a dev_err(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 7de9c4429920..2e8d777d7bc1 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1133,7 +1133,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) != DT2821_SUPCSR_VAL) || ((inw(dev->iobase + DT2821_TMRCTR) & DT2821_TMRCTR_MASK) != DT2821_TMRCTR_VAL)) { - printk(KERN_ERR " board not found"); + dev_err(dev->class_dev, "board not found\n"); return -EIO; } /* should do board test */ -- cgit v1.2.3 From d3ea1818f36991de1aaf8cc1958768a060a46cde Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:02 -0700 Subject: staging: comedi: dt282x: remove unnecessary blank line message This blank line message is not needed. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 2e8d777d7bc1..83e9d01839ab 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1221,8 +1221,6 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = 1; s->range_table = &range_digital; - printk(KERN_INFO "\n"); - return 0; } -- cgit v1.2.3 From 427f35222e7da82f4ffead939b1586623d92e1c5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:03 -0700 Subject: staging: comedi: dt282x: remove disable code that disables the irq The code that would disable the irq after getting a number of D/A errors is disabled. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 83e9d01839ab..b15520baef05 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -479,13 +479,6 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) handled = 1; } if (dacsr & DT2821_DAERR) { -#if 0 - static int warn = 5; - if (--warn <= 0) { - disable_irq(dev->irq); - printk(KERN_INFO "disabling irq\n"); - } -#endif comedi_error(dev, "D/A error"); dt282x_ao_cancel(dev, s_ao); s->async->events |= COMEDI_CB_ERROR; -- cgit v1.2.3 From 01112bf1efdec5ee63a8ee31c5b4c6b0331e83f0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:04 -0700 Subject: staging: comedi: dt282x: convert dt282x_ao_dma_interrupt() messages Convert the messages in this function to dev_err(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index b15520baef05..822ce0259b03 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -314,7 +314,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev) outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); if (!s->async->prealloc_buf) { - printk(KERN_ERR "async->data disappeared. dang!\n"); + dev_err(dev->class_dev, "no buffer in %s\n", __func__); return; } @@ -327,7 +327,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev) size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize); if (size == 0) { - printk(KERN_ERR "dt282x: AO underrun\n"); + dev_err(dev->class_dev, "AO underrun\n"); dt282x_ao_cancel(dev, s); s->async->events |= COMEDI_CB_OVERFLOW; return; -- cgit v1.2.3 From e0bee2de37da868c858891dd1c5e2fd93ec15297 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:05 -0700 Subject: staging: comedi: dt282x: convert dt282x_ai_dma_interrupt() messages Convert the messages in this function to dev_{level}(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 822ce0259b03..c8df18ae4084 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -348,7 +348,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev) outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); if (!s->async->prealloc_buf) { - printk(KERN_ERR "async->data disappeared. dang!\n"); + dev_err(dev->class_dev, "no buffer in %s\n", __func__); return; } @@ -369,7 +369,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev) devpriv->nread -= size / 2; if (devpriv->nread < 0) { - printk(KERN_INFO "dt282x: off by one\n"); + dev_info(dev->class_dev, "nread off by one\n"); devpriv->nread = 0; } if (!devpriv->nread) { -- cgit v1.2.3 From 50dbda4a9e3573a22b00bb8e7f179d0f75c641e6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:06 -0700 Subject: staging: comedi: dt282x: convert dt282x_ao_inttrig() messages Convert the messages in this function to dev_err(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index c8df18ae4084..a850e1d16aee 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -885,7 +885,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf, devpriv->dma_maxsize); if (size == 0) { - printk(KERN_ERR "dt282x: AO underrun\n"); + dev_err(dev->class_dev, "AO underrun\n"); return -EPIPE; } prep_ao_dma(dev, 0, size); @@ -893,7 +893,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf, devpriv->dma_maxsize); if (size == 0) { - printk(KERN_ERR "dt282x: AO underrun\n"); + dev_err(dev->class_dev, "AO underrun\n"); return -EPIPE; } prep_ao_dma(dev, 1, size); -- cgit v1.2.3 From 54bb2637645819302b0ca5b36ecb1391f684e87d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:07 -0700 Subject: staging: comedi: dt282x: remove commented out printk This printk is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index a850e1d16aee..df37d185125f 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -511,8 +511,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) } #endif comedi_event(dev, s); - /* printk("adcsr=0x%02x dacsr-0x%02x supcsr=0x%02x\n", - adcsr, dacsr, supcsr); */ + return IRQ_RETVAL(handled); } -- cgit v1.2.3 From b1ca6b1d479931a682ef443b23e00b4abae8ce25 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:08 -0700 Subject: staging: comedi: mpc624: remove commented out printk This printk is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mpc624.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index acbaeee6250c..2d6add4f97f7 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -159,7 +159,6 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, * We always write 0 to GNSWA bit, so the channel range is +-/10.1Vdc */ outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH); -/* printk("Channel %d:\n", insn->chanspec); */ if (!insn->n) { printk(KERN_INFO "MPC624: Warning, no data to acquire\n"); return 0; -- cgit v1.2.3 From c1ce7f10543d616920a1eb772b993c7d7815d653 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:09 -0700 Subject: staging: comedi: mpc624: remove unnecessary test It's not necessaary to vaidate insn->n passed to the (*insn_read) function. The for() loop following it will just be a NOP. Remove the test as well as the printk noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mpc624.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 2d6add4f97f7..b105dd98c358 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -159,10 +159,6 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, * We always write 0 to GNSWA bit, so the channel range is +-/10.1Vdc */ outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH); - if (!insn->n) { - printk(KERN_INFO "MPC624: Warning, no data to acquire\n"); - return 0; - } for (n = 0; n < insn->n; n++) { /* Trigger the conversion */ -- cgit v1.2.3 From 4a4ed3f96bc125f376d83f3d29aef6bb2780c10b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:10 -0700 Subject: staging: comedi: mpc624: remove unnecessary printk noise The ai read timeout will return -ETIMEDOUT. The printk is just added noise. Remove it. It's also not necessary to set data[n[ = 0 when the read timesout. Remove that also. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mpc624.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index b105dd98c358..01b281e83c61 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -177,11 +177,9 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, else break; } - if (i == TIMEOUT) { - printk(KERN_ERR "MPC624: timeout (%dms)\n", TIMEOUT); - data[n] = 0; + if (i == TIMEOUT) return -ETIMEDOUT; - } + /* Start reading data */ data_in = 0; data_out = devpriv->ulConvertionRate; -- cgit v1.2.3 From ba74f010ac5f14a836c64c1a53456da199b3ee7c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:11 -0700 Subject: staging: comedi: mpc624: convert printk messages in mpc624_ai_rinsn() There's no reason for these messages to be KERN_INFO. Convert them to dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mpc624.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 01b281e83c61..fe4621ea65c3 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -238,11 +238,11 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, */ if (data_in & MPC624_EOC_BIT) - printk(KERN_INFO "MPC624:EOC bit is set (data_in=%lu)!", - data_in); + dev_dbg(dev->class_dev, + "EOC bit is set (data_in=%lu)!", data_in); if (data_in & MPC624_DMY_BIT) - printk(KERN_INFO "MPC624:DMY bit is set (data_in=%lu)!", - data_in); + dev_dbg(dev->class_dev, + "DMY bit is set (data_in=%lu)!", data_in); if (data_in & MPC624_SGN_BIT) { /* Volatge is positive */ /* * comedi operates on unsigned numbers, so mask off EOC -- cgit v1.2.3 From d1483ea58b16cdfe49b4a2cf47b9b56f4a83b2ef Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:12 -0700 Subject: staging: comedi: rtd520: remove commented out printk debug These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rtd520.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index a1e4892eac31..c6a664f38c31 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -495,8 +495,6 @@ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev, case AREF_OTHER: /* ??? */ break; } - /*printk ("chan=%d r=%d a=%d -> 0x%x\n", - chan, range, aref, r); */ return r; } @@ -606,7 +604,6 @@ static int rtd_ai_rinsn(struct comedi_device *dev, /* read data */ d = readw(devpriv->las1 + LAS1_ADC_FIFO); - /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */ d = d >> 3; /* low 3 bits are marker lines */ if (test_bit(0, devpriv->chan_is_bipolar)) /* convert to comedi unsigned data */ -- cgit v1.2.3 From 3c64306183e2215671c70b378e4d445a46a96bcf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:13 -0700 Subject: staging: comedi: plx9080.h: remove unnecessary printk noise The timeouts will return -ETIMEDOUT. The printks are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/plx9080.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index 0d254a1b78a7..55e3c2e2bc52 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -402,12 +402,9 @@ static inline int plx9080_abort_dma(void __iomem *iobase, unsigned int channel) udelay(1); dma_status = readb(dma_cs_addr); } - if (i == timeout) { - printk - ("plx9080: cancel() timed out waiting for dma %i done clear\n", - channel); + if (i == timeout) return -ETIMEDOUT; - } + /* disable and abort channel */ writeb(PLX_DMA_ABORT_BIT, dma_cs_addr); /* wait for dma done bit */ @@ -416,12 +413,8 @@ static inline int plx9080_abort_dma(void __iomem *iobase, unsigned int channel) udelay(1); dma_status = readb(dma_cs_addr); } - if (i == timeout) { - printk - ("plx9080: cancel() timed out waiting for dma %i done set\n", - channel); + if (i == timeout) return -ETIMEDOUT; - } return 0; } -- cgit v1.2.3 From bab0e19c4d233f5705c4c9c0b5e4cd63936c344f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:14 -0700 Subject: staging: comedi: pcm3724: remove commented out printk debug These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcm3724.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index cc1dc7f66e5b..f4a49bd649f0 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -70,14 +70,11 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) { unsigned long iobase = arg; unsigned char inbres; - /* printk("8255cb %d %d %d %lx\n", dir,port,data,arg); */ if (dir) { - /* printk("8255 cb outb(%x, %lx)\n", data, iobase+port); */ outb(data, iobase + port); return 0; } else { inbres = inb(iobase + port); - /* printk("8255 cb inb(%lx) = %x\n", iobase+port, inbres); */ return inbres; } } @@ -137,8 +134,6 @@ static void do_3724_config(struct comedi_device *dev, port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR; outb(buffer_config, dev->iobase + 8); /* update buffer register */ - /* printk("pcm3724 buffer_config (%lx) %d, %x\n", - dev->iobase + _8255_CR, chanspec, buffer_config); */ outb(config, port_8255_cfg); } @@ -177,7 +172,6 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s, if (priv->dio_2 & 0xff) gatecfg |= GATE_A1; - /* printk("gate control %x\n", gatecfg); */ outb(gatecfg, dev->iobase + 9); } -- cgit v1.2.3 From aad6fd1fca730c89058a7b399790369772cb30f7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:15 -0700 Subject: staging: comedi: pcl818: remove commented out printk debug These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index def79c5b1a66..5b968003e16e 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -478,7 +478,6 @@ conv_finish: s->async->cur_chan++; if (s->async->cur_chan >= devpriv->ai_n_chan) { - /* printk("E"); */ s->async->cur_chan = 0; devpriv->ai_act_scan--; } @@ -562,7 +561,6 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) pcl818_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); - /* printk("done int ai13 dma\n"); */ return IRQ_HANDLED; } } @@ -661,7 +659,6 @@ static irqreturn_t interrupt_pcl818(int irq, void *d) comedi_error(dev, "premature interrupt"); return IRQ_HANDLED; } - /* printk("I\n"); */ if (devpriv->irq_blocked && devpriv->irq_was_now_closed) { if ((devpriv->neverending_ai || (!devpriv->neverending_ai && @@ -824,7 +821,6 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, case 0: if (!devpriv->usefifo) { /* IRQ */ - /* printk("IRQ\n"); */ if (mode == 1) { devpriv->ai_mode = INT_TYPE_AI1_INT; /* Pacer+IRQ */ @@ -899,10 +895,6 @@ static int check_channel_list(struct comedi_device *dev, chansegment[0] = chanlist[0]; /* build part of chanlist */ for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { - - /* printk("%d. %d * %d\n",i, - * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/ - /* we detect loop, this must by finish */ if (chanlist[0] == chanlist[i]) @@ -922,7 +914,6 @@ static int check_channel_list(struct comedi_device *dev, /* check whole chanlist */ for (i = 0, segpos = 0; i < n_chan; i++) { - /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */ if (chanlist[i] != chansegment[i % seglen]) { dev_dbg(dev->class_dev, "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", @@ -1296,7 +1287,6 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->dmapages[0] = pages; devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; - /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */ devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) return -EBUSY; -- cgit v1.2.3 From de4ea8e3c1d6fa5af584e48bfe321c9cff2a79fc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:16 -0700 Subject: staging: comedi: pcl818: remove printk function trace messages These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 5b968003e16e..931aed0e2c23 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -522,7 +522,6 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) release_dma_lock(flags); enable_dma(devpriv->dma); } - printk("comedi: A/D mode1/3 IRQ \n"); devpriv->dma_runs_to_end--; outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ @@ -723,7 +722,6 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev, unsigned int flags; unsigned int bytes; - printk("mode13dma_int, mode: %d\n", mode); disable_dma(devpriv->dma); /* disable dma */ bytes = devpriv->hwdmasize[0]; if (!devpriv->neverending_ai) { @@ -929,7 +927,6 @@ static int check_channel_list(struct comedi_device *dev, } else { seglen = 1; } - printk("check_channel_list: seglen %d\n", seglen); return seglen; } -- cgit v1.2.3 From eeb6f2d3b7406e569c718f265100cce0227841bd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:17 -0700 Subject: staging: comedi: pcl818: remove board attach noise These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 931aed0e2c23..945a5dd4ec48 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1234,16 +1234,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq = it->options[1]; if (irq) { /* we want to use IRQ */ if (((1 << irq) & board->IRQbits) == 0) { - printk - (", IRQ %u is out of allowed range, DISABLING IT", - irq); irq = 0; /* Bad IRQ */ } else { if (request_irq(irq, interrupt_pcl818, 0, dev->board_name, dev)) { - printk - (", unable to allocate IRQ %u, DISABLING IT", - irq); irq = 0; /* Can't use IRQ */ } } @@ -1308,11 +1302,9 @@ no_dma: if (check_single_ended(dev->iobase)) { s->n_chan = board->n_aichan_se; s->subdev_flags |= SDF_COMMON | SDF_GROUND; - printk(", %dchans S.E. DAC", s->n_chan); } else { s->n_chan = board->n_aichan_diff; s->subdev_flags |= SDF_DIFF; - printk(", %dchans DIFF DAC", s->n_chan); } s->maxdata = board->ai_maxdata; s->len_chanlist = s->n_chan; @@ -1431,8 +1423,6 @@ no_dma: pcl818_reset(dev); - printk("\n"); - return 0; } -- cgit v1.2.3 From e30b22a9ccbe0b3c2e9c68ab3e46c69f56c3ae35 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:18 -0700 Subject: staging: comedi: pcl818: tidy up the irq support in pcl818_attach() Tidy up the code that does the request_irq(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 945a5dd4ec48..15b424733a9e 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1204,7 +1204,6 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcl818_board *board = comedi_board(dev); struct pcl818_private *devpriv; int ret; - unsigned int irq; int dma; unsigned long pages; struct comedi_subdevice *s; @@ -1228,28 +1227,15 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EIO; } - /* grab our IRQ */ - irq = 0; - if (board->IRQbits != 0) { /* board support IRQ */ - irq = it->options[1]; - if (irq) { /* we want to use IRQ */ - if (((1 << irq) & board->IRQbits) == 0) { - irq = 0; /* Bad IRQ */ - } else { - if (request_irq(irq, interrupt_pcl818, 0, - dev->board_name, dev)) { - irq = 0; /* Can't use IRQ */ - } - } + if ((1 << it->options[1]) & board->IRQbits) { + ret = request_irq(it->options[1], interrupt_pcl818, 0, + dev->board_name, dev); + if (ret == 0) { + dev->irq = it->options[1]; + devpriv->irq_free = 1; } } - dev->irq = irq; - if (irq) - devpriv->irq_free = 1; /* 1=we have allocated irq */ - else - devpriv->irq_free = 0; - devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ devpriv->ai_mode = 0; /* mode of irq */ @@ -1311,7 +1297,7 @@ no_dma: s->range_table = board->ai_range_type; s->cancel = pcl818_ai_cancel; s->insn_read = pcl818_ai_insn_read; - if (irq) { + if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->do_cmdtest = ai_cmdtest; -- cgit v1.2.3 From d65e5b9d918aecd992947f1494ffb92b38c5f349 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:19 -0700 Subject: staging: comedi: pcl818: convert printk() messages to dev_{level} Convert the remaining printk messsages in this driver to dev_{level}. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 15b424733a9e..cacdca0983bb 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -463,10 +463,10 @@ conv_finish: outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ - printk - ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n", - (low & 0xf), - devpriv->act_chanlist[devpriv->act_chanlist_pos]); + dev_dbg(dev->class_dev, + "A/D mode1/3 IRQ - channel dropout %x!=%x !\n", + (low & 0xf), + devpriv->act_chanlist[devpriv->act_chanlist_pos]); pcl818_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); @@ -532,11 +532,11 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) for (i = 0; i < len; i++) { if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ - printk - ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n", - (ptr[bufptr] & 0xf), - devpriv->act_chanlist[devpriv->act_chanlist_pos], - devpriv->act_chanlist_pos); + dev_dbg(dev->class_dev, + "A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n", + (ptr[bufptr] & 0xf), + devpriv->act_chanlist[devpriv->act_chanlist_pos], + devpriv->act_chanlist_pos); pcl818_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); @@ -609,10 +609,10 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) for (i = 0; i < len; i++) { lo = inb(dev->iobase + PCL818_FI_DATALO); if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ - printk - ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n", - (lo & 0xf), - devpriv->act_chanlist[devpriv->act_chanlist_pos]); + dev_dbg(dev->class_dev, + "A/D mode1/3 FIFO - channel dropout %d!=%d !\n", + (lo & 0xf), + devpriv->act_chanlist[devpriv->act_chanlist_pos]); pcl818_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); @@ -1249,7 +1249,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (dma < 1) goto no_dma; /* DMA disabled */ if (((1 << dma) & board->DMAbits) == 0) { - printk(KERN_ERR "DMA is out of allowed range, FAIL!\n"); + dev_err(dev->class_dev, + "DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } ret = request_dma(dma, dev->board_name); -- cgit v1.2.3 From 11b7f7dc10fa1e5315bbefa11a2d1a5e1c408429 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:20 -0700 Subject: staging: comedi: pcl816: remove commented out outb() macro This macro is commented out, thankfully... Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 8776c596bad2..e1a59f167d29 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -48,8 +48,6 @@ Configuration Options: /* IO space len */ #define PCLx1x_RANGE 16 -/* #define outb(x,y) printk("OUTB(%x, 200+%d)\n", x,y-0x200); outb(x,y) */ - /* INTEL 8254 counters */ #define PCL816_CTR0 4 #define PCL816_CTR1 5 -- cgit v1.2.3 From d3629b2b1241e75971026e6ce6671f5b59b9172c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:21 -0700 Subject: staging: comedi: pcl816: remove TRIG_WAKE_EOS support stub The support code for this command flag is commented out. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index e1a59f167d29..149a28bbf086 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -539,15 +539,6 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_neverending = 1; } - /* don't we want wake up every scan? */ - if ((cmd->flags & TRIG_WAKE_EOS)) { - printk(KERN_INFO - "pl816: You wankt WAKE_EOS but I dont want handle it"); - /* devpriv->ai_eos=1; */ - /* if (devpriv->ai_n_chan==1) */ - /* devpriv->dma=0; // DMA is useless for this situation */ - } - if (devpriv->dma) { bytes = devpriv->hwdmasize[0]; if (!devpriv->ai_neverending) { -- cgit v1.2.3 From 8189061ea4a2f877c3867a57b9a33e7e56a44636 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 27 Nov 2013 11:05:19 -0700 Subject: staging: comedi: pcl816: tidy up the irq support in pcl816_attach() Tidy up the code that does the request_irq(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 35 +++++++-------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 149a28bbf086..57172156321b 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -854,7 +854,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcl816_board *board = comedi_board(dev); struct pcl816_private *devpriv; int ret; - unsigned int irq, dma; + unsigned int dma; unsigned long pages; /* int i; */ struct comedi_subdevice *s; @@ -872,36 +872,15 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - /* grab our IRQ */ - irq = 0; - if (board->IRQbits != 0) { /* board support IRQ */ - irq = it->options[1]; - if (irq) { /* we want to use IRQ */ - if (((1 << irq) & board->IRQbits) == 0) { - printk - (", IRQ %u is out of allowed range, " - "DISABLING IT", irq); - irq = 0; /* Bad IRQ */ - } else { - if (request_irq(irq, interrupt_pcl816, 0, - dev->board_name, dev)) { - printk - (", unable to allocate IRQ %u, " - "DISABLING IT", irq); - irq = 0; /* Can't use IRQ */ - } else { - printk(KERN_INFO ", irq=%u", irq); - } - } + if ((1 << it->options[1]) & board->IRQbits) { + ret = request_irq(it->options[1], interrupt_pcl816, 0, + dev->board_name, dev); + if (ret == 0) { + dev->irq = it->options[1]; + devpriv->irq_free = 1; } } - dev->irq = irq; - if (irq) /* 1=we have allocated irq */ - devpriv->irq_free = 1; - else - devpriv->irq_free = 0; - devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ devpriv->int816_mode = 0; /* mode of irq */ -- cgit v1.2.3 From e21f20e769c65cf0c327bc26e91b5e316b262491 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:23 -0700 Subject: staging: comedi: pcl816: remove commented out printk debug These messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 57172156321b..6d8dbf8d2dcf 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -922,7 +922,6 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->dmapages[0] = pages; devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; - /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */ devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { @@ -958,7 +957,6 @@ no_dma: s->subdev_flags = SDF_READABLE | SDF_CMD_READ; s->n_chan = board->n_aichan; s->subdev_flags |= SDF_DIFF; - /* printk (", %dchans DIFF DAC - %d", s->n_chan, i); */ s->maxdata = board->ai_maxdata; s->len_chanlist = board->ai_chanlist; s->range_table = board->ai_range_type; -- cgit v1.2.3 From 5d24b7de41ab53b3f309629fa73e285a8f9645e2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:24 -0700 Subject: staging: comedi: pcl816: convert printk messages in pcl816_attach() Convert the printk messages in this function to dev_{level} mesages. Remove the ones that are just added noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 6d8dbf8d2dcf..d54325047af6 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -864,7 +864,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; if (pcl816_check(dev->iobase)) { - printk(KERN_ERR ", I cann't detect board. FAIL!\n"); + dev_err(dev->class_dev, "I can't detect board. FAIL!\n"); return -EIO; } @@ -896,23 +896,24 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) goto no_dma; /* DMA disabled */ if (((1 << dma) & board->DMAbits) == 0) { - printk(", DMA is out of allowed range, FAIL!\n"); + dev_err(dev->class_dev, + "DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } ret = request_dma(dma, dev->board_name); if (ret) { - printk(KERN_ERR - ", unable to allocate DMA %u, FAIL!\n", dma); + dev_err(dev->class_dev, + "unable to allocate DMA %u, FAIL!\n", dma); return -EBUSY; /* DMA isn't free */ } devpriv->dma = dma; - printk(KERN_INFO ", dma=%u", dma); pages = 2; /* we need 16KB */ devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[0]) { - printk(", unable to allocate DMA buffer, FAIL!\n"); + dev_err(dev->class_dev, + "unable to allocate DMA buffer, FAIL!\n"); /* * maybe experiment with try_to_free_pages() * will help .... @@ -925,9 +926,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { - printk(KERN_ERR - ", unable to allocate DMA buffer, " - "FAIL!\n"); + dev_err(dev->class_dev, + "unable to allocate DMA buffer, FAIL!\n"); return -EBUSY; } devpriv->dmapages[1] = pages; @@ -997,8 +997,6 @@ case COMEDI_SUBD_DO: pcl816_reset(dev); - printk("\n"); - return 0; } -- cgit v1.2.3 From e2f6df943892654b221a27f0be66c838c2c2bbed Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:25 -0700 Subject: staging: comedi: pcl812: tidy up the irq support in pcl812_attach() Tidy up the code that does the request_irq(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index e31cf44faa33..804174b573c2 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1088,7 +1088,6 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcl812_board *board = comedi_board(dev); struct pcl812_private *devpriv; int ret, subdev; - unsigned int irq; unsigned int dma; unsigned long pages; struct comedi_subdevice *s; @@ -1102,31 +1101,13 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - irq = 0; - if (board->IRQbits != 0) { /* board support IRQ */ - irq = it->options[1]; - if (irq) { /* we want to use IRQ */ - if (((1 << irq) & board->IRQbits) == 0) { - printk - (", IRQ %u is out of allowed range, " - "DISABLING IT", irq); - irq = 0; /* Bad IRQ */ - } else { - if (request_irq(irq, interrupt_pcl812, 0, - dev->board_name, dev)) { - printk - (", unable to allocate IRQ %u, " - "DISABLING IT", irq); - irq = 0; /* Can't use IRQ */ - } else { - printk(KERN_INFO ", irq=%u", irq); - } - } - } + if ((1 << it->options[1]) & board->IRQbits) { + ret = request_irq(it->options[1], interrupt_pcl812, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } - dev->irq = irq; - dma = 0; devpriv->dma = dma; if (!dev->irq) @@ -1395,7 +1376,7 @@ no_dma: break; case boardA821: devpriv->max_812_ai_mode0_rangewait = 1; - devpriv->mode_reg_int = (irq << 4) & 0xf0; + devpriv->mode_reg_int = (dev->irq << 4) & 0xf0; break; case boardPCL813B: case boardPCL813: -- cgit v1.2.3 From 765a24be67e9fe1097f18e0cd7080da1f47c60a4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:26 -0700 Subject: staging: comedi: pcl812: convert printk messages in pcl812_attach() Convert the printk messages in this function to dev_{level} mesages. Remove the ones that are just added noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 804174b573c2..e1e4cd139b63 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1115,21 +1115,22 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (board->DMAbits != 0) { /* board support DMA */ dma = it->options[2]; if (((1 << dma) & board->DMAbits) == 0) { - printk(", DMA is out of allowed range, FAIL!\n"); + dev_err(dev->class_dev, + "DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } ret = request_dma(dma, dev->board_name); if (ret) { - printk(KERN_ERR ", unable to allocate DMA %u, FAIL!\n", - dma); + dev_err(dev->class_dev, + "unable to allocate DMA %u, FAIL!\n", dma); return -EBUSY; /* DMA isn't free */ } devpriv->dma = dma; - printk(KERN_INFO ", dma=%u", dma); pages = 1; /* we want 8KB */ devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[0]) { - printk(", unable to allocate DMA buffer, FAIL!\n"); + dev_err(dev->class_dev, + "unable to allocate DMA buffer, FAIL!\n"); /* * maybe experiment with try_to_free_pages() * will help .... @@ -1141,7 +1142,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages); devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { - printk(KERN_ERR ", unable to allocate DMA buffer, FAIL!\n"); + dev_err(dev->class_dev, + "unable to allocate DMA buffer, FAIL!\n"); return -EBUSY; } devpriv->dmapages[1] = pages; @@ -1243,10 +1245,6 @@ no_dma: default: s->range_table = &range_bipolar10; break; - printk - (", incorrect range number %d, changing " - "to 0 (+/-10V)", it->options[4]); - break; } break; break; @@ -1273,10 +1271,6 @@ no_dma: default: s->range_table = &range_iso813_1_ai; break; - printk - (", incorrect range number %d, " - "changing to 0 ", it->options[1]); - break; } break; case boardACL8113: @@ -1298,10 +1292,6 @@ no_dma: default: s->range_table = &range_acl8113_1_ai; break; - printk - (", incorrect range number %d, " - "changing to 0 ", it->options[1]); - break; } break; } @@ -1387,7 +1377,6 @@ no_dma: break; } - printk(KERN_INFO "\n"); devpriv->valid = 1; pcl812_reset(dev); -- cgit v1.2.3 From 9cc2bafb61bf8bc614a4570f7f78e09eb60e1dff Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:27 -0700 Subject: staging: comedi: ni_tio: remove commented out printk message This printk message is just added noise. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 9b120c77d83a..cf8892bcf01e 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1319,7 +1319,6 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, counter_dev->regs[abz_reg] &= ~mask; counter_dev->regs[abz_reg] |= (source << shift) & mask; write_register(counter, counter_dev->regs[abz_reg], abz_reg); -/* printk("%s %x %d %d\n", __func__, counter_dev->regs[abz_reg], index, source); */ return 0; } return -EINVAL; -- cgit v1.2.3 From 2f4a269b27a4a77b98fe466c6ae48985c913dc64 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:28 -0700 Subject: staging: comedi: ni_pcimio: convert printk() to dev_dbg() Convert this printk messages to a dev_dbg(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcimio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index b0ed0413bd0f..1166c45da49e 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1176,9 +1176,9 @@ static void m_series_stc_writew(struct comedi_device *dev, uint16_t data, offset = M_Offset_AO_FIFO_Clear; break; case DIO_Control_Register: - printk - ("%s: FIXME: register 0x%x does not map cleanly on to m-series boards.\n", - __func__, reg); + dev_dbg(dev->class_dev, + "%s: FIXME: register 0x%x does not map cleanly on to m-series boards.\n", + __func__, reg); return; break; case G_Autoincrement_Register(0): -- cgit v1.2.3 From d4bdba2f602e10ecad17e495ded089085cbd72f2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:29 -0700 Subject: staging: comedi: ni_atmio16d: remove printk() noise in atmio16d_ai_insn_read() These printk messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio16d.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index a9f7d40d6db2..95e98a8cb6a0 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -495,18 +495,13 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev, break; } if (status & STAT_AD_OVERFLOW) { - printk(KERN_INFO "atmio16d: a/d FIFO overflow\n"); outw(0, dev->iobase + AD_CLEAR_REG); - return -ETIME; } } /* end waiting, now check if it timed out */ - if (t == ATMIO16D_TIMEOUT) { - printk(KERN_INFO "atmio16d: timeout\n"); - + if (t == ATMIO16D_TIMEOUT) return -ETIME; - } } return i; -- cgit v1.2.3 From ec9b2f4f4fe6012ea426206e6d4f79da8ac19113 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:30 -0700 Subject: staging: comedi: ni_atmio16d: tidy up the irq support in atmio16d_attach() Tidy up the code that does the request_irq(). Only hookup the commad support if the irq was sucessfully requested. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio16d.c | 34 ++++++++++++---------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 95e98a8cb6a0..35cadc38b7fa 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -631,7 +631,6 @@ static int atmio16d_attach(struct comedi_device *dev, const struct atmio16_board_t *board = comedi_board(dev); struct atmio16d_private *devpriv; struct comedi_subdevice *s; - unsigned int irq; int ret; ret = comedi_request_region(dev, it->options[0], ATMIO16D_SIZE); @@ -649,19 +648,11 @@ static int atmio16d_attach(struct comedi_device *dev, /* reset the atmio16d hardware */ reset_atmio16d(dev); - /* check if our interrupt is available and get it */ - irq = it->options[1]; - if (irq) { - - ret = request_irq(irq, atmio16d_interrupt, 0, "atmio16d", dev); - if (ret < 0) { - printk(KERN_INFO "failed to allocate irq %u\n", irq); - return ret; - } - dev->irq = irq; - printk(KERN_INFO "( irq = %u )\n", irq); - } else { - printk(KERN_INFO "( no irq )"); + if (it->options[1]) { + ret = request_irq(it->options[1], atmio16d_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } /* set device options */ @@ -677,16 +668,11 @@ static int atmio16d_attach(struct comedi_device *dev, /* setup sub-devices */ s = &dev->subdevices[0]; - dev->read_subdev = s; /* ai subdevice */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = (devpriv->adc_mux ? 16 : 8); - s->len_chanlist = 16; s->insn_read = atmio16d_ai_insn_read; - s->do_cmdtest = atmio16d_ai_cmdtest; - s->do_cmd = atmio16d_ai_cmd; - s->cancel = atmio16d_ai_cancel; s->maxdata = 0xfff; /* 4095 decimal */ switch (devpriv->adc_range) { case adc_bipolar10: @@ -699,6 +685,14 @@ static int atmio16d_attach(struct comedi_device *dev, s->range_table = &range_atmio16d_ai_unipolar; break; } + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 16; + s->do_cmdtest = atmio16d_ai_cmdtest; + s->do_cmd = atmio16d_ai_cmd; + s->cancel = atmio16d_ai_cancel; + } /* ao subdevice */ s = &dev->subdevices[1]; -- cgit v1.2.3 From d12816156901d2e3d6dd310088dbdb37a65e7712 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 26 Nov 2013 16:42:31 -0700 Subject: staging: comedi: ni_atmio16d: remove an unnecessary printk This blank line printk is not necessary. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio16d.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 35cadc38b7fa..834c9e1e6058 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -745,7 +745,6 @@ static int atmio16d_attach(struct comedi_device *dev, s->n_chan = 0; s->maxdata = 0 #endif - printk("\n"); return 0; } -- cgit v1.2.3 From 49cf10c67bfbd68bc646390cd1f4cbe77aea12d5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 28 Nov 2013 10:27:59 +0800 Subject: staging: dwc2: fix sparse non static symbol warning Fixes the following sparse warning: drivers/staging/dwc2/core.c:2672:6: warning: symbol 'dwc2_set_param_uframe_sched' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index 8a71726a3566..8565d87f94b4 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -2510,7 +2510,7 @@ void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) hsotg->core_params->otg_ver = val; } -void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) +static void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) { if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { -- cgit v1.2.3 From 9a21e4770ac828a49e722897c3c0250f630f4a48 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:25:19 +0900 Subject: spi: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-dw-pci.c | 2 +- drivers/spi/spi-pxa2xx-pci.c | 2 +- drivers/spi/spi-topcliff-pch.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 66fa9955ea14..f7be4be59353 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -148,7 +148,7 @@ static int spi_resume(struct pci_dev *pdev) #define spi_resume NULL #endif -static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { +static const struct pci_device_id pci_ids[] = { /* Intel MID platform SPI controller 0 */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) }, {}, diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 74bc18775658..3f006d3ed2a8 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -62,7 +62,7 @@ static void ce4100_spi_remove(struct pci_dev *dev) platform_device_unregister(pdev); } -static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { +static const struct pci_device_id ce4100_spi_devices[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) }, { }, }; diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 446131308acb..338fc11913c1 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -217,7 +217,7 @@ struct pch_pd_dev_save { struct pch_spi_board_data *board_dat; }; -static DEFINE_PCI_DEVICE_TABLE(pch_spi_pcidev_id) = { +static const struct pci_device_id pch_spi_pcidev_id[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, }, -- cgit v1.2.3 From 46adcf3d82b44a4a9f147b2b898595d48873aa53 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 8 Nov 2013 01:09:47 -0200 Subject: usb: chipidea: host: Only disable the vbus regulator if it is not NULL Commit 40ed51a4b (usb: chipidea: host: add vbus regulator control) introduced a smatch complaint because regulator_disable() is called without checking whether ci->platdata->reg_vbus is not NULL. Fix this by adding the check. Reported-by: Dan Carpenter Signed-off-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 59e6020ea753..526cd77563d8 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci) return ret; disable_reg: - regulator_disable(ci->platdata->reg_vbus); + if (ci->platdata->reg_vbus) + regulator_disable(ci->platdata->reg_vbus); put_hcd: usb_put_hcd(hcd); -- cgit v1.2.3 From 4e065b8bba731af296f963e0608e6ea7d98c044f Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Nov 2013 14:15:26 +0900 Subject: usb: chipidea: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci_hdrc_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/ci_hdrc_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c index d514332ac081..241ae3444fde 100644 --- a/drivers/usb/chipidea/ci_hdrc_pci.c +++ b/drivers/usb/chipidea/ci_hdrc_pci.c @@ -112,7 +112,7 @@ static void ci_hdrc_pci_remove(struct pci_dev *pdev) * * Check "pci.h" for details */ -static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = { +static const struct pci_device_id ci_hdrc_pci_id_table[] = { { PCI_DEVICE(0x153F, 0x1004), .driver_data = (kernel_ulong_t)&pci_platdata, -- cgit v1.2.3 From 5a6a62bdb9257aa74ab0ad2b2c8a33b0f9b17ce4 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 20 Nov 2013 11:35:34 +0100 Subject: cdc-acm: add TIOCMIWAIT This implements TIOCMIWAIT for TIOCM_DSR, TIOCM_RI and TIOCM_CD Disconnect is handled as TIOCM_CD or an error. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 86 ++++++++++++++++++++++++++++++++++++++------- drivers/usb/class/cdc-acm.h | 3 ++ 2 files changed, 77 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3e7560f004f8..7c0051710a04 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -262,6 +262,7 @@ static void acm_ctrl_irq(struct urb *urb) struct usb_cdc_notification *dr = urb->transfer_buffer; unsigned char *data; int newctrl; + int difference; int retval; int status = urb->status; @@ -302,20 +303,31 @@ static void acm_ctrl_irq(struct urb *urb) tty_port_tty_hangup(&acm->port, false); } + difference = acm->ctrlin ^ newctrl; + spin_lock(&acm->read_lock); acm->ctrlin = newctrl; + acm->oldcount = acm->iocount; + + if (difference & ACM_CTRL_DSR) + acm->iocount.dsr++; + if (difference & ACM_CTRL_BRK) + acm->iocount.brk++; + if (difference & ACM_CTRL_RI) + acm->iocount.rng++; + if (difference & ACM_CTRL_DCD) + acm->iocount.dcd++; + if (difference & ACM_CTRL_FRAMING) + acm->iocount.frame++; + if (difference & ACM_CTRL_PARITY) + acm->iocount.parity++; + if (difference & ACM_CTRL_OVERRUN) + acm->iocount.overrun++; + spin_unlock(&acm->read_lock); + + if (difference) + wake_up_all(&acm->wioctl); - dev_dbg(&acm->control->dev, - "%s - input control lines: dcd%c dsr%c break%c " - "ring%c framing%c parity%c overrun%c\n", - __func__, - acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', - acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', - acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', - acm->ctrlin & ACM_CTRL_RI ? '+' : '-', - acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', - acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', - acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); - break; + break; default: dev_dbg(&acm->control->dev, @@ -796,6 +808,51 @@ static int set_serial_info(struct acm *acm, return retval; } +static int wait_serial_change(struct acm *acm, unsigned long arg) +{ + int rv = 0; + DECLARE_WAITQUEUE(wait, current); + struct async_icount old, new; + + if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD )) + return -EINVAL; + do { + spin_lock_irq(&acm->read_lock); + old = acm->oldcount; + new = acm->iocount; + acm->oldcount = new; + spin_unlock_irq(&acm->read_lock); + + if ((arg & TIOCM_DSR) && + old.dsr != new.dsr) + break; + if ((arg & TIOCM_CD) && + old.dcd != new.dcd) + break; + if ((arg & TIOCM_RI) && + old.rng != new.rng) + break; + + add_wait_queue(&acm->wioctl, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + remove_wait_queue(&acm->wioctl, &wait); + if (acm->disconnected) { + if (arg & TIOCM_CD) + break; + else + rv = -ENODEV; + } else { + if (signal_pending(current)) + rv = -ERESTARTSYS; + } + } while (!rv); + + + + return rv; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -809,6 +866,9 @@ static int acm_tty_ioctl(struct tty_struct *tty, case TIOCSSERIAL: rv = set_serial_info(acm, (struct serial_struct __user *) arg); break; + case TIOCMIWAIT: + rv = wait_serial_change(acm, arg); + break; } return rv; @@ -1167,6 +1227,7 @@ made_compressed_probe: acm->readsize = readsize; acm->rx_buflimit = num_rx_buf; INIT_WORK(&acm->work, acm_softint); + init_waitqueue_head(&acm->wioctl); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); mutex_init(&acm->mutex); @@ -1383,6 +1444,7 @@ static void acm_disconnect(struct usb_interface *intf) device_remove_file(&acm->control->dev, &dev_attr_iCountryCodeRelDate); } + wake_up_all(&acm->wioctl); device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); usb_set_intfdata(acm->control, NULL); usb_set_intfdata(acm->data, NULL); diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 0f76e4af600e..e38dc785808f 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -106,6 +106,9 @@ struct acm { struct work_struct work; /* work queue entry for line discipline waking up */ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ unsigned int ctrlout; /* output control lines (DTR, RTS) */ + struct async_icount iocount; /* counters for control line changes */ + struct async_icount oldcount; /* for comparison of counter */ + wait_queue_head_t wioctl; /* for ioctl */ unsigned int writesize; /* max packet size for the output bulk endpoint */ unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ unsigned int minor; /* acm minor number */ -- cgit v1.2.3 From 797ef13716ce05d26c5be12893ca75b2b003f25f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 20 Nov 2013 11:35:35 +0100 Subject: cdc-acm: add TIOCGICOUNT Simple straightforward implementation. Just returning the statistics gathered for TIOCMIWAIT Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7c0051710a04..92e28ecda834 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -853,6 +853,27 @@ static int wait_serial_change(struct acm *acm, unsigned long arg) return rv; } +static int get_serial_usage(struct acm *acm, + struct serial_icounter_struct __user *count) +{ + struct serial_icounter_struct icount; + int rv = 0; + + memset(&icount, 0, sizeof(icount)); + icount.dsr = acm->iocount.dsr; + icount.rng = acm->iocount.rng; + icount.dcd = acm->iocount.dcd; + icount.frame = acm->iocount.frame; + icount.overrun = acm->iocount.overrun; + icount.parity = acm->iocount.parity; + icount.brk = acm->iocount.brk; + + if (copy_to_user(count, &icount, sizeof(icount)) > 0) + rv = -EFAULT; + + return rv; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -869,6 +890,9 @@ static int acm_tty_ioctl(struct tty_struct *tty, case TIOCMIWAIT: rv = wait_serial_change(acm, arg); break; + case TIOCGICOUNT: + rv = get_serial_usage(acm, (struct serial_icounter_struct __user *) arg); + break; } return rv; -- cgit v1.2.3 From 8fdbeb26b5105282e55559b54a660fe7b6eed331 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 20 Nov 2013 11:35:36 +0100 Subject: cdc-acm: fix power management in ioctl An ioctl that does depends on communication with a device should prevent suspension of teh device. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 92e28ecda834..8fe32eb7970e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -888,7 +888,13 @@ static int acm_tty_ioctl(struct tty_struct *tty, rv = set_serial_info(acm, (struct serial_struct __user *) arg); break; case TIOCMIWAIT: + rv = usb_autopm_get_interface(acm->control); + if (rv < 0) { + rv = -EIO; + break; + } rv = wait_serial_change(acm, arg); + usb_autopm_put_interface(acm->control); break; case TIOCGICOUNT: rv = get_serial_usage(acm, (struct serial_icounter_struct __user *) arg); -- cgit v1.2.3 From 5c2a18014f906d81ae83484801831650f0fa07fe Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:22:57 +0100 Subject: ohci: remove conditional compilation Conditional compilation for debugging is removed in favor of dynamic debugging. To do so 1. the support for debugfs is always compiled 2. the support for the ancient print_urb debugging aid is removed Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-dbg.c | 69 --------------------------------------------- drivers/usb/host/ohci-hcd.c | 8 ------ drivers/usb/host/ohci-q.c | 4 --- drivers/usb/host/ohci.h | 7 +---- 4 files changed, 1 insertion(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 3fca52ec02ac..45032e933e18 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -9,8 +9,6 @@ /*-------------------------------------------------------------------------*/ -#ifdef DEBUG - #define edstring(ed_type) ({ char *temp; \ switch (ed_type) { \ case PIPE_CONTROL: temp = "ctrl"; break; \ @@ -20,57 +18,6 @@ } temp;}) #define pipestring(pipe) edstring(usb_pipetype(pipe)) -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header - */ -static void __maybe_unused -urb_print(struct urb * urb, char * str, int small, int status) -{ - unsigned int pipe= urb->pipe; - - if (!urb->dev || !urb->dev->bus) { - printk(KERN_DEBUG "%s URB: no dev\n", str); - return; - } - -#ifndef OHCI_VERBOSE_DEBUG - if (status != 0) -#endif - printk(KERN_DEBUG "%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d\n", - str, - urb, - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? "out" : "in", - pipestring (pipe), - urb->transfer_flags, - urb->actual_length, - urb->transfer_buffer_length, - status); - -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol (pipe)) { - printk (KERN_DEBUG "%s: setup(8):", __FILE__); - for (i = 0; i < 8 ; i++) - printk (" %02x", ((__u8 *) urb->setup_packet) [i]); - printk ("\n"); - } - if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { - printk (KERN_DEBUG "%s: data(%d/%d):", __FILE__, - urb->actual_length, - urb->transfer_buffer_length); - len = usb_pipeout (pipe)? - urb->transfer_buffer_length: urb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); - printk ("%s stat:%d\n", i < len? "...": "", status); - } - } -#endif -} #define ohci_dbg_sw(ohci, next, size, format, arg...) \ do { \ @@ -407,22 +354,8 @@ ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, } } -#else -static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {} - -#undef OHCI_VERBOSE_DEBUG - -#endif /* DEBUG */ - /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files (struct ohci_hcd *bus) { } -static inline void remove_debug_files (struct ohci_hcd *bus) { } - -#else - static int debug_async_open(struct inode *, struct file *); static int debug_periodic_open(struct inode *, struct file *); static int debug_registers_open(struct inode *, struct file *); @@ -871,7 +804,5 @@ static inline void remove_debug_files (struct ohci_hcd *ohci) debugfs_remove(ohci->debug_dir); } -#endif - /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 8ada13f8dde2..e1c68094508d 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -127,10 +127,6 @@ static int ohci_urb_enqueue ( unsigned long flags; int retval = 0; -#ifdef OHCI_VERBOSE_DEBUG - urb_print(urb, "SUB", usb_pipein(pipe), -EINPROGRESS); -#endif - /* every endpoint has a ed, locate and maybe (re)initialize it */ if (! (ed = ed_get (ohci, urb->ep, urb->dev, pipe, urb->interval))) return -ENOMEM; @@ -284,10 +280,6 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) unsigned long flags; int rc; -#ifdef OHCI_VERBOSE_DEBUG - urb_print(urb, "UNLINK", 1, status); -#endif - spin_lock_irqsave (&ohci->lock, flags); rc = usb_hcd_check_unlink_urb(hcd, urb, status); if (rc) { diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index e7f577e63624..182eaa2183b1 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -68,10 +68,6 @@ __acquires(ohci->lock) break; } -#ifdef OHCI_VERBOSE_DEBUG - urb_print(urb, "RET", usb_pipeout (urb->pipe), status); -#endif - /* urb->complete() can reenter this HCD */ usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb); spin_unlock (&ohci->lock); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index e2e5faa5a402..ea02722cab04 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -415,12 +415,11 @@ struct ohci_hcd { struct ed *ed_to_check; unsigned zf_delay; -#ifdef DEBUG struct dentry *debug_dir; struct dentry *debug_async; struct dentry *debug_periodic; struct dentry *debug_registers; -#endif + /* platform-specific data -- must come last */ unsigned long priv[0] __aligned(sizeof(s64)); @@ -474,10 +473,6 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci) /*-------------------------------------------------------------------------*/ -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - #define ohci_dbg(ohci, fmt, args...) \ dev_dbg (ohci_to_hcd(ohci)->self.controller , fmt , ## args ) #define ohci_err(ohci, fmt, args...) \ -- cgit v1.2.3 From d2c4254ff9753485900762dea98958ae4622aa05 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:22:58 +0100 Subject: ohci: kill ohci_vdbg With the introduction of dynamic debugging it has become redundant. Collapse it with ohci_dbg() Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 4 ++-- drivers/usb/host/ohci-q.c | 8 ++++---- drivers/usb/host/ohci.h | 6 ------ 3 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index e1c68094508d..501ecea4917f 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -832,7 +832,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) } if (ints & OHCI_INTR_RHSC) { - ohci_vdbg(ohci, "rhsc\n"); + ohci_dbg(ohci, "rhsc\n"); ohci->next_statechange = jiffies + STATECHANGE_DELAY; ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, ®s->intrstatus); @@ -854,7 +854,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) * this might not happen. */ else if (ints & OHCI_INTR_RD) { - ohci_vdbg(ohci, "resume detect\n"); + ohci_dbg(ohci, "resume detect\n"); ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); set_bit(HCD_FLAG_POLL_RH, &hcd->flags); if (ohci->autostop) { diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 182eaa2183b1..d4253e319428 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -143,7 +143,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) { unsigned i; - ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n", + ohci_dbg(ohci, "link %sed %p branch %d [%dus.], interval %d\n", (ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "", ed, ed->branch, ed->load, ed->interval); @@ -290,7 +290,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) } ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval; - ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", + ohci_dbg(ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", (ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "", ed, ed->branch, ed->load, ed->interval); } @@ -761,7 +761,7 @@ static int td_done(struct ohci_hcd *ohci, struct urb *urb, struct td *td) urb->iso_frame_desc [td->index].status = cc_to_error [cc]; if (cc != TD_CC_NOERROR) - ohci_vdbg (ohci, + ohci_dbg(ohci, "urb %p iso td %p (%d) len %d cc %d\n", urb, td, 1 + td->index, dlen, cc); @@ -793,7 +793,7 @@ static int td_done(struct ohci_hcd *ohci, struct urb *urb, struct td *td) } if (cc != TD_CC_NOERROR && cc < 0x0E) - ohci_vdbg (ohci, + ohci_dbg(ohci, "urb %p td %p (%d) cc %d, len=%d/%d\n", urb, td, 1 + td->index, cc, urb->actual_length, diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index ea02722cab04..9250cada13f0 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -482,12 +482,6 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci) #define ohci_warn(ohci, fmt, args...) \ dev_warn (ohci_to_hcd(ohci)->self.controller , fmt , ## args ) -#ifdef OHCI_VERBOSE_DEBUG -# define ohci_vdbg ohci_dbg -#else -# define ohci_vdbg(ohci, fmt, args...) do { } while (0) -#endif - /*-------------------------------------------------------------------------*/ /* -- cgit v1.2.3 From 1714ba0e8ec07ff9a7f6d165d4fbb471df6c10da Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:22:59 +0100 Subject: ohci:always register debug files Just remove the conditional compilation. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 501ecea4917f..de0e3e430ea0 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1225,13 +1225,11 @@ static int __init ohci_hcd_mod_init(void) sizeof (struct ed), sizeof (struct td)); set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); -#ifdef DEBUG ohci_debug_root = debugfs_create_dir("ohci", usb_debug_root); if (!ohci_debug_root) { retval = -ENOENT; goto error_debug; } -#endif #ifdef PS3_SYSTEM_BUS_DRIVER retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); @@ -1306,11 +1304,9 @@ static int __init ohci_hcd_mod_init(void) ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); error_ps3: #endif -#ifdef DEBUG debugfs_remove(ohci_debug_root); ohci_debug_root = NULL; error_debug: -#endif clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); return retval; @@ -1340,9 +1336,7 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif -#ifdef DEBUG debugfs_remove(ohci_debug_root); -#endif clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); } module_exit(ohci_hcd_mod_exit); -- cgit v1.2.3 From 00b033bb90c1e8838616f342abe6e2f0a56e839f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:00 +0100 Subject: ohci: no conditional debugging in root hub hadling With dynamic debugging the selection is done in user space Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 61705a760e7d..c81c8721cc5a 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -725,10 +725,8 @@ static int ohci_hub_control ( temp = roothub_portstatus (ohci, wIndex); put_unaligned_le32(temp, buf); -#ifndef OHCI_VERBOSE_DEBUG - if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ -#endif - dbg_port (ohci, "GetStatus", wIndex, temp); + if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ + dbg_port(ohci, "GetStatus", wIndex, temp); break; case SetHubFeature: switch (wValue) { -- cgit v1.2.3 From bbcd5cab03e61f69d50a1535ff2646f9698b9760 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:01 +0100 Subject: ehci: no conditional compilation for interestingness Simple elemination of the conditional compilation Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 835fc0844a66..47b858fc50b2 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -1114,10 +1114,8 @@ static int ehci_hub_control ( if (test_bit(wIndex, &ehci->port_c_suspend)) status |= USB_PORT_STAT_C_SUSPEND << 16; -#ifndef VERBOSE_DEBUG - if (status & ~0xffff) /* only if wPortChange is interesting */ -#endif - dbg_port (ehci, "GetStatus", wIndex + 1, temp); + if (status & ~0xffff) /* only if wPortChange is interesting */ + dbg_port(ehci, "GetStatus", wIndex + 1, temp); put_unaligned_le32(status, buf); break; case SetHubFeature: -- cgit v1.2.3 From 991fb3daac946441dbf4c237b2dd4d6c11fff633 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:02 +0100 Subject: ehci: Remove debugging at every interrupt This is overkill. Just removeit. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e8ba4c44223a..b57e997eb716 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -714,13 +714,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) cmd = ehci_readl(ehci, &ehci->regs->command); bh = 0; -#ifdef VERBOSE_DEBUG - /* unrequested/ignored: Frame List Rollover */ - dbg_status (ehci, "irq", status); -#endif - - /* INT, ERR, and IAA interrupt rates can be throttled */ - /* normal [4.15.1.2] or error [4.15.1.1] completion */ if (likely ((status & (STS_INT|STS_ERR)) != 0)) { if (likely ((status & STS_ERR) == 0)) -- cgit v1.2.3 From a90b8fc6f477ef40bd7a50354ce4ae029d8c70c5 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:03 +0100 Subject: fotg210: remove conditional compilation Always compile in the debugfs support Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 8 -------- drivers/usb/host/fotg210.h | 8 -------- 2 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 55486bd23cf1..3af053343cf4 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -352,13 +352,6 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files(struct fotg210_hcd *bus) { } -static inline void remove_debug_files(struct fotg210_hcd *bus) { } - -#else - /* troubleshooting help: expose state in debugfs */ static int debug_async_open(struct inode *, struct file *); @@ -954,7 +947,6 @@ static inline void remove_debug_files(struct fotg210_hcd *fotg210) debugfs_remove_recursive(fotg210->debug_dir); } -#endif /* STUB_DEBUG_FILES */ /*-------------------------------------------------------------------------*/ /* diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h index 8920f9d32564..ac6cd1bfd208 100644 --- a/drivers/usb/host/fotg210.h +++ b/drivers/usb/host/fotg210.h @@ -174,9 +174,7 @@ struct fotg210_hcd { /* one per controller */ #endif /* debug files */ -#ifdef DEBUG struct dentry *debug_dir; -#endif }; /* convert between an HCD pointer and the corresponding FOTG210_HCD */ @@ -741,10 +739,4 @@ static inline unsigned fotg210_read_frame_index(struct fotg210_hcd *fotg210) }) /*-------------------------------------------------------------------------*/ -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - #endif /* __LINUX_FOTG210_H */ -- cgit v1.2.3 From 063635ec3ac6d02cefce06038f2166bbff85d840 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:04 +0100 Subject: fotg210: always compile the support for debugfs Simply remove the conditional compilation and remove the empty stubs. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 47 ------------------------------------------ 1 file changed, 47 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 3af053343cf4..15ee566e46cb 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -59,9 +59,7 @@ static const char hcd_name[] = "fotg210_hcd"; #undef VERBOSE_DEBUG #undef FOTG210_URB_TRACE -#ifdef DEBUG #define FOTG210_STATS -#endif /* magic numbers that can affect system performance */ #define FOTG210_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ @@ -113,8 +111,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); static inline void fotg210_vdbg(struct fotg210_hcd *fotg210, ...) {} #endif -#ifdef DEBUG - /* check the values in the HCSPARAMS register * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value @@ -129,13 +125,6 @@ static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) HCS_N_PORTS(params) ); } -#else - -static inline void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) {} - -#endif - -#ifdef DEBUG /* check the values in the HCCPARAMS register * (host controller _Capability_ parameters) @@ -152,13 +141,6 @@ static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", HCC_CANPARK(params) ? " park" : ""); } -#else - -static inline void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) {} - -#endif - -#ifdef DEBUG static void __maybe_unused dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd) @@ -308,29 +290,6 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) (status & PORT_CONNECT) ? " CONNECT" : ""); } -#else -static inline void __maybe_unused -dbg_qh(char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{} - -static inline int __maybe_unused -dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) -{ return 0; } - -static inline int __maybe_unused -dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) -{ return 0; } - -static inline int __maybe_unused -dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } - -static inline int __maybe_unused -dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } - -#endif /* DEBUG */ - /* functions have the "wrong" filename when they're output... */ #define dbg_status(fotg210, label, status) { \ char _buf[80]; \ @@ -6005,13 +5964,11 @@ static int __init fotg210_hcd_init(void) sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd), sizeof(struct fotg210_itd)); -#ifdef DEBUG fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root); if (!fotg210_debug_root) { retval = -ENOENT; goto err_debug; } -#endif retval = platform_driver_register(&fotg210_hcd_driver); if (retval < 0) @@ -6020,11 +5977,9 @@ static int __init fotg210_hcd_init(void) platform_driver_unregister(&fotg210_hcd_driver); clean: -#ifdef DEBUG debugfs_remove(fotg210_debug_root); fotg210_debug_root = NULL; err_debug: -#endif clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); return retval; } @@ -6033,9 +5988,7 @@ module_init(fotg210_hcd_init); static void __exit fotg210_hcd_cleanup(void) { platform_driver_unregister(&fotg210_hcd_driver); -#ifdef DEBUG debugfs_remove(fotg210_debug_root); -#endif clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(fotg210_hcd_cleanup); -- cgit v1.2.3 From f848a88d223cafa43cb318839a1171b498cf5ec8 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:05 +0100 Subject: fotg210: change dbg_port() to evaluate parameters only if needed For dynamic debug the overhead for evaluating parameters must be sacrificed only if the message is actually printed Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 15ee566e46cb..4acb6a451391 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -254,8 +254,8 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) ); } -static int -dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) +static char +*dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) { char *sig; @@ -275,7 +275,7 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) break; } - return scnprintf(buf, len, + scnprintf(buf, len, "%s%sport:%d status %06x %d " "sig=%s%s%s%s%s%s%s%s", label, label[0] ? " " : "", port, status, @@ -288,6 +288,7 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) (status & PORT_PE) ? " PE" : "", (status & PORT_CSC) ? " CSC" : "", (status & PORT_CONNECT) ? " CONNECT" : ""); + return buf; } /* functions have the "wrong" filename when they're output... */ @@ -305,8 +306,7 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) #define dbg_port(fotg210, label, port, status) { \ char _buf[80]; \ - dbg_port_buf(_buf, sizeof(_buf), label, port, status); \ - fotg210_dbg(fotg210, "%s\n", _buf); \ + fotg210_dbg(fotg210, "%s\n", dbg_port_buf(_buf, sizeof(_buf), label, port, status) ); \ } /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 3b707ece5b286cca47104364b2064ebb526d69ea Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:06 +0100 Subject: fotg210: remove conditional compilation The decision what is interesting is made in user space. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 4acb6a451391..22f0b6859564 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -1761,10 +1761,8 @@ static int fotg210_hub_control( if (test_bit(wIndex, &fotg210->port_c_suspend)) status |= USB_PORT_STAT_C_SUSPEND << 16; -#ifndef VERBOSE_DEBUG - if (status & ~0xffff) /* only if wPortChange is interesting */ -#endif - dbg_port(fotg210, "GetStatus", wIndex + 1, temp); + if (status & ~0xffff) /* only if wPortChange is interesting */ + dbg_port(fotg210, "GetStatus", wIndex + 1, temp); put_unaligned_le32(status, buf); break; case SetHubFeature: @@ -2225,13 +2223,12 @@ static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210, * Note: this routine is never called for Isochronous transfers. */ if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { -#ifdef DEBUG struct usb_device *tt = urb->dev->tt->hub; dev_dbg(&tt->dev, "clear tt buffer port %d, a%d ep%d t%08x\n", urb->dev->ttport, urb->dev->devnum, usb_pipeendpoint(urb->pipe), token); -#endif /* DEBUG */ + if (urb->dev->tt->hub != fotg210_to_hcd(fotg210)->self.root_hub) { if (usb_hub_clear_tt_buffer(urb) == 0) @@ -3534,11 +3531,9 @@ periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe) break; } } -#ifdef DEBUG if (usecs > fotg210->uframe_periodic_max) fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n", frame * 8 + uframe, usecs); -#endif return usecs; } @@ -5395,10 +5390,8 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd) cmd = fotg210_readl(fotg210, &fotg210->regs->command); bh = 0; -#ifdef VERBOSE_DEBUG /* unrequested/ignored: Frame List Rollover */ dbg_status(fotg210, "irq", status); -#endif /* INT, ERR, and IAA interrupt rates can be throttled */ -- cgit v1.2.3 From be5ac4c43d13f68320de16c2d1bcecdba0adbea1 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:07 +0100 Subject: fotg210: kill fotg210_vdbg() The decision what is interesting is shifted to user space by dynamic debugging. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 22f0b6859564..070582bb41ae 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -105,12 +105,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); #define fotg210_warn(fotg210, fmt, args...) \ dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) -#ifdef VERBOSE_DEBUG -# define fotg210_vdbg fotg210_dbg -#else - static inline void fotg210_vdbg(struct fotg210_hcd *fotg210, ...) {} -#endif - /* check the values in the HCSPARAMS register * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value @@ -1349,7 +1343,7 @@ static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210) &fotg210->regs->status); } - fotg210_vdbg(fotg210, "IAA watchdog: status %x cmd %x\n", + fotg210_dbg(fotg210, "IAA watchdog: status %x cmd %x\n", status, cmd); end_unlink_async(fotg210); } @@ -1805,7 +1799,7 @@ static int fotg210_hub_control( * which can be fine if this root hub has a * transaction translator built in. */ - fotg210_vdbg(fotg210, "port %d reset\n", wIndex + 1); + fotg210_dbg(fotg210, "port %d reset\n", wIndex + 1); temp |= PORT_RESET; temp &= ~PORT_PE; @@ -2289,7 +2283,7 @@ static int qtd_copy_status( status = -EPROTO; } - fotg210_vdbg(fotg210, + fotg210_dbg(fotg210, "dev%d ep%d%s qtd token %08x --> status %d\n", usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe), @@ -4592,7 +4586,7 @@ static void itd_link_urb( if (unlikely(list_empty(&stream->td_list))) { fotg210_to_hcd(fotg210)->self.bandwidth_allocated += stream->bandwidth; - fotg210_vdbg(fotg210, + fotg210_dbg(fotg210, "schedule devp %s ep%d%s-iso period %d start %d.%d\n", urb->dev->devpath, stream->bEndpointAddress & 0x0f, (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", @@ -4725,7 +4719,7 @@ static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd) if (unlikely(list_is_singular(&stream->td_list))) { fotg210_to_hcd(fotg210)->self.bandwidth_allocated -= stream->bandwidth; - fotg210_vdbg(fotg210, + fotg210_dbg(fotg210, "deschedule devp %s ep%d%s-iso\n", dev->devpath, stream->bEndpointAddress & 0x0f, (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); -- cgit v1.2.3 From 0ada24a497c3f82cb806bb4b923a2edcf8ee7815 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:08 +0100 Subject: fusbh200: always build debugfs support This gets rid of conditional compilation. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fusbh200-hcd.c | 31 ------------------------------- drivers/usb/host/fusbh200.h | 8 -------- 2 files changed, 39 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index e1c6d850a7e1..b9f9592e2679 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -159,8 +159,6 @@ static inline void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label) { #endif -#ifdef DEBUG - static void __maybe_unused dbg_qtd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd) { @@ -302,29 +300,6 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) (status & PORT_CONNECT) ? " CONNECT" : ""); } -#else -static inline void __maybe_unused -dbg_qh (char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) -{} - -static inline int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) -{ return 0; } - -static inline int __maybe_unused -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) -{ return 0; } - -static inline int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } - -static inline int __maybe_unused -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } - -#endif /* DEBUG */ - /* functions have the "wrong" filename when they're output... */ #define dbg_status(fusbh200, label, status) { \ char _buf [80]; \ @@ -5936,13 +5911,11 @@ static int __init fusbh200_hcd_init(void) sizeof(struct fusbh200_qh), sizeof(struct fusbh200_qtd), sizeof(struct fusbh200_itd)); -#ifdef DEBUG fusbh200_debug_root = debugfs_create_dir("fusbh200", usb_debug_root); if (!fusbh200_debug_root) { retval = -ENOENT; goto err_debug; } -#endif retval = platform_driver_register(&fusbh200_hcd_fusbh200_driver); if (retval < 0) @@ -5951,11 +5924,9 @@ static int __init fusbh200_hcd_init(void) platform_driver_unregister(&fusbh200_hcd_fusbh200_driver); clean: -#ifdef DEBUG debugfs_remove(fusbh200_debug_root); fusbh200_debug_root = NULL; err_debug: -#endif clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); return retval; } @@ -5964,9 +5935,7 @@ module_init(fusbh200_hcd_init); static void __exit fusbh200_hcd_cleanup(void) { platform_driver_unregister(&fusbh200_hcd_fusbh200_driver); -#ifdef DEBUG debugfs_remove(fusbh200_debug_root); -#endif clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(fusbh200_hcd_cleanup); diff --git a/drivers/usb/host/fusbh200.h b/drivers/usb/host/fusbh200.h index 797c9e855270..5b732050ceba 100644 --- a/drivers/usb/host/fusbh200.h +++ b/drivers/usb/host/fusbh200.h @@ -173,9 +173,7 @@ struct fusbh200_hcd { /* one per controller */ #endif /* debug files */ -#ifdef DEBUG struct dentry *debug_dir; -#endif }; /* convert between an HCD pointer and the corresponding FUSBH200_HCD */ @@ -734,10 +732,4 @@ static inline unsigned fusbh200_read_frame_index(struct fusbh200_hcd *fusbh200) }) /*-------------------------------------------------------------------------*/ -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - #endif /* __LINUX_FUSBH200_H */ -- cgit v1.2.3 From cadb37569871018600531ee4f2bb3da3c746bd91 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:09 +0100 Subject: uhci: change dependency for debug parameter To allow a full switch to dynamic debugging make the debug parameter conditional on defined(DEBUF) || defined(CONFIG_DYNAMIC_DEBUG) Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4a86b63745b8..d9d3c5a98d83 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -69,18 +69,21 @@ MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications"); * show all queues in /sys/kernel/debug/uhci/[pci_addr] * debug = 3, show all TDs in URBs when dumping */ -#ifdef DEBUG -#define DEBUG_CONFIGURED 1 +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) + static int debug = 1; module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level"); +static char *errbuf; #else -#define DEBUG_CONFIGURED 0 -#define debug 0 + +#define debug 0 +#define errbuf NULL + #endif -static char *errbuf; + #define ERRBUF_LEN (32 * 1024) static struct kmem_cache *uhci_up_cachep; /* urb_priv */ @@ -516,13 +519,12 @@ static void release_uhci(struct uhci_hcd *uhci) { int i; - if (DEBUG_CONFIGURED) { - spin_lock_irq(&uhci->lock); - uhci->is_initialized = 0; - spin_unlock_irq(&uhci->lock); - debugfs_remove(uhci->dentry); - } + spin_lock_irq(&uhci->lock); + uhci->is_initialized = 0; + spin_unlock_irq(&uhci->lock); + + debugfs_remove(uhci->dentry); for (i = 0; i < UHCI_NUM_SKELQH; i++) uhci_free_qh(uhci, uhci->skelqh[i]); @@ -868,14 +870,14 @@ static int __init uhci_hcd_init(void) ignore_oc ? ", overcurrent ignored" : ""); set_bit(USB_UHCI_LOADED, &usb_hcds_loaded); - if (DEBUG_CONFIGURED) { - errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); - if (!errbuf) - goto errbuf_failed; - uhci_debugfs_root = debugfs_create_dir("uhci", usb_debug_root); - if (!uhci_debugfs_root) - goto debug_failed; - } +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) + errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); + if (!errbuf) + goto errbuf_failed; + uhci_debugfs_root = debugfs_create_dir("uhci", usb_debug_root); + if (!uhci_debugfs_root) + goto debug_failed; +#endif uhci_up_cachep = kmem_cache_create("uhci_urb_priv", sizeof(struct urb_priv), 0, 0, NULL); @@ -906,12 +908,14 @@ clean0: kmem_cache_destroy(uhci_up_cachep); up_failed: +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) debugfs_remove(uhci_debugfs_root); debug_failed: kfree(errbuf); errbuf_failed: +#endif clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); return retval; @@ -927,7 +931,9 @@ static void __exit uhci_hcd_cleanup(void) #endif kmem_cache_destroy(uhci_up_cachep); debugfs_remove(uhci_debugfs_root); +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) kfree(errbuf); +#endif clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); } -- cgit v1.2.3 From 9bab24afba2eb663efbd7f681731f8f49d42c4e8 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:10 +0100 Subject: uhci: compile debugfs conditional on CONFIG_DYNAMIC_DEBUG || DEBUG This makes sure the header files are all there Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 8e239cdd95d5..3989f0ad0539 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -20,7 +20,7 @@ static struct dentry *uhci_debugfs_root; -#ifdef DEBUG +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) /* Handle REALLY large printks so we don't overflow buffers */ static void lprintk(char *buf) @@ -635,7 +635,7 @@ static const struct file_operations uhci_debug_operations = { #endif /* CONFIG_DEBUG_FS */ -#else /* DEBUG */ +#else /* DEBUG || CONFIG_DYNAMIC_DEBUG*/ static inline void lprintk(char *buf) {} -- cgit v1.2.3 From 8f3fd9df2630a162f524b7633397cca95eeea28a Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:11 +0100 Subject: fusbh200: unconditionally compile debugging helpers These helpers are used only during setup of a HCD. A small overhead is no problem. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fusbh200-hcd.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index b9f9592e2679..17374a349e87 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -114,8 +114,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); static inline void fusbh200_vdbg(struct fusbh200_hcd *fusbh200, ...) {} #endif -#ifdef DEBUG - /* check the values in the HCSPARAMS register * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value @@ -130,13 +128,6 @@ static void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label) HCS_N_PORTS (params) ); } -#else - -static inline void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label) {} - -#endif - -#ifdef DEBUG /* check the values in the HCCPARAMS register * (host controller _Capability_ parameters) @@ -153,11 +144,6 @@ static void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label) HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", HCC_CANPARK(params) ? " park" : ""); } -#else - -static inline void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label) {} - -#endif static void __maybe_unused dbg_qtd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd) -- cgit v1.2.3 From cb0badad021f546dc5599cd2ec7da203c294586d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:12 +0100 Subject: fusb200h: don't log on every interrupt That logging is overkill. Simply remove it. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fusbh200-hcd.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index 17374a349e87..bbe1e22b2cb4 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -5326,13 +5326,6 @@ static irqreturn_t fusbh200_irq (struct usb_hcd *hcd) cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command); bh = 0; -#ifdef VERBOSE_DEBUG - /* unrequested/ignored: Frame List Rollover */ - dbg_status (fusbh200, "irq", status); -#endif - - /* INT, ERR, and IAA interrupt rates can be throttled */ - /* normal [4.15.1.2] or error [4.15.1.1] completion */ if (likely ((status & (STS_INT|STS_ERR)) != 0)) { if (likely ((status & STS_ERR) == 0)) -- cgit v1.2.3 From 514fbbf6635b06849fa776f71e5e00a4fff0ad36 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:13 +0100 Subject: fusbh200: always compile debugfs support This is a step in the conversion to only use dynamic debugging. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fusbh200-hcd.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index bbe1e22b2cb4..10cae6cd75a3 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -307,13 +307,6 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files (struct fusbh200_hcd *bus) { } -static inline void remove_debug_files (struct fusbh200_hcd *bus) { } - -#else - /* troubleshooting help: expose state in debugfs */ static int debug_async_open(struct inode *, struct file *); @@ -889,7 +882,6 @@ static inline void remove_debug_files (struct fusbh200_hcd *fusbh200) debugfs_remove_recursive(fusbh200->debug_dir); } -#endif /* STUB_DEBUG_FILES */ /*-------------------------------------------------------------------------*/ /* -- cgit v1.2.3 From c9472a2912e4ace063961c6f34ce80b105d6c1c6 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:14 +0100 Subject: fusb200h: always compile in debugfs support This allows removal of much conditional compilation. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fusbh200-hcd.c | 20 ++++---------------- drivers/usb/host/fusbh200.h | 4 ---- 2 files changed, 4 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index 10cae6cd75a3..b561e87b1fae 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -60,10 +60,6 @@ static const char hcd_name [] = "fusbh200_hcd"; #undef VERBOSE_DEBUG #undef FUSBH200_URB_TRACE -#ifdef DEBUG -#define FUSBH200_STATS -#endif - /* magic numbers that can affect system performance */ #define FUSBH200_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ #define FUSBH200_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ @@ -729,7 +725,6 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) next += temp; } -#ifdef FUSBH200_STATS temp = scnprintf (next, size, "irq normal %ld err %ld iaa %ld (lost %ld)\n", fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa, @@ -741,7 +736,6 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) fusbh200->stats.complete, fusbh200->stats.unlink); size -= temp; next += temp; -#endif done: spin_unlock_irqrestore (&fusbh200->lock, flags); @@ -1722,10 +1716,8 @@ static int fusbh200_hub_control ( if (test_bit(wIndex, &fusbh200->port_c_suspend)) status |= USB_PORT_STAT_C_SUSPEND << 16; -#ifndef VERBOSE_DEBUG - if (status & ~0xffff) /* only if wPortChange is interesting */ -#endif - dbg_port (fusbh200, "GetStatus", wIndex + 1, temp); + if (status & ~0xffff) /* only if wPortChange is interesting */ + dbg_port(fusbh200, "GetStatus", wIndex + 1, temp); put_unaligned_le32(status, buf); break; case SetHubFeature: @@ -2183,13 +2175,13 @@ static void fusbh200_clear_tt_buffer(struct fusbh200_hcd *fusbh200, struct fusbh * Note: this routine is never called for Isochronous transfers. */ if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { -#ifdef DEBUG struct usb_device *tt = urb->dev->tt->hub; + dev_dbg(&tt->dev, "clear tt buffer port %d, a%d ep%d t%08x\n", urb->dev->ttport, urb->dev->devnum, usb_pipeendpoint(urb->pipe), token); -#endif /* DEBUG */ + if (urb->dev->tt->hub != fusbh200_to_hcd(fusbh200)->self.root_hub) { if (usb_hub_clear_tt_buffer(urb) == 0) @@ -3482,11 +3474,9 @@ periodic_usecs (struct fusbh200_hcd *fusbh200, unsigned frame, unsigned uframe) break; } } -#ifdef DEBUG if (usecs > fusbh200->uframe_periodic_max) fusbh200_err (fusbh200, "uframe %d sched overrun: %d usecs\n", frame * 8 + uframe, usecs); -#endif return usecs; } @@ -5068,13 +5058,11 @@ static void fusbh200_stop (struct usb_hcd *hcd) spin_unlock_irq (&fusbh200->lock); fusbh200_mem_cleanup (fusbh200); -#ifdef FUSBH200_STATS fusbh200_dbg(fusbh200, "irq normal %ld err %ld iaa %ld (lost %ld)\n", fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa, fusbh200->stats.lost_iaa); fusbh200_dbg (fusbh200, "complete %ld unlink %ld\n", fusbh200->stats.complete, fusbh200->stats.unlink); -#endif dbg_status (fusbh200, "fusbh200_stop completed", fusbh200_readl(fusbh200, &fusbh200->regs->status)); diff --git a/drivers/usb/host/fusbh200.h b/drivers/usb/host/fusbh200.h index 5b732050ceba..6b719e066c3f 100644 --- a/drivers/usb/host/fusbh200.h +++ b/drivers/usb/host/fusbh200.h @@ -165,12 +165,8 @@ struct fusbh200_hcd { /* one per controller */ u8 sbrn; /* packed release number */ /* irq statistics */ -#ifdef FUSBH200_STATS struct fusbh200_stats stats; # define COUNT(x) do { (x)++; } while (0) -#else -# define COUNT(x) do {} while (0) -#endif /* debug files */ struct dentry *debug_dir; -- cgit v1.2.3 From 0b5fa3b21fac848de0df45c5f5e7f2086ee8e7f2 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:15 +0100 Subject: fusbh200: kill fusbh200_vdbg With dynamic debugging this log level is no longer supported. The decision which messages are interesting is done in user space. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fusbh200-hcd.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index b561e87b1fae..d5e379b8f73d 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -104,12 +104,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); #define fusbh200_warn(fusbh200, fmt, args...) \ dev_warn (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args ) -#ifdef VERBOSE_DEBUG -# define fusbh200_vdbg fusbh200_dbg -#else - static inline void fusbh200_vdbg(struct fusbh200_hcd *fusbh200, ...) {} -#endif - /* check the values in the HCSPARAMS register * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value @@ -1309,7 +1303,7 @@ static void fusbh200_iaa_watchdog(struct fusbh200_hcd *fusbh200) fusbh200_writel(fusbh200, STS_IAA, &fusbh200->regs->status); } - fusbh200_vdbg(fusbh200, "IAA watchdog: status %x cmd %x\n", + fusbh200_dbg(fusbh200, "IAA watchdog: status %x cmd %x\n", status, cmd); end_unlink_async(fusbh200); } @@ -1759,7 +1753,7 @@ static int fusbh200_hub_control ( * which can be fine if this root hub has a * transaction translator built in. */ - fusbh200_vdbg (fusbh200, "port %d reset\n", wIndex + 1); + fusbh200_dbg(fusbh200, "port %d reset\n", wIndex + 1); temp |= PORT_RESET; temp &= ~PORT_PE; @@ -2242,7 +2236,7 @@ static int qtd_copy_status ( status = -EPROTO; } - fusbh200_vdbg (fusbh200, + fusbh200_dbg(fusbh200, "dev%d ep%d%s qtd token %08x --> status %d\n", usb_pipedevice (urb->pipe), usb_pipeendpoint (urb->pipe), @@ -4529,7 +4523,7 @@ static void itd_link_urb( if (unlikely (list_empty(&stream->td_list))) { fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated += stream->bandwidth; - fusbh200_vdbg (fusbh200, + fusbh200_dbg(fusbh200, "schedule devp %s ep%d%s-iso period %d start %d.%d\n", urb->dev->devpath, stream->bEndpointAddress & 0x0f, (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", @@ -4660,7 +4654,7 @@ static bool itd_complete(struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd if (unlikely(list_is_singular(&stream->td_list))) { fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated -= stream->bandwidth; - fusbh200_vdbg (fusbh200, + fusbh200_dbg(fusbh200, "deschedule devp %s ep%d%s-iso\n", dev->devpath, stream->bEndpointAddress & 0x0f, (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); -- cgit v1.2.3 From 1c20163d30db28552a341d5e0d6c007d4c8dc8be Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:16 +0100 Subject: usb: kill DEBUG compile option In the drivers that no longer need it, it is removed. It is removed from the Makefile. Drivers not fully converted to dynamic debug have it shifted down into the individual drivers. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Makefile | 2 -- drivers/usb/host/ehci-dbg.c | 8 ++++---- drivers/usb/host/ehci-fsl.c | 2 +- drivers/usb/host/ehci-hcd.c | 6 +++--- drivers/usb/host/ehci-q.c | 4 ++-- drivers/usb/host/ehci.h | 8 ++++---- drivers/usb/host/imx21-dbg.c | 4 ++++ drivers/usb/host/imx21-hcd.c | 4 ++++ drivers/usb/host/imx21-hcd.h | 4 ++++ drivers/usb/host/oxu210hp-hcd.c | 4 ++++ drivers/usb/host/uhci-debug.c | 4 ++-- drivers/usb/host/uhci-hcd.c | 6 +++--- 12 files changed, 35 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 01e879ef3654..7530468c9a4f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -2,8 +2,6 @@ # Makefile for USB Host Controller Drivers # -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG - # tell define_trace.h where to find the xhci trace header CFLAGS_xhci-trace.o := -I$(src) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 4a9c2edbcb2b..9269782a7627 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -18,7 +18,7 @@ /* this file is part of ehci-hcd.c */ -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG /* check the values in the HCSPARAMS register * (host controller _Structural_ parameters) @@ -62,7 +62,7 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} #endif -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG /* check the values in the HCCPARAMS register * (host controller _Capability_ parameters) @@ -101,7 +101,7 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} #endif -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG static void __maybe_unused dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) @@ -301,7 +301,7 @@ static inline int __maybe_unused dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) { return 0; } -#endif /* DEBUG || CONFIG_DYNAMIC_DEBUG */ +#endif /* CONFIG_DYNAMIC_DEBUG */ /* functions have the "wrong" filename when they're output... */ #define dbg_status(ehci, label, status) { \ diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index a06d5012201f..87a7426a44f4 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -413,7 +413,7 @@ static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); u32 tmp; -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); mode &= USBMODE_CM_MASK; tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b57e997eb716..1e21a3623af9 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1313,7 +1313,7 @@ static int __init ehci_hcd_init(void) sizeof(struct ehci_qh), sizeof(struct ehci_qtd), sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); if (!ehci_debug_root) { retval = -ENOENT; @@ -1362,7 +1362,7 @@ clean2: platform_driver_unregister(&PLATFORM_DRIVER); clean0: #endif -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG debugfs_remove(ehci_debug_root); ehci_debug_root = NULL; err_debug: @@ -1386,7 +1386,7 @@ static void __exit ehci_hcd_cleanup(void) #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG debugfs_remove(ehci_debug_root); #endif clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index db05bd8ee9d5..54f5332f814d 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -168,13 +168,13 @@ static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh, * Note: this routine is never called for Isochronous transfers. */ if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG struct usb_device *tt = urb->dev->tt->hub; dev_dbg(&tt->dev, "clear tt buffer port %d, a%d ep%d t%08x\n", urb->dev->ttport, urb->dev->devnum, usb_pipeendpoint(urb->pipe), token); -#endif /* DEBUG || CONFIG_DYNAMIC_DEBUG */ +#endif /* CONFIG_DYNAMIC_DEBUG */ if (!ehci_is_TDI(ehci) || urb->dev->tt->hub != ehci_to_hcd(ehci)->self.root_hub) { diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index e8f41c5e771b..c35a6e2b94e5 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -38,7 +38,7 @@ typedef __u16 __bitwise __hc16; #endif /* statistics can be kept for tuning/monitoring */ -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG #define EHCI_STATS #endif @@ -248,7 +248,7 @@ struct ehci_hcd { /* one per controller */ #endif /* debug files */ -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG struct dentry *debug_dir; #endif @@ -832,9 +832,9 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#if !defined(DEBUG) && !defined(CONFIG_DYNAMIC_DEBUG) +#ifndef CONFIG_DYNAMIC_DEBUG #define STUB_DEBUG_FILES -#endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ +#endif /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c index ec98ecee3517..4f320d050da7 100644 --- a/drivers/usb/host/imx21-dbg.c +++ b/drivers/usb/host/imx21-dbg.c @@ -18,6 +18,10 @@ /* this file is part of imx21-hcd.c */ +#ifdef CONFIG_DYNAMIC_DEBUG +#define DEBUG +#endif + #ifndef DEBUG static inline void create_debug_files(struct imx21 *imx21) { } diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index adb01d950a16..cb6d60853502 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -62,6 +62,10 @@ #include "imx21-hcd.h" +#ifdef CONFIG_DYNAMIC_DEBUG +#define DEBUG +#endif + #ifdef DEBUG #define DEBUG_LOG_FRAME(imx21, etd, event) \ (etd)->event##_frame = readl((imx21)->regs + USBH_FRMNUB) diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h index c005770a73e9..05122f8a6983 100644 --- a/drivers/usb/host/imx21-hcd.h +++ b/drivers/usb/host/imx21-hcd.h @@ -24,6 +24,10 @@ #ifndef __LINUX_IMX21_HCD_H__ #define __LINUX_IMX21_HCD_H__ +#ifdef CONFIG_DYNAMIC_DEBUG +#define DEBUG +#endif + #include #define NUM_ISO_ETDS 2 diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 4a6df2d8f902..4a05148ee79b 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -60,6 +60,10 @@ #define oxu_info(oxu, fmt, args...) \ dev_info(oxu_to_hcd(oxu)->self.controller , fmt , ## args) +#ifdef CONFIG_DYNAMIC_DEBUG +#define DEBUG +#endif + static inline struct usb_hcd *oxu_to_hcd(struct oxu_hcd *oxu) { return container_of((void *) oxu, struct usb_hcd, hcd_priv); diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 3989f0ad0539..1b28a000d5c6 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -20,7 +20,7 @@ static struct dentry *uhci_debugfs_root; -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG /* Handle REALLY large printks so we don't overflow buffers */ static void lprintk(char *buf) @@ -635,7 +635,7 @@ static const struct file_operations uhci_debug_operations = { #endif /* CONFIG_DEBUG_FS */ -#else /* DEBUG || CONFIG_DYNAMIC_DEBUG*/ +#else /* CONFIG_DYNAMIC_DEBUG*/ static inline void lprintk(char *buf) {} diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d9d3c5a98d83..27f35e8f161b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -69,7 +69,7 @@ MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications"); * show all queues in /sys/kernel/debug/uhci/[pci_addr] * debug = 3, show all TDs in URBs when dumping */ -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG static int debug = 1; module_param(debug, int, S_IRUGO | S_IWUSR); @@ -870,7 +870,7 @@ static int __init uhci_hcd_init(void) ignore_oc ? ", overcurrent ignored" : ""); set_bit(USB_UHCI_LOADED, &usb_hcds_loaded); -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); if (!errbuf) goto errbuf_failed; @@ -931,7 +931,7 @@ static void __exit uhci_hcd_cleanup(void) #endif kmem_cache_destroy(uhci_up_cachep); debugfs_remove(uhci_debugfs_root); -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG kfree(errbuf); #endif clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); -- cgit v1.2.3 From c793d08ecd944b1a180c6712bb47825e37cc0626 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Nov 2013 13:23:17 +0100 Subject: USB: kill #undef VERBOSE_DEBUG It is useless now. Straight removal. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 1 - drivers/usb/host/fotg210-hcd.c | 1 - drivers/usb/host/fusbh200-hcd.c | 1 - drivers/usb/host/ohci-hcd.c | 2 -- 4 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 1e21a3623af9..471142725ffe 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -71,7 +71,6 @@ static const char hcd_name [] = "ehci_hcd"; -#undef VERBOSE_DEBUG #undef EHCI_URB_TRACE /* magic numbers that can affect system performance */ diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 070582bb41ae..97d6939189d6 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -56,7 +56,6 @@ static const char hcd_name[] = "fotg210_hcd"; -#undef VERBOSE_DEBUG #undef FOTG210_URB_TRACE #define FOTG210_STATS diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index d5e379b8f73d..9ea85b662a04 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -57,7 +57,6 @@ static const char hcd_name [] = "fusbh200_hcd"; -#undef VERBOSE_DEBUG #undef FUSBH200_URB_TRACE /* magic numbers that can affect system performance */ diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index de0e3e430ea0..c8e0e7637b7b 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -51,8 +51,6 @@ /*-------------------------------------------------------------------------*/ -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ - /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR #define OHCI_INTR_INIT \ -- cgit v1.2.3 From 978f47d64365fa1659178e54c5106154c315b595 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Fri, 8 Nov 2013 11:58:34 +0000 Subject: VME: Provide access to VME bus enumeration and fix vme_user match function The match function for vme_user is completely wrong. It will blindly bind against the first VME slot on each bus (at this point that would be just the first bus as the driver can only handle one bus). The original intention (before some major subsystem changes) was that the driver bind against the slot to which the bridge was attached in the VME system and to the bus(es) provided via the "bus" module parameter. To do this cleanly (i.e. without poking arround in the subsystems internal stuctures) a functionality has been added to provide access to the bus enumeration. Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- Documentation/vme_api.txt | 10 ++++++++++ drivers/staging/vme/devices/vme_user.c | 13 ++++++++++--- drivers/vme/vme.c | 13 +++++++++++++ include/linux/vme.h | 1 + 4 files changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/vme_api.txt b/Documentation/vme_api.txt index 856efa35f6e3..126a1f1d5151 100644 --- a/Documentation/vme_api.txt +++ b/Documentation/vme_api.txt @@ -394,3 +394,13 @@ Slot Detection This function returns the slot ID of the provided bridge. int vme_slot_get(struct vme_dev *dev); + + +Bus Detection +============= + +This function returns the bus ID of the provided bridge. + + int vme_bus_num(struct vme_dev *dev); + + diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index daec15565a43..caee906f9b38 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -663,9 +663,16 @@ err_nocard: static int vme_user_match(struct vme_dev *vdev) { - if (vdev->num >= VME_USER_BUS_MAX) - return 0; - return 1; + int i; + + int cur_bus = vme_bus_num(vdev); + int cur_slot = vme_slot_get(vdev); + + for (i = 0; i < bus_num; i++) + if ((cur_bus == bus[i]) && (cur_slot == vdev->num)) + return 1; + + return 0; } /* diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c index f6856b427496..8df5e4efc1ca 100644 --- a/drivers/vme/vme.c +++ b/drivers/vme/vme.c @@ -1293,6 +1293,19 @@ int vme_slot_get(struct vme_dev *vdev) } EXPORT_SYMBOL(vme_slot_get); +int vme_bus_num(struct vme_dev *vdev) +{ + struct vme_bridge *bridge; + + bridge = vdev->bridge; + if (bridge == NULL) { + pr_err("Can't find VME bus\n"); + return -EINVAL; + } + + return bridge->num; +} +EXPORT_SYMBOL(vme_bus_num); /* - Bridge Registration --------------------------------------------------- */ diff --git a/include/linux/vme.h b/include/linux/vme.h index c9d65bf14cec..4eb42c8f097d 100644 --- a/include/linux/vme.h +++ b/include/linux/vme.h @@ -165,6 +165,7 @@ int vme_lm_detach(struct vme_resource *, int); void vme_lm_free(struct vme_resource *); int vme_slot_get(struct vme_dev *); +int vme_bus_num(struct vme_dev *); int vme_register_driver(struct vme_driver *, unsigned int); void vme_unregister_driver(struct vme_driver *); -- cgit v1.2.3 From d7729f0fc40296f91b483dfb929e71b27cf75345 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Fri, 8 Nov 2013 11:58:35 +0000 Subject: VME: Rename vme_slot_get to avoid confusion with reference counting Traditionally the "get" functions increment the reference count of the object that is returned, which does not happen with vme_slot_get. The function vme_slot_get returns the physical VME slot associated with a particular struct vme_dev. Rename vme_slot_num to avoid any confusion. Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- Documentation/vme_api.txt | 2 +- drivers/staging/vme/devices/vme_user.c | 2 +- drivers/vme/vme.c | 6 +++--- include/linux/vme.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/vme_api.txt b/Documentation/vme_api.txt index 126a1f1d5151..ffe6e22a2ccd 100644 --- a/Documentation/vme_api.txt +++ b/Documentation/vme_api.txt @@ -393,7 +393,7 @@ Slot Detection This function returns the slot ID of the provided bridge. - int vme_slot_get(struct vme_dev *dev); + int vme_slot_num(struct vme_dev *dev); Bus Detection diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index caee906f9b38..bc4f8623c8cc 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -666,7 +666,7 @@ static int vme_user_match(struct vme_dev *vdev) int i; int cur_bus = vme_bus_num(vdev); - int cur_slot = vme_slot_get(vdev); + int cur_slot = vme_slot_num(vdev); for (i = 0; i < bus_num; i++) if ((cur_bus == bus[i]) && (cur_slot == vdev->num)) diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c index 8df5e4efc1ca..96562c9a8b1b 100644 --- a/drivers/vme/vme.c +++ b/drivers/vme/vme.c @@ -1274,7 +1274,7 @@ void vme_lm_free(struct vme_resource *resource) } EXPORT_SYMBOL(vme_lm_free); -int vme_slot_get(struct vme_dev *vdev) +int vme_slot_num(struct vme_dev *vdev) { struct vme_bridge *bridge; @@ -1285,13 +1285,13 @@ int vme_slot_get(struct vme_dev *vdev) } if (bridge->slot_get == NULL) { - printk(KERN_WARNING "vme_slot_get not supported\n"); + printk(KERN_WARNING "vme_slot_num not supported\n"); return -EINVAL; } return bridge->slot_get(bridge); } -EXPORT_SYMBOL(vme_slot_get); +EXPORT_SYMBOL(vme_slot_num); int vme_bus_num(struct vme_dev *vdev) { diff --git a/include/linux/vme.h b/include/linux/vme.h index 4eb42c8f097d..8cd6f19ca518 100644 --- a/include/linux/vme.h +++ b/include/linux/vme.h @@ -164,7 +164,7 @@ int vme_lm_attach(struct vme_resource *, int, void (*callback)(int)); int vme_lm_detach(struct vme_resource *, int); void vme_lm_free(struct vme_resource *); -int vme_slot_get(struct vme_dev *); +int vme_slot_num(struct vme_dev *); int vme_bus_num(struct vme_dev *); int vme_register_driver(struct vme_driver *, unsigned int); -- cgit v1.2.3 From c3a09c18ed4698ff80408af7bec8ddd28608b7f5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:29:48 +0900 Subject: vme: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/vme/boards/vme_vmivme7805.c | 2 +- drivers/vme/bridges/vme_ca91cx42.c | 2 +- drivers/vme/bridges/vme_tsi148.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/vme/boards/vme_vmivme7805.c b/drivers/vme/boards/vme_vmivme7805.c index cf74aee2cef0..ac422121f9bb 100644 --- a/drivers/vme/boards/vme_vmivme7805.c +++ b/drivers/vme/boards/vme_vmivme7805.c @@ -27,7 +27,7 @@ static void __iomem *vmic_base; static const char driver_name[] = "vmivme_7805"; -static DEFINE_PCI_DEVICE_TABLE(vmic_ids) = { +static const struct pci_device_id vmic_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) }, { }, }; diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index f8448573d030..a06edbfa95ca 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c @@ -42,7 +42,7 @@ static int geoid; static const char driver_name[] = "vme_ca91cx42"; -static DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = { +static const struct pci_device_id ca91cx42_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, { }, }; diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 9cf88337e4e9..16830d8b777c 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -45,7 +45,7 @@ static int geoid; static const char driver_name[] = "vme_tsi148"; -static DEFINE_PCI_DEVICE_TABLE(tsi148_ids) = { +static const struct pci_device_id tsi148_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) }, { }, }; -- cgit v1.2.3 From 9f9af82ff3e3927d29474049675303284e1266f7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:22 +0100 Subject: usb: core: Remove superfluous name casts device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 47aade2a5e74..8d989b1d3dc5 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -839,7 +839,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, return -ENODEV; new_udriver->drvwrap.for_devices = 1; - new_udriver->drvwrap.driver.name = (char *) new_udriver->name; + new_udriver->drvwrap.driver.name = new_udriver->name; new_udriver->drvwrap.driver.bus = &usb_bus_type; new_udriver->drvwrap.driver.probe = usb_probe_device; new_udriver->drvwrap.driver.remove = usb_unbind_device; @@ -900,7 +900,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, return -ENODEV; new_driver->drvwrap.for_devices = 0; - new_driver->drvwrap.driver.name = (char *) new_driver->name; + new_driver->drvwrap.driver.name = new_driver->name; new_driver->drvwrap.driver.bus = &usb_bus_type; new_driver->drvwrap.driver.probe = usb_probe_interface; new_driver->drvwrap.driver.remove = usb_unbind_interface; -- cgit v1.2.3 From bde5ae91e8204fb747ad409e79504cc672dc97d6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:24 +0100 Subject: usb: gadget: Remove superfluous name casts device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_qe_udc.c | 2 +- drivers/usb/gadget/fsl_udc_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 807127d56fa3..6315ee698d4d 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2717,7 +2717,7 @@ MODULE_DEVICE_TABLE(of, qe_udc_match); static struct platform_driver udc_driver = { .driver = { - .name = (char *)driver_name, + .name = driver_name, .owner = THIS_MODULE, .of_match_table = qe_udc_match, }, diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 36ac7cfba91d..b7dea4eec32c 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2666,7 +2666,7 @@ static struct platform_driver udc_driver = { .suspend = fsl_udc_suspend, .resume = fsl_udc_resume, .driver = { - .name = (char *)driver_name, + .name = driver_name, .owner = THIS_MODULE, /* udc suspend/resume called from OTG driver */ .suspend = fsl_udc_otg_suspend, -- cgit v1.2.3 From a458677db6a928535a7186248983d1e192142e83 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:25 +0100 Subject: usb: host: Remove superfluous name casts device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/isp1362-hcd.c | 2 +- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/u132-hcd.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index cb6d60853502..0122624c7ec1 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1930,7 +1930,7 @@ failed_request_mem: static struct platform_driver imx21_hcd_driver = { .driver = { - .name = (char *)hcd_name, + .name = hcd_name, }, .probe = imx21_probe, .remove = imx21_remove, diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index c7d0f8f231be..7722ec658b87 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1705,7 +1705,7 @@ static struct platform_driver isp116x_driver = { .suspend = isp116x_suspend, .resume = isp116x_resume, .driver = { - .name = (char *)hcd_name, + .name = hcd_name, .owner = THIS_MODULE, }, }; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 935a2dd367a8..cd94b108b57f 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2829,7 +2829,7 @@ static struct platform_driver isp1362_driver = { .suspend = isp1362_suspend, .resume = isp1362_resume, .driver = { - .name = (char *)hcd_name, + .name = hcd_name, .owner = THIS_MODULE, }, }; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 2ad004ae747c..3bddfcfafb79 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2534,7 +2534,7 @@ static struct platform_driver r8a66597_driver = { .probe = r8a66597_probe, .remove = r8a66597_remove, .driver = { - .name = (char *) hcd_name, + .name = hcd_name, .owner = THIS_MODULE, .pm = R8A66597_DEV_PM_OPS, }, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index e402beb5a069..46236e9fc87f 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3217,7 +3217,7 @@ static struct platform_driver u132_platform_driver = { .suspend = u132_suspend, .resume = u132_resume, .driver = { - .name = (char *)hcd_name, + .name = hcd_name, .owner = THIS_MODULE, }, }; -- cgit v1.2.3 From 59f0ad8076816d13f7cba80d2b178ff5ab787e2e Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Mon, 24 Jan 2011 15:48:19 -0300 Subject: [media] v4l: omap4iss: Add support for OMAP4 camera interface - Core This adds a very simplistic driver to utilize the CSI2A interface inside the ISS subsystem in OMAP4, and dump the data to memory. Check Documentation/video4linux/omap4_camera.txt for details. This commit adds the driver core, registers definitions and documentation. Signed-off-by: Sergio Aguirre Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/omap4_camera.txt | 60 ++ drivers/staging/media/omap4iss/iss.c | 1477 ++++++++++++++++++++++++++++ drivers/staging/media/omap4iss/iss.h | 153 +++ drivers/staging/media/omap4iss/iss_regs.h | 883 +++++++++++++++++ include/media/omap4iss.h | 65 ++ 5 files changed, 2638 insertions(+) create mode 100644 Documentation/video4linux/omap4_camera.txt create mode 100644 drivers/staging/media/omap4iss/iss.c create mode 100644 drivers/staging/media/omap4iss/iss.h create mode 100644 drivers/staging/media/omap4iss/iss_regs.h create mode 100644 include/media/omap4iss.h (limited to 'drivers') diff --git a/Documentation/video4linux/omap4_camera.txt b/Documentation/video4linux/omap4_camera.txt new file mode 100644 index 000000000000..25d9b40a4651 --- /dev/null +++ b/Documentation/video4linux/omap4_camera.txt @@ -0,0 +1,60 @@ + OMAP4 ISS Driver + ================ + +Introduction +------------ + +The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS), +Which contains several components that can be categorized in 3 big groups: + +- Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2) +- ISP (Image Signal Processor) +- SIMCOP (Still Image Coprocessor) + +For more information, please look in [1] for latest version of: + "OMAP4430 Multimedia Device Silicon Revision 2.x" + +As of Revision AB, the ISS is described in detail in section 8. + +This driver is supporting _only_ the CSI2-A/B interfaces for now. + +It makes use of the Media Controller framework [2], and inherited most of the +code from OMAP3 ISP driver (found under drivers/media/platform/omap3isp/*), +except that it doesn't need an IOMMU now for ISS buffers memory mapping. + +Supports usage of MMAP buffers only (for now). + +Tested platforms +---------------- + +- OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in + which only the last one is supported, outputting YUV422 frames). + +- TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in + which only the OV5650 are supported, outputting RAW10 frames). + +- PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with + following sensors: + * OV5640 + * OV5650 + +- Tested on mainline kernel: + + http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=summary + + Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7) + +File list +--------- +drivers/staging/media/omap4iss/ +include/media/omap4iss.h + +References +---------- + +[1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62 +[2] http://lwn.net/Articles/420485/ +[3] http://www.spinics.net/lists/linux-media/msg44370.html +-- +Author: Sergio Aguirre +Copyright (C) 2012, Texas Instruments diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c new file mode 100644 index 000000000000..d054d9b6eb0f --- /dev/null +++ b/drivers/staging/media/omap4iss/iss.c @@ -0,0 +1,1477 @@ +/* + * TI OMAP4 ISS V4L2 Driver + * + * Copyright (C) 2012, Texas Instruments + * + * Author: Sergio Aguirre + * + * 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 "iss.h" +#include "iss_regs.h" + +#define ISS_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_##name)) + +static void iss_print_status(struct iss_device *iss) +{ + dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n"); + + ISS_PRINT_REGISTER(iss, HL_REVISION); + ISS_PRINT_REGISTER(iss, HL_SYSCONFIG); + ISS_PRINT_REGISTER(iss, HL_IRQSTATUS_5); + ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_SET); + ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_CLR); + ISS_PRINT_REGISTER(iss, CTRL); + ISS_PRINT_REGISTER(iss, CLKCTRL); + ISS_PRINT_REGISTER(iss, CLKSTAT); + + dev_dbg(iss->dev, "-----------------------------------------------\n"); +} + +/* + * omap4iss_flush - Post pending L3 bus writes by doing a register readback + * @iss: OMAP4 ISS device + * + * In order to force posting of pending writes, we need to write and + * readback the same register, in this case the revision register. + * + * See this link for reference: + * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html + */ +void omap4iss_flush(struct iss_device *iss) +{ + writel(0, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); + readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); +} + +/* + * iss_enable_interrupts - Enable ISS interrupts. + * @iss: OMAP4 ISS device + */ +static void iss_enable_interrupts(struct iss_device *iss) +{ + static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB | ISS_HL_IRQ_ISP(0); + + /* Enable HL interrupts */ + writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); + writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_SET); + +} + +/* + * iss_disable_interrupts - Disable ISS interrupts. + * @iss: OMAP4 ISS device + */ +static void iss_disable_interrupts(struct iss_device *iss) +{ + writel(-1, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_CLR); +} + +/* + * iss_isp_enable_interrupts - Enable ISS ISP interrupts. + * @iss: OMAP4 ISS device + */ +void omap4iss_isp_enable_interrupts(struct iss_device *iss) +{ + static const u32 isp_irq = ISP5_IRQ_OCP_ERR | + ISP5_IRQ_RSZ_FIFO_IN_BLK | + ISP5_IRQ_RSZ_FIFO_OVF | + ISP5_IRQ_RSZ_INT_DMA | + ISP5_IRQ_ISIF0; + + /* Enable ISP interrupts */ + writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQSTATUS(0)); + writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_SET(0)); +} + +/* + * iss_isp_disable_interrupts - Disable ISS interrupts. + * @iss: OMAP4 ISS device + */ +void omap4iss_isp_disable_interrupts(struct iss_device *iss) +{ + writel(-1, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_CLR(0)); +} + +int omap4iss_get_external_info(struct iss_pipeline *pipe, + struct media_link *link) +{ + struct iss_device *iss = + container_of(pipe, struct iss_video, pipe)->iss; + struct v4l2_subdev_format fmt; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + int ret; + + if (!pipe->external) + return 0; + + if (pipe->external_rate) + return 0; + + memset(&fmt, 0, sizeof(fmt)); + + fmt.pad = link->source->index; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity), + pad, get_fmt, NULL, &fmt); + if (ret < 0) + return -EPIPE; + + pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; + + memset(&ctrls, 0, sizeof(ctrls)); + memset(&ctrl, 0, sizeof(ctrl)); + + ctrl.id = V4L2_CID_PIXEL_RATE; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(ctrl.id); + ctrls.count = 1; + ctrls.controls = &ctrl; + + ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls); + if (ret < 0) { + dev_warn(iss->dev, "no pixel rate control in subdev %s\n", + pipe->external->name); + return ret; + } + + pipe->external_rate = ctrl.value64; + + return 0; +} + +/* + * Configure the bridge. Valid inputs are + * + * IPIPEIF_INPUT_CSI2A: CSI2a receiver + * IPIPEIF_INPUT_CSI2B: CSI2b receiver + * + * The bridge and lane shifter are configured according to the selected input + * and the ISP platform data. + */ +void omap4iss_configure_bridge(struct iss_device *iss, + enum ipipeif_input_entity input) +{ + u32 issctrl_val; + u32 isp5ctrl_val; + + issctrl_val = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); + issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK; + issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK; + + isp5ctrl_val = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + + switch (input) { + case IPIPEIF_INPUT_CSI2A: + issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A; + isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT; + break; + + case IPIPEIF_INPUT_CSI2B: + issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B; + isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT; + break; + + default: + return; + } + + issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING; + + isp5ctrl_val |= ISP5_CTRL_PSYNC_CLK_SEL | ISP5_CTRL_SYNC_ENABLE; + + writel(issctrl_val, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); + writel(isp5ctrl_val, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); +} + +static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) +{ + static const char *name[] = { + "ISP_IRQ0", + "ISP_IRQ1", + "ISP_IRQ2", + "ISP_IRQ3", + "CSIA_IRQ", + "CSIB_IRQ", + "CCP2_IRQ0", + "CCP2_IRQ1", + "CCP2_IRQ2", + "CCP2_IRQ3", + "CBUFF_IRQ", + "BTE_IRQ", + "SIMCOP_IRQ0", + "SIMCOP_IRQ1", + "SIMCOP_IRQ2", + "SIMCOP_IRQ3", + "CCP2_IRQ8", + "HS_VS_IRQ", + "res18", + "res19", + "res20", + "res21", + "res22", + "res23", + "res24", + "res25", + "res26", + "res27", + "res28", + "res29", + "res30", + "res31", + }; + int i; + + dev_dbg(iss->dev, "ISS IRQ: "); + + for (i = 0; i < ARRAY_SIZE(name); i++) { + if ((1 << i) & irqstatus) + pr_cont("%s ", name[i]); + } + pr_cont("\n"); +} + +/* + * iss_isr - Interrupt Service Routine for ISS module. + * @irq: Not used currently. + * @_iss: Pointer to the OMAP4 ISS device + * + * Handles the corresponding callback if plugged in. + * + * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the + * IRQ wasn't handled. + */ +static irqreturn_t iss_isr(int irq, void *_iss) +{ + static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF | + ISP5_IRQ_ISIF0; + static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK | + ISP5_IRQ_RSZ_FIFO_OVF | + ISP5_IRQ_RSZ_INT_DMA; + struct iss_device *iss = _iss; + u32 irqstatus; + + irqstatus = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); + writel(irqstatus, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); + + if (irqstatus & ISS_HL_IRQ_CSIA) + omap4iss_csi2_isr(&iss->csi2a); + + if (irqstatus & ISS_HL_IRQ_CSIB) + omap4iss_csi2_isr(&iss->csi2b); + + if (irqstatus & ISS_HL_IRQ_ISP(0)) { + u32 isp_irqstatus = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + + ISP5_IRQSTATUS(0)); + writel(isp_irqstatus, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + + ISP5_IRQSTATUS(0)); + + if (isp_irqstatus & ISP5_IRQ_OCP_ERR) + dev_dbg(iss->dev, "ISP5 OCP Error!\n"); + + if (isp_irqstatus & ipipeif_events) { + omap4iss_ipipeif_isr(&iss->ipipeif, + isp_irqstatus & ipipeif_events); + } + + if (isp_irqstatus & resizer_events) + omap4iss_resizer_isr(&iss->resizer, + isp_irqstatus & resizer_events); + } + + omap4iss_flush(iss); + +#if defined(DEBUG) && defined(ISS_ISR_DEBUG) + iss_isr_dbg(iss, irqstatus); +#endif + + return IRQ_HANDLED; +} + +/* ----------------------------------------------------------------------------- + * Pipeline power management + * + * Entities must be powered up when part of a pipeline that contains at least + * one open video device node. + * + * To achieve this use the entity use_count field to track the number of users. + * For entities corresponding to video device nodes the use_count field stores + * the users count of the node. For entities corresponding to subdevs the + * use_count field stores the total number of users of all video device nodes + * in the pipeline. + * + * The omap4iss_pipeline_pm_use() function must be called in the open() and + * close() handlers of video device nodes. It increments or decrements the use + * count of all subdev entities in the pipeline. + * + * To react to link management on powered pipelines, the link setup notification + * callback updates the use count of all entities in the source and sink sides + * of the link. + */ + +/* + * iss_pipeline_pm_use_count - Count the number of users of a pipeline + * @entity: The entity + * + * Return the total number of users of all video device nodes in the pipeline. + */ +static int iss_pipeline_pm_use_count(struct media_entity *entity) +{ + struct media_entity_graph graph; + int use = 0; + + media_entity_graph_walk_start(&graph, entity); + + while ((entity = media_entity_graph_walk_next(&graph))) { + if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) + use += entity->use_count; + } + + return use; +} + +/* + * iss_pipeline_pm_power_one - Apply power change to an entity + * @entity: The entity + * @change: Use count change + * + * Change the entity use count by @change. If the entity is a subdev update its + * power state by calling the core::s_power operation when the use count goes + * from 0 to != 0 or from != 0 to 0. + * + * Return 0 on success or a negative error code on failure. + */ +static int iss_pipeline_pm_power_one(struct media_entity *entity, int change) +{ + struct v4l2_subdev *subdev; + + subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV + ? media_entity_to_v4l2_subdev(entity) : NULL; + + if (entity->use_count == 0 && change > 0 && subdev != NULL) { + int ret; + + ret = v4l2_subdev_call(subdev, core, s_power, 1); + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + } + + entity->use_count += change; + WARN_ON(entity->use_count < 0); + + if (entity->use_count == 0 && change < 0 && subdev != NULL) + v4l2_subdev_call(subdev, core, s_power, 0); + + return 0; +} + +/* + * iss_pipeline_pm_power - Apply power change to all entities in a pipeline + * @entity: The entity + * @change: Use count change + * + * Walk the pipeline to update the use count and the power state of all non-node + * entities. + * + * Return 0 on success or a negative error code on failure. + */ +static int iss_pipeline_pm_power(struct media_entity *entity, int change) +{ + struct media_entity_graph graph; + struct media_entity *first = entity; + int ret = 0; + + if (!change) + return 0; + + media_entity_graph_walk_start(&graph, entity); + + while (!ret && (entity = media_entity_graph_walk_next(&graph))) + if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) + ret = iss_pipeline_pm_power_one(entity, change); + + if (!ret) + return 0; + + media_entity_graph_walk_start(&graph, first); + + while ((first = media_entity_graph_walk_next(&graph)) + && first != entity) + if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE) + iss_pipeline_pm_power_one(first, -change); + + return ret; +} + +/* + * omap4iss_pipeline_pm_use - Update the use count of an entity + * @entity: The entity + * @use: Use (1) or stop using (0) the entity + * + * Update the use count of all entities in the pipeline and power entities on or + * off accordingly. + * + * Return 0 on success or a negative error code on failure. Powering entities + * off is assumed to never fail. No failure can occur when the use parameter is + * set to 0. + */ +int omap4iss_pipeline_pm_use(struct media_entity *entity, int use) +{ + int change = use ? 1 : -1; + int ret; + + mutex_lock(&entity->parent->graph_mutex); + + /* Apply use count to node. */ + entity->use_count += change; + WARN_ON(entity->use_count < 0); + + /* Apply power change to connected non-nodes. */ + ret = iss_pipeline_pm_power(entity, change); + if (ret < 0) + entity->use_count -= change; + + mutex_unlock(&entity->parent->graph_mutex); + + return ret; +} + +/* + * iss_pipeline_link_notify - Link management notification callback + * @link: The link + * @flags: New link flags that will be applied + * + * React to link management on powered pipelines by updating the use count of + * all entities in the source and sink sides of the link. Entities are powered + * on or off accordingly. + * + * Return 0 on success or a negative error code on failure. Powering entities + * off is assumed to never fail. This function will not fail for disconnection + * events. + */ +static int iss_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification) +{ + struct media_entity *source = link->source->entity; + struct media_entity *sink = link->sink->entity; + int source_use = iss_pipeline_pm_use_count(source); + int sink_use = iss_pipeline_pm_use_count(sink); + int ret; + + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + !(link->flags & MEDIA_LNK_FL_ENABLED)) { + /* Powering off entities is assumed to never fail. */ + iss_pipeline_pm_power(source, -sink_use); + iss_pipeline_pm_power(sink, -source_use); + return 0; + } + + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + (flags & MEDIA_LNK_FL_ENABLED)) { + ret = iss_pipeline_pm_power(source, sink_use); + if (ret < 0) + return ret; + + ret = iss_pipeline_pm_power(sink, source_use); + if (ret < 0) + iss_pipeline_pm_power(source, -sink_use); + + return ret; + } + + return 0; +} + +/* ----------------------------------------------------------------------------- + * Pipeline stream management + */ + +/* + * iss_pipeline_enable - Enable streaming on a pipeline + * @pipe: ISS pipeline + * @mode: Stream mode (single shot or continuous) + * + * Walk the entities chain starting at the pipeline output video node and start + * all modules in the chain in the given mode. + * + * Return 0 if successful, or the return value of the failed video::s_stream + * operation otherwise. + */ +static int iss_pipeline_enable(struct iss_pipeline *pipe, + enum iss_pipeline_stream_state mode) +{ + struct media_entity *entity; + struct media_pad *pad; + struct v4l2_subdev *subdev; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pipe->lock, flags); + pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT); + spin_unlock_irqrestore(&pipe->lock, flags); + + pipe->do_propagation = false; + + entity = &pipe->output->video.entity; + while (1) { + pad = &entity->pads[0]; + if (!(pad->flags & MEDIA_PAD_FL_SINK)) + break; + + pad = media_entity_remote_pad(pad); + if (pad == NULL || + media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + break; + + entity = pad->entity; + subdev = media_entity_to_v4l2_subdev(entity); + + ret = v4l2_subdev_call(subdev, video, s_stream, mode); + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + } + iss_print_status(pipe->output->iss); + return 0; +} + +/* + * iss_pipeline_disable - Disable streaming on a pipeline + * @pipe: ISS pipeline + * + * Walk the entities chain starting at the pipeline output video node and stop + * all modules in the chain. Wait synchronously for the modules to be stopped if + * necessary. + */ +static int iss_pipeline_disable(struct iss_pipeline *pipe) +{ + struct media_entity *entity; + struct media_pad *pad; + struct v4l2_subdev *subdev; + int failure = 0; + + entity = &pipe->output->video.entity; + while (1) { + pad = &entity->pads[0]; + if (!(pad->flags & MEDIA_PAD_FL_SINK)) + break; + + pad = media_entity_remote_pad(pad); + if (pad == NULL || + media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + break; + + entity = pad->entity; + subdev = media_entity_to_v4l2_subdev(entity); + + v4l2_subdev_call(subdev, video, s_stream, 0); + } + + return failure; +} + +/* + * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline + * @pipe: ISS pipeline + * @state: Stream state (stopped, single shot or continuous) + * + * Set the pipeline to the given stream state. Pipelines can be started in + * single-shot or continuous mode. + * + * Return 0 if successful, or the return value of the failed video::s_stream + * operation otherwise. The pipeline state is not updated when the operation + * fails, except when stopping the pipeline. + */ +int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, + enum iss_pipeline_stream_state state) +{ + int ret; + + if (state == ISS_PIPELINE_STREAM_STOPPED) + ret = iss_pipeline_disable(pipe); + else + ret = iss_pipeline_enable(pipe, state); + + if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED) + pipe->stream_state = state; + + return ret; +} + +/* + * iss_pipeline_is_last - Verify if entity has an enabled link to the output + * video node + * @me: ISS module's media entity + * + * Returns 1 if the entity has an enabled link to the output video node or 0 + * otherwise. It's true only while pipeline can have no more than one output + * node. + */ +static int iss_pipeline_is_last(struct media_entity *me) +{ + struct iss_pipeline *pipe; + struct media_pad *pad; + + if (!me->pipe) + return 0; + pipe = to_iss_pipeline(me); + if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED) + return 0; + pad = media_entity_remote_pad(&pipe->output->pad); + return pad->entity == me; +} + +static int iss_reset(struct iss_device *iss) +{ + unsigned long timeout = 0; + + writel(readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) | + ISS_HL_SYSCONFIG_SOFTRESET, + iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG); + + while (readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) & + ISS_HL_SYSCONFIG_SOFTRESET) { + if (timeout++ > 10000) { + dev_alert(iss->dev, "cannot reset ISS\n"); + return -ETIMEDOUT; + } + udelay(1); + } + + return 0; +} + +static int iss_isp_reset(struct iss_device *iss) +{ + unsigned long timeout = 0; + + /* Fist, ensure that the ISP is IDLE (no transactions happening) */ + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) & + ~ISP5_SYSCONFIG_STANDBYMODE_MASK) | + ISP5_SYSCONFIG_STANDBYMODE_SMART, + iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG); + + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) | + ISP5_CTRL_MSTANDBY, + iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + + for (;;) { + if (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & + ISP5_CTRL_MSTANDBY_WAIT) + break; + if (timeout++ > 1000) { + dev_alert(iss->dev, "cannot set ISP5 to standby\n"); + return -ETIMEDOUT; + } + msleep(1); + } + + /* Now finally, do the reset */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) | + ISP5_SYSCONFIG_SOFTRESET, + iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG); + + timeout = 0; + while (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) & + ISP5_SYSCONFIG_SOFTRESET) { + if (timeout++ > 1000) { + dev_alert(iss->dev, "cannot reset ISP5\n"); + return -ETIMEDOUT; + } + msleep(1); + } + + return 0; +} + +/* + * iss_module_sync_idle - Helper to sync module with its idle state + * @me: ISS submodule's media entity + * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization + * @stopping: flag which tells module wants to stop + * + * This function checks if ISS submodule needs to wait for next interrupt. If + * yes, makes the caller to sleep while waiting for such event. + */ +int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, + atomic_t *stopping) +{ + struct iss_pipeline *pipe = to_iss_pipeline(me); + struct iss_video *video = pipe->output; + unsigned long flags; + + if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED || + (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT && + !iss_pipeline_ready(pipe))) + return 0; + + /* + * atomic_set() doesn't include memory barrier on ARM platform for SMP + * scenario. We'll call it here to avoid race conditions. + */ + atomic_set(stopping, 1); + smp_wmb(); + + /* + * If module is the last one, it's writing to memory. In this case, + * it's necessary to check if the module is already paused due to + * DMA queue underrun or if it has to wait for next interrupt to be + * idle. + * If it isn't the last one, the function won't sleep but *stopping + * will still be set to warn next submodule caller's interrupt the + * module wants to be idle. + */ + if (!iss_pipeline_is_last(me)) + return 0; + + spin_lock_irqsave(&video->qlock, flags); + if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { + spin_unlock_irqrestore(&video->qlock, flags); + atomic_set(stopping, 0); + smp_wmb(); + return 0; + } + spin_unlock_irqrestore(&video->qlock, flags); + if (!wait_event_timeout(*wait, !atomic_read(stopping), + msecs_to_jiffies(1000))) { + atomic_set(stopping, 0); + smp_wmb(); + return -ETIMEDOUT; + } + + return 0; +} + +/* + * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping + * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization + * @stopping: flag which tells module wants to stop + * + * This function checks if ISS submodule was stopping. In case of yes, it + * notices the caller by setting stopping to 0 and waking up the wait queue. + * Returns 1 if it was stopping or 0 otherwise. + */ +int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, + atomic_t *stopping) +{ + if (atomic_cmpxchg(stopping, 1, 0)) { + wake_up(wait); + return 1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- + * Clock management + */ + +#define ISS_CLKCTRL_MASK (ISS_CLKCTRL_CSI2_A |\ + ISS_CLKCTRL_CSI2_B |\ + ISS_CLKCTRL_ISP) + +static int __iss_subclk_update(struct iss_device *iss) +{ + u32 clk = 0; + int ret = 0, timeout = 1000; + + if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A) + clk |= ISS_CLKCTRL_CSI2_A; + + if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B) + clk |= ISS_CLKCTRL_CSI2_B; + + if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP) + clk |= ISS_CLKCTRL_ISP; + + writel((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL) & + ~ISS_CLKCTRL_MASK) | clk, + iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL); + + /* Wait for HW assertion */ + while (--timeout > 0) { + udelay(1); + if ((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKSTAT) & + ISS_CLKCTRL_MASK) == clk) + break; + } + + if (!timeout) + ret = -EBUSY; + + return ret; +} + +int omap4iss_subclk_enable(struct iss_device *iss, + enum iss_subclk_resource res) +{ + iss->subclk_resources |= res; + + return __iss_subclk_update(iss); +} + +int omap4iss_subclk_disable(struct iss_device *iss, + enum iss_subclk_resource res) +{ + iss->subclk_resources &= ~res; + + return __iss_subclk_update(iss); +} + +#define ISS_ISP5_CLKCTRL_MASK (ISP5_CTRL_BL_CLK_ENABLE |\ + ISP5_CTRL_ISIF_CLK_ENABLE |\ + ISP5_CTRL_H3A_CLK_ENABLE |\ + ISP5_CTRL_RSZ_CLK_ENABLE |\ + ISP5_CTRL_IPIPE_CLK_ENABLE |\ + ISP5_CTRL_IPIPEIF_CLK_ENABLE) + +static int __iss_isp_subclk_update(struct iss_device *iss) +{ + u32 clk = 0; + + if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF) + clk |= ISP5_CTRL_ISIF_CLK_ENABLE; + + if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A) + clk |= ISP5_CTRL_H3A_CLK_ENABLE; + + if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ) + clk |= ISP5_CTRL_RSZ_CLK_ENABLE; + + if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE) + clk |= ISP5_CTRL_IPIPE_CLK_ENABLE; + + if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF) + clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE; + + if (clk) + clk |= ISP5_CTRL_BL_CLK_ENABLE; + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & + ~ISS_ISP5_CLKCTRL_MASK) | clk, + iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + + return 0; +} + +int omap4iss_isp_subclk_enable(struct iss_device *iss, + enum iss_isp_subclk_resource res) +{ + iss->isp_subclk_resources |= res; + + return __iss_isp_subclk_update(iss); +} + +int omap4iss_isp_subclk_disable(struct iss_device *iss, + enum iss_isp_subclk_resource res) +{ + iss->isp_subclk_resources &= ~res; + + return __iss_isp_subclk_update(iss); +} + +/* + * iss_enable_clocks - Enable ISS clocks + * @iss: OMAP4 ISS device + * + * Return 0 if successful, or clk_enable return value if any of tthem fails. + */ +static int iss_enable_clocks(struct iss_device *iss) +{ + int r; + + r = clk_enable(iss->iss_fck); + if (r) { + dev_err(iss->dev, "clk_enable iss_fck failed\n"); + return r; + } + + r = clk_enable(iss->iss_ctrlclk); + if (r) { + dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n"); + goto out_clk_enable_ctrlclk; + } + return 0; + +out_clk_enable_ctrlclk: + clk_disable(iss->iss_fck); + return r; +} + +/* + * iss_disable_clocks - Disable ISS clocks + * @iss: OMAP4 ISS device + */ +static void iss_disable_clocks(struct iss_device *iss) +{ + clk_disable(iss->iss_ctrlclk); + clk_disable(iss->iss_fck); +} + +static void iss_put_clocks(struct iss_device *iss) +{ + if (iss->iss_fck) { + clk_put(iss->iss_fck); + iss->iss_fck = NULL; + } + + if (iss->iss_ctrlclk) { + clk_put(iss->iss_ctrlclk); + iss->iss_ctrlclk = NULL; + } +} + +static int iss_get_clocks(struct iss_device *iss) +{ + iss->iss_fck = clk_get(iss->dev, "iss_fck"); + if (IS_ERR(iss->iss_fck)) { + dev_err(iss->dev, "Unable to get iss_fck clock info\n"); + iss_put_clocks(iss); + return PTR_ERR(iss->iss_fck); + } + + iss->iss_ctrlclk = clk_get(iss->dev, "iss_ctrlclk"); + if (IS_ERR(iss->iss_ctrlclk)) { + dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n"); + iss_put_clocks(iss); + return PTR_ERR(iss->iss_fck); + } + + return 0; +} + +/* + * omap4iss_get - Acquire the ISS resource. + * + * Initializes the clocks for the first acquire. + * + * Increment the reference count on the ISS. If the first reference is taken, + * enable clocks and power-up all submodules. + * + * Return a pointer to the ISS device structure, or NULL if an error occurred. + */ +struct iss_device *omap4iss_get(struct iss_device *iss) +{ + struct iss_device *__iss = iss; + + if (iss == NULL) + return NULL; + + mutex_lock(&iss->iss_mutex); + if (iss->ref_count > 0) + goto out; + + if (iss_enable_clocks(iss) < 0) { + __iss = NULL; + goto out; + } + + iss_enable_interrupts(iss); + +out: + if (__iss != NULL) + iss->ref_count++; + mutex_unlock(&iss->iss_mutex); + + return __iss; +} + +/* + * omap4iss_put - Release the ISS + * + * Decrement the reference count on the ISS. If the last reference is released, + * power-down all submodules, disable clocks and free temporary buffers. + */ +void omap4iss_put(struct iss_device *iss) +{ + if (iss == NULL) + return; + + mutex_lock(&iss->iss_mutex); + BUG_ON(iss->ref_count == 0); + if (--iss->ref_count == 0) { + iss_disable_interrupts(iss); + iss_disable_clocks(iss); + } + mutex_unlock(&iss->iss_mutex); +} + +static int iss_map_mem_resource(struct platform_device *pdev, + struct iss_device *iss, + enum iss_mem_resources res) +{ + struct resource *mem; + + /* request the mem region for the camera registers */ + + mem = platform_get_resource(pdev, IORESOURCE_MEM, res); + if (!mem) { + dev_err(iss->dev, "no mem resource?\n"); + return -ENODEV; + } + + if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) { + dev_err(iss->dev, + "cannot reserve camera register I/O region\n"); + return -ENODEV; + } + iss->res[res] = mem; + + /* map the region */ + iss->regs[res] = ioremap_nocache(mem->start, resource_size(mem)); + if (!iss->regs[res]) { + dev_err(iss->dev, "cannot map camera register I/O region\n"); + return -ENODEV; + } + + return 0; +} + +static void iss_unregister_entities(struct iss_device *iss) +{ + omap4iss_resizer_unregister_entities(&iss->resizer); + omap4iss_ipipe_unregister_entities(&iss->ipipe); + omap4iss_ipipeif_unregister_entities(&iss->ipipeif); + omap4iss_csi2_unregister_entities(&iss->csi2a); + omap4iss_csi2_unregister_entities(&iss->csi2b); + + v4l2_device_unregister(&iss->v4l2_dev); + media_device_unregister(&iss->media_dev); +} + +/* + * iss_register_subdev_group - Register a group of subdevices + * @iss: OMAP4 ISS device + * @board_info: I2C subdevs board information array + * + * Register all I2C subdevices in the board_info array. The array must be + * terminated by a NULL entry, and the first entry must be the sensor. + * + * Return a pointer to the sensor media entity if it has been successfully + * registered, or NULL otherwise. + */ +static struct v4l2_subdev * +iss_register_subdev_group(struct iss_device *iss, + struct iss_subdev_i2c_board_info *board_info) +{ + struct v4l2_subdev *sensor = NULL; + unsigned int first; + + if (board_info->board_info == NULL) + return NULL; + + for (first = 1; board_info->board_info; ++board_info, first = 0) { + struct v4l2_subdev *subdev; + struct i2c_adapter *adapter; + + adapter = i2c_get_adapter(board_info->i2c_adapter_id); + if (adapter == NULL) { + dev_err(iss->dev, "%s: Unable to get I2C adapter %d for " + "device %s\n", __func__, + board_info->i2c_adapter_id, + board_info->board_info->type); + continue; + } + + subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter, + board_info->board_info, NULL); + if (subdev == NULL) { + dev_err(iss->dev, "%s: Unable to register subdev %s\n", + __func__, board_info->board_info->type); + continue; + } + + if (first) + sensor = subdev; + } + + return sensor; +} + +static int iss_register_entities(struct iss_device *iss) +{ + struct iss_platform_data *pdata = iss->pdata; + struct iss_v4l2_subdevs_group *subdevs; + int ret; + + iss->media_dev.dev = iss->dev; + strlcpy(iss->media_dev.model, "TI OMAP4 ISS", + sizeof(iss->media_dev.model)); + iss->media_dev.hw_revision = iss->revision; + iss->media_dev.link_notify = iss_pipeline_link_notify; + ret = media_device_register(&iss->media_dev); + if (ret < 0) { + printk(KERN_ERR "%s: Media device registration failed (%d)\n", + __func__, ret); + return ret; + } + + iss->v4l2_dev.mdev = &iss->media_dev; + ret = v4l2_device_register(iss->dev, &iss->v4l2_dev); + if (ret < 0) { + printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n", + __func__, ret); + goto done; + } + + /* Register internal entities */ + ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev); + if (ret < 0) + goto done; + + ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev); + if (ret < 0) + goto done; + + ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev); + if (ret < 0) + goto done; + + ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev); + if (ret < 0) + goto done; + + ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev); + if (ret < 0) + goto done; + + /* Register external entities */ + for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { + struct v4l2_subdev *sensor; + struct media_entity *input; + unsigned int flags; + unsigned int pad; + + sensor = iss_register_subdev_group(iss, subdevs->subdevs); + if (sensor == NULL) + continue; + + sensor->host_priv = subdevs; + + /* Connect the sensor to the correct interface module. + * CSI2a receiver through CSIPHY1, or + * CSI2b receiver through CSIPHY2 + */ + switch (subdevs->interface) { + case ISS_INTERFACE_CSI2A_PHY1: + input = &iss->csi2a.subdev.entity; + pad = CSI2_PAD_SINK; + flags = MEDIA_LNK_FL_IMMUTABLE + | MEDIA_LNK_FL_ENABLED; + break; + + case ISS_INTERFACE_CSI2B_PHY2: + input = &iss->csi2b.subdev.entity; + pad = CSI2_PAD_SINK; + flags = MEDIA_LNK_FL_IMMUTABLE + | MEDIA_LNK_FL_ENABLED; + break; + + default: + printk(KERN_ERR "%s: invalid interface type %u\n", + __func__, subdevs->interface); + ret = -EINVAL; + goto done; + } + + ret = media_entity_create_link(&sensor->entity, 0, input, pad, + flags); + if (ret < 0) + goto done; + } + + ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev); + +done: + if (ret < 0) + iss_unregister_entities(iss); + + return ret; +} + +static void iss_cleanup_modules(struct iss_device *iss) +{ + omap4iss_csi2_cleanup(iss); + omap4iss_ipipeif_cleanup(iss); + omap4iss_ipipe_cleanup(iss); + omap4iss_resizer_cleanup(iss); +} + +static int iss_initialize_modules(struct iss_device *iss) +{ + int ret; + + ret = omap4iss_csiphy_init(iss); + if (ret < 0) { + dev_err(iss->dev, "CSI PHY initialization failed\n"); + goto error_csiphy; + } + + ret = omap4iss_csi2_init(iss); + if (ret < 0) { + dev_err(iss->dev, "CSI2 initialization failed\n"); + goto error_csi2; + } + + ret = omap4iss_ipipeif_init(iss); + if (ret < 0) { + dev_err(iss->dev, "ISP IPIPEIF initialization failed\n"); + goto error_ipipeif; + } + + ret = omap4iss_ipipe_init(iss); + if (ret < 0) { + dev_err(iss->dev, "ISP IPIPE initialization failed\n"); + goto error_ipipe; + } + + ret = omap4iss_resizer_init(iss); + if (ret < 0) { + dev_err(iss->dev, "ISP RESIZER initialization failed\n"); + goto error_resizer; + } + + /* Connect the submodules. */ + ret = media_entity_create_link( + &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, + &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); + if (ret < 0) + goto error_link; + + ret = media_entity_create_link( + &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, + &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); + if (ret < 0) + goto error_link; + + ret = media_entity_create_link( + &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, + &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); + if (ret < 0) + goto error_link; + + ret = media_entity_create_link( + &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, + &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); + if (ret < 0) + goto error_link; + + ret = media_entity_create_link( + &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, + &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); + if (ret < 0) + goto error_link; + + return 0; + +error_link: + omap4iss_resizer_cleanup(iss); +error_resizer: + omap4iss_ipipe_cleanup(iss); +error_ipipe: + omap4iss_ipipeif_cleanup(iss); +error_ipipeif: + omap4iss_csi2_cleanup(iss); +error_csi2: +error_csiphy: + return ret; +} + +static int iss_probe(struct platform_device *pdev) +{ + struct iss_platform_data *pdata = pdev->dev.platform_data; + struct iss_device *iss; + int i, ret; + + if (pdata == NULL) + return -EINVAL; + + iss = kzalloc(sizeof(*iss), GFP_KERNEL); + if (!iss) { + dev_err(&pdev->dev, "Could not allocate memory\n"); + return -ENOMEM; + } + + mutex_init(&iss->iss_mutex); + + iss->dev = &pdev->dev; + iss->pdata = pdata; + iss->ref_count = 0; + + iss->raw_dmamask = DMA_BIT_MASK(32); + iss->dev->dma_mask = &iss->raw_dmamask; + iss->dev->coherent_dma_mask = DMA_BIT_MASK(32); + + platform_set_drvdata(pdev, iss); + + /* Clocks */ + ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP); + if (ret < 0) + goto error; + + ret = iss_get_clocks(iss); + if (ret < 0) + goto error; + + if (omap4iss_get(iss) == NULL) + goto error; + + ret = iss_reset(iss); + if (ret < 0) + goto error_iss; + + iss->revision = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); + dev_info(iss->dev, "Revision %08x found\n", iss->revision); + + for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) { + ret = iss_map_mem_resource(pdev, iss, i); + if (ret) + goto error_iss; + } + + /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */ + writel((readl(iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL) & ~BTE_CTRL_BW_LIMITER_MASK) | + (18 << BTE_CTRL_BW_LIMITER_SHIFT), + iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL); + + /* Perform ISP reset */ + ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP); + if (ret < 0) + goto error_iss; + + ret = iss_isp_reset(iss); + if (ret < 0) + goto error_iss; + + dev_info(iss->dev, "ISP Revision %08x found\n", + readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_REVISION)); + + /* Interrupt */ + iss->irq_num = platform_get_irq(pdev, 0); + if (iss->irq_num <= 0) { + dev_err(iss->dev, "No IRQ resource\n"); + ret = -ENODEV; + goto error_iss; + } + + if (request_irq(iss->irq_num, iss_isr, IRQF_SHARED, "OMAP4 ISS", iss)) { + dev_err(iss->dev, "Unable to request IRQ\n"); + ret = -EINVAL; + goto error_iss; + } + + /* Entities */ + ret = iss_initialize_modules(iss); + if (ret < 0) + goto error_irq; + + ret = iss_register_entities(iss); + if (ret < 0) + goto error_modules; + + omap4iss_put(iss); + + return 0; + +error_modules: + iss_cleanup_modules(iss); +error_irq: + free_irq(iss->irq_num, iss); +error_iss: + omap4iss_put(iss); +error: + iss_put_clocks(iss); + + for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) { + if (iss->regs[i]) { + iounmap(iss->regs[i]); + iss->regs[i] = NULL; + } + + if (iss->res[i]) { + release_mem_region(iss->res[i]->start, + resource_size(iss->res[i])); + iss->res[i] = NULL; + } + } + platform_set_drvdata(pdev, NULL); + + mutex_destroy(&iss->iss_mutex); + kfree(iss); + + return ret; +} + +static int iss_remove(struct platform_device *pdev) +{ + struct iss_device *iss = platform_get_drvdata(pdev); + int i; + + iss_unregister_entities(iss); + iss_cleanup_modules(iss); + + free_irq(iss->irq_num, iss); + iss_put_clocks(iss); + + for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) { + if (iss->regs[i]) { + iounmap(iss->regs[i]); + iss->regs[i] = NULL; + } + + if (iss->res[i]) { + release_mem_region(iss->res[i]->start, + resource_size(iss->res[i])); + iss->res[i] = NULL; + } + } + + kfree(iss); + + return 0; +} + +static struct platform_device_id omap4iss_id_table[] = { + { "omap4iss", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(platform, omap4iss_id_table); + +static struct platform_driver iss_driver = { + .probe = iss_probe, + .remove = iss_remove, + .id_table = omap4iss_id_table, + .driver = { + .owner = THIS_MODULE, + .name = "omap4iss", + }, +}; + +module_platform_driver(iss_driver); + +MODULE_DESCRIPTION("TI OMAP4 ISS driver"); +MODULE_AUTHOR("Sergio Aguirre "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(ISS_VIDEO_DRIVER_VERSION); diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h new file mode 100644 index 000000000000..cc24f1ae17c6 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss.h @@ -0,0 +1,153 @@ +/* + * TI OMAP4 ISS V4L2 Driver + * + * Copyright (C) 2012 Texas Instruments. + * + * Author: Sergio Aguirre + * + * 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 _OMAP4_ISS_H_ +#define _OMAP4_ISS_H_ + +#include +#include +#include +#include +#include + +#include + +#include "iss_regs.h" +#include "iss_csiphy.h" +#include "iss_csi2.h" +#include "iss_ipipeif.h" +#include "iss_ipipe.h" +#include "iss_resizer.h" + +#define to_iss_device(ptr_module) \ + container_of(ptr_module, struct iss_device, ptr_module) +#define to_device(ptr_module) \ + (to_iss_device(ptr_module)->dev) + +enum iss_mem_resources { + OMAP4_ISS_MEM_TOP, + OMAP4_ISS_MEM_CSI2_A_REGS1, + OMAP4_ISS_MEM_CAMERARX_CORE1, + OMAP4_ISS_MEM_CSI2_B_REGS1, + OMAP4_ISS_MEM_CAMERARX_CORE2, + OMAP4_ISS_MEM_BTE, + OMAP4_ISS_MEM_ISP_SYS1, + OMAP4_ISS_MEM_ISP_RESIZER, + OMAP4_ISS_MEM_ISP_IPIPE, + OMAP4_ISS_MEM_ISP_ISIF, + OMAP4_ISS_MEM_ISP_IPIPEIF, + OMAP4_ISS_MEM_LAST, +}; + +enum iss_subclk_resource { + OMAP4_ISS_SUBCLK_SIMCOP = (1 << 0), + OMAP4_ISS_SUBCLK_ISP = (1 << 1), + OMAP4_ISS_SUBCLK_CSI2_A = (1 << 2), + OMAP4_ISS_SUBCLK_CSI2_B = (1 << 3), + OMAP4_ISS_SUBCLK_CCP2 = (1 << 4), +}; + +enum iss_isp_subclk_resource { + OMAP4_ISS_ISP_SUBCLK_BL = (1 << 0), + OMAP4_ISS_ISP_SUBCLK_ISIF = (1 << 1), + OMAP4_ISS_ISP_SUBCLK_H3A = (1 << 2), + OMAP4_ISS_ISP_SUBCLK_RSZ = (1 << 3), + OMAP4_ISS_ISP_SUBCLK_IPIPE = (1 << 4), + OMAP4_ISS_ISP_SUBCLK_IPIPEIF = (1 << 5), +}; + +/* + * struct iss_reg - Structure for ISS register values. + * @reg: 32-bit Register address. + * @val: 32-bit Register value. + */ +struct iss_reg { + enum iss_mem_resources mmio_range; + u32 reg; + u32 val; +}; + +struct iss_device { + struct v4l2_device v4l2_dev; + struct media_device media_dev; + struct device *dev; + u32 revision; + + /* platform HW resources */ + struct iss_platform_data *pdata; + unsigned int irq_num; + + struct resource *res[OMAP4_ISS_MEM_LAST]; + void __iomem *regs[OMAP4_ISS_MEM_LAST]; + + u64 raw_dmamask; + + struct mutex iss_mutex; /* For handling ref_count field */ + int has_context; + int ref_count; + + struct clk *iss_fck; + struct clk *iss_ctrlclk; + + /* ISS modules */ + struct iss_csi2_device csi2a; + struct iss_csi2_device csi2b; + struct iss_csiphy csiphy1; + struct iss_csiphy csiphy2; + struct iss_ipipeif_device ipipeif; + struct iss_ipipe_device ipipe; + struct iss_resizer_device resizer; + + unsigned int subclk_resources; + unsigned int isp_subclk_resources; +}; + +#define v4l2_dev_to_iss_device(dev) \ + container_of(dev, struct iss_device, v4l2_dev) + +int omap4iss_get_external_info(struct iss_pipeline *pipe, + struct media_link *link); + +int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, + atomic_t *stopping); + +int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, + atomic_t *stopping); + +int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, + enum iss_pipeline_stream_state state); + +void omap4iss_configure_bridge(struct iss_device *iss, + enum ipipeif_input_entity input); + +struct iss_device *omap4iss_get(struct iss_device *iss); +void omap4iss_put(struct iss_device *iss); +int omap4iss_subclk_enable(struct iss_device *iss, + enum iss_subclk_resource res); +int omap4iss_subclk_disable(struct iss_device *iss, + enum iss_subclk_resource res); +int omap4iss_isp_subclk_enable(struct iss_device *iss, + enum iss_isp_subclk_resource res); +int omap4iss_isp_subclk_disable(struct iss_device *iss, + enum iss_isp_subclk_resource res); + +void omap4iss_isp_enable_interrupts(struct iss_device *iss); +void omap4iss_isp_disable_interrupts(struct iss_device *iss); + +int omap4iss_pipeline_pm_use(struct media_entity *entity, int use); + +int omap4iss_register_entities(struct platform_device *pdev, + struct v4l2_device *v4l2_dev); +void omap4iss_unregister_entities(struct platform_device *pdev); + +#endif /* _OMAP4_ISS_H_ */ diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h new file mode 100644 index 000000000000..7327d0c1ae37 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -0,0 +1,883 @@ +/* + * TI OMAP4 ISS V4L2 Driver - Register defines + * + * Copyright (C) 2012 Texas Instruments. + * + * Author: Sergio Aguirre + * + * 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 _OMAP4_ISS_REGS_H_ +#define _OMAP4_ISS_REGS_H_ + +/* ISS */ +#define ISS_HL_REVISION 0x0 + +#define ISS_HL_SYSCONFIG 0x10 +#define ISS_HL_SYSCONFIG_IDLEMODE_SHIFT 2 +#define ISS_HL_SYSCONFIG_IDLEMODE_FORCEIDLE 0x0 +#define ISS_HL_SYSCONFIG_IDLEMODE_NOIDLE 0x1 +#define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE 0x2 +#define ISS_HL_SYSCONFIG_SOFTRESET (1 << 0) + +#define ISS_HL_IRQSTATUS_5 (0x24 + (0x10 * 5)) +#define ISS_HL_IRQENABLE_5_SET (0x28 + (0x10 * 5)) +#define ISS_HL_IRQENABLE_5_CLR (0x2C + (0x10 * 5)) + +#define ISS_HL_IRQ_BTE (1 << 11) +#define ISS_HL_IRQ_CBUFF (1 << 10) +#define ISS_HL_IRQ_CSIB (1 << 5) +#define ISS_HL_IRQ_CSIA (1 << 4) +#define ISS_HL_IRQ_ISP(i) (1 << (i)) + +#define ISS_CTRL 0x80 +#define ISS_CTRL_CLK_DIV_MASK (3 << 4) +#define ISS_CTRL_INPUT_SEL_MASK (3 << 2) +#define ISS_CTRL_INPUT_SEL_CSI2A (0 << 2) +#define ISS_CTRL_INPUT_SEL_CSI2B (1 << 2) +#define ISS_CTRL_SYNC_DETECT_VS_RAISING (3 << 0) + +#define ISS_CLKCTRL 0x84 +#define ISS_CLKCTRL_VPORT2_CLK (1 << 30) +#define ISS_CLKCTRL_VPORT1_CLK (1 << 29) +#define ISS_CLKCTRL_VPORT0_CLK (1 << 28) +#define ISS_CLKCTRL_CCP2 (1 << 4) +#define ISS_CLKCTRL_CSI2_B (1 << 3) +#define ISS_CLKCTRL_CSI2_A (1 << 2) +#define ISS_CLKCTRL_ISP (1 << 1) +#define ISS_CLKCTRL_SIMCOP (1 << 0) + +#define ISS_CLKSTAT 0x88 +#define ISS_CLKSTAT_VPORT2_CLK (1 << 30) +#define ISS_CLKSTAT_VPORT1_CLK (1 << 29) +#define ISS_CLKSTAT_VPORT0_CLK (1 << 28) +#define ISS_CLKSTAT_CCP2 (1 << 4) +#define ISS_CLKSTAT_CSI2_B (1 << 3) +#define ISS_CLKSTAT_CSI2_A (1 << 2) +#define ISS_CLKSTAT_ISP (1 << 1) +#define ISS_CLKSTAT_SIMCOP (1 << 0) + +#define ISS_PM_STATUS 0x8C +#define ISS_PM_STATUS_CBUFF_PM_MASK (3 << 12) +#define ISS_PM_STATUS_BTE_PM_MASK (3 << 10) +#define ISS_PM_STATUS_SIMCOP_PM_MASK (3 << 8) +#define ISS_PM_STATUS_ISP_PM_MASK (3 << 6) +#define ISS_PM_STATUS_CCP2_PM_MASK (3 << 4) +#define ISS_PM_STATUS_CSI2_B_PM_MASK (3 << 2) +#define ISS_PM_STATUS_CSI2_A_PM_MASK (3 << 0) + +#define REGISTER0 0x0 +#define REGISTER0_HSCLOCKCONFIG (1 << 24) +#define REGISTER0_THS_TERM_MASK (0xFF << 8) +#define REGISTER0_THS_TERM_SHIFT 8 +#define REGISTER0_THS_SETTLE_MASK (0xFF << 0) +#define REGISTER0_THS_SETTLE_SHIFT 0 + +#define REGISTER1 0x4 +#define REGISTER1_RESET_DONE_CTRLCLK (1 << 29) +#define REGISTER1_CLOCK_MISS_DETECTOR_STATUS (1 << 25) +#define REGISTER1_TCLK_TERM_MASK (0x3F << 18) +#define REGISTER1_TCLK_TERM_SHIFT 18 +#define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT 10 +#define REGISTER1_CTRLCLK_DIV_FACTOR_MASK (0x3 << 8) +#define REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT 8 +#define REGISTER1_TCLK_SETTLE_MASK (0xFF << 0) +#define REGISTER1_TCLK_SETTLE_SHIFT 0 + +#define REGISTER2 0x8 + +#define CSI2_SYSCONFIG 0x10 +#define CSI2_SYSCONFIG_MSTANDBY_MODE_MASK (3 << 12) +#define CSI2_SYSCONFIG_MSTANDBY_MODE_FORCE (0 << 12) +#define CSI2_SYSCONFIG_MSTANDBY_MODE_NO (1 << 12) +#define CSI2_SYSCONFIG_MSTANDBY_MODE_SMART (2 << 12) +#define CSI2_SYSCONFIG_SOFT_RESET (1 << 1) +#define CSI2_SYSCONFIG_AUTO_IDLE (1 << 0) + +#define CSI2_SYSSTATUS 0x14 +#define CSI2_SYSSTATUS_RESET_DONE (1 << 0) + +#define CSI2_IRQSTATUS 0x18 +#define CSI2_IRQENABLE 0x1C + +/* Shared bits across CSI2_IRQENABLE and IRQSTATUS */ + +#define CSI2_IRQ_OCP_ERR (1 << 14) +#define CSI2_IRQ_SHORT_PACKET (1 << 13) +#define CSI2_IRQ_ECC_CORRECTION (1 << 12) +#define CSI2_IRQ_ECC_NO_CORRECTION (1 << 11) +#define CSI2_IRQ_COMPLEXIO_ERR (1 << 9) +#define CSI2_IRQ_FIFO_OVF (1 << 8) +#define CSI2_IRQ_CONTEXT0 (1 << 0) + +#define CSI2_CTRL 0x40 +#define CSI2_CTRL_MFLAG_LEVH_MASK (7 << 20) +#define CSI2_CTRL_MFLAG_LEVH_SHIFT 20 +#define CSI2_CTRL_MFLAG_LEVL_MASK (7 << 17) +#define CSI2_CTRL_MFLAG_LEVL_SHIFT 17 +#define CSI2_CTRL_BURST_SIZE_EXPAND (1 << 16) +#define CSI2_CTRL_VP_CLK_EN (1 << 15) +#define CSI2_CTRL_NON_POSTED_WRITE (1 << 13) +#define CSI2_CTRL_VP_ONLY_EN (1 << 11) +#define CSI2_CTRL_VP_OUT_CTRL_MASK (3 << 8) +#define CSI2_CTRL_VP_OUT_CTRL_SHIFT 8 +#define CSI2_CTRL_DBG_EN (1 << 7) +#define CSI2_CTRL_BURST_SIZE_MASK (3 << 5) +#define CSI2_CTRL_ENDIANNESS (1 << 4) +#define CSI2_CTRL_FRAME (1 << 3) +#define CSI2_CTRL_ECC_EN (1 << 2) +#define CSI2_CTRL_IF_EN (1 << 0) + +#define CSI2_DBG_H 0x44 + +#define CSI2_COMPLEXIO_CFG 0x50 +#define CSI2_COMPLEXIO_CFG_RESET_CTRL (1 << 30) +#define CSI2_COMPLEXIO_CFG_RESET_DONE (1 << 29) +#define CSI2_COMPLEXIO_CFG_PWD_CMD_MASK (3 << 27) +#define CSI2_COMPLEXIO_CFG_PWD_CMD_OFF (0 << 27) +#define CSI2_COMPLEXIO_CFG_PWD_CMD_ON (1 << 27) +#define CSI2_COMPLEXIO_CFG_PWD_CMD_ULP (2 << 27) +#define CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK (3 << 25) +#define CSI2_COMPLEXIO_CFG_PWD_STATUS_OFF (0 << 25) +#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ON (1 << 25) +#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ULP (2 << 25) +#define CSI2_COMPLEXIO_CFG_PWR_AUTO (1 << 24) +#define CSI2_COMPLEXIO_CFG_DATA_POL(i) (1 << (((i) * 4) + 3)) +#define CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i) (7 << ((i) * 4)) +#define CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i) ((i) * 4) +#define CSI2_COMPLEXIO_CFG_CLOCK_POL (1 << 3) +#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK (7 << 0) +#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT 0 + +#define CSI2_COMPLEXIO_IRQSTATUS 0x54 + +#define CSI2_SHORT_PACKET 0x5C + +#define CSI2_COMPLEXIO_IRQENABLE 0x60 + +/* Shared bits across CSI2_COMPLEXIO_IRQENABLE and IRQSTATUS */ +#define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT (1 << 26) +#define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER (1 << 25) +#define CSI2_COMPLEXIO_IRQ_STATEULPM5 (1 << 24) +#define CSI2_COMPLEXIO_IRQ_STATEULPM4 (1 << 23) +#define CSI2_COMPLEXIO_IRQ_STATEULPM3 (1 << 22) +#define CSI2_COMPLEXIO_IRQ_STATEULPM2 (1 << 21) +#define CSI2_COMPLEXIO_IRQ_STATEULPM1 (1 << 20) +#define CSI2_COMPLEXIO_IRQ_ERRCONTROL5 (1 << 19) +#define CSI2_COMPLEXIO_IRQ_ERRCONTROL4 (1 << 18) +#define CSI2_COMPLEXIO_IRQ_ERRCONTROL3 (1 << 17) +#define CSI2_COMPLEXIO_IRQ_ERRCONTROL2 (1 << 16) +#define CSI2_COMPLEXIO_IRQ_ERRCONTROL1 (1 << 15) +#define CSI2_COMPLEXIO_IRQ_ERRESC5 (1 << 14) +#define CSI2_COMPLEXIO_IRQ_ERRESC4 (1 << 13) +#define CSI2_COMPLEXIO_IRQ_ERRESC3 (1 << 12) +#define CSI2_COMPLEXIO_IRQ_ERRESC2 (1 << 11) +#define CSI2_COMPLEXIO_IRQ_ERRESC1 (1 << 10) +#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 (1 << 9) +#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 (1 << 8) +#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 (1 << 7) +#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 (1 << 6) +#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 (1 << 5) +#define CSI2_COMPLEXIO_IRQ_ERRSOTHS5 (1 << 4) +#define CSI2_COMPLEXIO_IRQ_ERRSOTHS4 (1 << 3) +#define CSI2_COMPLEXIO_IRQ_ERRSOTHS3 (1 << 2) +#define CSI2_COMPLEXIO_IRQ_ERRSOTHS2 (1 << 1) +#define CSI2_COMPLEXIO_IRQ_ERRSOTHS1 (1 << 0) + +#define CSI2_DBG_P 0x68 + +#define CSI2_TIMING 0x6C +#define CSI2_TIMING_FORCE_RX_MODE_IO1 (1 << 15) +#define CSI2_TIMING_STOP_STATE_X16_IO1 (1 << 14) +#define CSI2_TIMING_STOP_STATE_X4_IO1 (1 << 13) +#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1FFF << 0) +#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT 0 + +#define CSI2_CTX_CTRL1(i) (0x70 + (0x20 * i)) +#define CSI2_CTX_CTRL1_GENERIC (1 << 30) +#define CSI2_CTX_CTRL1_TRANSCODE (0xF << 24) +#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xFF << 16) +#define CSI2_CTX_CTRL1_COUNT_MASK (0xFF << 8) +#define CSI2_CTX_CTRL1_COUNT_SHIFT 8 +#define CSI2_CTX_CTRL1_EOF_EN (1 << 7) +#define CSI2_CTX_CTRL1_EOL_EN (1 << 6) +#define CSI2_CTX_CTRL1_CS_EN (1 << 5) +#define CSI2_CTX_CTRL1_COUNT_UNLOCK (1 << 4) +#define CSI2_CTX_CTRL1_PING_PONG (1 << 3) +#define CSI2_CTX_CTRL1_CTX_EN (1 << 0) + +#define CSI2_CTX_CTRL2(i) (0x74 + (0x20 * i)) +#define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT 13 +#define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK \ + (0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT) +#define CSI2_CTX_CTRL2_VIRTUAL_ID_MASK (3 << 11) +#define CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11 +#define CSI2_CTX_CTRL2_DPCM_PRED (1 << 10) +#define CSI2_CTX_CTRL2_FORMAT_MASK (0x3FF << 0) +#define CSI2_CTX_CTRL2_FORMAT_SHIFT 0 + +#define CSI2_CTX_DAT_OFST(i) (0x78 + (0x20 * i)) +#define CSI2_CTX_DAT_OFST_MASK (0xFFF << 5) + +#define CSI2_CTX_PING_ADDR(i) (0x7C + (0x20 * i)) +#define CSI2_CTX_PING_ADDR_MASK 0xFFFFFFE0 + +#define CSI2_CTX_PONG_ADDR(i) (0x80 + (0x20 * i)) +#define CSI2_CTX_PONG_ADDR_MASK CSI2_CTX_PING_ADDR_MASK + +#define CSI2_CTX_IRQENABLE(i) (0x84 + (0x20 * i)) +#define CSI2_CTX_IRQSTATUS(i) (0x88 + (0x20 * i)) + +#define CSI2_CTX_CTRL3(i) (0x8C + (0x20 * i)) +#define CSI2_CTX_CTRL3_ALPHA_SHIFT 5 +#define CSI2_CTX_CTRL3_ALPHA_MASK \ + (0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT) + +/* Shared bits across CSI2_CTX_IRQENABLE and IRQSTATUS */ +#define CSI2_CTX_IRQ_ECC_CORRECTION (1 << 8) +#define CSI2_CTX_IRQ_LINE_NUMBER (1 << 7) +#define CSI2_CTX_IRQ_FRAME_NUMBER (1 << 6) +#define CSI2_CTX_IRQ_CS (1 << 5) +#define CSI2_CTX_IRQ_LE (1 << 3) +#define CSI2_CTX_IRQ_LS (1 << 2) +#define CSI2_CTX_IRQ_FE (1 << 1) +#define CSI2_CTX_IRQ_FS (1 << 0) + +/* ISS BTE */ +#define BTE_CTRL (0x0030) +#define BTE_CTRL_BW_LIMITER_MASK (0x3FF << 22) +#define BTE_CTRL_BW_LIMITER_SHIFT 22 + +/* ISS ISP_SYS1 */ +#define ISP5_REVISION (0x0000) +#define ISP5_SYSCONFIG (0x0010) +#define ISP5_SYSCONFIG_STANDBYMODE_MASK (3 << 4) +#define ISP5_SYSCONFIG_STANDBYMODE_FORCE (0 << 4) +#define ISP5_SYSCONFIG_STANDBYMODE_NO (1 << 4) +#define ISP5_SYSCONFIG_STANDBYMODE_SMART (2 << 4) +#define ISP5_SYSCONFIG_SOFTRESET (1 << 1) + +#define ISP5_IRQSTATUS(i) (0x0028 + (0x10 * (i))) +#define ISP5_IRQENABLE_SET(i) (0x002C + (0x10 * (i))) +#define ISP5_IRQENABLE_CLR(i) (0x0030 + (0x10 * (i))) + +/* Bits shared for ISP5_IRQ* registers */ +#define ISP5_IRQ_OCP_ERR (1 << 31) +#define ISP5_IRQ_RSZ_INT_EOF0 (1 << 22) +#define ISP5_IRQ_RSZ_FIFO_IN_BLK (1 << 19) +#define ISP5_IRQ_RSZ_FIFO_OVF (1 << 18) +#define ISP5_IRQ_RSZ_INT_CYC_RSZA (1 << 16) +#define ISP5_IRQ_RSZ_INT_DMA (1 << 15) +#define ISP5_IRQ_IPIPEIF (1 << 9) +#define ISP5_IRQ_ISIF3 (1 << 3) +#define ISP5_IRQ_ISIF2 (1 << 2) +#define ISP5_IRQ_ISIF1 (1 << 1) +#define ISP5_IRQ_ISIF0 (1 << 0) + +#define ISP5_CTRL (0x006C) +#define ISP5_CTRL_MSTANDBY (1 << 24) +#define ISP5_CTRL_VD_PULSE_EXT (1 << 23) +#define ISP5_CTRL_MSTANDBY_WAIT (1 << 20) +#define ISP5_CTRL_BL_CLK_ENABLE (1 << 15) +#define ISP5_CTRL_ISIF_CLK_ENABLE (1 << 14) +#define ISP5_CTRL_H3A_CLK_ENABLE (1 << 13) +#define ISP5_CTRL_RSZ_CLK_ENABLE (1 << 12) +#define ISP5_CTRL_IPIPE_CLK_ENABLE (1 << 11) +#define ISP5_CTRL_IPIPEIF_CLK_ENABLE (1 << 10) +#define ISP5_CTRL_SYNC_ENABLE (1 << 9) +#define ISP5_CTRL_PSYNC_CLK_SEL (1 << 8) + +/* ISS ISP ISIF register offsets */ +#define ISIF_SYNCEN (0x0000) +#define ISIF_SYNCEN_DWEN (1 << 1) +#define ISIF_SYNCEN_SYEN (1 << 0) + +#define ISIF_MODESET (0x0004) +#define ISIF_MODESET_INPMOD_MASK (3 << 12) +#define ISIF_MODESET_INPMOD_RAW (0 << 12) +#define ISIF_MODESET_INPMOD_YCBCR16 (1 << 12) +#define ISIF_MODESET_INPMOD_YCBCR8 (2 << 12) +#define ISIF_MODESET_CCDW_MASK (7 << 8) +#define ISIF_MODESET_CCDW_2BIT (2 << 8) +#define ISIF_MODESET_CCDMD (1 << 7) +#define ISIF_MODESET_SWEN (1 << 5) +#define ISIF_MODESET_HDPOL (1 << 3) +#define ISIF_MODESET_VDPOL (1 << 2) + +#define ISIF_SPH (0x0018) +#define ISIF_SPH_MASK (0x7FFF) + +#define ISIF_LNH (0x001C) +#define ISIF_LNH_MASK (0x7FFF) + +#define ISIF_LNV (0x0028) +#define ISIF_LNV_MASK (0x7FFF) + +#define ISIF_HSIZE (0x0034) +#define ISIF_HSIZE_ADCR (1 << 12) +#define ISIF_HSIZE_HSIZE_MASK (0xFFF) + +#define ISIF_CADU (0x003C) +#define ISIF_CADU_MASK (0x7FF) + +#define ISIF_CADL (0x0040) +#define ISIF_CADL_MASK (0xFFFF) + +#define ISIF_CCOLP (0x004C) +#define ISIF_CCOLP_CP0_F0_R (0 << 6) +#define ISIF_CCOLP_CP0_F0_GR (1 << 6) +#define ISIF_CCOLP_CP0_F0_B (3 << 6) +#define ISIF_CCOLP_CP0_F0_GB (2 << 6) +#define ISIF_CCOLP_CP1_F0_R (0 << 4) +#define ISIF_CCOLP_CP1_F0_GR (1 << 4) +#define ISIF_CCOLP_CP1_F0_B (3 << 4) +#define ISIF_CCOLP_CP1_F0_GB (2 << 4) +#define ISIF_CCOLP_CP2_F0_R (0 << 2) +#define ISIF_CCOLP_CP2_F0_GR (1 << 2) +#define ISIF_CCOLP_CP2_F0_B (3 << 2) +#define ISIF_CCOLP_CP2_F0_GB (2 << 2) +#define ISIF_CCOLP_CP3_F0_R (0 << 0) +#define ISIF_CCOLP_CP3_F0_GR (1 << 0) +#define ISIF_CCOLP_CP3_F0_B (3 << 0) +#define ISIF_CCOLP_CP3_F0_GB (2 << 0) + +#define ISIF_VDINT0 (0x0070) +#define ISIF_VDINT0_MASK (0x7FFF) + +#define ISIF_CGAMMAWD (0x0080) +#define ISIF_CGAMMAWD_GWDI_MASK (0xF << 1) +#define ISIF_CGAMMAWD_GWDI_BIT11 (0x4 << 1) + +#define ISIF_CCDCFG (0x0088) +#define ISIF_CCDCFG_Y8POS (1 << 11) + +/* ISS ISP IPIPEIF register offsets */ +#define IPIPEIF_ENABLE (0x0000) + +#define IPIPEIF_CFG1 (0x0004) +#define IPIPEIF_CFG1_INPSRC1_MASK (3 << 14) +#define IPIPEIF_CFG1_INPSRC1_VPORT_RAW (0 << 14) +#define IPIPEIF_CFG1_INPSRC1_SDRAM_RAW (1 << 14) +#define IPIPEIF_CFG1_INPSRC1_ISIF_DARKFM (2 << 14) +#define IPIPEIF_CFG1_INPSRC1_SDRAM_YUV (3 << 14) +#define IPIPEIF_CFG1_INPSRC2_MASK (3 << 2) +#define IPIPEIF_CFG1_INPSRC2_ISIF (0 << 2) +#define IPIPEIF_CFG1_INPSRC2_SDRAM_RAW (1 << 2) +#define IPIPEIF_CFG1_INPSRC2_ISIF_DARKFM (2 << 2) +#define IPIPEIF_CFG1_INPSRC2_SDRAM_YUV (3 << 2) + +#define IPIPEIF_CFG2 (0x0030) +#define IPIPEIF_CFG2_YUV8P (1 << 7) +#define IPIPEIF_CFG2_YUV8 (1 << 6) +#define IPIPEIF_CFG2_YUV16 (1 << 3) +#define IPIPEIF_CFG2_VDPOL (1 << 2) +#define IPIPEIF_CFG2_HDPOL (1 << 1) +#define IPIPEIF_CFG2_INTSW (1 << 0) + +#define IPIPEIF_CLKDIV (0x0040) + +/* ISS ISP IPIPE register offsets */ +#define IPIPE_SRC_EN (0x0000) +#define IPIPE_SRC_EN_EN (1 << 0) + +#define IPIPE_SRC_MODE (0x0004) +#define IPIPE_SRC_MODE_WRT (1 << 1) +#define IPIPE_SRC_MODE_OST (1 << 0) + +#define IPIPE_SRC_FMT (0x0008) +#define IPIPE_SRC_FMT_RAW2YUV (0 << 0) +#define IPIPE_SRC_FMT_RAW2RAW (1 << 0) +#define IPIPE_SRC_FMT_RAW2STATS (2 << 0) +#define IPIPE_SRC_FMT_YUV2YUV (3 << 0) + +#define IPIPE_SRC_COL (0x000C) +#define IPIPE_SRC_COL_OO_R (0 << 6) +#define IPIPE_SRC_COL_OO_GR (1 << 6) +#define IPIPE_SRC_COL_OO_B (3 << 6) +#define IPIPE_SRC_COL_OO_GB (2 << 6) +#define IPIPE_SRC_COL_OE_R (0 << 4) +#define IPIPE_SRC_COL_OE_GR (1 << 4) +#define IPIPE_SRC_COL_OE_B (3 << 4) +#define IPIPE_SRC_COL_OE_GB (2 << 4) +#define IPIPE_SRC_COL_EO_R (0 << 2) +#define IPIPE_SRC_COL_EO_GR (1 << 2) +#define IPIPE_SRC_COL_EO_B (3 << 2) +#define IPIPE_SRC_COL_EO_GB (2 << 2) +#define IPIPE_SRC_COL_EE_R (0 << 0) +#define IPIPE_SRC_COL_EE_GR (1 << 0) +#define IPIPE_SRC_COL_EE_B (3 << 0) +#define IPIPE_SRC_COL_EE_GB (2 << 0) + +#define IPIPE_SRC_VPS (0x0010) +#define IPIPE_SRC_VPS_MASK (0xFFFF) + +#define IPIPE_SRC_VSZ (0x0014) +#define IPIPE_SRC_VSZ_MASK (0x1FFF) + +#define IPIPE_SRC_HPS (0x0018) +#define IPIPE_SRC_HPS_MASK (0xFFFF) + +#define IPIPE_SRC_HSZ (0x001C) +#define IPIPE_SRC_HSZ_MASK (0x1FFE) + +#define IPIPE_SEL_SBU (0x0020) + +#define IPIPE_SRC_STA (0x0024) + +#define IPIPE_GCK_MMR (0x0028) +#define IPIPE_GCK_MMR_REG (1 << 0) + +#define IPIPE_GCK_PIX (0x002C) +#define IPIPE_GCK_PIX_G3 (1 << 3) +#define IPIPE_GCK_PIX_G2 (1 << 2) +#define IPIPE_GCK_PIX_G1 (1 << 1) +#define IPIPE_GCK_PIX_G0 (1 << 0) + +#define IPIPE_DPC_LUT_EN (0x0034) +#define IPIPE_DPC_LUT_SEL (0x0038) +#define IPIPE_DPC_LUT_ADR (0x003C) +#define IPIPE_DPC_LUT_SIZ (0x0040) + +#define IPIPE_DPC_OTF_EN (0x0044) +#define IPIPE_DPC_OTF_TYP (0x0048) +#define IPIPE_DPC_OTF_2_D_THR_R (0x004C) +#define IPIPE_DPC_OTF_2_D_THR_GR (0x0050) +#define IPIPE_DPC_OTF_2_D_THR_GB (0x0054) +#define IPIPE_DPC_OTF_2_D_THR_B (0x0058) +#define IPIPE_DPC_OTF_2_C_THR_R (0x005C) +#define IPIPE_DPC_OTF_2_C_THR_GR (0x0060) +#define IPIPE_DPC_OTF_2_C_THR_GB (0x0064) +#define IPIPE_DPC_OTF_2_C_THR_B (0x0068) +#define IPIPE_DPC_OTF_3_SHF (0x006C) +#define IPIPE_DPC_OTF_3_D_THR (0x0070) +#define IPIPE_DPC_OTF_3_D_SPL (0x0074) +#define IPIPE_DPC_OTF_3_D_MIN (0x0078) +#define IPIPE_DPC_OTF_3_D_MAX (0x007C) +#define IPIPE_DPC_OTF_3_C_THR (0x0080) +#define IPIPE_DPC_OTF_3_C_SLP (0x0084) +#define IPIPE_DPC_OTF_3_C_MIN (0x0088) +#define IPIPE_DPC_OTF_3_C_MAX (0x008C) + +#define IPIPE_LSC_VOFT (0x0090) +#define IPIPE_LSC_VA2 (0x0094) +#define IPIPE_LSC_VA1 (0x0098) +#define IPIPE_LSC_VS (0x009C) +#define IPIPE_LSC_HOFT (0x00A0) +#define IPIPE_LSC_HA2 (0x00A4) +#define IPIPE_LSC_HA1 (0x00A8) +#define IPIPE_LSC_HS (0x00AC) +#define IPIPE_LSC_GAN_R (0x00B0) +#define IPIPE_LSC_GAN_GR (0x00B4) +#define IPIPE_LSC_GAN_GB (0x00B8) +#define IPIPE_LSC_GAN_B (0x00BC) +#define IPIPE_LSC_OFT_R (0x00C0) +#define IPIPE_LSC_OFT_GR (0x00C4) +#define IPIPE_LSC_OFT_GB (0x00C8) +#define IPIPE_LSC_OFT_B (0x00CC) +#define IPIPE_LSC_SHF (0x00D0) +#define IPIPE_LSC_MAX (0x00D4) + +#define IPIPE_D2F_1ST_EN (0x00D8) +#define IPIPE_D2F_1ST_TYP (0x00DC) +#define IPIPE_D2F_1ST_THR_00 (0x00E0) +#define IPIPE_D2F_1ST_THR_01 (0x00E4) +#define IPIPE_D2F_1ST_THR_02 (0x00E8) +#define IPIPE_D2F_1ST_THR_03 (0x00EC) +#define IPIPE_D2F_1ST_THR_04 (0x00F0) +#define IPIPE_D2F_1ST_THR_05 (0x00F4) +#define IPIPE_D2F_1ST_THR_06 (0x00F8) +#define IPIPE_D2F_1ST_THR_07 (0x00FC) +#define IPIPE_D2F_1ST_STR_00 (0x0100) +#define IPIPE_D2F_1ST_STR_01 (0x0104) +#define IPIPE_D2F_1ST_STR_02 (0x0108) +#define IPIPE_D2F_1ST_STR_03 (0x010C) +#define IPIPE_D2F_1ST_STR_04 (0x0110) +#define IPIPE_D2F_1ST_STR_05 (0x0114) +#define IPIPE_D2F_1ST_STR_06 (0x0118) +#define IPIPE_D2F_1ST_STR_07 (0x011C) +#define IPIPE_D2F_1ST_SPR_00 (0x0120) +#define IPIPE_D2F_1ST_SPR_01 (0x0124) +#define IPIPE_D2F_1ST_SPR_02 (0x0128) +#define IPIPE_D2F_1ST_SPR_03 (0x012C) +#define IPIPE_D2F_1ST_SPR_04 (0x0130) +#define IPIPE_D2F_1ST_SPR_05 (0x0134) +#define IPIPE_D2F_1ST_SPR_06 (0x0138) +#define IPIPE_D2F_1ST_SPR_07 (0x013C) +#define IPIPE_D2F_1ST_EDG_MIN (0x0140) +#define IPIPE_D2F_1ST_EDG_MAX (0x0144) +#define IPIPE_D2F_2ND_EN (0x0148) +#define IPIPE_D2F_2ND_TYP (0x014C) +#define IPIPE_D2F_2ND_THR00 (0x0150) +#define IPIPE_D2F_2ND_THR01 (0x0154) +#define IPIPE_D2F_2ND_THR02 (0x0158) +#define IPIPE_D2F_2ND_THR03 (0x015C) +#define IPIPE_D2F_2ND_THR04 (0x0160) +#define IPIPE_D2F_2ND_THR05 (0x0164) +#define IPIPE_D2F_2ND_THR06 (0x0168) +#define IPIPE_D2F_2ND_THR07 (0x016C) +#define IPIPE_D2F_2ND_STR_00 (0x0170) +#define IPIPE_D2F_2ND_STR_01 (0x0174) +#define IPIPE_D2F_2ND_STR_02 (0x0178) +#define IPIPE_D2F_2ND_STR_03 (0x017C) +#define IPIPE_D2F_2ND_STR_04 (0x0180) +#define IPIPE_D2F_2ND_STR_05 (0x0184) +#define IPIPE_D2F_2ND_STR_06 (0x0188) +#define IPIPE_D2F_2ND_STR_07 (0x018C) +#define IPIPE_D2F_2ND_SPR_00 (0x0190) +#define IPIPE_D2F_2ND_SPR_01 (0x0194) +#define IPIPE_D2F_2ND_SPR_02 (0x0198) +#define IPIPE_D2F_2ND_SPR_03 (0x019C) +#define IPIPE_D2F_2ND_SPR_04 (0x01A0) +#define IPIPE_D2F_2ND_SPR_05 (0x01A4) +#define IPIPE_D2F_2ND_SPR_06 (0x01A8) +#define IPIPE_D2F_2ND_SPR_07 (0x01AC) +#define IPIPE_D2F_2ND_EDG_MIN (0x01B0) +#define IPIPE_D2F_2ND_EDG_MAX (0x01B4) + +#define IPIPE_GIC_EN (0x01B8) +#define IPIPE_GIC_TYP (0x01BC) +#define IPIPE_GIC_GAN (0x01C0) +#define IPIPE_GIC_NFGAIN (0x01C4) +#define IPIPE_GIC_THR (0x01C8) +#define IPIPE_GIC_SLP (0x01CC) + +#define IPIPE_WB2_OFT_R (0x01D0) +#define IPIPE_WB2_OFT_GR (0x01D4) +#define IPIPE_WB2_OFT_GB (0x01D8) +#define IPIPE_WB2_OFT_B (0x01DC) + +#define IPIPE_WB2_WGN_R (0x01E0) +#define IPIPE_WB2_WGN_GR (0x01E4) +#define IPIPE_WB2_WGN_GB (0x01E8) +#define IPIPE_WB2_WGN_B (0x01EC) + +#define IPIPE_CFA_MODE (0x01F0) +#define IPIPE_CFA_2DIR_HPF_THR (0x01F4) +#define IPIPE_CFA_2DIR_HPF_SLP (0x01F8) +#define IPIPE_CFA_2DIR_MIX_THR (0x01FC) +#define IPIPE_CFA_2DIR_MIX_SLP (0x0200) +#define IPIPE_CFA_2DIR_DIR_TRH (0x0204) +#define IPIPE_CFA_2DIR_DIR_SLP (0x0208) +#define IPIPE_CFA_2DIR_NDWT (0x020C) +#define IPIPE_CFA_MONO_HUE_FRA (0x0210) +#define IPIPE_CFA_MONO_EDG_THR (0x0214) +#define IPIPE_CFA_MONO_THR_MIN (0x0218) + +#define IPIPE_CFA_MONO_THR_SLP (0x021C) +#define IPIPE_CFA_MONO_SLP_MIN (0x0220) +#define IPIPE_CFA_MONO_SLP_SLP (0x0224) +#define IPIPE_CFA_MONO_LPWT (0x0228) + +#define IPIPE_RGB1_MUL_RR (0x022C) +#define IPIPE_RGB1_MUL_GR (0x0230) +#define IPIPE_RGB1_MUL_BR (0x0234) +#define IPIPE_RGB1_MUL_RG (0x0238) +#define IPIPE_RGB1_MUL_GG (0x023C) +#define IPIPE_RGB1_MUL_BG (0x0240) +#define IPIPE_RGB1_MUL_RB (0x0244) +#define IPIPE_RGB1_MUL_GB (0x0248) +#define IPIPE_RGB1_MUL_BB (0x024C) +#define IPIPE_RGB1_OFT_OR (0x0250) +#define IPIPE_RGB1_OFT_OG (0x0254) +#define IPIPE_RGB1_OFT_OB (0x0258) +#define IPIPE_GMM_CFG (0x025C) +#define IPIPE_RGB2_MUL_RR (0x0260) +#define IPIPE_RGB2_MUL_GR (0x0264) +#define IPIPE_RGB2_MUL_BR (0x0268) +#define IPIPE_RGB2_MUL_RG (0x026C) +#define IPIPE_RGB2_MUL_GG (0x0270) +#define IPIPE_RGB2_MUL_BG (0x0274) +#define IPIPE_RGB2_MUL_RB (0x0278) +#define IPIPE_RGB2_MUL_GB (0x027C) +#define IPIPE_RGB2_MUL_BB (0x0280) +#define IPIPE_RGB2_OFT_OR (0x0284) +#define IPIPE_RGB2_OFT_OG (0x0288) +#define IPIPE_RGB2_OFT_OB (0x028C) + +#define IPIPE_YUV_ADJ (0x0294) +#define IPIPE_YUV_MUL_RY (0x0298) +#define IPIPE_YUV_MUL_GY (0x029C) +#define IPIPE_YUV_MUL_BY (0x02A0) +#define IPIPE_YUV_MUL_RCB (0x02A4) +#define IPIPE_YUV_MUL_GCB (0x02A8) +#define IPIPE_YUV_MUL_BCB (0x02AC) +#define IPIPE_YUV_MUL_RCR (0x02B0) +#define IPIPE_YUV_MUL_GCR (0x02B4) +#define IPIPE_YUV_MUL_BCR (0x02B8) +#define IPIPE_YUV_OFT_Y (0x02BC) +#define IPIPE_YUV_OFT_CB (0x02C0) +#define IPIPE_YUV_OFT_CR (0x02C4) + +#define IPIPE_YUV_PHS (0x02C8) +#define IPIPE_YUV_PHS_LPF (1 << 1) +#define IPIPE_YUV_PHS_POS (1 << 0) + +#define IPIPE_YEE_EN (0x02D4) +#define IPIPE_YEE_TYP (0x02D8) +#define IPIPE_YEE_SHF (0x02DC) +#define IPIPE_YEE_MUL_00 (0x02E0) +#define IPIPE_YEE_MUL_01 (0x02E4) +#define IPIPE_YEE_MUL_02 (0x02E8) +#define IPIPE_YEE_MUL_10 (0x02EC) +#define IPIPE_YEE_MUL_11 (0x02F0) +#define IPIPE_YEE_MUL_12 (0x02F4) +#define IPIPE_YEE_MUL_20 (0x02F8) +#define IPIPE_YEE_MUL_21 (0x02FC) +#define IPIPE_YEE_MUL_22 (0x0300) +#define IPIPE_YEE_THR (0x0304) +#define IPIPE_YEE_E_GAN (0x0308) +#define IPIPE_YEE_E_THR_1 (0x030C) +#define IPIPE_YEE_E_THR_2 (0x0310) +#define IPIPE_YEE_G_GAN (0x0314) +#define IPIPE_YEE_G_OFT (0x0318) + +#define IPIPE_CAR_EN (0x031C) +#define IPIPE_CAR_TYP (0x0320) +#define IPIPE_CAR_SW (0x0324) +#define IPIPE_CAR_HPF_TYP (0x0328) +#define IPIPE_CAR_HPF_SHF (0x032C) +#define IPIPE_CAR_HPF_THR (0x0330) +#define IPIPE_CAR_GN1_GAN (0x0334) +#define IPIPE_CAR_GN1_SHF (0x0338) +#define IPIPE_CAR_GN1_MIN (0x033C) +#define IPIPE_CAR_GN2_GAN (0x0340) +#define IPIPE_CAR_GN2_SHF (0x0344) +#define IPIPE_CAR_GN2_MIN (0x0348) +#define IPIPE_CGS_EN (0x034C) +#define IPIPE_CGS_GN1_L_THR (0x0350) +#define IPIPE_CGS_GN1_L_GAIN (0x0354) +#define IPIPE_CGS_GN1_L_SHF (0x0358) +#define IPIPE_CGS_GN1_L_MIN (0x035C) +#define IPIPE_CGS_GN1_H_THR (0x0360) +#define IPIPE_CGS_GN1_H_GAIN (0x0364) +#define IPIPE_CGS_GN1_H_SHF (0x0368) +#define IPIPE_CGS_GN1_H_MIN (0x036C) +#define IPIPE_CGS_GN2_L_THR (0x0370) +#define IPIPE_CGS_GN2_L_GAIN (0x0374) +#define IPIPE_CGS_GN2_L_SHF (0x0378) +#define IPIPE_CGS_GN2_L_MIN (0x037C) + +#define IPIPE_BOX_EN (0x0380) +#define IPIPE_BOX_MODE (0x0384) +#define IPIPE_BOX_TYP (0x0388) +#define IPIPE_BOX_SHF (0x038C) +#define IPIPE_BOX_SDR_SAD_H (0x0390) +#define IPIPE_BOX_SDR_SAD_L (0x0394) + +#define IPIPE_HST_EN (0x039C) +#define IPIPE_HST_MODE (0x03A0) +#define IPIPE_HST_SEL (0x03A4) +#define IPIPE_HST_PARA (0x03A8) +#define IPIPE_HST_0_VPS (0x03AC) +#define IPIPE_HST_0_VSZ (0x03B0) +#define IPIPE_HST_0_HPS (0x03B4) +#define IPIPE_HST_0_HSZ (0x03B8) +#define IPIPE_HST_1_VPS (0x03BC) +#define IPIPE_HST_1_VSZ (0x03C0) +#define IPIPE_HST_1_HPS (0x03C4) +#define IPIPE_HST_1_HSZ (0x03C8) +#define IPIPE_HST_2_VPS (0x03CC) +#define IPIPE_HST_2_VSZ (0x03D0) +#define IPIPE_HST_2_HPS (0x03D4) +#define IPIPE_HST_2_HSZ (0x03D8) +#define IPIPE_HST_3_VPS (0x03DC) +#define IPIPE_HST_3_VSZ (0x03E0) +#define IPIPE_HST_3_HPS (0x03E4) +#define IPIPE_HST_3_HSZ (0x03E8) +#define IPIPE_HST_TBL (0x03EC) +#define IPIPE_HST_MUL_R (0x03F0) +#define IPIPE_HST_MUL_GR (0x03F4) +#define IPIPE_HST_MUL_GB (0x03F8) +#define IPIPE_HST_MUL_B (0x03FC) + +#define IPIPE_BSC_EN (0x0400) +#define IPIPE_BSC_MODE (0x0404) +#define IPIPE_BSC_TYP (0x0408) +#define IPIPE_BSC_ROW_VCT (0x040C) +#define IPIPE_BSC_ROW_SHF (0x0410) +#define IPIPE_BSC_ROW_VPO (0x0414) +#define IPIPE_BSC_ROW_VNU (0x0418) +#define IPIPE_BSC_ROW_VSKIP (0x041C) +#define IPIPE_BSC_ROW_HPO (0x0420) +#define IPIPE_BSC_ROW_HNU (0x0424) +#define IPIPE_BSC_ROW_HSKIP (0x0428) +#define IPIPE_BSC_COL_VCT (0x042C) +#define IPIPE_BSC_COL_SHF (0x0430) +#define IPIPE_BSC_COL_VPO (0x0434) +#define IPIPE_BSC_COL_VNU (0x0438) +#define IPIPE_BSC_COL_VSKIP (0x043C) +#define IPIPE_BSC_COL_HPO (0x0440) +#define IPIPE_BSC_COL_HNU (0x0444) +#define IPIPE_BSC_COL_HSKIP (0x0448) + +#define IPIPE_BSC_EN (0x0400) + +/* ISS ISP Resizer register offsets */ +#define RSZ_REVISION (0x0000) +#define RSZ_SYSCONFIG (0x0004) +#define RSZ_SYSCONFIG_RSZB_CLK_EN (1 << 9) +#define RSZ_SYSCONFIG_RSZA_CLK_EN (1 << 8) + +#define RSZ_IN_FIFO_CTRL (0x000C) +#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1FF << 16) +#define RSZ_IN_FIFO_CTRL_THRLD_LOW_SHIFT 16 +#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK (0x1FF << 0) +#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_SHIFT 0 + +#define RSZ_FRACDIV (0x0008) +#define RSZ_FRACDIV_MASK (0xFFFF) + +#define RSZ_SRC_EN (0x0020) +#define RSZ_SRC_EN_SRC_EN (1 << 0) + +#define RSZ_SRC_MODE (0x0024) +#define RSZ_SRC_MODE_OST (1 << 0) +#define RSZ_SRC_MODE_WRT (1 << 1) + +#define RSZ_SRC_FMT0 (0x0028) +#define RSZ_SRC_FMT0_BYPASS (1 << 1) +#define RSZ_SRC_FMT0_SEL (1 << 0) + +#define RSZ_SRC_FMT1 (0x002C) +#define RSZ_SRC_FMT1_IN420 (1 << 1) + +#define RSZ_SRC_VPS (0x0030) +#define RSZ_SRC_VSZ (0x0034) +#define RSZ_SRC_HPS (0x0038) +#define RSZ_SRC_HSZ (0x003C) +#define RSZ_DMA_RZA (0x0040) +#define RSZ_DMA_RZB (0x0044) +#define RSZ_DMA_STA (0x0048) +#define RSZ_GCK_MMR (0x004C) +#define RSZ_GCK_MMR_MMR (1 << 0) + +#define RSZ_GCK_SDR (0x0054) +#define RSZ_GCK_SDR_CORE (1 << 0) + +#define RSZ_IRQ_RZA (0x0058) +#define RSZ_IRQ_RZA_MASK (0x1FFF) + +#define RSZ_IRQ_RZB (0x005C) +#define RSZ_IRQ_RZB_MASK (0x1FFF) + +#define RSZ_YUV_Y_MIN (0x0060) +#define RSZ_YUV_Y_MAX (0x0064) +#define RSZ_YUV_C_MIN (0x0068) +#define RSZ_YUV_C_MAX (0x006C) + +#define RSZ_SEQ (0x0074) +#define RSZ_SEQ_HRVB (1 << 2) +#define RSZ_SEQ_HRVA (1 << 0) + +#define RZA_EN (0x0078) +#define RZA_MODE (0x007C) +#define RZA_MODE_ONE_SHOT (1 << 0) + +#define RZA_420 (0x0080) +#define RZA_I_VPS (0x0084) +#define RZA_I_HPS (0x0088) +#define RZA_O_VSZ (0x008C) +#define RZA_O_HSZ (0x0090) +#define RZA_V_PHS_Y (0x0094) +#define RZA_V_PHS_C (0x0098) +#define RZA_V_DIF (0x009C) +#define RZA_V_TYP (0x00A0) +#define RZA_V_LPF (0x00A4) +#define RZA_H_PHS (0x00A8) +#define RZA_H_DIF (0x00B0) +#define RZA_H_TYP (0x00B4) +#define RZA_H_LPF (0x00B8) +#define RZA_DWN_EN (0x00BC) +#define RZA_SDR_Y_BAD_H (0x00D0) +#define RZA_SDR_Y_BAD_L (0x00D4) +#define RZA_SDR_Y_SAD_H (0x00D8) +#define RZA_SDR_Y_SAD_L (0x00DC) +#define RZA_SDR_Y_OFT (0x00E0) +#define RZA_SDR_Y_PTR_S (0x00E4) +#define RZA_SDR_Y_PTR_E (0x00E8) +#define RZA_SDR_C_BAD_H (0x00EC) +#define RZA_SDR_C_BAD_L (0x00F0) +#define RZA_SDR_C_SAD_H (0x00F4) +#define RZA_SDR_C_SAD_L (0x00F8) +#define RZA_SDR_C_OFT (0x00FC) +#define RZA_SDR_C_PTR_S (0x0100) +#define RZA_SDR_C_PTR_E (0x0104) + +#define RZB_EN (0x0108) +#define RZB_MODE (0x010C) +#define RZB_420 (0x0110) +#define RZB_I_VPS (0x0114) +#define RZB_I_HPS (0x0118) +#define RZB_O_VSZ (0x011C) +#define RZB_O_HSZ (0x0120) + +#define RZB_V_DIF (0x012C) +#define RZB_V_TYP (0x0130) +#define RZB_V_LPF (0x0134) + +#define RZB_H_DIF (0x0140) +#define RZB_H_TYP (0x0144) +#define RZB_H_LPF (0x0148) + +#define RZB_SDR_Y_BAD_H (0x0160) +#define RZB_SDR_Y_BAD_L (0x0164) +#define RZB_SDR_Y_SAD_H (0x0168) +#define RZB_SDR_Y_SAD_L (0x016C) +#define RZB_SDR_Y_OFT (0x0170) +#define RZB_SDR_Y_PTR_S (0x0174) +#define RZB_SDR_Y_PTR_E (0x0178) +#define RZB_SDR_C_BAD_H (0x017C) +#define RZB_SDR_C_BAD_L (0x0180) +#define RZB_SDR_C_SAD_H (0x0184) +#define RZB_SDR_C_SAD_L (0x0188) + +#define RZB_SDR_C_PTR_S (0x0190) +#define RZB_SDR_C_PTR_E (0x0194) + +/* Shared Bitmasks between RZA & RZB */ +#define RSZ_EN_EN (1 << 0) + +#define RSZ_420_CEN (1 << 1) +#define RSZ_420_YEN (1 << 0) + +#define RSZ_I_VPS_MASK (0x1FFF) + +#define RSZ_I_HPS_MASK (0x1FFF) + +#define RSZ_O_VSZ_MASK (0x1FFF) + +#define RSZ_O_HSZ_MASK (0x1FFE) + +#define RSZ_V_PHS_Y_MASK (0x3FFF) + +#define RSZ_V_PHS_C_MASK (0x3FFF) + +#define RSZ_V_DIF_MASK (0x3FFF) + +#define RSZ_V_TYP_C (1 << 1) +#define RSZ_V_TYP_Y (1 << 0) + +#define RSZ_V_LPF_C_MASK (0x3F << 6) +#define RSZ_V_LPF_C_SHIFT 6 +#define RSZ_V_LPF_Y_MASK (0x3F << 0) +#define RSZ_V_LPF_Y_SHIFT 0 + +#define RSZ_H_PHS_MASK (0x3FFF) + +#define RSZ_H_DIF_MASK (0x3FFF) + +#define RSZ_H_TYP_C (1 << 1) +#define RSZ_H_TYP_Y (1 << 0) + +#define RSZ_H_LPF_C_MASK (0x3F << 6) +#define RSZ_H_LPF_C_SHIFT 6 +#define RSZ_H_LPF_Y_MASK (0x3F << 0) +#define RSZ_H_LPF_Y_SHIFT 0 + +#define RSZ_DWN_EN_DWN_EN (1 << 0) + +#endif /* _OMAP4_ISS_REGS_H_ */ diff --git a/include/media/omap4iss.h b/include/media/omap4iss.h new file mode 100644 index 000000000000..0d7620db5e32 --- /dev/null +++ b/include/media/omap4iss.h @@ -0,0 +1,65 @@ +#ifndef ARCH_ARM_PLAT_OMAP4_ISS_H +#define ARCH_ARM_PLAT_OMAP4_ISS_H + +#include + +struct iss_device; + +enum iss_interface_type { + ISS_INTERFACE_CSI2A_PHY1, + ISS_INTERFACE_CSI2B_PHY2, +}; + +/** + * struct iss_csiphy_lane: CSI2 lane position and polarity + * @pos: position of the lane + * @pol: polarity of the lane + */ +struct iss_csiphy_lane { + u8 pos; + u8 pol; +}; + +#define ISS_CSIPHY1_NUM_DATA_LANES 4 +#define ISS_CSIPHY2_NUM_DATA_LANES 1 + +/** + * struct iss_csiphy_lanes_cfg - CSI2 lane configuration + * @data: Configuration of one or two data lanes + * @clk: Clock lane configuration + */ +struct iss_csiphy_lanes_cfg { + struct iss_csiphy_lane data[ISS_CSIPHY1_NUM_DATA_LANES]; + struct iss_csiphy_lane clk; +}; + +/** + * struct iss_csi2_platform_data - CSI2 interface platform data + * @crc: Enable the cyclic redundancy check + * @vpclk_div: Video port output clock control + */ +struct iss_csi2_platform_data { + unsigned crc:1; + unsigned vpclk_div:2; + struct iss_csiphy_lanes_cfg lanecfg; +}; + +struct iss_subdev_i2c_board_info { + struct i2c_board_info *board_info; + int i2c_adapter_id; +}; + +struct iss_v4l2_subdevs_group { + struct iss_subdev_i2c_board_info *subdevs; + enum iss_interface_type interface; + union { + struct iss_csi2_platform_data csi2; + } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */ +}; + +struct iss_platform_data { + struct iss_v4l2_subdevs_group *subdevs; + void (*set_constraints)(struct iss_device *iss, bool enable); +}; + +#endif -- cgit v1.2.3 From fc96d58c10162d476138f135b5e9080fec41b478 Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Mon, 24 Jan 2011 15:48:19 -0300 Subject: [media] v4l: omap4iss: Add support for OMAP4 camera interface - Video devices This adds a very simplistic driver to utilize the CSI2A interface inside the ISS subsystem in OMAP4, and dump the data to memory. Check Documentation/video4linux/omap4_camera.txt for details. This commit adds video devices support. Signed-off-by: Sergio Aguirre Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 1129 ++++++++++++++++++++++++++++ drivers/staging/media/omap4iss/iss_video.h | 201 +++++ 2 files changed, 1330 insertions(+) create mode 100644 drivers/staging/media/omap4iss/iss_video.c create mode 100644 drivers/staging/media/omap4iss/iss_video.h (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c new file mode 100644 index 000000000000..31f1b8805711 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -0,0 +1,1129 @@ +/* + * TI OMAP4 ISS V4L2 Driver - Generic video node + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 "iss_video.h" +#include "iss.h" + + +/* ----------------------------------------------------------------------------- + * Helper functions + */ + +static struct iss_format_info formats[] = { + { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, + V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, + V4L2_PIX_FMT_GREY, 8, }, + { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10, + V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8, + V4L2_PIX_FMT_Y10, 10, }, + { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10, + V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8, + V4L2_PIX_FMT_Y12, 12, }, + { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_PIX_FMT_SBGGR8, 8, }, + { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_PIX_FMT_SGBRG8, 8, }, + { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_PIX_FMT_SGRBG8, 8, }, + { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_PIX_FMT_SRGGB8, 8, }, + { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, + V4L2_MBUS_FMT_SGRBG10_1X10, 0, + V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, + { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10, + V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_PIX_FMT_SBGGR10, 10, }, + { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10, + V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_PIX_FMT_SGBRG10, 10, }, + { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10, + V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_PIX_FMT_SGRBG10, 10, }, + { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, + V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_PIX_FMT_SRGGB10, 10, }, + { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10, + V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_PIX_FMT_SBGGR12, 12, }, + { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10, + V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_PIX_FMT_SGBRG12, 12, }, + { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10, + V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_PIX_FMT_SGRBG12, 12, }, + { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10, + V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_PIX_FMT_SRGGB12, 12, }, + { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16, + V4L2_MBUS_FMT_UYVY8_1X16, 0, + V4L2_PIX_FMT_UYVY, 16, }, + { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, + V4L2_MBUS_FMT_YUYV8_1X16, 0, + V4L2_PIX_FMT_YUYV, 16, }, + { V4L2_MBUS_FMT_YUYV8_1_5X8, V4L2_MBUS_FMT_YUYV8_1_5X8, + V4L2_MBUS_FMT_YUYV8_1_5X8, 0, + V4L2_PIX_FMT_NV12, 8, }, +}; + +const struct iss_format_info * +omap4iss_video_format_info(enum v4l2_mbus_pixelcode code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].code == code) + return &formats[i]; + } + + return NULL; +} + +/* + * iss_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format + * @video: ISS video instance + * @mbus: v4l2_mbus_framefmt format (input) + * @pix: v4l2_pix_format format (output) + * + * Fill the output pix structure with information from the input mbus format. + * The bytesperline and sizeimage fields are computed from the requested bytes + * per line value in the pix format and information from the video instance. + * + * Return the number of padding bytes at end of line. + */ +static unsigned int iss_video_mbus_to_pix(const struct iss_video *video, + const struct v4l2_mbus_framefmt *mbus, + struct v4l2_pix_format *pix) +{ + unsigned int bpl = pix->bytesperline; + unsigned int min_bpl; + unsigned int i; + + memset(pix, 0, sizeof(*pix)); + pix->width = mbus->width; + pix->height = mbus->height; + + /* Skip the last format in the loop so that it will be selected if no + * match is found. + */ + for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { + if (formats[i].code == mbus->code) + break; + } + + min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8; + + /* Clamp the requested bytes per line value. If the maximum bytes per + * line value is zero, the module doesn't support user configurable line + * sizes. Override the requested value with the minimum in that case. + */ + if (video->bpl_max) + bpl = clamp(bpl, min_bpl, video->bpl_max); + else + bpl = min_bpl; + + if (!video->bpl_zero_padding || bpl != min_bpl) + bpl = ALIGN(bpl, video->bpl_alignment); + + pix->pixelformat = formats[i].pixelformat; + pix->bytesperline = bpl; + pix->sizeimage = pix->bytesperline * pix->height; + pix->colorspace = mbus->colorspace; + pix->field = mbus->field; + + /* FIXME: Special case for NV12! We should make this nicer... */ + if (pix->pixelformat == V4L2_PIX_FMT_NV12) + pix->sizeimage += (pix->bytesperline * pix->height) / 2; + + return bpl - min_bpl; +} + +static void iss_video_pix_to_mbus(const struct v4l2_pix_format *pix, + struct v4l2_mbus_framefmt *mbus) +{ + unsigned int i; + + memset(mbus, 0, sizeof(*mbus)); + mbus->width = pix->width; + mbus->height = pix->height; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].pixelformat == pix->pixelformat) + break; + } + + if (WARN_ON(i == ARRAY_SIZE(formats))) + return; + + mbus->code = formats[i].code; + mbus->colorspace = pix->colorspace; + mbus->field = pix->field; +} + +static struct v4l2_subdev * +iss_video_remote_subdev(struct iss_video *video, u32 *pad) +{ + struct media_pad *remote; + + remote = media_entity_remote_pad(&video->pad); + + if (remote == NULL || + media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + return NULL; + + if (pad) + *pad = remote->index; + + return media_entity_to_v4l2_subdev(remote->entity); +} + +/* Return a pointer to the ISS video instance at the far end of the pipeline. */ +static struct iss_video * +iss_video_far_end(struct iss_video *video) +{ + struct media_entity_graph graph; + struct media_entity *entity = &video->video.entity; + struct media_device *mdev = entity->parent; + struct iss_video *far_end = NULL; + + mutex_lock(&mdev->graph_mutex); + media_entity_graph_walk_start(&graph, entity); + + while ((entity = media_entity_graph_walk_next(&graph))) { + if (entity == &video->video.entity) + continue; + + if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) + continue; + + far_end = to_iss_video(media_entity_to_video_device(entity)); + if (far_end->type != video->type) + break; + + far_end = NULL; + } + + mutex_unlock(&mdev->graph_mutex); + return far_end; +} + +static int +__iss_video_get_format(struct iss_video *video, struct v4l2_format *format) +{ + struct v4l2_subdev_format fmt; + struct v4l2_subdev *subdev; + u32 pad; + int ret; + + subdev = iss_video_remote_subdev(video, &pad); + if (subdev == NULL) + return -EINVAL; + + mutex_lock(&video->mutex); + + fmt.pad = pad; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); + if (ret == -ENOIOCTLCMD) + ret = -EINVAL; + + mutex_unlock(&video->mutex); + + if (ret) + return ret; + + format->type = video->type; + return iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); +} + +static int +iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh) +{ + struct v4l2_format format; + int ret; + + memcpy(&format, &vfh->format, sizeof(format)); + ret = __iss_video_get_format(video, &format); + if (ret < 0) + return ret; + + if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat || + vfh->format.fmt.pix.height != format.fmt.pix.height || + vfh->format.fmt.pix.width != format.fmt.pix.width || + vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline || + vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage) + return -EINVAL; + + return ret; +} + +/* ----------------------------------------------------------------------------- + * Video queue operations + */ + +static int iss_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *count, unsigned int *num_planes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct iss_video_fh *vfh = vb2_get_drv_priv(vq); + struct iss_video *video = vfh->video; + + /* Revisit multi-planar support for NV12 */ + *num_planes = 1; + + sizes[0] = vfh->format.fmt.pix.sizeimage; + if (sizes[0] == 0) + return -EINVAL; + + alloc_ctxs[0] = video->alloc_ctx; + + *count = min(*count, (unsigned int)(video->capture_mem / PAGE_ALIGN(sizes[0]))); + + return 0; +} + +static void iss_video_buf_cleanup(struct vb2_buffer *vb) +{ + struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb); + + if (buffer->iss_addr) + buffer->iss_addr = 0; +} + +static int iss_video_buf_prepare(struct vb2_buffer *vb) +{ + struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue); + struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb); + struct iss_video *video = vfh->video; + unsigned long size = vfh->format.fmt.pix.sizeimage; + dma_addr_t addr; + + if (vb2_plane_size(vb, 0) < size) + return -ENOBUFS; + + addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (!IS_ALIGNED(addr, 32)) { + dev_dbg(video->iss->dev, "Buffer address must be " + "aligned to 32 bytes boundary.\n"); + return -EINVAL; + } + + vb2_set_plane_payload(vb, 0, size); + buffer->iss_addr = addr; + return 0; +} + +static void iss_video_buf_queue(struct vb2_buffer *vb) +{ + struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue); + struct iss_video *video = vfh->video; + struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb); + struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); + unsigned int empty; + unsigned long flags; + + spin_lock_irqsave(&video->qlock, flags); + empty = list_empty(&video->dmaqueue); + list_add_tail(&buffer->list, &video->dmaqueue); + spin_unlock_irqrestore(&video->qlock, flags); + + if (empty) { + enum iss_pipeline_state state; + unsigned int start; + + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + state = ISS_PIPELINE_QUEUE_OUTPUT; + else + state = ISS_PIPELINE_QUEUE_INPUT; + + spin_lock_irqsave(&pipe->lock, flags); + pipe->state |= state; + video->ops->queue(video, buffer); + video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED; + + start = iss_pipeline_ready(pipe); + if (start) + pipe->state |= ISS_PIPELINE_STREAM; + spin_unlock_irqrestore(&pipe->lock, flags); + + if (start) + omap4iss_pipeline_set_stream(pipe, + ISS_PIPELINE_STREAM_SINGLESHOT); + } +} + +static struct vb2_ops iss_video_vb2ops = { + .queue_setup = iss_video_queue_setup, + .buf_prepare = iss_video_buf_prepare, + .buf_queue = iss_video_buf_queue, + .buf_cleanup = iss_video_buf_cleanup, +}; + +/* + * omap4iss_video_buffer_next - Complete the current buffer and return the next + * @video: ISS video object + * + * Remove the current video buffer from the DMA queue and fill its timestamp, + * field count and state fields before waking up its completion handler. + * + * For capture video nodes, the buffer state is set to VB2_BUF_STATE_DONE if no + * error has been flagged in the pipeline, or to VB2_BUF_STATE_ERROR otherwise. + * + * The DMA queue is expected to contain at least one buffer. + * + * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is + * empty. + */ +struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video) +{ + struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); + enum iss_pipeline_state state; + struct iss_buffer *buf; + unsigned long flags; + struct timespec ts; + + spin_lock_irqsave(&video->qlock, flags); + if (WARN_ON(list_empty(&video->dmaqueue))) { + spin_unlock_irqrestore(&video->qlock, flags); + return NULL; + } + + buf = list_first_entry(&video->dmaqueue, struct iss_buffer, + list); + list_del(&buf->list); + spin_unlock_irqrestore(&video->qlock, flags); + + ktime_get_ts(&ts); + buf->vb.v4l2_buf.timestamp.tv_sec = ts.tv_sec; + buf->vb.v4l2_buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; + + /* Do frame number propagation only if this is the output video node. + * Frame number either comes from the CSI receivers or it gets + * incremented here if H3A is not active. + * Note: There is no guarantee that the output buffer will finish + * first, so the input number might lag behind by 1 in some cases. + */ + if (video == pipe->output && !pipe->do_propagation) + buf->vb.v4l2_buf.sequence = atomic_inc_return(&pipe->frame_number); + else + buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number); + + vb2_buffer_done(&buf->vb, pipe->error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); + pipe->error = false; + + spin_lock_irqsave(&video->qlock, flags); + if (list_empty(&video->dmaqueue)) { + spin_unlock_irqrestore(&video->qlock, flags); + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + state = ISS_PIPELINE_QUEUE_OUTPUT + | ISS_PIPELINE_STREAM; + else + state = ISS_PIPELINE_QUEUE_INPUT + | ISS_PIPELINE_STREAM; + + spin_lock_irqsave(&pipe->lock, flags); + pipe->state &= ~state; + if (video->pipe.stream_state == ISS_PIPELINE_STREAM_CONTINUOUS) + video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN; + spin_unlock_irqrestore(&pipe->lock, flags); + return NULL; + } + + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) { + spin_lock_irqsave(&pipe->lock, flags); + pipe->state &= ~ISS_PIPELINE_STREAM; + spin_unlock_irqrestore(&pipe->lock, flags); + } + + buf = list_first_entry(&video->dmaqueue, struct iss_buffer, + list); + spin_unlock_irqrestore(&video->qlock, flags); + buf->vb.state = VB2_BUF_STATE_ACTIVE; + return buf; +} + +/* ----------------------------------------------------------------------------- + * V4L2 ioctls + */ + +static int +iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) +{ + struct iss_video *video = video_drvdata(file); + + strlcpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver)); + strlcpy(cap->card, video->video.name, sizeof(cap->card)); + strlcpy(cap->bus_info, "media", sizeof(cap->bus_info)); + + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + else + cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + + return 0; +} + +static int +iss_video_get_format(struct file *file, void *fh, struct v4l2_format *format) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + struct iss_video *video = video_drvdata(file); + + if (format->type != video->type) + return -EINVAL; + + mutex_lock(&video->mutex); + *format = vfh->format; + mutex_unlock(&video->mutex); + + return 0; +} + +static int +iss_video_set_format(struct file *file, void *fh, struct v4l2_format *format) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + struct iss_video *video = video_drvdata(file); + struct v4l2_mbus_framefmt fmt; + + if (format->type != video->type) + return -EINVAL; + + mutex_lock(&video->mutex); + + /* Fill the bytesperline and sizeimage fields by converting to media bus + * format and back to pixel format. + */ + iss_video_pix_to_mbus(&format->fmt.pix, &fmt); + iss_video_mbus_to_pix(video, &fmt, &format->fmt.pix); + + vfh->format = *format; + + mutex_unlock(&video->mutex); + return 0; +} + +static int +iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format) +{ + struct iss_video *video = video_drvdata(file); + struct v4l2_subdev_format fmt; + struct v4l2_subdev *subdev; + u32 pad; + int ret; + + if (format->type != video->type) + return -EINVAL; + + subdev = iss_video_remote_subdev(video, &pad); + if (subdev == NULL) + return -EINVAL; + + iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format); + + fmt.pad = pad; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); + if (ret) + return ret == -ENOIOCTLCMD ? -EINVAL : ret; + + iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); + return 0; +} + +static int +iss_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap) +{ + struct iss_video *video = video_drvdata(file); + struct v4l2_subdev *subdev; + int ret; + + subdev = iss_video_remote_subdev(video, NULL); + if (subdev == NULL) + return -EINVAL; + + mutex_lock(&video->mutex); + ret = v4l2_subdev_call(subdev, video, cropcap, cropcap); + mutex_unlock(&video->mutex); + + return ret == -ENOIOCTLCMD ? -EINVAL : ret; +} + +static int +iss_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) +{ + struct iss_video *video = video_drvdata(file); + struct v4l2_subdev_format format; + struct v4l2_subdev *subdev; + u32 pad; + int ret; + + subdev = iss_video_remote_subdev(video, &pad); + if (subdev == NULL) + return -EINVAL; + + /* Try the get crop operation first and fallback to get format if not + * implemented. + */ + ret = v4l2_subdev_call(subdev, video, g_crop, crop); + if (ret != -ENOIOCTLCMD) + return ret; + + format.pad = pad; + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format); + if (ret < 0) + return ret == -ENOIOCTLCMD ? -EINVAL : ret; + + crop->c.left = 0; + crop->c.top = 0; + crop->c.width = format.format.width; + crop->c.height = format.format.height; + + return 0; +} + +static int +iss_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop) +{ + struct iss_video *video = video_drvdata(file); + struct v4l2_subdev *subdev; + int ret; + + subdev = iss_video_remote_subdev(video, NULL); + if (subdev == NULL) + return -EINVAL; + + mutex_lock(&video->mutex); + ret = v4l2_subdev_call(subdev, video, s_crop, crop); + mutex_unlock(&video->mutex); + + return ret == -ENOIOCTLCMD ? -EINVAL : ret; +} + +static int +iss_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + struct iss_video *video = video_drvdata(file); + + if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || + video->type != a->type) + return -EINVAL; + + memset(a, 0, sizeof(*a)); + a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + a->parm.output.timeperframe = vfh->timeperframe; + + return 0; +} + +static int +iss_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + struct iss_video *video = video_drvdata(file); + + if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || + video->type != a->type) + return -EINVAL; + + if (a->parm.output.timeperframe.denominator == 0) + a->parm.output.timeperframe.denominator = 1; + + vfh->timeperframe = a->parm.output.timeperframe; + + return 0; +} + +static int +iss_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + + return vb2_reqbufs(&vfh->queue, rb); +} + +static int +iss_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + + return vb2_querybuf(&vfh->queue, b); +} + +static int +iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + + return vb2_qbuf(&vfh->queue, b); +} + +static int +iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + + return vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK); +} + +/* + * Stream management + * + * Every ISS pipeline has a single input and a single output. The input can be + * either a sensor or a video node. The output is always a video node. + * + * As every pipeline has an output video node, the ISS video objects at the + * pipeline output stores the pipeline state. It tracks the streaming state of + * both the input and output, as well as the availability of buffers. + * + * In sensor-to-memory mode, frames are always available at the pipeline input. + * Starting the sensor usually requires I2C transfers and must be done in + * interruptible context. The pipeline is started and stopped synchronously + * to the stream on/off commands. All modules in the pipeline will get their + * subdev set stream handler called. The module at the end of the pipeline must + * delay starting the hardware until buffers are available at its output. + * + * In memory-to-memory mode, starting/stopping the stream requires + * synchronization between the input and output. ISS modules can't be stopped + * in the middle of a frame, and at least some of the modules seem to become + * busy as soon as they're started, even if they don't receive a frame start + * event. For that reason frames need to be processed in single-shot mode. The + * driver needs to wait until a frame is completely processed and written to + * memory before restarting the pipeline for the next frame. Pipelined + * processing might be possible but requires more testing. + * + * Stream start must be delayed until buffers are available at both the input + * and output. The pipeline must be started in the videobuf queue callback with + * the buffers queue spinlock held. The modules subdev set stream operation must + * not sleep. + */ +static int +iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + struct iss_video *video = video_drvdata(file); + enum iss_pipeline_state state; + struct iss_pipeline *pipe; + struct iss_video *far_end; + unsigned long flags; + int ret; + + if (type != video->type) + return -EINVAL; + + mutex_lock(&video->stream_lock); + + if (video->streaming) { + mutex_unlock(&video->stream_lock); + return -EBUSY; + } + + /* Start streaming on the pipeline. No link touching an entity in the + * pipeline can be activated or deactivated once streaming is started. + */ + pipe = video->video.entity.pipe + ? to_iss_pipeline(&video->video.entity) : &video->pipe; + pipe->external = NULL; + pipe->external_rate = 0; + pipe->external_bpp = 0; + + if (video->iss->pdata->set_constraints) + video->iss->pdata->set_constraints(video->iss, true); + + ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); + if (ret < 0) + goto err_media_entity_pipeline_start; + + /* Verify that the currently configured format matches the output of + * the connected subdev. + */ + ret = iss_video_check_format(video, vfh); + if (ret < 0) + goto err_iss_video_check_format; + + video->bpl_padding = ret; + video->bpl_value = vfh->format.fmt.pix.bytesperline; + + /* Find the ISS video node connected at the far end of the pipeline and + * update the pipeline. + */ + far_end = iss_video_far_end(video); + + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + state = ISS_PIPELINE_STREAM_OUTPUT | ISS_PIPELINE_IDLE_OUTPUT; + pipe->input = far_end; + pipe->output = video; + } else { + if (far_end == NULL) { + ret = -EPIPE; + goto err_iss_video_check_format; + } + + state = ISS_PIPELINE_STREAM_INPUT | ISS_PIPELINE_IDLE_INPUT; + pipe->input = video; + pipe->output = far_end; + } + + spin_lock_irqsave(&pipe->lock, flags); + pipe->state &= ~ISS_PIPELINE_STREAM; + pipe->state |= state; + spin_unlock_irqrestore(&pipe->lock, flags); + + /* Set the maximum time per frame as the value requested by userspace. + * This is a soft limit that can be overridden if the hardware doesn't + * support the request limit. + */ + if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + pipe->max_timeperframe = vfh->timeperframe; + + video->queue = &vfh->queue; + INIT_LIST_HEAD(&video->dmaqueue); + spin_lock_init(&video->qlock); + atomic_set(&pipe->frame_number, -1); + + ret = vb2_streamon(&vfh->queue, type); + if (ret < 0) + goto err_iss_video_check_format; + + /* In sensor-to-memory mode, the stream can be started synchronously + * to the stream on command. In memory-to-memory mode, it will be + * started when buffers are queued on both the input and output. + */ + if (pipe->input == NULL) { + unsigned long flags; + ret = omap4iss_pipeline_set_stream(pipe, + ISS_PIPELINE_STREAM_CONTINUOUS); + if (ret < 0) + goto err_omap4iss_set_stream; + spin_lock_irqsave(&video->qlock, flags); + if (list_empty(&video->dmaqueue)) + video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN; + spin_unlock_irqrestore(&video->qlock, flags); + } + + if (ret < 0) { +err_omap4iss_set_stream: + vb2_streamoff(&vfh->queue, type); +err_iss_video_check_format: + media_entity_pipeline_stop(&video->video.entity); +err_media_entity_pipeline_start: + if (video->iss->pdata->set_constraints) + video->iss->pdata->set_constraints(video->iss, false); + video->queue = NULL; + } + + if (!ret) + video->streaming = 1; + + mutex_unlock(&video->stream_lock); + return ret; +} + +static int +iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) +{ + struct iss_video_fh *vfh = to_iss_video_fh(fh); + struct iss_video *video = video_drvdata(file); + struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); + enum iss_pipeline_state state; + unsigned long flags; + + if (type != video->type) + return -EINVAL; + + mutex_lock(&video->stream_lock); + + if (!vb2_is_streaming(&vfh->queue)) + goto done; + + /* Update the pipeline state. */ + if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + state = ISS_PIPELINE_STREAM_OUTPUT + | ISS_PIPELINE_QUEUE_OUTPUT; + else + state = ISS_PIPELINE_STREAM_INPUT + | ISS_PIPELINE_QUEUE_INPUT; + + spin_lock_irqsave(&pipe->lock, flags); + pipe->state &= ~state; + spin_unlock_irqrestore(&pipe->lock, flags); + + /* Stop the stream. */ + omap4iss_pipeline_set_stream(pipe, ISS_PIPELINE_STREAM_STOPPED); + vb2_streamoff(&vfh->queue, type); + video->queue = NULL; + video->streaming = 0; + + if (video->iss->pdata->set_constraints) + video->iss->pdata->set_constraints(video->iss, false); + media_entity_pipeline_stop(&video->video.entity); + +done: + mutex_unlock(&video->stream_lock); + return 0; +} + +static int +iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) +{ + if (input->index > 0) + return -EINVAL; + + strlcpy(input->name, "camera", sizeof(input->name)); + input->type = V4L2_INPUT_TYPE_CAMERA; + + return 0; +} + +static int +iss_video_g_input(struct file *file, void *fh, unsigned int *input) +{ + *input = 0; + + return 0; +} + +static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { + .vidioc_querycap = iss_video_querycap, + .vidioc_g_fmt_vid_cap = iss_video_get_format, + .vidioc_s_fmt_vid_cap = iss_video_set_format, + .vidioc_try_fmt_vid_cap = iss_video_try_format, + .vidioc_g_fmt_vid_out = iss_video_get_format, + .vidioc_s_fmt_vid_out = iss_video_set_format, + .vidioc_try_fmt_vid_out = iss_video_try_format, + .vidioc_cropcap = iss_video_cropcap, + .vidioc_g_crop = iss_video_get_crop, + .vidioc_s_crop = iss_video_set_crop, + .vidioc_g_parm = iss_video_get_param, + .vidioc_s_parm = iss_video_set_param, + .vidioc_reqbufs = iss_video_reqbufs, + .vidioc_querybuf = iss_video_querybuf, + .vidioc_qbuf = iss_video_qbuf, + .vidioc_dqbuf = iss_video_dqbuf, + .vidioc_streamon = iss_video_streamon, + .vidioc_streamoff = iss_video_streamoff, + .vidioc_enum_input = iss_video_enum_input, + .vidioc_g_input = iss_video_g_input, +}; + +/* ----------------------------------------------------------------------------- + * V4L2 file operations + */ + +static int iss_video_open(struct file *file) +{ + struct iss_video *video = video_drvdata(file); + struct iss_video_fh *handle; + struct vb2_queue *q; + int ret = 0; + + handle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (handle == NULL) + return -ENOMEM; + + v4l2_fh_init(&handle->vfh, &video->video); + v4l2_fh_add(&handle->vfh); + + /* If this is the first user, initialise the pipeline. */ + if (omap4iss_get(video->iss) == NULL) { + ret = -EBUSY; + goto done; + } + + ret = omap4iss_pipeline_pm_use(&video->video.entity, 1); + if (ret < 0) { + omap4iss_put(video->iss); + goto done; + } + + video->alloc_ctx = vb2_dma_contig_init_ctx(video->iss->dev); + if (IS_ERR(video->alloc_ctx)) { + ret = PTR_ERR(video->alloc_ctx); + omap4iss_put(video->iss); + goto done; + } + + q = &handle->queue; + + q->type = video->type; + q->io_modes = VB2_MMAP; + q->drv_priv = handle; + q->ops = &iss_video_vb2ops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct iss_buffer); + + ret = vb2_queue_init(q); + if (ret) { + omap4iss_put(video->iss); + goto done; + } + + memset(&handle->format, 0, sizeof(handle->format)); + handle->format.type = video->type; + handle->timeperframe.denominator = 1; + + handle->video = video; + file->private_data = &handle->vfh; + +done: + if (ret < 0) { + v4l2_fh_del(&handle->vfh); + kfree(handle); + } + + return ret; +} + +static int iss_video_release(struct file *file) +{ + struct iss_video *video = video_drvdata(file); + struct v4l2_fh *vfh = file->private_data; + struct iss_video_fh *handle = to_iss_video_fh(vfh); + + /* Disable streaming and free the buffers queue resources. */ + iss_video_streamoff(file, vfh, video->type); + + omap4iss_pipeline_pm_use(&video->video.entity, 0); + + /* Release the videobuf2 queue */ + vb2_queue_release(&handle->queue); + + /* Release the file handle. */ + v4l2_fh_del(vfh); + kfree(handle); + file->private_data = NULL; + + omap4iss_put(video->iss); + + return 0; +} + +static unsigned int iss_video_poll(struct file *file, poll_table *wait) +{ + struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); + + return vb2_poll(&vfh->queue, file, wait); +} + +static int iss_video_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); + + return vb2_mmap(&vfh->queue, vma);; +} + +static struct v4l2_file_operations iss_video_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .open = iss_video_open, + .release = iss_video_release, + .poll = iss_video_poll, + .mmap = iss_video_mmap, +}; + +/* ----------------------------------------------------------------------------- + * ISS video core + */ + +static const struct iss_video_operations iss_video_dummy_ops = { +}; + +int omap4iss_video_init(struct iss_video *video, const char *name) +{ + const char *direction; + int ret; + + switch (video->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + direction = "output"; + video->pad.flags = MEDIA_PAD_FL_SINK; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + direction = "input"; + video->pad.flags = MEDIA_PAD_FL_SOURCE; + break; + + default: + return -EINVAL; + } + + ret = media_entity_init(&video->video.entity, 1, &video->pad, 0); + if (ret < 0) + return ret; + + mutex_init(&video->mutex); + atomic_set(&video->active, 0); + + spin_lock_init(&video->pipe.lock); + mutex_init(&video->stream_lock); + + /* Initialize the video device. */ + if (video->ops == NULL) + video->ops = &iss_video_dummy_ops; + + video->video.fops = &iss_video_fops; + snprintf(video->video.name, sizeof(video->video.name), + "OMAP4 ISS %s %s", name, direction); + video->video.vfl_type = VFL_TYPE_GRABBER; + video->video.release = video_device_release_empty; + video->video.ioctl_ops = &iss_video_ioctl_ops; + video->pipe.stream_state = ISS_PIPELINE_STREAM_STOPPED; + + video_set_drvdata(&video->video, video); + + return 0; +} + +void omap4iss_video_cleanup(struct iss_video *video) +{ + media_entity_cleanup(&video->video.entity); + mutex_destroy(&video->stream_lock); + mutex_destroy(&video->mutex); +} + +int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev) +{ + int ret; + + video->video.v4l2_dev = vdev; + + ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1); + if (ret < 0) + printk(KERN_ERR "%s: could not register video device (%d)\n", + __func__, ret); + + return ret; +} + +void omap4iss_video_unregister(struct iss_video *video) +{ + if (video_is_registered(&video->video)) + video_unregister_device(&video->video); +} diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h new file mode 100644 index 000000000000..8cf1b3500e44 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -0,0 +1,201 @@ +/* + * TI OMAP4 ISS V4L2 Driver - Generic video node + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 OMAP4_ISS_VIDEO_H +#define OMAP4_ISS_VIDEO_H + +#include +#include +#include +#include +#include +#include + +#define ISS_VIDEO_DRIVER_NAME "issvideo" +#define ISS_VIDEO_DRIVER_VERSION "0.0.2" + +struct iss_device; +struct iss_video; +struct v4l2_mbus_framefmt; +struct v4l2_pix_format; + +/* + * struct iss_format_info - ISS media bus format information + * @code: V4L2 media bus format code + * @truncated: V4L2 media bus format code for the same format truncated to 10 + * bits. Identical to @code if the format is 10 bits wide or less. + * @uncompressed: V4L2 media bus format code for the corresponding uncompressed + * format. Identical to @code if the format is not DPCM compressed. + * @flavor: V4L2 media bus format code for the same pixel layout but + * shifted to be 8 bits per pixel. =0 if format is not shiftable. + * @pixelformat: V4L2 pixel format FCC identifier + * @bpp: Bits per pixel + */ +struct iss_format_info { + enum v4l2_mbus_pixelcode code; + enum v4l2_mbus_pixelcode truncated; + enum v4l2_mbus_pixelcode uncompressed; + enum v4l2_mbus_pixelcode flavor; + u32 pixelformat; + unsigned int bpp; +}; + +enum iss_pipeline_stream_state { + ISS_PIPELINE_STREAM_STOPPED = 0, + ISS_PIPELINE_STREAM_CONTINUOUS = 1, + ISS_PIPELINE_STREAM_SINGLESHOT = 2, +}; + +enum iss_pipeline_state { + /* The stream has been started on the input video node. */ + ISS_PIPELINE_STREAM_INPUT = 1, + /* The stream has been started on the output video node. */ + ISS_PIPELINE_STREAM_OUTPUT = (1 << 1), + /* At least one buffer is queued on the input video node. */ + ISS_PIPELINE_QUEUE_INPUT = (1 << 2), + /* At least one buffer is queued on the output video node. */ + ISS_PIPELINE_QUEUE_OUTPUT = (1 << 3), + /* The input entity is idle, ready to be started. */ + ISS_PIPELINE_IDLE_INPUT = (1 << 4), + /* The output entity is idle, ready to be started. */ + ISS_PIPELINE_IDLE_OUTPUT = (1 << 5), + /* The pipeline is currently streaming. */ + ISS_PIPELINE_STREAM = (1 << 6), +}; + +/* + * struct iss_pipeline - An OMAP4 ISS hardware pipeline + * @error: A hardware error occurred during capture + */ +struct iss_pipeline { + struct media_pipeline pipe; + spinlock_t lock; /* Pipeline state and queue flags */ + unsigned int state; + enum iss_pipeline_stream_state stream_state; + struct iss_video *input; + struct iss_video *output; + atomic_t frame_number; + bool do_propagation; /* of frame number */ + bool error; + struct v4l2_fract max_timeperframe; + struct v4l2_subdev *external; + unsigned int external_rate; + int external_bpp; +}; + +#define to_iss_pipeline(__e) \ + container_of((__e)->pipe, struct iss_pipeline, pipe) + +static inline int iss_pipeline_ready(struct iss_pipeline *pipe) +{ + return pipe->state == (ISS_PIPELINE_STREAM_INPUT | + ISS_PIPELINE_STREAM_OUTPUT | + ISS_PIPELINE_QUEUE_INPUT | + ISS_PIPELINE_QUEUE_OUTPUT | + ISS_PIPELINE_IDLE_INPUT | + ISS_PIPELINE_IDLE_OUTPUT); +} + +/* + * struct iss_buffer - ISS buffer + * @buffer: ISS video buffer + * @iss_addr: Physical address of the buffer. + */ +struct iss_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_buffer vb; + struct list_head list; + dma_addr_t iss_addr; +}; + +#define to_iss_buffer(buf) container_of(buf, struct iss_buffer, buffer) + +enum iss_video_dmaqueue_flags { + /* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */ + ISS_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0), + /* Set when queuing buffer to an empty DMA queue */ + ISS_VIDEO_DMAQUEUE_QUEUED = (1 << 1), +}; + +#define iss_video_dmaqueue_flags_clr(video) \ + ({ (video)->dmaqueue_flags = 0; }) + +/* + * struct iss_video_operations - ISS video operations + * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF + * if there was no buffer previously queued. + */ +struct iss_video_operations { + int(*queue)(struct iss_video *video, struct iss_buffer *buffer); +}; + +struct iss_video { + struct video_device video; + enum v4l2_buf_type type; + struct media_pad pad; + + struct mutex mutex; /* format and crop settings */ + atomic_t active; + + struct iss_device *iss; + + unsigned int capture_mem; + unsigned int bpl_alignment; /* alignment value */ + unsigned int bpl_zero_padding; /* whether the alignment is optional */ + unsigned int bpl_max; /* maximum bytes per line value */ + unsigned int bpl_value; /* bytes per line value */ + unsigned int bpl_padding; /* padding at end of line */ + + /* Entity video node streaming */ + unsigned int streaming:1; + + /* Pipeline state */ + struct iss_pipeline pipe; + struct mutex stream_lock; /* pipeline and stream states */ + + /* Video buffers queue */ + struct vb2_queue *queue; + spinlock_t qlock; /* Spinlock for dmaqueue */ + struct list_head dmaqueue; + enum iss_video_dmaqueue_flags dmaqueue_flags; + struct vb2_alloc_ctx *alloc_ctx; + + const struct iss_video_operations *ops; +}; + +#define to_iss_video(vdev) container_of(vdev, struct iss_video, video) + +struct iss_video_fh { + struct v4l2_fh vfh; + struct iss_video *video; + struct vb2_queue queue; + struct v4l2_format format; + struct v4l2_fract timeperframe; +}; + +#define to_iss_video_fh(fh) container_of(fh, struct iss_video_fh, vfh) +#define iss_video_queue_to_iss_video_fh(q) \ + container_of(q, struct iss_video_fh, queue) + +int omap4iss_video_init(struct iss_video *video, const char *name); +void omap4iss_video_cleanup(struct iss_video *video); +int omap4iss_video_register(struct iss_video *video, + struct v4l2_device *vdev); +void omap4iss_video_unregister(struct iss_video *video); +struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video); +struct media_pad *omap4iss_video_remote_pad(struct iss_video *video); + +const struct iss_format_info * +omap4iss_video_format_info(enum v4l2_mbus_pixelcode code); + +#endif /* OMAP4_ISS_VIDEO_H */ -- cgit v1.2.3 From b4a0477c0b87c5b7a20a84df8cf81311d1efb226 Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Mon, 24 Jan 2011 15:48:19 -0300 Subject: [media] v4l: omap4iss: Add support for OMAP4 camera interface - CSI receivers This adds a very simplistic driver to utilize the CSI2A interface inside the ISS subsystem in OMAP4, and dump the data to memory. Check Documentation/video4linux/omap4_camera.txt for details. This commit adds CSI receivers support. Signed-off-by: Sergio Aguirre Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csi2.c | 1368 +++++++++++++++++++++++++++ drivers/staging/media/omap4iss/iss_csi2.h | 156 +++ drivers/staging/media/omap4iss/iss_csiphy.c | 278 ++++++ drivers/staging/media/omap4iss/iss_csiphy.h | 51 + 4 files changed, 1853 insertions(+) create mode 100644 drivers/staging/media/omap4iss/iss_csi2.c create mode 100644 drivers/staging/media/omap4iss/iss_csi2.h create mode 100644 drivers/staging/media/omap4iss/iss_csiphy.c create mode 100644 drivers/staging/media/omap4iss/iss_csiphy.h (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c new file mode 100644 index 000000000000..0ee8381c738d --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -0,0 +1,1368 @@ +/* + * TI OMAP4 ISS V4L2 Driver - CSI PHY module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 "iss.h" +#include "iss_regs.h" +#include "iss_csi2.h" + +/* + * csi2_if_enable - Enable CSI2 Receiver interface. + * @enable: enable flag + * + */ +static void csi2_if_enable(struct iss_csi2_device *csi2, u8 enable) +{ + struct iss_csi2_ctrl_cfg *currctrl = &csi2->ctrl; + + writel((readl(csi2->regs1 + CSI2_CTRL) & ~CSI2_CTRL_IF_EN) | + (enable ? CSI2_CTRL_IF_EN : 0), + csi2->regs1 + CSI2_CTRL); + + currctrl->if_enable = enable; +} + +/* + * csi2_recv_config - CSI2 receiver module configuration. + * @currctrl: iss_csi2_ctrl_cfg structure + * + */ +static void csi2_recv_config(struct iss_csi2_device *csi2, + struct iss_csi2_ctrl_cfg *currctrl) +{ + u32 reg = 0; + + if (currctrl->frame_mode) + reg |= CSI2_CTRL_FRAME; + else + reg &= ~CSI2_CTRL_FRAME; + + if (currctrl->vp_clk_enable) + reg |= CSI2_CTRL_VP_CLK_EN; + else + reg &= ~CSI2_CTRL_VP_CLK_EN; + + if (currctrl->vp_only_enable) + reg |= CSI2_CTRL_VP_ONLY_EN; + else + reg &= ~CSI2_CTRL_VP_ONLY_EN; + + reg &= ~CSI2_CTRL_VP_OUT_CTRL_MASK; + reg |= currctrl->vp_out_ctrl << CSI2_CTRL_VP_OUT_CTRL_SHIFT; + + if (currctrl->ecc_enable) + reg |= CSI2_CTRL_ECC_EN; + else + reg &= ~CSI2_CTRL_ECC_EN; + + /* + * Set MFlag assertion boundaries to: + * Low: 4/8 of FIFO size + * High: 6/8 of FIFO size + */ + reg &= ~(CSI2_CTRL_MFLAG_LEVH_MASK | CSI2_CTRL_MFLAG_LEVL_MASK); + reg |= (2 << CSI2_CTRL_MFLAG_LEVH_SHIFT) | + (4 << CSI2_CTRL_MFLAG_LEVL_SHIFT); + + /* Generation of 16x64-bit bursts (Recommended) */ + reg |= CSI2_CTRL_BURST_SIZE_EXPAND; + + /* Do Non-Posted writes (Recommended) */ + reg |= CSI2_CTRL_NON_POSTED_WRITE; + + /* + * Enforce Little endian for all formats, including: + * YUV4:2:2 8-bit and YUV4:2:0 Legacy + */ + reg |= CSI2_CTRL_ENDIANNESS; + + writel(reg, csi2->regs1 + CSI2_CTRL); +} + +static const unsigned int csi2_input_fmts[] = { + V4L2_MBUS_FMT_SGRBG10_1X10, + V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, + V4L2_MBUS_FMT_SRGGB10_1X10, + V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, + V4L2_MBUS_FMT_SBGGR10_1X10, + V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, + V4L2_MBUS_FMT_SGBRG10_1X10, + V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, + V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_MBUS_FMT_UYVY8_1X16, + V4L2_MBUS_FMT_YUYV8_1X16, +}; + +/* To set the format on the CSI2 requires a mapping function that takes + * the following inputs: + * - 3 different formats (at this time) + * - 2 destinations (mem, vp+mem) (vp only handled separately) + * - 2 decompression options (on, off) + * Output should be CSI2 frame format code + * Array indices as follows: [format][dest][decompr] + * Not all combinations are valid. 0 means invalid. + */ +static const u16 __csi2_fmt_map[][2][2] = { + /* RAW10 formats */ + { + /* Output to memory */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_RAW10_EXP16, + /* DPCM decompression */ + 0, + }, + /* Output to both */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_RAW10_EXP16_VP, + /* DPCM decompression */ + 0, + }, + }, + /* RAW10 DPCM8 formats */ + { + /* Output to memory */ + { + /* No DPCM decompression */ + CSI2_USERDEF_8BIT_DATA1, + /* DPCM decompression */ + CSI2_USERDEF_8BIT_DATA1_DPCM10, + }, + /* Output to both */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_RAW8_VP, + /* DPCM decompression */ + CSI2_USERDEF_8BIT_DATA1_DPCM10_VP, + }, + }, + /* RAW8 formats */ + { + /* Output to memory */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_RAW8, + /* DPCM decompression */ + 0, + }, + /* Output to both */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_RAW8_VP, + /* DPCM decompression */ + 0, + }, + }, + /* YUV422 formats */ + { + /* Output to memory */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_YUV422_8BIT, + /* DPCM decompression */ + 0, + }, + /* Output to both */ + { + /* No DPCM decompression */ + CSI2_PIX_FMT_YUV422_8BIT_VP16, + /* DPCM decompression */ + 0, + }, + }, +}; + +/* + * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID + * @csi2: ISS CSI2 device + * + * Returns CSI2 physical format id + */ +static u16 csi2_ctx_map_format(struct iss_csi2_device *csi2) +{ + const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK]; + int fmtidx, destidx; + + switch (fmt->code) { + case V4L2_MBUS_FMT_SGRBG10_1X10: + case V4L2_MBUS_FMT_SRGGB10_1X10: + case V4L2_MBUS_FMT_SBGGR10_1X10: + case V4L2_MBUS_FMT_SGBRG10_1X10: + fmtidx = 0; + break; + case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8: + case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8: + case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8: + case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8: + fmtidx = 1; + break; + case V4L2_MBUS_FMT_SBGGR8_1X8: + case V4L2_MBUS_FMT_SGBRG8_1X8: + case V4L2_MBUS_FMT_SGRBG8_1X8: + case V4L2_MBUS_FMT_SRGGB8_1X8: + fmtidx = 2; + break; + case V4L2_MBUS_FMT_UYVY8_1X16: + case V4L2_MBUS_FMT_YUYV8_1X16: + fmtidx = 3; + break; + default: + WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n", + fmt->code); + return 0; + } + + if (!(csi2->output & CSI2_OUTPUT_IPIPEIF) && + !(csi2->output & CSI2_OUTPUT_MEMORY)) { + /* Neither output enabled is a valid combination */ + return CSI2_PIX_FMT_OTHERS; + } + + /* If we need to skip frames at the beginning of the stream disable the + * video port to avoid sending the skipped frames to the IPIPEIF. + */ + destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_IPIPEIF); + + return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress]; +} + +/* + * csi2_set_outaddr - Set memory address to save output image + * @csi2: Pointer to ISS CSI2a device. + * @addr: 32-bit memory address aligned on 32 byte boundary. + * + * Sets the memory address where the output will be saved. + * + * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte + * boundary. + */ +static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr) +{ + struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[0]; + + ctx->ping_addr = addr; + ctx->pong_addr = addr; + writel(ctx->ping_addr, + csi2->regs1 + CSI2_CTX_PING_ADDR(ctx->ctxnum)); + writel(ctx->pong_addr, + csi2->regs1 + CSI2_CTX_PONG_ADDR(ctx->ctxnum)); +} + +/* + * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should + * be enabled by CSI2. + * @format_id: mapped format id + * + */ +static inline int is_usr_def_mapping(u32 format_id) +{ + return ((format_id & 0xF0) == 0x40) ? 1 : 0; +} + +/* + * csi2_ctx_enable - Enable specified CSI2 context + * @ctxnum: Context number, valid between 0 and 7 values. + * @enable: enable + * + */ +static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable) +{ + struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum]; + u32 reg; + + reg = readl(csi2->regs1 + CSI2_CTX_CTRL1(ctxnum)); + + if (enable) { + unsigned int skip = 0; + + if (csi2->frame_skip) + skip = csi2->frame_skip; + else if (csi2->output & CSI2_OUTPUT_MEMORY) + skip = 1; + + reg &= ~CSI2_CTX_CTRL1_COUNT_MASK; + reg |= CSI2_CTX_CTRL1_COUNT_UNLOCK + | (skip << CSI2_CTX_CTRL1_COUNT_SHIFT) + | CSI2_CTX_CTRL1_CTX_EN; + } else { + reg &= ~CSI2_CTX_CTRL1_CTX_EN; + } + + writel(reg, csi2->regs1 + CSI2_CTX_CTRL1(ctxnum)); + ctx->enabled = enable; +} + +/* + * csi2_ctx_config - CSI2 context configuration. + * @ctx: context configuration + * + */ +static void csi2_ctx_config(struct iss_csi2_device *csi2, + struct iss_csi2_ctx_cfg *ctx) +{ + u32 reg; + + /* Set up CSI2_CTx_CTRL1 */ + if (ctx->eof_enabled) + reg = CSI2_CTX_CTRL1_EOF_EN; + + if (ctx->eol_enabled) + reg |= CSI2_CTX_CTRL1_EOL_EN; + + if (ctx->checksum_enabled) + reg |= CSI2_CTX_CTRL1_CS_EN; + + writel(reg, csi2->regs1 + CSI2_CTX_CTRL1(ctx->ctxnum)); + + /* Set up CSI2_CTx_CTRL2 */ + reg = ctx->virtual_id << CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT; + reg |= ctx->format_id << CSI2_CTX_CTRL2_FORMAT_SHIFT; + + if (ctx->dpcm_decompress && ctx->dpcm_predictor) + reg |= CSI2_CTX_CTRL2_DPCM_PRED; + + if (is_usr_def_mapping(ctx->format_id)) + reg |= 2 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT; + + writel(reg, csi2->regs1 + CSI2_CTX_CTRL2(ctx->ctxnum)); + + /* Set up CSI2_CTx_CTRL3 */ + writel(ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT, + csi2->regs1 + CSI2_CTX_CTRL3(ctx->ctxnum)); + + /* Set up CSI2_CTx_DAT_OFST */ + reg = readl(csi2->regs1 + CSI2_CTX_DAT_OFST(ctx->ctxnum)); + reg &= ~CSI2_CTX_DAT_OFST_MASK; + reg |= ctx->data_offset; + writel(reg, csi2->regs1 + CSI2_CTX_DAT_OFST(ctx->ctxnum)); + + writel(ctx->ping_addr, + csi2->regs1 + CSI2_CTX_PING_ADDR(ctx->ctxnum)); + + writel(ctx->pong_addr, + csi2->regs1 + CSI2_CTX_PONG_ADDR(ctx->ctxnum)); +} + +/* + * csi2_timing_config - CSI2 timing configuration. + * @timing: csi2_timing_cfg structure + */ +static void csi2_timing_config(struct iss_csi2_device *csi2, + struct iss_csi2_timing_cfg *timing) +{ + u32 reg; + + reg = readl(csi2->regs1 + CSI2_TIMING); + + if (timing->force_rx_mode) + reg |= CSI2_TIMING_FORCE_RX_MODE_IO1; + else + reg &= ~CSI2_TIMING_FORCE_RX_MODE_IO1; + + if (timing->stop_state_16x) + reg |= CSI2_TIMING_STOP_STATE_X16_IO1; + else + reg &= ~CSI2_TIMING_STOP_STATE_X16_IO1; + + if (timing->stop_state_4x) + reg |= CSI2_TIMING_STOP_STATE_X4_IO1; + else + reg &= ~CSI2_TIMING_STOP_STATE_X4_IO1; + + reg &= ~CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK; + reg |= timing->stop_state_counter << + CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT; + + writel(reg, csi2->regs1 + CSI2_TIMING); +} + +/* + * csi2_irq_ctx_set - Enables CSI2 Context IRQs. + * @enable: Enable/disable CSI2 Context interrupts + */ +static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) +{ + u32 reg = CSI2_CTX_IRQ_FE; + int i; + + if (csi2->use_fs_irq) + reg |= CSI2_CTX_IRQ_FS; + + for (i = 0; i < 8; i++) { + writel(reg, csi2->regs1 + CSI2_CTX_IRQSTATUS(i)); + if (enable) + writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) | reg, + csi2->regs1 + CSI2_CTX_IRQENABLE(i)); + else + writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) & + ~reg, + csi2->regs1 + CSI2_CTX_IRQENABLE(i)); + } +} + +/* + * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs. + * @enable: Enable/disable CSI2 ComplexIO #1 interrupts + */ +static void csi2_irq_complexio1_set(struct iss_csi2_device *csi2, int enable) +{ + u32 reg; + reg = CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT | + CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER | + CSI2_COMPLEXIO_IRQ_STATEULPM5 | + CSI2_COMPLEXIO_IRQ_ERRCONTROL5 | + CSI2_COMPLEXIO_IRQ_ERRESC5 | + CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 | + CSI2_COMPLEXIO_IRQ_ERRSOTHS5 | + CSI2_COMPLEXIO_IRQ_STATEULPM4 | + CSI2_COMPLEXIO_IRQ_ERRCONTROL4 | + CSI2_COMPLEXIO_IRQ_ERRESC4 | + CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 | + CSI2_COMPLEXIO_IRQ_ERRSOTHS4 | + CSI2_COMPLEXIO_IRQ_STATEULPM3 | + CSI2_COMPLEXIO_IRQ_ERRCONTROL3 | + CSI2_COMPLEXIO_IRQ_ERRESC3 | + CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 | + CSI2_COMPLEXIO_IRQ_ERRSOTHS3 | + CSI2_COMPLEXIO_IRQ_STATEULPM2 | + CSI2_COMPLEXIO_IRQ_ERRCONTROL2 | + CSI2_COMPLEXIO_IRQ_ERRESC2 | + CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 | + CSI2_COMPLEXIO_IRQ_ERRSOTHS2 | + CSI2_COMPLEXIO_IRQ_STATEULPM1 | + CSI2_COMPLEXIO_IRQ_ERRCONTROL1 | + CSI2_COMPLEXIO_IRQ_ERRESC1 | + CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 | + CSI2_COMPLEXIO_IRQ_ERRSOTHS1; + writel(reg, csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS); + if (enable) + reg |= readl(csi2->regs1 + CSI2_COMPLEXIO_IRQENABLE); + else + reg = 0; + writel(reg, csi2->regs1 + CSI2_COMPLEXIO_IRQENABLE); +} + +/* + * csi2_irq_status_set - Enables CSI2 Status IRQs. + * @enable: Enable/disable CSI2 Status interrupts + */ +static void csi2_irq_status_set(struct iss_csi2_device *csi2, int enable) +{ + u32 reg; + reg = CSI2_IRQ_OCP_ERR | + CSI2_IRQ_SHORT_PACKET | + CSI2_IRQ_ECC_CORRECTION | + CSI2_IRQ_ECC_NO_CORRECTION | + CSI2_IRQ_COMPLEXIO_ERR | + CSI2_IRQ_FIFO_OVF | + CSI2_IRQ_CONTEXT0; + writel(reg, csi2->regs1 + CSI2_IRQSTATUS); + if (enable) + reg |= readl(csi2->regs1 + CSI2_IRQENABLE); + else + reg = 0; + + writel(reg, csi2->regs1 + CSI2_IRQENABLE); +} + +/* + * omap4iss_csi2_reset - Resets the CSI2 module. + * + * Must be called with the phy lock held. + * + * Returns 0 if successful, or -EBUSY if power command didn't respond. + */ +int omap4iss_csi2_reset(struct iss_csi2_device *csi2) +{ + u8 soft_reset_retries = 0; + u32 reg; + int i; + + if (!csi2->available) + return -ENODEV; + + if (csi2->phy->phy_in_use) + return -EBUSY; + + writel(readl(csi2->regs1 + CSI2_SYSCONFIG) | + CSI2_SYSCONFIG_SOFT_RESET, + csi2->regs1 + CSI2_SYSCONFIG); + + do { + reg = readl(csi2->regs1 + CSI2_SYSSTATUS) & + CSI2_SYSSTATUS_RESET_DONE; + if (reg == CSI2_SYSSTATUS_RESET_DONE) + break; + soft_reset_retries++; + if (soft_reset_retries < 5) + usleep_range(100, 100); + } while (soft_reset_retries < 5); + + if (soft_reset_retries == 5) { + printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n"); + return -EBUSY; + } + + writel(readl(csi2->regs1 + CSI2_COMPLEXIO_CFG) | + CSI2_COMPLEXIO_CFG_RESET_CTRL, + csi2->regs1 + CSI2_COMPLEXIO_CFG); + + i = 100; + do { + reg = readl(csi2->phy->phy_regs + REGISTER1) + & REGISTER1_RESET_DONE_CTRLCLK; + if (reg == REGISTER1_RESET_DONE_CTRLCLK) + break; + usleep_range(100, 100); + } while (--i > 0); + + if (i == 0) { + printk(KERN_ERR + "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n"); + return -EBUSY; + } + + writel((readl(csi2->regs1 + CSI2_SYSCONFIG) & + ~(CSI2_SYSCONFIG_MSTANDBY_MODE_MASK | + CSI2_SYSCONFIG_AUTO_IDLE)) | + CSI2_SYSCONFIG_MSTANDBY_MODE_NO, + csi2->regs1 + CSI2_SYSCONFIG); + + return 0; +} + +static int csi2_configure(struct iss_csi2_device *csi2) +{ + const struct iss_v4l2_subdevs_group *pdata; + struct iss_csi2_timing_cfg *timing = &csi2->timing[0]; + struct v4l2_subdev *sensor; + struct media_pad *pad; + + /* + * CSI2 fields that can be updated while the context has + * been enabled or the interface has been enabled are not + * updated dynamically currently. So we do not allow to + * reconfigure if either has been enabled + */ + if (csi2->contexts[0].enabled || csi2->ctrl.if_enable) + return -EBUSY; + + pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]); + sensor = media_entity_to_v4l2_subdev(pad->entity); + pdata = sensor->host_priv; + + csi2->frame_skip = 0; + v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip); + + csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div; + csi2->ctrl.frame_mode = ISS_CSI2_FRAME_IMMEDIATE; + csi2->ctrl.ecc_enable = pdata->bus.csi2.crc; + + timing->force_rx_mode = 1; + timing->stop_state_16x = 1; + timing->stop_state_4x = 1; + timing->stop_state_counter = 0x1FF; + + /* + * The CSI2 receiver can't do any format conversion except DPCM + * decompression, so every set_format call configures both pads + * and enables DPCM decompression as a special case: + */ + if (csi2->formats[CSI2_PAD_SINK].code != + csi2->formats[CSI2_PAD_SOURCE].code) + csi2->dpcm_decompress = true; + else + csi2->dpcm_decompress = false; + + csi2->contexts[0].format_id = csi2_ctx_map_format(csi2); + + if (csi2->video_out.bpl_padding == 0) + csi2->contexts[0].data_offset = 0; + else + csi2->contexts[0].data_offset = csi2->video_out.bpl_value; + + /* + * Enable end of frame and end of line signals generation for + * context 0. These signals are generated from CSI2 receiver to + * qualify the last pixel of a frame and the last pixel of a line. + * Without enabling the signals CSI2 receiver writes data to memory + * beyond buffer size and/or data line offset is not handled correctly. + */ + csi2->contexts[0].eof_enabled = 1; + csi2->contexts[0].eol_enabled = 1; + + csi2_irq_complexio1_set(csi2, 1); + csi2_irq_ctx_set(csi2, 1); + csi2_irq_status_set(csi2, 1); + + /* Set configuration (timings, format and links) */ + csi2_timing_config(csi2, timing); + csi2_recv_config(csi2, &csi2->ctrl); + csi2_ctx_config(csi2, &csi2->contexts[0]); + + return 0; +} + +/* + * csi2_print_status - Prints CSI2 debug information. + */ +#define CSI2_PRINT_REGISTER(iss, regs, name)\ + dev_dbg(iss->dev, "###CSI2 " #name "=0x%08x\n", \ + readl(regs + CSI2_##name)) + +static void csi2_print_status(struct iss_csi2_device *csi2) +{ + struct iss_device *iss = csi2->iss; + + if (!csi2->available) + return; + + dev_dbg(iss->dev, "-------------CSI2 Register dump-------------\n"); + + CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSCONFIG); + CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSSTATUS); + CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQENABLE); + CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQSTATUS); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTRL); + CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_H); + CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_CFG); + CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQSTATUS); + CSI2_PRINT_REGISTER(iss, csi2->regs1, SHORT_PACKET); + CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQENABLE); + CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_P); + CSI2_PRINT_REGISTER(iss, csi2->regs1, TIMING); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL1(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL2(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_DAT_OFST(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PING_ADDR(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PONG_ADDR(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQENABLE(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQSTATUS(0)); + CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL3(0)); + + dev_dbg(iss->dev, "--------------------------------------------\n"); +} + +/* ----------------------------------------------------------------------------- + * Interrupt handling + */ + +/* + * csi2_isr_buffer - Does buffer handling at end-of-frame + * when writing to memory. + */ +static void csi2_isr_buffer(struct iss_csi2_device *csi2) +{ + struct iss_buffer *buffer; + + csi2_ctx_enable(csi2, 0, 0); + + buffer = omap4iss_video_buffer_next(&csi2->video_out); + + /* + * Let video queue operation restart engine if there is an underrun + * condition. + */ + if (buffer == NULL) + return; + + csi2_set_outaddr(csi2, buffer->iss_addr); + csi2_ctx_enable(csi2, 0, 1); +} + +static void csi2_isr_ctx(struct iss_csi2_device *csi2, + struct iss_csi2_ctx_cfg *ctx) +{ + unsigned int n = ctx->ctxnum; + u32 status; + + status = readl(csi2->regs1 + CSI2_CTX_IRQSTATUS(n)); + writel(status, csi2->regs1 + CSI2_CTX_IRQSTATUS(n)); + + /* Propagate frame number */ + if (status & CSI2_CTX_IRQ_FS) { + struct iss_pipeline *pipe = + to_iss_pipeline(&csi2->subdev.entity); + if (pipe->do_propagation) + atomic_inc(&pipe->frame_number); + } + + if (!(status & CSI2_CTX_IRQ_FE)) + return; + + /* Skip interrupts until we reach the frame skip count. The CSI2 will be + * automatically disabled, as the frame skip count has been programmed + * in the CSI2_CTx_CTRL1::COUNT field, so reenable it. + * + * It would have been nice to rely on the FRAME_NUMBER interrupt instead + * but it turned out that the interrupt is only generated when the CSI2 + * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased + * correctly and reaches 0 when data is forwarded to the video port only + * but no interrupt arrives). Maybe a CSI2 hardware bug. + */ + if (csi2->frame_skip) { + csi2->frame_skip--; + if (csi2->frame_skip == 0) { + ctx->format_id = csi2_ctx_map_format(csi2); + csi2_ctx_config(csi2, ctx); + csi2_ctx_enable(csi2, n, 1); + } + return; + } + + if (csi2->output & CSI2_OUTPUT_MEMORY) + csi2_isr_buffer(csi2); +} + +/* + * omap4iss_csi2_isr - CSI2 interrupt handling. + */ +void omap4iss_csi2_isr(struct iss_csi2_device *csi2) +{ + struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); + u32 csi2_irqstatus, cpxio1_irqstatus; + struct iss_device *iss = csi2->iss; + + if (!csi2->available) + return; + + csi2_irqstatus = readl(csi2->regs1 + CSI2_IRQSTATUS); + writel(csi2_irqstatus, csi2->regs1 + CSI2_IRQSTATUS); + + /* Failure Cases */ + if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) { + cpxio1_irqstatus = readl(csi2->regs1 + + CSI2_COMPLEXIO_IRQSTATUS); + writel(cpxio1_irqstatus, + csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS); + dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ " + "%x\n", cpxio1_irqstatus); + pipe->error = true; + } + + if (csi2_irqstatus & (CSI2_IRQ_OCP_ERR | + CSI2_IRQ_SHORT_PACKET | + CSI2_IRQ_ECC_NO_CORRECTION | + CSI2_IRQ_COMPLEXIO_ERR | + CSI2_IRQ_FIFO_OVF)) { + dev_dbg(iss->dev, "CSI2 Err:" + " OCP:%d," + " Short_pack:%d," + " ECC:%d," + " CPXIO:%d," + " FIFO_OVF:%d," + "\n", + (csi2_irqstatus & + CSI2_IRQ_OCP_ERR) ? 1 : 0, + (csi2_irqstatus & + CSI2_IRQ_SHORT_PACKET) ? 1 : 0, + (csi2_irqstatus & + CSI2_IRQ_ECC_NO_CORRECTION) ? 1 : 0, + (csi2_irqstatus & + CSI2_IRQ_COMPLEXIO_ERR) ? 1 : 0, + (csi2_irqstatus & + CSI2_IRQ_FIFO_OVF) ? 1 : 0); + pipe->error = true; + } + + if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping)) + return; + + /* Successful cases */ + if (csi2_irqstatus & CSI2_IRQ_CONTEXT0) + csi2_isr_ctx(csi2, &csi2->contexts[0]); + + if (csi2_irqstatus & CSI2_IRQ_ECC_CORRECTION) + dev_dbg(iss->dev, "CSI2: ECC correction done\n"); +} + +/* ----------------------------------------------------------------------------- + * ISS video operations + */ + +/* + * csi2_queue - Queues the first buffer when using memory output + * @video: The video node + * @buffer: buffer to queue + */ +static int csi2_queue(struct iss_video *video, struct iss_buffer *buffer) +{ + struct iss_csi2_device *csi2 = container_of(video, + struct iss_csi2_device, video_out); + + csi2_set_outaddr(csi2, buffer->iss_addr); + + /* + * If streaming was enabled before there was a buffer queued + * or underrun happened in the ISR, the hardware was not enabled + * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. + * Enable it now. + */ + if (csi2->video_out.dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { + /* Enable / disable context 0 and IRQs */ + csi2_if_enable(csi2, 1); + csi2_ctx_enable(csi2, 0, 1); + iss_video_dmaqueue_flags_clr(&csi2->video_out); + } + + return 0; +} + +static const struct iss_video_operations csi2_issvideo_ops = { + .queue = csi2_queue, +}; + +/* ----------------------------------------------------------------------------- + * V4L2 subdev operations + */ + +static struct v4l2_mbus_framefmt * +__csi2_get_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(fh, pad); + else + return &csi2->formats[pad]; +} + +static void +csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh, + unsigned int pad, struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) +{ + enum v4l2_mbus_pixelcode pixelcode; + struct v4l2_mbus_framefmt *format; + const struct iss_format_info *info; + unsigned int i; + + switch (pad) { + case CSI2_PAD_SINK: + /* Clamp the width and height to valid range (1-8191). */ + for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) { + if (fmt->code == csi2_input_fmts[i]) + break; + } + + /* If not found, use SGRBG10 as default */ + if (i >= ARRAY_SIZE(csi2_input_fmts)) + fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10; + + fmt->width = clamp_t(u32, fmt->width, 1, 8191); + fmt->height = clamp_t(u32, fmt->height, 1, 8191); + break; + + case CSI2_PAD_SOURCE: + /* Source format same as sink format, except for DPCM + * compression. + */ + pixelcode = fmt->code; + format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which); + memcpy(fmt, format, sizeof(*fmt)); + + /* + * Only Allow DPCM decompression, and check that the + * pattern is preserved + */ + info = omap4iss_video_format_info(fmt->code); + if (info->uncompressed == pixelcode) + fmt->code = pixelcode; + break; + } + + /* RGB, non-interlaced */ + fmt->colorspace = V4L2_COLORSPACE_SRGB; + fmt->field = V4L2_FIELD_NONE; +} + +/* + * csi2_enum_mbus_code - Handle pixel format enumeration + * @sd : pointer to v4l2 subdev structure + * @fh : V4L2 subdev file handle + * @code : pointer to v4l2_subdev_mbus_code_enum structure + * return -EINVAL or zero on success + */ +static int csi2_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + const struct iss_format_info *info; + + if (code->pad == CSI2_PAD_SINK) { + if (code->index >= ARRAY_SIZE(csi2_input_fmts)) + return -EINVAL; + + code->code = csi2_input_fmts[code->index]; + } else { + format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, + V4L2_SUBDEV_FORMAT_TRY); + switch (code->index) { + case 0: + /* Passthrough sink pad code */ + code->code = format->code; + break; + case 1: + /* Uncompressed code */ + info = omap4iss_video_format_info(format->code); + if (info->uncompressed == format->code) + return -EINVAL; + + code->code = info->uncompressed; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int csi2_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt format; + + if (fse->index != 0) + return -EINVAL; + + format.code = fse->code; + format.width = 1; + format.height = 1; + csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->min_width = format.width; + fse->min_height = format.height; + + if (format.code != fse->code) + return -EINVAL; + + format.code = fse->code; + format.width = -1; + format.height = -1; + csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->max_width = format.width; + fse->max_height = format.height; + + return 0; +} + +/* + * csi2_get_format - Handle get format by pads subdev method + * @sd : pointer to v4l2 subdev structure + * @fh : V4L2 subdev file handle + * @fmt: pointer to v4l2 subdev format structure + * return -EINVAL or zero on success + */ +static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + fmt->format = *format; + return 0; +} + +/* + * csi2_set_format - Handle set format by pads subdev method + * @sd : pointer to v4l2 subdev structure + * @fh : V4L2 subdev file handle + * @fmt: pointer to v4l2 subdev format structure + * return -EINVAL or zero on success + */ +static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which); + *format = fmt->format; + + /* Propagate the format from sink to source */ + if (fmt->pad == CSI2_PAD_SINK) { + format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE, + fmt->which); + *format = fmt->format; + csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which); + } + + return 0; +} + +static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, + struct v4l2_subdev_format *source_fmt, + struct v4l2_subdev_format *sink_fmt) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); + int rval; + + pipe->external = media_entity_to_v4l2_subdev(link->source->entity); + rval = omap4iss_get_external_info(pipe, link); + if (rval < 0) + return rval; + + return v4l2_subdev_link_validate_default(sd, link, source_fmt, + sink_fmt); +} + +/* + * csi2_init_formats - Initialize formats on all pads + * @sd: ISS CSI2 V4L2 subdevice + * @fh: V4L2 subdev file handle + * + * Initialize all pad formats with default values. If fh is not NULL, try + * formats are initialized on the file handle. Otherwise active formats are + * initialized on the device. + */ +static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_subdev_format format; + + memset(&format, 0, sizeof(format)); + format.pad = CSI2_PAD_SINK; + format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10; + format.format.width = 4096; + format.format.height = 4096; + csi2_set_format(sd, fh, &format); + + return 0; +} + +/* + * csi2_set_stream - Enable/Disable streaming on the CSI2 module + * @sd: ISS CSI2 V4L2 subdevice + * @enable: ISS pipeline stream state + * + * Return 0 on success or a negative error code otherwise. + */ +static int csi2_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct iss_device *iss = csi2->iss; + struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); + struct iss_video *video_out = &csi2->video_out; + + if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) { + if (enable == ISS_PIPELINE_STREAM_STOPPED) + return 0; + + if (csi2 == &iss->csi2a) + omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_A); + else if (csi2 == &iss->csi2b) + omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_B); + } + + switch (enable) { + case ISS_PIPELINE_STREAM_CONTINUOUS: { + int ret; + + ret = omap4iss_csiphy_config(iss, sd); + if (ret < 0) + return ret; + + if (omap4iss_csiphy_acquire(csi2->phy) < 0) + return -ENODEV; + csi2->use_fs_irq = pipe->do_propagation; + csi2_configure(csi2); + csi2_print_status(csi2); + + /* + * When outputting to memory with no buffer available, let the + * buffer queue handler start the hardware. A DMA queue flag + * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is + * a buffer available. + */ + if (csi2->output & CSI2_OUTPUT_MEMORY && + !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) + break; + /* Enable context 0 and IRQs */ + atomic_set(&csi2->stopping, 0); + csi2_ctx_enable(csi2, 0, 1); + csi2_if_enable(csi2, 1); + iss_video_dmaqueue_flags_clr(video_out); + break; + } + case ISS_PIPELINE_STREAM_STOPPED: + if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) + return 0; + if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait, + &csi2->stopping)) + dev_dbg(iss->dev, "%s: module stop timeout.\n", + sd->name); + csi2_ctx_enable(csi2, 0, 0); + csi2_if_enable(csi2, 0); + csi2_irq_ctx_set(csi2, 0); + omap4iss_csiphy_release(csi2->phy); + if (csi2 == &iss->csi2a) + omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_A); + else if (csi2 == &iss->csi2b) + omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_B); + iss_video_dmaqueue_flags_clr(video_out); + break; + } + + csi2->state = enable; + return 0; +} + +/* subdev video operations */ +static const struct v4l2_subdev_video_ops csi2_video_ops = { + .s_stream = csi2_set_stream, +}; + +/* subdev pad operations */ +static const struct v4l2_subdev_pad_ops csi2_pad_ops = { + .enum_mbus_code = csi2_enum_mbus_code, + .enum_frame_size = csi2_enum_frame_size, + .get_fmt = csi2_get_format, + .set_fmt = csi2_set_format, + .link_validate = csi2_link_validate, +}; + +/* subdev operations */ +static const struct v4l2_subdev_ops csi2_ops = { + .video = &csi2_video_ops, + .pad = &csi2_pad_ops, +}; + +/* subdev internal operations */ +static const struct v4l2_subdev_internal_ops csi2_internal_ops = { + .open = csi2_init_formats, +}; + +/* ----------------------------------------------------------------------------- + * Media entity operations + */ + +/* + * csi2_link_setup - Setup CSI2 connections. + * @entity : Pointer to media entity structure + * @local : Pointer to local pad array + * @remote : Pointer to remote pad array + * @flags : Link flags + * return -EINVAL or zero on success + */ +static int csi2_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); + struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl; + + /* + * The ISS core doesn't support pipelines with multiple video outputs. + * Revisit this when it will be implemented, and return -EBUSY for now. + */ + + switch (local->index | media_entity_type(remote->entity)) { + case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: + if (flags & MEDIA_LNK_FL_ENABLED) { + if (csi2->output & ~CSI2_OUTPUT_MEMORY) + return -EBUSY; + csi2->output |= CSI2_OUTPUT_MEMORY; + } else { + csi2->output &= ~CSI2_OUTPUT_MEMORY; + } + break; + + case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: + if (flags & MEDIA_LNK_FL_ENABLED) { + if (csi2->output & ~CSI2_OUTPUT_IPIPEIF) + return -EBUSY; + csi2->output |= CSI2_OUTPUT_IPIPEIF; + } else { + csi2->output &= ~CSI2_OUTPUT_IPIPEIF; + } + break; + + default: + /* Link from camera to CSI2 is fixed... */ + return -EINVAL; + } + + ctrl->vp_only_enable = + (csi2->output & CSI2_OUTPUT_MEMORY) ? false : true; + ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_IPIPEIF); + + return 0; +} + +/* media operations */ +static const struct media_entity_operations csi2_media_ops = { + .link_setup = csi2_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; + +void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2) +{ + v4l2_device_unregister_subdev(&csi2->subdev); + omap4iss_video_unregister(&csi2->video_out); +} + +int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, + struct v4l2_device *vdev) +{ + int ret; + + /* Register the subdev and video nodes. */ + ret = v4l2_device_register_subdev(vdev, &csi2->subdev); + if (ret < 0) + goto error; + + ret = omap4iss_video_register(&csi2->video_out, vdev); + if (ret < 0) + goto error; + + return 0; + +error: + omap4iss_csi2_unregister_entities(csi2); + return ret; +} + +/* ----------------------------------------------------------------------------- + * ISS CSI2 initialisation and cleanup + */ + +/* + * csi2_init_entities - Initialize subdev and media entity. + * @csi2: Pointer to csi2 structure. + * return -ENOMEM or zero on success + */ +static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname) +{ + struct v4l2_subdev *sd = &csi2->subdev; + struct media_pad *pads = csi2->pads; + struct media_entity *me = &sd->entity; + int ret; + char name[V4L2_SUBDEV_NAME_SIZE]; + + v4l2_subdev_init(sd, &csi2_ops); + sd->internal_ops = &csi2_internal_ops; + sprintf(name, "CSI2%s", subname); + strlcpy(sd->name, "", sizeof(sd->name)); + sprintf(sd->name, "OMAP4 ISS %s", name); + + sd->grp_id = 1 << 16; /* group ID for iss subdevs */ + v4l2_set_subdevdata(sd, csi2); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + + me->ops = &csi2_media_ops; + ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0); + if (ret < 0) + return ret; + + csi2_init_formats(sd, NULL); + + /* Video device node */ + csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + csi2->video_out.ops = &csi2_issvideo_ops; + csi2->video_out.bpl_alignment = 32; + csi2->video_out.bpl_zero_padding = 1; + csi2->video_out.bpl_max = 0x1ffe0; + csi2->video_out.iss = csi2->iss; + csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; + + ret = omap4iss_video_init(&csi2->video_out, name); + if (ret < 0) + goto error_video; + + /* Connect the CSI2 subdev to the video node. */ + ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE, + &csi2->video_out.video.entity, 0, 0); + if (ret < 0) + goto error_link; + + return 0; + +error_link: + omap4iss_video_cleanup(&csi2->video_out); +error_video: + media_entity_cleanup(&csi2->subdev.entity); + return ret; +} + +/* + * omap4iss_csi2_init - Routine for module driver init + */ +int omap4iss_csi2_init(struct iss_device *iss) +{ + struct iss_csi2_device *csi2a = &iss->csi2a; + struct iss_csi2_device *csi2b = &iss->csi2b; + int ret; + + csi2a->iss = iss; + csi2a->available = 1; + csi2a->regs1 = iss->regs[OMAP4_ISS_MEM_CSI2_A_REGS1]; + csi2a->phy = &iss->csiphy1; + csi2a->state = ISS_PIPELINE_STREAM_STOPPED; + init_waitqueue_head(&csi2a->wait); + + ret = csi2_init_entities(csi2a, "a"); + if (ret < 0) + return ret; + + csi2b->iss = iss; + csi2b->available = 1; + csi2b->regs1 = iss->regs[OMAP4_ISS_MEM_CSI2_B_REGS1]; + csi2b->phy = &iss->csiphy2; + csi2b->state = ISS_PIPELINE_STREAM_STOPPED; + init_waitqueue_head(&csi2b->wait); + + ret = csi2_init_entities(csi2b, "b"); + if (ret < 0) + return ret; + + return 0; +} + +/* + * omap4iss_csi2_cleanup - Routine for module driver cleanup + */ +void omap4iss_csi2_cleanup(struct iss_device *iss) +{ + struct iss_csi2_device *csi2a = &iss->csi2a; + struct iss_csi2_device *csi2b = &iss->csi2b; + + omap4iss_video_cleanup(&csi2a->video_out); + media_entity_cleanup(&csi2a->subdev.entity); + + omap4iss_video_cleanup(&csi2b->video_out); + media_entity_cleanup(&csi2b->subdev.entity); +} diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h new file mode 100644 index 000000000000..d1d077b18a1b --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_csi2.h @@ -0,0 +1,156 @@ +/* + * TI OMAP4 ISS V4L2 Driver - CSI2 module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 OMAP4_ISS_CSI2_H +#define OMAP4_ISS_CSI2_H + +#include +#include + +#include "iss_video.h" + +struct iss_csiphy; + +/* This is not an exhaustive list */ +enum iss_csi2_pix_formats { + CSI2_PIX_FMT_OTHERS = 0, + CSI2_PIX_FMT_YUV422_8BIT = 0x1e, + CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e, + CSI2_PIX_FMT_YUV422_8BIT_VP16 = 0xde, + CSI2_PIX_FMT_RAW10_EXP16 = 0xab, + CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f, + CSI2_PIX_FMT_RAW8 = 0x2a, + CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa, + CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a, + CSI2_PIX_FMT_RAW8_VP = 0x12a, + CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340, + CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0, + CSI2_USERDEF_8BIT_DATA1 = 0x40, +}; + +enum iss_csi2_irqevents { + OCP_ERR_IRQ = 0x4000, + SHORT_PACKET_IRQ = 0x2000, + ECC_CORRECTION_IRQ = 0x1000, + ECC_NO_CORRECTION_IRQ = 0x800, + COMPLEXIO2_ERR_IRQ = 0x400, + COMPLEXIO1_ERR_IRQ = 0x200, + FIFO_OVF_IRQ = 0x100, + CONTEXT7 = 0x80, + CONTEXT6 = 0x40, + CONTEXT5 = 0x20, + CONTEXT4 = 0x10, + CONTEXT3 = 0x8, + CONTEXT2 = 0x4, + CONTEXT1 = 0x2, + CONTEXT0 = 0x1, +}; + +enum iss_csi2_ctx_irqevents { + CTX_ECC_CORRECTION = 0x100, + CTX_LINE_NUMBER = 0x80, + CTX_FRAME_NUMBER = 0x40, + CTX_CS = 0x20, + CTX_LE = 0x8, + CTX_LS = 0x4, + CTX_FE = 0x2, + CTX_FS = 0x1, +}; + +enum iss_csi2_frame_mode { + ISS_CSI2_FRAME_IMMEDIATE, + ISS_CSI2_FRAME_AFTERFEC, +}; + +#define ISS_CSI2_MAX_CTX_NUM 7 + +struct iss_csi2_ctx_cfg { + u8 ctxnum; /* context number 0 - 7 */ + u8 dpcm_decompress; + + /* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */ + u8 virtual_id; + u16 format_id; /* as in CSI2_CTx_CTRL2[9:0] */ + u8 dpcm_predictor; /* 1: simple, 0: advanced */ + + /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */ + u16 alpha; + u16 data_offset; + u32 ping_addr; + u32 pong_addr; + u8 eof_enabled; + u8 eol_enabled; + u8 checksum_enabled; + u8 enabled; +}; + +struct iss_csi2_timing_cfg { + u8 ionum; /* IO1 or IO2 as in CSI2_TIMING */ + unsigned force_rx_mode:1; + unsigned stop_state_16x:1; + unsigned stop_state_4x:1; + u16 stop_state_counter; +}; + +struct iss_csi2_ctrl_cfg { + bool vp_clk_enable; + bool vp_only_enable; + u8 vp_out_ctrl; + enum iss_csi2_frame_mode frame_mode; + bool ecc_enable; + bool if_enable; +}; + +#define CSI2_PAD_SINK 0 +#define CSI2_PAD_SOURCE 1 +#define CSI2_PADS_NUM 2 + +#define CSI2_OUTPUT_IPIPEIF (1 << 0) +#define CSI2_OUTPUT_MEMORY (1 << 1) + +struct iss_csi2_device { + struct v4l2_subdev subdev; + struct media_pad pads[CSI2_PADS_NUM]; + struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM]; + + struct iss_video video_out; + struct iss_device *iss; + + u8 available; /* Is the IP present on the silicon? */ + + /* Pointer to register remaps into kernel space */ + void __iomem *regs1; + void __iomem *regs2; + + u32 output; /* output to IPIPEIF, memory or both? */ + bool dpcm_decompress; + unsigned int frame_skip; + bool use_fs_irq; + + struct iss_csiphy *phy; + struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1]; + struct iss_csi2_timing_cfg timing[2]; + struct iss_csi2_ctrl_cfg ctrl; + enum iss_pipeline_stream_state state; + wait_queue_head_t wait; + atomic_t stopping; +}; + +void omap4iss_csi2_isr(struct iss_csi2_device *csi2); +int omap4iss_csi2_reset(struct iss_csi2_device *csi2); +int omap4iss_csi2_init(struct iss_device *iss); +void omap4iss_csi2_cleanup(struct iss_device *iss); +void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2); +int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, + struct v4l2_device *vdev); +#endif /* OMAP4_ISS_CSI2_H */ diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c new file mode 100644 index 000000000000..2afea98106a6 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -0,0 +1,278 @@ +/* + * TI OMAP4 ISS V4L2 Driver - CSI PHY module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 "../../../../arch/arm/mach-omap2/control.h" + +#include "iss.h" +#include "iss_regs.h" +#include "iss_csiphy.h" + +/* + * csiphy_lanes_config - Configuration of CSIPHY lanes. + * + * Updates HW configuration. + * Called with phy->mutex taken. + */ +static void csiphy_lanes_config(struct iss_csiphy *phy) +{ + unsigned int i; + u32 reg; + + reg = readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG); + + for (i = 0; i < phy->max_data_lanes; i++) { + reg &= ~(CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) | + CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i + 1)); + reg |= (phy->lanes.data[i].pol ? + CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) : 0); + reg |= (phy->lanes.data[i].pos << + CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i + 1)); + } + + reg &= ~(CSI2_COMPLEXIO_CFG_CLOCK_POL | + CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK); + reg |= phy->lanes.clk.pol ? CSI2_COMPLEXIO_CFG_CLOCK_POL : 0; + reg |= phy->lanes.clk.pos << CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT; + + writel(reg, phy->cfg_regs + CSI2_COMPLEXIO_CFG); +} + +/* + * csiphy_set_power + * @power: Power state to be set. + * + * Returns 0 if successful, or -EBUSY if the retry count is exceeded. + */ +static int csiphy_set_power(struct iss_csiphy *phy, u32 power) +{ + u32 reg; + u8 retry_count; + + writel((readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) & + ~CSI2_COMPLEXIO_CFG_PWD_CMD_MASK) | + power, + phy->cfg_regs + CSI2_COMPLEXIO_CFG); + + retry_count = 0; + do { + udelay(1); + reg = readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) & + CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK; + + if (reg != power >> 2) + retry_count++; + + } while ((reg != power >> 2) && (retry_count < 250)); + + if (retry_count == 250) { + printk(KERN_ERR "CSI2 CIO set power failed!\n"); + return -EBUSY; + } + + return 0; +} + +/* + * csiphy_dphy_config - Configure CSI2 D-PHY parameters. + * + * Called with phy->mutex taken. + */ +static void csiphy_dphy_config(struct iss_csiphy *phy) +{ + u32 reg; + + /* Set up REGISTER0 */ + reg = phy->dphy.ths_term << REGISTER0_THS_TERM_SHIFT; + reg |= phy->dphy.ths_settle << REGISTER0_THS_SETTLE_SHIFT; + + writel(reg, phy->phy_regs + REGISTER0); + + /* Set up REGISTER1 */ + reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT; + reg |= phy->dphy.tclk_miss << REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT; + reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT; + reg |= 0xB8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT; + + writel(reg, phy->phy_regs + REGISTER1); +} + +/* + * TCLK values are OK at their reset values + */ +#define TCLK_TERM 0 +#define TCLK_MISS 1 +#define TCLK_SETTLE 14 + +int omap4iss_csiphy_config(struct iss_device *iss, + struct v4l2_subdev *csi2_subdev) +{ + struct iss_csi2_device *csi2 = v4l2_get_subdevdata(csi2_subdev); + struct iss_pipeline *pipe = to_iss_pipeline(&csi2_subdev->entity); + struct iss_v4l2_subdevs_group *subdevs = pipe->external->host_priv; + struct iss_csiphy_dphy_cfg csi2phy; + int csi2_ddrclk_khz; + struct iss_csiphy_lanes_cfg *lanes; + unsigned int used_lanes = 0; + u32 cam_rx_ctrl; + unsigned int i; + + lanes = &subdevs->bus.csi2.lanecfg; + + /* + * SCM.CONTROL_CAMERA_RX + * - bit [31] : CSIPHY2 lane 2 enable (4460+ only) + * - bit [30:29] : CSIPHY2 per-lane enable (1 to 0) + * - bit [28:24] : CSIPHY1 per-lane enable (4 to 0) + * - bit [21] : CSIPHY2 CTRLCLK enable + * - bit [20:19] : CSIPHY2 config: 00 d-phy, 01/10 ccp2 + * - bit [18] : CSIPHY1 CTRLCLK enable + * - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2 + */ + cam_rx_ctrl = omap4_ctrl_pad_readl( + OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX); + + + if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) { + cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK | + OMAP4_CAMERARX_CSI21_CAMMODE_MASK); + /* NOTE: Leave CSIPHY1 config to 0x0: D-PHY mode */ + /* Enable all lanes for now */ + cam_rx_ctrl |= + 0x1F << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT; + /* Enable CTRLCLK */ + cam_rx_ctrl |= OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK; + } + + if (subdevs->interface == ISS_INTERFACE_CSI2B_PHY2) { + cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI22_LANEENABLE_MASK | + OMAP4_CAMERARX_CSI22_CAMMODE_MASK); + /* NOTE: Leave CSIPHY2 config to 0x0: D-PHY mode */ + /* Enable all lanes for now */ + cam_rx_ctrl |= + 0x3 << OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT; + /* Enable CTRLCLK */ + cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK; + } + + omap4_ctrl_pad_writel(cam_rx_ctrl, + OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX); + + /* Reset used lane count */ + csi2->phy->used_data_lanes = 0; + + /* Clock and data lanes verification */ + for (i = 0; i < csi2->phy->max_data_lanes; i++) { + if (lanes->data[i].pos == 0) + continue; + + if (lanes->data[i].pol > 1 || lanes->data[i].pos > (csi2->phy->max_data_lanes + 1)) + return -EINVAL; + + if (used_lanes & (1 << lanes->data[i].pos)) + return -EINVAL; + + used_lanes |= 1 << lanes->data[i].pos; + csi2->phy->used_data_lanes++; + } + + if (lanes->clk.pol > 1 || lanes->clk.pos > (csi2->phy->max_data_lanes + 1)) + return -EINVAL; + + if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos)) + return -EINVAL; + + csi2_ddrclk_khz = pipe->external_rate / 1000 + / (2 * csi2->phy->used_data_lanes) + * pipe->external_bpp; + + /* + * THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1. + * THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3. + */ + csi2phy.ths_term = DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1; + csi2phy.ths_settle = DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3; + csi2phy.tclk_term = TCLK_TERM; + csi2phy.tclk_miss = TCLK_MISS; + csi2phy.tclk_settle = TCLK_SETTLE; + + mutex_lock(&csi2->phy->mutex); + csi2->phy->dphy = csi2phy; + csi2->phy->lanes = *lanes; + mutex_unlock(&csi2->phy->mutex); + + return 0; +} + +int omap4iss_csiphy_acquire(struct iss_csiphy *phy) +{ + int rval; + + mutex_lock(&phy->mutex); + + rval = omap4iss_csi2_reset(phy->csi2); + if (rval) + goto done; + + csiphy_dphy_config(phy); + csiphy_lanes_config(phy); + + rval = csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_ON); + if (rval) + goto done; + + phy->phy_in_use = 1; + +done: + mutex_unlock(&phy->mutex); + return rval; +} + +void omap4iss_csiphy_release(struct iss_csiphy *phy) +{ + mutex_lock(&phy->mutex); + if (phy->phy_in_use) { + csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_OFF); + phy->phy_in_use = 0; + } + mutex_unlock(&phy->mutex); +} + +/* + * omap4iss_csiphy_init - Initialize the CSI PHY frontends + */ +int omap4iss_csiphy_init(struct iss_device *iss) +{ + struct iss_csiphy *phy1 = &iss->csiphy1; + struct iss_csiphy *phy2 = &iss->csiphy2; + + phy1->iss = iss; + phy1->csi2 = &iss->csi2a; + phy1->max_data_lanes = ISS_CSIPHY1_NUM_DATA_LANES; + phy1->used_data_lanes = 0; + phy1->cfg_regs = iss->regs[OMAP4_ISS_MEM_CSI2_A_REGS1]; + phy1->phy_regs = iss->regs[OMAP4_ISS_MEM_CAMERARX_CORE1]; + mutex_init(&phy1->mutex); + + phy2->iss = iss; + phy2->csi2 = &iss->csi2b; + phy2->max_data_lanes = ISS_CSIPHY2_NUM_DATA_LANES; + phy2->used_data_lanes = 0; + phy2->cfg_regs = iss->regs[OMAP4_ISS_MEM_CSI2_B_REGS1]; + phy2->phy_regs = iss->regs[OMAP4_ISS_MEM_CAMERARX_CORE2]; + mutex_init(&phy2->mutex); + + return 0; +} diff --git a/drivers/staging/media/omap4iss/iss_csiphy.h b/drivers/staging/media/omap4iss/iss_csiphy.h new file mode 100644 index 000000000000..df63edaf9778 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_csiphy.h @@ -0,0 +1,51 @@ +/* + * TI OMAP4 ISS V4L2 Driver - CSI PHY module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 OMAP4_ISS_CSI_PHY_H +#define OMAP4_ISS_CSI_PHY_H + +#include + +struct iss_csi2_device; + +struct iss_csiphy_dphy_cfg { + u8 ths_term; + u8 ths_settle; + u8 tclk_term; + unsigned tclk_miss:1; + u8 tclk_settle; +}; + +struct iss_csiphy { + struct iss_device *iss; + struct mutex mutex; /* serialize csiphy configuration */ + u8 phy_in_use; + struct iss_csi2_device *csi2; + + /* Pointer to register remaps into kernel space */ + void __iomem *cfg_regs; + void __iomem *phy_regs; + + u8 max_data_lanes; /* number of CSI2 Data Lanes supported */ + u8 used_data_lanes; /* number of CSI2 Data Lanes used */ + struct iss_csiphy_lanes_cfg lanes; + struct iss_csiphy_dphy_cfg dphy; +}; + +int omap4iss_csiphy_config(struct iss_device *iss, + struct v4l2_subdev *csi2_subdev); +int omap4iss_csiphy_acquire(struct iss_csiphy *phy); +void omap4iss_csiphy_release(struct iss_csiphy *phy); +int omap4iss_csiphy_init(struct iss_device *iss); + +#endif /* OMAP4_ISS_CSI_PHY_H */ -- cgit v1.2.3 From 714148260d0585aedf72bd4d6d0a909886b0e9e1 Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Mon, 24 Jan 2011 15:48:19 -0300 Subject: [media] v4l: omap4iss: Add support for OMAP4 camera interface - IPIPE(IF) This adds a very simplistic driver to utilize the CSI2A interface inside the ISS subsystem in OMAP4, and dump the data to memory. Check Documentation/video4linux/omap4_camera.txt for details. This commit adds the IPIPEIF and IPIPE processing blocks support. Signed-off-by: Sergio Aguirre Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_ipipe.c | 581 ++++++++++++++++++ drivers/staging/media/omap4iss/iss_ipipe.h | 67 +++ drivers/staging/media/omap4iss/iss_ipipeif.c | 847 +++++++++++++++++++++++++++ drivers/staging/media/omap4iss/iss_ipipeif.h | 92 +++ 4 files changed, 1587 insertions(+) create mode 100644 drivers/staging/media/omap4iss/iss_ipipe.c create mode 100644 drivers/staging/media/omap4iss/iss_ipipe.h create mode 100644 drivers/staging/media/omap4iss/iss_ipipeif.c create mode 100644 drivers/staging/media/omap4iss/iss_ipipeif.h (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c new file mode 100644 index 000000000000..fc38a5c5c8f5 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_ipipe.c @@ -0,0 +1,581 @@ +/* + * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 "iss.h" +#include "iss_regs.h" +#include "iss_ipipe.h" + +static struct v4l2_mbus_framefmt * +__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which); + +static const unsigned int ipipe_fmts[] = { + V4L2_MBUS_FMT_SGRBG10_1X10, + V4L2_MBUS_FMT_SRGGB10_1X10, + V4L2_MBUS_FMT_SBGGR10_1X10, + V4L2_MBUS_FMT_SGBRG10_1X10, +}; + +/* + * ipipe_print_status - Print current IPIPE Module register values. + * @ipipe: Pointer to ISS ISP IPIPE device. + * + * Also prints other debug information stored in the IPIPE module. + */ +#define IPIPE_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_##name)) + +static void ipipe_print_status(struct iss_ipipe_device *ipipe) +{ + struct iss_device *iss = to_iss_device(ipipe); + + dev_dbg(iss->dev, "-------------IPIPE Register dump-------------\n"); + + IPIPE_PRINT_REGISTER(iss, SRC_EN); + IPIPE_PRINT_REGISTER(iss, SRC_MODE); + IPIPE_PRINT_REGISTER(iss, SRC_FMT); + IPIPE_PRINT_REGISTER(iss, SRC_COL); + IPIPE_PRINT_REGISTER(iss, SRC_VPS); + IPIPE_PRINT_REGISTER(iss, SRC_VSZ); + IPIPE_PRINT_REGISTER(iss, SRC_HPS); + IPIPE_PRINT_REGISTER(iss, SRC_HSZ); + IPIPE_PRINT_REGISTER(iss, GCK_MMR); + IPIPE_PRINT_REGISTER(iss, YUV_PHS); + + dev_dbg(iss->dev, "-----------------------------------------------\n"); +} + +/* + * ipipe_enable - Enable/Disable IPIPE. + * @enable: enable flag + * + */ +static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable) +{ + struct iss_device *iss = to_iss_device(ipipe); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN) & + ~IPIPE_SRC_EN_EN) | + enable ? IPIPE_SRC_EN_EN : 0, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN); +} + +/* ----------------------------------------------------------------------------- + * Format- and pipeline-related configuration helpers + */ + +static void ipipe_configure(struct iss_ipipe_device *ipipe) +{ + struct iss_device *iss = to_iss_device(ipipe); + struct v4l2_mbus_framefmt *format; + + /* IPIPE_PAD_SINK */ + format = &ipipe->formats[IPIPE_PAD_SINK]; + + /* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */ + writel(IPIPE_SRC_FMT_RAW2YUV, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_FMT); + + /* Enable YUV444 -> YUV422 conversion */ + writel(IPIPE_YUV_PHS_LPF, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_YUV_PHS); + + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_VPS); + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_HPS); + writel((format->height - 2) & IPIPE_SRC_VSZ_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_VSZ); + writel((format->width - 1) & IPIPE_SRC_HSZ_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_HSZ); + + /* Ignore ipipeif_wrt signal, and operate on-the-fly. */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_MODE) & + ~(IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST), + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_MODE); + + /* HACK: Values tuned for Ducati SW (OV) */ + writel(IPIPE_SRC_COL_EE_B | + IPIPE_SRC_COL_EO_GB | + IPIPE_SRC_COL_OE_GR | + IPIPE_SRC_COL_OO_R, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_COL); + + /* IPIPE_PAD_SOURCE_VP */ + format = &ipipe->formats[IPIPE_PAD_SOURCE_VP]; + /* Do nothing? */ + + omap4iss_isp_enable_interrupts(iss); +} + +/* ----------------------------------------------------------------------------- + * V4L2 subdev operations + */ + +/* + * ipipe_set_stream - Enable/Disable streaming on the IPIPE module + * @sd: ISP IPIPE V4L2 subdevice + * @enable: Enable/disable stream + */ +static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); + struct iss_device *iss = to_iss_device(ipipe); + int ret = 0; + + if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) { + if (enable == ISS_PIPELINE_STREAM_STOPPED) + return 0; + + omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); + + /* Enable clk_arm_g0 */ + writel(IPIPE_GCK_MMR_REG, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_GCK_MMR); + + /* Enable clk_pix_g[3:0] */ + writel(IPIPE_GCK_PIX_G3 | + IPIPE_GCK_PIX_G2 | + IPIPE_GCK_PIX_G1 | + IPIPE_GCK_PIX_G0, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_GCK_PIX); + } + + switch (enable) { + case ISS_PIPELINE_STREAM_CONTINUOUS: + + ipipe_configure(ipipe); + ipipe_print_status(ipipe); + + atomic_set(&ipipe->stopping, 0); + ipipe_enable(ipipe, 1); + break; + + case ISS_PIPELINE_STREAM_STOPPED: + if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) + return 0; + if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait, + &ipipe->stopping)) + dev_dbg(iss->dev, "%s: module stop timeout.\n", + sd->name); + + ipipe_enable(ipipe, 0); + omap4iss_isp_disable_interrupts(iss); + omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); + break; + } + + ipipe->state = enable; + return ret; +} + +static struct v4l2_mbus_framefmt * +__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(fh, pad); + else + return &ipipe->formats[pad]; +} + +/* + * ipipe_try_format - Try video format on a pad + * @ipipe: ISS IPIPE device + * @fh : V4L2 subdev file handle + * @pad: Pad number + * @fmt: Format + */ +static void +ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh, + unsigned int pad, struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) +{ + struct v4l2_mbus_framefmt *format; + unsigned int width = fmt->width; + unsigned int height = fmt->height; + unsigned int i; + + switch (pad) { + case IPIPE_PAD_SINK: + for (i = 0; i < ARRAY_SIZE(ipipe_fmts); i++) { + if (fmt->code == ipipe_fmts[i]) + break; + } + + /* If not found, use SGRBG10 as default */ + if (i >= ARRAY_SIZE(ipipe_fmts)) + fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10; + + /* Clamp the input size. */ + fmt->width = clamp_t(u32, width, 1, 8192); + fmt->height = clamp_t(u32, height, 1, 8192); + fmt->colorspace = V4L2_COLORSPACE_SRGB; + break; + + case IPIPE_PAD_SOURCE_VP: + format = __ipipe_get_format(ipipe, fh, IPIPE_PAD_SINK, which); + memcpy(fmt, format, sizeof(*fmt)); + + fmt->code = V4L2_MBUS_FMT_UYVY8_1X16; + fmt->width = clamp_t(u32, width, 32, fmt->width); + fmt->height = clamp_t(u32, height, 32, fmt->height); + fmt->colorspace = V4L2_COLORSPACE_JPEG; + break; + } + + fmt->field = V4L2_FIELD_NONE; +} + +/* + * ipipe_enum_mbus_code - Handle pixel format enumeration + * @sd : pointer to v4l2 subdev structure + * @fh : V4L2 subdev file handle + * @code : pointer to v4l2_subdev_mbus_code_enum structure + * return -EINVAL or zero on success + */ +static int ipipe_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + switch (code->pad) { + case IPIPE_PAD_SINK: + if (code->index >= ARRAY_SIZE(ipipe_fmts)) + return -EINVAL; + + code->code = ipipe_fmts[code->index]; + break; + + case IPIPE_PAD_SOURCE_VP: + /* FIXME: Forced format conversion inside IPIPE ? */ + if (code->index != 0) + return -EINVAL; + + code->code = V4L2_MBUS_FMT_UYVY8_1X16; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int ipipe_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt format; + + if (fse->index != 0) + return -EINVAL; + + format.code = fse->code; + format.width = 1; + format.height = 1; + ipipe_try_format(ipipe, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->min_width = format.width; + fse->min_height = format.height; + + if (format.code != fse->code) + return -EINVAL; + + format.code = fse->code; + format.width = -1; + format.height = -1; + ipipe_try_format(ipipe, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->max_width = format.width; + fse->max_height = format.height; + + return 0; +} + +/* + * ipipe_get_format - Retrieve the video format on a pad + * @sd : ISP IPIPE V4L2 subdevice + * @fh : V4L2 subdev file handle + * @fmt: Format + * + * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond + * to the format type. + */ +static int ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + fmt->format = *format; + return 0; +} + +/* + * ipipe_set_format - Set the video format on a pad + * @sd : ISP IPIPE V4L2 subdevice + * @fh : V4L2 subdev file handle + * @fmt: Format + * + * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond + * to the format type. + */ +static int ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + ipipe_try_format(ipipe, fh, fmt->pad, &fmt->format, fmt->which); + *format = fmt->format; + + /* Propagate the format from sink to source */ + if (fmt->pad == IPIPE_PAD_SINK) { + format = __ipipe_get_format(ipipe, fh, IPIPE_PAD_SOURCE_VP, + fmt->which); + *format = fmt->format; + ipipe_try_format(ipipe, fh, IPIPE_PAD_SOURCE_VP, format, + fmt->which); + } + + return 0; +} + +static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link, + struct v4l2_subdev_format *source_fmt, + struct v4l2_subdev_format *sink_fmt) +{ + /* Check if the two ends match */ + if (source_fmt->format.width != sink_fmt->format.width || + source_fmt->format.height != sink_fmt->format.height) + return -EPIPE; + + if (source_fmt->format.code != sink_fmt->format.code) + return -EPIPE; + + return 0; +} + +/* + * ipipe_init_formats - Initialize formats on all pads + * @sd: ISP IPIPE V4L2 subdevice + * @fh: V4L2 subdev file handle + * + * Initialize all pad formats with default values. If fh is not NULL, try + * formats are initialized on the file handle. Otherwise active formats are + * initialized on the device. + */ +static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_subdev_format format; + + memset(&format, 0, sizeof(format)); + format.pad = IPIPE_PAD_SINK; + format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10; + format.format.width = 4096; + format.format.height = 4096; + ipipe_set_format(sd, fh, &format); + + return 0; +} + +/* V4L2 subdev video operations */ +static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = { + .s_stream = ipipe_set_stream, +}; + +/* V4L2 subdev pad operations */ +static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = { + .enum_mbus_code = ipipe_enum_mbus_code, + .enum_frame_size = ipipe_enum_frame_size, + .get_fmt = ipipe_get_format, + .set_fmt = ipipe_set_format, + .link_validate = ipipe_link_validate, +}; + +/* V4L2 subdev operations */ +static const struct v4l2_subdev_ops ipipe_v4l2_ops = { + .video = &ipipe_v4l2_video_ops, + .pad = &ipipe_v4l2_pad_ops, +}; + +/* V4L2 subdev internal operations */ +static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = { + .open = ipipe_init_formats, +}; + +/* ----------------------------------------------------------------------------- + * Media entity operations + */ + +/* + * ipipe_link_setup - Setup IPIPE connections + * @entity: IPIPE media entity + * @local: Pad at the local end of the link + * @remote: Pad at the remote end of the link + * @flags: Link flags + * + * return -EINVAL or zero on success + */ +static int ipipe_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); + struct iss_device *iss = to_iss_device(ipipe); + + switch (local->index | media_entity_type(remote->entity)) { + case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: + /* Read from IPIPEIF. */ + if (!(flags & MEDIA_LNK_FL_ENABLED)) { + ipipe->input = IPIPE_INPUT_NONE; + break; + } + + if (ipipe->input != IPIPE_INPUT_NONE) + return -EBUSY; + + if (remote->entity == &iss->ipipeif.subdev.entity) + ipipe->input = IPIPE_INPUT_IPIPEIF; + + break; + + case IPIPE_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV: + /* Send to RESIZER */ + if (flags & MEDIA_LNK_FL_ENABLED) { + if (ipipe->output & ~IPIPE_OUTPUT_VP) + return -EBUSY; + ipipe->output |= IPIPE_OUTPUT_VP; + } else { + ipipe->output &= ~IPIPE_OUTPUT_VP; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* media operations */ +static const struct media_entity_operations ipipe_media_ops = { + .link_setup = ipipe_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; + +/* + * ipipe_init_entities - Initialize V4L2 subdev and media entity + * @ipipe: ISS ISP IPIPE module + * + * Return 0 on success and a negative error code on failure. + */ +static int ipipe_init_entities(struct iss_ipipe_device *ipipe) +{ + struct v4l2_subdev *sd = &ipipe->subdev; + struct media_pad *pads = ipipe->pads; + struct media_entity *me = &sd->entity; + int ret; + + ipipe->input = IPIPE_INPUT_NONE; + + v4l2_subdev_init(sd, &ipipe_v4l2_ops); + sd->internal_ops = &ipipe_v4l2_internal_ops; + strlcpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name)); + sd->grp_id = 1 << 16; /* group ID for iss subdevs */ + v4l2_set_subdevdata(sd, ipipe); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; + + me->ops = &ipipe_media_ops; + ret = media_entity_init(me, IPIPE_PADS_NUM, pads, 0); + if (ret < 0) + return ret; + + ipipe_init_formats(sd, NULL); + + return 0; +} + +void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe) +{ + media_entity_cleanup(&ipipe->subdev.entity); + + v4l2_device_unregister_subdev(&ipipe->subdev); +} + +int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe, + struct v4l2_device *vdev) +{ + int ret; + + /* Register the subdev and video node. */ + ret = v4l2_device_register_subdev(vdev, &ipipe->subdev); + if (ret < 0) + goto error; + + return 0; + +error: + omap4iss_ipipe_unregister_entities(ipipe); + return ret; +} + +/* ----------------------------------------------------------------------------- + * ISP IPIPE initialisation and cleanup + */ + +/* + * omap4iss_ipipe_init - IPIPE module initialization. + * @iss: Device pointer specific to the OMAP4 ISS. + * + * TODO: Get the initialisation values from platform data. + * + * Return 0 on success or a negative error code otherwise. + */ +int omap4iss_ipipe_init(struct iss_device *iss) +{ + struct iss_ipipe_device *ipipe = &iss->ipipe; + + ipipe->state = ISS_PIPELINE_STREAM_STOPPED; + init_waitqueue_head(&ipipe->wait); + + return ipipe_init_entities(ipipe); +} + +/* + * omap4iss_ipipe_cleanup - IPIPE module cleanup. + * @iss: Device pointer specific to the OMAP4 ISS. + */ +void omap4iss_ipipe_cleanup(struct iss_device *iss) +{ + /* FIXME: are you sure there's nothing to do? */ +} diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h new file mode 100644 index 000000000000..c22d9041f2a5 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_ipipe.h @@ -0,0 +1,67 @@ +/* + * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 OMAP4_ISS_IPIPE_H +#define OMAP4_ISS_IPIPE_H + +#include "iss_video.h" + +enum ipipe_input_entity { + IPIPE_INPUT_NONE, + IPIPE_INPUT_IPIPEIF, +}; + +#define IPIPE_OUTPUT_VP (1 << 0) + +/* Sink and source IPIPE pads */ +#define IPIPE_PAD_SINK 0 +#define IPIPE_PAD_SOURCE_VP 1 +#define IPIPE_PADS_NUM 2 + +/* + * struct iss_ipipe_device - Structure for the IPIPE module to store its own + * information + * @subdev: V4L2 subdevice + * @pads: Sink and source media entity pads + * @formats: Active video formats + * @input: Active input + * @output: Active outputs + * @error: A hardware error occurred during capture + * @state: Streaming state + * @wait: Wait queue used to stop the module + * @stopping: Stopping state + */ +struct iss_ipipe_device { + struct v4l2_subdev subdev; + struct media_pad pads[IPIPE_PADS_NUM]; + struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM]; + + enum ipipe_input_entity input; + unsigned int output; + unsigned int error; + + enum iss_pipeline_stream_state state; + wait_queue_head_t wait; + atomic_t stopping; +}; + +struct iss_device; + +int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe, + struct v4l2_device *vdev); +void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe); + +int omap4iss_ipipe_init(struct iss_device *iss); +void omap4iss_ipipe_cleanup(struct iss_device *iss); + +#endif /* OMAP4_ISS_IPIPE_H */ diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c new file mode 100644 index 000000000000..acc6005dfacf --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -0,0 +1,847 @@ +/* + * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 "iss.h" +#include "iss_regs.h" +#include "iss_ipipeif.h" + +static struct v4l2_mbus_framefmt * +__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which); + +static const unsigned int ipipeif_fmts[] = { + V4L2_MBUS_FMT_SGRBG10_1X10, + V4L2_MBUS_FMT_SRGGB10_1X10, + V4L2_MBUS_FMT_SBGGR10_1X10, + V4L2_MBUS_FMT_SGBRG10_1X10, + V4L2_MBUS_FMT_UYVY8_1X16, + V4L2_MBUS_FMT_YUYV8_1X16, +}; + +/* + * ipipeif_print_status - Print current IPIPEIF Module register values. + * @ipipeif: Pointer to ISS ISP IPIPEIF device. + * + * Also prints other debug information stored in the IPIPEIF module. + */ +#define IPIPEIF_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###IPIPEIF " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_##name)) + +#define ISIF_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###ISIF " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_##name)) + +#define ISP5_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###ISP5 " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_##name)) + +static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif) +{ + struct iss_device *iss = to_iss_device(ipipeif); + + dev_dbg(iss->dev, "-------------IPIPEIF Register dump-------------\n"); + + IPIPEIF_PRINT_REGISTER(iss, CFG1); + IPIPEIF_PRINT_REGISTER(iss, CFG2); + + ISIF_PRINT_REGISTER(iss, SYNCEN); + ISIF_PRINT_REGISTER(iss, CADU); + ISIF_PRINT_REGISTER(iss, CADL); + ISIF_PRINT_REGISTER(iss, MODESET); + ISIF_PRINT_REGISTER(iss, CCOLP); + ISIF_PRINT_REGISTER(iss, SPH); + ISIF_PRINT_REGISTER(iss, LNH); + ISIF_PRINT_REGISTER(iss, LNV); + ISIF_PRINT_REGISTER(iss, VDINT0); + ISIF_PRINT_REGISTER(iss, HSIZE); + + ISP5_PRINT_REGISTER(iss, SYSCONFIG); + ISP5_PRINT_REGISTER(iss, CTRL); + ISP5_PRINT_REGISTER(iss, IRQSTATUS(0)); + ISP5_PRINT_REGISTER(iss, IRQENABLE_SET(0)); + ISP5_PRINT_REGISTER(iss, IRQENABLE_CLR(0)); + + dev_dbg(iss->dev, "-----------------------------------------------\n"); +} + +static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable) +{ + struct iss_device *iss = to_iss_device(ipipeif); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) & + ~ISIF_SYNCEN_DWEN) | + enable ? ISIF_SYNCEN_DWEN : 0, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN); +} + +/* + * ipipeif_enable - Enable/Disable IPIPEIF. + * @enable: enable flag + * + */ +static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable) +{ + struct iss_device *iss = to_iss_device(ipipeif); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) & + ~ISIF_SYNCEN_SYEN) | + enable ? ISIF_SYNCEN_SYEN : 0, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN); +} + +/* ----------------------------------------------------------------------------- + * Format- and pipeline-related configuration helpers + */ + +/* + * ipipeif_set_outaddr - Set memory address to save output image + * @ipipeif: Pointer to ISP IPIPEIF device. + * @addr: 32-bit memory address aligned on 32 byte boundary. + * + * Sets the memory address where the output will be saved. + */ +static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr) +{ + struct iss_device *iss = to_iss_device(ipipeif); + + /* Save address splitted in Base Address H & L */ + writel((addr >> (16 + 5)) & ISIF_CADU_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CADU); + writel((addr >> 5) & ISIF_CADL_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CADL); +} + +static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) +{ + struct iss_device *iss = to_iss_device(ipipeif); + struct v4l2_mbus_framefmt *format; + u32 isif_ccolp = 0; + + omap4iss_configure_bridge(iss, ipipeif->input); + + /* IPIPEIF_PAD_SINK */ + format = &ipipeif->formats[IPIPEIF_PAD_SINK]; + + /* IPIPEIF with YUV422 input from ISIF */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG1) & + ~(IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK), + iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG1); + + /* Select ISIF/IPIPEIF input format */ + switch (format->code) { + case V4L2_MBUS_FMT_UYVY8_1X16: + case V4L2_MBUS_FMT_YUYV8_1X16: + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET) & + ~(ISIF_MODESET_CCDMD | + ISIF_MODESET_INPMOD_MASK | + ISIF_MODESET_CCDW_MASK)) | + ISIF_MODESET_INPMOD_YCBCR16, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2) & + ~IPIPEIF_CFG2_YUV8) | + IPIPEIF_CFG2_YUV16, + iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2); + + break; + case V4L2_MBUS_FMT_SGRBG10_1X10: + isif_ccolp = ISIF_CCOLP_CP0_F0_GR | + ISIF_CCOLP_CP1_F0_R | + ISIF_CCOLP_CP2_F0_B | + ISIF_CCOLP_CP3_F0_GB; + goto cont_raw; + case V4L2_MBUS_FMT_SRGGB10_1X10: + isif_ccolp = ISIF_CCOLP_CP0_F0_R | + ISIF_CCOLP_CP1_F0_GR | + ISIF_CCOLP_CP2_F0_GB | + ISIF_CCOLP_CP3_F0_B; + goto cont_raw; + case V4L2_MBUS_FMT_SBGGR10_1X10: + isif_ccolp = ISIF_CCOLP_CP0_F0_B | + ISIF_CCOLP_CP1_F0_GB | + ISIF_CCOLP_CP2_F0_GR | + ISIF_CCOLP_CP3_F0_R; + goto cont_raw; + case V4L2_MBUS_FMT_SGBRG10_1X10: + isif_ccolp = ISIF_CCOLP_CP0_F0_GB | + ISIF_CCOLP_CP1_F0_B | + ISIF_CCOLP_CP2_F0_R | + ISIF_CCOLP_CP3_F0_GR; +cont_raw: + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2) & + ~IPIPEIF_CFG2_YUV16), + iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET) & + ~(ISIF_MODESET_CCDMD | + ISIF_MODESET_INPMOD_MASK | + ISIF_MODESET_CCDW_MASK)) | + ISIF_MODESET_INPMOD_RAW | ISIF_MODESET_CCDW_2BIT, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD) & + ~ISIF_CGAMMAWD_GWDI_MASK) | + ISIF_CGAMMAWD_GWDI_BIT11, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD); + + /* Set RAW Bayer pattern */ + writel(isif_ccolp, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CCOLP); + break; + } + + writel(0 & ISIF_SPH_MASK, iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SPH); + writel((format->width - 1) & ISIF_LNH_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_LNH); + writel((format->height - 1) & ISIF_LNV_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_LNV); + + /* Generate ISIF0 on the last line of the image */ + writel(format->height - 1, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_VDINT0); + + /* IPIPEIF_PAD_SOURCE_ISIF_SF */ + format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF]; + + writel((ipipeif->video_out.bpl_value >> 5) & ISIF_HSIZE_HSIZE_MASK, + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_HSIZE); + + /* IPIPEIF_PAD_SOURCE_VP */ + /* Do nothing? */ + + omap4iss_isp_enable_interrupts(iss); +} + +/* ----------------------------------------------------------------------------- + * Interrupt handling + */ + +static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif) +{ + struct iss_buffer *buffer; + + ipipeif_write_enable(ipipeif, 0); + + buffer = omap4iss_video_buffer_next(&ipipeif->video_out); + if (buffer == NULL) + return; + + ipipeif_set_outaddr(ipipeif, buffer->iss_addr); + + ipipeif_write_enable(ipipeif, 1); +} + +/* + * ipipeif_isif0_isr - Handle ISIF0 event + * @ipipeif: Pointer to ISP IPIPEIF device. + * + * Executes LSC deferred enablement before next frame starts. + */ +static void ipipeif_isif0_isr(struct iss_ipipeif_device *ipipeif) +{ + struct iss_pipeline *pipe = + to_iss_pipeline(&ipipeif->subdev.entity); + if (pipe->do_propagation) + atomic_inc(&pipe->frame_number); + + if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) + ipipeif_isr_buffer(ipipeif); +} + +/* + * omap4iss_ipipeif_isr - Configure ipipeif during interframe time. + * @ipipeif: Pointer to ISP IPIPEIF device. + * @events: IPIPEIF events + */ +void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) +{ + if (omap4iss_module_sync_is_stopping(&ipipeif->wait, &ipipeif->stopping)) + return; + + if (events & ISP5_IRQ_ISIF0) + ipipeif_isif0_isr(ipipeif); +} + +/* ----------------------------------------------------------------------------- + * ISP video operations + */ + +static int ipipeif_video_queue(struct iss_video *video, struct iss_buffer *buffer) +{ + struct iss_ipipeif_device *ipipeif = container_of(video, + struct iss_ipipeif_device, video_out); + + if (!(ipipeif->output & IPIPEIF_OUTPUT_MEMORY)) + return -ENODEV; + + ipipeif_set_outaddr(ipipeif, buffer->iss_addr); + + /* + * If streaming was enabled before there was a buffer queued + * or underrun happened in the ISR, the hardware was not enabled + * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. + * Enable it now. + */ + if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { + if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) + ipipeif_write_enable(ipipeif, 1); + ipipeif_enable(ipipeif, 1); + iss_video_dmaqueue_flags_clr(video); + } + + return 0; +} + +static const struct iss_video_operations ipipeif_video_ops = { + .queue = ipipeif_video_queue, +}; + +/* ----------------------------------------------------------------------------- + * V4L2 subdev operations + */ + +#define IPIPEIF_DRV_SUBCLK_MASK (OMAP4_ISS_ISP_SUBCLK_IPIPEIF |\ + OMAP4_ISS_ISP_SUBCLK_ISIF) +/* + * ipipeif_set_stream - Enable/Disable streaming on the IPIPEIF module + * @sd: ISP IPIPEIF V4L2 subdevice + * @enable: Enable/disable stream + */ +static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); + struct iss_device *iss = to_iss_device(ipipeif); + struct iss_video *video_out = &ipipeif->video_out; + int ret = 0; + + if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) { + if (enable == ISS_PIPELINE_STREAM_STOPPED) + return 0; + + omap4iss_isp_subclk_enable(iss, IPIPEIF_DRV_SUBCLK_MASK); + } + + switch (enable) { + case ISS_PIPELINE_STREAM_CONTINUOUS: + + ipipeif_configure(ipipeif); + ipipeif_print_status(ipipeif); + + /* + * When outputting to memory with no buffer available, let the + * buffer queue handler start the hardware. A DMA queue flag + * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is + * a buffer available. + */ + if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY && + !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) + break; + + atomic_set(&ipipeif->stopping, 0); + if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) + ipipeif_write_enable(ipipeif, 1); + ipipeif_enable(ipipeif, 1); + iss_video_dmaqueue_flags_clr(video_out); + break; + + case ISS_PIPELINE_STREAM_STOPPED: + if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) + return 0; + if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait, + &ipipeif->stopping)) + dev_dbg(iss->dev, "%s: module stop timeout.\n", + sd->name); + + if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) + ipipeif_write_enable(ipipeif, 0); + ipipeif_enable(ipipeif, 0); + omap4iss_isp_disable_interrupts(iss); + omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK); + iss_video_dmaqueue_flags_clr(video_out); + break; + } + + ipipeif->state = enable; + return ret; +} + +static struct v4l2_mbus_framefmt * +__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(fh, pad); + else + return &ipipeif->formats[pad]; +} + +/* + * ipipeif_try_format - Try video format on a pad + * @ipipeif: ISS IPIPEIF device + * @fh : V4L2 subdev file handle + * @pad: Pad number + * @fmt: Format + */ +static void +ipipeif_try_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh, + unsigned int pad, struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) +{ + struct v4l2_mbus_framefmt *format; + unsigned int width = fmt->width; + unsigned int height = fmt->height; + unsigned int i; + + switch (pad) { + case IPIPEIF_PAD_SINK: + /* TODO: If the IPIPEIF output formatter pad is connected directly + * to the resizer, only YUV formats can be used. + */ + for (i = 0; i < ARRAY_SIZE(ipipeif_fmts); i++) { + if (fmt->code == ipipeif_fmts[i]) + break; + } + + /* If not found, use SGRBG10 as default */ + if (i >= ARRAY_SIZE(ipipeif_fmts)) + fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10; + + /* Clamp the input size. */ + fmt->width = clamp_t(u32, width, 1, 8192); + fmt->height = clamp_t(u32, height, 1, 8192); + break; + + case IPIPEIF_PAD_SOURCE_ISIF_SF: + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, which); + memcpy(fmt, format, sizeof(*fmt)); + + /* The data formatter truncates the number of horizontal output + * pixels to a multiple of 16. To avoid clipping data, allow + * callers to request an output size bigger than the input size + * up to the nearest multiple of 16. + */ + fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15); + fmt->width &= ~15; + fmt->height = clamp_t(u32, height, 32, fmt->height); + break; + + case IPIPEIF_PAD_SOURCE_VP: + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, which); + memcpy(fmt, format, sizeof(*fmt)); + + fmt->width = clamp_t(u32, width, 32, fmt->width); + fmt->height = clamp_t(u32, height, 32, fmt->height); + break; + } + + /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is + * stored on 2 bytes. + */ + fmt->colorspace = V4L2_COLORSPACE_SRGB; + fmt->field = V4L2_FIELD_NONE; +} + +/* + * ipipeif_enum_mbus_code - Handle pixel format enumeration + * @sd : pointer to v4l2 subdev structure + * @fh : V4L2 subdev file handle + * @code : pointer to v4l2_subdev_mbus_code_enum structure + * return -EINVAL or zero on success + */ +static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + switch (code->pad) { + case IPIPEIF_PAD_SINK: + if (code->index >= ARRAY_SIZE(ipipeif_fmts)) + return -EINVAL; + + code->code = ipipeif_fmts[code->index]; + break; + + case IPIPEIF_PAD_SOURCE_ISIF_SF: + case IPIPEIF_PAD_SOURCE_VP: + /* No format conversion inside IPIPEIF */ + if (code->index != 0) + return -EINVAL; + + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, + V4L2_SUBDEV_FORMAT_TRY); + + code->code = format->code; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int ipipeif_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt format; + + if (fse->index != 0) + return -EINVAL; + + format.code = fse->code; + format.width = 1; + format.height = 1; + ipipeif_try_format(ipipeif, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->min_width = format.width; + fse->min_height = format.height; + + if (format.code != fse->code) + return -EINVAL; + + format.code = fse->code; + format.width = -1; + format.height = -1; + ipipeif_try_format(ipipeif, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->max_width = format.width; + fse->max_height = format.height; + + return 0; +} + +/* + * ipipeif_get_format - Retrieve the video format on a pad + * @sd : ISP IPIPEIF V4L2 subdevice + * @fh : V4L2 subdev file handle + * @fmt: Format + * + * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond + * to the format type. + */ +static int ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + fmt->format = *format; + return 0; +} + +/* + * ipipeif_set_format - Set the video format on a pad + * @sd : ISP IPIPEIF V4L2 subdevice + * @fh : V4L2 subdev file handle + * @fmt: Format + * + * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond + * to the format type. + */ +static int ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which); + *format = fmt->format; + + /* Propagate the format from sink to source */ + if (fmt->pad == IPIPEIF_PAD_SINK) { + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF, + fmt->which); + *format = fmt->format; + ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF, format, + fmt->which); + + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP, + fmt->which); + *format = fmt->format; + ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP, format, + fmt->which); + } + + return 0; +} + +static int ipipeif_link_validate(struct v4l2_subdev *sd, struct media_link *link, + struct v4l2_subdev_format *source_fmt, + struct v4l2_subdev_format *sink_fmt) +{ + /* Check if the two ends match */ + if (source_fmt->format.width != sink_fmt->format.width || + source_fmt->format.height != sink_fmt->format.height) + return -EPIPE; + + if (source_fmt->format.code != sink_fmt->format.code) + return -EPIPE; + + return 0; +} + +/* + * ipipeif_init_formats - Initialize formats on all pads + * @sd: ISP IPIPEIF V4L2 subdevice + * @fh: V4L2 subdev file handle + * + * Initialize all pad formats with default values. If fh is not NULL, try + * formats are initialized on the file handle. Otherwise active formats are + * initialized on the device. + */ +static int ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_subdev_format format; + + memset(&format, 0, sizeof(format)); + format.pad = IPIPEIF_PAD_SINK; + format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10; + format.format.width = 4096; + format.format.height = 4096; + ipipeif_set_format(sd, fh, &format); + + return 0; +} + +/* V4L2 subdev video operations */ +static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = { + .s_stream = ipipeif_set_stream, +}; + +/* V4L2 subdev pad operations */ +static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = { + .enum_mbus_code = ipipeif_enum_mbus_code, + .enum_frame_size = ipipeif_enum_frame_size, + .get_fmt = ipipeif_get_format, + .set_fmt = ipipeif_set_format, + .link_validate = ipipeif_link_validate, +}; + +/* V4L2 subdev operations */ +static const struct v4l2_subdev_ops ipipeif_v4l2_ops = { + .video = &ipipeif_v4l2_video_ops, + .pad = &ipipeif_v4l2_pad_ops, +}; + +/* V4L2 subdev internal operations */ +static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = { + .open = ipipeif_init_formats, +}; + +/* ----------------------------------------------------------------------------- + * Media entity operations + */ + +/* + * ipipeif_link_setup - Setup IPIPEIF connections + * @entity: IPIPEIF media entity + * @local: Pad at the local end of the link + * @remote: Pad at the remote end of the link + * @flags: Link flags + * + * return -EINVAL or zero on success + */ +static int ipipeif_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); + struct iss_device *iss = to_iss_device(ipipeif); + + switch (local->index | media_entity_type(remote->entity)) { + case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: + /* Read from the sensor CSI2a or CSI2b. */ + if (!(flags & MEDIA_LNK_FL_ENABLED)) { + ipipeif->input = IPIPEIF_INPUT_NONE; + break; + } + + if (ipipeif->input != IPIPEIF_INPUT_NONE) + return -EBUSY; + + if (remote->entity == &iss->csi2a.subdev.entity) + ipipeif->input = IPIPEIF_INPUT_CSI2A; + else if (remote->entity == &iss->csi2b.subdev.entity) + ipipeif->input = IPIPEIF_INPUT_CSI2B; + + break; + + case IPIPEIF_PAD_SOURCE_ISIF_SF | MEDIA_ENT_T_DEVNODE: + /* Write to memory */ + if (flags & MEDIA_LNK_FL_ENABLED) { + if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY) + return -EBUSY; + ipipeif->output |= IPIPEIF_OUTPUT_MEMORY; + } else { + ipipeif->output &= ~IPIPEIF_OUTPUT_MEMORY; + } + break; + + case IPIPEIF_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV: + /* Send to IPIPE/RESIZER */ + if (flags & MEDIA_LNK_FL_ENABLED) { + if (ipipeif->output & ~IPIPEIF_OUTPUT_VP) + return -EBUSY; + ipipeif->output |= IPIPEIF_OUTPUT_VP; + } else { + ipipeif->output &= ~IPIPEIF_OUTPUT_VP; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* media operations */ +static const struct media_entity_operations ipipeif_media_ops = { + .link_setup = ipipeif_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; + +/* + * ipipeif_init_entities - Initialize V4L2 subdev and media entity + * @ipipeif: ISS ISP IPIPEIF module + * + * Return 0 on success and a negative error code on failure. + */ +static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) +{ + struct v4l2_subdev *sd = &ipipeif->subdev; + struct media_pad *pads = ipipeif->pads; + struct media_entity *me = &sd->entity; + int ret; + + ipipeif->input = IPIPEIF_INPUT_NONE; + + v4l2_subdev_init(sd, &ipipeif_v4l2_ops); + sd->internal_ops = &ipipeif_v4l2_internal_ops; + strlcpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name)); + sd->grp_id = 1 << 16; /* group ID for iss subdevs */ + v4l2_set_subdevdata(sd, ipipeif); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[IPIPEIF_PAD_SOURCE_ISIF_SF].flags = MEDIA_PAD_FL_SOURCE; + pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; + + me->ops = &ipipeif_media_ops; + ret = media_entity_init(me, IPIPEIF_PADS_NUM, pads, 0); + if (ret < 0) + return ret; + + ipipeif_init_formats(sd, NULL); + + ipipeif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ipipeif->video_out.ops = &ipipeif_video_ops; + ipipeif->video_out.iss = to_iss_device(ipipeif); + ipipeif->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; + ipipeif->video_out.bpl_alignment = 32; + ipipeif->video_out.bpl_zero_padding = 1; + ipipeif->video_out.bpl_max = 0x1ffe0; + + ret = omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF"); + if (ret < 0) + return ret; + + /* Connect the IPIPEIF subdev to the video node. */ + ret = media_entity_create_link(&ipipeif->subdev.entity, IPIPEIF_PAD_SOURCE_ISIF_SF, + &ipipeif->video_out.video.entity, 0, 0); + if (ret < 0) + return ret; + + return 0; +} + +void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif) +{ + media_entity_cleanup(&ipipeif->subdev.entity); + + v4l2_device_unregister_subdev(&ipipeif->subdev); + omap4iss_video_unregister(&ipipeif->video_out); +} + +int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, + struct v4l2_device *vdev) +{ + int ret; + + /* Register the subdev and video node. */ + ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev); + if (ret < 0) + goto error; + + ret = omap4iss_video_register(&ipipeif->video_out, vdev); + if (ret < 0) + goto error; + + return 0; + +error: + omap4iss_ipipeif_unregister_entities(ipipeif); + return ret; +} + +/* ----------------------------------------------------------------------------- + * ISP IPIPEIF initialisation and cleanup + */ + +/* + * omap4iss_ipipeif_init - IPIPEIF module initialization. + * @iss: Device pointer specific to the OMAP4 ISS. + * + * TODO: Get the initialisation values from platform data. + * + * Return 0 on success or a negative error code otherwise. + */ +int omap4iss_ipipeif_init(struct iss_device *iss) +{ + struct iss_ipipeif_device *ipipeif = &iss->ipipeif; + + ipipeif->state = ISS_PIPELINE_STREAM_STOPPED; + init_waitqueue_head(&ipipeif->wait); + + return ipipeif_init_entities(ipipeif); +} + +/* + * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup. + * @iss: Device pointer specific to the OMAP4 ISS. + */ +void omap4iss_ipipeif_cleanup(struct iss_device *iss) +{ + /* FIXME: are you sure there's nothing to do? */ +} diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h new file mode 100644 index 000000000000..cbdccb982eee --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_ipipeif.h @@ -0,0 +1,92 @@ +/* + * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 OMAP4_ISS_IPIPEIF_H +#define OMAP4_ISS_IPIPEIF_H + +#include "iss_video.h" + +enum ipipeif_input_entity { + IPIPEIF_INPUT_NONE, + IPIPEIF_INPUT_CSI2A, + IPIPEIF_INPUT_CSI2B +}; + +#define IPIPEIF_OUTPUT_MEMORY (1 << 0) +#define IPIPEIF_OUTPUT_VP (1 << 1) + +/* Sink and source IPIPEIF pads */ +#define IPIPEIF_PAD_SINK 0 +#define IPIPEIF_PAD_SOURCE_ISIF_SF 1 +#define IPIPEIF_PAD_SOURCE_VP 2 +#define IPIPEIF_PADS_NUM 3 + +/* + * struct iss_ipipeif_device - Structure for the IPIPEIF module to store its own + * information + * @subdev: V4L2 subdevice + * @pads: Sink and source media entity pads + * @formats: Active video formats + * @input: Active input + * @output: Active outputs + * @video_out: Output video node + * @error: A hardware error occurred during capture + * @alaw: A-law compression enabled (1) or disabled (0) + * @lpf: Low pass filter enabled (1) or disabled (0) + * @obclamp: Optical-black clamp enabled (1) or disabled (0) + * @fpc_en: Faulty pixels correction enabled (1) or disabled (0) + * @blcomp: Black level compensation configuration + * @clamp: Optical-black or digital clamp configuration + * @fpc: Faulty pixels correction configuration + * @lsc: Lens shading compensation configuration + * @update: Bitmask of controls to update during the next interrupt + * @shadow_update: Controls update in progress by userspace + * @syncif: Interface synchronization configuration + * @vpcfg: Video port configuration + * @underrun: A buffer underrun occurred and a new buffer has been queued + * @state: Streaming state + * @lock: Serializes shadow_update with interrupt handler + * @wait: Wait queue used to stop the module + * @stopping: Stopping state + * @ioctl_lock: Serializes ioctl calls and LSC requests freeing + */ +struct iss_ipipeif_device { + struct v4l2_subdev subdev; + struct media_pad pads[IPIPEIF_PADS_NUM]; + struct v4l2_mbus_framefmt formats[IPIPEIF_PADS_NUM]; + + enum ipipeif_input_entity input; + unsigned int output; + struct iss_video video_out; + unsigned int error; + + enum iss_pipeline_stream_state state; + wait_queue_head_t wait; + atomic_t stopping; +}; + +struct iss_device; + +int omap4iss_ipipeif_init(struct iss_device *iss); +void omap4iss_ipipeif_cleanup(struct iss_device *iss); +int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, + struct v4l2_device *vdev); +void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif); + +int omap4iss_ipipeif_busy(struct iss_ipipeif_device *ipipeif); +void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events); +void omap4iss_ipipeif_restore_context(struct iss_device *iss); +void omap4iss_ipipeif_max_rate(struct iss_ipipeif_device *ipipeif, + unsigned int *max_rate); + +#endif /* OMAP4_ISS_IPIPEIF_H */ -- cgit v1.2.3 From 69c536b2c2b338e0a162626aee5059e4e1c197eb Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Mon, 24 Jan 2011 15:48:19 -0300 Subject: [media] v4l: omap4iss: Add support for OMAP4 camera interface - Resizer This adds a very simplistic driver to utilize the CSI2A interface inside the ISS subsystem in OMAP4, and dump the data to memory. Check Documentation/video4linux/omap4_camera.txt for details. This commit adds resizer support. [Port the driver to v3.12-rc3, including the following changes - Don't include plat/ headers - Don't use cpu_is_omap44xx() macro - Don't depend on EXPERIMENTAL - Fix s_crop operation prototype - Update link_notify prototype - Rename media_entity_remote_source to media_entity_remote_pad] Signed-off-by: Sergio Aguirre Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_resizer.c | 905 +++++++++++++++++++++++++++ drivers/staging/media/omap4iss/iss_resizer.h | 75 +++ 2 files changed, 980 insertions(+) create mode 100644 drivers/staging/media/omap4iss/iss_resizer.c create mode 100644 drivers/staging/media/omap4iss/iss_resizer.h (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c new file mode 100644 index 000000000000..cb5df52e45a6 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -0,0 +1,905 @@ +/* + * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 "iss.h" +#include "iss_regs.h" +#include "iss_resizer.h" + +static struct v4l2_mbus_framefmt * +__resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which); + +static const unsigned int resizer_fmts[] = { + V4L2_MBUS_FMT_UYVY8_1X16, + V4L2_MBUS_FMT_YUYV8_1X16, +}; + +/* + * resizer_print_status - Print current RESIZER Module register values. + * @resizer: Pointer to ISS ISP RESIZER device. + * + * Also prints other debug information stored in the RESIZER module. + */ +#define RSZ_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###RSZ " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_##name)) + +#define RZA_PRINT_REGISTER(iss, name)\ + dev_dbg(iss->dev, "###RZA " #name "=0x%08x\n", \ + readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_##name)) + +static void resizer_print_status(struct iss_resizer_device *resizer) +{ + struct iss_device *iss = to_iss_device(resizer); + + dev_dbg(iss->dev, "-------------RESIZER Register dump-------------\n"); + + RSZ_PRINT_REGISTER(iss, SYSCONFIG); + RSZ_PRINT_REGISTER(iss, IN_FIFO_CTRL); + RSZ_PRINT_REGISTER(iss, FRACDIV); + RSZ_PRINT_REGISTER(iss, SRC_EN); + RSZ_PRINT_REGISTER(iss, SRC_MODE); + RSZ_PRINT_REGISTER(iss, SRC_FMT0); + RSZ_PRINT_REGISTER(iss, SRC_FMT1); + RSZ_PRINT_REGISTER(iss, SRC_VPS); + RSZ_PRINT_REGISTER(iss, SRC_VSZ); + RSZ_PRINT_REGISTER(iss, SRC_HPS); + RSZ_PRINT_REGISTER(iss, SRC_HSZ); + RSZ_PRINT_REGISTER(iss, DMA_RZA); + RSZ_PRINT_REGISTER(iss, DMA_RZB); + RSZ_PRINT_REGISTER(iss, DMA_STA); + RSZ_PRINT_REGISTER(iss, GCK_MMR); + RSZ_PRINT_REGISTER(iss, GCK_SDR); + RSZ_PRINT_REGISTER(iss, IRQ_RZA); + RSZ_PRINT_REGISTER(iss, IRQ_RZB); + RSZ_PRINT_REGISTER(iss, YUV_Y_MIN); + RSZ_PRINT_REGISTER(iss, YUV_Y_MAX); + RSZ_PRINT_REGISTER(iss, YUV_C_MIN); + RSZ_PRINT_REGISTER(iss, YUV_C_MAX); + RSZ_PRINT_REGISTER(iss, SEQ); + + RZA_PRINT_REGISTER(iss, EN); + RZA_PRINT_REGISTER(iss, MODE); + RZA_PRINT_REGISTER(iss, 420); + RZA_PRINT_REGISTER(iss, I_VPS); + RZA_PRINT_REGISTER(iss, I_HPS); + RZA_PRINT_REGISTER(iss, O_VSZ); + RZA_PRINT_REGISTER(iss, O_HSZ); + RZA_PRINT_REGISTER(iss, V_PHS_Y); + RZA_PRINT_REGISTER(iss, V_PHS_C); + RZA_PRINT_REGISTER(iss, V_DIF); + RZA_PRINT_REGISTER(iss, V_TYP); + RZA_PRINT_REGISTER(iss, V_LPF); + RZA_PRINT_REGISTER(iss, H_PHS); + RZA_PRINT_REGISTER(iss, H_DIF); + RZA_PRINT_REGISTER(iss, H_TYP); + RZA_PRINT_REGISTER(iss, H_LPF); + RZA_PRINT_REGISTER(iss, DWN_EN); + RZA_PRINT_REGISTER(iss, SDR_Y_BAD_H); + RZA_PRINT_REGISTER(iss, SDR_Y_BAD_L); + RZA_PRINT_REGISTER(iss, SDR_Y_SAD_H); + RZA_PRINT_REGISTER(iss, SDR_Y_SAD_L); + RZA_PRINT_REGISTER(iss, SDR_Y_OFT); + RZA_PRINT_REGISTER(iss, SDR_Y_PTR_S); + RZA_PRINT_REGISTER(iss, SDR_Y_PTR_E); + RZA_PRINT_REGISTER(iss, SDR_C_BAD_H); + RZA_PRINT_REGISTER(iss, SDR_C_BAD_L); + RZA_PRINT_REGISTER(iss, SDR_C_SAD_H); + RZA_PRINT_REGISTER(iss, SDR_C_SAD_L); + RZA_PRINT_REGISTER(iss, SDR_C_OFT); + RZA_PRINT_REGISTER(iss, SDR_C_PTR_S); + RZA_PRINT_REGISTER(iss, SDR_C_PTR_E); + + dev_dbg(iss->dev, "-----------------------------------------------\n"); +} + +/* + * resizer_enable - Enable/Disable RESIZER. + * @enable: enable flag + * + */ +static void resizer_enable(struct iss_resizer_device *resizer, u8 enable) +{ + struct iss_device *iss = to_iss_device(resizer); + + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN) & + ~RSZ_SRC_EN_SRC_EN) | + enable ? RSZ_SRC_EN_SRC_EN : 0, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN); + + /* TODO: Enable RSZB */ + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) & + ~RSZ_EN_EN) | + enable ? RSZ_EN_EN : 0, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); +} + +/* ----------------------------------------------------------------------------- + * Format- and pipeline-related configuration helpers + */ + +/* + * resizer_set_outaddr - Set memory address to save output image + * @resizer: Pointer to ISP RESIZER device. + * @addr: 32-bit memory address aligned on 32 byte boundary. + * + * Sets the memory address where the output will be saved. + */ +static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr) +{ + struct iss_device *iss = to_iss_device(resizer); + struct v4l2_mbus_framefmt *informat, *outformat; + + informat = &resizer->formats[RESIZER_PAD_SINK]; + outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; + + /* Save address splitted in Base Address H & L */ + writel((addr >> 16) & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_BAD_H); + writel(addr & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_BAD_L); + + /* SAD = BAD */ + writel((addr >> 16) & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_SAD_H); + writel(addr & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_SAD_L); + + /* Program UV buffer address... Hardcoded to be contiguous! */ + if ((informat->code == V4L2_MBUS_FMT_UYVY8_1X16) && + (outformat->code == V4L2_MBUS_FMT_YUYV8_1_5X8)) { + u32 c_addr = addr + (resizer->video_out.bpl_value * + (outformat->height - 1)); + + /* Ensure Y_BAD_L[6:0] = C_BAD_L[6:0]*/ + if ((c_addr ^ addr) & 0x7f) { + c_addr &= ~0x7f; + c_addr += 0x80; + c_addr |= addr & 0x7f; + } + + /* Save address splitted in Base Address H & L */ + writel((c_addr >> 16) & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_BAD_H); + writel(c_addr & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_BAD_L); + + /* SAD = BAD */ + writel((c_addr >> 16) & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_SAD_H); + writel(c_addr & 0xffff, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_SAD_L); + } +} + +static void resizer_configure(struct iss_resizer_device *resizer) +{ + struct iss_device *iss = to_iss_device(resizer); + struct v4l2_mbus_framefmt *informat, *outformat; + + informat = &resizer->formats[RESIZER_PAD_SINK]; + outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; + + /* Make sure we don't bypass the resizer */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) & + ~RSZ_SRC_FMT0_BYPASS, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0); + + /* Select RSZ input */ + writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) & + ~RSZ_SRC_FMT0_SEL) | + (resizer->input == RESIZER_INPUT_IPIPEIF) ? RSZ_SRC_FMT0_SEL : 0, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0); + + /* RSZ ignores WEN signal from IPIPE/IPIPEIF */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE) & + ~RSZ_SRC_MODE_WRT, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE); + + /* Set Resizer in free-running mode */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE) & + ~RSZ_SRC_MODE_OST, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE); + + /* Init Resizer A */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_MODE) & + ~RZA_MODE_ONE_SHOT, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_MODE); + + /* Set size related things now */ + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_VPS); + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_HPS); + writel(informat->height - 2, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_VSZ); + writel(informat->width - 1, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_HSZ); + + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_I_VPS); + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_I_HPS); + + writel(outformat->height - 2, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_O_VSZ); + writel(outformat->width - 1, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_O_HSZ); + + writel(0x100, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_V_DIF); + writel(0x100, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_H_DIF); + + /* Buffer output settings */ + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_PTR_S); + writel(outformat->height - 1, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_PTR_E); + + writel(resizer->video_out.bpl_value, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_OFT); + + /* UYVY -> NV12 conversion */ + if ((informat->code == V4L2_MBUS_FMT_UYVY8_1X16) && + (outformat->code == V4L2_MBUS_FMT_YUYV8_1_5X8)) { + writel(RSZ_420_CEN | RSZ_420_YEN, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_420); + + /* UV Buffer output settings */ + writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_PTR_S); + writel(outformat->height - 1, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_PTR_E); + + writel(resizer->video_out.bpl_value, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_OFT); + } else { + writel(0, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_420); + } + + omap4iss_isp_enable_interrupts(iss); +} + +/* ----------------------------------------------------------------------------- + * Interrupt handling + */ + +static void resizer_isr_buffer(struct iss_resizer_device *resizer) +{ + struct iss_device *iss = to_iss_device(resizer); + struct iss_buffer *buffer; + + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) & + ~RSZ_EN_EN, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); + + buffer = omap4iss_video_buffer_next(&resizer->video_out); + if (buffer == NULL) + return; + + resizer_set_outaddr(resizer, buffer->iss_addr); + + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) | + RSZ_EN_EN, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); +} + +/* + * resizer_isif0_isr - Handle ISIF0 event + * @resizer: Pointer to ISP RESIZER device. + * + * Executes LSC deferred enablement before next frame starts. + */ +static void resizer_int_dma_isr(struct iss_resizer_device *resizer) +{ + struct iss_pipeline *pipe = + to_iss_pipeline(&resizer->subdev.entity); + if (pipe->do_propagation) + atomic_inc(&pipe->frame_number); + + resizer_isr_buffer(resizer); +} + +/* + * omap4iss_resizer_isr - Configure resizer during interframe time. + * @resizer: Pointer to ISP RESIZER device. + * @events: RESIZER events + */ +void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) +{ + struct iss_device *iss = to_iss_device(resizer); + struct iss_pipeline *pipe = + to_iss_pipeline(&resizer->subdev.entity); + + if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK | + ISP5_IRQ_RSZ_FIFO_OVF)) { + dev_dbg(iss->dev, "RSZ Err:" + " FIFO_IN_BLK:%d," + " FIFO_OVF:%d," + "\n", + (events & + ISP5_IRQ_RSZ_FIFO_IN_BLK) ? 1 : 0, + (events & + ISP5_IRQ_RSZ_FIFO_OVF) ? 1 : 0); + pipe->error = true; + } + + if (omap4iss_module_sync_is_stopping(&resizer->wait, &resizer->stopping)) + return; + + if (events & ISP5_IRQ_RSZ_INT_DMA) + resizer_int_dma_isr(resizer); +} + +/* ----------------------------------------------------------------------------- + * ISS video operations + */ + +static int resizer_video_queue(struct iss_video *video, struct iss_buffer *buffer) +{ + struct iss_resizer_device *resizer = container_of(video, + struct iss_resizer_device, video_out); + + if (!(resizer->output & RESIZER_OUTPUT_MEMORY)) + return -ENODEV; + + resizer_set_outaddr(resizer, buffer->iss_addr); + + /* + * If streaming was enabled before there was a buffer queued + * or underrun happened in the ISR, the hardware was not enabled + * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set. + * Enable it now. + */ + if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { + resizer_enable(resizer, 1); + iss_video_dmaqueue_flags_clr(video); + } + + return 0; +} + +static const struct iss_video_operations resizer_video_ops = { + .queue = resizer_video_queue, +}; + +/* ----------------------------------------------------------------------------- + * V4L2 subdev operations + */ + +/* + * resizer_set_stream - Enable/Disable streaming on the RESIZER module + * @sd: ISP RESIZER V4L2 subdevice + * @enable: Enable/disable stream + */ +static int resizer_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); + struct iss_device *iss = to_iss_device(resizer); + struct iss_video *video_out = &resizer->video_out; + int ret = 0; + + if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) { + if (enable == ISS_PIPELINE_STREAM_STOPPED) + return 0; + + omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); + + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR) | + RSZ_GCK_MMR_MMR, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR); + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR) | + RSZ_GCK_SDR_CORE, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR); + + /* FIXME: Enable RSZB also */ + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG) | + RSZ_SYSCONFIG_RSZA_CLK_EN, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG); + } + + switch (enable) { + case ISS_PIPELINE_STREAM_CONTINUOUS: + + resizer_configure(resizer); + resizer_print_status(resizer); + + /* + * When outputting to memory with no buffer available, let the + * buffer queue handler start the hardware. A DMA queue flag + * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is + * a buffer available. + */ + if (resizer->output & RESIZER_OUTPUT_MEMORY && + !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED)) + break; + + atomic_set(&resizer->stopping, 0); + resizer_enable(resizer, 1); + iss_video_dmaqueue_flags_clr(video_out); + break; + + case ISS_PIPELINE_STREAM_STOPPED: + if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) + return 0; + if (omap4iss_module_sync_idle(&sd->entity, &resizer->wait, + &resizer->stopping)) + dev_dbg(iss->dev, "%s: module stop timeout.\n", + sd->name); + + resizer_enable(resizer, 0); + omap4iss_isp_disable_interrupts(iss); + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG) & + ~RSZ_SYSCONFIG_RSZA_CLK_EN, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG); + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR) & + ~RSZ_GCK_SDR_CORE, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR); + writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR) & + ~RSZ_GCK_MMR_MMR, + iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR); + omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); + iss_video_dmaqueue_flags_clr(video_out); + break; + } + + resizer->state = enable; + return ret; +} + +static struct v4l2_mbus_framefmt * +__resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(fh, pad); + else + return &resizer->formats[pad]; +} + +/* + * resizer_try_format - Try video format on a pad + * @resizer: ISS RESIZER device + * @fh : V4L2 subdev file handle + * @pad: Pad number + * @fmt: Format + */ +static void +resizer_try_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh, + unsigned int pad, struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) +{ + enum v4l2_mbus_pixelcode pixelcode; + struct v4l2_mbus_framefmt *format; + unsigned int width = fmt->width; + unsigned int height = fmt->height; + unsigned int i; + + switch (pad) { + case RESIZER_PAD_SINK: + for (i = 0; i < ARRAY_SIZE(resizer_fmts); i++) { + if (fmt->code == resizer_fmts[i]) + break; + } + + /* If not found, use UYVY as default */ + if (i >= ARRAY_SIZE(resizer_fmts)) + fmt->code = V4L2_MBUS_FMT_UYVY8_1X16; + + /* Clamp the input size. */ + fmt->width = clamp_t(u32, width, 1, 8192); + fmt->height = clamp_t(u32, height, 1, 8192); + break; + + case RESIZER_PAD_SOURCE_MEM: + pixelcode = fmt->code; + format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK, which); + memcpy(fmt, format, sizeof(*fmt)); + + if ((pixelcode == V4L2_MBUS_FMT_YUYV8_1_5X8) && + (fmt->code == V4L2_MBUS_FMT_UYVY8_1X16)) + fmt->code = pixelcode; + + /* The data formatter truncates the number of horizontal output + * pixels to a multiple of 16. To avoid clipping data, allow + * callers to request an output size bigger than the input size + * up to the nearest multiple of 16. + */ + fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15); + fmt->width &= ~15; + fmt->height = clamp_t(u32, height, 32, fmt->height); + break; + + } + + fmt->colorspace = V4L2_COLORSPACE_JPEG; + fmt->field = V4L2_FIELD_NONE; +} + +/* + * resizer_enum_mbus_code - Handle pixel format enumeration + * @sd : pointer to v4l2 subdev structure + * @fh : V4L2 subdev file handle + * @code : pointer to v4l2_subdev_mbus_code_enum structure + * return -EINVAL or zero on success + */ +static int resizer_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + switch (code->pad) { + case RESIZER_PAD_SINK: + if (code->index >= ARRAY_SIZE(resizer_fmts)) + return -EINVAL; + + code->code = resizer_fmts[code->index]; + break; + + case RESIZER_PAD_SOURCE_MEM: + format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK, + V4L2_SUBDEV_FORMAT_TRY); + + if (code->index == 0) { + code->code = format->code; + break; + } + + switch (format->code) { + case V4L2_MBUS_FMT_UYVY8_1X16: + if (code->index == 1) + code->code = V4L2_MBUS_FMT_YUYV8_1_5X8; + else + return -EINVAL; + break; + default: + if (code->index != 0) + return -EINVAL; + } + + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int resizer_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt format; + + if (fse->index != 0) + return -EINVAL; + + format.code = fse->code; + format.width = 1; + format.height = 1; + resizer_try_format(resizer, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->min_width = format.width; + fse->min_height = format.height; + + if (format.code != fse->code) + return -EINVAL; + + format.code = fse->code; + format.width = -1; + format.height = -1; + resizer_try_format(resizer, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + fse->max_width = format.width; + fse->max_height = format.height; + + return 0; +} + +/* + * resizer_get_format - Retrieve the video format on a pad + * @sd : ISP RESIZER V4L2 subdevice + * @fh : V4L2 subdev file handle + * @fmt: Format + * + * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond + * to the format type. + */ +static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __resizer_get_format(resizer, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + fmt->format = *format; + return 0; +} + +/* + * resizer_set_format - Set the video format on a pad + * @sd : ISP RESIZER V4L2 subdevice + * @fh : V4L2 subdev file handle + * @fmt: Format + * + * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond + * to the format type. + */ +static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __resizer_get_format(resizer, fh, fmt->pad, fmt->which); + if (format == NULL) + return -EINVAL; + + resizer_try_format(resizer, fh, fmt->pad, &fmt->format, fmt->which); + *format = fmt->format; + + /* Propagate the format from sink to source */ + if (fmt->pad == RESIZER_PAD_SINK) { + format = __resizer_get_format(resizer, fh, RESIZER_PAD_SOURCE_MEM, + fmt->which); + *format = fmt->format; + resizer_try_format(resizer, fh, RESIZER_PAD_SOURCE_MEM, format, + fmt->which); + } + + return 0; +} + +static int resizer_link_validate(struct v4l2_subdev *sd, struct media_link *link, + struct v4l2_subdev_format *source_fmt, + struct v4l2_subdev_format *sink_fmt) +{ + /* Check if the two ends match */ + if (source_fmt->format.width != sink_fmt->format.width || + source_fmt->format.height != sink_fmt->format.height) + return -EPIPE; + + if (source_fmt->format.code != sink_fmt->format.code) + return -EPIPE; + + return 0; +} + +/* + * resizer_init_formats - Initialize formats on all pads + * @sd: ISP RESIZER V4L2 subdevice + * @fh: V4L2 subdev file handle + * + * Initialize all pad formats with default values. If fh is not NULL, try + * formats are initialized on the file handle. Otherwise active formats are + * initialized on the device. + */ +static int resizer_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_subdev_format format; + + memset(&format, 0, sizeof(format)); + format.pad = RESIZER_PAD_SINK; + format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + format.format.code = V4L2_MBUS_FMT_UYVY8_1X16; + format.format.width = 4096; + format.format.height = 4096; + resizer_set_format(sd, fh, &format); + + return 0; +} + +/* V4L2 subdev video operations */ +static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = { + .s_stream = resizer_set_stream, +}; + +/* V4L2 subdev pad operations */ +static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = { + .enum_mbus_code = resizer_enum_mbus_code, + .enum_frame_size = resizer_enum_frame_size, + .get_fmt = resizer_get_format, + .set_fmt = resizer_set_format, + .link_validate = resizer_link_validate, +}; + +/* V4L2 subdev operations */ +static const struct v4l2_subdev_ops resizer_v4l2_ops = { + .video = &resizer_v4l2_video_ops, + .pad = &resizer_v4l2_pad_ops, +}; + +/* V4L2 subdev internal operations */ +static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = { + .open = resizer_init_formats, +}; + +/* ----------------------------------------------------------------------------- + * Media entity operations + */ + +/* + * resizer_link_setup - Setup RESIZER connections + * @entity: RESIZER media entity + * @local: Pad at the local end of the link + * @remote: Pad at the remote end of the link + * @flags: Link flags + * + * return -EINVAL or zero on success + */ +static int resizer_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); + struct iss_device *iss = to_iss_device(resizer); + + switch (local->index | media_entity_type(remote->entity)) { + case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: + /* Read from IPIPE or IPIPEIF. */ + if (!(flags & MEDIA_LNK_FL_ENABLED)) { + resizer->input = RESIZER_INPUT_NONE; + break; + } + + if (resizer->input != RESIZER_INPUT_NONE) + return -EBUSY; + + if (remote->entity == &iss->ipipeif.subdev.entity) + resizer->input = RESIZER_INPUT_IPIPEIF; + else if (remote->entity == &iss->ipipe.subdev.entity) + resizer->input = RESIZER_INPUT_IPIPE; + + + break; + + case RESIZER_PAD_SOURCE_MEM | MEDIA_ENT_T_DEVNODE: + /* Write to memory */ + if (flags & MEDIA_LNK_FL_ENABLED) { + if (resizer->output & ~RESIZER_OUTPUT_MEMORY) + return -EBUSY; + resizer->output |= RESIZER_OUTPUT_MEMORY; + } else { + resizer->output &= ~RESIZER_OUTPUT_MEMORY; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* media operations */ +static const struct media_entity_operations resizer_media_ops = { + .link_setup = resizer_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; + +/* + * resizer_init_entities - Initialize V4L2 subdev and media entity + * @resizer: ISS ISP RESIZER module + * + * Return 0 on success and a negative error code on failure. + */ +static int resizer_init_entities(struct iss_resizer_device *resizer) +{ + struct v4l2_subdev *sd = &resizer->subdev; + struct media_pad *pads = resizer->pads; + struct media_entity *me = &sd->entity; + int ret; + + resizer->input = RESIZER_INPUT_NONE; + + v4l2_subdev_init(sd, &resizer_v4l2_ops); + sd->internal_ops = &resizer_v4l2_internal_ops; + strlcpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name)); + sd->grp_id = 1 << 16; /* group ID for iss subdevs */ + v4l2_set_subdevdata(sd, resizer); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE; + + me->ops = &resizer_media_ops; + ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0); + if (ret < 0) + return ret; + + resizer_init_formats(sd, NULL); + + resizer->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + resizer->video_out.ops = &resizer_video_ops; + resizer->video_out.iss = to_iss_device(resizer); + resizer->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; + resizer->video_out.bpl_alignment = 32; + resizer->video_out.bpl_zero_padding = 1; + resizer->video_out.bpl_max = 0x1ffe0; + + ret = omap4iss_video_init(&resizer->video_out, "ISP resizer a"); + if (ret < 0) + return ret; + + /* Connect the RESIZER subdev to the video node. */ + ret = media_entity_create_link(&resizer->subdev.entity, RESIZER_PAD_SOURCE_MEM, + &resizer->video_out.video.entity, 0, 0); + if (ret < 0) + return ret; + + return 0; +} + +void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer) +{ + media_entity_cleanup(&resizer->subdev.entity); + + v4l2_device_unregister_subdev(&resizer->subdev); + omap4iss_video_unregister(&resizer->video_out); +} + +int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, + struct v4l2_device *vdev) +{ + int ret; + + /* Register the subdev and video node. */ + ret = v4l2_device_register_subdev(vdev, &resizer->subdev); + if (ret < 0) + goto error; + + ret = omap4iss_video_register(&resizer->video_out, vdev); + if (ret < 0) + goto error; + + return 0; + +error: + omap4iss_resizer_unregister_entities(resizer); + return ret; +} + +/* ----------------------------------------------------------------------------- + * ISP RESIZER initialisation and cleanup + */ + +/* + * omap4iss_resizer_init - RESIZER module initialization. + * @iss: Device pointer specific to the OMAP4 ISS. + * + * TODO: Get the initialisation values from platform data. + * + * Return 0 on success or a negative error code otherwise. + */ +int omap4iss_resizer_init(struct iss_device *iss) +{ + struct iss_resizer_device *resizer = &iss->resizer; + + resizer->state = ISS_PIPELINE_STREAM_STOPPED; + init_waitqueue_head(&resizer->wait); + + return resizer_init_entities(resizer); +} + +/* + * omap4iss_resizer_cleanup - RESIZER module cleanup. + * @iss: Device pointer specific to the OMAP4 ISS. + */ +void omap4iss_resizer_cleanup(struct iss_device *iss) +{ + /* FIXME: are you sure there's nothing to do? */ +} diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h new file mode 100644 index 000000000000..3727498b06a3 --- /dev/null +++ b/drivers/staging/media/omap4iss/iss_resizer.h @@ -0,0 +1,75 @@ +/* + * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Author: Sergio Aguirre + * + * 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 OMAP4_ISS_RESIZER_H +#define OMAP4_ISS_RESIZER_H + +#include "iss_video.h" + +enum resizer_input_entity { + RESIZER_INPUT_NONE, + RESIZER_INPUT_IPIPE, + RESIZER_INPUT_IPIPEIF +}; + +#define RESIZER_OUTPUT_MEMORY (1 << 0) + +/* Sink and source RESIZER pads */ +#define RESIZER_PAD_SINK 0 +#define RESIZER_PAD_SOURCE_MEM 1 +#define RESIZER_PADS_NUM 2 + +/* + * struct iss_resizer_device - Structure for the RESIZER module to store its own + * information + * @subdev: V4L2 subdevice + * @pads: Sink and source media entity pads + * @formats: Active video formats + * @input: Active input + * @output: Active outputs + * @video_out: Output video node + * @error: A hardware error occurred during capture + * @state: Streaming state + * @wait: Wait queue used to stop the module + * @stopping: Stopping state + */ +struct iss_resizer_device { + struct v4l2_subdev subdev; + struct media_pad pads[RESIZER_PADS_NUM]; + struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM]; + + enum resizer_input_entity input; + unsigned int output; + struct iss_video video_out; + unsigned int error; + + enum iss_pipeline_stream_state state; + wait_queue_head_t wait; + atomic_t stopping; +}; + +struct iss_device; + +int omap4iss_resizer_init(struct iss_device *iss); +void omap4iss_resizer_cleanup(struct iss_device *iss); +int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, + struct v4l2_device *vdev); +void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer); + +int omap4iss_resizer_busy(struct iss_resizer_device *resizer); +void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events); +void omap4iss_resizer_restore_context(struct iss_device *iss); +void omap4iss_resizer_max_rate(struct iss_resizer_device *resizer, + unsigned int *max_rate); + +#endif /* OMAP4_ISS_RESIZER_H */ -- cgit v1.2.3 From d632dfefd36f0794dd69a41f86bfff2cc0e5af73 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 2 Oct 2013 20:27:07 -0300 Subject: [media] v4l: omap4iss: Add support for OMAP4 camera interface - Build system This adds a very simplistic driver to utilize the CSI2A interface inside the ISS subsystem in OMAP4, and dump the data to memory. Check Documentation/video4linux/omap4_camera.txt for details. This commit adds and updates Kconfig's and Makefile's, as well as a TODO list. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/Kconfig | 2 ++ drivers/staging/media/Makefile | 1 + drivers/staging/media/omap4iss/Kconfig | 12 ++++++++++++ drivers/staging/media/omap4iss/Makefile | 6 ++++++ drivers/staging/media/omap4iss/TODO | 4 ++++ 5 files changed, 25 insertions(+) create mode 100644 drivers/staging/media/omap4iss/Kconfig create mode 100644 drivers/staging/media/omap4iss/Makefile create mode 100644 drivers/staging/media/omap4iss/TODO (limited to 'drivers') diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 46f1e619cbd8..bc4c7982360e 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -33,6 +33,8 @@ source "drivers/staging/media/msi3101/Kconfig" source "drivers/staging/media/solo6x10/Kconfig" +source "drivers/staging/media/omap4iss/Kconfig" + # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index eb7f30b1ccd8..a528d3f40105 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_USB_MSI3101) += msi3101/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ +obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig new file mode 100644 index 000000000000..b9fe753969bd --- /dev/null +++ b/drivers/staging/media/omap4iss/Kconfig @@ -0,0 +1,12 @@ +config VIDEO_OMAP4 + bool "OMAP 4 Camera support" + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && I2C && ARCH_OMAP4 + select VIDEOBUF2_DMA_CONTIG + ---help--- + Driver for an OMAP 4 ISS controller. + +config VIDEO_OMAP4_DEBUG + bool "OMAP 4 Camera debug messages" + depends on VIDEO_OMAP4 + ---help--- + Enable debug messages on OMAP 4 ISS controller driver. diff --git a/drivers/staging/media/omap4iss/Makefile b/drivers/staging/media/omap4iss/Makefile new file mode 100644 index 000000000000..a716ce936cf6 --- /dev/null +++ b/drivers/staging/media/omap4iss/Makefile @@ -0,0 +1,6 @@ +# Makefile for OMAP4 ISS driver + +omap4-iss-objs += \ + iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o + +obj-$(CONFIG_VIDEO_OMAP4) += omap4-iss.o diff --git a/drivers/staging/media/omap4iss/TODO b/drivers/staging/media/omap4iss/TODO new file mode 100644 index 000000000000..fcde88860a2c --- /dev/null +++ b/drivers/staging/media/omap4iss/TODO @@ -0,0 +1,4 @@ +* Make the driver compile as a module +* Fix FIFO/buffer overflows and underflows +* Replace dummy resizer code with a real implementation +* Fix checkpatch errors and warnings -- cgit v1.2.3 From ea72717e961d1166882370a87876bfeacc967eb0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:13:32 -0300 Subject: [media] v4l: omap4iss: Don't use v4l2_g_ext_ctrls() internally Instead of using the extended control API internally to get the sensor pixel rate, use the dedicated in-kernel APIs (find the control with v4l2_ctrl_find() and get its value with v4l2_ctrl_g_ctrl_int64()). Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index d054d9b6eb0f..1a5cac94209e 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -121,8 +121,7 @@ int omap4iss_get_external_info(struct iss_pipeline *pipe, struct iss_device *iss = container_of(pipe, struct iss_video, pipe)->iss; struct v4l2_subdev_format fmt; - struct v4l2_ext_controls ctrls; - struct v4l2_ext_control ctrl; + struct v4l2_ctrl *ctrl; int ret; if (!pipe->external) @@ -142,23 +141,15 @@ int omap4iss_get_external_info(struct iss_pipeline *pipe, pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; - memset(&ctrls, 0, sizeof(ctrls)); - memset(&ctrl, 0, sizeof(ctrl)); - - ctrl.id = V4L2_CID_PIXEL_RATE; - - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(ctrl.id); - ctrls.count = 1; - ctrls.controls = &ctrl; - - ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls); - if (ret < 0) { + ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler, + V4L2_CID_PIXEL_RATE); + if (ctrl == NULL) { dev_warn(iss->dev, "no pixel rate control in subdev %s\n", pipe->external->name); - return ret; + return -EPIPE; } - pipe->external_rate = ctrl.value64; + pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); return 0; } -- cgit v1.2.3 From cce093ee559779d376fbd767d70a5b0ce4cf015a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:17:51 -0300 Subject: [media] v4l: omap4iss: Move common code out of switch...case Code common to all cases can be moved out of the switch...case statement. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 1a5cac94209e..243fcb8b12be 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -178,12 +178,10 @@ void omap4iss_configure_bridge(struct iss_device *iss, switch (input) { case IPIPEIF_INPUT_CSI2A: issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A; - isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT; break; case IPIPEIF_INPUT_CSI2B: issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B; - isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT; break; default: @@ -192,7 +190,8 @@ void omap4iss_configure_bridge(struct iss_device *iss, issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING; - isp5ctrl_val |= ISP5_CTRL_PSYNC_CLK_SEL | ISP5_CTRL_SYNC_ENABLE; + isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL | + ISP5_CTRL_SYNC_ENABLE; writel(issctrl_val, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); writel(isp5ctrl_val, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); -- cgit v1.2.3 From 35c71be8c75dbf80d30f37347a5b2be19761f83e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Report device caps in response to VIDIOC_QUERYCAP Set the v4l2_capability capabilities and device_caps fields correctly. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 31f1b8805711..bab62d762add 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -480,9 +480,12 @@ iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) strlcpy(cap->bus_info, "media", sizeof(cap->bus_info)); if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; else - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + + cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING + | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT; return 0; } -- cgit v1.2.3 From f33354f0451dc6bf339052f28078a5e139fcf38c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Remove iss_video streaming field The vb2 queue already keeps track of the streaming state, there's no need to duplicate that in the driver. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 9 --------- drivers/staging/media/omap4iss/iss_video.h | 3 --- 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index bab62d762add..1cdfc4339498 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -743,11 +743,6 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) mutex_lock(&video->stream_lock); - if (video->streaming) { - mutex_unlock(&video->stream_lock); - return -EBUSY; - } - /* Start streaming on the pipeline. No link touching an entity in the * pipeline can be activated or deactivated once streaming is started. */ @@ -842,9 +837,6 @@ err_media_entity_pipeline_start: video->queue = NULL; } - if (!ret) - video->streaming = 1; - mutex_unlock(&video->stream_lock); return ret; } @@ -882,7 +874,6 @@ iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) omap4iss_pipeline_set_stream(pipe, ISS_PIPELINE_STREAM_STOPPED); vb2_streamoff(&vfh->queue, type); video->queue = NULL; - video->streaming = 0; if (video->iss->pdata->set_constraints) video->iss->pdata->set_constraints(video->iss, false); diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index 8cf1b3500e44..35f14d84330b 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -156,9 +156,6 @@ struct iss_video { unsigned int bpl_value; /* bytes per line value */ unsigned int bpl_padding; /* padding at end of line */ - /* Entity video node streaming */ - unsigned int streaming:1; - /* Pipeline state */ struct iss_pipeline pipe; struct mutex stream_lock; /* pipeline and stream states */ -- cgit v1.2.3 From bb4e7d6ea2b1e97348f8ac4be5b9493b70d9d54e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Set the vb2 timestamp type Timestamps use the monotonic clock, configure the vb2 queue accordingly. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 1cdfc4339498..ee3005482c48 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -972,6 +972,7 @@ static int iss_video_open(struct file *file) q->ops = &iss_video_vb2ops; q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct iss_buffer); + q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ret = vb2_queue_init(q); if (ret) { -- cgit v1.2.3 From 2b7f0b641ab125e06db707bee47ddf3f19218cbb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Remove duplicate video_is_registered() check The video_unregister_device() function checks if the video device is registered before proceeding, remote the duplicate check from the driver. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index ee3005482c48..ccbdecd0114c 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -1119,6 +1119,5 @@ int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev) void omap4iss_video_unregister(struct iss_video *video) { - if (video_is_registered(&video->video)) - video_unregister_device(&video->video); + video_unregister_device(&video->video); } -- cgit v1.2.3 From 57da5e47ccf3d727958aeef7675154d48635fa09 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Remove unneeded status variable The failure variable is initialized with 0 and used as a return value without ever being modified. Remove it and return 0 directly. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 243fcb8b12be..320bfd418218 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -560,7 +560,6 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe) struct media_entity *entity; struct media_pad *pad; struct v4l2_subdev *subdev; - int failure = 0; entity = &pipe->output->video.entity; while (1) { @@ -579,7 +578,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe) v4l2_subdev_call(subdev, video, s_stream, 0); } - return failure; + return 0; } /* -- cgit v1.2.3 From ca6f19b1cf0fac0fdf1ef06d6bed0f07f8f37ae9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Replace udelay/msleep with usleep_range The only udelay() call takes place in a sleepable context, we can sleep instead. Use usleep_range(). Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 320bfd418218..3103093f843d 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -642,11 +642,11 @@ static int iss_reset(struct iss_device *iss) while (readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) & ISS_HL_SYSCONFIG_SOFTRESET) { - if (timeout++ > 10000) { + if (timeout++ > 100) { dev_alert(iss->dev, "cannot reset ISS\n"); return -ETIMEDOUT; } - udelay(1); + usleep_range(10, 10); } return 0; @@ -674,7 +674,7 @@ static int iss_isp_reset(struct iss_device *iss) dev_alert(iss->dev, "cannot set ISP5 to standby\n"); return -ETIMEDOUT; } - msleep(1); + usleep_range(1000, 1500); } /* Now finally, do the reset */ @@ -689,7 +689,7 @@ static int iss_isp_reset(struct iss_device *iss) dev_alert(iss->dev, "cannot reset ISP5\n"); return -ETIMEDOUT; } - msleep(1); + usleep_range(1000, 1500); } return 0; -- cgit v1.2.3 From 68c03a666c36068428fed43010bde521d4341079 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Make omap4iss_isp_subclk_(en|dis)able() functions void The functions always succeed, there's no need to return an error value. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 14 ++++++-------- drivers/staging/media/omap4iss/iss.h | 6 +++--- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 3103093f843d..043a3f3b2426 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -836,7 +836,7 @@ int omap4iss_subclk_disable(struct iss_device *iss, ISP5_CTRL_IPIPE_CLK_ENABLE |\ ISP5_CTRL_IPIPEIF_CLK_ENABLE) -static int __iss_isp_subclk_update(struct iss_device *iss) +static void __iss_isp_subclk_update(struct iss_device *iss) { u32 clk = 0; @@ -861,24 +861,22 @@ static int __iss_isp_subclk_update(struct iss_device *iss) writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & ~ISS_ISP5_CLKCTRL_MASK) | clk, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); - - return 0; } -int omap4iss_isp_subclk_enable(struct iss_device *iss, +void omap4iss_isp_subclk_enable(struct iss_device *iss, enum iss_isp_subclk_resource res) { iss->isp_subclk_resources |= res; - return __iss_isp_subclk_update(iss); + __iss_isp_subclk_update(iss); } -int omap4iss_isp_subclk_disable(struct iss_device *iss, - enum iss_isp_subclk_resource res) +void omap4iss_isp_subclk_disable(struct iss_device *iss, + enum iss_isp_subclk_resource res) { iss->isp_subclk_resources &= ~res; - return __iss_isp_subclk_update(iss); + __iss_isp_subclk_update(iss); } /* diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index cc24f1ae17c6..f33664d1d7cf 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -136,10 +136,10 @@ int omap4iss_subclk_enable(struct iss_device *iss, enum iss_subclk_resource res); int omap4iss_subclk_disable(struct iss_device *iss, enum iss_subclk_resource res); -int omap4iss_isp_subclk_enable(struct iss_device *iss, - enum iss_isp_subclk_resource res); -int omap4iss_isp_subclk_disable(struct iss_device *iss, +void omap4iss_isp_subclk_enable(struct iss_device *iss, enum iss_isp_subclk_resource res); +void omap4iss_isp_subclk_disable(struct iss_device *iss, + enum iss_isp_subclk_resource res); void omap4iss_isp_enable_interrupts(struct iss_device *iss); void omap4iss_isp_disable_interrupts(struct iss_device *iss); -- cgit v1.2.3 From 4334fd18e2bcf9c6aa7c535c25b05b462aab05b3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Make loop counters unsigned where appropriate Loop counters that can only take positive values should be unsigned. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 043a3f3b2426..c7dffa656564 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1290,7 +1290,8 @@ static int iss_probe(struct platform_device *pdev) { struct iss_platform_data *pdata = pdev->dev.platform_data; struct iss_device *iss; - int i, ret; + unsigned int i; + int ret; if (pdata == NULL) return -EINVAL; @@ -1414,7 +1415,7 @@ error: static int iss_remove(struct platform_device *pdev) { struct iss_device *iss = platform_get_drvdata(pdev); - int i; + unsigned int i; iss_unregister_entities(iss); iss_cleanup_modules(iss); -- cgit v1.2.3 From 245d6b2d505b0575b34e5c02b694bf2e476904b4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Don't initialize fields to 0 manually The iss_device structure is allocated with kzalloc, there's no need to initialize its fields to 0 explicitly. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index c7dffa656564..7d427d541fd3 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1306,7 +1306,6 @@ static int iss_probe(struct platform_device *pdev) iss->dev = &pdev->dev; iss->pdata = pdata; - iss->ref_count = 0; iss->raw_dmamask = DMA_BIT_MASK(32); iss->dev->dma_mask = &iss->raw_dmamask; -- cgit v1.2.3 From 2b16b44a1c44814ed00cf750d20f3c404b5d4e48 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Simplify error paths Get rid of a goto statement for a simple error path that can be inlined, and split spaghetti error code to a separate section. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 20 +++++++++----------- drivers/staging/media/omap4iss/iss_video.c | 15 ++++++++------- 2 files changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 7d427d541fd3..b7c8a6bc7d80 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -887,24 +887,22 @@ void omap4iss_isp_subclk_disable(struct iss_device *iss, */ static int iss_enable_clocks(struct iss_device *iss) { - int r; + int ret; - r = clk_enable(iss->iss_fck); - if (r) { + ret = clk_enable(iss->iss_fck); + if (ret) { dev_err(iss->dev, "clk_enable iss_fck failed\n"); - return r; + return ret; } - r = clk_enable(iss->iss_ctrlclk); - if (r) { + ret = clk_enable(iss->iss_ctrlclk); + if (ret) { dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n"); - goto out_clk_enable_ctrlclk; + clk_disable(iss->iss_fck); + return ret; } - return 0; -out_clk_enable_ctrlclk: - clk_disable(iss->iss_fck); - return r; + return 0; } /* diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index ccbdecd0114c..a527330abc34 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -826,16 +826,17 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) spin_unlock_irqrestore(&video->qlock, flags); } - if (ret < 0) { + mutex_unlock(&video->stream_lock); + return 0; + err_omap4iss_set_stream: - vb2_streamoff(&vfh->queue, type); + vb2_streamoff(&vfh->queue, type); err_iss_video_check_format: - media_entity_pipeline_stop(&video->video.entity); + media_entity_pipeline_stop(&video->video.entity); err_media_entity_pipeline_start: - if (video->iss->pdata->set_constraints) - video->iss->pdata->set_constraints(video->iss, false); - video->queue = NULL; - } + if (video->iss->pdata->set_constraints) + video->iss->pdata->set_constraints(video->iss, false); + video->queue = NULL; mutex_unlock(&video->stream_lock); return ret; -- cgit v1.2.3 From e43484e42d5537ad2db11a1973790a105bed54ca Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Don't check for missing get_fmt op on remote subdev The remote subdev of any video node in the OMAP4 ISS is an internal subdev that is guaranteed to implement get_fmt. Don't check the return value for -ENOIOCTLCMD, as this can't happen. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index a527330abc34..0cb58206a564 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -248,8 +248,6 @@ __iss_video_get_format(struct iss_video *video, struct v4l2_format *format) fmt.pad = pad; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); - if (ret == -ENOIOCTLCMD) - ret = -EINVAL; mutex_unlock(&video->mutex); @@ -552,7 +550,7 @@ iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format) fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); if (ret) - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret; iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); return 0; -- cgit v1.2.3 From 4a62361f825325bd6dd228d3c05e254d40f74e47 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 3 Nov 2013 20:28:24 -0300 Subject: [media] v4l: omap4iss: Translate -ENOIOCTLCMD to -ENOTTY Translating -ENOIOCTLCMD to -EINVAL is invalid, the correct ioctl return value is -ENOTTY. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 0cb58206a564..63419b3769b5 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -571,7 +571,7 @@ iss_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap) ret = v4l2_subdev_call(subdev, video, cropcap, cropcap); mutex_unlock(&video->mutex); - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; } static int @@ -598,7 +598,7 @@ iss_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) format.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format); if (ret < 0) - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; crop->c.left = 0; crop->c.top = 0; @@ -623,7 +623,7 @@ iss_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop) ret = v4l2_subdev_call(subdev, video, s_crop, crop); mutex_unlock(&video->mutex); - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; } static int -- cgit v1.2.3 From c3dbc70d825968da10cf6fdde40447aeec632a2d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 4 Nov 2013 06:52:10 -0300 Subject: [media] v4l: omap4iss: Move code out of mutex-protected section The pad::get_fmt call must be protected by a mutex, but preparing its arguments doesn't need to be. Move the non-critical code out of the mutex-protected section. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 63419b3769b5..68006231cc41 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -243,12 +243,11 @@ __iss_video_get_format(struct iss_video *video, struct v4l2_format *format) if (subdev == NULL) return -EINVAL; - mutex_lock(&video->mutex); - fmt.pad = pad; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); + mutex_lock(&video->mutex); + ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); mutex_unlock(&video->mutex); if (ret) -- cgit v1.2.3 From 16422f552d4e70fa0953917e05f72033d629bdb8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 4 Nov 2013 06:59:26 -0300 Subject: [media] v4l: omap4iss: Implement VIDIOC_S_INPUT The ioctl is (at least currently) mandatory. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 68006231cc41..766491e6a8d0 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -902,6 +902,12 @@ iss_video_g_input(struct file *file, void *fh, unsigned int *input) return 0; } +static int +iss_video_s_input(struct file *file, void *fh, unsigned int input) +{ + return input == 0 ? 0 : -EINVAL; +} + static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { .vidioc_querycap = iss_video_querycap, .vidioc_g_fmt_vid_cap = iss_video_get_format, @@ -923,6 +929,7 @@ static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { .vidioc_streamoff = iss_video_streamoff, .vidioc_enum_input = iss_video_enum_input, .vidioc_g_input = iss_video_g_input, + .vidioc_s_input = iss_video_s_input, }; /* ----------------------------------------------------------------------------- -- cgit v1.2.3 From 61c358e3bc20abeab2ba2ae9625ca723409b6766 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5504: Mark transfer buffers as __be16 Fixes the following warnings from sparse: drivers/iio/dac/ad5504.c:71:19: warning: incorrect type in initializer (different base types) drivers/iio/dac/ad5504.c:71:19: expected unsigned short [unsigned] [usertype] tmp drivers/iio/dac/ad5504.c:71:19: got restricted __be16 [usertype] drivers/iio/dac/ad5504.c:80:19: warning: incorrect type in initializer (different base types) drivers/iio/dac/ad5504.c:80:19: expected unsigned short [unsigned] [usertype] tmp drivers/iio/dac/ad5504.c:80:19: got restricted __be16 [usertype] drivers/iio/dac/ad5504.c:93:16: warning: cast to restricted __be16 drivers/iio/dac/ad5504.c:93:16: warning: cast to restricted __be16 drivers/iio/dac/ad5504.c:93:16: warning: cast to restricted __be16 drivers/iio/dac/ad5504.c:93:16: warning: cast to restricted __be16 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5504.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index c0957a918e17..6cd0dd60c17f 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -68,7 +68,7 @@ enum ad5504_supported_device_ids { static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) { - u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | + __be16 tmp = cpu_to_be16(AD5504_CMD_WRITE | AD5504_ADDR(addr) | (val & AD5504_RES_MASK)); @@ -77,8 +77,8 @@ static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) static int ad5504_spi_read(struct spi_device *spi, u8 addr) { - u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); - u16 val; + __be16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); + __be16 val; int ret; struct spi_transfer t = { .tx_buf = &tmp, -- cgit v1.2.3 From 0dbe59c7a78811144cd1860c5bc603eb6b536cfb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5504: Do not store transfer buffers on the stack Some SPI controllers may not be able to handle transfer buffers that are placed on the stack. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5504.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index 6cd0dd60c17f..d44c8f5fadee 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -47,14 +47,16 @@ * @vref_mv: actual reference voltage used * @pwr_down_mask power down mask * @pwr_down_mode current power down mode + * @data: transfer buffer */ - struct ad5504_state { struct spi_device *spi; struct regulator *reg; unsigned short vref_mv; unsigned pwr_down_mask; unsigned pwr_down_mode; + + __be16 data[2] ____cacheline_aligned; }; /** @@ -66,31 +68,29 @@ enum ad5504_supported_device_ids { ID_AD5501, }; -static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) +static int ad5504_spi_write(struct ad5504_state *st, u8 addr, u16 val) { - __be16 tmp = cpu_to_be16(AD5504_CMD_WRITE | - AD5504_ADDR(addr) | + st->data[0] = cpu_to_be16(AD5504_CMD_WRITE | AD5504_ADDR(addr) | (val & AD5504_RES_MASK)); - return spi_write(spi, (u8 *)&tmp, 2); + return spi_write(st->spi, &st->data[0], 2); } -static int ad5504_spi_read(struct spi_device *spi, u8 addr) +static int ad5504_spi_read(struct ad5504_state *st, u8 addr) { - __be16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); - __be16 val; int ret; - struct spi_transfer t = { - .tx_buf = &tmp, - .rx_buf = &val, - .len = 2, - }; - ret = spi_sync_transfer(spi, &t, 1); - + struct spi_transfer t = { + .tx_buf = &st->data[0], + .rx_buf = &st->data[1], + .len = 2, + }; + + st->data[0] = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); + ret = spi_sync_transfer(st->spi, &t, 1); if (ret < 0) return ret; - return be16_to_cpu(val) & AD5504_RES_MASK; + return be16_to_cpu(st->data[1]) & AD5504_RES_MASK; } static int ad5504_read_raw(struct iio_dev *indio_dev, @@ -104,7 +104,7 @@ static int ad5504_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - ret = ad5504_spi_read(st->spi, chan->address); + ret = ad5504_spi_read(st, chan->address); if (ret < 0) return ret; @@ -133,7 +133,7 @@ static int ad5504_write_raw(struct iio_dev *indio_dev, if (val >= (1 << chan->scan_type.realbits) || val < 0) return -EINVAL; - return ad5504_spi_write(st->spi, chan->address, val); + return ad5504_spi_write(st, chan->address, val); default: ret = -EINVAL; } @@ -197,12 +197,12 @@ static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev, else st->pwr_down_mask &= ~(1 << chan->channel); - ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL, + ret = ad5504_spi_write(st, AD5504_ADDR_CTRL, AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | AD5504_DAC_PWR(st->pwr_down_mask)); /* writes to the CTRL register must be followed by a NOOP */ - ad5504_spi_write(st->spi, AD5504_ADDR_NOOP, 0); + ad5504_spi_write(st, AD5504_ADDR_NOOP, 0); return ret ? ret : len; } -- cgit v1.2.3 From 8ef411b78bfb2fc165ed11818c817256d3bc89cd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5421: Mark transfer buffer as __be32 Fixes the following warnings from sparse: drivers/iio/dac/ad5421.c:134:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5421.c:134:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5421.c:134:25: got restricted __be32 [usertype] drivers/iio/dac/ad5421.c:168:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5421.c:168:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5421.c:168:25: got restricted __be32 [usertype] drivers/iio/dac/ad5421.c:172:23: warning: cast to restricted __be32 drivers/iio/dac/ad5421.c:172:23: warning: cast to restricted __be32 drivers/iio/dac/ad5421.c:172:23: warning: cast to restricted __be32 drivers/iio/dac/ad5421.c:172:23: warning: cast to restricted __be32 drivers/iio/dac/ad5421.c:172:23: warning: cast to restricted __be32 drivers/iio/dac/ad5421.c:172:23: warning: cast to restricted __be32 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5421.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index 7d1e90811c71..59a0cb51265c 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -75,7 +75,7 @@ struct ad5421_state { * transfer buffers to live in their own cache lines. */ union { - u32 d32; + __be32 d32; u8 d8[4]; } data[2] ____cacheline_aligned; }; -- cgit v1.2.3 From cf87534b6f34ee5fdef4ec98b4e54ec36d7c9a88 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5686: Mark transfer buffer as __be32 Fixes the following warnings from sparse: drivers/iio/dac/ad5686.c:100:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5686.c:100:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5686.c:100:25: got restricted __be32 [usertype] drivers/iio/dac/ad5686.c:122:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5686.c:122:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5686.c:122:25: got restricted __be32 [usertype] drivers/iio/dac/ad5686.c:124:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5686.c:124:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5686.c:124:25: got restricted __be32 [usertype] drivers/iio/dac/ad5686.c:130:16: warning: cast to restricted __be32 drivers/iio/dac/ad5686.c:130:16: warning: cast to restricted __be32 drivers/iio/dac/ad5686.c:130:16: warning: cast to restricted __be32 drivers/iio/dac/ad5686.c:130:16: warning: cast to restricted __be32 drivers/iio/dac/ad5686.c:130:16: warning: cast to restricted __be32 drivers/iio/dac/ad5686.c:130:16: warning: cast to restricted __be32 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 30e506e37dd2..e56ec0abb509 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -78,7 +78,7 @@ struct ad5686_state { */ union { - u32 d32; + __be32 d32; u8 d8[4]; } data[3] ____cacheline_aligned; }; -- cgit v1.2.3 From edc05f26145c925deeeb7bfa50622e2cb22569b3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5755: Mark transfer buffer as __be32 Fixes the following warnings from sparse: drivers/iio/dac/ad5755.c:117:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5755.c:117:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5755.c:117:25: got restricted __be32 [usertype] drivers/iio/dac/ad5755.c:171:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5755.c:171:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5755.c:171:25: got restricted __be32 [usertype] drivers/iio/dac/ad5755.c:172:25: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5755.c:172:25: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5755.c:172:25: got restricted __be32 [usertype] drivers/iio/dac/ad5755.c:176:23: warning: cast to restricted __be32 drivers/iio/dac/ad5755.c:176:23: warning: cast to restricted __be32 drivers/iio/dac/ad5755.c:176:23: warning: cast to restricted __be32 drivers/iio/dac/ad5755.c:176:23: warning: cast to restricted __be32 drivers/iio/dac/ad5755.c:176:23: warning: cast to restricted __be32 drivers/iio/dac/ad5755.c:176:23: warning: cast to restricted __be32 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5755.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index ee1e95a3a0c3..c494276da4b0 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -97,7 +97,7 @@ struct ad5755_state { */ union { - u32 d32; + __be32 d32; u8 d8[4]; } data[2] ____cacheline_aligned; }; -- cgit v1.2.3 From ae8bb9b10124ff266c35507b347b31f34c0fe05d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5791: Mark transfer buffers as __be32 Fixes the following warnings from sparse: drivers/iio/dac/ad5791.c:114:18: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5791.c:114:18: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5791.c:114:18: got restricted __be32 [usertype] drivers/iio/dac/ad5791.c:142:21: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5791.c:142:21: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5791.c:142:21: got restricted __be32 [usertype] drivers/iio/dac/ad5791.c:144:21: warning: incorrect type in assignment (different base types) drivers/iio/dac/ad5791.c:144:21: expected unsigned int [unsigned] [usertype] d32 drivers/iio/dac/ad5791.c:144:21: got restricted __be32 [usertype] drivers/iio/dac/ad5791.c:148:16: warning: cast to restricted __be32 drivers/iio/dac/ad5791.c:148:16: warning: cast to restricted __be32 drivers/iio/dac/ad5791.c:148:16: warning: cast to restricted __be32 drivers/iio/dac/ad5791.c:148:16: warning: cast to restricted __be32 drivers/iio/dac/ad5791.c:148:16: warning: cast to restricted __be32 drivers/iio/dac/ad5791.c:148:16: warning: cast to restricted __be32 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5791.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index d64acbd89482..1e7f4cd7db83 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -107,7 +107,7 @@ enum ad5791_supported_device_ids { static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) { union { - u32 d32; + __be32 d32; u8 d8[4]; } data; @@ -121,7 +121,7 @@ static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) { union { - u32 d32; + __be32 d32; u8 d8[4]; } data[3]; int ret; -- cgit v1.2.3 From 791bb52a0cd2cc95f030e461cfafe26448bc6618 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:41:00 +0000 Subject: iio:ad5791: Do not store transfer buffers on the stack Some SPI controllers may not be able to handle transfer buffers that are placed on the stack. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5791.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 1e7f4cd7db83..79bf19945747 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -91,6 +91,11 @@ struct ad5791_state { unsigned ctrl; unsigned pwr_down_mode; bool pwr_down; + + union { + __be32 d32; + u8 d8[4]; + } data[3] ____cacheline_aligned; }; /** @@ -104,48 +109,39 @@ enum ad5791_supported_device_ids { ID_AD5791, }; -static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) +static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val) { - union { - __be32 d32; - u8 d8[4]; - } data; - - data.d32 = cpu_to_be32(AD5791_CMD_WRITE | + st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE | AD5791_ADDR(addr) | (val & AD5791_DAC_MASK)); - return spi_write(spi, &data.d8[1], 3); + return spi_write(st->spi, &st->data[0].d8[1], 3); } -static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) +static int ad5791_spi_read(struct ad5791_state *st, u8 addr, u32 *val) { - union { - __be32 d32; - u8 d8[4]; - } data[3]; int ret; struct spi_transfer xfers[] = { { - .tx_buf = &data[0].d8[1], + .tx_buf = &st->data[0].d8[1], .bits_per_word = 8, .len = 3, .cs_change = 1, }, { - .tx_buf = &data[1].d8[1], - .rx_buf = &data[2].d8[1], + .tx_buf = &st->data[1].d8[1], + .rx_buf = &st->data[2].d8[1], .bits_per_word = 8, .len = 3, }, }; - data[0].d32 = cpu_to_be32(AD5791_CMD_READ | + st->data[0].d32 = cpu_to_be32(AD5791_CMD_READ | AD5791_ADDR(addr)); - data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); + st->data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); - ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); - *val = be32_to_cpu(data[2].d32); + *val = be32_to_cpu(st->data[2].d32); return ret; } @@ -210,7 +206,7 @@ static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev, } st->pwr_down = pwr_down; - ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl); + ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl); return ret ? ret : len; } @@ -263,7 +259,7 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - ret = ad5791_spi_read(st->spi, chan->address, val); + ret = ad5791_spi_read(st, chan->address, val); if (ret) return ret; *val &= AD5791_DAC_MASK; @@ -330,7 +326,7 @@ static int ad5791_write_raw(struct iio_dev *indio_dev, val &= AD5791_RES_MASK(chan->scan_type.realbits); val <<= chan->scan_type.shift; - return ad5791_spi_write(st->spi, chan->address, val); + return ad5791_spi_write(st, chan->address, val); default: return -EINVAL; @@ -393,7 +389,7 @@ static int ad5791_probe(struct spi_device *spi) dev_warn(&spi->dev, "reference voltage unspecified\n"); } - ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); + ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); if (ret) goto error_disable_reg_neg; @@ -405,7 +401,7 @@ static int ad5791_probe(struct spi_device *spi) | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) | AD5791_CTRL_BIN2SC; - ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl | + ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl | AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); if (ret) goto error_disable_reg_neg; -- cgit v1.2.3 From 54e018da3141dbb41f3578d48be575087339710f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: iio:ad7266: Mark transfer buffer as __be16 Fixes the following warnings from sparse: drivers/iio/adc/ad7266.c:140:16: warning: cast to restricted __be16 drivers/iio/adc/ad7266.c:140:16: warning: cast to restricted __be16 drivers/iio/adc/ad7266.c:140:16: warning: cast to restricted __be16 drivers/iio/adc/ad7266.c:140:16: warning: cast to restricted __be16 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7266.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 58e945594c7b..70f78c3062a7 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -43,19 +43,22 @@ struct ad7266_state { * The buffer needs to be large enough to hold two samples (4 bytes) and * the naturally aligned timestamp (8 bytes). */ - uint8_t data[ALIGN(4, sizeof(s64)) + sizeof(s64)] ____cacheline_aligned; + struct { + __be16 sample[2]; + s64 timestamp; + } data ____cacheline_aligned; }; static int ad7266_wakeup(struct ad7266_state *st) { /* Any read with >= 2 bytes will wake the device */ - return spi_read(st->spi, st->data, 2); + return spi_read(st->spi, &st->data.sample[0], 2); } static int ad7266_powerdown(struct ad7266_state *st) { /* Any read with < 2 bytes will powerdown the device */ - return spi_read(st->spi, st->data, 1); + return spi_read(st->spi, &st->data.sample[0], 1); } static int ad7266_preenable(struct iio_dev *indio_dev) @@ -84,9 +87,9 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) struct ad7266_state *st = iio_priv(indio_dev); int ret; - ret = spi_read(st->spi, st->data, 4); + ret = spi_read(st->spi, st->data.sample, 4); if (ret == 0) { - iio_push_to_buffers_with_timestamp(indio_dev, st->data, + iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp); } @@ -137,7 +140,7 @@ static int ad7266_read_single(struct ad7266_state *st, int *val, ad7266_select_input(st, address); ret = spi_sync(st->spi, &st->single_msg); - *val = be16_to_cpu(st->data[address % 2]); + *val = be16_to_cpu(st->data.sample[address % 2]); return ret; } @@ -442,15 +445,15 @@ static int ad7266_probe(struct spi_device *spi) ad7266_init_channels(indio_dev); /* wakeup */ - st->single_xfer[0].rx_buf = &st->data; + st->single_xfer[0].rx_buf = &st->data.sample[0]; st->single_xfer[0].len = 2; st->single_xfer[0].cs_change = 1; /* conversion */ - st->single_xfer[1].rx_buf = &st->data; + st->single_xfer[1].rx_buf = st->data.sample; st->single_xfer[1].len = 4; st->single_xfer[1].cs_change = 1; /* powerdown */ - st->single_xfer[2].tx_buf = &st->data; + st->single_xfer[2].tx_buf = &st->data.sample[0]; st->single_xfer[2].len = 1; spi_message_init(&st->single_msg); -- cgit v1.2.3 From 91f197e0c0ceda88c442f7adce6a84e5faa53586 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: iio:vcnl4000: Mark transfer buffer as __be16 Fixes the following warnings from sparse: drivers/iio/light/vcnl4000.c:88:16: warning: cast to restricted __be16 drivers/iio/light/vcnl4000.c:88:16: warning: cast to restricted __be16 drivers/iio/light/vcnl4000.c:88:16: warning: cast to restricted __be16 drivers/iio/light/vcnl4000.c:88:16: warning: cast to restricted __be16 Signed-off-by: Lars-Peter Clausen Cc: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/light/vcnl4000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 384ac23f576f..d948c4778ba6 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -56,7 +56,7 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, u8 rdy_mask, u8 data_reg, int *val) { int tries = 20; - u16 buf; + __be16 buf; int ret; ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, -- cgit v1.2.3 From b39c47d1930191120d290e664740ba7ae04d0134 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: staging:iio:ad7280a: Mark transfer buffer as __be32 Fixes the following warnings from sparse: drivers/staging/iio/adc/ad7280a.c:194:35: warning: incorrect type in initializer (different base types) drivers/staging/iio/adc/ad7280a.c:194:35: expected unsigned int [unsigned] tx_buf drivers/staging/iio/adc/ad7280a.c:194:35: got restricted __be32 [usertype] drivers/staging/iio/adc/ad7280a.c:207:16: warning: cast to restricted __be32 drivers/staging/iio/adc/ad7280a.c:207:16: warning: cast to restricted __be32 drivers/staging/iio/adc/ad7280a.c:207:16: warning: cast to restricted __be32 drivers/staging/iio/adc/ad7280a.c:207:16: warning: cast to restricted __be32 drivers/staging/iio/adc/ad7280a.c:207:16: warning: cast to restricted __be32 drivers/staging/iio/adc/ad7280a.c:207:16: warning: cast to restricted __be32 drivers/staging/iio/adc/ad7280a.c:219:13: warning: incorrect type in assignment (different base types) drivers/staging/iio/adc/ad7280a.c:219:13: expected unsigned int [unsigned] [assigned] reg drivers/staging/iio/adc/ad7280a.c:219:13: got restricted __be32 [usertype] Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 8209fa542a8a..89ee65bdc279 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -191,7 +191,7 @@ static void ad7280_delay(struct ad7280_state *st) static int __ad7280_read32(struct spi_device *spi, unsigned *val) { - unsigned rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL); + __be32 rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL); int ret; struct spi_transfer t = { @@ -214,11 +214,12 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr, { unsigned reg = (devaddr << 27 | addr << 21 | (val & 0xFF) << 13 | all << 12); + __be32 tx_buf; reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; - reg = cpu_to_be32(reg); + tx_buf = cpu_to_be32(reg); - return spi_write(st->spi, ®, 4); + return spi_write(st->spi, &tx_buf, 4); } static int ad7280_read(struct ad7280_state *st, unsigned devaddr, -- cgit v1.2.3 From 93dbad639d93300977ed76acc0db20771cca98f7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: staging:iio:ad7280a: Do not store transfer buffer on the stack Some I2C controllers may not be able to handle transfer buffers that are placed on the stack. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 89ee65bdc279..1ac11f64827c 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -134,6 +134,8 @@ struct ad7280_state { unsigned char aux_threshhigh; unsigned char aux_threshlow; unsigned char cb_mask[AD7280A_MAX_CHAIN]; + + __be32 buf[2] ____cacheline_aligned; }; static void ad7280_crc8_build_table(unsigned char *crc_tab) @@ -189,22 +191,22 @@ static void ad7280_delay(struct ad7280_state *st) msleep(1); } -static int __ad7280_read32(struct spi_device *spi, unsigned *val) +static int __ad7280_read32(struct ad7280_state *st, unsigned *val) { - __be32 rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL); int ret; - struct spi_transfer t = { - .tx_buf = &tx_buf, - .rx_buf = &rx_buf, + .tx_buf = &st->buf[0], + .rx_buf = &st->buf[1], .len = 4, }; - ret = spi_sync_transfer(spi, &t, 1); + st->buf[0] = cpu_to_be32(AD7280A_READ_TXVAL); + + ret = spi_sync_transfer(st->spi, &t, 1); if (ret) return ret; - *val = be32_to_cpu(rx_buf); + *val = be32_to_cpu(st->buf[1]); return 0; } @@ -214,12 +216,11 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr, { unsigned reg = (devaddr << 27 | addr << 21 | (val & 0xFF) << 13 | all << 12); - __be32 tx_buf; reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; - tx_buf = cpu_to_be32(reg); + st->buf[0] = cpu_to_be32(reg); - return spi_write(st->spi, &tx_buf, 4); + return spi_write(st->spi, &st->buf[0], 4); } static int ad7280_read(struct ad7280_state *st, unsigned devaddr, @@ -249,7 +250,7 @@ static int ad7280_read(struct ad7280_state *st, unsigned devaddr, if (ret) return ret; - __ad7280_read32(st->spi, &tmp); + __ad7280_read32(st, &tmp); if (ad7280_check_crc(st, tmp)) return -EIO; @@ -287,7 +288,7 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, ad7280_delay(st); - __ad7280_read32(st->spi, &tmp); + __ad7280_read32(st, &tmp); if (ad7280_check_crc(st, tmp)) return -EIO; @@ -320,7 +321,7 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, ad7280_delay(st); for (i = 0; i < cnt; i++) { - __ad7280_read32(st->spi, &tmp); + __ad7280_read32(st, &tmp); if (ad7280_check_crc(st, tmp)) return -EIO; @@ -363,7 +364,7 @@ static int ad7280_chain_setup(struct ad7280_state *st) return ret; for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { - __ad7280_read32(st->spi, &val); + __ad7280_read32(st, &val); if (val == 0) return n - 1; -- cgit v1.2.3 From d4adb07c7ad56283419170afe2cf5d868635e9d4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: staging:iio:ad7746: Mark transfer buffer as __be32 Fixes the following warnings from sparse: drivers/staging/iio/cdc/ad7746.c:599:25: warning: cast to restricted __be32 drivers/staging/iio/cdc/ad7746.c:599:25: warning: cast to restricted __be32 drivers/staging/iio/cdc/ad7746.c:599:25: warning: cast to restricted __be32 drivers/staging/iio/cdc/ad7746.c:599:25: warning: cast to restricted __be32 drivers/staging/iio/cdc/ad7746.c:599:25: warning: cast to restricted __be32 drivers/staging/iio/cdc/ad7746.c:599:25: warning: cast to restricted __be32 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 862d68d99630..01e15e2f3f50 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -567,7 +567,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, u8 regval, reg; union { - u32 d32; + __be32 d32; u8 d8[4]; } data; -- cgit v1.2.3 From 112b0b79b2e7a552e8afe19fdddbacef734649f8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: staging:iio:ad7746: Do not store the transfer buffer on the stack Some I2C controllers might not be able to handle transfer buffers that are stored on stack. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 01e15e2f3f50..cbb1588d591f 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -105,6 +105,11 @@ struct ad7746_chip_info { u8 vt_setup; u8 capdac[2][2]; s8 capdac_set; + + union { + __be32 d32; + u8 d8[4]; + } data ____cacheline_aligned; }; enum ad7746_chan { @@ -566,11 +571,6 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, int ret, delay; u8 regval, reg; - union { - __be32 d32; - u8 d8[4]; - } data; - mutex_lock(&indio_dev->mlock); switch (mask) { @@ -591,12 +591,12 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, /* Now read the actual register */ ret = i2c_smbus_read_i2c_block_data(chip->client, - chan->address >> 8, 3, &data.d8[1]); + chan->address >> 8, 3, &chip->data.d8[1]); if (ret < 0) goto out; - *val = (be32_to_cpu(data.d32) & 0xFFFFFF) - 0x800000; + *val = (be32_to_cpu(chip->data.d32) & 0xFFFFFF) - 0x800000; switch (chan->type) { case IIO_TEMP: -- cgit v1.2.3 From 647cc7b9be861e01723a3183f5d06729a1613a97 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 14:56:00 +0000 Subject: iio: Add data_available callback for buffers This patch adds a new data_available() callback to the iio_buffer_access_funcs struct. The callback is used to indicate whether data is available in the buffer for reading. It is meant to replace the stufftoread flag from the iio_buffer struct. The reasoning for this is that the buffer implementation usually can determine whether data is available rather easily based on its state, on the other hand it can be rather tricky to update the stufftoread flag in a race free way. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 10 +++++++++- include/linux/iio/buffer.h | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 7f9152c3c4d3..4dcc3a0f9930 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -37,6 +37,14 @@ static bool iio_buffer_is_active(struct iio_buffer *buf) return !list_empty(&buf->buffer_list); } +static bool iio_buffer_data_available(struct iio_buffer *buf) +{ + if (buf->access->data_available) + return buf->access->data_available(buf); + + return buf->stufftoread; +} + /** * iio_buffer_read_first_n_outer() - chrdev read for buffer access * @@ -70,7 +78,7 @@ unsigned int iio_buffer_poll(struct file *filp, return -ENODEV; poll_wait(filp, &rb->pollq, wait); - if (rb->stufftoread) + if (iio_buffer_data_available(rb)) return POLLIN | POLLRDNORM; /* need a way of knowing if there may be enough data... */ return 0; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 15607b45221a..519392763393 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -21,6 +21,8 @@ struct iio_buffer; * struct iio_buffer_access_funcs - access functions for buffers. * @store_to: actually store stuff to the buffer * @read_first_n: try to get a specified number of bytes (must exist) + * @data_available: indicates whether data for reading from the buffer is + * available. * @request_update: if a parameter change has been marked, update underlying * storage. * @get_bytes_per_datum:get current bytes per datum @@ -43,6 +45,7 @@ struct iio_buffer_access_funcs { int (*read_first_n)(struct iio_buffer *buffer, size_t n, char __user *buf); + bool (*data_available)(struct iio_buffer *buffer); int (*request_update)(struct iio_buffer *buffer); -- cgit v1.2.3 From 355c1a14d4009a43e4d1f9cb42a382f0a94d01c4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 14:56:00 +0000 Subject: iio: kfifo_buf: Implement data_available() callback This patch implements the data_available() callback for the kfifo buffer instead of using the stufftoread flag. The kfifo used by the buffer already knows whether it is empty or not based on the position of its read and write pointer. Using this makes it a lot easier to tell whether data is available or not and it is not necessary to take special measures to ensure that no race conditions between reading and writing from the buffer occur. Note, that we still have to take the buffers lock to protect against concurrent resizeing of the kfifo. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/kfifo_buf.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 95c6fc81c2c7..7134e8ada09a 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -42,7 +42,6 @@ static int iio_request_update_kfifo(struct iio_buffer *r) } else { kfifo_reset_out(&buf->kf); } - r->stufftoread = false; mutex_unlock(&buf->user_lock); return ret; @@ -108,7 +107,7 @@ static int iio_store_to_kfifo(struct iio_buffer *r, ret = kfifo_in(&kf->kf, data, 1); if (ret != 1) return -EBUSY; - r->stufftoread = true; + wake_up_interruptible_poll(&r->pollq, POLLIN | POLLRDNORM); return 0; @@ -127,13 +126,6 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r, ret = -EINVAL; else ret = kfifo_to_user(&kf->kf, buf, n, &copied); - - if (kfifo_is_empty(&kf->kf)) - r->stufftoread = false; - /* verify it is still empty to avoid race */ - if (!kfifo_is_empty(&kf->kf)) - r->stufftoread = true; - mutex_unlock(&kf->user_lock); if (ret < 0) return ret; @@ -141,6 +133,18 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r, return copied; } +static bool iio_kfifo_buf_data_available(struct iio_buffer *r) +{ + struct iio_kfifo *kf = iio_to_kfifo(r); + bool empty; + + mutex_lock(&kf->user_lock); + empty = kfifo_is_empty(&kf->kf); + mutex_unlock(&kf->user_lock); + + return !empty; +} + static void iio_kfifo_buffer_release(struct iio_buffer *buffer) { struct iio_kfifo *kf = iio_to_kfifo(buffer); @@ -153,6 +157,7 @@ static void iio_kfifo_buffer_release(struct iio_buffer *buffer) static const struct iio_buffer_access_funcs kfifo_access_funcs = { .store_to = &iio_store_to_kfifo, .read_first_n = &iio_read_first_n_kfifo, + .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, -- cgit v1.2.3 From ee551a10006f3728c231bbe9c30635ff53250dbc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 14:56:00 +0000 Subject: iio: Add support for blocking IO on buffers Currently the IIO buffer interface only allows non-blocking reads. This patch adds support for blocking IO. In blocking mode the thread will go to sleep if no data is available and will wait for the buffer implementation to signal that new data is available by waking up the buffers waitqueue. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 4dcc3a0f9930..c67d83bdc8f0 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -56,13 +56,34 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, { struct iio_dev *indio_dev = filp->private_data; struct iio_buffer *rb = indio_dev->buffer; + int ret; if (!indio_dev->info) return -ENODEV; if (!rb || !rb->access->read_first_n) return -EINVAL; - return rb->access->read_first_n(rb, n, buf); + + do { + if (!iio_buffer_data_available(rb)) { + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + ret = wait_event_interruptible(rb->pollq, + iio_buffer_data_available(rb) || + indio_dev->info == NULL); + if (ret) + return ret; + if (indio_dev->info == NULL) + return -ENODEV; + } + + ret = rb->access->read_first_n(rb, n, buf); + if (ret == 0 && (filp->f_flags & O_NONBLOCK)) + ret = -EAGAIN; + } while (ret == 0); + + return ret; } /** -- cgit v1.2.3 From f59c2576c12d4367ca4bdade0eb054b4558f9762 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 2 Dec 2013 02:57:00 +0000 Subject: iio:trigger: Convert to use ATTRIBUTE_GROUPS Use new ATTRIBUTE_GROUPS macro to declare attribute groups. Signed-off-by: Axel Lin Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 7ba2f002ffca..766fab24b720 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -55,15 +55,7 @@ static struct attribute *iio_trig_dev_attrs[] = { &dev_attr_name.attr, NULL, }; - -static struct attribute_group iio_trig_attr_group = { - .attrs = iio_trig_dev_attrs, -}; - -static const struct attribute_group *iio_trig_attr_groups[] = { - &iio_trig_attr_group, - NULL -}; +ATTRIBUTE_GROUPS(iio_trig_dev); int iio_trigger_register(struct iio_trigger *trig_info) { @@ -403,7 +395,7 @@ static void iio_trig_release(struct device *device) static struct device_type iio_trig_type = { .release = iio_trig_release, - .groups = iio_trig_attr_groups, + .groups = iio_trig_dev_groups, }; static void iio_trig_subirqmask(struct irq_data *d) -- cgit v1.2.3 From 2a0c293e4896169fa9accfedc62b8467270c6abb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: staging:iio:ad9832: Mark transfer buffers as __be16 Fixes the following warnings from sparse: drivers/staging/iio/frequency/ad9832.c:43:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:43:26: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9832.c:43:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:46:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:46:26: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9832.c:46:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:49:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:49:26: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9832.c:49:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:52:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:52:26: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9832.c:52:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:65:27: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:65:27: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9832.c:65:27: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:68:27: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:68:27: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9832.c:68:27: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:107:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:107:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9832.c:107:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:120:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:120:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9832.c:120:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:133:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:133:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9832.c:133:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:144:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:144:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9832.c:144:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9832.c:277:18: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9832.c:277:18: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9832.c:277:18: got restricted __be16 [usertype] Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9832.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/frequency/ad9832.h b/drivers/staging/iio/frequency/ad9832.h index c5b701f8aabb..386f4dc8c9a1 100644 --- a/drivers/staging/iio/frequency/ad9832.h +++ b/drivers/staging/iio/frequency/ad9832.h @@ -92,9 +92,9 @@ struct ad9832_state { * transfer buffers to live in their own cache lines. */ union { - unsigned short freq_data[4]____cacheline_aligned; - unsigned short phase_data[2]; - unsigned short data; + __be16 freq_data[4]____cacheline_aligned; + __be16 phase_data[2]; + __be16 data; }; }; -- cgit v1.2.3 From 6f93910ebae3f0ca4c0db1ba098d1635618b9c2f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 12:42:00 +0000 Subject: staging:iio:ad9834: Mark transfer buffers as __b16 Fixes the following warnings from sparse: drivers/staging/iio/frequency/ad9834.c:45:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:45:26: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9834.c:45:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:47:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:47:26: expected unsigned short [unsigned] [short] drivers/staging/iio/frequency/ad9834.c:47:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:59:18: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:59:18: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:59:18: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:100:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:100:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:100:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:108:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:108:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:108:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:122:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:122:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:122:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:131:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:131:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:131:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:194:26: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:194:26: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:194:26: got restricted __be16 [usertype] drivers/staging/iio/frequency/ad9834.c:387:18: warning: incorrect type in assignment (different base types) drivers/staging/iio/frequency/ad9834.c:387:18: expected unsigned short [unsigned] data drivers/staging/iio/frequency/ad9834.c:387:18: got restricted __be16 [usertype] Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9834.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/frequency/ad9834.h b/drivers/staging/iio/frequency/ad9834.h index ed5ed8d0007f..8ca6e52bae6b 100644 --- a/drivers/staging/iio/frequency/ad9834.h +++ b/drivers/staging/iio/frequency/ad9834.h @@ -65,8 +65,8 @@ struct ad9834_state { * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. */ - unsigned short data ____cacheline_aligned; - unsigned short freq_data[2] ; + __be16 data ____cacheline_aligned; + __be16 freq_data[2]; }; -- cgit v1.2.3 From ac216aa290c48a5e9d7b9f2473abb977a175683a Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 1 Dec 2013 15:08:00 +0000 Subject: iio: Add support for humidity sensors There are already humidity sensors in the hwmon subsystem, so we use their unit (milli percent) here as well. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 13 +++++++++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/types.h | 1 + 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index b20e829d350f..6e02c5029152 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -197,6 +197,19 @@ Description: Raw pressure measurement from channel Y. Units after application of scale and offset are kilopascal. +What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_raw +KernelVersion: 3.14 +Contact: linux-iio@vger.kernel.org +Description: + Raw humidity measurement of air. Units after application of + scale and offset are milli percent. + +What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_input +KernelVersion: 3.14 +Contact: linux-iio@vger.kernel.org +Description: + Scaled humidity measurement in milli percent. + What: /sys/bus/iio/devices/iio:deviceX/in_accel_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2fe88c189f74..acc911a836ca 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -69,6 +69,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_ALTVOLTAGE] = "altvoltage", [IIO_CCT] = "cct", [IIO_PRESSURE] = "pressure", + [IIO_HUMIDITYRELATIVE] = "humidityrelative", }; static const char * const iio_modifier_names[] = { diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 4ac928ee31c5..084d882fe01b 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -29,6 +29,7 @@ enum iio_chan_type { IIO_ALTVOLTAGE, IIO_CCT, IIO_PRESSURE, + IIO_HUMIDITYRELATIVE, }; enum iio_modifier { -- cgit v1.2.3 From 091a121b04547fab2045951aff6219318ede0560 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 1 Dec 2013 15:04:00 +0000 Subject: iio: Add new driver dht11 This driver handles DHT11 and DHT22 sensors. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/humidity/dht11.txt | 14 + drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/humidity/Kconfig | 15 ++ drivers/iio/humidity/Makefile | 5 + drivers/iio/humidity/dht11.c | 294 +++++++++++++++++++++ 6 files changed, 330 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/humidity/dht11.txt create mode 100644 drivers/iio/humidity/Kconfig create mode 100644 drivers/iio/humidity/Makefile create mode 100644 drivers/iio/humidity/dht11.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/humidity/dht11.txt b/Documentation/devicetree/bindings/iio/humidity/dht11.txt new file mode 100644 index 000000000000..ecc24c199fd6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/humidity/dht11.txt @@ -0,0 +1,14 @@ +* DHT11 humidity/temperature sensor (and compatibles like DHT22) + +Required properties: + - compatible: Should be "dht11" + - gpios: Should specify the GPIO connected to the sensor's data + line, see "gpios property" in + Documentation/devicetree/bindings/gpio/gpio.txt. + +Example: + +humidity_sensor { + compatible = "dht11"; + gpios = <&gpio0 6 0>; +} diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 90cf0cda50c4..a5ed88226276 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -65,6 +65,7 @@ source "drivers/iio/common/Kconfig" source "drivers/iio/dac/Kconfig" source "drivers/iio/frequency/Kconfig" source "drivers/iio/gyro/Kconfig" +source "drivers/iio/humidity/Kconfig" source "drivers/iio/imu/Kconfig" source "drivers/iio/light/Kconfig" source "drivers/iio/magnetometer/Kconfig" diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index bcf7e9e3b053..b3b50968b46b 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -18,6 +18,7 @@ obj-y += common/ obj-y += dac/ obj-y += gyro/ obj-y += frequency/ +obj-y += humidity/ obj-y += imu/ obj-y += light/ obj-y += magnetometer/ diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig new file mode 100644 index 000000000000..463c4d9da79e --- /dev/null +++ b/drivers/iio/humidity/Kconfig @@ -0,0 +1,15 @@ +# +# humidity sensor drivers +# +menu "Humidity sensors" + +config DHT11 + tristate "DHT11 (and compatible sensors) driver" + depends on GPIOLIB + help + This driver supports reading data via a single interrupt + generating GPIO line. Currently tested are DHT11 and DHT22. + Other sensors should work as well as long as they speak the + same protocol. + +endmenu diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile new file mode 100644 index 000000000000..d5d36c0c95f9 --- /dev/null +++ b/drivers/iio/humidity/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for IIO humidity sensor drivers +# + +obj-$(CONFIG_DHT11) += dht11.o diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c new file mode 100644 index 000000000000..d8771f546bf2 --- /dev/null +++ b/drivers/iio/humidity/dht11.c @@ -0,0 +1,294 @@ +/* + * DHT11/DHT22 bit banging GPIO driver + * + * Copyright (c) Harald Geyer + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "dht11" + +#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */ + +#define DHT11_EDGES_PREAMBLE 4 +#define DHT11_BITS_PER_READ 40 +#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1) + +/* Data transmission timing (nano seconds) */ +#define DHT11_START_TRANSMISSION 18 /* ms */ +#define DHT11_SENSOR_RESPONSE 80000 +#define DHT11_START_BIT 50000 +#define DHT11_DATA_BIT_LOW 27000 +#define DHT11_DATA_BIT_HIGH 70000 + +struct dht11 { + struct device *dev; + + int gpio; + int irq; + + struct completion completion; + + s64 timestamp; + int temperature; + int humidity; + + /* num_edges: -1 means "no transmission in progress" */ + int num_edges; + struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ]; +}; + +static unsigned char dht11_decode_byte(int *timing, int threshold) +{ + unsigned char ret = 0; + int i; + + for (i = 0; i < 8; ++i) { + ret <<= 1; + if (timing[i] >= threshold) + ++ret; + } + + return ret; +} + +static int dht11_decode(struct dht11 *dht11, int offset) +{ + int i, t, timing[DHT11_BITS_PER_READ], threshold, + timeres = DHT11_SENSOR_RESPONSE; + unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum; + + /* Calculate timestamp resolution */ + for (i = 0; i < dht11->num_edges; ++i) { + t = dht11->edges[i].ts - dht11->edges[i-1].ts; + if (t > 0 && t < timeres) + timeres = t; + } + if (2*timeres > DHT11_DATA_BIT_HIGH) { + pr_err("dht11: timeresolution %d too bad for decoding\n", + timeres); + return -EIO; + } + threshold = DHT11_DATA_BIT_HIGH / timeres; + if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold) + pr_err("dht11: WARNING: decoding ambiguous\n"); + + /* scale down with timeres and check validity */ + for (i = 0; i < DHT11_BITS_PER_READ; ++i) { + t = dht11->edges[offset + 2*i + 2].ts - + dht11->edges[offset + 2*i + 1].ts; + if (!dht11->edges[offset + 2*i + 1].value) + return -EIO; /* lost synchronisation */ + timing[i] = t / timeres; + } + + hum_int = dht11_decode_byte(timing, threshold); + hum_dec = dht11_decode_byte(&timing[8], threshold); + temp_int = dht11_decode_byte(&timing[16], threshold); + temp_dec = dht11_decode_byte(&timing[24], threshold); + checksum = dht11_decode_byte(&timing[32], threshold); + + if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) + return -EIO; + + dht11->timestamp = iio_get_time_ns(); + if (hum_int < 20) { /* DHT22 */ + dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) * + ((temp_int & 0x80) ? -100 : 100); + dht11->humidity = ((hum_int << 8) + hum_dec) * 100; + } else if (temp_dec == 0 && hum_dec == 0) { /* DHT11 */ + dht11->temperature = temp_int * 1000; + dht11->humidity = hum_int * 1000; + } else { + dev_err(dht11->dev, + "Don't know how to decode data: %d %d %d %d\n", + hum_int, hum_dec, temp_int, temp_dec); + return -EIO; + } + + return 0; +} + +static int dht11_read_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long m) +{ + struct dht11 *dht11 = iio_priv(iio_dev); + int ret; + + if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) { + reinit_completion(&dht11->completion); + + dht11->num_edges = 0; + ret = gpio_direction_output(dht11->gpio, 0); + if (ret) + goto err; + msleep(DHT11_START_TRANSMISSION); + ret = gpio_direction_input(dht11->gpio); + if (ret) + goto err; + + ret = wait_for_completion_killable_timeout(&dht11->completion, + HZ); + if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { + dev_err(&iio_dev->dev, + "Only %d signal edges detected\n", + dht11->num_edges); + ret = -ETIMEDOUT; + } + if (ret < 0) + goto err; + + ret = dht11_decode(dht11, + dht11->num_edges == DHT11_EDGES_PER_READ ? + DHT11_EDGES_PREAMBLE : + DHT11_EDGES_PREAMBLE - 2); + if (ret) + goto err; + } + + ret = IIO_VAL_INT; + if (chan->type == IIO_TEMP) + *val = dht11->temperature; + else if (chan->type == IIO_HUMIDITYRELATIVE) + *val = dht11->humidity; + else + ret = -EINVAL; +err: + dht11->num_edges = -1; + return ret; +} + +static const struct iio_info dht11_iio_info = { + .driver_module = THIS_MODULE, + .read_raw = dht11_read_raw, +}; + +/* + * IRQ handler called on GPIO edges +*/ +static irqreturn_t dht11_handle_irq(int irq, void *data) +{ + struct iio_dev *iio = data; + struct dht11 *dht11 = iio_priv(iio); + + /* TODO: Consider making the handler safe for IRQ sharing */ + if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { + dht11->edges[dht11->num_edges].ts = iio_get_time_ns(); + dht11->edges[dht11->num_edges++].value = + gpio_get_value(dht11->gpio); + + if (dht11->num_edges >= DHT11_EDGES_PER_READ) + complete(&dht11->completion); + } + + return IRQ_HANDLED; +} + +static const struct iio_chan_spec dht11_chan_spec[] = { + { .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, + { .type = IIO_HUMIDITYRELATIVE, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), } +}; + +static const struct of_device_id dht11_dt_ids[] = { + { .compatible = "dht11", }, + { } +}; +MODULE_DEVICE_TABLE(of, dht11_dt_ids); + +static int dht11_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct dht11 *dht11; + struct iio_dev *iio; + int ret; + + iio = devm_iio_device_alloc(dev, sizeof(*dht11)); + if (!iio) { + dev_err(dev, "Failed to allocate IIO device\n"); + return -ENOMEM; + } + + dht11 = iio_priv(iio); + dht11->dev = dev; + + dht11->gpio = ret = of_get_gpio(node, 0); + if (ret < 0) + return ret; + ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name); + if (ret) + return ret; + + dht11->irq = gpio_to_irq(dht11->gpio); + if (dht11->irq < 0) { + dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio); + return -EINVAL; + } + ret = devm_request_irq(dev, dht11->irq, dht11_handle_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + pdev->name, iio); + if (ret) + return ret; + + dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1; + dht11->num_edges = -1; + + platform_set_drvdata(pdev, iio); + + init_completion(&dht11->completion); + iio->name = pdev->name; + iio->dev.parent = &pdev->dev; + iio->info = &dht11_iio_info; + iio->modes = INDIO_DIRECT_MODE; + iio->channels = dht11_chan_spec; + iio->num_channels = ARRAY_SIZE(dht11_chan_spec); + + return devm_iio_device_register(dev, iio); +} + +static struct platform_driver dht11_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = dht11_dt_ids, + }, + .probe = dht11_probe, +}; + +module_platform_driver(dht11_driver); + +MODULE_AUTHOR("Harald Geyer "); +MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 098d3beccfb6d678a926c4cc4f5e70c3b752fd5e Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 6 Nov 2013 00:11:00 +0000 Subject: iio: hid-sensors: Added Inclinometer 3D Added usage id processing for Inclinometer 3D. This uses IIO interfaces for triggered buffer to present data to user mode.This uses HID sensor framework for registering callback events from the sensor hub. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/Kconfig | 1 + drivers/iio/Makefile | 1 + drivers/iio/orientation/Kconfig | 19 ++ drivers/iio/orientation/Makefile | 6 + drivers/iio/orientation/hid-sensor-incl-3d.c | 428 +++++++++++++++++++++++++++ include/linux/hid-sensor-ids.h | 4 + 6 files changed, 459 insertions(+) create mode 100644 drivers/iio/orientation/Kconfig create mode 100644 drivers/iio/orientation/Makefile create mode 100644 drivers/iio/orientation/hid-sensor-incl-3d.c (limited to 'drivers') diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index a5ed88226276..5dd0e120a504 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -69,6 +69,7 @@ source "drivers/iio/humidity/Kconfig" source "drivers/iio/imu/Kconfig" source "drivers/iio/light/Kconfig" source "drivers/iio/magnetometer/Kconfig" +source "drivers/iio/orientation/Kconfig" if IIO_TRIGGER source "drivers/iio/trigger/Kconfig" endif #IIO_TRIGGER diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index b3b50968b46b..887d39090d75 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -22,6 +22,7 @@ obj-y += humidity/ obj-y += imu/ obj-y += light/ obj-y += magnetometer/ +obj-y += orientation/ obj-y += pressure/ obj-y += temperature/ obj-y += trigger/ diff --git a/drivers/iio/orientation/Kconfig b/drivers/iio/orientation/Kconfig new file mode 100644 index 000000000000..58c62c837e12 --- /dev/null +++ b/drivers/iio/orientation/Kconfig @@ -0,0 +1,19 @@ +# +# Inclinometer sensors +# +# When adding new entries keep the list in alphabetical order + +menu "Inclinometer sensors" + +config HID_SENSOR_INCLINOMETER_3D + depends on HID_SENSOR_HUB + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER + tristate "HID Inclinometer 3D" + help + Say yes here to build support for the HID SENSOR + Inclinometer 3D. + +endmenu diff --git a/drivers/iio/orientation/Makefile b/drivers/iio/orientation/Makefile new file mode 100644 index 000000000000..2c97572ee919 --- /dev/null +++ b/drivers/iio/orientation/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for industrial I/O Inclinometer sensor drivers +# + +# When adding new entries keep the list in alphabetical order +obj-$(CONFIG_HID_SENSOR_INCLINOMETER_3D) += hid-sensor-incl-3d.o diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c new file mode 100644 index 000000000000..070feab08faa --- /dev/null +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -0,0 +1,428 @@ +/* + * HID Sensors Driver + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/hid-sensors/hid-sensor-trigger.h" + +enum incl_3d_channel { + CHANNEL_SCAN_INDEX_X, + CHANNEL_SCAN_INDEX_Y, + CHANNEL_SCAN_INDEX_Z, + INCLI_3D_CHANNEL_MAX, +}; + +struct incl_3d_state { + struct hid_sensor_hub_callbacks callbacks; + struct hid_sensor_common common_attributes; + struct hid_sensor_hub_attribute_info incl[INCLI_3D_CHANNEL_MAX]; + u32 incl_val[INCLI_3D_CHANNEL_MAX]; +}; + +static const u32 incl_3d_addresses[INCLI_3D_CHANNEL_MAX] = { + HID_USAGE_SENSOR_ORIENT_TILT_X, + HID_USAGE_SENSOR_ORIENT_TILT_Y, + HID_USAGE_SENSOR_ORIENT_TILT_Z +}; + +/* Channel definitions */ +static const struct iio_chan_spec incl_3d_channels[] = { + { + .type = IIO_INCLI, + .modified = 1, + .channel2 = IIO_MOD_X, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_X, + }, { + .type = IIO_INCLI, + .modified = 1, + .channel2 = IIO_MOD_Y, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_Y, + }, { + .type = IIO_INCLI, + .modified = 1, + .channel2 = IIO_MOD_Z, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_Z, + } +}; + +/* Adjust channel real bits based on report descriptor */ +static void incl_3d_adjust_channel_bit_mask(struct iio_chan_spec *chan, + int size) +{ + chan->scan_type.sign = 's'; + /* Real storage bits will change based on the report desc. */ + chan->scan_type.realbits = size * 8; + /* Maximum size of a sample to capture is u32 */ + chan->scan_type.storagebits = sizeof(u32) * 8; +} + +/* Channel read_raw handler */ +static int incl_3d_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct incl_3d_state *incl_state = iio_priv(indio_dev); + int report_id = -1; + u32 address; + int ret_type; + + *val = 0; + *val2 = 0; + switch (mask) { + case IIO_CHAN_INFO_RAW: + report_id = + incl_state->incl[chan->scan_index].report_id; + address = incl_3d_addresses[chan->scan_index]; + if (report_id >= 0) + *val = sensor_hub_input_attr_get_raw_value( + incl_state->common_attributes.hsdev, + HID_USAGE_SENSOR_INCLINOMETER_3D, address, + report_id); + else { + return -EINVAL; + } + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + *val = incl_state->incl[CHANNEL_SCAN_INDEX_X].units; + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OFFSET: + *val = hid_sensor_convert_exponent( + incl_state->incl[CHANNEL_SCAN_INDEX_X].unit_expo); + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret_type = hid_sensor_read_samp_freq_value( + &incl_state->common_attributes, val, val2); + break; + case IIO_CHAN_INFO_HYSTERESIS: + ret_type = hid_sensor_read_raw_hyst_value( + &incl_state->common_attributes, val, val2); + break; + default: + ret_type = -EINVAL; + break; + } + + return ret_type; +} + +/* Channel write_raw handler */ +static int incl_3d_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct incl_3d_state *incl_state = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret = hid_sensor_write_samp_freq_value( + &incl_state->common_attributes, val, val2); + break; + case IIO_CHAN_INFO_HYSTERESIS: + ret = hid_sensor_write_raw_hyst_value( + &incl_state->common_attributes, val, val2); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info incl_3d_info = { + .driver_module = THIS_MODULE, + .read_raw = &incl_3d_read_raw, + .write_raw = &incl_3d_write_raw, +}; + +/* Function to push data to buffer */ +static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) +{ + dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); + iio_push_to_buffers(indio_dev, (u8 *)data); +} + +/* Callback handler to send event after all samples are received and captured */ +static int incl_3d_proc_event(struct hid_sensor_hub_device *hsdev, + unsigned usage_id, + void *priv) +{ + struct iio_dev *indio_dev = platform_get_drvdata(priv); + struct incl_3d_state *incl_state = iio_priv(indio_dev); + + dev_dbg(&indio_dev->dev, "incl_3d_proc_event [%d]\n", + incl_state->common_attributes.data_ready); + if (incl_state->common_attributes.data_ready) + hid_sensor_push_data(indio_dev, + (u8 *)incl_state->incl_val, + sizeof(incl_state->incl_val)); + + return 0; +} + +/* Capture samples in local storage */ +static int incl_3d_capture_sample(struct hid_sensor_hub_device *hsdev, + unsigned usage_id, + size_t raw_len, char *raw_data, + void *priv) +{ + struct iio_dev *indio_dev = platform_get_drvdata(priv); + struct incl_3d_state *incl_state = iio_priv(indio_dev); + int ret = 0; + + switch (usage_id) { + case HID_USAGE_SENSOR_ORIENT_TILT_X: + incl_state->incl_val[CHANNEL_SCAN_INDEX_X] = *(u32 *)raw_data; + break; + case HID_USAGE_SENSOR_ORIENT_TILT_Y: + incl_state->incl_val[CHANNEL_SCAN_INDEX_Y] = *(u32 *)raw_data; + break; + case HID_USAGE_SENSOR_ORIENT_TILT_Z: + incl_state->incl_val[CHANNEL_SCAN_INDEX_Z] = *(u32 *)raw_data; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/* Parse report which is specific to an usage id*/ +static int incl_3d_parse_report(struct platform_device *pdev, + struct hid_sensor_hub_device *hsdev, + struct iio_chan_spec *channels, + unsigned usage_id, + struct incl_3d_state *st) +{ + int ret; + + ret = sensor_hub_input_get_attribute_info(hsdev, + HID_INPUT_REPORT, + usage_id, + HID_USAGE_SENSOR_ORIENT_TILT_X, + &st->incl[CHANNEL_SCAN_INDEX_X]); + if (ret) + return ret; + incl_3d_adjust_channel_bit_mask(&channels[CHANNEL_SCAN_INDEX_X], + st->incl[CHANNEL_SCAN_INDEX_X].size); + + ret = sensor_hub_input_get_attribute_info(hsdev, + HID_INPUT_REPORT, + usage_id, + HID_USAGE_SENSOR_ORIENT_TILT_Y, + &st->incl[CHANNEL_SCAN_INDEX_Y]); + if (ret) + return ret; + incl_3d_adjust_channel_bit_mask(&channels[CHANNEL_SCAN_INDEX_Y], + st->incl[CHANNEL_SCAN_INDEX_Y].size); + + ret = sensor_hub_input_get_attribute_info(hsdev, + HID_INPUT_REPORT, + usage_id, + HID_USAGE_SENSOR_ORIENT_TILT_Z, + &st->incl[CHANNEL_SCAN_INDEX_Z]); + if (ret) + return ret; + incl_3d_adjust_channel_bit_mask(&channels[CHANNEL_SCAN_INDEX_Z], + st->incl[CHANNEL_SCAN_INDEX_Z].size); + + dev_dbg(&pdev->dev, "incl_3d %x:%x, %x:%x, %x:%x\n", + st->incl[0].index, + st->incl[0].report_id, + st->incl[1].index, st->incl[1].report_id, + st->incl[2].index, st->incl[2].report_id); + + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_ORIENTATION, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } + return ret; +} + +/* Function to initialize the processing for usage id */ +static int hid_incl_3d_probe(struct platform_device *pdev) +{ + int ret; + static char *name = "incli_3d"; + struct iio_dev *indio_dev; + struct incl_3d_state *incl_state; + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + struct iio_chan_spec *channels; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct incl_3d_state)); + if (indio_dev == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, indio_dev); + + incl_state = iio_priv(indio_dev); + incl_state->common_attributes.hsdev = hsdev; + incl_state->common_attributes.pdev = pdev; + + ret = hid_sensor_parse_common_attributes(hsdev, + HID_USAGE_SENSOR_INCLINOMETER_3D, + &incl_state->common_attributes); + if (ret) { + dev_err(&pdev->dev, "failed to setup common attributes\n"); + return ret; + } + + channels = kmemdup(incl_3d_channels, sizeof(incl_3d_channels), + GFP_KERNEL); + if (!channels) { + dev_err(&pdev->dev, "failed to duplicate channels\n"); + return -ENOMEM; + } + + ret = incl_3d_parse_report(pdev, hsdev, channels, + HID_USAGE_SENSOR_INCLINOMETER_3D, incl_state); + if (ret) { + dev_err(&pdev->dev, "failed to setup attributes\n"); + goto error_free_dev_mem; + } + + indio_dev->channels = channels; + indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &incl_3d_info; + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + NULL, NULL); + if (ret) { + dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); + goto error_free_dev_mem; + } + incl_state->common_attributes.data_ready = false; + ret = hid_sensor_setup_trigger(indio_dev, name, + &incl_state->common_attributes); + if (ret) { + dev_err(&pdev->dev, "trigger setup failed\n"); + goto error_unreg_buffer_funcs; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "device register failed\n"); + goto error_remove_trigger; + } + + incl_state->callbacks.send_event = incl_3d_proc_event; + incl_state->callbacks.capture_sample = incl_3d_capture_sample; + incl_state->callbacks.pdev = pdev; + ret = sensor_hub_register_callback(hsdev, + HID_USAGE_SENSOR_INCLINOMETER_3D, + &incl_state->callbacks); + if (ret) { + dev_err(&pdev->dev, "callback reg failed\n"); + goto error_iio_unreg; + } + + return 0; + +error_iio_unreg: + iio_device_unregister(indio_dev); +error_remove_trigger: + hid_sensor_remove_trigger(&incl_state->common_attributes); +error_unreg_buffer_funcs: + iio_triggered_buffer_cleanup(indio_dev); +error_free_dev_mem: + kfree(indio_dev->channels); + return ret; +} + +/* Function to deinitialize the processing for usage id */ +static int hid_incl_3d_remove(struct platform_device *pdev) +{ + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct incl_3d_state *incl_state = iio_priv(indio_dev); + + sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D); + iio_device_unregister(indio_dev); + hid_sensor_remove_trigger(&incl_state->common_attributes); + iio_triggered_buffer_cleanup(indio_dev); + kfree(indio_dev->channels); + + return 0; +} + +static struct platform_device_id hid_incl_3d_ids[] = { + { + /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ + .name = "HID-SENSOR-200086", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, hid_incl_3d_ids); + +static struct platform_driver hid_incl_3d_platform_driver = { + .id_table = hid_incl_3d_ids, + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .probe = hid_incl_3d_probe, + .remove = hid_incl_3d_remove, +}; +module_platform_driver(hid_incl_3d_platform_driver); + +MODULE_DESCRIPTION("HID Sensor Inclinometer 3D"); +MODULE_AUTHOR("Srinivas Pandruvada "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 4cc165887b09..558b7d43de7d 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -58,10 +58,14 @@ #define HID_USAGE_SENSOR_ORIENT_DISTANCE_Y 0x20047B #define HID_USAGE_SENSOR_ORIENT_DISTANCE_Z 0x20047C #define HID_USAGE_SENSOR_ORIENT_DISTANCE_OUT_OF_RANGE 0x20047D + +/* ORIENTATION: Inclinometer 3D: (200086) */ +#define HID_USAGE_SENSOR_INCLINOMETER_3D 0x200086 #define HID_USAGE_SENSOR_ORIENT_TILT 0x20047E #define HID_USAGE_SENSOR_ORIENT_TILT_X 0x20047F #define HID_USAGE_SENSOR_ORIENT_TILT_Y 0x200480 #define HID_USAGE_SENSOR_ORIENT_TILT_Z 0x200481 + #define HID_USAGE_SENSOR_ORIENT_ROTATION_MATRIX 0x200482 #define HID_USAGE_SENSOR_ORIENT_QUATERNION 0x200483 #define HID_USAGE_SENSOR_ORIENT_MAGN_FLUX 0x200484 -- cgit v1.2.3 From 027476642811f8559cbe00ef6cc54db230e48a20 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 2 Dec 2013 11:08:06 +0200 Subject: drm/i915: Take modeset locks around intel_modeset_setup_hw_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some lower level things get angry if we don't have modeset locks during intel_modeset_setup_hw_state(). Actually the resume and lid_notify codepaths alreday hold the locks, but the init codepath doesn't, so fix that. Note: This slipped through since we only disable pipes if the plane/pipe linking doesn't match. Which is only relevant on older gen3 mobile machines, if the BIOS fails to set up our preferred linking. Signed-off-by: Ville Syrjälä Cc: stable@vger.kernel.org Tested-and-reported-by: Paul Bolle [danvet: Add note now that I could confirm my theory with the log files Paul Bolle provided.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd4e839..114db51996bd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11046,7 +11046,9 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); + drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, false); + drm_modeset_unlock_all(dev); } void intel_modeset_cleanup(struct drm_device *dev) -- cgit v1.2.3 From edd5b13313551d6b04acfb90d3db58ed3cf3c814 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2013 17:39:09 +0000 Subject: drm/i915: Do not clobber config status after a forced restore of hw state We call intel_modeset_setup_hw_state() along two paths, driver load/resume and after a lid event notification. During initialisation of the driver, it is imperative that we reset the config state. This correctly sets up the initial connector statuses and prepares the hardware for a thorough probing. However, during a lid event, we only want to undo the damage caused by the bios by resetting our last known mode. In this cirumstance, we do not want to clobber our desired state. In order to try and keep sanity between the config state and our own tracking, do the drm_mode_config_reset() first along the load/resume paths before reading out the hw state and apply any definite known corrections. v2: "As discussed on irc I don't think we should force the connector state to anything here: Imo connector->status should reflect what we believe to be the true output connection state, whereas connector->encoder reflects whether this connector is wired up to a pipe. And since we no longer reject modeset on disconnected connectors and never nuked the pipe if the connector gets disconnected there's no reason for that - such policy is userspace's job. This regression has been introduced in commit 2e9388923e83bc4e2726f170a984621f1d582e77 Author: Daniel Vetter Date: Thu Oct 11 20:08:24 2012 +0200 drm/i915/crt: explicitly set up HOTPLUG_BITS on resume" so sayeth Daniel. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: stable@vger.kernel.org (v3.8 and later) Cc: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/intel_display.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2e367a1c6a64..5b7b7e06cb3a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -651,6 +651,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) intel_modeset_init_hw(dev); drm_modeset_lock_all(dev); + drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, true); drm_modeset_unlock_all(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 114db51996bd..8e44b16950cf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11036,8 +11036,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, } intel_modeset_check_state(dev); - - drm_mode_config_reset(dev); } void intel_modeset_gem_init(struct drm_device *dev) @@ -11047,6 +11045,7 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); drm_modeset_lock_all(dev); + drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, false); drm_modeset_unlock_all(dev); } -- cgit v1.2.3 From 5ae68b413214e847a2b5c6d3c65778482542bc1a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 2 Dec 2013 11:23:39 +0200 Subject: drm/i915: Skip clock checks on BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't have clock state readout support for DDI, so skip the pipe config clock checks on all DDI platforms. Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8e44b16950cf..8b8bde7dce53 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9135,7 +9135,7 @@ intel_pipe_config_compare(struct drm_device *dev, if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - if (!IS_HASWELL(dev)) { + if (!HAS_DDI(dev)) { PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); } -- cgit v1.2.3 From 8d30726912cb39c3a3ebde06214d54861f8fdde2 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 3 Dec 2013 19:16:04 -0700 Subject: dm cache: increment bi_remaining when bi_end_io is restored Move the bio->bi_remaining increment into dm_unhook_bio() so the overwrite_endio() handler works as expected. Signed-off-by: Mike Snitzer Signed-off-by: Jens Axboe --- drivers/md/dm-cache-target.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index bf3a206abd78..7c8dd1f69ce0 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -85,6 +85,12 @@ static void dm_unhook_bio(struct dm_hook_info *h, struct bio *bio) { bio->bi_end_io = h->bi_end_io; bio->bi_private = h->bi_private; + + /* + * Must bump bi_remaining to allow bio to complete with + * restored bi_end_io. + */ + atomic_inc(&bio->bi_remaining); } /*----------------------------------------------------------------*/ @@ -765,12 +771,6 @@ static void writethrough_endio(struct bio *bio, int err) dm_unhook_bio(&pb->hook_info, bio); - /* - * Must bump bi_remaining to allow bio to complete with - * restored bi_end_io. - */ - atomic_inc(&bio->bi_remaining); - if (err) { bio_endio(bio, err); return; -- cgit v1.2.3 From 644ff181da10e053dad8fa3de07d1bed8ac0a23f Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 3 Dec 2013 19:22:17 -0700 Subject: drivers/cdrom/gdrom.c: remove deprecated IRQF_DISABLED Remove the IRQF_DISABLED flag from drivers/cdrom/gdrom.c. It's a NOOP since 2.6.35 and it will be removed one day. Signed-off-by: Michael Opdenacker Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/cdrom/gdrom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 5980cb9af857..51e75ad96422 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -561,11 +561,11 @@ static int gdrom_set_interrupt_handlers(void) int err; err = request_irq(HW_EVENT_GDROM_CMD, gdrom_command_interrupt, - IRQF_DISABLED, "gdrom_command", &gd); + 0, "gdrom_command", &gd); if (err) return err; err = request_irq(HW_EVENT_GDROM_DMA, gdrom_dma_interrupt, - IRQF_DISABLED, "gdrom_dma", &gd); + 0, "gdrom_dma", &gd); if (err) free_irq(HW_EVENT_GDROM_CMD, &gd); return err; -- cgit v1.2.3 From 7d2dddda5c928f349a01f1d5ca8ee5e9d4283c7a Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 06:44:01 +1030 Subject: virtio: pci: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Rusty Russell --- drivers/virtio/virtio_pci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index a37c69941d30..a416f9b2a7f6 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -742,7 +742,6 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, return 0; out_set_drvdata: - pci_set_drvdata(pci_dev, NULL); pci_iounmap(pci_dev, vp_dev->ioaddr); out_req_regions: pci_release_regions(pci_dev); @@ -760,7 +759,6 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) unregister_virtio_device(&vp_dev->vdev); vp_del_vqs(&vp_dev->vdev); - pci_set_drvdata(pci_dev, NULL); pci_iounmap(pci_dev, vp_dev->ioaddr); pci_release_regions(pci_dev); pci_disable_device(pci_dev); -- cgit v1.2.3 From b52fa7bc5dc9697fb5983727d276dd565d85a8d0 Mon Sep 17 00:00:00 2001 From: Mike Dunn Date: Sat, 21 Sep 2013 12:19:33 -0700 Subject: pwm: pxa: Add device tree support This patch adds device tree support to the PXA's PWM driver. Nothing needs to be extracted from the device tree node by the PWM device. Client devices need only specify the period; the per-chip index is implicitly zero because one device node must be present for each PWM output in use. This approach is more convenient due to the wide variability in the number of PWM channels present across the various PXA variants, and is made possible by the fact that the register sets for each PWM channel are segregated from each other. An of_xlate() method is added to parse this single-cell node. The existing ID table is reused for the match table data. Tested on a Palm Treo 680 (both platform data and DT cases). Signed-off-by: Mike Dunn Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/pxa-pwm.txt | 30 +++++++++++++ drivers/pwm/pwm-pxa.c | 53 +++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/pxa-pwm.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pwm/pxa-pwm.txt b/Documentation/devicetree/bindings/pwm/pxa-pwm.txt new file mode 100644 index 000000000000..5ae9f1e3c338 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pxa-pwm.txt @@ -0,0 +1,30 @@ +Marvell PWM controller + +Required properties: +- compatible: should be one or more of: + - "marvell,pxa250-pwm" + - "marvell,pxa270-pwm" + - "marvell,pxa168-pwm" + - "marvell,pxa910-pwm" +- reg: Physical base address and length of the registers used by the PWM channel + Note that one device instance must be created for each PWM that is used, so the + length covers only the register window for one PWM output, not that of the + entire PWM controller. Currently length is 0x10 for all supported devices. +- #pwm-cells: Should be 1. This cell is used to specify the period in + nanoseconds. + +Example PWM device node: + +pwm0: pwm@40b00000 { + compatible = "marvell,pxa250-pwm"; + reg = <0x40b00000 0x10>; + #pwm-cells = <1>; +}; + +Example PWM client node: + +backlight { + compatible = "pwm-backlight"; + pwms = <&pwm0 5000000>; + ... +} diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c index a4d2164aaf55..3dc7c10bb7a0 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -124,6 +125,46 @@ static struct pwm_ops pxa_pwm_ops = { .owner = THIS_MODULE, }; +#ifdef CONFIG_OF +/* + * Device tree users must create one device instance for each pwm channel. + * Hence we dispense with the HAS_SECONDARY_PWM and "tell" the original driver + * code that this is a single channel pxa25x-pwm. Currently all devices are + * supported identically. + */ +static struct of_device_id pwm_of_match[] = { + { .compatible = "marvell,pxa250-pwm", .data = &pwm_id_table[0]}, + { .compatible = "marvell,pxa270-pwm", .data = &pwm_id_table[0]}, + { .compatible = "marvell,pxa168-pwm", .data = &pwm_id_table[0]}, + { .compatible = "marvell,pxa910-pwm", .data = &pwm_id_table[0]}, + { } +}; +MODULE_DEVICE_TABLE(of, pwm_of_match); +#else +#define pwm_of_match NULL +#endif + +static const struct platform_device_id *pxa_pwm_get_id_dt(struct device *dev) +{ + const struct of_device_id *id = of_match_device(pwm_of_match, dev); + + return id ? id->data : NULL; +} + +static struct pwm_device * +pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) +{ + struct pwm_device *pwm; + + pwm = pwm_request_from_chip(pc, 0, NULL); + if (IS_ERR(pwm)) + return pwm; + + pwm_set_period(pwm, args->args[0]); + + return pwm; +} + static int pwm_probe(struct platform_device *pdev) { const struct platform_device_id *id = platform_get_device_id(pdev); @@ -131,6 +172,12 @@ static int pwm_probe(struct platform_device *pdev) struct resource *r; int ret = 0; + if (IS_ENABLED(CONFIG_OF) && id == NULL) + id = pxa_pwm_get_id_dt(&pdev->dev); + + if (id == NULL) + return -EINVAL; + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); if (pwm == NULL) { dev_err(&pdev->dev, "failed to allocate memory\n"); @@ -146,6 +193,11 @@ static int pwm_probe(struct platform_device *pdev) pwm->chip.base = -1; pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; + if (IS_ENABLED(CONFIG_OF)) { + pwm->chip.of_xlate = pxa_pwm_of_xlate; + pwm->chip.of_pwm_n_cells = 1; + } + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(pwm->mmio_base)) @@ -176,6 +228,7 @@ static struct platform_driver pwm_driver = { .driver = { .name = "pxa25x-pwm", .owner = THIS_MODULE, + .of_match_table = pwm_of_match, }, .probe = pwm_probe, .remove = pwm_remove, -- cgit v1.2.3 From 6ca142ad0d1bdf8dd116351b7b9a2bc5670d5271 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 4 Dec 2013 18:29:53 +0800 Subject: pwm: sysfs: Convert to use ATTRIBUTE_GROUPS macro Use new ATTRIBUTE_GROUPS macro to reduce the number of lines of code. Signed-off-by: Axel Lin Signed-off-by: Thierry Reding --- drivers/pwm/sysfs.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 8c20332d4825..4bd0c639e16d 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -169,15 +169,7 @@ static struct attribute *pwm_attrs[] = { &dev_attr_polarity.attr, NULL }; - -static const struct attribute_group pwm_attr_group = { - .attrs = pwm_attrs, -}; - -static const struct attribute_group *pwm_attr_groups[] = { - &pwm_attr_group, - NULL, -}; +ATTRIBUTE_GROUPS(pwm); static void pwm_export_release(struct device *child) { @@ -205,7 +197,7 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) export->child.release = pwm_export_release; export->child.parent = parent; export->child.devt = MKDEV(0, 0); - export->child.groups = pwm_attr_groups; + export->child.groups = pwm_groups; dev_set_name(&export->child, "pwm%u", pwm->hwpwm); ret = device_register(&export->child); -- cgit v1.2.3 From 0aa0c95f743a06893dbc494b2a75fbf7093330d4 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 13 Nov 2013 08:51:23 +0800 Subject: clk: hisilicon: add common clock support Enable common clock driver of Hi3620 SoC. clkgate-seperated driver is used to support the clock gate that enable/disable/status registers are seperated. Signed-off-by: Haojian Zhuang --- .../devicetree/bindings/clock/hi3620-clock.txt | 19 ++ drivers/clk/Makefile | 1 + drivers/clk/hisilicon/Makefile | 5 + drivers/clk/hisilicon/clk-hi3620.c | 242 +++++++++++++++++++++ drivers/clk/hisilicon/clk.c | 171 +++++++++++++++ drivers/clk/hisilicon/clk.h | 103 +++++++++ drivers/clk/hisilicon/clkgate-separated.c | 130 +++++++++++ include/dt-bindings/clock/hi3620-clock.h | 152 +++++++++++++ 8 files changed, 823 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/hi3620-clock.txt create mode 100644 drivers/clk/hisilicon/Makefile create mode 100644 drivers/clk/hisilicon/clk-hi3620.c create mode 100644 drivers/clk/hisilicon/clk.c create mode 100644 drivers/clk/hisilicon/clk.h create mode 100644 drivers/clk/hisilicon/clkgate-separated.c create mode 100644 include/dt-bindings/clock/hi3620-clock.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt new file mode 100644 index 000000000000..4b71ab41be53 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt @@ -0,0 +1,19 @@ +* Hisilicon Hi3620 Clock Controller + +The Hi3620 clock controller generates and supplies clock to various +controllers within the Hi3620 SoC. + +Required Properties: + +- compatible: should be one of the following. + - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC. + +- reg: physical base address of the controller and length of memory mapped + region. + +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes use this identifier +to specify the clock which they consume. + +All these identifier could be found in . diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7a10bc9a23e7..cd51428c2aa2 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o +obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile new file mode 100644 index 000000000000..a049108341fc --- /dev/null +++ b/drivers/clk/hisilicon/Makefile @@ -0,0 +1,5 @@ +# +# Hisilicon Clock specific Makefile +# + +obj-y += clk.o clkgate-separated.o clk-hi3620.o diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c new file mode 100644 index 000000000000..b66b074fbda5 --- /dev/null +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -0,0 +1,242 @@ +/* + * Hisilicon Hi3620 clock driver + * + * Copyright (c) 2012-2013 Hisilicon Limited. + * Copyright (c) 2012-2013 Linaro Limited. + * + * Author: Haojian Zhuang + * Xin Li + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" + +/* clock parent list */ +static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", }; +static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", }; +static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", }; +static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", }; +static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", }; +static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", }; +static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", }; +static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", }; +static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", }; +static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", }; +static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", }; +static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", }; +static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", }; +static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", }; +static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", }; +static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; +static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; +static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; +/* share axi parent */ +static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", }; +static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", }; +static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", }; +static const char *sd_mux_p[] __initdata = { "armpll3", "armpll2", }; +static const char *mmc1_mux_p[] __initdata = { "armpll3", "armpll2", }; +static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", }; +static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4", + "armpll3", "armpll5", }; +static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4", + "armpll3", "armpll5", }; +static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", }; +static const char *mmc2_mux_p[] __initdata = { "armpll3", "armpll2", }; +static const char *mmc3_mux_p[] __initdata = { "armpll3", "armpll2", }; + + +/* fixed rate clocks */ +static struct hisi_fixed_rate_clock hi3620_fixed_rate_clks[] __initdata = { + { HI3620_OSC32K, "osc32k", NULL, CLK_IS_ROOT, 32768, }, + { HI3620_OSC26M, "osc26m", NULL, CLK_IS_ROOT, 26000000, }, + { HI3620_PCLK, "pclk", NULL, CLK_IS_ROOT, 26000000, }, + { HI3620_PLL_ARM0, "armpll0", NULL, CLK_IS_ROOT, 1600000000, }, + { HI3620_PLL_ARM1, "armpll1", NULL, CLK_IS_ROOT, 1600000000, }, + { HI3620_PLL_PERI, "armpll2", NULL, CLK_IS_ROOT, 1440000000, }, + { HI3620_PLL_USB, "armpll3", NULL, CLK_IS_ROOT, 1440000000, }, + { HI3620_PLL_HDMI, "armpll4", NULL, CLK_IS_ROOT, 1188000000, }, + { HI3620_PLL_GPU, "armpll5", NULL, CLK_IS_ROOT, 1300000000, }, +}; + +/* fixed factor clocks */ +static struct hisi_fixed_factor_clock hi3620_fixed_factor_clks[] __initdata = { + { HI3620_RCLK_TCXO, "rclk_tcxo", "osc26m", 1, 4, 0, }, + { HI3620_RCLK_CFGAXI, "rclk_cfgaxi", "armpll2", 1, 30, 0, }, + { HI3620_RCLK_PICO, "rclk_pico", "hsic_div", 1, 40, 0, }, +}; + +static struct hisi_mux_clock hi3620_mux_clks[] __initdata = { + { HI3620_TIMER0_MUX, "timer0_mux", timer0_mux_p, ARRAY_SIZE(timer0_mux_p), CLK_SET_RATE_PARENT, 0, 15, 2, 0, }, + { HI3620_TIMER1_MUX, "timer1_mux", timer1_mux_p, ARRAY_SIZE(timer1_mux_p), CLK_SET_RATE_PARENT, 0, 17, 2, 0, }, + { HI3620_TIMER2_MUX, "timer2_mux", timer2_mux_p, ARRAY_SIZE(timer2_mux_p), CLK_SET_RATE_PARENT, 0, 19, 2, 0, }, + { HI3620_TIMER3_MUX, "timer3_mux", timer3_mux_p, ARRAY_SIZE(timer3_mux_p), CLK_SET_RATE_PARENT, 0, 21, 2, 0, }, + { HI3620_TIMER4_MUX, "timer4_mux", timer4_mux_p, ARRAY_SIZE(timer4_mux_p), CLK_SET_RATE_PARENT, 0x18, 0, 2, 0, }, + { HI3620_TIMER5_MUX, "timer5_mux", timer5_mux_p, ARRAY_SIZE(timer5_mux_p), CLK_SET_RATE_PARENT, 0x18, 2, 2, 0, }, + { HI3620_TIMER6_MUX, "timer6_mux", timer6_mux_p, ARRAY_SIZE(timer6_mux_p), CLK_SET_RATE_PARENT, 0x18, 4, 2, 0, }, + { HI3620_TIMER7_MUX, "timer7_mux", timer7_mux_p, ARRAY_SIZE(timer7_mux_p), CLK_SET_RATE_PARENT, 0x18, 6, 2, 0, }, + { HI3620_TIMER8_MUX, "timer8_mux", timer8_mux_p, ARRAY_SIZE(timer8_mux_p), CLK_SET_RATE_PARENT, 0x18, 8, 2, 0, }, + { HI3620_TIMER9_MUX, "timer9_mux", timer9_mux_p, ARRAY_SIZE(timer9_mux_p), CLK_SET_RATE_PARENT, 0x18, 10, 2, 0, }, + { HI3620_UART0_MUX, "uart0_mux", uart0_mux_p, ARRAY_SIZE(uart0_mux_p), CLK_SET_RATE_PARENT, 0x100, 7, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_UART1_MUX, "uart1_mux", uart1_mux_p, ARRAY_SIZE(uart1_mux_p), CLK_SET_RATE_PARENT, 0x100, 8, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_UART2_MUX, "uart2_mux", uart2_mux_p, ARRAY_SIZE(uart2_mux_p), CLK_SET_RATE_PARENT, 0x100, 9, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_UART3_MUX, "uart3_mux", uart3_mux_p, ARRAY_SIZE(uart3_mux_p), CLK_SET_RATE_PARENT, 0x100, 10, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_UART4_MUX, "uart4_mux", uart4_mux_p, ARRAY_SIZE(uart4_mux_p), CLK_SET_RATE_PARENT, 0x100, 11, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_SPI0_MUX, "spi0_mux", spi0_mux_p, ARRAY_SIZE(spi0_mux_p), CLK_SET_RATE_PARENT, 0x100, 12, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_SPI1_MUX, "spi1_mux", spi1_mux_p, ARRAY_SIZE(spi1_mux_p), CLK_SET_RATE_PARENT, 0x100, 13, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_SPI2_MUX, "spi2_mux", spi2_mux_p, ARRAY_SIZE(spi2_mux_p), CLK_SET_RATE_PARENT, 0x100, 14, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_SAXI_MUX, "saxi_mux", saxi_mux_p, ARRAY_SIZE(saxi_mux_p), CLK_SET_RATE_PARENT, 0x100, 15, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_PWM0_MUX, "pwm0_mux", pwm0_mux_p, ARRAY_SIZE(pwm0_mux_p), CLK_SET_RATE_PARENT, 0x104, 10, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_PWM1_MUX, "pwm1_mux", pwm1_mux_p, ARRAY_SIZE(pwm1_mux_p), CLK_SET_RATE_PARENT, 0x104, 11, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_SD_MUX, "sd_mux", sd_mux_p, ARRAY_SIZE(sd_mux_p), CLK_SET_RATE_PARENT, 0x108, 4, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_MMC1_MUX, "mmc1_mux", mmc1_mux_p, ARRAY_SIZE(mmc1_mux_p), CLK_SET_RATE_PARENT, 0x108, 9, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_MMC1_MUX2, "mmc1_mux2", mmc1_mux2_p, ARRAY_SIZE(mmc1_mux2_p), CLK_SET_RATE_PARENT, 0x108, 10, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_G2D_MUX, "g2d_mux", g2d_mux_p, ARRAY_SIZE(g2d_mux_p), CLK_SET_RATE_PARENT, 0x10c, 5, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_VENC_MUX, "venc_mux", venc_mux_p, ARRAY_SIZE(venc_mux_p), CLK_SET_RATE_PARENT, 0x10c, 11, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_VDEC_MUX, "vdec_mux", vdec_mux_p, ARRAY_SIZE(vdec_mux_p), CLK_SET_RATE_PARENT, 0x110, 5, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_VPP_MUX, "vpp_mux", vpp_mux_p, ARRAY_SIZE(vpp_mux_p), CLK_SET_RATE_PARENT, 0x110, 11, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_EDC0_MUX, "edc0_mux", edc0_mux_p, ARRAY_SIZE(edc0_mux_p), CLK_SET_RATE_PARENT, 0x114, 6, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_LDI0_MUX, "ldi0_mux", ldi0_mux_p, ARRAY_SIZE(ldi0_mux_p), CLK_SET_RATE_PARENT, 0x114, 13, 2, CLK_MUX_HIWORD_MASK, }, + { HI3620_EDC1_MUX, "edc1_mux", edc1_mux_p, ARRAY_SIZE(edc1_mux_p), CLK_SET_RATE_PARENT, 0x118, 6, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_LDI1_MUX, "ldi1_mux", ldi1_mux_p, ARRAY_SIZE(ldi1_mux_p), CLK_SET_RATE_PARENT, 0x118, 14, 2, CLK_MUX_HIWORD_MASK, }, + { HI3620_RCLK_HSIC, "rclk_hsic", rclk_hsic_p, ARRAY_SIZE(rclk_hsic_p), CLK_SET_RATE_PARENT, 0x130, 2, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_MMC2_MUX, "mmc2_mux", mmc2_mux_p, ARRAY_SIZE(mmc2_mux_p), CLK_SET_RATE_PARENT, 0x140, 4, 1, CLK_MUX_HIWORD_MASK, }, + { HI3620_MMC3_MUX, "mmc3_mux", mmc3_mux_p, ARRAY_SIZE(mmc3_mux_p), CLK_SET_RATE_PARENT, 0x140, 9, 1, CLK_MUX_HIWORD_MASK, }, +}; + +static struct hisi_divider_clock hi3620_div_clks[] __initdata = { + { HI3620_SHAREAXI_DIV, "saxi_div", "saxi_mux", 0, 0x100, 0, 5, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_CFGAXI_DIV, "cfgaxi_div", "saxi_div", 0, 0x100, 5, 2, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_SD_DIV, "sd_div", "sd_mux", 0, 0x108, 0, 4, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_MMC1_DIV, "mmc1_div", "mmc1_mux", 0, 0x108, 5, 4, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_HSIC_DIV, "hsic_div", "rclk_hsic", 0, 0x130, 0, 2, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_MMC2_DIV, "mmc2_div", "mmc2_mux", 0, 0x140, 0, 4, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_MMC3_DIV, "mmc3_div", "mmc3_mux", 0, 0x140, 5, 4, CLK_MUX_HIWORD_MASK, NULL, }, +}; + +static struct hisi_gate_clock hi3620_seperated_gate_clks[] __initdata = { + { HI3620_TIMERCLK01, "timerclk01", "timer_rclk01", 0, 0x20, 0, 0, }, + { HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo", 0, 0x20, 1, 0, }, + { HI3620_TIMERCLK23, "timerclk23", "timer_rclk23", 0, 0x20, 2, 0, }, + { HI3620_TIMER_RCLK23, "timer_rclk23", "rclk_tcxo", 0, 0x20, 3, 0, }, + { HI3620_RTCCLK, "rtcclk", "pclk", 0, 0x20, 5, 0, }, + { HI3620_KPC_CLK, "kpc_clk", "pclk", 0, 0x20, 6, 0, }, + { HI3620_GPIOCLK0, "gpioclk0", "pclk", 0, 0x20, 8, 0, }, + { HI3620_GPIOCLK1, "gpioclk1", "pclk", 0, 0x20, 9, 0, }, + { HI3620_GPIOCLK2, "gpioclk2", "pclk", 0, 0x20, 10, 0, }, + { HI3620_GPIOCLK3, "gpioclk3", "pclk", 0, 0x20, 11, 0, }, + { HI3620_GPIOCLK4, "gpioclk4", "pclk", 0, 0x20, 12, 0, }, + { HI3620_GPIOCLK5, "gpioclk5", "pclk", 0, 0x20, 13, 0, }, + { HI3620_GPIOCLK6, "gpioclk6", "pclk", 0, 0x20, 14, 0, }, + { HI3620_GPIOCLK7, "gpioclk7", "pclk", 0, 0x20, 15, 0, }, + { HI3620_GPIOCLK8, "gpioclk8", "pclk", 0, 0x20, 16, 0, }, + { HI3620_GPIOCLK9, "gpioclk9", "pclk", 0, 0x20, 17, 0, }, + { HI3620_GPIOCLK10, "gpioclk10", "pclk", 0, 0x20, 18, 0, }, + { HI3620_GPIOCLK11, "gpioclk11", "pclk", 0, 0x20, 19, 0, }, + { HI3620_GPIOCLK12, "gpioclk12", "pclk", 0, 0x20, 20, 0, }, + { HI3620_GPIOCLK13, "gpioclk13", "pclk", 0, 0x20, 21, 0, }, + { HI3620_GPIOCLK14, "gpioclk14", "pclk", 0, 0x20, 22, 0, }, + { HI3620_GPIOCLK15, "gpioclk15", "pclk", 0, 0x20, 23, 0, }, + { HI3620_GPIOCLK16, "gpioclk16", "pclk", 0, 0x20, 24, 0, }, + { HI3620_GPIOCLK17, "gpioclk17", "pclk", 0, 0x20, 25, 0, }, + { HI3620_GPIOCLK18, "gpioclk18", "pclk", 0, 0x20, 26, 0, }, + { HI3620_GPIOCLK19, "gpioclk19", "pclk", 0, 0x20, 27, 0, }, + { HI3620_GPIOCLK20, "gpioclk20", "pclk", 0, 0x20, 28, 0, }, + { HI3620_GPIOCLK21, "gpioclk21", "pclk", 0, 0x20, 29, 0, }, + { HI3620_DPHY0_CLK, "dphy0_clk", "osc26m", 0, 0x30, 15, 0, }, + { HI3620_DPHY1_CLK, "dphy1_clk", "osc26m", 0, 0x30, 16, 0, }, + { HI3620_DPHY2_CLK, "dphy2_clk", "osc26m", 0, 0x30, 17, 0, }, + { HI3620_USBPHY_CLK, "usbphy_clk", "rclk_pico", 0, 0x30, 24, 0, }, + { HI3620_ACP_CLK, "acp_clk", "rclk_cfgaxi", 0, 0x30, 28, 0, }, + { HI3620_TIMERCLK45, "timerclk45", "rclk_tcxo", 0, 0x40, 3, 0, }, + { HI3620_TIMERCLK67, "timerclk67", "rclk_tcxo", 0, 0x40, 4, 0, }, + { HI3620_TIMERCLK89, "timerclk89", "rclk_tcxo", 0, 0x40, 5, 0, }, + { HI3620_PWMCLK0, "pwmclk0", "pwm0_mux", 0, 0x40, 7, 0, }, + { HI3620_PWMCLK1, "pwmclk1", "pwm1_mux", 0, 0x40, 8, 0, }, + { HI3620_UARTCLK0, "uartclk0", "uart0_mux", 0, 0x40, 16, 0, }, + { HI3620_UARTCLK1, "uartclk1", "uart1_mux", 0, 0x40, 17, 0, }, + { HI3620_UARTCLK2, "uartclk2", "uart2_mux", 0, 0x40, 18, 0, }, + { HI3620_UARTCLK3, "uartclk3", "uart3_mux", 0, 0x40, 19, 0, }, + { HI3620_UARTCLK4, "uartclk4", "uart4_mux", 0, 0x40, 20, 0, }, + { HI3620_SPICLK0, "spiclk0", "spi0_mux", 0, 0x40, 21, 0, }, + { HI3620_SPICLK1, "spiclk1", "spi1_mux", 0, 0x40, 22, 0, }, + { HI3620_SPICLK2, "spiclk2", "spi2_mux", 0, 0x40, 23, 0, }, + { HI3620_I2CCLK0, "i2cclk0", "pclk", 0, 0x40, 24, 0, }, + { HI3620_I2CCLK1, "i2cclk1", "pclk", 0, 0x40, 25, 0, }, + { HI3620_SCI_CLK, "sci_clk", "osc26m", 0, 0x40, 26, 0, }, + { HI3620_I2CCLK2, "i2cclk2", "pclk", 0, 0x40, 28, 0, }, + { HI3620_I2CCLK3, "i2cclk3", "pclk", 0, 0x40, 29, 0, }, + { HI3620_DDRC_PER_CLK, "ddrc_per_clk", "rclk_cfgaxi", 0, 0x50, 9, 0, }, + { HI3620_DMAC_CLK, "dmac_clk", "rclk_cfgaxi", 0, 0x50, 10, 0, }, + { HI3620_USB2DVC_CLK, "usb2dvc_clk", "rclk_cfgaxi", 0, 0x50, 17, 0, }, + { HI3620_SD_CLK, "sd_clk", "sd_div", 0, 0x50, 20, 0, }, + { HI3620_MMC_CLK1, "mmc_clk1", "mmc1_mux2", 0, 0x50, 21, 0, }, + { HI3620_MMC_CLK2, "mmc_clk2", "mmc2_div", 0, 0x50, 22, 0, }, + { HI3620_MMC_CLK3, "mmc_clk3", "mmc3_div", 0, 0x50, 23, 0, }, + { HI3620_MCU_CLK, "mcu_clk", "acp_clk", 0, 0x50, 24, 0, }, +}; + +static void __init hi3620_clk_init(struct device_node *np) +{ + void __iomem *base; + + if (np) { + base = of_iomap(np, 0); + if (!base) { + pr_err("failed to map Hi3620 clock registers\n"); + return; + } + } else { + pr_err("failed to find Hi3620 clock node in DTS\n"); + return; + } + + hisi_clk_init(np, HI3620_NR_CLKS); + + hisi_clk_register_fixed_rate(hi3620_fixed_rate_clks, + ARRAY_SIZE(hi3620_fixed_rate_clks), + base); + hisi_clk_register_fixed_factor(hi3620_fixed_factor_clks, + ARRAY_SIZE(hi3620_fixed_factor_clks), + base); + hisi_clk_register_mux(hi3620_mux_clks, ARRAY_SIZE(hi3620_mux_clks), + base); + hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks), + base); + hisi_clk_register_gate_sep(hi3620_seperated_gate_clks, + ARRAY_SIZE(hi3620_seperated_gate_clks), + base); +} +CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init); diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c new file mode 100644 index 000000000000..a3a7152c92d9 --- /dev/null +++ b/drivers/clk/hisilicon/clk.c @@ -0,0 +1,171 @@ +/* + * Hisilicon clock driver + * + * Copyright (c) 2012-2013 Hisilicon Limited. + * Copyright (c) 2012-2013 Linaro Limited. + * + * Author: Haojian Zhuang + * Xin Li + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +static DEFINE_SPINLOCK(hisi_clk_lock); +static struct clk **clk_table; +static struct clk_onecell_data clk_data; + +void __init hisi_clk_init(struct device_node *np, int nr_clks) +{ + clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); + if (!clk_table) { + pr_err("%s: could not allocate clock lookup table\n", __func__); + return; + } + clk_data.clks = clk_table; + clk_data.clk_num = nr_clks; + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} + +void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, + int nums, void __iomem *base) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + clk = clk_register_fixed_rate(NULL, clks[i].name, + clks[i].parent_name, + clks[i].flags, + clks[i].fixed_rate); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + } +} + +void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, + int nums, void __iomem *base) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + clk = clk_register_fixed_factor(NULL, clks[i].name, + clks[i].parent_name, + clks[i].flags, clks[i].mult, + clks[i].div); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + } +} + +void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, + int nums, void __iomem *base) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + clk = clk_register_mux(NULL, clks[i].name, clks[i].parent_names, + clks[i].num_parents, clks[i].flags, + base + clks[i].offset, clks[i].shift, + clks[i].width, clks[i].mux_flags, + &hisi_clk_lock); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + clk_table[clks[i].id] = clk; + } +} + +void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, + int nums, void __iomem *base) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + clk = clk_register_divider_table(NULL, clks[i].name, + clks[i].parent_name, + clks[i].flags, + base + clks[i].offset, + clks[i].shift, clks[i].width, + clks[i].div_flags, + clks[i].table, + &hisi_clk_lock); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + clk_table[clks[i].id] = clk; + } +} + +void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, + int nums, void __iomem *base) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + clk = hisi_register_clkgate_sep(NULL, clks[i].name, + clks[i].parent_name, + clks[i].flags, + base + clks[i].offset, + clks[i].bit_idx, + clks[i].gate_flags, + &hisi_clk_lock); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + clk_table[clks[i].id] = clk; + } +} diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h new file mode 100644 index 000000000000..4a6beebefb7a --- /dev/null +++ b/drivers/clk/hisilicon/clk.h @@ -0,0 +1,103 @@ +/* + * Hisilicon Hi3620 clock gate driver + * + * Copyright (c) 2012-2013 Hisilicon Limited. + * Copyright (c) 2012-2013 Linaro Limited. + * + * Author: Haojian Zhuang + * Xin Li + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __HISI_CLK_H +#define __HISI_CLK_H + +#include +#include +#include + +struct hisi_fixed_rate_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long flags; + unsigned long fixed_rate; +}; + +struct hisi_fixed_factor_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long mult; + unsigned long div; + unsigned long flags; +}; + +struct hisi_mux_clock { + unsigned int id; + const char *name; + const char **parent_names; + u8 num_parents; + unsigned long flags; + unsigned long offset; + u8 shift; + u8 width; + u8 mux_flags; + const char *alias; +}; + +struct hisi_divider_clock { + unsigned int id; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long offset; + u8 shift; + u8 width; + u8 div_flags; + struct clk_div_table *table; + const char *alias; +}; + +struct hisi_gate_clock { + unsigned int id; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long offset; + u8 bit_idx; + u8 gate_flags; + const char *alias; +}; + +struct clk *hisi_register_clkgate_sep(struct device *, const char *, + const char *, unsigned long, + void __iomem *, u8, + u8, spinlock_t *); + +void __init hisi_clk_init(struct device_node *, int); +void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *, + int, void __iomem *); +void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *, + int, void __iomem *); +void __init hisi_clk_register_mux(struct hisi_mux_clock *, int, + void __iomem *); +void __init hisi_clk_register_divider(struct hisi_divider_clock *, + int, void __iomem *); +void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, + int, void __iomem *); +#endif /* __HISI_CLK_H */ diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisilicon/clkgate-separated.c new file mode 100644 index 000000000000..b03d5a7246f9 --- /dev/null +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -0,0 +1,130 @@ +/* + * Hisilicon clock separated gate driver + * + * Copyright (c) 2012-2013 Hisilicon Limited. + * Copyright (c) 2012-2013 Linaro Limited. + * + * Author: Haojian Zhuang + * Xin Li + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +/* clock separated gate register offset */ +#define CLKGATE_SEPERATED_ENABLE 0x0 +#define CLKGATE_SEPERATED_DISABLE 0x4 +#define CLKGATE_SEPERATED_STATUS 0x8 + +struct clkgate_separated { + struct clk_hw hw; + void __iomem *enable; /* enable register */ + u8 bit_idx; /* bits in enable/disable register */ + u8 flags; + spinlock_t *lock; +}; + +static int clkgate_separated_enable(struct clk_hw *hw) +{ + struct clkgate_separated *sclk; + unsigned long flags = 0; + u32 reg; + + sclk = container_of(hw, struct clkgate_separated, hw); + if (sclk->lock) + spin_lock_irqsave(sclk->lock, flags); + reg = BIT(sclk->bit_idx); + writel_relaxed(reg, sclk->enable); + readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS); + if (sclk->lock) + spin_unlock_irqrestore(sclk->lock, flags); + return 0; +} + +static void clkgate_separated_disable(struct clk_hw *hw) +{ + struct clkgate_separated *sclk; + unsigned long flags = 0; + u32 reg; + + sclk = container_of(hw, struct clkgate_separated, hw); + if (sclk->lock) + spin_lock_irqsave(sclk->lock, flags); + reg = BIT(sclk->bit_idx); + writel_relaxed(reg, sclk->enable + CLKGATE_SEPERATED_DISABLE); + readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS); + if (sclk->lock) + spin_unlock_irqrestore(sclk->lock, flags); +} + +static int clkgate_separated_is_enabled(struct clk_hw *hw) +{ + struct clkgate_separated *sclk; + u32 reg; + + sclk = container_of(hw, struct clkgate_separated, hw); + reg = readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS); + reg &= BIT(sclk->bit_idx); + + return reg ? 1 : 0; +} + +static struct clk_ops clkgate_separated_ops = { + .enable = clkgate_separated_enable, + .disable = clkgate_separated_disable, + .is_enabled = clkgate_separated_is_enabled, +}; + +struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock) +{ + struct clkgate_separated *sclk; + struct clk *clk; + struct clk_init_data init; + + sclk = kzalloc(sizeof(*sclk), GFP_KERNEL); + if (!sclk) { + pr_err("%s: fail to allocate separated gated clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = name; + init.ops = &clkgate_separated_ops; + init.flags = flags | CLK_IS_BASIC; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + + sclk->enable = reg + CLKGATE_SEPERATED_ENABLE; + sclk->bit_idx = bit_idx; + sclk->flags = clk_gate_flags; + sclk->hw.init = &init; + + clk = clk_register(dev, &sclk->hw); + if (IS_ERR(clk)) + kfree(sclk); + return clk; +} diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h new file mode 100644 index 000000000000..6eaa6a45e110 --- /dev/null +++ b/include/dt-bindings/clock/hi3620-clock.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012-2013 Hisilicon Limited. + * Copyright (c) 2012-2013 Linaro Limited. + * + * Author: Haojian Zhuang + * Xin Li + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __DTS_HI3620_CLOCK_H +#define __DTS_HI3620_CLOCK_H + +#define HI3620_NONE_CLOCK 0 + +/* fixed rate & fixed factor clocks */ +#define HI3620_OSC32K 1 +#define HI3620_OSC26M 2 +#define HI3620_PCLK 3 +#define HI3620_PLL_ARM0 4 +#define HI3620_PLL_ARM1 5 +#define HI3620_PLL_PERI 6 +#define HI3620_PLL_USB 7 +#define HI3620_PLL_HDMI 8 +#define HI3620_PLL_GPU 9 +#define HI3620_RCLK_TCXO 10 +#define HI3620_RCLK_CFGAXI 11 +#define HI3620_RCLK_PICO 12 + +/* mux clocks */ +#define HI3620_TIMER0_MUX 32 +#define HI3620_TIMER1_MUX 33 +#define HI3620_TIMER2_MUX 34 +#define HI3620_TIMER3_MUX 35 +#define HI3620_TIMER4_MUX 36 +#define HI3620_TIMER5_MUX 37 +#define HI3620_TIMER6_MUX 38 +#define HI3620_TIMER7_MUX 39 +#define HI3620_TIMER8_MUX 40 +#define HI3620_TIMER9_MUX 41 +#define HI3620_UART0_MUX 42 +#define HI3620_UART1_MUX 43 +#define HI3620_UART2_MUX 44 +#define HI3620_UART3_MUX 45 +#define HI3620_UART4_MUX 46 +#define HI3620_SPI0_MUX 47 +#define HI3620_SPI1_MUX 48 +#define HI3620_SPI2_MUX 49 +#define HI3620_SAXI_MUX 50 +#define HI3620_PWM0_MUX 51 +#define HI3620_PWM1_MUX 52 +#define HI3620_SD_MUX 53 +#define HI3620_MMC1_MUX 54 +#define HI3620_MMC1_MUX2 55 +#define HI3620_G2D_MUX 56 +#define HI3620_VENC_MUX 57 +#define HI3620_VDEC_MUX 58 +#define HI3620_VPP_MUX 59 +#define HI3620_EDC0_MUX 60 +#define HI3620_LDI0_MUX 61 +#define HI3620_EDC1_MUX 62 +#define HI3620_LDI1_MUX 63 +#define HI3620_RCLK_HSIC 64 +#define HI3620_MMC2_MUX 65 +#define HI3620_MMC3_MUX 66 + +/* divider clocks */ +#define HI3620_SHAREAXI_DIV 128 +#define HI3620_CFGAXI_DIV 129 +#define HI3620_SD_DIV 130 +#define HI3620_MMC1_DIV 131 +#define HI3620_HSIC_DIV 132 +#define HI3620_MMC2_DIV 133 +#define HI3620_MMC3_DIV 134 + +/* gate clocks */ +#define HI3620_TIMERCLK01 160 +#define HI3620_TIMER_RCLK01 161 +#define HI3620_TIMERCLK23 162 +#define HI3620_TIMER_RCLK23 163 +#define HI3620_TIMERCLK45 164 +#define HI3620_TIMERCLK67 165 +#define HI3620_TIMERCLK89 166 +#define HI3620_RTCCLK 167 +#define HI3620_KPC_CLK 168 +#define HI3620_GPIOCLK0 169 +#define HI3620_GPIOCLK1 170 +#define HI3620_GPIOCLK2 171 +#define HI3620_GPIOCLK3 172 +#define HI3620_GPIOCLK4 173 +#define HI3620_GPIOCLK5 174 +#define HI3620_GPIOCLK6 175 +#define HI3620_GPIOCLK7 176 +#define HI3620_GPIOCLK8 177 +#define HI3620_GPIOCLK9 178 +#define HI3620_GPIOCLK10 179 +#define HI3620_GPIOCLK11 180 +#define HI3620_GPIOCLK12 181 +#define HI3620_GPIOCLK13 182 +#define HI3620_GPIOCLK14 183 +#define HI3620_GPIOCLK15 184 +#define HI3620_GPIOCLK16 185 +#define HI3620_GPIOCLK17 186 +#define HI3620_GPIOCLK18 187 +#define HI3620_GPIOCLK19 188 +#define HI3620_GPIOCLK20 189 +#define HI3620_GPIOCLK21 190 +#define HI3620_DPHY0_CLK 191 +#define HI3620_DPHY1_CLK 192 +#define HI3620_DPHY2_CLK 193 +#define HI3620_USBPHY_CLK 194 +#define HI3620_ACP_CLK 195 +#define HI3620_PWMCLK0 196 +#define HI3620_PWMCLK1 197 +#define HI3620_UARTCLK0 198 +#define HI3620_UARTCLK1 199 +#define HI3620_UARTCLK2 200 +#define HI3620_UARTCLK3 201 +#define HI3620_UARTCLK4 202 +#define HI3620_SPICLK0 203 +#define HI3620_SPICLK1 204 +#define HI3620_SPICLK2 205 +#define HI3620_I2CCLK0 206 +#define HI3620_I2CCLK1 207 +#define HI3620_I2CCLK2 208 +#define HI3620_I2CCLK3 209 +#define HI3620_SCI_CLK 210 +#define HI3620_DDRC_PER_CLK 211 +#define HI3620_DMAC_CLK 212 +#define HI3620_USB2DVC_CLK 213 +#define HI3620_SD_CLK 214 +#define HI3620_MMC_CLK1 215 +#define HI3620_MMC_CLK2 216 +#define HI3620_MMC_CLK3 217 +#define HI3620_MCU_CLK 218 + +#define HI3620_NR_CLKS 219 + +#endif /* __DTS_HI3620_CLOCK_H */ -- cgit v1.2.3 From 0d9653014f081eacdeb82b0a8ad0e0d4ce87e3da Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 2 Dec 2013 14:23:02 +0200 Subject: drm/i915: Add REG_WRITE_FOOTER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a REG_WRITE_FOOTER macro as a counterpart to the REG_WRITE_HEADER. The current code has the spin_lock() in the HEADER, but the spin_unlock() is open coded, which looks rather confusing on the first glance. A bit of additional symmetry might help. Signed-off-by: Ville Syrjälä Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d511e00095ac..ffb6edebd887 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -533,12 +533,15 @@ __gen4_read(64) trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) +#define REG_WRITE_FOOTER \ + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags) + #define __gen4_write(x) \ static void \ gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ REG_WRITE_HEADER; \ __raw_i915_write##x(dev_priv, reg, val); \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + REG_WRITE_FOOTER; \ } #define __gen5_write(x) \ @@ -547,7 +550,7 @@ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace REG_WRITE_HEADER; \ ilk_dummy_write(dev_priv); \ __raw_i915_write##x(dev_priv, reg, val); \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + REG_WRITE_FOOTER; \ } #define __gen6_write(x) \ @@ -562,7 +565,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace if (unlikely(__fifo_ret)) { \ gen6_gt_check_fifodbg(dev_priv); \ } \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + REG_WRITE_FOOTER; \ } #define __hsw_write(x) \ @@ -579,7 +582,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) gen6_gt_check_fifodbg(dev_priv); \ } \ hsw_unclaimed_reg_check(dev_priv, reg); \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + REG_WRITE_FOOTER; \ } static const u32 gen8_shadowed_regs[] = { @@ -617,7 +620,7 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace dev_priv->uncore.funcs.force_wake_put(dev_priv, \ FORCEWAKE_ALL); \ } \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + REG_WRITE_FOOTER; \ } __gen8_write(8) @@ -646,6 +649,7 @@ __gen4_write(64) #undef __gen6_write #undef __gen5_write #undef __gen4_write +#undef REG_WRITE_FOOTER #undef REG_WRITE_HEADER void intel_uncore_init(struct drm_device *dev) -- cgit v1.2.3 From 82f344967cca4d4d0bd3cbcdeddfc6bf00a46fd8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:29:55 +0200 Subject: drm/i915: Fix bogus FBC1 defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilons Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3be449d884a7..2d203905bd70 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1028,14 +1028,14 @@ #define FBC_CTL_UNCOMPRESSIBLE (1<<14) #define FBC_CTL_C3_IDLE (1<<13) #define FBC_CTL_STRIDE_SHIFT (5) -#define FBC_CTL_FENCENO (1<<0) +#define FBC_CTL_FENCENO_SHIFT (0) #define FBC_COMMAND 0x0320c #define FBC_CMD_COMPRESS (1<<0) #define FBC_STATUS 0x03210 #define FBC_STAT_COMPRESSING (1<<31) #define FBC_STAT_COMPRESSED (1<<30) #define FBC_STAT_MODIFIED (1<<29) -#define FBC_STAT_CURRENT_LINE (1<<0) +#define FBC_STAT_CURRENT_LINE_SHIFT (0) #define FBC_CONTROL2 0x03214 #define FBC_CTL_FENCE_DBL (0<<4) #define FBC_CTL_IDLE_IMM (0<<2) -- cgit v1.2.3 From c5a44aa012ee86b3dfd0c6050ba34cd6eb412875 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:29:58 +0200 Subject: drm/i915: Fix FBC1 plane checks for gen2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On gen2 and gen3 chipsets FBC is supported only on plane A. Fix (and simplify) the plane checks in intel_update_fbc() accordingly. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ff47520f8d40..d389078f0fe1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -537,10 +537,10 @@ void intel_update_fbc(struct drm_device *dev) DRM_DEBUG_KMS("mode too large for compression, disabling\n"); goto out_disable; } - if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) && - intel_crtc->plane != 0) { + if ((INTEL_INFO(dev)->gen < 4 || IS_HASWELL(dev)) && + intel_crtc->plane != PLANE_A) { if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE)) - DRM_DEBUG_KMS("plane not 0, disabling compression\n"); + DRM_DEBUG_KMS("plane not A, disabling compression\n"); goto out_disable; } -- cgit v1.2.3 From 40045465a91cad4e4bcd2691f0bece5f8b2910e3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:29:59 +0200 Subject: drm/i915: Reorganize FBC function pointer initializaition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize the FBC vfuncs on gen2 and gen3 chipsets. Also make a clean split for gen7+ vs. gen5+ vfunc initialization. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d389078f0fe1..ac4a74a41344 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5956,25 +5956,23 @@ void intel_init_pm(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; if (I915_HAS_FBC(dev)) { - if (HAS_PCH_SPLIT(dev)) { + if (INTEL_INFO(dev)->gen >= 7) { dev_priv->display.fbc_enabled = ironlake_fbc_enabled; - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) - dev_priv->display.enable_fbc = - gen7_enable_fbc; - else - dev_priv->display.enable_fbc = - ironlake_enable_fbc; + dev_priv->display.enable_fbc = gen7_enable_fbc; + dev_priv->display.disable_fbc = ironlake_disable_fbc; + } else if (INTEL_INFO(dev)->gen >= 5) { + dev_priv->display.fbc_enabled = ironlake_fbc_enabled; + dev_priv->display.enable_fbc = ironlake_enable_fbc; dev_priv->display.disable_fbc = ironlake_disable_fbc; } else if (IS_GM45(dev)) { dev_priv->display.fbc_enabled = g4x_fbc_enabled; dev_priv->display.enable_fbc = g4x_enable_fbc; dev_priv->display.disable_fbc = g4x_disable_fbc; - } else if (IS_CRESTLINE(dev)) { + } else { dev_priv->display.fbc_enabled = i8xx_fbc_enabled; dev_priv->display.enable_fbc = i8xx_enable_fbc; dev_priv->display.disable_fbc = i8xx_disable_fbc; } - /* 855GM needs testing */ } /* For cxsr */ -- cgit v1.2.3 From 1f1c2e2468f937cefd6bcb645c959c7b5d9821df Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:30:01 +0200 Subject: drm/i915: Swap primary planes on gen2 for FBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only plane A is FBC capable on gen2 (like gen3), but the panel fitter is hooked up to pipe B, so we want to prefer pipe B + plane A. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson [danvet: Add the code comment Chris requested in his review.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 14 +++++++++----- drivers/gpu/drm/i915/intel_display.c | 7 +++++-- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 271560080ad5..74918e7afeb5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3139,10 +3139,10 @@ static int i8xx_irq_postinstall(struct drm_device *dev) * Returns true when a page flip has completed. */ static bool i8xx_handle_vblank(struct drm_device *dev, - int pipe, u16 iir) + int plane, int pipe, u32 iir) { drm_i915_private_t *dev_priv = dev->dev_private; - u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe); + u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane); if (!drm_handle_vblank(dev, pipe)) return false; @@ -3150,7 +3150,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev, if ((iir & flip_pending) == 0) return false; - intel_prepare_page_flip(dev, pipe); + intel_prepare_page_flip(dev, plane); /* We detect FlipDone by looking for the change in PendingFlip from '1' * to '0' on the following vblank, i.e. IIR has the Pendingflip @@ -3219,9 +3219,13 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) notify_ring(dev, &dev_priv->ring[RCS]); for_each_pipe(pipe) { + int plane = pipe; + if (IS_MOBILE(dev)) + plane = !plane; + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS && - i8xx_handle_vblank(dev, pipe, iir)) - flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); + i8xx_handle_vblank(dev, plane, pipe, iir)) + flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane); if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) i9xx_pipe_crc_irq_handler(dev, pipe); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 66b39dbaf12c..2eaf7e7e5a40 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10109,10 +10109,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->lut_b[i] = i; } - /* Swap pipes & planes for FBC on pre-965 */ + /* + * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port + * is hooked to plane B. Hence we want plane A feeding pipe B. + */ intel_crtc->pipe = pipe; intel_crtc->plane = pipe; - if (IS_MOBILE(dev) && IS_GEN3(dev)) { + if (IS_MOBILE(dev) && INTEL_INFO(dev)->gen < 4) { DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); intel_crtc->plane = !pipe; } -- cgit v1.2.3 From 5135d64b7f0c91c69af3147e5c93eec05f80b820 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Fri, 29 Nov 2013 15:56:30 +0530 Subject: drm/i915/vlv: Update Wait for FIFO and wait for 20 free entries. v3 On VLV, FIFO will be shared by both SW and HW. So, we read the free entries through register and update dev_priv variable and wait for only 20 entries to be free From Deepak's follow-up mail explaining why vlv is special: "On SB, Out of 64 FIFO Entries, 20 Entries will be used by HW and remaining 44 will be used by the SW,. I think due to this reason, we have a threshold of 20 Entries." "On VLV, HW and SW can access all 64 fifo entries, I don't think having a threshold of 20 Entries is mandatory on VLV. Also, since both SW and HW can access all 64 Entries. I think on VLV, we need to update the fifo_count before waiting for the FIFO." v2: Apply mask when we read the number of free FIFO entries (Ville). v3: Mask applied after reading the register (Deepak). Signed-off-by: Deepak S [danvet: Add further explanation from Deepak to commit message.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ffb6edebd887..b737a32dd399 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -150,6 +150,13 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) { int ret = 0; + /* On VLV, FIFO will be shared by both SW and HW. + * So, we need to read the FREE_ENTRIES everytime */ + if (IS_VALLEYVIEW(dev_priv->dev)) + dev_priv->uncore.fifo_count = + __raw_i915_read32(dev_priv, GTFIFOCTL) & + GT_FIFO_FREE_ENTRIES_MASK; + if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { int loop = 500; u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK; -- cgit v1.2.3 From 70903c3ba8fa5ad391d1519c60666a389e4be597 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2013 09:59:09 +0000 Subject: drm/i915: Fix ordering of unbind vs unpin pages It is useful to assert that if the object is bound, then it must have its pages pinned to prevent the shrinker from reaping its backing store. This is even more useful with the introduction of real-ppgtt whereupon we may have the object bound into several vma, with each instance pinning the backing store. This assertion breaks down during unbind where we unpinned the backing store before decoupling the vma binding. This can be fixed with a trivial reording of the unbind sequence, which reinforces the pin pages bind to vma ... unbind from vma unpin pages concept. v2: Bonus comment Signed-off-by: Chris Wilson Cc: Ben Widawsky Reviewed-by: Ben Widawsky Tested-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 40d9dcf858bf..92149bcabe98 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2746,7 +2746,6 @@ int i915_vma_unbind(struct i915_vma *vma) obj->has_aliasing_ppgtt_mapping = 0; } i915_gem_gtt_finish_object(obj); - i915_gem_object_unpin_pages(obj); list_del(&vma->mm_list); /* Avoid an unnecessary call to unbind on rebind. */ @@ -2754,7 +2753,6 @@ int i915_vma_unbind(struct i915_vma *vma) obj->map_and_fenceable = true; drm_mm_remove_node(&vma->node); - i915_gem_vma_destroy(vma); /* Since the unbound list is global, only move to that list if @@ -2762,6 +2760,12 @@ int i915_vma_unbind(struct i915_vma *vma) if (list_empty(&obj->vma_list)) list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list); + /* And finally now the object is completely decoupled from this vma, + * we can drop its hold on the backing storage and allow it to be + * reaped by the shrinker. + */ + i915_gem_object_unpin_pages(obj); + return 0; } -- cgit v1.2.3 From c94cae53f9e564484f906a79be5639fc66e8cb02 Mon Sep 17 00:00:00 2001 From: Eric Trudeau Date: Wed, 4 Dec 2013 11:39:33 +0000 Subject: XEN: Grant table address, xen_hvm_resume_frames, is a phys_addr not a pfn From: Eric Trudeau xen_hvm_resume_frames stores the physical address of the grant table. englighten.c was incorrectly setting it as if it was a page frame number. This caused the table to be mapped into the guest at an unexpected physical address. Additionally, a warning is improved to include the grant table address which failed in xen_remap. Signed-off-by: Eric Trudeau Signed-off-by: Stefano Stabellini --- arch/arm/xen/enlighten.c | 4 ++-- drivers/xen/grant-table.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 83e4f959ee47..6a288c7be49f 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -224,10 +224,10 @@ static int __init xen_guest_init(void) } if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res)) return 0; - xen_hvm_resume_frames = res.start >> PAGE_SHIFT; + xen_hvm_resume_frames = res.start; xen_events_irq = irq_of_parse_and_map(node, 0); pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n", - version, xen_events_irq, xen_hvm_resume_frames); + version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT)); xen_domain_type = XEN_HVM_DOMAIN; xen_setup_features(); diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 028387192b60..aa846a48f400 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -1176,7 +1176,8 @@ static int gnttab_setup(void) gnttab_shared.addr = xen_remap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes); if (gnttab_shared.addr == NULL) { - pr_warn("Failed to ioremap gnttab share frames!\n"); + pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n", + xen_hvm_resume_frames); return -ENOMEM; } } -- cgit v1.2.3 From 9f87d6f26b2fcedfc3d1ec6c65ce568b21546ee2 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:07:51 +0900 Subject: spi: atmel: Use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Nicolas Ferre Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 273db0beb2b8..57fa73876223 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1510,7 +1510,7 @@ static int atmel_spi_probe(struct platform_device *pdev) if (irq < 0) return irq; - clk = clk_get(&pdev->dev, "spi_clk"); + clk = devm_clk_get(&pdev->dev, "spi_clk"); if (IS_ERR(clk)) return PTR_ERR(clk); @@ -1570,14 +1570,14 @@ static int atmel_spi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n"); if (as->use_pdc) { - ret = request_irq(irq, atmel_spi_pdc_interrupt, 0, - dev_name(&pdev->dev), master); + ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pdc_interrupt, + 0, dev_name(&pdev->dev), master); } else { tasklet_init(&as->tasklet, atmel_spi_tasklet_func, (unsigned long)master); - ret = request_irq(irq, atmel_spi_pio_interrupt, 0, - dev_name(&pdev->dev), master); + ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pio_interrupt, + 0, dev_name(&pdev->dev), master); } if (ret) goto out_unmap_regs; @@ -1603,7 +1603,7 @@ static int atmel_spi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", (unsigned long)regs->start, irq); - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret) goto out_free_dma; @@ -1617,7 +1617,6 @@ out_free_dma: spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ clk_disable_unprepare(clk); out_free_irq: - free_irq(irq, master); out_unmap_regs: out_free_buffer: if (!as->use_pdc) @@ -1625,7 +1624,6 @@ out_free_buffer: dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, as->buffer_dma); out_free: - clk_put(clk); spi_master_put(master); return ret; } @@ -1668,10 +1666,6 @@ static int atmel_spi_remove(struct platform_device *pdev) as->buffer_dma); clk_disable_unprepare(as->clk); - clk_put(as->clk); - free_irq(as->irq, master); - - spi_unregister_master(master); return 0; } -- cgit v1.2.3 From 9a3ced19d8da908234fe9879ee1c0609c8ed21e8 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:10:10 +0900 Subject: spi: coldfire-qspi: Use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 47 ++++++++++++----------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index cc5b75d10c38..9ee81a4c7351 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -403,38 +403,31 @@ static int mcfqspi_probe(struct platform_device *pdev) goto fail0; } - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_dbg(&pdev->dev, "request_mem_region failed\n"); - status = -EBUSY; + mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mcfqspi->iobase)) { + status = PTR_ERR(mcfqspi->iobase); goto fail0; } - mcfqspi->iobase = ioremap(res->start, resource_size(res)); - if (!mcfqspi->iobase) { - dev_dbg(&pdev->dev, "ioremap failed\n"); - status = -ENOMEM; - goto fail1; - } - mcfqspi->irq = platform_get_irq(pdev, 0); if (mcfqspi->irq < 0) { dev_dbg(&pdev->dev, "platform_get_irq failed\n"); status = -ENXIO; - goto fail2; + goto fail0; } - status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0, - pdev->name, mcfqspi); + status = devm_request_irq(&pdev->dev, mcfqspi->irq, mcfqspi_irq_handler, + 0, pdev->name, mcfqspi); if (status) { dev_dbg(&pdev->dev, "request_irq failed\n"); - goto fail2; + goto fail0; } - mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk"); + mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk"); if (IS_ERR(mcfqspi->clk)) { dev_dbg(&pdev->dev, "clk_get failed\n"); status = PTR_ERR(mcfqspi->clk); - goto fail3; + goto fail0; } clk_enable(mcfqspi->clk); @@ -445,7 +438,7 @@ static int mcfqspi_probe(struct platform_device *pdev) status = mcfqspi_cs_setup(mcfqspi); if (status) { dev_dbg(&pdev->dev, "error initializing cs_control\n"); - goto fail4; + goto fail1; } init_waitqueue_head(&mcfqspi->waitq); @@ -459,10 +452,10 @@ static int mcfqspi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); - status = spi_register_master(master); + status = devm_spi_register_master(&pdev->dev, master); if (status) { dev_dbg(&pdev->dev, "spi_register_master failed\n"); - goto fail5; + goto fail2; } pm_runtime_enable(mcfqspi->dev); @@ -470,17 +463,10 @@ static int mcfqspi_probe(struct platform_device *pdev) return 0; -fail5: - mcfqspi_cs_teardown(mcfqspi); -fail4: - clk_disable(mcfqspi->clk); - clk_put(mcfqspi->clk); -fail3: - free_irq(mcfqspi->irq, mcfqspi); fail2: - iounmap(mcfqspi->iobase); + mcfqspi_cs_teardown(mcfqspi); fail1: - release_mem_region(res->start, resource_size(res)); + clk_disable(mcfqspi->clk); fail0: spi_master_put(master); @@ -501,11 +487,6 @@ static int mcfqspi_remove(struct platform_device *pdev) mcfqspi_cs_teardown(mcfqspi); clk_disable(mcfqspi->clk); - clk_put(mcfqspi->clk); - free_irq(mcfqspi->irq, mcfqspi); - iounmap(mcfqspi->iobase); - release_mem_region(res->start, resource_size(res)); - spi_unregister_master(master); return 0; } -- cgit v1.2.3 From d299cce76e001406df40c4ff712b33fccbce1222 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 26 Nov 2013 16:14:33 +0200 Subject: drm/i915: check context reset stats before relocations Doing it early prevents moving and relocating objects in vain for contexts that won't get any GPU time. Reported-by: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 38 ++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b800fe449530..9282b4c411f6 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -884,6 +884,24 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, return 0; } +static int +i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, + const u32 ctx_id) +{ + struct i915_ctx_hang_stats *hs; + + hs = i915_gem_context_get_hang_stats(dev, file, ctx_id); + if (IS_ERR(hs)) + return PTR_ERR(hs); + + if (hs->banned) { + DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id); + return -EIO; + } + + return 0; +} + static void i915_gem_execbuffer_move_to_active(struct list_head *vmas, struct intel_ring_buffer *ring) @@ -963,8 +981,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_object *batch_obj; struct drm_clip_rect *cliprects = NULL; struct intel_ring_buffer *ring; - struct i915_ctx_hang_stats *hs; - u32 ctx_id = i915_execbuffer2_get_context_id(*args); + const u32 ctx_id = i915_execbuffer2_get_context_id(*args); u32 exec_start, exec_len; u32 mask, flags; int ret, mode, i; @@ -1101,6 +1118,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto pre_mutex_err; } + ret = i915_gem_validate_context(dev, file, ctx_id); + if (ret) { + mutex_unlock(&dev->struct_mutex); + goto pre_mutex_err; + } + eb = eb_create(args); if (eb == NULL) { mutex_unlock(&dev->struct_mutex); @@ -1153,17 +1176,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret) goto err; - hs = i915_gem_context_get_hang_stats(dev, file, ctx_id); - if (IS_ERR(hs)) { - ret = PTR_ERR(hs); - goto err; - } - - if (hs->banned) { - ret = -EIO; - goto err; - } - ret = i915_switch_context(ring, file, ctx_id); if (ret) goto err; -- cgit v1.2.3 From a87854da2c55b15adc7326a9ee5f8fde281ffe43 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 2 Dec 2013 11:27:59 +0100 Subject: gpio: MOXA ART: rename moxart_gpio_base to base Renaming "moxart_gpio_base" to "base" allows better fit, remove line breaks in moxart_gpio_get(). While doing trivial cleanup, also remove fields initialized with zero in moxart_template_chip. Signed-off-by: Jonas Jensen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-moxart.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c index d662cdededac..4ecd195e4a5b 100644 --- a/drivers/gpio/gpio-moxart.c +++ b/drivers/gpio/gpio-moxart.c @@ -30,7 +30,7 @@ struct moxart_gpio_chip { struct gpio_chip gpio; - void __iomem *moxart_gpio_base; + void __iomem *base; }; static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip) @@ -51,7 +51,7 @@ static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; writel(readl(ioaddr) & ~BIT(offset), ioaddr); return 0; @@ -61,7 +61,7 @@ static int moxart_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_PIN_DIRECTION; + void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; writel(readl(ioaddr) | BIT(offset), ioaddr); return 0; @@ -70,7 +70,7 @@ static int moxart_gpio_direction_output(struct gpio_chip *chip, static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - void __iomem *ioaddr = gc->moxart_gpio_base + GPIO_DATA_OUT; + void __iomem *ioaddr = gc->base + GPIO_DATA_OUT; u32 reg = readl(ioaddr); if (value) @@ -85,14 +85,12 @@ static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) { struct moxart_gpio_chip *gc = to_moxart_gpio(chip); - u32 ret = readl(gc->moxart_gpio_base + GPIO_PIN_DIRECTION); + u32 ret = readl(gc->base + GPIO_PIN_DIRECTION); if (ret & BIT(offset)) - return !!(readl(gc->moxart_gpio_base + GPIO_DATA_OUT) & - BIT(offset)); + return !!(readl(gc->base + GPIO_DATA_OUT) & BIT(offset)); else - return !!(readl(gc->moxart_gpio_base + GPIO_DATA_IN) & - BIT(offset)); + return !!(readl(gc->base + GPIO_DATA_IN) & BIT(offset)); } static struct gpio_chip moxart_template_chip = { @@ -103,9 +101,7 @@ static struct gpio_chip moxart_template_chip = { .direction_output = moxart_gpio_direction_output, .set = moxart_gpio_set, .get = moxart_gpio_get, - .base = 0, .ngpio = 32, - .can_sleep = 0, }; static int moxart_gpio_probe(struct platform_device *pdev) @@ -123,11 +119,11 @@ static int moxart_gpio_probe(struct platform_device *pdev) mgc->gpio = moxart_template_chip; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mgc->moxart_gpio_base = devm_ioremap_resource(dev, res); - if (IS_ERR(mgc->moxart_gpio_base)) { + mgc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(mgc->base)) { dev_err(dev, "%s: devm_ioremap_resource res_gpio failed\n", dev->of_node->full_name); - return PTR_ERR(mgc->moxart_gpio_base); + return PTR_ERR(mgc->base); } mgc->gpio.dev = dev; -- cgit v1.2.3 From b7d0a28a9f65c4f8a547ceece820b8167a854968 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 3 Dec 2013 12:31:11 +0900 Subject: gpio: rewrite gpiochip_offset_to_desc() gpiochip_offset_to_desc() was using gpio_to_desc(), which directly addresses the global GPIO array we are hoping to get rid of someday. Reimplement it using the descriptor array of the chip itself, after checking the requested offset is within the valid bounds of the chip. Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4e10b10d3ddd..c6326e44e2c0 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -150,9 +150,10 @@ EXPORT_SYMBOL_GPL(gpio_to_desc); static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip, unsigned int offset) { - unsigned int gpio = chip->base + offset; + if (offset >= chip->ngpio) + return ERR_PTR(-EINVAL); - return gpio_to_desc(gpio); + return &chip->desc[offset]; } /** -- cgit v1.2.3 From 4cc16085c80d3363315ad183ad72654993766a0f Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:15:23 +0900 Subject: spi: xcomm: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/spi/spi-xcomm.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index 4258c712ad3c..24c40b13dab1 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -231,22 +231,13 @@ static int spi_xcomm_probe(struct i2c_client *i2c, master->dev.of_node = i2c->dev.of_node; i2c_set_clientdata(i2c, master); - ret = spi_register_master(master); + ret = devm_spi_register_master(&i2c->dev, master); if (ret < 0) spi_master_put(master); return ret; } -static int spi_xcomm_remove(struct i2c_client *i2c) -{ - struct spi_master *master = i2c_get_clientdata(i2c); - - spi_unregister_master(master); - - return 0; -} - static const struct i2c_device_id spi_xcomm_ids[] = { { "spi-xcomm" }, { }, @@ -259,7 +250,6 @@ static struct i2c_driver spi_xcomm_driver = { }, .id_table = spi_xcomm_ids, .probe = spi_xcomm_probe, - .remove = spi_xcomm_remove, }; module_i2c_driver(spi_xcomm_driver); -- cgit v1.2.3 From 15e0964dc2a097de3cf518badf2237b6b6adf7fe Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:14:30 +0900 Subject: spi: sc18is602: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Acked-by: Guenter Roeck Signed-off-by: Mark Brown --- drivers/spi/spi-sc18is602.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index 9eda21d739c6..c1a01d1ac315 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -319,7 +319,7 @@ static int sc18is602_probe(struct i2c_client *client, master->transfer_one_message = sc18is602_transfer_one; master->dev.of_node = np; - error = spi_register_master(master); + error = devm_spi_register_master(dev, master); if (error) goto error_reg; @@ -330,16 +330,6 @@ error_reg: return error; } -static int sc18is602_remove(struct i2c_client *client) -{ - struct sc18is602 *hw = i2c_get_clientdata(client); - struct spi_master *master = hw->master; - - spi_unregister_master(master); - - return 0; -} - static const struct i2c_device_id sc18is602_id[] = { { "sc18is602", sc18is602 }, { "sc18is602b", sc18is602b }, @@ -353,7 +343,6 @@ static struct i2c_driver sc18is602_driver = { .name = "sc18is602", }, .probe = sc18is602_probe, - .remove = sc18is602_remove, .id_table = sc18is602_id, }; -- cgit v1.2.3 From 999b6e932bf7238a0d1eb35d0b3d6eac673b8777 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:11:56 +0900 Subject: spi: falcon: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Acked-by: Thomas Langer Signed-off-by: Mark Brown --- drivers/spi/spi-falcon.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index c7a74f0ef892..dd5bd468e962 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -433,21 +433,12 @@ static int falcon_sflash_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret) spi_master_put(master); return ret; } -static int falcon_sflash_remove(struct platform_device *pdev) -{ - struct falcon_sflash *priv = platform_get_drvdata(pdev); - - spi_unregister_master(priv->master); - - return 0; -} - static const struct of_device_id falcon_sflash_match[] = { { .compatible = "lantiq,sflash-falcon" }, {}, @@ -456,7 +447,6 @@ MODULE_DEVICE_TABLE(of, falcon_sflash_match); static struct platform_driver falcon_sflash_driver = { .probe = falcon_sflash_probe, - .remove = falcon_sflash_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, -- cgit v1.2.3 From 3e4543abf9deea8733341d235719e7e02b4068ed Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 31 Oct 2013 15:08:31 -0700 Subject: Bluetooth: btmrvl: operate on 16-bit opcodes instead of ogf/ocf Replace ogf/ocf and its packing with 16-bit opcodes. Signed-off-by: Bing Zhao Signed-off-by: Amitkumar Karwar Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 19 +++++++++++-------- drivers/bluetooth/btmrvl_main.c | 21 +++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index f9d183387f45..e3b49c68ea71 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -90,12 +90,12 @@ struct btmrvl_private { #define MRVL_VENDOR_PKT 0xFE -/* Bluetooth commands */ -#define BT_CMD_AUTO_SLEEP_MODE 0x23 -#define BT_CMD_HOST_SLEEP_CONFIG 0x59 -#define BT_CMD_HOST_SLEEP_ENABLE 0x5A -#define BT_CMD_MODULE_CFG_REQ 0x5B -#define BT_CMD_LOAD_CONFIG_DATA 0x61 +/* Vendor specific Bluetooth commands */ +#define BT_CMD_AUTO_SLEEP_MODE 0xFC23 +#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 +#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A +#define BT_CMD_MODULE_CFG_REQ 0xFC5B +#define BT_CMD_LOAD_CONFIG_DATA 0xFC61 /* Sub-commands: Module Bringup/Shutdown Request/Response */ #define MODULE_BRINGUP_REQ 0xF1 @@ -104,6 +104,11 @@ struct btmrvl_private { #define MODULE_SHUTDOWN_REQ 0xF2 +/* Vendor specific Bluetooth events */ +#define BT_EVENT_AUTO_SLEEP_MODE 0x23 +#define BT_EVENT_HOST_SLEEP_CONFIG 0x59 +#define BT_EVENT_HOST_SLEEP_ENABLE 0x5A +#define BT_EVENT_MODULE_CFG_REQ 0x5B #define BT_EVENT_POWER_STATE 0x20 /* Bluetooth Power States */ @@ -111,8 +116,6 @@ struct btmrvl_private { #define BT_PS_DISABLE 0x03 #define BT_PS_SLEEP 0x01 -#define OGF 0x3F - /* Host Sleep states */ #define HS_ACTIVATED 0x01 #define HS_DEACTIVATED 0x00 diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 5cf31c4fe6d1..477b658316b4 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -50,12 +50,10 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) if (hdr->evt == HCI_EV_CMD_COMPLETE) { struct hci_ev_cmd_complete *ec; - u16 opcode, ocf, ogf; + u16 opcode; ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE); opcode = __le16_to_cpu(ec->opcode); - ocf = hci_opcode_ocf(opcode); - ogf = hci_opcode_ogf(opcode); if (priv->btmrvl_dev.sendcmdflag) { priv->btmrvl_dev.sendcmdflag = false; @@ -63,9 +61,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) wake_up_interruptible(&priv->adapter->cmd_wait_q); } - if (ogf == OGF) { - BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x", - ogf, ocf); + if (hci_opcode_ogf(opcode) == 0x3F) { + BT_DBG("vendor event skipped: opcode=%#4.4x", opcode); kfree_skb(skb); return false; } @@ -89,7 +86,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) } switch (event->data[0]) { - case BT_CMD_AUTO_SLEEP_MODE: + case BT_EVENT_AUTO_SLEEP_MODE: if (!event->data[2]) { if (event->data[1] == BT_PS_ENABLE) adapter->psmode = 1; @@ -102,7 +99,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) } break; - case BT_CMD_HOST_SLEEP_CONFIG: + case BT_EVENT_HOST_SLEEP_CONFIG: if (!event->data[3]) BT_DBG("gpio=%x, gap=%x", event->data[1], event->data[2]); @@ -110,7 +107,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) BT_DBG("HSCFG command failed"); break; - case BT_CMD_HOST_SLEEP_ENABLE: + case BT_EVENT_HOST_SLEEP_ENABLE: if (!event->data[1]) { adapter->hs_state = HS_ACTIVATED; if (adapter->psmode) @@ -121,7 +118,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) } break; - case BT_CMD_MODULE_CFG_REQ: + case BT_EVENT_MODULE_CFG_REQ: if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_BRINGUP_REQ) { BT_DBG("EVENT:%s", @@ -166,7 +163,7 @@ exit: } EXPORT_SYMBOL_GPL(btmrvl_process_event); -static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, +static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, const void *param, u8 len) { struct sk_buff *skb; @@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, } hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE); - hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no)); + hdr->opcode = cpu_to_le16(opcode); hdr->plen = len; if (len) -- cgit v1.2.3 From 433a9389a11778f1bc342789abccac9ce46eee82 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 1 Nov 2013 15:28:24 -0700 Subject: Bluetooth: btmrvl: use cal-data from device-tree instead of conf file Some ARM versions of Chromebook need to download a new calibration data from host driver to firmware. They do have EEPROM but still need a piece of new calibration data in test mode. The cal-data is platform dependent. It's simpler and more feasible to use device tree based cal-data instead of configuration file based cal-data. This patch remove configuration file based cal-data downloading and replace it using cal-data from device tree. When CONFIG_OF is not selected, or the specific property is not present in the device tree, the calibration downloading will not happen. Cc: Mike Frysinger Cc: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Hyuckjoo Lee Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 4 -- drivers/bluetooth/btmrvl_main.c | 92 ++++++++--------------------------------- drivers/bluetooth/btmrvl_sdio.c | 9 +--- drivers/bluetooth/btmrvl_sdio.h | 2 - 4 files changed, 18 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index e3b49c68ea71..98187f09393d 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -23,8 +23,6 @@ #include #include #include -#include -#include #define BTM_HEADER_LEN 4 #define BTM_UPLD_SIZE 2312 @@ -43,8 +41,6 @@ struct btmrvl_thread { struct btmrvl_device { void *card; struct hci_dev *hcidev; - struct device *dev; - const char *cal_data; u8 dev_type; diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 477b658316b4..6441f724aeb0 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -19,7 +19,7 @@ **/ #include - +#include #include #include @@ -414,52 +414,8 @@ static int btmrvl_open(struct hci_dev *hdev) return 0; } -/* - * This function parses provided calibration data input. It should contain - * hex bytes separated by space or new line character. Here is an example. - * 00 1C 01 37 FF FF FF FF 02 04 7F 01 - * CE BA 00 00 00 2D C6 C0 00 00 00 00 - * 00 F0 00 00 - */ -static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size) -{ - const u8 *s = src; - u8 *d = dst; - int ret; - u8 tmp[3]; - - tmp[2] = '\0'; - while ((s - src) <= len - 2) { - if (isspace(*s)) { - s++; - continue; - } - - if (isxdigit(*s)) { - if ((d - dst) >= dst_size) { - BT_ERR("calibration data file too big!!!"); - return -EINVAL; - } - - memcpy(tmp, s, 2); - - ret = kstrtou8(tmp, 16, d++); - if (ret < 0) - return ret; - - s += 2; - } else { - return -EINVAL; - } - } - if (d == dst) - return -EINVAL; - - return 0; -} - -static int btmrvl_load_cal_data(struct btmrvl_private *priv, - u8 *config_data) +static int btmrvl_download_cal_data(struct btmrvl_private *priv, + u8 *config_data) { int i, ret; u8 data[BT_CMD_DATA_SIZE]; @@ -487,54 +443,40 @@ static int btmrvl_load_cal_data(struct btmrvl_private *priv, return 0; } -static int -btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size) +static int btmrvl_cal_data_dt(struct btmrvl_private *priv) { + struct device_node *dt_node; u8 cal_data[BT_CAL_DATA_SIZE]; + const char name[] = "btmrvl_caldata"; + const char property[] = "btmrvl,caldata"; int ret; - ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data)); + dt_node = of_find_node_by_name(NULL, name); + if (!dt_node) + return -ENODEV; + + ret = of_property_read_u8_array(dt_node, property, cal_data, + sizeof(cal_data)); if (ret) return ret; - ret = btmrvl_load_cal_data(priv, cal_data); + BT_DBG("Use cal data from device tree"); + ret = btmrvl_download_cal_data(priv, cal_data); if (ret) { - BT_ERR("Fail to load calibrate data"); + BT_ERR("Fail to download calibrate data"); return ret; } return 0; } -static int btmrvl_cal_data_config(struct btmrvl_private *priv) -{ - const struct firmware *cfg; - int ret; - const char *cal_data = priv->btmrvl_dev.cal_data; - - if (!cal_data) - return 0; - - ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev); - if (ret < 0) { - BT_DBG("Failed to get %s file, skipping cal data download", - cal_data); - return 0; - } - - ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size); - release_firmware(cfg); - return ret; -} - static int btmrvl_setup(struct hci_dev *hdev) { struct btmrvl_private *priv = hci_get_drvdata(hdev); btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); - if (btmrvl_cal_data_config(priv)) - BT_ERR("Set cal data failed"); + btmrvl_cal_data_dt(priv); priv->btmrvl_dev.psmode = 1; btmrvl_enable_ps(priv); diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index fabcf5bb48af..1b52c9f5230d 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -18,6 +18,7 @@ * this warranty disclaimer. **/ +#include #include #include @@ -101,7 +102,6 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { .helper = "mrvl/sd8688_helper.bin", .firmware = "mrvl/sd8688.bin", - .cal_data = NULL, .reg = &btmrvl_reg_8688, .sd_blksz_fw_dl = 64, }; @@ -109,7 +109,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { .helper = NULL, .firmware = "mrvl/sd8787_uapsta.bin", - .cal_data = NULL, .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -117,7 +116,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { .helper = NULL, .firmware = "mrvl/sd8797_uapsta.bin", - .cal_data = "mrvl/sd8797_caldata.conf", .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -125,7 +123,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { .helper = NULL, .firmware = "mrvl/sd8897_uapsta.bin", - .cal_data = NULL, .reg = &btmrvl_reg_88xx, .sd_blksz_fw_dl = 256, }; @@ -1007,7 +1004,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func, struct btmrvl_sdio_device *data = (void *) id->driver_data; card->helper = data->helper; card->firmware = data->firmware; - card->cal_data = data->cal_data; card->reg = data->reg; card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; } @@ -1036,8 +1032,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func, } card->priv = priv; - priv->btmrvl_dev.dev = &card->func->dev; - priv->btmrvl_dev.cal_data = card->cal_data; /* Initialize the interface specific function pointers */ priv->hw_host_to_card = btmrvl_sdio_host_to_card; @@ -1220,5 +1214,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); MODULE_FIRMWARE("mrvl/sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); -MODULE_FIRMWARE("mrvl/sd8797_caldata.conf"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 6872d9ecac07..43d35a609ca9 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -85,7 +85,6 @@ struct btmrvl_sdio_card { u32 ioport; const char *helper; const char *firmware; - const char *cal_data; const struct btmrvl_sdio_card_reg *reg; u16 sd_blksz_fw_dl; u8 rx_unit; @@ -95,7 +94,6 @@ struct btmrvl_sdio_card { struct btmrvl_sdio_device { const char *helper; const char *firmware; - const char *cal_data; const struct btmrvl_sdio_card_reg *reg; u16 sd_blksz_fw_dl; }; -- cgit v1.2.3 From 8a4934f1d62b8be7a00cdb4e65124f4d02d412f3 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 1 Nov 2013 15:28:25 -0700 Subject: Bluetooth: btmrvl: remove cal-data byte swapping and redundant mem copy The device tree property can define the cal-data in proper order. There is no need to swap the bytes in driver. Also remove the redundant cal-data memory copy after removing the byte swapping. Cc: Mike Frysinger Cc: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Hyuckjoo Lee Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 2 +- drivers/bluetooth/btmrvl_main.c | 27 ++++++++++----------------- 2 files changed, 11 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 98187f09393d..7399303d7d99 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -120,7 +120,7 @@ struct btmrvl_private { #define PS_SLEEP 0x01 #define PS_AWAKE 0x00 -#define BT_CMD_DATA_SIZE 32 +#define BT_CAL_HDR_LEN 4 #define BT_CAL_DATA_SIZE 28 struct btmrvl_event { diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 6441f724aeb0..1e0320af00c6 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -415,28 +415,20 @@ static int btmrvl_open(struct hci_dev *hdev) } static int btmrvl_download_cal_data(struct btmrvl_private *priv, - u8 *config_data) + u8 *data, int len) { - int i, ret; - u8 data[BT_CMD_DATA_SIZE]; + int ret; data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; - data[3] = BT_CMD_DATA_SIZE - 4; - - /* Swap cal-data bytes. Each four bytes are swapped. Considering 4 - * byte SDIO header offset, mapping of input and output bytes will be - * {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4}, - * {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */ - for (i = 4; i < BT_CMD_DATA_SIZE; i++) - data[i] = config_data[(i / 4) * 8 - 1 - i]; + data[3] = len; print_hex_dump_bytes("Calibration data: ", - DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE); + DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len); ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data, - BT_CMD_DATA_SIZE); + BT_CAL_HDR_LEN + len); if (ret) BT_ERR("Failed to download caibration data\n"); @@ -446,7 +438,7 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv, static int btmrvl_cal_data_dt(struct btmrvl_private *priv) { struct device_node *dt_node; - u8 cal_data[BT_CAL_DATA_SIZE]; + u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE]; const char name[] = "btmrvl_caldata"; const char property[] = "btmrvl,caldata"; int ret; @@ -455,13 +447,14 @@ static int btmrvl_cal_data_dt(struct btmrvl_private *priv) if (!dt_node) return -ENODEV; - ret = of_property_read_u8_array(dt_node, property, cal_data, - sizeof(cal_data)); + ret = of_property_read_u8_array(dt_node, property, + cal_data + BT_CAL_HDR_LEN, + BT_CAL_DATA_SIZE); if (ret) return ret; BT_DBG("Use cal data from device tree"); - ret = btmrvl_download_cal_data(priv, cal_data); + ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE); if (ret) { BT_ERR("Fail to download calibrate data"); return ret; -- cgit v1.2.3 From bd0fca1b2be8c96dfc391a2bc2ee4ce6970ae6af Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 6 Nov 2013 10:56:00 +0530 Subject: Bluetooth: ath3k: Add support for another AR3012 card T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=04ca ProdID=300b Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01 I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Reported-by: Face Signed-off-by: Sujith Manoharan Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 6bfc1bb318f6..cb5ef5ba9650 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -83,6 +83,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3006) }, { USB_DEVICE(0x04CA, 0x3008) }, + { USB_DEVICE(0x04CA, 0x300b) }, { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0CF3, 0xE005) }, @@ -125,6 +126,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c0ff34f2d2df..67790b78a974 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -150,6 +150,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, -- cgit v1.2.3 From 35580d223b6b04d9a570e4fe377c46a102413fe8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 4 Nov 2013 21:38:23 +0530 Subject: Bluetooth: ath3k: Add support for a new AR3012 device T: Bus=02 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 9 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e05f Rev= 0.02 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01 I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Reported-by: Joshua Richenhagen Signed-off-by: Sujith Manoharan Signed-off-by: Johan Hedberg --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index cb5ef5ba9650..d3fdc32b579d 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -97,6 +97,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x0cf3, 0x3121) }, { USB_DEVICE(0x0cf3, 0xe003) }, + { USB_DEVICE(0x0489, 0xe05f) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -140,6 +141,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 67790b78a974..3d04bce0d12f 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -164,6 +164,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, -- cgit v1.2.3 From ef4e5e4a756ff077dbdbdb8481d0e3788a07c005 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Tue, 12 Nov 2013 13:10:58 -0800 Subject: Bluetooth: Add support for Intel Bluetooth device [8087:0a2a] This patch adds support for new Intel Bluetooth device. T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=8087 ProdID=0a2a Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3d04bce0d12f..b73ae34cdbe0 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -225,6 +225,7 @@ static const struct usb_device_id blacklist_table[] = { /* Intel Bluetooth device */ { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, + { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, { } /* Terminating entry */ }; -- cgit v1.2.3 From d2bee8fb6e18f6116aada39851918473761f7ab1 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Tue, 12 Nov 2013 13:16:41 -0800 Subject: Bluetooth: Enable autosuspend for Intel Bluetooth device This patch enables autosuspend for Intel Bluetooth device. After btusb is loaded for Intel Bluetooth device, the power/control attribute contains "on" value by default which disables the autosuspend. Based on the USB PM document(Documentation/usb/power-management.txt), kernel disabled the autosuspend for all devices other than hub by default. "The USB specification states that all USB devices must support power management. Nevertheless, the sad fact is that many devices do not support it very well. You can suspend them all right, but when you try to resume them they disconnect themselves from the USB bus or they stop working entirely. This seems to be especially prevalent among printers and scanners, but plenty of other types of device have the same deficiency. For this reason, by default the kernel disables autosuspend (the power/control attribute is initialized to "on") for all devices other than hubs. Hubs, at least, appear to be reasonably well-behaved in this regard." This document also described how the driver can enables the autosuspend by using an USB api. "Drivers can enable autosuspend for their devices by calling usb_enable_autosuspend(struct usb_device *udev); in their probe() routine, if they know that the device is capable of suspending and resuming correctly. This is exactly equivalent to writing "auto" to the device's power/control attribute." For Intel Bluetooth device, the autosuspend needs to be enabled so the device can transit to LPM(Low Power Mode) and ULPM(Ultra LPM) states after receiving suspend message from the host. Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b73ae34cdbe0..bfbcc5a772a6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1438,8 +1438,10 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_BCM92035) hdev->setup = btusb_setup_bcm92035; - if (id->driver_info & BTUSB_INTEL) + if (id->driver_info & BTUSB_INTEL) { + usb_enable_autosuspend(data->udev); hdev->setup = btusb_setup_intel; + } /* Interface numbers are hardcoded in the specification */ data->isoc = usb_ifnum_to_if(data->udev, 1); -- cgit v1.2.3 From bd0976dd3379e790b031cef7f477c58b82a65fc2 Mon Sep 17 00:00:00 2001 From: Marco Piazza Date: Thu, 28 Nov 2013 00:15:25 +0100 Subject: Bluetooth: Add support for Toshiba Bluetooth device [0930:0220] This patch adds support for new Toshiba Bluetooth device. T: Bus=05 Lev=01 Prnt=01 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0930 ProdID=0220 Rev=00.02 C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Signed-off-by: Marco Piazza Signed-off-by: Gustavo Padovan --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 6bfc1bb318f6..dceb85f8d9a8 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0CF3, 0xE005) }, { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0930, 0x0220) }, { USB_DEVICE(0x0489, 0xe057) }, { USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x0489, 0xe04e) }, @@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c0ff34f2d2df..3980fd18f6ea 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, -- cgit v1.2.3 From 142168eba9dc5c20538a67049ad53c49bc6f8336 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sat, 30 Nov 2013 12:42:06 +0100 Subject: spi: bcm63xx-hsspi: add bcm63xx HSSPI driver Add a driver for the High Speed SPI controller found on newer BCM63XX SoCs. It does feature some new modes like 3-wire or dual spi, but neither of it is currently implemented. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-bcm63xx-hsspi.c | 484 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 492 insertions(+) create mode 100644 drivers/spi/spi-bcm63xx-hsspi.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index eb1f1ef5fa2e..62ce2a9ec612 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -118,6 +118,13 @@ config SPI_BCM63XX help Enable support for the SPI controller on the Broadcom BCM63xx SoCs. +config SPI_BCM63XX_HSSPI + tristate "Broadcom BCM63XX HS SPI controller driver" + depends on BCM63XX || COMPILE_TEST + help + This enables support for the High Speed SPI controller present on + newer Broadcom BCM63XX SoCs. + config SPI_BITBANG tristate "Utilities for Bitbanging SPI masters" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index ab8d8644af0e..95af48d2d360 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o +obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o obj-$(CONFIG_SPI_BFIN_V3) += spi-bfin-v3.o obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c new file mode 100644 index 000000000000..bc8d848d33b7 --- /dev/null +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -0,0 +1,484 @@ +/* + * Broadcom BCM63XX High Speed SPI Controller driver + * + * Copyright 2000-2010 Broadcom Corporation + * Copyright 2012-2013 Jonas Gorski + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HSSPI_GLOBAL_CTRL_REG 0x0 +#define GLOBAL_CTRL_CS_POLARITY_SHIFT 0 +#define GLOBAL_CTRL_CS_POLARITY_MASK 0x000000ff +#define GLOBAL_CTRL_PLL_CLK_CTRL_SHIFT 8 +#define GLOBAL_CTRL_PLL_CLK_CTRL_MASK 0x0000ff00 +#define GLOBAL_CTRL_CLK_GATE_SSOFF BIT(16) +#define GLOBAL_CTRL_CLK_POLARITY BIT(17) +#define GLOBAL_CTRL_MOSI_IDLE BIT(18) + +#define HSSPI_GLOBAL_EXT_TRIGGER_REG 0x4 + +#define HSSPI_INT_STATUS_REG 0x8 +#define HSSPI_INT_STATUS_MASKED_REG 0xc +#define HSSPI_INT_MASK_REG 0x10 + +#define HSSPI_PINGx_CMD_DONE(i) BIT((i * 8) + 0) +#define HSSPI_PINGx_RX_OVER(i) BIT((i * 8) + 1) +#define HSSPI_PINGx_TX_UNDER(i) BIT((i * 8) + 2) +#define HSSPI_PINGx_POLL_TIMEOUT(i) BIT((i * 8) + 3) +#define HSSPI_PINGx_CTRL_INVAL(i) BIT((i * 8) + 4) + +#define HSSPI_INT_CLEAR_ALL 0xff001f1f + +#define HSSPI_PINGPONG_COMMAND_REG(x) (0x80 + (x) * 0x40) +#define PINGPONG_CMD_COMMAND_MASK 0xf +#define PINGPONG_COMMAND_NOOP 0 +#define PINGPONG_COMMAND_START_NOW 1 +#define PINGPONG_COMMAND_START_TRIGGER 2 +#define PINGPONG_COMMAND_HALT 3 +#define PINGPONG_COMMAND_FLUSH 4 +#define PINGPONG_CMD_PROFILE_SHIFT 8 +#define PINGPONG_CMD_SS_SHIFT 12 + +#define HSSPI_PINGPONG_STATUS_REG(x) (0x84 + (x) * 0x40) + +#define HSSPI_PROFILE_CLK_CTRL_REG(x) (0x100 + (x) * 0x20) +#define CLK_CTRL_FREQ_CTRL_MASK 0x0000ffff +#define CLK_CTRL_SPI_CLK_2X_SEL BIT(14) +#define CLK_CTRL_ACCUM_RST_ON_LOOP BIT(15) + +#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x) (0x104 + (x) * 0x20) +#define SIGNAL_CTRL_LATCH_RISING BIT(12) +#define SIGNAL_CTRL_LAUNCH_RISING BIT(13) +#define SIGNAL_CTRL_ASYNC_INPUT_PATH BIT(16) + +#define HSSPI_PROFILE_MODE_CTRL_REG(x) (0x108 + (x) * 0x20) +#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT 8 +#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT 12 +#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT 16 +#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT 18 +#define MODE_CTRL_MODE_3WIRE BIT(20) +#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT 24 + +#define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200) + + +#define HSSPI_OP_CODE_SHIFT 13 +#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT) +#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT) +#define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT) +#define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT) +#define HSSPI_OP_SETIRQ (4 << HSSPI_OP_CODE_SHIFT) + +#define HSSPI_BUFFER_LEN 512 +#define HSSPI_OPCODE_LEN 2 + +#define HSSPI_MAX_PREPEND_LEN 15 + +#define HSSPI_MAX_SYNC_CLOCK 30000000 + +#define HSSPI_BUS_NUM 1 /* 0 is legacy SPI */ + +struct bcm63xx_hsspi { + struct completion done; + struct mutex bus_mutex; + + struct platform_device *pdev; + struct clk *clk; + void __iomem *regs; + u8 __iomem *fifo; + + u32 speed_hz; + u8 cs_polarity; +}; + +static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs, + bool active) +{ + u32 reg; + + mutex_lock(&bs->bus_mutex); + reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); + + reg &= ~BIT(cs); + if (active == !(bs->cs_polarity & BIT(cs))) + reg |= BIT(cs); + + __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); + mutex_unlock(&bs->bus_mutex); +} + +static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, + struct spi_device *spi, int hz) +{ + unsigned profile = spi->chip_select; + u32 reg; + + reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz)); + __raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg, + bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile)); + + reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile)); + if (hz > HSSPI_MAX_SYNC_CLOCK) + reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH; + else + reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH; + __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile)); + + mutex_lock(&bs->bus_mutex); + /* setup clock polarity */ + reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); + reg &= ~GLOBAL_CTRL_CLK_POLARITY; + if (spi->mode & SPI_CPOL) + reg |= GLOBAL_CTRL_CLK_POLARITY; + __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); + mutex_unlock(&bs->bus_mutex); +} + +static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) +{ + struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); + unsigned chip_select = spi->chip_select; + u16 opcode = 0; + int pending = t->len; + int step_size = HSSPI_BUFFER_LEN; + const u8 *tx = t->tx_buf; + u8 *rx = t->rx_buf; + + bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz); + bcm63xx_hsspi_set_cs(bs, spi->chip_select, true); + + if (tx && rx) + opcode = HSSPI_OP_READ_WRITE; + else if (tx) + opcode = HSSPI_OP_WRITE; + else if (rx) + opcode = HSSPI_OP_READ; + + if (opcode != HSSPI_OP_READ) + step_size -= HSSPI_OPCODE_LEN; + + __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT | + 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT | + 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff, + bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); + + while (pending > 0) { + int curr_step = min_t(int, step_size, pending); + + init_completion(&bs->done); + if (tx) { + memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step); + tx += curr_step; + } + + __raw_writew(opcode | curr_step, bs->fifo); + + /* enable interrupt */ + __raw_writel(HSSPI_PINGx_CMD_DONE(0), + bs->regs + HSSPI_INT_MASK_REG); + + /* start the transfer */ + __raw_writel(!chip_select << PINGPONG_CMD_SS_SHIFT | + chip_select << PINGPONG_CMD_PROFILE_SHIFT | + PINGPONG_COMMAND_START_NOW, + bs->regs + HSSPI_PINGPONG_COMMAND_REG(0)); + + if (wait_for_completion_timeout(&bs->done, HZ) == 0) { + dev_err(&bs->pdev->dev, "transfer timed out!\n"); + return -ETIMEDOUT; + } + + if (rx) { + memcpy_fromio(rx, bs->fifo, curr_step); + rx += curr_step; + } + + pending -= curr_step; + } + + return 0; +} + +static int bcm63xx_hsspi_setup(struct spi_device *spi) +{ + struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); + u32 reg; + + reg = __raw_readl(bs->regs + + HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select)); + reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING); + if (spi->mode & SPI_CPHA) + reg |= SIGNAL_CTRL_LAUNCH_RISING; + else + reg |= SIGNAL_CTRL_LATCH_RISING; + __raw_writel(reg, bs->regs + + HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select)); + + mutex_lock(&bs->bus_mutex); + reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); + + /* only change actual polarities if there is no transfer */ + if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) { + if (spi->mode & SPI_CS_HIGH) + reg |= BIT(spi->chip_select); + else + reg &= ~BIT(spi->chip_select); + __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); + } + + if (spi->mode & SPI_CS_HIGH) + bs->cs_polarity |= BIT(spi->chip_select); + else + bs->cs_polarity &= ~BIT(spi->chip_select); + + mutex_unlock(&bs->bus_mutex); + + return 0; +} + +static int bcm63xx_hsspi_transfer_one(struct spi_master *master, + struct spi_message *msg) +{ + struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + struct spi_transfer *t; + struct spi_device *spi = msg->spi; + int status = -EINVAL; + int dummy_cs; + u32 reg; + + /* This controller does not support keeping CS active during idle. + * To work around this, we use the following ugly hack: + * + * a. Invert the target chip select's polarity so it will be active. + * b. Select a "dummy" chip select to use as the hardware target. + * c. Invert the dummy chip select's polarity so it will be inactive + * during the actual transfers. + * d. Tell the hardware to send to the dummy chip select. Thanks to + * the multiplexed nature of SPI the actual target will receive + * the transfer and we see its response. + * + * e. At the end restore the polarities again to their default values. + */ + + dummy_cs = !spi->chip_select; + bcm63xx_hsspi_set_cs(bs, dummy_cs, true); + + list_for_each_entry(t, &msg->transfers, transfer_list) { + status = bcm63xx_hsspi_do_txrx(spi, t); + if (status) + break; + + msg->actual_length += t->len; + + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (t->cs_change) + bcm63xx_hsspi_set_cs(bs, spi->chip_select, false); + } + + mutex_lock(&bs->bus_mutex); + reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); + reg &= ~GLOBAL_CTRL_CS_POLARITY_MASK; + reg |= bs->cs_polarity; + __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); + mutex_unlock(&bs->bus_mutex); + + msg->status = status; + spi_finalize_current_message(master); + + return 0; +} + +static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id) +{ + struct bcm63xx_hsspi *bs = (struct bcm63xx_hsspi *)dev_id; + + if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0) + return IRQ_NONE; + + __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); + __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); + + complete(&bs->done); + + return IRQ_HANDLED; +} + +static int bcm63xx_hsspi_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct bcm63xx_hsspi *bs; + struct resource *res_mem; + void __iomem *regs; + struct device *dev = &pdev->dev; + struct clk *clk; + int irq, ret; + u32 reg, rate; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "no irq\n"); + return -ENXIO; + } + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_request_and_ioremap(dev, res_mem); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + clk = clk_get(dev, "hsspi"); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + rate = clk_get_rate(clk); + if (!rate) { + ret = -EINVAL; + goto out_put_clk; + } + + clk_prepare_enable(clk); + + master = spi_alloc_master(&pdev->dev, sizeof(*bs)); + if (!master) { + ret = -ENOMEM; + goto out_disable_clk; + } + + bs = spi_master_get_devdata(master); + bs->pdev = pdev; + bs->clk = clk; + bs->regs = regs; + bs->speed_hz = rate; + bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0)); + + mutex_init(&bs->bus_mutex); + + master->bus_num = HSSPI_BUS_NUM; + master->num_chipselect = 8; + master->setup = bcm63xx_hsspi_setup; + master->transfer_one_message = bcm63xx_hsspi_transfer_one; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->bits_per_word_mask = SPI_BPW_MASK(8); + master->auto_runtime_pm = true; + + platform_set_drvdata(pdev, master); + + /* Initialize the hardware */ + __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); + + /* clean up any pending interrupts */ + __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); + + /* read out default CS polarities */ + reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); + bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK; + __raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF, + bs->regs + HSSPI_GLOBAL_CTRL_REG); + + ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED, + pdev->name, bs); + + if (ret) + goto out_put_master; + + /* register and we are done */ + ret = spi_register_master(master); + if (ret) + goto out_put_master; + + return 0; + +out_put_master: + spi_master_put(master); +out_disable_clk: + clk_disable_unprepare(clk); +out_put_clk: + clk_put(clk); + + return ret; +} + + +static int bcm63xx_hsspi_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + + spi_unregister_master(master); + + /* reset the hardware and block queue progress */ + __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); + clk_disable_unprepare(bs->clk); + clk_put(bs->clk); + + return 0; +} + +#ifdef CONFIG_PM +static int bcm63xx_hsspi_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + + spi_master_suspend(master); + clk_disable(bs->clk); + + return 0; +} + +static int bcm63xx_hsspi_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + + clk_enable(bs->clk); + spi_master_resume(master); + + return 0; +} + +static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = { + .suspend = bcm63xx_hsspi_suspend, + .resume = bcm63xx_hsspi_resume, +}; + +#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops) +#else +#define BCM63XX_HSSPI_PM_OPS NULL +#endif + + + +static struct platform_driver bcm63xx_hsspi_driver = { + .driver = { + .name = "bcm63xx-hsspi", + .owner = THIS_MODULE, + .pm = BCM63XX_HSSPI_PM_OPS, + }, + .probe = bcm63xx_hsspi_probe, + .remove = bcm63xx_hsspi_remove, +}; + +module_platform_driver(bcm63xx_hsspi_driver); + +MODULE_ALIAS("platform:bcm63xx_hsspi"); +MODULE_DESCRIPTION("Broadcom BCM63xx High Speed SPI Controller driver"); +MODULE_AUTHOR("Jonas Gorski "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 81bd4e1cebed5efb85bd94a15342ee4d6965a416 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Thu, 12 Sep 2013 19:15:44 -0400 Subject: thermal: allow registering without .get_temp This patch changes the thermal core driver to allow registration of thermal zones without the .get_temp callback. The idea behind this change is to allow lazy registration of sensor callbacks. The thermal zone will be disabled whenever the ops does not contain a .get_temp callback. The sysfs interface will be returning -EINVAL on any temperature read operation. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal_core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f1d511a9475b..0e43dc208fc6 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -403,7 +403,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp) enum thermal_trip_type type; #endif - if (!tz || IS_ERR(tz)) + if (!tz || IS_ERR(tz) || !tz->ops->get_temp) goto exit; mutex_lock(&tz->lock); @@ -456,6 +456,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) { int count; + if (!tz->ops->get_temp) + return; + update_temperature(tz); for (count = 0; count < tz->trips; count++) @@ -1386,7 +1389,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) return ERR_PTR(-EINVAL); - if (!ops || !ops->get_temp) + if (!ops) return ERR_PTR(-EINVAL); if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) @@ -1490,6 +1493,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); + if (!tz->ops->get_temp) + thermal_zone_device_set_polling(tz, 0); + thermal_zone_device_update(tz); if (!result) -- cgit v1.2.3 From 4e5e4705bf69ea450f58fc709ac5888f321a9299 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 3 Jul 2013 15:35:39 -0400 Subject: thermal: introduce device tree parser This patch introduces a device tree bindings for describing the hardware thermal behavior and limits. Also a parser to read and interpret the data and feed it in the thermal framework is presented. This patch introduces a thermal data parser for device tree. The parsed data is used to build thermal zones and thermal binding parameters. The output data can then be used to deploy thermal policies. This patch adds also documentation regarding this API and how to define tree nodes to use this infrastructure. Note that, in order to be able to have control on the sensor registration on the DT thermal zone, it was required to allow changing the thermal zone .get_temp callback. For this reason, this patch also removes the 'const' modifier from the .ops field of thermal zone devices. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Mark Rutland Signed-off-by: Eduardo Valentin --- .../devicetree/bindings/thermal/thermal.txt | 595 +++++++++++++++ drivers/thermal/Kconfig | 13 + drivers/thermal/Makefile | 1 + drivers/thermal/of-thermal.c | 849 +++++++++++++++++++++ drivers/thermal/thermal_core.c | 9 +- drivers/thermal/thermal_core.h | 9 + include/dt-bindings/thermal/thermal.h | 17 + include/linux/thermal.h | 28 +- 8 files changed, 1518 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt create mode 100644 drivers/thermal/of-thermal.c create mode 100644 include/dt-bindings/thermal/thermal.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt new file mode 100644 index 000000000000..f5db6b72a36f --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/thermal.txt @@ -0,0 +1,595 @@ +* Thermal Framework Device Tree descriptor + +This file describes a generic binding to provide a way of +defining hardware thermal structure using device tree. +A thermal structure includes thermal zones and their components, +such as trip points, polling intervals, sensors and cooling devices +binding descriptors. + +The target of device tree thermal descriptors is to describe only +the hardware thermal aspects. The thermal device tree bindings are +not about how the system must control or which algorithm or policy +must be taken in place. + +There are five types of nodes involved to describe thermal bindings: +- thermal sensors: devices which may be used to take temperature + measurements. +- cooling devices: devices which may be used to dissipate heat. +- trip points: describe key temperatures at which cooling is recommended. The + set of points should be chosen based on hardware limits. +- cooling maps: used to describe links between trip points and cooling devices; +- thermal zones: used to describe thermal data within the hardware; + +The following is a description of each of these node types. + +* Thermal sensor devices + +Thermal sensor devices are nodes providing temperature sensing capabilities on +thermal zones. Typical devices are I2C ADC converters and bandgaps. These are +nodes providing temperature data to thermal zones. Thermal sensor devices may +control one or more internal sensors. + +Required property: +- #thermal-sensor-cells: Used to provide sensor device specific information + Type: unsigned while referring to it. Typically 0 on thermal sensor + Size: one cell nodes with only one sensor, and at least 1 on nodes + with several internal sensors, in order + to identify uniquely the sensor instances within + the IC. See thermal zone binding for more details + on how consumers refer to sensor devices. + +* Cooling device nodes + +Cooling devices are nodes providing control on power dissipation. There +are essentially two ways to provide control on power dissipation. First +is by means of regulating device performance, which is known as passive +cooling. A typical passive cooling is a CPU that has dynamic voltage and +frequency scaling (DVFS), and uses lower frequencies as cooling states. +Second is by means of activating devices in order to remove +the dissipated heat, which is known as active cooling, e.g. regulating +fan speeds. In both cases, cooling devices shall have a way to determine +the state of cooling in which the device is. + +Any cooling device has a range of cooling states (i.e. different levels +of heat dissipation). For example a fan's cooling states correspond to +the different fan speeds possible. Cooling states are referred to by +single unsigned integers, where larger numbers mean greater heat +dissipation. The precise set of cooling states associated with a device +(as referred to be the cooling-min-state and cooling-max-state +properties) should be defined in a particular device's binding. +For more examples of cooling devices, refer to the example sections below. + +Required properties: +- cooling-min-state: An integer indicating the smallest + Type: unsigned cooling state accepted. Typically 0. + Size: one cell + +- cooling-max-state: An integer indicating the largest + Type: unsigned cooling state accepted. + Size: one cell + +- #cooling-cells: Used to provide cooling device specific information + Type: unsigned while referring to it. Must be at least 2, in order + Size: one cell to specify minimum and maximum cooling state used + in the reference. The first cell is the minimum + cooling state requested and the second cell is + the maximum cooling state requested in the reference. + See Cooling device maps section below for more details + on how consumers refer to cooling devices. + +* Trip points + +The trip node is a node to describe a point in the temperature domain +in which the system takes an action. This node describes just the point, +not the action. + +Required properties: +- temperature: An integer indicating the trip temperature level, + Type: signed in millicelsius. + Size: one cell + +- hysteresis: A low hysteresis value on temperature property (above). + Type: unsigned This is a relative value, in millicelsius. + Size: one cell + +- type: a string containing the trip type. Expected values are: + "active": A trip point to enable active cooling + "passive": A trip point to enable passive cooling + "hot": A trip point to notify emergency + "critical": Hardware not reliable. + Type: string + +* Cooling device maps + +The cooling device maps node is a node to describe how cooling devices +get assigned to trip points of the zone. The cooling devices are expected +to be loaded in the target system. + +Required properties: +- cooling-device: A phandle of a cooling device with its specifier, + Type: phandle + referring to which cooling device is used in this + cooling specifier binding. In the cooling specifier, the first cell + is the minimum cooling state and the second cell + is the maximum cooling state used in this map. +- trip: A phandle of a trip point node within the same thermal + Type: phandle of zone. + trip point node + +Optional property: +- contribution: The cooling contribution to the thermal zone of the + Type: unsigned referred cooling device at the referred trip point. + Size: one cell The contribution is a ratio of the sum + of all cooling contributions within a thermal zone. + +Note: Using the THERMAL_NO_LIMIT (-1UL) constant in the cooling-device phandle +limit specifier means: +(i) - minimum state allowed for minimum cooling state used in the reference. +(ii) - maximum state allowed for maximum cooling state used in the reference. +Refer to include/dt-bindings/thermal/thermal.h for definition of this constant. + +* Thermal zone nodes + +The thermal zone node is the node containing all the required info +for describing a thermal zone, including its cooling device bindings. The +thermal zone node must contain, apart from its own properties, one sub-node +containing trip nodes and one sub-node containing all the zone cooling maps. + +Required properties: +- polling-delay: The maximum number of milliseconds to wait between polls + Type: unsigned when checking this thermal zone. + Size: one cell + +- polling-delay-passive: The maximum number of milliseconds to wait + Type: unsigned between polls when performing passive cooling. + Size: one cell + +- thermal-sensors: A list of thermal sensor phandles and sensor specifier + Type: list of used while monitoring the thermal zone. + phandles + sensor + specifier + +- trips: A sub-node which is a container of only trip point nodes + Type: sub-node required to describe the thermal zone. + +- cooling-maps: A sub-node which is a container of only cooling device + Type: sub-node map nodes, used to describe the relation between trips + and cooling devices. + +Optional property: +- coefficients: An array of integers (one signed cell) containing + Type: array coefficients to compose a linear relation between + Elem size: one cell the sensors listed in the thermal-sensors property. + Elem type: signed Coefficients defaults to 1, in case this property + is not specified. A simple linear polynomial is used: + Z = c0 * x0 + c1 + x1 + ... + c(n-1) * x(n-1) + cn. + + The coefficients are ordered and they match with sensors + by means of sensor ID. Additional coefficients are + interpreted as constant offset. + +Note: The delay properties are bound to the maximum dT/dt (temperature +derivative over time) in two situations for a thermal zone: +(i) - when passive cooling is activated (polling-delay-passive); and +(ii) - when the zone just needs to be monitored (polling-delay) or +when active cooling is activated. + +The maximum dT/dt is highly bound to hardware power consumption and dissipation +capability. The delays should be chosen to account for said max dT/dt, +such that a device does not cross several trip boundaries unexpectedly +between polls. Choosing the right polling delays shall avoid having the +device in temperature ranges that may damage the silicon structures and +reduce silicon lifetime. + +* The thermal-zones node + +The "thermal-zones" node is a container for all thermal zone nodes. It shall +contain only sub-nodes describing thermal zones as in the section +"Thermal zone nodes". The "thermal-zones" node appears under "/". + +* Examples + +Below are several examples on how to use thermal data descriptors +using device tree bindings: + +(a) - CPU thermal zone + +The CPU thermal zone example below describes how to setup one thermal zone +using one single sensor as temperature source and many cooling devices and +power dissipation control sources. + +#include + +cpus { + /* + * Here is an example of describing a cooling device for a DVFS + * capable CPU. The CPU node describes its four OPPs. + * The cooling states possible are 0..3, and they are + * used as OPP indexes. The minimum cooling state is 0, which means + * all four OPPs can be available to the system. The maximum + * cooling state is 3, which means only the lowest OPPs (198MHz@0.85V) + * can be available in the system. + */ + cpu0: cpu@0 { + ... + operating-points = < + /* kHz uV */ + 970000 1200000 + 792000 1100000 + 396000 950000 + 198000 850000 + >; + cooling-min-state = <0>; + cooling-max-state = <3>; + #cooling-cells = <2>; /* min followed by max */ + }; + ... +}; + +&i2c1 { + ... + /* + * A simple fan controller which supports 10 speeds of operation + * (represented as 0-9). + */ + fan0: fan@0x48 { + ... + cooling-min-state = <0>; + cooling-max-state = <9>; + #cooling-cells = <2>; /* min followed by max */ + }; +}; + +ocp { + ... + /* + * A simple IC with a single bandgap temperature sensor. + */ + bandgap0: bandgap@0x0000ED00 { + ... + #thermal-sensor-cells = <0>; + }; +}; + +thermal-zones { + cpu-thermal: cpu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + thermal-sensors = <&bandgap0>; + + trips { + cpu-alert0: cpu-alert { + temperature = <90000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "active"; + }; + cpu-alert1: cpu-alert { + temperature = <100000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu-crit: cpu-crit { + temperature = <125000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu-alert0>; + cooling-device = <&fan0 THERMAL_NO_LIMITS 4>; + }; + map1 { + trip = <&cpu-alert1>; + cooling-device = <&fan0 5 THERMAL_NO_LIMITS>; + }; + map2 { + trip = <&cpu-alert1>; + cooling-device = + <&cpu0 THERMAL_NO_LIMITS THERMAL_NO_LIMITS>; + }; + }; + }; +}; + +In the example above, the ADC sensor (bandgap0) at address 0x0000ED00 is +used to monitor the zone 'cpu-thermal' using its sole sensor. A fan +device (fan0) is controlled via I2C bus 1, at address 0x48, and has ten +different cooling states 0-9. It is used to remove the heat out of +the thermal zone 'cpu-thermal' using its cooling states +from its minimum to 4, when it reaches trip point 'cpu-alert0' +at 90C, as an example of active cooling. The same cooling device is used at +'cpu-alert1', but from 5 to its maximum state. The cpu@0 device is also +linked to the same thermal zone, 'cpu-thermal', as a passive cooling device, +using all its cooling states at trip point 'cpu-alert1', +which is a trip point at 100C. On the thermal zone 'cpu-thermal', at the +temperature of 125C, represented by the trip point 'cpu-crit', the silicon +is not reliable anymore. + +(b) - IC with several internal sensors + +The example below describes how to deploy several thermal zones based off a +single sensor IC, assuming it has several internal sensors. This is a common +case on SoC designs with several internal IPs that may need different thermal +requirements, and thus may have their own sensor to monitor or detect internal +hotspots in their silicon. + +#include + +ocp { + ... + /* + * A simple IC with several bandgap temperature sensors. + */ + bandgap0: bandgap@0x0000ED00 { + ... + #thermal-sensor-cells = <1>; + }; +}; + +thermal-zones { + cpu-thermal: cpu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + /* sensor ID */ + thermal-sensors = <&bandgap0 0>; + + trips { + /* each zone within the SoC may have its own trips */ + cpu-alert: cpu-alert { + temperature = <100000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + cpu-crit: cpu-crit { + temperature = <125000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + /* each zone within the SoC may have its own cooling */ + ... + }; + }; + + gpu-thermal: gpu-thermal { + polling-delay-passive = <120>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + /* sensor ID */ + thermal-sensors = <&bandgap0 1>; + + trips { + /* each zone within the SoC may have its own trips */ + gpu-alert: gpu-alert { + temperature = <90000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + gpu-crit: gpu-crit { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + /* each zone within the SoC may have its own cooling */ + ... + }; + }; + + dsp-thermal: dsp-thermal { + polling-delay-passive = <50>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + /* sensor ID */ + thermal-sensors = <&bandgap0 2>; + + trips { + /* each zone within the SoC may have its own trips */ + dsp-alert: gpu-alert { + temperature = <90000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + dsp-crit: gpu-crit { + temperature = <135000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + /* each zone within the SoC may have its own cooling */ + ... + }; + }; +}; + +In the example above, there is one bandgap IC which has the capability to +monitor three sensors. The hardware has been designed so that sensors are +placed on different places in the DIE to monitor different temperature +hotspots: one for CPU thermal zone, one for GPU thermal zone and the +other to monitor a DSP thermal zone. + +Thus, there is a need to assign each sensor provided by the bandgap IC +to different thermal zones. This is achieved by means of using the +#thermal-sensor-cells property and using the first cell of the sensor +specifier as sensor ID. In the example, then, is used to +monitor CPU thermal zone, is used to monitor GPU thermal +zone and is used to monitor DSP thermal zone. Each zone +may be uncorrelated, having its own dT/dt requirements, trips +and cooling maps. + + +(c) - Several sensors within one single thermal zone + +The example below illustrates how to use more than one sensor within +one thermal zone. + +#include + +&i2c1 { + ... + /* + * A simple IC with a single temperature sensor. + */ + adc: sensor@0x49 { + ... + #thermal-sensor-cells = <0>; + }; +}; + +ocp { + ... + /* + * A simple IC with a single bandgap temperature sensor. + */ + bandgap0: bandgap@0x0000ED00 { + ... + #thermal-sensor-cells = <0>; + }; +}; + +thermal-zones { + cpu-thermal: cpu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + thermal-sensors = <&bandgap0>, /* cpu */ + <&adc>; /* pcb north */ + + /* hotspot = 100 * bandgap - 120 * adc + 484 */ + coefficients = <100 -120 484>; + + trips { + ... + }; + + cooling-maps { + ... + }; + }; +}; + +In some cases, there is a need to use more than one sensor to extrapolate +a thermal hotspot in the silicon. The above example illustrates this situation. +For instance, it may be the case that a sensor external to CPU IP may be placed +close to CPU hotspot and together with internal CPU sensor, it is used +to determine the hotspot. Assuming this is the case for the above example, +the hypothetical extrapolation rule would be: + hotspot = 100 * bandgap - 120 * adc + 484 + +In other context, the same idea can be used to add fixed offset. For instance, +consider the hotspot extrapolation rule below: + hotspot = 1 * adc + 6000 + +In the above equation, the hotspot is always 6C higher than what is read +from the ADC sensor. The binding would be then: + thermal-sensors = <&adc>; + + /* hotspot = 1 * adc + 6000 */ + coefficients = <1 6000>; + +(d) - Board thermal + +The board thermal example below illustrates how to setup one thermal zone +with many sensors and many cooling devices. + +#include + +&i2c1 { + ... + /* + * An IC with several temperature sensor. + */ + adc-dummy: sensor@0x50 { + ... + #thermal-sensor-cells = <1>; /* sensor internal ID */ + }; +}; + +thermal-zones { + batt-thermal { + polling-delay-passive = <500>; /* milliseconds */ + polling-delay = <2500>; /* milliseconds */ + + /* sensor ID */ + thermal-sensors = <&adc-dummy 4>; + + trips { + ... + }; + + cooling-maps { + ... + }; + }; + + board-thermal: board-thermal { + polling-delay-passive = <1000>; /* milliseconds */ + polling-delay = <2500>; /* milliseconds */ + + /* sensor ID */ + thermal-sensors = <&adc-dummy 0>, /* pcb top edge */ + <&adc-dummy 1>, /* lcd */ + <&adc-dymmy 2>; /* back cover */ + /* + * An array of coefficients describing the sensor + * linear relation. E.g.: + * z = c1*x1 + c2*x2 + c3*x3 + */ + coefficients = <1200 -345 890>; + + trips { + /* Trips are based on resulting linear equation */ + cpu-trip: cpu-trip { + temperature = <60000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + gpu-trip: gpu-trip { + temperature = <55000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + } + lcd-trip: lcp-trip { + temperature = <53000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + crit-trip: crit-trip { + temperature = <68000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu-trip>; + cooling-device = <&cpu0 0 2>; + contribution = <55>; + }; + map1 { + trip = <&gpu-trip>; + cooling-device = <&gpu0 0 2>; + contribution = <20>; + }; + map2 { + trip = <&lcd-trip>; + cooling-device = <&lcd0 5 10>; + contribution = <15>; + }; + }; + }; +}; + +The above example is a mix of previous examples, a sensor IP with several internal +sensors used to monitor different zones, one of them is composed by several sensors and +with different cooling devices. diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index f35a1f75b15b..a150f8d53322 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -29,6 +29,19 @@ config THERMAL_HWMON Say 'Y' here if you want all thermal sensors to have hwmon sysfs interface too. +config THERMAL_OF + bool + prompt "APIs to parse thermal data out of device tree" + depends on OF + default y + help + This options provides helpers to add the support to + read and parse thermal data definitions out of the + device tree blob. + + Say 'Y' here if you need to build thermal infrastructure + based on device tree. + choice prompt "Default Thermal governor" default THERMAL_DEFAULT_GOV_STEP_WISE diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 584b36319d51..4b03956b929c 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -7,6 +7,7 @@ thermal_sys-y += thermal_core.o # interface to/from other layers providing sensors thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o +thermal_sys-$(CONFIG_THERMAL_OF) += of-thermal.o # governors thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c new file mode 100644 index 000000000000..04b1be7fa018 --- /dev/null +++ b/drivers/thermal/of-thermal.c @@ -0,0 +1,849 @@ +/* + * of-thermal.c - Generic Thermal Management device tree support. + * + * Copyright (C) 2013 Texas Instruments + * Copyright (C) 2013 Eduardo Valentin + * + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, 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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +/*** Private data structures to represent thermal device tree data ***/ + +/** + * struct __thermal_trip - representation of a point in temperature domain + * @np: pointer to struct device_node that this trip point was created from + * @temperature: temperature value in miliCelsius + * @hysteresis: relative hysteresis in miliCelsius + * @type: trip point type + */ + +struct __thermal_trip { + struct device_node *np; + unsigned long int temperature; + unsigned long int hysteresis; + enum thermal_trip_type type; +}; + +/** + * struct __thermal_bind_param - a match between trip and cooling device + * @cooling_device: a pointer to identify the referred cooling device + * @trip_id: the trip point index + * @usage: the percentage (from 0 to 100) of cooling contribution + * @min: minimum cooling state used at this trip point + * @max: maximum cooling state used at this trip point + */ + +struct __thermal_bind_params { + struct device_node *cooling_device; + unsigned int trip_id; + unsigned int usage; + unsigned long min; + unsigned long max; +}; + +/** + * struct __thermal_zone - internal representation of a thermal zone + * @mode: current thermal zone device mode (enabled/disabled) + * @passive_delay: polling interval while passive cooling is activated + * @polling_delay: zone polling interval + * @ntrips: number of trip points + * @trips: an array of trip points (0..ntrips - 1) + * @num_tbps: number of thermal bind params + * @tbps: an array of thermal bind params (0..num_tbps - 1) + * @sensor_data: sensor private data used while reading temperature and trend + * @get_temp: sensor callback to read temperature + * @get_trend: sensor callback to read temperature trend + */ + +struct __thermal_zone { + enum thermal_device_mode mode; + int passive_delay; + int polling_delay; + + /* trip data */ + int ntrips; + struct __thermal_trip *trips; + + /* cooling binding data */ + int num_tbps; + struct __thermal_bind_params *tbps; + + /* sensor interface */ + void *sensor_data; + int (*get_temp)(void *, long *); + int (*get_trend)(void *, long *); +}; + +/*** DT thermal zone device callbacks ***/ + +static int of_thermal_get_temp(struct thermal_zone_device *tz, + unsigned long *temp) +{ + struct __thermal_zone *data = tz->devdata; + + if (!data->get_temp) + return -EINVAL; + + return data->get_temp(data->sensor_data, temp); +} + +static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, + enum thermal_trend *trend) +{ + struct __thermal_zone *data = tz->devdata; + long dev_trend; + int r; + + if (!data->get_trend) + return -EINVAL; + + r = data->get_trend(data->sensor_data, &dev_trend); + if (r) + return r; + + /* TODO: These intervals might have some thresholds, but in core code */ + if (dev_trend > 0) + *trend = THERMAL_TREND_RAISING; + else if (dev_trend < 0) + *trend = THERMAL_TREND_DROPPING; + else + *trend = THERMAL_TREND_STABLE; + + return 0; +} + +static int of_thermal_bind(struct thermal_zone_device *thermal, + struct thermal_cooling_device *cdev) +{ + struct __thermal_zone *data = thermal->devdata; + int i; + + if (!data || IS_ERR(data)) + return -ENODEV; + + /* find where to bind */ + for (i = 0; i < data->num_tbps; i++) { + struct __thermal_bind_params *tbp = data->tbps + i; + + if (tbp->cooling_device == cdev->np) { + int ret; + + ret = thermal_zone_bind_cooling_device(thermal, + tbp->trip_id, cdev, + tbp->min, + tbp->max); + if (ret) + return ret; + } + } + + return 0; +} + +static int of_thermal_unbind(struct thermal_zone_device *thermal, + struct thermal_cooling_device *cdev) +{ + struct __thermal_zone *data = thermal->devdata; + int i; + + if (!data || IS_ERR(data)) + return -ENODEV; + + /* find where to unbind */ + for (i = 0; i < data->num_tbps; i++) { + struct __thermal_bind_params *tbp = data->tbps + i; + + if (tbp->cooling_device == cdev->np) { + int ret; + + ret = thermal_zone_unbind_cooling_device(thermal, + tbp->trip_id, cdev); + if (ret) + return ret; + } + } + + return 0; +} + +static int of_thermal_get_mode(struct thermal_zone_device *tz, + enum thermal_device_mode *mode) +{ + struct __thermal_zone *data = tz->devdata; + + *mode = data->mode; + + return 0; +} + +static int of_thermal_set_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) +{ + struct __thermal_zone *data = tz->devdata; + + mutex_lock(&tz->lock); + + if (mode == THERMAL_DEVICE_ENABLED) + tz->polling_delay = data->polling_delay; + else + tz->polling_delay = 0; + + mutex_unlock(&tz->lock); + + data->mode = mode; + thermal_zone_device_update(tz); + + return 0; +} + +static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, + enum thermal_trip_type *type) +{ + struct __thermal_zone *data = tz->devdata; + + if (trip >= data->ntrips || trip < 0) + return -EDOM; + + *type = data->trips[trip].type; + + return 0; +} + +static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, + unsigned long *temp) +{ + struct __thermal_zone *data = tz->devdata; + + if (trip >= data->ntrips || trip < 0) + return -EDOM; + + *temp = data->trips[trip].temperature; + + return 0; +} + +static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, + unsigned long temp) +{ + struct __thermal_zone *data = tz->devdata; + + if (trip >= data->ntrips || trip < 0) + return -EDOM; + + /* thermal framework should take care of data->mask & (1 << trip) */ + data->trips[trip].temperature = temp; + + return 0; +} + +static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip, + unsigned long *hyst) +{ + struct __thermal_zone *data = tz->devdata; + + if (trip >= data->ntrips || trip < 0) + return -EDOM; + + *hyst = data->trips[trip].hysteresis; + + return 0; +} + +static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip, + unsigned long hyst) +{ + struct __thermal_zone *data = tz->devdata; + + if (trip >= data->ntrips || trip < 0) + return -EDOM; + + /* thermal framework should take care of data->mask & (1 << trip) */ + data->trips[trip].hysteresis = hyst; + + return 0; +} + +static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, + unsigned long *temp) +{ + struct __thermal_zone *data = tz->devdata; + int i; + + for (i = 0; i < data->ntrips; i++) + if (data->trips[i].type == THERMAL_TRIP_CRITICAL) { + *temp = data->trips[i].temperature; + return 0; + } + + return -EINVAL; +} + +static struct thermal_zone_device_ops of_thermal_ops = { + .get_mode = of_thermal_get_mode, + .set_mode = of_thermal_set_mode, + + .get_trip_type = of_thermal_get_trip_type, + .get_trip_temp = of_thermal_get_trip_temp, + .set_trip_temp = of_thermal_set_trip_temp, + .get_trip_hyst = of_thermal_get_trip_hyst, + .set_trip_hyst = of_thermal_set_trip_hyst, + .get_crit_temp = of_thermal_get_crit_temp, + + .bind = of_thermal_bind, + .unbind = of_thermal_unbind, +}; + +/*** sensor API ***/ + +static struct thermal_zone_device * +thermal_zone_of_add_sensor(struct device_node *zone, + struct device_node *sensor, void *data, + int (*get_temp)(void *, long *), + int (*get_trend)(void *, long *)) +{ + struct thermal_zone_device *tzd; + struct __thermal_zone *tz; + + tzd = thermal_zone_get_zone_by_name(zone->name); + if (IS_ERR(tzd)) + return ERR_PTR(-EPROBE_DEFER); + + tz = tzd->devdata; + + mutex_lock(&tzd->lock); + tz->get_temp = get_temp; + tz->get_trend = get_trend; + tz->sensor_data = data; + + tzd->ops->get_temp = of_thermal_get_temp; + tzd->ops->get_trend = of_thermal_get_trend; + mutex_unlock(&tzd->lock); + + return tzd; +} + +/** + * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone + * @dev: a valid struct device pointer of a sensor device. Must contain + * a valid .of_node, for the sensor node. + * @sensor_id: a sensor identifier, in case the sensor IP has more + * than one sensors + * @data: a private pointer (owned by the caller) that will be passed + * back, when a temperature reading is needed. + * @get_temp: a pointer to a function that reads the sensor temperature. + * @get_trend: a pointer to a function that reads the sensor temperature trend. + * + * This function will search the list of thermal zones described in device + * tree and look for the zone that refer to the sensor device pointed by + * @dev->of_node as temperature providers. For the zone pointing to the + * sensor node, the sensor will be added to the DT thermal zone device. + * + * The thermal zone temperature is provided by the @get_temp function + * pointer. When called, it will have the private pointer @data back. + * + * The thermal zone temperature trend is provided by the @get_trend function + * pointer. When called, it will have the private pointer @data back. + * + * TODO: + * 01 - This function must enqueue the new sensor instead of using + * it as the only source of temperature values. + * + * 02 - There must be a way to match the sensor with all thermal zones + * that refer to it. + * + * Return: On success returns a valid struct thermal_zone_device, + * otherwise, it returns a corresponding ERR_PTR(). Caller must + * check the return value with help of IS_ERR() helper. + */ +struct thermal_zone_device * +thermal_zone_of_sensor_register(struct device *dev, int sensor_id, + void *data, int (*get_temp)(void *, long *), + int (*get_trend)(void *, long *)) +{ + struct device_node *np, *child, *sensor_np; + + np = of_find_node_by_name(NULL, "thermal-zones"); + if (!np) + return ERR_PTR(-ENODEV); + + if (!dev || !dev->of_node) + return ERR_PTR(-EINVAL); + + sensor_np = dev->of_node; + + for_each_child_of_node(np, child) { + struct of_phandle_args sensor_specs; + int ret, id; + + /* For now, thermal framework supports only 1 sensor per zone */ + ret = of_parse_phandle_with_args(child, "thermal-sensors", + "#thermal-sensor-cells", + 0, &sensor_specs); + if (ret) + continue; + + if (sensor_specs.args_count >= 1) { + id = sensor_specs.args[0]; + WARN(sensor_specs.args_count > 1, + "%s: too many cells in sensor specifier %d\n", + sensor_specs.np->name, sensor_specs.args_count); + } else { + id = 0; + } + + if (sensor_specs.np == sensor_np && id == sensor_id) { + of_node_put(np); + return thermal_zone_of_add_sensor(child, sensor_np, + data, + get_temp, + get_trend); + } + } + of_node_put(np); + + return ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register); + +/** + * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone + * @dev: a valid struct device pointer of a sensor device. Must contain + * a valid .of_node, for the sensor node. + * @tzd: a pointer to struct thermal_zone_device where the sensor is registered. + * + * This function removes the sensor callbacks and private data from the + * thermal zone device registered with thermal_zone_of_sensor_register() + * API. It will also silent the zone by remove the .get_temp() and .get_trend() + * thermal zone device callbacks. + * + * TODO: When the support to several sensors per zone is added, this + * function must search the sensor list based on @dev parameter. + * + */ +void thermal_zone_of_sensor_unregister(struct device *dev, + struct thermal_zone_device *tzd) +{ + struct __thermal_zone *tz; + + if (!dev || !tzd || !tzd->devdata) + return; + + tz = tzd->devdata; + + /* no __thermal_zone, nothing to be done */ + if (!tz) + return; + + mutex_lock(&tzd->lock); + tzd->ops->get_temp = NULL; + tzd->ops->get_trend = NULL; + + tz->get_temp = NULL; + tz->get_trend = NULL; + tz->sensor_data = NULL; + mutex_unlock(&tzd->lock); +} +EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister); + +/*** functions parsing device tree nodes ***/ + +/** + * thermal_of_populate_bind_params - parse and fill cooling map data + * @np: DT node containing a cooling-map node + * @__tbp: data structure to be filled with cooling map info + * @trips: array of thermal zone trip points + * @ntrips: number of trip points inside trips. + * + * This function parses a cooling-map type of node represented by + * @np parameter and fills the read data into @__tbp data structure. + * It needs the already parsed array of trip points of the thermal zone + * in consideration. + * + * Return: 0 on success, proper error code otherwise + */ +static int thermal_of_populate_bind_params(struct device_node *np, + struct __thermal_bind_params *__tbp, + struct __thermal_trip *trips, + int ntrips) +{ + struct of_phandle_args cooling_spec; + struct device_node *trip; + int ret, i; + u32 prop; + + /* Default weight. Usage is optional */ + __tbp->usage = 0; + ret = of_property_read_u32(np, "contribution", &prop); + if (ret == 0) + __tbp->usage = prop; + + trip = of_parse_phandle(np, "trip", 0); + if (!trip) { + pr_err("missing trip property\n"); + return -ENODEV; + } + + /* match using device_node */ + for (i = 0; i < ntrips; i++) + if (trip == trips[i].np) { + __tbp->trip_id = i; + break; + } + + if (i == ntrips) { + ret = -ENODEV; + goto end; + } + + ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells", + 0, &cooling_spec); + if (ret < 0) { + pr_err("missing cooling_device property\n"); + goto end; + } + __tbp->cooling_device = cooling_spec.np; + if (cooling_spec.args_count >= 2) { /* at least min and max */ + __tbp->min = cooling_spec.args[0]; + __tbp->max = cooling_spec.args[1]; + } else { + pr_err("wrong reference to cooling device, missing limits\n"); + } + +end: + of_node_put(trip); + + return ret; +} + +/** + * It maps 'enum thermal_trip_type' found in include/linux/thermal.h + * into the device tree binding of 'trip', property type. + */ +static const char * const trip_types[] = { + [THERMAL_TRIP_ACTIVE] = "active", + [THERMAL_TRIP_PASSIVE] = "passive", + [THERMAL_TRIP_HOT] = "hot", + [THERMAL_TRIP_CRITICAL] = "critical", +}; + +/** + * thermal_of_get_trip_type - Get phy mode for given device_node + * @np: Pointer to the given device_node + * @type: Pointer to resulting trip type + * + * The function gets trip type string from property 'type', + * and store its index in trip_types table in @type, + * + * Return: 0 on success, or errno in error case. + */ +static int thermal_of_get_trip_type(struct device_node *np, + enum thermal_trip_type *type) +{ + const char *t; + int err, i; + + err = of_property_read_string(np, "type", &t); + if (err < 0) + return err; + + for (i = 0; i < ARRAY_SIZE(trip_types); i++) + if (!strcasecmp(t, trip_types[i])) { + *type = i; + return 0; + } + + return -ENODEV; +} + +/** + * thermal_of_populate_trip - parse and fill one trip point data + * @np: DT node containing a trip point node + * @trip: trip point data structure to be filled up + * + * This function parses a trip point type of node represented by + * @np parameter and fills the read data into @trip data structure. + * + * Return: 0 on success, proper error code otherwise + */ +static int thermal_of_populate_trip(struct device_node *np, + struct __thermal_trip *trip) +{ + int prop; + int ret; + + ret = of_property_read_u32(np, "temperature", &prop); + if (ret < 0) { + pr_err("missing temperature property\n"); + return ret; + } + trip->temperature = prop; + + ret = of_property_read_u32(np, "hysteresis", &prop); + if (ret < 0) { + pr_err("missing hysteresis property\n"); + return ret; + } + trip->hysteresis = prop; + + ret = thermal_of_get_trip_type(np, &trip->type); + if (ret < 0) { + pr_err("wrong trip type property\n"); + return ret; + } + + /* Required for cooling map matching */ + trip->np = np; + + return 0; +} + +/** + * thermal_of_build_thermal_zone - parse and fill one thermal zone data + * @np: DT node containing a thermal zone node + * + * This function parses a thermal zone type of node represented by + * @np parameter and fills the read data into a __thermal_zone data structure + * and return this pointer. + * + * TODO: Missing properties to parse: thermal-sensor-names and coefficients + * + * Return: On success returns a valid struct __thermal_zone, + * otherwise, it returns a corresponding ERR_PTR(). Caller must + * check the return value with help of IS_ERR() helper. + */ +static struct __thermal_zone * +thermal_of_build_thermal_zone(struct device_node *np) +{ + struct device_node *child = NULL, *gchild; + struct __thermal_zone *tz; + int ret, i; + u32 prop; + + if (!np) { + pr_err("no thermal zone np\n"); + return ERR_PTR(-EINVAL); + } + + tz = kzalloc(sizeof(*tz), GFP_KERNEL); + if (!tz) + return ERR_PTR(-ENOMEM); + + ret = of_property_read_u32(np, "polling-delay-passive", &prop); + if (ret < 0) { + pr_err("missing polling-delay-passive property\n"); + goto free_tz; + } + tz->passive_delay = prop; + + ret = of_property_read_u32(np, "polling-delay", &prop); + if (ret < 0) { + pr_err("missing polling-delay property\n"); + goto free_tz; + } + tz->polling_delay = prop; + + /* trips */ + child = of_get_child_by_name(np, "trips"); + + /* No trips provided */ + if (!child) + goto finish; + + tz->ntrips = of_get_child_count(child); + if (tz->ntrips == 0) /* must have at least one child */ + goto finish; + + tz->trips = kzalloc(tz->ntrips * sizeof(*tz->trips), GFP_KERNEL); + if (!tz->trips) { + ret = -ENOMEM; + goto free_tz; + } + + i = 0; + for_each_child_of_node(child, gchild) { + ret = thermal_of_populate_trip(gchild, &tz->trips[i++]); + if (ret) + goto free_trips; + } + + of_node_put(child); + + /* cooling-maps */ + child = of_get_child_by_name(np, "cooling-maps"); + + /* cooling-maps not provided */ + if (!child) + goto finish; + + tz->num_tbps = of_get_child_count(child); + if (tz->num_tbps == 0) + goto finish; + + tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL); + if (!tz->tbps) { + ret = -ENOMEM; + goto free_trips; + } + + i = 0; + for_each_child_of_node(child, gchild) + ret = thermal_of_populate_bind_params(gchild, &tz->tbps[i++], + tz->trips, tz->ntrips); + if (ret) + goto free_tbps; + +finish: + of_node_put(child); + tz->mode = THERMAL_DEVICE_DISABLED; + + return tz; + +free_tbps: + kfree(tz->tbps); +free_trips: + kfree(tz->trips); +free_tz: + kfree(tz); + of_node_put(child); + + return ERR_PTR(ret); +} + +static inline void of_thermal_free_zone(struct __thermal_zone *tz) +{ + kfree(tz->tbps); + kfree(tz->trips); + kfree(tz); +} + +/** + * of_parse_thermal_zones - parse device tree thermal data + * + * Initialization function that can be called by machine initialization + * code to parse thermal data and populate the thermal framework + * with hardware thermal zones info. This function only parses thermal zones. + * Cooling devices and sensor devices nodes are supposed to be parsed + * by their respective drivers. + * + * Return: 0 on success, proper error code otherwise + * + */ +int __init of_parse_thermal_zones(void) +{ + struct device_node *np, *child; + struct __thermal_zone *tz; + struct thermal_zone_device_ops *ops; + + np = of_find_node_by_name(NULL, "thermal-zones"); + if (!np) { + pr_debug("unable to find thermal zones\n"); + return 0; /* Run successfully on systems without thermal DT */ + } + + for_each_child_of_node(np, child) { + struct thermal_zone_device *zone; + struct thermal_zone_params *tzp; + + tz = thermal_of_build_thermal_zone(child); + if (IS_ERR(tz)) { + pr_err("failed to build thermal zone %s: %ld\n", + child->name, + PTR_ERR(tz)); + continue; + } + + ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL); + if (!ops) + goto exit_free; + + tzp = kzalloc(sizeof(*tzp), GFP_KERNEL); + if (!tzp) { + kfree(ops); + goto exit_free; + } + + /* No hwmon because there might be hwmon drivers registering */ + tzp->no_hwmon = true; + + zone = thermal_zone_device_register(child->name, tz->ntrips, + 0, tz, + ops, tzp, + tz->passive_delay, + tz->polling_delay); + if (IS_ERR(zone)) { + pr_err("Failed to build %s zone %ld\n", child->name, + PTR_ERR(zone)); + kfree(tzp); + kfree(ops); + of_thermal_free_zone(tz); + /* attempting to build remaining zones still */ + } + } + + return 0; + +exit_free: + of_thermal_free_zone(tz); + + /* no memory available, so free what we have built */ + of_thermal_destroy_zones(); + + return -ENOMEM; +} + +/** + * of_thermal_destroy_zones - remove all zones parsed and allocated resources + * + * Finds all zones parsed and added to the thermal framework and remove them + * from the system, together with their resources. + * + */ +void of_thermal_destroy_zones(void) +{ + struct device_node *np, *child; + + np = of_find_node_by_name(NULL, "thermal-zones"); + if (!np) { + pr_err("unable to find thermal zones\n"); + return; + } + + for_each_child_of_node(np, child) { + struct thermal_zone_device *zone; + + zone = thermal_zone_get_zone_by_name(child->name); + if (IS_ERR(zone)) + continue; + + thermal_zone_device_unregister(zone); + kfree(zone->tzp); + kfree(zone->ops); + of_thermal_free_zone(zone->devdata); + } +} diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 0e43dc208fc6..3392fcb92796 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1373,7 +1373,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) */ struct thermal_zone_device *thermal_zone_device_register(const char *type, int trips, int mask, void *devdata, - const struct thermal_zone_device_ops *ops, + struct thermal_zone_device_ops *ops, const struct thermal_zone_params *tzp, int passive_delay, int polling_delay) { @@ -1746,8 +1746,14 @@ static int __init thermal_init(void) if (result) goto unregister_class; + result = of_parse_thermal_zones(); + if (result) + goto exit_netlink; + return 0; +exit_netlink: + genetlink_exit(); unregister_governors: thermal_unregister_governors(); unregister_class: @@ -1763,6 +1769,7 @@ error: static void __exit thermal_exit(void) { + of_thermal_destroy_zones(); genetlink_exit(); class_unregister(&thermal_class); thermal_unregister_governors(); diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 7cf2f6626251..3db339fb636f 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -77,4 +77,13 @@ static inline int thermal_gov_user_space_register(void) { return 0; } static inline void thermal_gov_user_space_unregister(void) {} #endif /* CONFIG_THERMAL_GOV_USER_SPACE */ +/* device tree support */ +#ifdef CONFIG_THERMAL_OF +int of_parse_thermal_zones(void); +void of_thermal_destroy_zones(void); +#else +static inline int of_parse_thermal_zones(void) { return 0; } +static inline void of_thermal_destroy_zones(void) { } +#endif + #endif /* __THERMAL_CORE_H__ */ diff --git a/include/dt-bindings/thermal/thermal.h b/include/dt-bindings/thermal/thermal.h new file mode 100644 index 000000000000..59822a995858 --- /dev/null +++ b/include/dt-bindings/thermal/thermal.h @@ -0,0 +1,17 @@ +/* + * This header provides constants for most thermal bindings. + * + * Copyright (C) 2013 Texas Instruments + * Eduardo Valentin + * + * GPLv2 only + */ + +#ifndef _DT_BINDINGS_THERMAL_THERMAL_H +#define _DT_BINDINGS_THERMAL_THERMAL_H + +/* On cooling devices upper and lower limits */ +#define THERMAL_NO_LIMIT (-1UL) + +#endif + diff --git a/include/linux/thermal.h b/include/linux/thermal.h index b268d3cf7ae3..b780c5b27122 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -143,6 +143,7 @@ struct thermal_cooling_device { int id; char type[THERMAL_NAME_LENGTH]; struct device device; + struct device_node *np; void *devdata; const struct thermal_cooling_device_ops *ops; bool updated; /* true if the cooling device does not need update */ @@ -172,7 +173,7 @@ struct thermal_zone_device { int emul_temperature; int passive; unsigned int forced_passive; - const struct thermal_zone_device_ops *ops; + struct thermal_zone_device_ops *ops; const struct thermal_zone_params *tzp; struct thermal_governor *governor; struct list_head thermal_instances; @@ -242,8 +243,31 @@ struct thermal_genl_event { }; /* Function declarations */ +#ifdef CONFIG_THERMAL_OF +struct thermal_zone_device * +thermal_zone_of_sensor_register(struct device *dev, int id, + void *data, int (*get_temp)(void *, long *), + int (*get_trend)(void *, long *)); +void thermal_zone_of_sensor_unregister(struct device *dev, + struct thermal_zone_device *tz); +#else +static inline struct thermal_zone_device * +thermal_zone_of_sensor_register(struct device *dev, int id, + void *data, int (*get_temp)(void *, long *), + int (*get_trend)(void *, long *)) +{ + return NULL; +} + +static inline +void thermal_zone_of_sensor_unregister(struct device *dev, + struct thermal_zone_device *tz) +{ +} + +#endif struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, - void *, const struct thermal_zone_device_ops *, + void *, struct thermal_zone_device_ops *, const struct thermal_zone_params *, int, int); void thermal_zone_device_unregister(struct thermal_zone_device *); -- cgit v1.2.3 From a116b5d44f144586ef03a93f14ddc63f4a85e906 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Thu, 26 Sep 2013 15:55:01 -0400 Subject: thermal: core: introduce thermal_of_cooling_device_register This patch adds a new API to allow registering cooling devices in the thermal framework derived from device tree nodes. This API links the cooling device with the device tree node so that binding with thermal zones is possible, given that thermal zones are pointing to cooling device device tree nodes. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal_core.c | 58 +++++++++++++++++++++++++++++++++++++++--- include/linux/thermal.h | 4 +++ 2 files changed, 58 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3392fcb92796..e381d521c355 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -1055,7 +1056,8 @@ static struct class thermal_class = { }; /** - * thermal_cooling_device_register() - register a new thermal cooling device + * __thermal_cooling_device_register() - register a new thermal cooling device + * @np: a pointer to a device tree node. * @type: the thermal cooling device type. * @devdata: device private data. * @ops: standard thermal cooling devices callbacks. @@ -1063,13 +1065,16 @@ static struct class thermal_class = { * This interface function adds a new thermal cooling device (fan/processor/...) * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself * to all the thermal zone devices registered at the same time. + * It also gives the opportunity to link the cooling device to a device tree + * node, so that it can be bound to a thermal zone created out of device tree. * * Return: a pointer to the created struct thermal_cooling_device or an * ERR_PTR. Caller must check return value with IS_ERR*() helpers. */ -struct thermal_cooling_device * -thermal_cooling_device_register(char *type, void *devdata, - const struct thermal_cooling_device_ops *ops) +static struct thermal_cooling_device * +__thermal_cooling_device_register(struct device_node *np, + char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) { struct thermal_cooling_device *cdev; int result; @@ -1094,6 +1099,7 @@ thermal_cooling_device_register(char *type, void *devdata, strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); mutex_init(&cdev->lock); INIT_LIST_HEAD(&cdev->thermal_instances); + cdev->np = np; cdev->ops = ops; cdev->updated = true; cdev->device.class = &thermal_class; @@ -1136,8 +1142,52 @@ unregister: device_unregister(&cdev->device); return ERR_PTR(result); } + +/** + * thermal_cooling_device_register() - register a new thermal cooling device + * @type: the thermal cooling device type. + * @devdata: device private data. + * @ops: standard thermal cooling devices callbacks. + * + * This interface function adds a new thermal cooling device (fan/processor/...) + * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself + * to all the thermal zone devices registered at the same time. + * + * Return: a pointer to the created struct thermal_cooling_device or an + * ERR_PTR. Caller must check return value with IS_ERR*() helpers. + */ +struct thermal_cooling_device * +thermal_cooling_device_register(char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) +{ + return __thermal_cooling_device_register(NULL, type, devdata, ops); +} EXPORT_SYMBOL_GPL(thermal_cooling_device_register); +/** + * thermal_of_cooling_device_register() - register an OF thermal cooling device + * @np: a pointer to a device tree node. + * @type: the thermal cooling device type. + * @devdata: device private data. + * @ops: standard thermal cooling devices callbacks. + * + * This function will register a cooling device with device tree node reference. + * This interface function adds a new thermal cooling device (fan/processor/...) + * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself + * to all the thermal zone devices registered at the same time. + * + * Return: a pointer to the created struct thermal_cooling_device or an + * ERR_PTR. Caller must check return value with IS_ERR*() helpers. + */ +struct thermal_cooling_device * +thermal_of_cooling_device_register(struct device_node *np, + char *type, void *devdata, + const struct thermal_cooling_device_ops *ops) +{ + return __thermal_cooling_device_register(np, type, devdata, ops); +} +EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register); + /** * thermal_cooling_device_unregister - removes the registered thermal cooling device * @cdev: the thermal cooling device to remove. diff --git a/include/linux/thermal.h b/include/linux/thermal.h index b780c5b27122..f7e11c7ea7d9 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -25,6 +25,7 @@ #ifndef __THERMAL_H__ #define __THERMAL_H__ +#include #include #include #include @@ -280,6 +281,9 @@ void thermal_zone_device_update(struct thermal_zone_device *); struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, const struct thermal_cooling_device_ops *); +struct thermal_cooling_device * +thermal_of_cooling_device_register(struct device_node *np, char *, void *, + const struct thermal_cooling_device_ops *); void thermal_cooling_device_unregister(struct thermal_cooling_device *); struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name); int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp); -- cgit v1.2.3 From 39d99cff76bf2992fd6dd4b1fc62da139e62e90c Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Thu, 12 Sep 2013 19:26:45 -0400 Subject: thermal: cpu_cooling: introduce of_cpufreq_cooling_register This patch introduces an API to register cpufreq cooling device based on device tree node. The registration via device tree node differs from normal registration due to the fact that it is needed to fill the device_node structure in order to be able to match the cooling devices with trip points. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin --- drivers/thermal/Kconfig | 1 + drivers/thermal/cpu_cooling.c | 56 ++++++++++++++++++++++++++++++++++++++----- include/linux/cpu_cooling.h | 25 +++++++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index a150f8d53322..3feb5377fbf6 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -92,6 +92,7 @@ config THERMAL_GOV_USER_SPACE config CPU_THERMAL bool "generic cpu cooling support" depends on CPU_FREQ + depends on THERMAL_OF help This implements the generic cpu cooling mechanism through frequency reduction. An ACPI version of this already exists diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 02a46f23d14c..a6cb5531403f 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -417,18 +417,21 @@ static struct notifier_block thermal_cpufreq_notifier_block = { }; /** - * cpufreq_cooling_register - function to create cpufreq cooling device. + * __cpufreq_cooling_register - helper function to create cpufreq cooling device + * @np: a valid struct device_node to the cooling device device tree node * @clip_cpus: cpumask of cpus where the frequency constraints will happen. * * This interface function registers the cpufreq cooling device with the name * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq - * cooling devices. + * cooling devices. It also gives the opportunity to link the cooling device + * with a device tree node, in order to bind it via the thermal DT code. * * Return: a valid struct thermal_cooling_device pointer on success, * on failure, it returns a corresponding ERR_PTR(). */ -struct thermal_cooling_device * -cpufreq_cooling_register(const struct cpumask *clip_cpus) +static struct thermal_cooling_device * +__cpufreq_cooling_register(struct device_node *np, + const struct cpumask *clip_cpus) { struct thermal_cooling_device *cool_dev; struct cpufreq_cooling_device *cpufreq_dev = NULL; @@ -467,8 +470,8 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus) snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", cpufreq_dev->id); - cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev, - &cpufreq_cooling_ops); + cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev, + &cpufreq_cooling_ops); if (IS_ERR(cool_dev)) { release_idr(&cpufreq_idr, cpufreq_dev->id); kfree(cpufreq_dev); @@ -488,8 +491,49 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus) return cool_dev; } + +/** + * cpufreq_cooling_register - function to create cpufreq cooling device. + * @clip_cpus: cpumask of cpus where the frequency constraints will happen. + * + * This interface function registers the cpufreq cooling device with the name + * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq + * cooling devices. + * + * Return: a valid struct thermal_cooling_device pointer on success, + * on failure, it returns a corresponding ERR_PTR(). + */ +struct thermal_cooling_device * +cpufreq_cooling_register(const struct cpumask *clip_cpus) +{ + return __cpufreq_cooling_register(NULL, clip_cpus); +} EXPORT_SYMBOL_GPL(cpufreq_cooling_register); +/** + * of_cpufreq_cooling_register - function to create cpufreq cooling device. + * @np: a valid struct device_node to the cooling device device tree node + * @clip_cpus: cpumask of cpus where the frequency constraints will happen. + * + * This interface function registers the cpufreq cooling device with the name + * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq + * cooling devices. Using this API, the cpufreq cooling device will be + * linked to the device tree node provided. + * + * Return: a valid struct thermal_cooling_device pointer on success, + * on failure, it returns a corresponding ERR_PTR(). + */ +struct thermal_cooling_device * +of_cpufreq_cooling_register(struct device_node *np, + const struct cpumask *clip_cpus) +{ + if (!np) + return ERR_PTR(-EINVAL); + + return __cpufreq_cooling_register(np, clip_cpus); +} +EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); + /** * cpufreq_cooling_unregister - function to remove cpufreq cooling device. * @cdev: thermal cooling device pointer. diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index a5d52eea8232..c303d383def1 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h @@ -24,6 +24,7 @@ #ifndef __CPU_COOLING_H__ #define __CPU_COOLING_H__ +#include #include #include @@ -35,6 +36,24 @@ struct thermal_cooling_device * cpufreq_cooling_register(const struct cpumask *clip_cpus); +/** + * of_cpufreq_cooling_register - create cpufreq cooling device based on DT. + * @np: a valid struct device_node to the cooling device device tree node. + * @clip_cpus: cpumask of cpus where the frequency constraints will happen + */ +#ifdef CONFIG_THERMAL_OF +struct thermal_cooling_device * +of_cpufreq_cooling_register(struct device_node *np, + const struct cpumask *clip_cpus); +#else +static inline struct thermal_cooling_device * +of_cpufreq_cooling_register(struct device_node *np, + const struct cpumask *clip_cpus) +{ + return NULL; +} +#endif + /** * cpufreq_cooling_unregister - function to remove cpufreq cooling device. * @cdev: thermal cooling device pointer. @@ -48,6 +67,12 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus) { return NULL; } +static inline struct thermal_cooling_device * +of_cpufreq_cooling_register(struct device_node *np, + const struct cpumask *clip_cpus) +{ + return NULL; +} static inline void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) { -- cgit v1.2.3 From 77cff5926a14e80d4545be5841d5938b87b654a4 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 15 Jul 2013 09:09:14 -0400 Subject: cpufreq: cpufreq-cpu0: add dt node parsing for cooling device properties This patch changes the cpufreq-cpu0 driver to consider if a cpu needs cooling (with cpufreq). In case the cooling is needed, the cpu0 device tree node needs to be properly configured with cooling device properties. In case these properties are present,, the driver will load a cpufreq cooling device in the system. The cpufreq-cpu0 driver is not interested in determining how the system should be using the cooling device. The driver is responsible only of loading the cooling device. Describing how the cooling device will be used can be accomplished by setting up a thermal zone that references and is composed by the cpufreq cooling device. Cc: "Rafael J. Wysocki" Cc: Grant Likely Cc: Rob Herring Cc: cpufreq@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: devicetree-discuss@lists.ozlabs.org Acked-by: Viresh Kumar Signed-off-by: Eduardo Valentin --- .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 7 +++++++ drivers/cpufreq/Kconfig | 2 +- drivers/cpufreq/cpufreq-cpu0.c | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt index 051f764bedb8..f055515d2b62 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt @@ -15,6 +15,10 @@ Optional properties: - clock-latency: Specify the possible maximum transition latency for clock, in unit of nanoseconds. - voltage-tolerance: Specify the CPU voltage tolerance in percentage. +- #cooling-cells: +- cooling-min-level: +- cooling-max-level: + Please refer to Documentation/devicetree/bindings/thermal/thermal.txt. Examples: @@ -33,6 +37,9 @@ cpus { 198000 850000 >; clock-latency = <61036>; /* two CLK32 periods */ + #cooling-cells = <2>; + cooling-min-level = <0>; + cooling-max-level = <2>; }; cpu@1 { diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 38093e272377..6b8cde5f98af 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -181,7 +181,7 @@ config CPU_FREQ_GOV_CONSERVATIVE config GENERIC_CPUFREQ_CPU0 tristate "Generic CPU0 cpufreq driver" - depends on HAVE_CLK && REGULATOR && PM_OPP && OF + depends on HAVE_CLK && REGULATOR && PM_OPP && OF && THERMAL && CPU_THERMAL help This adds a generic cpufreq driver for CPU0 frequency management. It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index d4585ce2346c..91c7bb67bc74 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -13,7 +13,9 @@ #include #include +#include #include +#include #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#include static unsigned int transition_latency; static unsigned int voltage_tolerance; /* in percentage */ @@ -29,6 +32,7 @@ static struct device *cpu_dev; static struct clk *cpu_clk; static struct regulator *cpu_reg; static struct cpufreq_frequency_table *freq_table; +static struct thermal_cooling_device *cdev; static unsigned int cpu0_get_speed(unsigned int cpu) { @@ -201,6 +205,17 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) goto out_free_table; } + /* + * For now, just loading the cooling device; + * thermal DT code takes care of matching them. + */ + if (of_find_property(np, "#cooling-cells", NULL)) { + cdev = of_cpufreq_cooling_register(np, cpu_present_mask); + if (IS_ERR(cdev)) + pr_err("running cpufreq without cooling device: %ld\n", + PTR_ERR(cdev)); + } + of_node_put(np); return 0; @@ -213,6 +228,7 @@ out_put_node: static int cpu0_cpufreq_remove(struct platform_device *pdev) { + cpufreq_cooling_unregister(cdev); cpufreq_unregister_driver(&cpu0_cpufreq_driver); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -- cgit v1.2.3 From 22e731838b0e337fed5f16c67aa0b954028dfe93 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Tue, 16 Jul 2013 14:54:55 -0400 Subject: hwmon: lm75: expose to thermal fw via DT nodes This patch adds to lm75 temperature sensor the possibility to expose itself as thermal zone device, registered on the thermal framework. The thermal zone is built only if a device tree node describing a thermal zone for this sensor is present inside the lm75 DT node. Otherwise, the driver behavior will be the same. Note: This patch has also been reviewed by Jean D. He has requested to perform a wider inspection of possible users of thermal and hwmon interaction API. On the other hand, the change on this patch is acceptable on first step of overall code change. Cc: Jean Delvare Cc: lm-sensors@lm-sensors.org Cc: linux-kernel@vger.kernel.org Acked-by: Guenter Roeck Signed-off-by: Eduardo Valentin --- drivers/hwmon/lm75.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 7e3ef134f1d2..84a55eacd903 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "lm75.h" @@ -71,6 +73,7 @@ static const u8 LM75_REG_TEMP[3] = { /* Each client has this additional data */ struct lm75_data { struct device *hwmon_dev; + struct thermal_zone_device *tz; struct mutex update_lock; u8 orig_conf; u8 resolution; /* In bits, between 9 and 12 */ @@ -91,22 +94,36 @@ static struct lm75_data *lm75_update_device(struct device *dev); /*-----------------------------------------------------------------------*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + /* sysfs attributes for hwmon */ +static int lm75_read_temp(void *dev, long *temp) +{ + struct lm75_data *data = lm75_update_device(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + *temp = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm75_data *data = lm75_update_device(dev); - long temp; if (IS_ERR(data)) return PTR_ERR(data); - temp = ((data->temp[attr->index] >> (16 - data->resolution)) * 1000) - >> (data->resolution - 8); - - return sprintf(buf, "%ld\n", temp); + return sprintf(buf, "%ld\n", lm75_reg_to_mc(data->temp[attr->index], + data->resolution)); } static ssize_t set_temp(struct device *dev, struct device_attribute *da, @@ -273,6 +290,13 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) goto exit_remove; } + data->tz = thermal_zone_of_sensor_register(&client->dev, + 0, + &client->dev, + lm75_read_temp, NULL); + if (IS_ERR(data->tz)) + data->tz = NULL; + dev_info(&client->dev, "%s: sensor '%s'\n", dev_name(data->hwmon_dev), client->name); @@ -287,6 +311,7 @@ static int lm75_remove(struct i2c_client *client) { struct lm75_data *data = i2c_get_clientdata(client); + thermal_zone_of_sensor_unregister(&client->dev, data->tz); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm75_group); lm75_write_value(client, LM75_REG_CONF, data->orig_conf); -- cgit v1.2.3 From 6a027523f30f1cc90037686e6a682d15c6a555d6 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Tue, 16 Jul 2013 14:57:51 -0400 Subject: hwmon: tmp102: expose to thermal fw via DT nodes This patch adds to tmp102 temperature sensor the possibility to expose itself as thermal zone device, registered on the thermal framework. The thermal zone is built only if a device tree node describing a thermal zone for this sensor is present inside the tmp102 DT node. Otherwise, the driver behavior will be the same. Note: This patch has also been reviewed by Jean D. He has requested to perform a wider inspection of possible users of thermal and hwmon interaction API. On the other hand, the change on this patch is acceptable on first step of overall code change. Cc: Jean Delvare Cc: lm-sensors@lm-sensors.org Cc: linux-kernel@vger.kernel.org Acked-by: Guenter Roeck Signed-off-by: Eduardo Valentin --- drivers/hwmon/tmp102.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index d7b47abf37fe..6748b4583e7b 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #define DRIVER_NAME "tmp102" @@ -50,6 +52,7 @@ struct tmp102 { struct device *hwmon_dev; + struct thermal_zone_device *tz; struct mutex lock; u16 config_orig; unsigned long last_update; @@ -93,6 +96,15 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client) return tmp102; } +static int tmp102_read_temp(void *dev, long *temp) +{ + struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev)); + + *temp = tmp102->temp[0]; + + return 0; +} + static ssize_t tmp102_show_temp(struct device *dev, struct device_attribute *attr, char *buf) @@ -204,6 +216,12 @@ static int tmp102_probe(struct i2c_client *client, goto fail_remove_sysfs; } + tmp102->tz = thermal_zone_of_sensor_register(&client->dev, 0, + &client->dev, + tmp102_read_temp, NULL); + if (IS_ERR(tmp102->tz)) + tmp102->tz = NULL; + dev_info(&client->dev, "initialized\n"); return 0; @@ -220,6 +238,7 @@ static int tmp102_remove(struct i2c_client *client) { struct tmp102 *tmp102 = i2c_get_clientdata(client); + thermal_zone_of_sensor_unregister(&client->dev, tmp102->tz); hwmon_device_unregister(tmp102->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); -- cgit v1.2.3 From 26d9cc65fa769d80cfca27eb8f85b4c3df56a04b Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Thu, 4 Jul 2013 16:43:54 -0400 Subject: thermal: ti-soc-thermal: use thermal DT infrastructure This patch improves the ti-soc-thermal driver by adding the support to build the thermal zones based on DT nodes. The driver will have two options now to build the thermal zones. The first option is the zones originally coded in this driver. So, the driver behavior will be same if there is no DT node describing the zones. The second option, when it is found a DT node with thermal data, will used the common infrastructure to build the thermal zone and bind its cooling devices. In case the driver loads thermal data using the legacy mode, this driver still adds to the system a cpufreq cooling device. Loading the thermal data from DT, the driver assumes someone else will add the cpufreq cooling device, like the cpufreq driver. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin --- drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 77 +++++++++++++++++----- 1 file changed, 62 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 5a47cc8c8f85..9eec26dc0448 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "ti-thermal.h" #include "ti-bandgap.h" @@ -44,6 +45,7 @@ struct ti_thermal_data { enum thermal_device_mode mode; struct work_struct thermal_wq; int sensor_id; + bool our_zone; }; static void ti_thermal_work(struct work_struct *work) @@ -75,11 +77,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c) /* thermal zone ops */ /* Get temperature callback function for thermal zone*/ -static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) +static inline int __ti_thermal_get_temp(void *devdata, long *temp) { struct thermal_zone_device *pcb_tz = NULL; - struct ti_thermal_data *data = thermal->devdata; + struct ti_thermal_data *data = devdata; struct ti_bandgap *bgp; const struct ti_temp_sensor *s; int ret, tmp, slope, constant; @@ -118,6 +119,14 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, return ret; } +static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, + unsigned long *temp) +{ + struct ti_thermal_data *data = thermal->devdata; + + return __ti_thermal_get_temp(data, temp); +} + /* Bind callback functions for thermal zone */ static int ti_thermal_bind(struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev) @@ -230,11 +239,9 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal, return 0; } -/* Get the temperature trend callback functions for thermal zone */ -static int ti_thermal_get_trend(struct thermal_zone_device *thermal, - int trip, enum thermal_trend *trend) +static int __ti_thermal_get_trend(void *p, long *trend) { - struct ti_thermal_data *data = thermal->devdata; + struct ti_thermal_data *data = p; struct ti_bandgap *bgp; int id, tr, ret = 0; @@ -245,6 +252,22 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal, if (ret) return ret; + *trend = tr; + + return 0; +} + +/* Get the temperature trend callback functions for thermal zone */ +static int ti_thermal_get_trend(struct thermal_zone_device *thermal, + int trip, enum thermal_trend *trend) +{ + int ret; + long tr; + + ret = __ti_thermal_get_trend(thermal->devdata, &tr); + if (ret) + return ret; + if (tr > 0) *trend = THERMAL_TREND_RAISING; else if (tr < 0) @@ -308,16 +331,23 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, if (!data) return -EINVAL; - /* Create thermal zone */ - data->ti_thermal = thermal_zone_device_register(domain, + /* in case this is specified by DT */ + data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id, + data, __ti_thermal_get_temp, + __ti_thermal_get_trend); + if (IS_ERR(data->ti_thermal)) { + /* Create thermal zone */ + data->ti_thermal = thermal_zone_device_register(domain, OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, NULL, FAST_TEMP_MONITORING_RATE, FAST_TEMP_MONITORING_RATE); - if (IS_ERR(data->ti_thermal)) { - dev_err(bgp->dev, "thermal zone device is NULL\n"); - return PTR_ERR(data->ti_thermal); + if (IS_ERR(data->ti_thermal)) { + dev_err(bgp->dev, "thermal zone device is NULL\n"); + return PTR_ERR(data->ti_thermal); + } + data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; + data->our_zone = true; } - data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; ti_bandgap_set_sensor_data(bgp, id, data); ti_bandgap_write_update_interval(bgp, data->sensor_id, data->ti_thermal->polling_delay); @@ -331,7 +361,13 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id) data = ti_bandgap_get_sensor_data(bgp, id); - thermal_zone_device_unregister(data->ti_thermal); + if (data && data->ti_thermal) { + if (data->our_zone) + thermal_zone_device_unregister(data->ti_thermal); + else + thermal_zone_of_sensor_unregister(bgp->dev, + data->ti_thermal); + } return 0; } @@ -350,6 +386,15 @@ int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id) int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) { struct ti_thermal_data *data; + struct device_node *np = bgp->dev->of_node; + + /* + * We are assuming here that if one deploys the zone + * using DT, then it must be aware that the cooling device + * loading has to happen via cpufreq driver. + */ + if (of_find_property(np, "#thermal-sensor-cells", NULL)) + return 0; data = ti_bandgap_get_sensor_data(bgp, id); if (!data || IS_ERR(data)) @@ -380,7 +425,9 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id) struct ti_thermal_data *data; data = ti_bandgap_get_sensor_data(bgp, id); - cpufreq_cooling_unregister(data->cool_dev); + + if (data && data->cool_dev) + cpufreq_cooling_unregister(data->cool_dev); return 0; } -- cgit v1.2.3 From 9fb1f39eb2d6707d265087ee186376e24995f55a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 4 Dec 2013 14:42:46 +0100 Subject: gpio/pinctrl: make gpio_chip members typed boolean This switches the two members of struct gpio_chip that were defined as unsigned foo:1 to bool, because that is indeed what they are. Switch all users in the gpio and pinctrl subsystems to assign these values with true/false instead of 0/1. The users outside these subsystems will survive since true/false is 1/0, atleast we set some kind of more strict typing example. Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74x164.c | 2 +- drivers/gpio/gpio-adnp.c | 2 +- drivers/gpio/gpio-adp5520.c | 2 +- drivers/gpio/gpio-adp5588.c | 2 +- drivers/gpio/gpio-arizona.c | 2 +- drivers/gpio/gpio-bt8xx.c | 2 +- drivers/gpio/gpio-da9052.c | 2 +- drivers/gpio/gpio-da9055.c | 2 +- drivers/gpio/gpio-ich.c | 2 +- drivers/gpio/gpio-intel-mid.c | 2 +- drivers/gpio/gpio-kempld.c | 2 +- drivers/gpio/gpio-ks8695.c | 2 +- drivers/gpio/gpio-lpc32xx.c | 12 ++++++------ drivers/gpio/gpio-lynxpoint.c | 2 +- drivers/gpio/gpio-max730x.c | 2 +- drivers/gpio/gpio-max732x.c | 2 +- drivers/gpio/gpio-mc33880.c | 2 +- drivers/gpio/gpio-mc9s08dz60.c | 2 +- drivers/gpio/gpio-mcp23s08.c | 2 +- drivers/gpio/gpio-ml-ioh.c | 2 +- drivers/gpio/gpio-msic.c | 2 +- drivers/gpio/gpio-mvebu.c | 2 +- drivers/gpio/gpio-octeon.c | 2 +- drivers/gpio/gpio-palmas.c | 2 +- drivers/gpio/gpio-pca953x.c | 2 +- drivers/gpio/gpio-pcf857x.c | 2 +- drivers/gpio/gpio-pch.c | 2 +- drivers/gpio/gpio-rc5t583.c | 2 +- drivers/gpio/gpio-sta2x11.c | 2 +- drivers/gpio/gpio-stmpe.c | 2 +- drivers/gpio/gpio-sx150x.c | 2 +- drivers/gpio/gpio-tb10x.c | 2 +- drivers/gpio/gpio-tc3589x.c | 2 +- drivers/gpio/gpio-timberdale.c | 2 +- drivers/gpio/gpio-tnetv107x.c | 2 +- drivers/gpio/gpio-tps6586x.c | 2 +- drivers/gpio/gpio-tps65910.c | 2 +- drivers/gpio/gpio-tps65912.c | 2 +- drivers/gpio/gpio-twl4030.c | 2 +- drivers/gpio/gpio-twl6040.c | 2 +- drivers/gpio/gpio-ucb1400.c | 2 +- drivers/gpio/gpio-viperboard.c | 4 ++-- drivers/gpio/gpio-vx855.c | 2 +- drivers/gpio/gpio-wm831x.c | 2 +- drivers/gpio/gpio-wm8350.c | 2 +- drivers/gpio/gpio-wm8994.c | 2 +- drivers/gpio/gpiolib.c | 2 +- drivers/pinctrl/pinctrl-as3722.c | 2 +- drivers/pinctrl/pinctrl-at91.c | 2 +- drivers/pinctrl/pinctrl-baytrail.c | 2 +- drivers/pinctrl/pinctrl-bcm2835.c | 2 +- drivers/pinctrl/pinctrl-nomadik.c | 2 +- drivers/pinctrl/pinctrl-sunxi.c | 2 +- drivers/pinctrl/vt8500/pinctrl-wmt.c | 2 +- include/linux/gpio/driver.h | 9 +++++---- 55 files changed, 65 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 1e04bf91328d..ddb831232407 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -159,7 +159,7 @@ static int gen_74x164_probe(struct spi_device *spi) goto exit_destroy; } - chip->gpio_chip.can_sleep = 1; + chip->gpio_chip.can_sleep = true; chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index b204033acaeb..030a3897d9f7 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -260,7 +260,7 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) chip->direction_output = adnp_gpio_direction_output; chip->get = adnp_gpio_get; chip->set = adnp_gpio_set; - chip->can_sleep = 1; + chip->can_sleep = true; if (IS_ENABLED(CONFIG_DEBUG_FS)) chip->dbg_show = adnp_gpio_dbg_show; diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 084337d5514d..613265944e2e 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -127,7 +127,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev) gc->direction_output = adp5520_gpio_direction_output; gc->get = adp5520_gpio_get_value; gc->set = adp5520_gpio_set_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = pdata->gpio_start; gc->ngpio = gpios; diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 90fc4c99c024..3f190e68f973 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -380,7 +380,7 @@ static int adp5588_gpio_probe(struct i2c_client *client, gc->direction_output = adp5588_gpio_direction_output; gc->get = adp5588_gpio_get_value; gc->set = adp5588_gpio_set_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = pdata->gpio_start; gc->ngpio = ADP5588_MAXGPIO; diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index dceb5dcf9d16..29bdff558981 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -91,7 +91,7 @@ static struct gpio_chip template_chip = { .get = arizona_gpio_get, .direction_output = arizona_gpio_direction_out, .set = arizona_gpio_set, - .can_sleep = 1, + .can_sleep = true, }; static int arizona_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index c5c356b7f2ce..ecb3ca2d1d10 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -169,7 +169,7 @@ static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) c->dbg_show = NULL; c->base = modparam_gpiobase; c->ngpio = BT8XXGPIO_NR_GPIOS; - c->can_sleep = 0; + c->can_sleep = false; } static int bt8xxgpio_probe(struct pci_dev *dev, diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9b77dc05d4ad..416cdf786b05 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -200,7 +200,7 @@ static struct gpio_chip reference_gp = { .direction_input = da9052_gpio_direction_input, .direction_output = da9052_gpio_direction_output, .to_irq = da9052_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, .ngpio = 16, .base = -1, }; diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 7ef0820032bd..f992997bc301 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -134,7 +134,7 @@ static struct gpio_chip reference_gp = { .direction_input = da9055_gpio_direction_input, .direction_output = da9055_gpio_direction_output, .to_irq = da9055_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, .ngpio = 3, .base = -1, }; diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 814addb62d2c..f5bf3c38bca6 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -252,7 +252,7 @@ static void ichx_gpiolib_setup(struct gpio_chip *chip) chip->direction_output = ichx_gpio_direction_output; chip->base = modparam_gpiobase; chip->ngpio = ichx_priv.desc->ngpio; - chip->can_sleep = 0; + chip->can_sleep = false; chip->dbg_show = NULL; } diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index f2035c01577f..1535ebae8fc8 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -425,7 +425,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, priv->chip.to_irq = intel_gpio_to_irq; priv->chip.base = gpio_base; priv->chip.ngpio = ddata->ngpio; - priv->chip.can_sleep = 0; + priv->chip.can_sleep = false; priv->pdev = pdev; spin_lock_init(&priv->lock); diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c index efdc3924d7df..c6d88173f5a2 100644 --- a/drivers/gpio/gpio-kempld.c +++ b/drivers/gpio/gpio-kempld.c @@ -167,7 +167,7 @@ static int kempld_gpio_probe(struct platform_device *pdev) chip->label = "gpio-kempld"; chip->owner = THIS_MODULE; chip->dev = dev; - chip->can_sleep = 1; + chip->can_sleep = true; if (pdata && pdata->gpio_base) chip->base = pdata->gpio_base; else diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index a3ac66ea364b..464a83de0d6a 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c @@ -228,7 +228,7 @@ static struct gpio_chip ks8695_gpio_chip = { .to_irq = ks8695_gpio_to_irq, .base = 0, .ngpio = 16, - .can_sleep = 0, + .can_sleep = false, }; /* Register the GPIOs */ diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index a7093e010149..225344d66404 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -448,7 +448,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P0_GRP, .ngpio = LPC32XX_GPIO_P0_MAX, .names = gpio_p0_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p0, }, @@ -464,7 +464,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P1_GRP, .ngpio = LPC32XX_GPIO_P1_MAX, .names = gpio_p1_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p1, }, @@ -479,7 +479,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P2_GRP, .ngpio = LPC32XX_GPIO_P2_MAX, .names = gpio_p2_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p2, }, @@ -495,7 +495,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPIO_P3_GRP, .ngpio = LPC32XX_GPIO_P3_MAX, .names = gpio_p3_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p3, }, @@ -509,7 +509,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPI_P3_GRP, .ngpio = LPC32XX_GPI_P3_MAX, .names = gpi_p3_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p3, }, @@ -523,7 +523,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = { .base = LPC32XX_GPO_P3_GRP, .ngpio = LPC32XX_GPO_P3_MAX, .names = gpo_p3_names, - .can_sleep = 0, + .can_sleep = false, }, .gpio_grp = &gpio_grp_regs_p3, }, diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 1a7443ee6016..c283cd3b247a 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -391,7 +391,7 @@ static int lp_gpio_probe(struct platform_device *pdev) gc->set = lp_gpio_set; gc->base = -1; gc->ngpio = LP_NUM_GPIO; - gc->can_sleep = 0; + gc->can_sleep = false; gc->dev = dev; /* set up interrupts */ diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index f4f4ed19bdc1..89226a36b08c 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -188,7 +188,7 @@ int __max730x_probe(struct max7301 *ts) ts->chip.set = max7301_set; ts->chip.ngpio = PIN_NUMBER; - ts->chip.can_sleep = 1; + ts->chip.can_sleep = true; ts->chip.dev = dev; ts->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 91ad74dea8ce..36cb290764b6 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -564,7 +564,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip, gc->set = max732x_gpio_set_value; } gc->get = max732x_gpio_get_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = gpio_start; gc->ngpio = port; diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c index c0b7835f5136..553a80a5eaf3 100644 --- a/drivers/gpio/gpio-mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -115,7 +115,7 @@ static int mc33880_probe(struct spi_device *spi) mc->chip.set = mc33880_set; mc->chip.base = pdata->base; mc->chip.ngpio = PIN_NUMBER; - mc->chip.can_sleep = 1; + mc->chip.can_sleep = true; mc->chip.dev = &spi->dev; mc->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c index 0ab700046a23..dce35ff00db7 100644 --- a/drivers/gpio/gpio-mc9s08dz60.c +++ b/drivers/gpio/gpio-mc9s08dz60.c @@ -102,7 +102,7 @@ static int mc9s08dz60_probe(struct i2c_client *client, mc9s->chip.dev = &client->dev; mc9s->chip.owner = THIS_MODULE; mc9s->chip.ngpio = GPIO_NUM; - mc9s->chip.can_sleep = 1; + mc9s->chip.can_sleep = true; mc9s->chip.get = mc9s08dz60_get_value; mc9s->chip.set = mc9s08dz60_set_value; mc9s->chip.direction_output = mc9s08dz60_direction_output; diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 2deb0c5e54a4..b16401ee4766 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -425,7 +425,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, } mcp->chip.base = base; - mcp->chip.can_sleep = 1; + mcp->chip.can_sleep = true; mcp->chip.dev = dev; mcp->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 5c94af3c84e0..d51329d23d38 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -242,7 +242,7 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) gpio->dbg_show = NULL; gpio->base = -1; gpio->ngpio = num_port; - gpio->can_sleep = 0; + gpio->can_sleep = false; gpio->to_irq = ioh_gpio_to_irq; } diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 69d60ab1d698..8f70ded82a2b 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -292,7 +292,7 @@ static int platform_msic_gpio_probe(struct platform_device *pdev) mg->chip.to_irq = msic_gpio_to_irq; mg->chip.base = pdata->gpio_base; mg->chip.ngpio = MSIC_NUM_GPIO; - mg->chip.can_sleep = 1; + mg->chip.can_sleep = true; mg->chip.dev = dev; mutex_init(&mg->buslock); diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 3c3321f94053..a8908009803f 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -600,7 +600,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->chip.to_irq = mvebu_gpio_to_irq; mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; mvchip->chip.ngpio = ngpios; - mvchip->chip.can_sleep = 0; + mvchip->chip.can_sleep = false; mvchip->chip.of_node = np; mvchip->chip.dbg_show = mvebu_gpio_dbg_show; diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 71a4a318315d..dbb08546b9ec 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -111,7 +111,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->owner = THIS_MODULE; chip->base = 0; - chip->can_sleep = 0; + chip->can_sleep = false; chip->ngpio = 20; chip->direction_input = octeon_gpio_dir_in; chip->get = octeon_gpio_get; diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 11801e986dd9..da9d33252e56 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -182,7 +182,7 @@ static int palmas_gpio_probe(struct platform_device *pdev) palmas_gpio->gpio_chip.owner = THIS_MODULE; palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); palmas_gpio->gpio_chip.ngpio = dev_data->ngpio; - palmas_gpio->gpio_chip.can_sleep = 1; + palmas_gpio->gpio_chip.can_sleep = true; palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 6e48c07e3d8c..019b23b955a2 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -354,7 +354,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) gc->direction_output = pca953x_gpio_direction_output; gc->get = pca953x_gpio_get_value; gc->set = pca953x_gpio_set_value; - gc->can_sleep = 1; + gc->can_sleep = true; gc->base = chip->gpio_start; gc->ngpio = gpios; diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 1535686e74ea..82735822bc9d 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -305,7 +305,7 @@ static int pcf857x_probe(struct i2c_client *client, spin_lock_init(&gpio->slock); gpio->chip.base = pdata ? pdata->gpio_base : -1; - gpio->chip.can_sleep = 1; + gpio->chip.can_sleep = true; gpio->chip.dev = &client->dev; gpio->chip.owner = THIS_MODULE; gpio->chip.get = pcf857x_get; diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index ef7a756c9ded..9656c196772e 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -224,7 +224,7 @@ static void pch_gpio_setup(struct pch_gpio *chip) gpio->dbg_show = NULL; gpio->base = -1; gpio->ngpio = gpio_pins[chip->ioh]; - gpio->can_sleep = 0; + gpio->can_sleep = false; gpio->to_irq = pch_gpio_to_irq; } diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index e63d6a397e17..122b776fdc0b 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -133,7 +133,7 @@ static int rc5t583_gpio_probe(struct platform_device *pdev) rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, - rc5t583_gpio->gpio_chip.can_sleep = 1, + rc5t583_gpio->gpio_chip.can_sleep = true, rc5t583_gpio->gpio_chip.dev = &pdev->dev; rc5t583_gpio->gpio_chip.base = -1; rc5t583_gpio->rc5t583 = rc5t583; diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index f2fb12c18da9..68e3fcb1acea 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -146,7 +146,7 @@ static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */ gpio->dbg_show = NULL; gpio->base = gpio_base; gpio->ngpio = GSTA_NR_GPIO; - gpio->can_sleep = 0; + gpio->can_sleep = false; gpio->to_irq = gsta_gpio_to_irq; /* diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 2647e243d471..2776a09bee58 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -129,7 +129,7 @@ static struct gpio_chip template_chip = { .set = stmpe_gpio_set, .to_irq = stmpe_gpio_to_irq, .request = stmpe_gpio_request, - .can_sleep = 1, + .can_sleep = true, }; static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d2983e9ad6af..13d73fb2b5e1 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -436,7 +436,7 @@ static void sx150x_init_chip(struct sx150x_chip *chip, chip->gpio_chip.set = sx150x_gpio_set; chip->gpio_chip.to_irq = sx150x_gpio_to_irq; chip->gpio_chip.base = pdata->gpio_base; - chip->gpio_chip.can_sleep = 1; + chip->gpio_chip.can_sleep = true; chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; if (pdata->oscio_is_gpo) ++chip->gpio_chip.ngpio; diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index 0502b9a041a5..66a54ea4f779 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -221,7 +221,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) tb10x_gpio->gc.free = tb10x_gpio_free; tb10x_gpio->gc.base = -1; tb10x_gpio->gc.ngpio = ngpio; - tb10x_gpio->gc.can_sleep = 0; + tb10x_gpio->gc.can_sleep = false; ret = gpiochip_add(&tb10x_gpio->gc); diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index ddb5fefaa715..1019320984d7 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -127,7 +127,7 @@ static struct gpio_chip template_chip = { .direction_output = tc3589x_gpio_direction_output, .set = tc3589x_gpio_set, .to_irq = tc3589x_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, }; static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 521971e6a9f5..f9a8fbde108e 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -275,7 +275,7 @@ static int timbgpio_probe(struct platform_device *pdev) gc->dbg_show = NULL; gc->base = pdata->gpio_base; gc->ngpio = pdata->nr_pins; - gc->can_sleep = 0; + gc->can_sleep = false; err = gpiochip_add(gc); if (err) diff --git a/drivers/gpio/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c index 58445bb69106..4aa481579a05 100644 --- a/drivers/gpio/gpio-tnetv107x.c +++ b/drivers/gpio/gpio-tnetv107x.c @@ -176,7 +176,7 @@ static int __init tnetv107x_gpio_setup(void) ctlr = &chips[i]; ctlr->chip.label = "tnetv107x"; - ctlr->chip.can_sleep = 0; + ctlr->chip.can_sleep = false; ctlr->chip.base = base; ctlr->chip.ngpio = ngpio - base; if (ctlr->chip.ngpio > 32) diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 29e8e750bd49..8994dfa13491 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -108,7 +108,7 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) tps6586x_gpio->gpio_chip.label = pdev->name; tps6586x_gpio->gpio_chip.dev = &pdev->dev; tps6586x_gpio->gpio_chip.ngpio = 4; - tps6586x_gpio->gpio_chip.can_sleep = 1; + tps6586x_gpio->gpio_chip.can_sleep = true; /* FIXME: add handling of GPIOs as dedicated inputs */ tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 06146219d9d2..b6e818e68007 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -143,7 +143,7 @@ static int tps65910_gpio_probe(struct platform_device *pdev) default: return -EINVAL; } - tps65910_gpio->gpio_chip.can_sleep = 1; + tps65910_gpio->gpio_chip.can_sleep = true; tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input; tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output; tps65910_gpio->gpio_chip.set = tps65910_gpio_set; diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 276a4229b032..59ee486cb8b9 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -79,7 +79,7 @@ static struct gpio_chip template_chip = { .direction_output = tps65912_gpio_output, .get = tps65912_gpio_get, .set = tps65912_gpio_set, - .can_sleep = 1, + .can_sleep = true, .ngpio = 5, .base = -1, }; diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 0c7e891c8651..cd06678a29f7 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -386,7 +386,7 @@ static struct gpio_chip template_chip = { .direction_output = twl_direction_out, .set = twl_set, .to_irq = twl_to_irq, - .can_sleep = 1, + .can_sleep = true, }; /*----------------------------------------------------------------------*/ diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c index d420d30b86e7..0caf5cd1b47d 100644 --- a/drivers/gpio/gpio-twl6040.c +++ b/drivers/gpio/gpio-twl6040.c @@ -77,7 +77,7 @@ static struct gpio_chip twl6040gpo_chip = { .get = twl6040gpo_get, .direction_output = twl6040gpo_direction_out, .set = twl6040gpo_set, - .can_sleep = 1, + .can_sleep = true, }; /*----------------------------------------------------------------------*/ diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c index 1a605f2a0f55..c6a53971387b 100644 --- a/drivers/gpio/gpio-ucb1400.c +++ b/drivers/gpio/gpio-ucb1400.c @@ -64,7 +64,7 @@ static int ucb1400_gpio_probe(struct platform_device *dev) ucb->gc.direction_output = ucb1400_gpio_dir_out; ucb->gc.get = ucb1400_gpio_get; ucb->gc.set = ucb1400_gpio_set; - ucb->gc.can_sleep = 1; + ucb->gc.can_sleep = true; err = gpiochip_add(&ucb->gc); if (err) diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 5ac2919197fe..79e3b5836712 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c @@ -413,7 +413,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) vb_gpio->gpioa.owner = THIS_MODULE; vb_gpio->gpioa.base = -1; vb_gpio->gpioa.ngpio = 16; - vb_gpio->gpioa.can_sleep = 1; + vb_gpio->gpioa.can_sleep = true; vb_gpio->gpioa.set = vprbrd_gpioa_set; vb_gpio->gpioa.get = vprbrd_gpioa_get; vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input; @@ -430,7 +430,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) vb_gpio->gpiob.owner = THIS_MODULE; vb_gpio->gpiob.base = -1; vb_gpio->gpiob.ngpio = 16; - vb_gpio->gpiob.can_sleep = 1; + vb_gpio->gpiob.can_sleep = true; vb_gpio->gpiob.set = vprbrd_gpiob_set; vb_gpio->gpiob.get = vprbrd_gpiob_get; vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input; diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index cddfa22edb41..0fd23b6a753d 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c @@ -214,7 +214,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg) c->dbg_show = NULL; c->base = 0; c->ngpio = NR_VX855_GP; - c->can_sleep = 0; + c->can_sleep = false; c->names = vx855gpio_names; } diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 456000c5c457..b18a1a26425e 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -240,7 +240,7 @@ static struct gpio_chip template_chip = { .to_irq = wm831x_gpio_to_irq, .set_debounce = wm831x_gpio_set_debounce, .dbg_show = wm831x_gpio_dbg_show, - .can_sleep = 1, + .can_sleep = true, }; static int wm831x_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index fc49154be7b1..2487f9d575d3 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -106,7 +106,7 @@ static struct gpio_chip template_chip = { .direction_output = wm8350_gpio_direction_out, .set = wm8350_gpio_set, .to_irq = wm8350_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, }; static int wm8350_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index a53dbdefc7ee..d93b6b581677 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -242,7 +242,7 @@ static struct gpio_chip template_chip = { .set = wm8994_gpio_set, .to_irq = wm8994_gpio_to_irq, .dbg_show = wm8994_gpio_dbg_show, - .can_sleep = 1, + .can_sleep = true, }; static int wm8994_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c6326e44e2c0..94467ddb3711 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1051,7 +1051,7 @@ static void gpiochip_unexport(struct gpio_chip *chip) if (dev) { put_device(dev); device_unregister(dev); - chip->exported = 0; + chip->exported = false; status = 0; } else status = -ENODEV; diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c index 01bffc1d52fd..b80f1e150f53 100644 --- a/drivers/pinctrl/pinctrl-as3722.c +++ b/drivers/pinctrl/pinctrl-as3722.c @@ -531,7 +531,7 @@ static const struct gpio_chip as3722_gpio_chip = { .direction_input = as3722_gpio_direction_input, .direction_output = as3722_gpio_direction_output, .to_irq = as3722_gpio_to_irq, - .can_sleep = 1, + .can_sleep = true, .ngpio = AS3722_PIN_NUM, .base = -1, }; diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index a7549c4c83b4..943805185f3f 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1527,7 +1527,7 @@ static struct gpio_chip at91_gpio_template = { .set = at91_gpio_set, .to_irq = at91_gpio_to_irq, .dbg_show = at91_gpio_dbg_show, - .can_sleep = 0, + .can_sleep = false, .ngpio = MAX_NB_GPIO_PER_BANK, }; diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 2832576d8b12..31c8b3257a94 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -461,7 +461,7 @@ static int byt_gpio_probe(struct platform_device *pdev) gc->set = byt_gpio_set; gc->dbg_show = byt_gpio_dbg_show; gc->base = -1; - gc->can_sleep = 0; + gc->can_sleep = false; gc->dev = dev; ret = gpiochip_add(gc); diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index c05c1ef2cc3c..3d907de9bc91 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -384,7 +384,7 @@ static struct gpio_chip bcm2835_gpio_chip = { .to_irq = bcm2835_gpio_to_irq, .base = -1, .ngpio = BCM2835_NUM_GPIOS, - .can_sleep = 0, + .can_sleep = false, }; static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 7111c3b59130..a21820fc4b7c 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -904,7 +904,7 @@ static struct gpio_chip nmk_gpio_template = { .set = nmk_gpio_set_output, .to_irq = nmk_gpio_to_irq, .dbg_show = nmk_gpio_dbg_show, - .can_sleep = 0, + .can_sleep = false, }; void nmk_gpio_clocks_enable(void) diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c index 119d2ddedfe7..6b181cb90d39 100644 --- a/drivers/pinctrl/pinctrl-sunxi.c +++ b/drivers/pinctrl/pinctrl-sunxi.c @@ -547,7 +547,7 @@ static struct gpio_chip sunxi_pinctrl_gpio_chip = { .of_xlate = sunxi_pinctrl_gpio_of_xlate, .to_irq = sunxi_pinctrl_gpio_to_irq, .of_gpio_n_cells = 3, - .can_sleep = 0, + .can_sleep = false, }; static int sunxi_pinctrl_irq_set_type(struct irq_data *d, diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index 39aec0850810..b28d1af9c232 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -565,7 +565,7 @@ static struct gpio_chip wmt_gpio_chip = { .direction_output = wmt_gpio_direction_output, .get = wmt_gpio_get_value, .set = wmt_gpio_set_value, - .can_sleep = 0, + .can_sleep = false, }; int wmt_pinctrl_probe(struct platform_device *pdev, diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 656a27efb2c8..804ec45365b7 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -36,14 +36,15 @@ struct seq_file; * @ngpio: the number of GPIOs handled by this controller; the last GPIO * handled is (base + ngpio - 1). * @desc: array of ngpio descriptors. Private. - * @can_sleep: flag must be set iff get()/set() methods sleep, as they - * must while accessing GPIO expander chips over I2C or SPI * @names: if set, must be an array of strings to use as alternative * names for the GPIOs in this chip. Any entry in the array * may be NULL if there is no alias for the GPIO, however the * array must be @ngpio entries long. A name can include a single printk * format specifier for an unsigned int. It is substituted by the actual * number of the gpio. + * @can_sleep: flag must be set iff get()/set() methods sleep, as they + * must while accessing GPIO expander chips over I2C or SPI + * @exported: flags if the gpiochip is exported for use from sysfs. Private. * * A gpio_chip can help platforms abstract various sources of GPIOs so * they can all be accessed through a common programing interface. @@ -88,8 +89,8 @@ struct gpio_chip { u16 ngpio; struct gpio_desc *desc; const char *const *names; - unsigned can_sleep:1; - unsigned exported:1; + bool can_sleep; + bool exported; #if defined(CONFIG_OF_GPIO) /* -- cgit v1.2.3 From f41cd3c2876bd31e7c71908548ae3c7a5b7ff649 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Nov 2013 13:34:56 +0100 Subject: gpio: lock adnp IRQs when enabling them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Only compile tested on the lpc32xx. ChangeLog v2->v3: - Switch to using the startup()/shutdown() callbacks again. Still satisfy the mask/unmask semantics. ChangeLog v1->v2: - Use the .enable() callback from the irq_chip - Call .unmask() from the .enable() callback to satisfy semantics. Cc: Lars Poeschel Cc: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-adnp.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index b204033acaeb..a7b471977dc5 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -408,6 +408,27 @@ static void adnp_irq_bus_unlock(struct irq_data *data) mutex_unlock(&adnp->irq_lock); } +static unsigned int adnp_irq_startup(struct irq_data *data) +{ + struct adnp *adnp = irq_data_get_irq_chip_data(data); + + if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) + dev_err(adnp->gpio.dev, + "unable to lock HW IRQ %lu for IRQ\n", + data->hwirq); + /* Satisfy the .enable semantics by unmasking the line */ + adnp_irq_unmask(data); + return 0; +} + +static void adnp_irq_shutdown(struct irq_data *data) +{ + struct adnp *adnp = irq_data_get_irq_chip_data(data); + + adnp_irq_mask(data); + gpio_unlock_as_irq(&adnp->gpio, data->hwirq); +} + static struct irq_chip adnp_irq_chip = { .name = "gpio-adnp", .irq_mask = adnp_irq_mask, @@ -415,6 +436,8 @@ static struct irq_chip adnp_irq_chip = { .irq_set_type = adnp_irq_set_type, .irq_bus_lock = adnp_irq_bus_lock, .irq_bus_sync_unlock = adnp_irq_bus_unlock, + .irq_startup = adnp_irq_startup, + .irq_shutdown = adnp_irq_shutdown, }; static int adnp_irq_map(struct irq_domain *domain, unsigned int irq, -- cgit v1.2.3 From db6b3ad1772e0e0e82c52d6337378e79da2effad Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 19 Nov 2013 14:14:50 +0100 Subject: gpio: bcm-kona: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Cc: Christian Daudt Cc: Grygorii Strashko Reviewed-by: Markus Mayer Tested-by: Markus Mayer Reviewed-by: Javier Martinez Canillas Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bcm-kona.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 72c927dc3be1..3437414eaef2 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -449,12 +449,34 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) chained_irq_exit(chip, desc); } +static unsigned int bcm_kona_gpio_irq_startup(struct irq_data *d) +{ + struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) + dev_err(kona_gpio->gpio_chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + d->hwirq); + bcm_kona_gpio_irq_unmask(d); + return 0; +} + +static void bcm_kona_gpio_irq_shutdown(struct irq_data *d) +{ + struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); + + bcm_kona_gpio_irq_mask(d); + gpio_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq); +} + static struct irq_chip bcm_gpio_irq_chip = { .name = "bcm-kona-gpio", .irq_ack = bcm_kona_gpio_irq_ack, .irq_mask = bcm_kona_gpio_irq_mask, .irq_unmask = bcm_kona_gpio_irq_unmask, .irq_set_type = bcm_kona_gpio_irq_set_type, + .irq_startup = bcm_kona_gpio_irq_startup, + .irq_shutdown = bcm_kona_gpio_irq_shutdown, }; static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { -- cgit v1.2.3 From 0dc616236961e39e0fefecb4301f9e4632e4a511 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 10:16:54 +0100 Subject: gpio: em: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Also assign the gpio_chip.dev pointer to be used for error messages. ChangeLog v1->v2: - Satisfy implicit semantics by calling .enable and .disable callbacks in the startup/shutdown callbacks. Cc: Ian Molton Cc: Simon Horman Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index ec190361bf2e..1cc53516e8b4 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -99,6 +99,27 @@ static void em_gio_irq_enable(struct irq_data *d) em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d))); } +static unsigned int em_gio_irq_startup(struct irq_data *d) +{ + struct em_gio_priv *p = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) + dev_err(p->gpio_chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + em_gio_irq_enable(d); + return 0; +} + +static void em_gio_irq_shutdown(struct irq_data *d) +{ + struct em_gio_priv *p = irq_data_get_irq_chip_data(d); + + em_gio_irq_disable(d); + gpio_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d)); +} + + #define GIO_ASYNC(x) (x + 8) static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { @@ -328,6 +349,7 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->request = em_gio_request; gpio_chip->free = em_gio_free; gpio_chip->label = name; + gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = pdata->gpio_base; gpio_chip->ngpio = pdata->number_of_pins; @@ -339,6 +361,8 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_enable = em_gio_irq_enable; irq_chip->irq_disable = em_gio_irq_disable; irq_chip->irq_set_type = em_gio_irq_set_type; + irq_chip->irq_startup = em_gio_irq_startup; + irq_chip->irq_shutdown = em_gio_irq_shutdown; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, -- cgit v1.2.3 From aa6baa7e374dccbec619dcdd1291bc529a008051 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 15:24:32 +0100 Subject: gpio: intel-mid: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. ChangeLog v1->v2: - Explicitly call the - empty - mask/unmask functions from the startup/shutdown hooks. These are currently empty, but maybe they will not be that forever, so better be safe than sorry. Acked-by: David Cohen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-intel-mid.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index be803af658ac..039de0e6cf16 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -235,11 +235,33 @@ static void intel_mid_irq_mask(struct irq_data *d) { } +static unsigned int intel_mid_irq_startup(struct irq_data *d) +{ + struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) + dev_err(priv->chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + intel_mid_irq_unmask(d); + return 0; +} + +static void intel_mid_irq_shutdown(struct irq_data *d) +{ + struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); + + intel_mid_irq_mask(d); + gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d)); +} + static struct irq_chip intel_mid_irqchip = { .name = "INTEL_MID-GPIO", .irq_mask = intel_mid_irq_mask, .irq_unmask = intel_mid_irq_unmask, .irq_set_type = intel_mid_irq_type, + .irq_startup = intel_mid_irq_startup, + .irq_shutdown = intel_mid_irq_shutdown, }; static const struct intel_mid_gpio_ddata gpio_lincroft = { @@ -418,6 +440,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, priv->reg_base = pcim_iomap_table(pdev)[0]; priv->chip.label = dev_name(&pdev->dev); + priv->chip.dev = &pdev->dev; priv->chip.request = intel_gpio_request; priv->chip.direction_input = intel_gpio_direction_input; priv->chip.direction_output = intel_gpio_direction_output; -- cgit v1.2.3 From eb7cce1ea96b6399672abce787598f6e7a4352c3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 15:36:53 +0100 Subject: gpio: lynxpoint: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Cc: Mathias Nyman Tested-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lynxpoint.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index a0804740a0b7..70831e4b2c8b 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -301,6 +301,26 @@ static void lp_irq_disable(struct irq_data *d) spin_unlock_irqrestore(&lg->lock, flags); } +static unsigned int lp_irq_startup(struct irq_data *d) +{ + struct lp_gpio *lg = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) + dev_err(lg->chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + lp_irq_enable(d); + return 0; +} + +static void lp_irq_shutdown(struct irq_data *d) +{ + struct lp_gpio *lg = irq_data_get_irq_chip_data(d); + + lp_irq_disable(d); + gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d)); +} + static struct irq_chip lp_irqchip = { .name = "LP-GPIO", .irq_mask = lp_irq_mask, @@ -308,6 +328,8 @@ static struct irq_chip lp_irqchip = { .irq_enable = lp_irq_enable, .irq_disable = lp_irq_disable, .irq_set_type = lp_irq_type, + .irq_startup = lp_irq_startup, + .irq_shutdown = lp_irq_shutdown, .flags = IRQCHIP_SKIP_SET_WAKE, }; -- cgit v1.2.3 From 0d1430a3f4b7cfd8779b78740a4182321f3ca7f3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2013 14:52:06 +0000 Subject: drm/i915: Hold mutex across i915_gem_release Inorder to serialise the closing of the file descriptor and its subsequent release of client requests with i915_gem_free_request(), we need to hold the struct_mutex in i915_gem_release(). Failing to do so has the potential to trigger an OOPS, later with a use-after-free. Testcase: igt/gem_close_race Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70874 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71029 Reported-by: Eric Anholt Signed-off-by: Chris Wilson Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 ++ drivers/gpu/drm/i915/i915_gem_context.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d045135..ac9dac99b585 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1848,8 +1848,10 @@ void i915_driver_lastclose(struct drm_device * dev) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { + mutex_lock(&dev->struct_mutex); i915_gem_context_close(dev, file_priv); i915_gem_release(dev, file_priv); + mutex_unlock(&dev->struct_mutex); } void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 72a3df32292f..4a05956162c1 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -347,10 +347,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - mutex_lock(&dev->struct_mutex); idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_destroy(&file_priv->context_idr); - mutex_unlock(&dev->struct_mutex); } static struct i915_hw_context * -- cgit v1.2.3 From 4eadfc38c4d6e30775d3764f9a1a3098789d2acc Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 29 Oct 2013 20:51:04 +0100 Subject: omap3isp: Modify clocks registration to avoid circular references The clock core code is going to be modified so clk_get() takes reference on the clock provider module. Until the potential circular reference issue is properly addressed, we pass NULL as the first argument to clk_register(), in order to disallow sub-devices taking a reference on the ISP module back trough clk_get(). This should prevent locking the modules in memory. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Laurent Pinchart --- drivers/media/platform/omap3isp/isp.c | 22 ++++++++++++++++------ drivers/media/platform/omap3isp/isp.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1c3608039663..59106623e71e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -290,9 +290,11 @@ static int isp_xclk_init(struct isp_device *isp) struct clk_init_data init; unsigned int i; + for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) + isp->xclks[i].clk = ERR_PTR(-EINVAL); + for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { struct isp_xclk *xclk = &isp->xclks[i]; - struct clk *clk; xclk->isp = isp; xclk->id = i == 0 ? ISP_XCLK_A : ISP_XCLK_B; @@ -305,10 +307,15 @@ static int isp_xclk_init(struct isp_device *isp) init.num_parents = 1; xclk->hw.init = &init; - - clk = devm_clk_register(isp->dev, &xclk->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + /* + * The first argument is NULL in order to avoid circular + * reference, as this driver takes reference on the + * sensor subdevice modules and the sensors would take + * reference on this module through clk_get(). + */ + xclk->clk = clk_register(NULL, &xclk->hw); + if (IS_ERR(xclk->clk)) + return PTR_ERR(xclk->clk); if (pdata->xclks[i].con_id == NULL && pdata->xclks[i].dev_id == NULL) @@ -320,7 +327,7 @@ static int isp_xclk_init(struct isp_device *isp) xclk->lookup->con_id = pdata->xclks[i].con_id; xclk->lookup->dev_id = pdata->xclks[i].dev_id; - xclk->lookup->clk = clk; + xclk->lookup->clk = xclk->clk; clkdev_add(xclk->lookup); } @@ -335,6 +342,9 @@ static void isp_xclk_cleanup(struct isp_device *isp) for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { struct isp_xclk *xclk = &isp->xclks[i]; + if (!IS_ERR(xclk->clk)) + clk_unregister(xclk->clk); + if (xclk->lookup) clkdev_drop(xclk->lookup); } diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index ce65d3ae1aa7..d1e857e41731 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -135,6 +135,7 @@ struct isp_xclk { struct isp_device *isp; struct clk_hw hw; struct clk_lookup *lookup; + struct clk *clk; enum isp_xclk_id id; spinlock_t lock; /* Protects enabled and divider */ -- cgit v1.2.3 From d6782c263661abd6c7e8a375141d69fdc457f9e1 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 23 Aug 2013 17:03:43 +0200 Subject: clk: Provide not locked variant of of_clk_get_from_provider() Add helper functions for the of_clk_providers list locking and an unlocked variant of of_clk_get_from_provider(). These functions are intended to be used in the clkdev to avoid race condition in the device tree based clock look up in clk_get(). Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Russell King --- drivers/clk/clk.c | 38 ++++++++++++++++++++++++++++++-------- drivers/clk/clk.h | 16 ++++++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 drivers/clk/clk.h (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 77fcd069c64a..c687dc8d0b64 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -21,6 +21,8 @@ #include #include +#include "clk.h" + static DEFINE_SPINLOCK(enable_lock); static DEFINE_MUTEX(prepare_lock); @@ -2111,7 +2113,18 @@ static const struct of_device_id __clk_of_table_sentinel __used __section(__clk_of_table_end); static LIST_HEAD(of_clk_providers); -static DEFINE_MUTEX(of_clk_lock); +static DEFINE_MUTEX(of_clk_mutex); + +/* of_clk_provider list locking helpers */ +void of_clk_lock(void) +{ + mutex_lock(&of_clk_mutex); +} + +void of_clk_unlock(void) +{ + mutex_unlock(&of_clk_mutex); +} struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data) @@ -2155,9 +2168,9 @@ int of_clk_add_provider(struct device_node *np, cp->data = data; cp->get = clk_src_get; - mutex_lock(&of_clk_lock); + mutex_lock(&of_clk_mutex); list_add(&cp->link, &of_clk_providers); - mutex_unlock(&of_clk_lock); + mutex_unlock(&of_clk_mutex); pr_debug("Added clock from %s\n", np->full_name); return 0; @@ -2172,7 +2185,7 @@ void of_clk_del_provider(struct device_node *np) { struct of_clk_provider *cp; - mutex_lock(&of_clk_lock); + mutex_lock(&of_clk_mutex); list_for_each_entry(cp, &of_clk_providers, link) { if (cp->node == np) { list_del(&cp->link); @@ -2181,24 +2194,33 @@ void of_clk_del_provider(struct device_node *np) break; } } - mutex_unlock(&of_clk_lock); + mutex_unlock(&of_clk_mutex); } EXPORT_SYMBOL_GPL(of_clk_del_provider); -struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec) { struct of_clk_provider *provider; struct clk *clk = ERR_PTR(-ENOENT); /* Check if we have such a provider in our array */ - mutex_lock(&of_clk_lock); list_for_each_entry(provider, &of_clk_providers, link) { if (provider->node == clkspec->np) clk = provider->get(clkspec, provider->data); if (!IS_ERR(clk)) break; } - mutex_unlock(&of_clk_lock); + + return clk; +} + +struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +{ + struct clk *clk; + + mutex_lock(&of_clk_mutex); + clk = __of_clk_get_from_provider(clkspec); + mutex_unlock(&of_clk_mutex); return clk; } diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h new file mode 100644 index 000000000000..795cc9f0dac0 --- /dev/null +++ b/drivers/clk/clk.h @@ -0,0 +1,16 @@ +/* + * linux/drivers/clk/clk.h + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * Sylwester Nawrocki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) +struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec); +void of_clk_lock(void); +void of_clk_unlock(void); +#endif -- cgit v1.2.3 From 3a3d2b0551d79ef476ef57424beeb8f68789fbcd Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 23 Aug 2013 17:03:44 +0200 Subject: clkdev: Fix race condition in clock lookup from device tree There is currently a race condition in the device tree part of clk_get() function, since the pointer returned from of_clk_get_by_name() may become invalid before __clk_get() call. E.g. due to the clock provider driver remove() callback being called in between of_clk_get_by_name() and __clk_get(). Fix this by doing both the look up and __clk_get() operations with the clock providers list mutex held. This ensures that the clock pointer returned from __of_clk_get_from_provider() call and passed to __clk_get() is valid, as long as the clock supplier module first removes its clock provider instance and then does clk_unregister() on the corresponding clocks. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Reviewed-by: Mike Turquette Acked-by: Russell King --- drivers/clk/clkdev.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 442a31363873..48f67218247c 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -21,6 +21,8 @@ #include #include +#include "clk.h" + static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); @@ -39,7 +41,13 @@ struct clk *of_clk_get(struct device_node *np, int index) if (rc) return ERR_PTR(rc); - clk = of_clk_get_from_provider(&clkspec); + of_clk_lock(); + clk = __of_clk_get_from_provider(&clkspec); + + if (!IS_ERR(clk) && !__clk_get(clk)) + clk = ERR_PTR(-ENOENT); + + of_clk_unlock(); of_node_put(clkspec.np); return clk; } @@ -157,7 +165,7 @@ struct clk *clk_get(struct device *dev, const char *con_id) if (dev) { clk = of_clk_get_by_name(dev->of_node, con_id); - if (!IS_ERR(clk) && __clk_get(clk)) + if (!IS_ERR(clk)) return clk; } -- cgit v1.2.3 From ac2df527fb407b61f9c812a99035b62a75a77d6d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sat, 24 Aug 2013 20:10:41 +0200 Subject: clk: Add common __clk_get(), __clk_put() implementations This patch adds common __clk_get(), __clk_put() clkdev helpers that replace their platform specific counterparts when the common clock API is used. The owner module pointer field is added to struct clk so a reference to the clock supplier module can be taken by the clock consumers. The owner module is assigned while the clock is being registered, in functions _clk_register() and __clk_register(). Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Russell King --- arch/arm/include/asm/clkdev.h | 2 ++ arch/blackfin/include/asm/clkdev.h | 2 ++ arch/mips/include/asm/clkdev.h | 2 ++ arch/sh/include/asm/clkdev.h | 2 ++ drivers/clk/clk.c | 26 ++++++++++++++++++++++++++ include/linux/clk-private.h | 3 +++ include/linux/clkdev.h | 5 +++++ 7 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h index 80751c15c300..4e8a4b27d7c7 100644 --- a/arch/arm/include/asm/clkdev.h +++ b/arch/arm/include/asm/clkdev.h @@ -14,12 +14,14 @@ #include +#ifndef CONFIG_COMMON_CLK #ifdef CONFIG_HAVE_MACH_CLKDEV #include #else #define __clk_get(clk) ({ 1; }) #define __clk_put(clk) do { } while (0) #endif +#endif static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) { diff --git a/arch/blackfin/include/asm/clkdev.h b/arch/blackfin/include/asm/clkdev.h index 9053beda8c50..7ac2436856a5 100644 --- a/arch/blackfin/include/asm/clkdev.h +++ b/arch/blackfin/include/asm/clkdev.h @@ -8,7 +8,9 @@ static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) return kzalloc(size, GFP_KERNEL); } +#ifndef CONFIG_COMMON_CLK #define __clk_put(clk) #define __clk_get(clk) ({ 1; }) +#endif #endif diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h index 262475414e5f..1b3ad7b09dc1 100644 --- a/arch/mips/include/asm/clkdev.h +++ b/arch/mips/include/asm/clkdev.h @@ -14,8 +14,10 @@ #include +#ifndef CONFIG_COMMON_CLK #define __clk_get(clk) ({ 1; }) #define __clk_put(clk) do { } while (0) +#endif static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) { diff --git a/arch/sh/include/asm/clkdev.h b/arch/sh/include/asm/clkdev.h index 6ba91868201c..c41901465fb0 100644 --- a/arch/sh/include/asm/clkdev.h +++ b/arch/sh/include/asm/clkdev.h @@ -25,7 +25,9 @@ static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) return kzalloc(size, GFP_KERNEL); } +#ifndef CONFIG_COMMON_CLK #define __clk_put(clk) #define __clk_get(clk) ({ 1; }) +#endif #endif /* __CLKDEV_H__ */ diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c687dc8d0b64..baa2f66a7d19 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1813,6 +1813,10 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw) clk->flags = hw->init->flags; clk->parent_names = hw->init->parent_names; clk->num_parents = hw->init->num_parents; + if (dev && dev->driver) + clk->owner = dev->driver->owner; + else + clk->owner = NULL; ret = __clk_init(dev, clk); if (ret) @@ -1833,6 +1837,8 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) goto fail_name; } clk->ops = hw->init->ops; + if (dev && dev->driver) + clk->owner = dev->driver->owner; clk->hw = hw; clk->flags = hw->init->flags; clk->num_parents = hw->init->num_parents; @@ -1973,6 +1979,26 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) } EXPORT_SYMBOL_GPL(devm_clk_unregister); +/* + * clkdev helpers + */ +int __clk_get(struct clk *clk) +{ + if (clk && !try_module_get(clk->owner)) + return 0; + + return 1; +} + +void __clk_put(struct clk *clk) +{ + if (WARN_ON_ONCE(IS_ERR(clk))) + return; + + if (clk) + module_put(clk->owner); +} + /*** clk rate change notifiers ***/ /** diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index 8138c94409f3..8cb1865e7d9d 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -25,10 +25,13 @@ #ifdef CONFIG_COMMON_CLK +struct module; + struct clk { const char *name; const struct clk_ops *ops; struct clk_hw *hw; + struct module *owner; struct clk *parent; const char **parent_names; struct clk **parents; diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index a6a6f603103b..94bad77eeb4a 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h @@ -43,4 +43,9 @@ int clk_add_alias(const char *, const char *, char *, struct device *); int clk_register_clkdev(struct clk *, const char *, const char *, ...); int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t); +#ifdef CONFIG_COMMON_CLK +int __clk_get(struct clk *clk); +void __clk_put(struct clk *clk); +#endif + #endif -- cgit v1.2.3 From fcb0ee6a3d331fb23dbb546500021f6e4cac5689 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sat, 24 Aug 2013 15:00:10 +0200 Subject: clk: Implement clk_unregister clk_unregister() is currently not implemented and it is required when a clock provider module needs to be unloaded. Normally the clock supplier module is prevented to be unloaded by taking reference on the module in clk_get(). For cases when the clock supplier module deinitializes despite the consumers of its clocks holding a reference on the module, e.g. when the driver is unbound through "unbind" sysfs attribute, there are empty clock ops added. These ops are assigned temporarily to struct clk and used until all consumers release the clock, to avoid invoking callbacks from the module which just got removed. Signed-off-by: Jiada Wang Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park --- drivers/clk/clk.c | 121 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/clk-private.h | 2 + 2 files changed, 120 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index baa2f66a7d19..da7b33e4c5a2 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -345,6 +345,21 @@ out: return ret; } + /** + * clk_debug_unregister - remove a clk node from the debugfs clk tree + * @clk: the clk being removed from the debugfs clk tree + * + * Dynamically removes a clk and all it's children clk nodes from the + * debugfs clk tree if clk->dentry points to debugfs created by + * clk_debug_register in __clk_init. + * + * Caller must hold prepare_lock. + */ +static void clk_debug_unregister(struct clk *clk) +{ + debugfs_remove_recursive(clk->dentry); +} + /** * clk_debug_reparent - reparent clk node in the debugfs clk tree * @clk: the clk being reparented @@ -435,6 +450,9 @@ static inline int clk_debug_register(struct clk *clk) { return 0; } static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent) { } +static inline void clk_debug_unregister(struct clk *clk) +{ +} #endif /* caller must hold prepare_lock */ @@ -1778,6 +1796,7 @@ int __clk_init(struct device *dev, struct clk *clk) clk_debug_register(clk); + kref_init(&clk->ref); out: clk_prepare_unlock(); @@ -1913,13 +1932,104 @@ fail_out: } EXPORT_SYMBOL_GPL(clk_register); +/* + * Free memory allocated for a clock. + * Caller must hold prepare_lock. + */ +static void __clk_release(struct kref *ref) +{ + struct clk *clk = container_of(ref, struct clk, ref); + int i = clk->num_parents; + + kfree(clk->parents); + while (--i >= 0) + kfree(clk->parent_names[i]); + + kfree(clk->parent_names); + kfree(clk->name); + kfree(clk); +} + +/* + * Empty clk_ops for unregistered clocks. These are used temporarily + * after clk_unregister() was called on a clock and until last clock + * consumer calls clk_put() and the struct clk object is freed. + */ +static int clk_nodrv_prepare_enable(struct clk_hw *hw) +{ + return -ENXIO; +} + +static void clk_nodrv_disable_unprepare(struct clk_hw *hw) +{ + WARN_ON_ONCE(1); +} + +static int clk_nodrv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return -ENXIO; +} + +static int clk_nodrv_set_parent(struct clk_hw *hw, u8 index) +{ + return -ENXIO; +} + +static const struct clk_ops clk_nodrv_ops = { + .enable = clk_nodrv_prepare_enable, + .disable = clk_nodrv_disable_unprepare, + .prepare = clk_nodrv_prepare_enable, + .unprepare = clk_nodrv_disable_unprepare, + .set_rate = clk_nodrv_set_rate, + .set_parent = clk_nodrv_set_parent, +}; + /** * clk_unregister - unregister a currently registered clock * @clk: clock to unregister - * - * Currently unimplemented. */ -void clk_unregister(struct clk *clk) {} +void clk_unregister(struct clk *clk) +{ + unsigned long flags; + + if (!clk || WARN_ON_ONCE(IS_ERR(clk))) + return; + + clk_prepare_lock(); + + if (clk->ops == &clk_nodrv_ops) { + pr_err("%s: unregistered clock: %s\n", __func__, clk->name); + goto out; + } + /* + * Assign empty clock ops for consumers that might still hold + * a reference to this clock. + */ + flags = clk_enable_lock(); + clk->ops = &clk_nodrv_ops; + clk_enable_unlock(flags); + + if (!hlist_empty(&clk->children)) { + struct clk *child; + + /* Reparent all children to the orphan list. */ + hlist_for_each_entry(child, &clk->children, child_node) + clk_set_parent(child, NULL); + } + + clk_debug_unregister(clk); + + hlist_del_init(&clk->child_node); + + if (clk->prepare_count) + pr_warn("%s: unregistering prepared clock: %s\n", + __func__, clk->name); + + kref_put(&clk->ref, __clk_release); +out: + clk_prepare_unlock(); +} EXPORT_SYMBOL_GPL(clk_unregister); static void devm_clk_release(struct device *dev, void *res) @@ -1987,6 +2097,7 @@ int __clk_get(struct clk *clk) if (clk && !try_module_get(clk->owner)) return 0; + kref_get(&clk->ref); return 1; } @@ -1995,6 +2106,10 @@ void __clk_put(struct clk *clk) if (WARN_ON_ONCE(IS_ERR(clk))) return; + clk_prepare_lock(); + kref_put(&clk->ref, __clk_release); + clk_prepare_unlock(); + if (clk) module_put(clk->owner); } diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index 8cb1865e7d9d..72c65e05450b 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -12,6 +12,7 @@ #define __LINUX_CLK_PRIVATE_H #include +#include #include /* @@ -50,6 +51,7 @@ struct clk { #ifdef CONFIG_COMMON_CLK_DEBUG struct dentry *dentry; #endif + struct kref ref; }; /* -- cgit v1.2.3 From de49c285a3604955dcbf746edd871f2a4f128122 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 13 Oct 2013 08:00:26 -0300 Subject: [media] media: Check for active links on pads with MEDIA_PAD_FL_MUST_CONNECT flag Do not allow streaming if a pad with MEDIA_PAD_FL_MUST_CONNECT flag is not connected by an active link. This patch makes it possible to avoid drivers having to check for the most common case of link state validation: a sink pad that must be connected. Signed-off-by: Sakari Ailus Tested-by: Sylwester Nawrocki Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 2c286c307145..37c334edc7e8 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -235,6 +235,8 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, media_entity_graph_walk_start(&graph, entity); while ((entity = media_entity_graph_walk_next(&graph))) { + DECLARE_BITMAP(active, entity->num_pads); + DECLARE_BITMAP(has_no_links, entity->num_pads); unsigned int i; entity->stream_count++; @@ -248,21 +250,46 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, if (!entity->ops || !entity->ops->link_validate) continue; + bitmap_zero(active, entity->num_pads); + bitmap_fill(has_no_links, entity->num_pads); + for (i = 0; i < entity->num_links; i++) { struct media_link *link = &entity->links[i]; - - /* Is this pad part of an enabled link? */ - if (!(link->flags & MEDIA_LNK_FL_ENABLED)) - continue; - - /* Are we the sink or not? */ - if (link->sink->entity != entity) + struct media_pad *pad = link->sink->entity == entity + ? link->sink : link->source; + + /* Mark that a pad is connected by a link. */ + bitmap_clear(has_no_links, pad->index, 1); + + /* + * Pads that either do not need to connect or + * are connected through an enabled link are + * fine. + */ + if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) || + link->flags & MEDIA_LNK_FL_ENABLED) + bitmap_set(active, pad->index, 1); + + /* + * Link validation will only take place for + * sink ends of the link that are enabled. + */ + if (link->sink != pad || + !(link->flags & MEDIA_LNK_FL_ENABLED)) continue; ret = entity->ops->link_validate(link); if (ret < 0 && ret != -ENOIOCTLCMD) goto error; } + + /* Either no links or validated links are fine. */ + bitmap_or(active, active, has_no_links, entity->num_pads); + + if (!bitmap_full(active, entity->num_pads)) { + ret = -EPIPE; + goto error; + } } mutex_unlock(&mdev->graph_mutex); -- cgit v1.2.3 From 8dad936ab3e28b1fd396972c70f523d4b50dfcf4 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 2 Oct 2013 20:17:52 -0300 Subject: [media] omap3isp: Mark which pads must connect Mark pads that must be connected. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispccdc.c | 3 ++- drivers/media/platform/omap3isp/ispccp2.c | 3 ++- drivers/media/platform/omap3isp/ispcsi2.c | 3 ++- drivers/media/platform/omap3isp/isppreview.c | 3 ++- drivers/media/platform/omap3isp/ispresizer.c | 3 ++- drivers/media/platform/omap3isp/ispstat.c | 2 +- drivers/media/platform/omap3isp/ispvideo.c | 6 ++++-- 7 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index 907a205da5a5..561c991529e6 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -2484,7 +2484,8 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc) v4l2_set_subdevdata(sd, ccdc); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE; diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index e71651429dda..e84fe0543e47 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c @@ -1076,7 +1076,8 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2) v4l2_set_subdevdata(sd, ccp2); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; me->ops = &ccp2_media_ops; diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index 6db245d84bbb..620560828a48 100644 --- a/drivers/media/platform/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c @@ -1245,7 +1245,8 @@ static int csi2_init_entities(struct isp_csi2_device *csi2) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; me->ops = &csi2_media_ops; ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0); diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index cd8831aebdeb..1c776c1186f1 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -2283,7 +2283,8 @@ static int preview_init_entities(struct isp_prev_device *prev) v4l2_ctrl_handler_setup(&prev->ctrls); sd->ctrl_handler = &prev->ctrls; - pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; me->ops = &preview_media_ops; diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c index d11fb261d530..fa35f2cd64dd 100644 --- a/drivers/media/platform/omap3isp/ispresizer.c +++ b/drivers/media/platform/omap3isp/ispresizer.c @@ -1701,7 +1701,8 @@ static int resizer_init_entities(struct isp_res_device *res) v4l2_set_subdevdata(sd, res); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; me->ops = &resizer_media_ops; diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c index 61e17f9bd8b9..a75407c3a726 100644 --- a/drivers/media/platform/omap3isp/ispstat.c +++ b/drivers/media/platform/omap3isp/ispstat.c @@ -1067,7 +1067,7 @@ static int isp_stat_init_entities(struct ispstat *stat, const char *name, subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; v4l2_set_subdevdata(subdev, stat); - stat->pad.flags = MEDIA_PAD_FL_SINK; + stat->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; me->ops = NULL; return media_entity_init(me, 1, &stat->pad, 0); diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index a908d006f527..d45af5cc8109 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -1335,11 +1335,13 @@ int omap3isp_video_init(struct isp_video *video, const char *name) switch (video->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; + video->pad.flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: direction = "input"; - video->pad.flags = MEDIA_PAD_FL_SOURCE; + video->pad.flags = MEDIA_PAD_FL_SOURCE + | MEDIA_PAD_FL_MUST_CONNECT; video->video.vfl_dir = VFL_DIR_TX; break; -- cgit v1.2.3 From 2e1ab9cb94a257dcd7561601be44ca8b35b27365 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 2 Oct 2013 20:17:53 -0300 Subject: [media] omap3isp: Add resizer data rate configuration to resizer_link_validate The configuration of many other blocks depend on resizer maximum data rate. Get the value from resizer at link validation time. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispresizer.c | 15 ++++++++ drivers/media/platform/omap3isp/ispvideo.c | 54 ---------------------------- 2 files changed, 15 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c index fa35f2cd64dd..0d36b8bc9f98 100644 --- a/drivers/media/platform/omap3isp/ispresizer.c +++ b/drivers/media/platform/omap3isp/ispresizer.c @@ -1532,6 +1532,20 @@ static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return 0; } +static int resizer_link_validate(struct v4l2_subdev *sd, + struct media_link *link, + struct v4l2_subdev_format *source_fmt, + struct v4l2_subdev_format *sink_fmt) +{ + struct isp_res_device *res = v4l2_get_subdevdata(sd); + struct isp_pipeline *pipe = to_isp_pipeline(&sd->entity); + + omap3isp_resizer_max_rate(res, &pipe->max_rate); + + return v4l2_subdev_link_validate_default(sd, link, + source_fmt, sink_fmt); +} + /* * resizer_init_formats - Initialize formats on all pads * @sd: ISP resizer V4L2 subdevice @@ -1570,6 +1584,7 @@ static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = { .set_fmt = resizer_set_format, .get_selection = resizer_get_selection, .set_selection = resizer_set_selection, + .link_validate = resizer_link_validate, }; /* subdev operations */ diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index d45af5cc8109..9319e4d6c701 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -278,55 +278,6 @@ static int isp_video_get_graph_data(struct isp_video *video, return 0; } -/* - * Validate a pipeline by checking both ends of all links for format - * discrepancies. - * - * Compute the minimum time per frame value as the maximum of time per frame - * limits reported by every block in the pipeline. - * - * Return 0 if all formats match, or -EPIPE if at least one link is found with - * different formats on its two ends or if the pipeline doesn't start with a - * video source (either a subdev with no input pad, or a non-subdev entity). - */ -static int isp_video_validate_pipeline(struct isp_pipeline *pipe) -{ - struct isp_device *isp = pipe->output->isp; - struct media_pad *pad; - struct v4l2_subdev *subdev; - - subdev = isp_video_remote_subdev(pipe->output, NULL); - if (subdev == NULL) - return -EPIPE; - - while (1) { - /* Retrieve the sink format */ - pad = &subdev->entity.pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - - /* Update the maximum frame rate */ - if (subdev == &isp->isp_res.subdev) - omap3isp_resizer_max_rate(&isp->isp_res, - &pipe->max_rate); - - /* Retrieve the source format. Return an error if no source - * entity can be found, and stop checking the pipeline if the - * source entity isn't a subdev. - */ - pad = media_entity_remote_pad(pad); - if (pad == NULL) - return -EPIPE; - - if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - break; - - subdev = media_entity_to_v4l2_subdev(pad->entity); - } - - return 0; -} - static int __isp_video_get_format(struct isp_video *video, struct v4l2_format *format) { @@ -1054,11 +1005,6 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_check_format; - /* Validate the pipeline and update its state. */ - ret = isp_video_validate_pipeline(pipe); - if (ret < 0) - goto err_check_format; - pipe->error = false; spin_lock_irqsave(&pipe->lock, flags); -- cgit v1.2.3 From 8e6e8f93f7cb3452b1c00da8a30d01558628d913 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sat, 14 Sep 2013 18:39:04 -0300 Subject: [media] V4L: Add mem2mem ioctl and file operation helpers This patch adds ioctl helpers to the V4L2 mem-to-mem API, so we can avoid several ioctl handlers in the mem-to-mem video node drivers that are simply a pass-through to the v4l2_m2m_* calls. These helpers will only be useful for drivers that use same mutex for both OUTPUT and CAPTURE queue, which is the case for all currently in tree v4l2 m2m drivers. In order to use the helpers the drivers are required to use struct v4l2_fh. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mem2mem.c | 126 +++++++++++++++++++++++++++++++++ include/media/v4l2-fh.h | 4 ++ include/media/v4l2-mem2mem.h | 24 +++++++ 3 files changed, 154 insertions(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 73035ee0f4de..178ce96556c6 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -558,6 +558,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, if (m2m_ctx->m2m_dev->m2m_ops->unlock) m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv); + else if (m2m_ctx->q_lock) + mutex_unlock(m2m_ctx->q_lock); if (list_empty(&src_q->done_list)) poll_wait(file, &src_q->done_wq, wait); @@ -566,6 +568,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, if (m2m_ctx->m2m_dev->m2m_ops->lock) m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv); + else if (m2m_ctx->q_lock) + mutex_lock(m2m_ctx->q_lock); spin_lock_irqsave(&src_q->done_lock, flags); if (!list_empty(&src_q->done_list)) @@ -693,6 +697,13 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, if (ret) goto err; + /* + * If both queues use same mutex assign it as the common buffer + * queues lock to the m2m context. This lock is used in the + * v4l2_m2m_ioctl_* helpers. + */ + if (out_q_ctx->q.lock == cap_q_ctx->q.lock) + m2m_ctx->q_lock = out_q_ctx->q.lock; return m2m_ctx; err: @@ -740,3 +751,118 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb) } EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue); +/* Videobuf2 ioctl helpers */ + +int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_reqbufs(file, fh->m2m_ctx, rb); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_reqbufs); + +int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv, + struct v4l2_create_buffers *create) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_create_bufs(file, fh->m2m_ctx, create); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs); + +int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_querybuf(file, fh->m2m_ctx, buf); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_querybuf); + +int v4l2_m2m_ioctl_qbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_qbuf); + +int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_dqbuf); + +int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv, + struct v4l2_exportbuffer *eb) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_expbuf(file, fh->m2m_ctx, eb); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_expbuf); + +int v4l2_m2m_ioctl_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_streamon(file, fh->m2m_ctx, type); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamon); + +int v4l2_m2m_ioctl_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct v4l2_fh *fh = file->private_data; + + return v4l2_m2m_streamoff(file, fh->m2m_ctx, type); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamoff); + +/* + * v4l2_file_operations helpers. It is assumed here same lock is used + * for the output and the capture buffer queue. + */ + +int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct v4l2_fh *fh = file->private_data; + struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx; + int ret; + + if (m2m_ctx->q_lock && mutex_lock_interruptible(m2m_ctx->q_lock)) + return -ERESTARTSYS; + + ret = v4l2_m2m_mmap(file, m2m_ctx, vma); + + if (m2m_ctx->q_lock) + mutex_unlock(m2m_ctx->q_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap); + +unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait) +{ + struct v4l2_fh *fh = file->private_data; + struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx; + unsigned int ret; + + if (m2m_ctx->q_lock) + mutex_lock(m2m_ctx->q_lock); + + ret = v4l2_m2m_poll(file, m2m_ctx, wait); + + if (m2m_ctx->q_lock) + mutex_unlock(m2m_ctx->q_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_fop_poll); + diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h index 528cdaf622e1..803516775162 100644 --- a/include/media/v4l2-fh.h +++ b/include/media/v4l2-fh.h @@ -45,6 +45,10 @@ struct v4l2_fh { struct list_head available; /* Dequeueable event */ unsigned int navailable; u32 sequence; + +#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) + struct v4l2_m2m_ctx *m2m_ctx; +#endif }; /* diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 44542a20ab81..12ea5a6a4331 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -64,6 +64,9 @@ struct v4l2_m2m_queue_ctx { }; struct v4l2_m2m_ctx { + /* optional cap/out vb2 queues lock */ + struct mutex *q_lock; + /* private: internal use only */ struct v4l2_m2m_dev *m2m_dev; @@ -229,5 +232,26 @@ static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx); } +/* v4l2 ioctl helpers */ + +int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb); +int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh, + struct v4l2_create_buffers *create); +int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh, + struct v4l2_buffer *buf); +int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh, + struct v4l2_exportbuffer *eb); +int v4l2_m2m_ioctl_qbuf(struct file *file, void *fh, + struct v4l2_buffer *buf); +int v4l2_m2m_ioctl_dqbuf(struct file *file, void *fh, + struct v4l2_buffer *buf); +int v4l2_m2m_ioctl_streamon(struct file *file, void *fh, + enum v4l2_buf_type type); +int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh, + enum v4l2_buf_type type); +int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma); +unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait); + #endif /* _MEDIA_V4L2_MEM2MEM_H */ -- cgit v1.2.3 From 20702ebc2c3bd12235db90f3e0348698fe4c8fb5 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 25 Aug 2013 17:27:45 -0300 Subject: [media] mem2mem_testdev: Use mem-to-mem ioctl and vb2 helpers Simplify the driver by using the m2m ioctl and vb2 helpers. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Hans Verkuil Acked-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mem2mem_testdev.c | 152 ++++++------------------------- 1 file changed, 28 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 8df5975b700a..08e24379b794 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c @@ -177,8 +177,6 @@ struct m2mtest_ctx { enum v4l2_colorspace colorspace; - struct v4l2_m2m_ctx *m2m_ctx; - /* Source and destination queue data */ struct m2mtest_q_data q_data[2]; }; @@ -342,8 +340,8 @@ static int job_ready(void *priv) { struct m2mtest_ctx *ctx = priv; - if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < ctx->translen - || v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < ctx->translen) { + if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen + || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) { dprintk(ctx->dev, "Not enough buffers available\n"); return 0; } @@ -359,21 +357,6 @@ static void job_abort(void *priv) ctx->aborting = 1; } -static void m2mtest_lock(void *priv) -{ - struct m2mtest_ctx *ctx = priv; - struct m2mtest_dev *dev = ctx->dev; - mutex_lock(&dev->dev_mutex); -} - -static void m2mtest_unlock(void *priv) -{ - struct m2mtest_ctx *ctx = priv; - struct m2mtest_dev *dev = ctx->dev; - mutex_unlock(&dev->dev_mutex); -} - - /* device_run() - prepares and starts the device * * This simulates all the immediate preparations required before starting @@ -386,8 +369,8 @@ static void device_run(void *priv) struct m2mtest_dev *dev = ctx->dev; struct vb2_buffer *src_buf, *dst_buf; - src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); device_process(ctx, src_buf, dst_buf); @@ -409,8 +392,8 @@ static void device_isr(unsigned long priv) return; } - src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); - dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); + src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); curr_ctx->num_processed++; @@ -423,7 +406,7 @@ static void device_isr(unsigned long priv) || curr_ctx->aborting) { dprintk(curr_ctx->dev, "Finishing transaction\n"); curr_ctx->num_processed = 0; - v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx); + v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->fh.m2m_ctx); } else { device_run(curr_ctx); } @@ -491,7 +474,7 @@ static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) struct vb2_queue *vq; struct m2mtest_q_data *q_data; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -594,7 +577,7 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) struct m2mtest_q_data *q_data; struct vb2_queue *vq; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -648,52 +631,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, return ret; } -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - static int m2mtest_s_ctrl(struct v4l2_ctrl *ctrl) { struct m2mtest_ctx *ctx = @@ -748,14 +685,14 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = { .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; @@ -818,27 +755,15 @@ static int m2mtest_buf_prepare(struct vb2_buffer *vb) static void m2mtest_buf_queue(struct vb2_buffer *vb) { struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); -} - -static void m2mtest_wait_prepare(struct vb2_queue *q) -{ - struct m2mtest_ctx *ctx = vb2_get_drv_priv(q); - m2mtest_unlock(ctx); -} - -static void m2mtest_wait_finish(struct vb2_queue *q) -{ - struct m2mtest_ctx *ctx = vb2_get_drv_priv(q); - m2mtest_lock(ctx); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); } static struct vb2_ops m2mtest_qops = { .queue_setup = m2mtest_queue_setup, .buf_prepare = m2mtest_buf_prepare, .buf_queue = m2mtest_buf_queue, - .wait_prepare = m2mtest_wait_prepare, - .wait_finish = m2mtest_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) @@ -853,6 +778,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds src_vq->ops = &m2mtest_qops; src_vq->mem_ops = &vb2_vmalloc_memops; src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->dev->dev_mutex; ret = vb2_queue_init(src_vq); if (ret) @@ -865,6 +791,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds dst_vq->ops = &m2mtest_qops; dst_vq->mem_ops = &vb2_vmalloc_memops; dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->dev->dev_mutex; return vb2_queue_init(dst_vq); } @@ -936,10 +863,10 @@ static int m2mtest_open(struct file *file) ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC]; ctx->colorspace = V4L2_COLORSPACE_REC709; - ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - rc = PTR_ERR(ctx->m2m_ctx); + if (IS_ERR(ctx->fh.m2m_ctx)) { + rc = PTR_ERR(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(hdl); kfree(ctx); @@ -949,7 +876,8 @@ static int m2mtest_open(struct file *file) v4l2_fh_add(&ctx->fh); atomic_inc(&dev->num_inst); - dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); + dprintk(dev, "Created instance: %p, m2m_ctx: %p\n", + ctx, ctx->fh.m2m_ctx); open_unlock: mutex_unlock(&dev->dev_mutex); @@ -967,7 +895,7 @@ static int m2mtest_release(struct file *file) v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&dev->dev_mutex); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&dev->dev_mutex); kfree(ctx); @@ -976,34 +904,13 @@ static int m2mtest_release(struct file *file) return 0; } -static unsigned int m2mtest_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct m2mtest_ctx *ctx = file2ctx(file); - - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); -} - -static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct m2mtest_dev *dev = video_drvdata(file); - struct m2mtest_ctx *ctx = file2ctx(file); - int res; - - if (mutex_lock_interruptible(&dev->dev_mutex)) - return -ERESTARTSYS; - res = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - mutex_unlock(&dev->dev_mutex); - return res; -} - static const struct v4l2_file_operations m2mtest_fops = { .owner = THIS_MODULE, .open = m2mtest_open, .release = m2mtest_release, - .poll = m2mtest_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = m2mtest_mmap, + .mmap = v4l2_m2m_fop_mmap, }; static struct video_device m2mtest_videodev = { @@ -1019,8 +926,6 @@ static struct v4l2_m2m_ops m2m_ops = { .device_run = device_run, .job_ready = job_ready, .job_abort = job_abort, - .lock = m2mtest_lock, - .unlock = m2mtest_unlock, }; static int m2mtest_probe(struct platform_device *pdev) @@ -1133,4 +1038,3 @@ static int __init m2mtest_init(void) module_init(m2mtest_init); module_exit(m2mtest_exit); - -- cgit v1.2.3 From 43894d848a40075320898bc2bdfdd99c6d3b7b35 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 25 Aug 2013 16:55:58 -0300 Subject: [media] exynos4-is: Use mem-to-mem ioctl helpers Simplify the FIMC mem-to-mem driver by using the m2m ioctl and vb2 helpers. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Hans Verkuil Acked-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-core.h | 2 - drivers/media/platform/exynos4-is/fimc-m2m.c | 148 +++++--------------------- 2 files changed, 26 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index 3d376faec777..1790fb4e32ea 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -481,7 +481,6 @@ struct fimc_ctrls { * @flags: additional flags for image conversion * @state: flags to keep track of user configuration * @fimc_dev: the FIMC device this context applies to - * @m2m_ctx: memory-to-memory device context * @fh: v4l2 file handle * @ctrls: v4l2 controls structure */ @@ -502,7 +501,6 @@ struct fimc_ctx { u32 flags; u32 state; struct fimc_dev *fimc_dev; - struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_fh fh; struct fimc_ctrls ctrls; }; diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 8d33b68c76ba..9da95bd14820 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -44,17 +44,17 @@ void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state) { struct vb2_buffer *src_vb, *dst_vb; - if (!ctx || !ctx->m2m_ctx) + if (!ctx || !ctx->fh.m2m_ctx) return; - src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); if (src_vb && dst_vb) { v4l2_m2m_buf_done(src_vb, vb_state); v4l2_m2m_buf_done(dst_vb, vb_state); v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev, - ctx->m2m_ctx); + ctx->fh.m2m_ctx); } } @@ -123,12 +123,12 @@ static void fimc_device_run(void *priv) fimc_prepare_dma_offset(ctx, df); } - src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ret = fimc_prepare_addr(ctx, src_vb, sf, &sf->paddr); if (ret) goto dma_unlock; - dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ret = fimc_prepare_addr(ctx, dst_vb, df, &df->paddr); if (ret) goto dma_unlock; @@ -219,31 +219,15 @@ static int fimc_buf_prepare(struct vb2_buffer *vb) static void fimc_buf_queue(struct vb2_buffer *vb) { struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - - dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); - - if (ctx->m2m_ctx) - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); -} - -static void fimc_lock(struct vb2_queue *vq) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_lock(&ctx->fimc_dev->lock); -} - -static void fimc_unlock(struct vb2_queue *vq) -{ - struct fimc_ctx *ctx = vb2_get_drv_priv(vq); - mutex_unlock(&ctx->fimc_dev->lock); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); } static struct vb2_ops fimc_qops = { .queue_setup = fimc_queue_setup, .buf_prepare = fimc_buf_prepare, .buf_queue = fimc_buf_queue, - .wait_prepare = fimc_unlock, - .wait_finish = fimc_lock, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .stop_streaming = stop_streaming, .start_streaming = start_streaming, }; @@ -385,7 +369,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, if (ret) return ret; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (vb2_is_busy(vq)) { v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type); @@ -410,56 +394,6 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, return 0; } -static int fimc_m2m_reqbufs(struct file *file, void *fh, - struct v4l2_requestbuffers *reqbufs) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int fimc_m2m_querybuf(struct file *file, void *fh, - struct v4l2_buffer *buf) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int fimc_m2m_qbuf(struct file *file, void *fh, - struct v4l2_buffer *buf) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int fimc_m2m_dqbuf(struct file *file, void *fh, - struct v4l2_buffer *buf) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int fimc_m2m_expbuf(struct file *file, void *fh, - struct v4l2_exportbuffer *eb) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); -} - - -static int fimc_m2m_streamon(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int fimc_m2m_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - static int fimc_m2m_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cr) { @@ -598,13 +532,13 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = fimc_m2m_try_fmt_mplane, .vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane, .vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane, - .vidioc_reqbufs = fimc_m2m_reqbufs, - .vidioc_querybuf = fimc_m2m_querybuf, - .vidioc_qbuf = fimc_m2m_qbuf, - .vidioc_dqbuf = fimc_m2m_dqbuf, - .vidioc_expbuf = fimc_m2m_expbuf, - .vidioc_streamon = fimc_m2m_streamon, - .vidioc_streamoff = fimc_m2m_streamoff, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_g_crop = fimc_m2m_g_crop, .vidioc_s_crop = fimc_m2m_s_crop, .vidioc_cropcap = fimc_m2m_cropcap @@ -624,6 +558,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->fimc_dev->lock; ret = vb2_queue_init(src_vq); if (ret) @@ -636,6 +571,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->fimc_dev->lock; return vb2_queue_init(dst_vq); } @@ -708,9 +644,9 @@ static int fimc_m2m_open(struct file *file) ctx->out_path = FIMC_IO_DMA; ctx->scaler.enabled = 1; - ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - ret = PTR_ERR(ctx->m2m_ctx); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); goto error_c; } @@ -725,7 +661,7 @@ static int fimc_m2m_open(struct file *file) return 0; error_m2m_ctx: - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); error_c: fimc_ctrls_delete(ctx); error_fh: @@ -747,7 +683,7 @@ static int fimc_m2m_release(struct file *file) mutex_lock(&fimc->lock); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); fimc_ctrls_delete(ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); @@ -760,45 +696,13 @@ static int fimc_m2m_release(struct file *file) return 0; } -static unsigned int fimc_m2m_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); - struct fimc_dev *fimc = ctx->fimc_dev; - int ret; - - if (mutex_lock_interruptible(&fimc->lock)) - return -ERESTARTSYS; - - ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - mutex_unlock(&fimc->lock); - - return ret; -} - - -static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); - struct fimc_dev *fimc = ctx->fimc_dev; - int ret; - - if (mutex_lock_interruptible(&fimc->lock)) - return -ERESTARTSYS; - - ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - mutex_unlock(&fimc->lock); - - return ret; -} - static const struct v4l2_file_operations fimc_m2m_fops = { .owner = THIS_MODULE, .open = fimc_m2m_open, .release = fimc_m2m_release, - .poll = fimc_m2m_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = fimc_m2m_mmap, + .mmap = v4l2_m2m_fop_mmap, }; static struct v4l2_m2m_ops m2m_ops = { -- cgit v1.2.3 From 718cf4a9da22b2abf3d4f220b7a0a4e4a5b6287d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 25 Aug 2013 17:16:56 -0300 Subject: [media] s5p-jpeg: Use mem-to-mem ioctl helpers Simplify the driver by using the m2m ioctl and vb2 helpers. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Hans Verkuil Acked-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 134 +++++----------------------- drivers/media/platform/s5p-jpeg/jpeg-core.h | 2 - 2 files changed, 24 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 9b88a4601007..c818cbe6dd5d 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -316,9 +316,9 @@ static int s5p_jpeg_open(struct file *file) if (ret < 0) goto error; - ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - ret = PTR_ERR(ctx->m2m_ctx); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); goto error; } @@ -342,7 +342,7 @@ static int s5p_jpeg_release(struct file *file) struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); mutex_lock(&jpeg->lock); - v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&jpeg->lock); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_fh_del(&ctx->fh); @@ -352,39 +352,13 @@ static int s5p_jpeg_release(struct file *file) return 0; } -static unsigned int s5p_jpeg_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct s5p_jpeg *jpeg = video_drvdata(file); - struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); - unsigned int res; - - mutex_lock(&jpeg->lock); - res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - mutex_unlock(&jpeg->lock); - return res; -} - -static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct s5p_jpeg *jpeg = video_drvdata(file); - struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); - int ret; - - if (mutex_lock_interruptible(&jpeg->lock)) - return -ERESTARTSYS; - ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - mutex_unlock(&jpeg->lock); - return ret; -} - static const struct v4l2_file_operations s5p_jpeg_fops = { .owner = THIS_MODULE, .open = s5p_jpeg_open, .release = s5p_jpeg_release, - .poll = s5p_jpeg_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = s5p_jpeg_mmap, + .mmap = v4l2_m2m_fop_mmap, }; /* @@ -589,7 +563,7 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) struct v4l2_pix_format *pix = &f->fmt.pix; struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); - vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -745,7 +719,7 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) struct s5p_jpeg_q_data *q_data = NULL; struct v4l2_pix_format *pix = &f->fmt.pix; - vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; @@ -792,53 +766,6 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); } -static int s5p_jpeg_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int s5p_jpeg_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int s5p_jpeg_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - -static int s5p_jpeg_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int s5p_jpeg_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - static int s5p_jpeg_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { @@ -972,14 +899,13 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap, .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out, - .vidioc_reqbufs = s5p_jpeg_reqbufs, - .vidioc_querybuf = s5p_jpeg_querybuf, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, - .vidioc_qbuf = s5p_jpeg_qbuf, - .vidioc_dqbuf = s5p_jpeg_dqbuf, - - .vidioc_streamon = s5p_jpeg_streamon, - .vidioc_streamoff = s5p_jpeg_streamoff, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_g_selection = s5p_jpeg_g_selection, }; @@ -997,8 +923,8 @@ static void s5p_jpeg_device_run(void *priv) struct vb2_buffer *src_buf, *dst_buf; unsigned long src_addr, dst_addr; - src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); @@ -1170,22 +1096,8 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) ); q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; } - if (ctx->m2m_ctx) - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); -} - -static void s5p_jpeg_wait_prepare(struct vb2_queue *vq) -{ - struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq); - - mutex_unlock(&ctx->jpeg->lock); -} - -static void s5p_jpeg_wait_finish(struct vb2_queue *vq) -{ - struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq); - mutex_lock(&ctx->jpeg->lock); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); } static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) @@ -1211,8 +1123,8 @@ static struct vb2_ops s5p_jpeg_qops = { .queue_setup = s5p_jpeg_queue_setup, .buf_prepare = s5p_jpeg_buf_prepare, .buf_queue = s5p_jpeg_buf_queue, - .wait_prepare = s5p_jpeg_wait_prepare, - .wait_finish = s5p_jpeg_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, .start_streaming = s5p_jpeg_start_streaming, .stop_streaming = s5p_jpeg_stop_streaming, }; @@ -1230,6 +1142,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->ops = &s5p_jpeg_qops; src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->jpeg->lock; ret = vb2_queue_init(src_vq); if (ret) @@ -1242,6 +1155,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->ops = &s5p_jpeg_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->jpeg->lock; return vb2_queue_init(dst_vq); } @@ -1267,8 +1181,8 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); - src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); - dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); + src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); if (curr_ctx->mode == S5P_JPEG_ENCODE) enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs); @@ -1296,7 +1210,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) if (curr_ctx->mode == S5P_JPEG_ENCODE) vb2_set_plane_payload(dst_buf, 0, payload_size); v4l2_m2m_buf_done(dst_buf, state); - v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); + v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx); curr_ctx->subsampling = jpeg_get_subsampling_mode(jpeg->regs); spin_unlock(&jpeg->slock); diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 8a4013e3aee7..4a4776b7e1d4 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h @@ -115,7 +115,6 @@ struct s5p_jpeg_q_data { * @jpeg: JPEG IP device for this context * @mode: compression (encode) operation or decompression (decode) * @compr_quality: destination image quality in compression (encode) mode - * @m2m_ctx: mem2mem device context * @out_q: source (output) queue information * @cap_fmt: destination (capture) queue queue information * @hdr_parsed: set if header has been parsed during decompression @@ -127,7 +126,6 @@ struct s5p_jpeg_ctx { unsigned short compr_quality; unsigned short restart_interval; unsigned short subsampling; - struct v4l2_m2m_ctx *m2m_ctx; struct s5p_jpeg_q_data out_q; struct s5p_jpeg_q_data cap_q; struct v4l2_fh fh; -- cgit v1.2.3 From febeaa45a692e93275b166e6a6f5852a46196ec9 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 25 Aug 2013 18:13:17 -0300 Subject: [media] s5p-g2d: Use mem-to-mem ioctl helpers Simplify the driver by using the m2m ioctl and vb2 helpers. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Hans Verkuil Acked-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-g2d/g2d.c | 124 ++++++----------------------------- drivers/media/platform/s5p-g2d/g2d.h | 1 - 2 files changed, 21 insertions(+), 104 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 0b2948376aee..0fcf7d75e841 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -136,10 +136,9 @@ static int g2d_buf_prepare(struct vb2_buffer *vb) static void g2d_buf_queue(struct vb2_buffer *vb) { struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); } - static struct vb2_ops g2d_qops = { .queue_setup = g2d_queue_setup, .buf_prepare = g2d_buf_prepare, @@ -159,6 +158,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->dev->mutex; ret = vb2_queue_init(src_vq); if (ret) @@ -171,6 +171,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->dev->mutex; return vb2_queue_init(dst_vq); } @@ -253,9 +254,9 @@ static int g2d_open(struct file *file) kfree(ctx); return -ERESTARTSYS; } - ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); - if (IS_ERR(ctx->m2m_ctx)) { - ret = PTR_ERR(ctx->m2m_ctx); + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); mutex_unlock(&dev->mutex); kfree(ctx); return ret; @@ -324,7 +325,7 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) struct vb2_queue *vq; struct g2d_frame *frm; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; frm = get_frame(ctx, f->type); @@ -384,7 +385,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) ret = vidioc_try_fmt(file, prv, f); if (ret) return ret; - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (vb2_is_busy(vq)) { v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type); return -EBUSY; @@ -410,72 +411,6 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait) -{ - struct g2d_ctx *ctx = fh2ctx(file->private_data); - struct g2d_dev *dev = ctx->dev; - unsigned int res; - - mutex_lock(&dev->mutex); - res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - mutex_unlock(&dev->mutex); - return res; -} - -static int g2d_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct g2d_ctx *ctx = fh2ctx(file->private_data); - struct g2d_dev *dev = ctx->dev; - int ret; - - if (mutex_lock_interruptible(&dev->mutex)) - return -ERESTARTSYS; - ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - mutex_unlock(&dev->mutex); - return ret; -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) -{ - struct g2d_ctx *ctx = priv; - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct g2d_ctx *ctx = priv; - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct g2d_ctx *ctx = priv; - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct g2d_ctx *ctx = priv; - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -} - - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct g2d_ctx *ctx = priv; - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct g2d_ctx *ctx = priv; - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -} - static int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cr) { @@ -551,20 +486,6 @@ static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *c return 0; } -static void g2d_lock(void *prv) -{ - struct g2d_ctx *ctx = prv; - struct g2d_dev *dev = ctx->dev; - mutex_lock(&dev->mutex); -} - -static void g2d_unlock(void *prv) -{ - struct g2d_ctx *ctx = prv; - struct g2d_dev *dev = ctx->dev; - mutex_unlock(&dev->mutex); -} - static void job_abort(void *prv) { struct g2d_ctx *ctx = prv; @@ -589,8 +510,8 @@ static void device_run(void *prv) dev->curr = ctx; - src = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); clk_enable(dev->gate); g2d_reset(dev); @@ -631,8 +552,8 @@ static irqreturn_t g2d_isr(int irq, void *prv) BUG_ON(ctx == NULL); - src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); BUG_ON(src == NULL); BUG_ON(dst == NULL); @@ -642,7 +563,7 @@ static irqreturn_t g2d_isr(int irq, void *prv) v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); - v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); + v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx); dev->curr = NULL; wake_up(&dev->irq_queue); @@ -653,9 +574,9 @@ static const struct v4l2_file_operations g2d_fops = { .owner = THIS_MODULE, .open = g2d_open, .release = g2d_release, - .poll = g2d_poll, + .poll = v4l2_m2m_fop_poll, .unlocked_ioctl = video_ioctl2, - .mmap = g2d_mmap, + .mmap = v4l2_m2m_fop_mmap, }; static const struct v4l2_ioctl_ops g2d_ioctl_ops = { @@ -671,14 +592,13 @@ static const struct v4l2_ioctl_ops g2d_ioctl_ops = { .vidioc_try_fmt_vid_out = vidioc_try_fmt, .vidioc_s_fmt_vid_out = vidioc_s_fmt, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_g_crop = vidioc_g_crop, .vidioc_s_crop = vidioc_s_crop, @@ -697,8 +617,6 @@ static struct video_device g2d_videodev = { static struct v4l2_m2m_ops g2d_m2m_ops = { .device_run = device_run, .job_abort = job_abort, - .lock = g2d_lock, - .unlock = g2d_unlock, }; static const struct of_device_id exynos_g2d_match[]; diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h index 300ca05ba404..b0e52ab7ecdb 100644 --- a/drivers/media/platform/s5p-g2d/g2d.h +++ b/drivers/media/platform/s5p-g2d/g2d.h @@ -57,7 +57,6 @@ struct g2d_frame { struct g2d_ctx { struct v4l2_fh fh; struct g2d_dev *dev; - struct v4l2_m2m_ctx *m2m_ctx; struct g2d_frame in; struct g2d_frame out; struct v4l2_ctrl *ctrl_hflip; -- cgit v1.2.3 From 0495d405f319171ac1cb6276019fc49a382fa295 Mon Sep 17 00:00:00 2001 From: Mateusz Krawczuk Date: Sat, 21 Sep 2013 11:00:47 -0300 Subject: [media] s5p-tv: sdo: Restore vpll clock rate after streamoff Restore vpll clock rate if start stream fail or stream is off. Signed-off-by: Mateusz Krawczuk Signed-off-by: Kyungmin Park [s.nawrocki@samsung.com: fixed whitespace error reported by checkpath.pl] Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/sdo_drv.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c index 0afa90f0f6ab..fbc6d7ae7297 100644 --- a/drivers/media/platform/s5p-tv/sdo_drv.c +++ b/drivers/media/platform/s5p-tv/sdo_drv.c @@ -55,6 +55,8 @@ struct sdo_device { struct clk *dacphy; /** clock for control of VPLL */ struct clk *fout_vpll; + /** vpll rate before sdo stream was on */ + unsigned long vpll_rate; /** regulator for SDO IP power */ struct regulator *vdac; /** regulator for SDO plug detection */ @@ -193,17 +195,33 @@ static int sdo_s_power(struct v4l2_subdev *sd, int on) static int sdo_streamon(struct sdo_device *sdev) { + int ret; + /* set proper clock for Timing Generator */ - clk_set_rate(sdev->fout_vpll, 54000000); + sdev->vpll_rate = clk_get_rate(sdev->fout_vpll); + ret = clk_set_rate(sdev->fout_vpll, 54000000); + if (ret < 0) { + dev_err(sdev->dev, "Failed to set vpll rate\n"); + return ret; + } dev_info(sdev->dev, "fout_vpll.rate = %lu\n", clk_get_rate(sdev->fout_vpll)); /* enable clock in SDO */ sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON); - clk_enable(sdev->dacphy); + ret = clk_enable(sdev->dacphy); + if (ret < 0) { + dev_err(sdev->dev, "clk_enable(dacphy) failed\n"); + goto fail; + } /* enable DAC */ sdo_write_mask(sdev, SDO_DAC, ~0, SDO_POWER_ON_DAC); sdo_reg_debug(sdev); return 0; + +fail: + sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); + clk_set_rate(sdev->fout_vpll, sdev->vpll_rate); + return ret; } static int sdo_streamoff(struct sdo_device *sdev) @@ -220,6 +238,7 @@ static int sdo_streamoff(struct sdo_device *sdev) } if (tries == 0) dev_err(sdev->dev, "failed to stop streaming\n"); + clk_set_rate(sdev->fout_vpll, sdev->vpll_rate); return tries ? 0 : -EIO; } -- cgit v1.2.3 From a889c11519b425dce284c6233cfb4629f519ccac Mon Sep 17 00:00:00 2001 From: Mateusz Krawczuk Date: Sat, 21 Sep 2013 11:00:48 -0300 Subject: [media] s5p-tv: sdo: Prepare for common clock framework Replace clk_enable() by clock_enable_prepare() and clk_disable() with clk_disable_unprepare(). clk_{prepare/unprepare} calls are required by common clock framework and this driver was missed while converting all users of the Samsung original clocks driver to its new implementation based on the common clock API. Signed-off-by: Mateusz Krawczuk Signed-off-by: Kyungmin Park [s.nawrocki@samsung.com: edited commit description] Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/sdo_drv.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c index fbc6d7ae7297..5a7c3796f22e 100644 --- a/drivers/media/platform/s5p-tv/sdo_drv.c +++ b/drivers/media/platform/s5p-tv/sdo_drv.c @@ -208,9 +208,9 @@ static int sdo_streamon(struct sdo_device *sdev) clk_get_rate(sdev->fout_vpll)); /* enable clock in SDO */ sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON); - ret = clk_enable(sdev->dacphy); + ret = clk_prepare_enable(sdev->dacphy); if (ret < 0) { - dev_err(sdev->dev, "clk_enable(dacphy) failed\n"); + dev_err(sdev->dev, "clk_prepare_enable(dacphy) failed\n"); goto fail; } /* enable DAC */ @@ -229,7 +229,7 @@ static int sdo_streamoff(struct sdo_device *sdev) int tries; sdo_write_mask(sdev, SDO_DAC, 0, SDO_POWER_ON_DAC); - clk_disable(sdev->dacphy); + clk_disable_unprepare(sdev->dacphy); sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); for (tries = 100; tries; --tries) { if (sdo_read(sdev, SDO_CLKCON) & SDO_TVOUT_CLOCK_READY) @@ -273,7 +273,7 @@ static int sdo_runtime_suspend(struct device *dev) dev_info(dev, "suspend\n"); regulator_disable(sdev->vdet); regulator_disable(sdev->vdac); - clk_disable(sdev->sclk_dac); + clk_disable_unprepare(sdev->sclk_dac); return 0; } @@ -285,7 +285,7 @@ static int sdo_runtime_resume(struct device *dev) dev_info(dev, "resume\n"); - ret = clk_enable(sdev->sclk_dac); + ret = clk_prepare_enable(sdev->sclk_dac); if (ret < 0) return ret; @@ -318,7 +318,7 @@ static int sdo_runtime_resume(struct device *dev) vdac_r_dis: regulator_disable(sdev->vdac); dac_clk_dis: - clk_disable(sdev->sclk_dac); + clk_disable_unprepare(sdev->sclk_dac); return ret; } @@ -424,7 +424,11 @@ static int sdo_probe(struct platform_device *pdev) } /* enable gate for dac clock, because mixer uses it */ - clk_enable(sdev->dac); + ret = clk_prepare_enable(sdev->dac); + if (ret < 0) { + dev_err(dev, "clk_prepare_enable(dac) failed\n"); + goto fail_fout_vpll; + } /* configure power management */ pm_runtime_enable(dev); @@ -463,7 +467,7 @@ static int sdo_remove(struct platform_device *pdev) struct sdo_device *sdev = sd_to_sdev(sd); pm_runtime_disable(&pdev->dev); - clk_disable(sdev->dac); + clk_disable_unprepare(sdev->dac); clk_put(sdev->fout_vpll); clk_put(sdev->dacphy); clk_put(sdev->dac); -- cgit v1.2.3 From 03ce1a13ccdfa61bf8f3bdcc7f10e2580db71149 Mon Sep 17 00:00:00 2001 From: Mateusz Krawczuk Date: Sat, 21 Sep 2013 11:00:49 -0300 Subject: [media] s5p-tv: mixer: Prepare for common clock framework Replace clk_enable() by clock_enable_prepare() and clk_disable() with clk_disable_unprepare(). clk_{prepare/unprepare} calls are required by common clock framework and this driver was missed while converting all users of the Samsung original clocks driver to its new implementation based on the common clock API. Signed-off-by: Mateusz Krawczuk Signed-off-by: Kyungmin Park Acked-by: Tomasz Stanislawski [s.nawrocki@samsung.com: edited commit description] Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer_drv.c | 34 +++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index 51805a5e2beb..bc08b5f28e44 100644 --- a/drivers/media/platform/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -347,19 +347,41 @@ static int mxr_runtime_resume(struct device *dev) { struct mxr_device *mdev = to_mdev(dev); struct mxr_resources *res = &mdev->res; + int ret; mxr_dbg(mdev, "resume - start\n"); mutex_lock(&mdev->mutex); /* turn clocks on */ - clk_enable(res->mixer); - clk_enable(res->vp); - clk_enable(res->sclk_mixer); + ret = clk_prepare_enable(res->mixer); + if (ret < 0) { + dev_err(mdev->dev, "clk_prepare_enable(mixer) failed\n"); + goto fail; + } + ret = clk_prepare_enable(res->vp); + if (ret < 0) { + dev_err(mdev->dev, "clk_prepare_enable(vp) failed\n"); + goto fail_mixer; + } + ret = clk_prepare_enable(res->sclk_mixer); + if (ret < 0) { + dev_err(mdev->dev, "clk_prepare_enable(sclk_mixer) failed\n"); + goto fail_vp; + } /* apply default configuration */ mxr_reg_reset(mdev); mxr_dbg(mdev, "resume - finished\n"); mutex_unlock(&mdev->mutex); return 0; + +fail_vp: + clk_disable_unprepare(res->vp); +fail_mixer: + clk_disable_unprepare(res->mixer); +fail: + mutex_unlock(&mdev->mutex); + dev_err(mdev->dev, "resume failed\n"); + return ret; } static int mxr_runtime_suspend(struct device *dev) @@ -369,9 +391,9 @@ static int mxr_runtime_suspend(struct device *dev) mxr_dbg(mdev, "suspend - start\n"); mutex_lock(&mdev->mutex); /* turn clocks off */ - clk_disable(res->sclk_mixer); - clk_disable(res->vp); - clk_disable(res->mixer); + clk_disable_unprepare(res->sclk_mixer); + clk_disable_unprepare(res->vp); + clk_disable_unprepare(res->mixer); mutex_unlock(&mdev->mutex); mxr_dbg(mdev, "suspend - finished\n"); return 0; -- cgit v1.2.3 From e1163236f5214e3447f1132a355a26db3db7d9f3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Nov 2013 06:52:24 -0300 Subject: [media] exynos4-is: Cleanup a define in mipi-csis driver This define is only used in s5pcsis_irq_handler(): if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) { The problem is that "status" is a 32 bit and (0xff << 28) is larger than 32 bits and that sets off a static checker warning. I consulted with Sylwester Nawrocki and the define should actually be (0xf << 28). Signed-off-by: Dan Carpenter Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/mipi-csis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 9fc2af6a0446..31dfc5015247 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -91,7 +91,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define S5PCSIS_INTSRC_ODD_BEFORE (1 << 29) #define S5PCSIS_INTSRC_ODD_AFTER (1 << 28) #define S5PCSIS_INTSRC_ODD (0x3 << 28) -#define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xff << 28) +#define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xf << 28) #define S5PCSIS_INTSRC_FRAME_START (1 << 27) #define S5PCSIS_INTSRC_FRAME_END (1 << 26) #define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12) -- cgit v1.2.3 From b1fbe051c1ff608eaab3d46cf38be03ac374294b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 13 Oct 2013 07:50:40 -0300 Subject: [media] exynos4-is: fimc-lite: Index out of bounds if no pixelcode found In case no valid pixelcode is found, an i of -1 after the loop is out of bounds for the array. Signed-off-by: Roel Kluin Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite-reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c index 72a343e3b5e8..d0dc7ee04452 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c @@ -133,7 +133,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) int i = ARRAY_SIZE(src_pixfmt_map); u32 cfg; - while (--i >= 0) { + while (--i) { if (src_pixfmt_map[i][0] == pixelcode) break; } @@ -240,7 +240,7 @@ static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); int i = ARRAY_SIZE(pixcode); - while (--i >= 0) + while (--i) if (pixcode[i][0] == f->fmt->mbus_code) break; cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK; -- cgit v1.2.3 From 3f823e094b935c1882605f8720336ee23433a16d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 18 Oct 2013 11:14:32 -0300 Subject: [media] exynos4-is: Simplify fimc-is hardware polling helpers The fimc_is_hw_wait_intsr0_intsd0() function is currently unused and can be safely removed. The other polling function simplified and ETIME error code is replaced with more commonly used ETIMEDOUT. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-is-regs.c | 36 ++++-------------------- drivers/media/platform/exynos4-is/fimc-is-regs.h | 1 - 2 files changed, 6 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c index f758e2694fa3..2628733c4e10 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c @@ -33,47 +33,23 @@ void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is) mcuctl_write(INTGR0_INTGD(0), is, MCUCTL_REG_INTGR0); } -int fimc_is_hw_wait_intsr0_intsd0(struct fimc_is *is) -{ - unsigned int timeout = 2000; - u32 cfg, status; - - cfg = mcuctl_read(is, MCUCTL_REG_INTSR0); - status = INTSR0_GET_INTSD(0, cfg); - - while (status) { - cfg = mcuctl_read(is, MCUCTL_REG_INTSR0); - status = INTSR0_GET_INTSD(0, cfg); - if (timeout == 0) { - dev_warn(&is->pdev->dev, "%s timeout\n", - __func__); - return -ETIME; - } - timeout--; - udelay(1); - } - return 0; -} - int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is) { unsigned int timeout = 2000; u32 cfg, status; - cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0); - status = INTMSR0_GET_INTMSD(0, cfg); - - while (status) { + do { cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0); status = INTMSR0_GET_INTMSD(0, cfg); - if (timeout == 0) { + + if (--timeout == 0) { dev_warn(&is->pdev->dev, "%s timeout\n", __func__); - return -ETIME; + return -ETIMEDOUT; } - timeout--; udelay(1); - } + } while (status != 0); + return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.h b/drivers/media/platform/exynos4-is/fimc-is-regs.h index 5fa2fda46742..1d9d4ffc6ad5 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.h +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.h @@ -145,7 +145,6 @@ void fimc_is_fw_clear_irq2(struct fimc_is *is); int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num); void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is); -int fimc_is_hw_wait_intsr0_intsd0(struct fimc_is *is); int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is); void fimc_is_hw_set_sensor_num(struct fimc_is *is); void fimc_is_hw_stream_on(struct fimc_is *is); -- cgit v1.2.3 From cdf64eeeb0d762585e2126f3024458d199c2635d Mon Sep 17 00:00:00 2001 From: Chander Kashyap Date: Thu, 26 Sep 2013 14:36:35 +0530 Subject: clk: exynos5420: fix cpll clock register offsets Fixes cpll control and lock register offset values for Exynos5420 SoC. Signed-off-by: Chander Kashyap Acked-by: Kukjin Kim Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5420.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 48c4a9350b91..87ea79633862 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -737,8 +737,8 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { [apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), - [cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, - MPLL_CON0, NULL), + [cpll] = PLL(pll_2550, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK, + CPLL_CON0, NULL), [dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK, DPLL_CON0, NULL), [epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, -- cgit v1.2.3 From 105353145eafb3ea919f5cdeb652a9d8f270228e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Tue, 3 Dec 2013 14:52:00 +0100 Subject: OF: base: match each node compatible against all given matches first Currently, of_match_node compares each given match against all node's compatible strings with of_device_is_compatible. To achieve multiple compatible strings per node with ordering from specific to generic, this requires given matches to be ordered from specific to generic. For most of the drivers this is not true and also an alphabetical ordering is more sane there. Therefore, this patch modifies of_match_node to match each of the node's compatible strings against all given matches first, before checking the next compatible string. This implies that node's compatibles are ordered from specific to generic while given matches can be in any order. Signed-off-by: Sebastian Hesselbarth Tested-by: Meelis Roos Signed-off-by: Rob Herring --- drivers/of/base.c | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0edabf3..8d007d8b8c78 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -731,24 +731,42 @@ static const struct of_device_id *__of_match_node(const struct of_device_id *matches, const struct device_node *node) { + const char *cp; + int cplen, l; + if (!matches) return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= node->name - && !strcmp(matches->name, node->name); - if (matches->type[0]) - match &= node->type - && !strcmp(matches->type, node->type); - if (matches->compatible[0]) - match &= __of_device_is_compatible(node, - matches->compatible); - if (match) - return matches; - matches++; - } + cp = __of_get_property(node, "compatible", &cplen); + do { + const struct of_device_id *m = matches; + + /* Check against matches with current compatible string */ + while (m->name[0] || m->type[0] || m->compatible[0]) { + int match = 1; + if (m->name[0]) + match &= node->name + && !strcmp(m->name, node->name); + if (m->type[0]) + match &= node->type + && !strcmp(m->type, node->type); + if (m->compatible[0]) + match &= cp + && !of_compat_cmp(m->compatible, cp, + strlen(m->compatible)); + if (match) + return m; + m++; + } + + /* Get node's next compatible string */ + if (cp) { + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + } while (cp && (cplen > 0)); + return NULL; } @@ -757,7 +775,10 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, * @matches: array of of device match structures to search in * @node: the of device structure to match against * - * Low level utility function used by device matching. + * Low level utility function used by device matching. Matching order + * is to compare each of the node's compatibles with all given matches + * first. This implies node's compatible is sorted from specific to + * generic while matches can be in any order. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) -- cgit v1.2.3 From bf49be02d6f92b95c2462e5027fc90b98f62e324 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Wed, 27 Nov 2013 23:26:13 -0800 Subject: of: irq: Ignore disabled interrupt controllers When searching the system for interrupt controllers, skip over any that are explicitly disabled. This makes interrupt controllers consistent with regular devices, which can be marked as do-not-probe via the status = "disabled" dts property. Signed-off-by: Peter Crosthwaite Acked-by: Michal Simek Signed-off-by: Rob Herring --- drivers/of/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 786b0b47fae4..9876963ed7b3 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -438,7 +438,8 @@ void __init of_irq_init(const struct of_device_id *matches) INIT_LIST_HEAD(&intc_parent_list); for_each_matching_node(np, matches) { - if (!of_find_property(np, "interrupt-controller", NULL)) + if (!of_find_property(np, "interrupt-controller", NULL) || + !of_device_is_available(np)) continue; /* * Here, we allocate and populate an intc_desc with the node -- cgit v1.2.3 From 1ca56e7dcadd865ae2c235789cbdbfebae719ffb Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Wed, 27 Nov 2013 23:26:12 -0800 Subject: of: irq: Ignore disabled intc's when searching map When searching the interrupt map, if a matched parent is disabled, just ignore it and move on with the search. This allows for specifying connection of a single device IRQ to multiple interrupt controllers via the interrupt map schema. This change allows for selection of the active interrupt controller via the already existing status = "disabled" mechanism. Signed-off-by: Peter Crosthwaite Acked-by: Michal Simek Signed-off-by: Rob Herring --- drivers/of/irq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9876963ed7b3..bf8026895c5e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -217,6 +217,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) goto fail; } + if (!of_device_is_available(newpar)) + match = 0; + /* Get #interrupt-cells and #address-cells of new * parent */ -- cgit v1.2.3 From 877494a7e29c38b0203b32012f7f673304693437 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Dec 2013 11:26:20 -0800 Subject: staging: lustre: reapply an older patch that was reverted This reapplies part of 9edf0f670bdc8fa8b6676893b0a3bd2bf3 (staging: lustre: clean up format string usages) as it was reverted in a recent change to this file. That proves the big problem of having external trees you have to have patches flowing back into them from upstream or things break down... Reported-by: Kees Cook Reported-by: kbuild test robot Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 8a95fa5e1052..2d26fd543d46 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -636,7 +636,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) GOTO(out_env, rc); } - task = kthread_run(ptlrpcd, pc, pc->pc_name); + task = kthread_run(ptlrpcd, pc, "%s", pc->pc_name); if (IS_ERR(task)) GOTO(out_env, rc = PTR_ERR(task)); -- cgit v1.2.3 From 1ff70a7c99ac74aadba6f1cf5d21730ec9eb483a Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Wed, 4 Dec 2013 15:24:12 +0800 Subject: staging: et131x: change function name Change function name from et1310_phy_power_down to et1310_phy_power_switch to better describe its functionality. Signed-off-by: ZHAO Gang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index ca36b04d3c1b..fe6619a520a8 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1679,7 +1679,7 @@ static int et131x_mdio_reset(struct mii_bus *bus) return 0; } -/* et1310_phy_power_down - PHY power control +/* et1310_phy_power_switch - PHY power control * @adapter: device to control * @down: true for off/false for back on * @@ -1688,7 +1688,7 @@ static int et131x_mdio_reset(struct mii_bus *bus) * Can't you see that this code processed * Phy power, phy power.. */ -static void et1310_phy_power_down(struct et131x_adapter *adapter, bool down) +static void et1310_phy_power_switch(struct et131x_adapter *adapter, bool down) { u16 data; @@ -1938,7 +1938,7 @@ static void et131x_adapter_setup(struct et131x_adapter *adapter) et1310_config_macstat_regs(adapter); - et1310_phy_power_down(adapter, 0); + et1310_phy_power_switch(adapter, 0); et131x_xcvr_init(adapter); } -- cgit v1.2.3 From 4eb946285aa07669568af3e0a19f694409ccc0d4 Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Wed, 4 Dec 2013 15:24:13 +0800 Subject: staging: et131x: delete unnecessary variable in function et131x_init Variable u32 numrfd is not necessary in this function. Signed-off-by: ZHAO Gang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index fe6619a520a8..e3a71d3fafcc 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -2450,7 +2450,6 @@ static int et131x_init_recv(struct et131x_adapter *adapter) { struct rfd *rfd; u32 rfdct; - u32 numrfd = 0; struct rx_ring *rx_ring; /* Setup some convenience pointers */ @@ -2467,9 +2466,8 @@ static int et131x_init_recv(struct et131x_adapter *adapter) /* Add this RFD to the recv_list */ list_add_tail(&rfd->list_node, &rx_ring->recv_list); - /* Increment both the available RFD's, and the total RFD's. */ + /* Increment the available RFD's */ rx_ring->num_ready_recv++; - numrfd++; } return 0; -- cgit v1.2.3 From f95321f33af8b75cce171ba18e5fa04ed1fcb88f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:10 -0700 Subject: staging: comedi: s626: fix async command hookup Only set the SDF_CMD_READ subdev_flag if the irq was sucessfully requested. Remove the unnecessary sanity check of dev->irq in s626_ai_cmd(). This callback is only hooked up if the irq is available. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 6d266235ae4f..583583854dca 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2079,12 +2079,6 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd == NULL) return -EINVAL; - if (dev->irq == 0) { - comedi_error(dev, - "s626_ai_cmd: cannot run command without an irq"); - return -EIO; - } - s626_ai_load_polllist(ppl, cmd); devpriv->ai_cmd_running = 1; devpriv->ai_convert_count = 0; @@ -2833,7 +2827,7 @@ static int s626_auto_attach(struct comedi_device *dev, s = &dev->subdevices[0]; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_DIFF; s->n_chan = S626_ADC_CHANNELS; s->maxdata = 0x3fff; s->range_table = &s626_range_table; @@ -2841,6 +2835,7 @@ static int s626_auto_attach(struct comedi_device *dev, s->insn_read = s626_ai_insn_read; if (dev->irq) { dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; s->do_cmd = s626_ai_cmd; s->do_cmdtest = s626_ai_cmdtest; s->cancel = s626_ai_cancel; -- cgit v1.2.3 From 6a8f6de10567e0b46e0d8ff605b54886ca13a9f4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:11 -0700 Subject: staging: comedi: pcl816: remove 'irq_free' from private data This member of the private data is not needed. We can check if dev->irq is none zero instead. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index d54325047af6..a102db34e131 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -128,7 +128,6 @@ struct pcl816_private { unsigned int ai_scans; /* len of scanlist */ unsigned char ai_neverending; /* if=1, then we do neverending record (you must use cancel()) */ - int irq_free; /* 1=have allocated IRQ */ int irq_blocked; /* 1=IRQ now uses any subdev */ int irq_was_now_closed; /* when IRQ finish, there's stored int816_mode for last interrupt */ int int816_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */ @@ -382,8 +381,7 @@ static irqreturn_t interrupt_pcl816(int irq, void *d) } outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ - if (!dev->irq || !devpriv->irq_free || !devpriv->irq_blocked || - !devpriv->int816_mode) { + if (!dev->irq || !devpriv->irq_blocked || !devpriv->int816_mode) { if (devpriv->irq_was_now_closed) { devpriv->irq_was_now_closed = 0; /* comedi_error(dev,"last IRQ.."); */ @@ -875,10 +873,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if ((1 << it->options[1]) & board->IRQbits) { ret = request_irq(it->options[1], interrupt_pcl816, 0, dev->board_name, dev); - if (ret == 0) { + if (ret == 0) dev->irq = it->options[1]; - devpriv->irq_free = 1; - } } devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ @@ -887,7 +883,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* grab our DMA */ dma = 0; devpriv->dma = dma; - if (!devpriv->irq_free) + if (!dev->irq) goto no_dma; /* if we haven't IRQ, we can't use DMA */ if (board->DMAbits != 0) { /* board support DMA */ -- cgit v1.2.3 From 109b4d00f92be265f5795d0baf12722ecbf2d146 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:12 -0700 Subject: staging: comedi: pcl816: only init command support if irq is available The async command support requires an irq. Only initialize the subdevice command support if the request_irq was successfull. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index a102db34e131..ed4d57f8a1bd 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -949,18 +949,20 @@ no_dma: if (board->n_aichan > 0) { s->type = COMEDI_SUBD_AI; devpriv->sub_ai = s; - dev->read_subdev = s; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->subdev_flags = SDF_CMD_READ | SDF_DIFF; s->n_chan = board->n_aichan; - s->subdev_flags |= SDF_DIFF; s->maxdata = board->ai_maxdata; - s->len_chanlist = board->ai_chanlist; s->range_table = board->ai_range_type; - s->cancel = pcl816_ai_cancel; - s->do_cmdtest = pcl816_ai_cmdtest; - s->do_cmd = pcl816_ai_cmd; - s->poll = pcl816_ai_poll; s->insn_read = pcl816_ai_insn_read; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = board->ai_chanlist; + s->do_cmdtest = pcl816_ai_cmdtest; + s->do_cmd = pcl816_ai_cmd; + s->poll = pcl816_ai_poll; + s->cancel = pcl816_ai_cancel; + } } else { s->type = COMEDI_SUBD_UNUSED; } -- cgit v1.2.3 From 5d6f1a2ede8060fedb6baf652cbb24ae9db25b1b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:13 -0700 Subject: staging: comedi: pcl816: remove 'sub_ai' from private data This member of the private data is a duplicate of the comedi_device 'read_subdev' member. Remove the private data member and use the comedi_device member instead. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index ed4d57f8a1bd..6445e1fe4e5e 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -138,7 +138,6 @@ struct pcl816_private { unsigned int ai_act_chanlist_pos; /* actual position in MUX list */ unsigned int ai_n_chan; /* how many channels per scan */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ - struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */ }; /* @@ -948,7 +947,6 @@ no_dma: s = &dev->subdevices[0]; if (board->n_aichan > 0) { s->type = COMEDI_SUBD_AI; - devpriv->sub_ai = s; s->subdev_flags = SDF_CMD_READ | SDF_DIFF; s->n_chan = board->n_aichan; s->maxdata = board->ai_maxdata; @@ -1003,7 +1001,7 @@ static void pcl816_detach(struct comedi_device *dev) struct pcl816_private *devpriv = dev->private; if (dev->private) { - pcl816_ai_cancel(dev, devpriv->sub_ai); + pcl816_ai_cancel(dev, dev->read_subdev); pcl816_reset(dev); if (devpriv->dma) free_dma(devpriv->dma); -- cgit v1.2.3 From 5451274a3211c7efcea9a268d1177633d841350a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:14 -0700 Subject: staging: comedi: pcl816: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 6445e1fe4e5e..a2e0b545401b 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -221,7 +221,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) { struct comedi_device *dev = d; struct pcl816_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; unsigned char low, hi; int timeout = 50; /* wait max 50us */ @@ -315,7 +315,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) { struct comedi_device *dev = d; struct pcl816_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; int len, bufptr, this_dma_buf; unsigned long dma_flags; unsigned short *ptr; -- cgit v1.2.3 From 35a8735d1cea548c12ca00e38fb56f91d053035b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:15 -0700 Subject: staging: comedi: pcl818: remove 'irq_free' from private data This member of the private data is not needed. We can check if dev->irq is none zero instead. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index cacdca0983bb..3dac1dd1372f 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -274,7 +274,6 @@ struct pcl818_private { unsigned char neverending_ai; /* if=1, then we do neverending record (you must use cancel()) */ unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ int i8253_osc_base; /* 1/frequency of on board oscilator in ns */ - int irq_free; /* 1=have allocated IRQ */ int irq_blocked; /* 1=IRQ now uses any subdev */ int irq_was_now_closed; /* when IRQ finish, there's stored int818_mode for last interrupt */ int ai_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */ @@ -701,8 +700,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d) outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ - if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked) - || (!devpriv->ai_mode)) { + if (!dev->irq || !devpriv->irq_blocked || !devpriv->ai_mode) { comedi_error(dev, "bad IRQ!"); return IRQ_NONE; } @@ -1230,10 +1228,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) if ((1 << it->options[1]) & board->IRQbits) { ret = request_irq(it->options[1], interrupt_pcl818, 0, dev->board_name, dev); - if (ret == 0) { + if (ret == 0) dev->irq = it->options[1]; - devpriv->irq_free = 1; - } } devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ @@ -1242,7 +1238,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* grab our DMA */ dma = 0; devpriv->dma = dma; - if (!devpriv->irq_free) + if (!dev->irq) goto no_dma; /* if we haven't IRQ, we can't use DMA */ if (board->DMAbits != 0) { /* board support DMA */ dma = it->options[2]; -- cgit v1.2.3 From 1dcea26a226c18cb843014d1f68d88a89c784912 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:16 -0700 Subject: staging: comedi: pcl818: remove unnecessary 'dev->irq' tests These functions can only be called if the irq was sucessfully requested. The dev->irq will always be valid. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 3dac1dd1372f..5fc470800b01 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -700,7 +700,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d) outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ - if (!dev->irq || !devpriv->irq_blocked || !devpriv->ai_mode) { + if (!devpriv->irq_blocked || !devpriv->ai_mode) { comedi_error(dev, "bad IRQ!"); return IRQ_NONE; } @@ -762,10 +762,6 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, unsigned int seglen; dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode()\n"); - if (!dev->irq) { - comedi_error(dev, "IRQ not defined!"); - return -EINVAL; - } if (devpriv->irq_blocked) return -EBUSY; -- cgit v1.2.3 From 281b6e75fd95db1517406e0ec671691115de482d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:17 -0700 Subject: staging: comedi: pcl818: remove function trace noise These kernel messages are just added noise. Remove them. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 5fc470800b01..e1fef1b57547 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -761,8 +761,6 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, int divisor1 = 0, divisor2 = 0; unsigned int seglen; - dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode()\n"); - if (devpriv->irq_blocked) return -EBUSY; @@ -841,7 +839,6 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, start_pacer(dev, mode, divisor1, divisor2); - dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode() end\n"); return 0; } @@ -1049,7 +1046,6 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; int retval; - dev_dbg(dev->class_dev, "pcl818_ai_cmd()\n"); devpriv->ai_n_chan = cmd->chanlist_len; devpriv->ai_chanlist = cmd->chanlist; devpriv->ai_flags = cmd->flags; @@ -1066,7 +1062,6 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */ devpriv->ai_timer1 = cmd->convert_arg; retval = pcl818_ai_cmd_mode(1, dev, s); - dev_dbg(dev->class_dev, "pcl818_ai_cmd() end\n"); return retval; } if (cmd->convert_src == TRIG_EXT) { /* mode 3 */ @@ -1087,7 +1082,6 @@ static int pcl818_ai_cancel(struct comedi_device *dev, struct pcl818_private *devpriv = dev->private; if (devpriv->irq_blocked > 0) { - dev_dbg(dev->class_dev, "pcl818_ai_cancel()\n"); devpriv->irq_was_now_closed = 1; switch (devpriv->ai_mode) { @@ -1131,7 +1125,6 @@ static int pcl818_ai_cancel(struct comedi_device *dev, } end: - dev_dbg(dev->class_dev, "pcl818_ai_cancel() end\n"); return 0; } -- cgit v1.2.3 From 5d788d019c4c7c36878a5149f60b40bfeba26ea0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:18 -0700 Subject: staging: comedi: pcl818: only init async command members when needed The 'len_chanlist' and 'cancel' members of the comedi_subdevice are only used with async command support. Only initialize them if the irq was sucessfully requested. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index e1fef1b57547..ad1f34706643 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1279,15 +1279,15 @@ no_dma: s->subdev_flags |= SDF_DIFF; } s->maxdata = board->ai_maxdata; - s->len_chanlist = s->n_chan; s->range_table = board->ai_range_type; - s->cancel = pcl818_ai_cancel; s->insn_read = pcl818_ai_insn_read; if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; s->do_cmdtest = ai_cmdtest; s->do_cmd = ai_cmd; + s->cancel = pcl818_ai_cancel; } if (board->is_818) { if ((it->options[4] == 1) || (it->options[4] == 10)) -- cgit v1.2.3 From 89dac49eed7d82d8f9164dcf22f15ad228d43446 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:19 -0700 Subject: staging: comedi: pcl818: remove 'sub_ai' from private data This member of the private data is a duplicate of the comedi_device 'read_subdev' member. Remove the private data member and use the comedi_device member instead. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index ad1f34706643..fb9141274e19 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -290,7 +290,6 @@ struct pcl818_private { unsigned int ai_data_len; /* len of data buffer */ unsigned int ai_timer1; /* timers */ unsigned int ai_timer2; - struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */ unsigned char usefifo; /* 1=use fifo */ unsigned int ao_readback[2]; }; @@ -1269,7 +1268,6 @@ no_dma: s->type = COMEDI_SUBD_UNUSED; } else { s->type = COMEDI_SUBD_AI; - devpriv->sub_ai = s; s->subdev_flags = SDF_READABLE; if (check_single_ended(dev->iobase)) { s->n_chan = board->n_aichan_se; @@ -1403,7 +1401,7 @@ static void pcl818_detach(struct comedi_device *dev) struct pcl818_private *devpriv = dev->private; if (devpriv) { - pcl818_ai_cancel(dev, devpriv->sub_ai); + pcl818_ai_cancel(dev, dev->read_subdev); pcl818_reset(dev); if (devpriv->dma) free_dma(devpriv->dma); -- cgit v1.2.3 From e4bfb085ed75ba3553b6621b67ed80550dcfdac3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:20 -0700 Subject: staging: comedi: pcl818: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index fb9141274e19..fc587002f9cb 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -439,7 +439,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) { struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; unsigned char low; int timeout = 50; /* wait max 50us */ @@ -498,7 +498,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) { struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; int i, len, bufptr; unsigned long flags; unsigned short *ptr; @@ -575,7 +575,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) { struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; int i, len; unsigned char lo; @@ -667,10 +667,9 @@ static irqreturn_t interrupt_pcl818(int irq, void *d) being reprogrammed while a DMA transfer is in progress. */ - struct comedi_subdevice *s = &dev->subdevices[0]; devpriv->ai_act_scan = 0; devpriv->neverending_ai = 0; - pcl818_ai_cancel(dev, s); + pcl818_ai_cancel(dev, dev->read_subdev); } outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ -- cgit v1.2.3 From 6464e2ff4303108b20fc60c45e843c95f314a814 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:21 -0700 Subject: staging: comedi: pcl818: remove unnecessary s->len_chanlist init The subdevice 'len_chanlist' member is only used with async command support. Remove the initialization of this member for the subdevices that do not support commands. The core will then correctly initialize it to the default value of '1'. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index fc587002f9cb..695e84a94ced 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1333,7 +1333,6 @@ no_dma: s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->n_chan = board->n_aochan; s->maxdata = board->ao_maxdata; - s->len_chanlist = board->n_aochan; s->range_table = board->ao_range_type; s->insn_read = pcl818_ao_insn_read; s->insn_write = pcl818_ao_insn_write; @@ -1358,7 +1357,6 @@ no_dma: s->subdev_flags = SDF_READABLE; s->n_chan = board->n_dichan; s->maxdata = 1; - s->len_chanlist = board->n_dichan; s->range_table = &range_digital; s->insn_bits = pcl818_di_insn_bits; } @@ -1371,7 +1369,6 @@ no_dma: s->subdev_flags = SDF_WRITABLE; s->n_chan = board->n_dochan; s->maxdata = 1; - s->len_chanlist = board->n_dochan; s->range_table = &range_digital; s->insn_bits = pcl818_do_insn_bits; } -- cgit v1.2.3 From e5fc1a19255616e77ab538bfce16b3ef0836f4b2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:22 -0700 Subject: staging: comedi: pcl812: remove unnecessary s->len_chanlist init The subdevice 'len_chanlist' member is only used with async command support. Remove the initialization of this member for the subdevices that do not support commands. The core will then correctly initialize it to the default value of '1'. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index e1e4cd139b63..aabadea58fd6 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1305,7 +1305,6 @@ no_dma: s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->n_chan = board->n_aochan; s->maxdata = 0xfff; - s->len_chanlist = 1; s->range_table = board->rangelist_ao; s->insn_read = pcl812_ao_insn_read; s->insn_write = pcl812_ao_insn_write; @@ -1334,7 +1333,6 @@ no_dma: s->subdev_flags = SDF_READABLE; s->n_chan = board->n_dichan; s->maxdata = 1; - s->len_chanlist = board->n_dichan; s->range_table = &range_digital; s->insn_bits = pcl812_di_insn_bits; subdev++; @@ -1347,7 +1345,6 @@ no_dma: s->subdev_flags = SDF_WRITABLE; s->n_chan = board->n_dochan; s->maxdata = 1; - s->len_chanlist = board->n_dochan; s->range_table = &range_digital; s->insn_bits = pcl812_do_insn_bits; subdev++; -- cgit v1.2.3 From 12f24996ccb8a2d627776cca6a1ad19a30954a74 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:23 -0700 Subject: staging: comedi: pcl812: only init async command members when needed The 'len_chanlist' and 'cancel' members of the comedi_subdevice are only used with async command support. Only initialize them if the irq was sucessfully requested. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index aabadea58fd6..218b05d3d567 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1201,7 +1201,6 @@ no_dma: break; } s->maxdata = board->ai_maxdata; - s->len_chanlist = MAX_CHANLIST_LEN; s->range_table = board->rangelist_ai; if (board->board_type == boardACL8216) s->insn_read = acl8216_ai_insn_read; @@ -1209,13 +1208,14 @@ no_dma: s->insn_read = pcl812_ai_insn_read; devpriv->use_MPC = board->haveMPC508; - s->cancel = pcl812_ai_cancel; if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = MAX_CHANLIST_LEN; s->do_cmdtest = pcl812_ai_cmdtest; s->do_cmd = pcl812_ai_cmd; s->poll = pcl812_ai_poll; + s->cancel = pcl812_ai_cancel; } switch (board->board_type) { case boardPCL812PG: -- cgit v1.2.3 From 18a764ce56a086f76bfdd91deba3ae758087872b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:24 -0700 Subject: staging: comedi: pcl812: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl812.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 218b05d3d567..380c9c29645a 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -755,7 +755,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) unsigned int mask, timeout; struct comedi_device *dev = d; struct pcl812_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; unsigned int next_chan; s->async->events = 0; @@ -858,7 +858,7 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) { struct comedi_device *dev = d; struct pcl812_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; unsigned long dma_flags; int len, bufptr; unsigned short *ptr; -- cgit v1.2.3 From c108a5e09803850217c5b9d9079f99383401a312 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:25 -0700 Subject: staging: comedi: ni_pcimio: tidy up the irq request The irq is only needed to support async commands. Tidy up the code that does the request_irq() and remove the noise. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcimio.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 1166c45da49e..ec4fa3d839c4 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1469,6 +1469,7 @@ static int pcimio_auto_attach(struct comedi_device *dev, struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct ni_board_struct *board = NULL; struct ni_private *devpriv; + unsigned int irq; int ret; if (context < ARRAY_SIZE(ni_boards)) @@ -1530,18 +1531,12 @@ static int pcimio_auto_attach(struct comedi_device *dev, if (board->reg_type == ni_reg_6143) init_6143(dev); - dev->irq = mite_irq(devpriv->mite); - - if (dev->irq == 0) { - pr_warn("unknown irq (bad)\n"); - } else { - pr_debug("( irq = %u )\n", dev->irq); - ret = request_irq(dev->irq, ni_E_interrupt, NI_E_IRQ_FLAGS, - DRV_NAME, dev); - if (ret < 0) { - pr_warn("irq not available\n"); - dev->irq = 0; - } + irq = mite_irq(devpriv->mite); + if (irq) { + ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS, + dev->board_name, dev); + if (ret == 0) + dev->irq = irq; } ret = ni_E_init(dev); -- cgit v1.2.3 From 19f5224b754823f1649f3094d916b0a775fc9d42 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 3 Dec 2013 12:07:26 -0700 Subject: staging: comedi: ni_pcidio: tidy up the irq request The irq is only needed to support async commands. Tidy up the code that does the request_irq() and remove the noise. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 313b436617bb..645a4d80e608 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -990,7 +990,6 @@ static int nidio_auto_attach(struct comedi_device *dev, if (devpriv->di_mite_ring == NULL) return -ENOMEM; - irq = mite_irq(devpriv->mite); if (board->uses_firmware) { ret = pci_6534_upload_firmware(dev); if (ret < 0) @@ -1033,12 +1032,13 @@ static int nidio_auto_attach(struct comedi_device *dev, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); - ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, - "ni_pcidio", dev); - if (ret < 0) - dev_warn(dev->class_dev, "irq not available\n"); - - dev->irq = irq; + irq = mite_irq(devpriv->mite); + if (irq) { + ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (ret == 0) + dev->irq = irq; + } return 0; } -- cgit v1.2.3 From 284c145e7e06858ce93a7164fc8420434f4f72cb Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 4 Dec 2013 01:54:56 +0800 Subject: staging/lustre: fix build error in ll_setxattr_common MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With CONFIG_FS_POSIX_ACL off, we'll get drivers/staging/lustre/lustre/llite/xattr.c: In function ‘ll_setxattr_common’: drivers/staging/lustre/lustre/llite/xattr.c:187:7: error: ‘rce’ undeclared (first use in this function) drivers/staging/lustre/lustre/llite/xattr.c:187:7: note: each undeclared identifier is reported only once for each function it appears in It was introduced by 7fc1f83 (staging/lustre/llite: extended attribute cache) that added new reference but didn't take care of CONFIG_FS_POSIX_ACL. Reported-by: Fengguang Wu Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index ee95855a2cf3..3a7d03c12dd9 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -112,9 +112,9 @@ int ll_setxattr_common(struct inode *inode, const char *name, struct ptlrpc_request *req = NULL; int xattr_type, rc; struct obd_capa *oc; + struct rmtacl_ctl_entry *rce = NULL; #ifdef CONFIG_FS_POSIX_ACL posix_acl_xattr_header *new_value = NULL; - struct rmtacl_ctl_entry *rce = NULL; ext_acl_xattr_header *acl = NULL; #endif const char *pv = value; -- cgit v1.2.3 From 960edbe307b1f23fa481bed2c6fa492649ea3f30 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 4 Dec 2013 01:54:57 +0800 Subject: staging/lustre/llite: remove ll_file_get_iov_count It exactly copies generic_segment_checks() except wrongly calling access_ok(VERIFY_READ) for aio read range. Drop it and just call generic_segment_checks() instead. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 36 ++---------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 8f03eb0d2ff3..996c19d7370c 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1148,38 +1148,6 @@ out: return result; } - -/* - * XXX: exact copy from kernel code (__generic_file_aio_write_nolock) - */ -static int ll_file_get_iov_count(const struct iovec *iov, - unsigned long *nr_segs, size_t *count) -{ - size_t cnt = 0; - unsigned long seg; - - for (seg = 0; seg < *nr_segs; seg++) { - const struct iovec *iv = &iov[seg]; - - /* - * If any segment has a negative length, or the cumulative - * length ever wraps negative then return -EINVAL. - */ - cnt += iv->iov_len; - if (unlikely((ssize_t)(cnt|iv->iov_len) < 0)) - return -EINVAL; - if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len)) - continue; - if (seg == 0) - return -EFAULT; - *nr_segs = seg; - cnt -= iv->iov_len; /* This segment is no good */ - break; - } - *count = cnt; - return 0; -} - static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { @@ -1189,7 +1157,7 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, ssize_t result; int refcheck; - result = ll_file_get_iov_count(iov, &nr_segs, &count); + result = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); if (result) return result; @@ -1248,7 +1216,7 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ssize_t result; int refcheck; - result = ll_file_get_iov_count(iov, &nr_segs, &count); + result = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ); if (result) return result; -- cgit v1.2.3 From 9d2834ddae599b82948772786ae0e693277ef7cc Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 4 Dec 2013 01:54:58 +0800 Subject: staging/lustre: fix undefined reference if CONFIG_PROC_FS is off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building Lustre with CONFIG_PROC_FS off, we'll get many errors like: drivers/staging/lustre/lustre/obdclass/llog_test.c:1053: error: implicit declaration of function ‘lprocfs_llog_test_init_vars’ make[3]: *** [drivers/staging/lustre/lustre/obdclass/llog_test.o] Error 1 make[2]: *** [drivers/staging/lustre/lustre/obdclass] Error 2 make[2]: *** Waiting for unfinished jobs.... CC [M] drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.o drivers/staging/lustre/lustre/ptlrpc/pinger.c: In function ‘ptlrpc_pinger_main’: drivers/staging/lustre/lustre/ptlrpc/pinger.c:331: error: implicit declaration of function ‘obd_update_maxusage’ The patch defines following symbols when CONFIG_PROC_FS is off: fld_type_proc_dir, obd_update_maxusage(), obd_max_pages, obd_max_alloc, obd_alloc, obd_pages, lprocfs_llog_test_init_vars(). Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/fld_internal.h | 1 - drivers/staging/lustre/lustre/fld/fld_request.c | 2 +- drivers/staging/lustre/lustre/include/obd_support.h | 3 ++- drivers/staging/lustre/lustre/obdclass/class_obd.c | 6 ++++++ drivers/staging/lustre/lustre/obdclass/llog_test.c | 4 ++++ 5 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h index 56686b138ac1..5f3935cc0fd7 100644 --- a/drivers/staging/lustre/lustre/fld/fld_internal.h +++ b/drivers/staging/lustre/lustre/fld/fld_internal.h @@ -190,5 +190,4 @@ fld_target_name(struct lu_fld_target *tar) return (const char *)tar->ft_exp->exp_obd->obd_name; } -extern struct proc_dir_entry *fld_type_proc_dir; #endif /* __FLD_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 3191a398675d..896f9fe83ffd 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -274,9 +274,9 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) } EXPORT_SYMBOL(fld_client_del_target); -#ifdef LPROCFS struct proc_dir_entry *fld_type_proc_dir = NULL; +#ifdef LPROCFS static int fld_client_proc_init(struct lu_client_fld *fld) { int rc; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 2dc95de1059c..977bc231df9d 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -507,6 +507,8 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, extern atomic_t libcfs_kmemory; +extern void obd_update_maxusage(void); + #ifdef LPROCFS #define obd_memory_add(size) \ lprocfs_counter_add(obd_memory, OBD_MEMORY_STAT, (long)(size)) @@ -525,7 +527,6 @@ extern atomic_t libcfs_kmemory; lprocfs_stats_collector(obd_memory, OBD_MEMORY_PAGES_STAT, \ LPROCFS_FIELDS_FLAGS_SUM) -extern void obd_update_maxusage(void); extern __u64 obd_memory_max(void); extern __u64 obd_pages_max(void); diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 7b1d1b685803..5f8d9f2db277 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -54,7 +54,13 @@ struct list_head obd_types; DEFINE_RWLOCK(obd_dev_lock); __u64 obd_max_pages = 0; +EXPORT_SYMBOL(obd_max_pages); __u64 obd_max_alloc = 0; +EXPORT_SYMBOL(obd_max_alloc); +__u64 obd_alloc; +EXPORT_SYMBOL(obd_alloc); +__u64 obd_pages; +EXPORT_SYMBOL(obd_pages); DEFINE_SPINLOCK(obd_updatemax_lock); /* The following are visible and mutable through /proc/sys/lustre/. */ diff --git a/drivers/staging/lustre/lustre/obdclass/llog_test.c b/drivers/staging/lustre/lustre/obdclass/llog_test.c index 7427c125a3ab..764068fc4ef7 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_test.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_test.c @@ -947,6 +947,10 @@ static void lprocfs_llog_test_init_vars(struct lprocfs_static_vars *lvars) lvars->module_vars = lprocfs_llog_test_module_vars; lvars->obd_vars = lprocfs_llog_test_obd_vars; } +#else +static void lprocfs_llog_test_init_vars(struct lprocfs_static_vars *lvars) +{ +} #endif static int llog_test_cleanup(struct obd_device *obd) -- cgit v1.2.3 From 2c185ffa270a95e3699c223a0ee67f560ec0db8c Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Wed, 4 Dec 2013 01:54:59 +0800 Subject: staging/lustre: don't compile procfs code when CONFIG_PROC_FS is off The patch changes to conditionally compile procfs related source files. This includes lproc_fid.c, lproc_fld.c, lproc_lov.c, lvfs_lib.c, lproc_mdc.c, lproc_mgc.c, lprocfs_status.c, lproc_osc.c and sec_lproc.c. There is a checkpatch warning about usage of simple_strtoul() in the patch. But it needs to be fixed in a separate patch because it is not related to CONFIG_PROC_FS breakage here. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fid/Makefile | 3 +- drivers/staging/lustre/lustre/fid/lproc_fid.c | 2 - drivers/staging/lustre/lustre/fld/Makefile | 3 +- drivers/staging/lustre/lustre/fld/lproc_fld.c | 3 - .../staging/lustre/lustre/include/lprocfs_status.h | 8 +- drivers/staging/lustre/lustre/include/lustre_sec.h | 17 +- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c | 9 + drivers/staging/lustre/lustre/llite/Makefile | 3 +- .../staging/lustre/lustre/llite/llite_internal.h | 14 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 1 + drivers/staging/lustre/lustre/llite/lproc_llite.c | 4 - drivers/staging/lustre/lustre/lmv/Makefile | 4 +- drivers/staging/lustre/lustre/lmv/lproc_lmv.c | 5 - drivers/staging/lustre/lustre/lov/Makefile | 3 +- drivers/staging/lustre/lustre/lov/lov_internal.h | 2 +- drivers/staging/lustre/lustre/lov/lproc_lov.c | 4 +- drivers/staging/lustre/lustre/lvfs/Makefile | 3 +- drivers/staging/lustre/lustre/lvfs/lvfs_lib.c | 2 - drivers/staging/lustre/lustre/mdc/Makefile | 3 +- drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 3 - drivers/staging/lustre/lustre/mgc/Makefile | 3 +- drivers/staging/lustre/lustre/mgc/lproc_mgc.c | 3 - drivers/staging/lustre/lustre/mgc/mgc_internal.h | 2 +- drivers/staging/lustre/lustre/mgc/mgc_request.c | 2 + drivers/staging/lustre/lustre/obdclass/class_obd.c | 7 + .../lustre/lustre/obdclass/linux/linux-module.c | 4 +- .../lustre/lustre/obdclass/lprocfs_status.c | 348 ++++++++++----------- drivers/staging/lustre/lustre/osc/Makefile | 3 +- drivers/staging/lustre/lustre/osc/lproc_osc.c | 2 - drivers/staging/lustre/lustre/ptlrpc/Makefile | 3 +- .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h | 6 + 31 files changed, 247 insertions(+), 232 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/fid/Makefile b/drivers/staging/lustre/lustre/fid/Makefile index ed21bea162ba..d24f2df7c0af 100644 --- a/drivers/staging/lustre/lustre/fid/Makefile +++ b/drivers/staging/lustre/lustre/fid/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += fid.o -fid-y := fid_request.o lproc_fid.o fid_lib.o +fid-y := fid_request.o fid_lib.o +fid-$(CONFIG_PROC_FS) += lproc_fid.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 294070da9d43..ddd813cab501 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -54,7 +54,6 @@ #include #include "fid_internal.h" -#ifdef LPROCFS /* * Note: this function is only used for testing, it is no safe for production * use. @@ -209,4 +208,3 @@ struct lprocfs_vars seq_client_proc_list[] = { { "fid", &lprocfs_fid_fid_fops }, { NULL } }; -#endif diff --git a/drivers/staging/lustre/lustre/fld/Makefile b/drivers/staging/lustre/lustre/fld/Makefile index 90d46d84fbbb..640fba4b827d 100644 --- a/drivers/staging/lustre/lustre/fld/Makefile +++ b/drivers/staging/lustre/lustre/fld/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += fld.o -fld-y := fld_request.o fld_cache.o lproc_fld.o +fld-y := fld_request.o fld_cache.o +fld-$(CONFIG_PROC_FS) += lproc_fld.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index 052f7d51a07c..530adde46963 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -56,7 +56,6 @@ #include #include "fld_internal.h" -#ifdef LPROCFS static int fld_proc_targets_seq_show(struct seq_file *m, void *unused) { @@ -162,5 +161,3 @@ struct lprocfs_vars fld_client_proc_list[] = { { "hash", &fld_proc_hash_fops }, { "cache_flush", &fld_proc_cache_flush_fops }, { NULL }}; - -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 56b05728f611..428e3e4ce05c 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -370,6 +370,10 @@ static inline void s2dhms(struct dhms *ts, time_t secs) #define JOBSTATS_DISABLE "disable" #define JOBSTATS_PROCNAME_UID "procname_uid" +extern int lprocfs_write_frac_helper(const char *buffer, unsigned long count, + int *val, int mult); +extern int lprocfs_read_frac_helper(char *buffer, unsigned long count, + long val, int mult); #ifdef LPROCFS extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, @@ -641,11 +645,7 @@ extern int lprocfs_rd_filesfree(struct seq_file *m, void *data); extern int lprocfs_write_helper(const char *buffer, unsigned long count, int *val); -extern int lprocfs_write_frac_helper(const char *buffer, unsigned long count, - int *val, int mult); extern int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult); -extern int lprocfs_read_frac_helper(char *buffer, unsigned long count, - long val, int mult); extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count, __u64 *val); extern int lprocfs_write_frac_u64_helper(const char *buffer, diff --git a/drivers/staging/lustre/lustre/include/lustre_sec.h b/drivers/staging/lustre/lustre/include/lustre_sec.h index 70b8b133a5c3..885247d28b3a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_sec.h +++ b/drivers/staging/lustre/lustre/include/lustre_sec.h @@ -902,12 +902,6 @@ struct ptlrpc_bulk_sec_desc { }; -/* - * lprocfs - */ -struct proc_dir_entry; -extern struct proc_dir_entry *sptlrpc_proc_root; - /* * round size up to next power of 2, for slab allocation. * @size must be sane (can't overflow after round up) @@ -1067,7 +1061,18 @@ void sptlrpc_gc_add_ctx(struct ptlrpc_cli_ctx *ctx); /* misc */ const char * sec2target_str(struct ptlrpc_sec *sec); +/* + * lprocfs + */ +#ifdef LPROCFS +struct proc_dir_entry; +extern struct proc_dir_entry *sptlrpc_proc_root; int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev); +#else +#define sptlrpc_proc_root NULL +static inline int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev) +{ return 0; } +#endif /* * server side diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 0025ee6356da..6758646f575f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -638,6 +638,7 @@ int ldlm_pool_setup(struct ldlm_pool *pl, int limit) } EXPORT_SYMBOL(ldlm_pool_setup); +#ifdef LPROCFS static int lprocfs_pool_state_seq_show(struct seq_file *m, void *unused) { int granted, grant_rate, cancel_rate, grant_step; @@ -822,6 +823,14 @@ static void ldlm_pool_proc_fini(struct ldlm_pool *pl) pl->pl_proc_dir = NULL; } } +#else /* !LPROCFS */ +static int ldlm_pool_proc_init(struct ldlm_pool *pl) +{ + return 0; +} + +static void ldlm_pool_proc_fini(struct ldlm_pool *pl) {} +#endif /* LPROCFS */ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns, int idx, ldlm_side_t client) diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index bb34b8b40645..c76f3cfedab0 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -1,12 +1,13 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o obj-$(CONFIG_LUSTRE_LLITE_LLOOP) += llite_lloop.o lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ - rw.o lproc_llite.o namei.o symlink.o llite_mmap.o \ + rw.o namei.o symlink.o llite_mmap.o \ xattr.o xattr_cache.o remote_perm.o llite_rmtacl.o llite_capa.o \ rw26.o super25.o statahead.o \ ../lclient/glimpse.o ../lclient/lcommon_cl.o ../lclient/lcommon_misc.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o +lustre-$(CONFIG_PROC_FS) += lproc_llite.o llite_lloop-y := lloop.o diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 10ffaf62e9d3..61bb69a80438 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -702,15 +702,22 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi); void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count); void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars); +void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, + struct ll_file_data *file, loff_t pos, + size_t count, int rw); #else static inline int lprocfs_register_mountpoint(struct proc_dir_entry *parent, struct super_block *sb, char *osc, char *mdc){return 0;} static inline void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi) {} -static void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count) {} -static void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars) +static inline +void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count) {} +static inline void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars) { memset(lvars, 0, sizeof(*lvars)); } +static inline void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, + struct ll_file_data *file, loff_t pos, + size_t count, int rw) {} #endif @@ -786,9 +793,6 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, struct md_open_data **mod); void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, struct lustre_handle *fh); -extern void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, - struct ll_file_data *file, loff_t pos, - size_t count, int rw); int ll_getattr_it(struct vfsmount *mnt, struct dentry *de, struct lookup_intent *it, struct kstat *stat); int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 154bdb235655..1a9678625af5 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -56,6 +56,7 @@ #include "llite_internal.h" struct kmem_cache *ll_file_data_slab; +struct proc_dir_entry *proc_lustre_fs_root; LIST_HEAD(ll_super_blocks); DEFINE_SPINLOCK(ll_sb_lock); diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 1ded16a0586e..a9a104a6a4ee 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -42,9 +42,6 @@ #include "llite_internal.h" -struct proc_dir_entry *proc_lustre_fs_root; - -#ifdef LPROCFS /* /proc/lustre/llite mount point registration */ extern struct file_operations vvp_dump_pgcache_file_ops; struct file_operations ll_rw_extents_stats_fops; @@ -1404,4 +1401,3 @@ void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars) lvars->module_vars = NULL; lvars->obd_vars = lprocfs_llite_obd_vars; } -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/lmv/Makefile b/drivers/staging/lustre/lustre/lmv/Makefile index 8cc81ade126c..9162ef724aea 100644 --- a/drivers/staging/lustre/lustre/lmv/Makefile +++ b/drivers/staging/lustre/lustre/lmv/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_LUSTRE_FS) += lmv.o -lmv-y := lmv_obd.o lmv_intent.o lmv_fld.o lproc_lmv.o - +lmv-y := lmv_obd.o lmv_intent.o lmv_fld.o +lmv-$(CONFIG_PROC_FS) += lproc_lmv.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index edb5a3a99d57..b355d01410e4 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -41,10 +41,6 @@ #include #include -#ifndef LPROCFS -static struct lprocfs_vars lprocfs_module_vars[] = { {0} }; -static struct lprocfs_vars lprocfs_obd_vars[] = { {0} }; -#else static int lmv_numobd_seq_show(struct seq_file *m, void *v) { struct obd_device *dev = (struct obd_device *)m->private; @@ -226,7 +222,6 @@ struct file_operations lmv_proc_target_fops = { .release = seq_release, }; -#endif /* LPROCFS */ void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars) { lvars->module_vars = lprocfs_lmv_module_vars; diff --git a/drivers/staging/lustre/lustre/lov/Makefile b/drivers/staging/lustre/lustre/lov/Makefile index 67eaec29bef1..9a5f26d5558d 100644 --- a/drivers/staging/lustre/lustre/lov/Makefile +++ b/drivers/staging/lustre/lustre/lov/Makefile @@ -1,8 +1,9 @@ obj-$(CONFIG_LUSTRE_FS) += lov.o -lov-y := lov_log.o lov_obd.o lov_pack.o lproc_lov.o lov_offset.o lov_merge.o \ +lov-y := lov_log.o lov_obd.o lov_pack.o lov_offset.o lov_merge.o \ lov_request.o lov_ea.o lov_dev.o lov_object.o lov_page.o \ lov_lock.o lov_io.o lovsub_dev.o lovsub_object.o lovsub_page.o \ lovsub_lock.o lovsub_io.o lov_pool.o +lov-$(CONFIG_PROC_FS) += lproc_lov.o diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 796da8930876..2b22a03c038e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -283,8 +283,8 @@ void lsm_free_plain(struct lov_stripe_md *lsm); int lovea_destroy_object(struct lov_obd *lov, struct lov_stripe_md *lsm, struct obdo *oa, void *data); /* lproc_lov.c */ -extern struct file_operations lov_proc_target_fops; #ifdef LPROCFS +extern const struct file_operations lov_proc_target_fops; void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars); #else static inline void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars) diff --git a/drivers/staging/lustre/lustre/lov/lproc_lov.c b/drivers/staging/lustre/lustre/lov/lproc_lov.c index e6f22e3a3a38..bd7da56b0713 100644 --- a/drivers/staging/lustre/lustre/lov/lproc_lov.c +++ b/drivers/staging/lustre/lustre/lov/lproc_lov.c @@ -41,7 +41,6 @@ #include #include "lov_internal.h" -#ifdef LPROCFS static int lov_stripesize_seq_show(struct seq_file *m, void *v) { struct obd_device *dev = (struct obd_device *)m->private; @@ -291,11 +290,10 @@ void lprocfs_lov_init_vars(struct lprocfs_static_vars *lvars) lvars->obd_vars = lprocfs_lov_obd_vars; } -struct file_operations lov_proc_target_fops = { +const struct file_operations lov_proc_target_fops = { .owner = THIS_MODULE, .open = lov_target_seq_open, .read = seq_read, .llseek = seq_lseek, .release = lprocfs_seq_release, }; -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/lvfs/Makefile b/drivers/staging/lustre/lustre/lvfs/Makefile index f50b1c574385..e0367c3fc416 100644 --- a/drivers/staging/lustre/lustre/lvfs/Makefile +++ b/drivers/staging/lustre/lustre/lvfs/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_LUSTRE_FS) += lvfs.o -lvfs-y := lvfs_linux.o fsfilt.o lvfs_lib.o +lvfs-y := lvfs_linux.o fsfilt.o +lvfs-$(CONFIG_PROC_FS) += lvfs_lib.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c b/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c index b21e40cdacab..7e47fc4a7e4e 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c @@ -43,7 +43,6 @@ #include #include -#ifdef LPROCFS void lprocfs_counter_add(struct lprocfs_stats *stats, int idx, long amount) { struct lprocfs_counter *percpu_cntr; @@ -169,4 +168,3 @@ int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid) return rc; } EXPORT_SYMBOL(lprocfs_stats_alloc_one); -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/mdc/Makefile b/drivers/staging/lustre/lustre/mdc/Makefile index 93bae242e761..4c0bed14de80 100644 --- a/drivers/staging/lustre/lustre/mdc/Makefile +++ b/drivers/staging/lustre/lustre/mdc/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += mdc.o -mdc-y := mdc_request.o mdc_reint.o lproc_mdc.o mdc_lib.o mdc_locks.o +mdc-y := mdc_request.o mdc_reint.o mdc_lib.o mdc_locks.o +mdc-$(CONFIG_PROC_FS) += lproc_mdc.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index e0b8f1866253..2663480a68c5 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -39,8 +39,6 @@ #include #include -#ifdef LPROCFS - static int mdc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v) { struct obd_device *dev = m->private; @@ -214,4 +212,3 @@ void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars) lvars->module_vars = lprocfs_mdc_module_vars; lvars->obd_vars = lprocfs_mdc_obd_vars; } -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/mgc/Makefile b/drivers/staging/lustre/lustre/mgc/Makefile index 267246344e1c..2f5ee649456d 100644 --- a/drivers/staging/lustre/lustre/mgc/Makefile +++ b/drivers/staging/lustre/lustre/mgc/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += mgc.o -mgc-y := mgc_request.o lproc_mgc.o +mgc-y := mgc_request.o +mgc-$(CONFIG_PROC_FS) += lproc_mgc.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/mgc/lproc_mgc.c b/drivers/staging/lustre/lustre/mgc/lproc_mgc.c index ebecec2b0078..1506af13f1bf 100644 --- a/drivers/staging/lustre/lustre/mgc/lproc_mgc.c +++ b/drivers/staging/lustre/lustre/mgc/lproc_mgc.c @@ -40,8 +40,6 @@ #include #include "mgc_internal.h" -#ifdef LPROCFS - LPROC_SEQ_FOPS_RO_TYPE(mgc, uuid); LPROC_SEQ_FOPS_RO_TYPE(mgc, connect_flags); LPROC_SEQ_FOPS_RO_TYPE(mgc, server_uuid); @@ -80,4 +78,3 @@ void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars) lvars->module_vars = lprocfs_mgc_module_vars; lvars->obd_vars = lprocfs_mgc_obd_vars; } -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/mgc/mgc_internal.h b/drivers/staging/lustre/lustre/mgc/mgc_internal.h index dbd698272a84..73b454898844 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_internal.h +++ b/drivers/staging/lustre/lustre/mgc/mgc_internal.h @@ -48,7 +48,7 @@ void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars); int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data); #else -static void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars) +static inline void lprocfs_mgc_init_vars(struct lprocfs_static_vars *lvars) { memset(lvars, 0, sizeof(*lvars)); } diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index f6e4bacc3a15..b32382088e96 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -397,6 +397,7 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg) return rc; } +#ifdef LPROCFS int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data) { struct obd_device *obd = data; @@ -420,6 +421,7 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data) return 0; } +#endif /* reenqueue any lost locks */ #define RQ_RUNNING 0x1 diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 5f8d9f2db277..c93131e0d2da 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -507,8 +507,15 @@ int obd_init_checks(void) } extern spinlock_t obd_types_lock; +#ifdef LPROCFS extern int class_procfs_init(void); extern int class_procfs_clean(void); +#else +static inline int class_procfs_init(void) +{ return 0; } +static inline int class_procfs_clean(void) +{ return 0; } +#endif static int __init init_obdclass(void) { diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 2efc43720ecb..a70ead1be6a9 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -295,9 +295,6 @@ struct lprocfs_vars lprocfs_base[] = { { "jobid_var", &obd_proc_jobid_var_fops }, { 0 } }; -#else -#define lprocfs_base NULL -#endif /* LPROCFS */ static void *obd_device_list_seq_start(struct seq_file *p, loff_t *pos) { @@ -403,3 +400,4 @@ int class_procfs_clean(void) } return 0; } +#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 882841923e5f..ec3b605dae6b 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -46,7 +46,179 @@ #include #include -#if defined(LPROCFS) +static const char * const obd_connect_names[] = { + "read_only", + "lov_index", + "unused", + "write_grant", + "server_lock", + "version", + "request_portal", + "acl", + "xattr", + "create_on_write", + "truncate_lock", + "initial_transno", + "inode_bit_locks", + "join_file(obsolete)", + "getattr_by_fid", + "no_oh_for_devices", + "remote_client", + "remote_client_by_force", + "max_byte_per_rpc", + "64bit_qdata", + "mds_capability", + "oss_capability", + "early_lock_cancel", + "som", + "adaptive_timeouts", + "lru_resize", + "mds_mds_connection", + "real_conn", + "change_qunit_size", + "alt_checksum_algorithm", + "fid_is_enabled", + "version_recovery", + "pools", + "grant_shrink", + "skip_orphan", + "large_ea", + "full20", + "layout_lock", + "64bithash", + "object_max_bytes", + "imp_recov", + "jobstats", + "umask", + "einprogress", + "grant_param", + "flock_owner", + "lvb_type", + "nanoseconds_times", + "lightweight_conn", + "short_io", + "pingless", + "unknown", + NULL +}; + +int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep) +{ + __u64 mask = 1; + int i, ret = 0; + + for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) { + if (flags & mask) + ret += snprintf(page + ret, count - ret, "%s%s", + ret ? sep : "", obd_connect_names[i]); + } + if (flags & ~(mask - 1)) + ret += snprintf(page + ret, count - ret, + "%sunknown flags "LPX64, + ret ? sep : "", flags & ~(mask - 1)); + return ret; +} +EXPORT_SYMBOL(obd_connect_flags2str); + +int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, + int mult) +{ + long decimal_val, frac_val; + int prtn; + + if (count < 10) + return -EINVAL; + + decimal_val = val / mult; + prtn = snprintf(buffer, count, "%ld", decimal_val); + frac_val = val % mult; + + if (prtn < (count - 4) && frac_val > 0) { + long temp_frac; + int i, temp_mult = 1, frac_bits = 0; + + temp_frac = frac_val * 10; + buffer[prtn++] = '.'; + while (frac_bits < 2 && (temp_frac / mult) < 1) { + /* only reserved 2 bits fraction */ + buffer[prtn++] = '0'; + temp_frac *= 10; + frac_bits++; + } + /* + * Need to think these cases : + * 1. #echo x.00 > /proc/xxx output result : x + * 2. #echo x.0x > /proc/xxx output result : x.0x + * 3. #echo x.x0 > /proc/xxx output result : x.x + * 4. #echo x.xx > /proc/xxx output result : x.xx + * Only reserved 2 bits fraction. + */ + for (i = 0; i < (5 - prtn); i++) + temp_mult *= 10; + + frac_bits = min((int)count - prtn, 3 - frac_bits); + prtn += snprintf(buffer + prtn, frac_bits, "%ld", + frac_val * temp_mult / mult); + + prtn--; + while (buffer[prtn] < '1' || buffer[prtn] > '9') { + prtn--; + if (buffer[prtn] == '.') { + prtn--; + break; + } + } + prtn++; + } + buffer[prtn++] = '\n'; + return prtn; +} +EXPORT_SYMBOL(lprocfs_read_frac_helper); + +int lprocfs_write_frac_helper(const char *buffer, unsigned long count, + int *val, int mult) +{ + char kernbuf[20], *end, *pbuf; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + + kernbuf[count] = '\0'; + pbuf = kernbuf; + if (*pbuf == '-') { + mult = -mult; + pbuf++; + } + + *val = (int)simple_strtoul(pbuf, &end, 10) * mult; + if (pbuf == end) + return -EINVAL; + + if (end != NULL && *end == '.') { + int temp_val, pow = 1; + int i; + + pbuf = end + 1; + if (strlen(pbuf) > 5) + pbuf[5] = '\0'; /*only allow 5bits fractional*/ + + temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult; + + if (pbuf < end) { + for (i = 0; i < (end - pbuf); i++) + pow *= 10; + + *val += temp_val / pow; + } + } + return 0; +} +EXPORT_SYMBOL(lprocfs_write_frac_helper); + +#ifdef LPROCFS static int lprocfs_no_percpu_stats = 0; module_param(lprocfs_no_percpu_stats, int, 0644); @@ -479,62 +651,6 @@ static int obd_import_flags2str(struct obd_import *imp, struct seq_file *m) } #undef flags2str -static const char *obd_connect_names[] = { - "read_only", - "lov_index", - "unused", - "write_grant", - "server_lock", - "version", - "request_portal", - "acl", - "xattr", - "create_on_write", - "truncate_lock", - "initial_transno", - "inode_bit_locks", - "join_file(obsolete)", - "getattr_by_fid", - "no_oh_for_devices", - "remote_client", - "remote_client_by_force", - "max_byte_per_rpc", - "64bit_qdata", - "mds_capability", - "oss_capability", - "early_lock_cancel", - "som", - "adaptive_timeouts", - "lru_resize", - "mds_mds_connection", - "real_conn", - "change_qunit_size", - "alt_checksum_algorithm", - "fid_is_enabled", - "version_recovery", - "pools", - "grant_shrink", - "skip_orphan", - "large_ea", - "full20", - "layout_lock", - "64bithash", - "object_max_bytes", - "imp_recov", - "jobstats", - "umask", - "einprogress", - "grant_param", - "flock_owner", - "lvb_type", - "nanoseconds_times", - "lightweight_conn", - "short_io", - "pingless", - "unknown", - NULL -}; - static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep) { __u64 mask = 1; @@ -553,24 +669,6 @@ static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep first ? sep : "", flags & ~(mask - 1)); } -int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep) -{ - __u64 mask = 1; - int i, ret = 0; - - for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) { - if (flags & mask) - ret += snprintf(page + ret, count - ret, "%s%s", - ret ? sep : "", obd_connect_names[i]); - } - if (flags & ~(mask - 1)) - ret += snprintf(page + ret, count - ret, - "%sunknown flags "LPX64, - ret ? sep : "", flags & ~(mask - 1)); - return ret; -} -EXPORT_SYMBOL(obd_connect_flags2str); - int lprocfs_rd_import(struct seq_file *m, void *data) { struct lprocfs_counter ret; @@ -1658,104 +1756,6 @@ int lprocfs_write_helper(const char *buffer, unsigned long count, } EXPORT_SYMBOL(lprocfs_write_helper); -int lprocfs_write_frac_helper(const char *buffer, unsigned long count, - int *val, int mult) -{ - char kernbuf[20], *end, *pbuf; - - if (count > (sizeof(kernbuf) - 1)) - return -EINVAL; - - if (copy_from_user(kernbuf, buffer, count)) - return -EFAULT; - - kernbuf[count] = '\0'; - pbuf = kernbuf; - if (*pbuf == '-') { - mult = -mult; - pbuf++; - } - - *val = (int)simple_strtoul(pbuf, &end, 10) * mult; - if (pbuf == end) - return -EINVAL; - - if (end != NULL && *end == '.') { - int temp_val, pow = 1; - int i; - - pbuf = end + 1; - if (strlen(pbuf) > 5) - pbuf[5] = '\0'; /*only allow 5bits fractional*/ - - temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult; - - if (pbuf < end) { - for (i = 0; i < (end - pbuf); i++) - pow *= 10; - - *val += temp_val / pow; - } - } - return 0; -} -EXPORT_SYMBOL(lprocfs_write_frac_helper); - -int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, - int mult) -{ - long decimal_val, frac_val; - int prtn; - - if (count < 10) - return -EINVAL; - - decimal_val = val / mult; - prtn = snprintf(buffer, count, "%ld", decimal_val); - frac_val = val % mult; - - if (prtn < (count - 4) && frac_val > 0) { - long temp_frac; - int i, temp_mult = 1, frac_bits = 0; - - temp_frac = frac_val * 10; - buffer[prtn++] = '.'; - while (frac_bits < 2 && (temp_frac / mult) < 1 ) { - /* only reserved 2 bits fraction */ - buffer[prtn++] ='0'; - temp_frac *= 10; - frac_bits++; - } - /* - * Need to think these cases : - * 1. #echo x.00 > /proc/xxx output result : x - * 2. #echo x.0x > /proc/xxx output result : x.0x - * 3. #echo x.x0 > /proc/xxx output result : x.x - * 4. #echo x.xx > /proc/xxx output result : x.xx - * Only reserved 2 bits fraction. - */ - for (i = 0; i < (5 - prtn); i++) - temp_mult *= 10; - - frac_bits = min((int)count - prtn, 3 - frac_bits); - prtn += snprintf(buffer + prtn, frac_bits, "%ld", - frac_val * temp_mult / mult); - - prtn--; - while(buffer[prtn] < '1' || buffer[prtn] > '9') { - prtn--; - if (buffer[prtn] == '.') { - prtn--; - break; - } - } - prtn++; - } - buffer[prtn++] ='\n'; - return prtn; -} -EXPORT_SYMBOL(lprocfs_read_frac_helper); - int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult) { long decimal_val, frac_val; @@ -1979,4 +1979,4 @@ int lprocfs_obd_rd_max_pages_per_rpc(struct seq_file *m, void *data) } EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc); -#endif /* LPROCFS*/ +#endif diff --git a/drivers/staging/lustre/lustre/osc/Makefile b/drivers/staging/lustre/lustre/osc/Makefile index bbd2f7707e9f..4488162d228a 100644 --- a/drivers/staging/lustre/lustre/osc/Makefile +++ b/drivers/staging/lustre/lustre/osc/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_LUSTRE_FS) += osc.o -osc-y := osc_request.o lproc_osc.o osc_dev.o osc_object.o \ +osc-y := osc_request.o osc_dev.o osc_object.o \ osc_page.o osc_lock.o osc_io.o osc_quota.o osc_cache.o +osc-$(CONFIG_PROC_FS) += lproc_osc.o diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index ef10e2af787f..0b59fc16c50c 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -42,7 +42,6 @@ #include #include "osc_internal.h" -#ifdef LPROCFS static int osc_active_seq_show(struct seq_file *m, void *v) { struct obd_device *dev = m->private; @@ -724,4 +723,3 @@ void lprocfs_osc_init_vars(struct lprocfs_static_vars *lvars) lvars->module_vars = lprocfs_osc_module_vars; lvars->obd_vars = lprocfs_osc_obd_vars; } -#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/Makefile b/drivers/staging/lustre/lustre/ptlrpc/Makefile index 2ec0c24ff38b..1c338aaf18a6 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/Makefile +++ b/drivers/staging/lustre/lustre/ptlrpc/Makefile @@ -12,10 +12,11 @@ ptlrpc_objs := client.o recover.o connection.o niobuf.o pack_generic.o ptlrpc_objs += events.o ptlrpc_module.o service.o pinger.o ptlrpc_objs += llog_net.o llog_client.o import.o ptlrpcd.o ptlrpc_objs += pers.o lproc_ptlrpc.o wiretest.o layout.o -ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o sec_lproc.o +ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o ptlrpc_objs += sec_null.o sec_plain.o nrs.o nrs_fifo.o ptlrpc-y := $(ldlm_objs) $(ptlrpc_objs) +ptlrpc-$(CONFIG_PROC_FS) += sec_lproc.o ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.o obj-$(CONFIG_PTLRPC_GSS) += gss/ diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index 5d0749cc4b0f..e3b5a920bca2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -259,8 +259,14 @@ void sptlrpc_enc_pool_fini(void); int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v); /* sec_lproc.c */ +#ifdef LPROCFS int sptlrpc_lproc_init(void); void sptlrpc_lproc_fini(void); +#else +static inline int sptlrpc_lproc_init(void) +{ return 0; } +static inline void sptlrpc_lproc_fini(void) {} +#endif /* sec_gc.c */ int sptlrpc_gc_init(void); -- cgit v1.2.3 From 58b179dcf28c672b89fbe0420684b3dbaec8330a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 3 Dec 2013 20:56:05 -0700 Subject: staging: dwc2: disable uframe_sched on the bcm2835 While Paul said that .uframe_sched should be enabled on the BCM2835, and doing so works fine with the built-in wired Ethernet, it prevents my WiFi dongle from operating correctly. Hence, disable the option so that everything works. Signed-off-by: Stephen Warren Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/platform.c b/drivers/staging/dwc2/platform.c index 28a78fe48453..d01d0d3f2cf0 100644 --- a/drivers/staging/dwc2/platform.c +++ b/drivers/staging/dwc2/platform.c @@ -72,7 +72,7 @@ static const struct dwc2_core_params params_bcm2835 = { .ts_dline = 0, .reload_ctl = 0, .ahbcfg = 0x10, - .uframe_sched = 1, + .uframe_sched = 0, }; /** -- cgit v1.2.3 From 2fd3f65132958e9ec95563cc981cc1ffca2b81a0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:27:58 +0900 Subject: USB: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-pci.c | 2 +- drivers/usb/gadget/amd5536udc.c | 2 +- drivers/usb/gadget/pch_udc.c | 2 +- drivers/usb/host/uhci-pci.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 31443aeedcdb..665686e7c8cd 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -182,7 +182,7 @@ static void dwc3_pci_remove(struct pci_dev *pci) pci_disable_device(pci); } -static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { +static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 54a1e2954cea..f0ff4a675e9d 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3338,7 +3338,7 @@ static int udc_remote_wakeup(struct udc *dev) } /* PCI device parameters */ -static DEFINE_PCI_DEVICE_TABLE(pci_id) = { +static const struct pci_device_id pci_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096), .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 32d5e923750b..78a3d9289816 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -3210,7 +3210,7 @@ finished: return retval; } -static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { +static const struct pci_device_id pch_udc_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c index 4cd79888804b..940304c33224 100644 --- a/drivers/usb/host/uhci-pci.c +++ b/drivers/usb/host/uhci-pci.c @@ -279,7 +279,7 @@ static const struct hc_driver uhci_driver = { .hub_control = uhci_hub_control, }; -static DEFINE_PCI_DEVICE_TABLE(uhci_pci_ids) = { { +static const struct pci_device_id uhci_pci_ids[] = { { /* handle any USB UHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0), .driver_data = (unsigned long) &uhci_driver, -- cgit v1.2.3 From 3459f11a8b16f40f9cde8e4281c2d5dd2ff1a732 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 5 Dec 2013 13:04:10 +1030 Subject: virtio_balloon: update_balloon_size(): update correct field According to the virtio spec, the device configuration field that should be updated after an inflation or deflation operation is the 'actual' field, not the 'num_pages' one. Commit 855e0c5288177bcb193f6f6316952d2490478e1c swapped them in update_balloon_size(). Fix it. Signed-off-by: Luiz Capitulino Signed-off-by: Rusty Russell Fixes: 855e0c5288177bcb193f6f6316952d2490478e1c --- drivers/virtio/virtio_balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index c444654fc33f..5c4a95b516cf 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -285,7 +285,7 @@ static void update_balloon_size(struct virtio_balloon *vb) { __le32 actual = cpu_to_le32(vb->num_pages); - virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages, + virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual, &actual); } -- cgit v1.2.3 From 94459a975b7d4d70c20df1a32d63825469b8d4cc Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 29 Nov 2013 18:00:35 -0500 Subject: drivers/misc/ti-st: Prefer tty_driver_flush_buffer The tty core provides an interface for flushing the driver's write buffer: tty_driver_flush_buffer(); prefer the provided interface over open-coded. Open-coding can lead to errors such as the duplicated call in the st_kim driver. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_core.c | 2 +- drivers/misc/ti-st/st_kim.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 8d64b681dd93..3aed525e55b4 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -812,7 +812,7 @@ static void st_tty_flush_buffer(struct tty_struct *tty) kfree_skb(st_gdata->tx_skb); st_gdata->tx_skb = NULL; - tty->ops->flush_buffer(tty); + tty_driver_flush_buffer(tty); return; } diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 96853a09788a..9d3dbb28734b 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -531,7 +531,6 @@ long st_kim_stop(void *kim_data) /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); - tty->ops->flush_buffer(tty); } /* send uninstall notification to UIM */ -- cgit v1.2.3 From 612340b155290ac02a047bbb073a31ae4cfffdd8 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 12:29:35 +0900 Subject: misc: eeprom_93xx46: remove unnecessary spi_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 3a015abb444a..78e55b501c94 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -378,7 +378,6 @@ static int eeprom_93xx46_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_erase); sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin); - spi_set_drvdata(spi, NULL); kfree(edev); return 0; } -- cgit v1.2.3 From c07f85c5d7d490653967ded4b78230372f67970d Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 30 Nov 2013 16:26:00 +0100 Subject: misc: bmp085: Clean up and enable use of interrupt for completion. - pass IRQ to driver and have it initialize - finish waiting early if interrupt fires Signed-off-by: NeilBrown Signed-off-by: H. Nikolaus Schaller Signed-off-by: Marek Belisko Signed-off-by: Greg Kroah-Hartman --- drivers/misc/bmp085-i2c.c | 2 +- drivers/misc/bmp085-spi.c | 2 +- drivers/misc/bmp085.c | 39 ++++++++++++++++++++++++++++++++++----- drivers/misc/bmp085.h | 2 +- 4 files changed, 37 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c index 3abfcecf8424..a7c16295b816 100644 --- a/drivers/misc/bmp085-i2c.c +++ b/drivers/misc/bmp085-i2c.c @@ -49,7 +49,7 @@ static int bmp085_i2c_probe(struct i2c_client *client, return err; } - return bmp085_probe(&client->dev, regmap); + return bmp085_probe(&client->dev, regmap, client->irq); } static int bmp085_i2c_remove(struct i2c_client *client) diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c index d6a52659cf24..864ecac32373 100644 --- a/drivers/misc/bmp085-spi.c +++ b/drivers/misc/bmp085-spi.c @@ -41,7 +41,7 @@ static int bmp085_spi_probe(struct spi_device *client) return err; } - return bmp085_probe(&client->dev, regmap); + return bmp085_probe(&client->dev, regmap, client->irq); } static int bmp085_spi_remove(struct spi_device *client) diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c index 2704d885a9b3..820e53d0048f 100644 --- a/drivers/misc/bmp085.c +++ b/drivers/misc/bmp085.c @@ -49,9 +49,11 @@ #include #include #include -#include #include #include "bmp085.h" +#include +#include +#include #define BMP085_CHIP_ID 0x55 #define BMP085_CALIBRATION_DATA_START 0xAA @@ -84,8 +86,19 @@ struct bmp085_data { unsigned long last_temp_measurement; u8 chip_id; s32 b6; /* calculated temperature correction coefficient */ + int irq; + struct completion done; }; +static irqreturn_t bmp085_eoc_isr(int irq, void *devid) +{ + struct bmp085_data *data = devid; + + complete(&data->done); + + return IRQ_HANDLED; +} + static s32 bmp085_read_calibration_data(struct bmp085_data *data) { u16 tmp[BMP085_CALIBRATION_DATA_LENGTH]; @@ -116,6 +129,9 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data) s32 status; mutex_lock(&data->lock); + + init_completion(&data->done); + status = regmap_write(data->regmap, BMP085_CTRL_REG, BMP085_TEMP_MEASUREMENT); if (status < 0) { @@ -123,7 +139,8 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data) "Error while requesting temperature measurement.\n"); goto exit; } - msleep(BMP085_TEMP_CONVERSION_TIME); + wait_for_completion_timeout(&data->done, 1 + msecs_to_jiffies( + BMP085_TEMP_CONVERSION_TIME)); status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, &tmp, sizeof(tmp)); @@ -147,6 +164,9 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data) s32 status; mutex_lock(&data->lock); + + init_completion(&data->done); + status = regmap_write(data->regmap, BMP085_CTRL_REG, BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting << 6)); @@ -157,8 +177,8 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data) } /* wait for the end of conversion */ - msleep(2+(3 << data->oversampling_setting)); - + wait_for_completion_timeout(&data->done, 1 + msecs_to_jiffies( + 2+(3 << data->oversampling_setting))); /* copy data into a u32 (4 bytes), but skip the first byte. */ status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, ((u8 *)&tmp)+1, 3); @@ -420,7 +440,7 @@ struct regmap_config bmp085_regmap_config = { }; EXPORT_SYMBOL_GPL(bmp085_regmap_config); -int bmp085_probe(struct device *dev, struct regmap *regmap) +int bmp085_probe(struct device *dev, struct regmap *regmap, int irq) { struct bmp085_data *data; int err = 0; @@ -434,6 +454,15 @@ int bmp085_probe(struct device *dev, struct regmap *regmap) dev_set_drvdata(dev, data); data->dev = dev; data->regmap = regmap; + data->irq = irq; + + if (data->irq > 0) { + err = devm_request_irq(dev, data->irq, bmp085_eoc_isr, + IRQF_TRIGGER_RISING, "bmp085", + data); + if (err < 0) + goto exit_free; + } /* Initialize the BMP085 chip */ err = bmp085_init_client(data); diff --git a/drivers/misc/bmp085.h b/drivers/misc/bmp085.h index 2b8f615bca92..8b8e3b1f5ca5 100644 --- a/drivers/misc/bmp085.h +++ b/drivers/misc/bmp085.h @@ -26,7 +26,7 @@ extern struct regmap_config bmp085_regmap_config; -int bmp085_probe(struct device *dev, struct regmap *regmap); +int bmp085_probe(struct device *dev, struct regmap *regmap, int irq); int bmp085_remove(struct device *dev); int bmp085_detect(struct device *dev); -- cgit v1.2.3 From 2e30d14f12421f39329faefd5ae92b02cc9ff255 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Wed, 4 Dec 2013 20:36:31 -0800 Subject: USB: fix coccinelle warnings drivers/usb/host/ehci-mv.c:181:26-27: WARNING comparing pointer to 0, suggest !E /c/kernel-tests/src/cocci/drivers/usb/host/ehci-mv.c:181:26-27: WARNING comparing pointer to 0 Compare pointer-typed values to NULL rather than 0 Semantic patch information: This makes an effort to choose between !x and x == NULL. !x is used if it has previously been used with the function used to initialize x. This relies on type information. More type information can be obtained using the option -all_includes and the option -I to specify an include path. Generated by: coccinelle/null/badzero.cocci CC: Jingoo Han CC: Greg Kroah-Hartman Signed-off-by: Fengguang Wu --- drivers/usb/host/ehci-mv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 417c10da9450..6e8afcaa8ff0 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -178,7 +178,7 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); - if (ehci_mv->phy_regs == 0) { + if (!ehci_mv->phy_regs) { dev_err(&pdev->dev, "failed to map phy I/O memory\n"); retval = -EFAULT; goto err_put_hcd; -- cgit v1.2.3 From 8bb61fe1d03123a625265d599a22fb12af79e1ae Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:14 +0100 Subject: powerpc/windfarm: Remove superfluous name casts wf_sensor.name is "const char *" Signed-off-by: Geert Uytterhoeven Cc: Benjamin Herrenschmidt Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/windfarm_lm75_sensor.c | 2 +- drivers/macintosh/windfarm_max6690_sensor.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 9ef32b3df91f..590214ba736c 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -133,7 +133,7 @@ static int wf_lm75_probe(struct i2c_client *client, lm->inited = 0; lm->ds1775 = ds1775; lm->i2c = client; - lm->sens.name = (char *)name; /* XXX fix constness in structure */ + lm->sens.name = name; lm->sens.ops = &wf_lm75_ops; i2c_set_clientdata(client, lm); diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index 945a25b2f31e..87e439b10318 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -95,7 +95,7 @@ static int wf_max6690_probe(struct i2c_client *client, } max->i2c = client; - max->sens.name = (char *)name; /* XXX fix constness in structure */ + max->sens.name = name; max->sens.ops = &wf_max6690_ops; i2c_set_clientdata(client, max); -- cgit v1.2.3 From 5b1ada83bae7d689cf1fe76eb1bdd058ea84a97c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Dec 2013 00:29:57 +0000 Subject: regulator: gpio: Don't require a regulator-type property Since essentially all GPIO controlled regulators are voltage regulators make the regulator-type property optional, defaulting to voltage. Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index bcd827c363dc..cdb9d947d914 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -203,17 +203,15 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) } config->nr_states = i; + config->type = REGULATOR_VOLTAGE; ret = of_property_read_string(np, "regulator-type", ®type); - if (ret < 0) { - dev_err(dev, "Missing 'regulator-type' property\n"); - return ERR_PTR(-EINVAL); + if (ret >= 0) { + if (!strncmp("voltage", regtype, 7)) + config->type = REGULATOR_VOLTAGE; + else if (!strncmp("current", regtype, 7)) + config->type = REGULATOR_CURRENT; } - if (!strncmp("voltage", regtype, 7)) - config->type = REGULATOR_VOLTAGE; - else if (!strncmp("current", regtype, 7)) - config->type = REGULATOR_CURRENT; - return config; } -- cgit v1.2.3 From ce58c32b106efbe228b33b65f1ef6ab505fb7840 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2013 11:26:07 -0200 Subject: drm/i915: Do hw quiescing first during unload If we force the hw to idle as our first step during unload, we can abort the unload upon failure. Later we can probe whether the hardware remain active even after we try to shut it down. Signed-off-by: Chris Wilson Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 89e4cf1bb073..a5d010c86368 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1702,6 +1702,12 @@ int i915_driver_unload(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; + ret = i915_gem_suspend(dev); + if (ret) { + DRM_ERROR("failed to idle hardware: %d\n", ret); + return ret; + } + intel_gpu_ips_teardown(); /* The i915.ko module is still not prepared to be loaded when @@ -1715,10 +1721,6 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->mm.inactive_shrinker.scan_objects) unregister_shrinker(&dev_priv->mm.inactive_shrinker); - ret = i915_gem_suspend(dev); - if (ret) - DRM_ERROR("failed to idle hardware: %d\n", ret); - io_mapping_free(dev_priv->gtt.mappable); arch_phys_wc_del(dev_priv->gtt.mtrr); -- cgit v1.2.3 From 63b945091a070d8d4275dc0f7699ba22cd5f9435 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:16 -0600 Subject: crypto: ccp - CCP device driver and interface support These routines provide the device driver support for the AMD Cryptographic Coprocessor (CCP). Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev.c | 582 ++++++++++++ drivers/crypto/ccp/ccp-dev.h | 272 ++++++ drivers/crypto/ccp/ccp-ops.c | 2020 ++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-pci.c | 360 ++++++++ include/linux/ccp.h | 525 +++++++++++ 5 files changed, 3759 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-dev.c create mode 100644 drivers/crypto/ccp/ccp-dev.h create mode 100644 drivers/crypto/ccp/ccp-ops.c create mode 100644 drivers/crypto/ccp/ccp-pci.c create mode 100644 include/linux/ccp.h (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c new file mode 100644 index 000000000000..de59df970176 --- /dev/null +++ b/drivers/crypto/ccp/ccp-dev.c @@ -0,0 +1,582 @@ +/* + * AMD Cryptographic Coprocessor (CCP) driver + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-dev.h" + +MODULE_AUTHOR("Tom Lendacky "); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0.0"); +MODULE_DESCRIPTION("AMD Cryptographic Coprocessor driver"); + + +static struct ccp_device *ccp_dev; +static inline struct ccp_device *ccp_get_device(void) +{ + return ccp_dev; +} + +static inline void ccp_add_device(struct ccp_device *ccp) +{ + ccp_dev = ccp; +} + +static inline void ccp_del_device(struct ccp_device *ccp) +{ + ccp_dev = NULL; +} + +/** + * ccp_enqueue_cmd - queue an operation for processing by the CCP + * + * @cmd: ccp_cmd struct to be processed + * + * Queue a cmd to be processed by the CCP. If queueing the cmd + * would exceed the defined length of the cmd queue the cmd will + * only be queued if the CCP_CMD_MAY_BACKLOG flag is set and will + * result in a return code of -EBUSY. + * + * The callback routine specified in the ccp_cmd struct will be + * called to notify the caller of completion (if the cmd was not + * backlogged) or advancement out of the backlog. If the cmd has + * advanced out of the backlog the "err" value of the callback + * will be -EINPROGRESS. Any other "err" value during callback is + * the result of the operation. + * + * The cmd has been successfully queued if: + * the return code is -EINPROGRESS or + * the return code is -EBUSY and CCP_CMD_MAY_BACKLOG flag is set + */ +int ccp_enqueue_cmd(struct ccp_cmd *cmd) +{ + struct ccp_device *ccp = ccp_get_device(); + unsigned long flags; + unsigned int i; + int ret; + + if (!ccp) + return -ENODEV; + + /* Caller must supply a callback routine */ + if (!cmd->callback) + return -EINVAL; + + cmd->ccp = ccp; + + spin_lock_irqsave(&ccp->cmd_lock, flags); + + i = ccp->cmd_q_count; + + if (ccp->cmd_count >= MAX_CMD_QLEN) { + ret = -EBUSY; + if (cmd->flags & CCP_CMD_MAY_BACKLOG) + list_add_tail(&cmd->entry, &ccp->backlog); + } else { + ret = -EINPROGRESS; + ccp->cmd_count++; + list_add_tail(&cmd->entry, &ccp->cmd); + + /* Find an idle queue */ + if (!ccp->suspending) { + for (i = 0; i < ccp->cmd_q_count; i++) { + if (ccp->cmd_q[i].active) + continue; + + break; + } + } + } + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + + /* If we found an idle queue, wake it up */ + if (i < ccp->cmd_q_count) + wake_up_process(ccp->cmd_q[i].kthread); + + return ret; +} +EXPORT_SYMBOL_GPL(ccp_enqueue_cmd); + +static void ccp_do_cmd_backlog(struct work_struct *work) +{ + struct ccp_cmd *cmd = container_of(work, struct ccp_cmd, work); + struct ccp_device *ccp = cmd->ccp; + unsigned long flags; + unsigned int i; + + cmd->callback(cmd->data, -EINPROGRESS); + + spin_lock_irqsave(&ccp->cmd_lock, flags); + + ccp->cmd_count++; + list_add_tail(&cmd->entry, &ccp->cmd); + + /* Find an idle queue */ + for (i = 0; i < ccp->cmd_q_count; i++) { + if (ccp->cmd_q[i].active) + continue; + + break; + } + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + + /* If we found an idle queue, wake it up */ + if (i < ccp->cmd_q_count) + wake_up_process(ccp->cmd_q[i].kthread); +} + +static struct ccp_cmd *ccp_dequeue_cmd(struct ccp_cmd_queue *cmd_q) +{ + struct ccp_device *ccp = cmd_q->ccp; + struct ccp_cmd *cmd = NULL; + struct ccp_cmd *backlog = NULL; + unsigned long flags; + + spin_lock_irqsave(&ccp->cmd_lock, flags); + + cmd_q->active = 0; + + if (ccp->suspending) { + cmd_q->suspended = 1; + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + wake_up_interruptible(&ccp->suspend_queue); + + return NULL; + } + + if (ccp->cmd_count) { + cmd_q->active = 1; + + cmd = list_first_entry(&ccp->cmd, struct ccp_cmd, entry); + list_del(&cmd->entry); + + ccp->cmd_count--; + } + + if (!list_empty(&ccp->backlog)) { + backlog = list_first_entry(&ccp->backlog, struct ccp_cmd, + entry); + list_del(&backlog->entry); + } + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + + if (backlog) { + INIT_WORK(&backlog->work, ccp_do_cmd_backlog); + schedule_work(&backlog->work); + } + + return cmd; +} + +static void ccp_do_cmd_complete(struct work_struct *work) +{ + struct ccp_cmd *cmd = container_of(work, struct ccp_cmd, work); + + cmd->callback(cmd->data, cmd->ret); +} + +static int ccp_cmd_queue_thread(void *data) +{ + struct ccp_cmd_queue *cmd_q = (struct ccp_cmd_queue *)data; + struct ccp_cmd *cmd; + + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + schedule(); + + set_current_state(TASK_INTERRUPTIBLE); + + cmd = ccp_dequeue_cmd(cmd_q); + if (!cmd) + continue; + + __set_current_state(TASK_RUNNING); + + /* Execute the command */ + cmd->ret = ccp_run_cmd(cmd_q, cmd); + + /* Schedule the completion callback */ + INIT_WORK(&cmd->work, ccp_do_cmd_complete); + schedule_work(&cmd->work); + } + + __set_current_state(TASK_RUNNING); + + return 0; +} + +static int ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) +{ + struct ccp_device *ccp = container_of(rng, struct ccp_device, hwrng); + u32 trng_value; + int len = min_t(int, sizeof(trng_value), max); + + /* + * Locking is provided by the caller so we can update device + * hwrng-related fields safely + */ + trng_value = ioread32(ccp->io_regs + TRNG_OUT_REG); + if (!trng_value) { + /* Zero is returned if not data is available or if a + * bad-entropy error is present. Assume an error if + * we exceed TRNG_RETRIES reads of zero. + */ + if (ccp->hwrng_retries++ > TRNG_RETRIES) + return -EIO; + + return 0; + } + + /* Reset the counter and save the rng value */ + ccp->hwrng_retries = 0; + memcpy(data, &trng_value, len); + + return len; +} + +/** + * ccp_alloc_struct - allocate and initialize the ccp_device struct + * + * @dev: device struct of the CCP + */ +struct ccp_device *ccp_alloc_struct(struct device *dev) +{ + struct ccp_device *ccp; + + ccp = kzalloc(sizeof(*ccp), GFP_KERNEL); + if (ccp == NULL) { + dev_err(dev, "unable to allocate device struct\n"); + return NULL; + } + ccp->dev = dev; + + INIT_LIST_HEAD(&ccp->cmd); + INIT_LIST_HEAD(&ccp->backlog); + + spin_lock_init(&ccp->cmd_lock); + mutex_init(&ccp->req_mutex); + mutex_init(&ccp->ksb_mutex); + ccp->ksb_count = KSB_COUNT; + ccp->ksb_start = 0; + + return ccp; +} + +/** + * ccp_init - initialize the CCP device + * + * @ccp: ccp_device struct + */ +int ccp_init(struct ccp_device *ccp) +{ + struct device *dev = ccp->dev; + struct ccp_cmd_queue *cmd_q; + struct dma_pool *dma_pool; + char dma_pool_name[MAX_DMAPOOL_NAME_LEN]; + unsigned int qmr, qim, i; + int ret; + + /* Find available queues */ + qim = 0; + qmr = ioread32(ccp->io_regs + Q_MASK_REG); + for (i = 0; i < MAX_HW_QUEUES; i++) { + if (!(qmr & (1 << i))) + continue; + + /* Allocate a dma pool for this queue */ + snprintf(dma_pool_name, sizeof(dma_pool_name), "ccp_q%d", i); + dma_pool = dma_pool_create(dma_pool_name, dev, + CCP_DMAPOOL_MAX_SIZE, + CCP_DMAPOOL_ALIGN, 0); + if (!dma_pool) { + dev_err(dev, "unable to allocate dma pool\n"); + ret = -ENOMEM; + goto e_pool; + } + + cmd_q = &ccp->cmd_q[ccp->cmd_q_count]; + ccp->cmd_q_count++; + + cmd_q->ccp = ccp; + cmd_q->id = i; + cmd_q->dma_pool = dma_pool; + + /* Reserve 2 KSB regions for the queue */ + cmd_q->ksb_key = KSB_START + ccp->ksb_start++; + cmd_q->ksb_ctx = KSB_START + ccp->ksb_start++; + ccp->ksb_count -= 2; + + /* Preset some register values and masks that are queue + * number dependent + */ + cmd_q->reg_status = ccp->io_regs + CMD_Q_STATUS_BASE + + (CMD_Q_STATUS_INCR * i); + cmd_q->reg_int_status = ccp->io_regs + CMD_Q_INT_STATUS_BASE + + (CMD_Q_STATUS_INCR * i); + cmd_q->int_ok = 1 << (i * 2); + cmd_q->int_err = 1 << ((i * 2) + 1); + + cmd_q->free_slots = CMD_Q_DEPTH(ioread32(cmd_q->reg_status)); + + init_waitqueue_head(&cmd_q->int_queue); + + /* Build queue interrupt mask (two interrupts per queue) */ + qim |= cmd_q->int_ok | cmd_q->int_err; + + dev_dbg(dev, "queue #%u available\n", i); + } + if (ccp->cmd_q_count == 0) { + dev_notice(dev, "no command queues available\n"); + ret = -EIO; + goto e_pool; + } + dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count); + + /* Disable and clear interrupts until ready */ + iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG); + for (i = 0; i < ccp->cmd_q_count; i++) { + cmd_q = &ccp->cmd_q[i]; + + ioread32(cmd_q->reg_int_status); + ioread32(cmd_q->reg_status); + } + iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG); + + /* Request an irq */ + ret = ccp->get_irq(ccp); + if (ret) { + dev_err(dev, "unable to allocate an IRQ\n"); + goto e_pool; + } + + /* Initialize the queues used to wait for KSB space and suspend */ + init_waitqueue_head(&ccp->ksb_queue); + init_waitqueue_head(&ccp->suspend_queue); + + /* Create a kthread for each queue */ + for (i = 0; i < ccp->cmd_q_count; i++) { + struct task_struct *kthread; + + cmd_q = &ccp->cmd_q[i]; + + kthread = kthread_create(ccp_cmd_queue_thread, cmd_q, + "ccp-q%u", cmd_q->id); + if (IS_ERR(kthread)) { + dev_err(dev, "error creating queue thread (%ld)\n", + PTR_ERR(kthread)); + ret = PTR_ERR(kthread); + goto e_kthread; + } + + cmd_q->kthread = kthread; + wake_up_process(kthread); + } + + /* Register the RNG */ + ccp->hwrng.name = "ccp-rng"; + ccp->hwrng.read = ccp_trng_read; + ret = hwrng_register(&ccp->hwrng); + if (ret) { + dev_err(dev, "error registering hwrng (%d)\n", ret); + goto e_kthread; + } + + /* Make the device struct available before enabling interrupts */ + ccp_add_device(ccp); + + /* Enable interrupts */ + iowrite32(qim, ccp->io_regs + IRQ_MASK_REG); + + return 0; + +e_kthread: + for (i = 0; i < ccp->cmd_q_count; i++) + if (ccp->cmd_q[i].kthread) + kthread_stop(ccp->cmd_q[i].kthread); + + ccp->free_irq(ccp); + +e_pool: + for (i = 0; i < ccp->cmd_q_count; i++) + dma_pool_destroy(ccp->cmd_q[i].dma_pool); + + return ret; +} + +/** + * ccp_destroy - tear down the CCP device + * + * @ccp: ccp_device struct + */ +void ccp_destroy(struct ccp_device *ccp) +{ + struct ccp_cmd_queue *cmd_q; + struct ccp_cmd *cmd; + unsigned int qim, i; + + /* Remove general access to the device struct */ + ccp_del_device(ccp); + + /* Unregister the RNG */ + hwrng_unregister(&ccp->hwrng); + + /* Stop the queue kthreads */ + for (i = 0; i < ccp->cmd_q_count; i++) + if (ccp->cmd_q[i].kthread) + kthread_stop(ccp->cmd_q[i].kthread); + + /* Build queue interrupt mask (two interrupt masks per queue) */ + qim = 0; + for (i = 0; i < ccp->cmd_q_count; i++) { + cmd_q = &ccp->cmd_q[i]; + qim |= cmd_q->int_ok | cmd_q->int_err; + } + + /* Disable and clear interrupts */ + iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG); + for (i = 0; i < ccp->cmd_q_count; i++) { + cmd_q = &ccp->cmd_q[i]; + + ioread32(cmd_q->reg_int_status); + ioread32(cmd_q->reg_status); + } + iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG); + + ccp->free_irq(ccp); + + for (i = 0; i < ccp->cmd_q_count; i++) + dma_pool_destroy(ccp->cmd_q[i].dma_pool); + + /* Flush the cmd and backlog queue */ + while (!list_empty(&ccp->cmd)) { + /* Invoke the callback directly with an error code */ + cmd = list_first_entry(&ccp->cmd, struct ccp_cmd, entry); + list_del(&cmd->entry); + cmd->callback(cmd->data, -ENODEV); + } + while (!list_empty(&ccp->backlog)) { + /* Invoke the callback directly with an error code */ + cmd = list_first_entry(&ccp->backlog, struct ccp_cmd, entry); + list_del(&cmd->entry); + cmd->callback(cmd->data, -ENODEV); + } +} + +/** + * ccp_irq_handler - handle interrupts generated by the CCP device + * + * @irq: the irq associated with the interrupt + * @data: the data value supplied when the irq was created + */ +irqreturn_t ccp_irq_handler(int irq, void *data) +{ + struct device *dev = data; + struct ccp_device *ccp = dev_get_drvdata(dev); + struct ccp_cmd_queue *cmd_q; + u32 q_int, status; + unsigned int i; + + status = ioread32(ccp->io_regs + IRQ_STATUS_REG); + + for (i = 0; i < ccp->cmd_q_count; i++) { + cmd_q = &ccp->cmd_q[i]; + + q_int = status & (cmd_q->int_ok | cmd_q->int_err); + if (q_int) { + cmd_q->int_status = status; + cmd_q->q_status = ioread32(cmd_q->reg_status); + cmd_q->q_int_status = ioread32(cmd_q->reg_int_status); + + /* On error, only save the first error value */ + if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error) + cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status); + + cmd_q->int_rcvd = 1; + + /* Acknowledge the interrupt and wake the kthread */ + iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG); + wake_up_interruptible(&cmd_q->int_queue); + } + } + + return IRQ_HANDLED; +} + +#ifdef CONFIG_PM +bool ccp_queues_suspended(struct ccp_device *ccp) +{ + unsigned int suspended = 0; + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&ccp->cmd_lock, flags); + + for (i = 0; i < ccp->cmd_q_count; i++) + if (ccp->cmd_q[i].suspended) + suspended++; + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + + return ccp->cmd_q_count == suspended; +} +#endif + +static const struct x86_cpu_id ccp_support[] = { + { X86_VENDOR_AMD, 22, }, +}; + +static int __init ccp_mod_init(void) +{ + struct cpuinfo_x86 *cpuinfo = &boot_cpu_data; + + if (!x86_match_cpu(ccp_support)) + return -ENODEV; + + switch (cpuinfo->x86) { + case 22: + if ((cpuinfo->x86_model < 48) || (cpuinfo->x86_model > 63)) + return -ENODEV; + return ccp_pci_init(); + break; + }; + + return -ENODEV; +} + +static void __exit ccp_mod_exit(void) +{ + struct cpuinfo_x86 *cpuinfo = &boot_cpu_data; + + switch (cpuinfo->x86) { + case 22: + ccp_pci_exit(); + break; + }; +} + +module_init(ccp_mod_init); +module_exit(ccp_mod_exit); diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h new file mode 100644 index 000000000000..7ec536e702ec --- /dev/null +++ b/drivers/crypto/ccp/ccp-dev.h @@ -0,0 +1,272 @@ +/* + * AMD Cryptographic Coprocessor (CCP) driver + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __CCP_DEV_H__ +#define __CCP_DEV_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define IO_OFFSET 0x20000 + +#define MAX_DMAPOOL_NAME_LEN 32 + +#define MAX_HW_QUEUES 5 +#define MAX_CMD_QLEN 100 + +#define TRNG_RETRIES 10 + + +/****** Register Mappings ******/ +#define Q_MASK_REG 0x000 +#define TRNG_OUT_REG 0x00c +#define IRQ_MASK_REG 0x040 +#define IRQ_STATUS_REG 0x200 + +#define DEL_CMD_Q_JOB 0x124 +#define DEL_Q_ACTIVE 0x00000200 +#define DEL_Q_ID_SHIFT 6 + +#define CMD_REQ0 0x180 +#define CMD_REQ_INCR 0x04 + +#define CMD_Q_STATUS_BASE 0x210 +#define CMD_Q_INT_STATUS_BASE 0x214 +#define CMD_Q_STATUS_INCR 0x20 + +#define CMD_Q_CACHE 0x228 +#define CMD_Q_CACHE_INC 0x20 + +#define CMD_Q_ERROR(__qs) ((__qs) & 0x0000003f); +#define CMD_Q_DEPTH(__qs) (((__qs) >> 12) & 0x0000000f); + +/****** REQ0 Related Values ******/ +#define REQ0_WAIT_FOR_WRITE 0x00000004 +#define REQ0_INT_ON_COMPLETE 0x00000002 +#define REQ0_STOP_ON_COMPLETE 0x00000001 + +#define REQ0_CMD_Q_SHIFT 9 +#define REQ0_JOBID_SHIFT 3 + +/****** REQ1 Related Values ******/ +#define REQ1_PROTECT_SHIFT 27 +#define REQ1_ENGINE_SHIFT 23 +#define REQ1_KEY_KSB_SHIFT 2 + +#define REQ1_EOM 0x00000002 +#define REQ1_INIT 0x00000001 + +/* AES Related Values */ +#define REQ1_AES_TYPE_SHIFT 21 +#define REQ1_AES_MODE_SHIFT 18 +#define REQ1_AES_ACTION_SHIFT 17 +#define REQ1_AES_CFB_SIZE_SHIFT 10 + +/* XTS-AES Related Values */ +#define REQ1_XTS_AES_SIZE_SHIFT 10 + +/* SHA Related Values */ +#define REQ1_SHA_TYPE_SHIFT 21 + +/* RSA Related Values */ +#define REQ1_RSA_MOD_SIZE_SHIFT 10 + +/* Pass-Through Related Values */ +#define REQ1_PT_BW_SHIFT 12 +#define REQ1_PT_BS_SHIFT 10 + +/* ECC Related Values */ +#define REQ1_ECC_AFFINE_CONVERT 0x00200000 +#define REQ1_ECC_FUNCTION_SHIFT 18 + +/****** REQ4 Related Values ******/ +#define REQ4_KSB_SHIFT 18 +#define REQ4_MEMTYPE_SHIFT 16 + +/****** REQ6 Related Values ******/ +#define REQ6_MEMTYPE_SHIFT 16 + + +/****** Key Storage Block ******/ +#define KSB_START 77 +#define KSB_END 127 +#define KSB_COUNT (KSB_END - KSB_START + 1) +#define CCP_KSB_BITS 256 +#define CCP_KSB_BYTES 32 + +#define CCP_JOBID_MASK 0x0000003f + +#define CCP_DMAPOOL_MAX_SIZE 64 +#define CCP_DMAPOOL_ALIGN (1 << 5) + +#define CCP_REVERSE_BUF_SIZE 64 + +#define CCP_AES_KEY_KSB_COUNT 1 +#define CCP_AES_CTX_KSB_COUNT 1 + +#define CCP_XTS_AES_KEY_KSB_COUNT 1 +#define CCP_XTS_AES_CTX_KSB_COUNT 1 + +#define CCP_SHA_KSB_COUNT 1 + +#define CCP_RSA_MAX_WIDTH 4096 + +#define CCP_PASSTHRU_BLOCKSIZE 256 +#define CCP_PASSTHRU_MASKSIZE 32 +#define CCP_PASSTHRU_KSB_COUNT 1 + +#define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */ +#define CCP_ECC_MAX_OPERANDS 6 +#define CCP_ECC_MAX_OUTPUTS 3 +#define CCP_ECC_SRC_BUF_SIZE 448 +#define CCP_ECC_DST_BUF_SIZE 192 +#define CCP_ECC_OPERAND_SIZE 64 +#define CCP_ECC_OUTPUT_SIZE 64 +#define CCP_ECC_RESULT_OFFSET 60 +#define CCP_ECC_RESULT_SUCCESS 0x0001 + + +struct ccp_device; +struct ccp_cmd; + +struct ccp_cmd_queue { + struct ccp_device *ccp; + + /* Queue identifier */ + u32 id; + + /* Queue dma pool */ + struct dma_pool *dma_pool; + + /* Queue reserved KSB regions */ + u32 ksb_key; + u32 ksb_ctx; + + /* Queue processing thread */ + struct task_struct *kthread; + unsigned int active; + unsigned int suspended; + + /* Number of free command slots available */ + unsigned int free_slots; + + /* Interrupt masks */ + u32 int_ok; + u32 int_err; + + /* Register addresses for queue */ + void __iomem *reg_status; + void __iomem *reg_int_status; + + /* Status values from job */ + u32 int_status; + u32 q_status; + u32 q_int_status; + u32 cmd_error; + + /* Interrupt wait queue */ + wait_queue_head_t int_queue; + unsigned int int_rcvd; +} ____cacheline_aligned; + +struct ccp_device { + struct device *dev; + + /* + * Bus specific device information + */ + void *dev_specific; + int (*get_irq)(struct ccp_device *ccp); + void (*free_irq)(struct ccp_device *ccp); + + /* + * I/O area used for device communication. The register mapping + * starts at an offset into the mapped bar. + * The CMD_REQx registers and the Delete_Cmd_Queue_Job register + * need to be protected while a command queue thread is accessing + * them. + */ + struct mutex req_mutex ____cacheline_aligned; + void __iomem *io_map; + void __iomem *io_regs; + + /* + * Master lists that all cmds are queued on. Because there can be + * more than one CCP command queue that can process a cmd a separate + * backlog list is neeeded so that the backlog completion call + * completes before the cmd is available for execution. + */ + spinlock_t cmd_lock ____cacheline_aligned; + unsigned int cmd_count; + struct list_head cmd; + struct list_head backlog; + + /* + * The command queues. These represent the queues available on the + * CCP that are available for processing cmds + */ + struct ccp_cmd_queue cmd_q[MAX_HW_QUEUES]; + unsigned int cmd_q_count; + + /* + * Support for the CCP True RNG + */ + struct hwrng hwrng; + unsigned int hwrng_retries; + + /* + * A counter used to generate job-ids for cmds submitted to the CCP + */ + atomic_t current_id ____cacheline_aligned; + + /* + * The CCP uses key storage blocks (KSB) to maintain context for certain + * operations. To prevent multiple cmds from using the same KSB range + * a command queue reserves a KSB range for the duration of the cmd. + * Each queue, will however, reserve 2 KSB blocks for operations that + * only require single KSB entries (eg. AES context/iv and key) in order + * to avoid allocation contention. This will reserve at most 10 KSB + * entries, leaving 40 KSB entries available for dynamic allocation. + */ + struct mutex ksb_mutex ____cacheline_aligned; + DECLARE_BITMAP(ksb, KSB_COUNT); + wait_queue_head_t ksb_queue; + unsigned int ksb_avail; + unsigned int ksb_count; + u32 ksb_start; + + /* Suspend support */ + unsigned int suspending; + wait_queue_head_t suspend_queue; +}; + + +int ccp_pci_init(void); +void ccp_pci_exit(void); + +struct ccp_device *ccp_alloc_struct(struct device *dev); +int ccp_init(struct ccp_device *ccp); +void ccp_destroy(struct ccp_device *ccp); +bool ccp_queues_suspended(struct ccp_device *ccp); + +irqreturn_t ccp_irq_handler(int irq, void *data); + +int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd); + +#endif diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c new file mode 100644 index 000000000000..4be091037549 --- /dev/null +++ b/drivers/crypto/ccp/ccp-ops.c @@ -0,0 +1,2020 @@ +/* + * AMD Cryptographic Coprocessor (CCP) driver + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-dev.h" + + +enum ccp_memtype { + CCP_MEMTYPE_SYSTEM = 0, + CCP_MEMTYPE_KSB, + CCP_MEMTYPE_LOCAL, + CCP_MEMTYPE__LAST, +}; + +struct ccp_dma_info { + dma_addr_t address; + unsigned int offset; + unsigned int length; + enum dma_data_direction dir; +}; + +struct ccp_dm_workarea { + struct device *dev; + struct dma_pool *dma_pool; + unsigned int length; + + u8 *address; + struct ccp_dma_info dma; +}; + +struct ccp_sg_workarea { + struct scatterlist *sg; + unsigned int nents; + unsigned int length; + + struct scatterlist *dma_sg; + struct device *dma_dev; + unsigned int dma_count; + enum dma_data_direction dma_dir; + + u32 sg_used; + + u32 bytes_left; +}; + +struct ccp_data { + struct ccp_sg_workarea sg_wa; + struct ccp_dm_workarea dm_wa; +}; + +struct ccp_mem { + enum ccp_memtype type; + union { + struct ccp_dma_info dma; + u32 ksb; + } u; +}; + +struct ccp_aes_op { + enum ccp_aes_type type; + enum ccp_aes_mode mode; + enum ccp_aes_action action; +}; + +struct ccp_xts_aes_op { + enum ccp_aes_action action; + enum ccp_xts_aes_unit_size unit_size; +}; + +struct ccp_sha_op { + enum ccp_sha_type type; + u64 msg_bits; +}; + +struct ccp_rsa_op { + u32 mod_size; + u32 input_len; +}; + +struct ccp_passthru_op { + enum ccp_passthru_bitwise bit_mod; + enum ccp_passthru_byteswap byte_swap; +}; + +struct ccp_ecc_op { + enum ccp_ecc_function function; +}; + +struct ccp_op { + struct ccp_cmd_queue *cmd_q; + + u32 jobid; + u32 ioc; + u32 soc; + u32 ksb_key; + u32 ksb_ctx; + u32 init; + u32 eom; + + struct ccp_mem src; + struct ccp_mem dst; + + union { + struct ccp_aes_op aes; + struct ccp_xts_aes_op xts; + struct ccp_sha_op sha; + struct ccp_rsa_op rsa; + struct ccp_passthru_op passthru; + struct ccp_ecc_op ecc; + } u; +}; + +/* The CCP cannot perform zero-length sha operations so the caller + * is required to buffer data for the final operation. However, a + * sha operation for a message with a total length of zero is valid + * so known values are required to supply the result. + */ +static const u8 ccp_sha1_zero[CCP_SHA_CTXSIZE] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, + 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const u8 ccp_sha224_zero[CCP_SHA_CTXSIZE] = { + 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, + 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, + 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, + 0xc5, 0xb3, 0xe4, 0x2f, 0x00, 0x00, 0x00, 0x00, +}; + +static const u8 ccp_sha256_zero[CCP_SHA_CTXSIZE] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, +}; + +static u32 ccp_addr_lo(struct ccp_dma_info *info) +{ + return lower_32_bits(info->address + info->offset); +} + +static u32 ccp_addr_hi(struct ccp_dma_info *info) +{ + return upper_32_bits(info->address + info->offset) & 0x0000ffff; +} + +static int ccp_do_cmd(struct ccp_op *op, u32 *cr, unsigned int cr_count) +{ + struct ccp_cmd_queue *cmd_q = op->cmd_q; + struct ccp_device *ccp = cmd_q->ccp; + void __iomem *cr_addr; + u32 cr0, cmd; + unsigned int i; + int ret = 0; + + /* We could read a status register to see how many free slots + * are actually available, but reading that register resets it + * and you could lose some error information. + */ + cmd_q->free_slots--; + + cr0 = (cmd_q->id << REQ0_CMD_Q_SHIFT) + | (op->jobid << REQ0_JOBID_SHIFT) + | REQ0_WAIT_FOR_WRITE; + + if (op->soc) + cr0 |= REQ0_STOP_ON_COMPLETE + | REQ0_INT_ON_COMPLETE; + + if (op->ioc || !cmd_q->free_slots) + cr0 |= REQ0_INT_ON_COMPLETE; + + /* Start at CMD_REQ1 */ + cr_addr = ccp->io_regs + CMD_REQ0 + CMD_REQ_INCR; + + mutex_lock(&ccp->req_mutex); + + /* Write CMD_REQ1 through CMD_REQx first */ + for (i = 0; i < cr_count; i++, cr_addr += CMD_REQ_INCR) + iowrite32(*(cr + i), cr_addr); + + /* Tell the CCP to start */ + wmb(); + iowrite32(cr0, ccp->io_regs + CMD_REQ0); + + mutex_unlock(&ccp->req_mutex); + + if (cr0 & REQ0_INT_ON_COMPLETE) { + /* Wait for the job to complete */ + ret = wait_event_interruptible(cmd_q->int_queue, + cmd_q->int_rcvd); + if (ret || cmd_q->cmd_error) { + /* On error delete all related jobs from the queue */ + cmd = (cmd_q->id << DEL_Q_ID_SHIFT) + | op->jobid; + + iowrite32(cmd, ccp->io_regs + DEL_CMD_Q_JOB); + + if (!ret) + ret = -EIO; + } else if (op->soc) { + /* Delete just head job from the queue on SoC */ + cmd = DEL_Q_ACTIVE + | (cmd_q->id << DEL_Q_ID_SHIFT) + | op->jobid; + + iowrite32(cmd, ccp->io_regs + DEL_CMD_Q_JOB); + } + + cmd_q->free_slots = CMD_Q_DEPTH(cmd_q->q_status); + + cmd_q->int_rcvd = 0; + } + + return ret; +} + +static int ccp_perform_aes(struct ccp_op *op) +{ + u32 cr[6]; + + /* Fill out the register contents for REQ1 through REQ6 */ + cr[0] = (CCP_ENGINE_AES << REQ1_ENGINE_SHIFT) + | (op->u.aes.type << REQ1_AES_TYPE_SHIFT) + | (op->u.aes.mode << REQ1_AES_MODE_SHIFT) + | (op->u.aes.action << REQ1_AES_ACTION_SHIFT) + | (op->ksb_key << REQ1_KEY_KSB_SHIFT); + cr[1] = op->src.u.dma.length - 1; + cr[2] = ccp_addr_lo(&op->src.u.dma); + cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT) + | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->src.u.dma); + cr[4] = ccp_addr_lo(&op->dst.u.dma); + cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->dst.u.dma); + + if (op->u.aes.mode == CCP_AES_MODE_CFB) + cr[0] |= ((0x7f) << REQ1_AES_CFB_SIZE_SHIFT); + + if (op->eom) + cr[0] |= REQ1_EOM; + + if (op->init) + cr[0] |= REQ1_INIT; + + return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); +} + +static int ccp_perform_xts_aes(struct ccp_op *op) +{ + u32 cr[6]; + + /* Fill out the register contents for REQ1 through REQ6 */ + cr[0] = (CCP_ENGINE_XTS_AES_128 << REQ1_ENGINE_SHIFT) + | (op->u.xts.action << REQ1_AES_ACTION_SHIFT) + | (op->u.xts.unit_size << REQ1_XTS_AES_SIZE_SHIFT) + | (op->ksb_key << REQ1_KEY_KSB_SHIFT); + cr[1] = op->src.u.dma.length - 1; + cr[2] = ccp_addr_lo(&op->src.u.dma); + cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT) + | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->src.u.dma); + cr[4] = ccp_addr_lo(&op->dst.u.dma); + cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->dst.u.dma); + + if (op->eom) + cr[0] |= REQ1_EOM; + + if (op->init) + cr[0] |= REQ1_INIT; + + return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); +} + +static int ccp_perform_sha(struct ccp_op *op) +{ + u32 cr[6]; + + /* Fill out the register contents for REQ1 through REQ6 */ + cr[0] = (CCP_ENGINE_SHA << REQ1_ENGINE_SHIFT) + | (op->u.sha.type << REQ1_SHA_TYPE_SHIFT) + | REQ1_INIT; + cr[1] = op->src.u.dma.length - 1; + cr[2] = ccp_addr_lo(&op->src.u.dma); + cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT) + | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->src.u.dma); + + if (op->eom) { + cr[0] |= REQ1_EOM; + cr[4] = lower_32_bits(op->u.sha.msg_bits); + cr[5] = upper_32_bits(op->u.sha.msg_bits); + } else { + cr[4] = 0; + cr[5] = 0; + } + + return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); +} + +static int ccp_perform_rsa(struct ccp_op *op) +{ + u32 cr[6]; + + /* Fill out the register contents for REQ1 through REQ6 */ + cr[0] = (CCP_ENGINE_RSA << REQ1_ENGINE_SHIFT) + | (op->u.rsa.mod_size << REQ1_RSA_MOD_SIZE_SHIFT) + | (op->ksb_key << REQ1_KEY_KSB_SHIFT) + | REQ1_EOM; + cr[1] = op->u.rsa.input_len - 1; + cr[2] = ccp_addr_lo(&op->src.u.dma); + cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT) + | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->src.u.dma); + cr[4] = ccp_addr_lo(&op->dst.u.dma); + cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->dst.u.dma); + + return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); +} + +static int ccp_perform_passthru(struct ccp_op *op) +{ + u32 cr[6]; + + /* Fill out the register contents for REQ1 through REQ6 */ + cr[0] = (CCP_ENGINE_PASSTHRU << REQ1_ENGINE_SHIFT) + | (op->u.passthru.bit_mod << REQ1_PT_BW_SHIFT) + | (op->u.passthru.byte_swap << REQ1_PT_BS_SHIFT); + + if (op->src.type == CCP_MEMTYPE_SYSTEM) + cr[1] = op->src.u.dma.length - 1; + else + cr[1] = op->dst.u.dma.length - 1; + + if (op->src.type == CCP_MEMTYPE_SYSTEM) { + cr[2] = ccp_addr_lo(&op->src.u.dma); + cr[3] = (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->src.u.dma); + + if (op->u.passthru.bit_mod != CCP_PASSTHRU_BITWISE_NOOP) + cr[3] |= (op->ksb_key << REQ4_KSB_SHIFT); + } else { + cr[2] = op->src.u.ksb * CCP_KSB_BYTES; + cr[3] = (CCP_MEMTYPE_KSB << REQ4_MEMTYPE_SHIFT); + } + + if (op->dst.type == CCP_MEMTYPE_SYSTEM) { + cr[4] = ccp_addr_lo(&op->dst.u.dma); + cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->dst.u.dma); + } else { + cr[4] = op->dst.u.ksb * CCP_KSB_BYTES; + cr[5] = (CCP_MEMTYPE_KSB << REQ6_MEMTYPE_SHIFT); + } + + if (op->eom) + cr[0] |= REQ1_EOM; + + return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); +} + +static int ccp_perform_ecc(struct ccp_op *op) +{ + u32 cr[6]; + + /* Fill out the register contents for REQ1 through REQ6 */ + cr[0] = REQ1_ECC_AFFINE_CONVERT + | (CCP_ENGINE_ECC << REQ1_ENGINE_SHIFT) + | (op->u.ecc.function << REQ1_ECC_FUNCTION_SHIFT) + | REQ1_EOM; + cr[1] = op->src.u.dma.length - 1; + cr[2] = ccp_addr_lo(&op->src.u.dma); + cr[3] = (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->src.u.dma); + cr[4] = ccp_addr_lo(&op->dst.u.dma); + cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT) + | ccp_addr_hi(&op->dst.u.dma); + + return ccp_do_cmd(op, cr, ARRAY_SIZE(cr)); +} + +static u32 ccp_alloc_ksb(struct ccp_device *ccp, unsigned int count) +{ + int start; + + for (;;) { + mutex_lock(&ccp->ksb_mutex); + + start = (u32)bitmap_find_next_zero_area(ccp->ksb, + ccp->ksb_count, + ccp->ksb_start, + count, 0); + if (start <= ccp->ksb_count) { + bitmap_set(ccp->ksb, start, count); + + mutex_unlock(&ccp->ksb_mutex); + break; + } + + ccp->ksb_avail = 0; + + mutex_unlock(&ccp->ksb_mutex); + + /* Wait for KSB entries to become available */ + if (wait_event_interruptible(ccp->ksb_queue, ccp->ksb_avail)) + return 0; + } + + return KSB_START + start; +} + +static void ccp_free_ksb(struct ccp_device *ccp, unsigned int start, + unsigned int count) +{ + if (!start) + return; + + mutex_lock(&ccp->ksb_mutex); + + bitmap_clear(ccp->ksb, start - KSB_START, count); + + ccp->ksb_avail = 1; + + mutex_unlock(&ccp->ksb_mutex); + + wake_up_interruptible_all(&ccp->ksb_queue); +} + +static u32 ccp_gen_jobid(struct ccp_device *ccp) +{ + return atomic_inc_return(&ccp->current_id) & CCP_JOBID_MASK; +} + +static void ccp_sg_free(struct ccp_sg_workarea *wa) +{ + if (wa->dma_count) + dma_unmap_sg(wa->dma_dev, wa->dma_sg, wa->nents, wa->dma_dir); + + wa->dma_count = 0; +} + +static int ccp_init_sg_workarea(struct ccp_sg_workarea *wa, struct device *dev, + struct scatterlist *sg, unsigned int len, + enum dma_data_direction dma_dir) +{ + memset(wa, 0, sizeof(*wa)); + + wa->sg = sg; + if (!sg) + return 0; + + wa->nents = sg_nents(sg); + wa->length = sg->length; + wa->bytes_left = len; + wa->sg_used = 0; + + if (len == 0) + return 0; + + if (dma_dir == DMA_NONE) + return 0; + + wa->dma_sg = sg; + wa->dma_dev = dev; + wa->dma_dir = dma_dir; + wa->dma_count = dma_map_sg(dev, sg, wa->nents, dma_dir); + if (!wa->dma_count) + return -ENOMEM; + + + return 0; +} + +static void ccp_update_sg_workarea(struct ccp_sg_workarea *wa, unsigned int len) +{ + unsigned int nbytes = min(len, wa->bytes_left); + + if (!wa->sg) + return; + + wa->sg_used += nbytes; + wa->bytes_left -= nbytes; + if (wa->sg_used == wa->sg->length) { + wa->sg = sg_next(wa->sg); + wa->sg_used = 0; + } +} + +static void ccp_dm_free(struct ccp_dm_workarea *wa) +{ + if (wa->length <= CCP_DMAPOOL_MAX_SIZE) { + if (wa->address) + dma_pool_free(wa->dma_pool, wa->address, + wa->dma.address); + } else { + if (wa->dma.address) + dma_unmap_single(wa->dev, wa->dma.address, wa->length, + wa->dma.dir); + kfree(wa->address); + } + + wa->address = NULL; + wa->dma.address = 0; +} + +static int ccp_init_dm_workarea(struct ccp_dm_workarea *wa, + struct ccp_cmd_queue *cmd_q, + unsigned int len, + enum dma_data_direction dir) +{ + memset(wa, 0, sizeof(*wa)); + + if (!len) + return 0; + + wa->dev = cmd_q->ccp->dev; + wa->length = len; + + if (len <= CCP_DMAPOOL_MAX_SIZE) { + wa->dma_pool = cmd_q->dma_pool; + + wa->address = dma_pool_alloc(wa->dma_pool, GFP_KERNEL, + &wa->dma.address); + if (!wa->address) + return -ENOMEM; + + wa->dma.length = CCP_DMAPOOL_MAX_SIZE; + + memset(wa->address, 0, CCP_DMAPOOL_MAX_SIZE); + } else { + wa->address = kzalloc(len, GFP_KERNEL); + if (!wa->address) + return -ENOMEM; + + wa->dma.address = dma_map_single(wa->dev, wa->address, len, + dir); + if (!wa->dma.address) + return -ENOMEM; + + wa->dma.length = len; + } + wa->dma.dir = dir; + + return 0; +} + +static void ccp_set_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset, + struct scatterlist *sg, unsigned int sg_offset, + unsigned int len) +{ + WARN_ON(!wa->address); + + scatterwalk_map_and_copy(wa->address + wa_offset, sg, sg_offset, len, + 0); +} + +static void ccp_get_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset, + struct scatterlist *sg, unsigned int sg_offset, + unsigned int len) +{ + WARN_ON(!wa->address); + + scatterwalk_map_and_copy(wa->address + wa_offset, sg, sg_offset, len, + 1); +} + +static void ccp_reverse_set_dm_area(struct ccp_dm_workarea *wa, + struct scatterlist *sg, + unsigned int len, unsigned int se_len, + bool sign_extend) +{ + unsigned int nbytes, sg_offset, dm_offset, ksb_len, i; + u8 buffer[CCP_REVERSE_BUF_SIZE]; + + BUG_ON(se_len > sizeof(buffer)); + + sg_offset = len; + dm_offset = 0; + nbytes = len; + while (nbytes) { + ksb_len = min_t(unsigned int, nbytes, se_len); + sg_offset -= ksb_len; + + scatterwalk_map_and_copy(buffer, sg, sg_offset, ksb_len, 0); + for (i = 0; i < ksb_len; i++) + wa->address[dm_offset + i] = buffer[ksb_len - i - 1]; + + dm_offset += ksb_len; + nbytes -= ksb_len; + + if ((ksb_len != se_len) && sign_extend) { + /* Must sign-extend to nearest sign-extend length */ + if (wa->address[dm_offset - 1] & 0x80) + memset(wa->address + dm_offset, 0xff, + se_len - ksb_len); + } + } +} + +static void ccp_reverse_get_dm_area(struct ccp_dm_workarea *wa, + struct scatterlist *sg, + unsigned int len) +{ + unsigned int nbytes, sg_offset, dm_offset, ksb_len, i; + u8 buffer[CCP_REVERSE_BUF_SIZE]; + + sg_offset = 0; + dm_offset = len; + nbytes = len; + while (nbytes) { + ksb_len = min_t(unsigned int, nbytes, sizeof(buffer)); + dm_offset -= ksb_len; + + for (i = 0; i < ksb_len; i++) + buffer[ksb_len - i - 1] = wa->address[dm_offset + i]; + scatterwalk_map_and_copy(buffer, sg, sg_offset, ksb_len, 1); + + sg_offset += ksb_len; + nbytes -= ksb_len; + } +} + +static void ccp_free_data(struct ccp_data *data, struct ccp_cmd_queue *cmd_q) +{ + ccp_dm_free(&data->dm_wa); + ccp_sg_free(&data->sg_wa); +} + +static int ccp_init_data(struct ccp_data *data, struct ccp_cmd_queue *cmd_q, + struct scatterlist *sg, unsigned int sg_len, + unsigned int dm_len, + enum dma_data_direction dir) +{ + int ret; + + memset(data, 0, sizeof(*data)); + + ret = ccp_init_sg_workarea(&data->sg_wa, cmd_q->ccp->dev, sg, sg_len, + dir); + if (ret) + goto e_err; + + ret = ccp_init_dm_workarea(&data->dm_wa, cmd_q, dm_len, dir); + if (ret) + goto e_err; + + return 0; + +e_err: + ccp_free_data(data, cmd_q); + + return ret; +} + +static unsigned int ccp_queue_buf(struct ccp_data *data, unsigned int from) +{ + struct ccp_sg_workarea *sg_wa = &data->sg_wa; + struct ccp_dm_workarea *dm_wa = &data->dm_wa; + unsigned int buf_count, nbytes; + + /* Clear the buffer if setting it */ + if (!from) + memset(dm_wa->address, 0, dm_wa->length); + + if (!sg_wa->sg) + return 0; + + /* Perform the copy operation */ + nbytes = min(sg_wa->bytes_left, dm_wa->length); + scatterwalk_map_and_copy(dm_wa->address, sg_wa->sg, sg_wa->sg_used, + nbytes, from); + + /* Update the structures and generate the count */ + buf_count = 0; + while (sg_wa->bytes_left && (buf_count < dm_wa->length)) { + nbytes = min3(sg_wa->sg->length - sg_wa->sg_used, + dm_wa->length - buf_count, + sg_wa->bytes_left); + + buf_count += nbytes; + ccp_update_sg_workarea(sg_wa, nbytes); + } + + return buf_count; +} + +static unsigned int ccp_fill_queue_buf(struct ccp_data *data) +{ + return ccp_queue_buf(data, 0); +} + +static unsigned int ccp_empty_queue_buf(struct ccp_data *data) +{ + return ccp_queue_buf(data, 1); +} + +static void ccp_prepare_data(struct ccp_data *src, struct ccp_data *dst, + struct ccp_op *op, unsigned int block_size, + bool blocksize_op) +{ + unsigned int sg_src_len, sg_dst_len, op_len; + + /* The CCP can only DMA from/to one address each per operation. This + * requires that we find the smallest DMA area between the source + * and destination. + */ + sg_src_len = min(sg_dma_len(src->sg_wa.sg) - src->sg_wa.sg_used, + src->sg_wa.bytes_left); + + if (dst) { + sg_dst_len = min(sg_dma_len(dst->sg_wa.sg) - dst->sg_wa.sg_used, + src->sg_wa.bytes_left); + op_len = min(sg_src_len, sg_dst_len); + } else + op_len = sg_src_len; + + /* The data operation length will be at least block_size in length + * or the smaller of available sg room remaining for the source or + * the destination + */ + op_len = max(op_len, block_size); + + /* Unless we have to buffer data, there's no reason to wait */ + op->soc = 0; + + if (sg_src_len < block_size) { + /* Not enough data in the sg element, so it + * needs to be buffered into a blocksize chunk + */ + int cp_len = ccp_fill_queue_buf(src); + + op->soc = 1; + op->src.u.dma.address = src->dm_wa.dma.address; + op->src.u.dma.offset = 0; + op->src.u.dma.length = (blocksize_op) ? block_size : cp_len; + } else { + /* Enough data in the sg element, but we need to + * adjust for any previously copied data + */ + op->src.u.dma.address = sg_dma_address(src->sg_wa.sg); + op->src.u.dma.offset = src->sg_wa.sg_used; + op->src.u.dma.length = op_len & ~(block_size - 1); + + ccp_update_sg_workarea(&src->sg_wa, op->src.u.dma.length); + } + + if (dst) { + if (sg_dst_len < block_size) { + /* Not enough room in the sg element or we're on the + * last piece of data (when using padding), so the + * output needs to be buffered into a blocksize chunk + */ + op->soc = 1; + op->dst.u.dma.address = dst->dm_wa.dma.address; + op->dst.u.dma.offset = 0; + op->dst.u.dma.length = op->src.u.dma.length; + } else { + /* Enough room in the sg element, but we need to + * adjust for any previously used area + */ + op->dst.u.dma.address = sg_dma_address(dst->sg_wa.sg); + op->dst.u.dma.offset = dst->sg_wa.sg_used; + op->dst.u.dma.length = op->src.u.dma.length; + } + } +} + +static void ccp_process_data(struct ccp_data *src, struct ccp_data *dst, + struct ccp_op *op) +{ + op->init = 0; + + if (dst) { + if (op->dst.u.dma.address == dst->dm_wa.dma.address) + ccp_empty_queue_buf(dst); + else + ccp_update_sg_workarea(&dst->sg_wa, + op->dst.u.dma.length); + } +} + +static int ccp_copy_to_from_ksb(struct ccp_cmd_queue *cmd_q, + struct ccp_dm_workarea *wa, u32 jobid, u32 ksb, + u32 byte_swap, bool from) +{ + struct ccp_op op; + + memset(&op, 0, sizeof(op)); + + op.cmd_q = cmd_q; + op.jobid = jobid; + op.eom = 1; + + if (from) { + op.soc = 1; + op.src.type = CCP_MEMTYPE_KSB; + op.src.u.ksb = ksb; + op.dst.type = CCP_MEMTYPE_SYSTEM; + op.dst.u.dma.address = wa->dma.address; + op.dst.u.dma.length = wa->length; + } else { + op.src.type = CCP_MEMTYPE_SYSTEM; + op.src.u.dma.address = wa->dma.address; + op.src.u.dma.length = wa->length; + op.dst.type = CCP_MEMTYPE_KSB; + op.dst.u.ksb = ksb; + } + + op.u.passthru.byte_swap = byte_swap; + + return ccp_perform_passthru(&op); +} + +static int ccp_copy_to_ksb(struct ccp_cmd_queue *cmd_q, + struct ccp_dm_workarea *wa, u32 jobid, u32 ksb, + u32 byte_swap) +{ + return ccp_copy_to_from_ksb(cmd_q, wa, jobid, ksb, byte_swap, false); +} + +static int ccp_copy_from_ksb(struct ccp_cmd_queue *cmd_q, + struct ccp_dm_workarea *wa, u32 jobid, u32 ksb, + u32 byte_swap) +{ + return ccp_copy_to_from_ksb(cmd_q, wa, jobid, ksb, byte_swap, true); +} + +static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, + struct ccp_cmd *cmd) +{ + struct ccp_aes_engine *aes = &cmd->u.aes; + struct ccp_dm_workarea key, ctx; + struct ccp_data src; + struct ccp_op op; + unsigned int dm_offset; + int ret; + + if (!((aes->key_len == AES_KEYSIZE_128) || + (aes->key_len == AES_KEYSIZE_192) || + (aes->key_len == AES_KEYSIZE_256))) + return -EINVAL; + + if (aes->src_len & (AES_BLOCK_SIZE - 1)) + return -EINVAL; + + if (aes->iv_len != AES_BLOCK_SIZE) + return -EINVAL; + + if (!aes->key || !aes->iv || !aes->src) + return -EINVAL; + + if (aes->cmac_final) { + if (aes->cmac_key_len != AES_BLOCK_SIZE) + return -EINVAL; + + if (!aes->cmac_key) + return -EINVAL; + } + + BUILD_BUG_ON(CCP_AES_KEY_KSB_COUNT != 1); + BUILD_BUG_ON(CCP_AES_CTX_KSB_COUNT != 1); + + ret = -EIO; + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + op.ksb_key = cmd_q->ksb_key; + op.ksb_ctx = cmd_q->ksb_ctx; + op.init = 1; + op.u.aes.type = aes->type; + op.u.aes.mode = aes->mode; + op.u.aes.action = aes->action; + + /* All supported key sizes fit in a single (32-byte) KSB entry + * and must be in little endian format. Use the 256-bit byte + * swap passthru option to convert from big endian to little + * endian. + */ + ret = ccp_init_dm_workarea(&key, cmd_q, + CCP_AES_KEY_KSB_COUNT * CCP_KSB_BYTES, + DMA_TO_DEVICE); + if (ret) + return ret; + + dm_offset = CCP_KSB_BYTES - aes->key_len; + ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); + ret = ccp_copy_to_ksb(cmd_q, &key, op.jobid, op.ksb_key, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_key; + } + + /* The AES context fits in a single (32-byte) KSB entry and + * must be in little endian format. Use the 256-bit byte swap + * passthru option to convert from big endian to little endian. + */ + ret = ccp_init_dm_workarea(&ctx, cmd_q, + CCP_AES_CTX_KSB_COUNT * CCP_KSB_BYTES, + DMA_BIDIRECTIONAL); + if (ret) + goto e_key; + + dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE; + ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); + ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_ctx; + } + + /* Send data to the CCP AES engine */ + ret = ccp_init_data(&src, cmd_q, aes->src, aes->src_len, + AES_BLOCK_SIZE, DMA_TO_DEVICE); + if (ret) + goto e_ctx; + + while (src.sg_wa.bytes_left) { + ccp_prepare_data(&src, NULL, &op, AES_BLOCK_SIZE, true); + if (aes->cmac_final && !src.sg_wa.bytes_left) { + op.eom = 1; + + /* Push the K1/K2 key to the CCP now */ + ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, + op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_src; + } + + ccp_set_dm_area(&ctx, 0, aes->cmac_key, 0, + aes->cmac_key_len); + ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_src; + } + } + + ret = ccp_perform_aes(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_src; + } + + ccp_process_data(&src, NULL, &op); + } + + /* Retrieve the AES context - convert from LE to BE using + * 32-byte (256-bit) byteswapping + */ + ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_src; + } + + /* ...but we only need AES_BLOCK_SIZE bytes */ + dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE; + ccp_get_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); + +e_src: + ccp_free_data(&src, cmd_q); + +e_ctx: + ccp_dm_free(&ctx); + +e_key: + ccp_dm_free(&key); + + return ret; +} + +static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_aes_engine *aes = &cmd->u.aes; + struct ccp_dm_workarea key, ctx; + struct ccp_data src, dst; + struct ccp_op op; + unsigned int dm_offset; + bool in_place = false; + int ret; + + if (aes->mode == CCP_AES_MODE_CMAC) + return ccp_run_aes_cmac_cmd(cmd_q, cmd); + + if (!((aes->key_len == AES_KEYSIZE_128) || + (aes->key_len == AES_KEYSIZE_192) || + (aes->key_len == AES_KEYSIZE_256))) + return -EINVAL; + + if (((aes->mode == CCP_AES_MODE_ECB) || + (aes->mode == CCP_AES_MODE_CBC) || + (aes->mode == CCP_AES_MODE_CFB)) && + (aes->src_len & (AES_BLOCK_SIZE - 1))) + return -EINVAL; + + if (!aes->key || !aes->src || !aes->dst) + return -EINVAL; + + if (aes->mode != CCP_AES_MODE_ECB) { + if (aes->iv_len != AES_BLOCK_SIZE) + return -EINVAL; + + if (!aes->iv) + return -EINVAL; + } + + BUILD_BUG_ON(CCP_AES_KEY_KSB_COUNT != 1); + BUILD_BUG_ON(CCP_AES_CTX_KSB_COUNT != 1); + + ret = -EIO; + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + op.ksb_key = cmd_q->ksb_key; + op.ksb_ctx = cmd_q->ksb_ctx; + op.init = (aes->mode == CCP_AES_MODE_ECB) ? 0 : 1; + op.u.aes.type = aes->type; + op.u.aes.mode = aes->mode; + op.u.aes.action = aes->action; + + /* All supported key sizes fit in a single (32-byte) KSB entry + * and must be in little endian format. Use the 256-bit byte + * swap passthru option to convert from big endian to little + * endian. + */ + ret = ccp_init_dm_workarea(&key, cmd_q, + CCP_AES_KEY_KSB_COUNT * CCP_KSB_BYTES, + DMA_TO_DEVICE); + if (ret) + return ret; + + dm_offset = CCP_KSB_BYTES - aes->key_len; + ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); + ret = ccp_copy_to_ksb(cmd_q, &key, op.jobid, op.ksb_key, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_key; + } + + /* The AES context fits in a single (32-byte) KSB entry and + * must be in little endian format. Use the 256-bit byte swap + * passthru option to convert from big endian to little endian. + */ + ret = ccp_init_dm_workarea(&ctx, cmd_q, + CCP_AES_CTX_KSB_COUNT * CCP_KSB_BYTES, + DMA_BIDIRECTIONAL); + if (ret) + goto e_key; + + if (aes->mode != CCP_AES_MODE_ECB) { + /* Load the AES context - conver to LE */ + dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE; + ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); + ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_ctx; + } + } + + /* Prepare the input and output data workareas. For in-place + * operations we need to set the dma direction to BIDIRECTIONAL + * and copy the src workarea to the dst workarea. + */ + if (sg_virt(aes->src) == sg_virt(aes->dst)) + in_place = true; + + ret = ccp_init_data(&src, cmd_q, aes->src, aes->src_len, + AES_BLOCK_SIZE, + in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE); + if (ret) + goto e_ctx; + + if (in_place) + dst = src; + else { + ret = ccp_init_data(&dst, cmd_q, aes->dst, aes->src_len, + AES_BLOCK_SIZE, DMA_FROM_DEVICE); + if (ret) + goto e_src; + } + + /* Send data to the CCP AES engine */ + while (src.sg_wa.bytes_left) { + ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true); + if (!src.sg_wa.bytes_left) { + op.eom = 1; + + /* Since we don't retrieve the AES context in ECB + * mode we have to wait for the operation to complete + * on the last piece of data + */ + if (aes->mode == CCP_AES_MODE_ECB) + op.soc = 1; + } + + ret = ccp_perform_aes(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ccp_process_data(&src, &dst, &op); + } + + if (aes->mode != CCP_AES_MODE_ECB) { + /* Retrieve the AES context - convert from LE to BE using + * 32-byte (256-bit) byteswapping + */ + ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + /* ...but we only need AES_BLOCK_SIZE bytes */ + dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE; + ccp_get_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); + } + +e_dst: + if (!in_place) + ccp_free_data(&dst, cmd_q); + +e_src: + ccp_free_data(&src, cmd_q); + +e_ctx: + ccp_dm_free(&ctx); + +e_key: + ccp_dm_free(&key); + + return ret; +} + +static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q, + struct ccp_cmd *cmd) +{ + struct ccp_xts_aes_engine *xts = &cmd->u.xts; + struct ccp_dm_workarea key, ctx; + struct ccp_data src, dst; + struct ccp_op op; + unsigned int unit_size, dm_offset; + bool in_place = false; + int ret; + + switch (xts->unit_size) { + case CCP_XTS_AES_UNIT_SIZE_16: + unit_size = 16; + break; + case CCP_XTS_AES_UNIT_SIZE_512: + unit_size = 512; + break; + case CCP_XTS_AES_UNIT_SIZE_1024: + unit_size = 1024; + break; + case CCP_XTS_AES_UNIT_SIZE_2048: + unit_size = 2048; + break; + case CCP_XTS_AES_UNIT_SIZE_4096: + unit_size = 4096; + break; + + default: + return -EINVAL; + } + + if (xts->key_len != AES_KEYSIZE_128) + return -EINVAL; + + if (!xts->final && (xts->src_len & (AES_BLOCK_SIZE - 1))) + return -EINVAL; + + if (xts->iv_len != AES_BLOCK_SIZE) + return -EINVAL; + + if (!xts->key || !xts->iv || !xts->src || !xts->dst) + return -EINVAL; + + BUILD_BUG_ON(CCP_XTS_AES_KEY_KSB_COUNT != 1); + BUILD_BUG_ON(CCP_XTS_AES_CTX_KSB_COUNT != 1); + + ret = -EIO; + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + op.ksb_key = cmd_q->ksb_key; + op.ksb_ctx = cmd_q->ksb_ctx; + op.init = 1; + op.u.xts.action = xts->action; + op.u.xts.unit_size = xts->unit_size; + + /* All supported key sizes fit in a single (32-byte) KSB entry + * and must be in little endian format. Use the 256-bit byte + * swap passthru option to convert from big endian to little + * endian. + */ + ret = ccp_init_dm_workarea(&key, cmd_q, + CCP_XTS_AES_KEY_KSB_COUNT * CCP_KSB_BYTES, + DMA_TO_DEVICE); + if (ret) + return ret; + + dm_offset = CCP_KSB_BYTES - AES_KEYSIZE_128; + ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len); + ccp_set_dm_area(&key, 0, xts->key, dm_offset, xts->key_len); + ret = ccp_copy_to_ksb(cmd_q, &key, op.jobid, op.ksb_key, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_key; + } + + /* The AES context fits in a single (32-byte) KSB entry and + * for XTS is already in little endian format so no byte swapping + * is needed. + */ + ret = ccp_init_dm_workarea(&ctx, cmd_q, + CCP_XTS_AES_CTX_KSB_COUNT * CCP_KSB_BYTES, + DMA_BIDIRECTIONAL); + if (ret) + goto e_key; + + ccp_set_dm_area(&ctx, 0, xts->iv, 0, xts->iv_len); + ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_NOOP); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_ctx; + } + + /* Prepare the input and output data workareas. For in-place + * operations we need to set the dma direction to BIDIRECTIONAL + * and copy the src workarea to the dst workarea. + */ + if (sg_virt(xts->src) == sg_virt(xts->dst)) + in_place = true; + + ret = ccp_init_data(&src, cmd_q, xts->src, xts->src_len, + unit_size, + in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE); + if (ret) + goto e_ctx; + + if (in_place) + dst = src; + else { + ret = ccp_init_data(&dst, cmd_q, xts->dst, xts->src_len, + unit_size, DMA_FROM_DEVICE); + if (ret) + goto e_src; + } + + /* Send data to the CCP AES engine */ + while (src.sg_wa.bytes_left) { + ccp_prepare_data(&src, &dst, &op, unit_size, true); + if (!src.sg_wa.bytes_left) + op.eom = 1; + + ret = ccp_perform_xts_aes(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ccp_process_data(&src, &dst, &op); + } + + /* Retrieve the AES context - convert from LE to BE using + * 32-byte (256-bit) byteswapping + */ + ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + /* ...but we only need AES_BLOCK_SIZE bytes */ + dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE; + ccp_get_dm_area(&ctx, dm_offset, xts->iv, 0, xts->iv_len); + +e_dst: + if (!in_place) + ccp_free_data(&dst, cmd_q); + +e_src: + ccp_free_data(&src, cmd_q); + +e_ctx: + ccp_dm_free(&ctx); + +e_key: + ccp_dm_free(&key); + + return ret; +} + +static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_sha_engine *sha = &cmd->u.sha; + struct ccp_dm_workarea ctx; + struct ccp_data src; + struct ccp_op op; + int ret; + + if (sha->ctx_len != CCP_SHA_CTXSIZE) + return -EINVAL; + + if (!sha->ctx) + return -EINVAL; + + if (!sha->final && (sha->src_len & (CCP_SHA_BLOCKSIZE - 1))) + return -EINVAL; + + if (!sha->src_len) { + const u8 *sha_zero; + + /* Not final, just return */ + if (!sha->final) + return 0; + + /* CCP can't do a zero length sha operation so the caller + * must buffer the data. + */ + if (sha->msg_bits) + return -EINVAL; + + /* A sha operation for a message with a total length of zero, + * return known result. + */ + switch (sha->type) { + case CCP_SHA_TYPE_1: + sha_zero = ccp_sha1_zero; + break; + case CCP_SHA_TYPE_224: + sha_zero = ccp_sha224_zero; + break; + case CCP_SHA_TYPE_256: + sha_zero = ccp_sha256_zero; + break; + default: + return -EINVAL; + } + + scatterwalk_map_and_copy((void *)sha_zero, sha->ctx, 0, + sha->ctx_len, 1); + + return 0; + } + + if (!sha->src) + return -EINVAL; + + BUILD_BUG_ON(CCP_SHA_KSB_COUNT != 1); + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + op.ksb_ctx = cmd_q->ksb_ctx; + op.u.sha.type = sha->type; + op.u.sha.msg_bits = sha->msg_bits; + + /* The SHA context fits in a single (32-byte) KSB entry and + * must be in little endian format. Use the 256-bit byte swap + * passthru option to convert from big endian to little endian. + */ + ret = ccp_init_dm_workarea(&ctx, cmd_q, + CCP_SHA_KSB_COUNT * CCP_KSB_BYTES, + DMA_BIDIRECTIONAL); + if (ret) + return ret; + + ccp_set_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len); + ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_ctx; + } + + /* Send data to the CCP SHA engine */ + ret = ccp_init_data(&src, cmd_q, sha->src, sha->src_len, + CCP_SHA_BLOCKSIZE, DMA_TO_DEVICE); + if (ret) + goto e_ctx; + + while (src.sg_wa.bytes_left) { + ccp_prepare_data(&src, NULL, &op, CCP_SHA_BLOCKSIZE, false); + if (sha->final && !src.sg_wa.bytes_left) + op.eom = 1; + + ret = ccp_perform_sha(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_data; + } + + ccp_process_data(&src, NULL, &op); + } + + /* Retrieve the SHA context - convert from LE to BE using + * 32-byte (256-bit) byteswapping to BE + */ + ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_data; + } + + ccp_get_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len); + +e_data: + ccp_free_data(&src, cmd_q); + +e_ctx: + ccp_dm_free(&ctx); + + return ret; +} + +static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_rsa_engine *rsa = &cmd->u.rsa; + struct ccp_dm_workarea exp, src; + struct ccp_data dst; + struct ccp_op op; + unsigned int ksb_count, i_len, o_len; + int ret; + + if (rsa->key_size > CCP_RSA_MAX_WIDTH) + return -EINVAL; + + if (!rsa->exp || !rsa->mod || !rsa->src || !rsa->dst) + return -EINVAL; + + /* The RSA modulus must precede the message being acted upon, so + * it must be copied to a DMA area where the message and the + * modulus can be concatenated. Therefore the input buffer + * length required is twice the output buffer length (which + * must be a multiple of 256-bits). + */ + o_len = ((rsa->key_size + 255) / 256) * 32; + i_len = o_len * 2; + + ksb_count = o_len / CCP_KSB_BYTES; + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + op.ksb_key = ccp_alloc_ksb(cmd_q->ccp, ksb_count); + if (!op.ksb_key) + return -EIO; + + /* The RSA exponent may span multiple (32-byte) KSB entries and must + * be in little endian format. Reverse copy each 32-byte chunk + * of the exponent (En chunk to E0 chunk, E(n-1) chunk to E1 chunk) + * and each byte within that chunk and do not perform any byte swap + * operations on the passthru operation. + */ + ret = ccp_init_dm_workarea(&exp, cmd_q, o_len, DMA_TO_DEVICE); + if (ret) + goto e_ksb; + + ccp_reverse_set_dm_area(&exp, rsa->exp, rsa->exp_len, CCP_KSB_BYTES, + true); + ret = ccp_copy_to_ksb(cmd_q, &exp, op.jobid, op.ksb_key, + CCP_PASSTHRU_BYTESWAP_NOOP); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_exp; + } + + /* Concatenate the modulus and the message. Both the modulus and + * the operands must be in little endian format. Since the input + * is in big endian format it must be converted. + */ + ret = ccp_init_dm_workarea(&src, cmd_q, i_len, DMA_TO_DEVICE); + if (ret) + goto e_exp; + + ccp_reverse_set_dm_area(&src, rsa->mod, rsa->mod_len, CCP_KSB_BYTES, + true); + src.address += o_len; /* Adjust the address for the copy operation */ + ccp_reverse_set_dm_area(&src, rsa->src, rsa->src_len, CCP_KSB_BYTES, + true); + src.address -= o_len; /* Reset the address to original value */ + + /* Prepare the output area for the operation */ + ret = ccp_init_data(&dst, cmd_q, rsa->dst, rsa->mod_len, + o_len, DMA_FROM_DEVICE); + if (ret) + goto e_src; + + op.soc = 1; + op.src.u.dma.address = src.dma.address; + op.src.u.dma.offset = 0; + op.src.u.dma.length = i_len; + op.dst.u.dma.address = dst.dm_wa.dma.address; + op.dst.u.dma.offset = 0; + op.dst.u.dma.length = o_len; + + op.u.rsa.mod_size = rsa->key_size; + op.u.rsa.input_len = i_len; + + ret = ccp_perform_rsa(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ccp_reverse_get_dm_area(&dst.dm_wa, rsa->dst, rsa->mod_len); + +e_dst: + ccp_free_data(&dst, cmd_q); + +e_src: + ccp_dm_free(&src); + +e_exp: + ccp_dm_free(&exp); + +e_ksb: + ccp_free_ksb(cmd_q->ccp, op.ksb_key, ksb_count); + + return ret; +} + +static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, + struct ccp_cmd *cmd) +{ + struct ccp_passthru_engine *pt = &cmd->u.passthru; + struct ccp_dm_workarea mask; + struct ccp_data src, dst; + struct ccp_op op; + bool in_place = false; + unsigned int i; + int ret; + + if (!pt->final && (pt->src_len & (CCP_PASSTHRU_BLOCKSIZE - 1))) + return -EINVAL; + + if (!pt->src || !pt->dst) + return -EINVAL; + + if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) { + if (pt->mask_len != CCP_PASSTHRU_MASKSIZE) + return -EINVAL; + if (!pt->mask) + return -EINVAL; + } + + BUILD_BUG_ON(CCP_PASSTHRU_KSB_COUNT != 1); + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + + if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) { + /* Load the mask */ + op.ksb_key = cmd_q->ksb_key; + + ret = ccp_init_dm_workarea(&mask, cmd_q, + CCP_PASSTHRU_KSB_COUNT * + CCP_KSB_BYTES, + DMA_TO_DEVICE); + if (ret) + return ret; + + ccp_set_dm_area(&mask, 0, pt->mask, 0, pt->mask_len); + ret = ccp_copy_to_ksb(cmd_q, &mask, op.jobid, op.ksb_key, + CCP_PASSTHRU_BYTESWAP_NOOP); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_mask; + } + } + + /* Prepare the input and output data workareas. For in-place + * operations we need to set the dma direction to BIDIRECTIONAL + * and copy the src workarea to the dst workarea. + */ + if (sg_virt(pt->src) == sg_virt(pt->dst)) + in_place = true; + + ret = ccp_init_data(&src, cmd_q, pt->src, pt->src_len, + CCP_PASSTHRU_MASKSIZE, + in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE); + if (ret) + goto e_mask; + + if (in_place) + dst = src; + else { + ret = ccp_init_data(&dst, cmd_q, pt->dst, pt->src_len, + CCP_PASSTHRU_MASKSIZE, DMA_FROM_DEVICE); + if (ret) + goto e_src; + } + + /* Send data to the CCP Passthru engine + * Because the CCP engine works on a single source and destination + * dma address at a time, each entry in the source scatterlist + * (after the dma_map_sg call) must be less than or equal to the + * (remaining) length in the destination scatterlist entry and the + * length must be a multiple of CCP_PASSTHRU_BLOCKSIZE + */ + dst.sg_wa.sg_used = 0; + for (i = 1; i <= src.sg_wa.dma_count; i++) { + if (!dst.sg_wa.sg || + (dst.sg_wa.sg->length < src.sg_wa.sg->length)) { + ret = -EINVAL; + goto e_dst; + } + + if (i == src.sg_wa.dma_count) { + op.eom = 1; + op.soc = 1; + } + + op.src.type = CCP_MEMTYPE_SYSTEM; + op.src.u.dma.address = sg_dma_address(src.sg_wa.sg); + op.src.u.dma.offset = 0; + op.src.u.dma.length = sg_dma_len(src.sg_wa.sg); + + op.dst.type = CCP_MEMTYPE_SYSTEM; + op.dst.u.dma.address = sg_dma_address(dst.sg_wa.sg); + op.src.u.dma.offset = dst.sg_wa.sg_used; + op.src.u.dma.length = op.src.u.dma.length; + + ret = ccp_perform_passthru(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + dst.sg_wa.sg_used += src.sg_wa.sg->length; + if (dst.sg_wa.sg_used == dst.sg_wa.sg->length) { + dst.sg_wa.sg = sg_next(dst.sg_wa.sg); + dst.sg_wa.sg_used = 0; + } + src.sg_wa.sg = sg_next(src.sg_wa.sg); + } + +e_dst: + if (!in_place) + ccp_free_data(&dst, cmd_q); + +e_src: + ccp_free_data(&src, cmd_q); + +e_mask: + if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) + ccp_dm_free(&mask); + + return ret; +} + +static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_ecc_engine *ecc = &cmd->u.ecc; + struct ccp_dm_workarea src, dst; + struct ccp_op op; + int ret; + u8 *save; + + if (!ecc->u.mm.operand_1 || + (ecc->u.mm.operand_1_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT) + if (!ecc->u.mm.operand_2 || + (ecc->u.mm.operand_2_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + if (!ecc->u.mm.result || + (ecc->u.mm.result_len < CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + + /* Concatenate the modulus and the operands. Both the modulus and + * the operands must be in little endian format. Since the input + * is in big endian format it must be converted and placed in a + * fixed length buffer. + */ + ret = ccp_init_dm_workarea(&src, cmd_q, CCP_ECC_SRC_BUF_SIZE, + DMA_TO_DEVICE); + if (ret) + return ret; + + /* Save the workarea address since it is updated in order to perform + * the concatenation + */ + save = src.address; + + /* Copy the ECC modulus */ + ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + + /* Copy the first operand */ + ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_1, + ecc->u.mm.operand_1_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + + if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT) { + /* Copy the second operand */ + ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_2, + ecc->u.mm.operand_2_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + } + + /* Restore the workarea address */ + src.address = save; + + /* Prepare the output area for the operation */ + ret = ccp_init_dm_workarea(&dst, cmd_q, CCP_ECC_DST_BUF_SIZE, + DMA_FROM_DEVICE); + if (ret) + goto e_src; + + op.soc = 1; + op.src.u.dma.address = src.dma.address; + op.src.u.dma.offset = 0; + op.src.u.dma.length = src.length; + op.dst.u.dma.address = dst.dma.address; + op.dst.u.dma.offset = 0; + op.dst.u.dma.length = dst.length; + + op.u.ecc.function = cmd->u.ecc.function; + + ret = ccp_perform_ecc(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ecc->ecc_result = le16_to_cpup( + (const __le16 *)(dst.address + CCP_ECC_RESULT_OFFSET)); + if (!(ecc->ecc_result & CCP_ECC_RESULT_SUCCESS)) { + ret = -EIO; + goto e_dst; + } + + /* Save the ECC result */ + ccp_reverse_get_dm_area(&dst, ecc->u.mm.result, CCP_ECC_MODULUS_BYTES); + +e_dst: + ccp_dm_free(&dst); + +e_src: + ccp_dm_free(&src); + + return ret; +} + +static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_ecc_engine *ecc = &cmd->u.ecc; + struct ccp_dm_workarea src, dst; + struct ccp_op op; + int ret; + u8 *save; + + if (!ecc->u.pm.point_1.x || + (ecc->u.pm.point_1.x_len > CCP_ECC_MODULUS_BYTES) || + !ecc->u.pm.point_1.y || + (ecc->u.pm.point_1.y_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + if (ecc->function == CCP_ECC_FUNCTION_PADD_384BIT) { + if (!ecc->u.pm.point_2.x || + (ecc->u.pm.point_2.x_len > CCP_ECC_MODULUS_BYTES) || + !ecc->u.pm.point_2.y || + (ecc->u.pm.point_2.y_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + } else { + if (!ecc->u.pm.domain_a || + (ecc->u.pm.domain_a_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT) + if (!ecc->u.pm.scalar || + (ecc->u.pm.scalar_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + } + + if (!ecc->u.pm.result.x || + (ecc->u.pm.result.x_len < CCP_ECC_MODULUS_BYTES) || + !ecc->u.pm.result.y || + (ecc->u.pm.result.y_len < CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = ccp_gen_jobid(cmd_q->ccp); + + /* Concatenate the modulus and the operands. Both the modulus and + * the operands must be in little endian format. Since the input + * is in big endian format it must be converted and placed in a + * fixed length buffer. + */ + ret = ccp_init_dm_workarea(&src, cmd_q, CCP_ECC_SRC_BUF_SIZE, + DMA_TO_DEVICE); + if (ret) + return ret; + + /* Save the workarea address since it is updated in order to perform + * the concatenation + */ + save = src.address; + + /* Copy the ECC modulus */ + ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + + /* Copy the first point X and Y coordinate */ + ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.x, + ecc->u.pm.point_1.x_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.y, + ecc->u.pm.point_1.y_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + + /* Set the first point Z coordianate to 1 */ + *(src.address) = 0x01; + src.address += CCP_ECC_OPERAND_SIZE; + + if (ecc->function == CCP_ECC_FUNCTION_PADD_384BIT) { + /* Copy the second point X and Y coordinate */ + ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.x, + ecc->u.pm.point_2.x_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.y, + ecc->u.pm.point_2.y_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + + /* Set the second point Z coordianate to 1 */ + *(src.address) = 0x01; + src.address += CCP_ECC_OPERAND_SIZE; + } else { + /* Copy the Domain "a" parameter */ + ccp_reverse_set_dm_area(&src, ecc->u.pm.domain_a, + ecc->u.pm.domain_a_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + + if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT) { + /* Copy the scalar value */ + ccp_reverse_set_dm_area(&src, ecc->u.pm.scalar, + ecc->u.pm.scalar_len, + CCP_ECC_OPERAND_SIZE, true); + src.address += CCP_ECC_OPERAND_SIZE; + } + } + + /* Restore the workarea address */ + src.address = save; + + /* Prepare the output area for the operation */ + ret = ccp_init_dm_workarea(&dst, cmd_q, CCP_ECC_DST_BUF_SIZE, + DMA_FROM_DEVICE); + if (ret) + goto e_src; + + op.soc = 1; + op.src.u.dma.address = src.dma.address; + op.src.u.dma.offset = 0; + op.src.u.dma.length = src.length; + op.dst.u.dma.address = dst.dma.address; + op.dst.u.dma.offset = 0; + op.dst.u.dma.length = dst.length; + + op.u.ecc.function = cmd->u.ecc.function; + + ret = ccp_perform_ecc(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ecc->ecc_result = le16_to_cpup( + (const __le16 *)(dst.address + CCP_ECC_RESULT_OFFSET)); + if (!(ecc->ecc_result & CCP_ECC_RESULT_SUCCESS)) { + ret = -EIO; + goto e_dst; + } + + /* Save the workarea address since it is updated as we walk through + * to copy the point math result + */ + save = dst.address; + + /* Save the ECC result X and Y coordinates */ + ccp_reverse_get_dm_area(&dst, ecc->u.pm.result.x, + CCP_ECC_MODULUS_BYTES); + dst.address += CCP_ECC_OUTPUT_SIZE; + ccp_reverse_get_dm_area(&dst, ecc->u.pm.result.y, + CCP_ECC_MODULUS_BYTES); + dst.address += CCP_ECC_OUTPUT_SIZE; + + /* Restore the workarea address */ + dst.address = save; + +e_dst: + ccp_dm_free(&dst); + +e_src: + ccp_dm_free(&src); + + return ret; +} + +static int ccp_run_ecc_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_ecc_engine *ecc = &cmd->u.ecc; + + ecc->ecc_result = 0; + + if (!ecc->mod || + (ecc->mod_len > CCP_ECC_MODULUS_BYTES)) + return -EINVAL; + + switch (ecc->function) { + case CCP_ECC_FUNCTION_MMUL_384BIT: + case CCP_ECC_FUNCTION_MADD_384BIT: + case CCP_ECC_FUNCTION_MINV_384BIT: + return ccp_run_ecc_mm_cmd(cmd_q, cmd); + + case CCP_ECC_FUNCTION_PADD_384BIT: + case CCP_ECC_FUNCTION_PMUL_384BIT: + case CCP_ECC_FUNCTION_PDBL_384BIT: + return ccp_run_ecc_pm_cmd(cmd_q, cmd); + + default: + return -EINVAL; + } +} + +int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + int ret; + + cmd->engine_error = 0; + cmd_q->cmd_error = 0; + cmd_q->int_rcvd = 0; + cmd_q->free_slots = CMD_Q_DEPTH(ioread32(cmd_q->reg_status)); + + switch (cmd->engine) { + case CCP_ENGINE_AES: + ret = ccp_run_aes_cmd(cmd_q, cmd); + break; + case CCP_ENGINE_XTS_AES_128: + ret = ccp_run_xts_aes_cmd(cmd_q, cmd); + break; + case CCP_ENGINE_SHA: + ret = ccp_run_sha_cmd(cmd_q, cmd); + break; + case CCP_ENGINE_RSA: + ret = ccp_run_rsa_cmd(cmd_q, cmd); + break; + case CCP_ENGINE_PASSTHRU: + ret = ccp_run_passthru_cmd(cmd_q, cmd); + break; + case CCP_ENGINE_ECC: + ret = ccp_run_ecc_cmd(cmd_q, cmd); + break; + default: + ret = -EINVAL; + } + + return ret; +} diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c new file mode 100644 index 000000000000..1fbeaf1856a8 --- /dev/null +++ b/drivers/crypto/ccp/ccp-pci.c @@ -0,0 +1,360 @@ +/* + * AMD Cryptographic Coprocessor (CCP) driver + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-dev.h" + +#define IO_BAR 2 +#define MSIX_VECTORS 2 + +struct ccp_msix { + u32 vector; + char name[16]; +}; + +struct ccp_pci { + int msix_count; + struct ccp_msix msix[MSIX_VECTORS]; +}; + +static int ccp_get_msix_irqs(struct ccp_device *ccp) +{ + struct ccp_pci *ccp_pci = ccp->dev_specific; + struct device *dev = ccp->dev; + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct msix_entry msix_entry[MSIX_VECTORS]; + unsigned int name_len = sizeof(ccp_pci->msix[0].name) - 1; + int v, ret; + + for (v = 0; v < ARRAY_SIZE(msix_entry); v++) + msix_entry[v].entry = v; + + while ((ret = pci_enable_msix(pdev, msix_entry, v)) > 0) + v = ret; + if (ret) + return ret; + + ccp_pci->msix_count = v; + for (v = 0; v < ccp_pci->msix_count; v++) { + /* Set the interrupt names and request the irqs */ + snprintf(ccp_pci->msix[v].name, name_len, "ccp-%u", v); + ccp_pci->msix[v].vector = msix_entry[v].vector; + ret = request_irq(ccp_pci->msix[v].vector, ccp_irq_handler, + 0, ccp_pci->msix[v].name, dev); + if (ret) { + dev_notice(dev, "unable to allocate MSI-X IRQ (%d)\n", + ret); + goto e_irq; + } + } + + return 0; + +e_irq: + while (v--) + free_irq(ccp_pci->msix[v].vector, dev); + + pci_disable_msix(pdev); + + ccp_pci->msix_count = 0; + + return ret; +} + +static int ccp_get_msi_irq(struct ccp_device *ccp) +{ + struct device *dev = ccp->dev; + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + int ret; + + ret = pci_enable_msi(pdev); + if (ret) + return ret; + + ret = request_irq(pdev->irq, ccp_irq_handler, 0, "ccp", dev); + if (ret) { + dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret); + goto e_msi; + } + + return 0; + +e_msi: + pci_disable_msi(pdev); + + return ret; +} + +static int ccp_get_irqs(struct ccp_device *ccp) +{ + struct device *dev = ccp->dev; + int ret; + + ret = ccp_get_msix_irqs(ccp); + if (!ret) + return 0; + + /* Couldn't get MSI-X vectors, try MSI */ + dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret); + ret = ccp_get_msi_irq(ccp); + if (!ret) + return 0; + + /* Couldn't get MSI interrupt */ + dev_notice(dev, "could not enable MSI (%d)\n", ret); + + return ret; +} + +static void ccp_free_irqs(struct ccp_device *ccp) +{ + struct ccp_pci *ccp_pci = ccp->dev_specific; + struct device *dev = ccp->dev; + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + + if (ccp_pci->msix_count) { + while (ccp_pci->msix_count--) + free_irq(ccp_pci->msix[ccp_pci->msix_count].vector, + dev); + pci_disable_msix(pdev); + } else { + free_irq(pdev->irq, dev); + pci_disable_msi(pdev); + } +} + +static int ccp_find_mmio_area(struct ccp_device *ccp) +{ + struct device *dev = ccp->dev; + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + resource_size_t io_len; + unsigned long io_flags; + int bar; + + io_flags = pci_resource_flags(pdev, IO_BAR); + io_len = pci_resource_len(pdev, IO_BAR); + if ((io_flags & IORESOURCE_MEM) && (io_len >= (IO_OFFSET + 0x800))) + return IO_BAR; + + for (bar = 0; bar < PCI_STD_RESOURCE_END; bar++) { + io_flags = pci_resource_flags(pdev, bar); + io_len = pci_resource_len(pdev, bar); + if ((io_flags & IORESOURCE_MEM) && + (io_len >= (IO_OFFSET + 0x800))) + return bar; + } + + return -EIO; +} + +static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct ccp_device *ccp; + struct ccp_pci *ccp_pci; + struct device *dev = &pdev->dev; + unsigned int bar; + int ret; + + ret = -ENOMEM; + ccp = ccp_alloc_struct(dev); + if (!ccp) + goto e_err; + + ccp_pci = kzalloc(sizeof(*ccp_pci), GFP_KERNEL); + if (!ccp_pci) { + ret = -ENOMEM; + goto e_free1; + } + ccp->dev_specific = ccp_pci; + ccp->get_irq = ccp_get_irqs; + ccp->free_irq = ccp_free_irqs; + + ret = pci_request_regions(pdev, "ccp"); + if (ret) { + dev_err(dev, "pci_request_regions failed (%d)\n", ret); + goto e_free2; + } + + ret = pci_enable_device(pdev); + if (ret) { + dev_err(dev, "pci_enable_device failed (%d)\n", ret); + goto e_regions; + } + + pci_set_master(pdev); + + ret = ccp_find_mmio_area(ccp); + if (ret < 0) + goto e_device; + bar = ret; + + ret = -EIO; + ccp->io_map = pci_iomap(pdev, bar, 0); + if (ccp->io_map == NULL) { + dev_err(dev, "pci_iomap failed\n"); + goto e_device; + } + ccp->io_regs = ccp->io_map + IO_OFFSET; + + ret = dma_set_mask(dev, DMA_BIT_MASK(48)); + if (ret == 0) { + ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(48)); + if (ret) { + dev_err(dev, + "pci_set_consistent_dma_mask failed (%d)\n", + ret); + goto e_bar0; + } + } else { + ret = dma_set_mask(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "pci_set_dma_mask failed (%d)\n", ret); + goto e_bar0; + } + } + + dev_set_drvdata(dev, ccp); + + ret = ccp_init(ccp); + if (ret) + goto e_bar0; + + dev_notice(dev, "enabled\n"); + + return 0; + +e_bar0: + pci_iounmap(pdev, ccp->io_map); + +e_device: + pci_disable_device(pdev); + dev_set_drvdata(dev, NULL); + +e_regions: + pci_release_regions(pdev); + +e_free2: + kfree(ccp_pci); + +e_free1: + kfree(ccp); + +e_err: + dev_notice(dev, "initialization failed\n"); + return ret; +} + +static void ccp_pci_remove(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct ccp_device *ccp = dev_get_drvdata(dev); + + ccp_destroy(ccp); + + pci_iounmap(pdev, ccp->io_map); + + pci_disable_device(pdev); + dev_set_drvdata(dev, NULL); + + pci_release_regions(pdev); + + kfree(ccp); + + dev_notice(dev, "disabled\n"); +} + +#ifdef CONFIG_PM +static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct device *dev = &pdev->dev; + struct ccp_device *ccp = dev_get_drvdata(dev); + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&ccp->cmd_lock, flags); + + ccp->suspending = 1; + + /* Wake all the queue kthreads to prepare for suspend */ + for (i = 0; i < ccp->cmd_q_count; i++) + wake_up_process(ccp->cmd_q[i].kthread); + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + + /* Wait for all queue kthreads to say they're done */ + while (!ccp_queues_suspended(ccp)) + wait_event_interruptible(ccp->suspend_queue, + ccp_queues_suspended(ccp)); + + return 0; +} + +static int ccp_pci_resume(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct ccp_device *ccp = dev_get_drvdata(dev); + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&ccp->cmd_lock, flags); + + ccp->suspending = 0; + + /* Wake up all the kthreads */ + for (i = 0; i < ccp->cmd_q_count; i++) { + ccp->cmd_q[i].suspended = 0; + wake_up_process(ccp->cmd_q[i].kthread); + } + + spin_unlock_irqrestore(&ccp->cmd_lock, flags); + + return 0; +} +#endif + +static DEFINE_PCI_DEVICE_TABLE(ccp_pci_table) = { + { PCI_VDEVICE(AMD, 0x1537), }, + /* Last entry must be zero */ + { 0, } +}; +MODULE_DEVICE_TABLE(pci, ccp_pci_table); + +static struct pci_driver ccp_pci_driver = { + .name = "AMD Cryptographic Coprocessor", + .id_table = ccp_pci_table, + .probe = ccp_pci_probe, + .remove = ccp_pci_remove, +#ifdef CONFIG_PM + .suspend = ccp_pci_suspend, + .resume = ccp_pci_resume, +#endif +}; + +int ccp_pci_init(void) +{ + return pci_register_driver(&ccp_pci_driver); +} + +void ccp_pci_exit(void) +{ + pci_unregister_driver(&ccp_pci_driver); +} diff --git a/include/linux/ccp.h b/include/linux/ccp.h new file mode 100644 index 000000000000..e8c23493ab4b --- /dev/null +++ b/include/linux/ccp.h @@ -0,0 +1,525 @@ +/* + * AMD Cryptographic Coprocessor (CCP) driver + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __CPP_H__ +#define __CPP_H__ + +#include +#include +#include +#include +#include + + +struct ccp_device; +struct ccp_cmd; + +/** + * ccp_enqueue_cmd - queue an operation for processing by the CCP + * + * @cmd: ccp_cmd struct to be processed + * + * Refer to the ccp_cmd struct below for required fields. + * + * Queue a cmd to be processed by the CCP. If queueing the cmd + * would exceed the defined length of the cmd queue the cmd will + * only be queued if the CCP_CMD_MAY_BACKLOG flag is set and will + * result in a return code of -EBUSY. + * + * The callback routine specified in the ccp_cmd struct will be + * called to notify the caller of completion (if the cmd was not + * backlogged) or advancement out of the backlog. If the cmd has + * advanced out of the backlog the "err" value of the callback + * will be -EINPROGRESS. Any other "err" value during callback is + * the result of the operation. + * + * The cmd has been successfully queued if: + * the return code is -EINPROGRESS or + * the return code is -EBUSY and CCP_CMD_MAY_BACKLOG flag is set + */ +int ccp_enqueue_cmd(struct ccp_cmd *cmd); + + +/***** AES engine *****/ +/** + * ccp_aes_type - AES key size + * + * @CCP_AES_TYPE_128: 128-bit key + * @CCP_AES_TYPE_192: 192-bit key + * @CCP_AES_TYPE_256: 256-bit key + */ +enum ccp_aes_type { + CCP_AES_TYPE_128 = 0, + CCP_AES_TYPE_192, + CCP_AES_TYPE_256, + CCP_AES_TYPE__LAST, +}; + +/** + * ccp_aes_mode - AES operation mode + * + * @CCP_AES_MODE_ECB: ECB mode + * @CCP_AES_MODE_CBC: CBC mode + * @CCP_AES_MODE_OFB: OFB mode + * @CCP_AES_MODE_CFB: CFB mode + * @CCP_AES_MODE_CTR: CTR mode + * @CCP_AES_MODE_CMAC: CMAC mode + */ +enum ccp_aes_mode { + CCP_AES_MODE_ECB = 0, + CCP_AES_MODE_CBC, + CCP_AES_MODE_OFB, + CCP_AES_MODE_CFB, + CCP_AES_MODE_CTR, + CCP_AES_MODE_CMAC, + CCP_AES_MODE__LAST, +}; + +/** + * ccp_aes_mode - AES operation mode + * + * @CCP_AES_ACTION_DECRYPT: AES decrypt operation + * @CCP_AES_ACTION_ENCRYPT: AES encrypt operation + */ +enum ccp_aes_action { + CCP_AES_ACTION_DECRYPT = 0, + CCP_AES_ACTION_ENCRYPT, + CCP_AES_ACTION__LAST, +}; + +/** + * struct ccp_aes_engine - CCP AES operation + * @type: AES operation key size + * @mode: AES operation mode + * @action: AES operation (decrypt/encrypt) + * @key: key to be used for this AES operation + * @key_len: length in bytes of key + * @iv: IV to be used for this AES operation + * @iv_len: length in bytes of iv + * @src: data to be used for this operation + * @dst: data produced by this operation + * @src_len: length in bytes of data used for this operation + * @cmac_final: indicates final operation when running in CMAC mode + * @cmac_key: K1/K2 key used in final CMAC operation + * @cmac_key_len: length in bytes of cmac_key + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - type, mode, action, key, key_len, src, dst, src_len + * - iv, iv_len for any mode other than ECB + * - cmac_final for CMAC mode + * - cmac_key, cmac_key_len for CMAC mode if cmac_final is non-zero + * + * The iv variable is used as both input and output. On completion of the + * AES operation the new IV overwrites the old IV. + */ +struct ccp_aes_engine { + enum ccp_aes_type type; + enum ccp_aes_mode mode; + enum ccp_aes_action action; + + struct scatterlist *key; + u32 key_len; /* In bytes */ + + struct scatterlist *iv; + u32 iv_len; /* In bytes */ + + struct scatterlist *src, *dst; + u32 src_len; /* In bytes */ + + u32 cmac_final; /* Indicates final cmac cmd */ + struct scatterlist *cmac_key; /* K1/K2 cmac key required for + * final cmac cmd */ + u32 cmac_key_len; /* In bytes */ +}; + +/***** XTS-AES engine *****/ +/** + * ccp_xts_aes_unit_size - XTS unit size + * + * @CCP_XTS_AES_UNIT_SIZE_16: Unit size of 16 bytes + * @CCP_XTS_AES_UNIT_SIZE_512: Unit size of 512 bytes + * @CCP_XTS_AES_UNIT_SIZE_1024: Unit size of 1024 bytes + * @CCP_XTS_AES_UNIT_SIZE_2048: Unit size of 2048 bytes + * @CCP_XTS_AES_UNIT_SIZE_4096: Unit size of 4096 bytes + */ +enum ccp_xts_aes_unit_size { + CCP_XTS_AES_UNIT_SIZE_16 = 0, + CCP_XTS_AES_UNIT_SIZE_512, + CCP_XTS_AES_UNIT_SIZE_1024, + CCP_XTS_AES_UNIT_SIZE_2048, + CCP_XTS_AES_UNIT_SIZE_4096, + CCP_XTS_AES_UNIT_SIZE__LAST, +}; + +/** + * struct ccp_xts_aes_engine - CCP XTS AES operation + * @action: AES operation (decrypt/encrypt) + * @unit_size: unit size of the XTS operation + * @key: key to be used for this XTS AES operation + * @key_len: length in bytes of key + * @iv: IV to be used for this XTS AES operation + * @iv_len: length in bytes of iv + * @src: data to be used for this operation + * @dst: data produced by this operation + * @src_len: length in bytes of data used for this operation + * @final: indicates final XTS operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - action, unit_size, key, key_len, iv, iv_len, src, dst, src_len, final + * + * The iv variable is used as both input and output. On completion of the + * AES operation the new IV overwrites the old IV. + */ +struct ccp_xts_aes_engine { + enum ccp_aes_action action; + enum ccp_xts_aes_unit_size unit_size; + + struct scatterlist *key; + u32 key_len; /* In bytes */ + + struct scatterlist *iv; + u32 iv_len; /* In bytes */ + + struct scatterlist *src, *dst; + u32 src_len; /* In bytes */ + + u32 final; +}; + +/***** SHA engine *****/ +#define CCP_SHA_BLOCKSIZE SHA256_BLOCK_SIZE +#define CCP_SHA_CTXSIZE SHA256_DIGEST_SIZE + +/** + * ccp_sha_type - type of SHA operation + * + * @CCP_SHA_TYPE_1: SHA-1 operation + * @CCP_SHA_TYPE_224: SHA-224 operation + * @CCP_SHA_TYPE_256: SHA-256 operation + */ +enum ccp_sha_type { + CCP_SHA_TYPE_1 = 1, + CCP_SHA_TYPE_224, + CCP_SHA_TYPE_256, + CCP_SHA_TYPE__LAST, +}; + +/** + * struct ccp_sha_engine - CCP SHA operation + * @type: Type of SHA operation + * @ctx: current hash value + * @ctx_len: length in bytes of hash value + * @src: data to be used for this operation + * @src_len: length in bytes of data used for this operation + * @final: indicates final SHA operation + * @msg_bits: total length of the message in bits used in final SHA operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - type, ctx, ctx_len, src, src_len, final + * - msg_bits if final is non-zero + * + * The ctx variable is used as both input and output. On completion of the + * SHA operation the new hash value overwrites the old hash value. + */ +struct ccp_sha_engine { + enum ccp_sha_type type; + + struct scatterlist *ctx; + u32 ctx_len; /* In bytes */ + + struct scatterlist *src; + u32 src_len; /* In bytes */ + + u32 final; /* Indicates final sha cmd */ + u64 msg_bits; /* Message length in bits required for + * final sha cmd */ +}; + +/***** RSA engine *****/ +/** + * struct ccp_rsa_engine - CCP RSA operation + * @key_size: length in bits of RSA key + * @exp: RSA exponent + * @exp_len: length in bytes of exponent + * @mod: RSA modulus + * @mod_len: length in bytes of modulus + * @src: data to be used for this operation + * @dst: data produced by this operation + * @src_len: length in bytes of data used for this operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - key_size, exp, exp_len, mod, mod_len, src, dst, src_len + */ +struct ccp_rsa_engine { + u32 key_size; /* In bits */ + + struct scatterlist *exp; + u32 exp_len; /* In bytes */ + + struct scatterlist *mod; + u32 mod_len; /* In bytes */ + + struct scatterlist *src, *dst; + u32 src_len; /* In bytes */ +}; + +/***** Passthru engine *****/ +/** + * ccp_passthru_bitwise - type of bitwise passthru operation + * + * @CCP_PASSTHRU_BITWISE_NOOP: no bitwise operation performed + * @CCP_PASSTHRU_BITWISE_AND: perform bitwise AND of src with mask + * @CCP_PASSTHRU_BITWISE_OR: perform bitwise OR of src with mask + * @CCP_PASSTHRU_BITWISE_XOR: perform bitwise XOR of src with mask + * @CCP_PASSTHRU_BITWISE_MASK: overwrite with mask + */ +enum ccp_passthru_bitwise { + CCP_PASSTHRU_BITWISE_NOOP = 0, + CCP_PASSTHRU_BITWISE_AND, + CCP_PASSTHRU_BITWISE_OR, + CCP_PASSTHRU_BITWISE_XOR, + CCP_PASSTHRU_BITWISE_MASK, + CCP_PASSTHRU_BITWISE__LAST, +}; + +/** + * ccp_passthru_byteswap - type of byteswap passthru operation + * + * @CCP_PASSTHRU_BYTESWAP_NOOP: no byte swapping performed + * @CCP_PASSTHRU_BYTESWAP_32BIT: swap bytes within 32-bit words + * @CCP_PASSTHRU_BYTESWAP_256BIT: swap bytes within 256-bit words + */ +enum ccp_passthru_byteswap { + CCP_PASSTHRU_BYTESWAP_NOOP = 0, + CCP_PASSTHRU_BYTESWAP_32BIT, + CCP_PASSTHRU_BYTESWAP_256BIT, + CCP_PASSTHRU_BYTESWAP__LAST, +}; + +/** + * struct ccp_passthru_engine - CCP pass-through operation + * @bit_mod: bitwise operation to perform + * @byte_swap: byteswap operation to perform + * @mask: mask to be applied to data + * @mask_len: length in bytes of mask + * @src: data to be used for this operation + * @dst: data produced by this operation + * @src_len: length in bytes of data used for this operation + * @final: indicate final pass-through operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - bit_mod, byte_swap, src, dst, src_len + * - mask, mask_len if bit_mod is not CCP_PASSTHRU_BITWISE_NOOP + */ +struct ccp_passthru_engine { + enum ccp_passthru_bitwise bit_mod; + enum ccp_passthru_byteswap byte_swap; + + struct scatterlist *mask; + u32 mask_len; /* In bytes */ + + struct scatterlist *src, *dst; + u32 src_len; /* In bytes */ + + u32 final; +}; + +/***** ECC engine *****/ +#define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */ +#define CCP_ECC_MAX_OPERANDS 6 +#define CCP_ECC_MAX_OUTPUTS 3 + +/** + * ccp_ecc_function - type of ECC function + * + * @CCP_ECC_FUNCTION_MMUL_384BIT: 384-bit modular multiplication + * @CCP_ECC_FUNCTION_MADD_384BIT: 384-bit modular addition + * @CCP_ECC_FUNCTION_MINV_384BIT: 384-bit multiplicative inverse + * @CCP_ECC_FUNCTION_PADD_384BIT: 384-bit point addition + * @CCP_ECC_FUNCTION_PMUL_384BIT: 384-bit point multiplication + * @CCP_ECC_FUNCTION_PDBL_384BIT: 384-bit point doubling + */ +enum ccp_ecc_function { + CCP_ECC_FUNCTION_MMUL_384BIT = 0, + CCP_ECC_FUNCTION_MADD_384BIT, + CCP_ECC_FUNCTION_MINV_384BIT, + CCP_ECC_FUNCTION_PADD_384BIT, + CCP_ECC_FUNCTION_PMUL_384BIT, + CCP_ECC_FUNCTION_PDBL_384BIT, +}; + +/** + * struct ccp_ecc_modular_math - CCP ECC modular math parameters + * @operand_1: first operand for the modular math operation + * @operand_1_len: length of the first operand + * @operand_2: second operand for the modular math operation + * (not used for CCP_ECC_FUNCTION_MINV_384BIT) + * @operand_2_len: length of the second operand + * (not used for CCP_ECC_FUNCTION_MINV_384BIT) + * @result: result of the modular math operation + * @result_len: length of the supplied result buffer + */ +struct ccp_ecc_modular_math { + struct scatterlist *operand_1; + unsigned int operand_1_len; /* In bytes */ + + struct scatterlist *operand_2; + unsigned int operand_2_len; /* In bytes */ + + struct scatterlist *result; + unsigned int result_len; /* In bytes */ +}; + +/** + * struct ccp_ecc_point - CCP ECC point definition + * @x: the x coordinate of the ECC point + * @x_len: the length of the x coordinate + * @y: the y coordinate of the ECC point + * @y_len: the length of the y coordinate + */ +struct ccp_ecc_point { + struct scatterlist *x; + unsigned int x_len; /* In bytes */ + + struct scatterlist *y; + unsigned int y_len; /* In bytes */ +}; + +/** + * struct ccp_ecc_point_math - CCP ECC point math parameters + * @point_1: the first point of the ECC point math operation + * @point_2: the second point of the ECC point math operation + * (only used for CCP_ECC_FUNCTION_PADD_384BIT) + * @domain_a: the a parameter of the ECC curve + * @domain_a_len: the length of the a parameter + * @scalar: the scalar parameter for the point match operation + * (only used for CCP_ECC_FUNCTION_PMUL_384BIT) + * @scalar_len: the length of the scalar parameter + * (only used for CCP_ECC_FUNCTION_PMUL_384BIT) + * @result: the point resulting from the point math operation + */ +struct ccp_ecc_point_math { + struct ccp_ecc_point point_1; + struct ccp_ecc_point point_2; + + struct scatterlist *domain_a; + unsigned int domain_a_len; /* In bytes */ + + struct scatterlist *scalar; + unsigned int scalar_len; /* In bytes */ + + struct ccp_ecc_point result; +}; + +/** + * struct ccp_ecc_engine - CCP ECC operation + * @function: ECC function to perform + * @mod: ECC modulus + * @mod_len: length in bytes of modulus + * @mm: module math parameters + * @pm: point math parameters + * @ecc_result: result of the ECC operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - function, mod, mod_len + * - operand, operand_len, operand_count, output, output_len, output_count + * - ecc_result + */ +struct ccp_ecc_engine { + enum ccp_ecc_function function; + + struct scatterlist *mod; + u32 mod_len; /* In bytes */ + + union { + struct ccp_ecc_modular_math mm; + struct ccp_ecc_point_math pm; + } u; + + u16 ecc_result; +}; + + +/** + * ccp_engine - CCP operation identifiers + * + * @CCP_ENGINE_AES: AES operation + * @CCP_ENGINE_XTS_AES: 128-bit XTS AES operation + * @CCP_ENGINE_RSVD1: unused + * @CCP_ENGINE_SHA: SHA operation + * @CCP_ENGINE_RSA: RSA operation + * @CCP_ENGINE_PASSTHRU: pass-through operation + * @CCP_ENGINE_ZLIB_DECOMPRESS: unused + * @CCP_ENGINE_ECC: ECC operation + */ +enum ccp_engine { + CCP_ENGINE_AES = 0, + CCP_ENGINE_XTS_AES_128, + CCP_ENGINE_RSVD1, + CCP_ENGINE_SHA, + CCP_ENGINE_RSA, + CCP_ENGINE_PASSTHRU, + CCP_ENGINE_ZLIB_DECOMPRESS, + CCP_ENGINE_ECC, + CCP_ENGINE__LAST, +}; + +/* Flag values for flags member of ccp_cmd */ +#define CCP_CMD_MAY_BACKLOG 0x00000001 + +/** + * struct ccp_cmd - CPP operation request + * @entry: list element (ccp driver use only) + * @work: work element used for callbacks (ccp driver use only) + * @ccp: CCP device to be run on (ccp driver use only) + * @ret: operation return code (ccp driver use only) + * @flags: cmd processing flags + * @engine: CCP operation to perform + * @engine_error: CCP engine return code + * @u: engine specific structures, refer to specific engine struct below + * @callback: operation completion callback function + * @data: parameter value to be supplied to the callback function + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - engine, callback + * - See the operation structures below for what is required for each + * operation. + */ +struct ccp_cmd { + /* The list_head, work_struct, ccp and ret variables are for use + * by the CCP driver only. + */ + struct list_head entry; + struct work_struct work; + struct ccp_device *ccp; + int ret; + + u32 flags; + + enum ccp_engine engine; + u32 engine_error; + + union { + struct ccp_aes_engine aes; + struct ccp_xts_aes_engine xts; + struct ccp_sha_engine sha; + struct ccp_rsa_engine rsa; + struct ccp_passthru_engine passthru; + struct ccp_ecc_engine ecc; + } u; + + /* Completion callback support */ + void (*callback)(void *data, int err); + void *data; +}; + +#endif -- cgit v1.2.3 From d312359978e91fc43889ac0d386ab617215f802a Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:22 -0600 Subject: crypto: ccp - crypto API interface to the CCP device driver These routines provide the support for the interface between the crypto API and the AMD CCP. This includes insuring that requests associated with a given tfm on the same cpu are processed in the order received. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-main.c | 432 +++++++++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto.h | 191 ++++++++++++++++ 2 files changed, 623 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-crypto-main.c create mode 100644 drivers/crypto/ccp/ccp-crypto.h (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c new file mode 100644 index 000000000000..2636f044789d --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-main.c @@ -0,0 +1,432 @@ +/* + * AMD Cryptographic Coprocessor (CCP) crypto API support + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "ccp-crypto.h" + +MODULE_AUTHOR("Tom Lendacky "); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0.0"); +MODULE_DESCRIPTION("AMD Cryptographic Coprocessor crypto API support"); + + +/* List heads for the supported algorithms */ +static LIST_HEAD(hash_algs); +static LIST_HEAD(cipher_algs); + +/* For any tfm, requests for that tfm on the same CPU must be returned + * in the order received. With multiple queues available, the CCP can + * process more than one cmd at a time. Therefore we must maintain + * a cmd list to insure the proper ordering of requests on a given tfm/cpu + * combination. + */ +struct ccp_crypto_cpu_queue { + struct list_head cmds; + struct list_head *backlog; + unsigned int cmd_count; +}; +#define CCP_CRYPTO_MAX_QLEN 50 + +struct ccp_crypto_percpu_queue { + struct ccp_crypto_cpu_queue __percpu *cpu_queue; +}; +static struct ccp_crypto_percpu_queue req_queue; + +struct ccp_crypto_cmd { + struct list_head entry; + + struct ccp_cmd *cmd; + + /* Save the crypto_tfm and crypto_async_request addresses + * separately to avoid any reference to a possibly invalid + * crypto_async_request structure after invoking the request + * callback + */ + struct crypto_async_request *req; + struct crypto_tfm *tfm; + + /* Used for held command processing to determine state */ + int ret; + + int cpu; +}; + +struct ccp_crypto_cpu { + struct work_struct work; + struct completion completion; + struct ccp_crypto_cmd *crypto_cmd; + int err; +}; + + +static inline bool ccp_crypto_success(int err) +{ + if (err && (err != -EINPROGRESS) && (err != -EBUSY)) + return false; + + return true; +} + +/* + * ccp_crypto_cmd_complete must be called while running on the appropriate + * cpu and the caller must have done a get_cpu to disable preemption + */ +static struct ccp_crypto_cmd *ccp_crypto_cmd_complete( + struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog) +{ + struct ccp_crypto_cpu_queue *cpu_queue; + struct ccp_crypto_cmd *held = NULL, *tmp; + + *backlog = NULL; + + cpu_queue = this_cpu_ptr(req_queue.cpu_queue); + + /* Held cmds will be after the current cmd in the queue so start + * searching for a cmd with a matching tfm for submission. + */ + tmp = crypto_cmd; + list_for_each_entry_continue(tmp, &cpu_queue->cmds, entry) { + if (crypto_cmd->tfm != tmp->tfm) + continue; + held = tmp; + break; + } + + /* Process the backlog: + * Because cmds can be executed from any point in the cmd list + * special precautions have to be taken when handling the backlog. + */ + if (cpu_queue->backlog != &cpu_queue->cmds) { + /* Skip over this cmd if it is the next backlog cmd */ + if (cpu_queue->backlog == &crypto_cmd->entry) + cpu_queue->backlog = crypto_cmd->entry.next; + + *backlog = container_of(cpu_queue->backlog, + struct ccp_crypto_cmd, entry); + cpu_queue->backlog = cpu_queue->backlog->next; + + /* Skip over this cmd if it is now the next backlog cmd */ + if (cpu_queue->backlog == &crypto_cmd->entry) + cpu_queue->backlog = crypto_cmd->entry.next; + } + + /* Remove the cmd entry from the list of cmds */ + cpu_queue->cmd_count--; + list_del(&crypto_cmd->entry); + + return held; +} + +static void ccp_crypto_complete_on_cpu(struct work_struct *work) +{ + struct ccp_crypto_cpu *cpu_work = + container_of(work, struct ccp_crypto_cpu, work); + struct ccp_crypto_cmd *crypto_cmd = cpu_work->crypto_cmd; + struct ccp_crypto_cmd *held, *next, *backlog; + struct crypto_async_request *req = crypto_cmd->req; + struct ccp_ctx *ctx = crypto_tfm_ctx(req->tfm); + int cpu, ret; + + cpu = get_cpu(); + + if (cpu_work->err == -EINPROGRESS) { + /* Only propogate the -EINPROGRESS if necessary */ + if (crypto_cmd->ret == -EBUSY) { + crypto_cmd->ret = -EINPROGRESS; + req->complete(req, -EINPROGRESS); + } + + goto e_cpu; + } + + /* Operation has completed - update the queue before invoking + * the completion callbacks and retrieve the next cmd (cmd with + * a matching tfm) that can be submitted to the CCP. + */ + held = ccp_crypto_cmd_complete(crypto_cmd, &backlog); + if (backlog) { + backlog->ret = -EINPROGRESS; + backlog->req->complete(backlog->req, -EINPROGRESS); + } + + /* Transition the state from -EBUSY to -EINPROGRESS first */ + if (crypto_cmd->ret == -EBUSY) + req->complete(req, -EINPROGRESS); + + /* Completion callbacks */ + ret = cpu_work->err; + if (ctx->complete) + ret = ctx->complete(req, ret); + req->complete(req, ret); + + /* Submit the next cmd */ + while (held) { + ret = ccp_enqueue_cmd(held->cmd); + if (ccp_crypto_success(ret)) + break; + + /* Error occurred, report it and get the next entry */ + held->req->complete(held->req, ret); + + next = ccp_crypto_cmd_complete(held, &backlog); + if (backlog) { + backlog->ret = -EINPROGRESS; + backlog->req->complete(backlog->req, -EINPROGRESS); + } + + kfree(held); + held = next; + } + + kfree(crypto_cmd); + +e_cpu: + put_cpu(); + + complete(&cpu_work->completion); +} + +static void ccp_crypto_complete(void *data, int err) +{ + struct ccp_crypto_cmd *crypto_cmd = data; + struct ccp_crypto_cpu cpu_work; + + INIT_WORK(&cpu_work.work, ccp_crypto_complete_on_cpu); + init_completion(&cpu_work.completion); + cpu_work.crypto_cmd = crypto_cmd; + cpu_work.err = err; + + schedule_work_on(crypto_cmd->cpu, &cpu_work.work); + + /* Keep the completion call synchronous */ + wait_for_completion(&cpu_work.completion); +} + +static int ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd *crypto_cmd) +{ + struct ccp_crypto_cpu_queue *cpu_queue; + struct ccp_crypto_cmd *active = NULL, *tmp; + int cpu, ret; + + cpu = get_cpu(); + crypto_cmd->cpu = cpu; + + cpu_queue = this_cpu_ptr(req_queue.cpu_queue); + + /* Check if the cmd can/should be queued */ + if (cpu_queue->cmd_count >= CCP_CRYPTO_MAX_QLEN) { + ret = -EBUSY; + if (!(crypto_cmd->cmd->flags & CCP_CMD_MAY_BACKLOG)) + goto e_cpu; + } + + /* Look for an entry with the same tfm. If there is a cmd + * with the same tfm in the list for this cpu then the current + * cmd cannot be submitted to the CCP yet. + */ + list_for_each_entry(tmp, &cpu_queue->cmds, entry) { + if (crypto_cmd->tfm != tmp->tfm) + continue; + active = tmp; + break; + } + + ret = -EINPROGRESS; + if (!active) { + ret = ccp_enqueue_cmd(crypto_cmd->cmd); + if (!ccp_crypto_success(ret)) + goto e_cpu; + } + + if (cpu_queue->cmd_count >= CCP_CRYPTO_MAX_QLEN) { + ret = -EBUSY; + if (cpu_queue->backlog == &cpu_queue->cmds) + cpu_queue->backlog = &crypto_cmd->entry; + } + crypto_cmd->ret = ret; + + cpu_queue->cmd_count++; + list_add_tail(&crypto_cmd->entry, &cpu_queue->cmds); + +e_cpu: + put_cpu(); + + return ret; +} + +/** + * ccp_crypto_enqueue_request - queue an crypto async request for processing + * by the CCP + * + * @req: crypto_async_request struct to be processed + * @cmd: ccp_cmd struct to be sent to the CCP + */ +int ccp_crypto_enqueue_request(struct crypto_async_request *req, + struct ccp_cmd *cmd) +{ + struct ccp_crypto_cmd *crypto_cmd; + gfp_t gfp; + int ret; + + gfp = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; + + crypto_cmd = kzalloc(sizeof(*crypto_cmd), gfp); + if (!crypto_cmd) + return -ENOMEM; + + /* The tfm pointer must be saved and not referenced from the + * crypto_async_request (req) pointer because it is used after + * completion callback for the request and the req pointer + * might not be valid anymore. + */ + crypto_cmd->cmd = cmd; + crypto_cmd->req = req; + crypto_cmd->tfm = req->tfm; + + cmd->callback = ccp_crypto_complete; + cmd->data = crypto_cmd; + + if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG) + cmd->flags |= CCP_CMD_MAY_BACKLOG; + else + cmd->flags &= ~CCP_CMD_MAY_BACKLOG; + + ret = ccp_crypto_enqueue_cmd(crypto_cmd); + if (!ccp_crypto_success(ret)) + kfree(crypto_cmd); + + return ret; +} + +struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table, + struct scatterlist *sg_add) +{ + struct scatterlist *sg, *sg_last = NULL; + + for (sg = table->sgl; sg; sg = sg_next(sg)) + if (!sg_page(sg)) + break; + BUG_ON(!sg); + + for (; sg && sg_add; sg = sg_next(sg), sg_add = sg_next(sg_add)) { + sg_set_page(sg, sg_page(sg_add), sg_add->length, + sg_add->offset); + sg_last = sg; + } + BUG_ON(sg_add); + + return sg_last; +} + +static int ccp_register_algs(void) +{ + int ret; + + ret = ccp_register_aes_algs(&cipher_algs); + if (ret) + return ret; + + ret = ccp_register_aes_cmac_algs(&hash_algs); + if (ret) + return ret; + + ret = ccp_register_aes_xts_algs(&cipher_algs); + if (ret) + return ret; + + ret = ccp_register_sha_algs(&hash_algs); + if (ret) + return ret; + + return 0; +} + +static void ccp_unregister_algs(void) +{ + struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp; + struct ccp_crypto_ablkcipher_alg *ablk_alg, *ablk_tmp; + + list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) { + crypto_unregister_ahash(&ahash_alg->alg); + list_del(&ahash_alg->entry); + kfree(ahash_alg); + } + + list_for_each_entry_safe(ablk_alg, ablk_tmp, &cipher_algs, entry) { + crypto_unregister_alg(&ablk_alg->alg); + list_del(&ablk_alg->entry); + kfree(ablk_alg); + } +} + +static int ccp_init_queues(void) +{ + struct ccp_crypto_cpu_queue *cpu_queue; + int cpu; + + req_queue.cpu_queue = alloc_percpu(struct ccp_crypto_cpu_queue); + if (!req_queue.cpu_queue) + return -ENOMEM; + + for_each_possible_cpu(cpu) { + cpu_queue = per_cpu_ptr(req_queue.cpu_queue, cpu); + INIT_LIST_HEAD(&cpu_queue->cmds); + cpu_queue->backlog = &cpu_queue->cmds; + cpu_queue->cmd_count = 0; + } + + return 0; +} + +static void ccp_fini_queue(void) +{ + struct ccp_crypto_cpu_queue *cpu_queue; + int cpu; + + for_each_possible_cpu(cpu) { + cpu_queue = per_cpu_ptr(req_queue.cpu_queue, cpu); + BUG_ON(!list_empty(&cpu_queue->cmds)); + } + free_percpu(req_queue.cpu_queue); +} + +static int ccp_crypto_init(void) +{ + int ret; + + ret = ccp_init_queues(); + if (ret) + return ret; + + ret = ccp_register_algs(); + if (ret) { + ccp_unregister_algs(); + ccp_fini_queue(); + } + + return ret; +} + +static void ccp_crypto_exit(void) +{ + ccp_unregister_algs(); + ccp_fini_queue(); +} + +module_init(ccp_crypto_init); +module_exit(ccp_crypto_exit); diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h new file mode 100644 index 000000000000..45f17c394e4a --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -0,0 +1,191 @@ +/* + * AMD Cryptographic Coprocessor (CCP) crypto API support + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __CCP_CRYPTO_H__ +#define __CCP_CRYPTO_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CCP_CRA_PRIORITY 300 + +struct ccp_crypto_ablkcipher_alg { + struct list_head entry; + + u32 mode; + + struct crypto_alg alg; +}; + +struct ccp_crypto_ahash_alg { + struct list_head entry; + + const u32 *init; + u32 type; + u32 mode; + + /* Child algorithm used for HMAC, CMAC, etc */ + char child_alg[CRYPTO_MAX_ALG_NAME]; + + struct ahash_alg alg; +}; + +static inline struct ccp_crypto_ablkcipher_alg * + ccp_crypto_ablkcipher_alg(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + + return container_of(alg, struct ccp_crypto_ablkcipher_alg, alg); +} + +static inline struct ccp_crypto_ahash_alg * + ccp_crypto_ahash_alg(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + struct ahash_alg *ahash_alg; + + ahash_alg = container_of(alg, struct ahash_alg, halg.base); + + return container_of(ahash_alg, struct ccp_crypto_ahash_alg, alg); +} + + +/***** AES related defines *****/ +struct ccp_aes_ctx { + /* Fallback cipher for XTS with unsupported unit sizes */ + struct crypto_ablkcipher *tfm_ablkcipher; + + /* Cipher used to generate CMAC K1/K2 keys */ + struct crypto_cipher *tfm_cipher; + + enum ccp_engine engine; + enum ccp_aes_type type; + enum ccp_aes_mode mode; + + struct scatterlist key_sg; + unsigned int key_len; + u8 key[AES_MAX_KEY_SIZE]; + + u8 nonce[CTR_RFC3686_NONCE_SIZE]; + + /* CMAC key structures */ + struct scatterlist k1_sg; + struct scatterlist k2_sg; + unsigned int kn_len; + u8 k1[AES_BLOCK_SIZE]; + u8 k2[AES_BLOCK_SIZE]; +}; + +struct ccp_aes_req_ctx { + struct scatterlist iv_sg; + u8 iv[AES_BLOCK_SIZE]; + + /* Fields used for RFC3686 requests */ + u8 *rfc3686_info; + u8 rfc3686_iv[AES_BLOCK_SIZE]; + + struct ccp_cmd cmd; +}; + +struct ccp_aes_cmac_req_ctx { + unsigned int null_msg; + unsigned int final; + + unsigned int hash_cnt; + unsigned int hash_rem; + + struct sg_table data_sg; + + struct scatterlist iv_sg; + u8 iv[AES_BLOCK_SIZE]; + + struct scatterlist buf_sg; + unsigned int buf_count; + u8 buf[AES_BLOCK_SIZE]; + + struct scatterlist pad_sg; + unsigned int pad_count; + u8 pad[AES_BLOCK_SIZE]; + + struct ccp_cmd cmd; +}; + +/***** SHA related defines *****/ +#define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE +#define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE + +struct ccp_sha_ctx { + unsigned int key_len; + u8 key[MAX_SHA_BLOCK_SIZE]; + u8 ipad[MAX_SHA_BLOCK_SIZE]; + u8 opad[MAX_SHA_BLOCK_SIZE]; + struct crypto_ahash *hmac_tfm; +}; + +struct ccp_sha_req_ctx { + enum ccp_sha_type type; + + u64 msg_bits; + + unsigned int first; + unsigned int final; + + unsigned int hash_cnt; + unsigned int hash_rem; + + struct sg_table data_sg; + + struct scatterlist ctx_sg; + u8 ctx[MAX_SHA_CONTEXT_SIZE]; + + struct scatterlist buf_sg; + unsigned int buf_count; + u8 buf[MAX_SHA_BLOCK_SIZE]; + + /* HMAC support field */ + struct scatterlist pad_sg; + + /* CCP driver command */ + struct ccp_cmd cmd; +}; + +/***** Common Context Structure *****/ +struct ccp_ctx { + int (*complete)(struct crypto_async_request *req, int ret); + + union { + struct ccp_aes_ctx aes; + struct ccp_sha_ctx sha; + } u; +}; + +int ccp_crypto_enqueue_request(struct crypto_async_request *req, + struct ccp_cmd *cmd); +struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table, + struct scatterlist *sg_add); + +int ccp_register_aes_algs(struct list_head *head); +int ccp_register_aes_cmac_algs(struct list_head *head); +int ccp_register_aes_xts_algs(struct list_head *head); +int ccp_register_sha_algs(struct list_head *head); + +#endif -- cgit v1.2.3 From 2b789435d7f36ed918d92db647f3a2f3fec9bb1f Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:28 -0600 Subject: crypto: ccp - CCP AES crypto API support These routines provide crypto API support for AES on the AMD CCP. Support for AES modes: ECB, CBC, OFB, CFB and CTR Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes.c | 375 ++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-crypto-aes.c (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes.c b/drivers/crypto/ccp/ccp-crypto-aes.c new file mode 100644 index 000000000000..f302a5b7473b --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-aes.c @@ -0,0 +1,375 @@ +/* + * AMD Cryptographic Coprocessor (CCP) AES crypto API support + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-crypto.h" + + +static int ccp_aes_complete(struct crypto_async_request *async_req, int ret) +{ + struct ablkcipher_request *req = ablkcipher_request_cast(async_req); + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + + if (ret) + return ret; + + if (ctx->u.aes.mode != CCP_AES_MODE_ECB) + memcpy(req->info, rctx->iv, AES_BLOCK_SIZE); + + return 0; +} + +static int ccp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); + struct ccp_crypto_ablkcipher_alg *alg = + ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm)); + + switch (key_len) { + case AES_KEYSIZE_128: + ctx->u.aes.type = CCP_AES_TYPE_128; + break; + case AES_KEYSIZE_192: + ctx->u.aes.type = CCP_AES_TYPE_192; + break; + case AES_KEYSIZE_256: + ctx->u.aes.type = CCP_AES_TYPE_256; + break; + default: + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + ctx->u.aes.mode = alg->mode; + ctx->u.aes.key_len = key_len; + + memcpy(ctx->u.aes.key, key, key_len); + sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); + + return 0; +} + +static int ccp_aes_crypt(struct ablkcipher_request *req, bool encrypt) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + struct scatterlist *iv_sg = NULL; + unsigned int iv_len = 0; + int ret; + + if (!ctx->u.aes.key_len) { + pr_err("AES key not set\n"); + return -EINVAL; + } + + if (((ctx->u.aes.mode == CCP_AES_MODE_ECB) || + (ctx->u.aes.mode == CCP_AES_MODE_CBC) || + (ctx->u.aes.mode == CCP_AES_MODE_CFB)) && + (req->nbytes & (AES_BLOCK_SIZE - 1))) { + pr_err("AES request size is not a multiple of the block size\n"); + return -EINVAL; + } + + if (ctx->u.aes.mode != CCP_AES_MODE_ECB) { + if (!req->info) { + pr_err("AES IV not supplied"); + return -EINVAL; + } + + memcpy(rctx->iv, req->info, AES_BLOCK_SIZE); + iv_sg = &rctx->iv_sg; + iv_len = AES_BLOCK_SIZE; + sg_init_one(iv_sg, rctx->iv, iv_len); + } + + memset(&rctx->cmd, 0, sizeof(rctx->cmd)); + INIT_LIST_HEAD(&rctx->cmd.entry); + rctx->cmd.engine = CCP_ENGINE_AES; + rctx->cmd.u.aes.type = ctx->u.aes.type; + rctx->cmd.u.aes.mode = ctx->u.aes.mode; + rctx->cmd.u.aes.action = + (encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT; + rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; + rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; + rctx->cmd.u.aes.iv = iv_sg; + rctx->cmd.u.aes.iv_len = iv_len; + rctx->cmd.u.aes.src = req->src; + rctx->cmd.u.aes.src_len = req->nbytes; + rctx->cmd.u.aes.dst = req->dst; + + ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); + + return ret; +} + +static int ccp_aes_encrypt(struct ablkcipher_request *req) +{ + return ccp_aes_crypt(req, true); +} + +static int ccp_aes_decrypt(struct ablkcipher_request *req) +{ + return ccp_aes_crypt(req, false); +} + +static int ccp_aes_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->complete = ccp_aes_complete; + ctx->u.aes.key_len = 0; + + tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx); + + return 0; +} + +static void ccp_aes_cra_exit(struct crypto_tfm *tfm) +{ +} + +static int ccp_aes_rfc3686_complete(struct crypto_async_request *async_req, + int ret) +{ + struct ablkcipher_request *req = ablkcipher_request_cast(async_req); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + + /* Restore the original pointer */ + req->info = rctx->rfc3686_info; + + return ccp_aes_complete(async_req, ret); +} + +static int ccp_aes_rfc3686_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); + + if (key_len < CTR_RFC3686_NONCE_SIZE) + return -EINVAL; + + key_len -= CTR_RFC3686_NONCE_SIZE; + memcpy(ctx->u.aes.nonce, key + key_len, CTR_RFC3686_NONCE_SIZE); + + return ccp_aes_setkey(tfm, key, key_len); +} + +static int ccp_aes_rfc3686_crypt(struct ablkcipher_request *req, bool encrypt) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + u8 *iv; + + /* Initialize the CTR block */ + iv = rctx->rfc3686_iv; + memcpy(iv, ctx->u.aes.nonce, CTR_RFC3686_NONCE_SIZE); + + iv += CTR_RFC3686_NONCE_SIZE; + memcpy(iv, req->info, CTR_RFC3686_IV_SIZE); + + iv += CTR_RFC3686_IV_SIZE; + *(__be32 *)iv = cpu_to_be32(1); + + /* Point to the new IV */ + rctx->rfc3686_info = req->info; + req->info = rctx->rfc3686_iv; + + return ccp_aes_crypt(req, encrypt); +} + +static int ccp_aes_rfc3686_encrypt(struct ablkcipher_request *req) +{ + return ccp_aes_rfc3686_crypt(req, true); +} + +static int ccp_aes_rfc3686_decrypt(struct ablkcipher_request *req) +{ + return ccp_aes_rfc3686_crypt(req, false); +} + +static int ccp_aes_rfc3686_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->complete = ccp_aes_rfc3686_complete; + ctx->u.aes.key_len = 0; + + tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx); + + return 0; +} + +static void ccp_aes_rfc3686_cra_exit(struct crypto_tfm *tfm) +{ +} + +static struct crypto_alg ccp_aes_defaults = { + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct ccp_ctx), + .cra_priority = CCP_CRA_PRIORITY, + .cra_type = &crypto_ablkcipher_type, + .cra_init = ccp_aes_cra_init, + .cra_exit = ccp_aes_cra_exit, + .cra_module = THIS_MODULE, + .cra_ablkcipher = { + .setkey = ccp_aes_setkey, + .encrypt = ccp_aes_encrypt, + .decrypt = ccp_aes_decrypt, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + }, +}; + +static struct crypto_alg ccp_aes_rfc3686_defaults = { + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = CTR_RFC3686_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct ccp_ctx), + .cra_priority = CCP_CRA_PRIORITY, + .cra_type = &crypto_ablkcipher_type, + .cra_init = ccp_aes_rfc3686_cra_init, + .cra_exit = ccp_aes_rfc3686_cra_exit, + .cra_module = THIS_MODULE, + .cra_ablkcipher = { + .setkey = ccp_aes_rfc3686_setkey, + .encrypt = ccp_aes_rfc3686_encrypt, + .decrypt = ccp_aes_rfc3686_decrypt, + .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, + .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, + }, +}; + +struct ccp_aes_def { + enum ccp_aes_mode mode; + const char *name; + const char *driver_name; + unsigned int blocksize; + unsigned int ivsize; + struct crypto_alg *alg_defaults; +}; + +static struct ccp_aes_def aes_algs[] = { + { + .mode = CCP_AES_MODE_ECB, + .name = "ecb(aes)", + .driver_name = "ecb-aes-ccp", + .blocksize = AES_BLOCK_SIZE, + .ivsize = 0, + .alg_defaults = &ccp_aes_defaults, + }, + { + .mode = CCP_AES_MODE_CBC, + .name = "cbc(aes)", + .driver_name = "cbc-aes-ccp", + .blocksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, + .alg_defaults = &ccp_aes_defaults, + }, + { + .mode = CCP_AES_MODE_CFB, + .name = "cfb(aes)", + .driver_name = "cfb-aes-ccp", + .blocksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, + .alg_defaults = &ccp_aes_defaults, + }, + { + .mode = CCP_AES_MODE_OFB, + .name = "ofb(aes)", + .driver_name = "ofb-aes-ccp", + .blocksize = 1, + .ivsize = AES_BLOCK_SIZE, + .alg_defaults = &ccp_aes_defaults, + }, + { + .mode = CCP_AES_MODE_CTR, + .name = "ctr(aes)", + .driver_name = "ctr-aes-ccp", + .blocksize = 1, + .ivsize = AES_BLOCK_SIZE, + .alg_defaults = &ccp_aes_defaults, + }, + { + .mode = CCP_AES_MODE_CTR, + .name = "rfc3686(ctr(aes))", + .driver_name = "rfc3686-ctr-aes-ccp", + .blocksize = 1, + .ivsize = CTR_RFC3686_IV_SIZE, + .alg_defaults = &ccp_aes_rfc3686_defaults, + }, +}; + +static int ccp_register_aes_alg(struct list_head *head, + const struct ccp_aes_def *def) +{ + struct ccp_crypto_ablkcipher_alg *ccp_alg; + struct crypto_alg *alg; + int ret; + + ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); + if (!ccp_alg) + return -ENOMEM; + + INIT_LIST_HEAD(&ccp_alg->entry); + + ccp_alg->mode = def->mode; + + /* Copy the defaults and override as necessary */ + alg = &ccp_alg->alg; + memcpy(alg, def->alg_defaults, sizeof(*alg)); + snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); + snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + def->driver_name); + alg->cra_blocksize = def->blocksize; + alg->cra_ablkcipher.ivsize = def->ivsize; + + ret = crypto_register_alg(alg); + if (ret) { + pr_err("%s ablkcipher algorithm registration error (%d)\n", + alg->cra_name, ret); + kfree(ccp_alg); + return ret; + } + + list_add(&ccp_alg->entry, head); + + return 0; +} + +int ccp_register_aes_algs(struct list_head *head) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { + ret = ccp_register_aes_alg(head, &aes_algs[i]); + if (ret) + return ret; + } + + return 0; +} -- cgit v1.2.3 From 7c1853711fc11df00f20bb6989358f1d3ce0fc04 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:34 -0600 Subject: crypto: ccp - CCP AES CMAC mode crypto API support These routines provide crypto API support for the CMAC mode of AES on the AMD CCP. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 355 +++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-cmac.c (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c new file mode 100644 index 000000000000..5b9cd982339d --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -0,0 +1,355 @@ +/* + * AMD Cryptographic Coprocessor (CCP) AES CMAC crypto API support + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-crypto.h" + + +static int ccp_aes_cmac_complete(struct crypto_async_request *async_req, + int ret) +{ + struct ahash_request *req = ahash_request_cast(async_req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + unsigned int digest_size = crypto_ahash_digestsize(tfm); + + if (ret) + goto e_free; + + if (rctx->hash_rem) { + /* Save remaining data to buffer */ + scatterwalk_map_and_copy(rctx->buf, rctx->cmd.u.aes.src, + rctx->hash_cnt, rctx->hash_rem, 0); + rctx->buf_count = rctx->hash_rem; + } else + rctx->buf_count = 0; + + memcpy(req->result, rctx->iv, digest_size); + +e_free: + sg_free_table(&rctx->data_sg); + + return ret; +} + +static int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes, + unsigned int final) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ccp_ctx *ctx = crypto_ahash_ctx(tfm); + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + struct scatterlist *sg, *cmac_key_sg = NULL; + unsigned int block_size = + crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + unsigned int len, need_pad, sg_count; + int ret; + + if (!ctx->u.aes.key_len) { + pr_err("AES key not set\n"); + return -EINVAL; + } + + if (nbytes) + rctx->null_msg = 0; + + if (!final && ((nbytes + rctx->buf_count) <= block_size)) { + scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src, + 0, nbytes, 0); + rctx->buf_count += nbytes; + + return 0; + } + + len = rctx->buf_count + nbytes; + + rctx->final = final; + rctx->hash_cnt = final ? len : len & ~(block_size - 1); + rctx->hash_rem = final ? 0 : len & (block_size - 1); + if (!final && (rctx->hash_cnt == len)) { + /* CCP can't do zero length final, so keep some data around */ + rctx->hash_cnt -= block_size; + rctx->hash_rem = block_size; + } + + if (final && (rctx->null_msg || (len & (block_size - 1)))) + need_pad = 1; + else + need_pad = 0; + + sg_init_one(&rctx->iv_sg, rctx->iv, sizeof(rctx->iv)); + + /* Build the data scatterlist table - allocate enough entries for all + * possible data pieces (buffer, input data, padding) + */ + sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2; + ret = sg_alloc_table(&rctx->data_sg, sg_count, GFP_KERNEL); + if (ret) + return ret; + + sg = NULL; + if (rctx->buf_count) { + sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count); + sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg); + } + + if (nbytes) + sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src); + + if (need_pad) { + int pad_length = block_size - (len & (block_size - 1)); + + rctx->hash_cnt += pad_length; + + memset(rctx->pad, 0, sizeof(rctx->pad)); + rctx->pad[0] = 0x80; + sg_init_one(&rctx->pad_sg, rctx->pad, pad_length); + sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg); + } + if (sg) + sg_mark_end(sg); + + /* Initialize the K1/K2 scatterlist */ + if (final) + cmac_key_sg = (need_pad) ? &ctx->u.aes.k2_sg + : &ctx->u.aes.k1_sg; + + memset(&rctx->cmd, 0, sizeof(rctx->cmd)); + INIT_LIST_HEAD(&rctx->cmd.entry); + rctx->cmd.engine = CCP_ENGINE_AES; + rctx->cmd.u.aes.type = ctx->u.aes.type; + rctx->cmd.u.aes.mode = ctx->u.aes.mode; + rctx->cmd.u.aes.action = CCP_AES_ACTION_ENCRYPT; + rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; + rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; + rctx->cmd.u.aes.iv = &rctx->iv_sg; + rctx->cmd.u.aes.iv_len = AES_BLOCK_SIZE; + rctx->cmd.u.aes.src = (sg) ? rctx->data_sg.sgl : NULL; + rctx->cmd.u.aes.src_len = rctx->hash_cnt; + rctx->cmd.u.aes.dst = NULL; + rctx->cmd.u.aes.cmac_key = cmac_key_sg; + rctx->cmd.u.aes.cmac_key_len = ctx->u.aes.kn_len; + rctx->cmd.u.aes.cmac_final = final; + + ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); + + return ret; +} + +static int ccp_aes_cmac_init(struct ahash_request *req) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + + memset(rctx, 0, sizeof(*rctx)); + + rctx->null_msg = 1; + + return 0; +} + +static int ccp_aes_cmac_update(struct ahash_request *req) +{ + return ccp_do_cmac_update(req, req->nbytes, 0); +} + +static int ccp_aes_cmac_final(struct ahash_request *req) +{ + return ccp_do_cmac_update(req, 0, 1); +} + +static int ccp_aes_cmac_finup(struct ahash_request *req) +{ + return ccp_do_cmac_update(req, req->nbytes, 1); +} + +static int ccp_aes_cmac_digest(struct ahash_request *req) +{ + int ret; + + ret = ccp_aes_cmac_init(req); + if (ret) + return ret; + + return ccp_do_cmac_update(req, req->nbytes, 1); +} + +static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); + struct ccp_crypto_ahash_alg *alg = + ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm)); + u64 k0_hi, k0_lo, k1_hi, k1_lo, k2_hi, k2_lo; + u64 rb_hi = 0x00, rb_lo = 0x87; + __be64 *gk; + int ret; + + switch (key_len) { + case AES_KEYSIZE_128: + ctx->u.aes.type = CCP_AES_TYPE_128; + break; + case AES_KEYSIZE_192: + ctx->u.aes.type = CCP_AES_TYPE_192; + break; + case AES_KEYSIZE_256: + ctx->u.aes.type = CCP_AES_TYPE_256; + break; + default: + crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + ctx->u.aes.mode = alg->mode; + + /* Set to zero until complete */ + ctx->u.aes.key_len = 0; + + /* Set the key for the AES cipher used to generate the keys */ + ret = crypto_cipher_setkey(ctx->u.aes.tfm_cipher, key, key_len); + if (ret) + return ret; + + /* Encrypt a block of zeroes - use key area in context */ + memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); + crypto_cipher_encrypt_one(ctx->u.aes.tfm_cipher, ctx->u.aes.key, + ctx->u.aes.key); + + /* Generate K1 and K2 */ + k0_hi = be64_to_cpu(*((__be64 *)ctx->u.aes.key)); + k0_lo = be64_to_cpu(*((__be64 *)ctx->u.aes.key + 1)); + + k1_hi = (k0_hi << 1) | (k0_lo >> 63); + k1_lo = k0_lo << 1; + if (ctx->u.aes.key[0] & 0x80) { + k1_hi ^= rb_hi; + k1_lo ^= rb_lo; + } + gk = (__be64 *)ctx->u.aes.k1; + *gk = cpu_to_be64(k1_hi); + gk++; + *gk = cpu_to_be64(k1_lo); + + k2_hi = (k1_hi << 1) | (k1_lo >> 63); + k2_lo = k1_lo << 1; + if (ctx->u.aes.k1[0] & 0x80) { + k2_hi ^= rb_hi; + k2_lo ^= rb_lo; + } + gk = (__be64 *)ctx->u.aes.k2; + *gk = cpu_to_be64(k2_hi); + gk++; + *gk = cpu_to_be64(k2_lo); + + ctx->u.aes.kn_len = sizeof(ctx->u.aes.k1); + sg_init_one(&ctx->u.aes.k1_sg, ctx->u.aes.k1, sizeof(ctx->u.aes.k1)); + sg_init_one(&ctx->u.aes.k2_sg, ctx->u.aes.k2, sizeof(ctx->u.aes.k2)); + + /* Save the supplied key */ + memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key)); + memcpy(ctx->u.aes.key, key, key_len); + ctx->u.aes.key_len = key_len; + sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); + + return ret; +} + +static int ccp_aes_cmac_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); + struct crypto_cipher *cipher_tfm; + + ctx->complete = ccp_aes_cmac_complete; + ctx->u.aes.key_len = 0; + + crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_aes_cmac_req_ctx)); + + cipher_tfm = crypto_alloc_cipher("aes", 0, + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(cipher_tfm)) { + pr_warn("could not load aes cipher driver\n"); + return PTR_ERR(cipher_tfm); + } + ctx->u.aes.tfm_cipher = cipher_tfm; + + return 0; +} + +static void ccp_aes_cmac_cra_exit(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + + if (ctx->u.aes.tfm_cipher) + crypto_free_cipher(ctx->u.aes.tfm_cipher); + ctx->u.aes.tfm_cipher = NULL; +} + +int ccp_register_aes_cmac_algs(struct list_head *head) +{ + struct ccp_crypto_ahash_alg *ccp_alg; + struct ahash_alg *alg; + struct hash_alg_common *halg; + struct crypto_alg *base; + int ret; + + ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); + if (!ccp_alg) + return -ENOMEM; + + INIT_LIST_HEAD(&ccp_alg->entry); + ccp_alg->mode = CCP_AES_MODE_CMAC; + + alg = &ccp_alg->alg; + alg->init = ccp_aes_cmac_init; + alg->update = ccp_aes_cmac_update; + alg->final = ccp_aes_cmac_final; + alg->finup = ccp_aes_cmac_finup; + alg->digest = ccp_aes_cmac_digest; + alg->setkey = ccp_aes_cmac_setkey; + + halg = &alg->halg; + halg->digestsize = AES_BLOCK_SIZE; + + base = &halg->base; + snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); + snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "cmac-aes-ccp"); + base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK; + base->cra_blocksize = AES_BLOCK_SIZE; + base->cra_ctxsize = sizeof(struct ccp_ctx); + base->cra_priority = CCP_CRA_PRIORITY; + base->cra_type = &crypto_ahash_type; + base->cra_init = ccp_aes_cmac_cra_init; + base->cra_exit = ccp_aes_cmac_cra_exit; + base->cra_module = THIS_MODULE; + + ret = crypto_register_ahash(alg); + if (ret) { + pr_err("%s ahash algorithm registration error (%d)\n", + base->cra_name, ret); + kfree(ccp_alg); + return ret; + } + + list_add(&ccp_alg->entry, head); + + return 0; +} -- cgit v1.2.3 From 1d6b8a6f64076aee9e63474c0778a50f95c054ee Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:40 -0600 Subject: crypto: ccp - CCP XTS-AES crypto API support These routines provide crypto API support for the XTS-AES mode of AES on the AMD CCP. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-xts.c | 285 ++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-xts.c (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c new file mode 100644 index 000000000000..d100b48415b6 --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-aes-xts.c @@ -0,0 +1,285 @@ +/* + * AMD Cryptographic Coprocessor (CCP) AES XTS crypto API support + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-crypto.h" + + +struct ccp_aes_xts_def { + const char *name; + const char *drv_name; +}; + +static struct ccp_aes_xts_def aes_xts_algs[] = { + { + .name = "xts(aes)", + .drv_name = "xts-aes-ccp", + }, +}; + +struct ccp_unit_size_map { + unsigned int size; + u32 value; +}; + +static struct ccp_unit_size_map unit_size_map[] = { + { + .size = 4096, + .value = CCP_XTS_AES_UNIT_SIZE_4096, + }, + { + .size = 2048, + .value = CCP_XTS_AES_UNIT_SIZE_2048, + }, + { + .size = 1024, + .value = CCP_XTS_AES_UNIT_SIZE_1024, + }, + { + .size = 512, + .value = CCP_XTS_AES_UNIT_SIZE_512, + }, + { + .size = 256, + .value = CCP_XTS_AES_UNIT_SIZE__LAST, + }, + { + .size = 128, + .value = CCP_XTS_AES_UNIT_SIZE__LAST, + }, + { + .size = 64, + .value = CCP_XTS_AES_UNIT_SIZE__LAST, + }, + { + .size = 32, + .value = CCP_XTS_AES_UNIT_SIZE__LAST, + }, + { + .size = 16, + .value = CCP_XTS_AES_UNIT_SIZE_16, + }, + { + .size = 1, + .value = CCP_XTS_AES_UNIT_SIZE__LAST, + }, +}; + +static int ccp_aes_xts_complete(struct crypto_async_request *async_req, int ret) +{ + struct ablkcipher_request *req = ablkcipher_request_cast(async_req); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + + if (ret) + return ret; + + memcpy(req->info, rctx->iv, AES_BLOCK_SIZE); + + return 0; +} + +static int ccp_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); + + /* Only support 128-bit AES key with a 128-bit Tweak key, + * otherwise use the fallback + */ + switch (key_len) { + case AES_KEYSIZE_128 * 2: + memcpy(ctx->u.aes.key, key, key_len); + break; + } + ctx->u.aes.key_len = key_len / 2; + sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); + + return crypto_ablkcipher_setkey(ctx->u.aes.tfm_ablkcipher, key, + key_len); +} + +static int ccp_aes_xts_crypt(struct ablkcipher_request *req, + unsigned int encrypt) +{ + struct crypto_tfm *tfm = + crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req); + unsigned int unit; + int ret; + + if (!ctx->u.aes.key_len) { + pr_err("AES key not set\n"); + return -EINVAL; + } + + if (req->nbytes & (AES_BLOCK_SIZE - 1)) { + pr_err("AES request size is not a multiple of the block size\n"); + return -EINVAL; + } + + if (!req->info) { + pr_err("AES IV not supplied"); + return -EINVAL; + } + + for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) + if (!(req->nbytes & (unit_size_map[unit].size - 1))) + break; + + if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) || + (ctx->u.aes.key_len != AES_KEYSIZE_128)) { + /* Use the fallback to process the request for any + * unsupported unit sizes or key sizes + */ + ablkcipher_request_set_tfm(req, ctx->u.aes.tfm_ablkcipher); + ret = (encrypt) ? crypto_ablkcipher_encrypt(req) : + crypto_ablkcipher_decrypt(req); + ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm)); + + return ret; + } + + memcpy(rctx->iv, req->info, AES_BLOCK_SIZE); + sg_init_one(&rctx->iv_sg, rctx->iv, AES_BLOCK_SIZE); + + memset(&rctx->cmd, 0, sizeof(rctx->cmd)); + INIT_LIST_HEAD(&rctx->cmd.entry); + rctx->cmd.engine = CCP_ENGINE_XTS_AES_128; + rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT + : CCP_AES_ACTION_DECRYPT; + rctx->cmd.u.xts.unit_size = unit_size_map[unit].value; + rctx->cmd.u.xts.key = &ctx->u.aes.key_sg; + rctx->cmd.u.xts.key_len = ctx->u.aes.key_len; + rctx->cmd.u.xts.iv = &rctx->iv_sg; + rctx->cmd.u.xts.iv_len = AES_BLOCK_SIZE; + rctx->cmd.u.xts.src = req->src; + rctx->cmd.u.xts.src_len = req->nbytes; + rctx->cmd.u.xts.dst = req->dst; + + ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); + + return ret; +} + +static int ccp_aes_xts_encrypt(struct ablkcipher_request *req) +{ + return ccp_aes_xts_crypt(req, 1); +} + +static int ccp_aes_xts_decrypt(struct ablkcipher_request *req) +{ + return ccp_aes_xts_crypt(req, 0); +} + +static int ccp_aes_xts_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_ablkcipher *fallback_tfm; + + ctx->complete = ccp_aes_xts_complete; + ctx->u.aes.key_len = 0; + + fallback_tfm = crypto_alloc_ablkcipher(tfm->__crt_alg->cra_name, 0, + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(fallback_tfm)) { + pr_warn("could not load fallback driver %s\n", + tfm->__crt_alg->cra_name); + return PTR_ERR(fallback_tfm); + } + ctx->u.aes.tfm_ablkcipher = fallback_tfm; + + tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx) + + fallback_tfm->base.crt_ablkcipher.reqsize; + + return 0; +} + +static void ccp_aes_xts_cra_exit(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + + if (ctx->u.aes.tfm_ablkcipher) + crypto_free_ablkcipher(ctx->u.aes.tfm_ablkcipher); + ctx->u.aes.tfm_ablkcipher = NULL; +} + + +static int ccp_register_aes_xts_alg(struct list_head *head, + const struct ccp_aes_xts_def *def) +{ + struct ccp_crypto_ablkcipher_alg *ccp_alg; + struct crypto_alg *alg; + int ret; + + ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); + if (!ccp_alg) + return -ENOMEM; + + INIT_LIST_HEAD(&ccp_alg->entry); + + alg = &ccp_alg->alg; + + snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); + snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + def->drv_name); + alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK; + alg->cra_blocksize = AES_BLOCK_SIZE; + alg->cra_ctxsize = sizeof(struct ccp_ctx); + alg->cra_priority = CCP_CRA_PRIORITY; + alg->cra_type = &crypto_ablkcipher_type; + alg->cra_ablkcipher.setkey = ccp_aes_xts_setkey; + alg->cra_ablkcipher.encrypt = ccp_aes_xts_encrypt; + alg->cra_ablkcipher.decrypt = ccp_aes_xts_decrypt; + alg->cra_ablkcipher.min_keysize = AES_MIN_KEY_SIZE * 2; + alg->cra_ablkcipher.max_keysize = AES_MAX_KEY_SIZE * 2; + alg->cra_ablkcipher.ivsize = AES_BLOCK_SIZE; + alg->cra_init = ccp_aes_xts_cra_init; + alg->cra_exit = ccp_aes_xts_cra_exit; + alg->cra_module = THIS_MODULE; + + ret = crypto_register_alg(alg); + if (ret) { + pr_err("%s ablkcipher algorithm registration error (%d)\n", + alg->cra_name, ret); + kfree(ccp_alg); + return ret; + } + + list_add(&ccp_alg->entry, head); + + return 0; +} + +int ccp_register_aes_xts_algs(struct list_head *head) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(aes_xts_algs); i++) { + ret = ccp_register_aes_xts_alg(head, &aes_xts_algs[i]); + if (ret) + return ret; + } + + return 0; +} -- cgit v1.2.3 From 0ab0a1d505ab6f684076b9c5ef9279e29c2b08ae Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:45 -0600 Subject: crypto: ccp - CCP SHA crypto API support These routines provide crypto API support for SHA1, SHA224 and SHA256 on the AMD CCP. HMAC support for these SHA modes is also provided. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-sha.c | 497 ++++++++++++++++++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-crypto-sha.c (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c new file mode 100644 index 000000000000..44ff00a09c8a --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -0,0 +1,497 @@ +/* + * AMD Cryptographic Coprocessor (CCP) SHA crypto API support + * + * Copyright (C) 2013 Advanced Micro Devices, Inc. + * + * Author: Tom Lendacky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-crypto.h" + + +struct ccp_sha_result { + struct completion completion; + int err; +}; + +static void ccp_sync_hash_complete(struct crypto_async_request *req, int err) +{ + struct ccp_sha_result *result = req->data; + + if (err == -EINPROGRESS) + return; + + result->err = err; + complete(&result->completion); +} + +static int ccp_sync_hash(struct crypto_ahash *tfm, u8 *buf, + struct scatterlist *sg, unsigned int len) +{ + struct ccp_sha_result result; + struct ahash_request *req; + int ret; + + init_completion(&result.completion); + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) + return -ENOMEM; + + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + ccp_sync_hash_complete, &result); + ahash_request_set_crypt(req, sg, buf, len); + + ret = crypto_ahash_digest(req); + if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { + ret = wait_for_completion_interruptible(&result.completion); + if (!ret) + ret = result.err; + } + + ahash_request_free(req); + + return ret; +} + +static int ccp_sha_finish_hmac(struct crypto_async_request *async_req) +{ + struct ahash_request *req = ahash_request_cast(async_req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ccp_ctx *ctx = crypto_ahash_ctx(tfm); + struct scatterlist sg[2]; + unsigned int block_size = + crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + unsigned int digest_size = crypto_ahash_digestsize(tfm); + + sg_init_table(sg, ARRAY_SIZE(sg)); + sg_set_buf(&sg[0], ctx->u.sha.opad, block_size); + sg_set_buf(&sg[1], req->result, digest_size); + + return ccp_sync_hash(ctx->u.sha.hmac_tfm, req->result, sg, + block_size + digest_size); +} + +static int ccp_sha_complete(struct crypto_async_request *async_req, int ret) +{ + struct ahash_request *req = ahash_request_cast(async_req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ccp_ctx *ctx = crypto_ahash_ctx(tfm); + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + unsigned int digest_size = crypto_ahash_digestsize(tfm); + + if (ret) + goto e_free; + + if (rctx->hash_rem) { + /* Save remaining data to buffer */ + scatterwalk_map_and_copy(rctx->buf, rctx->cmd.u.sha.src, + rctx->hash_cnt, rctx->hash_rem, 0); + rctx->buf_count = rctx->hash_rem; + } else + rctx->buf_count = 0; + + memcpy(req->result, rctx->ctx, digest_size); + + /* If we're doing an HMAC, we need to perform that on the final op */ + if (rctx->final && ctx->u.sha.key_len) + ret = ccp_sha_finish_hmac(async_req); + +e_free: + sg_free_table(&rctx->data_sg); + + return ret; +} + +static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes, + unsigned int final) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ccp_ctx *ctx = crypto_ahash_ctx(tfm); + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct scatterlist *sg; + unsigned int block_size = + crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + unsigned int len, sg_count; + int ret; + + if (!final && ((nbytes + rctx->buf_count) <= block_size)) { + scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src, + 0, nbytes, 0); + rctx->buf_count += nbytes; + + return 0; + } + + len = rctx->buf_count + nbytes; + + rctx->final = final; + rctx->hash_cnt = final ? len : len & ~(block_size - 1); + rctx->hash_rem = final ? 0 : len & (block_size - 1); + if (!final && (rctx->hash_cnt == len)) { + /* CCP can't do zero length final, so keep some data around */ + rctx->hash_cnt -= block_size; + rctx->hash_rem = block_size; + } + + /* Initialize the context scatterlist */ + sg_init_one(&rctx->ctx_sg, rctx->ctx, sizeof(rctx->ctx)); + + /* Build the data scatterlist table - allocate enough entries for all + * possible data pieces (hmac ipad, buffer, input data) + */ + sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2; + ret = sg_alloc_table(&rctx->data_sg, sg_count, GFP_KERNEL); + if (ret) + return ret; + + sg = NULL; + if (rctx->first && ctx->u.sha.key_len) { + rctx->hash_cnt += block_size; + + sg_init_one(&rctx->pad_sg, ctx->u.sha.ipad, block_size); + sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg); + } + + if (rctx->buf_count) { + sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count); + sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg); + } + + if (nbytes) + sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src); + + if (sg) + sg_mark_end(sg); + + rctx->msg_bits += (rctx->hash_cnt << 3); /* Total in bits */ + + memset(&rctx->cmd, 0, sizeof(rctx->cmd)); + INIT_LIST_HEAD(&rctx->cmd.entry); + rctx->cmd.engine = CCP_ENGINE_SHA; + rctx->cmd.u.sha.type = rctx->type; + rctx->cmd.u.sha.ctx = &rctx->ctx_sg; + rctx->cmd.u.sha.ctx_len = sizeof(rctx->ctx); + rctx->cmd.u.sha.src = (sg) ? rctx->data_sg.sgl : NULL; + rctx->cmd.u.sha.src_len = rctx->hash_cnt; + rctx->cmd.u.sha.final = rctx->final; + rctx->cmd.u.sha.msg_bits = rctx->msg_bits; + + rctx->first = 0; + + ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); + + return ret; +} + +static int ccp_sha_init(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_crypto_ahash_alg *alg = + ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm)); + + memset(rctx, 0, sizeof(*rctx)); + + memcpy(rctx->ctx, alg->init, sizeof(rctx->ctx)); + rctx->type = alg->type; + rctx->first = 1; + + return 0; +} + +static int ccp_sha_update(struct ahash_request *req) +{ + return ccp_do_sha_update(req, req->nbytes, 0); +} + +static int ccp_sha_final(struct ahash_request *req) +{ + return ccp_do_sha_update(req, 0, 1); +} + +static int ccp_sha_finup(struct ahash_request *req) +{ + return ccp_do_sha_update(req, req->nbytes, 1); +} + +static int ccp_sha_digest(struct ahash_request *req) +{ + ccp_sha_init(req); + + return ccp_do_sha_update(req, req->nbytes, 1); +} + +static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); + struct scatterlist sg; + unsigned int block_size = + crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + unsigned int digest_size = crypto_ahash_digestsize(tfm); + int i, ret; + + /* Set to zero until complete */ + ctx->u.sha.key_len = 0; + + /* Clear key area to provide zero padding for keys smaller + * than the block size + */ + memset(ctx->u.sha.key, 0, sizeof(ctx->u.sha.key)); + + if (key_len > block_size) { + /* Must hash the input key */ + sg_init_one(&sg, key, key_len); + ret = ccp_sync_hash(tfm, ctx->u.sha.key, &sg, key_len); + if (ret) { + crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + key_len = digest_size; + } else + memcpy(ctx->u.sha.key, key, key_len); + + for (i = 0; i < block_size; i++) { + ctx->u.sha.ipad[i] = ctx->u.sha.key[i] ^ 0x36; + ctx->u.sha.opad[i] = ctx->u.sha.key[i] ^ 0x5c; + } + + ctx->u.sha.key_len = key_len; + + return 0; +} + +static int ccp_sha_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); + + ctx->complete = ccp_sha_complete; + ctx->u.sha.key_len = 0; + + crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_sha_req_ctx)); + + return 0; +} + +static void ccp_sha_cra_exit(struct crypto_tfm *tfm) +{ +} + +static int ccp_hmac_sha_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + struct ccp_crypto_ahash_alg *alg = ccp_crypto_ahash_alg(tfm); + struct crypto_ahash *hmac_tfm; + + hmac_tfm = crypto_alloc_ahash(alg->child_alg, + CRYPTO_ALG_TYPE_AHASH, 0); + if (IS_ERR(hmac_tfm)) { + pr_warn("could not load driver %s need for HMAC support\n", + alg->child_alg); + return PTR_ERR(hmac_tfm); + } + + ctx->u.sha.hmac_tfm = hmac_tfm; + + return ccp_sha_cra_init(tfm); +} + +static void ccp_hmac_sha_cra_exit(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + + if (ctx->u.sha.hmac_tfm) + crypto_free_ahash(ctx->u.sha.hmac_tfm); + + ccp_sha_cra_exit(tfm); +} + +static const u32 sha1_init[CCP_SHA_CTXSIZE / sizeof(u32)] = { + cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1), + cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3), + cpu_to_be32(SHA1_H4), 0, 0, 0, +}; + +static const u32 sha224_init[CCP_SHA_CTXSIZE / sizeof(u32)] = { + cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1), + cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3), + cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5), + cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7), +}; + +static const u32 sha256_init[CCP_SHA_CTXSIZE / sizeof(u32)] = { + cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1), + cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3), + cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5), + cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7), +}; + +struct ccp_sha_def { + const char *name; + const char *drv_name; + const u32 *init; + enum ccp_sha_type type; + u32 digest_size; + u32 block_size; +}; + +static struct ccp_sha_def sha_algs[] = { + { + .name = "sha1", + .drv_name = "sha1-ccp", + .init = sha1_init, + .type = CCP_SHA_TYPE_1, + .digest_size = SHA1_DIGEST_SIZE, + .block_size = SHA1_BLOCK_SIZE, + }, + { + .name = "sha224", + .drv_name = "sha224-ccp", + .init = sha224_init, + .type = CCP_SHA_TYPE_224, + .digest_size = SHA224_DIGEST_SIZE, + .block_size = SHA224_BLOCK_SIZE, + }, + { + .name = "sha256", + .drv_name = "sha256-ccp", + .init = sha256_init, + .type = CCP_SHA_TYPE_256, + .digest_size = SHA256_DIGEST_SIZE, + .block_size = SHA256_BLOCK_SIZE, + }, +}; + +static int ccp_register_hmac_alg(struct list_head *head, + const struct ccp_sha_def *def, + const struct ccp_crypto_ahash_alg *base_alg) +{ + struct ccp_crypto_ahash_alg *ccp_alg; + struct ahash_alg *alg; + struct hash_alg_common *halg; + struct crypto_alg *base; + int ret; + + ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); + if (!ccp_alg) + return -ENOMEM; + + /* Copy the base algorithm and only change what's necessary */ + memcpy(ccp_alg, base_alg, sizeof(*ccp_alg)); + INIT_LIST_HEAD(&ccp_alg->entry); + + strncpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME); + + alg = &ccp_alg->alg; + alg->setkey = ccp_sha_setkey; + + halg = &alg->halg; + + base = &halg->base; + snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", def->name); + snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "hmac-%s", + def->drv_name); + base->cra_init = ccp_hmac_sha_cra_init; + base->cra_exit = ccp_hmac_sha_cra_exit; + + ret = crypto_register_ahash(alg); + if (ret) { + pr_err("%s ahash algorithm registration error (%d)\n", + base->cra_name, ret); + kfree(ccp_alg); + return ret; + } + + list_add(&ccp_alg->entry, head); + + return ret; +} + +static int ccp_register_sha_alg(struct list_head *head, + const struct ccp_sha_def *def) +{ + struct ccp_crypto_ahash_alg *ccp_alg; + struct ahash_alg *alg; + struct hash_alg_common *halg; + struct crypto_alg *base; + int ret; + + ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); + if (!ccp_alg) + return -ENOMEM; + + INIT_LIST_HEAD(&ccp_alg->entry); + + ccp_alg->init = def->init; + ccp_alg->type = def->type; + + alg = &ccp_alg->alg; + alg->init = ccp_sha_init; + alg->update = ccp_sha_update; + alg->final = ccp_sha_final; + alg->finup = ccp_sha_finup; + alg->digest = ccp_sha_digest; + + halg = &alg->halg; + halg->digestsize = def->digest_size; + + base = &halg->base; + snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); + snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + def->drv_name); + base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK; + base->cra_blocksize = def->block_size; + base->cra_ctxsize = sizeof(struct ccp_ctx); + base->cra_priority = CCP_CRA_PRIORITY; + base->cra_type = &crypto_ahash_type; + base->cra_init = ccp_sha_cra_init; + base->cra_exit = ccp_sha_cra_exit; + base->cra_module = THIS_MODULE; + + ret = crypto_register_ahash(alg); + if (ret) { + pr_err("%s ahash algorithm registration error (%d)\n", + base->cra_name, ret); + kfree(ccp_alg); + return ret; + } + + list_add(&ccp_alg->entry, head); + + ret = ccp_register_hmac_alg(head, def, ccp_alg); + + return ret; +} + +int ccp_register_sha_algs(struct list_head *head) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(sha_algs); i++) { + ret = ccp_register_sha_alg(head, &sha_algs[i]); + if (ret) + return ret; + } + + return 0; +} -- cgit v1.2.3 From f114766088f352a47f57307ff927b815e0239644 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:51 -0600 Subject: crytpo: ccp - CCP device driver build files These files provide the ability to configure and build the AMD CCP device driver and crypto API support. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 12 ++++++++++++ drivers/crypto/Makefile | 1 + drivers/crypto/ccp/Kconfig | 23 +++++++++++++++++++++++ drivers/crypto/ccp/Makefile | 10 ++++++++++ 4 files changed, 46 insertions(+) create mode 100644 drivers/crypto/ccp/Kconfig create mode 100644 drivers/crypto/ccp/Makefile (limited to 'drivers') diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index f4fd837bcb82..4954d7579c5b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -399,4 +399,16 @@ config CRYPTO_DEV_ATMEL_SHA To compile this driver as a module, choose M here: the module will be called atmel-sha. +config CRYPTO_DEV_CCP + bool "Support for AMD Cryptographic Coprocessor" + depends on X86 + default n + help + The AMD Cryptographic Coprocessor provides hardware support + for encryption, hashing and related operations. + +if CRYPTO_DEV_CCP + source "drivers/crypto/ccp/Kconfig" +endif + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index b4946ddd2550..8a6c86a2e2c9 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o +obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/ diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig new file mode 100644 index 000000000000..335ed5cac7a0 --- /dev/null +++ b/drivers/crypto/ccp/Kconfig @@ -0,0 +1,23 @@ +config CRYPTO_DEV_CCP_DD + tristate "Cryptographic Coprocessor device driver" + depends on CRYPTO_DEV_CCP + default m + help + Provides the interface to use the AMD Cryptographic Coprocessor + which can be used to accelerate or offload encryption operations + such as SHA, AES and more. If you choose 'M' here, this module + will be called ccp. + +config CRYPTO_DEV_CCP_CRYPTO + tristate "Encryption and hashing acceleration support" + depends on CRYPTO_DEV_CCP_DD + default m + select CRYPTO_ALGAPI + select CRYPTO_HASH + select CRYPTO_BLKCIPHER + select CRYPTO_AUTHENC + help + Support for using the cryptographic API with the AMD Cryptographic + Coprocessor. This module supports acceleration and offload of SHA + and AES algorithms. If you choose 'M' here, this module will be + called ccp_crypto. diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile new file mode 100644 index 000000000000..d3505a018720 --- /dev/null +++ b/drivers/crypto/ccp/Makefile @@ -0,0 +1,10 @@ +obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o +ccp-objs := ccp-dev.o ccp-ops.o +ccp-objs += ccp-pci.o + +obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o +ccp-crypto-objs := ccp-crypto-main.o \ + ccp-crypto-aes.o \ + ccp-crypto-aes-cmac.o \ + ccp-crypto-aes-xts.o \ + ccp-crypto-sha.o -- cgit v1.2.3 From f13ab86a6123cc85c072253769fcaac72949ae93 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 12 Nov 2013 13:12:27 -0700 Subject: crypto: omap-sham - Only release DMA channel if successfully requested In omap_sham_probe() and omap_sham_remove(), 'dd->dma_lch' is released without checking to see if it was successfully requested or not. This is a bug and was identified and reported by Dan Carpenter here: http://www.spinics.net/lists/devicetree/msg11023.html Add code to only release 'dd->dma_lch' when its not NULL (that is, when it was successfully requested). Reported-by: Dan Carpenter CC: Joel Fernandes Signed-off-by: Mark A. Greer Signed-off-by: Herbert Xu --- drivers/crypto/omap-sham.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index e45aaaf0db30..831f9a438b03 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -1970,7 +1970,8 @@ err_algs: crypto_unregister_ahash( &dd->pdata->algs_info[i].algs_list[j]); pm_runtime_disable(dev); - dma_release_channel(dd->dma_lch); + if (dd->dma_lch) + dma_release_channel(dd->dma_lch); data_err: dev_err(dev, "initialization failed.\n"); @@ -1994,7 +1995,9 @@ static int omap_sham_remove(struct platform_device *pdev) &dd->pdata->algs_info[i].algs_list[j]); tasklet_kill(&dd->done_task); pm_runtime_disable(&pdev->dev); - dma_release_channel(dd->dma_lch); + + if (dd->dma_lch) + dma_release_channel(dd->dma_lch); return 0; } -- cgit v1.2.3 From b62ffd8c72c2f04ac737ef3ff0f7ba37d2013633 Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Wed, 13 Nov 2013 12:20:37 +0200 Subject: crypto: talitos - fix locating offending descriptor in error path Commit 3e721aeb3df3816e283ab18e327cd4652972e213 ("crypto: talitos - handle descriptor not found in error path") tried to address the fact that CDPR (Current Descriptor Pointer Register) is unreliable. As it turns out, there are still issues in the function detecting the offending descriptor: -only 32 bits of the descriptor address are read, however the address is 36-bit - since reset_channel() initializes channels with EAE (extended address) bit set -reading CDPR can return zero in cur_desc; when searching the channel fifo for this address, cur_desc == dma_desc (= 0) case might happen, leading to an oops when trying to return desc->hdr (desc is zero) -read channel's .tail only once; the tail is a moving target; use a local variable for the end of search condition Signed-off-by: Lei Xu Signed-off-by: Horia Geanta Tested-by: Kalyani Chowdhury Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index b44f4ddc565c..a3d2e9b88c41 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -338,20 +338,29 @@ DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE) static u32 current_desc_hdr(struct device *dev, int ch) { struct talitos_private *priv = dev_get_drvdata(dev); - int tail = priv->chan[ch].tail; + int tail, iter; dma_addr_t cur_desc; - cur_desc = in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); + cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32; + cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); - while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) { - tail = (tail + 1) & (priv->fifo_len - 1); - if (tail == priv->chan[ch].tail) { + if (!cur_desc) { + dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n"); + return 0; + } + + tail = priv->chan[ch].tail; + + iter = tail; + while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) { + iter = (iter + 1) & (priv->fifo_len - 1); + if (iter == tail) { dev_err(dev, "couldn't locate current descriptor\n"); return 0; } } - return priv->chan[ch].fifo[tail].desc->hdr; + return priv->chan[ch].fifo[iter].desc->hdr; } /* -- cgit v1.2.3 From f7b2b5dd6a62a47e871627c71ed01aa3482154d9 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 3 Dec 2013 19:43:13 -0600 Subject: crypto: omap-aes - add error check for pm_runtime_get_sync The AES driver currently assumes that pm_runtime_get_sync will always succeed, which may not always be true, so add error handling for the same. This scenario was reported in the following bug: place. https://bugzilla.kernel.org/show_bug.cgi?id=66441 Reported-by: Tobias Jakobi Signed-off-by: Nishanth Menon Signed-off-by: Herbert Xu --- drivers/crypto/omap-aes.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index a9ccbf14096e..dde41f1df608 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -784,6 +784,7 @@ static int omap_aes_ctr_decrypt(struct ablkcipher_request *req) static int omap_aes_cra_init(struct crypto_tfm *tfm) { struct omap_aes_dev *dd = NULL; + int err; /* Find AES device, currently picks the first device */ spin_lock_bh(&list_lock); @@ -792,7 +793,13 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm) } spin_unlock_bh(&list_lock); - pm_runtime_get_sync(dd->dev); + err = pm_runtime_get_sync(dd->dev); + if (err < 0) { + dev_err(dd->dev, "%s: failed to get_sync(%d)\n", + __func__, err); + return err; + } + tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx); return 0; @@ -1182,7 +1189,12 @@ static int omap_aes_probe(struct platform_device *pdev) dd->phys_base = res.start; pm_runtime_enable(dev); - pm_runtime_get_sync(dev); + err = pm_runtime_get_sync(dev); + if (err < 0) { + dev_err(dev, "%s: failed to get_sync(%d)\n", + __func__, err); + goto err_res; + } omap_aes_dma_stop(dd); -- cgit v1.2.3 From d1e33e654ef6bb3dee766353ed9dd31e7dcb8a94 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Thu, 5 Dec 2013 10:02:15 +0100 Subject: cfg80211: in bitrate_mask, rename mcs to ht_mcs Rename NL80211_TXRATE_MCS to NL80211_TXRATE_HT and also rename mcs to ht_mcs in struct cfg80211_bitrate_mask. Signed-off-by: Janusz Dziedzic [reword commit message] Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/wmi.c | 6 +++--- drivers/net/wireless/mwifiex/cfg80211.c | 6 +++--- include/net/cfg80211.h | 2 +- include/uapi/linux/nl80211.h | 6 ++++-- net/mac80211/cfg.c | 4 ++-- net/wireless/nl80211.c | 18 +++++++++--------- 6 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 546d5da0b894..4f16d79c9eb1 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2754,9 +2754,9 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx, mask->control[band].legacy << 4; /* copy mcs rate mask */ - mcsrate = mask->control[band].mcs[1]; + mcsrate = mask->control[band].ht_mcs[1]; mcsrate <<= 8; - mcsrate |= mask->control[band].mcs[0]; + mcsrate |= mask->control[band].ht_mcs[0]; ratemask[band] |= mcsrate << 12; ratemask[band] |= mcsrate << 28; } @@ -2806,7 +2806,7 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx, mask->control[band].legacy << 4; /* copy mcs rate mask */ - mcsrate = mask->control[band].mcs[0]; + mcsrate = mask->control[band].ht_mcs[0]; ratemask[band] |= mcsrate << 12; ratemask[band] |= mcsrate << 20; } diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 1c8116d46845..6f5e49b32e79 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1170,10 +1170,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, else bitmap_rates[1] = mask->control[band].legacy; - /* Fill MCS rates */ - bitmap_rates[2] = mask->control[band].mcs[0]; + /* Fill HT MCS rates */ + bitmap_rates[2] = mask->control[band].ht_mcs[0]; if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) - bitmap_rates[2] |= mask->control[band].mcs[1] << 8; + bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, HostCmd_ACT_GEN_SET, 0, bitmap_rates); diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 884ac69b5e55..6c3a650f3a8f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1766,7 +1766,7 @@ enum wiphy_params_flags { struct cfg80211_bitrate_mask { struct { u32 legacy; - u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; + u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; } control[IEEE80211_NUM_BANDS]; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 72ba3584c90d..6e700645cd27 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3110,7 +3110,7 @@ enum nl80211_key_attributes { * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with * 1 = 500 kbps) but without the IE length restriction (at most * %NL80211_MAX_SUPP_RATES in a single array). - * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection + * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection * in an array of MCS numbers. * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute @@ -3118,13 +3118,15 @@ enum nl80211_key_attributes { enum nl80211_tx_rate_attributes { __NL80211_TXRATE_INVALID, NL80211_TXRATE_LEGACY, - NL80211_TXRATE_MCS, + NL80211_TXRATE_HT, /* keep last */ __NL80211_TXRATE_AFTER_LAST, NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 }; +#define NL80211_TXRATE_MCS NL80211_TXRATE_HT + /** * enum nl80211_band - Frequency band * @NL80211_BAND_2GHZ: 2.4 GHz ISM band diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 754069cbb756..a74d61d520b0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2588,8 +2588,8 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, int j; sdata->rc_rateidx_mask[i] = mask->control[i].legacy; - memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, - sizeof(mask->control[i].mcs)); + memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].ht_mcs, + sizeof(mask->control[i].ht_mcs)); sdata->rc_has_mcs_mask[i] = false; if (!sband) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f61b74c40d28..801e57da88b4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7312,8 +7312,8 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, .len = NL80211_MAX_SUPP_RATES }, - [NL80211_TXRATE_MCS] = { .type = NLA_BINARY, - .len = NL80211_MAX_SUPP_HT_RATES }, + [NL80211_TXRATE_HT] = { .type = NLA_BINARY, + .len = NL80211_MAX_SUPP_HT_RATES }, }; static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, @@ -7339,9 +7339,9 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, continue; mask.control[i].legacy = (1 << sband->n_bitrates) - 1; - memcpy(mask.control[i].mcs, + memcpy(mask.control[i].ht_mcs, sband->ht_cap.mcs.rx_mask, - sizeof(mask.control[i].mcs)); + sizeof(mask.control[i].ht_mcs)); } /* if no rates are given set it back to the defaults */ @@ -7372,12 +7372,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, nla_len(tb[NL80211_TXRATE_LEGACY])) return -EINVAL; } - if (tb[NL80211_TXRATE_MCS]) { + if (tb[NL80211_TXRATE_HT]) { if (!ht_rateset_to_mask( sband, - nla_data(tb[NL80211_TXRATE_MCS]), - nla_len(tb[NL80211_TXRATE_MCS]), - mask.control[band].mcs)) + nla_data(tb[NL80211_TXRATE_HT]), + nla_len(tb[NL80211_TXRATE_HT]), + mask.control[band].ht_mcs)) return -EINVAL; } @@ -7388,7 +7388,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, return -EINVAL; for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) - if (mask.control[band].mcs[i]) + if (mask.control[band].ht_mcs[i]) break; /* legacy and mcs rates may not be both empty */ -- cgit v1.2.3 From eac40d9631a7db43570df859fa8a9922e9623607 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Mon, 21 Oct 2013 15:38:31 +0800 Subject: rt2x00: rt2800lib: Update BBP register initialization for RT53xx Update bbp register initialization for RT53xx chips to match with the latest MediaTek/Ralink driver. Based on: NICInitRT5390BbpRegisters() From: DPO_RT5572_LinuxSTA_2.6.1.3_20121022/chips/rt5390.c Signed-off-by: Kevin Lo Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 776aff3678ff..aaf28d59296b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -5462,15 +5462,14 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 68, 0x0b); - rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 69, 0x0d); + rt2800_bbp_write(rt2x00dev, 70, 0x06); rt2800_bbp_write(rt2x00dev, 73, 0x13); rt2800_bbp_write(rt2x00dev, 75, 0x46); rt2800_bbp_write(rt2x00dev, 76, 0x28); rt2800_bbp_write(rt2x00dev, 77, 0x59); - rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); @@ -5513,6 +5512,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT5392)) { rt2800_bbp_write(rt2x00dev, 134, 0xd0); rt2800_bbp_write(rt2x00dev, 135, 0xf6); + rt2800_bbp_write(rt2x00dev, 148, 0x84); } rt2800_disable_unused_dac_adc(rt2x00dev); -- cgit v1.2.3 From d8d13d32c4a7c6653f22c7649cd3d2d86c2eeacd Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 22 Oct 2013 15:24:47 -0700 Subject: mwifiex: improvements in mwifiex_ret_tx_power_cfg() 1) Move common code out of switch case handling 2) Return from the function if number of bytes left in response buffer are less than tlv size 3) Pass pg_tlv_hdr directly instead of txp_cfg to mwifiex_get_power_level() Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_cmdresp.c | 35 ++++++++++++++---------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 2675ca7f8d14..551194605aa7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -338,8 +338,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) if (!data_buf) return -1; - pg_tlv_hdr = (struct mwifiex_types_power_group *) - ((u8 *) data_buf + sizeof(struct host_cmd_ds_txpwr_cfg)); + pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf); pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group)); length = le16_to_cpu(pg_tlv_hdr->length); @@ -383,19 +382,25 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, struct mwifiex_types_power_group *pg_tlv_hdr; struct mwifiex_power_group *pg; u16 action = le16_to_cpu(txp_cfg->action); + u16 tlv_buf_left; - switch (action) { - case HostCmd_ACT_GEN_GET: - pg_tlv_hdr = (struct mwifiex_types_power_group *) - ((u8 *) txp_cfg + - sizeof(struct host_cmd_ds_txpwr_cfg)); + pg_tlv_hdr = (struct mwifiex_types_power_group *) + ((u8 *)txp_cfg + + sizeof(struct host_cmd_ds_txpwr_cfg)); - pg = (struct mwifiex_power_group *) - ((u8 *) pg_tlv_hdr + - sizeof(struct mwifiex_types_power_group)); + pg = (struct mwifiex_power_group *) + ((u8 *)pg_tlv_hdr + + sizeof(struct mwifiex_types_power_group)); + tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg); + if (tlv_buf_left < + le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr)) + return 0; + + switch (action) { + case HostCmd_ACT_GEN_GET: if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) - mwifiex_get_power_level(priv, txp_cfg); + mwifiex_get_power_level(priv, pg_tlv_hdr); priv->tx_power_level = (u16) pg->power_min; break; @@ -404,14 +409,6 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, if (!le32_to_cpu(txp_cfg->mode)) break; - pg_tlv_hdr = (struct mwifiex_types_power_group *) - ((u8 *) txp_cfg + - sizeof(struct host_cmd_ds_txpwr_cfg)); - - pg = (struct mwifiex_power_group *) - ((u8 *) pg_tlv_hdr + - sizeof(struct mwifiex_types_power_group)); - if (pg->power_max == pg->power_min) priv->tx_power_level = (u16) pg->power_min; break; -- cgit v1.2.3 From c8520bcb784df69cf5960308846253814ec45db7 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Thu, 24 Oct 2013 13:24:08 +0800 Subject: rt2x00: rt2800lib: update RF registers for RT5390 Mirror the latest MediaTek/Ralink driver with respect to RT5390 RF register programming. The PCI and USB devices use different init values. Signed-off-by: Kevin Lo Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index aaf28d59296b..7848b39078c3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6453,7 +6453,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 7, 0x00); rt2800_rfcsr_write(rt2x00dev, 10, 0x53); rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); - rt2800_rfcsr_write(rt2x00dev, 12, 0xc6); + rt2800_rfcsr_write(rt2x00dev, 12, 0x46); rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); rt2800_rfcsr_write(rt2x00dev, 14, 0x00); rt2800_rfcsr_write(rt2x00dev, 15, 0x00); @@ -6466,7 +6466,8 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 22, 0x20); rt2800_rfcsr_write(rt2x00dev, 23, 0x00); rt2800_rfcsr_write(rt2x00dev, 24, 0x00); - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) + if (rt2x00_is_usb(rt2x00dev) && + rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) rt2800_rfcsr_write(rt2x00dev, 25, 0x80); else rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); @@ -6486,10 +6487,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 38, 0x85); rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) - rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); - else - rt2800_rfcsr_write(rt2x00dev, 40, 0x4b); + rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); @@ -6510,16 +6508,26 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 53, 0x84); rt2800_rfcsr_write(rt2x00dev, 54, 0x78); rt2800_rfcsr_write(rt2x00dev, 55, 0x44); - rt2800_rfcsr_write(rt2x00dev, 56, 0x22); + if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) + rt2800_rfcsr_write(rt2x00dev, 56, 0x42); + else + rt2800_rfcsr_write(rt2x00dev, 56, 0x22); rt2800_rfcsr_write(rt2x00dev, 57, 0x80); rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); rt2800_rfcsr_write(rt2x00dev, 60, 0x45); - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) - rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); - else - rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); + if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { + if (rt2x00_is_usb(rt2x00dev)) + rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); + else + rt2800_rfcsr_write(rt2x00dev, 61, 0xd5); + } else { + if (rt2x00_is_usb(rt2x00dev)) + rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); + else + rt2800_rfcsr_write(rt2x00dev, 61, 0xb5); + } rt2800_rfcsr_write(rt2x00dev, 62, 0x00); rt2800_rfcsr_write(rt2x00dev, 63, 0x00); -- cgit v1.2.3 From d94248ac2aef78e39a76321458a78ba7805dba2e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 24 Oct 2013 18:33:33 +1100 Subject: libertas/sdio: make sure card enters power-off when firmware is loaded. Since firmware loading became async it is possible that if_sdio_finish_power_of is called with only one remaining runtime_pm reference, so it isn't safe to call pm_runtime_put_noidle. We must call pm_runtime_put(). Diagnosed-by: "Dr. H. Nikolaus Schaller" Signed-off-by: NeilBrown Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 991238afd1b6..828e7f4fc633 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -849,7 +849,7 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) card->started = true; /* Tell PM core that we don't need the card to be * powered now */ - pm_runtime_put_noidle(&func->dev); + pm_runtime_put(&func->dev); } } -- cgit v1.2.3 From 60ce473e4938a42d355dd6c83e55211a08ebe25d Mon Sep 17 00:00:00 2001 From: Jing Wang Date: Thu, 24 Oct 2013 16:14:11 +0800 Subject: wl1251: return -ENOMEM if kzalloc fails the original code used goto out if kzalloc fails,but the out include kfree, so return -ENOMEM if kzalloc fails. Signed-off-by: Jing Wang Signed-off-by: John W. Linville --- drivers/net/wireless/ti/wl1251/acx.c | 209 ++++++++++++----------------------- 1 file changed, 68 insertions(+), 141 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c index db6430c1a084..374268d5ac6a 100644 --- a/drivers/net/wireless/ti/wl1251/acx.c +++ b/drivers/net/wireless/ti/wl1251/acx.c @@ -18,10 +18,8 @@ int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, wl1251_debug(DEBUG_ACX, "acx frame rates"); rates = kzalloc(sizeof(*rates), GFP_KERNEL); - if (!rates) { - ret = -ENOMEM; - goto out; - } + if (!rates) + return -ENOMEM; rates->tx_ctrl_frame_rate = ctrl_rate; rates->tx_ctrl_frame_mod = ctrl_mod; @@ -49,10 +47,8 @@ int wl1251_acx_station_id(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx dot11_station_id"); mac = kzalloc(sizeof(*mac), GFP_KERNEL); - if (!mac) { - ret = -ENOMEM; - goto out; - } + if (!mac) + return -ENOMEM; for (i = 0; i < ETH_ALEN; i++) mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; @@ -74,10 +70,8 @@ int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); - if (!default_key) { - ret = -ENOMEM; - goto out; - } + if (!default_key) + return -ENOMEM; default_key->id = key_id; @@ -104,10 +98,8 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, wl1251_debug(DEBUG_ACX, "acx wake up conditions"); wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); - if (!wake_up) { - ret = -ENOMEM; - goto out; - } + if (!wake_up) + return -ENOMEM; wake_up->wake_up_event = wake_up_event; wake_up->listen_interval = listen_interval; @@ -132,16 +124,13 @@ int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth) wl1251_debug(DEBUG_ACX, "acx sleep auth"); auth = kzalloc(sizeof(*auth), GFP_KERNEL); - if (!auth) { - ret = -ENOMEM; - goto out; - } + if (!auth) + return -ENOMEM; auth->sleep_auth = sleep_auth; ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); -out: kfree(auth); return ret; } @@ -154,10 +143,8 @@ int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len) wl1251_debug(DEBUG_ACX, "acx fw rev"); rev = kzalloc(sizeof(*rev), GFP_KERNEL); - if (!rev) { - ret = -ENOMEM; - goto out; - } + if (!rev) + return -ENOMEM; ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); if (ret < 0) { @@ -191,10 +178,8 @@ int wl1251_acx_tx_power(struct wl1251 *wl, int power) return -EINVAL; acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->current_tx_power = power * 10; @@ -217,10 +202,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx feature cfg"); feature = kzalloc(sizeof(*feature), GFP_KERNEL); - if (!feature) { - ret = -ENOMEM; - goto out; - } + if (!feature) + return -ENOMEM; /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ feature->data_flow_options = 0; @@ -261,10 +244,8 @@ int wl1251_acx_data_path_params(struct wl1251 *wl, wl1251_debug(DEBUG_ACX, "acx data path params"); params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - ret = -ENOMEM; - goto out; - } + if (!params) + return -ENOMEM; params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; @@ -309,10 +290,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time) wl1251_debug(DEBUG_ACX, "acx rx msdu life time"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->lifetime = life_time; ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, @@ -335,10 +314,8 @@ int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter) wl1251_debug(DEBUG_ACX, "acx rx config"); rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); - if (!rx_config) { - ret = -ENOMEM; - goto out; - } + if (!rx_config) + return -ENOMEM; rx_config->config_options = config; rx_config->filter_options = filter; @@ -363,10 +340,8 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx data pd threshold"); pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) { - ret = -ENOMEM; - goto out; - } + if (!pd) + return -ENOMEM; /* FIXME: threshold value not set */ @@ -389,10 +364,8 @@ int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) wl1251_debug(DEBUG_ACX, "acx slot"); slot = kzalloc(sizeof(*slot), GFP_KERNEL); - if (!slot) { - ret = -ENOMEM; - goto out; - } + if (!slot) + return -ENOMEM; slot->wone_index = STATION_WONE_INDEX; slot->slot_time = slot_time; @@ -416,10 +389,8 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx group address tbl"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; /* MAC filtering */ acx->enabled = 0; @@ -444,10 +415,8 @@ int wl1251_acx_service_period_timeout(struct wl1251 *wl) int ret; rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); - if (!rx_timeout) { - ret = -ENOMEM; - goto out; - } + if (!rx_timeout) + return -ENOMEM; wl1251_debug(DEBUG_ACX, "acx service period timeout"); @@ -475,10 +444,8 @@ int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold) wl1251_debug(DEBUG_ACX, "acx rts threshold"); rts = kzalloc(sizeof(*rts), GFP_KERNEL); - if (!rts) { - ret = -ENOMEM; - goto out; - } + if (!rts) + return -ENOMEM; rts->threshold = rts_threshold; @@ -501,10 +468,8 @@ int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter) wl1251_debug(DEBUG_ACX, "acx beacon filter opt"); beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); - if (!beacon_filter) { - ret = -ENOMEM; - goto out; - } + if (!beacon_filter) + return -ENOMEM; beacon_filter->enable = enable_filter; beacon_filter->max_num_beacons = 0; @@ -530,10 +495,8 @@ int wl1251_acx_beacon_filter_table(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx beacon filter table"); ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); - if (!ie_table) { - ret = -ENOMEM; - goto out; - } + if (!ie_table) + return -ENOMEM; /* configure default beacon pass-through rules */ ie_table->num_ie = 1; @@ -560,10 +523,8 @@ int wl1251_acx_conn_monit_params(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx connection monitor parameters"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD; acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT; @@ -589,10 +550,8 @@ int wl1251_acx_sg_enable(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx sg enable"); pta = kzalloc(sizeof(*pta), GFP_KERNEL); - if (!pta) { - ret = -ENOMEM; - goto out; - } + if (!pta) + return -ENOMEM; pta->enable = SG_ENABLE; @@ -615,10 +574,8 @@ int wl1251_acx_sg_cfg(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx sg cfg"); param = kzalloc(sizeof(*param), GFP_KERNEL); - if (!param) { - ret = -ENOMEM; - goto out; - } + if (!param) + return -ENOMEM; /* BT-WLAN coext parameters */ param->min_rate = RATE_INDEX_24MBPS; @@ -669,10 +626,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx cca threshold"); detection = kzalloc(sizeof(*detection), GFP_KERNEL); - if (!detection) { - ret = -ENOMEM; - goto out; - } + if (!detection) + return -ENOMEM; detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; detection->tx_energy_detection = 0; @@ -682,7 +637,6 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl) if (ret < 0) wl1251_warning("failed to set cca threshold: %d", ret); -out: kfree(detection); return ret; } @@ -695,10 +649,8 @@ int wl1251_acx_bcn_dtim_options(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx bcn dtim options"); bb = kzalloc(sizeof(*bb), GFP_KERNEL); - if (!bb) { - ret = -ENOMEM; - goto out; - } + if (!bb) + return -ENOMEM; bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; @@ -724,10 +676,8 @@ int wl1251_acx_aid(struct wl1251 *wl, u16 aid) wl1251_debug(DEBUG_ACX, "acx aid"); acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); - if (!acx_aid) { - ret = -ENOMEM; - goto out; - } + if (!acx_aid) + return -ENOMEM; acx_aid->aid = aid; @@ -750,10 +700,8 @@ int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask) wl1251_debug(DEBUG_ACX, "acx event mbox mask"); mask = kzalloc(sizeof(*mask), GFP_KERNEL); - if (!mask) { - ret = -ENOMEM; - goto out; - } + if (!mask) + return -ENOMEM; /* high event mask is unused */ mask->high_event_mask = 0xffffffff; @@ -805,10 +753,8 @@ int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) wl1251_debug(DEBUG_ACX, "acx_set_preamble"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->preamble = preamble; @@ -832,10 +778,8 @@ int wl1251_acx_cts_protect(struct wl1251 *wl, wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->ctsprotect = ctsprotect; @@ -856,10 +800,8 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime) int ret; tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); - if (!tsf_info) { - ret = -ENOMEM; - goto out; - } + if (!tsf_info) + return -ENOMEM; ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info, sizeof(*tsf_info)); @@ -900,11 +842,8 @@ int wl1251_acx_rate_policies(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx rate policies"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; /* configure one default (one-size-fits-all) rate class */ acx->rate_class_cnt = 1; @@ -932,10 +871,8 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl) wl1251_debug(DEBUG_ACX, "acx mem cfg"); mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); - if (!mem_conf) { - ret = -ENOMEM; - goto out; - } + if (!mem_conf) + return -ENOMEM; /* memory config */ mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); @@ -979,10 +916,8 @@ int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim) wl1251_debug(DEBUG_ACX, "acx tbtt and dtim"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->tbtt = tbtt; acx->dtim = dtim; @@ -1008,10 +943,8 @@ int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode, wl1251_debug(DEBUG_ACX, "acx bet enable"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->enable = mode; acx->max_consecutive = max_consecutive; @@ -1037,11 +970,8 @@ int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->ac = ac; acx->cw_min = cw_min; @@ -1073,11 +1003,8 @@ int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, ps_scheme, ack_policy); acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } + if (!acx) + return -ENOMEM; acx->queue = queue; acx->type = type; -- cgit v1.2.3 From 5f5deff34e4f9339e1e18a5af92fb1b79233783f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 25 Oct 2013 12:37:54 +0200 Subject: iwl3945: do not print RFKILL message We can mess logs if user space try to open device again and again if RFKILL switch is on. Do not print message and return ERFKILL error instead to indicate where the problem is. Note that iwl4965 handle this problem differently, it allows to open device when radio is disabled. Reported-by: Dietmar Rudolph Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 5c3bcedd679b..0487461ae4da 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -2396,8 +2396,7 @@ __il3945_up(struct il_priv *il) clear_bit(S_RFKILL, &il->status); else { set_bit(S_RFKILL, &il->status); - IL_WARN("Radio disabled by HW RF Kill switch\n"); - return -ENODEV; + return -ERFKILL; } _il_wr(il, CSR_INT, 0xFFFFFFFF); -- cgit v1.2.3 From 809c5255d87580d14ad746f059f73231d94b50a7 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 25 Oct 2013 18:15:42 -0400 Subject: cw1200: Make the "scan failed" message into a warning The reason that a scan failed for some reason (typically bad parameters) should be logged even when debugging is turned off. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/scan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index 8c017bfd2ffc..9afcd4ce3368 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c @@ -173,8 +173,9 @@ void cw1200_scan_work(struct work_struct *work) cw1200_set_pm(priv, &priv->powersave_mode); if (priv->scan.status < 0) - wiphy_dbg(priv->hw->wiphy, "[SCAN] Scan failed (%d).\n", - priv->scan.status); + wiphy_warn(priv->hw->wiphy, + "[SCAN] Scan failed (%d).\n", + priv->scan.status); else if (priv->scan.req) wiphy_dbg(priv->hw->wiphy, "[SCAN] Scan completed.\n"); -- cgit v1.2.3 From cf1ad8f94766a22b55f6515ac28b8edb0504e1d6 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 25 Oct 2013 18:15:43 -0400 Subject: wireless: cw1200: Use consistent internal locking conventions The cw1200_irq_handler() function expects the hwbus lock to be held when it is called. On the SDIO platform, this lock is implemented in terms of sdio_claim_host/sdio_release_host. This trivial patch makes it explicit that we are performing the hwbus lock rather than something SDIO-specific. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index ebdcdf44f155..d3acc85932a5 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -108,9 +108,9 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) struct hwbus_priv *self = dev_id; if (self->core) { - sdio_claim_host(self->func); + cw1200_sdio_lock(self); cw1200_irq_handler(self->core); - sdio_release_host(self->func); + cw1200_sdio_unlock(self); return IRQ_HANDLED; } else { return IRQ_NONE; -- cgit v1.2.3 From 685cc47174f730e68867d83b7db5e36283255e6d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 29 Oct 2013 19:34:25 +0100 Subject: brcm80211: fix usage of freq_reg_info() freq_reg_info() expects KHz and not MHz, fix this. In this case we'll now be getting the no-ir flags cleared on channels for any channel when the country IE trusts that channel. @@ struct ieee80211_channel *ch; struct wiphy *wiphy; const struct ieee80211_reg_rule *rule; @@ -rule = freq_reg_info(wiphy, ch->center_freq); +rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); Generated-by: Coccinelle SmPL Cc: Julia Lawall Cc: Peter Senna Tschudin Cc: Seth Forshee Cc: Arend van Spriel Reported-by: Mihir Shete Signed-off-by: Luis R. Rodriguez Acked-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/channel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index ef05df04136b..635ae034c7e5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -679,7 +679,8 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - rule = freq_reg_info(wiphy, ch->center_freq); + rule = freq_reg_info(wiphy, + MHZ_TO_KHZ(ch->center_freq)); if (IS_ERR(rule)) continue; -- cgit v1.2.3 From 856a4ef9f01e9f4b42c96dd70268f4864a93f72c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 29 Oct 2013 19:34:26 +0100 Subject: rtlwifi: fix usage of freq_reg_info() freq_reg_info() expects KHz and not MHz, fix this. In this case we'll now be getting the no-ir flags cleared on channels for any channel when the country IE trusts that channel. @@ struct ieee80211_channel *ch; struct wiphy *wiphy; const struct ieee80211_reg_rule *rule; @@ -rule = freq_reg_info(wiphy, ch->center_freq); +rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); Generated-by: Coccinelle SmPL Cc: Julia Lawall Cc: Peter Senna Tschudin Cc: Larry Finger Reported-by: Mihir Shete Signed-off-by: Luis R. Rodriguez Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/regd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index 89e36568e70f..a4eb9b271438 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -168,7 +168,8 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, (ch->flags & IEEE80211_CHAN_RADAR)) continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - reg_rule = freq_reg_info(wiphy, ch->center_freq); + reg_rule = freq_reg_info(wiphy, + MHZ_TO_KHZ(ch->center_freq)); if (IS_ERR(reg_rule)) continue; @@ -226,7 +227,7 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, */ ch = &sband->channels[11]; /* CH 12 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); + reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (!IS_ERR(reg_rule)) { if (!(reg_rule->flags & NL80211_RRF_NO_IR)) if (ch->flags & IEEE80211_CHAN_NO_IR) @@ -234,7 +235,7 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, } ch = &sband->channels[12]; /* CH 13 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); + reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (!IS_ERR(reg_rule)) { if (!(reg_rule->flags & NL80211_RRF_NO_IR)) if (ch->flags & IEEE80211_CHAN_NO_IR) -- cgit v1.2.3 From 9b0fa73d1e85b4e4aa6b5281e4438b5180d261bb Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 29 Oct 2013 17:06:41 -0500 Subject: rtl8187: Increase RX queue depth Under heavy load, the relatively small number of RX queue entries are completely filled. With an increase from 16 to 32 entries, this condition rarely happens. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 9a6edb0c014e..ec9aa5b67381 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -416,7 +416,7 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) struct rtl8187_rx_info *info; int ret = 0; - while (skb_queue_len(&priv->rx_queue) < 16) { + while (skb_queue_len(&priv->rx_queue) < 32) { skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); if (!skb) { ret = -ENOMEM; -- cgit v1.2.3 From b3e3f87160c1654e0478d0cb52e5e9b8790535f2 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Thu, 31 Oct 2013 14:07:45 +0800 Subject: wcn36xx: enable beacon change using BSS_CHANGED_BEACON Enable the beacon changed using BSS_CHANGED_BEACON. This is especially useful for mesh mode. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wcn36xx/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7839b31e4826..e64a6784079e 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -641,7 +641,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, dev_kfree_skb(skb); } - if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (changed & BSS_CHANGED_BEACON_ENABLED || + changed & BSS_CHANGED_BEACON) { wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed beacon enabled %d\n", bss_conf->enable_beacon); -- cgit v1.2.3 From 684e55f53ec0fda8933f2caeb439e4f7a803002a Mon Sep 17 00:00:00 2001 From: Eugene Krasnikov Date: Fri, 8 Nov 2013 17:34:39 +0000 Subject: wcn36xx: Fix logging macro with unnecessary semicolon The wcn36xx_err macro should not end in a semicolon as there are 2 consecutive semicolons in the preprocessed output. Signed-off-by: Joe Perches Signed-off-by: Eugene Krasnikov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 58b63833e8e7..8fa5cbace5ab 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -54,7 +54,7 @@ enum wcn36xx_debug_mask { }; #define wcn36xx_err(fmt, arg...) \ - printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg); + printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg) #define wcn36xx_warn(fmt, arg...) \ printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) -- cgit v1.2.3 From dc14b02c0dd87ca7bbb9d566ac209e4aaedddad5 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 12 Nov 2013 11:02:20 -0600 Subject: rtlwifi: Remove unused calls to rtl_is_special_data() When routine rtl_is_special_data() is called with false as its last argument, and the returned value is not tested, the call is essentially an extended no-op. Accordingly, these calls may be removed. Signed-off-by: Larry Finger Reported-by: Mark Cave-Ayland Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 2 -- drivers/net/wireless/rtlwifi/usb.c | 4 ---- 2 files changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 0f494444bcd1..8707d1a94995 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -688,8 +688,6 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->stats.rxbytesunicast += skb->len; } - rtl_is_special_data(hw, skb, false); - if (ieee80211_is_data(fc)) { rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 6e2b5c5c83c8..ec385e46d560 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -475,8 +475,6 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, rtlpriv->stats.rxbytesunicast += skb->len; } - rtl_is_special_data(hw, skb, false); - if (ieee80211_is_data(fc)) { rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); @@ -517,8 +515,6 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, rtlpriv->stats.rxbytesunicast += skb->len; } - rtl_is_special_data(hw, skb, false); - if (ieee80211_is_data(fc)) { rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); -- cgit v1.2.3 From ac0ef8139bc4f6493b6bb560bfeb31b883b7e8ae Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Thu, 14 Nov 2013 13:53:44 +0800 Subject: rt2x00: rt2800lib: no need to write RF register 3 twice for RT5592 In rt2800_init_rfcsr_5592(), there's no need to write RF register 3 twice. Signed-off-by: Kevin Lo Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7848b39078c3..5ee5b296ad28 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6610,7 +6610,6 @@ static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); rt2800_rfcsr_write(rt2x00dev, 3, 0x08); - rt2800_rfcsr_write(rt2x00dev, 3, 0x08); rt2800_rfcsr_write(rt2x00dev, 5, 0x10); rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); rt2800_rfcsr_write(rt2x00dev, 7, 0x00); -- cgit v1.2.3 From 8fd77aec1a9d6f4328fc0244f21932114e066df3 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:25 -0600 Subject: rtlwifi: rtl8192c: Prevent reconnect attempts if not connected This driver has a watchdog timer that attempts to reconnect when beacon frames are not seen for 6 seconds. This patch disables that reconnect whenever the device has never been connected. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index ff784072fb42..fcf9b621918c 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1437,7 +1437,8 @@ void rtl_watchdog_wq_callback(void *data) /* if we can't recv beacon for 6s, we should * reconnect this AP */ - if (rtlpriv->link_info.roam_times >= 3) { + if ((rtlpriv->link_info.roam_times >= 3) && + !is_zero_ether_addr(rtlpriv->mac80211.bssid)) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AP off, try to reconnect now\n"); rtlpriv->link_info.roam_times = 0; -- cgit v1.2.3 From 62009b7f12793c932aaba0df946b04cb4a77d022 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:26 -0600 Subject: rtlwifi: rtl8192cu: Add new firmware Vendor driver rtl8188C_8192C_8192D_usb_linux_v3.4.2_3727.20120404 introduced new firmware for these chips. The code try for the new file, and fall back to the original firmware if the new file is not available. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/core.c | 10 ++++++++++ drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 16 +++++++++++++--- drivers/net/wireless/rtlwifi/wifi.h | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 210ce7cd94d8..8dc4d9308593 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -46,10 +46,20 @@ void rtl_fw_cb(const struct firmware *firmware, void *context) "Firmware callback routine entered!\n"); complete(&rtlpriv->firmware_loading_complete); if (!firmware) { + if (rtlpriv->cfg->alt_fw_name) { + err = request_firmware(&firmware, + rtlpriv->cfg->alt_fw_name, + rtlpriv->io.dev); + pr_info("Loading alternative firmware %s\n", + rtlpriv->cfg->alt_fw_name); + if (!err) + goto found_alt; + } pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); rtlpriv->max_fw_size = 0; return; } +found_alt: if (firmware->size > rtlpriv->max_fw_size) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Firmware is too big!\n"); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 9936de716ad5..8501954cfb44 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -50,6 +50,9 @@ MODULE_AUTHOR("Larry Finger "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { @@ -69,14 +72,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) "Can't alloc buffer for fw\n"); return 1; } - + if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) && + !IS_92C_SERIAL(rtlpriv->rtlhal.version)) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin"; + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin"; + } else { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; + } + /* provide name of alternative file */ + rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin"; pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); rtlpriv->max_fw_size = 0x4000; err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, rtlpriv->io.dev, GFP_KERNEL, hw, rtl_fw_cb); - - return err; } diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 0c65386fa30d..0aa89fd89f35 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1804,6 +1804,7 @@ struct rtl_hal_cfg { bool write_readback; char *name; char *fw_name; + char *alt_fw_name; struct rtl_hal_ops *ops; struct rtl_mod_params *mod_params; struct rtl_hal_usbint_cfg *usb_interface_cfg; -- cgit v1.2.3 From b9a758a8c905fc59e783ae91ad645452d877ea88 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:27 -0600 Subject: rtlwifi: Redo register save locations The initial USB driver did not use some register save locations in the private data storage. To save some memory, a union was used to overlay these variables with USB I/O components. In an update of the gain-control code, these register save locations are now needed for USB drivers. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/wifi.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 0aa89fd89f35..8c647391bedf 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1033,6 +1033,7 @@ struct rtl_ht_agg { struct rssi_sta { long undec_sm_pwdb; + long undec_sm_cck; }; struct rtl_tid_data { @@ -1323,8 +1324,10 @@ struct fast_ant_training { struct rtl_dm { /*PHY status for Dynamic Management */ long entry_min_undec_sm_pwdb; + long undec_sm_cck; long undec_sm_pwdb; /*out dm */ long entry_max_undec_sm_pwdb; + s32 ofdm_pkt_cnt; bool dm_initialgain_enable; bool dynamic_txpower_enable; bool current_turbo_edca; @@ -1339,6 +1342,7 @@ struct rtl_dm { bool inform_fw_driverctrldm; bool current_mrc_switch; u8 txpowercount; + u8 powerindex_backup[6]; u8 thermalvalue_rxgain; u8 thermalvalue_iqk; @@ -1350,7 +1354,9 @@ struct rtl_dm { bool done_txpower; u8 dynamic_txhighpower_lvl; /*Tx high power level */ u8 dm_flag; /*Indicate each dynamic mechanism's status. */ + u8 dm_flag_tmp; u8 dm_type; + u8 dm_rssi_sel; u8 txpower_track_control; bool interrupt_migration; bool disable_tx_int; @@ -1949,6 +1955,7 @@ struct dig_t { u8 pre_ccastate; u8 cur_ccasate; u8 large_fa_hit; + u8 dig_dynamic_min; u8 forbidden_igi; u8 dig_state; u8 dig_highpwrstate; @@ -2029,22 +2036,15 @@ struct rtl_priv { struct dig_t dm_digtable; struct ps_t dm_pstable; - /* section shared by individual drivers */ - union { - struct { /* data buffer pointer for USB reads */ - __le32 *usb_data; - int usb_data_index; - bool initialized; - }; - struct { /* section for 8723ae */ - bool reg_init; /* true if regs saved */ - u32 reg_874; - u32 reg_c70; - u32 reg_85c; - u32 reg_a74; - bool bt_operation_on; - }; - }; + u32 reg_874; + u32 reg_c70; + u32 reg_85c; + u32 reg_a74; + bool reg_init; /* true if regs saved */ + bool bt_operation_on; + __le32 *usb_data; + int usb_data_index; + bool initialized; bool enter_ps; /* true when entering PS */ u8 rate_mask[5]; -- cgit v1.2.3 From 619ce76f8bb850b57032501a39f26aa6c6731c70 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:28 -0600 Subject: rtlwifi: Set the link state The present code fails to set the linked state when an interface is added. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 8dc4d9308593..2d337a0c3df0 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -194,6 +194,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS]); } + mac->link_state = MAC80211_LINKED; break; case NL80211_IFTYPE_ADHOC: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, -- cgit v1.2.3 From c908c74e005de780fddbe8cb6fcd44803f5d4b74 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:29 -0600 Subject: rtlwifi: rtl8192c: Add new definitions in the dm_common header Changes in the gain-control mechanism will require some changes in the header. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h index 518e208c0180..4f232a063636 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h @@ -91,6 +91,17 @@ #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define DYNAMIC_FUNC_DISABLE 0x0 +#define DYNAMIC_FUNC_DIG BIT(0) +#define DYNAMIC_FUNC_HP BIT(1) +#define DYNAMIC_FUNC_SS BIT(2) /*Tx Power Tracking*/ +#define DYNAMIC_FUNC_BT BIT(3) +#define DYNAMIC_FUNC_ANT_DIV BIT(4) + +#define RSSI_CCK 0 +#define RSSI_OFDM 1 +#define RSSI_DEFAULT 2 + struct swat_t { u8 failure_cnt; u8 try_flag; @@ -167,5 +178,8 @@ void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); +void dm_savepowerindex(struct ieee80211_hw *hw); +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); +void dm_restorepowerindex(struct ieee80211_hw *hw); #endif -- cgit v1.2.3 From dc6405712268fe514d3dd89aa936c4397b0871b9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:30 -0600 Subject: rtlwifi: Increase the RX queue length for USB drivers The current number of RX buffers queued is 32, which is too small under heavy load. That number is doubled. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index ec385e46d560..767b6832bbde 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -549,7 +549,7 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) } } -#define __RX_SKB_MAX_QUEUED 32 +#define __RX_SKB_MAX_QUEUED 64 static void _rtl_rx_work(unsigned long param) { -- cgit v1.2.3 From 65b9cc97c6852fae19dc5c7745e9abc8dd380aad Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:31 -0600 Subject: rtlwifi: Update beacon statistics for USB driver The USB drivers were not updating the beacon statistics, which led to false beacon loss indications. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 767b6832bbde..4933f02ce1d5 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -481,6 +481,8 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, if (unicast) rtlpriv->link_info.num_rx_inperiod++; } + /* static bcn for roaming */ + rtl_beacon_statistic(hw, skb); } } -- cgit v1.2.3 From 97204e93f01868eeba6ae5c4f3270f32905bb418 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:32 -0600 Subject: rtlwifi: rtl8192c: Add routines to save/restore power index registers Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index e9caa5d4cff0..9fc4b64d6bf0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -158,6 +158,42 @@ static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} }; +static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; + +void dm_restorepowerindex(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + + for (index = 0; index < 6; index++) + rtl_write_byte(rtlpriv, power_index_reg[index], + rtlpriv->dm.powerindex_backup[index]); +} +EXPORT_SYMBOL_GPL(dm_restorepowerindex); + +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + + for (index = 0; index < 6; index++) + rtl_write_byte(rtlpriv, power_index_reg[index], value); +} +EXPORT_SYMBOL_GPL(dm_writepowerindex); + +void dm_savepowerindex(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + u8 tmp; + + for (index = 0; index < 6; index++) { + tmp = rtl_read_byte(rtlpriv, power_index_reg[index]); + rtlpriv->dm.powerindex_backup[index] = tmp; + } +} +EXPORT_SYMBOL_GPL(dm_savepowerindex); + static void rtl92c_dm_diginit(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); -- cgit v1.2.3 From 9806eacf5de27ab01d680c5d75c92a3a89734e4f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:33 -0600 Subject: rtlwifi: rtl8192cu: Update the power index registers This patch uses the newly introduced power index register routines. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/dm.c | 9 +++++++++ drivers/net/wireless/rtlwifi/rtl8192cu/dm.h | 3 +++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c index 16a0b9e59acf..c16209a336ea 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c @@ -101,6 +101,15 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) "PHY_SetTxPowerLevel8192S() Channel = %d\n", rtlphy->current_channel); rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_NORMAL) + dm_restorepowerindex(hw); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) + dm_writepowerindex(hw, 0x14); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) + dm_writepowerindex(hw, 0x10); } rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h index d947e7d350bb..fafa6bac2a3f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h @@ -30,3 +30,6 @@ #include "../rtl8192ce/dm.h" void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw); +void dm_savepowerindex(struct ieee80211_hw *hw); +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); +void dm_restorepowerindex(struct ieee80211_hw *hw); -- cgit v1.2.3 From e9b0784bb9de3152e787ee779868c626b137fb3b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:34 -0600 Subject: rtlwifi: rtl8192cu: Fix some code in RF handling Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 2119313a737b..b878d56d2f4d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -85,17 +85,15 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, if (mac->act_scanning) { tx_agc[RF90_PATH_A] = 0x3f3f3f3f; tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - if (rtlhal->interface == INTF_USB) { - if (tx_agc[idx1] > 0x20 && - rtlefuse->external_pa) - tx_agc[idx1] = 0x20; - } + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + if (rtlhal->interface == INTF_USB) { + if (tx_agc[idx1] > 0x20 && + rtlefuse->external_pa) + tx_agc[idx1] = 0x20; } } } else { @@ -107,7 +105,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, TXHIGHPWRLEVEL_LEVEL2) { tx_agc[RF90_PATH_A] = 0x00000000; tx_agc[RF90_PATH_B] = 0x00000000; - } else{ + } else { for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { tx_agc[idx1] = ppowerlevel[idx1] | (ppowerlevel[idx1] << 8) | @@ -373,7 +371,12 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, regoffset == RTXAGC_B_MCS07_MCS04) regoffset = 0xc98; for (i = 0; i < 3; i++) { - writeVal = (writeVal > 6) ? (writeVal - 6) : 0; + if (i != 2) + writeVal = (writeVal > 8) ? + (writeVal - 8) : 0; + else + writeVal = (writeVal > 6) ? + (writeVal - 6) : 0; rtl_write_byte(rtlpriv, (u32)(regoffset + i), (u8)writeVal); } -- cgit v1.2.3 From d82403a9f407217b6aed5260aa92a120e8e98310 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:35 -0600 Subject: rtlwifi: Add missing code to PWDB statics routine Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/stats.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c index 8ed31744a054..4f083fc1d360 100644 --- a/drivers/net/wireless/rtlwifi/stats.c +++ b/drivers/net/wireless/rtlwifi/stats.c @@ -176,6 +176,7 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) struct rtl_sta_info *drv_priv = NULL; struct ieee80211_sta *sta = NULL; long undec_sm_pwdb; + long undec_sm_cck; rcu_read_lock(); if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) @@ -185,12 +186,16 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) if (sta) { drv_priv = (struct rtl_sta_info *) sta->drv_priv; undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; + undec_sm_cck = drv_priv->rssi_stat.undec_sm_cck; } else { undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + undec_sm_cck = rtlpriv->dm.undec_sm_cck; } if (undec_sm_pwdb < 0) undec_sm_pwdb = pstatus->rx_pwdb_all; + if (undec_sm_cck < 0) + undec_sm_cck = pstatus->rx_pwdb_all; if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) { undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) + @@ -200,6 +205,15 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); } + if (pstatus->rx_pwdb_all > (u32) undec_sm_cck) { + undec_sm_cck = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + undec_sm_cck = undec_sm_cck + 1; + } else { + undec_sm_pwdb = (((undec_sm_cck) * (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + } if (sta) { drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb; -- cgit v1.2.3 From 796e453436b183057e2d7d9b2bcff88d0bf53ba7 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Nov 2013 11:11:36 -0600 Subject: rtlwifi: rtl8192c: Update dynamic gain calculations The vendor driver contained a number of improvements in the gain settings for the rtl8192c{e,u} devices. This patch implements them in the kernel driver. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 291 ++++++++++++++-------- 1 file changed, 193 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 9fc4b64d6bf0..fd7e4a7c94de 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -216,7 +216,12 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw) dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; - dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; + dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LowRssi; + + dm_digtable->forbidden_igi = DM_DIG_MIN; + dm_digtable->large_fa_hit = 0; + dm_digtable->recover_cnt = 0; + dm_digtable->dig_dynamic_min = 0x25; } static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) @@ -242,7 +247,9 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; } - return (u8) rssi_val_min; + if (rssi_val_min > 100) + rssi_val_min = 100; + return (u8)rssi_val_min; } static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) @@ -260,9 +267,17 @@ static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); + falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail; + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail; rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); @@ -307,12 +322,14 @@ static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) value_igi++; else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) value_igi += 2; + if (value_igi > DM_DIG_FA_UPPER) value_igi = DM_DIG_FA_UPPER; else if (value_igi < DM_DIG_FA_LOWER) value_igi = DM_DIG_FA_LOWER; + if (rtlpriv->falsealm_cnt.cnt_all > 10000) - value_igi = 0x32; + value_igi = DM_DIG_FA_UPPER; dm_digtable->cur_igvalue = value_igi; rtl92c_dm_write_dig(hw); @@ -322,32 +339,80 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct dig_t *digtable = &rtlpriv->dm_digtable; + u32 isbt; + + /* modify DIG lower bound, deal with abnorally large false alarm */ + if (rtlpriv->falsealm_cnt.cnt_all > 10000) { + digtable->large_fa_hit++; + if (digtable->forbidden_igi < digtable->cur_igvalue) { + digtable->forbidden_igi = digtable->cur_igvalue; + digtable->large_fa_hit = 1; + } - if (rtlpriv->falsealm_cnt.cnt_all > digtable->fa_highthresh) { - if ((digtable->back_val - 2) < digtable->back_range_min) - digtable->back_val = digtable->back_range_min; - else - digtable->back_val -= 2; - } else if (rtlpriv->falsealm_cnt.cnt_all < digtable->fa_lowthresh) { - if ((digtable->back_val + 2) > digtable->back_range_max) - digtable->back_val = digtable->back_range_max; - else - digtable->back_val += 2; + if (digtable->large_fa_hit >= 3) { + if ((digtable->forbidden_igi + 1) > + digtable->rx_gain_max) + digtable->rx_gain_min = digtable->rx_gain_max; + else + digtable->rx_gain_min = (digtable->forbidden_igi + 1); + digtable->recover_cnt = 3600; /* 3600=2hr */ + } + } else { + /* Recovery mechanism for IGI lower bound */ + if (digtable->recover_cnt != 0) { + digtable->recover_cnt--; + } else { + if (digtable->large_fa_hit == 0) { + if ((digtable->forbidden_igi-1) < DM_DIG_MIN) { + digtable->forbidden_igi = DM_DIG_MIN; + digtable->rx_gain_min = DM_DIG_MIN; + } else { + digtable->forbidden_igi--; + digtable->rx_gain_min = digtable->forbidden_igi + 1; + } + } else if (digtable->large_fa_hit == 3) { + digtable->large_fa_hit = 0; + } + } + } + if (rtlpriv->falsealm_cnt.cnt_all < 250) { + isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01; + + if (!isbt) { + if (rtlpriv->falsealm_cnt.cnt_all > + digtable->fa_lowthresh) { + if ((digtable->back_val - 2) < + digtable->back_range_min) + digtable->back_val = digtable->back_range_min; + else + digtable->back_val -= 2; + } else if (rtlpriv->falsealm_cnt.cnt_all < + digtable->fa_lowthresh) { + if ((digtable->back_val + 2) > + digtable->back_range_max) + digtable->back_val = digtable->back_range_max; + else + digtable->back_val += 2; + } + } else { + digtable->back_val = DM_DIG_BACKOFF_DEFAULT; + } + } else { + /* Adjust initial gain by false alarm */ + if (rtlpriv->falsealm_cnt.cnt_all > 1000) + digtable->cur_igvalue = digtable->pre_igvalue + 2; + else if (rtlpriv->falsealm_cnt.cnt_all > 750) + digtable->cur_igvalue = digtable->pre_igvalue + 1; + else if (rtlpriv->falsealm_cnt.cnt_all < 500) + digtable->cur_igvalue = digtable->pre_igvalue - 1; } - if ((digtable->rssi_val_min + 10 - digtable->back_val) > - digtable->rx_gain_max) + /* Check initial gain by upper/lower bound */ + if (digtable->cur_igvalue > digtable->rx_gain_max) digtable->cur_igvalue = digtable->rx_gain_max; - else if ((digtable->rssi_val_min + 10 - - digtable->back_val) < digtable->rx_gain_min) - digtable->cur_igvalue = digtable->rx_gain_min; - else - digtable->cur_igvalue = digtable->rssi_val_min + 10 - - digtable->back_val; - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "rssi_val_min = %x back_val %x\n", - digtable->rssi_val_min, digtable->back_val); + if (digtable->cur_igvalue < digtable->rx_gain_min) + digtable->cur_igvalue = digtable->rx_gain_min; rtl92c_dm_write_dig(hw); } @@ -365,7 +430,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) multi_sta = true; if (!multi_sta || - dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { + dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) { initialized = false; dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; return; @@ -411,7 +476,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "presta_cstate = %x, cursta_cstate = %x\n", dm_digtable->presta_cstate, dm_digtable->cursta_cstate); - if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || dm_digtable->cursta_cstate == DIG_STA_CONNECT) { @@ -419,6 +483,8 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); + if (dm_digtable->rssi_val_min > 100) + dm_digtable->rssi_val_min = 100; rtl92c_dm_ctrl_initgain_by_rssi(hw); } } else { @@ -434,11 +500,12 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct dig_t *dm_digtable = &rtlpriv->dm_digtable; if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); + if (dm_digtable->rssi_val_min > 100) + dm_digtable->rssi_val_min = 100; if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) { if (dm_digtable->rssi_val_min <= 25) @@ -460,48 +527,14 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) } if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { - if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800) - dm_digtable->cur_cck_fa_state = - CCK_FA_STAGE_High; - else - dm_digtable->cur_cck_fa_state = CCK_FA_STAGE_Low; - - if (dm_digtable->pre_cck_fa_state != - dm_digtable->cur_cck_fa_state) { - if (dm_digtable->cur_cck_fa_state == - CCK_FA_STAGE_Low) - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, - 0x83); - else - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, - 0xcd); - - dm_digtable->pre_cck_fa_state = - dm_digtable->cur_cck_fa_state; - } - - rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40); - - if (IS_92C_SERIAL(rtlhal->version)) - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, - MASKBYTE2, 0xd7); - } else { + if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) || + (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX)) + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83); + else rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); - rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47); - if (IS_92C_SERIAL(rtlhal->version)) - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, - MASKBYTE2, 0xd3); - } dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; } - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "CCKPDStage=%x\n", - dm_digtable->cur_cck_pd_state); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "is92C=%x\n", - IS_92C_SERIAL(rtlhal->version)); } static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) @@ -518,6 +551,8 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) else dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; + dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; + rtl92c_dm_initial_gain_sta(hw); rtl92c_dm_initial_gain_multi_sta(hw); rtl92c_dm_cck_packet_detection_thresh(hw); @@ -529,23 +564,26 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) static void rtl92c_dm_dig(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; if (rtlpriv->dm.dm_initialgain_enable == false) return; - if (dm_digtable->dig_enable_flag == false) + if (!rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG) return; rtl92c_dm_ctrl_initgain_by_twoport(hw); - } static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - rtlpriv->dm.dynamic_txpower_enable = false; - + if (rtlpriv->rtlhal.interface == INTF_USB && + rtlpriv->rtlhal.board_type & 0x1) { + dm_savepowerindex(hw); + rtlpriv->dm.dynamic_txpower_enable = true; + } else { + rtlpriv->dm.dynamic_txpower_enable = false; + } rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; } @@ -560,9 +598,14 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, dm_digtable->back_val); - dm_digtable->cur_igvalue += 2; - if (dm_digtable->cur_igvalue > 0x3f) - dm_digtable->cur_igvalue = 0x3f; + if (rtlpriv->rtlhal.interface == INTF_USB && + !dm_digtable->dig_enable_flag) { + dm_digtable->pre_igvalue = 0x17; + return; + } + dm_digtable->cur_igvalue -= 1; + if (dm_digtable->cur_igvalue < DM_DIG_MIN) + dm_digtable->cur_igvalue = DM_DIG_MIN; if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, @@ -572,11 +615,47 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; } + RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING, + "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, + dm_digtable->rssi_val_min, dm_digtable->back_val, + dm_digtable->rx_gain_max, dm_digtable->rx_gain_min, + dm_digtable->large_fa_hit, dm_digtable->forbidden_igi); } EXPORT_SYMBOL(rtl92c_dm_write_dig); static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff; + + if (mac->link_state != MAC80211_LINKED) + return; + + if (mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_AP) { + /* TODO: Handle ADHOC and AP Mode */ + } + + if (tmpentry_max_pwdb != 0) + rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb; + else + rtlpriv->dm.entry_max_undec_sm_pwdb = 0; + + if (tmpentry_min_pwdb != 0xff) + rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb; + else + rtlpriv->dm.entry_min_undec_sm_pwdb = 0; + +/* TODO: + * if (mac->opmode == NL80211_IFTYPE_STATION) { + * if (rtlpriv->rtlhal.fw_ready) { + * u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16); + * rtl8192c_set_rssi_cmd(hw, param); + * } + * } + */ } void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) @@ -786,6 +865,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; rtlpriv->dm.cck_index = cck_index_old; } + /* Handle USB High PA boards */ delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? (thermalvalue - rtlpriv->dm.thermalvalue) : @@ -1176,22 +1256,22 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - static u8 initialize; - static u32 reg_874, reg_c70, reg_85c, reg_a74; - if (initialize == 0) { - reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - MASKDWORD) & 0x1CC000) >> 14; + if (!rtlpriv->reg_init) { + rtlpriv->reg_874 = (rtl_get_bbreg(hw, + RFPGA0_XCD_RFINTERFACESW, + MASKDWORD) & 0x1CC000) >> 14; - reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, - MASKDWORD) & BIT(3)) >> 3; + rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, + MASKDWORD) & BIT(3)) >> 3; - reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, - MASKDWORD) & 0xFF000000) >> 24; + rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + MASKDWORD) & 0xFF000000) >> 24; - reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12; + rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & + 0xF000) >> 12; - initialize = 1; + rtlpriv->reg_init = true; } if (!bforce_in_normal) { @@ -1228,12 +1308,12 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); } else { rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0x1CC000, reg_874); + 0x1CC000, rtlpriv->reg_874); rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), - reg_c70); + rtlpriv->reg_c70); rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, - reg_85c); - rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74); + rtlpriv->reg_85c); + rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74); rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); } @@ -1249,6 +1329,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + /* Determine the minimum RSSI */ if (((mac->link_state == MAC80211_NOLINK)) && (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { dm_pstable->rssi_val_min = 0; @@ -1277,6 +1358,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) dm_pstable->rssi_val_min); } + /* Power Saving for 92C */ if (IS_92C_SERIAL(rtlhal->version)) ;/* rtl92c_dm_1r_cca(hw); */ else @@ -1288,12 +1370,23 @@ void rtl92c_dm_init(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG; + rtlpriv->dm.undec_sm_pwdb = -1; + rtlpriv->dm.undec_sm_cck = -1; + rtlpriv->dm.dm_initialgain_enable = true; rtl92c_dm_diginit(hw); + + rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE; rtl92c_dm_init_dynamic_txpower(hw); + rtl92c_dm_init_edca_turbo(hw); rtl92c_dm_init_rate_adaptive_mask(hw); + rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS; rtl92c_dm_initialize_txpower_tracking(hw); rtl92c_dm_init_dynamic_bb_powersaving(hw); + + rtlpriv->dm.ofdm_pkt_cnt = 0; + rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT; } EXPORT_SYMBOL(rtl92c_dm_init); @@ -1344,7 +1437,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) } if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2; RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && @@ -1364,8 +1457,16 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) "PHY_SetTxPowerLevel8192S() Channel = %d\n", rtlphy->current_channel); rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_NORMAL) + dm_restorepowerindex(hw); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) + dm_writepowerindex(hw, 0x14); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) + dm_writepowerindex(hw, 0x10); } - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; } @@ -1436,12 +1537,6 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) else curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); - /* Set Tx Power according to BT status. */ - if (undec_sm_pwdb >= 30) - curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; - else if (undec_sm_pwdb < 25) - curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); - /* Check BT state related to BT_Idle in B/G mode. */ if (undec_sm_pwdb < 15) curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; -- cgit v1.2.3 From d3af1ce1388b00f8335ce3f9720032168d41e3c7 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 18 Nov 2013 13:06:55 -0600 Subject: rtlwifi: Bring _rtl92c_phy_iq_calibrate() in line with the vendor driver Bring _rtl92c_phy_iq_calibrate() in line with the vendor driver function _PHY_IQCalibrate(). Also fix incorrect initialisation for rtl8192cu. Signed-of-by: Mark Cave-Ayland Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 39 ++++++++++++++++------ drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 2 +- 2 files changed, 29 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 0c0e78263a66..9e32ac8a4425 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -1147,6 +1147,12 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, 0x522, 0x550, 0x551, 0x040 }; + u32 iqk_bb_reg_92C[9] = { + 0xc04, 0xc08, 0x874, 0xb68, + 0xb6c, 0x870, 0x860, 0x864, + 0x800 + }; + const u32 retrycount = 2; if (t == 0) { @@ -1157,6 +1163,8 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, rtlphy->adda_backup, 16); _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); + _rtl92c_phy_save_adda_registers(hw, iqk_bb_reg_92C, + rtlphy->iqk_bb_backup, 9); } _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t); if (t == 0) { @@ -1167,14 +1175,18 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, if (!rtlphy->rfpi_enable) _rtl92c_phy_pi_mode_switch(hw, true); - if (t == 0) { - rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); - rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); - rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); - } + + rtl_set_bbreg(hw, 0x800, BIT(24), 0x0); + rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); + + rtl_set_bbreg(hw, 0x870, BIT(10), 0x1); + rtl_set_bbreg(hw, 0x870, BIT(26), 0x1); + rtl_set_bbreg(hw, 0x860, BIT(10), 0x0); + rtl_set_bbreg(hw, 0x864, BIT(10), 0x0); + if (is2t) { rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); @@ -1239,13 +1251,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, 0x3FF0000) >> 16; } } - rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); - rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); - if (is2t) - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); + if (t != 0) { if (!rtlphy->rfpi_enable) _rtl92c_phy_pi_mode_switch(hw, false); @@ -1253,6 +1261,15 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, rtlphy->adda_backup, 16); _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); + _rtl92c_phy_reload_adda_registers(hw, iqk_bb_reg_92C, + rtlphy->iqk_bb_backup, 9); + + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); + if (is2t) + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); + + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); } } diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 189ba124a8c6..468bf73cc883 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -1022,7 +1022,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) if (ppsc->rfpwr_state == ERFON) { rtl92c_phy_set_rfpath_switch(hw, 1); if (iqk_initialized) { - rtl92c_phy_iq_calibrate(hw, false); + rtl92c_phy_iq_calibrate(hw, true); } else { rtl92c_phy_iq_calibrate(hw, false); iqk_initialized = true; -- cgit v1.2.3 From 8a7192080f45f2e7858bc4448f45a9d05f7f4da3 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 18 Nov 2013 13:06:56 -0600 Subject: rtlwifi: rtl8192cu: Bring rtl92cu_phy_bb_config() up to date The latest vendor driver contains some changes not in the kernel version. Signed-off-by: Mark Cave-Ayland Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 34e56308301e..0c09240eadcc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -120,6 +120,7 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u16 regval; + u32 regval32; u8 b_reg_hwparafile = 1; _rtl92c_phy_init_bb_rf_register_definition(hw); @@ -135,8 +136,11 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) { rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB); - rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); } + regval32 = rtl_read_dword(rtlpriv, 0x87c); + rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); + if (IS_HARDWARE_TYPE_8192CU(rtlhal)) + rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); if (b_reg_hwparafile == 1) rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); -- cgit v1.2.3 From 18a7424f8c76ff7acdda49e4346571cc2a69b7f9 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 18 Nov 2013 13:06:57 -0600 Subject: rtlwifi: rtl8192cu: Update table.c The latest vendor driver has some new values. Signed-off-by: Larry Finger Signed-off-by: Mark Cave-Ayland Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/table.c | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c index 966be519edb8..7903c154de00 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c @@ -36,7 +36,7 @@ u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = { 0x804, 0x00000003, 0x808, 0x0000fc00, 0x80c, 0x0000000a, - 0x810, 0x10005388, + 0x810, 0x10000330, 0x814, 0x020c3d10, 0x818, 0x02200385, 0x81c, 0x00000000, @@ -110,22 +110,22 @@ u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = { 0xc44, 0x000100b7, 0xc48, 0xec020107, 0xc4c, 0x007f037f, - 0xc50, 0x6954341e, + 0xc50, 0x69543420, 0xc54, 0x43bc0094, - 0xc58, 0x6954341e, + 0xc58, 0x69543420, 0xc5c, 0x433c0094, 0xc60, 0x00000000, 0xc64, 0x5116848b, 0xc68, 0x47c00bff, 0xc6c, 0x00000036, 0xc70, 0x2c7f000d, - 0xc74, 0x0186115b, + 0xc74, 0x2186115b, 0xc78, 0x0000001f, 0xc7c, 0x00b99612, 0xc80, 0x40000100, 0xc84, 0x20f60000, 0xc88, 0x40000100, - 0xc8c, 0x20200000, + 0xc8c, 0xa0e40000, 0xc90, 0x00121820, 0xc94, 0x00000000, 0xc98, 0x00121820, @@ -226,7 +226,7 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { 0x804, 0x00000001, 0x808, 0x0000fc00, 0x80c, 0x0000000a, - 0x810, 0x10005388, + 0x810, 0x10000330, 0x814, 0x020c3d10, 0x818, 0x02200385, 0x81c, 0x00000000, @@ -300,9 +300,9 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { 0xc44, 0x000100b7, 0xc48, 0xec020107, 0xc4c, 0x007f037f, - 0xc50, 0x6954341e, + 0xc50, 0x69543420, 0xc54, 0x43bc0094, - 0xc58, 0x6954341e, + 0xc58, 0x69543420, 0xc5c, 0x433c0094, 0xc60, 0x00000000, 0xc64, 0x5116848b, @@ -340,7 +340,7 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { 0xce4, 0x00000000, 0xce8, 0x37644302, 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, + 0xd00, 0x00000740, 0xd04, 0x00020401, 0xd08, 0x0000907f, 0xd0c, 0x20010201, @@ -633,17 +633,17 @@ u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = { 0x012, 0x00071000, 0x012, 0x000b0000, 0x012, 0x000fc000, - 0x013, 0x000287af, + 0x013, 0x000287b3, 0x013, 0x000244b7, 0x013, 0x000204ab, 0x013, 0x0001c49f, 0x013, 0x00018493, - 0x013, 0x00014297, - 0x013, 0x00010295, - 0x013, 0x0000c298, - 0x013, 0x0000819c, - 0x013, 0x000040a8, - 0x013, 0x0000001c, + 0x013, 0x0001429b, + 0x013, 0x00010299, + 0x013, 0x0000c29c, + 0x013, 0x000081a0, + 0x013, 0x000040ac, + 0x013, 0x00000020, 0x014, 0x0001944c, 0x014, 0x00059444, 0x014, 0x0009944c, @@ -932,10 +932,10 @@ u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = { 0x608, 0x0000000e, 0x609, 0x0000002a, 0x652, 0x00000020, - 0x63c, 0x0000000a, - 0x63d, 0x0000000e, - 0x63e, 0x0000000a, - 0x63f, 0x0000000e, + 0x63c, 0x00000008, + 0x63d, 0x00000008, + 0x63e, 0x0000000c, + 0x63f, 0x0000000c, 0x66e, 0x00000005, 0x700, 0x00000021, 0x701, 0x00000043, -- cgit v1.2.3 From eddc633a3abcffbbe2fb1eb460670f0c63b11211 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Tue, 19 Nov 2013 01:45:08 +0400 Subject: libertas sdio: claim device before calling sdio_disable_func() There is a failure path in if_sdio_power_on(), where sdio_disable_func() is called without claiming the device. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 828e7f4fc633..58c6ee5de98f 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -907,8 +907,8 @@ static int if_sdio_power_on(struct if_sdio_card *card) sdio_release_host(func); ret = if_sdio_prog_firmware(card); if (ret) { - sdio_disable_func(func); - return ret; + sdio_claim_host(func); + goto disable; } return 0; -- cgit v1.2.3 From 42bc702e76fc459dfb3f2fb50c99bd7f680eb2b4 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Wed, 20 Nov 2013 17:57:01 +0800 Subject: wcn36xx: set self STA default HT parameters These default HT parameters are required for self STA entry. In example, set the HT capable of self STA entry for bss configuration in mesh allows the MCS rate to be used. Otherwise, only legacy rate will be used. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wcn36xx/smd.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index de9eb2cfbf4b..7216152f4c0c 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -115,6 +115,22 @@ static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, } } +static void wcn36xx_smd_set_sta_default_ht_params( + struct wcn36xx_hal_config_sta_params *sta_params) +{ + sta_params->ht_capable = 1; + sta_params->tx_channel_width_set = 1; + sta_params->lsig_txop_protection = 1; + sta_params->max_ampdu_size = 3; + sta_params->max_ampdu_density = 5; + sta_params->max_amsdu_size = 0; + sta_params->sgi_20Mhz = 1; + sta_params->sgi_40mhz = 1; + sta_params->green_field_capable = 1; + sta_params->delayed_ba_support = 0; + sta_params->dsss_cck_mode_40mhz = 1; +} + static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -172,6 +188,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sizeof(priv_sta->supported_rates)); } else { wcn36xx_set_default_rates(&sta_params->supported_rates); + wcn36xx_smd_set_sta_default_ht_params(sta_params); } } -- cgit v1.2.3 From fc70ff7207a42e3d1f3d76317fe5e3169391dc47 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 24 Nov 2013 17:56:51 +0100 Subject: ath9k: fix retry chain initialization in tx99 code Initialize first chain attempt counter to 1 in ath9k_build_tx99_skb(). Otherwise multi-retry chain is initialized to {idx,count} = {-1, 0} in rate_control_fill_sta_table() and tx99 transmission rate is not configured in rate_control_apply_mask() since first chain idx is set to -1 Signed-off-by: Lorenzo Bianconi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/tx99.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index c65c37fe1014..57d775783ec8 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -76,6 +76,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) tx_info->band = hw->conf.chandef.chan->band; tx_info->flags = IEEE80211_TX_CTL_NO_ACK; tx_info->control.vif = sc->tx99_vif; + tx_info->control.rates[0].count = 1; memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); -- cgit v1.2.3 From cb500a7c299f03e0a8061ca408e68b13ffe8d35d Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 24 Nov 2013 22:03:41 +0100 Subject: brcmsmac: remove dependency on CRC8 and CRC_CCITT There is no code in brcmsmac that uses a function from CRC8 or CRC_CCITT any more. Building brcmsmac with these two disabled works without any problems. This was probably only used by the bus code which was replaced by bcma some time ago. Signed-off-by: Hauke Mehrtens Acked-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index d9d85e93d098..57918579d55d 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -8,8 +8,6 @@ config BRCMSMAC select BCMA select BRCMUTIL select FW_LOADER - select CRC_CCITT - select CRC8 select CORDIC ---help--- This module adds support for PCIe wireless adapters based on Broadcom -- cgit v1.2.3 From 8e27f360c52470981149359bf7d6ce000ad628f1 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 10:49:53 +0900 Subject: wireless: ipw2100: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 813c9af0ebd6..3aba49259ef1 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6362,7 +6362,6 @@ out: &ipw2100_attribute_group); free_libipw(dev, 0); - pci_set_drvdata(pci_dev, NULL); } pci_iounmap(pci_dev, ioaddr); -- cgit v1.2.3 From c44354d232ff80d5e6e55c3730a7079c5c3566fb Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 10:51:09 +0900 Subject: wireless: prism54: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_dev.c | 1 - drivers/net/wireless/prism54/islpci_hotplug.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index e05d9b4c8317..7fa2898d0619 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -914,7 +914,6 @@ islpci_setup(struct pci_dev *pdev) do_islpci_free_memory: islpci_free_memory(priv); do_free_netdev: - pci_set_drvdata(pdev, NULL); free_netdev(ndev); priv = NULL; return NULL; diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 9e68e0cb718e..d7b9e6376424 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -199,7 +199,6 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) do_unregister_netdev: unregister_netdev(ndev); islpci_free_memory(priv); - pci_set_drvdata(pdev, NULL); free_netdev(ndev); priv = NULL; do_pci_clear_mwi: @@ -247,7 +246,6 @@ prism54_remove(struct pci_dev *pdev) /* free the PCI memory and unmap the remapped page */ islpci_free_memory(priv); - pci_set_drvdata(pdev, NULL); free_netdev(ndev); priv = NULL; -- cgit v1.2.3 From 515adc14cb860f1fb83f48acc6558baec10386f4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 10:52:33 +0900 Subject: wireless: rt2x00: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 25da20e7e1f3..af721831dcbc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -156,8 +156,6 @@ exit_release_regions: exit_disable_device: pci_disable_device(pci_dev); - pci_set_drvdata(pci_dev, NULL); - return retval; } EXPORT_SYMBOL_GPL(rt2x00pci_probe); @@ -177,7 +175,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev) /* * Free the PCI device data. */ - pci_set_drvdata(pci_dev, NULL); pci_disable_device(pci_dev); pci_release_regions(pci_dev); } -- cgit v1.2.3 From 85f66a0e9bddb37570788ae040a9755d64127a2e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 11:11:15 +0900 Subject: wireless: libertas: remove unnecessary spi_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 83669151bb82..f11728a866ff 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -93,7 +93,6 @@ static void free_if_spi_card(struct if_spi_card *card) list_del(&packet->list); kfree(packet); } - spi_set_drvdata(card->spi, NULL); kfree(card); } -- cgit v1.2.3 From 0a7a109e134c619245e6e77dd93260fa0b427684 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 12:37:24 +0900 Subject: bcma: pci: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: John W. Linville --- drivers/bcma/host_pci.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 6fb98b53533f..12a4ff751359 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -238,7 +238,6 @@ static void bcma_host_pci_remove(struct pci_dev *dev) pci_release_regions(dev); pci_disable_device(dev); kfree(bus); - pci_set_drvdata(dev, NULL); } #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From f699273d6a624266ebc9198774f06ee64a3847a1 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 25 Nov 2013 10:45:28 -0600 Subject: rtlwifi: rtl8188ee: Fix typo in code The static analyser "cppcheck" shows the following typo: drivers/net/wireless/rtlwifi/rtl8188ee/dm.c:1081]: (style) Same expression on both sides of '!='. Signed-off-by: Larry Finger Reported-by: David Binderman Cc: David Binderman Cc: Stable [3.10+] Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8188ee/dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c index 21a5cf060677..a6184b6e1d57 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c @@ -1078,7 +1078,7 @@ static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw rtldm->swing_flag_ofdm = true; } - if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) { + if (rtldm->swing_idx_cck_cur != rtldm->swing_idx_cck) { rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; rtldm->swing_flag_cck = true; } -- cgit v1.2.3 From cddc6046391db27c543a422e8964502546ae1dd1 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Fri, 29 Nov 2013 23:47:30 +0800 Subject: wcn36xx: fix typo error Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wcn36xx/hal.h | 2 +- drivers/net/wireless/ath/wcn36xx/smd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index c02dbc618724..3c2ef0c32f72 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2644,7 +2644,7 @@ struct wcn36xx_hal_trigger_ba_rsp_candidate { struct add_ba_info ba_info[STACFG_MAX_TC]; } __packed; -struct wcn36xx_hal_trigget_ba_req_candidate { +struct wcn36xx_hal_trigger_ba_req_candidate { u8 sta_index; u8 tid_bitmap; } __packed; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 7216152f4c0c..ddb5b2f7a4b0 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1855,7 +1855,7 @@ out: int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) { struct wcn36xx_hal_trigger_ba_req_msg msg_body; - struct wcn36xx_hal_trigget_ba_req_candidate *candidate; + struct wcn36xx_hal_trigger_ba_req_candidate *candidate; int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1866,7 +1866,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) msg_body.header.len += sizeof(*candidate); PREPARE_HAL_BUF(wcn->hal_buf, msg_body); - candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) + candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *) (wcn->hal_buf + sizeof(msg_body)); candidate->sta_index = sta_index; candidate->tid_bitmap = 1; -- cgit v1.2.3 From d44040de6a991999b466adefc7588e479680b98d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Oct 2013 19:14:47 +0200 Subject: ath: fix logic on ath_reg_apply_active_scan_flags() The existing logic removes the passive scan flag from channels 12 and 13 when a regulatory hint coming from something other than a country IE has been passed. This is incorrect, the original intention was to ensure we always have passive scan enabled for these two channels for a specific set of custom world regulatory domains. Cc: smihir@qti.qualcomm.com Cc: tushnimb@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index d3bbf48522b6..3d596e25ba82 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -249,16 +249,16 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, return; /* - * If no country IE has been received always enable active scan - * on these channels. This is only done for specific regulatory SKUs + * If no country IE has been received always enable passive scan + * and no-ibss on these channels. This is only done for specific + * regulatory SKUs. */ if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { ch = &sband->channels[11]; /* CH 12 */ - if (ch->flags & IEEE80211_CHAN_NO_IR) - ch->flags &= ~IEEE80211_CHAN_NO_IR; + ch->flags |= IEEE80211_CHAN_NO_IR; + ch = &sband->channels[12]; /* CH 13 */ - if (ch->flags & IEEE80211_CHAN_NO_IR) - ch->flags &= ~IEEE80211_CHAN_NO_IR; + ch->flags |= IEEE80211_CHAN_NO_IR; return; } -- cgit v1.2.3 From bc0aa0691806dc30cf1a69fe50ae90cf8f752977 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Oct 2013 19:14:48 +0200 Subject: ath: clean up ath_reg_apply_active_scan_flags() The routine ath_reg_apply_active_scan_flags() can be a bit hard to read, this cleans it up by adding helpers for the two cases of clearing IR flags or adding them. This approach also makes no assumptions on the index of channels 12 and 13 so it should be portable accross different drivers. Cc: smihir@qti.qualcomm.com Cc: tushnimb@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 101 +++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 3d596e25ba82..f4bb9295b6c6 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -178,6 +178,47 @@ static bool ath_is_radar_freq(u16 center_freq) return (center_freq >= 5260 && center_freq <= 5700); } +static void ath_force_clear_no_ir_chan(struct wiphy *wiphy, + struct ieee80211_channel *ch) +{ + const struct ieee80211_reg_rule *reg_rule; + + reg_rule = freq_reg_info(wiphy, ch->center_freq); + if (IS_ERR(reg_rule)) + return; + + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + if (ch->flags & IEEE80211_CHAN_NO_IR) + ch->flags &= ~IEEE80211_CHAN_NO_IR; +} + +static void ath_force_clear_no_ir_freq(struct wiphy *wiphy, u16 center_freq) +{ + struct ieee80211_channel *ch; + + ch = ieee80211_get_channel(wiphy, center_freq); + if (!ch) + return; + + ath_force_clear_no_ir_chan(wiphy, ch); +} + +static void ath_force_no_ir_chan(struct ieee80211_channel *ch) +{ + ch->flags |= IEEE80211_CHAN_NO_IR; +} + +static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq) +{ + struct ieee80211_channel *ch; + + ch = ieee80211_get_channel(wiphy, center_freq); + if (!ch) + return; + + ath_force_no_ir_chan(ch); +} + /* * N.B: These exception rules do not apply radar freqs. * @@ -235,54 +276,38 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, } -/* Allows active scan scan on Ch 12 and 13 */ +/** + * ath_reg_apply_active_scan_flags() + * @wiphy: the wiphy to use + * @initiator: the regulatory hint initiator + * + * If no country IE has been received always enable passive scan + * and no-ibss on these channels. This is only done for specific + * regulatory SKUs. + * + * If a country IE has been received check its rule for this + * channel first before enabling active scan. The passive scan + * would have been enforced by the initial processing of our + * custom regulatory domain. + */ static void ath_reg_apply_active_scan_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - const struct ieee80211_reg_rule *reg_rule; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; if (!sband) return; - /* - * If no country IE has been received always enable passive scan - * and no-ibss on these channels. This is only done for specific - * regulatory SKUs. - */ - if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { - ch = &sband->channels[11]; /* CH 12 */ - ch->flags |= IEEE80211_CHAN_NO_IR; - - ch = &sband->channels[12]; /* CH 13 */ - ch->flags |= IEEE80211_CHAN_NO_IR; - return; - } - - /* - * If a country IE has been received check its rule for this - * channel first before enabling active scan. The passive scan - * would have been enforced by the initial processing of our - * custom regulatory domain. - */ - - ch = &sband->channels[11]; /* CH 12 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_NO_IR)) - if (ch->flags & IEEE80211_CHAN_NO_IR) - ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - - ch = &sband->channels[12]; /* CH 13 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_NO_IR)) - if (ch->flags & IEEE80211_CHAN_NO_IR) - ch->flags &= ~IEEE80211_CHAN_NO_IR; + switch(initiator) { + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + ath_force_clear_no_ir_freq(wiphy, 2467); + ath_force_clear_no_ir_freq(wiphy, 2472); + break; + default: + ath_force_no_ir_freq(wiphy, 2467); + ath_force_no_ir_freq(wiphy, 2472); } } -- cgit v1.2.3 From f33cbc4f4350003a0cfb12be07750f3a95965867 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Oct 2013 19:14:49 +0200 Subject: ath: rename ath_reg_apply_active_scan_flags() to ath_reg_apply_ir_flags() This also applies the no-ibss flag to the channels or clears it. The idea here is to clarify no initiated radiation should be allowed on these channels. Cc: smihir@qti.qualcomm.com Cc: tushnimb@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index f4bb9295b6c6..a5cbaca41b7b 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -277,7 +277,7 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, } /** - * ath_reg_apply_active_scan_flags() + * ath_reg_apply_ir_flags() * @wiphy: the wiphy to use * @initiator: the regulatory hint initiator * @@ -291,7 +291,7 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, * custom regulatory domain. */ static void -ath_reg_apply_active_scan_flags(struct wiphy *wiphy, +ath_reg_apply_ir_flags(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; @@ -357,7 +357,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, break; case 0x68: ath_reg_apply_beaconing_flags(wiphy, initiator); - ath_reg_apply_active_scan_flags(wiphy, initiator); + ath_reg_apply_ir_flags(wiphy, initiator); break; } } -- cgit v1.2.3 From 6c3af5888eb1df139c81bf74024f5d63ab336b04 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Oct 2013 19:14:50 +0200 Subject: ath: simplify ath_reg_apply_beaconing_flags() Simplify ath_reg_apply_beaconing_flags() by making use of thew new no-ir helper. Cc: smihir@qti.qualcomm.com Cc: tushnimb@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index a5cbaca41b7b..817340acfb53 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -220,13 +220,11 @@ static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq) } /* - * N.B: These exception rules do not apply radar freqs. + * These exception rules do not apply radar frequencies. * - * - We enable adhoc (or beaconing) if allowed by 11d - * - We enable active scan if the channel is allowed by 11d + * - We enable initiating radiation if the country IE says its fine: * - If no country IE has been processed and a we determine we have - * received a beacon on a channel we can enable active scan and - * adhoc (or beaconing). + * received a beacon on a channel we can enable initiating radiation. */ static void ath_reg_apply_beaconing_flags(struct wiphy *wiphy, @@ -234,7 +232,6 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, { enum ieee80211_band band; struct ieee80211_supported_band *sband; - const struct ieee80211_reg_rule *reg_rule; struct ieee80211_channel *ch; unsigned int i; @@ -253,21 +250,13 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, (ch->flags & IEEE80211_CHAN_RADAR)) continue; - if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (IS_ERR(reg_rule)) - continue; - /* - * If 11d had a rule for this channel ensure - * we enable adhoc/beaconing if it allows us to - * use it. Note that we would have disabled it - * by applying our static world regdomain by - * default during init, prior to calling our - * regulatory_hint(). - */ - if (!(reg_rule->flags & NL80211_RRF_NO_IR)) - ch->flags &= ~IEEE80211_CHAN_NO_IR; - } else { + /* + * If the country IE says initiating radiation + * is OK we trust that. + */ + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) + ath_force_clear_no_ir_chan(wiphy, ch); + else { if (ch->beacon_found) ch->flags &= ~IEEE80211_CHAN_NO_IR; } -- cgit v1.2.3 From 07782d94d90b9ab94a97b1a1841575251484e5bb Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 21 Oct 2013 19:14:51 +0200 Subject: ath: move the channel for ath_reg_apply_beaconing_flags() into helper While at it convert this into a switch statement, this makes it easier and manage. Cc: smihir@qti.qualcomm.com Cc: tushnimb@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 817340acfb53..b02b43e690d9 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -219,6 +219,25 @@ static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq) ath_force_no_ir_chan(ch); } +static void +__ath_reg_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct ieee80211_channel *ch) +{ + if (ath_is_radar_freq(ch->center_freq) || + (ch->flags & IEEE80211_CHAN_RADAR)) + return; + + switch (initiator) { + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + ath_force_clear_no_ir_chan(wiphy, ch); + break; + default: + if (ch->beacon_found) + ch->flags &= ~IEEE80211_CHAN_NO_IR; + } +} + /* * These exception rules do not apply radar frequencies. * @@ -236,33 +255,15 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, unsigned int i; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!wiphy->bands[band]) continue; - sband = wiphy->bands[band]; - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; + __ath_reg_apply_beaconing_flags(wiphy, initiator, ch); - if (ath_is_radar_freq(ch->center_freq) || - (ch->flags & IEEE80211_CHAN_RADAR)) - continue; - - /* - * If the country IE says initiating radiation - * is OK we trust that. - */ - if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) - ath_force_clear_no_ir_chan(wiphy, ch); - else { - if (ch->beacon_found) - ch->flags &= ~IEEE80211_CHAN_NO_IR; - } } } - } /** -- cgit v1.2.3 From 62452a99d0b225a0f5d34d34b2aef63d7b44157b Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 29 Oct 2013 19:34:24 +0100 Subject: ath: fix usage of freq_reg_info() freq_reg_info() expects KHz and not MHz, fix this. In this case we'll now be getting the no-ir flags cleared on channels for any channel when the country IE trusts that channel. @@ struct ieee80211_channel *ch; struct wiphy *wiphy; const struct ieee80211_reg_rule *rule; @@ -rule = freq_reg_info(wiphy, ch->center_freq); +rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); Generated-by: Coccinelle SmPL Cc: Julia Lawall Cc: Peter Senna Tschudin Reported-by: Mihir Shete Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index b02b43e690d9..3baafa5b8ce0 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -183,7 +183,7 @@ static void ath_force_clear_no_ir_chan(struct wiphy *wiphy, { const struct ieee80211_reg_rule *reg_rule; - reg_rule = freq_reg_info(wiphy, ch->center_freq); + reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); if (IS_ERR(reg_rule)) return; -- cgit v1.2.3 From a44ea6ffbbf716cca9c2abaa4a3a3a9a9ce7c75a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 29 Oct 2013 23:39:04 +0100 Subject: ath: move dynamic_country_user_possible() to the top This will be used later. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 144 ++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 3baafa5b8ce0..e7d01723ea09 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -114,6 +114,78 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { } }; +static bool dynamic_country_user_possible(struct ath_regulatory *reg) +{ + if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) + return true; + + switch (reg->country_code) { + case CTRY_UNITED_STATES: + case CTRY_JAPAN1: + case CTRY_JAPAN2: + case CTRY_JAPAN3: + case CTRY_JAPAN4: + case CTRY_JAPAN5: + case CTRY_JAPAN6: + case CTRY_JAPAN7: + case CTRY_JAPAN8: + case CTRY_JAPAN9: + case CTRY_JAPAN10: + case CTRY_JAPAN11: + case CTRY_JAPAN12: + case CTRY_JAPAN13: + case CTRY_JAPAN14: + case CTRY_JAPAN15: + case CTRY_JAPAN16: + case CTRY_JAPAN17: + case CTRY_JAPAN18: + case CTRY_JAPAN19: + case CTRY_JAPAN20: + case CTRY_JAPAN21: + case CTRY_JAPAN22: + case CTRY_JAPAN23: + case CTRY_JAPAN24: + case CTRY_JAPAN25: + case CTRY_JAPAN26: + case CTRY_JAPAN27: + case CTRY_JAPAN28: + case CTRY_JAPAN29: + case CTRY_JAPAN30: + case CTRY_JAPAN31: + case CTRY_JAPAN32: + case CTRY_JAPAN33: + case CTRY_JAPAN34: + case CTRY_JAPAN35: + case CTRY_JAPAN36: + case CTRY_JAPAN37: + case CTRY_JAPAN38: + case CTRY_JAPAN39: + case CTRY_JAPAN40: + case CTRY_JAPAN41: + case CTRY_JAPAN42: + case CTRY_JAPAN43: + case CTRY_JAPAN44: + case CTRY_JAPAN45: + case CTRY_JAPAN46: + case CTRY_JAPAN47: + case CTRY_JAPAN48: + case CTRY_JAPAN49: + case CTRY_JAPAN50: + case CTRY_JAPAN51: + case CTRY_JAPAN52: + case CTRY_JAPAN53: + case CTRY_JAPAN54: + case CTRY_JAPAN55: + case CTRY_JAPAN56: + case CTRY_JAPAN57: + case CTRY_JAPAN58: + case CTRY_JAPAN59: + return false; + } + + return true; +} + static inline bool is_wwr_sku(u16 regd) { return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && @@ -401,78 +473,6 @@ static void ath_reg_dyn_country(struct wiphy *wiphy, reg_initiator_name(request->initiator)); } -static bool dynamic_country_user_possible(struct ath_regulatory *reg) -{ - if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) - return true; - - switch (reg->country_code) { - case CTRY_UNITED_STATES: - case CTRY_JAPAN1: - case CTRY_JAPAN2: - case CTRY_JAPAN3: - case CTRY_JAPAN4: - case CTRY_JAPAN5: - case CTRY_JAPAN6: - case CTRY_JAPAN7: - case CTRY_JAPAN8: - case CTRY_JAPAN9: - case CTRY_JAPAN10: - case CTRY_JAPAN11: - case CTRY_JAPAN12: - case CTRY_JAPAN13: - case CTRY_JAPAN14: - case CTRY_JAPAN15: - case CTRY_JAPAN16: - case CTRY_JAPAN17: - case CTRY_JAPAN18: - case CTRY_JAPAN19: - case CTRY_JAPAN20: - case CTRY_JAPAN21: - case CTRY_JAPAN22: - case CTRY_JAPAN23: - case CTRY_JAPAN24: - case CTRY_JAPAN25: - case CTRY_JAPAN26: - case CTRY_JAPAN27: - case CTRY_JAPAN28: - case CTRY_JAPAN29: - case CTRY_JAPAN30: - case CTRY_JAPAN31: - case CTRY_JAPAN32: - case CTRY_JAPAN33: - case CTRY_JAPAN34: - case CTRY_JAPAN35: - case CTRY_JAPAN36: - case CTRY_JAPAN37: - case CTRY_JAPAN38: - case CTRY_JAPAN39: - case CTRY_JAPAN40: - case CTRY_JAPAN41: - case CTRY_JAPAN42: - case CTRY_JAPAN43: - case CTRY_JAPAN44: - case CTRY_JAPAN45: - case CTRY_JAPAN46: - case CTRY_JAPAN47: - case CTRY_JAPAN48: - case CTRY_JAPAN49: - case CTRY_JAPAN50: - case CTRY_JAPAN51: - case CTRY_JAPAN52: - case CTRY_JAPAN53: - case CTRY_JAPAN54: - case CTRY_JAPAN55: - case CTRY_JAPAN56: - case CTRY_JAPAN57: - case CTRY_JAPAN58: - case CTRY_JAPAN59: - return false; - } - - return true; -} - static void ath_reg_dyn_country_user(struct wiphy *wiphy, struct ath_regulatory *reg, struct regulatory_request *request) -- cgit v1.2.3 From ba94c049e555d1701d547025f7d547a582833d03 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 29 Oct 2013 23:39:05 +0100 Subject: ath: dynamic user allow check helper to the top This will be used later. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index e7d01723ea09..4a6c232c6c9b 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -186,6 +186,15 @@ static bool dynamic_country_user_possible(struct ath_regulatory *reg) return true; } +static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg) +{ + if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) + return false; + if (!dynamic_country_user_possible(reg)) + return false; + return true; +} + static inline bool is_wwr_sku(u16 regd) { return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && @@ -473,17 +482,6 @@ static void ath_reg_dyn_country(struct wiphy *wiphy, reg_initiator_name(request->initiator)); } -static void ath_reg_dyn_country_user(struct wiphy *wiphy, - struct ath_regulatory *reg, - struct regulatory_request *request) -{ - if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) - return; - if (!dynamic_country_user_possible(reg)) - return; - ath_reg_dyn_country(wiphy, reg, request); -} - void ath_reg_notifier_apply(struct wiphy *wiphy, struct regulatory_request *request, struct ath_regulatory *reg) @@ -516,7 +514,8 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, case NL80211_REGDOM_SET_BY_DRIVER: break; case NL80211_REGDOM_SET_BY_USER: - ath_reg_dyn_country_user(wiphy, reg, request); + if (ath_reg_dyn_country_user_allow(reg)) + ath_reg_dyn_country(wiphy, reg, request); break; case NL80211_REGDOM_SET_BY_COUNTRY_IE: ath_reg_dyn_country(wiphy, reg, request); -- cgit v1.2.3 From 251c9ba19143caa5eb5b6ec52c77c70c9d7b3d8f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 30 Oct 2013 00:10:07 +0100 Subject: ath: fix dynamic user regulatory domain support As it stands dynamic user regulatory domain support is only possible for a few programmed regulatory domains as a few countries do not allow for this. The existing code however only would take advantage of the feature if a custom world regulatory domain is used though as that's when we clear beconing flags. We need to lift this restriction as otherwise this feature is pointless. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 4a6c232c6c9b..9e154732afaa 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -302,6 +302,7 @@ static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq) static void __ath_reg_apply_beaconing_flags(struct wiphy *wiphy, + struct ath_regulatory *reg, enum nl80211_reg_initiator initiator, struct ieee80211_channel *ch) { @@ -313,6 +314,10 @@ __ath_reg_apply_beaconing_flags(struct wiphy *wiphy, case NL80211_REGDOM_SET_BY_COUNTRY_IE: ath_force_clear_no_ir_chan(wiphy, ch); break; + case NL80211_REGDOM_SET_BY_USER: + if (ath_reg_dyn_country_user_allow(reg)) + ath_force_clear_no_ir_chan(wiphy, ch); + break; default: if (ch->beacon_found) ch->flags &= ~IEEE80211_CHAN_NO_IR; @@ -328,6 +333,7 @@ __ath_reg_apply_beaconing_flags(struct wiphy *wiphy, */ static void ath_reg_apply_beaconing_flags(struct wiphy *wiphy, + struct ath_regulatory *reg, enum nl80211_reg_initiator initiator) { enum ieee80211_band band; @@ -341,8 +347,8 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, sband = wiphy->bands[band]; for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; - __ath_reg_apply_beaconing_flags(wiphy, initiator, ch); - + __ath_reg_apply_beaconing_flags(wiphy, reg, + initiator, ch); } } } @@ -363,7 +369,8 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, */ static void ath_reg_apply_ir_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) + struct ath_regulatory *reg, + enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; @@ -376,6 +383,12 @@ ath_reg_apply_ir_flags(struct wiphy *wiphy, ath_force_clear_no_ir_freq(wiphy, 2467); ath_force_clear_no_ir_freq(wiphy, 2472); break; + case NL80211_REGDOM_SET_BY_USER: + if (!ath_reg_dyn_country_user_allow(reg)) + break; + ath_force_clear_no_ir_freq(wiphy, 2467); + ath_force_clear_no_ir_freq(wiphy, 2472); + break; default: ath_force_no_ir_freq(wiphy, 2467); ath_force_no_ir_freq(wiphy, 2472); @@ -424,12 +437,15 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, case 0x66: case 0x67: case 0x6C: - ath_reg_apply_beaconing_flags(wiphy, initiator); + ath_reg_apply_beaconing_flags(wiphy, reg, initiator); break; case 0x68: - ath_reg_apply_beaconing_flags(wiphy, initiator); - ath_reg_apply_ir_flags(wiphy, initiator); + ath_reg_apply_beaconing_flags(wiphy, reg, initiator); + ath_reg_apply_ir_flags(wiphy, reg, initiator); break; + default: + if (ath_reg_dyn_country_user_allow(reg)) + ath_reg_apply_beaconing_flags(wiphy, reg, initiator); } } -- cgit v1.2.3 From 54f05e95132bdb47fa408308d64fd293d3ffb908 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 4 Dec 2013 08:46:06 -0800 Subject: Input: sh_keysc - restrict non-COMPILE_TEST compilation Hardware supported by the driver is only found on SUPERH or ARCH_SHMOBILE platforms. Restrict non-COMPILE_TEST compilation to them. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index bb174c1a9886..a673c9f3a0b9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -525,7 +525,7 @@ config KEYBOARD_SUNKBD config KEYBOARD_SH_KEYSC tristate "SuperH KEYSC keypad support" - depends on SUPERH || ARM || COMPILE_TEST + depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST help Say Y here if you want to use a keypad attached to the KEYSC block on SuperH processors such as sh7722 and sh7343. -- cgit v1.2.3 From d70f2cf520cf8c86c6b467fc5dcea524ec51dc2f Mon Sep 17 00:00:00 2001 From: Kevin Wallace Date: Tue, 3 Dec 2013 02:55:22 -0800 Subject: macvlan: Support creating macvtaps from macvlans When running in a network namespace whose only link to the outside world is a macvlan device, not being able to create a macvtap off of it is a real pain. So modify macvtap creation to automatically forward a creation of a macvtap on a macvlan to become a creation of a macvtap on the underlying network device, just like is currently done with macvlan-on-macvlan devices. v2: Use netif_is_macvlan and macvlan_dev_real_dev helpers to make it more clear what we're doing. Signed-off-by: Kevin Wallace Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index acf93798dc67..cfb91570cddd 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -820,13 +820,11 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, if (lowerdev == NULL) return -ENODEV; - /* When creating macvlans on top of other macvlans - use + /* When creating macvlans or macvtaps on top of other macvlans - use * the real device as the lowerdev. */ - if (lowerdev->rtnl_link_ops == dev->rtnl_link_ops) { - struct macvlan_dev *lowervlan = netdev_priv(lowerdev); - lowerdev = lowervlan->lowerdev; - } + if (netif_is_macvlan(lowerdev)) + lowerdev = macvlan_dev_real_dev(lowerdev); if (!tb[IFLA_MTU]) dev->mtu = lowerdev->mtu; -- cgit v1.2.3 From 71bd4b8ec0bf5fbeea54270b390bebe8e108fbf8 Mon Sep 17 00:00:00 2001 From: Christopher Pau Date: Sat, 16 Nov 2013 10:00:33 +0000 Subject: i40e: set pf_id based on device and function numbers pf_id needs to be encoded for cards with ARI enabled, which allows for larger function numbers than 8. Commit-Id: I23fa7df9dabf3878cc08c9b2151729c8539f5f17 Signed-off-by: Christopher Pau Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 1e4ea134975a..9e868eac8e1e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -297,7 +297,11 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) } /* Determine the PF number based on the PCI fn */ - hw->pf_id = (u8)hw->bus.func; + reg = rd32(hw, I40E_GLPCI_CAPSUP); + if (reg & I40E_GLPCI_CAPSUP_ARI_EN_MASK) + hw->pf_id = (u8)((hw->bus.device << 3) | hw->bus.func); + else + hw->pf_id = (u8)hw->bus.func; /* If there was a Global Reset in progress when we got here, * we don't need to do the PF Reset -- cgit v1.2.3 From 5807822f84a2e2420d6db2359409894ea7c69880 Mon Sep 17 00:00:00 2001 From: Anjali Singhai jain Date: Sat, 16 Nov 2013 10:00:34 +0000 Subject: i40e: register file updates Hardware definitions changed slightly so sync up the defines file with the updated state of the hardware. Change-Id: I8349d91630a3208df306bd1dc88f028c87be2248 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_register.h | 134 ++++++++---------------- 1 file changed, 44 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index 6bd333cde28b..db4958bea583 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -28,6 +28,10 @@ #ifndef _I40E_REGISTER_H_ #define _I40E_REGISTER_H_ +#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */ +#define I40E_GL_GP_FUSE_MAX_INDEX 28 +#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0 +#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT) #define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4 #define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0 #define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT) @@ -38,6 +42,11 @@ #define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT) #define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16 #define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT) +#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC +#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0 +#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT) +#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8 +#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT) #define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8 #define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0 #define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT) @@ -50,6 +59,10 @@ #define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600 #define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT) +#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */ +#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127 +#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0 +#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT) #define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT) @@ -837,7 +850,7 @@ #define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT) #define I40E_GLHMC_PEQ1FLMAX 0x000C2058 #define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0 -#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT) +#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT) #define I40E_GLHMC_PEQ1MAX 0x000C2054 #define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0 #define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT) @@ -903,7 +916,7 @@ #define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT) #define I40E_GLHMC_PEXFFLMAX 0x000C204c #define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0 -#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x3FFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT) +#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT) #define I40E_GLHMC_PEXFMAX 0x000C2048 #define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0 #define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT) @@ -1636,7 +1649,7 @@ #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11 #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT) #define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4)) -#define I40E_VSILAN_QTABLE_MAX_INDEX 15 +#define I40E_VSILAN_QTABLE_MAX_INDEX 7 #define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0 #define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT) #define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16 @@ -1773,16 +1786,20 @@ #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT) #define I40E_GL_MNG_FWSM 0x000B6134 -#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0 -#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x3FF << I40E_GL_MNG_FWSM_FW_MODES_SHIFT) -#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10 +#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1 +#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT) +#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6 #define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT) #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11 #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT) #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15 #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT) +#define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16 +#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT) #define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19 #define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT) +#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25 +#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT) #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26 #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT) #define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27 @@ -2380,8 +2397,7 @@ #define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT) #define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16 #define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT) -#define I40E_PFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT 17 -#define I40E_PFPE_IPCONFIG0_USEUPPERIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT) + #define I40E_PFPE_MRTEIDXMASK 0x00008600 #define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0 #define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT) @@ -2460,8 +2476,6 @@ #define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT) #define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16 #define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT) -#define I40E_VFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT 17 -#define I40E_VFPE_IPCONFIG0_USEUPPERIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT) #define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */ #define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127 #define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0 @@ -3141,30 +3155,6 @@ #define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31 #define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0 #define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT) -#define I40E_GLPM_DMACR 0x000881F4 -#define I40E_GLPM_DMACR_DMACWT_SHIFT 0 -#define I40E_GLPM_DMACR_DMACWT_MASK (0xFFFF << I40E_GLPM_DMACR_DMACWT_SHIFT) -#define I40E_GLPM_DMACR_EXIT_DC_SHIFT 29 -#define I40E_GLPM_DMACR_EXIT_DC_MASK (0x1 << I40E_GLPM_DMACR_EXIT_DC_SHIFT) -#define I40E_GLPM_DMACR_LX_COALESCING_INDICATION_SHIFT 30 -#define I40E_GLPM_DMACR_LX_COALESCING_INDICATION_MASK (0x1 << I40E_GLPM_DMACR_LX_COALESCING_INDICATION_SHIFT) -#define I40E_GLPM_DMACR_DMAC_EN_SHIFT 31 -#define I40E_GLPM_DMACR_DMAC_EN_MASK (0x1 << I40E_GLPM_DMACR_DMAC_EN_SHIFT) -#define I40E_GLPM_LTRC 0x000BE500 -#define I40E_GLPM_LTRC_SLTRV_SHIFT 0 -#define I40E_GLPM_LTRC_SLTRV_MASK (0x3FF << I40E_GLPM_LTRC_SLTRV_SHIFT) -#define I40E_GLPM_LTRC_SSCALE_SHIFT 10 -#define I40E_GLPM_LTRC_SSCALE_MASK (0x7 << I40E_GLPM_LTRC_SSCALE_SHIFT) -#define I40E_GLPM_LTRC_LTRS_REQUIREMENT_SHIFT 15 -#define I40E_GLPM_LTRC_LTRS_REQUIREMENT_MASK (0x1 << I40E_GLPM_LTRC_LTRS_REQUIREMENT_SHIFT) -#define I40E_GLPM_LTRC_NSLTRV_SHIFT 16 -#define I40E_GLPM_LTRC_NSLTRV_MASK (0x3FF << I40E_GLPM_LTRC_NSLTRV_SHIFT) -#define I40E_GLPM_LTRC_NSSCALE_SHIFT 26 -#define I40E_GLPM_LTRC_NSSCALE_MASK (0x7 << I40E_GLPM_LTRC_NSSCALE_SHIFT) -#define I40E_GLPM_LTRC_LTR_SEND_SHIFT 30 -#define I40E_GLPM_LTRC_LTR_SEND_MASK (0x1 << I40E_GLPM_LTRC_LTR_SEND_SHIFT) -#define I40E_GLPM_LTRC_LTRNS_REQUIREMENT_SHIFT 31 -#define I40E_GLPM_LTRC_LTRNS_REQUIREMENT_MASK (0x1 << I40E_GLPM_LTRC_LTRNS_REQUIREMENT_SHIFT) #define I40E_PRTPM_EEE_STAT 0x001E4320 #define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29 #define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT) @@ -3201,9 +3191,6 @@ #define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT) #define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31 #define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT) -#define I40E_PRTPM_HPTC 0x000AC800 -#define I40E_PRTPM_HPTC_HIGH_PRI_TC_SHIFT 0 -#define I40E_PRTPM_HPTC_HIGH_PRI_TC_MASK (0xFF << I40E_PRTPM_HPTC_HIGH_PRI_TC_SHIFT) #define I40E_PRTPM_RLPIC 0x001E43A0 #define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0 #define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT) @@ -3265,8 +3252,8 @@ #define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT) #define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3 #define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT) -#define I40E_GLQF_CTL_DDPLPEN_SHIFT 7 -#define I40E_GLQF_CTL_DDPLPEN_MASK (0x1 << I40E_GLQF_CTL_DDPLPEN_SHIFT) +#define I40E_GLQF_CTL_RSVD_SHIFT 7 +#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT) #define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8 #define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT) #define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11 @@ -3416,9 +3403,9 @@ #define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */ #define I40E_PRTQF_FLX_PIT_MAX_INDEX 8 #define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0 -#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) -#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 6 -#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0xF << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) +#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) +#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5 +#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) #define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10 #define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) #define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4)) @@ -3504,7 +3491,7 @@ #define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5 #define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT) #define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4)) -#define I40E_VSIQF_TCREGION_MAX_INDEX 7 +#define I40E_VSIQF_TCREGION_MAX_INDEX 3 #define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0 #define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT) #define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9 @@ -3521,10 +3508,7 @@ #define I40E_GL_FCOEDDPC_MAX_INDEX 143 #define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0 #define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT) -#define I40E_GL_FCOEDDPEC(_i) (0x00314900 + ((_i) * 8)) /* _i=0...143 */ -#define I40E_GL_FCOEDDPEC_MAX_INDEX 143 -#define I40E_GL_FCOEDDPEC_CFOEDDPEC_SHIFT 0 -#define I40E_GL_FCOEDDPEC_CFOEDDPEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPEC_CFOEDDPEC_SHIFT) +/* _i=0...143 */ #define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */ #define I40E_GL_FCOEDIFEC_MAX_INDEX 143 #define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0 @@ -4276,46 +4260,10 @@ #define I40E_PFPM_APM 0x000B8080 #define I40E_PFPM_APM_APME_SHIFT 0 #define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT) -#define I40E_PFPM_FHFT_DATA(_i, _j) (0x00060000 + ((_i) * 4096 + (_j) * 128)) -#define I40E_PFPM_FHFT_DATA_MAX_INDEX 7 -#define I40E_PFPM_FHFT_DATA_DWORD_SHIFT 0 -#define I40E_PFPM_FHFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PFPM_FHFT_DATA_DWORD_SHIFT) #define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */ #define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7 #define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0 #define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT) -#define I40E_PFPM_FHFT_MASK(_i, _j) (0x00068000 + ((_i) * 1024 + (_j) * 128)) -#define I40E_PFPM_FHFT_MASK_MAX_INDEX 7 -#define I40E_PFPM_FHFT_MASK_MASK_SHIFT 0 -#define I40E_PFPM_FHFT_MASK_MASK_MASK (0xFFFF << I40E_PFPM_FHFT_MASK_MASK_SHIFT) -#define I40E_PFPM_PROXYFC 0x00245A80 -#define I40E_PFPM_PROXYFC_PPROXYE_SHIFT 0 -#define I40E_PFPM_PROXYFC_PPROXYE_MASK (0x1 << I40E_PFPM_PROXYFC_PPROXYE_SHIFT) -#define I40E_PFPM_PROXYFC_EX_SHIFT 1 -#define I40E_PFPM_PROXYFC_EX_MASK (0x1 << I40E_PFPM_PROXYFC_EX_SHIFT) -#define I40E_PFPM_PROXYFC_ARP_SHIFT 4 -#define I40E_PFPM_PROXYFC_ARP_MASK (0x1 << I40E_PFPM_PROXYFC_ARP_SHIFT) -#define I40E_PFPM_PROXYFC_ARP_DIRECTED_SHIFT 5 -#define I40E_PFPM_PROXYFC_ARP_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYFC_ARP_DIRECTED_SHIFT) -#define I40E_PFPM_PROXYFC_NS_SHIFT 9 -#define I40E_PFPM_PROXYFC_NS_MASK (0x1 << I40E_PFPM_PROXYFC_NS_SHIFT) -#define I40E_PFPM_PROXYFC_NS_DIRECTED_SHIFT 10 -#define I40E_PFPM_PROXYFC_NS_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYFC_NS_DIRECTED_SHIFT) -#define I40E_PFPM_PROXYFC_MLD_SHIFT 12 -#define I40E_PFPM_PROXYFC_MLD_MASK (0x1 << I40E_PFPM_PROXYFC_MLD_SHIFT) -#define I40E_PFPM_PROXYS 0x00245B80 -#define I40E_PFPM_PROXYS_EX_SHIFT 1 -#define I40E_PFPM_PROXYS_EX_MASK (0x1 << I40E_PFPM_PROXYS_EX_SHIFT) -#define I40E_PFPM_PROXYS_ARP_SHIFT 4 -#define I40E_PFPM_PROXYS_ARP_MASK (0x1 << I40E_PFPM_PROXYS_ARP_SHIFT) -#define I40E_PFPM_PROXYS_ARP_DIRECTED_SHIFT 5 -#define I40E_PFPM_PROXYS_ARP_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYS_ARP_DIRECTED_SHIFT) -#define I40E_PFPM_PROXYS_NS_SHIFT 9 -#define I40E_PFPM_PROXYS_NS_MASK (0x1 << I40E_PFPM_PROXYS_NS_SHIFT) -#define I40E_PFPM_PROXYS_NS_DIRECTED_SHIFT 10 -#define I40E_PFPM_PROXYS_NS_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYS_NS_DIRECTED_SHIFT) -#define I40E_PFPM_PROXYS_MLD_SHIFT 12 -#define I40E_PFPM_PROXYS_MLD_MASK (0x1 << I40E_PFPM_PROXYS_MLD_SHIFT) #define I40E_PFPM_WUC 0x0006B200 #define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5 #define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT) @@ -4536,21 +4484,21 @@ #define I40E_VFMSIX_PBA 0x00002000 #define I40E_VFMSIX_PBA_PENBIT_SHIFT 0 #define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT) -#define I40E_VFMSIX_TADD(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ +#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ #define I40E_VFMSIX_TADD_MAX_INDEX 16 #define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0 #define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT) #define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2 #define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT) -#define I40E_VFMSIX_TMSG(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ +#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ #define I40E_VFMSIX_TMSG_MAX_INDEX 16 #define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0 #define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT) -#define I40E_VFMSIX_TUADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ +#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ #define I40E_VFMSIX_TUADD_MAX_INDEX 16 #define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0 #define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT) -#define I40E_VFMSIX_TVCTRL(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ +#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ #define I40E_VFMSIX_TVCTRL_MAX_INDEX 16 #define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0 #define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT) @@ -4610,8 +4558,6 @@ #define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT) #define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16 #define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT) -#define I40E_VFPE_IPCONFIG01_USEUPPERIDRANGE_SHIFT 17 -#define I40E_VFPE_IPCONFIG01_USEUPPERIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEUPPERIDRANGE_SHIFT) #define I40E_VFPE_MRTEIDXMASK1 0x00009000 #define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0 #define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT) @@ -4684,5 +4630,13 @@ #define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT) #define I40E_VFQF_HREGION_REGION_7_SHIFT 29 #define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT) - +#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110 +#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0 +#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT) +#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8 +#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT) +#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16 +#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT) +#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24 +#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT) #endif -- cgit v1.2.3 From 26d7178f5ba164e329f137b00a542fd67b850051 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:35 +0000 Subject: i40e: clear AQ head and tail registers During admin queue shutdown clear some more registers explicitly. Change-Id: Ifb235c691e1c55e76bf66e0642207f464153d05a Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index cfef7fc32cdd..2bf73dda160b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -466,10 +466,15 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw) return I40E_ERR_NOT_READY; /* Stop firmware AdminQ processing */ - if (hw->mac.type == I40E_MAC_VF) + if (hw->mac.type == I40E_MAC_VF) { wr32(hw, I40E_VF_ATQLEN1, 0); - else + wr32(hw, I40E_VF_ATQH1, 0); + wr32(hw, I40E_VF_ATQT1, 0); + } else { wr32(hw, I40E_PF_ATQLEN, 0); + wr32(hw, I40E_PF_ATQH, 0); + wr32(hw, I40E_PF_ATQT, 0); + } /* make sure lock is available */ mutex_lock(&hw->aq.asq_mutex); @@ -500,10 +505,15 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) return I40E_ERR_NOT_READY; /* Stop firmware AdminQ processing */ - if (hw->mac.type == I40E_MAC_VF) + if (hw->mac.type == I40E_MAC_VF) { wr32(hw, I40E_VF_ARQLEN1, 0); - else + wr32(hw, I40E_VF_ARQH1, 0); + wr32(hw, I40E_VF_ARQT1, 0); + } else { wr32(hw, I40E_PF_ARQLEN, 0); + wr32(hw, I40E_PF_ARQH, 0); + wr32(hw, I40E_PF_ARQT, 0); + } /* make sure lock is available */ mutex_lock(&hw->aq.arq_mutex); -- cgit v1.2.3 From 17e6a845dc808f9e9cb3085517fd851d1ccc2bc3 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:36 +0000 Subject: i40e: simplify aq head-tail-len setups Use more virtual registers to simplify code flows. Change-Id: I32cff3818c5ca3a3792487ba4fed8f1d0ea6145a Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 50 ++++++++------------------- drivers/net/ethernet/intel/i40e/i40e_adminq.h | 1 + 2 files changed, 15 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 2bf73dda160b..92c01ad9de15 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -43,13 +43,17 @@ static void i40e_adminq_init_regs(struct i40e_hw *hw) if (hw->mac.type == I40E_MAC_VF) { hw->aq.asq.tail = I40E_VF_ATQT1; hw->aq.asq.head = I40E_VF_ATQH1; + hw->aq.asq.len = I40E_VF_ATQLEN1; hw->aq.arq.tail = I40E_VF_ARQT1; hw->aq.arq.head = I40E_VF_ARQH1; + hw->aq.arq.len = I40E_VF_ARQLEN1; } else { hw->aq.asq.tail = I40E_PF_ATQT; hw->aq.asq.head = I40E_PF_ATQH; + hw->aq.asq.len = I40E_PF_ATQLEN; hw->aq.arq.tail = I40E_PF_ARQT; hw->aq.arq.head = I40E_PF_ARQH; + hw->aq.arq.len = I40E_PF_ARQLEN; } } @@ -466,15 +470,9 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw) return I40E_ERR_NOT_READY; /* Stop firmware AdminQ processing */ - if (hw->mac.type == I40E_MAC_VF) { - wr32(hw, I40E_VF_ATQLEN1, 0); - wr32(hw, I40E_VF_ATQH1, 0); - wr32(hw, I40E_VF_ATQT1, 0); - } else { - wr32(hw, I40E_PF_ATQLEN, 0); - wr32(hw, I40E_PF_ATQH, 0); - wr32(hw, I40E_PF_ATQT, 0); - } + wr32(hw, hw->aq.asq.head, 0); + wr32(hw, hw->aq.asq.tail, 0); + wr32(hw, hw->aq.asq.len, 0); /* make sure lock is available */ mutex_lock(&hw->aq.asq_mutex); @@ -505,15 +503,9 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) return I40E_ERR_NOT_READY; /* Stop firmware AdminQ processing */ - if (hw->mac.type == I40E_MAC_VF) { - wr32(hw, I40E_VF_ARQLEN1, 0); - wr32(hw, I40E_VF_ARQH1, 0); - wr32(hw, I40E_VF_ARQT1, 0); - } else { - wr32(hw, I40E_PF_ARQLEN, 0); - wr32(hw, I40E_PF_ARQH, 0); - wr32(hw, I40E_PF_ARQT, 0); - } + wr32(hw, hw->aq.arq.head, 0); + wr32(hw, hw->aq.arq.tail, 0); + wr32(hw, hw->aq.arq.len, 0); /* make sure lock is available */ mutex_lock(&hw->aq.arq_mutex); @@ -966,27 +958,13 @@ void i40e_resume_aq(struct i40e_hw *hw) hw->aq.asq.next_to_clean = 0; i40e_config_asq_regs(hw); - reg = hw->aq.num_asq_entries; - - if (hw->mac.type == I40E_MAC_VF) { - reg |= I40E_VF_ATQLEN_ATQENABLE_MASK; - wr32(hw, I40E_VF_ATQLEN1, reg); - } else { - reg |= I40E_PF_ATQLEN_ATQENABLE_MASK; - wr32(hw, I40E_PF_ATQLEN, reg); - } + reg = hw->aq.num_asq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK; + wr32(hw, hw->aq.asq.len, reg); hw->aq.arq.next_to_use = 0; hw->aq.arq.next_to_clean = 0; i40e_config_arq_regs(hw); - reg = hw->aq.num_arq_entries; - - if (hw->mac.type == I40E_MAC_VF) { - reg |= I40E_VF_ATQLEN_ATQENABLE_MASK; - wr32(hw, I40E_VF_ARQLEN1, reg); - } else { - reg |= I40E_PF_ATQLEN_ATQENABLE_MASK; - wr32(hw, I40E_PF_ARQLEN, reg); - } + reg = hw->aq.num_arq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK; + wr32(hw, hw->aq.arq.len, reg); } diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index 22e5ed683e47..f8c2c44e233d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -56,6 +56,7 @@ struct i40e_adminq_ring { /* used for queue tracking */ u32 head; u32 tail; + u32 len; }; /* ASQ transaction details */ -- cgit v1.2.3 From fe31070444268e7b70279bd4a1403625820793b0 Mon Sep 17 00:00:00 2001 From: Anjali Singhai jain Date: Sat, 16 Nov 2013 10:00:37 +0000 Subject: i40e: firmware version fields offsets update The version bits reported by the hardware changed, so fix up the offsets to print the version correctly. Change-Id: I8a8207b401ea88f6da024aebafe7d3826ee6512c Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 17 +++++++++-------- drivers/net/ethernet/intel/i40e/i40e_main.c | 7 +++++++ 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 1ca9834cdfda..b82f501602c3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -81,11 +81,14 @@ #define I40E_DEFAULT_MSG_ENABLE 4 #define I40E_NVM_VERSION_LO_SHIFT 0 -#define I40E_NVM_VERSION_LO_MASK (0xf << I40E_NVM_VERSION_LO_SHIFT) -#define I40E_NVM_VERSION_MID_SHIFT 4 -#define I40E_NVM_VERSION_MID_MASK (0xff << I40E_NVM_VERSION_MID_SHIFT) -#define I40E_NVM_VERSION_HI_SHIFT 12 -#define I40E_NVM_VERSION_HI_MASK (0xf << I40E_NVM_VERSION_HI_SHIFT) +#define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) +#define I40E_NVM_VERSION_HI_SHIFT 8 +#define I40E_NVM_VERSION_HI_MASK (0xff << I40E_NVM_VERSION_HI_SHIFT) + +/* The values in here are decimal coded as hex as is the case in the NVM map*/ +#define I40E_CURRENT_NVM_VERSION_HI 0x2 +#define I40E_CURRENT_NVM_VERSION_LO 0x1 + /* magic for getting defines into strings */ #define STRINGIFY(foo) #foo @@ -441,13 +444,11 @@ static inline char *i40e_fw_version_str(struct i40e_hw *hw) static char buf[32]; snprintf(buf, sizeof(buf), - "f%d.%d a%d.%d n%02d.%02d.%02d e%08x", + "f%d.%d a%d.%d n%02x.%02x e%08x", hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.api_maj_ver, hw->aq.api_min_ver, (hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >> I40E_NVM_VERSION_HI_SHIFT, - (hw->nvm.version & I40E_NVM_VERSION_MID_MASK) - >> I40E_NVM_VERSION_MID_SHIFT, (hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >> I40E_NVM_VERSION_LO_SHIFT, hw->nvm.eetrack); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index be15938ba213..6e0f2cb3ae11 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7141,6 +7141,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = i40e_init_adminq(hw); dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw)); + if (((hw->nvm.version & I40E_NVM_VERSION_HI_MASK) + >> I40E_NVM_VERSION_HI_SHIFT) != I40E_CURRENT_NVM_VERSION_HI) { + dev_info(&pdev->dev, + "warning: NVM version not supported, supported version: %02x.%02x\n", + I40E_CURRENT_NVM_VERSION_HI, + I40E_CURRENT_NVM_VERSION_LO); + } if (err) { dev_info(&pdev->dev, "init_adminq failed: %d expecting API %02x.%02x\n", -- cgit v1.2.3 From 54692b403c7a1353f7b851efd69bdfe91966c1d9 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Sat, 16 Nov 2013 10:00:38 +0000 Subject: i40e: allow one more vector for VFs The number of vectors per VF as reported by the hardware does not include vector 0, so we need to account for this when checking to see if the VF is configuring a valid vector. Change-Id: I051d8bebae8f4722239f5a3fa5e1de4cf0f4e817 Signed-off-by: Mitch Williams Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 07596982a477..d98cc9b351f9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -70,7 +70,7 @@ static inline bool i40e_vc_isvalid_vector_id(struct i40e_vf *vf, u8 vector_id) { struct i40e_pf *pf = vf->pf; - return vector_id < pf->hw.func_caps.num_msix_vectors_vf; + return vector_id <= pf->hw.func_caps.num_msix_vectors_vf; } /***********************vf resource mgmt routines*****************/ -- cgit v1.2.3 From d52cf0a948267afc1d330ff1603a704a55c9f9fc Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:39 +0000 Subject: i40e: select reset counters correctly The indication for telling which reset happened is a value, not a bit pattern, so select by ==, not &. Change-Id: Ie04097388ff16b85015d6ab1236d7511ef653e8c Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 6e0f2cb3ae11..2dd4be523bb0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2790,11 +2790,11 @@ static irqreturn_t i40e_intr(int irq, void *data) val = rd32(hw, I40E_GLGEN_RSTAT); val = (val & I40E_GLGEN_RSTAT_RESET_TYPE_MASK) >> I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT; - if (val & I40E_RESET_CORER) + if (val == I40E_RESET_CORER) pf->corer_count++; - else if (val & I40E_RESET_GLOBR) + else if (val == I40E_RESET_GLOBR) pf->globr_count++; - else if (val & I40E_RESET_EMPR) + else if (val == I40E_RESET_EMPR) pf->empr_count++; } -- cgit v1.2.3 From d4946cf555c62590dbdcf1f17376025f6368cadd Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:40 +0000 Subject: i40e: retry call on timeout If the admin queue times out, retry some more to make driver load and reset more robust. Change-Id: I45c977b3d10a62c770d6072659ec27834849ca33 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 92c01ad9de15..30f32f3a86bc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -535,8 +535,9 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) **/ i40e_status i40e_init_adminq(struct i40e_hw *hw) { - u16 eetrack_lo, eetrack_hi; i40e_status ret_code; + u16 eetrack_lo, eetrack_hi; + int retry = 0; /* verify input for valid configuration */ if ((hw->aq.num_arq_entries == 0) || @@ -564,11 +565,24 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) if (ret_code) goto init_adminq_free_asq; - ret_code = i40e_aq_get_firmware_version(hw, - &hw->aq.fw_maj_ver, &hw->aq.fw_min_ver, - &hw->aq.api_maj_ver, &hw->aq.api_min_ver, - NULL); - if (ret_code) + /* There are some cases where the firmware may not be quite ready + * for AdminQ operations, so we retry the AdminQ setup a few times + * if we see timeouts in this first AQ call. + */ + do { + ret_code = i40e_aq_get_firmware_version(hw, + &hw->aq.fw_maj_ver, + &hw->aq.fw_min_ver, + &hw->aq.api_maj_ver, + &hw->aq.api_min_ver, + NULL); + if (ret_code != I40E_ERR_ADMIN_QUEUE_TIMEOUT) + break; + retry++; + msleep(100); + i40e_resume_aq(hw); + } while (retry < 10); + if (ret_code != I40E_SUCCESS) goto init_adminq_free_arq; if (hw->aq.api_maj_ver != I40E_FW_API_VERSION_MAJOR || -- cgit v1.2.3 From 7e68edf9e364783cddf7ba2ccf75bc8d62ff9bda Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Sat, 16 Nov 2013 10:00:41 +0000 Subject: i40e: properly add VF MAC addresses The code that added new MAC addresses from the VFs did not, in fact, work. Due to inverse logic, the only addresses that could be added were addresses that already had been added. Change-Id: Idce9169bd2f36e2c5ee10b130587a65705465d31 Signed-off-by: Mitch Williams Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index d98cc9b351f9..59973012c35d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1603,7 +1603,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) struct i40e_mac_filter *f; f = i40e_find_mac(vsi, al->list[i].addr, true, false); - if (f) { + if (!f) { if (i40e_is_vsi_in_vlan(vsi)) f = i40e_put_mac_in_vlan(vsi, al->list[i].addr, true, false); -- cgit v1.2.3 From 4f28c7276043ceec6c668292d0341fa9a45aaaeb Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Sat, 16 Nov 2013 10:00:42 +0000 Subject: i40e: fix debugging messages Clean up some messages that had arguments reversed. Change-Id: I0f38a4f01132a2918d61dbaf23de1e1eaed5e56d Signed-off-by: Mitch Williams Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 59973012c35d..e7bdd47bafcf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -620,13 +620,13 @@ int i40e_reset_vf(struct i40e_vf *vf, bool flr) if (ret) dev_info(&pf->pdev->dev, "Queue control check failed on Tx queue %d of VSI %d VF %d\n", - vf->lan_vsi_index, j, vf->vf_id); + j, vf->lan_vsi_index, vf->vf_id); ret = i40e_ctrl_vsi_rx_queue(vf, vf->lan_vsi_index, j, I40E_QUEUE_CTRL_FASTDISABLECHECK); if (ret) dev_info(&pf->pdev->dev, "Queue control check failed on Rx queue %d of VSI %d VF %d\n", - vf->lan_vsi_index, j, vf->vf_id); + j, vf->lan_vsi_index, vf->vf_id); } /* clear the irq settings */ -- cgit v1.2.3 From 2759997b0c84e5483482d5486df780da7935086b Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:43 +0000 Subject: i40e: default debug mask setting Set the debug mask by default. Change-Id: I10346ccb1a47f79747eb2108a83af059e947f1e2 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2dd4be523bb0..db626e04db24 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5579,6 +5579,7 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE, (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)); + pf->hw.debug_mask = pf->msg_enable | I40E_DEBUG_DIAG; if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) { if (I40E_DEBUG_USER & debug) pf->hw.debug_mask = debug; -- cgit v1.2.3 From cd92e72f2d0a5b576f025f693cfd306cebd8b84a Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:44 +0000 Subject: i40e: add interrupt test Add a quick ethtool test for interrupts using the SW interrupt. Also, change the loopback test (for now) to not report failure. Change-Id: Id8ef154b82475e3163087a8d1df01dfec4d529fc Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 10 ++++++++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index b82f501602c3..8806cab28c6a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -250,6 +250,7 @@ struct i40e_pf { u16 globr_count; /* Global reset count */ u16 empr_count; /* EMP reset count */ u16 pfr_count; /* PF reset count */ + u16 sw_int_count; /* SW interrupt count */ struct mutex switch_mutex; u16 lan_vsi; /* our default LAN VSI */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 1b86138fa9e1..8f5d538c11c3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -734,14 +734,20 @@ static int i40e_eeprom_test(struct i40e_pf *pf, u64 *data) static int i40e_intr_test(struct i40e_pf *pf, u64 *data) { - *data = -ENOSYS; + u16 swc_old = pf->sw_int_count; + + wr32(&pf->hw, I40E_PFINT_DYN_CTL0, + (I40E_PFINT_DYN_CTL0_INTENA_MASK | + I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK)); + usleep_range(1000, 2000); + *data = (swc_old == pf->sw_int_count); return *data; } static int i40e_loopback_test(struct i40e_pf *pf, u64 *data) { - *data = -ENOSYS; + *data = 0; return *data; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index db626e04db24..d60673ebf139 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2752,6 +2752,11 @@ static irqreturn_t i40e_intr(int irq, void *data) ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA); + /* if interrupt but no bits showing, must be SWINT */ + if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) || + (icr0 & I40E_PFINT_ICR0_SWINT_MASK)) + pf->sw_int_count++; + /* only q0 is used in MSI/Legacy mode, and none are used in MSIX */ if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK) { -- cgit v1.2.3 From 7823fe341da4660c9aab9fec8fbff94e3070ceaf Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Sat, 16 Nov 2013 10:00:45 +0000 Subject: i40e: add support for triggering EMPR Allow debugfs to trigger a reset called EMPR. Change-Id: I2f6600a8242759ec60c8198d03f70c2b774e0740 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 ++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 8806cab28c6a..df685bc72eca 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -130,6 +130,7 @@ enum i40e_state_t { __I40E_PF_RESET_REQUESTED, __I40E_CORE_RESET_REQUESTED, __I40E_GLOBAL_RESET_REQUESTED, + __I40E_EMP_RESET_REQUESTED, __I40E_FILTER_OVERFLOW_PROMISC, }; diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index ef4cb1cf31f2..9c675b5f1466 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1472,6 +1472,10 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, "forcing GlobR\n"); i40e_do_reset(pf, (1 << __I40E_GLOBAL_RESET_REQUESTED)); + } else if (strncmp(cmd_buf, "empr", 4) == 0) { + dev_info(&pf->pdev->dev, "forcing EMPR\n"); + i40e_do_reset(pf, (1 << __I40E_EMP_RESET_REQUESTED)); + } else if (strncmp(cmd_buf, "read", 4) == 0) { u32 address; u32 value; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d60673ebf139..5d234a13abc5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4056,6 +4056,24 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) wr32(&pf->hw, I40E_GLGEN_RTRIG, val); i40e_flush(&pf->hw); + } else if (reset_flags & (1 << __I40E_EMP_RESET_REQUESTED)) { + + /* Request a Firmware Reset + * + * Same as Global reset, plus restarting the + * embedded firmware engine. + */ + /* enable EMP Reset */ + val = rd32(&pf->hw, I40E_GLGEN_RSTENA_EMP); + val |= I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK; + wr32(&pf->hw, I40E_GLGEN_RSTENA_EMP, val); + + /* force the reset */ + val = rd32(&pf->hw, I40E_GLGEN_RTRIG); + val |= I40E_GLGEN_RTRIG_EMPFWR_MASK; + wr32(&pf->hw, I40E_GLGEN_RTRIG, val); + i40e_flush(&pf->hw); + } else if (reset_flags & (1 << __I40E_PF_RESET_REQUESTED)) { /* Request a PF Reset -- cgit v1.2.3 From b7b580a5324f5e14ede59bd094a43a9d8ce3fecf Mon Sep 17 00:00:00 2001 From: Kamil Krawczyk Date: Sat, 16 Nov 2013 10:00:46 +0000 Subject: i40e: restrict diag test length The diagnostics test needs some slightly different limits in order to succeed. Change-Id: Ia1c49148af92fa4be20778a819f69350381bf865 Signed-off-by: Kamil Krawczyk Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_diag.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c index de255143bde6..dc6c41fade9e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.c +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c @@ -68,16 +68,16 @@ static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw, struct i40e_diag_reg_test_info i40e_reg_list[] = { /* offset mask elements stride */ - {I40E_QTX_CTL(0), 0x0000FFBF, 64, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)}, + {I40E_QTX_CTL(0), 0x0000FFBF, 4, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)}, {I40E_PFINT_ITR0(0), 0x00000FFF, 3, I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)}, {I40E_PFINT_ITRN(0, 0), 0x00000FFF, 64, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)}, {I40E_PFINT_ITRN(1, 0), 0x00000FFF, 64, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)}, {I40E_PFINT_ITRN(2, 0), 0x00000FFF, 64, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)}, {I40E_PFINT_STAT_CTL0, 0x0000000C, 1, 0}, {I40E_PFINT_LNKLST0, 0x00001FFF, 1, 0}, - {I40E_PFINT_LNKLSTN(0), 0x000007FF, 511, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)}, - {I40E_QINT_TQCTL(0), 0x000000FF, I40E_QINT_TQCTL_MAX_INDEX + 1, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)}, - {I40E_QINT_RQCTL(0), 0x000000FF, I40E_QINT_RQCTL_MAX_INDEX + 1, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)}, + {I40E_PFINT_LNKLSTN(0), 0x000007FF, 64, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)}, + {I40E_QINT_TQCTL(0), 0x000000FF, 64, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)}, + {I40E_QINT_RQCTL(0), 0x000000FF, 64, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)}, {I40E_PFINT_ICR0_ENA, 0xF7F20000, 1, 0}, { 0 } }; -- cgit v1.2.3 From 91612c331070bfd4f20d7bf7dafccde8c45893ac Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Sat, 16 Nov 2013 10:00:47 +0000 Subject: i40e: sync header files with hardware Update the PCTYPE table fix fcoe HMC object sizes Change-Id: I1f12cd2653168859661e8700f929b7c65b0e21b7 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_type.h | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h index 00ff35006077..f8afbcb053c5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h +++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h @@ -113,8 +113,8 @@ enum i40e_hmc_lan_object_size { #define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512 #define I40E_HMC_OBJ_SIZE_TXQ 128 #define I40E_HMC_OBJ_SIZE_RXQ 32 -#define I40E_HMC_OBJ_SIZE_FCOE_CNTX 128 -#define I40E_HMC_OBJ_SIZE_FCOE_FILT 32 +#define I40E_HMC_OBJ_SIZE_FCOE_CNTX 64 +#define I40E_HMC_OBJ_SIZE_FCOE_FILT 64 enum i40e_hmc_lan_rsrc_type { I40E_HMC_LAN_FULL = 0, diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index f3f22b20f02f..5f81bd52e6f0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -852,10 +852,7 @@ struct i40e_filter_program_desc { /* Packet Classifier Types for filters */ enum i40e_filter_pctype { - /* Note: Value 0-25 are reserved for future use */ - I40E_FILTER_PCTYPE_IPV4_TEREDO_UDP = 26, - I40E_FILTER_PCTYPE_IPV6_TEREDO_UDP = 27, - I40E_FILTER_PCTYPE_NONF_IPV4_1588_UDP = 28, + /* Note: Values 0-28 are reserved for future use */ I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP = 29, I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP = 30, I40E_FILTER_PCTYPE_NONF_IPV4_UDP = 31, @@ -864,8 +861,7 @@ enum i40e_filter_pctype { I40E_FILTER_PCTYPE_NONF_IPV4_SCTP = 34, I40E_FILTER_PCTYPE_NONF_IPV4_OTHER = 35, I40E_FILTER_PCTYPE_FRAG_IPV4 = 36, - /* Note: Value 37 is reserved for future use */ - I40E_FILTER_PCTYPE_NONF_IPV6_1588_UDP = 38, + /* Note: Values 37-38 are reserved for future use */ I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP = 39, I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP = 40, I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41, @@ -877,7 +873,8 @@ enum i40e_filter_pctype { /* Note: Value 47 is reserved for future use */ I40E_FILTER_PCTYPE_FCOE_OX = 48, I40E_FILTER_PCTYPE_FCOE_RX = 49, - /* Note: Value 50-62 are reserved for future use */ + I40E_FILTER_PCTYPE_FCOE_OTHER = 50, + /* Note: Values 51-62 are reserved for future use */ I40E_FILTER_PCTYPE_L2_PAYLOAD = 63, }; -- cgit v1.2.3 From 7f3f5240ce64b2b59e2a9a338b4a38931724192a Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Wed, 4 Dec 2013 11:40:11 -0600 Subject: amd64_edac: Fix condition to verify max channels allowed for F15 M30h The value returned from 'f15_m30h_determine_channel' will always be 0x3 max. The condition (channel > 4 || channel < 0) works as hardware never returns a value of 4, but it leads to static checker analysis errors like http://marc.info/?l=linux-edac&m=138607615131951&w=2. Fix that. Reported-by: Dan Carpenter Signed-off-by: Aravind Gopalakrishnan Link: http://lkml.kernel.org/r/20131203130857.GA32170@elgon.mountain [ Boris: massage commit message a bit. ] Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index b53d0de17e15..e2079b2dfcb4 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1578,7 +1578,7 @@ static int f15_m30h_match_to_this_node(struct amd64_pvt *pvt, unsigned range, num_dcts_intlv, dct_sel); /* Verify we stay within the MAX number of channels allowed */ - if (channel > 4 || channel < 0) + if (channel > 3) return -EINVAL; leg_mmio_hole = (u8) (dct_cont_base_reg >> 1 & BIT(0)); -- cgit v1.2.3 From ba935f40979b32924824759111ed95d35469c5fa Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 6 Dec 2013 10:23:08 +0100 Subject: EDAC: Remove DEFINE_PCI_DEVICE_TABLE macro Currently, there is no other bus that has something like this macro for their device ids. Thus, DEFINE_PCI_DEVICE_TABLE macro should be removed. Signed-off-by: Jingoo Han Link: http://lkml.kernel.org/r/001c01ceefb3$5724d860$056e8920$%han@samsung.com [ Boris: swap commit message with better one. ] Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- drivers/edac/amd76x_edac.c | 2 +- drivers/edac/e752x_edac.c | 2 +- drivers/edac/e7xxx_edac.c | 2 +- drivers/edac/i3000_edac.c | 2 +- drivers/edac/i3200_edac.c | 2 +- drivers/edac/i5000_edac.c | 2 +- drivers/edac/i5100_edac.c | 2 +- drivers/edac/i5400_edac.c | 2 +- drivers/edac/i7300_edac.c | 2 +- drivers/edac/i7core_edac.c | 2 +- drivers/edac/i82443bxgx_edac.c | 2 +- drivers/edac/i82860_edac.c | 2 +- drivers/edac/i82875p_edac.c | 2 +- drivers/edac/i82975x_edac.c | 2 +- drivers/edac/r82600_edac.c | 2 +- drivers/edac/sb_edac.c | 2 +- drivers/edac/x38_edac.c | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e2079b2dfcb4..a2f1854891f3 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2795,7 +2795,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev) * PCI core identifies what devices are on a system during boot, and then * inquiry this table to see if this driver is for a given device found. */ -static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = { +static const struct pci_device_id amd64_pci_table[] = { { .vendor = PCI_VENDOR_ID_AMD, .device = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 96e3ee3460a5..3a501b530e11 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -333,7 +333,7 @@ static void amd76x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(amd76x_pci_tbl) = { +static const struct pci_device_id amd76x_pci_tbl[] = { { PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD762}, diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 644fec54681f..5fb01b03773a 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1421,7 +1421,7 @@ static void e752x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(e752x_pci_tbl) = { +static const struct pci_device_id e752x_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, E7520}, diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 1c4056a50383..3cda79bc8b00 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -555,7 +555,7 @@ static void e7xxx_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(e7xxx_pci_tbl) = { +static const struct pci_device_id e7xxx_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, E7205}, diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 694efcbf19c0..cd28b968e5c7 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -487,7 +487,7 @@ static void i3000_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(i3000_pci_tbl) = { +static const struct pci_device_id i3000_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 3000_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, I3000}, diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index be10a74b16ea..fa1326e5a4b0 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -466,7 +466,7 @@ static void i3200_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(i3200_pci_tbl) = { +static const struct pci_device_id i3200_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 3200_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, I3200}, diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 63b2194e8c20..72e07e3cf718 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1530,7 +1530,7 @@ static void i5000_remove_one(struct pci_dev *pdev) * * The "E500P" device is the first device supported. */ -static DEFINE_PCI_DEVICE_TABLE(i5000_pci_tbl) = { +static const struct pci_device_id i5000_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I5000_DEV16), .driver_data = I5000P}, diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 157b934e8ce3..36a38ee94fa8 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -1213,7 +1213,7 @@ static void i5100_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(i5100_pci_tbl) = { +static const struct pci_device_id i5100_pci_tbl[] = { /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) }, { 0, } diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 0a05bbceb08f..e080cbfa8fc9 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1416,7 +1416,7 @@ static void i5400_remove_one(struct pci_dev *pdev) * * The "E500P" device is the first device supported. */ -static DEFINE_PCI_DEVICE_TABLE(i5400_pci_tbl) = { +static const struct pci_device_id i5400_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)}, {0,} /* 0 terminated list. */ }; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 9004c64b169e..d63f4798f7d0 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -1160,7 +1160,7 @@ static void i7300_remove_one(struct pci_dev *pdev) * * Has only 8086:360c PCI ID */ -static DEFINE_PCI_DEVICE_TABLE(i7300_pci_tbl) = { +static const struct pci_device_id i7300_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)}, {0,} /* 0 terminated list. */ }; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 80a963d64e58..87533ca7752e 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -394,7 +394,7 @@ static const struct pci_id_table pci_dev_table[] = { /* * pci_device_id table for which devices we are looking for */ -static DEFINE_PCI_DEVICE_TABLE(i7core_pci_tbl) = { +static const struct pci_device_id i7core_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)}, {0,} /* 0 terminated list. */ diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 57fdb77903ba..d730e276d1a8 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -386,7 +386,7 @@ static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_remove_one); -static DEFINE_PCI_DEVICE_TABLE(i82443bxgx_pci_tbl) = { +static const struct pci_device_id i82443bxgx_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0)}, diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 3e3e431c8301..3382f6344e42 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -288,7 +288,7 @@ static void i82860_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(i82860_pci_tbl) = { +static const struct pci_device_id i82860_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, I82860}, diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 2f8535fc451e..80573df0a4d7 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -527,7 +527,7 @@ static void i82875p_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(i82875p_pci_tbl) = { +static const struct pci_device_id i82875p_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, I82875P}, diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 0c8d4b0eaa32..10b10521f62e 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -628,7 +628,7 @@ static void i82975x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(i82975x_pci_tbl) = { +static const struct pci_device_id i82975x_pci_tbl[] = { { PCI_VEND_DEV(INTEL, 82975_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, I82975X diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 2fd6a5490905..8f936bc7a010 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -383,7 +383,7 @@ static void r82600_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(r82600_pci_tbl) = { +static const struct pci_device_id r82600_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID) }, diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 8472405c5586..b5d254bb4913 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -461,7 +461,7 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { /* * pci_device_id table for which devices we are looking for */ -static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = { +static const struct pci_device_id sbridge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, {0,} /* 0 terminated list. */ diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 1a4df82376ba..4891b450830b 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -448,7 +448,7 @@ static void x38_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } -static DEFINE_PCI_DEVICE_TABLE(x38_pci_tbl) = { +static const struct pci_device_id x38_pci_tbl[] = { { PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, X38}, -- cgit v1.2.3 From c838cb3d477f79738ee03ede53a3f724021f3ae0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 5 Dec 2013 19:21:10 -0800 Subject: Input: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. This is a cosmetic change to make the code simpler and enhance the readability. Signed-off-by: Jingoo Han Acked-by: Fugang Duan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5520-keys.c | 2 +- drivers/input/keyboard/adp5588-keys.c | 10 ++++++---- drivers/input/keyboard/adp5589-keys.c | 8 ++++---- drivers/input/keyboard/bf54x-keys.c | 4 ++-- drivers/input/keyboard/davinci_keyscan.c | 2 +- drivers/input/keyboard/ep93xx_keypad.c | 2 +- drivers/input/keyboard/imx_keypad.c | 3 ++- drivers/input/keyboard/lm8323.c | 2 +- drivers/input/keyboard/lm8333.c | 3 ++- drivers/input/keyboard/max7359_keypad.c | 3 ++- drivers/input/keyboard/mcs_touchkey.c | 2 +- drivers/input/keyboard/mpr121_touchkey.c | 3 ++- drivers/input/keyboard/nomadik-ske-keypad.c | 3 ++- drivers/input/keyboard/omap-keypad.c | 2 +- drivers/input/keyboard/pxa930_rotary.c | 3 ++- drivers/input/keyboard/samsung-keypad.c | 2 +- drivers/input/keyboard/sh_keysc.c | 4 ++-- drivers/input/keyboard/tca6416-keypad.c | 2 +- drivers/input/keyboard/tnetv107x-keypad.c | 2 +- drivers/input/keyboard/twl4030_keypad.c | 2 +- drivers/input/keyboard/w90p910_keypad.c | 2 +- drivers/input/misc/ad714x.c | 4 ++-- drivers/input/misc/adxl34x.c | 2 +- drivers/input/misc/bfin_rotary.c | 2 +- drivers/input/misc/bma150.c | 3 ++- drivers/input/misc/cma3000_d0x.c | 2 +- drivers/input/misc/gp2ap002a00f.c | 2 +- drivers/input/misc/gpio_tilt_polled.c | 3 ++- drivers/input/misc/kxtj9.c | 3 ++- drivers/input/misc/pwm-beeper.c | 2 +- drivers/input/misc/twl4030-vibra.c | 2 +- drivers/input/mouse/gpio_mouse.c | 2 +- drivers/input/mouse/pxa930_trkball.c | 2 +- drivers/input/touchscreen/88pm860x-ts.c | 2 +- drivers/input/touchscreen/ad7877.c | 2 +- drivers/input/touchscreen/ad7879.c | 4 ++-- drivers/input/touchscreen/atmel_mxt_ts.c | 2 +- drivers/input/touchscreen/atmel_tsadcc.c | 2 +- drivers/input/touchscreen/cy8ctmg110_ts.c | 2 +- drivers/input/touchscreen/cyttsp_core.c | 4 ++-- drivers/input/touchscreen/da9034-ts.c | 2 +- drivers/input/touchscreen/edt-ft5x06.c | 2 +- drivers/input/touchscreen/eeti_ts.c | 2 +- drivers/input/touchscreen/ili210x.c | 2 +- drivers/input/touchscreen/mcs5000_ts.c | 4 ++-- drivers/input/touchscreen/pixcir_i2c_ts.c | 3 ++- drivers/input/touchscreen/s3c2410_ts.c | 4 ++-- drivers/input/touchscreen/st1232.c | 2 +- drivers/input/touchscreen/tsc2005.c | 2 +- drivers/input/touchscreen/ucb1400_ts.c | 8 ++++---- drivers/input/touchscreen/wm97xx-core.c | 2 +- 51 files changed, 79 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index ef26b17fb159..0dc1151d02fb 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -71,7 +71,7 @@ static int adp5520_keys_notifier(struct notifier_block *nb, static int adp5520_keys_probe(struct platform_device *pdev) { - struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data; + struct adp5520_keys_platform_data *pdata = dev_get_platdata(&pdev->dev); struct input_dev *input; struct adp5520_keys *dev; int ret, i; diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index dbd2047f1641..e3874d3410b4 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -173,7 +173,7 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad, static int adp5588_gpio_add(struct adp5588_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5588_kpad_platform_data *pdata = dev->platform_data; + const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; int i, error; @@ -227,7 +227,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad) static void adp5588_gpio_remove(struct adp5588_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5588_kpad_platform_data *pdata = dev->platform_data; + const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; int error; @@ -321,7 +321,8 @@ static irqreturn_t adp5588_irq(int irq, void *handle) static int adp5588_setup(struct i2c_client *client) { - const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; + const struct adp5588_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; int i, ret; unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; @@ -424,7 +425,8 @@ static int adp5588_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adp5588_kpad *kpad; - const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; + const struct adp5588_kpad_platform_data *pdata = + dev_get_platdata(&client->dev); struct input_dev *input; unsigned int revid; int ret, i; diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 67d12b3427c9..e43efa03f3e7 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -499,7 +499,7 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, static int adp5589_gpio_add(struct adp5589_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev->platform_data; + const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; int i, error; @@ -553,7 +553,7 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad) static void adp5589_gpio_remove(struct adp5589_kpad *kpad) { struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev->platform_data; + const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; int error; @@ -658,7 +658,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad) { struct i2c_client *client = kpad->client; const struct adp5589_kpad_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); u8 (*reg) (u8) = kpad->var->reg; unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; unsigned char pull_mask = 0; @@ -864,7 +864,7 @@ static int adp5589_probe(struct i2c_client *client, { struct adp5589_kpad *kpad; const struct adp5589_kpad_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct input_dev *input; unsigned int revid; int ret, i; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index fc88fb48d70d..16fa3400d86a 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -180,7 +180,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) static int bfin_kpad_probe(struct platform_device *pdev) { struct bf54x_kpad *bf54x_kpad; - struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; + struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); struct input_dev *input; int i, error; @@ -332,7 +332,7 @@ out: static int bfin_kpad_remove(struct platform_device *pdev) { - struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; + struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); del_timer_sync(&bf54x_kpad->timer); diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index d15977a8361e..1559dc1cf951 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -172,7 +172,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev) struct input_dev *key_dev; struct resource *res, *mem; struct device *dev = &pdev->dev; - struct davinci_ks_platform_data *pdata = pdev->dev.platform_data; + struct davinci_ks_platform_data *pdata = dev_get_platdata(&pdev->dev); int error, i; if (pdata->device_enable) { diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 47206bdba411..e59876212b8c 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -244,7 +244,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) if (!keypad) return -ENOMEM; - keypad->pdata = pdev->dev.platform_data; + keypad->pdata = dev_get_platdata(&pdev->dev); if (!keypad->pdata) { err = -EINVAL; goto failed_free; diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 328cfc1eed95..34bb35895268 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -425,7 +425,8 @@ MODULE_DEVICE_TABLE(of, imx_keypad_of_match); static int imx_keypad_probe(struct platform_device *pdev) { - const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data; + const struct matrix_keymap_data *keymap_data = + dev_get_platdata(&pdev->dev); struct imx_keypad *keypad; struct input_dev *input_dev; struct resource *res; diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 0de23f41b2d3..0b42118cbf8f 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -627,7 +627,7 @@ static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable); static int lm8323_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct lm8323_platform_data *pdata = client->dev.platform_data; + struct lm8323_platform_data *pdata = dev_get_platdata(&client->dev); struct input_dev *idev; struct lm8323_chip *lm; int pwm; diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 5a8ca35dc9af..9081cbef11ea 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -131,7 +131,8 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data) static int lm8333_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct lm8333_platform_data *pdata = client->dev.platform_data; + const struct lm8333_platform_data *pdata = + dev_get_platdata(&client->dev); struct lm8333 *lm8333; struct input_dev *input; int err, active_time; diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index bc2cdaf563fd..430b54539720 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -182,7 +182,8 @@ static void max7359_initialize(struct i2c_client *client) static int max7359_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct matrix_keymap_data *keymap_data = client->dev.platform_data; + const struct matrix_keymap_data *keymap_data = + dev_get_platdata(&client->dev); struct max7359_keypad *keypad; struct input_dev *input_dev; int ret; diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 7c236f9c6a51..5ec77523e040 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -108,7 +108,7 @@ static int mcs_touchkey_probe(struct i2c_client *client, int error; int i; - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata) { dev_err(&client->dev, "no platform data defined\n"); return -EINVAL; diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index f7f3e9a9fd3f..98b8467aa6c9 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -188,7 +188,8 @@ err_i2c_write: static int mpr_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct mpr121_platform_data *pdata = client->dev.platform_data; + const struct mpr121_platform_data *pdata = + dev_get_platdata(&client->dev); struct mpr121_touchkey *mpr121; struct input_dev *input_dev; int error; diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index c7d505cce72f..63332e2f8628 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -222,7 +222,8 @@ static irqreturn_t ske_keypad_irq(int irq, void *dev_id) static int __init ske_keypad_probe(struct platform_device *pdev) { - const struct ske_keypad_platform_data *plat = pdev->dev.platform_data; + const struct ske_keypad_platform_data *plat = + dev_get_platdata(&pdev->dev); struct ske_keypad *keypad; struct input_dev *input; struct resource *res; diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index d0d5226d9cd4..e80bb9743356 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -248,7 +248,7 @@ static int omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; struct input_dev *input_dev; - struct omap_kp_platform_data *pdata = pdev->dev.platform_data; + struct omap_kp_platform_data *pdata = dev_get_platdata(&pdev->dev); int i, col_idx, row_idx, ret; unsigned int row_shift, keycodemax; diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index 248cdcf95296..367b03ab92a2 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -84,7 +84,8 @@ static void pxa930_rotary_close(struct input_dev *dev) static int pxa930_rotary_probe(struct platform_device *pdev) { - struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data; + struct pxa930_rotary_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct pxa930_rotary *r; struct input_dev *input_dev; struct resource *res; diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index ac43a486c775..9ac8a1e0c08e 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -321,7 +321,7 @@ static int samsung_keypad_probe(struct platform_device *pdev) if (pdev->dev.of_node) pdata = samsung_keypad_parse_dt(&pdev->dev); else - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "no platform data defined\n"); return -EINVAL; diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index fe0e498d2479..d65a98b1d7dd 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -171,7 +171,7 @@ static int sh_keysc_probe(struct platform_device *pdev) int i; int irq, error; - if (!pdev->dev.platform_data) { + if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "no platform data defined\n"); error = -EINVAL; goto err0; @@ -198,7 +198,7 @@ static int sh_keysc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, priv); - memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); + memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata)); pdata = &priv->pdata; priv->iomem_base = ioremap_nocache(res->start, resource_size(res)); diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index bfc832c35a7c..dc983ab6c0ad 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -213,7 +213,7 @@ static int tca6416_keypad_probe(struct i2c_client *client, return -ENODEV; } - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata) { dev_dbg(&client->dev, "no platform data\n"); return -EINVAL; diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index 8bd24d52bf1b..086511c2121b 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -162,7 +162,7 @@ static int keypad_probe(struct platform_device *pdev) int error = 0, sz, row_shift; u32 rev = 0; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(dev, "cannot find device data\n"); return -EINVAL; diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index d2d178c84ea7..8bc2879b4c87 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -330,7 +330,7 @@ static int twl4030_kp_program(struct twl4030_keypad *kp) */ static int twl4030_kp_probe(struct platform_device *pdev) { - struct twl4030_keypad_data *pdata = pdev->dev.platform_data; + struct twl4030_keypad_data *pdata = dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct twl4030_keypad *kp; struct input_dev *input; diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 7b039162a3f8..e03614f20d3b 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -121,7 +121,7 @@ static void w90p910_keypad_close(struct input_dev *dev) static int w90p910_keypad_probe(struct platform_device *pdev) { const struct w90p910_keypad_platform_data *pdata = - pdev->dev.platform_data; + dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct w90p910_keypad *keypad; struct input_dev *input_dev; diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 2e5d5e1de647..6deecdd3d11b 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -969,7 +969,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, int error; struct input_dev *input[MAX_DEVICE_NUM]; - struct ad714x_platform_data *plat_data = dev->platform_data; + struct ad714x_platform_data *plat_data = dev_get_platdata(dev); struct ad714x_chip *ad714x; void *drv_mem; unsigned long irqflags; @@ -986,7 +986,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, goto err_out; } - if (dev->platform_data == NULL) { + if (dev_get_platdata(dev) == NULL) { dev_err(dev, "platform data for ad714x doesn't exist\n"); error = -EINVAL; goto err_out; diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 0735de3a6468..d2049972f70a 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -714,7 +714,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ac->fifo_delay = fifo_delay_default; - pdata = dev->platform_data; + pdata = dev_get_platdata(dev); if (!pdata) { dev_dbg(dev, "No platform data: Using default initialization\n"); diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index cd139cb17e32..7703447d1fd9 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -92,7 +92,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) static int bfin_rotary_probe(struct platform_device *pdev) { - struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; + struct bfin_rotary_platform_data *pdata = dev_get_platdata(&pdev->dev); struct bfin_rot *rotary; struct input_dev *input; int error; diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 865c2f9d25b9..52d3a9b28f0b 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -526,7 +526,8 @@ static int bma150_register_polled_device(struct bma150_data *bma150) static int bma150_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct bma150_platform_data *pdata = client->dev.platform_data; + const struct bma150_platform_data *pdata = + dev_get_platdata(&client->dev); const struct bma150_cfg *cfg; struct bma150_data *bma150; int chip_id; diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index df9b756594f8..c7d00748277b 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -284,7 +284,7 @@ EXPORT_SYMBOL(cma3000_resume); struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, const struct cma3000_bus_ops *bops) { - const struct cma3000_platform_data *pdata = dev->platform_data; + const struct cma3000_platform_data *pdata = dev_get_platdata(dev); struct cma3000_accl_data *data; struct input_dev *input_dev; int rev; diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c index fe30bd0fe4bd..de21e317da32 100644 --- a/drivers/input/misc/gp2ap002a00f.c +++ b/drivers/input/misc/gp2ap002a00f.c @@ -125,7 +125,7 @@ static int gp2a_initialize(struct gp2a_data *dt) static int gp2a_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct gp2a_platform_data *pdata = client->dev.platform_data; + const struct gp2a_platform_data *pdata = dev_get_platdata(&client->dev); struct gp2a_data *dt; int error; diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c index 714c68369134..38b3c11a8ae9 100644 --- a/drivers/input/misc/gpio_tilt_polled.c +++ b/drivers/input/misc/gpio_tilt_polled.c @@ -98,7 +98,8 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev) static int gpio_tilt_polled_probe(struct platform_device *pdev) { - const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data; + const struct gpio_tilt_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct gpio_tilt_polled_dev *tdev; struct input_polled_dev *poll_dev; diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index a993b67a8a5b..d708478bc5b5 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -509,7 +509,8 @@ out: static int kxtj9_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct kxtj9_platform_data *pdata = client->dev.platform_data; + const struct kxtj9_platform_data *pdata = + dev_get_platdata(&client->dev); struct kxtj9_data *tj9; int err; diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 940566e7be13..8ef288e7c971 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -68,7 +68,7 @@ static int pwm_beeper_event(struct input_dev *input, static int pwm_beeper_probe(struct platform_device *pdev) { - unsigned long pwm_id = (unsigned long)pdev->dev.platform_data; + unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev); struct pwm_beeper *beeper; int error; diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 68a5f33152a8..d993775a7c39 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -193,7 +193,7 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, static int twl4030_vibra_probe(struct platform_device *pdev) { - struct twl4030_vibra_data *pdata = pdev->dev.platform_data; + struct twl4030_vibra_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *twl4030_core_node = pdev->dev.parent->of_node; struct vibra_info *info; int ret; diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 6b44413f54e3..6810a4626a2a 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -48,7 +48,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) static int gpio_mouse_probe(struct platform_device *pdev) { - struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; + struct gpio_mouse_platform_data *pdata = dev_get_platdata(&pdev->dev); struct input_polled_dev *input_poll; struct input_dev *input; int pin, i; diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 0ecb9e7945eb..d20d2ae5f1ee 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -166,7 +166,7 @@ static int pxa930_trkball_probe(struct platform_device *pdev) if (!trkball) return -ENOMEM; - trkball->pdata = pdev->dev.platform_data; + trkball->pdata = dev_get_platdata(&pdev->dev); if (!trkball->pdata) { dev_err(&pdev->dev, "no platform data defined\n"); error = -EINVAL; diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index f7de14a268bf..544e20c551f8 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -172,7 +172,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, static int pm860x_touch_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_touch_pdata *pdata = pdev->dev.platform_data; + struct pm860x_touch_pdata *pdata = dev_get_platdata(&pdev->dev); struct pm860x_touch *touch; struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ : chip->companion; diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 69834dd3c313..b9f9bcb22683 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -686,7 +686,7 @@ static int ad7877_probe(struct spi_device *spi) { struct ad7877 *ts; struct input_dev *input_dev; - struct ad7877_platform_data *pdata = spi->dev.platform_data; + struct ad7877_platform_data *pdata = dev_get_platdata(&spi->dev); int err; u16 verify; diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index facd3057b62d..a0364d8ae6c6 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -470,7 +470,7 @@ static int ad7879_gpio_add(struct ad7879 *ts, static void ad7879_gpio_remove(struct ad7879 *ts) { - const struct ad7879_platform_data *pdata = ts->dev->platform_data; + const struct ad7879_platform_data *pdata = dev_get_platdata(ts->dev); int ret; if (pdata->gpio_export) { @@ -495,7 +495,7 @@ static inline void ad7879_gpio_remove(struct ad7879 *ts) struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, const struct ad7879_bus_ops *bops) { - struct ad7879_platform_data *pdata = dev->platform_data; + struct ad7879_platform_data *pdata = dev_get_platdata(dev); struct ad7879 *ts; struct input_dev *input_dev; int err; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 59aa24002c7b..37ea05741d20 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1130,7 +1130,7 @@ static void mxt_input_close(struct input_dev *dev) static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct mxt_platform_data *pdata = client->dev.platform_data; + const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev); struct mxt_data *data; struct input_dev *input_dev; int error; diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index bddabc595077..f7d1ea5849ba 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -182,7 +182,7 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) struct atmel_tsadcc *ts_dev; struct input_dev *input_dev; struct resource *res; - struct at91_tsadcc_data *pdata = pdev->dev.platform_data; + struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev); int err; unsigned int prsc; unsigned int reg; diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 8c651985a5c4..5bf1aeeea825 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -178,7 +178,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) static int cy8ctmg110_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct cy8ctmg110_pdata *pdata = client->dev.platform_data; + const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev); struct cy8ctmg110 *ts; struct input_dev *input_dev; int err; diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index d53e0b72a407..56088eceacdc 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -534,7 +534,7 @@ static void cyttsp_close(struct input_dev *dev) struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { - const struct cyttsp_platform_data *pdata = dev->platform_data; + const struct cyttsp_platform_data *pdata = dev_get_platdata(dev); struct cyttsp *ts; struct input_dev *input_dev; int error; @@ -553,7 +553,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->dev = dev; ts->input = input_dev; - ts->pdata = dev->platform_data; + ts->pdata = dev_get_platdata(dev); ts->bus_ops = bus_ops; ts->irq = irq; diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 34ad84105e6e..ea0f7645220f 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c @@ -299,7 +299,7 @@ static void da9034_touch_close(struct input_dev *dev) static int da9034_touch_probe(struct platform_device *pdev) { - struct da9034_touch_pdata *pdata = pdev->dev.platform_data; + struct da9034_touch_pdata *pdata = dev_get_platdata(&pdev->dev); struct da9034_touch *touch; struct input_dev *input_dev; int ret; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 83fa1b15a97f..af0d68b703b7 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -705,7 +705,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct edt_ft5x06_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct edt_ft5x06_ts_data *tsdata; struct input_dev *input; int error; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 1ce3d29ffca5..b1884ddd7a84 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev) static int eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata = client->dev.platform_data; + struct eeti_ts_platform_data *pdata = dev_get_platdata(&client->dev); struct eeti_ts_priv *priv; struct input_dev *input; unsigned int irq_flags; diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 1418bdda61bb..2a5089139818 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -184,7 +184,7 @@ static int ili210x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; - const struct ili210x_platform_data *pdata = dev->platform_data; + const struct ili210x_platform_data *pdata = dev_get_platdata(dev); struct ili210x *priv; struct input_dev *input; struct panel_info panel; diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index f9f4e0c56eda..58486f135a4c 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -194,7 +194,7 @@ static int mcs5000_ts_probe(struct i2c_client *client, struct input_dev *input_dev; int ret; - if (!client->dev.platform_data) + if (!dev_get_platdata(&client->dev)) return -EINVAL; data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL); @@ -207,7 +207,7 @@ static int mcs5000_ts_probe(struct i2c_client *client, data->client = client; data->input_dev = input_dev; - data->platform_data = client->dev.platform_data; + data->platform_data = dev_get_platdata(&client->dev); input_dev->name = "MELPAS MCS-5000 Touchscreen"; input_dev->id.bustype = BUS_I2C; diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 6cc6b36663ff..02392d2061d6 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -128,7 +128,8 @@ static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, static int pixcir_i2c_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct pixcir_ts_platform_data *pdata = client->dev.platform_data; + const struct pixcir_ts_platform_data *pdata = + dev_get_platdata(&client->dev); struct pixcir_i2c_ts_data *tsdata; struct input_dev *input; int error; diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index b061af2c8376..d32bd9e6d215 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -251,7 +251,7 @@ static int s3c2410ts_probe(struct platform_device *pdev) ts.dev = dev; - info = pdev->dev.platform_data; + info = dev_get_platdata(&pdev->dev); if (!info) { dev_err(dev, "no platform data, cannot attach\n"); return -EINVAL; @@ -392,7 +392,7 @@ static int s3c2410ts_suspend(struct device *dev) static int s3c2410ts_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - struct s3c2410_ts_mach_info *info = pdev->dev.platform_data; + struct s3c2410_ts_mach_info *info = dev_get_platdata(&pdev->dev); clk_enable(ts.clock); enable_irq(ts.irq_tc); diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 2f03b2f289dd..5c342b3139e8 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -154,7 +154,7 @@ static int st1232_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct st1232_ts_data *ts; - struct st1232_pdata *pdata = client->dev.platform_data; + struct st1232_pdata *pdata = dev_get_platdata(&client->dev); struct input_dev *input_dev; int error; diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 811353353917..550adcbbfc23 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -571,7 +571,7 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) static int tsc2005_probe(struct spi_device *spi) { - const struct tsc2005_platform_data *pdata = spi->dev.platform_data; + const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev); struct tsc2005 *ts; struct input_dev *input_dev; unsigned int max_x, max_y, max_p; diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 1271f97b4079..5b3ca807d179 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -320,7 +320,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, static int ucb1400_ts_probe(struct platform_device *pdev) { - struct ucb1400_ts *ucb = pdev->dev.platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(&pdev->dev); int error, x_res, y_res; u16 fcsr; @@ -399,7 +399,7 @@ err: static int ucb1400_ts_remove(struct platform_device *pdev) { - struct ucb1400_ts *ucb = pdev->dev.platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(&pdev->dev); free_irq(ucb->irq, ucb); input_unregister_device(ucb->ts_idev); @@ -410,7 +410,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int ucb1400_ts_suspend(struct device *dev) { - struct ucb1400_ts *ucb = dev->platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(dev); struct input_dev *idev = ucb->ts_idev; mutex_lock(&idev->mutex); @@ -424,7 +424,7 @@ static int ucb1400_ts_suspend(struct device *dev) static int ucb1400_ts_resume(struct device *dev) { - struct ucb1400_ts *ucb = dev->platform_data; + struct ucb1400_ts *ucb = dev_get_platdata(dev); struct input_dev *idev = ucb->ts_idev; mutex_lock(&idev->mutex); diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 7e45c9f6e6b7..d0ef91fc87d1 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -584,7 +584,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev) static int wm97xx_probe(struct device *dev) { struct wm97xx *wm; - struct wm97xx_pdata *pdata = dev->platform_data; + struct wm97xx_pdata *pdata = dev_get_platdata(dev); int ret = 0, id = 0; wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL); -- cgit v1.2.3 From f742a55231b950ed71ac8cc8beec0944ddda312c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 6 Dec 2013 10:17:53 +0100 Subject: drm/i915: fix pm init ordering Shovel a bit more of the the code into the setup function, and call it earlier. Otherwise lockdep is unhappy since we cancel the delayed resume work before it's initialized. While at it also shovel the pc8 setup code into the same functions. I wanted to also ditch the header declaration of the hws pc8 functions, but for unfathomable reasons that stuff is in intel_display.c instead of intel_pm.c. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71980 Tested-by: Guo Jinxian Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 10 +--------- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 11 ++++++++++- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ac9dac99b585..197db0993a24 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1490,16 +1490,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->uncore.lock); spin_lock_init(&dev_priv->mm.object_stat_lock); mutex_init(&dev_priv->dpio_lock); - mutex_init(&dev_priv->rps.hw_lock); mutex_init(&dev_priv->modeset_restore_lock); - mutex_init(&dev_priv->pc8.lock); - dev_priv->pc8.requirements_met = false; - dev_priv->pc8.gpu_idle = false; - dev_priv->pc8.irqs_disabled = false; - dev_priv->pc8.enabled = false; - dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ - INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); + intel_pm_setup(dev); intel_display_crc_init(dev); @@ -1603,7 +1596,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } intel_irq_init(dev); - intel_pm_init(dev); intel_uncore_sanitize(dev); /* Try to make sure MCHBAR is enabled before poking at it */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccdbecca070d..6f04fa4b31fd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1901,9 +1901,7 @@ void i915_queue_hangcheck(struct drm_device *dev); void i915_handle_error(struct drm_device *dev, bool wedged); extern void intel_irq_init(struct drm_device *dev); -extern void intel_pm_init(struct drm_device *dev); extern void intel_hpd_init(struct drm_device *dev); -extern void intel_pm_init(struct drm_device *dev); extern void intel_uncore_sanitize(struct drm_device *dev); extern void intel_uncore_early_sanitize(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a18e88b3e425..79f91f26e288 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -821,6 +821,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane, uint32_t sprite_width, int pixel_size, bool enabled, bool scaled); void intel_init_pm(struct drm_device *dev); +void intel_pm_setup(struct drm_device *dev); bool intel_fbc_enabled(struct drm_device *dev); void intel_update_fbc(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6e0d5e075b15..e0dec95c764e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6130,10 +6130,19 @@ int vlv_freq_opcode(int ddr_freq, int val) return val; } -void intel_pm_init(struct drm_device *dev) +void intel_pm_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + mutex_init(&dev_priv->rps.hw_lock); + + mutex_init(&dev_priv->pc8.lock); + dev_priv->pc8.requirements_met = false; + dev_priv->pc8.gpu_idle = false; + dev_priv->pc8.irqs_disabled = false; + dev_priv->pc8.enabled = false; + dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ + INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); } -- cgit v1.2.3 From acc240d41ea1ab9c488a79219fb313b5b46265ae Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 5 Dec 2013 15:42:34 +0100 Subject: drm/i915: Fix use-after-free in do_switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So apparently under ridiculous amounts of memory pressure we can get into trouble in do_switch when we try to move the old hw context backing storage object onto the active lists. With list debugging enabled that usually results in us chasing a poisoned pointer - which means we've hit upon a vma that has been removed from all lrus with list_del (and then deallocated, so it's a real use-after free). Ian Lister has done some great callchain chasing and noticed that we can reenter do_switch: i915_gem_do_execbuffer() i915_switch_context() do_switch() from = ring->last_context; i915_gem_object_pin() i915_gem_object_bind_to_gtt() ret = drm_mm_insert_node_in_range_generic(); // If the above call fails then it will try i915_gem_evict_something() // If that fails it will call i915_gem_evict_everything() ... i915_gem_evict_everything() i915_gpu_idle() i915_switch_context(DEFAULT_CONTEXT) Like with everything else where the shrinker or eviction code can invalidate pointers we need to reload relevant state. Note that there's no need to recheck whether a context switch is still required because: - Doing a switch to the same context is harmless (besides wasting a bit of energy). - This can only happen with the default context. But since that one's pinned we'll never call down into evict_everything under normal circumstances. Note that there's a little driver bringup fun involved namely that we could recourse into do_switch for the initial switch. Atm we're fine since we assign the context pointer only after the call to do_switch at driver load or resume time. And in the gpu reset case we skip the entire setup sequence (which might be a bug on its own, but definitely not this one here). Cc'ing stable since apparently ChromeOS guys are seeing this in the wild (and not just on artificial stress tests), see the reference. Note that in upstream code doesn't calle evict_everything directly from evict_something, that's an extension in this product branch. But we can still hit upon this bug (and apparently we do, see the linked backtraces). I've noticed this while trying to construct a testcase for this bug and utterly failed to provoke it. It looks like we need to driver the system squarly into the lowmem wall and provoke the shrinker to evict the context object by doing the last-ditch evict_everything call. Aside: There's currently no means to get a badly-fragmenting hw context object away from a bad spot in the upstream code. We should fix this by at least adding some code to evict_something to handle hw contexts. References: https://code.google.com/p/chromium/issues/detail?id=248191 Reported-by: Ian Lister Cc: Ian Lister Cc: stable@vger.kernel.org Cc: Ben Widawsky Cc: Stéphane Marchesin Cc: Bloomfield, Jon Tested-by: Rafael Barbalho Reviewed-by: Ian Lister Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 4a05956162c1..b0f42b9ca037 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -421,11 +421,21 @@ static int do_switch(struct i915_hw_context *to) if (ret) return ret; - /* Clear this page out of any CPU caches for coherent swap-in/out. Note + /* + * Pin can switch back to the default context if we end up calling into + * evict_everything - as a last ditch gtt defrag effort that also + * switches to the default context. Hence we need to reload from here. + */ + from = ring->last_context; + + /* + * Clear this page out of any CPU caches for coherent swap-in/out. Note * that thanks to write = false in this call and us not setting any gpu * write domains when putting a context object onto the active list * (when switching away from it), this won't block. - * XXX: We need a real interface to do this instead of trickery. */ + * + * XXX: We need a real interface to do this instead of trickery. + */ ret = i915_gem_object_set_to_gtt_domain(to->obj, false); if (ret) { i915_gem_object_unpin(to->obj); -- cgit v1.2.3 From 9eb9d3150bd941be2f2e370e0081736d9d51e31b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Dec 2013 19:09:55 +0000 Subject: regulator: gpio: Warn if an invalid regulator-type is supplied Reported-by: Laurent Pinchart Acked-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index cdb9d947d914..49fe20f58d2a 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -210,6 +210,9 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) config->type = REGULATOR_VOLTAGE; else if (!strncmp("current", regtype, 7)) config->type = REGULATOR_CURRENT; + else + dev_warn(dev, "Unknown regulator-type '%s'\n", + regtype); } return config; -- cgit v1.2.3 From f365be0925729508fd8e62f8bdb504ef896cb6e0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 5 Dec 2013 18:10:03 -0800 Subject: pinctrl: Add Qualcomm TLMM driver This adds a pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block. Signed-off-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 6 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-msm.c | 1028 +++++++++++++++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-msm.h | 122 +++++ 4 files changed, 1157 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-msm.c create mode 100644 drivers/pinctrl/pinctrl-msm.h (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 5e4418f4282b..f5a7d7c0c1ee 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -203,6 +203,12 @@ config PINCTRL_IMX28 bool select PINCTRL_MXS +config PINCTRL_MSM + bool + select PINMUX + select PINCONF + select GENERIC_PINCONF + config PINCTRL_NOMADIK bool "Nomadik pin controller driver" depends on ARCH_U8500 || ARCH_NOMADIK diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index dcb01a4ef653..4eed91ff0676 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o +obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c new file mode 100644 index 000000000000..28b90aba708d --- /dev/null +++ b/drivers/pinctrl/pinctrl-msm.c @@ -0,0 +1,1028 @@ +/* + * Copyright (c) 2013, Sony Mobile Communications AB. + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-msm.h" +#include "pinctrl-utils.h" + +/** + * struct msm_pinctrl - state for a pinctrl-msm device + * @dev: device handle. + * @pctrl: pinctrl handle. + * @domain: irqdomain handle. + * @chip: gpiochip handle. + * @irq: parent irq for the TLMM irq_chip. + * @lock: Spinlock to protect register resources as well + * as msm_pinctrl data structures. + * @enabled_irqs: Bitmap of currently enabled irqs. + * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge + * detection. + * @wake_irqs: Bitmap of irqs with requested as wakeup source. + * @soc; Reference to soc_data of platform specific data. + * @regs: Base address for the TLMM register map. + */ +struct msm_pinctrl { + struct device *dev; + struct pinctrl_dev *pctrl; + struct irq_domain *domain; + struct gpio_chip chip; + unsigned irq; + + spinlock_t lock; + + unsigned long *enabled_irqs; + unsigned long *dual_edge_irqs; + unsigned long *wake_irqs; + + const struct msm_pinctrl_soc_data *soc; + void __iomem *regs; +}; + +static int msm_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->ngroups; +} + +static const char *msm_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->groups[group].name; +} + +static int msm_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + *pins = pctrl->soc->groups[group].pins; + *num_pins = pctrl->soc->groups[group].npins; + return 0; +} + +static struct pinctrl_ops msm_pinctrl_ops = { + .get_groups_count = msm_get_groups_count, + .get_group_name = msm_get_group_name, + .get_group_pins = msm_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, + .dt_free_map = pinctrl_utils_dt_free_map, +}; + +static int msm_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->nfunctions; +} + +static const char *msm_get_function_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->functions[function].name; +} + +static int msm_get_function_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctrl->soc->functions[function].groups; + *num_groups = pctrl->soc->functions[function].ngroups; + return 0; +} + +static int msm_pinmux_enable(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct msm_pingroup *g; + unsigned long flags; + u32 val; + int i; + + g = &pctrl->soc->groups[group]; + + if (WARN_ON(g->mux_bit < 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { + if (g->funcs[i] == function) + break; + } + + if (WARN_ON(i == ARRAY_SIZE(g->funcs))) + return -EINVAL; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->ctl_reg); + val &= ~(0x7 << g->mux_bit); + val |= i << g->mux_bit; + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static void msm_pinmux_disable(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct msm_pingroup *g; + unsigned long flags; + u32 val; + + g = &pctrl->soc->groups[group]; + + if (WARN_ON(g->mux_bit < 0)) + return; + + spin_lock_irqsave(&pctrl->lock, flags); + + /* Clear the mux bits to select gpio mode */ + val = readl(pctrl->regs + g->ctl_reg); + val &= ~(0x7 << g->mux_bit); + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static struct pinmux_ops msm_pinmux_ops = { + .get_functions_count = msm_get_functions_count, + .get_function_name = msm_get_function_name, + .get_function_groups = msm_get_function_groups, + .enable = msm_pinmux_enable, + .disable = msm_pinmux_disable, +}; + +static int msm_config_reg(struct msm_pinctrl *pctrl, + const struct msm_pingroup *g, + unsigned param, + unsigned *reg, + unsigned *mask, + unsigned *bit) +{ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + *reg = g->ctl_reg; + *bit = g->pull_bit; + *mask = 3; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + *reg = g->ctl_reg; + *bit = g->pull_bit; + *mask = 3; + break; + case PIN_CONFIG_BIAS_PULL_UP: + *reg = g->ctl_reg; + *bit = g->pull_bit; + *mask = 3; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + *reg = g->ctl_reg; + *bit = g->drv_bit; + *mask = 7; + break; + default: + dev_err(pctrl->dev, "Invalid config param %04x\n", param); + return -ENOTSUPP; + } + + if (*reg < 0) { + dev_err(pctrl->dev, "Config param %04x not supported on group %s\n", + param, g->name); + return -ENOTSUPP; + } + + return 0; +} + +static int msm_config_get(struct pinctrl_dev *pctldev, + unsigned int pin, + unsigned long *config) +{ + dev_err(pctldev->dev, "pin_config_set op not supported\n"); + return -ENOTSUPP; +} + +static int msm_config_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned num_configs) +{ + dev_err(pctldev->dev, "pin_config_set op not supported\n"); + return -ENOTSUPP; +} + +#define MSM_NO_PULL 0 +#define MSM_PULL_DOWN 1 +#define MSM_PULL_UP 3 + +static const unsigned msm_regval_to_drive[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; +static const unsigned msm_drive_to_regval[] = { -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, 7 }; + +static int msm_config_group_get(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *config) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + unsigned param = pinconf_to_config_param(*config); + unsigned mask; + unsigned arg; + unsigned bit; + unsigned reg; + int ret; + u32 val; + + g = &pctrl->soc->groups[group]; + + ret = msm_config_reg(pctrl, g, param, ®, &mask, &bit); + if (ret < 0) + return ret; + + val = readl(pctrl->regs + reg); + arg = (val >> bit) & mask; + + /* Convert register value to pinconf value */ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + arg = arg == MSM_NO_PULL; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = arg == MSM_PULL_DOWN; + break; + case PIN_CONFIG_BIAS_PULL_UP: + arg = arg == MSM_PULL_UP; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = msm_regval_to_drive[arg]; + break; + default: + dev_err(pctrl->dev, "Unsupported config parameter: %x\n", + param); + return -EINVAL; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int msm_config_group_set(struct pinctrl_dev *pctldev, + unsigned group, + unsigned long *configs, + unsigned num_configs) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + unsigned long flags; + unsigned param; + unsigned mask; + unsigned arg; + unsigned bit; + unsigned reg; + int ret; + u32 val; + int i; + + g = &pctrl->soc->groups[group]; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + ret = msm_config_reg(pctrl, g, param, ®, &mask, &bit); + if (ret < 0) + return ret; + + /* Convert pinconf values to register values */ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + arg = MSM_NO_PULL; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = MSM_PULL_DOWN; + break; + case PIN_CONFIG_BIAS_PULL_UP: + arg = MSM_PULL_UP; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + /* Check for invalid values */ + if (arg > ARRAY_SIZE(msm_drive_to_regval)) + arg = -1; + else + arg = msm_drive_to_regval[arg]; + break; + default: + dev_err(pctrl->dev, "Unsupported config parameter: %x\n", + param); + return -EINVAL; + } + + /* Range-check user-supplied value */ + if (arg & ~mask) { + dev_err(pctrl->dev, "config %x: %x is invalid\n", param, arg); + return -EINVAL; + } + + spin_lock_irqsave(&pctrl->lock, flags); + val = readl(pctrl->regs + reg); + val &= ~(mask << bit); + val |= arg << bit; + writel(val, pctrl->regs + reg); + spin_unlock_irqrestore(&pctrl->lock, flags); + } + + return 0; +} + +static struct pinconf_ops msm_pinconf_ops = { + .pin_config_get = msm_config_get, + .pin_config_set = msm_config_set, + .pin_config_group_get = msm_config_group_get, + .pin_config_group_set = msm_config_group_set, +}; + +static struct pinctrl_desc msm_pinctrl_desc = { + .pctlops = &msm_pinctrl_ops, + .pmxops = &msm_pinmux_ops, + .confops = &msm_pinconf_ops, + .owner = THIS_MODULE, +}; + +static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned long flags; + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[offset]; + + if (WARN_ON(g->oe_bit < 0)) + return -EINVAL; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->ctl_reg); + val &= ~BIT(g->oe_bit); + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned long flags; + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[offset]; + + if (WARN_ON(g->oe_bit < 0)) + return -EINVAL; + + spin_lock_irqsave(&pctrl->lock, flags); + + writel(value ? BIT(g->out_bit) : 0, pctrl->regs + g->io_reg); + + val = readl(pctrl->regs + g->ctl_reg); + val |= BIT(g->oe_bit); + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[offset]; + + val = readl(pctrl->regs + g->io_reg); + return !!(val & BIT(g->in_bit)); +} + +static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned long flags; + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[offset]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->io_reg); + val |= BIT(g->out_bit); + writel(val, pctrl->regs + g->io_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + + return irq_find_mapping(pctrl->domain, offset); +} + +static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + return pinctrl_request_gpio(gpio); +} + +static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + return pinctrl_free_gpio(gpio); +} + +#ifdef CONFIG_DEBUG_FS +#include + +static void msm_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, + struct gpio_chip *chip, + unsigned offset, + unsigned gpio) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned func; + int is_out; + int drive; + int pull; + u32 ctl_reg; + + const char *pulls[] = { + "no pull", + "pull down", + "keeper", + "pull up" + }; + + g = &pctrl->soc->groups[offset]; + ctl_reg = readl(pctrl->regs + g->ctl_reg); + + is_out = !!(ctl_reg & BIT(g->oe_bit)); + func = (ctl_reg >> g->mux_bit) & 7; + drive = (ctl_reg >> g->drv_bit) & 7; + pull = (ctl_reg >> g->pull_bit) & 3; + + seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func); + seq_printf(s, " %dmA", msm_regval_to_drive[drive]); + seq_printf(s, " %s", pulls[pull]); +} + +static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + unsigned gpio = chip->base; + unsigned i; + + for (i = 0; i < chip->ngpio; i++, gpio++) { + msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); + seq_printf(s, "\n"); + } +} + +#else +#define msm_gpio_dbg_show NULL +#endif + +static struct gpio_chip msm_gpio_template = { + .direction_input = msm_gpio_direction_input, + .direction_output = msm_gpio_direction_output, + .get = msm_gpio_get, + .set = msm_gpio_set, + .to_irq = msm_gpio_to_irq, + .request = msm_gpio_request, + .free = msm_gpio_free, + .dbg_show = msm_gpio_dbg_show, +}; + +/* For dual-edge interrupts in software, since some hardware has no + * such support: + * + * At appropriate moments, this function may be called to flip the polarity + * settings of both-edge irq lines to try and catch the next edge. + * + * The attempt is considered successful if: + * - the status bit goes high, indicating that an edge was caught, or + * - the input value of the gpio doesn't change during the attempt. + * If the value changes twice during the process, that would cause the first + * test to fail but would force the second, as two opposite + * transitions would cause a detection no matter the polarity setting. + * + * The do-loop tries to sledge-hammer closed the timing hole between + * the initial value-read and the polarity-write - if the line value changes + * during that window, an interrupt is lost, the new polarity setting is + * incorrect, and the first success test will fail, causing a retry. + * + * Algorithm comes from Google's msmgpio driver. + */ +static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl, + const struct msm_pingroup *g, + struct irq_data *d) +{ + int loop_limit = 100; + unsigned val, val2, intstat; + unsigned pol; + + do { + val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit); + + pol = readl(pctrl->regs + g->intr_cfg_reg); + pol ^= BIT(g->intr_polarity_bit); + writel(pol, pctrl->regs + g->intr_cfg_reg); + + val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit); + intstat = readl(pctrl->regs + g->intr_status_reg); + if (intstat || (val == val2)) + return; + } while (loop_limit-- > 0); + dev_err(pctrl->dev, "dual-edge irq failed to stabilize, %#08x != %#08x\n", + val, val2); +} + +static void msm_gpio_irq_mask(struct irq_data *d) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->intr_cfg_reg); + val &= ~BIT(g->intr_enable_bit); + writel(val, pctrl->regs + g->intr_cfg_reg); + + clear_bit(d->hwirq, pctrl->enabled_irqs); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static void msm_gpio_irq_unmask(struct irq_data *d) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->intr_status_reg); + val &= ~BIT(g->intr_status_bit); + writel(val, pctrl->regs + g->intr_status_reg); + + val = readl(pctrl->regs + g->intr_cfg_reg); + val |= BIT(g->intr_enable_bit); + writel(val, pctrl->regs + g->intr_cfg_reg); + + set_bit(d->hwirq, pctrl->enabled_irqs); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static void msm_gpio_irq_ack(struct irq_data *d) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->intr_status_reg); + val &= ~BIT(g->intr_status_bit); + writel(val, pctrl->regs + g->intr_status_reg); + + if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) + msm_gpio_update_dual_edge_pos(pctrl, g, d); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +#define INTR_TARGET_PROC_APPS 4 + +static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return -EINVAL; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + /* + * For hw without possibility of detecting both edges + */ + if (g->intr_detection_width == 1 && type == IRQ_TYPE_EDGE_BOTH) + set_bit(d->hwirq, pctrl->dual_edge_irqs); + else + clear_bit(d->hwirq, pctrl->dual_edge_irqs); + + /* Route interrupts to application cpu */ + val = readl(pctrl->regs + g->intr_target_reg); + val &= ~(7 << g->intr_target_bit); + val |= INTR_TARGET_PROC_APPS << g->intr_target_bit; + writel(val, pctrl->regs + g->intr_target_reg); + + /* Update configuration for gpio. + * RAW_STATUS_EN is left on for all gpio irqs. Due to the + * internal circuitry of TLMM, toggling the RAW_STATUS + * could cause the INTR_STATUS to be set for EDGE interrupts. + */ + val = readl(pctrl->regs + g->intr_cfg_reg); + val |= BIT(g->intr_raw_status_bit); + if (g->intr_detection_width == 2) { + val &= ~(3 << g->intr_detection_bit); + val &= ~(1 << g->intr_polarity_bit); + switch (type) { + case IRQ_TYPE_EDGE_RISING: + val |= 1 << g->intr_detection_bit; + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_EDGE_FALLING: + val |= 2 << g->intr_detection_bit; + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_EDGE_BOTH: + val |= 3 << g->intr_detection_bit; + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_LEVEL_LOW: + break; + case IRQ_TYPE_LEVEL_HIGH: + val |= BIT(g->intr_polarity_bit); + break; + } + } else if (g->intr_detection_width == 1) { + val &= ~(1 << g->intr_detection_bit); + val &= ~(1 << g->intr_polarity_bit); + switch (type) { + case IRQ_TYPE_EDGE_RISING: + val |= BIT(g->intr_detection_bit); + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_EDGE_FALLING: + val |= BIT(g->intr_detection_bit); + break; + case IRQ_TYPE_EDGE_BOTH: + val |= BIT(g->intr_detection_bit); + break; + case IRQ_TYPE_LEVEL_LOW: + break; + case IRQ_TYPE_LEVEL_HIGH: + val |= BIT(g->intr_polarity_bit); + break; + } + } else { + BUG(); + } + writel(val, pctrl->regs + g->intr_cfg_reg); + + if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) + msm_gpio_update_dual_edge_pos(pctrl, g, d); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + __irq_set_handler_locked(d->irq, handle_level_irq); + else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + __irq_set_handler_locked(d->irq, handle_edge_irq); + + return 0; +} + +static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct msm_pinctrl *pctrl; + unsigned long flags; + unsigned ngpio; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return -EINVAL; + + ngpio = pctrl->chip.ngpio; + + spin_lock_irqsave(&pctrl->lock, flags); + + if (on) { + if (bitmap_empty(pctrl->wake_irqs, ngpio)) + enable_irq_wake(pctrl->irq); + set_bit(d->hwirq, pctrl->wake_irqs); + } else { + clear_bit(d->hwirq, pctrl->wake_irqs); + if (bitmap_empty(pctrl->wake_irqs, ngpio)) + disable_irq_wake(pctrl->irq); + } + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static unsigned int msm_gpio_irq_startup(struct irq_data *d) +{ + struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&pctrl->chip, d->hwirq)) { + dev_err(pctrl->dev, "unable to lock HW IRQ %lu for IRQ\n", + d->hwirq); + } + msm_gpio_irq_unmask(d); + return 0; +} + +static void msm_gpio_irq_shutdown(struct irq_data *d) +{ + struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); + + msm_gpio_irq_mask(d); + gpio_unlock_as_irq(&pctrl->chip, d->hwirq); +} + +static struct irq_chip msm_gpio_irq_chip = { + .name = "msmgpio", + .irq_mask = msm_gpio_irq_mask, + .irq_unmask = msm_gpio_irq_unmask, + .irq_ack = msm_gpio_irq_ack, + .irq_set_type = msm_gpio_irq_set_type, + .irq_set_wake = msm_gpio_irq_set_wake, + .irq_startup = msm_gpio_irq_startup, + .irq_shutdown = msm_gpio_irq_shutdown, +}; + +static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_get_chip(irq); + int irq_pin; + int handled = 0; + u32 val; + int i; + + chained_irq_enter(chip, desc); + + /* + * Each pin have it's own IRQ status register, so use + * enabled_irq bitmap to limit the number of reads. + */ + for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) { + g = &pctrl->soc->groups[i]; + val = readl(pctrl->regs + g->intr_status_reg); + if (val & BIT(g->intr_status_bit)) { + irq_pin = irq_find_mapping(pctrl->domain, i); + generic_handle_irq(irq_pin); + handled++; + } + } + + /* No interrutps where flagged */ + if (handled == 0) + handle_bad_irq(irq, desc); + + chained_irq_exit(chip, desc); +} + +static int msm_gpio_init(struct msm_pinctrl *pctrl) +{ + struct gpio_chip *chip; + int irq; + int ret; + int i; + int r; + + chip = &pctrl->chip; + chip->base = 0; + chip->ngpio = pctrl->soc->ngpios; + chip->label = dev_name(pctrl->dev); + chip->dev = pctrl->dev; + chip->owner = THIS_MODULE; + chip->of_node = pctrl->dev->of_node; + + pctrl->enabled_irqs = devm_kzalloc(pctrl->dev, + sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), + GFP_KERNEL); + if (!pctrl->enabled_irqs) { + dev_err(pctrl->dev, "Failed to allocate enabled_irqs bitmap\n"); + return -ENOMEM; + } + + pctrl->dual_edge_irqs = devm_kzalloc(pctrl->dev, + sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), + GFP_KERNEL); + if (!pctrl->dual_edge_irqs) { + dev_err(pctrl->dev, "Failed to allocate dual_edge_irqs bitmap\n"); + return -ENOMEM; + } + + pctrl->wake_irqs = devm_kzalloc(pctrl->dev, + sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), + GFP_KERNEL); + if (!pctrl->wake_irqs) { + dev_err(pctrl->dev, "Failed to allocate wake_irqs bitmap\n"); + return -ENOMEM; + } + + ret = gpiochip_add(&pctrl->chip); + if (ret) { + dev_err(pctrl->dev, "Failed register gpiochip\n"); + return ret; + } + + ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio); + if (ret) { + dev_err(pctrl->dev, "Failed to add pin range\n"); + return ret; + } + + pctrl->domain = irq_domain_add_linear(pctrl->dev->of_node, chip->ngpio, + &irq_domain_simple_ops, NULL); + if (!pctrl->domain) { + dev_err(pctrl->dev, "Failed to register irq domain\n"); + r = gpiochip_remove(&pctrl->chip); + return -ENOSYS; + } + + for (i = 0; i < chip->ngpio; i++) { + irq = irq_create_mapping(pctrl->domain, i); + irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, handle_edge_irq); + irq_set_chip_data(irq, pctrl); + } + + irq_set_handler_data(pctrl->irq, pctrl); + irq_set_chained_handler(pctrl->irq, msm_gpio_irq_handler); + + return 0; +} + +int msm_pinctrl_probe(struct platform_device *pdev, + const struct msm_pinctrl_soc_data *soc_data) +{ + struct msm_pinctrl *pctrl; + struct resource *res; + int ret; + + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) { + dev_err(&pdev->dev, "Can't allocate msm_pinctrl\n"); + return -ENOMEM; + } + pctrl->dev = &pdev->dev; + pctrl->soc = soc_data; + pctrl->chip = msm_gpio_template; + + spin_lock_init(&pctrl->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pctrl->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pctrl->regs)) + return PTR_ERR(pctrl->regs); + + pctrl->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (pctrl->irq < 0) { + dev_err(&pdev->dev, "No interrupt defined for msmgpio\n"); + return pctrl->irq; + } + + msm_pinctrl_desc.name = dev_name(&pdev->dev); + msm_pinctrl_desc.pins = pctrl->soc->pins; + msm_pinctrl_desc.npins = pctrl->soc->npins; + pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl); + if (!pctrl->pctrl) { + dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); + return -ENODEV; + } + + ret = msm_gpio_init(pctrl); + if (ret) { + pinctrl_unregister(pctrl->pctrl); + return ret; + } + + platform_set_drvdata(pdev, pctrl); + + dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n"); + + return 0; +} +EXPORT_SYMBOL(msm_pinctrl_probe); + +int msm_pinctrl_remove(struct platform_device *pdev) +{ + struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); + int ret; + + irq_set_chained_handler(pctrl->irq, NULL); + irq_domain_remove(pctrl->domain); + ret = gpiochip_remove(&pctrl->chip); + pinctrl_unregister(pctrl->pctrl); + + return 0; +} +EXPORT_SYMBOL(msm_pinctrl_remove); + diff --git a/drivers/pinctrl/pinctrl-msm.h b/drivers/pinctrl/pinctrl-msm.h new file mode 100644 index 000000000000..206e782e2daa --- /dev/null +++ b/drivers/pinctrl/pinctrl-msm.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013, Sony Mobile Communications AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ +#ifndef __PINCTRL_MSM_H__ +#define __PINCTRL_MSM_H__ + +#include +#include +#include +#include + +/** + * struct msm_function - a pinmux function + * @name: Name of the pinmux function. + * @groups: List of pingroups for this function. + * @ngroups: Number of entries in @groups. + */ +struct msm_function { + const char *name; + const char * const *groups; + unsigned ngroups; +}; + +/** + * struct msm_pingroup - Qualcomm pingroup definition + * @name: Name of the pingroup. + * @pins: A list of pins assigned to this pingroup. + * @npins: Number of entries in @pins. + * @funcs: A list of pinmux functions that can be selected for + * this group. The index of the selected function is used + * for programming the function selector. + * Entries should be indices into the groups list of the + * struct msm_pinctrl_soc_data. + * @ctl_reg: Offset of the register holding control bits for this group. + * @io_reg: Offset of the register holding input/output bits for this group. + * @intr_cfg_reg: Offset of the register holding interrupt configuration bits. + * @intr_status_reg: Offset of the register holding the status bits for this group. + * @intr_target_reg: Offset of the register specifying routing of the interrupts + * from this group. + * @mux_bit: Offset in @ctl_reg for the pinmux function selection. + * @pull_bit: Offset in @ctl_reg for the bias configuration. + * @drv_bit: Offset in @ctl_reg for the drive strength configuration. + * @oe_bit: Offset in @ctl_reg for controlling output enable. + * @in_bit: Offset in @io_reg for the input bit value. + * @out_bit: Offset in @io_reg for the output bit value. + * @intr_enable_bit: Offset in @intr_cfg_reg for enabling the interrupt for this group. + * @intr_status_bit: Offset in @intr_status_reg for reading and acking the interrupt + * status. + * @intr_target_bit: Offset in @intr_target_reg for configuring the interrupt routing. + * @intr_raw_status_bit: Offset in @intr_cfg_reg for the raw status bit. + * @intr_polarity_bit: Offset in @intr_cfg_reg for specifying polarity of the interrupt. + * @intr_detection_bit: Offset in @intr_cfg_reg for specifying interrupt type. + * @intr_detection_width: Number of bits used for specifying interrupt type, + * Should be 2 for SoCs that can detect both edges in hardware, + * otherwise 1. + */ +struct msm_pingroup { + const char *name; + const unsigned *pins; + unsigned npins; + + unsigned funcs[8]; + + s16 ctl_reg; + s16 io_reg; + s16 intr_cfg_reg; + s16 intr_status_reg; + s16 intr_target_reg; + + unsigned mux_bit:5; + + unsigned pull_bit:5; + unsigned drv_bit:5; + + unsigned oe_bit:5; + unsigned in_bit:5; + unsigned out_bit:5; + + unsigned intr_enable_bit:5; + unsigned intr_status_bit:5; + + unsigned intr_target_bit:5; + unsigned intr_raw_status_bit:5; + unsigned intr_polarity_bit:5; + unsigned intr_detection_bit:5; + unsigned intr_detection_width:5; +}; + +/** + * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration + * @pins: An array describing all pins the pin controller affects. + * @npins: The number of entries in @pins. + * @functions: An array describing all mux functions the SoC supports. + * @nfunctions: The number of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The numbmer of entries in @groups. + * @ngpio: The number of pingroups the driver should expose as GPIOs. + */ +struct msm_pinctrl_soc_data { + const struct pinctrl_pin_desc *pins; + unsigned npins; + const struct msm_function *functions; + unsigned nfunctions; + const struct msm_pingroup *groups; + unsigned ngroups; + unsigned ngpios; +}; + +int msm_pinctrl_probe(struct platform_device *pdev, + const struct msm_pinctrl_soc_data *soc_data); +int msm_pinctrl_remove(struct platform_device *pdev); + +#endif -- cgit v1.2.3 From 55aaf8342db44c1d0d8bb911c50774f6eaeefbf3 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 5 Dec 2013 18:10:04 -0800 Subject: pinctrl: Add msm8x74 configuration Add initial definition of parameters for pinctrl-msm for the msm8x74 platform. Signed-off-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 4 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-msm8x74.c | 636 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 641 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-msm8x74.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index f5a7d7c0c1ee..06e057bb3376 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -209,6 +209,10 @@ config PINCTRL_MSM select PINCONF select GENERIC_PINCONF +config PINCTRL_MSM8X74 + bool "Qualcomm 8x74 pin controller driver" + select PINCTRL_MSM + config PINCTRL_NOMADIK bool "Nomadik pin controller driver" depends on ARCH_U8500 || ARCH_NOMADIK diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 4eed91ff0676..5d91e4b448d4 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o +obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/pinctrl-msm8x74.c new file mode 100644 index 000000000000..762552bc53b9 --- /dev/null +++ b/drivers/pinctrl/pinctrl-msm8x74.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2013, Sony Mobile Communications AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-msm.h" + +static const struct pinctrl_pin_desc msm8x74_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + + PINCTRL_PIN(146, "SDC1_CLK"), + PINCTRL_PIN(147, "SDC1_CMD"), + PINCTRL_PIN(148, "SDC1_DATA"), + PINCTRL_PIN(149, "SDC2_CLK"), + PINCTRL_PIN(150, "SDC2_CMD"), + PINCTRL_PIN(151, "SDC2_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); + +static const unsigned int sdc1_clk_pins[] = { 146 }; +static const unsigned int sdc1_cmd_pins[] = { 147 }; +static const unsigned int sdc1_data_pins[] = { 148 }; +static const unsigned int sdc2_clk_pins[] = { 149 }; +static const unsigned int sdc2_cmd_pins[] = { 150 }; +static const unsigned int sdc2_data_pins[] = { 151 }; + +#define FUNCTION(fname) \ + [MSM_MUX_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = { \ + MSM_MUX_NA, /* gpio mode */ \ + MSM_MUX_##f1, \ + MSM_MUX_##f2, \ + MSM_MUX_##f3, \ + MSM_MUX_##f4, \ + MSM_MUX_##f5, \ + MSM_MUX_##f6, \ + MSM_MUX_##f7 \ + }, \ + .ctl_reg = 0x1000 + 0x10 * id , \ + .io_reg = 0x1004 + 0x10 * id, \ + .intr_cfg_reg = 0x1008 + 0x10 * id, \ + .intr_status_reg = 0x100c + 0x10 * id, \ + .intr_target_reg = 0x1008 + 0x10 * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +/* + * TODO: Add the rest of the possible functions and fill out + * the pingroup table below. + */ +enum msm8x74_functions { + MSM_MUX_blsp_i2c2, + MSM_MUX_blsp_i2c6, + MSM_MUX_blsp_i2c11, + MSM_MUX_blsp_spi1, + MSM_MUX_blsp_uart2, + MSM_MUX_blsp_uart8, + MSM_MUX_slimbus, + MSM_MUX_NA, +}; + +static const char * const blsp_i2c2_groups[] = { "gpio6", "gpio7" }; +static const char * const blsp_i2c6_groups[] = { "gpio29", "gpio30" }; +static const char * const blsp_i2c11_groups[] = { "gpio83", "gpio84" }; +static const char * const blsp_spi1_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3" }; +static const char * const blsp_uart2_groups[] = { "gpio4", "gpio5" }; +static const char * const blsp_uart8_groups[] = { "gpio45", "gpio46" }; +static const char * const slimbus_groups[] = { "gpio70", "gpio71" }; + +static const struct msm_function msm8x74_functions[] = { + FUNCTION(blsp_i2c2), + FUNCTION(blsp_i2c6), + FUNCTION(blsp_i2c11), + FUNCTION(blsp_spi1), + FUNCTION(blsp_uart2), + FUNCTION(blsp_uart8), + FUNCTION(slimbus), +}; + +static const struct msm_pingroup msm8x74_groups[] = { + PINGROUP(0, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(1, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(2, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(3, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(4, NA, blsp_uart2, NA, NA, NA, NA, NA), + PINGROUP(5, NA, blsp_uart2, NA, NA, NA, NA, NA), + PINGROUP(6, NA, NA, blsp_i2c2, NA, NA, NA, NA), + PINGROUP(7, NA, NA, blsp_i2c2, NA, NA, NA, NA), + PINGROUP(8, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(9, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(10, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(11, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(12, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(13, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(14, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(15, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(16, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(17, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(18, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(19, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(20, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(21, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(22, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(23, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(24, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(25, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(26, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(27, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(28, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(29, NA, NA, blsp_i2c6, NA, NA, NA, NA), + PINGROUP(30, NA, NA, blsp_i2c6, NA, NA, NA, NA), + PINGROUP(31, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(32, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(33, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(34, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(35, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(36, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(37, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(38, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(39, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(40, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(41, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(42, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(43, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(44, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(45, NA, blsp_uart8, NA, NA, NA, NA, NA), + PINGROUP(46, NA, blsp_uart8, NA, NA, NA, NA, NA), + PINGROUP(47, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(48, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(49, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(50, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(51, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(52, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(53, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(54, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(55, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(56, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(57, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(58, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(59, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(60, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(61, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(62, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(63, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(64, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(65, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(66, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(67, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(68, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(69, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(70, slimbus, NA, NA, NA, NA, NA, NA), + PINGROUP(71, slimbus, NA, NA, NA, NA, NA, NA), + PINGROUP(72, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(73, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(74, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(75, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(76, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(77, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(78, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(79, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(80, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(81, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(82, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(83, NA, NA, blsp_i2c11, NA, NA, NA, NA), + PINGROUP(84, NA, NA, blsp_i2c11, NA, NA, NA, NA), + PINGROUP(85, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(86, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(87, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(88, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(89, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(90, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(91, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(92, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(93, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(94, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(95, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(96, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(97, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(98, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(99, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(100, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(101, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(102, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(103, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(104, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(105, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(106, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(107, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(108, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(109, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(110, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(111, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(112, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(113, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(114, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(115, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(116, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(117, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(118, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(119, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(120, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(121, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(122, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(123, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(124, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(125, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(126, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(127, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(128, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(129, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(130, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(131, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(132, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(133, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(134, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(135, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(136, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(137, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(138, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(139, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(140, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(141, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(144, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(145, NA, NA, NA, NA, NA, NA, NA), + SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6), + SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3), + SDC_PINGROUP(sdc1_data, 0x2044, 9, 0), + SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6), + SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3), + SDC_PINGROUP(sdc2_data, 0x2048, 9, 0), +}; + +#define NUM_GPIO_PINGROUPS 146 + +static const struct msm_pinctrl_soc_data msm8x74_pinctrl = { + .pins = msm8x74_pins, + .npins = ARRAY_SIZE(msm8x74_pins), + .functions = msm8x74_functions, + .nfunctions = ARRAY_SIZE(msm8x74_functions), + .groups = msm8x74_groups, + .ngroups = ARRAY_SIZE(msm8x74_groups), + .ngpios = NUM_GPIO_PINGROUPS, +}; + +static int msm8x74_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &msm8x74_pinctrl); +} + +static struct of_device_id msm8x74_pinctrl_of_match[] = { + { .compatible = "qcom,msm8x74-pinctrl", }, + { }, +}; + +static struct platform_driver msm8x74_pinctrl_driver = { + .driver = { + .name = "msm8x74-pinctrl", + .owner = THIS_MODULE, + .of_match_table = msm8x74_pinctrl_of_match, + }, + .probe = msm8x74_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init msm8x74_pinctrl_init(void) +{ + return platform_driver_register(&msm8x74_pinctrl_driver); +} +arch_initcall(msm8x74_pinctrl_init); + +static void __exit msm8x74_pinctrl_exit(void) +{ + platform_driver_unregister(&msm8x74_pinctrl_driver); +} +module_exit(msm8x74_pinctrl_exit); + +MODULE_AUTHOR("Bjorn Andersson "); +MODULE_DESCRIPTION("Qualcomm MSM8x74 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, msm8x74_pinctrl_of_match); + -- cgit v1.2.3 From 0ab75ae81da249988bf3c7a38e0a48d4b9be1e0c Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 06:28:43 -0800 Subject: ethernet: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: Santosh Raspatur CC: Dimitris Michailidis CC: Michael Chan CC: Santiago Leon CC: Sebastian Hesselbarth CC: Olof Johansson CC: Manish Chopra CC: Sony Chacko CC: Rajesh Borundia CC: Nicolas Pitre CC: Steve Glendinning Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/amd8111e.c | 4 +--- drivers/net/ethernet/amd/amd8111e.h | 4 +--- drivers/net/ethernet/amd/au1000_eth.c | 3 +-- drivers/net/ethernet/amd/au1000_eth.h | 3 +-- drivers/net/ethernet/broadcom/sb1250-mac.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/common.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/cphy.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/elmer0.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/espi.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/espi.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/gmac.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/mv88x201x.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/pm3393.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/regs.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/sge.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/sge.h | 3 +-- drivers/net/ethernet/chelsio/cxgb/subr.c | 3 +-- drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h | 3 +-- drivers/net/ethernet/ibm/ibmveth.c | 3 +-- drivers/net/ethernet/ibm/ibmveth.h | 3 +-- drivers/net/ethernet/lantiq_etop.c | 3 +-- drivers/net/ethernet/marvell/mv643xx_eth.c | 3 +-- drivers/net/ethernet/marvell/pxa168_eth.c | 3 +-- drivers/net/ethernet/natsemi/ns83820.c | 3 +-- drivers/net/ethernet/netx-eth.c | 3 +-- drivers/net/ethernet/nvidia/forcedeth.c | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c | 3 +-- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h | 3 +-- drivers/net/ethernet/pasemi/pasemi_mac.c | 3 +-- drivers/net/ethernet/pasemi/pasemi_mac.h | 3 +-- drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c | 3 +-- drivers/net/ethernet/qlogic/netxen/Makefile | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 4 +--- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 4 +--- drivers/net/ethernet/smsc/smc911x.c | 3 +-- drivers/net/ethernet/smsc/smc911x.h | 3 +-- drivers/net/ethernet/smsc/smc91x.c | 3 +-- drivers/net/ethernet/smsc/smc91x.h | 3 +-- drivers/net/ethernet/smsc/smsc911x.c | 3 +-- drivers/net/ethernet/smsc/smsc911x.h | 3 +-- drivers/net/ethernet/smsc/smsc9420.c | 3 +-- drivers/net/ethernet/smsc/smsc9420.h | 3 +-- drivers/net/ethernet/sun/cassini.c | 4 +--- drivers/net/ethernet/sun/cassini.h | 4 +--- drivers/net/ethernet/tundra/tsi108_eth.h | 4 +--- drivers/net/ethernet/xircom/xirc2ps_cs.c | 3 +-- 60 files changed, 60 insertions(+), 134 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index d042511bdc13..d6beba0bc01f 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -24,9 +24,7 @@ * 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 + * along with this program; if not, see . Module Name: diff --git a/drivers/net/ethernet/amd/amd8111e.h b/drivers/net/ethernet/amd/amd8111e.h index 8baa3527ba74..b1fae36360d2 100644 --- a/drivers/net/ethernet/amd/amd8111e.h +++ b/drivers/net/ethernet/amd/amd8111e.h @@ -13,9 +13,7 @@ * 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 + * along with this program; if not, see . Module Name: diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 427c148bb643..2eee5764805d 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -27,8 +27,7 @@ * 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. + * with this program; if not, see . * * ######################################################################## * diff --git a/drivers/net/ethernet/amd/au1000_eth.h b/drivers/net/ethernet/amd/au1000_eth.h index 4b7f7ad62bb8..ca53024f017f 100644 --- a/drivers/net/ethernet/amd/au1000_eth.h +++ b/drivers/net/ethernet/amd/au1000_eth.h @@ -18,8 +18,7 @@ * 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. + * with this program; if not, see . * * ######################################################################## * diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index c2777712da99..31a076d86709 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * * * This driver is designed for the Broadcom SiByte SOC built-in diff --git a/drivers/net/ethernet/chelsio/cxgb/common.h b/drivers/net/ethernet/chelsio/cxgb/common.h index 8abb46b39032..5dd20f7285eb 100644 --- a/drivers/net/ethernet/chelsio/cxgb/common.h +++ b/drivers/net/ethernet/chelsio/cxgb/common.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/cphy.h b/drivers/net/ethernet/chelsio/cxgb/cphy.h index 1f095a9fc739..a4d2a4c08d3f 100644 --- a/drivers/net/ethernet/chelsio/cxgb/cphy.h +++ b/drivers/net/ethernet/chelsio/cxgb/cphy.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h b/drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h index e36d45b78cc7..5249686afe71 100644 --- a/drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h +++ b/drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c index 1d021059f097..e5987139a1ae 100644 --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/elmer0.h b/drivers/net/ethernet/chelsio/cxgb/elmer0.h index eef655c827d9..81526ad36339 100644 --- a/drivers/net/ethernet/chelsio/cxgb/elmer0.h +++ b/drivers/net/ethernet/chelsio/cxgb/elmer0.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/espi.c b/drivers/net/ethernet/chelsio/cxgb/espi.c index 639ff1955739..3e182eee799e 100644 --- a/drivers/net/ethernet/chelsio/cxgb/espi.c +++ b/drivers/net/ethernet/chelsio/cxgb/espi.c @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/espi.h b/drivers/net/ethernet/chelsio/cxgb/espi.h index 5694aad4fbc0..162de5259df9 100644 --- a/drivers/net/ethernet/chelsio/cxgb/espi.h +++ b/drivers/net/ethernet/chelsio/cxgb/espi.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/gmac.h b/drivers/net/ethernet/chelsio/cxgb/gmac.h index d42337457cf7..dfa77491a910 100644 --- a/drivers/net/ethernet/chelsio/cxgb/gmac.h +++ b/drivers/net/ethernet/chelsio/cxgb/gmac.h @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/mv88x201x.c b/drivers/net/ethernet/chelsio/cxgb/mv88x201x.c index f7136b2fd1e5..d0cf611551a1 100644 --- a/drivers/net/ethernet/chelsio/cxgb/mv88x201x.c +++ b/drivers/net/ethernet/chelsio/cxgb/mv88x201x.c @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/pm3393.c b/drivers/net/ethernet/chelsio/cxgb/pm3393.c index eb33a31b08a0..ec5e05052d99 100644 --- a/drivers/net/ethernet/chelsio/cxgb/pm3393.c +++ b/drivers/net/ethernet/chelsio/cxgb/pm3393.c @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/regs.h b/drivers/net/ethernet/chelsio/cxgb/regs.h index c80bf4d6d0a6..964ce59ee169 100644 --- a/drivers/net/ethernet/chelsio/cxgb/regs.h +++ b/drivers/net/ethernet/chelsio/cxgb/regs.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c index 8061fb0ef7ed..0341537cdd37 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.h b/drivers/net/ethernet/chelsio/cxgb/sge.h index b9bf16b385f7..a1ba591b3431 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.h +++ b/drivers/net/ethernet/chelsio/cxgb/sge.h @@ -11,8 +11,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c index e0a03a31e7c4..816719314cc8 100644 --- a/drivers/net/ethernet/chelsio/cxgb/subr.c +++ b/drivers/net/ethernet/chelsio/cxgb/subr.c @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h b/drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h index d0f87d82566a..7f79cc7ceb75 100644 --- a/drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h @@ -12,8 +12,7 @@ * published by the Free Software Foundation. * * * * 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. * + * with this program; if not, see . * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 952d795230a4..cde0fd941f0c 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -12,8 +12,7 @@ * 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. + * along with this program; if not, see . * * Copyright (C) IBM Corporation, 2003, 2010 * diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h index 84066bafe057..451ba7949e15 100644 --- a/drivers/net/ethernet/ibm/ibmveth.h +++ b/drivers/net/ethernet/ibm/ibmveth.h @@ -12,8 +12,7 @@ * 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. + * along with this program; if not, see . * * Copyright (C) IBM Corporation, 2003, 2010 * diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 6a6c1f76d8e0..974a007c4277 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -9,8 +9,7 @@ * 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. + * along with this program; if not, see . * * Copyright (C) 2011 John Crispin */ diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 61088a6a9424..fa905052fbf4 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -33,8 +33,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index fff62460185c..2ad32417a52c 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -19,8 +19,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index d3b47003a575..5213e73f0ea5 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -22,8 +22,7 @@ * 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 + * along with this program; if not, see . * * * ChangeLog diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c index e6f0a4366f90..31eb911e4763 100644 --- a/drivers/net/ethernet/netx-eth.c +++ b/drivers/net/ethernet/netx-eth.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 2d045be4b5cf..ab67babbfdd1 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -26,8 +26,7 @@ * 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 + * along with this program; if not, see . * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h index 2a9003071d51..2a55d6d53ee6 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #ifndef _PCH_GBE_H_ diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c index ff3ad70935a6..51250363566b 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #include "pch_gbe.h" #include "pch_gbe_phy.h" diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h index 94aaac5b057b..91ce07c8306c 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #ifndef _PCH_GBE_API_H_ #define _PCH_GBE_API_H_ diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c index f0ceb89af931..826f0ccdc23c 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #include "pch_gbe.h" #include "pch_gbe_api.h" diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 27ffe0ebf0a6..464e91058c81 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #include "pch_gbe.h" diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c index cf7c9b3a255b..08d4be616064 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #include "pch_gbe.h" diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c index 8b7ff75fc8e0..a5cad5ea9436 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #include "pch_gbe.h" diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h index 0cbe69206e04..95ad0151ad02 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #ifndef _PCH_GBE_PHY_H_ #define _PCH_GBE_PHY_H_ diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index dbaa49e58b0c..0734758ff5ba 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.h b/drivers/net/ethernet/pasemi/pasemi_mac.h index f2749d46c125..a5807703ab96 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.h +++ b/drivers/net/ethernet/pasemi/pasemi_mac.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef PASEMI_MAC_H diff --git a/drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c b/drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c index 4825959a0efe..25fae568261f 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ diff --git a/drivers/net/ethernet/qlogic/netxen/Makefile b/drivers/net/ethernet/qlogic/netxen/Makefile index 861a0590b1f4..e14e60c88381 100644 --- a/drivers/net/ethernet/qlogic/netxen/Makefile +++ b/drivers/net/ethernet/qlogic/netxen/Makefile @@ -13,9 +13,7 @@ # 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. +# along with this program; if not, see . # # The full GNU General Public License is included in this distribution # in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index 9adcdbb49476..6e426ae94692 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index 1bcaf45aa864..6f6be57f4690 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 4ca2c196c98a..87e073c6e291 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h index 0c64c82b9acf..a310c2f6502a 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 67efe754367d..b72b6bea326e 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h index e2c5b6f2df03..7433c4d21601 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 7692dfd4f262..3010abb55fbd 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 3bec8cfebf99..70849dea32b1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * The full GNU General Public License is included in this distribution * in the file called "COPYING". diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 0f096a890059..5a4278d1f7d0 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -17,8 +17,7 @@ * 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 + * along with this program; if not, see . * * Arguments: * watchdog = TX watchdog timeout diff --git a/drivers/net/ethernet/smsc/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h index 9965da39281b..04b35f55df97 100644 --- a/drivers/net/ethernet/smsc/smc911x.h +++ b/drivers/net/ethernet/smsc/smc911x.h @@ -15,8 +15,7 @@ . 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 + . along with this program; if not, see . . . Information contained in this file was obtained from the LAN9118 . manual from SMC. To get a copy, if you really want one, you can find diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 0c9b5d94154f..b84c4ddf7add 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -19,8 +19,7 @@ * 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 + * along with this program; if not, see . * * Arguments: * io = for the base address diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 749654b976bc..47dce918eb0f 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -18,8 +18,7 @@ . 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 + . along with this program; if not, see . . . Information contained in this file was obtained from the LAN91C111 . manual from SMC. To get a copy, if you really want one, you can find diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 8564f23a6796..6382b7c416f4 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . * *************************************************************************** * Rewritten, heavily based on smsc911x simple driver by SMSC. diff --git a/drivers/net/ethernet/smsc/smsc911x.h b/drivers/net/ethernet/smsc/smsc911x.h index 9ad5e5d39a03..23953957fed8 100644 --- a/drivers/net/ethernet/smsc/smsc911x.h +++ b/drivers/net/ethernet/smsc/smsc911x.h @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . * ***************************************************************************/ #ifndef __SMSC911X_H__ diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index f433d97aa097..9d6effe5f699 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * *************************************************************************** */ diff --git a/drivers/net/ethernet/smsc/smsc9420.h b/drivers/net/ethernet/smsc/smsc9420.h index e441402f77a2..c63c76381af6 100644 --- a/drivers/net/ethernet/smsc/smsc9420.h +++ b/drivers/net/ethernet/smsc/smsc9420.h @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * *************************************************************************** */ diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index b4d50d74ba18..df8d383acf48 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -14,9 +14,7 @@ * 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. + * along with this program; if not, see . * * This driver uses the sungem driver (c) David Miller * (davem@redhat.com) as its basis. diff --git a/drivers/net/ethernet/sun/cassini.h b/drivers/net/ethernet/sun/cassini.h index b361424d5f57..882ce168a799 100644 --- a/drivers/net/ethernet/sun/cassini.h +++ b/drivers/net/ethernet/sun/cassini.h @@ -15,9 +15,7 @@ * 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. + * along with this program; if not, see . * * vendor id: 0x108E (Sun Microsystems, Inc.) * device id: 0xabba (Cassini) diff --git a/drivers/net/ethernet/tundra/tsi108_eth.h b/drivers/net/ethernet/tundra/tsi108_eth.h index 5fee7d78dc6d..4a03c594b2b1 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.h +++ b/drivers/net/ethernet/tundra/tsi108_eth.h @@ -16,9 +16,7 @@ * 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 + * along with this program; if not, see . */ /* diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c index bdd20b888cf6..7c81ffb861e8 100644 --- a/drivers/net/ethernet/xircom/xirc2ps_cs.c +++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c @@ -27,8 +27,7 @@ * 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 + * along with this program; if not, see . * * * ALTERNATIVELY, this driver may be distributed under the terms of -- cgit v1.2.3 From e8478de32ead801a09a073c4286abf892d907465 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 06:28:44 -0800 Subject: irda: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: Samuel Ortiz Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/irda/au1k_ir.c | 3 +-- drivers/net/irda/esi-sir.c | 4 +--- drivers/net/irda/litelink-sir.c | 4 +--- drivers/net/irda/ma600-sir.c | 4 +--- drivers/net/irda/old_belkin-sir.c | 4 +--- drivers/net/irda/smsc-ircc2.c | 4 +--- drivers/net/irda/smsc-ircc2.h | 4 +--- drivers/net/irda/via-ircc.c | 3 +-- drivers/net/irda/via-ircc.h | 3 +-- drivers/net/irda/vlsi_ir.c | 4 +--- drivers/net/irda/vlsi_ir.h | 4 +--- 11 files changed, 11 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 7a1f684edcb5..5b7a665c6d83 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -15,8 +15,7 @@ * 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. + * with this program; if not, see . */ #include diff --git a/drivers/net/irda/esi-sir.c b/drivers/net/irda/esi-sir.c index a908df7c4b9d..019a3e848bcb 100644 --- a/drivers/net/irda/esi-sir.c +++ b/drivers/net/irda/esi-sir.c @@ -25,9 +25,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/litelink-sir.c b/drivers/net/irda/litelink-sir.c index d6d9d2e5ad49..6827777cbeea 100644 --- a/drivers/net/irda/litelink-sir.c +++ b/drivers/net/irda/litelink-sir.c @@ -22,9 +22,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c index e91216452379..a9a81358477b 100644 --- a/drivers/net/irda/ma600-sir.c +++ b/drivers/net/irda/ma600-sir.c @@ -25,9 +25,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/old_belkin-sir.c b/drivers/net/irda/old_belkin-sir.c index 75714bc71030..f237136f3827 100644 --- a/drivers/net/irda/old_belkin-sir.c +++ b/drivers/net/irda/old_belkin-sir.c @@ -22,9 +22,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 0dcdf1592f6b..282120430f12 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -34,9 +34,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/smsc-ircc2.h b/drivers/net/irda/smsc-ircc2.h index 317b7fd69bb3..4829fa22cb29 100644 --- a/drivers/net/irda/smsc-ircc2.h +++ b/drivers/net/irda/smsc-ircc2.h @@ -25,9 +25,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 9abaec27f962..26cb45d59702 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -17,8 +17,7 @@ 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. +this program; if not, see . F01 Oct/02/02: Modify code for V0.11(move out back to back transfer) F02 Oct/28/02: Add SB device ID for 3147 and 3177. diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h index f903a6a2dcb7..7ce820ecc361 100644 --- a/drivers/net/irda/via-ircc.h +++ b/drivers/net/irda/via-ircc.h @@ -18,8 +18,7 @@ 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. +this program; if not, see . * Comment: * jul/08/2002 : Rx buffer length should use Rx ring ptr. diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index c5bd58b4d8a8..cc9b8665e73c 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -15,9 +15,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index a076eb125349..56399204e68c 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -18,9 +18,7 @@ * 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 + * along with this program; if not, see . * ********************************************************************/ -- cgit v1.2.3 From 9cb00073d754249604f735a79734fa58df92a456 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 06:28:46 -0800 Subject: usb: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: Oliver Neukum CC: Steve Glendinning CC: Oliver Neukum Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/usb/asix.h | 3 +-- drivers/net/usb/asix_common.c | 3 +-- drivers/net/usb/asix_devices.c | 3 +-- drivers/net/usb/ax88172a.c | 3 +-- drivers/net/usb/ax88179_178a.c | 3 +-- drivers/net/usb/catc.c | 3 +-- drivers/net/usb/cdc_eem.c | 3 +-- drivers/net/usb/cdc_ether.c | 3 +-- drivers/net/usb/cdc_subset.c | 3 +-- drivers/net/usb/cx82310_eth.c | 3 +-- drivers/net/usb/gl620a.c | 3 +-- drivers/net/usb/int51x1.c | 3 +-- drivers/net/usb/kaweth.c | 3 +-- drivers/net/usb/lg-vl600.c | 3 +-- drivers/net/usb/mcs7830.c | 3 +-- drivers/net/usb/net1080.c | 3 +-- drivers/net/usb/plusb.c | 3 +-- drivers/net/usb/rndis_host.c | 3 +-- drivers/net/usb/sierra_net.c | 3 +-- drivers/net/usb/smsc75xx.c | 3 +-- drivers/net/usb/smsc75xx.h | 3 +-- drivers/net/usb/smsc95xx.c | 3 +-- drivers/net/usb/smsc95xx.h | 3 +-- drivers/net/usb/usbnet.c | 3 +-- drivers/net/usb/zaurus.c | 3 +-- 25 files changed, 25 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h index bdaa12d07a12..bad857aacd1a 100644 --- a/drivers/net/usb/asix.h +++ b/drivers/net/usb/asix.h @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _ASIX_H diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 577c72d5f369..5c55f11572ba 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #include "asix.h" diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 386a3df53678..9765a7d4766d 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #include "asix.h" diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c index 723b3879ecc2..5f18fcb8dcc7 100644 --- a/drivers/net/usb/ax88172a.c +++ b/drivers/net/usb/ax88172a.c @@ -21,8 +21,7 @@ * 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 + * along with this program; if not, see . */ #include "asix.h" diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 8e8d0fcd4979..d6f64dad05bc 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -14,8 +14,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index df507e6dbb9c..da6b8a5dcc0d 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -24,8 +24,7 @@ * 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 + * along with this program; if not, see . * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index 08d55b6bf272..57fd7170ae60 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 2023f3ea891e..4b1c0f3f727d 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ // #define DEBUG // error path messages, extra info diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c index 0d1fe89ae0bd..3b2593a7602b 100644 --- a/drivers/net/usb/cdc_subset.c +++ b/drivers/net/usb/cdc_subset.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c index 1e207f086b75..5233e6d070ec 100644 --- a/drivers/net/usb/cx82310_eth.c +++ b/drivers/net/usb/cx82310_eth.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index a7e3f4e55bf3..3569da1135c1 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ // #define DEBUG // error path messages, extra info diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c index ace9e74ffbdd..4ff70b22c6ee 100644 --- a/drivers/net/usb/int51x1.c +++ b/drivers/net/usb/int51x1.c @@ -20,8 +20,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index afb117c16d2d..250fc21d9781 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -25,8 +25,7 @@ * 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. + * along with this program; if not, see . * ****************************************************************/ diff --git a/drivers/net/usb/lg-vl600.c b/drivers/net/usb/lg-vl600.c index 808d6506da41..acfcc32b323d 100644 --- a/drivers/net/usb/lg-vl600.c +++ b/drivers/net/usb/lg-vl600.c @@ -15,8 +15,7 @@ * 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 + * along with this program; if not, see . */ #include #include diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 03832d3780aa..aea68bc33583 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -36,8 +36,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 93e0716a118c..8b2493f05a1c 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ // #define DEBUG // error path messages, extra info diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 0fcc8e65a068..ee705b7bba08 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ // #define DEBUG // error path messages, extra info diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index cc49aac70224..72aee8516ca8 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include #include diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index a79e9d334928..a251588762ec 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -21,8 +21,7 @@ * 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 + * along with this program; if not, see . */ #define DRIVER_VERSION "v.2.0" diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 66ebbacf066f..0217b282e7ec 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * *****************************************************************************/ diff --git a/drivers/net/usb/smsc75xx.h b/drivers/net/usb/smsc75xx.h index 67eba39e6ee2..2c7ea8fd184f 100644 --- a/drivers/net/usb/smsc75xx.h +++ b/drivers/net/usb/smsc75xx.h @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * *****************************************************************************/ diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 3f38ba868f61..96f5eee20fa4 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * *****************************************************************************/ diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h index f360ee372554..526faa0c44e6 100644 --- a/drivers/net/usb/smsc95xx.h +++ b/drivers/net/usb/smsc95xx.h @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . * *****************************************************************************/ diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8494bb53ebdc..56c175ebae3c 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ /* diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index 35c90307d473..25d1e667a061 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ // #define DEBUG // error path messages, extra info -- cgit v1.2.3 From adf8d3ff6e982621c8cc2e8cac8e68d19fba6ac0 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 06:28:47 -0800 Subject: drivers/net/*: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek CC: Haiyang Zhang CC: "K. Y. Srinivasan" CC: Paul Mackerras CC: Ian Campbell CC: Wei Liu CC: Rusty Russell CC: "Michael S. Tsirkin" Signed-off-by: Jeff Kirsher Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 3 +-- drivers/net/bonding/bond_alb.h | 3 +-- drivers/net/bonding/bond_sysfs.c | 3 +-- drivers/net/hamradio/mkiss.c | 3 +-- drivers/net/hyperv/hyperv_net.h | 3 +-- drivers/net/hyperv/netvsc.c | 3 +-- drivers/net/hyperv/netvsc_drv.c | 3 +-- drivers/net/hyperv/rndis_filter.c | 3 +-- drivers/net/ppp/ppp_mppe.c | 3 +-- drivers/net/virtio_net.c | 3 +-- drivers/net/xen-netback/xenbus.c | 3 +-- 11 files changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 02872405d35d..2250b063ab89 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -12,8 +12,7 @@ * 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. + * with this program; if not, see . * * The full GNU General Public License is included in this distribution in the * file called LICENSE. diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index 4226044efd08..e09dd4bfafff 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -12,8 +12,7 @@ * 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. + * with this program; if not, see . * * The full GNU General Public License is included in this distribution in the * file called LICENSE. diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index abf5e106edc5..c778a26fb4da 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -12,8 +12,7 @@ * 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. + * with this program; if not, see . * * The full GNU General Public License is included in this distribution in the * file called LICENSE. diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 8e01c457015b..8a6c720a4cc9 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -9,8 +9,7 @@ * 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. + * with this program; if not, see . * * Copyright (C) Hans Alblas PE1AYX * Copyright (C) 2004, 05 Ralf Baechle DL5RB diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index e6fe0d80d612..a26eecb1212c 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -12,8 +12,7 @@ * 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. + * this program; if not, see . * * Authors: * Haiyang Zhang diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 2b0480416b31..93b485b96249 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -11,8 +11,7 @@ * 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. + * this program; if not, see . * * Authors: * Haiyang Zhang diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 524f713f6017..9184c82d5c50 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -11,8 +11,7 @@ * 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. + * this program; if not, see . * * Authors: * Haiyang Zhang diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 0775f0aefd1e..1084e5de3ceb 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -11,8 +11,7 @@ * 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. + * this program; if not, see . * * Authors: * Haiyang Zhang diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c index 9a1849a83e2a..911b21602ff2 100644 --- a/drivers/net/ppp/ppp_mppe.c +++ b/drivers/net/ppp/ppp_mppe.c @@ -27,8 +27,7 @@ * 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 + * along with this program; if not, see . * * * Changelog: diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 916241d16c67..5c24288814db 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ //#define DEBUG #include diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index f0358992b04f..7a206cffb062 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -15,8 +15,7 @@ * 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 + * along with this program; if not, see . */ #include "common.h" -- cgit v1.2.3 From 92d4ea6e412a023434b477c04fd5632aefb233d4 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 5 Dec 2013 20:42:58 -0800 Subject: tun: spelling fixes Fix spelling errors in tun driver. Signed-off-by: Stephen Hemminger Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/tun.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 782e38bfc1ee..5ac2877a89c3 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -110,7 +110,7 @@ struct tap_filter { unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; }; -/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for +/* DEFAULT_MAX_NUM_RSS_QUEUES were chosen to let the rx/tx queues allocated for * the netdevice to be fit in one page. So we can make sure the success of * memory allocation. TODO: increase the limit. */ #define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES @@ -119,7 +119,7 @@ struct tap_filter { #define TUN_FLOW_EXPIRE (3 * HZ) /* A tun_file connects an open character device to a tuntap netdevice. It - * also contains all socket related strctures (except sock_fprog and tap_filter) + * also contains all socket related structures (except sock_fprog and tap_filter) * to serve as one transmit queue for tuntap device. The sock_fprog and * tap_filter were kept in tun_struct since they were used for filtering for the * netdevice not for a specific queue (at least I didn't see the requirement for @@ -342,7 +342,7 @@ unlock: } /* We try to identify a flow through its rxhash first. The reason that - * we do not check rxq no. is becuase some cards(e.g 82599), chooses + * we do not check rxq no. is because some cards(e.g 82599), chooses * the rxq based on the txq where the last packet of the flow comes. As * the userspace application move between processors, we may get a * different rxq no. here. If we could not get rxhash, then we would @@ -531,7 +531,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte err = 0; - /* Re-attach the filter to presist device */ + /* Re-attach the filter to persist device */ if (!skip_filter && (tun->filter_attached == true)) { err = sk_attach_filter(&tun->fprog, tfile->socket.sk); if (!err) @@ -819,9 +819,9 @@ static void tun_poll_controller(struct net_device *dev) * Tun only receives frames when: * 1) the char device endpoint gets data from user space * 2) the tun socket gets a sendmsg call from user space - * Since both of those are syncronous operations, we are guaranteed + * Since both of those are synchronous operations, we are guaranteed * never to have pending data when we poll for it - * so theres nothing to do here but return. + * so there is nothing to do here but return. * We need this though so netpoll recognizes us as an interface that * supports polling, which enables bridge devices in virt setups to * still use netconsole -- cgit v1.2.3 From 5349d937739a752b3a3c0981543c13654af3bec9 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 6 Dec 2013 14:34:19 +0800 Subject: net/fddi: Replace local macro with PCI standard macro Replace local macro DFX_BUS_PCI() with PCI standard macro dev_is_pci(). Acked-by: Maciej W. Rozycki Signed-off-by: Yijing Wang Signed-off-by: David S. Miller --- drivers/net/fddi/defxx.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index 0b40e1c46f07..0344f71bf4a5 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -241,12 +241,6 @@ static char version[] = */ #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128) -#ifdef CONFIG_PCI -#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type) -#else -#define DFX_BUS_PCI(dev) 0 -#endif - #ifdef CONFIG_EISA #define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type) #else @@ -436,7 +430,7 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) static void dfx_get_bars(struct device *bdev, resource_size_t *bar_start, resource_size_t *bar_len) { - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -518,7 +512,7 @@ static const struct net_device_ops dfx_netdev_ops = { static int dfx_register(struct device *bdev) { static int version_disp; - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; const char *print_name = dev_name(bdev); @@ -667,7 +661,7 @@ static void dfx_bus_init(struct net_device *dev) { DFX_board_t *bp = netdev_priv(dev); struct device *bdev = bp->bus_dev; - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -813,7 +807,7 @@ static void dfx_bus_uninit(struct net_device *dev) { DFX_board_t *bp = netdev_priv(dev); struct device *bdev = bp->bus_dev; - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); u8 val; @@ -967,7 +961,7 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name, { DFX_board_t *bp = netdev_priv(dev); struct device *bdev = bp->bus_dev; - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -1877,7 +1871,7 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; DFX_board_t *bp = netdev_priv(dev); struct device *bdev = bp->bus_dev; - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); @@ -3579,7 +3573,7 @@ static void dfx_unregister(struct device *bdev) { struct net_device *dev = dev_get_drvdata(bdev); DFX_board_t *bp = netdev_priv(dev); - int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; resource_size_t bar_start = 0; /* pointer to port */ -- cgit v1.2.3 From d8535a0a02d6e772122339c131151dfaf007866b Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 6 Dec 2013 14:34:55 +0800 Subject: 3c59x/net: Use dev_is_pci() instead of hardcoding Use PCI standard macro dev_is_pci() instead of hardcoding. Signed-off-by: Yijing Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c59x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index ad5272b348f0..af24c3cf8215 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -693,7 +693,7 @@ DEFINE_WINDOW_IO(16) DEFINE_WINDOW_IO(32) #ifdef CONFIG_PCI -#define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL) +#define DEVICE_PCI(dev) ((dev_is_pci(dev)) ? to_pci_dev((dev)) : NULL) #else #define DEVICE_PCI(dev) NULL #endif -- cgit v1.2.3 From b6497b383f65dd1bc60ea1f5d70e157a268fbd15 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 6 Dec 2013 17:55:56 +0000 Subject: xen: privcmd: do not return pages which we have failed to unmap This failure represents a hypervisor issue, but if it does occur then nothing good can come of returning pages which still refer to a foreign owned page into the general allocation pool. Instead we are forced to leak them. Log that we have done so. The potential for failure only exists for autotranslated guest (e.g. ARM and x86 PVH). Signed-off-by: Ian Campbell Signed-off-by: Stefano Stabellini Reviewed-by: David Vrabel --- drivers/xen/privcmd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 8e74590fa1bb..569a13b9e856 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -533,12 +533,17 @@ static void privcmd_close(struct vm_area_struct *vma) { struct page **pages = vma->vm_private_data; int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + int rc; if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages) return; - xen_unmap_domain_mfn_range(vma, numpgs, pages); - free_xenballooned_pages(numpgs, pages); + rc = xen_unmap_domain_mfn_range(vma, numpgs, pages); + if (rc == 0) + free_xenballooned_pages(numpgs, pages); + else + pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n", + numpgs, rc); kfree(pages); } -- cgit v1.2.3 From 782df20c5f2ad45bd453e1f0fb58a49f251845b4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Nov 2013 14:15:46 +0900 Subject: usb: dwc3: pci: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 31443aeedcdb..665686e7c8cd 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -182,7 +182,7 @@ static void dwc3_pci_remove(struct pci_dev *pci) pci_disable_device(pci); } -static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { +static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), -- cgit v1.2.3 From ea25c37ea85b9d2b0ed3698f40753da005cfd4dc Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Nov 2013 14:16:09 +0900 Subject: usb: gadget: pch_udc: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 32d5e923750b..78a3d9289816 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -3210,7 +3210,7 @@ finished: return retval; } -static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { +static const struct pci_device_id pch_udc_pcidev_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, -- cgit v1.2.3 From 9510ecee62dff8cc603ea163bf72729c491fbe5b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 28 Nov 2013 14:16:30 +0900 Subject: usb: gadget: amd5536udc: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 54a1e2954cea..f0ff4a675e9d 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3338,7 +3338,7 @@ static int udc_remote_wakeup(struct udc *dev) } /* PCI device parameters */ -static DEFINE_PCI_DEVICE_TABLE(pci_id) = { +static const struct pci_device_id pci_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096), .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, -- cgit v1.2.3 From 2e79cb303010d5d2b7810c11bc5d1f09a8500405 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 5 Dec 2013 14:52:10 -0800 Subject: net: of_mdio: factor PHY registration from of_mdiobus_register Since commit 779d835e ("net: of_mdio: scan mdiobus for PHYs without reg property") we have two foreach loops which do pretty much the same thing. Factor the PHY device registration in a function helper: of_mdiobus_register_phy() which takes care of the details and allows for future PHY specific extensions. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 109 ++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index d5a57a9e329c..82485d2dac89 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -22,6 +22,47 @@ MODULE_AUTHOR("Grant Likely "); MODULE_LICENSE("GPL"); +static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child, + u32 addr) +{ + struct phy_device *phy; + bool is_c45; + int rc; + + is_c45 = of_device_is_compatible(child, + "ethernet-phy-ieee802.3-c45"); + + phy = get_phy_device(mdio, addr, is_c45); + if (!phy || IS_ERR(phy)) + return 1; + + if (mdio->irq) { + mdio->irq[addr] = + irq_of_parse_and_map(child, 0); + if (!mdio->irq[addr]) + mdio->irq[addr] = PHY_POLL; + } + + /* Associate the OF node with the device structure so it + * can be looked up later */ + of_node_get(child); + phy->dev.of_node = child; + + /* All data is now stored in the phy struct; + * register it */ + rc = phy_device_register(phy); + if (rc) { + phy_device_free(phy); + of_node_put(child); + return 1; + } + + dev_dbg(&mdio->dev, "registered phy %s at address %i\n", + child->name, addr); + + return 0; +} + /** * of_mdiobus_register - Register mii_bus and create PHYs from the device tree * @mdio: pointer to mii_bus structure @@ -32,11 +73,10 @@ MODULE_LICENSE("GPL"); */ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { - struct phy_device *phy; struct device_node *child; const __be32 *paddr; u32 addr; - bool is_c45, scanphys = false; + bool scanphys = false; int rc, i, len; /* Mask out all PHYs from auto probing. Instead the PHYs listed in @@ -73,38 +113,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) continue; } - if (mdio->irq) { - mdio->irq[addr] = irq_of_parse_and_map(child, 0); - if (!mdio->irq[addr]) - mdio->irq[addr] = PHY_POLL; - } - - is_c45 = of_device_is_compatible(child, - "ethernet-phy-ieee802.3-c45"); - phy = get_phy_device(mdio, addr, is_c45); - - if (!phy || IS_ERR(phy)) { - dev_err(&mdio->dev, - "cannot get PHY at address %i\n", - addr); - continue; - } - - /* Associate the OF node with the device structure so it - * can be looked up later */ - of_node_get(child); - phy->dev.of_node = child; - - /* All data is now stored in the phy struct; register it */ - rc = phy_device_register(phy); - if (rc) { - phy_device_free(phy); - of_node_put(child); + rc = of_mdiobus_register_phy(mdio, child, addr); + if (rc) continue; - } - - dev_dbg(&mdio->dev, "registered phy %s at address %i\n", - child->name, addr); } if (!scanphys) @@ -117,9 +128,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) if (paddr) continue; - is_c45 = of_device_is_compatible(child, - "ethernet-phy-ieee802.3-c45"); - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { /* skip already registered PHYs */ if (mdio->phy_map[addr]) @@ -129,34 +137,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) dev_info(&mdio->dev, "scan phy %s at address %i\n", child->name, addr); - phy = get_phy_device(mdio, addr, is_c45); - if (!phy || IS_ERR(phy)) + rc = of_mdiobus_register_phy(mdio, child, addr); + if (rc) continue; - - if (mdio->irq) { - mdio->irq[addr] = - irq_of_parse_and_map(child, 0); - if (!mdio->irq[addr]) - mdio->irq[addr] = PHY_POLL; - } - - /* Associate the OF node with the device structure so it - * can be looked up later */ - of_node_get(child); - phy->dev.of_node = child; - - /* All data is now stored in the phy struct; - * register it */ - rc = phy_device_register(phy); - if (rc) { - phy_device_free(phy); - of_node_put(child); - continue; - } - - dev_info(&mdio->dev, "registered phy %s at address %i\n", - child->name, addr); - break; } } -- cgit v1.2.3 From bed2f9ed2f3c4debe2e930c44ee95af980db7e20 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 5 Dec 2013 14:52:11 -0800 Subject: net: of_mdio: use PHY_MAX_ADDR constant Use the PHY_MAX_ADDR constant for checking if a MDIO bus address is valid instead of using a plain "32". Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 82485d2dac89..f93ebca0fcb7 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -107,7 +107,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) } addr = be32_to_cpup(paddr); - if (addr >= 32) { + if (addr >= PHY_MAX_ADDR) { dev_err(&mdio->dev, "%s PHY address %i is too large\n", child->full_name, addr); continue; -- cgit v1.2.3 From 7d976376560b72e187c96e4b18d059e0a0f9eba5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 5 Dec 2013 14:52:12 -0800 Subject: net: of_mdio: do not overwrite PHY interrupt configuration If irq_of_parse_and_map fails to find an interrupt line for a given PHY, we will force the PHY interrupt to be PHY_POLL, completely overriding the previous value that the MDIO bus may have set for us (e.g: PHY_IGNORE_INTERRUPT). In case of failure, just restore the previous value. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index f93ebca0fcb7..14feffc36964 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -27,7 +27,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi { struct phy_device *phy; bool is_c45; - int rc; + int rc, prev_irq; is_c45 = of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); @@ -37,10 +37,11 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi return 1; if (mdio->irq) { + prev_irq = mdio->irq[addr]; mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) - mdio->irq[addr] = PHY_POLL; + mdio->irq[addr] = prev_irq; } /* Associate the OF node with the device structure so it -- cgit v1.2.3 From 8fdade4be755af17a3d205d07f594f939f173504 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 5 Dec 2013 14:52:14 -0800 Subject: net: of_mdio: parse "max-speed" property to set PHY supported features The "max-speed" property is defined per the ePAPR specification to express the maximum speed a PHY supports. Use that property, if present to set the phydev->supported features which properly restricts the PHY within the range of defined speeds. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 14feffc36964..a43b8523c61e 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -22,12 +22,30 @@ MODULE_AUTHOR("Grant Likely "); MODULE_LICENSE("GPL"); +static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed) +{ + phydev->supported |= PHY_DEFAULT_FEATURES; + + switch (max_speed) { + default: + return; + + case SPEED_1000: + phydev->supported |= PHY_1000BT_FEATURES; + case SPEED_100: + phydev->supported |= PHY_100BT_FEATURES; + case SPEED_10: + phydev->supported |= PHY_10BT_FEATURES; + } +} + static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child, u32 addr) { struct phy_device *phy; bool is_c45; int rc, prev_irq; + u32 max_speed = 0; is_c45 = of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); @@ -58,8 +76,13 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi return 1; } + /* Set phydev->supported based on the "max-speed" property + * if present */ + if (!of_property_read_u32(child, "max-speed", &max_speed)) + of_set_phy_supported(phy, max_speed); + dev_dbg(&mdio->dev, "registered phy %s at address %i\n", - child->name, addr); + child->name, addr); return 0; } -- cgit v1.2.3 From b0ac9564061265dd14e6f8f777622e3401b82b4b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 5 Dec 2013 14:52:15 -0800 Subject: arc_emac: remove custom "max-speed" parsing code The ARC emac driver was the only in-tree to parse a PHY device 'max-speed' property but yet failed to do it correctly because 'max-speed' is supposed to set a PHY device supported features, not the advertising features as it was done. Now that of_mdiobus_register() takes care of doing that, remove the custom 'max-speed' parsing code. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/arc/emac.h | 2 -- drivers/net/ethernet/arc/emac_main.c | 20 +------------------- 2 files changed, 1 insertion(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h index dc08678bf9a4..928fac6dd10a 100644 --- a/drivers/net/ethernet/arc/emac.h +++ b/drivers/net/ethernet/arc/emac.h @@ -122,7 +122,6 @@ struct buffer_state { * @link: PHY's last seen link state. * @duplex: PHY's last set duplex mode. * @speed: PHY's last set speed. - * @max_speed: Maximum supported by current system network data-rate. */ struct arc_emac_priv { /* Devices */ @@ -152,7 +151,6 @@ struct arc_emac_priv { unsigned int link; unsigned int duplex; unsigned int speed; - unsigned int max_speed; }; /** diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index b2ffad1304d2..eedf2a5fc2be 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -381,17 +381,7 @@ static int arc_emac_open(struct net_device *ndev) phy_dev->autoneg = AUTONEG_ENABLE; phy_dev->speed = 0; phy_dev->duplex = 0; - phy_dev->advertising = phy_dev->supported; - - if (priv->max_speed > 100) { - phy_dev->advertising &= PHY_GBIT_FEATURES; - } else if (priv->max_speed <= 100) { - phy_dev->advertising &= PHY_BASIC_FEATURES; - if (priv->max_speed <= 10) { - phy_dev->advertising &= ~SUPPORTED_100baseT_Half; - phy_dev->advertising &= ~SUPPORTED_100baseT_Full; - } - } + phy_dev->advertising &= phy_dev->supported; priv->last_rx_bd = 0; @@ -704,14 +694,6 @@ static int arc_emac_probe(struct platform_device *pdev) /* Set poll rate so that it polls every 1 ms */ arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000); - /* Get max speed of operation from device tree */ - if (of_property_read_u32(pdev->dev.of_node, "max-speed", - &priv->max_speed)) { - dev_err(&pdev->dev, "failed to retrieve from device tree\n"); - err = -EINVAL; - goto out; - } - ndev->irq = irq; dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq); -- cgit v1.2.3 From ec99f76d281bae0194c6060417d3465ded94f0ed Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Fri, 6 Dec 2013 09:53:16 -0800 Subject: tg3: Don't add rxbds_empty to rx_over_errors rxbds_empty is an informational statistic signifying that a ring full condition was observed. It does not mean an overflow has occurred. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e35a1c5fc9b1..886d50b72cde 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -11746,8 +11746,6 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats) get_stat64(&hw_stats->rx_frame_too_long_errors) + get_stat64(&hw_stats->rx_undersize_packets); - stats->rx_over_errors = old_stats->rx_over_errors + - get_stat64(&hw_stats->rxbds_empty); stats->rx_frame_errors = old_stats->rx_frame_errors + get_stat64(&hw_stats->rx_align_errors); stats->tx_aborted_errors = old_stats->tx_aborted_errors + -- cgit v1.2.3 From 7c786065b12344ada19e11fa1043555dfeda478a Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Fri, 6 Dec 2013 09:53:17 -0800 Subject: tg3: Add flag to disable 1G Half Duplex advertisement Some link partners have issues if the non-standard 1G half duplex is advertised. This patch adds support for an nvram setting to disable the advertisement. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 28 +++++++++++++++++++++------- drivers/net/ethernet/broadcom/tg3.h | 4 ++++ 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 886d50b72cde..e8847ccc6399 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4403,9 +4403,12 @@ static void tg3_phy_copper_begin(struct tg3 *tp) if (tg3_flag(tp, WOL_SPEED_100MB)) adv |= ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK) - adv |= ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full; + if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK) { + if (!(tp->phy_flags & + TG3_PHYFLG_DISABLE_1G_HD_ADV)) + adv |= ADVERTISED_1000baseT_Half; + adv |= ADVERTISED_1000baseT_Full; + } fc = FLOW_CTRL_TX | FLOW_CTRL_RX; } else { @@ -14917,7 +14920,8 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; - u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id; + u32 cfg2 = 0, cfg4 = 0, cfg5 = 0; + u32 nic_phy_id, ver, eeprom_phy_id; int eeprom_phy_serdes = 0; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); @@ -14934,6 +14938,11 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (tg3_asic_rev(tp) == ASIC_REV_5785) tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4); + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) + tg3_read_mem(tp, NIC_SRAM_DATA_CFG_5, &cfg5); + if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) eeprom_phy_serdes = 1; @@ -15086,6 +15095,9 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN); if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN) tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN); + + if (cfg5 & NIC_SRAM_DISABLE_1G_HALF_ADV) + tp->phy_flags |= TG3_PHYFLG_DISABLE_1G_HD_ADV; } done: if (tg3_flag(tp, WOL_CAP)) @@ -15181,9 +15193,11 @@ static void tg3_phy_init_link_config(struct tg3 *tp) { u32 adv = ADVERTISED_Autoneg; - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) - adv |= ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full; + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { + if (!(tp->phy_flags & TG3_PHYFLG_DISABLE_1G_HD_ADV)) + adv |= ADVERTISED_1000baseT_Half; + adv |= ADVERTISED_1000baseT_Full; + } if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) adv |= ADVERTISED_100baseT_Half | diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 5c3835aa1e1b..e128f37282d7 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2226,6 +2226,9 @@ #define NIC_SRAM_CPMUSTAT_SIG 0x0000362c #define NIC_SRAM_CPMUSTAT_SIG_MSK 0x0000ffff +#define NIC_SRAM_DATA_CFG_5 0x00000e0c +#define NIC_SRAM_DISABLE_1G_HALF_ADV 0x00000002 + #define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000 #define NIC_SRAM_DMA_DESC_POOL_BASE 0x00002000 @@ -3325,6 +3328,7 @@ struct tg3 { #define TG3_PHYFLG_1G_ON_VAUX_OK 0x00080000 #define TG3_PHYFLG_KEEP_LINK_ON_PWRDN 0x00100000 #define TG3_PHYFLG_MDIX_STATE 0x00200000 +#define TG3_PHYFLG_DISABLE_1G_HD_ADV 0x00400000 u32 led_ctrl; u32 phy_otp; -- cgit v1.2.3 From efe8f0eaaed3c5ebc19cc34ddf012dfdf6f3747d Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Fri, 6 Dec 2013 09:53:18 -0800 Subject: tg3: Fix bit definition for the nvram Auto Power Down setting The APD bit is 14 and not bit 10. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index e128f37282d7..e4da9d7834ce 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2204,7 +2204,7 @@ #define NIC_SRAM_DATA_CFG_2 0x00000d38 -#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00000400 +#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00004000 #define SHASTA_EXT_LED_MODE_MASK 0x00018000 #define SHASTA_EXT_LED_LEGACY 0x00000000 #define SHASTA_EXT_LED_SHARED 0x00008000 -- cgit v1.2.3 From 94962f7fddb0fb1373ec284a5b7b9e10ff1859ec Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Fri, 6 Dec 2013 09:53:19 -0800 Subject: tg3: Expand multicast drop counter miscounting fix to 5762 commit 4d95847381228639844c7197deb8b2211274ef22 - "tg3: Workaround rx_discards stat bug", added a workaround for miscounted statistics for multicast packets. This fix needs to be applied to the 5762. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e8847ccc6399..7cba13969342 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -9969,6 +9969,7 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) if (tg3_asic_rev(tp) == ASIC_REV_5719) val |= BUFMGR_MODE_NO_TX_UNDERRUN; if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5762 || tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 || tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0) val |= BUFMGR_MODE_MBLOW_ATTN_ENAB; @@ -10754,6 +10755,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT); if (tg3_asic_rev(tp) != ASIC_REV_5717 && + tg3_asic_rev(tp) != ASIC_REV_5762 && tg3_chip_rev_id(tp) != CHIPREV_ID_5719_A0 && tg3_chip_rev_id(tp) != CHIPREV_ID_5720_A0) { TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); @@ -16545,6 +16547,7 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) /* Set these bits to enable statistics workaround. */ if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5762 || tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 || tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0) { tp->coalesce_mode |= HOSTCC_MODE_ATTN; -- cgit v1.2.3 From 941c22532f40dafa1320adbbc3776e7971bc0764 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Fri, 6 Dec 2013 09:53:20 -0800 Subject: tg3: Update version to 3.135 Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 7cba13969342..9a4a601ae6cf 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -94,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 134 +#define TG3_MIN_NUM 135 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "Sep 16, 2013" +#define DRV_MODULE_RELDATE "Nov 14, 2013" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 -- cgit v1.2.3 From 59566b6e8cc8f8a05022e0f01a1b90974003f092 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 7 Dec 2013 04:13:03 +0800 Subject: vhost: remove the dead branch Since vhost_dev_init() forever return 0, some branches are never run, therefore need to be removed. Signed-off-by: Zhi Yong Wu Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/vhost/net.c | 9 ++------- drivers/vhost/scsi.c | 7 +------ drivers/vhost/test.c | 8 +------- drivers/vhost/vhost.c | 4 +--- drivers/vhost/vhost.h | 2 +- 5 files changed, 6 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 831eb4fd197d..9a68409580d5 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -683,7 +683,7 @@ static int vhost_net_open(struct inode *inode, struct file *f) struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL); struct vhost_dev *dev; struct vhost_virtqueue **vqs; - int r, i; + int i; if (!n) return -ENOMEM; @@ -706,12 +706,7 @@ static int vhost_net_open(struct inode *inode, struct file *f) n->vqs[i].vhost_hlen = 0; n->vqs[i].sock_hlen = 0; } - r = vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX); - if (r < 0) { - kfree(n); - kfree(vqs); - return r; - } + vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX); vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, POLLOUT, dev); vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, POLLIN, dev); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index f175629513ed..1e4c75c5b36b 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1417,18 +1417,13 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) vqs[i] = &vs->vqs[i].vq; vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; } - r = vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ); + vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ); tcm_vhost_init_inflight(vs, NULL); - if (r < 0) - goto err_init; - f->private_data = vs; return 0; -err_init: - kfree(vqs); err_vqs: vhost_scsi_free(vs); err_vs: diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 339eae85859a..c2a54fbf7f99 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -104,7 +104,6 @@ static int vhost_test_open(struct inode *inode, struct file *f) struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL); struct vhost_dev *dev; struct vhost_virtqueue **vqs; - int r; if (!n) return -ENOMEM; @@ -117,12 +116,7 @@ static int vhost_test_open(struct inode *inode, struct file *f) dev = &n->dev; vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ]; n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick; - r = vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX); - if (r < 0) { - kfree(vqs); - kfree(n); - return r; - } + vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX); f->private_data = n; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 69068e0d8f31..78987e481bc6 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -290,7 +290,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev) vhost_vq_free_iovecs(dev->vqs[i]); } -long vhost_dev_init(struct vhost_dev *dev, +void vhost_dev_init(struct vhost_dev *dev, struct vhost_virtqueue **vqs, int nvqs) { struct vhost_virtqueue *vq; @@ -319,8 +319,6 @@ long vhost_dev_init(struct vhost_dev *dev, vhost_poll_init(&vq->poll, vq->handle_kick, POLLIN, dev); } - - return 0; } EXPORT_SYMBOL_GPL(vhost_dev_init); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 4465ed5f316d..35eeb2a1bada 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -127,7 +127,7 @@ struct vhost_dev { struct task_struct *worker; }; -long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs); +void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs); long vhost_dev_set_owner(struct vhost_dev *dev); bool vhost_dev_has_owner(struct vhost_dev *dev); long vhost_dev_check_owner(struct vhost_dev *); -- cgit v1.2.3 From 359d44d764f5e2a8e5bd9aee66f89f240ad7b622 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 7 Dec 2013 04:13:04 +0800 Subject: macvtap: remove the dead branch Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 9093004f9b63..f599c47524f4 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -588,7 +588,7 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, return 0; } -static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, +static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, struct virtio_net_hdr *vnet_hdr) { memset(vnet_hdr, 0, sizeof(*vnet_hdr)); @@ -619,8 +619,6 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; } /* else everything is zero */ - - return 0; } /* Get packet from user space buffer */ @@ -778,9 +776,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if ((len -= vnet_hdr_len) < 0) return -EINVAL; - ret = macvtap_skb_to_vnet_hdr(skb, &vnet_hdr); - if (ret) - return ret; + macvtap_skb_to_vnet_hdr(skb, &vnet_hdr); if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) return -EFAULT; -- cgit v1.2.3 From 55ec8e25cd9752060c80f926707d0187ea918d73 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 7 Dec 2013 04:13:05 +0800 Subject: macvtap: remove unused parameter in macvtap_do_read() Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index f599c47524f4..4c6f84c79e95 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -819,7 +819,7 @@ done: return ret ? ret : copied; } -static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, +static ssize_t macvtap_do_read(struct macvtap_queue *q, const struct iovec *iv, unsigned long len, int noblock) { @@ -870,7 +870,7 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, goto out; } - ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); + ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ out: return ret; @@ -1102,7 +1102,7 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, int ret; if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) return -EINVAL; - ret = macvtap_do_read(q, iocb, m->msg_iov, total_len, + ret = macvtap_do_read(q, m->msg_iov, total_len, flags & MSG_DONTWAIT); if (ret > total_len) { m->msg_flags |= MSG_TRUNC; -- cgit v1.2.3 From f96eb74c84ebb09a03031f7f1e51789a928f9de0 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 7 Dec 2013 04:13:06 +0800 Subject: tun: remove unused parameter in tun_do_read() Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller --- drivers/net/tun.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5ac2877a89c3..6b0b2a057a47 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1289,8 +1289,7 @@ done: } static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, - struct kiocb *iocb, const struct iovec *iv, - ssize_t len, int noblock) + const struct iovec *iv, ssize_t len, int noblock) { DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; @@ -1353,7 +1352,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, goto out; } - ret = tun_do_read(tun, tfile, iocb, iv, len, + ret = tun_do_read(tun, tfile, iv, len, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); out: @@ -1452,7 +1451,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, SOL_PACKET, TUN_TX_TIMESTAMP); goto out; } - ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len, + ret = tun_do_read(tun, tfile, m->msg_iov, total_len, flags & MSG_DONTWAIT); if (ret > total_len) { m->msg_flags |= MSG_TRUNC; -- cgit v1.2.3 From 67c21fc803de62369dfc8e41dab352107d7f06ef Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Dec 2013 01:02:34 -0200 Subject: usb: phy: phy-mxs-usb: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Acked-by: Peter Chen Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-mxs-usb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index fdd33b44dbd3..797c45b9ddab 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -63,9 +63,13 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) static int mxs_phy_init(struct usb_phy *phy) { + int ret; struct mxs_phy *mxs_phy = to_mxs_phy(phy); - clk_prepare_enable(mxs_phy->clk); + ret = clk_prepare_enable(mxs_phy->clk); + if (ret) + return ret; + return mxs_phy_hw_init(mxs_phy); } @@ -81,6 +85,7 @@ static void mxs_phy_shutdown(struct usb_phy *phy) static int mxs_phy_suspend(struct usb_phy *x, int suspend) { + int ret; struct mxs_phy *mxs_phy = to_mxs_phy(x); if (suspend) { @@ -89,7 +94,9 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend) x->io_priv + HW_USBPHY_CTRL_SET); clk_disable_unprepare(mxs_phy->clk); } else { - clk_prepare_enable(mxs_phy->clk); + ret = clk_prepare_enable(mxs_phy->clk); + if (ret) + return ret; writel(BM_USBPHY_CTRL_CLKGATE, x->io_priv + HW_USBPHY_CTRL_CLR); writel(0, x->io_priv + HW_USBPHY_PWD); -- cgit v1.2.3 From 851dd02b4f1fdb437586190f87217e3382a736bd Mon Sep 17 00:00:00 2001 From: Chris Ruehl Date: Wed, 4 Dec 2013 10:02:44 +0800 Subject: usb: phy-tegra-usb.c: wrong pointer check for remap UTMI usb: phy-tegra-usb.c: wrong pointer check for remap UTMI A wrong pointer was used to test the result of devm_ioremap() Acked-by: Stephen Warren Reviewed-by: Thierry Reding Signed-off-by: Chris Ruehl Acked-by: Venu Byravarasu Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 82232acf1ab6..bbe4f8e6e8d7 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -876,7 +876,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!tegra_phy->regs) { + if (!tegra_phy->pad_regs) { dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); return -ENOMEM; } -- cgit v1.2.3 From 449d2ba613a551046544ea75b99563ee643c8d7c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 6 Dec 2013 16:13:06 +0200 Subject: usb: omap1: OTG controller driver Transceivers need to manage OTG controller state on OMAP1 to enable switching between peripheral and host modes. Provide a driver for that. Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- drivers/usb/phy/Kconfig | 10 +++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-omap-otg.c | 169 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/usb/phy/phy-omap-otg.c (limited to 'drivers') diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 921a9f43e309..0dbab6f5c2d4 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -142,6 +142,16 @@ config USB_GPIO_VBUS optionally control of a D+ pullup GPIO as well as a VBUS current limit regulator. +config OMAP_OTG + tristate "OMAP USB OTG controller driver" + depends on ARCH_OMAP_OTG && EXTCON + help + Enable this to support some transceivers on OMAP1 platforms. OTG + controller is needed to switch between host and peripheral modes. + + This driver can also be built as a module. If so, the module + will be called omap-otg. + config USB_ISP1301 tristate "NXP ISP1301 USB transceiver support" depends on USB || USB_GADGET diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 1bf6c083a36e..64a9345e5633 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o +obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c new file mode 100644 index 000000000000..11598cdb3189 --- /dev/null +++ b/drivers/usb/phy/phy-omap-otg.c @@ -0,0 +1,169 @@ +/* + * OMAP OTG controller driver + * + * Based on code from tahvo-usb.c and isp1301_omap.c drivers. + * + * Copyright (C) 2005-2006 Nokia Corporation + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2004 David Brownell + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct otg_device { + void __iomem *base; + bool id; + bool vbus; + struct extcon_specific_cable_nb vbus_dev; + struct extcon_specific_cable_nb id_dev; + struct notifier_block vbus_nb; + struct notifier_block id_nb; +}; + +#define OMAP_OTG_CTRL 0x0c +#define OMAP_OTG_ASESSVLD (1 << 20) +#define OMAP_OTG_BSESSEND (1 << 19) +#define OMAP_OTG_BSESSVLD (1 << 18) +#define OMAP_OTG_VBUSVLD (1 << 17) +#define OMAP_OTG_ID (1 << 16) +#define OMAP_OTG_XCEIV_OUTPUTS \ + (OMAP_OTG_ASESSVLD | OMAP_OTG_BSESSEND | OMAP_OTG_BSESSVLD | \ + OMAP_OTG_VBUSVLD | OMAP_OTG_ID) + +static void omap_otg_ctrl(struct otg_device *otg_dev, u32 outputs) +{ + u32 l; + + l = readl(otg_dev->base + OMAP_OTG_CTRL); + l &= ~OMAP_OTG_XCEIV_OUTPUTS; + l |= outputs; + writel(l, otg_dev->base + OMAP_OTG_CTRL); +} + +static void omap_otg_set_mode(struct otg_device *otg_dev) +{ + if (!otg_dev->id && otg_dev->vbus) + /* Set B-session valid. */ + omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSVLD); + else if (otg_dev->vbus) + /* Set A-session valid. */ + omap_otg_ctrl(otg_dev, OMAP_OTG_ASESSVLD); + else if (!otg_dev->id) + /* Set B-session end to indicate no VBUS. */ + omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSEND); +} + +static int omap_otg_id_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct otg_device *otg_dev = container_of(nb, struct otg_device, id_nb); + + otg_dev->id = event; + omap_otg_set_mode(otg_dev); + + return NOTIFY_DONE; +} + +static int omap_otg_vbus_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct otg_device *otg_dev = container_of(nb, struct otg_device, + vbus_nb); + + otg_dev->vbus = event; + omap_otg_set_mode(otg_dev); + + return NOTIFY_DONE; +} + +static int omap_otg_probe(struct platform_device *pdev) +{ + const struct omap_usb_config *config = pdev->dev.platform_data; + struct otg_device *otg_dev; + struct extcon_dev *extcon; + int ret; + u32 rev; + + if (!config || !config->extcon) + return -ENODEV; + + extcon = extcon_get_extcon_dev(config->extcon); + if (!extcon) + return -EPROBE_DEFER; + + otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL); + if (!otg_dev) + return -ENOMEM; + + otg_dev->base = devm_ioremap_resource(&pdev->dev, &pdev->resource[0]); + if (IS_ERR(otg_dev->base)) + return PTR_ERR(otg_dev->base); + + otg_dev->id_nb.notifier_call = omap_otg_id_notifier; + otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier; + + ret = extcon_register_interest(&otg_dev->id_dev, config->extcon, + "USB-HOST", &otg_dev->id_nb); + if (ret) + return ret; + + ret = extcon_register_interest(&otg_dev->vbus_dev, config->extcon, + "USB", &otg_dev->vbus_nb); + if (ret) { + extcon_unregister_interest(&otg_dev->id_dev); + return ret; + } + + otg_dev->id = extcon_get_cable_state(extcon, "USB-HOST"); + otg_dev->vbus = extcon_get_cable_state(extcon, "USB"); + omap_otg_set_mode(otg_dev); + + rev = readl(otg_dev->base); + + dev_info(&pdev->dev, + "OMAP USB OTG controller rev %d.%d (%s, id=%d, vbus=%d)\n", + (rev >> 4) & 0xf, rev & 0xf, config->extcon, otg_dev->id, + otg_dev->vbus); + + return 0; +} + +static int omap_otg_remove(struct platform_device *pdev) +{ + struct otg_device *otg_dev = platform_get_drvdata(pdev); + + extcon_unregister_interest(&otg_dev->id_dev); + extcon_unregister_interest(&otg_dev->vbus_dev); + + return 0; +} + +static struct platform_driver omap_otg_driver = { + .probe = omap_otg_probe, + .remove = omap_otg_remove, + .driver = { + .owner = THIS_MODULE, + .name = "omap_otg", + }, +}; +module_platform_driver(omap_otg_driver); + +MODULE_DESCRIPTION("OMAP USB OTG controller driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Aaro Koskinen "); -- cgit v1.2.3 From 9ba96ae5074c9f15b357919e704ceba2bd34972d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 6 Dec 2013 16:13:07 +0200 Subject: usb: omap1: Tahvo USB transceiver driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Tahvo USB transceiver driver. Based on old code from linux-omap tree. The original driver was written by Juha Yrjölä, Tony Lindgren, and Timo Teräs. Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- Documentation/ABI/testing/sysfs-platform-tahvo-usb | 16 + drivers/usb/phy/Kconfig | 15 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-tahvo.c | 463 +++++++++++++++++++++ 4 files changed, 495 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-platform-tahvo-usb create mode 100644 drivers/usb/phy/phy-tahvo.c (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-platform-tahvo-usb b/Documentation/ABI/testing/sysfs-platform-tahvo-usb new file mode 100644 index 000000000000..f6e20ce4b538 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-tahvo-usb @@ -0,0 +1,16 @@ +What: /sys/bus/platform/devices/tahvo-usb/otg_mode +Date: December 2013 +Contact: Aaro Koskinen +Description: + Set or read the current OTG mode. Valid values are "host" and + "peripheral". + + Reading: returns the current mode. + +What: /sys/bus/platform/devices/tahvo-usb/vbus +Date: December 2013 +Contact: Aaro Koskinen +Description: + Read the current VBUS state. + + Reading: returns "on" or "off". diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 0dbab6f5c2d4..4f22762f3d6f 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -152,6 +152,21 @@ config OMAP_OTG This driver can also be built as a module. If so, the module will be called omap-otg. +config TAHVO_USB + tristate "Tahvo USB transceiver driver" + depends on MFD_RETU && EXTCON + select USB_PHY + help + Enable this to support USB transceiver on Tahvo. This is used + at least on Nokia 770. + +config TAHVO_USB_HOST_BY_DEFAULT + depends on TAHVO_USB + boolean "Device in USB host mode by default" + help + Say Y here, if you want the device to enter USB host mode + by default on bootup. + config USB_ISP1301 tristate "NXP ISP1301 USB transceiver support" depends on USB || USB_GADGET diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 64a9345e5633..9b3be9e0aeb4 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb.o obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o +obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c new file mode 100644 index 000000000000..8bb833e22d64 --- /dev/null +++ b/drivers/usb/phy/phy-tahvo.c @@ -0,0 +1,463 @@ +/* + * Tahvo USB transceiver driver + * + * Copyright (C) 2005-2006 Nokia Corporation + * + * Parts copied from isp1301_omap.c. + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2004 David Brownell + * + * Original driver written by Juha Yrjölä, Tony Lindgren and Timo Teräs. + * Modified for Retu/Tahvo MFD by Aaro Koskinen. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "tahvo-usb" + +#define TAHVO_REG_IDSR 0x02 +#define TAHVO_REG_USBR 0x06 + +#define USBR_SLAVE_CONTROL (1 << 8) +#define USBR_VPPVIO_SW (1 << 7) +#define USBR_SPEED (1 << 6) +#define USBR_REGOUT (1 << 5) +#define USBR_MASTER_SW2 (1 << 4) +#define USBR_MASTER_SW1 (1 << 3) +#define USBR_SLAVE_SW (1 << 2) +#define USBR_NSUSPEND (1 << 1) +#define USBR_SEMODE (1 << 0) + +#define TAHVO_MODE_HOST 0 +#define TAHVO_MODE_PERIPHERAL 1 + +struct tahvo_usb { + struct platform_device *pt_dev; + struct usb_phy phy; + int vbus_state; + struct mutex serialize; + struct clk *ick; + int irq; + int tahvo_mode; + struct extcon_dev extcon; +}; + +static const char *tahvo_cable[] = { + "USB-HOST", + "USB", + NULL, +}; + +static ssize_t vbus_state_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct tahvo_usb *tu = dev_get_drvdata(device); + return sprintf(buf, "%s\n", tu->vbus_state ? "on" : "off"); +} +static DEVICE_ATTR(vbus, 0444, vbus_state_show, NULL); + +static void check_vbus_state(struct tahvo_usb *tu) +{ + struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); + int reg, prev_state; + + reg = retu_read(rdev, TAHVO_REG_IDSR); + if (reg & TAHVO_STAT_VBUS) { + switch (tu->phy.state) { + case OTG_STATE_B_IDLE: + /* Enable the gadget driver */ + if (tu->phy.otg->gadget) + usb_gadget_vbus_connect(tu->phy.otg->gadget); + tu->phy.state = OTG_STATE_B_PERIPHERAL; + break; + case OTG_STATE_A_IDLE: + /* + * Session is now valid assuming the USB hub is driving + * Vbus. + */ + tu->phy.state = OTG_STATE_A_HOST; + break; + default: + break; + } + dev_info(&tu->pt_dev->dev, "USB cable connected\n"); + } else { + switch (tu->phy.state) { + case OTG_STATE_B_PERIPHERAL: + if (tu->phy.otg->gadget) + usb_gadget_vbus_disconnect(tu->phy.otg->gadget); + tu->phy.state = OTG_STATE_B_IDLE; + break; + case OTG_STATE_A_HOST: + tu->phy.state = OTG_STATE_A_IDLE; + break; + default: + break; + } + dev_info(&tu->pt_dev->dev, "USB cable disconnected\n"); + } + + prev_state = tu->vbus_state; + tu->vbus_state = reg & TAHVO_STAT_VBUS; + if (prev_state != tu->vbus_state) { + extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state); + sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state"); + } +} + +static void tahvo_usb_become_host(struct tahvo_usb *tu) +{ + struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); + + extcon_set_cable_state(&tu->extcon, "USB-HOST", true); + + /* Power up the transceiver in USB host mode */ + retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND | + USBR_MASTER_SW2 | USBR_MASTER_SW1); + tu->phy.state = OTG_STATE_A_IDLE; + + check_vbus_state(tu); +} + +static void tahvo_usb_stop_host(struct tahvo_usb *tu) +{ + tu->phy.state = OTG_STATE_A_IDLE; +} + +static void tahvo_usb_become_peripheral(struct tahvo_usb *tu) +{ + struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); + + extcon_set_cable_state(&tu->extcon, "USB-HOST", false); + + /* Power up transceiver and set it in USB peripheral mode */ + retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT | + USBR_NSUSPEND | USBR_SLAVE_SW); + tu->phy.state = OTG_STATE_B_IDLE; + + check_vbus_state(tu); +} + +static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu) +{ + if (tu->phy.otg->gadget) + usb_gadget_vbus_disconnect(tu->phy.otg->gadget); + tu->phy.state = OTG_STATE_B_IDLE; +} + +static void tahvo_usb_power_off(struct tahvo_usb *tu) +{ + struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); + + /* Disable gadget controller if any */ + if (tu->phy.otg->gadget) + usb_gadget_vbus_disconnect(tu->phy.otg->gadget); + + /* Power off transceiver */ + retu_write(rdev, TAHVO_REG_USBR, 0); + tu->phy.state = OTG_STATE_UNDEFINED; +} + +static int tahvo_usb_set_suspend(struct usb_phy *dev, int suspend) +{ + struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, phy); + struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); + u16 w; + + dev_dbg(&tu->pt_dev->dev, "%s\n", __func__); + + w = retu_read(rdev, TAHVO_REG_USBR); + if (suspend) + w &= ~USBR_NSUSPEND; + else + w |= USBR_NSUSPEND; + retu_write(rdev, TAHVO_REG_USBR, w); + + return 0; +} + +static int tahvo_usb_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + struct tahvo_usb *tu = container_of(otg->phy, struct tahvo_usb, phy); + + dev_dbg(&tu->pt_dev->dev, "%s %p\n", __func__, host); + + if (otg == NULL) + return -ENODEV; + + mutex_lock(&tu->serialize); + + if (host == NULL) { + if (tu->tahvo_mode == TAHVO_MODE_HOST) + tahvo_usb_power_off(tu); + otg->host = NULL; + mutex_unlock(&tu->serialize); + return 0; + } + + if (tu->tahvo_mode == TAHVO_MODE_HOST) { + otg->host = NULL; + tahvo_usb_become_host(tu); + } + + otg->host = host; + + mutex_unlock(&tu->serialize); + + return 0; +} + +static int tahvo_usb_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) +{ + struct tahvo_usb *tu = container_of(otg->phy, struct tahvo_usb, phy); + + dev_dbg(&tu->pt_dev->dev, "%s %p\n", __func__, gadget); + + if (!otg) + return -ENODEV; + + mutex_lock(&tu->serialize); + + if (!gadget) { + if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL) + tahvo_usb_power_off(tu); + tu->phy.otg->gadget = NULL; + mutex_unlock(&tu->serialize); + return 0; + } + + tu->phy.otg->gadget = gadget; + if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL) + tahvo_usb_become_peripheral(tu); + + mutex_unlock(&tu->serialize); + + return 0; +} + +static irqreturn_t tahvo_usb_vbus_interrupt(int irq, void *_tu) +{ + struct tahvo_usb *tu = _tu; + + mutex_lock(&tu->serialize); + check_vbus_state(tu); + mutex_unlock(&tu->serialize); + + return IRQ_HANDLED; +} + +static ssize_t otg_mode_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct tahvo_usb *tu = dev_get_drvdata(device); + + switch (tu->tahvo_mode) { + case TAHVO_MODE_HOST: + return sprintf(buf, "host\n"); + case TAHVO_MODE_PERIPHERAL: + return sprintf(buf, "peripheral\n"); + } + + return -EINVAL; +} + +static ssize_t otg_mode_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct tahvo_usb *tu = dev_get_drvdata(device); + int r; + + mutex_lock(&tu->serialize); + if (count >= 4 && strncmp(buf, "host", 4) == 0) { + if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL) + tahvo_usb_stop_peripheral(tu); + tu->tahvo_mode = TAHVO_MODE_HOST; + if (tu->phy.otg->host) { + dev_info(device, "HOST mode: host controller present\n"); + tahvo_usb_become_host(tu); + } else { + dev_info(device, "HOST mode: no host controller, powering off\n"); + tahvo_usb_power_off(tu); + } + r = strlen(buf); + } else if (count >= 10 && strncmp(buf, "peripheral", 10) == 0) { + if (tu->tahvo_mode == TAHVO_MODE_HOST) + tahvo_usb_stop_host(tu); + tu->tahvo_mode = TAHVO_MODE_PERIPHERAL; + if (tu->phy.otg->gadget) { + dev_info(device, "PERIPHERAL mode: gadget driver present\n"); + tahvo_usb_become_peripheral(tu); + } else { + dev_info(device, "PERIPHERAL mode: no gadget driver, powering off\n"); + tahvo_usb_power_off(tu); + } + r = strlen(buf); + } else { + r = -EINVAL; + } + mutex_unlock(&tu->serialize); + + return r; +} +static DEVICE_ATTR(otg_mode, 0644, otg_mode_show, otg_mode_store); + +static struct attribute *tahvo_attributes[] = { + &dev_attr_vbus.attr, + &dev_attr_otg_mode.attr, + NULL +}; + +static struct attribute_group tahvo_attr_group = { + .attrs = tahvo_attributes, +}; + +static int tahvo_usb_probe(struct platform_device *pdev) +{ + struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent); + struct tahvo_usb *tu; + int ret; + + tu = devm_kzalloc(&pdev->dev, sizeof(*tu), GFP_KERNEL); + if (!tu) + return -ENOMEM; + + tu->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*tu->phy.otg), + GFP_KERNEL); + if (!tu->phy.otg) + return -ENOMEM; + + tu->pt_dev = pdev; + + /* Default mode */ +#ifdef CONFIG_TAHVO_USB_HOST_BY_DEFAULT + tu->tahvo_mode = TAHVO_MODE_HOST; +#else + tu->tahvo_mode = TAHVO_MODE_PERIPHERAL; +#endif + + mutex_init(&tu->serialize); + + tu->ick = devm_clk_get(&pdev->dev, "usb_l4_ick"); + if (!IS_ERR(tu->ick)) + clk_enable(tu->ick); + + /* + * Set initial state, so that we generate kevents only on state changes. + */ + tu->vbus_state = retu_read(rdev, TAHVO_REG_IDSR) & TAHVO_STAT_VBUS; + + tu->extcon.name = DRIVER_NAME; + tu->extcon.supported_cable = tahvo_cable; + tu->extcon.dev.parent = &pdev->dev; + + ret = extcon_dev_register(&tu->extcon); + if (ret) { + dev_err(&pdev->dev, "could not register extcon device: %d\n", + ret); + goto err_disable_clk; + } + + /* Set the initial cable state. */ + extcon_set_cable_state(&tu->extcon, "USB-HOST", + tu->tahvo_mode == TAHVO_MODE_HOST); + extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state); + + /* Create OTG interface */ + tahvo_usb_power_off(tu); + tu->phy.dev = &pdev->dev; + tu->phy.state = OTG_STATE_UNDEFINED; + tu->phy.label = DRIVER_NAME; + tu->phy.set_suspend = tahvo_usb_set_suspend; + + tu->phy.otg->phy = &tu->phy; + tu->phy.otg->set_host = tahvo_usb_set_host; + tu->phy.otg->set_peripheral = tahvo_usb_set_peripheral; + + ret = usb_add_phy(&tu->phy, USB_PHY_TYPE_USB2); + if (ret < 0) { + dev_err(&pdev->dev, "cannot register USB transceiver: %d\n", + ret); + goto err_extcon_unreg; + } + + dev_set_drvdata(&pdev->dev, tu); + + tu->irq = platform_get_irq(pdev, 0); + ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt, 0, + "tahvo-vbus", tu); + if (ret) { + dev_err(&pdev->dev, "could not register tahvo-vbus irq: %d\n", + ret); + goto err_remove_phy; + } + + /* Attributes */ + ret = sysfs_create_group(&pdev->dev.kobj, &tahvo_attr_group); + if (ret) { + dev_err(&pdev->dev, "cannot create sysfs group: %d\n", ret); + goto err_free_irq; + } + + return 0; + +err_free_irq: + free_irq(tu->irq, tu); +err_remove_phy: + usb_remove_phy(&tu->phy); +err_extcon_unreg: + extcon_dev_unregister(&tu->extcon); +err_disable_clk: + if (!IS_ERR(tu->ick)) + clk_disable(tu->ick); + + return ret; +} + +static int tahvo_usb_remove(struct platform_device *pdev) +{ + struct tahvo_usb *tu = platform_get_drvdata(pdev); + + sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group); + free_irq(tu->irq, tu); + usb_remove_phy(&tu->phy); + extcon_dev_unregister(&tu->extcon); + if (!IS_ERR(tu->ick)) + clk_disable(tu->ick); + + return 0; +} + +static struct platform_driver tahvo_usb_driver = { + .probe = tahvo_usb_probe, + .remove = tahvo_usb_remove, + .driver = { + .name = "tahvo-usb", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(tahvo_usb_driver); + +MODULE_DESCRIPTION("Tahvo USB transceiver driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Juha Yrjölä, Tony Lindgren, and Timo Teräs"); +MODULE_AUTHOR("Aaro Koskinen "); -- cgit v1.2.3 From b96ab7cc8278bf45719bf8d8bf69500d0cadbc5b Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:37:40 +0000 Subject: staging: et131x: improve indenting in et131x_adjust_link() Negate some 'if' checks to return early, allowing a large block of code to be un-indented. Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 160 ++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index e3a71d3fafcc..8a30726518a0 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -3754,97 +3754,99 @@ static void et131x_adjust_link(struct net_device *netdev) struct et131x_adapter *adapter = netdev_priv(netdev); struct phy_device *phydev = adapter->phydev; - if (phydev && phydev->link != adapter->link) { - /* Check to see if we are in coma mode and if - * so, disable it because we will not be able - * to read PHY values until we are out. - */ - if (et1310_in_phy_coma(adapter)) - et1310_disable_phy_coma(adapter); - - adapter->link = phydev->link; - phy_print_status(phydev); - - if (phydev->link) { - adapter->boot_coma = 20; - if (phydev && phydev->speed == SPEED_10) { - /* NOTE - Is there a way to query this without - * TruePHY? - * && TRU_QueryCoreType(adapter->hTruePhy, 0)== - * EMI_TRUEPHY_A13O) { - */ - u16 register18; - - et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, - ®ister18); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, - register18 | 0x4); - et131x_mii_write(adapter, PHY_INDEX_REG, - register18 | 0x8402); - et131x_mii_write(adapter, PHY_DATA_REG, - register18 | 511); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, - register18); - } + if (!phydev) + return; + if (phydev->link == adapter->link) + return; - et1310_config_flow_control(adapter); + /* Check to see if we are in coma mode and if + * so, disable it because we will not be able + * to read PHY values until we are out. + */ + if (et1310_in_phy_coma(adapter)) + et1310_disable_phy_coma(adapter); - if (phydev && phydev->speed == SPEED_1000 && - adapter->registry_jumbo_packet > 2048) { - u16 reg; + adapter->link = phydev->link; + phy_print_status(phydev); - et131x_mii_read(adapter, PHY_CONFIG, ®); - reg &= ~ET_PHY_CONFIG_TX_FIFO_DEPTH; - reg |= ET_PHY_CONFIG_FIFO_DEPTH_32; - et131x_mii_write(adapter, PHY_CONFIG, reg); - } + if (phydev->link) { + adapter->boot_coma = 20; + if (phydev && phydev->speed == SPEED_10) { + /* NOTE - Is there a way to query this without + * TruePHY? + * && TRU_QueryCoreType(adapter->hTruePhy, 0)== + * EMI_TRUEPHY_A13O) { + */ + u16 register18; + + et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, + ®ister18); + et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, + register18 | 0x4); + et131x_mii_write(adapter, PHY_INDEX_REG, + register18 | 0x8402); + et131x_mii_write(adapter, PHY_DATA_REG, + register18 | 511); + et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, + register18); + } - et131x_set_rx_dma_timer(adapter); - et1310_config_mac_regs2(adapter); - } else { - adapter->boot_coma = 0; + et1310_config_flow_control(adapter); - if (phydev->speed == SPEED_10) { - /* NOTE - Is there a way to query this without - * TruePHY? - * && TRU_QueryCoreType(adapter->hTruePhy, 0) == - * EMI_TRUEPHY_A13O) - */ - u16 register18; - - et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, - ®ister18); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, - register18 | 0x4); - et131x_mii_write(adapter, PHY_INDEX_REG, - register18 | 0x8402); - et131x_mii_write(adapter, PHY_DATA_REG, - register18 | 511); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, - register18); - } + if (phydev && phydev->speed == SPEED_1000 && + adapter->registry_jumbo_packet > 2048) { + u16 reg; - /* Free the packets being actively sent & stopped */ - et131x_free_busy_send_packets(adapter); + et131x_mii_read(adapter, PHY_CONFIG, ®); + reg &= ~ET_PHY_CONFIG_TX_FIFO_DEPTH; + reg |= ET_PHY_CONFIG_FIFO_DEPTH_32; + et131x_mii_write(adapter, PHY_CONFIG, reg); + } - /* Re-initialize the send structures */ - et131x_init_send(adapter); + et131x_set_rx_dma_timer(adapter); + et1310_config_mac_regs2(adapter); + } else { + adapter->boot_coma = 0; - /* Bring the device back to the state it was during - * init prior to autonegotiation being complete. This - * way, when we get the auto-neg complete interrupt, - * we can complete init by calling config_mac_regs2. + if (phydev->speed == SPEED_10) { + /* NOTE - Is there a way to query this without + * TruePHY? + * && TRU_QueryCoreType(adapter->hTruePhy, 0) == + * EMI_TRUEPHY_A13O) */ - et131x_soft_reset(adapter); + u16 register18; + + et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, + ®ister18); + et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, + register18 | 0x4); + et131x_mii_write(adapter, PHY_INDEX_REG, + register18 | 0x8402); + et131x_mii_write(adapter, PHY_DATA_REG, + register18 | 511); + et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, + register18); + } - /* Setup ET1310 as per the documentation */ - et131x_adapter_setup(adapter); + /* Free the packets being actively sent & stopped */ + et131x_free_busy_send_packets(adapter); - /* perform reset of tx/rx */ - et131x_disable_txrx(netdev); - et131x_enable_txrx(netdev); - } + /* Re-initialize the send structures */ + et131x_init_send(adapter); + + /* Bring the device back to the state it was during + * init prior to autonegotiation being complete. This + * way, when we get the auto-neg complete interrupt, + * we can complete init by calling config_mac_regs2. + */ + et131x_soft_reset(adapter); + + /* Setup ET1310 as per the documentation */ + et131x_adapter_setup(adapter); + /* perform reset of tx/rx */ + et131x_disable_txrx(netdev); + et131x_enable_txrx(netdev); } } -- cgit v1.2.3 From 76af0140c0cfb2e72ab1d98a73d6fd25f1070cbc Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:37:41 +0000 Subject: staging: et131x: Remove unnecessary phydev checks Several checks for a valid adapter->phydev pointer are made where the pointer has already been checked previously in the code path. Remove these redundant checks. Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 8a30726518a0..4d76d79f4477 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -968,7 +968,7 @@ static void et1310_config_mac_regs2(struct et131x_adapter *adapter) /* Set up the if mode bits */ cfg2 &= ~ET_MAC_CFG2_IFMODE_MASK; - if (phydev && phydev->speed == SPEED_1000) { + if (phydev->speed == SPEED_1000) { cfg2 |= ET_MAC_CFG2_IFMODE_1000; /* Phy mode bit */ ifctrl &= ~ET_MAC_IFCTRL_PHYMODE; @@ -999,11 +999,11 @@ static void et1310_config_mac_regs2(struct et131x_adapter *adapter) cfg2 &= ~ET_MAC_CFG2_IFMODE_FULL_DPLX; /* Turn on duplex if needed */ - if (phydev && phydev->duplex == DUPLEX_FULL) + if (phydev->duplex == DUPLEX_FULL) cfg2 |= ET_MAC_CFG2_IFMODE_FULL_DPLX; ifctrl &= ~ET_MAC_IFCTRL_GHDMODE; - if (phydev && phydev->duplex == DUPLEX_HALF) + if (phydev->duplex == DUPLEX_HALF) ifctrl |= ET_MAC_IFCTRL_GHDMODE; writel(ifctrl, &mac->if_ctrl); @@ -2480,9 +2480,6 @@ static void et131x_set_rx_dma_timer(struct et131x_adapter *adapter) { struct phy_device *phydev = adapter->phydev; - if (!phydev) - return; - /* For version B silicon, we do not use the RxDMA timer for 10 and 100 * Mbits/s line rates. We do not enable and RxDMA interrupt coalescing. */ @@ -3771,7 +3768,7 @@ static void et131x_adjust_link(struct net_device *netdev) if (phydev->link) { adapter->boot_coma = 20; - if (phydev && phydev->speed == SPEED_10) { + if (phydev->speed == SPEED_10) { /* NOTE - Is there a way to query this without * TruePHY? * && TRU_QueryCoreType(adapter->hTruePhy, 0)== @@ -3793,7 +3790,7 @@ static void et131x_adjust_link(struct net_device *netdev) et1310_config_flow_control(adapter); - if (phydev && phydev->speed == SPEED_1000 && + if (phydev->speed == SPEED_1000 && adapter->registry_jumbo_packet > 2048) { u16 reg; -- cgit v1.2.3 From 6ff6280f4e88bf751e31641072d63f3c8b038208 Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:55:49 +0000 Subject: staging: et131x: replace magic number bitmask with defined values Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 4d76d79f4477..2f3c84a659dd 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -4122,7 +4122,7 @@ static void et131x_isr_handler(struct work_struct *work) if (status & ET_INTR_RXDMA_XFR_DONE) et131x_handle_recv_interrupt(adapter); - status &= 0xffffffd7; + status &= ~(ET_INTR_TXDMA_ERR | ET_INTR_RXDMA_XFR_DONE); if (!status) goto out; -- cgit v1.2.3 From 19d857de4a8e18b9c00021e94b8681d2a453cbdf Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:37:43 +0000 Subject: staging: et131x: clear up use of TRUEPHY defines There are a large number of TRUEPHY defines in the driver, all of which are unused or unnecessary. Remove / replace these. As this results in et1310_phy_access_mii_bit() only being used for reading bits, also change it's name to et1310_phy_read_mii_bit(). Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 45 ++++++++++------------------------------- drivers/staging/et131x/et131x.h | 40 ------------------------------------ 2 files changed, 11 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 2f3c84a659dd..3f70106bcf5b 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1494,10 +1494,10 @@ static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) return status; } -/* Still used from _mac for BIT_READ */ -static void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, - u16 action, u16 regnum, u16 bitnum, - u8 *value) +static void et1310_phy_read_mii_bit(struct et131x_adapter *adapter, + u16 regnum, + u16 bitnum, + u8 *value) { u16 reg; u16 mask = 1 << bitnum; @@ -1505,22 +1505,7 @@ static void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, /* Read the requested register */ et131x_mii_read(adapter, regnum, ®); - switch (action) { - case TRUEPHY_BIT_READ: - *value = (reg & mask) >> bitnum; - break; - - case TRUEPHY_BIT_SET: - et131x_mii_write(adapter, regnum, reg | mask); - break; - - case TRUEPHY_BIT_CLEAR: - et131x_mii_write(adapter, regnum, reg & ~mask); - break; - - default: - break; - } + *value = (reg & mask) >> bitnum; } static void et1310_config_flow_control(struct et131x_adapter *adapter) @@ -1532,27 +1517,19 @@ static void et1310_config_flow_control(struct et131x_adapter *adapter) } else { char remote_pause, remote_async_pause; - et1310_phy_access_mii_bit(adapter, - TRUEPHY_BIT_READ, 5, 10, &remote_pause); - et1310_phy_access_mii_bit(adapter, - TRUEPHY_BIT_READ, 5, 11, - &remote_async_pause); + et1310_phy_read_mii_bit(adapter, 5, 10, &remote_pause); + et1310_phy_read_mii_bit(adapter, 5, 11, &remote_async_pause); - if ((remote_pause == TRUEPHY_BIT_SET) && - (remote_async_pause == TRUEPHY_BIT_SET)) { + if (remote_pause && remote_async_pause) { adapter->flowcontrol = adapter->wanted_flow; - } else if ((remote_pause == TRUEPHY_BIT_SET) && - (remote_async_pause == TRUEPHY_BIT_CLEAR)) { + } else if (remote_pause && !remote_async_pause) { if (adapter->wanted_flow == FLOW_BOTH) adapter->flowcontrol = FLOW_BOTH; else adapter->flowcontrol = FLOW_NONE; - } else if ((remote_pause == TRUEPHY_BIT_CLEAR) && - (remote_async_pause == TRUEPHY_BIT_CLEAR)) { + } else if (!remote_pause && !remote_async_pause) { adapter->flowcontrol = FLOW_NONE; - } else {/* if (remote_pause == TRUEPHY_CLEAR_BIT && - * remote_async_pause == TRUEPHY_SET_BIT) - */ + } else { if (adapter->wanted_flow == FLOW_BOTH) adapter->flowcontrol = FLOW_RXONLY; else diff --git a/drivers/staging/et131x/et131x.h b/drivers/staging/et131x/et131x.h index bbe78a703a23..2ac6e9980117 100644 --- a/drivers/staging/et131x/et131x.h +++ b/drivers/staging/et131x/et131x.h @@ -1668,43 +1668,3 @@ struct address_map { #define LED_100TX_SHIFT 4 /* MI Register 29 - 31: Reserved Reg(0x1D - 0x1E) */ - -/* Defines for PHY access routines */ - -/* Define bit operation flags */ -#define TRUEPHY_BIT_CLEAR 0 -#define TRUEPHY_BIT_SET 1 -#define TRUEPHY_BIT_READ 2 - -/* Define read/write operation flags */ -#ifndef TRUEPHY_READ -#define TRUEPHY_READ 0 -#define TRUEPHY_WRITE 1 -#define TRUEPHY_MASK 2 -#endif - -/* Define master/slave configuration values */ -#define TRUEPHY_CFG_SLAVE 0 -#define TRUEPHY_CFG_MASTER 1 - -/* Define MDI/MDI-X settings */ -#define TRUEPHY_MDI 0 -#define TRUEPHY_MDIX 1 -#define TRUEPHY_AUTO_MDI_MDIX 2 - -/* Define 10Base-T link polarities */ -#define TRUEPHY_POLARITY_NORMAL 0 -#define TRUEPHY_POLARITY_INVERTED 1 - -/* Define auto-negotiation results */ -#define TRUEPHY_ANEG_NOT_COMPLETE 0 -#define TRUEPHY_ANEG_COMPLETE 1 -#define TRUEPHY_ANEG_DISABLED 2 - -/* Define duplex advertisement flags */ -#define TRUEPHY_ADV_DUPLEX_NONE 0x00 -#define TRUEPHY_ADV_DUPLEX_FULL 0x01 -#define TRUEPHY_ADV_DUPLEX_HALF 0x02 -#define TRUEPHY_ADV_DUPLEX_BOTH \ - (TRUEPHY_ADV_DUPLEX_FULL | TRUEPHY_ADV_DUPLEX_HALF) - -- cgit v1.2.3 From c36cef9377659dd67048c9afa6d4ddffd1b91cf6 Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:37:44 +0000 Subject: staging: et131x: remove two useless debug statements Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 3f70106bcf5b..d88b8296bb8a 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -2302,8 +2302,6 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) "Cannot alloc memory for Packet Status Ring\n"); return -ENOMEM; } - pr_info("Packet Status Ring %llx\n", - (unsigned long long) rx_ring->ps_ring_physaddr); /* NOTE : dma_alloc_coherent(), used above to alloc DMA regions, * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses @@ -2322,7 +2320,6 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) return -ENOMEM; } rx_ring->num_rfd = NIC_DEFAULT_NUM_RFD; - pr_info("PRS %llx\n", (unsigned long long)rx_ring->rx_status_bus); /* The RFDs are going to be put on lists later on, so initialize the * lists now. -- cgit v1.2.3 From 15ae239d101994a1c65d607351605d0c55bff7bb Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:37:45 +0000 Subject: staging: et131x: remove unhelpful comments Get rid of some of the more unhelpful comments. Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 204 ++++++---------------------------------- 1 file changed, 28 insertions(+), 176 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index d88b8296bb8a..91c985fc0ffe 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1351,8 +1351,6 @@ static void et1310_config_macstat_regs(struct et131x_adapter *adapter) * @addr: the address of the transceiver * @reg: the register to read * @value: pointer to a 16-bit value in which the value will be stored - * - * Returns 0 on success, errno on failure (as defined in errno.h) */ static int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr, u8 reg, u16 *value) @@ -1425,10 +1423,6 @@ static int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value) * @adapter: pointer to our private adapter structure * @reg: the register to read * @value: 16-bit value to write - * - * FIXME: one caller in netdev still - * - * Return 0 on success, errno on failure (as defined in errno.h) */ static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) { @@ -1538,9 +1532,7 @@ static void et1310_config_flow_control(struct et131x_adapter *adapter) } } -/* et1310_update_macstat_host_counters - Update the local copy of the statistics - * @adapter: pointer to the adapter structure - */ +/* et1310_update_macstat_host_counters - Update local copy of the statistics */ static void et1310_update_macstat_host_counters(struct et131x_adapter *adapter) { struct ce_stats *stats = &adapter->stats; @@ -1566,7 +1558,6 @@ static void et1310_update_macstat_host_counters(struct et131x_adapter *adapter) } /* et1310_handle_macstat_interrupt - * @adapter: pointer to the adapter structure * * One of the MACSTAT counters has wrapped. Update the local copy of * the statistics held in the adapter structure, checking the "wrap" @@ -1676,10 +1667,7 @@ static void et1310_phy_power_switch(struct et131x_adapter *adapter, bool down) et131x_mii_write(adapter, MII_BMCR, data); } -/* et131x_xcvr_init - Init the phy if we are setting it into force mode - * @adapter: pointer to our private adapter structure - * - */ +/* et131x_xcvr_init - Init the phy if we are setting it into force mode */ static void et131x_xcvr_init(struct et131x_adapter *adapter) { u16 lcr2; @@ -1708,7 +1696,6 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter) } /* et131x_configure_global_regs - configure JAGCore global regs - * @adapter: pointer to our adapter structure * * Used to configure the global registers on the JAGCore */ @@ -1753,9 +1740,7 @@ static void et131x_configure_global_regs(struct et131x_adapter *adapter) writel(0, ®s->watchdog_timer); } -/* et131x_config_rx_dma_regs - Start of Rx_DMA init sequence - * @adapter: pointer to our adapter structure - */ +/* et131x_config_rx_dma_regs - Start of Rx_DMA init sequence */ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) { struct rxdma_regs __iomem *rx_dma = &adapter->regs->rxdma; @@ -1861,7 +1846,6 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) } /* et131x_config_tx_dma_regs - Set up the tx dma section of the JAGCore. - * @adapter: pointer to our private adapter structure * * Configure the transmit engine with the ring buffers we have created * and prepare it for use. @@ -1891,11 +1875,7 @@ static void et131x_config_tx_dma_regs(struct et131x_adapter *adapter) adapter->tx_ring.send_idx = 0; } -/* et131x_adapter_setup - Set the adapter up as per cassini+ documentation - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ +/* et131x_adapter_setup - Set the adapter up as per cassini+ documentation */ static void et131x_adapter_setup(struct et131x_adapter *adapter) { /* Configure the JAGCore */ @@ -1919,9 +1899,7 @@ static void et131x_adapter_setup(struct et131x_adapter *adapter) et131x_xcvr_init(adapter); } -/* et131x_soft_reset - Issue a soft reset to the hardware, complete for ET1310 - * @adapter: pointer to our private adapter structure - */ +/* et131x_soft_reset - Issue soft reset to the hardware, complete for ET1310 */ static void et131x_soft_reset(struct et131x_adapter *adapter) { u32 reg; @@ -1942,7 +1920,6 @@ static void et131x_soft_reset(struct et131x_adapter *adapter) } /* et131x_enable_interrupts - enable interrupt - * @adapter: et131x device * * Enable the appropriate interrupts on the ET131x according to our * configuration @@ -1962,7 +1939,6 @@ static void et131x_enable_interrupts(struct et131x_adapter *adapter) } /* et131x_disable_interrupts - interrupt disable - * @adapter: et131x device * * Block all interrupts from the et131x device at the device itself */ @@ -1972,9 +1948,7 @@ static void et131x_disable_interrupts(struct et131x_adapter *adapter) writel(INT_MASK_DISABLE, &adapter->regs->global.int_mask); } -/* et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310 - * @adapter: pointer to our adapter structure - */ +/* et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310 */ static void et131x_tx_dma_disable(struct et131x_adapter *adapter) { /* Setup the tramsmit dma configuration register */ @@ -1982,9 +1956,7 @@ static void et131x_tx_dma_disable(struct et131x_adapter *adapter) &adapter->regs->txdma.csr); } -/* et131x_enable_txrx - Enable tx/rx queues - * @netdev: device to be enabled - */ +/* et131x_enable_txrx - Enable tx/rx queues */ static void et131x_enable_txrx(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -2001,9 +1973,7 @@ static void et131x_enable_txrx(struct net_device *netdev) netif_start_queue(netdev); } -/* et131x_disable_txrx - Disable tx/rx queues - * @netdev: device to be disabled - */ +/* et131x_disable_txrx - Disable tx/rx queues */ static void et131x_disable_txrx(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -2019,9 +1989,7 @@ static void et131x_disable_txrx(struct net_device *netdev) et131x_disable_interrupts(adapter); } -/* et131x_init_send - Initialize send data structures - * @adapter: pointer to our private adapter structure - */ +/* et131x_init_send - Initialize send data structures */ static void et131x_init_send(struct et131x_adapter *adapter) { struct tcb *tcb; @@ -2053,7 +2021,6 @@ static void et131x_init_send(struct et131x_adapter *adapter) } /* et1310_enable_phy_coma - called when network cable is unplugged - * @adapter: pointer to our adapter structure * * driver receive an phy status change interrupt while in D0 and check that * phy_status is down. @@ -2081,11 +2048,6 @@ static void et1310_enable_phy_coma(struct et131x_adapter *adapter) /* Save the GbE PHY speed and duplex modes. Need to restore this * when cable is plugged back in */ - /* TODO - when PM is re-enabled, check if we need to - * perform a similar task as this - - * adapter->pdown_speed = adapter->ai_force_speed; - * adapter->pdown_duplex = adapter->ai_force_duplex; - */ /* Stop sending packets. */ spin_lock_irqsave(&adapter->send_hw_lock, flags); @@ -2105,9 +2067,7 @@ static void et1310_enable_phy_coma(struct et131x_adapter *adapter) writel(pmcsr, &adapter->regs->global.pm_csr); } -/* et1310_disable_phy_coma - Disable the Phy Coma Mode - * @adapter: pointer to our adapter structure - */ +/* et1310_disable_phy_coma - Disable the Phy Coma Mode */ static void et1310_disable_phy_coma(struct et131x_adapter *adapter) { u32 pmcsr; @@ -2122,11 +2082,6 @@ static void et1310_disable_phy_coma(struct et131x_adapter *adapter) /* Restore the GbE PHY speed and duplex modes; * Reset JAGCore; re-configure and initialize JAGCore and gigE PHY */ - /* TODO - when PM is re-enabled, check if we need to - * perform a similar task as this - - * adapter->ai_force_speed = adapter->pdown_speed; - * adapter->ai_force_duplex = adapter->pdown_duplex; - */ /* Re-initialize the send structures */ et131x_init_send(adapter); @@ -2166,9 +2121,6 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit) } /* et131x_rx_dma_memory_alloc - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success and errno on failure (as defined in errno.h) * * Allocates Free buffer ring 1 for sure, free buffer ring 0 if required, * and the Packet Status Ring. @@ -2328,9 +2280,7 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) return 0; } -/* et131x_rx_dma_memory_free - Free all memory allocated within this module. - * @adapter: pointer to our private adapter structure - */ +/* et131x_rx_dma_memory_free - Free all memory allocated within this module */ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) { u8 id; @@ -2415,11 +2365,7 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) rx_ring->num_ready_recv = 0; } -/* et131x_init_recv - Initialize receive data structures. - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success and errno on failure (as defined in errno.h) - */ +/* et131x_init_recv - Initialize receive data structures */ static int et131x_init_recv(struct et131x_adapter *adapter) { struct rfd *rfd; @@ -2447,9 +2393,7 @@ static int et131x_init_recv(struct et131x_adapter *adapter) return 0; } -/* et131x_set_rx_dma_timer - Set the heartbeat timer according to line rate. - * @adapter: pointer to our adapter structure - */ +/* et131x_set_rx_dma_timer - Set the heartbeat timer according to line rate */ static void et131x_set_rx_dma_timer(struct et131x_adapter *adapter) { struct phy_device *phydev = adapter->phydev; @@ -2524,7 +2468,6 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd) } /* nic_rx_pkts - Checks the hardware for available packets - * @adapter: pointer to our adapter * * Returns rfd, a pointer to our MPRFD. * @@ -2706,7 +2649,6 @@ out: } /* et131x_handle_recv_interrupt - Interrupt handler for receive processing - * @adapter: pointer to our adapter * * Assumption, Rcv spinlock has been acquired. */ @@ -2759,9 +2701,6 @@ static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) } /* et131x_tx_dma_memory_alloc - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success and errno on failure (as defined in errno.h). * * Allocates memory that will be visible both to the device and to the CPU. * The OS will pass us packets, pointers to which we will insert in the Tx @@ -2812,11 +2751,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) return 0; } -/* et131x_tx_dma_memory_free - Free all memory allocated within this module - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success and errno on failure (as defined in errno.h). - */ +/* et131x_tx_dma_memory_free - Free all memory allocated within this module */ static void et131x_tx_dma_memory_free(struct et131x_adapter *adapter) { int desc_size = 0; @@ -2847,8 +2782,6 @@ static void et131x_tx_dma_memory_free(struct et131x_adapter *adapter) /* nic_send_packet - NIC specific send handler for version B silicon. * @adapter: pointer to our adapter * @tcb: pointer to struct tcb - * - * Returns 0 or errno. */ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) { @@ -3025,10 +2958,6 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) } /* send_packet - Do the work to send a packet - * @skb: the packet(s) to send - * @adapter: a pointer to the device's private adapter structure - * - * Return 0 in almost all cases; non-zero value in extreme hard failure only. * * Assumption: Send spinlock has been acquired */ @@ -3094,12 +3023,7 @@ static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter) return 0; } -/* et131x_send_packets - This function is called by the OS to send packets - * @skb: the packet(s) to send - * @netdev:device on which to TX the above packet(s) - * - * Return 0 in almost all cases; non-zero value in extreme hard failure only - */ +/* et131x_send_packets - This function is called by the OS to send packets */ static int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) { int status = 0; @@ -3216,7 +3140,6 @@ static inline void free_send_packet(struct et131x_adapter *adapter, } /* et131x_free_busy_send_packets - Free and complete the stopped active sends - * @adapter: pointer to our adapter * * Assumption - Send spinlock has been acquired */ @@ -3259,7 +3182,6 @@ static void et131x_free_busy_send_packets(struct et131x_adapter *adapter) } /* et131x_handle_send_interrupt - Interrupt handler for sending processing - * @adapter: pointer to our adapter * * Re-claim the send resources, complete sends and get more to send from * the send wait queue. @@ -3517,9 +3439,7 @@ static struct ethtool_ops et131x_ethtool_ops = { .get_link = ethtool_op_get_link, }; -/* et131x_hwaddr_init - set up the MAC Address on the ET1310 - * @adapter: pointer to our private adapter structure - */ +/* et131x_hwaddr_init - set up the MAC Address on the ET1310 */ static void et131x_hwaddr_init(struct et131x_adapter *adapter) { /* If have our default mac from init and no mac address from @@ -3549,8 +3469,6 @@ static void et131x_hwaddr_init(struct et131x_adapter *adapter) } /* et131x_pci_init - initial PCI setup - * @adapter: pointer to our private adapter structure - * @pdev: our PCI device * * Perform the initial setup of PCI registers and if possible initialise * the MAC address. At this point the I/O registers have yet to be mapped @@ -3673,21 +3591,14 @@ static void et131x_error_timer_handler(unsigned long data) mod_timer(&adapter->error_timer, jiffies + TX_ERROR_PERIOD * HZ / 1000); } -/* et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx - * @adapter: pointer to our private adapter structure - */ +/* et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx */ static void et131x_adapter_memory_free(struct et131x_adapter *adapter) { - /* Free DMA memory */ et131x_tx_dma_memory_free(adapter); et131x_rx_dma_memory_free(adapter); } /* et131x_adapter_memory_alloc - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success, errno on failure (as defined in errno.h). - * * Allocate all the memory blocks for send, receive and others. */ static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) @@ -3743,11 +3654,6 @@ static void et131x_adjust_link(struct net_device *netdev) if (phydev->link) { adapter->boot_coma = 20; if (phydev->speed == SPEED_10) { - /* NOTE - Is there a way to query this without - * TruePHY? - * && TRU_QueryCoreType(adapter->hTruePhy, 0)== - * EMI_TRUEPHY_A13O) { - */ u16 register18; et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, @@ -3780,11 +3686,6 @@ static void et131x_adjust_link(struct net_device *netdev) adapter->boot_coma = 0; if (phydev->speed == SPEED_10) { - /* NOTE - Is there a way to query this without - * TruePHY? - * && TRU_QueryCoreType(adapter->hTruePhy, 0) == - * EMI_TRUEPHY_A13O) - */ u16 register18; et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, @@ -3861,8 +3762,6 @@ static int et131x_mii_probe(struct net_device *netdev) } /* et131x_adapter_init - * @adapter: pointer to the private adapter struct - * @pdev: pointer to the PCI device * * Initialize the data structures for the et131x_adapter object and link * them together with the platform provided device structures. @@ -3896,7 +3795,6 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, } /* et131x_pci_remove - * @pdev: a pointer to the device's pci_dev structure * * Registered in the pci_driver structure, this function is called when the * PCI subsystem detects that a PCI device which matches the information @@ -3923,9 +3821,7 @@ static void et131x_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -/* et131x_up - Bring up a device for use. - * @netdev: device to be opened - */ +/* et131x_up - Bring up a device for use. */ static void et131x_up(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -3934,9 +3830,7 @@ static void et131x_up(struct net_device *netdev) phy_start(adapter->phydev); } -/* et131x_down - Bring down the device - * @netdev: device to be brought down - */ +/* et131x_down - Bring down the device */ static void et131x_down(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4072,7 +3966,6 @@ out: } /* et131x_isr_handler - The ISR handler - * @p_adapter, a pointer to the device's private adapter structure * * scheduled to run in a deferred context by the ISR. This is where the ISR's * work actually gets done. @@ -4252,11 +4145,7 @@ out: et131x_enable_interrupts(adapter); } -/* et131x_stats - Return the current device statistics. - * @netdev: device whose stats are being queried - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ +/* et131x_stats - Return the current device statistics */ static struct net_device_stats *et131x_stats(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4298,11 +4187,7 @@ static struct net_device_stats *et131x_stats(struct net_device *netdev) return stats; } -/* et131x_open - Open the device for use. - * @netdev: device to be opened - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ +/* et131x_open - Open the device for use. */ static int et131x_open(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4331,11 +4216,7 @@ static int et131x_open(struct net_device *netdev) return result; } -/* et131x_close - Close the device - * @netdev: device to be closed - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ +/* et131x_close - Close the device */ static int et131x_close(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4353,8 +4234,6 @@ static int et131x_close(struct net_device *netdev) * @netdev: device on which the control request is being made * @reqbuf: a pointer to the IOCTL request buffer * @cmd: the IOCTL command code - * - * Returns 0 on success, errno on failure (as defined in errno.h) */ static int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, int cmd) @@ -4371,8 +4250,6 @@ static int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, * @adapter: pointer to our private adapter structure * * FIXME: lot of dups with MAC code - * - * Returns 0 on success, errno on failure */ static int et131x_set_packet_filter(struct et131x_adapter *adapter) { @@ -4431,9 +4308,7 @@ static int et131x_set_packet_filter(struct et131x_adapter *adapter) return status; } -/* et131x_multicast - The handler to configure multicasting on the interface - * @netdev: a pointer to a net_device struct representing the device - */ +/* et131x_multicast - The handler to configure multicasting on the interface */ static void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4493,19 +4368,13 @@ static void et131x_multicast(struct net_device *netdev) * NOTE - This block will always update the multicast_list with the * hardware, even if the addresses aren't the same. */ - if (packet_filter != adapter->packet_filter) { - /* Call the device's filter function */ + if (packet_filter != adapter->packet_filter) et131x_set_packet_filter(adapter); - } + spin_unlock_irqrestore(&adapter->lock, flags); } -/* et131x_tx - The handler to tx a packet on the device - * @skb: data to be Tx'd - * @netdev: device on which data is to be Tx'd - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ +/* et131x_tx - The handler to tx a packet on the device */ static int et131x_tx(struct sk_buff *skb, struct net_device *netdev) { int status = 0; @@ -4533,7 +4402,6 @@ static int et131x_tx(struct sk_buff *skb, struct net_device *netdev) } /* et131x_tx_timeout - Timeout handler - * @netdev: a pointer to a net_device struct representing the device * * The handler called when a Tx request times out. The timeout period is * specified by the 'tx_timeo" element in the net_device structure (see @@ -4590,12 +4458,7 @@ static void et131x_tx_timeout(struct net_device *netdev) spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); } -/* et131x_change_mtu - The handler called to change the MTU for the device - * @netdev: device whose MTU is to be changed - * @new_mtu: the desired MTU - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ +/* et131x_change_mtu - The handler called to change the MTU for the device */ static int et131x_change_mtu(struct net_device *netdev, int new_mtu) { int result = 0; @@ -4640,22 +4503,13 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu) return result; } -/* et131x_set_mac_addr - handler to change the MAC address for the device - * @netdev: device whose MAC is to be changed - * @new_mac: the desired MAC address - * - * Returns 0 on success, errno on failure (as defined in errno.h) - * - * IMPLEMENTED BY : blux http://berndlux.de 22.01.2007 21:14 - */ +/* et131x_set_mac_addr - handler to change the MAC address for the device */ static int et131x_set_mac_addr(struct net_device *netdev, void *new_mac) { int result = 0; struct et131x_adapter *adapter = netdev_priv(netdev); struct sockaddr *address = new_mac; - /* begin blux */ - if (adapter == NULL) return -ENODEV; @@ -4717,8 +4571,6 @@ static const struct net_device_ops et131x_netdev_ops = { * @pdev: a pointer to the device's pci_dev structure * @ent: this device's entry in the pci_device_id table * - * Returns 0 on success, errno on failure (as defined in errno.h) - * * Registered in the pci_driver structure, this function is called when the * PCI subsystem finds a new PCI device which matches the information * contained in the pci_device_id table. This routine is the equivalent to -- cgit v1.2.3 From 12a2f3f3f4f3f6cebf78b075f44c55ec4e146356 Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Thu, 5 Dec 2013 22:37:46 +0000 Subject: staging: et131x: trivial whitespace and line / character reductions Tweak some whitespace, also remove a few redundant lines and characters (mainly of type 'if (status != 0)' -> 'if (status)'). Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 91c985fc0ffe..5dd217062096 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1039,9 +1039,7 @@ static void et1310_config_mac_regs2(struct et131x_adapter *adapter) */ static int et1310_in_phy_coma(struct et131x_adapter *adapter) { - u32 pmcsr; - - pmcsr = readl(&adapter->regs->global.pm_csr); + u32 pmcsr = readl(&adapter->regs->global.pm_csr); return ET_PM_PHY_SW_COMA & pmcsr ? 1 : 0; } @@ -1930,7 +1928,7 @@ static void et131x_enable_interrupts(struct et131x_adapter *adapter) /* Enable all global interrupts */ if (adapter->flowcontrol == FLOW_TXONLY || - adapter->flowcontrol == FLOW_BOTH) + adapter->flowcontrol == FLOW_BOTH) mask = INT_MASK_ENABLE; else mask = INT_MASK_ENABLE_NO_FLOW; @@ -2115,7 +2113,7 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit) tmp_free_buff_ring ^= ET_DMA10_WRAP; } /* For the 1023 case */ - tmp_free_buff_ring &= (ET_DMA10_MASK|ET_DMA10_WRAP); + tmp_free_buff_ring &= (ET_DMA10_MASK | ET_DMA10_WRAP); *free_buff_ring = tmp_free_buff_ring; return tmp_free_buff_ring; } @@ -2620,7 +2618,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) adapter->stats.unicast_pkts_rcvd++; } - if (len == 0) { + if (!len) { rfd->len = 0; goto out; } @@ -3474,7 +3472,7 @@ static void et131x_hwaddr_init(struct et131x_adapter *adapter) * the MAC address. At this point the I/O registers have yet to be mapped */ static int et131x_pci_init(struct et131x_adapter *adapter, - struct pci_dev *pdev) + struct pci_dev *pdev) { u16 max_payload; int i, rc; @@ -3607,14 +3605,14 @@ static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) /* Allocate memory for the Tx Ring */ status = et131x_tx_dma_memory_alloc(adapter); - if (status != 0) { + if (status) { dev_err(&adapter->pdev->dev, "et131x_tx_dma_memory_alloc FAILED\n"); return status; } /* Receive buffer memory allocation */ status = et131x_rx_dma_memory_alloc(adapter); - if (status != 0) { + if (status) { dev_err(&adapter->pdev->dev, "et131x_rx_dma_memory_alloc FAILED\n"); et131x_tx_dma_memory_free(adapter); @@ -3624,8 +3622,7 @@ static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) /* Init receive data structures */ status = et131x_init_recv(adapter); if (status) { - dev_err(&adapter->pdev->dev, - "et131x_init_recv FAILED\n"); + dev_err(&adapter->pdev->dev, "et131x_init_recv FAILED\n"); et131x_adapter_memory_free(adapter); } return status; @@ -3755,7 +3752,8 @@ static int et131x_mii_probe(struct net_device *netdev) phydev->advertising = phydev->supported; adapter->phydev = phydev; - dev_info(&adapter->pdev->dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", + dev_info(&adapter->pdev->dev, + "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", phydev->drv->name, dev_name(&phydev->dev)); return 0; @@ -3767,7 +3765,7 @@ static int et131x_mii_probe(struct net_device *netdev) * them together with the platform provided device structures. */ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, - struct pci_dev *pdev) + struct pci_dev *pdev) { static const u8 default_mac[] = { 0x00, 0x05, 0x3d, 0x00, 0x02, 0x00 }; @@ -3940,7 +3938,7 @@ static irqreturn_t et131x_isr(int irq, void *dev_id) status &= ~ET_INTR_WATCHDOG; } - if (status == 0) { + if (!status) { /* This interrupt has in some way been "handled" by * the ISR. Either it was a spurious Rx interrupt, or * it was a Tx interrupt that has been filtered by @@ -3996,10 +3994,8 @@ static void et131x_isr_handler(struct work_struct *work) /* Handle the TXDMA Error interrupt */ if (status & ET_INTR_TXDMA_ERR) { - u32 txdma_err; - /* Following read also clears the register (COR) */ - txdma_err = readl(&iomem->txdma.tx_dma_error); + u32 txdma_err = readl(&iomem->txdma.tx_dma_error); dev_warn(&adapter->pdev->dev, "TXDMA_ERR interrupt, error = %d\n", @@ -4577,7 +4573,7 @@ static const struct net_device_ops et131x_netdev_ops = { * a device insertion routine. */ static int et131x_pci_setup(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { struct net_device *netdev; struct et131x_adapter *adapter; -- cgit v1.2.3 From ae7d27c086b5eba849ff868065bbba04c0da60b1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 5 Dec 2013 15:57:26 -0800 Subject: staging: slicoss: Remove last reference to compare_ether_addr And use the normal is__ether_addr functions and ETH_ALEN too. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/README | 1 - drivers/staging/slicoss/slicoss.c | 21 ++++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/slicoss/README b/drivers/staging/slicoss/README index cb04a87b2017..53052c4e78ae 100644 --- a/drivers/staging/slicoss/README +++ b/drivers/staging/slicoss/README @@ -14,7 +14,6 @@ TODO: - use net_device_ops - use dev->stats rather than adapter->stats - don't cast netdev_priv it is already void - - use compare_ether_addr - GET RID OF MACROS - work on all architectures - without CONFIG_X86_64 confusion diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index f340cb9a90ff..1426ca49bfe8 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -595,15 +595,12 @@ static void slic_adapter_set_hwaddr(struct adapter *adapter) memcpy(adapter->macaddr, card->config.MacInfo[adapter->functionnumber].macaddrA, sizeof(struct slic_config_mac)); - if (!(adapter->currmacaddr[0] || adapter->currmacaddr[1] || - adapter->currmacaddr[2] || adapter->currmacaddr[3] || - adapter->currmacaddr[4] || adapter->currmacaddr[5])) { - memcpy(adapter->currmacaddr, adapter->macaddr, 6); - } - if (adapter->netdev) { + if (is_zero_ether_addr(adapter->currmacaddr)) + memcpy(adapter->currmacaddr, adapter->macaddr, + ETH_ALEN); + if (adapter->netdev) memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, - 6); - } + ETH_ALEN); } } @@ -767,13 +764,11 @@ static bool slic_mac_filter(struct adapter *adapter, { struct net_device *netdev = adapter->netdev; u32 opts = adapter->macopts; - u32 *dhost4 = (u32 *)ðer_frame->ether_dhost[0]; - u16 *dhost2 = (u16 *)ðer_frame->ether_dhost[4]; if (opts & MAC_PROMISC) return true; - if ((*dhost4 == 0xFFFFFFFF) && (*dhost2 == 0xFFFF)) { + if (is_broadcast_ether_addr(ether_frame->ether_dhost)) { if (opts & MAC_BCAST) { adapter->rcv_broadcasts++; return true; @@ -782,7 +777,7 @@ static bool slic_mac_filter(struct adapter *adapter, } } - if (ether_frame->ether_dhost[0] & 0x01) { + if (is_multicast_ether_addr(ether_frame->ether_dhost)) { if (opts & MAC_ALLMCAST) { adapter->rcv_multicasts++; netdev->stats.multicast++; @@ -2335,7 +2330,7 @@ static int slic_mcast_add_list(struct adapter *adapter, char *address) if (mcaddr == NULL) return 1; - memcpy(mcaddr->address, address, 6); + memcpy(mcaddr->address, address, ETH_ALEN); mcaddr->next = adapter->mcastaddrs; adapter->mcastaddrs = mcaddr; -- cgit v1.2.3 From cc922722d5faff6f83f857104eac99358feb50d4 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 6 Dec 2013 23:27:55 +0900 Subject: staging: crystalhd: Fix typo in crystalhd Correct spelling typo. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/crystalhd/bc_dts_glob_lnx.h | 2 +- drivers/staging/crystalhd/crystalhd_cmds.c | 2 +- drivers/staging/crystalhd/crystalhd_cmds.h | 2 +- drivers/staging/crystalhd/crystalhd_fw_if.h | 2 +- drivers/staging/crystalhd/crystalhd_hw.c | 2 +- drivers/staging/crystalhd/crystalhd_hw.h | 6 +++--- drivers/staging/crystalhd/crystalhd_lnx.h | 2 +- drivers/staging/crystalhd/crystalhd_misc.c | 4 ++-- drivers/staging/crystalhd/crystalhd_misc.h | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/crystalhd/bc_dts_glob_lnx.h b/drivers/staging/crystalhd/bc_dts_glob_lnx.h index 981708f3ee39..92b0cff248cb 100644 --- a/drivers/staging/crystalhd/bc_dts_glob_lnx.h +++ b/drivers/staging/crystalhd/bc_dts_glob_lnx.h @@ -229,7 +229,7 @@ enum BC_DRV_CMD { DRV_CMD_REG_RD, /* Read Device Register */ DRV_CMD_REG_WR, /* Write Device Register */ DRV_CMD_FPGA_RD, /* Read FPGA Register */ - DRV_CMD_FPGA_WR, /* Wrtie FPGA Reister */ + DRV_CMD_FPGA_WR, /* Write FPGA Register */ DRV_CMD_MEM_RD, /* Read Device Memory */ DRV_CMD_MEM_WR, /* Write Device Memory */ DRV_CMD_RD_PCI_CFG, /* Read PCI Config Space */ diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c index 3972b52e1416..642f438793c3 100644 --- a/drivers/staging/crystalhd/crystalhd_cmds.c +++ b/drivers/staging/crystalhd/crystalhd_cmds.c @@ -798,7 +798,7 @@ static const struct crystalhd_cmd_tbl g_crystalhd_cproc_tbl[] = { * * Current gstreamer frame work does not provide any power management * related notification to user mode decoder plug-in. As a work-around - * we pass on the power mangement notification to our plug-in by completing + * we pass on the power management notification to our plug-in by completing * all outstanding requests with BC_STS_IO_USER_ABORT return code. */ enum BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, diff --git a/drivers/staging/crystalhd/crystalhd_cmds.h b/drivers/staging/crystalhd/crystalhd_cmds.h index 377cd9d68b08..b5bf59dbcde9 100644 --- a/drivers/staging/crystalhd/crystalhd_cmds.h +++ b/drivers/staging/crystalhd/crystalhd_cmds.h @@ -29,7 +29,7 @@ /* * NOTE:: This is the main interface file between the Linux layer - * and the harware layer. This file will use the definitions + * and the hardware layer. This file will use the definitions * from _dts_glob and dts_defs etc.. which are defined for * windows. */ diff --git a/drivers/staging/crystalhd/crystalhd_fw_if.h b/drivers/staging/crystalhd/crystalhd_fw_if.h index 4b363a5069d7..05615e2a231a 100644 --- a/drivers/staging/crystalhd/crystalhd_fw_if.h +++ b/drivers/staging/crystalhd/crystalhd_fw_if.h @@ -115,7 +115,7 @@ struct fgt_sei { unsigned char model_id; /* Model id. */ /* +unused SE based on Thomson spec */ - unsigned char color_desc_flag; /* Separate color descrition flag. */ + unsigned char color_desc_flag; /* Separate color description flag. */ unsigned char bit_depth_luma; /* Bit depth luma minus 8. */ unsigned char bit_depth_chroma; /* Bit depth chroma minus 8. */ unsigned char full_range_flag; /* Full range flag. */ diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c index 043bd49843ff..8d0680d93684 100644 --- a/drivers/staging/crystalhd/crystalhd_hw.c +++ b/drivers/staging/crystalhd/crystalhd_hw.c @@ -398,7 +398,7 @@ static void crystalhd_hw_free_rx_pkt(struct crystalhd_hw *hw, * Call back from TX - IOQ deletion. * * This routine will release the TX DMA rings allocated - * druing setup_dma rings interface. + * during setup_dma rings interface. * * Memory is allocated per DMA ring basis. This is just * a place holder to be able to create the dio queues. diff --git a/drivers/staging/crystalhd/crystalhd_hw.h b/drivers/staging/crystalhd/crystalhd_hw.h index 37809442c553..d5cb68dfe695 100644 --- a/drivers/staging/crystalhd/crystalhd_hw.h +++ b/drivers/staging/crystalhd/crystalhd_hw.h @@ -46,7 +46,7 @@ #define Cpu2HstMbx1 0x00100F04 #define MbxStat1 0x00100F08 #define Stream2Host_Intr_Sts 0x00100F24 -#define C011_RET_SUCCESS 0x0 /* Reutrn status of firmware command. */ +#define C011_RET_SUCCESS 0x0 /* Return status of firmware command. */ /* TS input status register */ #define TS_StreamAFIFOStatus 0x0010044C @@ -141,7 +141,7 @@ union link_misc_perst_deco_ctrl { uint32_t reserved0:3; /* Reserved.No Effect*/ uint32_t stop_bcm_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/ - uint32_t reserved1:27; /* Reseved. No Effect*/ + uint32_t reserved1:27; /* Reserved. No Effect*/ }; uint32_t whole_reg; @@ -176,7 +176,7 @@ union link_misc_perst_decoder_ctrl { uint32_t res0:3; /* Reserved.No Effect*/ uint32_t stop_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/ - uint32_t res1:27; /* Reseved. No Effect */ + uint32_t res1:27; /* Reserved. No Effect */ }; uint32_t whole_reg; diff --git a/drivers/staging/crystalhd/crystalhd_lnx.h b/drivers/staging/crystalhd/crystalhd_lnx.h index bac572a8bc2e..33d7431de837 100644 --- a/drivers/staging/crystalhd/crystalhd_lnx.h +++ b/drivers/staging/crystalhd/crystalhd_lnx.h @@ -53,7 +53,7 @@ /* OS specific PCI information structure and adapter information. */ struct crystalhd_adp { - /* Hardware borad/PCI specifics */ + /* Hardware board/PCI specifics */ char name[32]; struct pci_dev *pdev; diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c index 51f698052aff..c3d024406337 100644 --- a/drivers/staging/crystalhd/crystalhd_misc.c +++ b/drivers/staging/crystalhd/crystalhd_misc.c @@ -389,7 +389,7 @@ void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz, void *temp = NULL; if (!adp || !sz || !phy_addr) { - BCMLOG_ERR("Invalide Arg..\n"); + BCMLOG_ERR("Invalid Arg..\n"); return temp; } @@ -415,7 +415,7 @@ void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka, dma_addr_t phy_addr) { if (!adp || !ka || !sz || !phy_addr) { - BCMLOG_ERR("Invalide Arg..\n"); + BCMLOG_ERR("Invalid Arg..\n"); return; } diff --git a/drivers/staging/crystalhd/crystalhd_misc.h b/drivers/staging/crystalhd/crystalhd_misc.h index aa736c8855de..77ab72a2a061 100644 --- a/drivers/staging/crystalhd/crystalhd_misc.h +++ b/drivers/staging/crystalhd/crystalhd_misc.h @@ -206,7 +206,7 @@ extern void crystalhd_show_buffer(uint32_t off, uint8_t *buff, enum _chd_log_levels { BCMLOG_ERROR = 0x80000000, /* Don't disable this option */ BCMLOG_DATA = 0x40000000, /* Data, enable by default */ - BCMLOG_SPINLOCK = 0x20000000, /* Spcial case for Spin locks*/ + BCMLOG_SPINLOCK = 0x20000000, /* Special case for Spin locks*/ /* Following are allowed only in debug mode */ BCMLOG_INFO = 0x00000001, /* Generic informational */ -- cgit v1.2.3 From a1caff6de83acca44faecea14b72724cebb9972e Mon Sep 17 00:00:00 2001 From: Samuel Domínguez Date: Thu, 5 Dec 2013 16:16:13 +0000 Subject: staging: lustre: lnet: lnet: fixed space coding style issues Fixed a coding style issue with spaces between function names and arguments: func (x) -> func(x) Signed-off-by: Samuel Dominguez Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/lib-msg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 61ae88be6f02..761f1e12f847 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -43,7 +43,7 @@ #include void -lnet_build_unlink_event (lnet_libmd_t *md, lnet_event_t *ev) +lnet_build_unlink_event(lnet_libmd_t *md, lnet_event_t *ev) { memset(ev, 0, sizeof(*ev)); @@ -362,7 +362,7 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) int rc; int status = msg->msg_ev.status; - LASSERT (msg->msg_onactivelist); + LASSERT(msg->msg_onactivelist); if (status == 0 && msg->msg_ack) { /* Only send an ACK if the PUT completed successfully */ @@ -432,7 +432,7 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) } void -lnet_finalize (lnet_ni_t *ni, lnet_msg_t *msg, int status) +lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) { struct lnet_msg_container *container; int my_slot; @@ -440,7 +440,7 @@ lnet_finalize (lnet_ni_t *ni, lnet_msg_t *msg, int status) int rc; int i; - LASSERT (!in_interrupt ()); + LASSERT(!in_interrupt()); if (msg == NULL) return; -- cgit v1.2.3 From 6cb8e1a27ad7a966ba2cce1b968404b590943105 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:21 -0700 Subject: staging: comedi: ni_at_2150: tidy up irq/dma request This driver needs both an irq and dma in order to support async commands. If the irq and dma are not available the driver will still function for single analog input reads. Tidy up the code that does the irq and dma requests so that the driver will still attach if they are not avaliable. The attach will still fail, with -ENOMEM, if the dma buffer cannot be allocated. Remove the noise about the irq and dma during the attach. Only hook up the async commands support if the irq and dma are available. Remove the then unnecessary sanity check in a2150_ai_cmd(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_at_a2150.c | 79 ++++++++++++---------------- 1 file changed, 33 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index cc69ddef0a67..0876bc5c0209 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -395,11 +395,6 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int old_config_bits = devpriv->config_bits; unsigned int trigger_bits; - if (!dev->irq || !devpriv->dma) { - comedi_error(dev, - " irq and dma required, cannot do hardware conversions"); - return -1; - } if (cmd->flags & TRIG_RT) { comedi_error(dev, " dma incompatible with hard real-time interrupt (TRIG_RT), aborting"); @@ -703,46 +698,35 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - /* grab our IRQ */ - if (irq) { - /* check that irq is supported */ - if (irq < 3 || irq == 8 || irq == 13 || irq > 15) { - printk(" invalid irq line %u\n", irq); - return -EINVAL; - } - if (request_irq(irq, a2150_interrupt, 0, - dev->driver->driver_name, dev)) { - printk("unable to allocate irq %u\n", irq); - return -EINVAL; + dev->board_ptr = a2150_boards + a2150_probe(dev); + thisboard = comedi_board(dev); + dev->board_name = thisboard->name; + + if ((irq >= 3 && irq <= 7) || (irq >= 9 && irq <= 12) || + irq == 14 || irq == 15) { + ret = request_irq(irq, a2150_interrupt, 0, + dev->board_name, dev); + if (ret == 0) { + devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq); + dev->irq = irq; } - devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq); - dev->irq = irq; } - /* initialize dma */ - if (dma) { - if (dma == 4 || dma > 7) { - printk(" invalid dma channel %u\n", dma); - return -EINVAL; - } - if (request_dma(dma, dev->driver->driver_name)) { - printk(" failed to allocate dma channel %u\n", dma); - return -EINVAL; - } - devpriv->dma = dma; - devpriv->dma_buffer = - kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->dma_buffer == NULL) - return -ENOMEM; - disable_dma(dma); - set_dma_mode(dma, DMA_MODE_READ); + if (dev->irq && ((dma >= 0 && dma <= 4) || (dma >= 5 && dma <= 7))) { + ret = request_dma(dma, dev->board_name); + if (ret == 0) { + devpriv->dma = dma; + devpriv->dma_buffer = kmalloc(A2150_DMA_BUFFER_SIZE, + GFP_KERNEL | GFP_DMA); + if (!devpriv->dma_buffer) + return -ENOMEM; - devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma); - } + disable_dma(dma); + set_dma_mode(dma, DMA_MODE_READ); - dev->board_ptr = a2150_boards + a2150_probe(dev); - thisboard = comedi_board(dev); - dev->board_name = thisboard->name; + devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma); + } + } ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -750,17 +734,20 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* analog input subdevice */ s = &dev->subdevices[0]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER; s->n_chan = 4; - s->len_chanlist = 4; s->maxdata = 0xffff; s->range_table = &range_a2150; - s->do_cmd = a2150_ai_cmd; - s->do_cmdtest = a2150_ai_cmdtest; s->insn_read = a2150_ai_rinsn; - s->cancel = a2150_cancel; + if (dev->irq && devpriv->dma) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmd = a2150_ai_cmd; + s->do_cmdtest = a2150_ai_cmdtest; + s->cancel = a2150_cancel; + } /* need to do this for software counting of completed conversions, to * prevent hardware count from stopping acquisition */ -- cgit v1.2.3 From b3403f2e5e4b860bc26e2a5556a5a2d201c752e2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:22 -0700 Subject: staging: comedi: me4000: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 081a31004801..e4afca44b5e0 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1105,7 +1105,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) { unsigned int tmp; struct comedi_device *dev = dev_id; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; int i; int c = 0; unsigned int lval; -- cgit v1.2.3 From a9b7ff9398a2c994662ea7ea02a0dd474d5c5ac7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:23 -0700 Subject: staging: comedi: me4000: refactor request_irq() during attach Do the request_irq() before setting up the subdevices. This removes an indent level and makes the code a bit cleaner. Also, remove the dev_warn() noise about the irq. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index e4afca44b5e0..cb1032fb3248 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1505,6 +1505,13 @@ static int me4000_auto_attach(struct comedi_device *dev, me4000_reset(dev); + if (pcidev->irq > 0) { + result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED, + dev->board_name, dev); + if (result == 0) + dev->irq = pcidev->irq; + } + result = comedi_alloc_subdevices(dev, 4); if (result) return result; @@ -1525,22 +1532,12 @@ static int me4000_auto_attach(struct comedi_device *dev, s->range_table = &me4000_ai_range; s->insn_read = me4000_ai_insn_read; - if (pcidev->irq > 0) { - if (request_irq(pcidev->irq, me4000_ai_isr, - IRQF_SHARED, dev->board_name, dev)) { - dev_warn(dev->class_dev, - "request_irq failed\n"); - } else { - dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->cancel = me4000_ai_cancel; - s->do_cmdtest = me4000_ai_do_cmd_test; - s->do_cmd = me4000_ai_do_cmd; - - dev->irq = pcidev->irq; - } - } else { - dev_warn(dev->class_dev, "No interrupt available\n"); + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->cancel = me4000_ai_cancel; + s->do_cmdtest = me4000_ai_do_cmd_test; + s->do_cmd = me4000_ai_do_cmd; } } else { s->type = COMEDI_SUBD_UNUSED; -- cgit v1.2.3 From 2d85664807cda87acf61c3d37f554bdcc298112c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:24 -0700 Subject: staging: comedi: me4000: remove unnecessary check in the irq handler The sanity check of the irq is not necessary. If it _is_ wrong we have bigger problems in the kernel... Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/me4000.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index cb1032fb3248..7276002db38d 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1116,12 +1116,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) /* Reset all events */ s->async->events = 0; - /* Check if irq number is right */ - if (irq != dev->irq) { - dev_err(dev->class_dev, "Incorrect interrupt num: %d\n", irq); - return IRQ_HANDLED; - } - if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & ME4000_IRQ_STATUS_BIT_AI_HF) { /* Read status register to find out what happened */ -- cgit v1.2.3 From ed7a693f1391c053a355e7210c238bcb4fb7a332 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:25 -0700 Subject: staging: comedi: das1800: tidy up irq request This driver only needs an irq in order to support async commands. If the irq is not available the driver will still function for single analog input reads. Tidy up the code that does the irq requests so that the driver will still attach if it is not avaliable. Remove the noise about the irq during the attach. Only hook up the async commands support if the irq is available. Remove the then unnecessary sanity check in das1800_ai_do_cmd(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das1800.c | 86 ++++++++++++++------------------ 1 file changed, 37 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 1880038956d0..92df02d989a6 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1150,12 +1150,6 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_async *async = s->async; const struct comedi_cmd *cmd = &async->cmd; - if (!dev->irq) { - comedi_error(dev, - "no irq assigned for das-1800, cannot do hardware conversions"); - return -1; - } - /* disable dma on TRIG_WAKE_EOS, or TRIG_RT * (because dma in handler is unsafe at hard real-time priority) */ if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) @@ -1522,43 +1516,34 @@ static int das1800_attach(struct comedi_device *dev, devpriv->iobase2 = iobase2; } - /* grab our IRQ */ - if (irq) { - if (request_irq(irq, das1800_interrupt, 0, - dev->driver->driver_name, dev)) { - dev_dbg(dev->class_dev, "unable to allocate irq %u\n", - irq); - return -EINVAL; - } - } - dev->irq = irq; + if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 || + irq == 15) { + ret = request_irq(irq, das1800_interrupt, 0, + dev->board_name, dev); + if (ret == 0) { + dev->irq = irq; - /* set bits that tell card which irq to use */ - switch (irq) { - case 0: - break; - case 3: - devpriv->irq_dma_bits |= 0x8; - break; - case 5: - devpriv->irq_dma_bits |= 0x10; - break; - case 7: - devpriv->irq_dma_bits |= 0x18; - break; - case 10: - devpriv->irq_dma_bits |= 0x28; - break; - case 11: - devpriv->irq_dma_bits |= 0x30; - break; - case 15: - devpriv->irq_dma_bits |= 0x38; - break; - default: - dev_err(dev->class_dev, "irq out of range\n"); - return -EINVAL; - break; + switch (irq) { + case 3: + devpriv->irq_dma_bits |= 0x8; + break; + case 5: + devpriv->irq_dma_bits |= 0x10; + break; + case 7: + devpriv->irq_dma_bits |= 0x18; + break; + case 10: + devpriv->irq_dma_bits |= 0x28; + break; + case 11: + devpriv->irq_dma_bits |= 0x30; + break; + case 15: + devpriv->irq_dma_bits |= 0x38; + break; + } + } } ret = das1800_init_dma(dev, dma0, dma1); @@ -1578,20 +1563,23 @@ static int das1800_attach(struct comedi_device *dev, /* analog input subdevice */ s = &dev->subdevices[0]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; if (thisboard->common) s->subdev_flags |= SDF_COMMON; s->n_chan = thisboard->qram_len; - s->len_chanlist = thisboard->qram_len; s->maxdata = (1 << thisboard->resolution) - 1; s->range_table = thisboard->range_ai; - s->do_cmd = das1800_ai_do_cmd; - s->do_cmdtest = das1800_ai_do_cmdtest; s->insn_read = das1800_ai_rinsn; - s->poll = das1800_ai_poll; - s->cancel = das1800_cancel; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmd = das1800_ai_do_cmd; + s->do_cmdtest = das1800_ai_do_cmdtest; + s->poll = das1800_ai_poll; + s->cancel = das1800_cancel; + } /* analog out */ s = &dev->subdevices[1]; -- cgit v1.2.3 From 6f6e144d4d53e29a9f6487e4baed748f3fde1fa2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:26 -0700 Subject: staging: comedi: das1800: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das1800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 92df02d989a6..37e92a0373f1 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -644,7 +644,7 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static void das1800_ai_handler(struct comedi_device *dev) { struct das1800_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int status = inb(dev->iobase + DAS1800_STATUS); -- cgit v1.2.3 From b70625c684529c80d9cff4b8e44afb34d5ee99de Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:27 -0700 Subject: staging: comedi: das16m1: remove unnecessary 'dev->irq' test This function can only be called if the irq was sucessfully requested. The dev->irq will always be valid. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16m1.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 0081ee4f4dc1..36c2ba5057fa 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -269,11 +269,6 @@ static int das16m1_cmd_exec(struct comedi_device *dev, struct comedi_cmd *cmd = &async->cmd; unsigned int byte, i; - if (dev->irq == 0) { - comedi_error(dev, "irq required to execute comedi_cmd"); - return -1; - } - /* disable interrupts and internal pacer */ devpriv->control_state &= ~INTE & ~PACER_MASK; outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); -- cgit v1.2.3 From 48108fe3daa0d142f9b97178fdb23704ea3a407b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:28 -0700 Subject: staging: comedi: adl_pci9111: fix incorrect irq passed to request_irq() The dev->irq passed to request_irq() will always be 0 when the auto_attach function is called. The pcidev->irq should be used instead to get the correct irq number. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9111.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 03b38ea92cb0..8dd39739b462 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -859,7 +859,7 @@ static int pci9111_auto_attach(struct comedi_device *dev, pci9111_reset(dev); if (pcidev->irq > 0) { - ret = request_irq(dev->irq, pci9111_interrupt, + ret = request_irq(pcidev->irq, pci9111_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret) return ret; -- cgit v1.2.3 From 66d10158e03d4bad0520c13b953c63ff7a4bd741 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:29 -0700 Subject: staging: comedi: adl_pci9111: the irq is only needed for async command support An irq is only needed for async command support, modify the attach of the subdevices so that the command support is only hooked up if the irq request was successful. Remove the then unnecessary sanity check in pci9111_ai_do_cmd(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9111.c | 29 +++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 8dd39739b462..de763ec4ce21 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -470,11 +470,6 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, struct pci9111_private_data *dev_private = dev->private; struct comedi_cmd *async_cmd = &s->async->cmd; - if (!dev->irq) { - comedi_error(dev, - "no irq assigned for PCI9111, cannot do hardware conversion"); - return -1; - } /* Set channel scan limit */ /* PCI9111 allows only scanning from channel 0 to channel n */ /* TODO: handle the case of an external multiplexer */ @@ -858,12 +853,11 @@ static int pci9111_auto_attach(struct comedi_device *dev, pci9111_reset(dev); - if (pcidev->irq > 0) { + if (pcidev->irq) { ret = request_irq(pcidev->irq, pci9111_interrupt, IRQF_SHARED, dev->board_name, dev); - if (ret) - return ret; - dev->irq = pcidev->irq; + if (ret == 0) + dev->irq = pcidev->irq; } ret = comedi_alloc_subdevices(dev, 4); @@ -871,18 +865,21 @@ static int pci9111_auto_attach(struct comedi_device *dev, return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_COMMON; s->n_chan = 16; s->maxdata = 0xffff; - s->len_chanlist = 16; s->range_table = &pci9111_ai_range; - s->cancel = pci9111_ai_cancel; s->insn_read = pci9111_ai_insn_read; - s->do_cmdtest = pci9111_ai_do_cmd_test; - s->do_cmd = pci9111_ai_do_cmd; - s->munge = pci9111_ai_munge; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmdtest = pci9111_ai_do_cmd_test; + s->do_cmd = pci9111_ai_do_cmd; + s->cancel = pci9111_ai_cancel; + s->munge = pci9111_ai_munge; + } s = &dev->subdevices[1]; s->type = COMEDI_SUBD_AO; -- cgit v1.2.3 From 89d483850f4c378ec15e4b1eafcbc2ae845fc67e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:30 -0700 Subject: staging: comedi: dt2814: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2814.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index e52d22e0ba63..abad6e49c1c1 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -197,7 +197,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d) int lo, hi; struct comedi_device *dev = d; struct dt2814_private *devpriv = dev->private; - struct comedi_subdevice *s; + struct comedi_subdevice *s = dev->read_subdev; int data; if (!dev->attached) { @@ -205,8 +205,6 @@ static irqreturn_t dt2814_interrupt(int irq, void *d) return IRQ_HANDLED; } - s = &dev->subdevices[0]; - hi = inb(dev->iobase + DT2814_DATA); lo = inb(dev->iobase + DT2814_DATA); -- cgit v1.2.3 From 9ee0de0ec1196df99c9d6ecec6a25ee383de6bc1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:31 -0700 Subject: staging: comedi: dt282x: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index df37d185125f..5815fc289299 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -339,11 +339,11 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev) static void dt282x_ai_dma_interrupt(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; void *ptr; int size; int i; int ret; - struct comedi_subdevice *s = &dev->subdevices[0]; outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); @@ -448,7 +448,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct dt282x_private *devpriv = dev->private; - struct comedi_subdevice *s; + struct comedi_subdevice *s = dev->read_subdev; struct comedi_subdevice *s_ao; unsigned int supcsr, adcsr, dacsr; int handled = 0; @@ -458,7 +458,6 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) return IRQ_HANDLED; } - s = &dev->subdevices[0]; s_ao = &dev->subdevices[1]; adcsr = inw(dev->iobase + DT2821_ADCSR); dacsr = inw(dev->iobase + DT2821_DACSR); -- cgit v1.2.3 From 95dc140a5e9210c6305b4f8b91cf2e654e1bba1e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:32 -0700 Subject: staging: comedi: dt282x: use dev->write_subdev Use the dev->write_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 5815fc289299..ae714a526c35 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -306,10 +306,10 @@ static void dt282x_munge(struct comedi_device *dev, unsigned short *buf, static void dt282x_ao_dma_interrupt(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->write_subdev; void *ptr; int size; int i; - struct comedi_subdevice *s = &dev->subdevices[1]; outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); @@ -449,7 +449,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) struct comedi_device *dev = d; struct dt282x_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_subdevice *s_ao; + struct comedi_subdevice *s_ao = dev->write_subdev; unsigned int supcsr, adcsr, dacsr; int handled = 0; @@ -458,7 +458,6 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) return IRQ_HANDLED; } - s_ao = &dev->subdevices[1]; adcsr = inw(dev->iobase + DT2821_ADCSR); dacsr = inw(dev->iobase + DT2821_DACSR); supcsr = inw(dev->iobase + DT2821_SUPCSR); -- cgit v1.2.3 From e10c19a83c223777d5b302c683fdbad9cc57ff53 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:33 -0700 Subject: staging: comedi: amplc_pci230: tidy up irq request Clean up the irq request in the attach of this driver and remove the dev_{level} noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 58e7a43586e6..48a0f527b431 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2633,7 +2633,7 @@ static int pci230_attach_common(struct comedi_device *dev, struct comedi_subdevice *s; unsigned long iobase1, iobase2; /* PCI230's I/O spaces 1 and 2 respectively. */ - int irq_hdl, rc; + int rc; comedi_set_hw_dev(dev, &pci_dev->dev); @@ -2705,16 +2705,12 @@ static int pci230_attach_common(struct comedi_device *dev, outw(devpriv->adcg, dev->iobase + PCI230_ADCG); outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); - /* Register the interrupt handler. */ - irq_hdl = request_irq(pci_dev->irq, pci230_interrupt, - IRQF_SHARED, "amplc_pci230", dev); - if (irq_hdl < 0) { - dev_warn(dev->class_dev, - "unable to register irq %u, commands will not be available\n", - pci_dev->irq); - } else { - dev->irq = pci_dev->irq; - dev_dbg(dev->class_dev, "registered irq %u\n", pci_dev->irq); + + if (pci_dev->irq) { + rc = request_irq(pci_dev->irq, pci230_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (rc == 0) + dev->irq = pci_dev->irq; } rc = comedi_alloc_subdevices(dev, 3); @@ -2730,14 +2726,14 @@ static int pci230_attach_common(struct comedi_device *dev, s->range_table = &pci230_ai_range; s->insn_read = &pci230_ai_rinsn; s->len_chanlist = 256; /* but there are restrictions. */ - /* Only register commands if the interrupt handler is installed. */ - if (irq_hdl == 0) { + if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->do_cmd = &pci230_ai_cmd; s->do_cmdtest = &pci230_ai_cmdtest; s->cancel = pci230_ai_cancel; } + s = &dev->subdevices[1]; /* analog output subdevice */ if (thisboard->ao_chans > 0) { @@ -2749,9 +2745,7 @@ static int pci230_attach_common(struct comedi_device *dev, s->insn_write = &pci230_ao_winsn; s->insn_read = &pci230_ao_rinsn; s->len_chanlist = thisboard->ao_chans; - /* Only register commands if the interrupt handler is - * installed. */ - if (irq_hdl == 0) { + if (dev->irq) { dev->write_subdev = s; s->subdev_flags |= SDF_CMD_WRITE; s->do_cmd = &pci230_ao_cmd; @@ -2761,6 +2755,7 @@ static int pci230_attach_common(struct comedi_device *dev, } else { s->type = COMEDI_SUBD_UNUSED; } + s = &dev->subdevices[2]; /* digital i/o subdevice */ if (thisboard->have_dio) { -- cgit v1.2.3 From 19cf54dd39f2213232ceb4ed1102876a3bd983f1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:34 -0700 Subject: staging: comedi: adl_pci9118: tidy up irq request Clean up the irq request in the attach of this driver and remove the dev_{level} noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9118.c | 43 +++++++++++----------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 97343cc40515..7e66978dc4b2 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1965,7 +1965,6 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int ret, pages, i; - unsigned int irq; u16 u16w; dev->board_name = this_board->name; @@ -2036,12 +2035,18 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64); /* Enable parity check for parity error */ + if (!disable_irq && pcidev->irq) { + ret = request_irq(pcidev->irq, interrupt_pci9118, IRQF_SHARED, + dev->board_name, dev); + if (ret == 0) + dev->irq = pcidev->irq; + } + ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; if (devpriv->usemux) @@ -2050,11 +2055,17 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, s->n_chan = this_board->n_aichan; s->maxdata = this_board->ai_maxdata; - s->len_chanlist = this_board->n_aichanlist; s->range_table = this_board->rangelist_ai; - s->cancel = pci9118_ai_cancel; s->insn_read = pci9118_insn_read_ai; - s->munge = pci9118_ai_munge; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = this_board->n_aichanlist; + s->do_cmdtest = pci9118_ai_cmdtest; + s->do_cmd = pci9118_ai_cmd; + s->cancel = pci9118_ai_cancel; + s->munge = pci9118_ai_munge; + } s = &dev->subdevices[1]; s->type = COMEDI_SUBD_AO; @@ -2100,27 +2111,7 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, break; } - if (disable_irq) - irq = 0; - else - irq = pcidev->irq; - if (irq > 0) { - if (request_irq(irq, interrupt_pci9118, IRQF_SHARED, - dev->board_name, dev)) { - dev_warn(dev->class_dev, - "unable to allocate IRQ %u, DISABLING IT\n", - irq); - } else { - dev->irq = irq; - /* Enable AI commands */ - s = &dev->subdevices[0]; - s->subdev_flags |= SDF_CMD_READ; - s->do_cmdtest = pci9118_ai_cmdtest; - s->do_cmd = pci9118_ai_cmd; - } - } - - pci9118_report_attach(dev, irq); + pci9118_report_attach(dev, dev->irq); return 0; } -- cgit v1.2.3 From 67fb892cc14aa3159aa68cbda2bd6cc30e2e7fd8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:35 -0700 Subject: staging: comedi: adv_pci1710: only init async command members when needed The 'len_chanlist' and 'cancel' members of the comedi_subdevice are only used with async command support. Only initialize them if the irq was sucessfully requested. Also, only init the dev->read_subdev if we have the irq. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adv_pci1710.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index a1519c98022f..69ab2a67dcb4 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1264,21 +1264,21 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (this_board->n_aichan) { s = &dev->subdevices[subdev]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; if (this_board->n_aichand) s->subdev_flags |= SDF_DIFF; s->n_chan = this_board->n_aichan; s->maxdata = this_board->ai_maxdata; - s->len_chanlist = this_board->n_aichan; s->range_table = this_board->rangelist_ai; - s->cancel = pci171x_ai_cancel; s->insn_read = pci171x_insn_read_ai; if (dev->irq) { + dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; s->do_cmdtest = pci171x_ai_cmdtest; s->do_cmd = pci171x_ai_cmd; + s->cancel = pci171x_ai_cancel; } devpriv->i8254_osc_base = I8254_OSC_BASE_10MHZ; subdev++; -- cgit v1.2.3 From 1f0e7161888a4852ef529d7def6ef1700a9f93e4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:36 -0700 Subject: staging: comedi: adv_pci1710: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adv_pci1710.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 69ab2a67dcb4..3957da5500e2 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -731,7 +731,7 @@ static void interrupt_pci1710_every_sample(void *d) { struct comedi_device *dev = d; struct pci1710_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; int m; #ifdef PCI171x_PARANOIDCHECK const struct boardtype *this_board = comedi_board(dev); @@ -859,7 +859,7 @@ static void interrupt_pci1710_half_fifo(void *d) struct comedi_device *dev = d; const struct boardtype *this_board = comedi_board(dev); struct pci1710_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; int m, samplesinbuf; m = inw(dev->iobase + PCI171x_STATUS); -- cgit v1.2.3 From 98f6303b6faf342e3e8ad8d2be2e51f5f32ed30e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:37 -0700 Subject: staging: comedi: dt3000: don't fail attach if irq is not available The irq is only needed to support async commands. Don't fail the attach if it is not available. Only hook up the command support if the request_irq() was successful. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt3000.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 1410943807b9..50aaa011153c 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -702,29 +702,33 @@ static int dt3000_auto_attach(struct comedi_device *dev, if (!devpriv->io_addr) return -ENOMEM; - ret = request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED, - dev->board_name, dev); - if (ret) - return ret; - dev->irq = pcidev->irq; + if (pcidev->irq) { + ret = request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (ret == 0) + dev->irq = pcidev->irq; + } ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; /* ai subdevice */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = this_board->adchan; s->insn_read = dt3k_ai_insn; s->maxdata = (1 << this_board->adbits) - 1; - s->len_chanlist = 512; s->range_table = &range_dt3000_ai; /* XXX */ - s->do_cmd = dt3k_ai_cmd; - s->do_cmdtest = dt3k_ai_cmdtest; - s->cancel = dt3k_ai_cancel; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 512; + s->do_cmd = dt3k_ai_cmd; + s->do_cmdtest = dt3k_ai_cmdtest; + s->cancel = dt3k_ai_cancel; + } s = &dev->subdevices[1]; /* ao subsystem */ -- cgit v1.2.3 From 1580994f6c81b8c4b47f2c8f1e2c7cefcf2923fe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:38 -0700 Subject: staging: comedi: dt3000: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt3000.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 50aaa011153c..f52a4476cb73 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -352,13 +352,12 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct dt3k_private *devpriv = dev->private; - struct comedi_subdevice *s; + struct comedi_subdevice *s = dev->read_subdev; unsigned int status; if (!dev->attached) return IRQ_NONE; - s = &dev->subdevices[0]; status = readw(devpriv->io_addr + DPR_Intr_Flag); if (status & DT3000_ADFULL) { -- cgit v1.2.3 From 9c9ab3c1a477aa3f8bdb91f51061e567867d4c60 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:39 -0700 Subject: staging: comedi: s626: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 583583854dca..ae13b0ee725b 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1614,12 +1614,13 @@ static irqreturn_t s626_irq_handler(int irq, void *d) static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl) { struct s626_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_cmd *cmd = &s->async->cmd; uint32_t *rps; uint32_t jmp_adrs; uint16_t i; uint16_t n; uint32_t local_ppl; - struct comedi_cmd *cmd = &dev->subdevices->async->cmd; /* Stop RPS program in case it is currently running */ s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); @@ -2639,6 +2640,7 @@ static void s626_initialize(struct comedi_device *dev) * a defined state after a PCI reset. */ { + struct comedi_subdevice *s = dev->read_subdev; uint8_t poll_list; uint16_t adc_data; uint16_t start_val; @@ -2650,7 +2652,7 @@ static void s626_initialize(struct comedi_device *dev) s626_reset_adc(dev, &poll_list); /* Get initial ADC value */ - s626_ai_rinsn(dev, dev->subdevices, NULL, data); + s626_ai_rinsn(dev, s, NULL, data); start_val = data[0]; /* @@ -2664,7 +2666,7 @@ static void s626_initialize(struct comedi_device *dev) * being unusually quiet or at the rail. */ for (index = 0; index < 500; index++) { - s626_ai_rinsn(dev, dev->subdevices, NULL, data); + s626_ai_rinsn(dev, s, NULL, data); adc_data = data[0]; if (adc_data != start_val) break; -- cgit v1.2.3 From 156041e9e432eaa97999c976be4203416038c9f6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:40 -0700 Subject: staging: comedi: hwrdv_apci3120: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index 3c9eec84f0eb..bd05857b82f2 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -1414,7 +1414,7 @@ static void v_APCI3120_InterruptDma(int irq, void *d) { struct comedi_device *dev = d; struct addi_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; unsigned int next_dma_buf, samplesinbuf; unsigned long low_word, high_word, var; unsigned int ui_Tmp; @@ -1568,8 +1568,8 @@ static void v_APCI3120_InterruptDma(int irq, void *d) static int i_APCI3120_InterruptHandleEos(struct comedi_device *dev) { struct addi_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; int n_chan, i; - struct comedi_subdevice *s = &dev->subdevices[0]; int err = 1; n_chan = devpriv->ui_AiNbrofChannels; @@ -1593,11 +1593,11 @@ static void v_APCI3120_Interrupt(int irq, void *d) { struct comedi_device *dev = d; struct addi_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; unsigned short int_daq; unsigned int int_amcc, ui_Check, i; unsigned short us_TmpValue; unsigned char b_DummyRead; - struct comedi_subdevice *s = &dev->subdevices[0]; ui_Check = 1; -- cgit v1.2.3 From c9e004dad9dd63d5c0e16d3a4e8a8761e616a6ce Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:41 -0700 Subject: staging: comedi: hwrdv_apci3200: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index dc73d4d348ed..8c85a09d1c66 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -2590,8 +2590,8 @@ static int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, static int i_APCI3200_InterruptHandleEos(struct comedi_device *dev) { struct addi_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; unsigned int ui_StatusRegister = 0; - struct comedi_subdevice *s = &dev->subdevices[0]; /* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */ /* comedi_async *async = s->async; */ -- cgit v1.2.3 From d2443fe3b1b968a7bde4fa8e70542ba5baac3d89 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:42 -0700 Subject: staging: comedi: adl_pci9118: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adl_pci9118.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 7e66978dc4b2..a1de96356e30 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1126,7 +1126,7 @@ static irqreturn_t interrupt_pci9118(int irq, void *d) } } - (devpriv->int_ai_func) (dev, &dev->subdevices[0], int_adstat, + (devpriv->int_ai_func) (dev, dev->read_subdev, int_adstat, int_amcc, int_daq); } -- cgit v1.2.3 From c82ea5b4a9ca1ff9c36e4f077898775d82f1dec4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:43 -0700 Subject: staging: comedi: amplc_pc236: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index eaf21ce37ed5..31734e1142fd 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -356,7 +356,7 @@ static int pc236_intr_cancel(struct comedi_device *dev, static irqreturn_t pc236_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[1]; + struct comedi_subdevice *s = dev->read_subdev; int handled; handled = pc236_intr_check(dev); -- cgit v1.2.3 From f127c47d23613a7f61c6c4783932ece566873888 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:44 -0700 Subject: staging: comedi: amplc_pci224: use dev->write_subdev Use the dev->write_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 230a0103497b..f16b4724632c 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1140,7 +1140,7 @@ static irqreturn_t pci224_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct pci224_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->write_subdev; struct comedi_cmd *cmd; unsigned char intstat, valid_intstat; unsigned char curenab; -- cgit v1.2.3 From 33524ed16f1491a0c439a95a932d5dd7f005e557 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:45 -0700 Subject: staging: comedi: ni_65xx: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_65xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index effa12482c8d..6e42001f686e 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -427,7 +427,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct ni_65xx_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[2]; + struct comedi_subdevice *s = dev->read_subdev; unsigned int status; status = readb(devpriv->mite->daq_io_addr + Change_Status); -- cgit v1.2.3 From bea70d0b2dc078c7eab3049c44aade037ffbcb90 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:46 -0700 Subject: staging: comedi: ni_atmio16d: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio16d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 834c9e1e6058..3a92fe52b9ac 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -229,7 +229,7 @@ static void reset_atmio16d(struct comedi_device *dev) static irqreturn_t atmio16d_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); -- cgit v1.2.3 From 9eba3a279be68ec7ff553fac33749498e7a9b733 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:47 -0700 Subject: staging: comedi: rtd520: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rtd520.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index c6a664f38c31..0f026afde9be 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -689,7 +689,7 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) static irqreturn_t rtd_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; struct rtd_private *devpriv = dev->private; u32 overrun; u16 status; -- cgit v1.2.3 From de1e27a6df158162c963f44edfb4c0a1fcfe0766 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:48 -0700 Subject: staging: comedi: ni_pcidio: factor board reset out of attach Factor the code that resets the board and disables the interrupts out of the attach. Move the reset so it happens before the subdevices are initialized. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 645a4d80e608..ef72fc79523e 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -949,6 +949,19 @@ static int pci_6534_upload_firmware(struct comedi_device *dev) return ret; } +static void nidio_reset_board(struct comedi_device *dev) +{ + struct nidio96_private *devpriv = dev->private; + void __iomem *daq_mmio = devpriv->mite->daq_io_addr; + + writel(0, daq_mmio + Port_IO(0)); + writel(0, daq_mmio + Port_Pin_Directions(0)); + writel(0, daq_mmio + Port_Pin_Mask(0)); + + /* disable interrupts on board */ + writeb(0, daq_mmio + Master_DMA_And_Interrupt_Control); +} + static int nidio_auto_attach(struct comedi_device *dev, unsigned long context) { @@ -996,6 +1009,8 @@ static int nidio_auto_attach(struct comedi_device *dev, return ret; } + nidio_reset_board(dev); + ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; @@ -1023,15 +1038,6 @@ static int nidio_auto_attach(struct comedi_device *dev, s->async_dma_dir = DMA_BIDIRECTIONAL; s->poll = &ni_pcidio_poll; - writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); - writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); - writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0)); - - /* disable interrupts on board */ - writeb(0x00, - devpriv->mite->daq_io_addr + - Master_DMA_And_Interrupt_Control); - irq = mite_irq(devpriv->mite); if (irq) { ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, -- cgit v1.2.3 From 7a68ef933b8d244fafed5bafd1572ed444ca4d1a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 13:43:49 -0700 Subject: staging: comedi: ni_pcidio: use dev->read_subdev Use the dev->read_subdev that was setup in the device attach instead of accessing the dev->subdevices array directly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index ef72fc79523e..30c46a3c1767 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -384,7 +384,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct nidio96_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct mite_struct *mite = devpriv->mite; -- cgit v1.2.3 From 04426acfb86ad10968340771bb15f6074e12912f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:03 -0700 Subject: staging: comedi: pcmuio: fix interrupt requests Legacy (ISA) interrupts are not sharable so this driver should not be passing the IRQF_SHARED flag when requesting the interrupts. This driver supports two board types: PCM-UIO48 with one asic (one interrupt source) PCM-UIO96 with two asics (two interrupt sources) The PCM-UIO96 has a jumper that allows the two interrupt sources to share an interrupt. This is safe for legacy interrupts as long as the "shared" interrupt is handled by a single driver. Modify the request_irq() code in this driver to correctly request the interrupts. For the PCM-UI048 case (one asic) only one request_irq() is needed. For the PCM-UIO96 (two asics) there are three cases: 1) irq is shared, one request_irq() call 2) only one asic has an irq, one request_irq() call 3) two irqs, two request_irq() calls The irq for the first asic (dev->irq) will be requested during the attach if required. The comedi core will handle the freeing of this irq during the detach. The irq for the second asic (devpriv->irq2) will also be requested during the attach if required. The freeing of this irq will be handled by the driver during the detach. Move the board reset and interrupt request code so it occurs early in the attach. We can then check dev->irq and devpriv->irq2 to see if the subdevice command support actually needs to be initialized. This also simplifies the interrupt handler. The irq can be simply checked against dev->irq and devpriv->irq2 to see which asic caused the interrupt. Add a call to pcmuio_reset() in the (*detach) to make sure the interrupts are disabled before freeing the irqs. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 81 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 954fa96a50ac..dfa728052265 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -146,10 +146,10 @@ struct pcmuio_subdev_private { struct pcmuio_private { struct { - unsigned int irq; spinlock_t spinlock; } asics[PCMUIO_MAX_ASICS]; struct pcmuio_subdev_private *sprivs; + unsigned int irq2; }; static void pcmuio_write(struct comedi_device *dev, unsigned int val, @@ -390,19 +390,14 @@ static irqreturn_t pcmuio_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct pcmuio_private *devpriv = dev->private; - int got1 = 0; - int asic; + int handled = 0; - for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) { - if (irq == devpriv->asics[asic].irq) { - /* it is an interrupt for ASIC #asic */ - if (pcmuio_handle_asic_interrupt(dev, asic)) - got1++; - } - } - if (!got1) - return IRQ_NONE; /* interrupt from other source */ - return IRQ_HANDLED; + if (irq == dev->irq) + handled += pcmuio_handle_asic_interrupt(dev, 0); + if (irq == devpriv->irq2) + handled += pcmuio_handle_asic_interrupt(dev, 1); + + return handled ? IRQ_HANDLED : IRQ_NONE; } static int pcmuio_start_intr(struct comedi_device *dev, @@ -591,12 +586,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pcmuio_private *devpriv; struct pcmuio_subdev_private *subpriv; int sdev_no, n_subdevs, asic; - unsigned int irq[PCMUIO_MAX_ASICS]; int ret; - irq[0] = it->options[1]; - irq[1] = it->options[2]; - ret = comedi_request_region(dev, it->options[0], board->num_asics * PCMUIO_ASIC_IOSIZE); if (ret) @@ -609,6 +600,29 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) spin_lock_init(&devpriv->asics[asic].spinlock); + pcmuio_reset(dev); + + if (it->options[1]) { + /* request the irq for the 1st asic */ + ret = request_irq(it->options[1], pcmuio_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; + } + + if (board->num_asics == 2) { + if (it->options[2] == dev->irq) { + /* the same irq (or none) is used by both asics */ + devpriv->irq2 = it->options[2]; + } else if (it->options[2]) { + /* request the irq for the 2nd asic */ + ret = request_irq(it->options[2], pcmuio_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + devpriv->irq2 = it->options[2]; + } + } + n_subdevs = board->num_asics * 2; devpriv->sprivs = kcalloc(n_subdevs, sizeof(*subpriv), GFP_KERNEL); if (!devpriv->sprivs) @@ -630,8 +644,9 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_config = pcmuio_dio_insn_config; s->n_chan = 24; - /* subdevices 0 and 2 suppport interrupts */ - if ((sdev_no % 2) == 0) { + /* subdevices 0 and 2 can suppport interrupts */ + if ((sdev_no == 0 && dev->irq) || + (sdev_no == 2 && devpriv->irq2)) { /* setup the interrupt subdevice */ subpriv->intr.asic = sdev_no / 2; dev->read_subdev = s; @@ -647,36 +662,20 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) spin_lock_init(&subpriv->intr.spinlock); } - pcmuio_reset(dev); - - for (asic = 0; irq[0] && asic < PCMUIO_MAX_ASICS; ++asic) { - if (irq[asic] - && request_irq(irq[asic], pcmuio_interrupt, - IRQF_SHARED, board->name, dev)) { - int i; - /* unroll the allocated irqs.. */ - for (i = asic - 1; i >= 0; --i) { - free_irq(irq[i], dev); - devpriv->asics[i].irq = irq[i] = 0; - } - irq[asic] = 0; - } - devpriv->asics[asic].irq = irq[asic]; - } - return 0; } static void pcmuio_detach(struct comedi_device *dev) { struct pcmuio_private *devpriv = dev->private; - int i; if (devpriv) { - for (i = 0; i < PCMUIO_MAX_ASICS; ++i) { - if (devpriv->asics[i].irq) - free_irq(devpriv->asics[i].irq, dev); - } + pcmuio_reset(dev); + + /* free the 2nd irq if used, the core will free the 1st one */ + if (devpriv->irq2 && devpriv->irq2 != dev->irq) + free_irq(devpriv->irq2, dev); + kfree(devpriv->sprivs); } comedi_legacy_detach(dev); -- cgit v1.2.3 From 099ec87df0ff7c2c66173876a9b8910aafb7ca39 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:04 -0700 Subject: staging: comedi: pcmuio: spinlock protect pcmuio_{write, read}() Currently only the pcmuio_handle_asic_interrupt() function uses the spinlock in the private data to protect the read of the paged interrupt id registers. All accesses to the paged registers should be protected to ensure that the page is not changed until the access is complete. Move the lock/unlock into the pcmuio_{write,read}() functions to make sure the access completes correctly. Rename the spinlock to variable to clarify its use. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index dfa728052265..f7032fe251b1 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -146,7 +146,7 @@ struct pcmuio_subdev_private { struct pcmuio_private { struct { - spinlock_t spinlock; + spinlock_t pagelock; } asics[PCMUIO_MAX_ASICS]; struct pcmuio_subdev_private *sprivs; unsigned int irq2; @@ -155,8 +155,11 @@ struct pcmuio_private { static void pcmuio_write(struct comedi_device *dev, unsigned int val, int asic, int page, int port) { + struct pcmuio_private *devpriv = dev->private; unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); + unsigned long flags; + spin_lock_irqsave(&devpriv->asics[asic].pagelock, flags); if (page == 0) { /* Port registers are valid for any page */ outb(val & 0xff, iobase + PCMUIO_PORT_REG(port + 0)); @@ -168,14 +171,18 @@ static void pcmuio_write(struct comedi_device *dev, unsigned int val, outb((val >> 8) & 0xff, iobase + PCMUIO_PAGE_REG(1)); outb((val >> 16) & 0xff, iobase + PCMUIO_PAGE_REG(2)); } + spin_unlock_irqrestore(&devpriv->asics[asic].pagelock, flags); } static unsigned int pcmuio_read(struct comedi_device *dev, int asic, int page, int port) { + struct pcmuio_private *devpriv = dev->private; unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); + unsigned long flags; unsigned int val; + spin_lock_irqsave(&devpriv->asics[asic].pagelock, flags); if (page == 0) { /* Port registers are valid for any page */ val = inb(iobase + PCMUIO_PORT_REG(port + 0)); @@ -187,6 +194,7 @@ static unsigned int pcmuio_read(struct comedi_device *dev, val |= (inb(iobase + PCMUIO_PAGE_REG(1)) << 8); val |= (inb(iobase + PCMUIO_PAGE_REG(2)) << 16); } + spin_unlock_irqrestore(&devpriv->asics[asic].pagelock, flags); return val; } @@ -346,17 +354,13 @@ done: static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic) { - struct pcmuio_private *devpriv = dev->private; struct pcmuio_subdev_private *subpriv; unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); unsigned int triggered = 0; int got1 = 0; - unsigned long flags; unsigned char int_pend; int i; - spin_lock_irqsave(&devpriv->asics[asic].spinlock, flags); - int_pend = inb(iobase + PCMUIO_INT_PENDING_REG) & 0x07; if (int_pend) { triggered = pcmuio_read(dev, asic, PCMUIO_PAGE_INT_ID, 0); @@ -365,8 +369,6 @@ static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic) ++got1; } - spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, flags); - if (triggered) { struct comedi_subdevice *s; /* TODO here: dispatch io lines to subdevs with commands.. */ @@ -598,7 +600,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) - spin_lock_init(&devpriv->asics[asic].spinlock); + spin_lock_init(&devpriv->asics[asic].pagelock); pcmuio_reset(dev); -- cgit v1.2.3 From 741ba8cdf0e938d131b49fda37f80057286e459b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 6 Dec 2013 09:43:02 -0700 Subject: staging: comedi: pcmuio: tidy up pcmuio_handle_asic_interrupt() Unfortunatly, since there could be two asics, we can't use dev->read_subdev to get the subdevice. But, the comedi_subdevice associated with the 'asic' can easily be calculated. This allows removing the for () loop that searched for the correct subdevice. Tidy up the function. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 44 +++++++++++---------------------- 1 file changed, 15 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index f7032fe251b1..8752d4d09f3f 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -354,38 +354,24 @@ done: static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic) { - struct pcmuio_subdev_private *subpriv; + /* there are could be two asics so we can't use dev->read_subdev */ + struct comedi_subdevice *s = &dev->subdevices[asic * 2]; unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); - unsigned int triggered = 0; - int got1 = 0; - unsigned char int_pend; - int i; - - int_pend = inb(iobase + PCMUIO_INT_PENDING_REG) & 0x07; - if (int_pend) { - triggered = pcmuio_read(dev, asic, PCMUIO_PAGE_INT_ID, 0); - pcmuio_write(dev, 0, asic, PCMUIO_PAGE_INT_ID, 0); + unsigned int val; - ++got1; - } + /* are there any interrupts pending */ + val = inb(iobase + PCMUIO_INT_PENDING_REG) & 0x07; + if (!val) + return 0; - if (triggered) { - struct comedi_subdevice *s; - /* TODO here: dispatch io lines to subdevs with commands.. */ - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - subpriv = s->private; - if (subpriv->intr.asic == asic) { - /* - * This is an interrupt subdev, and it - * matches this asic! - */ - pcmuio_handle_intr_subdev(dev, s, - triggered); - } - } - } - return got1; + /* get, and clear, the pending interrupts */ + val = pcmuio_read(dev, asic, PCMUIO_PAGE_INT_ID, 0); + pcmuio_write(dev, 0, asic, PCMUIO_PAGE_INT_ID, 0); + + /* handle the pending interrupts */ + pcmuio_handle_intr_subdev(dev, s, val); + + return 1; } static irqreturn_t pcmuio_interrupt(int irq, void *d) -- cgit v1.2.3 From 0d1ead4809161867651b6f19e2cd793d2408abfd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:06 -0700 Subject: staging: comedi: pcmuio: remove 'asic' member from subdevice private data The 'asic' associated with a subdevice can be easily calculated. The functions that use this member in the subdevice private data can only be called by the subdevices that support interrupts. Just calculate the 'asic' when needed and remove the member variable and sanity checks. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 8752d4d09f3f..57a52dafac47 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -130,8 +130,6 @@ static const struct pcmuio_board pcmuio_boards[] = { struct pcmuio_subdev_private { /* The below is only used for intr subdevices */ struct { - /* if non-negative, this subdev has an interrupt asic */ - int asic; /* * subdev-relative channel mask for channels * we are interested in @@ -279,11 +277,7 @@ static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcmuio_subdev_private *subpriv = s->private; - int asic; - - asic = subpriv->intr.asic; - if (asic < 0) - return; /* not an interrupt subdev */ + int asic = s->index / 2; subpriv->intr.enabled_mask = 0; subpriv->intr.active = 0; @@ -399,14 +393,10 @@ static int pcmuio_start_intr(struct comedi_device *dev, subpriv->intr.active = 0; return 1; } else { - unsigned bits = 0, pol_bits = 0, n; - int asic; struct comedi_cmd *cmd = &s->async->cmd; + int asic = s->index / 2; + unsigned bits = 0, pol_bits = 0, n; - asic = subpriv->intr.asic; - if (asic < 0) - return 1; /* not an interrupt - subdev */ subpriv->intr.enabled_mask = 0; subpriv->intr.active = 1; if (cmd->chanlist) { @@ -636,7 +626,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if ((sdev_no == 0 && dev->irq) || (sdev_no == 2 && devpriv->irq2)) { /* setup the interrupt subdevice */ - subpriv->intr.asic = sdev_no / 2; dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->cancel = pcmuio_cancel; @@ -644,7 +633,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->do_cmdtest = pcmuio_cmdtest; s->len_chanlist = s->n_chan; } else { - subpriv->intr.asic = -1; s->len_chanlist = 1; } spin_lock_init(&subpriv->intr.spinlock); -- cgit v1.2.3 From 063b590413b5d132d542358e7975fe4955bfeb96 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:07 -0700 Subject: staging: comedi: pcmuio: remove subdevice private data The subdevice private data is only needed for each 'asic' not for each subdevice. Since the 'asic' can be calculated easily from the subdevice we can merge the subdevice private data members directly into the private data. This removes the need to kcalloc/free the subdevice private data and saves a bit of space. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 132 ++++++++++++++++---------------- 1 file changed, 65 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 57a52dafac47..fb0cbf047501 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -127,26 +127,17 @@ static const struct pcmuio_board pcmuio_boards[] = { }, }; -struct pcmuio_subdev_private { - /* The below is only used for intr subdevices */ - struct { - /* - * subdev-relative channel mask for channels - * we are interested in - */ - int enabled_mask; - int active; - int stop_count; - int continuous; - spinlock_t spinlock; - } intr; +struct pcmuio_asic { + spinlock_t pagelock; + spinlock_t spinlock; + int enabled_mask; + int active; + int stop_count; + int continuous; }; struct pcmuio_private { - struct { - spinlock_t pagelock; - } asics[PCMUIO_MAX_ASICS]; - struct pcmuio_subdev_private *sprivs; + struct pcmuio_asic asics[PCMUIO_MAX_ASICS]; unsigned int irq2; }; @@ -154,10 +145,11 @@ static void pcmuio_write(struct comedi_device *dev, unsigned int val, int asic, int page, int port) { struct pcmuio_private *devpriv = dev->private; + struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); unsigned long flags; - spin_lock_irqsave(&devpriv->asics[asic].pagelock, flags); + spin_lock_irqsave(&chip->pagelock, flags); if (page == 0) { /* Port registers are valid for any page */ outb(val & 0xff, iobase + PCMUIO_PORT_REG(port + 0)); @@ -169,18 +161,19 @@ static void pcmuio_write(struct comedi_device *dev, unsigned int val, outb((val >> 8) & 0xff, iobase + PCMUIO_PAGE_REG(1)); outb((val >> 16) & 0xff, iobase + PCMUIO_PAGE_REG(2)); } - spin_unlock_irqrestore(&devpriv->asics[asic].pagelock, flags); + spin_unlock_irqrestore(&chip->pagelock, flags); } static unsigned int pcmuio_read(struct comedi_device *dev, int asic, int page, int port) { struct pcmuio_private *devpriv = dev->private; + struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); unsigned long flags; unsigned int val; - spin_lock_irqsave(&devpriv->asics[asic].pagelock, flags); + spin_lock_irqsave(&chip->pagelock, flags); if (page == 0) { /* Port registers are valid for any page */ val = inb(iobase + PCMUIO_PORT_REG(port + 0)); @@ -192,7 +185,7 @@ static unsigned int pcmuio_read(struct comedi_device *dev, val |= (inb(iobase + PCMUIO_PAGE_REG(1)) << 8); val |= (inb(iobase + PCMUIO_PAGE_REG(2)) << 16); } - spin_unlock_irqrestore(&devpriv->asics[asic].pagelock, flags); + spin_unlock_irqrestore(&chip->pagelock, flags); return val; } @@ -276,11 +269,12 @@ static void pcmuio_reset(struct comedi_device *dev) static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pcmuio_subdev_private *subpriv = s->private; + struct pcmuio_private *devpriv = dev->private; int asic = s->index / 2; + struct pcmuio_asic *chip = &devpriv->asics[asic]; - subpriv->intr.enabled_mask = 0; - subpriv->intr.active = 0; + chip->enabled_mask = 0; + chip->active = 0; s->async->inttrig = NULL; /* disable all intrs for this subdev.. */ @@ -291,7 +285,9 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, struct comedi_subdevice *s, unsigned triggered) { - struct pcmuio_subdev_private *subpriv = s->private; + struct pcmuio_private *devpriv = dev->private; + int asic = s->index / 2; + struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned int len = s->async->cmd.chanlist_len; unsigned oldevents = s->async->events; unsigned int val = 0; @@ -299,15 +295,15 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, unsigned mytrig; unsigned int i; - spin_lock_irqsave(&subpriv->intr.spinlock, flags); + spin_lock_irqsave(&chip->spinlock, flags); - if (!subpriv->intr.active) + if (!chip->active) goto done; mytrig = triggered; mytrig &= ((0x1 << s->n_chan) - 1); - if (!(mytrig & subpriv->intr.enabled_mask)) + if (!(mytrig & chip->enabled_mask)) goto done; for (i = 0; i < len; i++) { @@ -327,11 +323,11 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, } /* Check for end of acquisition. */ - if (!subpriv->intr.continuous) { + if (!chip->continuous) { /* stop_src == TRIG_COUNT */ - if (subpriv->intr.stop_count > 0) { - subpriv->intr.stop_count--; - if (subpriv->intr.stop_count == 0) { + if (chip->stop_count > 0) { + chip->stop_count--; + if (chip->stop_count == 0) { s->async->events |= COMEDI_CB_EOA; /* TODO: STOP_ACQUISITION_CALL_HERE!! */ pcmuio_stop_intr(dev, s); @@ -340,7 +336,7 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, } done: - spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&chip->spinlock, flags); if (oldevents != s->async->events) comedi_event(dev, s); @@ -385,20 +381,21 @@ static irqreturn_t pcmuio_interrupt(int irq, void *d) static int pcmuio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pcmuio_subdev_private *subpriv = s->private; + struct pcmuio_private *devpriv = dev->private; + int asic = s->index / 2; + struct pcmuio_asic *chip = &devpriv->asics[asic]; - if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) { + if (!chip->continuous && chip->stop_count == 0) { /* An empty acquisition! */ s->async->events |= COMEDI_CB_EOA; - subpriv->intr.active = 0; + chip->active = 0; return 1; } else { struct comedi_cmd *cmd = &s->async->cmd; - int asic = s->index / 2; unsigned bits = 0, pol_bits = 0, n; - subpriv->intr.enabled_mask = 0; - subpriv->intr.active = 1; + chip->enabled_mask = 0; + chip->active = 1; if (cmd->chanlist) { for (n = 0; n < cmd->chanlist_len; n++) { bits |= (1U << CR_CHAN(cmd->chanlist[n])); @@ -409,7 +406,7 @@ static int pcmuio_start_intr(struct comedi_device *dev, } } bits &= ((0x1 << s->n_chan) - 1); - subpriv->intr.enabled_mask = bits; + chip->enabled_mask = bits; /* set pol and enab intrs for this subdev.. */ pcmuio_write(dev, pol_bits, asic, PCMUIO_PAGE_POL, 0); @@ -420,13 +417,15 @@ static int pcmuio_start_intr(struct comedi_device *dev, static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pcmuio_subdev_private *subpriv = s->private; + struct pcmuio_private *devpriv = dev->private; + int asic = s->index / 2; + struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; - spin_lock_irqsave(&subpriv->intr.spinlock, flags); - if (subpriv->intr.active) + spin_lock_irqsave(&chip->spinlock, flags); + if (chip->active) pcmuio_stop_intr(dev, s); - spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&chip->spinlock, flags); return 0; } @@ -438,19 +437,21 @@ static int pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { - struct pcmuio_subdev_private *subpriv = s->private; + struct pcmuio_private *devpriv = dev->private; + int asic = s->index / 2; + struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; int event = 0; if (trignum != 0) return -EINVAL; - spin_lock_irqsave(&subpriv->intr.spinlock, flags); + spin_lock_irqsave(&chip->spinlock, flags); s->async->inttrig = NULL; - if (subpriv->intr.active) + if (chip->active) event = pcmuio_start_intr(dev, s); - spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&chip->spinlock, flags); if (event) comedi_event(dev, s); @@ -463,24 +464,26 @@ pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, */ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pcmuio_subdev_private *subpriv = s->private; + struct pcmuio_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; + int asic = s->index / 2; + struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; int event = 0; - spin_lock_irqsave(&subpriv->intr.spinlock, flags); - subpriv->intr.active = 1; + spin_lock_irqsave(&chip->spinlock, flags); + chip->active = 1; /* Set up end of acquisition. */ switch (cmd->stop_src) { case TRIG_COUNT: - subpriv->intr.continuous = 0; - subpriv->intr.stop_count = cmd->stop_arg; + chip->continuous = 0; + chip->stop_count = cmd->stop_arg; break; default: /* TRIG_NONE */ - subpriv->intr.continuous = 1; - subpriv->intr.stop_count = 0; + chip->continuous = 1; + chip->stop_count = 0; break; } @@ -494,7 +497,7 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) event = pcmuio_start_intr(dev, s); break; } - spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&chip->spinlock, flags); if (event) comedi_event(dev, s); @@ -562,7 +565,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcmuio_board *board = comedi_board(dev); struct comedi_subdevice *s; struct pcmuio_private *devpriv; - struct pcmuio_subdev_private *subpriv; int sdev_no, n_subdevs, asic; int ret; @@ -575,8 +577,12 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) - spin_lock_init(&devpriv->asics[asic].pagelock); + for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) { + struct pcmuio_asic *chip = &devpriv->asics[asic]; + + spin_lock_init(&chip->pagelock); + spin_lock_init(&chip->spinlock); + } pcmuio_reset(dev); @@ -602,9 +608,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) } n_subdevs = board->num_asics * 2; - devpriv->sprivs = kcalloc(n_subdevs, sizeof(*subpriv), GFP_KERNEL); - if (!devpriv->sprivs) - return -ENOMEM; ret = comedi_alloc_subdevices(dev, n_subdevs); if (ret) @@ -612,8 +615,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) { s = &dev->subdevices[sdev_no]; - subpriv = &devpriv->sprivs[sdev_no]; - s->private = subpriv; s->maxdata = 1; s->range_table = &range_digital; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -635,7 +636,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) } else { s->len_chanlist = 1; } - spin_lock_init(&subpriv->intr.spinlock); } return 0; @@ -651,8 +651,6 @@ static void pcmuio_detach(struct comedi_device *dev) /* free the 2nd irq if used, the core will free the 1st one */ if (devpriv->irq2 && devpriv->irq2 != dev->irq) free_irq(devpriv->irq2, dev); - - kfree(devpriv->sprivs); } comedi_legacy_detach(dev); } -- cgit v1.2.3 From beecd01b720f3d907a5eacfc142090cf06326836 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:08 -0700 Subject: staging: comedi: pcmuio: fix pcmuio_dio_insn_bits() This dio subdevice (*insn_bits) function does not follow the "norm" for comedi drivers. It also _appears_ to return the incorrect state of the channels. Use the comedi_dio_update_state() helper to handle the boilerplate for updating the output channel state. Due to the hardware we then need to invert the state and mask the input channels before updating the outputs. Then read the hardware and invert the result to get the current true state of the dio channels. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 35 +++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index fb0cbf047501..2dca1199d175 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -202,30 +202,35 @@ static unsigned int pcmuio_read(struct comedi_device *dev, */ static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - unsigned int mask = data[0] & s->io_bits; /* outputs only */ - unsigned int bits = data[1]; + unsigned int chanmask = (1 << s->n_chan) - 1; int asic = s->index / 2; int port = (s->index % 2) ? 3 : 0; + unsigned int mask; unsigned int val; - /* get inverted state of the channels from the port */ - val = pcmuio_read(dev, asic, 0, port); - - /* get the true state of the channels */ - s->state = val ^ ((0x1 << s->n_chan) - 1); - + mask = comedi_dio_update_state(s, data); if (mask) { - s->state &= ~mask; - s->state |= (mask & bits); - - /* invert the state and update the channels */ - val = s->state ^ ((0x1 << s->n_chan) - 1); + /* + * Outputs are inverted, invert the state and + * update the channels. + * + * The s->io_bits mask makes sure the input channels + * are '0' so that the outputs pins stay in a high + * z-state. + */ + val = ~s->state & chanmask; + val &= s->io_bits; pcmuio_write(dev, val, asic, 0, port); } - data[1] = s->state; + /* get inverted state of the channels from the port */ + val = pcmuio_read(dev, asic, 0, port); + + /* return the true state of the channels */ + data[1] = ~val & chanmask; return insn->n; } -- cgit v1.2.3 From d3d2d75da52982968ddb25f715c86c65dde04903 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:09 -0700 Subject: staging: comedi: pcmuio: remove unnecessary mask of triggered channels The 'triggered' value is read directly from the three trigger id registers and does not have any extra data that needs masked off. Remove the 'mytrig' local variable and just use 'triggered' directly. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 2dca1199d175..3dbc1d3e1bdd 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -297,7 +297,6 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, unsigned oldevents = s->async->events; unsigned int val = 0; unsigned long flags; - unsigned mytrig; unsigned int i; spin_lock_irqsave(&chip->spinlock, flags); @@ -305,16 +304,13 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, if (!chip->active) goto done; - mytrig = triggered; - mytrig &= ((0x1 << s->n_chan) - 1); - - if (!(mytrig & chip->enabled_mask)) + if (!(triggered & chip->enabled_mask)) goto done; for (i = 0; i < len; i++) { unsigned int chan = CR_CHAN(s->async->cmd.chanlist[i]); - if (mytrig & (1U << chan)) - val |= (1U << i); + if (triggered & (1 << chan)) + val |= (1 << i); } /* Write the scan to the buffer. */ -- cgit v1.2.3 From 4344158f3ea32eefd4942915c76d35afdc11b76e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:10 -0700 Subject: staging: comedi: pcmuio: add inline helpers to get the 'iobase', 'asic', and 'port' To reduce the potential for bugs, and better document the code, introduce some inline helper functions to consolidate the calculations needed to get the 'iobase' for a given asic and the 'asic' and 'port' associated with a given subdevice. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 50 ++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 3dbc1d3e1bdd..6ee876d9905a 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -141,12 +141,36 @@ struct pcmuio_private { unsigned int irq2; }; +static inline unsigned long pcmuio_asic_iobase(struct comedi_device *dev, + int asic) +{ + return dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); +} + +static inline int pcmuio_subdevice_to_asic(struct comedi_subdevice *s) +{ + /* + * subdevice 0 and 1 are handled by the first asic + * subdevice 2 and 3 are handled by the second asic + */ + return s->index / 2; +} + +static inline int pcmuio_subdevice_to_port(struct comedi_subdevice *s) +{ + /* + * subdevice 0 and 2 use port registers 0-2 + * subdevice 1 and 3 use port registers 3-5 + */ + return (s->index % 2) ? 3 : 0; +} + static void pcmuio_write(struct comedi_device *dev, unsigned int val, int asic, int page, int port) { struct pcmuio_private *devpriv = dev->private; struct pcmuio_asic *chip = &devpriv->asics[asic]; - unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); + unsigned long iobase = pcmuio_asic_iobase(dev, asic); unsigned long flags; spin_lock_irqsave(&chip->pagelock, flags); @@ -169,7 +193,7 @@ static unsigned int pcmuio_read(struct comedi_device *dev, { struct pcmuio_private *devpriv = dev->private; struct pcmuio_asic *chip = &devpriv->asics[asic]; - unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); + unsigned long iobase = pcmuio_asic_iobase(dev, asic); unsigned long flags; unsigned int val; @@ -205,9 +229,9 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { + int asic = pcmuio_subdevice_to_asic(s); + int port = pcmuio_subdevice_to_port(s); unsigned int chanmask = (1 << s->n_chan) - 1; - int asic = s->index / 2; - int port = (s->index % 2) ? 3 : 0; unsigned int mask; unsigned int val; @@ -240,8 +264,8 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int asic = s->index / 2; - int port = (s->index % 2) ? 3 : 0; + int asic = pcmuio_subdevice_to_asic(s); + int port = pcmuio_subdevice_to_port(s); int ret; ret = comedi_dio_insn_config(dev, s, insn, data, 0); @@ -275,7 +299,7 @@ static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcmuio_private *devpriv = dev->private; - int asic = s->index / 2; + int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; chip->enabled_mask = 0; @@ -291,7 +315,7 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, unsigned triggered) { struct pcmuio_private *devpriv = dev->private; - int asic = s->index / 2; + int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned int len = s->async->cmd.chanlist_len; unsigned oldevents = s->async->events; @@ -347,7 +371,7 @@ static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic) { /* there are could be two asics so we can't use dev->read_subdev */ struct comedi_subdevice *s = &dev->subdevices[asic * 2]; - unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE); + unsigned long iobase = pcmuio_asic_iobase(dev, asic); unsigned int val; /* are there any interrupts pending */ @@ -383,7 +407,7 @@ static int pcmuio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcmuio_private *devpriv = dev->private; - int asic = s->index / 2; + int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; if (!chip->continuous && chip->stop_count == 0) { @@ -419,7 +443,7 @@ static int pcmuio_start_intr(struct comedi_device *dev, static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcmuio_private *devpriv = dev->private; - int asic = s->index / 2; + int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; @@ -439,7 +463,7 @@ pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { struct pcmuio_private *devpriv = dev->private; - int asic = s->index / 2; + int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; int event = 0; @@ -467,7 +491,7 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcmuio_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - int asic = s->index / 2; + int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; int event = 0; -- cgit v1.2.3 From 25ad998892c05cf1a3f14ac882af8edbb8f62cc8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:11 -0700 Subject: staging: comedi: pcmuio: document the spinlock_t variables Add some comments about the two spinlock_t variables in the private data. Also, add come comments for the functions that do not need to lock/unlock the spinlock. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 6ee876d9905a..c83f5bd686cc 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -128,8 +128,8 @@ static const struct pcmuio_board pcmuio_boards[] = { }; struct pcmuio_asic { - spinlock_t pagelock; - spinlock_t spinlock; + spinlock_t pagelock; /* protects the page registers */ + spinlock_t spinlock; /* protects member variables */ int enabled_mask; int active; int stop_count; @@ -295,6 +295,7 @@ static void pcmuio_reset(struct comedi_device *dev) } } +/* chip->spinlock is already locked */ static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -403,6 +404,7 @@ static irqreturn_t pcmuio_interrupt(int irq, void *d) return handled ? IRQ_HANDLED : IRQ_NONE; } +/* chip->spinlock is already locked */ static int pcmuio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s) { -- cgit v1.2.3 From d5f81755d6f650881a7ee0ee4498d4a1a7540c49 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:12 -0700 Subject: staging: comedi: pcmuio: fix types of some private data variables The 'enabled_mask' is a bit mask of the channels that are enabled for interrupt detection and should be an unsigned int. The 'stop_count' is a >= 0 value that is set by the unsigned int cmd->stop_arg. Make it an unsigned int. The 'active' and 'continuous' members are flags. Make them unsigned int bit-fields to save a bit of space. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index c83f5bd686cc..b86eb1e8d35c 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -130,10 +130,10 @@ static const struct pcmuio_board pcmuio_boards[] = { struct pcmuio_asic { spinlock_t pagelock; /* protects the page registers */ spinlock_t spinlock; /* protects member variables */ - int enabled_mask; - int active; - int stop_count; - int continuous; + unsigned int enabled_mask; + unsigned int stop_count; + unsigned int active:1; + unsigned int continuous:1; }; struct pcmuio_private { -- cgit v1.2.3 From fbd66a7e87e0289f389d20f385bb3062d617f2d3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:14 -0700 Subject: staging: comedi: pcmuio: remove unneeded include The header is no longer needed by this driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index b86eb1e8d35c..32da92f45b40 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -75,7 +75,6 @@ #include #include -#include #include "../comedidev.h" -- cgit v1.2.3 From fc5ba1bd717b1daad46bb990f86cb30b2f2e219e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:15 -0700 Subject: staging: comedi: pcmuio: tidy up pcmuio_attach() Clean up the local variables, 'sdev_no' and 'asic' are both used in simple for () loops. Use the local variable 'i' for both cases. The 'n_subdevs' variable is only used in one place, just remove it. For aesthetics, add some whitespace to the subdevice init and reorder it to follow the more typical style in comedi drivers. Remove the unnecessary init of s->len_chanlist for subdevices that do not support async commands (interrupts). The core will default it to the correct value. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 43 +++++++++++++++------------------ 1 file changed, 19 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 32da92f45b40..edcac2679c40 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -591,8 +591,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcmuio_board *board = comedi_board(dev); struct comedi_subdevice *s; struct pcmuio_private *devpriv; - int sdev_no, n_subdevs, asic; int ret; + int i; ret = comedi_request_region(dev, it->options[0], board->num_asics * PCMUIO_ASIC_IOSIZE); @@ -603,8 +603,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) { - struct pcmuio_asic *chip = &devpriv->asics[asic]; + for (i = 0; i < PCMUIO_MAX_ASICS; ++i) { + struct pcmuio_asic *chip = &devpriv->asics[i]; spin_lock_init(&chip->pagelock); spin_lock_init(&chip->spinlock); @@ -633,34 +633,29 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - n_subdevs = board->num_asics * 2; - - ret = comedi_alloc_subdevices(dev, n_subdevs); + ret = comedi_alloc_subdevices(dev, board->num_asics * 2); if (ret) return ret; - for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) { - s = &dev->subdevices[sdev_no]; - s->maxdata = 1; - s->range_table = &range_digital; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->type = COMEDI_SUBD_DIO; - s->insn_bits = pcmuio_dio_insn_bits; - s->insn_config = pcmuio_dio_insn_config; - s->n_chan = 24; + for (i = 0; i < dev->n_subdevices; ++i) { + s = &dev->subdevices[i]; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pcmuio_dio_insn_bits; + s->insn_config = pcmuio_dio_insn_config; /* subdevices 0 and 2 can suppport interrupts */ - if ((sdev_no == 0 && dev->irq) || - (sdev_no == 2 && devpriv->irq2)) { + if ((i == 0 && dev->irq) || (i == 2 && devpriv->irq2)) { /* setup the interrupt subdevice */ dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->cancel = pcmuio_cancel; - s->do_cmd = pcmuio_cmd; - s->do_cmdtest = pcmuio_cmdtest; - s->len_chanlist = s->n_chan; - } else { - s->len_chanlist = 1; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->cancel = pcmuio_cancel; + s->do_cmd = pcmuio_cmd; + s->do_cmdtest = pcmuio_cmdtest; } } -- cgit v1.2.3 From bf4063e6f4a33b8f7ec067e6f180b1daa03c951a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 5 Dec 2013 16:54:16 -0700 Subject: staging: comedi: pcmuio: tidy up pcmuio_start_intr() Refactor this function a bit to remove the need for an extra indent level and cleanup some of the odd line breaks. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcmuio.c | 44 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index edcac2679c40..a8f390f7a874 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -410,34 +410,38 @@ static int pcmuio_start_intr(struct comedi_device *dev, struct pcmuio_private *devpriv = dev->private; int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int bits = 0; + unsigned int pol_bits = 0; + int i; if (!chip->continuous && chip->stop_count == 0) { /* An empty acquisition! */ s->async->events |= COMEDI_CB_EOA; chip->active = 0; return 1; - } else { - struct comedi_cmd *cmd = &s->async->cmd; - unsigned bits = 0, pol_bits = 0, n; - - chip->enabled_mask = 0; - chip->active = 1; - if (cmd->chanlist) { - for (n = 0; n < cmd->chanlist_len; n++) { - bits |= (1U << CR_CHAN(cmd->chanlist[n])); - pol_bits |= (CR_AREF(cmd->chanlist[n]) - || CR_RANGE(cmd-> - chanlist[n]) ? 1U : 0U) - << CR_CHAN(cmd->chanlist[n]); - } - } - bits &= ((0x1 << s->n_chan) - 1); - chip->enabled_mask = bits; + } - /* set pol and enab intrs for this subdev.. */ - pcmuio_write(dev, pol_bits, asic, PCMUIO_PAGE_POL, 0); - pcmuio_write(dev, bits, asic, PCMUIO_PAGE_ENAB, 0); + chip->enabled_mask = 0; + chip->active = 1; + if (cmd->chanlist) { + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chanspec = cmd->chanlist[i]; + unsigned int chan = CR_CHAN(chanspec); + unsigned int range = CR_RANGE(chanspec); + unsigned int aref = CR_AREF(chanspec); + + bits |= (1 << chan); + pol_bits |= ((aref || range) ? 1 : 0) << chan; + } } + bits &= ((1 << s->n_chan) - 1); + chip->enabled_mask = bits; + + /* set pol and enab intrs for this subdev.. */ + pcmuio_write(dev, pol_bits, asic, PCMUIO_PAGE_POL, 0); + pcmuio_write(dev, bits, asic, PCMUIO_PAGE_ENAB, 0); + return 0; } -- cgit v1.2.3 From 2209b0c964c7c402b07d0df6fcfbecf8ff53db30 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 25 Nov 2013 18:01:18 -0800 Subject: cpufreq: cpufreq-cpu0: clk_round_rate() can return a zero upon error Treat both negative and zero return values from clk_round_rate() as errors. This is needed since subsequent patches will convert clk_round_rate()'s return value to be an unsigned type, rather than a signed type, since some clock sources can generate rates higher than (2^31)-1 Hz. Eventually, when calling clk_round_rate(), only a return value of zero will be considered a error. All other values will be considered valid rates. The comparison against values less than 0 is kept to preserve the correct behavior in the meantime. Signed-off-by: Paul Walmsley Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-cpu0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index d4585ce2346c..0faf756f6197 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) int ret; freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); - if (freq_Hz < 0) + if (freq_Hz <= 0) freq_Hz = freq_table[index].frequency * 1000; freq_exact = freq_Hz; -- cgit v1.2.3 From 189c9b8d925691cc58823ffdc3bf75dc8630ccdf Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 25 Nov 2013 18:04:34 -0800 Subject: cpufreq: SPEAr: clk_round_rate() can return a zero upon error Treat both negative and zero return values from clk_round_rate() as errors. This is needed since subsequent patches will convert clk_round_rate()'s return value to be an unsigned type, rather than a signed type, since some clock sources can generate rates higher than (2^31)-1 Hz. Eventually, when calling clk_round_rate(), only a return value of zero will be considered a error. All other values will be considered valid rates. The comparison against values less than 0 is kept to preserve the correct behavior in the meantime. Signed-off-by: Paul Walmsley Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/spear-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index d02ccd19c9c4..45ea4c094542 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, } newfreq = clk_round_rate(srcclk, newfreq * mult); - if (newfreq < 0) { + if (newfreq <= 0) { pr_err("clk_round_rate failed for cpu src clock\n"); return newfreq; } -- cgit v1.2.3 From 2d9955bedb18a403bde1290607d5c02cd86ae5fe Mon Sep 17 00:00:00 2001 From: Robert Stonehouse Date: Mon, 7 Oct 2013 18:44:17 +0100 Subject: sfc: Demote "MC Scheduler error" messages The MC firmware is cooperatively multitasking and its scheduler will send an event when a task yields after running for more than the expected maximum time. This can be useful for firmware development but does not usually indicate a serious error and does not help to detect a lockup (there is a hardware watchdog that does that). Change the message and reduce log level accordingly. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 4b0bd8a1514d..25f91c0ca6a6 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -867,8 +867,8 @@ void efx_mcdi_process_event(struct efx_channel *channel, efx_mcdi_sensor_event(efx, event); break; case MCDI_EVENT_CODE_SCHEDERR: - netif_info(efx, hw, efx->net_dev, - "MC Scheduler error address=0x%x\n", data); + netif_dbg(efx, hw, efx->net_dev, + "MC Scheduler alert (0x%x)\n", data); break; case MCDI_EVENT_CODE_REBOOT: case MCDI_EVENT_CODE_MC_REBOOT: -- cgit v1.2.3 From 512bb06c65aa25e08d42456e5a28ca6b72306062 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Dec 2013 19:48:07 +0000 Subject: sfc: Update MCDI protocol definitions Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi_pcol.h | 733 +++++++++++++++++++++++++++++++---- 1 file changed, 663 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h index e0a63ddb7a6c..a707fb5ef14c 100644 --- a/drivers/net/ethernet/sfc/mcdi_pcol.h +++ b/drivers/net/ethernet/sfc/mcdi_pcol.h @@ -224,6 +224,8 @@ #define MC_CMD_ERR_MAC_EXIST 0x1009 /* Slave core not present */ #define MC_CMD_ERR_SLAVE_NOT_PRESENT 0x100a +/* The datapath is disabled. */ +#define MC_CMD_ERR_DATAPATH_DISABLED 0x100b #define MC_CMD_ERR_CODE_OFST 0 @@ -390,6 +392,8 @@ * AOE_ERR_DATA) */ #define MCDI_EVENT_AOE_BYTEBLASTER 0x9 +/* enum: DDR ECC status update */ +#define MCDI_EVENT_AOE_DDR_ECC_STATUS 0xa #define MCDI_EVENT_AOE_ERR_DATA_LBN 8 #define MCDI_EVENT_AOE_ERR_DATA_WIDTH 8 #define MCDI_EVENT_RX_ERR_RXQ_LBN 0 @@ -462,6 +466,10 @@ #define MCDI_EVENT_CODE_ECC_CORR_ERR 0x17 /* enum: the MC has detected an uncorrectable error */ #define MCDI_EVENT_CODE_ECC_FATAL_ERR 0x18 +/* enum: The MC has entered offline BIST mode */ +#define MCDI_EVENT_CODE_MC_BIST 0x19 +/* enum: PTP tick event providing current NIC time */ +#define MCDI_EVENT_CODE_PTP_TIME 0x1a /* enum: Artificial event generated by host and posted via MC for test * purposes. */ @@ -481,15 +489,32 @@ #define MCDI_EVENT_TX_ERR_DATA_OFST 0 #define MCDI_EVENT_TX_ERR_DATA_LBN 0 #define MCDI_EVENT_TX_ERR_DATA_WIDTH 32 -/* Seconds field of timestamp */ +/* For CODE_PTP_RX, CODE_PTP_PPS and CODE_HW_PPS events the seconds field of + * timestamp + */ #define MCDI_EVENT_PTP_SECONDS_OFST 0 #define MCDI_EVENT_PTP_SECONDS_LBN 0 #define MCDI_EVENT_PTP_SECONDS_WIDTH 32 -/* Nanoseconds field of timestamp */ +/* For CODE_PTP_RX, CODE_PTP_PPS and CODE_HW_PPS events the major field of + * timestamp + */ +#define MCDI_EVENT_PTP_MAJOR_OFST 0 +#define MCDI_EVENT_PTP_MAJOR_LBN 0 +#define MCDI_EVENT_PTP_MAJOR_WIDTH 32 +/* For CODE_PTP_RX, CODE_PTP_PPS and CODE_HW_PPS events the nanoseconds field + * of timestamp + */ #define MCDI_EVENT_PTP_NANOSECONDS_OFST 0 #define MCDI_EVENT_PTP_NANOSECONDS_LBN 0 #define MCDI_EVENT_PTP_NANOSECONDS_WIDTH 32 -/* Lowest four bytes of sourceUUID from PTP packet */ +/* For CODE_PTP_RX, CODE_PTP_PPS and CODE_HW_PPS events the minor field of + * timestamp + */ +#define MCDI_EVENT_PTP_MINOR_OFST 0 +#define MCDI_EVENT_PTP_MINOR_LBN 0 +#define MCDI_EVENT_PTP_MINOR_WIDTH 32 +/* For CODE_PTP_RX events, the lowest four bytes of sourceUUID from PTP packet + */ #define MCDI_EVENT_PTP_UUID_OFST 0 #define MCDI_EVENT_PTP_UUID_LBN 0 #define MCDI_EVENT_PTP_UUID_WIDTH 32 @@ -505,6 +530,13 @@ #define MCDI_EVENT_ECC_FATAL_ERR_DATA_OFST 0 #define MCDI_EVENT_ECC_FATAL_ERR_DATA_LBN 0 #define MCDI_EVENT_ECC_FATAL_ERR_DATA_WIDTH 32 +/* For CODE_PTP_TIME events, the major value of the PTP clock */ +#define MCDI_EVENT_PTP_TIME_MAJOR_OFST 0 +#define MCDI_EVENT_PTP_TIME_MAJOR_LBN 0 +#define MCDI_EVENT_PTP_TIME_MAJOR_WIDTH 32 +/* For CODE_PTP_TIME events, bits 19-26 of the minor value of the PTP clock */ +#define MCDI_EVENT_PTP_TIME_MINOR_26_19_LBN 36 +#define MCDI_EVENT_PTP_TIME_MINOR_26_19_WIDTH 8 /* FCDI_EVENT structuredef */ #define FCDI_EVENT_LEN 8 @@ -545,8 +577,10 @@ #define FCDI_EVENT_CODE_TIMED_READ 0x5 /* enum: One or more PPS IN events */ #define FCDI_EVENT_CODE_PPS_IN 0x6 -/* enum: One or more PPS OUT events */ -#define FCDI_EVENT_CODE_PPS_OUT 0x7 +/* enum: Tick event from PTP clock */ +#define FCDI_EVENT_CODE_PTP_TICK 0x7 +/* enum: ECC error counters */ +#define FCDI_EVENT_CODE_DDR_ECC_STATUS 0x8 #define FCDI_EVENT_ASSERT_INSTR_ADDRESS_OFST 0 #define FCDI_EVENT_ASSERT_INSTR_ADDRESS_LBN 0 #define FCDI_EVENT_ASSERT_INSTR_ADDRESS_WIDTH 32 @@ -560,14 +594,21 @@ #define FCDI_EVENT_LINK_STATE_DATA_OFST 0 #define FCDI_EVENT_LINK_STATE_DATA_LBN 0 #define FCDI_EVENT_LINK_STATE_DATA_WIDTH 32 -#define FCDI_EVENT_PPS_COUNT_OFST 0 -#define FCDI_EVENT_PPS_COUNT_LBN 0 -#define FCDI_EVENT_PPS_COUNT_WIDTH 32 - -/* FCDI_EXTENDED_EVENT structuredef */ -#define FCDI_EXTENDED_EVENT_LENMIN 16 -#define FCDI_EXTENDED_EVENT_LENMAX 248 -#define FCDI_EXTENDED_EVENT_LEN(num) (8+8*(num)) +#define FCDI_EVENT_DDR_ECC_STATUS_BANK_ID_LBN 36 +#define FCDI_EVENT_DDR_ECC_STATUS_BANK_ID_WIDTH 8 +#define FCDI_EVENT_DDR_ECC_STATUS_STATUS_OFST 0 +#define FCDI_EVENT_DDR_ECC_STATUS_STATUS_LBN 0 +#define FCDI_EVENT_DDR_ECC_STATUS_STATUS_WIDTH 32 + +/* FCDI_EXTENDED_EVENT_PPS structuredef: Extended FCDI event to send PPS events + * to the MC. Note that this structure | is overlayed over a normal FCDI event + * such that bits 32-63 containing | event code, level, source etc remain the + * same. In this case the data | field of the header is defined to be the + * number of timestamps + */ +#define FCDI_EXTENDED_EVENT_PPS_LENMIN 16 +#define FCDI_EXTENDED_EVENT_PPS_LENMAX 248 +#define FCDI_EXTENDED_EVENT_PPS_LEN(num) (8+8*(num)) /* Number of timestamps following */ #define FCDI_EXTENDED_EVENT_PPS_COUNT_OFST 0 #define FCDI_EXTENDED_EVENT_PPS_COUNT_LBN 0 @@ -581,14 +622,14 @@ #define FCDI_EXTENDED_EVENT_PPS_NANOSECONDS_LBN 96 #define FCDI_EXTENDED_EVENT_PPS_NANOSECONDS_WIDTH 32 /* Timestamp records comprising the event */ -#define FCDI_EXTENDED_EVENT_PPS_TIME_OFST 8 -#define FCDI_EXTENDED_EVENT_PPS_TIME_LEN 8 -#define FCDI_EXTENDED_EVENT_PPS_TIME_LO_OFST 8 -#define FCDI_EXTENDED_EVENT_PPS_TIME_HI_OFST 12 -#define FCDI_EXTENDED_EVENT_PPS_TIME_MINNUM 1 -#define FCDI_EXTENDED_EVENT_PPS_TIME_MAXNUM 30 -#define FCDI_EXTENDED_EVENT_PPS_TIME_LBN 64 -#define FCDI_EXTENDED_EVENT_PPS_TIME_WIDTH 64 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_OFST 8 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_LEN 8 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_LO_OFST 8 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_HI_OFST 12 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_MINNUM 1 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_MAXNUM 30 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_LBN 64 +#define FCDI_EXTENDED_EVENT_PPS_TIMESTAMPS_WIDTH 64 /***********************************/ @@ -642,6 +683,10 @@ #define MC_CMD_COPYCODE_IN_LEN 16 /* Source address */ #define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0 +/* enum: The main image should be entered via a copy of a single word from and + * to this address when none of the other magic behaviours are required. + */ +#define MC_CMD_COPYCODE_HUNT_NO_MAGIC_ADDR 0x10000 /* enum: Entering the main image via a copy of a single word from and to this * address indicates that it should not attempt to start the datapath CPUs. * This is useful for certain soft rebooting scenarios. (Huntington only) @@ -872,8 +917,28 @@ #define MC_CMD_PTP_OP_RST_CLK 0x14 /* enum: Enable the forwarding of PPS events to the host */ #define MC_CMD_PTP_OP_PPS_ENABLE 0x15 +/* enum: Get the time format used by this NIC for PTP operations */ +#define MC_CMD_PTP_OP_GET_TIME_FORMAT 0x16 +/* enum: Get the clock attributes. NOTE- extended version of + * MC_CMD_PTP_OP_GET_TIME_FORMAT + */ +#define MC_CMD_PTP_OP_GET_ATTRIBUTES 0x16 +/* enum: Get corrections that should be applied to the various different + * timestamps + */ +#define MC_CMD_PTP_OP_GET_TIMESTAMP_CORRECTIONS 0x17 +/* enum: Subscribe to receive periodic time events indicating the current NIC + * time + */ +#define MC_CMD_PTP_OP_TIME_EVENT_SUBSCRIBE 0x18 +/* enum: Unsubscribe to stop receiving time events */ +#define MC_CMD_PTP_OP_TIME_EVENT_UNSUBSCRIBE 0x19 +/* enum: PPS based manfacturing tests. Requires PPS output to be looped to PPS + * input on the same NIC. + */ +#define MC_CMD_PTP_OP_MANFTEST_PPS 0x1a /* enum: Above this for future use. */ -#define MC_CMD_PTP_OP_MAX 0x16 +#define MC_CMD_PTP_OP_MAX 0x1b /* MC_CMD_PTP_IN_ENABLE msgrequest */ #define MC_CMD_PTP_IN_ENABLE_LEN 16 @@ -938,8 +1003,12 @@ #define MC_CMD_PTP_IN_ADJUST_BITS 0x28 /* Time adjustment in seconds */ #define MC_CMD_PTP_IN_ADJUST_SECONDS_OFST 16 +/* Time adjustment major value */ +#define MC_CMD_PTP_IN_ADJUST_MAJOR_OFST 16 /* Time adjustment in nanoseconds */ #define MC_CMD_PTP_IN_ADJUST_NANOSECONDS_OFST 20 +/* Time adjustment minor value */ +#define MC_CMD_PTP_IN_ADJUST_MINOR_OFST 20 /* MC_CMD_PTP_IN_SYNCHRONIZE msgrequest */ #define MC_CMD_PTP_IN_SYNCHRONIZE_LEN 20 @@ -1005,8 +1074,12 @@ /* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ /* Time adjustment in seconds */ #define MC_CMD_PTP_IN_CLOCK_OFFSET_ADJUST_SECONDS_OFST 8 +/* Time adjustment major value */ +#define MC_CMD_PTP_IN_CLOCK_OFFSET_ADJUST_MAJOR_OFST 8 /* Time adjustment in nanoseconds */ #define MC_CMD_PTP_IN_CLOCK_OFFSET_ADJUST_NANOSECONDS_OFST 12 +/* Time adjustment minor value */ +#define MC_CMD_PTP_IN_CLOCK_OFFSET_ADJUST_MINOR_OFST 12 /* MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST msgrequest */ #define MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST_LEN 16 @@ -1078,9 +1151,51 @@ #define MC_CMD_PTP_ENABLE_PPS 0x0 /* enum: Disable */ #define MC_CMD_PTP_DISABLE_PPS 0x1 -/* Queueid to send events back */ +/* Queue id to send events back */ #define MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_OFST 8 +/* MC_CMD_PTP_IN_GET_TIME_FORMAT msgrequest */ +#define MC_CMD_PTP_IN_GET_TIME_FORMAT_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_GET_ATTRIBUTES msgrequest */ +#define MC_CMD_PTP_IN_GET_ATTRIBUTES_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_GET_TIMESTAMP_CORRECTIONS msgrequest */ +#define MC_CMD_PTP_IN_GET_TIMESTAMP_CORRECTIONS_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE msgrequest */ +#define MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE_LEN 12 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +/* Event queue to send PTP time events to */ +#define MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE_QUEUE_OFST 8 + +/* MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE msgrequest */ +#define MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_LEN 16 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +/* Unsubscribe options */ +#define MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_CONTROL_OFST 8 +/* enum: Unsubscribe a single queue */ +#define MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_SINGLE 0x0 +/* enum: Unsubscribe all queues */ +#define MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_ALL 0x1 +/* Event queue ID */ +#define MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_QUEUE_OFST 12 + +/* MC_CMD_PTP_IN_MANFTEST_PPS msgrequest */ +#define MC_CMD_PTP_IN_MANFTEST_PPS_LEN 12 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +/* 1 to enable PPS test mode, 0 to disable and return result. */ +#define MC_CMD_PTP_IN_MANFTEST_PPS_TEST_ENABLE_OFST 8 + /* MC_CMD_PTP_OUT msgresponse */ #define MC_CMD_PTP_OUT_LEN 0 @@ -1088,15 +1203,29 @@ #define MC_CMD_PTP_OUT_TRANSMIT_LEN 8 /* Value of seconds timestamp */ #define MC_CMD_PTP_OUT_TRANSMIT_SECONDS_OFST 0 +/* Timestamp major value */ +#define MC_CMD_PTP_OUT_TRANSMIT_MAJOR_OFST 0 /* Value of nanoseconds timestamp */ #define MC_CMD_PTP_OUT_TRANSMIT_NANOSECONDS_OFST 4 +/* Timestamp minor value */ +#define MC_CMD_PTP_OUT_TRANSMIT_MINOR_OFST 4 + +/* MC_CMD_PTP_OUT_TIME_EVENT_SUBSCRIBE msgresponse */ +#define MC_CMD_PTP_OUT_TIME_EVENT_SUBSCRIBE_LEN 0 + +/* MC_CMD_PTP_OUT_TIME_EVENT_UNSUBSCRIBE msgresponse */ +#define MC_CMD_PTP_OUT_TIME_EVENT_UNSUBSCRIBE_LEN 0 /* MC_CMD_PTP_OUT_READ_NIC_TIME msgresponse */ #define MC_CMD_PTP_OUT_READ_NIC_TIME_LEN 8 /* Value of seconds timestamp */ #define MC_CMD_PTP_OUT_READ_NIC_TIME_SECONDS_OFST 0 +/* Timestamp major value */ +#define MC_CMD_PTP_OUT_READ_NIC_TIME_MAJOR_OFST 0 /* Value of nanoseconds timestamp */ #define MC_CMD_PTP_OUT_READ_NIC_TIME_NANOSECONDS_OFST 4 +/* Timestamp minor value */ +#define MC_CMD_PTP_OUT_READ_NIC_TIME_MINOR_OFST 4 /* MC_CMD_PTP_OUT_STATUS msgresponse */ #define MC_CMD_PTP_OUT_STATUS_LEN 64 @@ -1116,21 +1245,21 @@ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFLOW_OFST 24 /* Number of PPS bad periods */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_BAD_OFST 28 -/* Minimum period of PPS pulse */ +/* Minimum period of PPS pulse in nanoseconds */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MIN_OFST 32 -/* Maximum period of PPS pulse */ +/* Maximum period of PPS pulse in nanoseconds */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MAX_OFST 36 -/* Last period of PPS pulse */ +/* Last period of PPS pulse in nanoseconds */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_LAST_OFST 40 -/* Mean period of PPS pulse */ +/* Mean period of PPS pulse in nanoseconds */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MEAN_OFST 44 -/* Minimum offset of PPS pulse (signed) */ +/* Minimum offset of PPS pulse in nanoseconds (signed) */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MIN_OFST 48 -/* Maximum offset of PPS pulse (signed) */ +/* Maximum offset of PPS pulse in nanoseconds (signed) */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MAX_OFST 52 -/* Last offset of PPS pulse (signed) */ +/* Last offset of PPS pulse in nanoseconds (signed) */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_LAST_OFST 56 -/* Mean offset of PPS pulse (signed) */ +/* Mean offset of PPS pulse in nanoseconds (signed) */ #define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MEAN_OFST 60 /* MC_CMD_PTP_OUT_SYNCHRONIZE msgresponse */ @@ -1146,8 +1275,12 @@ #define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTSTART_OFST 0 /* Value of seconds timestamp */ #define MC_CMD_PTP_OUT_SYNCHRONIZE_SECONDS_OFST 4 +/* Timestamp major value */ +#define MC_CMD_PTP_OUT_SYNCHRONIZE_MAJOR_OFST 4 /* Value of nanoseconds timestamp */ #define MC_CMD_PTP_OUT_SYNCHRONIZE_NANOSECONDS_OFST 8 +/* Timestamp minor value */ +#define MC_CMD_PTP_OUT_SYNCHRONIZE_MINOR_OFST 8 /* Host time immediately after NIC's hardware clock read */ #define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTEND_OFST 12 /* Number of nanoseconds waited after reading NIC's hardware clock */ @@ -1177,6 +1310,16 @@ #define MC_CMD_PTP_MANF_PACKET_ENOUGH 0x8 /* enum: Timestamp trigger GPIO not working */ #define MC_CMD_PTP_MANF_GPIO_TRIGGER 0x9 +/* enum: Insufficient PPS events to perform checks */ +#define MC_CMD_PTP_MANF_PPS_ENOUGH 0xa +/* enum: PPS time event period not sufficiently close to 1s. */ +#define MC_CMD_PTP_MANF_PPS_PERIOD 0xb +/* enum: PPS time event nS reading not sufficiently close to zero. */ +#define MC_CMD_PTP_MANF_PPS_NS 0xc +/* enum: PTP peripheral registers incorrect */ +#define MC_CMD_PTP_MANF_REGISTERS 0xd +/* enum: Failed to read time from PTP peripheral */ +#define MC_CMD_PTP_MANF_CLOCK_READ 0xe /* Presence of external oscillator */ #define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_EXTOSC_OFST 4 @@ -1198,6 +1341,62 @@ #define MC_CMD_PTP_OUT_FPGAREAD_BUFFER_MINNUM 1 #define MC_CMD_PTP_OUT_FPGAREAD_BUFFER_MAXNUM 252 +/* MC_CMD_PTP_OUT_GET_TIME_FORMAT msgresponse */ +#define MC_CMD_PTP_OUT_GET_TIME_FORMAT_LEN 4 +/* Time format required/used by for this NIC. Applies to all PTP MCDI + * operations that pass times between the host and firmware. If this operation + * is not supported (older firmware) a format of seconds and nanoseconds should + * be assumed. + */ +#define MC_CMD_PTP_OUT_GET_TIME_FORMAT_FORMAT_OFST 0 +/* enum: Times are in seconds and nanoseconds */ +#define MC_CMD_PTP_OUT_GET_TIME_FORMAT_SECONDS_NANOSECONDS 0x0 +/* enum: Major register has units of 16 second per tick, minor 8 ns per tick */ +#define MC_CMD_PTP_OUT_GET_TIME_FORMAT_16SECONDS_8NANOSECONDS 0x1 +/* enum: Major register has units of seconds, minor 2^-27s per tick */ +#define MC_CMD_PTP_OUT_GET_TIME_FORMAT_SECONDS_27FRACTION 0x2 + +/* MC_CMD_PTP_OUT_GET_ATTRIBUTES msgresponse */ +#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_LEN 8 +/* Time format required/used by for this NIC. Applies to all PTP MCDI + * operations that pass times between the host and firmware. If this operation + * is not supported (older firmware) a format of seconds and nanoseconds should + * be assumed. + */ +#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_TIME_FORMAT_OFST 0 +/* enum: Times are in seconds and nanoseconds */ +#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS 0x0 +/* enum: Major register has units of 16 second per tick, minor 8 ns per tick */ +#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_16SECONDS_8NANOSECONDS 0x1 +/* enum: Major register has units of seconds, minor 2^-27s per tick */ +#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_27FRACTION 0x2 +/* Minimum acceptable value for a corrected synchronization timeset. When + * comparing host and NIC clock times, the MC returns a set of samples that + * contain the host start and end time, the MC time when the host start was + * detected and the time the MC waited between reading the time and detecting + * the host end. The corrected sync window is the difference between the host + * end and start times minus the time that the MC waited for host end. + */ +#define MC_CMD_PTP_OUT_GET_ATTRIBUTES_SYNC_WINDOW_MIN_OFST 4 + +/* MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS msgresponse */ +#define MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN 16 +/* Uncorrected error on transmit timestamps in NIC clock format */ +#define MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_TRANSMIT_OFST 0 +/* Uncorrected error on receive timestamps in NIC clock format */ +#define MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_RECEIVE_OFST 4 +/* Uncorrected error on PPS output in NIC clock format */ +#define MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_OUT_OFST 8 +/* Uncorrected error on PPS input in NIC clock format */ +#define MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_IN_OFST 12 + +/* MC_CMD_PTP_OUT_MANFTEST_PPS msgresponse */ +#define MC_CMD_PTP_OUT_MANFTEST_PPS_LEN 4 +/* Results of testing */ +#define MC_CMD_PTP_OUT_MANFTEST_PPS_TEST_RESULT_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_PTP_OUT_MANFTEST_BASIC/TEST_RESULT */ + /***********************************/ /* MC_CMD_CSR_READ32 @@ -1923,6 +2122,8 @@ #define MC_CMD_MEDIA_SFP_PLUS 0x5 /* enum: 10GBaseT. */ #define MC_CMD_MEDIA_BASE_T 0x6 +/* enum: QSFP+. */ +#define MC_CMD_MEDIA_QSFP_PLUS 0x7 #define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48 /* enum: Native clause 22 */ #define MC_CMD_MMD_CLAUSE22 0x0 @@ -2223,6 +2424,8 @@ #define MC_CMD_LOOPBACK_SD_FEP_WS 0x21 /* enum: KR Serdes Serial Wireside. */ #define MC_CMD_LOOPBACK_SD_FES_WS 0x22 +/* enum: Near side of AOE Siena side port */ +#define MC_CMD_LOOPBACK_AOE_INT_NEAR 0x23 /* Supported loopbacks. */ #define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_OFST 8 #define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LEN 8 @@ -2286,6 +2489,10 @@ #define MC_CMD_GET_LINK_OUT_BPX_LINK_WIDTH 1 #define MC_CMD_GET_LINK_OUT_PHY_LINK_LBN 3 #define MC_CMD_GET_LINK_OUT_PHY_LINK_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_LINK_FAULT_RX_LBN 6 +#define MC_CMD_GET_LINK_OUT_LINK_FAULT_RX_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_LINK_FAULT_TX_LBN 7 +#define MC_CMD_GET_LINK_OUT_LINK_FAULT_TX_WIDTH 1 /* This returns the negotiated flow control value. */ #define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20 /* enum: Flow control is off. */ @@ -3175,7 +3382,7 @@ #define MC_CMD_SENSOR_INFO_EXT_IN_PAGE_OFST 0 /* MC_CMD_SENSOR_INFO_OUT msgresponse */ -#define MC_CMD_SENSOR_INFO_OUT_LENMIN 12 +#define MC_CMD_SENSOR_INFO_OUT_LENMIN 4 #define MC_CMD_SENSOR_INFO_OUT_LENMAX 252 #define MC_CMD_SENSOR_INFO_OUT_LEN(num) (4+8*(num)) #define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0 @@ -3269,16 +3476,18 @@ #define MC_CMD_SENSOR_VDD08D_VSS08D_CSR 0x2b /* enum: voltage between VSS08D and VSS08D at CSR (external ADC): mV */ #define MC_CMD_SENSOR_VDD08D_VSS08D_CSR_EXTADC 0x2c +/* enum: Hotpoint temperature: degC */ +#define MC_CMD_SENSOR_HOTPOINT_TEMP 0x2d /* MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF */ #define MC_CMD_SENSOR_ENTRY_OFST 4 #define MC_CMD_SENSOR_ENTRY_LEN 8 #define MC_CMD_SENSOR_ENTRY_LO_OFST 4 #define MC_CMD_SENSOR_ENTRY_HI_OFST 8 -#define MC_CMD_SENSOR_ENTRY_MINNUM 1 +#define MC_CMD_SENSOR_ENTRY_MINNUM 0 #define MC_CMD_SENSOR_ENTRY_MAXNUM 31 /* MC_CMD_SENSOR_INFO_EXT_OUT msgresponse */ -#define MC_CMD_SENSOR_INFO_EXT_OUT_LENMIN 12 +#define MC_CMD_SENSOR_INFO_EXT_OUT_LENMIN 4 #define MC_CMD_SENSOR_INFO_EXT_OUT_LENMAX 252 #define MC_CMD_SENSOR_INFO_EXT_OUT_LEN(num) (4+8*(num)) #define MC_CMD_SENSOR_INFO_EXT_OUT_MASK_OFST 0 @@ -3291,7 +3500,7 @@ /* MC_CMD_SENSOR_ENTRY_LEN 8 */ /* MC_CMD_SENSOR_ENTRY_LO_OFST 4 */ /* MC_CMD_SENSOR_ENTRY_HI_OFST 8 */ -/* MC_CMD_SENSOR_ENTRY_MINNUM 1 */ +/* MC_CMD_SENSOR_ENTRY_MINNUM 0 */ /* MC_CMD_SENSOR_ENTRY_MAXNUM 31 */ /* MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF structuredef */ @@ -3864,6 +4073,18 @@ #define NVRAM_PARTITION_TYPE_ID_LBN 0 #define NVRAM_PARTITION_TYPE_ID_WIDTH 16 +/* LICENSED_APP_ID structuredef */ +#define LICENSED_APP_ID_LEN 4 +#define LICENSED_APP_ID_ID_OFST 0 +/* enum: OpenOnload */ +#define LICENSED_APP_ID_ONLOAD 0x1 +/* enum: PTP timestamping */ +#define LICENSED_APP_ID_PTP 0x2 +/* enum: SolarCapture Pro */ +#define LICENSED_APP_ID_SOLARCAPTURE_PRO 0x4 +#define LICENSED_APP_ID_ID_LBN 0 +#define LICENSED_APP_ID_ID_WIDTH 32 + /***********************************/ /* MC_CMD_READ_REGS @@ -4021,6 +4242,8 @@ #define MC_CMD_INIT_RXQ_IN_FLAG_CHAIN_WIDTH 1 #define MC_CMD_INIT_RXQ_IN_FLAG_PREFIX_LBN 8 #define MC_CMD_INIT_RXQ_IN_FLAG_PREFIX_WIDTH 1 +#define MC_CMD_INIT_RXQ_IN_FLAG_DISABLE_SCATTER_LBN 9 +#define MC_CMD_INIT_RXQ_IN_FLAG_DISABLE_SCATTER_WIDTH 1 /* Owner ID to use if in buffer mode (zero if physical) */ #define MC_CMD_INIT_RXQ_IN_OWNER_ID_OFST 20 /* The port ID associated with the v-adaptor which should contain this DMAQ. */ @@ -4179,6 +4402,9 @@ #define MC_CMD_PROXY_CMD_IN_TARGET_VF_WIDTH 16 #define MC_CMD_PROXY_CMD_IN_VF_NULL 0xffff /* enum */ +/* MC_CMD_PROXY_CMD_OUT msgresponse */ +#define MC_CMD_PROXY_CMD_OUT_LEN 0 + /***********************************/ /* MC_CMD_ALLOC_BUFTBL_CHUNK @@ -4213,7 +4439,7 @@ /* MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN msgrequest */ #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LENMIN 20 -#define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LENMAX 252 +#define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LENMAX 268 #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LEN(num) (12+8*(num)) #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_HANDLE_OFST 0 /* ID */ @@ -4226,7 +4452,7 @@ #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_LO_OFST 12 #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_HI_OFST 16 #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_MINNUM 1 -#define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_MAXNUM 30 +#define MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_MAXNUM 32 /* MC_CMD_PROGRAM_BUFTBL_ENTRIES_OUT msgresponse */ #define MC_CMD_PROGRAM_BUFTBL_ENTRIES_OUT_LEN 0 @@ -6799,6 +7025,30 @@ #define MC_CMD_TRIGGER_INTERRUPT_OUT_LEN 0 +/***********************************/ +/* MC_CMD_CAP_BLK_READ + * Read multiple 64bit words from capture block memory + */ +#define MC_CMD_CAP_BLK_READ 0xe7 + +/* MC_CMD_CAP_BLK_READ_IN msgrequest */ +#define MC_CMD_CAP_BLK_READ_IN_LEN 12 +#define MC_CMD_CAP_BLK_READ_IN_CAP_REG_OFST 0 +#define MC_CMD_CAP_BLK_READ_IN_ADDR_OFST 4 +#define MC_CMD_CAP_BLK_READ_IN_COUNT_OFST 8 + +/* MC_CMD_CAP_BLK_READ_OUT msgresponse */ +#define MC_CMD_CAP_BLK_READ_OUT_LENMIN 8 +#define MC_CMD_CAP_BLK_READ_OUT_LENMAX 248 +#define MC_CMD_CAP_BLK_READ_OUT_LEN(num) (0+8*(num)) +#define MC_CMD_CAP_BLK_READ_OUT_BUFFER_OFST 0 +#define MC_CMD_CAP_BLK_READ_OUT_BUFFER_LEN 8 +#define MC_CMD_CAP_BLK_READ_OUT_BUFFER_LO_OFST 0 +#define MC_CMD_CAP_BLK_READ_OUT_BUFFER_HI_OFST 4 +#define MC_CMD_CAP_BLK_READ_OUT_BUFFER_MINNUM 1 +#define MC_CMD_CAP_BLK_READ_OUT_BUFFER_MAXNUM 31 + + /***********************************/ /* MC_CMD_DUMP_DO * Take a dump of the DUT state @@ -6826,6 +7076,10 @@ #define MC_CMD_DUMP_DO_IN_DUMPSPEC_SRC_CUSTOM_HOST_MEMORY_MLI_DEPTH_OFST 20 #define MC_CMD_DUMP_DO_IN_HOST_MEMORY_MLI_MAX_DEPTH 0x2 /* enum */ #define MC_CMD_DUMP_DO_IN_DUMPSPEC_SRC_CUSTOM_UART_PORT_OFST 12 +/* enum: The uart port this command was received over (if using a uart + * transport) + */ +#define MC_CMD_DUMP_DO_IN_UART_PORT_SRC 0xff #define MC_CMD_DUMP_DO_IN_DUMPSPEC_SRC_CUSTOM_SIZE_OFST 24 #define MC_CMD_DUMP_DO_IN_DUMPFILE_DST_OFST 28 #define MC_CMD_DUMP_DO_IN_DUMPFILE_DST_CUSTOM 0x0 /* enum */ @@ -6942,39 +7196,68 @@ /***********************************/ -/* MC_CMD_START_KR_EYE_PLOT - * Start KR Serdes Eye diagram plot on a given lane. Lane must have valid - * signal. - */ -#define MC_CMD_START_KR_EYE_PLOT 0xee - -/* MC_CMD_START_KR_EYE_PLOT_IN msgrequest */ -#define MC_CMD_START_KR_EYE_PLOT_IN_LEN 4 -#define MC_CMD_START_KR_EYE_PLOT_IN_LANE_OFST 0 - -/* MC_CMD_START_KR_EYE_PLOT_OUT msgresponse */ -#define MC_CMD_START_KR_EYE_PLOT_OUT_LEN 0 - - -/***********************************/ -/* MC_CMD_POLL_KR_EYE_PLOT - * Poll KR Serdes Eye diagram plot. Returns one row of BER data. The caller - * should call this command repeatedly after starting eye plot, until no more - * data is returned. - */ -#define MC_CMD_POLL_KR_EYE_PLOT 0xef - -/* MC_CMD_POLL_KR_EYE_PLOT_IN msgrequest */ -#define MC_CMD_POLL_KR_EYE_PLOT_IN_LEN 0 - -/* MC_CMD_POLL_KR_EYE_PLOT_OUT msgresponse */ -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_LENMIN 0 -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_LENMAX 252 -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_LEN(num) (0+2*(num)) -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_SAMPLES_OFST 0 -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_SAMPLES_LEN 2 -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_SAMPLES_MINNUM 0 -#define MC_CMD_POLL_KR_EYE_PLOT_OUT_SAMPLES_MAXNUM 126 +/* MC_CMD_UART_SEND_DATA + * Send checksummed[sic] block of data over the uart. Response is a placeholder + * should we wish to make this reliable; currently requests are fire-and- + * forget. + */ +#define MC_CMD_UART_SEND_DATA 0xee + +/* MC_CMD_UART_SEND_DATA_OUT msgrequest */ +#define MC_CMD_UART_SEND_DATA_OUT_LENMIN 16 +#define MC_CMD_UART_SEND_DATA_OUT_LENMAX 252 +#define MC_CMD_UART_SEND_DATA_OUT_LEN(num) (16+1*(num)) +/* CRC32 over OFFSET, LENGTH, RESERVED, DATA */ +#define MC_CMD_UART_SEND_DATA_OUT_CHECKSUM_OFST 0 +/* Offset at which to write the data */ +#define MC_CMD_UART_SEND_DATA_OUT_OFFSET_OFST 4 +/* Length of data */ +#define MC_CMD_UART_SEND_DATA_OUT_LENGTH_OFST 8 +/* Reserved for future use */ +#define MC_CMD_UART_SEND_DATA_OUT_RESERVED_OFST 12 +#define MC_CMD_UART_SEND_DATA_OUT_DATA_OFST 16 +#define MC_CMD_UART_SEND_DATA_OUT_DATA_LEN 1 +#define MC_CMD_UART_SEND_DATA_OUT_DATA_MINNUM 0 +#define MC_CMD_UART_SEND_DATA_OUT_DATA_MAXNUM 236 + +/* MC_CMD_UART_SEND_DATA_IN msgresponse */ +#define MC_CMD_UART_SEND_DATA_IN_LEN 0 + + +/***********************************/ +/* MC_CMD_UART_RECV_DATA + * Request checksummed[sic] block of data over the uart. Only a placeholder, + * subject to change and not currently implemented. + */ +#define MC_CMD_UART_RECV_DATA 0xef + +/* MC_CMD_UART_RECV_DATA_OUT msgrequest */ +#define MC_CMD_UART_RECV_DATA_OUT_LEN 16 +/* CRC32 over OFFSET, LENGTH, RESERVED */ +#define MC_CMD_UART_RECV_DATA_OUT_CHECKSUM_OFST 0 +/* Offset from which to read the data */ +#define MC_CMD_UART_RECV_DATA_OUT_OFFSET_OFST 4 +/* Length of data */ +#define MC_CMD_UART_RECV_DATA_OUT_LENGTH_OFST 8 +/* Reserved for future use */ +#define MC_CMD_UART_RECV_DATA_OUT_RESERVED_OFST 12 + +/* MC_CMD_UART_RECV_DATA_IN msgresponse */ +#define MC_CMD_UART_RECV_DATA_IN_LENMIN 16 +#define MC_CMD_UART_RECV_DATA_IN_LENMAX 252 +#define MC_CMD_UART_RECV_DATA_IN_LEN(num) (16+1*(num)) +/* CRC32 over RESERVED1, RESERVED2, RESERVED3, DATA */ +#define MC_CMD_UART_RECV_DATA_IN_CHECKSUM_OFST 0 +/* Offset at which to write the data */ +#define MC_CMD_UART_RECV_DATA_IN_RESERVED1_OFST 4 +/* Length of data */ +#define MC_CMD_UART_RECV_DATA_IN_RESERVED2_OFST 8 +/* Reserved for future use */ +#define MC_CMD_UART_RECV_DATA_IN_RESERVED3_OFST 12 +#define MC_CMD_UART_RECV_DATA_IN_DATA_OFST 16 +#define MC_CMD_UART_RECV_DATA_IN_DATA_LEN 1 +#define MC_CMD_UART_RECV_DATA_IN_DATA_MINNUM 0 +#define MC_CMD_UART_RECV_DATA_IN_DATA_MAXNUM 236 /***********************************/ @@ -7026,6 +7309,15 @@ #define MC_CMD_KR_TUNE_IN_TXEQ_SET 0x3 /* enum: Force KR Serdes reset / recalibration */ #define MC_CMD_KR_TUNE_IN_RECAL 0x4 +/* enum: Start KR Serdes Eye diagram plot on a given lane. Lane must have valid + * signal. + */ +#define MC_CMD_KR_TUNE_IN_START_EYE_PLOT 0x5 +/* enum: Poll KR Serdes Eye diagram plot. Returns one row of BER data. The + * caller should call this command repeatedly after starting eye plot, until no + * more data is returned. + */ +#define MC_CMD_KR_TUNE_IN_POLL_EYE_PLOT 0x6 /* Align the arguments to 32 bits */ #define MC_CMD_KR_TUNE_IN_KR_TUNE_RSVD_OFST 1 #define MC_CMD_KR_TUNE_IN_KR_TUNE_RSVD_LEN 3 @@ -7123,6 +7415,91 @@ /* MC_CMD_KR_TUNE_RXEQ_SET_OUT msgresponse */ #define MC_CMD_KR_TUNE_RXEQ_SET_OUT_LEN 0 +/* MC_CMD_KR_TUNE_TXEQ_GET_IN msgrequest */ +#define MC_CMD_KR_TUNE_TXEQ_GET_IN_LEN 4 +/* Requested operation */ +#define MC_CMD_KR_TUNE_TXEQ_GET_IN_KR_TUNE_OP_OFST 0 +#define MC_CMD_KR_TUNE_TXEQ_GET_IN_KR_TUNE_OP_LEN 1 +/* Align the arguments to 32 bits */ +#define MC_CMD_KR_TUNE_TXEQ_GET_IN_KR_TUNE_RSVD_OFST 1 +#define MC_CMD_KR_TUNE_TXEQ_GET_IN_KR_TUNE_RSVD_LEN 3 + +/* MC_CMD_KR_TUNE_TXEQ_GET_OUT msgresponse */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LENMIN 4 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LENMAX 252 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LEN(num) (0+4*(num)) +/* TXEQ Parameter */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_OFST 0 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_LEN 4 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_MINNUM 1 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_MAXNUM 63 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_ID_LBN 0 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_ID_WIDTH 8 +/* enum: TX Amplitude */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_LEV 0x0 +/* enum: De-Emphasis Tap1 Magnitude (0-7) */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_MODE 0x1 +/* enum: De-Emphasis Tap1 Fine */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_DTLEV 0x2 +/* enum: De-Emphasis Tap2 Magnitude (0-6) */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_D2 0x3 +/* enum: De-Emphasis Tap2 Fine */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_D2TLEV 0x4 +/* enum: Pre-Emphasis Magnitude */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_E 0x5 +/* enum: Pre-Emphasis Fine */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_ETLEV 0x6 +/* enum: TX Slew Rate Coarse control */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_PREDRV_DLY 0x7 +/* enum: TX Slew Rate Fine control */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_TX_SR_SET 0x8 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_LANE_LBN 8 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_LANE_WIDTH 3 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LANE_0 0x0 /* enum */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LANE_1 0x1 /* enum */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LANE_2 0x2 /* enum */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LANE_3 0x3 /* enum */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_LANE_ALL 0x4 /* enum */ +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_RESERVED_LBN 11 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_RESERVED_WIDTH 5 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_INITIAL_LBN 16 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_PARAM_INITIAL_WIDTH 8 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_RESERVED2_LBN 24 +#define MC_CMD_KR_TUNE_TXEQ_GET_OUT_RESERVED2_WIDTH 8 + +/* MC_CMD_KR_TUNE_TXEQ_SET_IN msgrequest */ +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_LENMIN 8 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_LENMAX 252 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_LEN(num) (4+4*(num)) +/* Requested operation */ +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_KR_TUNE_OP_OFST 0 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_KR_TUNE_OP_LEN 1 +/* Align the arguments to 32 bits */ +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_KR_TUNE_RSVD_OFST 1 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_KR_TUNE_RSVD_LEN 3 +/* TXEQ Parameter */ +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_OFST 4 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_LEN 4 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_MINNUM 1 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_MAXNUM 62 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_ID_LBN 0 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_ID_WIDTH 8 +/* Enum values, see field(s): */ +/* MC_CMD_KR_TUNE_TXEQ_GET_OUT/PARAM_ID */ +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_LANE_LBN 8 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_LANE_WIDTH 3 +/* Enum values, see field(s): */ +/* MC_CMD_KR_TUNE_TXEQ_GET_OUT/PARAM_LANE */ +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_RESERVED_LBN 11 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_RESERVED_WIDTH 5 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_INITIAL_LBN 16 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_PARAM_INITIAL_WIDTH 8 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_RESERVED2_LBN 24 +#define MC_CMD_KR_TUNE_TXEQ_SET_IN_RESERVED2_WIDTH 8 + +/* MC_CMD_KR_TUNE_TXEQ_SET_OUT msgresponse */ +#define MC_CMD_KR_TUNE_TXEQ_SET_OUT_LEN 0 + /* MC_CMD_KR_TUNE_RECAL_IN msgrequest */ #define MC_CMD_KR_TUNE_RECAL_IN_LEN 4 /* Requested operation */ @@ -7135,6 +7512,37 @@ /* MC_CMD_KR_TUNE_RECAL_OUT msgresponse */ #define MC_CMD_KR_TUNE_RECAL_OUT_LEN 0 +/* MC_CMD_KR_TUNE_START_EYE_PLOT_IN msgrequest */ +#define MC_CMD_KR_TUNE_START_EYE_PLOT_IN_LEN 8 +/* Requested operation */ +#define MC_CMD_KR_TUNE_START_EYE_PLOT_IN_KR_TUNE_OP_OFST 0 +#define MC_CMD_KR_TUNE_START_EYE_PLOT_IN_KR_TUNE_OP_LEN 1 +/* Align the arguments to 32 bits */ +#define MC_CMD_KR_TUNE_START_EYE_PLOT_IN_KR_TUNE_RSVD_OFST 1 +#define MC_CMD_KR_TUNE_START_EYE_PLOT_IN_KR_TUNE_RSVD_LEN 3 +#define MC_CMD_KR_TUNE_START_EYE_PLOT_IN_LANE_OFST 4 + +/* MC_CMD_KR_TUNE_START_EYE_PLOT_OUT msgresponse */ +#define MC_CMD_KR_TUNE_START_EYE_PLOT_OUT_LEN 0 + +/* MC_CMD_KR_TUNE_POLL_EYE_PLOT_IN msgrequest */ +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_IN_LEN 4 +/* Requested operation */ +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_IN_KR_TUNE_OP_OFST 0 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_IN_KR_TUNE_OP_LEN 1 +/* Align the arguments to 32 bits */ +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_IN_KR_TUNE_RSVD_OFST 1 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_IN_KR_TUNE_RSVD_LEN 3 + +/* MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT msgresponse */ +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_LENMIN 0 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_LENMAX 252 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_LEN(num) (0+2*(num)) +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_OFST 0 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_LEN 2 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_MINNUM 0 +#define MC_CMD_KR_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_MAXNUM 126 + /***********************************/ /* MC_CMD_PCIE_TUNE @@ -7157,6 +7565,13 @@ #define MC_CMD_PCIE_TUNE_IN_TXEQ_GET 0x2 /* enum: Override TX Driver settings */ #define MC_CMD_PCIE_TUNE_IN_TXEQ_SET 0x3 +/* enum: Start PCIe Serdes Eye diagram plot on a given lane. */ +#define MC_CMD_PCIE_TUNE_IN_START_EYE_PLOT 0x5 +/* enum: Poll PCIe Serdes Eye diagram plot. Returns one row of BER data. The + * caller should call this command repeatedly after starting eye plot, until no + * more data is returned. + */ +#define MC_CMD_PCIE_TUNE_IN_POLL_EYE_PLOT 0x6 /* Align the arguments to 32 bits */ #define MC_CMD_PCIE_TUNE_IN_PCIE_TUNE_RSVD_OFST 1 #define MC_CMD_PCIE_TUNE_IN_PCIE_TUNE_RSVD_LEN 3 @@ -7258,6 +7673,37 @@ #define MC_CMD_PCIE_TUNE_TXEQ_GET_OUT_PARAM_CURRENT_LBN 24 #define MC_CMD_PCIE_TUNE_TXEQ_GET_OUT_PARAM_CURRENT_WIDTH 8 +/* MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN msgrequest */ +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN_LEN 8 +/* Requested operation */ +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN_PCIE_TUNE_OP_OFST 0 +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN_PCIE_TUNE_OP_LEN 1 +/* Align the arguments to 32 bits */ +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN_PCIE_TUNE_RSVD_OFST 1 +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN_PCIE_TUNE_RSVD_LEN 3 +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_IN_LANE_OFST 4 + +/* MC_CMD_PCIE_TUNE_START_EYE_PLOT_OUT msgresponse */ +#define MC_CMD_PCIE_TUNE_START_EYE_PLOT_OUT_LEN 0 + +/* MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_IN msgrequest */ +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_IN_LEN 4 +/* Requested operation */ +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_IN_PCIE_TUNE_OP_OFST 0 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_IN_PCIE_TUNE_OP_LEN 1 +/* Align the arguments to 32 bits */ +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_IN_PCIE_TUNE_RSVD_OFST 1 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_IN_PCIE_TUNE_RSVD_LEN 3 + +/* MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT msgresponse */ +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_LENMIN 0 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_LENMAX 252 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_LEN(num) (0+2*(num)) +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_OFST 0 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_LEN 2 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_MINNUM 0 +#define MC_CMD_PCIE_TUNE_POLL_EYE_PLOT_OUT_SAMPLES_MAXNUM 126 + /***********************************/ /* MC_CMD_LICENSING @@ -7310,5 +7756,152 @@ */ #define MC_CMD_MC2MC_PROXY 0xf4 +/* MC_CMD_MC2MC_PROXY_IN msgrequest */ +#define MC_CMD_MC2MC_PROXY_IN_LEN 0 + +/* MC_CMD_MC2MC_PROXY_OUT msgresponse */ +#define MC_CMD_MC2MC_PROXY_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_LICENSED_APP_STATE + * Query the state of an individual licensed application. (Note that the actual + * state may be invalidated by the MC_CMD_LICENSING OP_UPDATE_LICENSE operation + * or a reboot of the MC.) + */ +#define MC_CMD_GET_LICENSED_APP_STATE 0xf5 + +/* MC_CMD_GET_LICENSED_APP_STATE_IN msgrequest */ +#define MC_CMD_GET_LICENSED_APP_STATE_IN_LEN 4 +/* application ID to query (LICENSED_APP_ID_xxx) */ +#define MC_CMD_GET_LICENSED_APP_STATE_IN_APP_ID_OFST 0 + +/* MC_CMD_GET_LICENSED_APP_STATE_OUT msgresponse */ +#define MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN 4 +/* state of this application */ +#define MC_CMD_GET_LICENSED_APP_STATE_OUT_STATE_OFST 0 +/* enum: no (or invalid) license is present for the application */ +#define MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED 0x0 +/* enum: a valid license is present for the application */ +#define MC_CMD_GET_LICENSED_APP_STATE_OUT_LICENSED 0x1 + + +/***********************************/ +/* MC_CMD_LICENSED_APP_OP + * Perform an action for an individual licensed application. + */ +#define MC_CMD_LICENSED_APP_OP 0xf6 + +/* MC_CMD_LICENSED_APP_OP_IN msgrequest */ +#define MC_CMD_LICENSED_APP_OP_IN_LENMIN 8 +#define MC_CMD_LICENSED_APP_OP_IN_LENMAX 252 +#define MC_CMD_LICENSED_APP_OP_IN_LEN(num) (8+4*(num)) +/* application ID */ +#define MC_CMD_LICENSED_APP_OP_IN_APP_ID_OFST 0 +/* the type of operation requested */ +#define MC_CMD_LICENSED_APP_OP_IN_OP_OFST 4 +/* enum: validate application */ +#define MC_CMD_LICENSED_APP_OP_IN_OP_VALIDATE 0x0 +/* arguments specific to this particular operation */ +#define MC_CMD_LICENSED_APP_OP_IN_ARGS_OFST 8 +#define MC_CMD_LICENSED_APP_OP_IN_ARGS_LEN 4 +#define MC_CMD_LICENSED_APP_OP_IN_ARGS_MINNUM 0 +#define MC_CMD_LICENSED_APP_OP_IN_ARGS_MAXNUM 61 + +/* MC_CMD_LICENSED_APP_OP_OUT msgresponse */ +#define MC_CMD_LICENSED_APP_OP_OUT_LENMIN 0 +#define MC_CMD_LICENSED_APP_OP_OUT_LENMAX 252 +#define MC_CMD_LICENSED_APP_OP_OUT_LEN(num) (0+4*(num)) +/* result specific to this particular operation */ +#define MC_CMD_LICENSED_APP_OP_OUT_RESULT_OFST 0 +#define MC_CMD_LICENSED_APP_OP_OUT_RESULT_LEN 4 +#define MC_CMD_LICENSED_APP_OP_OUT_RESULT_MINNUM 0 +#define MC_CMD_LICENSED_APP_OP_OUT_RESULT_MAXNUM 63 + +/* MC_CMD_LICENSED_APP_OP_VALIDATE_IN msgrequest */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_IN_LEN 72 +/* application ID */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_IN_APP_ID_OFST 0 +/* the type of operation requested */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_IN_OP_OFST 4 +/* validation challenge */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_IN_CHALLENGE_OFST 8 +#define MC_CMD_LICENSED_APP_OP_VALIDATE_IN_CHALLENGE_LEN 64 + +/* MC_CMD_LICENSED_APP_OP_VALIDATE_OUT msgresponse */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_OUT_LEN 68 +/* feature expiry (time_t) */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_OUT_EXPIRY_OFST 0 +/* validation response */ +#define MC_CMD_LICENSED_APP_OP_VALIDATE_OUT_RESPONSE_OFST 4 +#define MC_CMD_LICENSED_APP_OP_VALIDATE_OUT_RESPONSE_LEN 64 + + +/***********************************/ +/* MC_CMD_SET_PORT_SNIFF_CONFIG + * Configure port sniffing for the physical port associated with the calling + * function. Only a privileged function may change the port sniffing + * configuration. A copy of all traffic delivered to the host (non-promiscuous + * mode) or all traffic arriving at the port (promiscuous mode) may be + * delivered to a specific queue, or a set of queues with RSS. + */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG 0xf7 + +/* MC_CMD_SET_PORT_SNIFF_CONFIG_IN msgrequest */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_LEN 16 +/* configuration flags */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_FLAGS_OFST 0 +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_ENABLE_LBN 0 +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_ENABLE_WIDTH 1 +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_PROMISCUOUS_LBN 1 +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_PROMISCUOUS_WIDTH 1 +/* receive queue handle (for RSS mode, this is the base queue) */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_RX_QUEUE_OFST 4 +/* receive mode */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_RX_MODE_OFST 8 +/* enum: receive to just the specified queue */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_RX_MODE_SIMPLE 0x0 +/* enum: receive to multiple queues using RSS context */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_RX_MODE_RSS 0x1 +/* RSS context (for RX_MODE_RSS) as returned by MC_CMD_RSS_CONTEXT_ALLOC. Note + * that these handles should be considered opaque to the host, although a value + * of 0xFFFFFFFF is guaranteed never to be a valid handle. + */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_IN_RX_CONTEXT_OFST 12 + +/* MC_CMD_SET_PORT_SNIFF_CONFIG_OUT msgresponse */ +#define MC_CMD_SET_PORT_SNIFF_CONFIG_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_PORT_SNIFF_CONFIG + * Obtain the current port sniffing configuration for the physical port + * associated with the calling function. Only a privileged function may read + * the configuration. + */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG 0xf8 + +/* MC_CMD_GET_PORT_SNIFF_CONFIG_IN msgrequest */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_IN_LEN 0 + +/* MC_CMD_GET_PORT_SNIFF_CONFIG_OUT msgresponse */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_LEN 16 +/* configuration flags */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_FLAGS_OFST 0 +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_ENABLE_LBN 0 +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_ENABLE_WIDTH 1 +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_PROMISCUOUS_LBN 1 +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_PROMISCUOUS_WIDTH 1 +/* receiving queue handle (for RSS mode, this is the base queue) */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_RX_QUEUE_OFST 4 +/* receive mode */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_RX_MODE_OFST 8 +/* enum: receiving to just the specified queue */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_RX_MODE_SIMPLE 0x0 +/* enum: receiving to multiple queues using RSS context */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_RX_MODE_RSS 0x1 +/* RSS context (for RX_MODE_RSS) */ +#define MC_CMD_GET_PORT_SNIFF_CONFIG_OUT_RX_CONTEXT_OFST 12 + #endif /* MCDI_PCOL_H */ -- cgit v1.2.3 From 798183c54799fbe1e5a5bfabb3a8c0505ffd2149 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 20:29:01 -0200 Subject: drm/i915: change CRTC assertion on LCPLL disable Currently, PC8 is enabled at modeset_global_resources, which is called after intel_modeset_update_state. Due to this, there's a small race condition on the case where we start enabling PC8, then do a modeset while PC8 is still being enabled. The racing condition triggers a WARN because intel_modeset_update_state will mark the CRTC as enabled, then the thread that's still enabling PC8 might look at the data structure and think that PC8 is being enabled while a pipe is enabled. Despite the WARN, this is not really a bug since we'll wait for the PC8-enabling thread to finish when we call modeset_global_resources. The spec says the CRTC cannot be enabled when we disable LCPLL, so we had a check for crtc->base.enabled. If we change to crtc->active we will still prevent disabling LCPLL while the CRTC is enabled, and we will also prevent the WARN above. This is a replacement for the previous patch named "drm/i915: get/put PC8 when we get/put a CRTC" Testcase: igt/pm_pc8/modeset-lpsp-stress-no-wait Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2eaf7e7e5a40..1f7af63b31df 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6490,7 +6490,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) uint32_t val; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) - WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n", + WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); -- cgit v1.2.3 From dcf8f55b15ea290a50091ea86d862c688c2d1188 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 20 Nov 2013 10:02:48 +0000 Subject: i40e: separate TSYNVALID and TSYNINDX fields in Rx descriptor In order to get 1588 to work correctly the defines need a bit of a tweak. Change-Id: Ie50ce2a18e1593441f1560411e5a4f51c6d48aaa Signed-off-by: Jacob Keller Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_type.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 5f81bd52e6f0..fdad028f3321 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -500,7 +500,8 @@ enum i40e_rx_desc_status_bits { I40E_RX_DESC_STATUS_L2TAG1P_SHIFT = 2, I40E_RX_DESC_STATUS_L3L4P_SHIFT = 3, I40E_RX_DESC_STATUS_CRCP_SHIFT = 4, - I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 3 BITS */ + I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */ + I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7, I40E_RX_DESC_STATUS_PIF_SHIFT = 8, I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */ I40E_RX_DESC_STATUS_FLM_SHIFT = 11, @@ -509,9 +510,13 @@ enum i40e_rx_desc_status_bits { }; #define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT I40E_RX_DESC_STATUS_TSYNINDX_SHIFT -#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK (0x7UL << \ +#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK (0x3UL << \ I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT) +#define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT I40E_RX_DESC_STATUS_TSYNVALID_SHIFT +#define I40E_RXD_QW1_STATUS_TSYNVALID_MASK (0x1UL << \ + I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT) + enum i40e_rx_desc_fltstat_values { I40E_RX_DESC_FLTSTAT_NO_DATA = 0, I40E_RX_DESC_FLTSTAT_RSV_FD_ID = 1, /* 16byte desc? FD_ID : RSV */ -- cgit v1.2.3 From 8b48463f89429af408ff695244dc627e1acff4f7 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 3 Dec 2013 08:49:16 +0800 Subject: ACPI: Clean up inclusions of ACPI header files Replace direct inclusions of , and , which are incorrect, with inclusions and remove some inclusions of those files that aren't necessary. First of all, , and should not be included directly from any files that are built for CONFIG_ACPI unset, because that generally leads to build warnings about undefined symbols in !CONFIG_ACPI builds. For CONFIG_ACPI set, includes those files and for CONFIG_ACPI unset it provides stub ACPI symbols to be used in that case. Second, there are ordering dependencies between those files that always have to be met. Namely, it is required that be included prior to so that the acpi_pci_root declarations the latter depends on are always there. And which provides basic ACPICA type declarations should always be included prior to any other ACPI headers in CONFIG_ACPI builds. That also is taken care of including as appropriate. Signed-off-by: Lv Zheng Cc: Greg Kroah-Hartman Cc: Matthew Garrett Cc: Tony Luck Cc: "H. Peter Anvin" Acked-by: Bjorn Helgaas (drivers/pci stuff) Acked-by: Konrad Rzeszutek Wilk (Xen stuff) Signed-off-by: Rafael J. Wysocki --- arch/ia64/hp/common/aml_nfw.c | 3 +-- arch/x86/kernel/apic/apic_flat_64.c | 4 +--- arch/x86/kernel/apic/io_apic.c | 3 --- arch/x86/pci/mmconfig_32.c | 1 - arch/x86/platform/olpc/olpc-xo15-sci.c | 3 +-- drivers/acpi/ac.c | 3 +-- drivers/acpi/acpi_extlog.c | 1 - drivers/acpi/acpi_pad.c | 3 +-- drivers/acpi/apei/einj.c | 1 - drivers/acpi/battery.c | 3 +-- drivers/acpi/blacklist.c | 1 - drivers/acpi/bus.c | 2 -- drivers/acpi/button.c | 3 +-- drivers/acpi/custom_method.c | 2 +- drivers/acpi/debugfs.c | 2 +- drivers/acpi/dock.c | 2 -- drivers/acpi/ec.c | 5 ++--- drivers/acpi/event.c | 2 +- drivers/acpi/fan.c | 3 +-- drivers/acpi/hed.c | 2 -- drivers/acpi/numa.c | 1 - drivers/acpi/osl.c | 3 --- drivers/acpi/pci_irq.c | 2 -- drivers/acpi/pci_link.c | 4 +--- drivers/acpi/pci_root.c | 4 +--- drivers/acpi/power.c | 3 +-- drivers/acpi/proc.c | 4 +--- drivers/acpi/processor_core.c | 3 +-- drivers/acpi/processor_idle.c | 4 +--- drivers/acpi/processor_perflib.c | 7 ++----- drivers/acpi/processor_thermal.c | 7 ++----- drivers/acpi/processor_throttling.c | 7 ++----- drivers/acpi/sbshc.c | 3 +-- drivers/acpi/scan.c | 2 -- drivers/acpi/sleep.c | 4 ---- drivers/acpi/sysfs.c | 2 +- drivers/acpi/thermal.c | 5 ++--- drivers/acpi/utils.c | 2 -- drivers/acpi/video.c | 5 ++--- drivers/acpi/wakeup.c | 1 - drivers/ata/libata-acpi.c | 2 -- drivers/ata/pata_acpi.c | 5 ++--- drivers/char/hpet.c | 7 ++----- drivers/char/tpm/tpm_acpi.c | 2 +- drivers/char/tpm/tpm_ppi.c | 1 - drivers/gpu/drm/i915/intel_acpi.c | 2 -- drivers/gpu/drm/nouveau/nouveau_acpi.c | 7 +------ drivers/gpu/drm/radeon/radeon_acpi.c | 6 +----- drivers/hv/vmbus_drv.c | 2 -- drivers/hwmon/acpi_power_meter.c | 3 +-- drivers/hwmon/asus_atk0110.c | 7 +------ drivers/ide/ide-acpi.c | 1 - drivers/input/misc/atlas_btns.c | 2 +- drivers/iommu/amd_iommu_init.c | 1 - drivers/iommu/intel_irq_remapping.c | 4 ++-- drivers/pci/hotplug/acpiphp_ibm.c | 3 +-- drivers/pci/hotplug/pciehp.h | 2 -- drivers/pci/ioapic.c | 1 - drivers/pci/pci-acpi.c | 3 --- drivers/pci/pci-label.c | 1 - drivers/platform/x86/acer-wmi.c | 2 -- drivers/platform/x86/asus-laptop.c | 3 +-- drivers/platform/x86/asus-wmi.c | 3 +-- drivers/platform/x86/classmate-laptop.c | 3 +-- drivers/platform/x86/dell-wmi-aio.c | 1 - drivers/platform/x86/dell-wmi.c | 1 - drivers/platform/x86/eeepc-laptop.c | 3 +-- drivers/platform/x86/eeepc-wmi.c | 2 +- drivers/platform/x86/hp_accel.c | 2 +- drivers/platform/x86/ideapad-laptop.c | 3 +-- drivers/platform/x86/intel-rst.c | 2 +- drivers/platform/x86/intel-smartconnect.c | 2 +- drivers/platform/x86/intel_menlow.c | 4 +--- drivers/platform/x86/intel_oaktrail.c | 3 --- drivers/platform/x86/mxm-wmi.c | 3 +-- drivers/platform/x86/panasonic-laptop.c | 4 +--- drivers/platform/x86/pvpanic.c | 3 +-- drivers/platform/x86/samsung-q10.c | 2 +- drivers/platform/x86/sony-laptop.c | 4 +--- drivers/platform/x86/tc1100-wmi.c | 4 +--- drivers/platform/x86/thinkpad_acpi.c | 14 ++++---------- drivers/platform/x86/toshiba_acpi.c | 4 +--- drivers/platform/x86/toshiba_bluetooth.c | 4 +--- drivers/platform/x86/wmi.c | 2 -- drivers/platform/x86/xo15-ebook.c | 3 +-- drivers/pnp/pnpacpi/core.c | 1 - drivers/pnp/pnpacpi/pnpacpi.h | 1 - drivers/sfi/sfi_acpi.c | 2 +- drivers/staging/quickstart/quickstart.c | 2 +- drivers/usb/core/usb-acpi.c | 1 - drivers/xen/xen-acpi-cpuhotplug.c | 3 --- drivers/xen/xen-acpi-memhotplug.c | 1 - drivers/xen/xen-acpi-pad.c | 5 ++--- drivers/xen/xen-acpi-processor.c | 4 +--- include/acpi/acpi_bus.h | 2 -- include/acpi/acpi_drivers.h | 3 --- include/linux/acpi_io.h | 2 +- include/linux/ide.h | 8 ++------ include/linux/iscsi_ibft.h | 2 +- include/linux/pci_hotplug.h | 3 +-- include/linux/sfi_acpi.h | 2 +- include/linux/tboot.h | 2 +- tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c | 5 +---- 103 files changed, 80 insertions(+), 234 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c index 916ffe770bcf..84715fcbba08 100644 --- a/arch/ia64/hp/common/aml_nfw.c +++ b/arch/ia64/hp/common/aml_nfw.c @@ -23,8 +23,7 @@ */ #include -#include -#include +#include #include MODULE_AUTHOR("Bjorn Helgaas "); diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 00c77cf78e9e..ccbf857d1d55 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -21,9 +21,7 @@ #include #include -#ifdef CONFIG_ACPI -#include -#endif +#include static struct apic apic_physflat; static struct apic apic_flat; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e63a5bd2a78f..4d67a7531d45 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -37,9 +37,6 @@ #include #include /* time_after() */ #include -#ifdef CONFIG_ACPI -#include -#endif #include #include #include diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index 5c90975cdf0f..43984bc1665a 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -14,7 +14,6 @@ #include #include #include -#include /* Assume systems with more busses have correct MCFG */ #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index 649a12befba9..08e350e757dc 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c @@ -15,8 +15,7 @@ #include #include -#include -#include +#include #include #define DRV_NAME "olpc-xo15-sci" diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 8711e3797165..8095943e6e11 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -32,8 +32,7 @@ #include #include #include -#include -#include +#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index a6869e110ce5..2635a01c5b3e 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index fc6008fbce35..65610c0e7243 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -28,8 +28,7 @@ #include #include #include -#include -#include +#include #include #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index fb57d03e698b..ca0c6d7ec0d4 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "apei-internal.h" diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index fbf1aceda8b8..e90ef8b96f26 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -36,8 +36,7 @@ #include #include -#include -#include +#include #include #define PREFIX "ACPI: " diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 078c4f7fe2dd..05ee8f61bfb5 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "internal.h" diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index bba9b72e25f8..cfea1c58f034 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -37,8 +37,6 @@ #include #endif #include -#include -#include #include #include #include diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index c971929d75c2..9e3a6cb99f90 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -31,8 +31,7 @@ #include #include #include -#include -#include +#include #include #define PREFIX "ACPI: " diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c index 12b62f2cdb3f..c68e72414a67 100644 --- a/drivers/acpi/custom_method.c +++ b/drivers/acpi/custom_method.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "internal.h" diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c index b55d6a20dc0e..6b1919f6bd82 100644 --- a/drivers/acpi/debugfs.c +++ b/drivers/acpi/debugfs.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("debugfs"); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index dcd73ccb514c..9ab9e783a894 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ba5b56db9d27..ff40120e930e 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -39,10 +39,9 @@ #include #include #include -#include -#include -#include +#include #include +#include #include "internal.h" diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index cae3b387b867..ef2d730734dc 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index ba3da88cee45..1fb62900f32a 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -29,8 +29,7 @@ #include #include #include -#include -#include +#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index 13b1d39d7cdf..aafe3ca829c2 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include static struct acpi_device_id acpi_hed_ids[] = { diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index a2343a1d9e0b..9e6816ef280a 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -29,7 +29,6 @@ #include #include #include -#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 54a20ff4b864..244be2affea7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -49,9 +49,6 @@ #include #include -#include -#include -#include #include "internal.h" #define _COMPONENT ACPI_OS_SERVICES diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 41c5e1b799ef..52d45ea2bc4f 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 2652a614deeb..ea6b8d16dcc8 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -39,9 +39,7 @@ #include #include #include - -#include -#include +#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0703bff5e60e..cd20f3486cfa 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -35,9 +35,7 @@ #include #include #include -#include -#include -#include +#include /* for acpi_hest_init() */ #include "internal.h" diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index c2ad391d8041..ad7da686e6e6 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -42,8 +42,7 @@ #include #include #include -#include -#include +#include #include "sleep.h" #include "internal.h" diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 6a5b152ad4d0..db061bfd95a8 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -3,11 +3,9 @@ #include #include #include +#include #include -#include -#include - #include "sleep.h" #define _COMPONENT ACPI_SYSTEM_COMPONENT diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index b3171f30b319..34e7b3c6a08d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -10,8 +10,7 @@ #include #include #include - -#include +#include #include #include "internal.h" diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 644516d9bde6..d2d44e0190a3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * Include the apic definitions for x86 to have the APIC timer related defines @@ -46,9 +47,6 @@ #include #endif -#include -#include - #define PREFIX "ACPI: " #define ACPI_PROCESSOR_CLASS "processor" diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 60a7c28fc167..ff90054f04fd 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -31,15 +31,12 @@ #include #include #include - +#include +#include #ifdef CONFIG_X86 #include #endif -#include -#include -#include - #define PREFIX "ACPI: " #define ACPI_PROCESSOR_CLASS "processor" diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index d1d2e7fb5b30..f95e7584d6e6 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -30,12 +30,9 @@ #include #include #include - -#include - -#include +#include #include -#include +#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index e7dd2c1fee79..28baa05b8018 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -32,14 +32,11 @@ #include #include #include - +#include +#include #include #include -#include -#include -#include - #define PREFIX "ACPI: " #define ACPI_PROCESSOR_CLASS "processor" diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index b78bc605837e..26e5b5060523 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -8,8 +8,7 @@ * the Free Software Foundation version 2. */ -#include -#include +#include #include #include #include diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 15daa21fcd05..56421a921a2b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -12,8 +12,6 @@ #include #include -#include - #include "internal.h" #define _COMPONENT ACPI_BUS_COMPONENT diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 14df30580e15..ea9cc373ffd8 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -18,12 +18,8 @@ #include #include #include - #include -#include -#include - #include "internal.h" #include "sleep.h" diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index db5293650f62..ba07d9a927ab 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include "internal.h" diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 0d9f46b5ae6d..1fd21ad69c98 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -41,10 +41,9 @@ #include #include #include -#include #include -#include -#include +#include +#include #define PREFIX "ACPI: " diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 6d408bfbbb1d..1336b9151479 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include "internal.h" diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 995e91bcb97b..b727d105046d 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -37,12 +37,11 @@ #include #include #include -#include #include -#include -#include #include +#include #include +#include #include "internal.h" diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 7bfbe40bc43b..1638401ab282 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -5,7 +5,6 @@ #include #include -#include #include #include diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 4372cfa883c9..8e22d9762328 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -20,8 +20,6 @@ #include #include "libata.h" -#include - unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)"); diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 73212c9c6d5b..62c9ac80c6e9 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -12,11 +12,10 @@ #include #include #include -#include -#include - +#include #include #include +#include #define DRV_NAME "pata_acpi" #define DRV_VERSION "0.2.3" diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 5d9c31dfc905..d5d4cd82b9f7 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -34,15 +34,12 @@ #include #include #include - +#include +#include #include #include #include -#include -#include -#include - /* * The High Precision Event Timer driver. * This driver is closely modelled after the rtc.c driver. diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c index 64420b3396a2..b9a57fa4b710 100644 --- a/drivers/char/tpm/tpm_acpi.c +++ b/drivers/char/tpm/tpm_acpi.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "tpm.h" #include "tpm_eventlog.h" diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 8e562dc65601..dd60ef336f8d 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c @@ -1,5 +1,4 @@ #include -#include #include "tpm.h" static const u8 tpm_ppi_uuid[] = { diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index dfff0907f70e..5325b25ccbb4 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -6,8 +6,6 @@ #include #include #include -#include - #include #include "i915_drv.h" diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 95c740454049..1f0b6d238cfa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -1,15 +1,10 @@ #include #include #include -#include -#include -#include -#include #include - #include - #include +#include #include "nouveau_drm.h" #include "nouveau_acpi.h" diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index 98a9074b306b..77e9d07c55b6 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -25,18 +25,14 @@ #include #include #include -#include -#include +#include #include - #include #include #include "radeon.h" #include "radeon_acpi.h" #include "atom.h" -#include - #define ACPI_AC_CLASS "ac_adapter" extern void radeon_pm_acpi_event_handler(struct radeon_device *rdev); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 48aad4faea06..077bb1bdac34 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -39,7 +38,6 @@ #include #include "hyperv_vmbus.h" - static struct acpi_device *hv_acpi_dev; static struct tasklet_struct msg_dpc; diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 6a34f7f48eb9..579bdf93be43 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -30,8 +30,7 @@ #include #include #include -#include -#include +#include #define ACPI_POWER_METER_NAME "power_meter" ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 1d7ff46812c3..ae208f612198 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -16,12 +16,7 @@ #include #include #include - -#include -#include -#include -#include - +#include #define ATK_HID "ATK0110" diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index d9e1f7ccfe6f..333d4053e727 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 5d4402365a52..d781b5e52065 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -28,8 +28,8 @@ #include #include #include +#include #include -#include #define ACPI_ATLAS_NAME "Atlas ACPI" #define ACPI_ATLAS_CLASS "Atlas" diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 8f798be6e398..28b4bea7c109 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index bab10b1002fb..0cb7528b30a1 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -6,11 +6,11 @@ #include #include #include +#include +#include #include #include #include -#include -#include #include #include #include diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index ecfac7e72d91..8dcccffd6e21 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -31,12 +31,11 @@ #include #include #include -#include #include #include -#include #include #include +#include #include "acpiphp.h" #include "../pci.h" diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 21e865ded1dc..24e147cae667 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -163,8 +163,6 @@ static inline const char *slot_name(struct slot *slot) } #ifdef CONFIG_ACPI -#include -#include #include void __init pciehp_acpi_slot_detection_init(void); diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c index 50ce68098298..2122b2bf006f 100644 --- a/drivers/pci/ioapic.c +++ b/drivers/pci/ioapic.c @@ -20,7 +20,6 @@ #include #include #include -#include struct ioapic { acpi_handle handle; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 577074efbe62..43e317991326 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include - #include #include #include diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index d51f45aa669e..dbafcc8ef673 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -29,7 +29,6 @@ #include #include #include -#include #include "pci.h" #define DEVICE_LABEL_DSM 0x07 diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index c9076bdaf2c1..c91f69b39db4 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -41,8 +41,6 @@ #include #include #include - -#include #include MODULE_AUTHOR("Carlos Corbacho"); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 0e9c169b42f8..430b5c3c46b4 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -53,8 +53,7 @@ #include #include #include -#include -#include +#include #define ASUS_LAPTOP_VERSION "0.42" diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 19c313b056c3..df7ecb9ecd9d 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -45,8 +45,7 @@ #include #include #include -#include -#include +#include #include #include "asus-wmi.h" diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 6dfa8d3b4eec..70d355a9ae2c 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -21,14 +21,13 @@ #include #include #include -#include +#include #include #include #include MODULE_LICENSE("GPL"); - struct cmpc_accel { int sensitivity; int g_select; diff --git a/drivers/platform/x86/dell-wmi-aio.c b/drivers/platform/x86/dell-wmi-aio.c index bcf8cc6b5537..dbc97a33bbc8 100644 --- a/drivers/platform/x86/dell-wmi-aio.c +++ b/drivers/platform/x86/dell-wmi-aio.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index fa9a2171cc13..bdf483babb43 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index aefcc32e5634..cabd56700cae 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -28,8 +28,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index af67e6e56ebb..6112933f6278 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "asus-wmi.h" diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index a8e43cf70fac..aff4d0670edf 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include "../../misc/lis3lv02d/lis3lv02d.h" #define DRIVER_NAME "hp_accel" diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 6788acc22ab9..70b57295d0a0 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -26,8 +26,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c index a2083a9e5662..d45bca34bf1b 100644 --- a/drivers/platform/x86/intel-rst.c +++ b/drivers/platform/x86/intel-rst.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel-smartconnect.c index 1838400dc036..04cf5dffdfd9 100644 --- a/drivers/platform/x86/intel-smartconnect.c +++ b/drivers/platform/x86/intel-smartconnect.c @@ -19,7 +19,7 @@ #include #include -#include +#include MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c index 11244f8703c4..e8b46d2c468c 100644 --- a/drivers/platform/x86/intel_menlow.c +++ b/drivers/platform/x86/intel_menlow.c @@ -36,10 +36,8 @@ #include #include #include - #include -#include -#include +#include MODULE_AUTHOR("Thomas Sujith"); MODULE_AUTHOR("Zhang Rui"); diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel_oaktrail.c index f6f18cde0f11..4bc960416785 100644 --- a/drivers/platform/x86/intel_oaktrail.c +++ b/drivers/platform/x86/intel_oaktrail.c @@ -50,9 +50,6 @@ #include #include #include -#include -#include - #define DRIVER_NAME "intel_oaktrail" #define DRIVER_VERSION "0.4ac1" diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c index 0aea63b3729a..3c59c0a3ee0f 100644 --- a/drivers/platform/x86/mxm-wmi.c +++ b/drivers/platform/x86/mxm-wmi.c @@ -20,8 +20,7 @@ #include #include #include -#include -#include +#include MODULE_AUTHOR("Dave Airlie"); MODULE_DESCRIPTION("MXM WMI Driver"); diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 10d12b221601..137d602395e8 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -125,12 +125,10 @@ #include #include #include -#include -#include +#include #include #include - #ifndef ACPI_HOTKEY_COMPONENT #define ACPI_HOTKEY_COMPONENT 0x10000000 #endif diff --git a/drivers/platform/x86/pvpanic.c b/drivers/platform/x86/pvpanic.c index 47ae0c47d4b5..c9f6e511daa6 100644 --- a/drivers/platform/x86/pvpanic.c +++ b/drivers/platform/x86/pvpanic.c @@ -24,8 +24,7 @@ #include #include #include -#include -#include +#include MODULE_AUTHOR("Hu Tao "); MODULE_DESCRIPTION("pvpanic device driver"); diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c index cae7098e9b0d..5413f62d2e61 100644 --- a/drivers/platform/x86/samsung-q10.c +++ b/drivers/platform/x86/samsung-q10.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #define SAMSUNGQ10_BL_MAX_INTENSITY 7 diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 47caab0ea7a1..1d00039de72a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -61,9 +61,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -71,6 +68,7 @@ #include #include #endif +#include #define dprintk(fmt, ...) \ do { \ diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index 9b93fdb61ed7..6a6ea28a7e51 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -32,9 +32,7 @@ #include #include #include -#include -#include -#include +#include #include #define GUID "C364AC71-36DB-495A-8494-B439D472A505" diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 05e046aa5e31..9d7e34b0109c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -61,7 +61,6 @@ #include #include #include - #include #include #include @@ -74,21 +73,16 @@ #include #include #include -#include - #include #include #include - +#include +#include +#include #include #include #include - -#include - -#include - -#include +#include /* ThinkPad CMOS commands */ #define TP_CMOS_VOLUME_DOWN 0 diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 0cfadb65f7c6..b5f17eb7ad2e 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -54,11 +54,9 @@ #include #include #include - +#include #include -#include - MODULE_AUTHOR("John Belmonte"); MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index 74dd01ae343b..2cb1ea62b4a7 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -23,14 +23,12 @@ #include #include #include -#include -#include +#include MODULE_AUTHOR("Jes Sorensen "); MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver"); MODULE_LICENSE("GPL"); - static int toshiba_bt_rfkill_add(struct acpi_device *device); static int toshiba_bt_rfkill_remove(struct acpi_device *device); static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event); diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 62e8c221d01e..ba13adea08b0 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include ACPI_MODULE_NAME("wmi"); MODULE_AUTHOR("Carlos Corbacho"); diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index 4b1377bd5944..49cbccec6e2d 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c @@ -18,8 +18,7 @@ #include #include #include -#include -#include +#include #define MODULE_NAME "xo15-ebook" diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 14655a0f0431..e869ba698ac0 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "../base.h" #include "pnpacpi.h" diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h index 3e60225b0227..051ef9699777 100644 --- a/drivers/pnp/pnpacpi/pnpacpi.h +++ b/drivers/pnp/pnpacpi/pnpacpi.h @@ -1,7 +1,6 @@ #ifndef ACPI_PNP_H #define ACPI_PNP_H -#include #include #include diff --git a/drivers/sfi/sfi_acpi.c b/drivers/sfi/sfi_acpi.c index f5b4ca581541..5e753d799f61 100644 --- a/drivers/sfi/sfi_acpi.c +++ b/drivers/sfi/sfi_acpi.c @@ -60,7 +60,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include -#include +#include /* FIXME: inclusion should be removed */ #include #include "sfi_core.h" diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 9f6ebdb23740..a85c3d68c462 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 4e243c37f17f..11c656976cb5 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -16,7 +16,6 @@ #include #include #include -#include #include "usb.h" diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c index 8dae6c13063a..cd5bb0a507a2 100644 --- a/drivers/xen/xen-acpi-cpuhotplug.c +++ b/drivers/xen/xen-acpi-cpuhotplug.c @@ -24,10 +24,7 @@ #include #include #include -#include -#include #include - #include #include #include diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c index 9083f1e474f8..f2872a1bb096 100644 --- a/drivers/xen/xen-acpi-memhotplug.c +++ b/drivers/xen/xen-acpi-memhotplug.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c index 59708fdd068b..40c4bc06b5fa 100644 --- a/drivers/xen/xen-acpi-pad.c +++ b/drivers/xen/xen-acpi-pad.c @@ -18,11 +18,10 @@ #include #include -#include -#include -#include +#include #include #include +#include #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 13bc6c31c060..7231859119f1 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c @@ -28,10 +28,8 @@ #include #include #include -#include -#include +#include #include - #include #include #include diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7b2de026a4f3..510119a63fb2 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -28,8 +28,6 @@ #include -#include - /* TBD: Make dynamic */ #define ACPI_MAX_HANDLES 10 struct acpi_handle_list { diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 1cedfcb1bd88..b124fdb26046 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -26,9 +26,6 @@ #ifndef __ACPI_DRIVERS_H__ #define __ACPI_DRIVERS_H__ -#include -#include - #define ACPI_MAX_STRING 80 /* diff --git a/include/linux/acpi_io.h b/include/linux/acpi_io.h index b0ffa219993e..2a5a1391ce72 100644 --- a/include/linux/acpi_io.h +++ b/include/linux/acpi_io.h @@ -2,7 +2,7 @@ #define _ACPI_IO_H_ #include -#include +#include /* FIXME: inclusion should be removed */ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) diff --git a/include/linux/ide.h b/include/linux/ide.h index 46a14229a162..93b5ca754b5b 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -18,14 +18,10 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_IDEACPI -#include -#endif -#include -#include - /* for request_sense */ #include +#include +#include #if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300) # define SUPPORT_VLB_SYNC 0 diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h index 8ba7e5b9d62c..82f9673c2527 100644 --- a/include/linux/iscsi_ibft.h +++ b/include/linux/iscsi_ibft.h @@ -21,7 +21,7 @@ #ifndef ISCSI_IBFT_H #define ISCSI_IBFT_H -#include +#include /* FIXME: inclusion should be removed */ /* * Logical location of iSCSI Boot Format Table. diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h index a2e2f1d17e16..5f2e559af6b0 100644 --- a/include/linux/pci_hotplug.h +++ b/include/linux/pci_hotplug.h @@ -175,8 +175,7 @@ struct hotplug_params { }; #ifdef CONFIG_ACPI -#include -#include +#include int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp); int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h index 631af63af42d..2cfcb7944a49 100644 --- a/include/linux/sfi_acpi.h +++ b/include/linux/sfi_acpi.h @@ -60,7 +60,7 @@ #define _LINUX_SFI_ACPI_H #ifdef CONFIG_SFI -#include /* struct acpi_table_header */ +#include /* FIXME: inclusion should be removed */ extern int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, diff --git a/include/linux/tboot.h b/include/linux/tboot.h index c75128bed5fa..9a54b331f938 100644 --- a/include/linux/tboot.h +++ b/include/linux/tboot.h @@ -34,7 +34,7 @@ enum { }; #ifdef CONFIG_INTEL_TXT -#include +#include /* used to communicate between tboot and the launched kernel */ #define TB_KEY_SIZE 64 /* 512 bits */ diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c index 66cace601e57..0f10b81e3322 100644 --- a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c +++ b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c @@ -25,12 +25,9 @@ #include #include #include - +#include #include -#include -#include - static int pm_tmr_ioport = 0; /*helper function to safely read acpi pm timesource*/ -- cgit v1.2.3 From d9fef0c4d2e08c3888add77f1dc54fb12afb3928 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Nov 2013 23:57:58 +0100 Subject: ACPI / bind: Simplify child device lookups Now that we create a struct acpi_device object for every ACPI namespace node representing a device, it is not necessary to use acpi_walk_namespace() for child device lookup in acpi_find_child() any more. Instead, we can simply walk the list of children of the given struct acpi_device object and return the matching one (or the one which is the best match if there are more of them). The checks done during the matching loop can be simplified too so that the secondary namespace walks in find_child_checks() are not necessary any more. Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu --- drivers/acpi/glue.c | 137 +++++++++++++++++++----------------------------- include/acpi/acpi_bus.h | 3 ++ 2 files changed, 58 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index a22a295edb69..ea77512ad70c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -82,107 +82,80 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) #define FIND_CHILD_MIN_SCORE 1 #define FIND_CHILD_MAX_SCORE 2 -static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_p) -{ - struct acpi_device *adev = NULL; - - acpi_bus_get_device(handle, &adev); - if (adev) { - *ret_p = handle; - return AE_CTRL_TERMINATE; - } - return AE_OK; -} - -static int do_find_child_checks(acpi_handle handle, bool is_bridge) +static int find_child_checks(struct acpi_device *adev, bool check_children) { bool sta_present = true; unsigned long long sta; acpi_status status; - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); if (status == AE_NOT_FOUND) sta_present = false; else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) return -ENODEV; - if (is_bridge) { - void *test = NULL; + if (check_children && list_empty(&adev->children)) + return -ENODEV; - /* Check if this object has at least one child device. */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, - acpi_dev_present, NULL, NULL, &test); - if (!test) - return -ENODEV; - } return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; } -struct find_child_context { - u64 addr; - bool is_bridge; - acpi_handle ret; - int ret_score; -}; - -static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, - void *data, void **not_used) +struct acpi_device *acpi_find_child_device(struct acpi_device *parent, + u64 address, bool check_children) { - struct find_child_context *context = data; - unsigned long long addr; - acpi_status status; - int score; - - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); - if (ACPI_FAILURE(status) || addr != context->addr) - return AE_OK; - - if (!context->ret) { - /* This is the first matching object. Save its handle. */ - context->ret = handle; - return AE_OK; - } - /* - * There is more than one matching object with the same _ADR value. - * That really is unexpected, so we are kind of beyond the scope of the - * spec here. We have to choose which one to return, though. - * - * First, check if the previously found object is good enough and return - * its handle if so. Second, check the same for the object that we've - * just found. - */ - if (!context->ret_score) { - score = do_find_child_checks(context->ret, context->is_bridge); - if (score == FIND_CHILD_MAX_SCORE) - return AE_CTRL_TERMINATE; - else - context->ret_score = score; - } - score = do_find_child_checks(handle, context->is_bridge); - if (score == FIND_CHILD_MAX_SCORE) { - context->ret = handle; - return AE_CTRL_TERMINATE; - } else if (score > context->ret_score) { - context->ret = handle; - context->ret_score = score; + struct acpi_device *adev, *ret = NULL; + int ret_score = 0; + + list_for_each_entry(adev, &parent->children, node) { + unsigned long long addr; + acpi_status status; + int score; + + status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR, + NULL, &addr); + if (ACPI_FAILURE(status) || addr != address) + continue; + + if (!ret) { + /* This is the first matching object. Save it. */ + ret = adev; + continue; + } + /* + * There is more than one matching device object with the same + * _ADR value. That really is unexpected, so we are kind of + * beyond the scope of the spec here. We have to choose which + * one to return, though. + * + * First, check if the previously found object is good enough + * and return it if so. Second, do the same for the object that + * we've just found. + */ + if (!ret_score) { + ret_score = find_child_checks(ret, check_children); + if (ret_score == FIND_CHILD_MAX_SCORE) + return ret; + } + score = find_child_checks(adev, check_children); + if (score == FIND_CHILD_MAX_SCORE) { + return adev; + } else if (score > ret_score) { + ret = adev; + ret_score = score; + } } - return AE_OK; + return ret; } -acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge) +acpi_handle acpi_find_child(acpi_handle handle, u64 addr, bool is_bridge) { - if (parent) { - struct find_child_context context = { - .addr = addr, - .is_bridge = is_bridge, - }; - - acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child, - NULL, &context, NULL); - return context.ret; - } - return NULL; + struct acpi_device *adev; + + if (!handle || acpi_bus_get_device(handle, &adev)) + return NULL; + + adev = acpi_find_child_device(adev, addr, is_bridge); + return adev ? adev->handle : NULL; } EXPORT_SYMBOL_GPL(acpi_find_child); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index b241b733052e..6d82c5c14c0f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -431,6 +431,9 @@ struct acpi_pci_root { }; /* helper */ + +struct acpi_device *acpi_find_child_device(struct acpi_device *parent, + u64 address, bool check_children); acpi_handle acpi_find_child(acpi_handle, u64, bool); static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr) { -- cgit v1.2.3 From 5ce79d201358d36f13d13b01d8614bd8e646036c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Nov 2013 23:58:08 +0100 Subject: PCI / ACPI: Use acpi_find_child_device() for child devices lookup It is much more efficient to use acpi_find_child_device() for child devices lookup in acpi_pci_find_device() and pass ACPI_COMPANION(dev->parent) to it directly instead of obtaining ACPI_HANDLE() of ACPI_COMPANION(dev->parent) and passing it to acpi_find_child() which has to run acpi_bus_get_device() to obtain ACPI_COMPANION(dev->parent) from that again. Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu --- drivers/acpi/glue.c | 3 +++ drivers/pci/pci-acpi.c | 16 ++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index ea77512ad70c..9d200d5029ca 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -106,6 +106,9 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent, struct acpi_device *adev, *ret = NULL; int ret_score = 0; + if (!parent) + return NULL; + list_for_each_entry(adev, &parent->children, node) { unsigned long long addr; acpi_status status; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 43e317991326..adbf34003995 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -306,7 +306,8 @@ void acpi_pci_remove_bus(struct pci_bus *bus) static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { struct pci_dev *pci_dev = to_pci_dev(dev); - bool is_bridge; + struct acpi_device *adev; + bool check_children; u64 addr; /* @@ -314,14 +315,17 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) * is set only after acpi_pci_find_device() has been called for the * given device. */ - is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE + check_children = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS; /* Please ref to ACPI spec for the syntax of _ADR */ addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); - *handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge); - if (!*handle) - return -ENODEV; - return 0; + adev = acpi_find_child_device(ACPI_COMPANION(dev->parent), addr, + check_children); + if (adev) { + *handle = adev->handle; + return 0; + } + return -ENODEV; } static void pci_acpi_setup(struct device *dev) -- cgit v1.2.3 From 11dcc75dba5bf8b69c4612de10e366c4e04cb123 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Nov 2013 23:58:18 +0100 Subject: ACPI / bind: Redefine acpi_get_child() Since acpi_get_child() is the only user of acpi_find_child() now, drop the static inline definition of the former and redefine the latter as new acpi_get_child(). Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu Tested-by: Aaron Lu # for ATA binding --- drivers/acpi/glue.c | 6 +++--- include/acpi/acpi_bus.h | 6 +----- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 9d200d5029ca..12b2acbaa116 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -150,17 +150,17 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent, return ret; } -acpi_handle acpi_find_child(acpi_handle handle, u64 addr, bool is_bridge) +acpi_handle acpi_get_child(acpi_handle handle, u64 addr) { struct acpi_device *adev; if (!handle || acpi_bus_get_device(handle, &adev)) return NULL; - adev = acpi_find_child_device(adev, addr, is_bridge); + adev = acpi_find_child_device(adev, addr, false); return adev ? adev->handle : NULL; } -EXPORT_SYMBOL_GPL(acpi_find_child); +EXPORT_SYMBOL_GPL(acpi_get_child); static void acpi_physnode_link_name(char *buf, unsigned int node_id) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6d82c5c14c0f..a1a48f27933a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -434,11 +434,7 @@ struct acpi_pci_root { struct acpi_device *acpi_find_child_device(struct acpi_device *parent, u64 address, bool check_children); -acpi_handle acpi_find_child(acpi_handle, u64, bool); -static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr) -{ - return acpi_find_child(handle, addr, false); -} +acpi_handle acpi_get_child(acpi_handle handle, u64 addr); void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr); int acpi_is_root_bridge(acpi_handle); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); -- cgit v1.2.3 From 9c5ad36d987a1b06f6b0b9dc7bc61a45d277455d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Nov 2013 23:58:28 +0100 Subject: ACPI / bind: Redefine acpi_preset_companion() Modify acpi_preset_companion() to take a struct acpi_device pointer instead of an ACPI handle as its second argument and redefine it as a static inline wrapper around ACPI_COMPANION_SET() passing the return value of acpi_find_child_device() directly as the second argument to it. Update its users to pass struct acpi_device pointers instead of ACPI handles to it. This allows some unnecessary acpi_bus_get_device() calls to be avoided. Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu Tested-by: Aaron Lu # for ATA binding --- drivers/acpi/glue.c | 10 +--------- drivers/ata/libata-acpi.c | 26 +++++++++++++------------- drivers/mmc/core/sdio_bus.c | 2 +- include/acpi/acpi_bus.h | 1 - include/linux/acpi.h | 6 ++++++ 5 files changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 12b2acbaa116..c0d18b2145c1 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -149,6 +149,7 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent, } return ret; } +EXPORT_SYMBOL_GPL(acpi_find_child_device); acpi_handle acpi_get_child(acpi_handle handle, u64 addr) { @@ -298,15 +299,6 @@ int acpi_unbind_one(struct device *dev) } EXPORT_SYMBOL_GPL(acpi_unbind_one); -void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr) -{ - struct acpi_device *adev; - - if (!acpi_bus_get_device(acpi_get_child(parent, addr), &adev)) - ACPI_COMPANION_SET(dev, adev); -} -EXPORT_SYMBOL_GPL(acpi_preset_companion); - static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type = acpi_get_bus_type(dev); diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 8e22d9762328..9e69a5308693 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -178,12 +178,12 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { /* bind acpi handle to pata port */ void ata_acpi_bind_port(struct ata_port *ap) { - acpi_handle host_handle = ACPI_HANDLE(ap->host->dev); + struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); - if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_handle) + if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) return; - acpi_preset_companion(&ap->tdev, host_handle, ap->port_no); + acpi_preset_companion(&ap->tdev, host_companion, ap->port_no); if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; @@ -196,17 +196,17 @@ void ata_acpi_bind_port(struct ata_port *ap) void ata_acpi_bind_dev(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; - acpi_handle port_handle = ACPI_HANDLE(&ap->tdev); - acpi_handle host_handle = ACPI_HANDLE(ap->host->dev); - acpi_handle parent_handle; + struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); + struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); + struct acpi_device *parent; u64 adr; /* - * For both sata/pata devices, host handle is required. - * For pata device, port handle is also required. + * For both sata/pata devices, host companion device is required. + * For pata device, port companion device is also required. */ - if (libata_noacpi || !host_handle || - (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_handle)) + if (libata_noacpi || !host_companion || + (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_companion)) return; if (ap->flags & ATA_FLAG_ACPI_SATA) { @@ -214,13 +214,13 @@ void ata_acpi_bind_dev(struct ata_device *dev) adr = SATA_ADR(ap->port_no, NO_PORT_MULT); else adr = SATA_ADR(ap->port_no, dev->link->pmp); - parent_handle = host_handle; + parent = host_companion; } else { adr = dev->devno; - parent_handle = port_handle; + parent = port_companion; } - acpi_preset_companion(&dev->tdev, parent_handle, adr); + acpi_preset_companion(&dev->tdev, parent, adr); register_hotplug_dock_device(ata_dev_acpi_handle(dev), &ata_acpi_dev_dock_ops, dev, NULL, NULL); diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 157b570ba343..92d1ba8e8153 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -308,7 +308,7 @@ static void sdio_acpi_set_handle(struct sdio_func *func) struct mmc_host *host = func->card->host; u64 addr = (host->slotno << 16) | func->num; - acpi_preset_companion(&func->dev, ACPI_HANDLE(host->parent), addr); + acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr); } #else static inline void sdio_acpi_set_handle(struct sdio_func *func) {} diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a1a48f27933a..918eaab892e1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -435,7 +435,6 @@ struct acpi_pci_root { struct acpi_device *acpi_find_child_device(struct acpi_device *parent, u64 address, bool check_children); acpi_handle acpi_get_child(acpi_handle handle, u64 addr); -void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr); int acpi_is_root_bridge(acpi_handle); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d9099b15b472..115c610324d1 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -53,6 +53,12 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) #define ACPI_COMPANION_SET(dev, adev) ACPI_COMPANION(dev) = (adev) #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) +static inline void acpi_preset_companion(struct device *dev, + struct acpi_device *parent, u64 addr) +{ + ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, NULL)); +} + static inline const char *acpi_dev_name(struct acpi_device *adev) { return dev_name(&adev->dev); -- cgit v1.2.3 From e3f02c5228c4b600abf6ca243301176f25553bd5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 29 Nov 2013 16:27:34 +0100 Subject: ACPI / bind: Rework struct acpi_bus_type Replace the .find_device function pointer in struct acpi_bus_type with a new one, .find_companion, that is supposed to point to a function returning struct acpi_device pointer (instead of an int) and takes one argument (instead of two). This way the role of this callback is more clear and the implementation of it can be more straightforward. Update all of the users of struct acpi_bus_type (PCI, PNP/ACPI and USB) to reflect the structure change. Signed-off-by: Rafael J. Wysocki Tested-by: Lan Tianyu # for USB/ACPI --- drivers/acpi/glue.c | 12 +++++++----- drivers/pci/pci-acpi.c | 12 +++--------- drivers/pnp/pnpacpi/core.c | 21 ++++++++------------- drivers/usb/core/usb-acpi.c | 40 ++++++++++++++++++++-------------------- include/acpi/acpi_bus.h | 2 +- 5 files changed, 39 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index c0d18b2145c1..7608d66f289b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -37,7 +37,7 @@ int register_acpi_bus_type(struct acpi_bus_type *type) { if (acpi_disabled) return -ENODEV; - if (type && type->match && type->find_device) { + if (type && type->match && type->find_companion) { down_write(&bus_type_sem); list_add_tail(&type->list, &bus_type_list); up_write(&bus_type_sem); @@ -302,17 +302,19 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one); static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type = acpi_get_bus_type(dev); - acpi_handle handle; int ret; ret = acpi_bind_one(dev, NULL); if (ret && type) { - ret = type->find_device(dev, &handle); - if (ret) { + struct acpi_device *adev; + + adev = type->find_companion(dev); + if (!adev) { DBG("Unable to get handle for %s\n", dev_name(dev)); + ret = -ENODEV; goto out; } - ret = acpi_bind_one(dev, handle); + ret = acpi_bind_one(dev, adev->handle); if (ret) goto out; } diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index adbf34003995..ce31eb0cdca7 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -303,10 +303,9 @@ void acpi_pci_remove_bus(struct pci_bus *bus) } /* ACPI bus type */ -static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) +static struct acpi_device *acpi_pci_find_companion(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct acpi_device *adev; bool check_children; u64 addr; @@ -319,13 +318,8 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS; /* Please ref to ACPI spec for the syntax of _ADR */ addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); - adev = acpi_find_child_device(ACPI_COMPANION(dev->parent), addr, + return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr, check_children); - if (adev) { - *handle = adev->handle; - return 0; - } - return -ENODEV; } static void pci_acpi_setup(struct device *dev) @@ -365,7 +359,7 @@ static bool pci_acpi_bus_match(struct device *dev) static struct acpi_bus_type acpi_pci_bus = { .name = "PCI", .match = pci_acpi_bus_match, - .find_device = acpi_pci_find_device, + .find_companion = acpi_pci_find_companion, .setup = pci_acpi_setup, .cleanup = pci_acpi_cleanup, }; diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index e869ba698ac0..156d14e2587e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -328,20 +328,15 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp) && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); } -static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) +static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev) { - struct device *adev; - struct acpi_device *acpi; - - adev = bus_find_device(&acpi_bus_type, NULL, - to_pnp_dev(dev), acpi_pnp_match); - if (!adev) - return -ENODEV; + dev = bus_find_device(&acpi_bus_type, NULL, to_pnp_dev(dev), + acpi_pnp_match); + if (!dev) + return NULL; - acpi = to_acpi_device(adev); - *handle = acpi->handle; - put_device(adev); - return 0; + put_device(dev); + return to_acpi_device(dev); } /* complete initialization of a PNPACPI device includes having @@ -355,7 +350,7 @@ static bool acpi_pnp_bus_match(struct device *dev) static struct acpi_bus_type __initdata acpi_pnp_bus = { .name = "PNP", .match = acpi_pnp_bus_match, - .find_device = acpi_pnp_find_device, + .find_companion = acpi_pnp_find_companion, }; int pnpacpi_disabled __initdata; diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 11c656976cb5..f0155a39aaa3 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -126,7 +126,7 @@ out: return ret; } -static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) +static struct acpi_device *usb_acpi_find_companion(struct device *dev) { struct usb_device *udev; acpi_handle *parent_handle; @@ -168,16 +168,15 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) break; } - return -ENODEV; + return NULL; } /* root hub's parent is the usb hcd. */ - parent_handle = ACPI_HANDLE(dev->parent); - *handle = acpi_get_child(parent_handle, udev->portnum); - if (!*handle) - return -ENODEV; - return 0; + return acpi_find_child_device(ACPI_COMPANION(dev->parent), + udev->portnum, false); } else if (is_usb_port(dev)) { + struct acpi_device *adev = NULL; + sscanf(dev_name(dev), "port%d", &port_num); /* Get the struct usb_device point of port's hub */ udev = to_usb_device(dev->parent->parent); @@ -193,26 +192,27 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) raw_port_num = usb_hcd_find_raw_port_number(hcd, port_num); - *handle = acpi_get_child(ACPI_HANDLE(&udev->dev), - raw_port_num); - if (!*handle) - return -ENODEV; + adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev), + raw_port_num, false); + if (!adev) + return NULL; } else { parent_handle = usb_get_hub_port_acpi_handle(udev->parent, udev->portnum); if (!parent_handle) - return -ENODEV; + return NULL; - *handle = acpi_get_child(parent_handle, port_num); - if (!*handle) - return -ENODEV; + acpi_bus_get_device(parent_handle, &adev); + adev = acpi_find_child_device(adev, port_num, false); + if (!adev) + return NULL; } - usb_acpi_check_port_connect_type(udev, *handle, port_num); - } else - return -ENODEV; + usb_acpi_check_port_connect_type(udev, adev->handle, port_num); + return adev; + } - return 0; + return NULL; } static bool usb_acpi_bus_match(struct device *dev) @@ -223,7 +223,7 @@ static bool usb_acpi_bus_match(struct device *dev) static struct acpi_bus_type usb_acpi_bus = { .name = "USB", .match = usb_acpi_bus_match, - .find_device = usb_acpi_find_device, + .find_companion = usb_acpi_find_companion, }; int usb_acpi_register(void) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 918eaab892e1..a50898e67a68 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -412,7 +412,7 @@ struct acpi_bus_type { struct list_head list; const char *name; bool (*match)(struct device *dev); - int (*find_device) (struct device *, acpi_handle *); + struct acpi_device * (*find_companion)(struct device *); void (*setup)(struct device *); void (*cleanup)(struct device *); }; -- cgit v1.2.3 From 24dee1fc99fd6d38fc859d7f6dda1dab21493bef Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 29 Nov 2013 16:27:43 +0100 Subject: ACPI / bind: Pass struct acpi_device pointer to acpi_bind_one() There is no reason to pass an ACPI handle to acpi_bind_one() instead of a struct acpi_device pointer to the target device object, so modify that function to take a struct acpi_device pointer as its second argument and update all code depending on it accordingly. Signed-off-by: Rafael J. Wysocki Tested-by: Lan Tianyu # for USB/ACPI --- drivers/acpi/acpi_memhotplug.c | 15 +++++++-------- drivers/acpi/acpi_processor.c | 2 +- drivers/acpi/glue.c | 9 +++------ drivers/acpi/internal.h | 2 +- 4 files changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 551dad712ffe..9aeacdfca410 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -180,14 +180,14 @@ static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info) static int acpi_bind_memblk(struct memory_block *mem, void *arg) { - return acpi_bind_one(&mem->dev, (acpi_handle)arg); + return acpi_bind_one(&mem->dev, arg); } static int acpi_bind_memory_blocks(struct acpi_memory_info *info, - acpi_handle handle) + struct acpi_device *adev) { return walk_memory_range(acpi_meminfo_start_pfn(info), - acpi_meminfo_end_pfn(info), (void *)handle, + acpi_meminfo_end_pfn(info), adev, acpi_bind_memblk); } @@ -197,8 +197,7 @@ static int acpi_unbind_memblk(struct memory_block *mem, void *arg) return 0; } -static void acpi_unbind_memory_blocks(struct acpi_memory_info *info, - acpi_handle handle) +static void acpi_unbind_memory_blocks(struct acpi_memory_info *info) { walk_memory_range(acpi_meminfo_start_pfn(info), acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk); @@ -242,9 +241,9 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) if (result && result != -EEXIST) continue; - result = acpi_bind_memory_blocks(info, handle); + result = acpi_bind_memory_blocks(info, mem_device->device); if (result) { - acpi_unbind_memory_blocks(info, handle); + acpi_unbind_memory_blocks(info); return -ENODEV; } @@ -285,7 +284,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device) if (nid == NUMA_NO_NODE) nid = memory_add_physaddr_to_nid(info->start_addr); - acpi_unbind_memory_blocks(info, handle); + acpi_unbind_memory_blocks(info); remove_memory(nid, info->start_addr, info->length); list_del(&info->list); kfree(info); diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 3c1d6b0c09a4..d58a2aba0930 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -395,7 +395,7 @@ static int acpi_processor_add(struct acpi_device *device, goto err; } - result = acpi_bind_one(dev, pr->handle); + result = acpi_bind_one(dev, device); if (result) goto err; diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 7608d66f289b..896351b9d483 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -172,9 +172,8 @@ static void acpi_physnode_link_name(char *buf, unsigned int node_id) strcpy(buf, PHYSICAL_NODE_STRING); } -int acpi_bind_one(struct device *dev, acpi_handle handle) +int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev) { - struct acpi_device *acpi_dev = NULL; struct acpi_device_physical_node *physical_node, *pn; char physical_node_name[PHYSICAL_NODE_NAME_SIZE]; struct list_head *physnode_list; @@ -182,14 +181,12 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) int retval = -EINVAL; if (ACPI_COMPANION(dev)) { - if (handle) { + if (acpi_dev) { dev_warn(dev, "ACPI companion already set\n"); return -EINVAL; } else { acpi_dev = ACPI_COMPANION(dev); } - } else { - acpi_bus_get_device(handle, &acpi_dev); } if (!acpi_dev) return -EINVAL; @@ -314,7 +311,7 @@ static int acpi_platform_notify(struct device *dev) ret = -ENODEV; goto out; } - ret = acpi_bind_one(dev, adev->handle); + ret = acpi_bind_one(dev, adev); if (ret) goto out; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index f4aa467c407e..b125fdb0b30c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -86,7 +86,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, int type, unsigned long long sta); void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); -int acpi_bind_one(struct device *dev, acpi_handle handle); +int acpi_bind_one(struct device *dev, struct acpi_device *adev); int acpi_unbind_one(struct device *dev); bool acpi_device_is_present(struct acpi_device *adev); -- cgit v1.2.3 From bfecc2b3e34c6751343bacd317c4dfd1d695142c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 29 Nov 2013 16:27:53 +0100 Subject: ACPI / bind: Move acpi_get_child() to drivers/ide/ide-acpi.c Since drivers/ide/ide-acpi.c is the only remaining user of acpi_get_child(), move that function into that file as a static routine. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/glue.c | 12 ------------ drivers/ide/ide-acpi.c | 11 +++++++++++ include/acpi/acpi_bus.h | 1 - 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 896351b9d483..0c789224d40d 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -151,18 +151,6 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent, } EXPORT_SYMBOL_GPL(acpi_find_child_device); -acpi_handle acpi_get_child(acpi_handle handle, u64 addr) -{ - struct acpi_device *adev; - - if (!handle || acpi_bus_get_device(handle, &adev)) - return NULL; - - adev = acpi_find_child_device(adev, addr, false); - return adev ? adev->handle : NULL; -} -EXPORT_SYMBOL_GPL(acpi_get_child); - static void acpi_physnode_link_name(char *buf, unsigned int node_id) { if (node_id > 0) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 333d4053e727..b6940992a6ff 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -97,6 +97,17 @@ bool ide_port_acpi(ide_hwif_t *hwif) return ide_noacpi == 0 && hwif->acpidata; } +static acpi_handle acpi_get_child(acpi_handle handle, u64 addr) +{ + struct acpi_device *adev; + + if (!handle || acpi_bus_get_device(handle, &adev)) + return NULL; + + adev = acpi_find_child_device(adev, addr, false); + return adev ? adev->handle : NULL; +} + /** * ide_get_dev_handle - finds acpi_handle and PCI device.function * @dev: device to locate diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a50898e67a68..7135fe3d6daa 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -434,7 +434,6 @@ struct acpi_pci_root { struct acpi_device *acpi_find_child_device(struct acpi_device *parent, u64 address, bool check_children); -acpi_handle acpi_get_child(acpi_handle handle, u64 addr); int acpi_is_root_bridge(acpi_handle); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); -- cgit v1.2.3 From 8a4949200812b865a8c101958bdde1b7f8cdd020 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 20 Nov 2013 10:02:49 +0000 Subject: i40e: check multi-bit state correctly The hash is reported correctly in the rss field if and only if the filter status is 3. Other values of filter status mean different things and we shouldn't depend on a bitwise result. The issue was that a & b --> returns true for b={1,2,3} the fix is a & b == b Also refactor this function to use constant operations because we are in fast path. Change-Id: I4e29be87439c1cf8b60bc31bea29dff89596c013 Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index f1f03bc5c729..01d0334fa926 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -891,13 +891,15 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, static inline u32 i40e_rx_hash(struct i40e_ring *ring, union i40e_rx_desc *rx_desc) { - if (ring->netdev->features & NETIF_F_RXHASH) { - if ((le64_to_cpu(rx_desc->wb.qword1.status_error_len) >> - I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) & - I40E_RX_DESC_FLTSTAT_RSS_HASH) - return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); - } - return 0; + const __le64 rss_mask = + cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH << + I40E_RX_DESC_STATUS_FLTSTAT_SHIFT); + + if ((ring->netdev->features & NETIF_F_RXHASH) && + (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) + return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); + else + return 0; } /** -- cgit v1.2.3 From be405eb0e47f1ee027e9c0e1087129fb29b7bc08 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 20 Nov 2013 10:02:50 +0000 Subject: i40e: get media type during link info Set the media type in the hardware structure, based on the external connection type. Add Direct Attach to the type of media reported by ethtool. Change-Id: I4ad2f5bf882766d6e737fac4477abf049491b3b3 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 47 ++++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 +++ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + 3 files changed, 52 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 9e868eac8e1e..2cc01c21681a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -266,6 +266,52 @@ i40e_status i40e_validate_mac_addr(u8 *mac_addr) return status; } +/** + * i40e_get_media_type - Gets media type + * @hw: pointer to the hardware structure + **/ +static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) +{ + enum i40e_media_type media; + + switch (hw->phy.link_info.phy_type) { + case I40E_PHY_TYPE_10GBASE_SR: + case I40E_PHY_TYPE_10GBASE_LR: + case I40E_PHY_TYPE_40GBASE_SR4: + case I40E_PHY_TYPE_40GBASE_LR4: + media = I40E_MEDIA_TYPE_FIBER; + break; + case I40E_PHY_TYPE_100BASE_TX: + case I40E_PHY_TYPE_1000BASE_T: + case I40E_PHY_TYPE_10GBASE_T: + media = I40E_MEDIA_TYPE_BASET; + break; + case I40E_PHY_TYPE_10GBASE_CR1_CU: + case I40E_PHY_TYPE_40GBASE_CR4_CU: + case I40E_PHY_TYPE_10GBASE_CR1: + case I40E_PHY_TYPE_40GBASE_CR4: + case I40E_PHY_TYPE_10GBASE_SFPP_CU: + media = I40E_MEDIA_TYPE_DA; + break; + case I40E_PHY_TYPE_1000BASE_KX: + case I40E_PHY_TYPE_10GBASE_KX4: + case I40E_PHY_TYPE_10GBASE_KR: + case I40E_PHY_TYPE_40GBASE_KR4: + media = I40E_MEDIA_TYPE_BACKPLANE; + break; + case I40E_PHY_TYPE_SGMII: + case I40E_PHY_TYPE_XAUI: + case I40E_PHY_TYPE_XFI: + case I40E_PHY_TYPE_XLAUI: + case I40E_PHY_TYPE_XLPPI: + default: + media = I40E_MEDIA_TYPE_UNKNOWN; + break; + } + + return media; +} + /** * i40e_pf_reset - Reset the PF * @hw: pointer to the hardware structure @@ -499,6 +545,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, /* update link status */ hw_link_info->phy_type = (enum i40e_aq_phy_type)resp->phy_type; + hw->phy.media_type = i40e_get_media_type(hw); hw_link_info->link_speed = (enum i40e_aq_link_speed)resp->link_speed; hw_link_info->link_info = resp->link_info; hw_link_info->an_info = resp->an_info; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 8f5d538c11c3..7fb669bd0472 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -211,6 +211,10 @@ static int i40e_get_settings(struct net_device *netdev, ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; + } else if (hw->phy.media_type == I40E_MEDIA_TYPE_DA) { + ecmd->supported |= SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_FIBRE; + ecmd->port = PORT_DA; } else { ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index fdad028f3321..88b37e07b255 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -134,6 +134,7 @@ enum i40e_media_type { I40E_MEDIA_TYPE_BASET, I40E_MEDIA_TYPE_BACKPLANE, I40E_MEDIA_TYPE_CX4, + I40E_MEDIA_TYPE_DA, I40E_MEDIA_TYPE_VIRTUAL }; -- cgit v1.2.3 From fe5e49cb5ac57f984a44287cf123fbbc712d7bec Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 6 Dec 2013 16:51:46 +0800 Subject: ACPI: Clean up incorrect inclusion of an ACPICA header Since drivers/acpi/nvs.c includes and is only compiled for CONFIG_ACPI set, it doesn't need to include directly, which is formally incorrect. Remove the inclusion from that file. Signed-off-by: Lv Zheng [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/nvs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 266bc58ce0ce..386a9fe497b4 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c @@ -13,7 +13,6 @@ #include #include #include -#include /* ACPI NVS regions, APEI may use it */ -- cgit v1.2.3 From c099eacbcaec4475936fbf73e499507728ce47e1 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 6 Dec 2013 16:51:59 +0800 Subject: SFI / ACPI: Fix warnings reported during builds with W=1 The following warnings can be seen in W=1 builds, because the original sfi_acpi.[ch] header inclusions are incorrect: include/linux/sfi_acpi.h:72:2: error: implicit declaration of function 'acpi_table_parse' [-Werror=implicit-function-declaration] drivers/sfi/sfi_acpi.c:154:5: warning: no previous prototype for 'sfi_acpi_table_parse' [-Wmissing-prototypes] Fix linux/sfi_acpi.h and modify drivers/sfi/sfi_acpi.c accordingly. Reported-by: Andy Shevchenko Signed-off-by: Lv Zheng [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- arch/x86/pci/mmconfig-shared.c | 1 - drivers/sfi/sfi_acpi.c | 4 +--- include/linux/sfi_acpi.h | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 082e88129712..248642f4bab7 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/sfi/sfi_acpi.c b/drivers/sfi/sfi_acpi.c index 5e753d799f61..d277b36eb389 100644 --- a/drivers/sfi/sfi_acpi.c +++ b/drivers/sfi/sfi_acpi.c @@ -60,9 +60,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include -#include /* FIXME: inclusion should be removed */ - -#include +#include #include "sfi_core.h" /* diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h index 2cfcb7944a49..4723bbfa1c26 100644 --- a/include/linux/sfi_acpi.h +++ b/include/linux/sfi_acpi.h @@ -59,6 +59,9 @@ #ifndef _LINUX_SFI_ACPI_H #define _LINUX_SFI_ACPI_H +#include +#include + #ifdef CONFIG_SFI #include /* FIXME: inclusion should be removed */ -- cgit v1.2.3 From 27d50c82714f6477ac690034b37d202f76eb4f70 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 6 Dec 2013 16:52:05 +0800 Subject: ACPI / i915: Fix incorrect inclusions via To avoid build problems and breaking dependencies between ACPI header files, should not be included directly by code outside of the ACPI core subsystem. However, that is possible if is included, because that file contains a direct inclusion of . For this reason, remove the direct inclusion from , move that file from include/linux/ to include/acpi/ and make include it for CONFIG_ACPI set along with the other ACPI header files. Accordingly, Remove the inclusions of from everywhere. Of course, that causes the contents of the new file to be available for CONFIG_ACPI set only, so intel_opregion.o that depends on it should also depend on CONFIG_ACPI (and it really should not be compiled for CONFIG_ACPI unset anyway). References: https://01.org/linuxgraphics/sites/default/files/documentation/acpi_igd_opregion_spec.pdf Cc: Matthew Garrett Signed-off-by: Lv Zheng Acked-by: Daniel Vetter [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/apei/apei-base.c | 1 - drivers/acpi/apei/apei-internal.h | 1 - drivers/acpi/apei/ghes.c | 1 - drivers/acpi/nvs.c | 1 - drivers/acpi/osl.c | 1 - drivers/gpu/drm/gma500/opregion.c | 1 - drivers/gpu/drm/i915/Makefile | 3 +-- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_opregion.c | 1 - include/acpi/acpi_io.h | 17 +++++++++++++++++ include/linux/acpi.h | 1 + include/linux/acpi_io.h | 18 ------------------ 12 files changed, 21 insertions(+), 28 deletions(-) create mode 100644 include/acpi/acpi_io.h delete mode 100644 include/linux/acpi_io.h (limited to 'drivers') diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 6d2c49b86b7f..0760b75f79cc 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index 21ba34a73883..e5bcd919d4e6 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -8,7 +8,6 @@ #include #include -#include struct apei_exec_context; diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index a30bc313787b..694c486a12ed 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 386a9fe497b4..ef28613d5192 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c @@ -12,7 +12,6 @@ #include #include #include -#include /* ACPI NVS regions, APEI may use it */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 244be2affea7..064b8b365060 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index ad0d6de938f3..13ec6283bf59 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c @@ -22,7 +22,6 @@ * */ #include -#include #include "psb_drv.h" #include "psb_intel_reg.h" diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 41838eaa799c..d4ae48b04cf2 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -38,7 +38,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ intel_ringbuffer.o \ intel_overlay.o \ intel_sprite.o \ - intel_opregion.o \ intel_sideband.o \ intel_uncore.o \ dvo_ch7xxx.o \ @@ -51,7 +50,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ i915-$(CONFIG_COMPAT) += i915_ioc32.o -i915-$(CONFIG_ACPI) += intel_acpi.o +i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccdbecca070d..7f37b838802e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2336,8 +2336,8 @@ extern void intel_i2c_reset(struct drm_device *dev); /* intel_opregion.c */ struct intel_encoder; -extern int intel_opregion_setup(struct drm_device *dev); #ifdef CONFIG_ACPI +extern int intel_opregion_setup(struct drm_device *dev); extern void intel_opregion_init(struct drm_device *dev); extern void intel_opregion_fini(struct drm_device *dev); extern void intel_opregion_asle_intr(struct drm_device *dev); @@ -2346,6 +2346,7 @@ extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, extern int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state); #else +static inline int intel_opregion_setup(struct drm_device *dev) { return 0; } static inline void intel_opregion_init(struct drm_device *dev) { return; } static inline void intel_opregion_fini(struct drm_device *dev) { return; } static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; } diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 6d69a9bad865..9a8804bee5cd 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -28,7 +28,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include diff --git a/include/acpi/acpi_io.h b/include/acpi/acpi_io.h new file mode 100644 index 000000000000..2be858018c7f --- /dev/null +++ b/include/acpi/acpi_io.h @@ -0,0 +1,17 @@ +#ifndef _ACPI_IO_H_ +#define _ACPI_IO_H_ + +#include + +static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, + acpi_size size) +{ + return ioremap_cache(phys, size); +} + +void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); + +int acpi_os_map_generic_address(struct acpi_generic_address *addr); +void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); + +#endif diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d9099b15b472..726a6aa62b64 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -42,6 +42,7 @@ #include #include #include +#include #include static inline acpi_handle acpi_device_handle(struct acpi_device *adev) diff --git a/include/linux/acpi_io.h b/include/linux/acpi_io.h deleted file mode 100644 index 2a5a1391ce72..000000000000 --- a/include/linux/acpi_io.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _ACPI_IO_H_ -#define _ACPI_IO_H_ - -#include -#include /* FIXME: inclusion should be removed */ - -static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, - acpi_size size) -{ - return ioremap_cache(phys, size); -} - -void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size); - -int acpi_os_map_generic_address(struct acpi_generic_address *addr); -void acpi_os_unmap_generic_address(struct acpi_generic_address *addr); - -#endif -- cgit v1.2.3 From 9d24622ced329e35e2349ef419355a87d94be61f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 6 Dec 2013 16:52:19 +0800 Subject: ACPI / IBFT: Fix incorrect inclusion in iSCSI boot firmware module To avoid build problems and breaking dependencies between ACPI header files, should not be included directly by code outside of the ACPI core subsystem, but this is done by the ACPI iSCSI Boot Firmware code. The iBFT specification doesn't mention whether or not it can appear on a non-ACPI platform, but is says that ACPI 3.0b defines the mechanism. The current CONFIG_ISCSI_IBFT_FIND code doesn't use the ACPI tables API to locate the table, so it doesn't rely on CONFIG_ACPI directly. However, since iBFT is is an ACPI-based mechanism (please refer to the documentation link below for more information), it should be correct to make CONFIG_ISCSI_IBFT_FIND depend on CONFIG_ACPI (even though the table location can be implemented without using ACPI tables API). After that change, include/linux/iscsi_ibft.h can be modified to include instead of as appropriate. References: http://www.microsoft.com/whdc/system/platform/firmware/ibft.mspx Cc: Konrad Rzeszutek Wilk Cc: Peter Jones Signed-off-by: Lv Zheng [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/firmware/Kconfig | 2 +- include/linux/iscsi_ibft.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 074787281c94..a6ef6acaa1c8 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -110,7 +110,7 @@ config DMI_SYSFS config ISCSI_IBFT_FIND bool "iSCSI Boot Firmware Table Attributes" - depends on X86 + depends on X86 && ACPI default n help This option enables the kernel to find the region of memory diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h index 82f9673c2527..605cc5c333d9 100644 --- a/include/linux/iscsi_ibft.h +++ b/include/linux/iscsi_ibft.h @@ -21,7 +21,7 @@ #ifndef ISCSI_IBFT_H #define ISCSI_IBFT_H -#include /* FIXME: inclusion should be removed */ +#include /* * Logical location of iSCSI Boot Format Table. -- cgit v1.2.3 From e1c51b9586759d2ceaa0cdcddbe648d765accf04 Mon Sep 17 00:00:00 2001 From: Kevin Scott Date: Wed, 20 Nov 2013 10:02:51 +0000 Subject: i40e: Add flag for L2 VEB filtering Add a new flag to the add VEB command which allows the driver to request the hardware to filter on L2 parameters. This is an implementation of the driver access to a new firmware feature. Change-Id: Id61d3cad4125bdc68b8fd9d555c448a10c344b6b Signed-off-by: Kevin Scott Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 8 +++++++- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +++- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 2cc01c21681a..1300d3d0aac4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -924,6 +924,7 @@ i40e_get_link_status_exit: * @downlink_seid: the VSI SEID * @enabled_tc: bitmap of TCs to be enabled * @default_port: true for default port VSI, false for control port + * @enable_l2_filtering: true to add L2 filter table rules to regular forwarding rules for cloud support * @veb_seid: pointer to where to put the resulting VEB SEID * @cmd_details: pointer to command details structure or NULL * @@ -932,7 +933,8 @@ i40e_get_link_status_exit: **/ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc, - bool default_port, u16 *veb_seid, + bool default_port, bool enable_l2_filtering, + u16 *veb_seid, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; @@ -958,6 +960,10 @@ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT; else veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DATA; + + if (enable_l2_filtering) + veb_flags |= I40E_AQC_ADD_VEB_ENABLE_L2_FILTER; + cmd->veb_flags = cpu_to_le16(veb_flags); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5d234a13abc5..b6d6494a84ae 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6525,11 +6525,13 @@ void i40e_veb_release(struct i40e_veb *veb) static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi) { bool is_default = (vsi->idx == vsi->back->lan_vsi); + bool is_cloud = false; int ret; /* get a VEB from the hardware */ ret = i40e_aq_add_veb(&veb->pf->hw, veb->uplink_seid, vsi->seid, - veb->enabled_tc, is_default, &veb->seid, NULL); + veb->enabled_tc, is_default, + is_cloud, &veb->seid, NULL); if (ret) { dev_info(&veb->pf->pdev->dev, "couldn't add VEB, err %d, aq_err %d\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index f75bb9ccc900..930f53a2f50c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -106,7 +106,8 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc, - bool default_port, u16 *pveb_seid, + bool default_port, bool enable_l2_filtering, + u16 *pveb_seid, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_get_veb_parameters(struct i40e_hw *hw, u16 veb_seid, u16 *switch_id, bool *floating, -- cgit v1.2.3 From cad1525a5e7443cd93368a22e5b7571c373c8cc0 Mon Sep 17 00:00:00 2001 From: Al Stone Date: Wed, 4 Dec 2013 12:59:11 -0700 Subject: ACPI: remove trailing whitespace Minor cleanup: remove some extra trailing white space. Signed-off-by: Al Stone Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 2 +- drivers/acpi/processor_idle.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 064b8b365060..26c111341ead 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1278,7 +1278,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) jiffies = MAX_SCHEDULE_TIMEOUT; else jiffies = msecs_to_jiffies(timeout); - + ret = down_timeout(sem, jiffies); if (ret) status = AE_TIME; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d2d44e0190a3..a0cc5ef4f06f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -596,7 +596,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) case ACPI_STATE_C2: if (!cx->address) break; - cx->valid = 1; + cx->valid = 1; break; case ACPI_STATE_C3: -- cgit v1.2.3 From 95df812dbdc350bfcf31e247e9100c378a472480 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Thu, 5 Dec 2013 23:42:38 +0800 Subject: ACPI / table: Replace '1' with specific error return values After commit 7f8f97c3cc (ACPI: acpi_table_parse() now returns success/fail, not count), acpi_table_parse() returns '1' when it is unable to find the table, but it should return a negative error code in that case. Make it return -ENODEV instead. Fix the same problem in acpi_table_init() analogously. Signed-off-by: Hanjun Guo [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/tables.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index d67a1fe07f0e..4ec44258e4ff 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -306,7 +306,7 @@ int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler) early_acpi_os_unmap_memory(table, tbl_size); return 0; } else - return 1; + return -ENODEV; } /* @@ -351,7 +351,7 @@ int __init acpi_table_init(void) status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); if (ACPI_FAILURE(status)) - return 1; + return -EINVAL; check_multiple_madt(); return 0; -- cgit v1.2.3 From 7134f9cee04142715c586dd686537c9626f4e03f Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 26 Nov 2013 08:56:05 +0000 Subject: i40e: enable early hardware support Enable a couple of workarounds based on revision ID that allow the driver to work more fully on early hardware. Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_common.c | 22 ++++++++--- drivers/net/ethernet/intel/i40e/i40e_main.c | 49 ++++++++++++++++++++++--- drivers/net/ethernet/intel/i40e/i40e_register.h | 6 +++ 4 files changed, 68 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index df685bc72eca..5aa2ea21aaa9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -61,6 +61,7 @@ #define I40E_BASE_VSI_SEID 512 #define I40E_BASE_VEB_SEID 288 #define I40E_MAX_VEB 16 +#define I40E_MAX_NPAR_QPS 32 #define I40E_MAX_NUM_DESCRIPTORS 4096 #define I40E_MAX_REGISTER 0x0038FFFF diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 1300d3d0aac4..0b52fbc7d56d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -312,6 +312,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) return media; } +#define I40E_PF_RESET_WAIT_COUNT_A0 200 +#define I40E_PF_RESET_WAIT_COUNT 10 /** * i40e_pf_reset - Reset the PF * @hw: pointer to the hardware structure @@ -321,7 +323,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) **/ i40e_status i40e_pf_reset(struct i40e_hw *hw) { - u32 wait_cnt = 0; + u32 cnt = 0; u32 reg = 0; u32 grst_del; @@ -331,7 +333,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) */ grst_del = rd32(hw, I40E_GLGEN_RSTCTL) & I40E_GLGEN_RSTCTL_GRSTDEL_MASK >> I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT; - for (wait_cnt = 0; wait_cnt < grst_del + 2; wait_cnt++) { + for (cnt = 0; cnt < grst_del + 2; cnt++) { reg = rd32(hw, I40E_GLGEN_RSTAT); if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK)) break; @@ -352,11 +354,15 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) /* If there was a Global Reset in progress when we got here, * we don't need to do the PF Reset */ - if (!wait_cnt) { + if (!cnt) { + if (hw->revision_id == 0) + cnt = I40E_PF_RESET_WAIT_COUNT_A0; + else + cnt = I40E_PF_RESET_WAIT_COUNT; reg = rd32(hw, I40E_PFGEN_CTRL); wr32(hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); - for (wait_cnt = 0; wait_cnt < 10; wait_cnt++) { + for (; cnt; cnt--) { reg = rd32(hw, I40E_PFGEN_CTRL); if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK)) break; @@ -385,7 +391,13 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw) /* Clear single descriptor fetch/write-back mode */ reg = rd32(hw, I40E_GLLAN_RCTL_0); - wr32(hw, I40E_GLLAN_RCTL_0, (reg | I40E_GLLAN_RCTL_0_PXE_MODE_MASK)); + + if (hw->revision_id == 0) { + /* As a work around clear PXE_MODE instead of setting it */ + wr32(hw, I40E_GLLAN_RCTL_0, (reg & (~I40E_GLLAN_RCTL_0_PXE_MODE_MASK))); + } else { + wr32(hw, I40E_GLLAN_RCTL_0, (reg | I40E_GLLAN_RCTL_0_PXE_MODE_MASK)); + } } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b6d6494a84ae..ee8152be86be 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -574,10 +574,11 @@ static void i40e_update_veb_stats(struct i40e_veb *veb) i40e_stat_update32(hw, I40E_GLSW_TDPC(idx), veb->stat_offsets_loaded, &oes->tx_discards, &es->tx_discards); - i40e_stat_update32(hw, I40E_GLSW_RUPP(idx), - veb->stat_offsets_loaded, - &oes->rx_unknown_protocol, &es->rx_unknown_protocol); - + if (hw->revision_id > 0) + i40e_stat_update32(hw, I40E_GLSW_RUPP(idx), + veb->stat_offsets_loaded, + &oes->rx_unknown_protocol, + &es->rx_unknown_protocol); i40e_stat_update48(hw, I40E_GLSW_GORCH(idx), I40E_GLSW_GORCL(idx), veb->stat_offsets_loaded, &oes->rx_bytes, &es->rx_bytes); @@ -2240,7 +2241,10 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) rx_ctx.tphwdesc_ena = 1; rx_ctx.tphdata_ena = 1; rx_ctx.tphhead_ena = 1; - rx_ctx.lrxqthresh = 2; + if (hw->revision_id == 0) + rx_ctx.lrxqthresh = 0; + else + rx_ctx.lrxqthresh = 2; rx_ctx.crcstrip = 1; rx_ctx.l2tsel = 1; rx_ctx.showiv = 1; @@ -3021,6 +3025,9 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) } } + if (hw->revision_id == 0) + mdelay(50); + return 0; } @@ -4612,6 +4619,13 @@ static int i40e_get_capabilities(struct i40e_pf *pf) } } while (err); + if (pf->hw.revision_id == 0 && pf->hw.func_caps.npar_enable) { + pf->hw.func_caps.num_msix_vectors += 1; + pf->hw.func_caps.num_tx_qp = + min_t(int, pf->hw.func_caps.num_tx_qp, + I40E_MAX_NPAR_QPS); + } + if (pf->hw.debug_mask & I40E_DEBUG_USER) dev_info(&pf->pdev->dev, "pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n", @@ -4623,6 +4637,15 @@ static int i40e_get_capabilities(struct i40e_pf *pf) pf->hw.func_caps.num_tx_qp, pf->hw.func_caps.num_vsis); +#define DEF_NUM_VSI (1 + (pf->hw.func_caps.fcoe ? 1 : 0) \ + + pf->hw.func_caps.num_vfs) + if (pf->hw.revision_id == 0 && (DEF_NUM_VSI > pf->hw.func_caps.num_vsis)) { + dev_info(&pf->pdev->dev, + "got num_vsis %d, setting num_vsis to %d\n", + pf->hw.func_caps.num_vsis, DEF_NUM_VSI); + pf->hw.func_caps.num_vsis = DEF_NUM_VSI; + } + return 0; } @@ -5618,7 +5641,12 @@ static int i40e_sw_init(struct i40e_pf *pf) I40E_FLAG_MQ_ENABLED | I40E_FLAG_RX_1BUF_ENABLED; + /* Depending on PF configurations, it is possible that the RSS + * maximum might end up larger than the available queues + */ pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width; + pf->rss_size_max = min_t(int, pf->rss_size_max, + pf->hw.func_caps.num_tx_qp); if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; pf->rss_size = min_t(int, pf->rss_size_max, @@ -7142,6 +7170,17 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->bus.device = PCI_SLOT(pdev->devfn); hw->bus.func = PCI_FUNC(pdev->devfn); + /* do a special CORER for clearing PXE mode once at init */ + if (hw->revision_id == 0 && + (rd32(hw, I40E_GLLAN_RCTL_0) & I40E_GLLAN_RCTL_0_PXE_MODE_MASK)) { + wr32(hw, I40E_GLGEN_RTRIG, I40E_GLGEN_RTRIG_CORER_MASK); + i40e_flush(hw); + msleep(200); + pf->corer_count++; + + i40e_clear_pxe_mode(hw); + } + /* Reset here to make sure all is clean and to define PF 'n' */ err = i40e_pf_reset(hw); if (err) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index db4958bea583..46a2f40944e7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -2187,6 +2187,12 @@ #define I40E_GLPCI_PCIERR 0x000BE4FC #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0 #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT) +#define I40E_GLPCI_PCITEST2 0x000BE4BC +#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0 +#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT) +#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1 +#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT) + #define I40E_GLPCI_PKTCT 0x0009C4BC #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0 #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT) -- cgit v1.2.3 From 4ef54410ca6e7e5f32d67c5fb8094ae07460814a Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 6 Dec 2013 00:03:40 +0800 Subject: ACPI / dock: Drop redundant acpi_disabled check acpi_dock_init() is only called from acpi_scan_init() and the code logic shows that it doesn't need to check acpi_disabled: acpi_init(); if (acpi_disabled) return; acpi_scan_init(); acpi_dock_init(); if (acpi_disabled) /* redundant */ return; Signed-off-by: Hanjun Guo [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 9ab9e783a894..c2090c023102 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -896,9 +896,6 @@ find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv) void __init acpi_dock_init(void) { - if (acpi_disabled) - return; - /* look for dock stations and bays */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL); -- cgit v1.2.3 From 100eb0b04293fbb7af689ff7ddfe8fc8a46ab65c Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 6 Dec 2013 00:03:41 +0800 Subject: ACPI / sleep: Drop redundant acpi_disabled check acpi_sleep_init() is only called from acpi_bus_init() and the code logic shows that it doesn't need to check acpi_disabled: acpi_init(); if (acpi_disabled) return; acpi_bus_init(); acpi_sleep_init(); if (acpi_disabled) return 0; Signed-off-by: Hanjun Guo [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index ea9cc373ffd8..cb889c715e14 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -802,9 +802,6 @@ int __init acpi_sleep_init(void) char *pos = supported; int i; - if (acpi_disabled) - return 0; - acpi_sleep_dmi_check(); sleep_states[ACPI_STATE_S0] = 1; -- cgit v1.2.3 From 6dd7aca824df3bd2f9c684b9dc68ee00afb065e8 Mon Sep 17 00:00:00 2001 From: Al Stone Date: Thu, 5 Dec 2013 11:14:16 -0700 Subject: ACPI: correct minor typos Correct "coolign" to "cooling" and "*_ptg" to "*_pctg" as intended. This changes comment text only. Signed-off-by: Al Stone Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index f95e7584d6e6..e003663b2f8e 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -183,14 +183,14 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) #endif -/* thermal coolign device callbacks */ +/* thermal cooling device callbacks */ static int acpi_processor_max_state(struct acpi_processor *pr) { int max_state = 0; /* * There exists four states according to - * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 + * cpufreq_thermal_reduction_pctg. 0, 1, 2, 3 */ max_state += cpufreq_get_max_state(pr->id); if (pr->flags.throttling) -- cgit v1.2.3 From d0a7edbb6608d05b0718a0949be914067b5980fb Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 6 Dec 2013 15:36:26 +0800 Subject: ACPI / processor: use ACPI_COMPANION() to get ACPI device Use ACPI_COMPANION() to get an ACPI device instead of acpi_bus_get_device() in the processor driver. Signed-off-by: Lan Tianyu [rjw: Changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_driver.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 146ab7e2b81d..c1c35623550f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -224,9 +224,9 @@ static int __acpi_processor_start(struct acpi_device *device) static int acpi_processor_start(struct device *dev) { - struct acpi_device *device; + struct acpi_device *device = ACPI_COMPANION(dev); - if (acpi_bus_get_device(ACPI_HANDLE(dev), &device)) + if (!device) return -ENODEV; return __acpi_processor_start(device); @@ -234,10 +234,10 @@ static int acpi_processor_start(struct device *dev) static int acpi_processor_stop(struct device *dev) { - struct acpi_device *device; + struct acpi_device *device = ACPI_COMPANION(dev); struct acpi_processor *pr; - if (acpi_bus_get_device(ACPI_HANDLE(dev), &device)) + if (!device) return 0; acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, -- cgit v1.2.3 From a19a41e0fa2f482804443224a5e3e2d390f8f970 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 20 Nov 2013 10:02:53 +0000 Subject: i40e: whitespace Whitespace fixes Change-Id: I95f4d02e4a2a92d6b6fca3ae2b7865c4b916a9bb Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala --- drivers/net/ethernet/intel/i40e/i40e_register.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index 46a2f40944e7..2394c66870f4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -66,6 +66,7 @@ #define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT) + #define I40E_PF_ARQBAH 0x00080180 #define I40E_PF_ARQBAH_ARQBAH_SHIFT 0 #define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT) -- cgit v1.2.3 From 217ffd411702e6cd1f0d4c00f72333ae1c4731dc Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 20 Nov 2013 10:02:54 +0000 Subject: i40e: Bump version Update the driver version to 0.3.12-k Signed-off-by: Catherine Sullivan Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index ee8152be86be..969a6871e3c3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -36,7 +36,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 0 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 11 +#define DRV_VERSION_BUILD 12 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN -- cgit v1.2.3 From f650a38b4d3a3b5a14d0bc093f0ae7773faf7f41 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 20 Nov 2013 10:02:55 +0000 Subject: i40e: refactor reset code In order to re-size queues and vectors while the interface is still up, we need to be able to call functions to free and re-allocate without bringing down the VSI. We also need to reset the existing setup, update the configuration and then rebuild again. This requires us to have the reset flow broken down into two parts. Change-Id: I374dd25aabf769decda69b676491c7b7730a4635 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 131 ++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 969a6871e3c3..273db9940ff1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4716,22 +4716,20 @@ static void i40e_fdir_teardown(struct i40e_pf *pf) } /** - * i40e_handle_reset_warning - prep for the core to reset + * i40e_prep_for_reset - prep for the core to reset * @pf: board private structure * - * Close up the VFs and other things in prep for a Core Reset, - * then get ready to rebuild the world. - **/ -static void i40e_handle_reset_warning(struct i40e_pf *pf) + * Close up the VFs and other things in prep for pf Reset. + **/ +static int i40e_prep_for_reset(struct i40e_pf *pf) { - struct i40e_driver_version dv; struct i40e_hw *hw = &pf->hw; i40e_status ret; u32 v; clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state); if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) - return; + return 0; dev_info(&pf->pdev->dev, "Tearing down internal switch for reset\n"); @@ -4747,6 +4745,26 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf) i40e_shutdown_adminq(&pf->hw); + /* call shutdown HMC */ + ret = i40e_shutdown_lan_hmc(hw); + if (ret) { + dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); + clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); + } + return ret; +} + +/** + * i40e_reset_and_rebuild - reset and rebuid using a saved config + * @pf: board private structure + **/ +static void i40e_reset_and_rebuild(struct i40e_pf *pf) +{ + struct i40e_driver_version dv; + struct i40e_hw *hw = &pf->hw; + i40e_status ret; + u32 v; + /* Now we wait for GRST to settle out. * We don't have to delete the VEBs or VSIs from the hw switch * because the reset will make them disappear. @@ -4774,13 +4792,6 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf) goto end_core_reset; } - /* call shutdown HMC */ - ret = i40e_shutdown_lan_hmc(hw); - if (ret) { - dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); - goto end_core_reset; - } - ret = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, hw->func_caps.num_rx_qp, pf->fcoe_hmc_cntx_num, pf->fcoe_hmc_filt_num); @@ -4873,6 +4884,22 @@ end_core_reset: clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); } +/** + * i40e_handle_reset_warning - prep for the pf to reset, reset and rebuild + * @pf: board private structure + * + * Close up the VFs and other things in prep for a Core Reset, + * then get ready to rebuild the world. + **/ +static void i40e_handle_reset_warning(struct i40e_pf *pf) +{ + i40e_status ret; + + ret = i40e_prep_for_reset(pf); + if (!ret) + i40e_reset_and_rebuild(pf); +} + /** * i40e_handle_mdd_event * @pf: pointer to the pf structure @@ -5048,6 +5075,40 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi) return 0; } +/** + * i40e_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the vsi + * @type: VSI pointer + * + * On error: returns error code (negative) + * On success: returns 0 + **/ +static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi) +{ + int size; + int ret = 0; + + /* allocate memory for ring pointers */ + size = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2; + vsi->tx_rings = kzalloc(size, GFP_KERNEL); + if (!vsi->tx_rings) + return -ENOMEM; + + vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs]; + + /* allocate memory for q_vector pointers */ + size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; + vsi->q_vectors = kzalloc(size, GFP_KERNEL); + if (!vsi->q_vectors) { + ret = -ENOMEM; + goto err_vectors; + } + return ret; + +err_vectors: + kfree(vsi->tx_rings); + return ret; +} + /** * i40e_vsi_mem_alloc - Allocates the next available struct vsi in the PF * @pf: board private structure @@ -5060,8 +5121,6 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) { int ret = -ENODEV; struct i40e_vsi *vsi; - int sz_vectors; - int sz_rings; int vsi_idx; int i; @@ -5111,22 +5170,9 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) if (ret) goto err_rings; - /* allocate memory for ring pointers */ - sz_rings = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2; - vsi->tx_rings = kzalloc(sz_rings, GFP_KERNEL); - if (!vsi->tx_rings) { - ret = -ENOMEM; + ret = i40e_vsi_alloc_arrays(vsi); + if (ret) goto err_rings; - } - vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs]; - - /* allocate memory for q_vector pointers */ - sz_vectors = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; - vsi->q_vectors = kzalloc(sz_vectors, GFP_KERNEL); - if (!vsi->q_vectors) { - ret = -ENOMEM; - goto err_vectors; - } /* Setup default MSIX irq handler for VSI */ i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings); @@ -5135,8 +5181,6 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) ret = vsi_idx; goto unlock_pf; -err_vectors: - kfree(vsi->tx_rings); err_rings: pf->next_vsi = i - 1; kfree(vsi); @@ -5145,6 +5189,23 @@ unlock_pf: return ret; } +/** + * i40e_vsi_free_arrays - Free queue and vector pointer arrays for the VSI + * @type: VSI pointer + * + * On error: returns error code (negative) + * On success: returns 0 + **/ +static void i40e_vsi_free_arrays(struct i40e_vsi *vsi) +{ + /* free the ring and vector containers */ + kfree(vsi->q_vectors); + vsi->q_vectors = NULL; + kfree(vsi->tx_rings); + vsi->tx_rings = NULL; + vsi->rx_rings = NULL; +} + /** * i40e_vsi_clear - Deallocate the VSI provided * @vsi: the VSI being un-configured @@ -5181,9 +5242,7 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi) i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx); i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx); - /* free the ring and vector containers */ - kfree(vsi->q_vectors); - kfree(vsi->tx_rings); + i40e_vsi_free_arrays(vsi); pf->vsi[vsi->idx] = NULL; if (vsi->idx < pf->next_vsi) -- cgit v1.2.3 From 4617e8c081382baf11377b999e9eed22ffa1bdf6 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 20 Nov 2013 10:02:56 +0000 Subject: i40e: Enable all PCTYPEs except FCOE for RSS. RSS can steer packets based on recognition of all sorts of different headers. Enable some more of them. Change-Id: I2264dedae66fb0bceca6fb6e772e050e3ca8efc8 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 38 ++++++++++++++++++----------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 273db9940ff1..40c64c4d9882 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5615,15 +5615,34 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf) **/ static int i40e_config_rss(struct i40e_pf *pf) { - struct i40e_hw *hw = &pf->hw; - u32 lut = 0; - int i, j; - u64 hena; + const u64 default_hena = + ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | + ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | + ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | + ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD); + /* Set of random keys generated using kernel random number generator */ static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687, 0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377, 0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d, 0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be}; + struct i40e_hw *hw = &pf->hw; + u32 lut = 0; + int i, j; + u64 hena; /* Fill out hash function seed */ for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) @@ -5632,16 +5651,7 @@ static int i40e_config_rss(struct i40e_pf *pf) /* By default we enable TCP/UDP with IPv4/IPv6 ptypes */ hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) | ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32); - hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | - ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | - ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4)| - ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6); + hena |= default_hena; wr32(hw, I40E_PFQF_HENA(0), (u32)hena); wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32)); -- cgit v1.2.3 From ac6c5e3d0e9e784ef8b015085c83dee0253324b0 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 20 Nov 2013 10:02:57 +0000 Subject: i40e: only set up the rings to be used The VSI may be allocated more queues (alloc_queue_pairs) than actually are to be used (num_queue_pairs), so only allocate rings for the queues to be used. The numbers will likely be the same for most VSIs, but can be different based on how TCs are assigned and enabled. Change-Id: Ie40f7ad0affbc4b45d6f049bcf02ee2fa24edc74 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 40c64c4d9882..aae2f04ab0a4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5087,12 +5087,11 @@ static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi) int size; int ret = 0; - /* allocate memory for ring pointers */ + /* allocate memory for both Tx and Rx ring pointers */ size = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2; vsi->tx_rings = kzalloc(size, GFP_KERNEL); if (!vsi->tx_rings) return -ENOMEM; - vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs]; /* allocate memory for q_vector pointers */ @@ -5265,7 +5264,7 @@ static s32 i40e_vsi_clear_rings(struct i40e_vsi *vsi) int i; if (vsi->tx_rings[0]) - for (i = 0; i < vsi->alloc_queue_pairs; i++) { + for (i = 0; i < vsi->num_queue_pairs; i++) { kfree_rcu(vsi->tx_rings[i], rcu); vsi->tx_rings[i] = NULL; vsi->rx_rings[i] = NULL; @@ -5284,10 +5283,11 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi) int i; /* Set basic values in the rings to be used later during open() */ - for (i = 0; i < vsi->alloc_queue_pairs; i++) { + for (i = 0; i < vsi->num_queue_pairs; i++) { struct i40e_ring *tx_ring; struct i40e_ring *rx_ring; + /* allocate space for both Tx and Rx in one shot */ tx_ring = kzalloc(sizeof(struct i40e_ring) * 2, GFP_KERNEL); if (!tx_ring) goto err_out; @@ -5858,7 +5858,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) int etherdev_size; etherdev_size = sizeof(struct i40e_netdev_priv); - netdev = alloc_etherdev_mq(etherdev_size, vsi->alloc_queue_pairs); + netdev = alloc_etherdev_mq(etherdev_size, vsi->num_queue_pairs); if (!netdev) return -ENOMEM; @@ -6939,8 +6939,8 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf) * into the pf, since this newer code pushes the pf queue * info down a level into a VSI */ - pf->num_rx_queues = vsi->alloc_queue_pairs; - pf->num_tx_queues = vsi->alloc_queue_pairs; + pf->num_rx_queues = vsi->num_queue_pairs; + pf->num_tx_queues = vsi->num_queue_pairs; } else { /* force a reset of TC and queue layout configurations */ u8 enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc; -- cgit v1.2.3 From c140c17b98f246d736e20757e39ec597fae7bc9e Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 20 Nov 2013 10:02:58 +0000 Subject: i40e: clear test state bit after all ethtool tests Fix a bug where the TESTING state was still set when exiting the ethtool diagnostics. Change-Id: Ic47950d2e86a67167d1d282256d477cecd86d820 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 7fb669bd0472..44d4a7f84787 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -805,9 +805,10 @@ static void i40e_diag_test(struct net_device *netdev, data[I40E_ETH_TEST_EEPROM] = 0; data[I40E_ETH_TEST_INTR] = 0; data[I40E_ETH_TEST_LOOPBACK] = 0; - - clear_bit(__I40E_TESTING, &pf->state); } + clear_bit(__I40E_TESTING, &pf->state); + + netdev_info(netdev, "testing finished\n"); } static void i40e_get_wol(struct net_device *netdev, -- cgit v1.2.3 From 7b0863977f097190fc91d949fea16741d92c30ce Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 20 Nov 2013 10:02:59 +0000 Subject: i40e: refactor ethtool tests Put the print and reset statements in the actual test functions to make them more self-contained, and only run the reset for tests that need it. Change-Id: Ic70f49b11bf8bae82e59d8fd25b46215c90c4510 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 57 ++++++++++++++------------ 1 file changed, 30 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 44d4a7f84787..f0bab1704dd1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -706,8 +706,12 @@ static int i40e_get_ts_info(struct net_device *dev, return ethtool_op_get_ts_info(dev, info); } -static int i40e_link_test(struct i40e_pf *pf, u64 *data) +static int i40e_link_test(struct net_device *netdev, u64 *data) { + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; + + netdev_info(netdev, "link test\n"); if (i40e_get_link_status(&pf->hw)) *data = 0; else @@ -716,30 +720,36 @@ static int i40e_link_test(struct i40e_pf *pf, u64 *data) return *data; } -static int i40e_reg_test(struct i40e_pf *pf, u64 *data) +static int i40e_reg_test(struct net_device *netdev, u64 *data) { - i40e_status ret; + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; - ret = i40e_diag_reg_test(&pf->hw); - *data = ret; + netdev_info(netdev, "register test\n"); + *data = i40e_diag_reg_test(&pf->hw); - return ret; + i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); + return *data; } -static int i40e_eeprom_test(struct i40e_pf *pf, u64 *data) +static int i40e_eeprom_test(struct net_device *netdev, u64 *data) { - i40e_status ret; + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; - ret = i40e_diag_eeprom_test(&pf->hw); - *data = ret; + netdev_info(netdev, "eeprom test\n"); + *data = i40e_diag_eeprom_test(&pf->hw); - return ret; + return *data; } -static int i40e_intr_test(struct i40e_pf *pf, u64 *data) +static int i40e_intr_test(struct net_device *netdev, u64 *data) { + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; u16 swc_old = pf->sw_int_count; + netdev_info(netdev, "interrupt test\n"); wr32(&pf->hw, I40E_PFINT_DYN_CTL0, (I40E_PFINT_DYN_CTL0_INTENA_MASK | I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK)); @@ -749,8 +759,9 @@ static int i40e_intr_test(struct i40e_pf *pf, u64 *data) return *data; } -static int i40e_loopback_test(struct i40e_pf *pf, u64 *data) +static int i40e_loopback_test(struct net_device *netdev, u64 *data) { + netdev_info(netdev, "loopback test not implemented\n"); *data = 0; return *data; @@ -771,33 +782,25 @@ static void i40e_diag_test(struct net_device *netdev, /* Link test performed before hardware reset * so autoneg doesn't interfere with test result */ - netdev_info(netdev, "link test starting\n"); - if (i40e_link_test(pf, &data[I40E_ETH_TEST_LINK])) + if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK])) eth_test->flags |= ETH_TEST_FL_FAILED; - netdev_info(netdev, "register test starting\n"); - if (i40e_reg_test(pf, &data[I40E_ETH_TEST_REG])) + if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG])) eth_test->flags |= ETH_TEST_FL_FAILED; - i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); - netdev_info(netdev, "eeprom test starting\n"); - if (i40e_eeprom_test(pf, &data[I40E_ETH_TEST_EEPROM])) + if (i40e_eeprom_test(netdev, &data[I40E_ETH_TEST_EEPROM])) eth_test->flags |= ETH_TEST_FL_FAILED; - i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); - netdev_info(netdev, "interrupt test starting\n"); - if (i40e_intr_test(pf, &data[I40E_ETH_TEST_INTR])) + if (i40e_intr_test(netdev, &data[I40E_ETH_TEST_INTR])) eth_test->flags |= ETH_TEST_FL_FAILED; - i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); - netdev_info(netdev, "loopback test starting\n"); - if (i40e_loopback_test(pf, &data[I40E_ETH_TEST_LOOPBACK])) + if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK])) eth_test->flags |= ETH_TEST_FL_FAILED; } else { netdev_info(netdev, "online test starting\n"); /* Online tests */ - if (i40e_link_test(pf, &data[I40E_ETH_TEST_LINK])) + if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK])) eth_test->flags |= ETH_TEST_FL_FAILED; /* Offline only tests, not run in online; pass by default */ -- cgit v1.2.3 From 4a38d09cd9e27d81aaa04891dc1f7d7c81677c5a Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 20 Nov 2013 10:03:00 +0000 Subject: i40e: add num_VFs message Print a message to notify the user of how many VFs are initialized on each port. Change-Id: I29ac2acc478ee4e588fd6ffcc35133d4c6607ca9 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index aae2f04ab0a4..08ac9604ec67 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5765,6 +5765,9 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->num_req_vfs = min_t(int, pf->hw.func_caps.num_vfs, I40E_MAX_VF_COUNT); + dev_info(&pf->pdev->dev, + "Number of VFs being requested for PF[%d] = %d\n", + pf->hw.pf_id, pf->num_req_vfs); } #endif /* CONFIG_PCI_IOV */ pf->eeprom_version = 0xDEAD; -- cgit v1.2.3 From 93cd765bb27365e7be92c510c73b017426eb490d Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 20 Nov 2013 10:03:01 +0000 Subject: i40e: Add a new variable to track number of pf instances Track the number of physical functions (PFs) found, this is a global counter on purpose so that each pf loaded has a unique ID. Change-Id: I74d618520afbce4a774d0235449e3b5f97ff6d4a Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 5aa2ea21aaa9..001d7cfc9129 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -276,6 +276,8 @@ struct i40e_pf { struct dentry *i40e_dbg_pf; #endif /* CONFIG_DEBUG_FS */ + u16 instance; /* A unique number per i40e_pf instance in the system */ + /* sr-iov config info */ struct i40e_vf *vf; int num_alloc_vfs; /* actual number of VFs allocated */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 08ac9604ec67..d2b48bb237fd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7176,6 +7176,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct i40e_driver_version dv; struct i40e_pf *pf; struct i40e_hw *hw; + static u16 pfs_found; int err = 0; u32 len; @@ -7241,6 +7242,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->subsystem_device_id = pdev->subsystem_device; hw->bus.device = PCI_SLOT(pdev->devfn); hw->bus.func = PCI_FUNC(pdev->devfn); + pf->instance = pfs_found; /* do a special CORER for clearing PXE mode once at init */ if (hw->revision_id == 0 && @@ -7391,6 +7393,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_flush(hw); } + pfs_found++; + i40e_dbg_pf_init(pf); /* tell the firmware that we're starting */ -- cgit v1.2.3 From 670d20725e4f707feca89769587bd192bc5786ae Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 3 Nov 2012 12:16:09 -0700 Subject: Input: samsung-keypad - favor platform data if present We should be able to override firmware-provided parameters with in-kernel data, if needed. To that effect favor platform data, if present, over devicetree data. Acked-by: Joonyoung Shim Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/samsung-keypad.c | 36 +++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 9ac8a1e0c08e..a7357adeaf24 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -244,8 +244,8 @@ static void samsung_keypad_close(struct input_dev *input_dev) } #ifdef CONFIG_OF -static struct samsung_keypad_platdata *samsung_keypad_parse_dt( - struct device *dev) +static struct samsung_keypad_platdata * +samsung_keypad_parse_dt(struct device *dev) { struct samsung_keypad_platdata *pdata; struct matrix_keymap_data *keymap_data; @@ -253,17 +253,22 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( struct device_node *np = dev->of_node, *key_np; unsigned int key_count; + if (!np) { + dev_err(dev, "missing device tree data\n"); + return ERR_PTR(-EINVAL); + } + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(dev, "could not allocate memory for platform data\n"); - return NULL; + return ERR_PTR(-ENOMEM); } of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows); of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols); if (!num_rows || !num_cols) { dev_err(dev, "number of keypad rows/columns not specified\n"); - return NULL; + return ERR_PTR(-EINVAL); } pdata->rows = num_rows; pdata->cols = num_cols; @@ -271,7 +276,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL); if (!keymap_data) { dev_err(dev, "could not allocate memory for keymap data\n"); - return NULL; + return ERR_PTR(-ENOMEM); } pdata->keymap_data = keymap_data; @@ -280,7 +285,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); if (!keymap) { dev_err(dev, "could not allocate memory for keymap\n"); - return NULL; + return ERR_PTR(-ENOMEM); } keymap_data->keymap = keymap; @@ -294,16 +299,19 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( if (of_get_property(np, "linux,input-no-autorepeat", NULL)) pdata->no_autorepeat = true; + if (of_get_property(np, "linux,input-wakeup", NULL)) pdata->wakeup = true; return pdata; } #else -static -struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) +static struct samsung_keypad_platdata * +samsung_keypad_parse_dt(struct device *dev) { - return NULL; + dev_err(dev, "no platform data defined\n"); + + return ERR_PTR(-EINVAL); } #endif @@ -318,13 +326,11 @@ static int samsung_keypad_probe(struct platform_device *pdev) unsigned int keymap_size; int error; - if (pdev->dev.of_node) - pdata = samsung_keypad_parse_dt(&pdev->dev); - else - pdata = dev_get_platdata(&pdev->dev); + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; + pdata = samsung_keypad_parse_dt(&pdev->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); } keymap_data = pdata->keymap_data; -- cgit v1.2.3 From c8231a9af8147f8a401fc55931ec44abfb937660 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 6 Dec 2013 19:31:00 +0000 Subject: iio: mxs-lradc: compute temperature from channel 8 and 9 The mxs LRADC is able to read an internal die temperature sensor. The temperature has to be calculated from the value read on channel 8 and channel 9. To be able to expose the result to hwmon, implement iio channel 8 as (channel 9 - channel 8). Then, implement IIO_CHAN_INFO_SCALE and IIO_CHAN_INFO_OFFSET so that it can be processed by hwmon through the in kernel provider/consumer mechanism. Signed-off-by: Alexandre Belloni Signed-off-by: Maxime Ripard Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/mxs-lradc.c | 91 +++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index e2dd7830b320..5a4499c3d22a 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -759,20 +759,11 @@ static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) /* * Raw I/O operations */ -static int mxs_lradc_read_raw(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - int *val, int *val2, long m) +static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) { struct mxs_lradc *lradc = iio_priv(iio_dev); int ret; - if (m != IIO_CHAN_INFO_RAW) - return -EINVAL; - - /* Check for invalid channel */ - if (chan->channel > LRADC_MAX_TOTAL_CHANS) - return -EINVAL; - /* * See if there is no buffered operation in progess. If there is, simply * bail out. This can be improved to support both buffered and raw IO at @@ -797,7 +788,7 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, /* Clean the slot's previous content, then set new one. */ mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4); - mxs_lradc_reg_set(lradc, chan->channel, LRADC_CTRL4); + mxs_lradc_reg_set(lradc, chan, LRADC_CTRL4); mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0)); @@ -824,6 +815,71 @@ err: return ret; } +static int mxs_lradc_read_temp(struct iio_dev *iio_dev, int *val) +{ + int ret, min, max; + + ret = mxs_lradc_read_single(iio_dev, 8, &min); + if (ret != IIO_VAL_INT) + return ret; + + ret = mxs_lradc_read_single(iio_dev, 9, &max); + if (ret != IIO_VAL_INT) + return ret; + + *val = max - min; + + return IIO_VAL_INT; +} + +static int mxs_lradc_read_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long m) +{ + /* Check for invalid channel */ + if (chan->channel > LRADC_MAX_TOTAL_CHANS) + return -EINVAL; + + switch (m) { + case IIO_CHAN_INFO_RAW: + if (chan->type == IIO_TEMP) + return mxs_lradc_read_temp(iio_dev, val); + + return mxs_lradc_read_single(iio_dev, chan->channel, val); + + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_TEMP) { + /* From the datasheet, we have to multiply by 1.012 and + * divide by 4 + */ + *val = 0; + *val2 = 253000; + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; + + case IIO_CHAN_INFO_OFFSET: + if (chan->type == IIO_TEMP) { + /* The calculated value from the ADC is in Kelvin, we + * want Celsius for hwmon so the offset is + * -272.15 * scale + */ + *val = -1075; + *val2 = 691699; + + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; + + default: + break; + } + + return -EINVAL; +} + static const struct iio_info mxs_lradc_iio_info = { .driver_module = THIS_MODULE, .read_raw = mxs_lradc_read_raw, @@ -1151,8 +1207,17 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = { MXS_ADC_CHAN(5, IIO_VOLTAGE), MXS_ADC_CHAN(6, IIO_VOLTAGE), MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */ - MXS_ADC_CHAN(8, IIO_TEMP), /* Temp sense 0 */ - MXS_ADC_CHAN(9, IIO_TEMP), /* Temp sense 1 */ + /* Combined Temperature sensors */ + { + .type = IIO_TEMP, + .indexed = 1, + .scan_index = 8, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), + .channel = 8, + .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, + }, MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ -- cgit v1.2.3 From 17bd86c69cea4a8364e2ef8a49947dd9d5e26f13 Mon Sep 17 00:00:00 2001 From: Eric Brower Date: Mon, 18 Nov 2013 14:55:06 -0800 Subject: PCI: Disable Gen2 for Tegra20 and Tegra30 Tegra20 and Tegra30 do not support gen2 PCIe, so correct the register setting to disable it. Signed-off-by: Eric Brower Signed-off-by: Bjorn Helgaas Acked-by: Thierry Reding --- drivers/pci/host/pci-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 0afbbbc55c81..b8ba2f794559 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -805,7 +805,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) afi_writel(pcie, value, AFI_PCIE_CONFIG); value = afi_readl(pcie, AFI_FUSE); - value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS; + value |= AFI_FUSE_PCIE_T0_GEN2_DIS; afi_writel(pcie, value, AFI_FUSE); /* initialize internal PHY, enable up to 16 PCIE lanes */ -- cgit v1.2.3 From c176d1c71bd18238e5d77d6acc6b991aa6a17f3b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 19 Nov 2013 11:40:28 +0800 Subject: PCI: rcar: Fix rcar_pci_probe() return value check In case of error, the function devm_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Signed-off-by: Bjorn Helgaas Reviewed-by: Jingoo Han --- drivers/pci/host/pci-rcar-gen2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index cbaa5c4397e3..96d118242ae2 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -276,8 +276,8 @@ static int __init rcar_pci_probe(struct platform_device *pdev) cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg = devm_ioremap_resource(&pdev->dev, cfg_res); - if (!reg) - return -ENODEV; + if (IS_ERR(reg)) + return PTR_ERR(reg); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!mem_res || !mem_res->start) -- cgit v1.2.3 From 6cf30b35475435f453d87838fb14ad3483955a19 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 24 May 2013 14:10:51 +0200 Subject: m68k/mac: Mark Mac IIsi ADB driver BROKEN As reported by Finn Thain, the Mac IIsi ADB driver should be disabled because it will crash. Signed-off-by: Geert Uytterhoeven --- drivers/macintosh/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index d26a312f117a..3067d56b11a6 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -32,7 +32,7 @@ config ADB_MACII config ADB_MACIISI bool "Include Mac IIsi ADB driver" - depends on ADB && MAC + depends on ADB && MAC && BROKEN help Say Y here if want your kernel to support Macintosh systems that use the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic -- cgit v1.2.3 From bb7f9d90a5c0c29885cc37418ae208118e04bd4f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 7 Dec 2013 10:45:00 +0000 Subject: iio:cm36651: Convert to new event config interface Switch the cm36651 driver to the new IIO event config interface as the old one is going to be removed. Signed-off-by: Lars-Peter Clausen Cc: Beomho Seo Signed-off-by: Jonathan Cameron --- drivers/iio/light/cm36651.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 21df57130018..2a0eb8de3396 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -488,7 +488,11 @@ static int cm36651_write_raw(struct iio_dev *indio_dev, } static int cm36651_read_prox_thresh(struct iio_dev *indio_dev, - u64 event_code, int *val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct cm36651_data *cm36651 = iio_priv(indio_dev); @@ -498,7 +502,11 @@ static int cm36651_read_prox_thresh(struct iio_dev *indio_dev, } static int cm36651_write_prox_thresh(struct iio_dev *indio_dev, - u64 event_code, int val) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct cm36651_data *cm36651 = iio_priv(indio_dev); struct i2c_client *client = cm36651->client; @@ -520,7 +528,10 @@ static int cm36651_write_prox_thresh(struct iio_dev *indio_dev, } static int cm36651_write_prox_event_config(struct iio_dev *indio_dev, - u64 event_code, int state) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) { struct cm36651_data *cm36651 = iio_priv(indio_dev); int cmd, ret = -EINVAL; @@ -536,7 +547,9 @@ static int cm36651_write_prox_event_config(struct iio_dev *indio_dev, } static int cm36651_read_prox_event_config(struct iio_dev *indio_dev, - u64 event_code) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) { struct cm36651_data *cm36651 = iio_priv(indio_dev); int event_en; @@ -559,12 +572,22 @@ static int cm36651_read_prox_event_config(struct iio_dev *indio_dev, .channel2 = IIO_MOD_LIGHT_##_color, \ } \ +static const struct iio_event_spec cm36651_event_spec[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + } +}; + static const struct iio_chan_spec cm36651_channels[] = { { .type = IIO_PROXIMITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_INT_TIME), - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER) + .event_spec = cm36651_event_spec, + .num_event_specs = ARRAY_SIZE(cm36651_event_spec), }, CM36651_LIGHT_CHANNEL(RED, CM36651_LIGHT_CHANNEL_IDX_RED), CM36651_LIGHT_CHANNEL(GREEN, CM36651_LIGHT_CHANNEL_IDX_GREEN), @@ -591,10 +614,10 @@ static const struct iio_info cm36651_info = { .driver_module = THIS_MODULE, .read_raw = &cm36651_read_raw, .write_raw = &cm36651_write_raw, - .read_event_value = &cm36651_read_prox_thresh, - .write_event_value = &cm36651_write_prox_thresh, - .read_event_config = &cm36651_read_prox_event_config, - .write_event_config = &cm36651_write_prox_event_config, + .read_event_value_new = &cm36651_read_prox_thresh, + .write_event_value_new = &cm36651_write_prox_thresh, + .read_event_config_new = &cm36651_read_prox_event_config, + .write_event_config_new = &cm36651_write_prox_event_config, .attrs = &cm36651_attribute_group, }; -- cgit v1.2.3 From cb955852a48c29ef7bd847ce993102e2b58295d4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 7 Dec 2013 10:45:00 +0000 Subject: iio: Remove support for the legacy event config interface Now that all drivers have been converted to the new event config interface we can remove for the legacy event config interface. Also drop the '_new' suffix for the event config interface callbacks, since those are the only callbacks now. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1363.c | 8 +- drivers/iio/dac/ad5421.c | 6 +- drivers/iio/industrialio-event.c | 154 +++++------------------------ drivers/iio/light/apds9300.c | 8 +- drivers/iio/light/cm36651.c | 8 +- drivers/iio/light/gp2ap020a00f.c | 8 +- drivers/iio/light/tsl2563.c | 8 +- drivers/staging/iio/accel/lis3l02dq_core.c | 8 +- drivers/staging/iio/accel/sca3000_core.c | 16 +-- drivers/staging/iio/adc/ad7291.c | 8 +- drivers/staging/iio/adc/ad799x_core.c | 6 +- drivers/staging/iio/cdc/ad7150.c | 8 +- drivers/staging/iio/iio_simple_dummy.c | 8 +- drivers/staging/iio/light/tsl2x7x_core.c | 40 ++++---- include/linux/iio/events.h | 4 - include/linux/iio/iio.h | 34 +------ 16 files changed, 97 insertions(+), 235 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 6118dced02b6..e283f2f2ee2f 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1039,10 +1039,10 @@ static const struct iio_info max1238_info = { }; static const struct iio_info max1363_info = { - .read_event_value_new = &max1363_read_thresh, - .write_event_value_new = &max1363_write_thresh, - .read_event_config_new = &max1363_read_event_config, - .write_event_config_new = &max1363_write_event_config, + .read_event_value = &max1363_read_thresh, + .write_event_value = &max1363_write_thresh, + .read_event_config = &max1363_read_event_config, + .write_event_config = &max1363_write_event_config, .read_raw = &max1363_read_raw, .update_scan_mode = &max1363_update_scan_mode, .driver_module = THIS_MODULE, diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index 59a0cb51265c..1cb15d8e94b7 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -458,9 +458,9 @@ static int ad5421_read_event_value(struct iio_dev *indio_dev, static const struct iio_info ad5421_info = { .read_raw = ad5421_read_raw, .write_raw = ad5421_write_raw, - .read_event_config_new = ad5421_read_event_config, - .write_event_config_new = ad5421_write_event_config, - .read_event_value_new = ad5421_read_event_value, + .read_event_config = ad5421_read_event_config, + .write_event_config = ad5421_write_event_config, + .read_event_value = ad5421_read_event_value, .driver_module = THIS_MODULE, }; diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index bc043fab4cd1..c9c1419fe6e0 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -242,13 +242,9 @@ static ssize_t iio_ev_state_store(struct device *dev, if (ret < 0) return ret; - if (indio_dev->info->write_event_config) - ret = indio_dev->info->write_event_config(indio_dev, - this_attr->address, val); - else - ret = indio_dev->info->write_event_config_new(indio_dev, - this_attr->c, iio_ev_attr_type(this_attr), - iio_ev_attr_dir(this_attr), val); + ret = indio_dev->info->write_event_config(indio_dev, + this_attr->c, iio_ev_attr_type(this_attr), + iio_ev_attr_dir(this_attr), val); return (ret < 0) ? ret : len; } @@ -261,13 +257,9 @@ static ssize_t iio_ev_state_show(struct device *dev, struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int val; - if (indio_dev->info->read_event_config) - val = indio_dev->info->read_event_config(indio_dev, - this_attr->address); - else - val = indio_dev->info->read_event_config_new(indio_dev, - this_attr->c, iio_ev_attr_type(this_attr), - iio_ev_attr_dir(this_attr)); + val = indio_dev->info->read_event_config(indio_dev, + this_attr->c, iio_ev_attr_type(this_attr), + iio_ev_attr_dir(this_attr)); if (val < 0) return val; else @@ -283,21 +275,13 @@ static ssize_t iio_ev_value_show(struct device *dev, int val, val2; int ret; - if (indio_dev->info->read_event_value) { - ret = indio_dev->info->read_event_value(indio_dev, - this_attr->address, &val); - if (ret < 0) - return ret; - return sprintf(buf, "%d\n", val); - } else { - ret = indio_dev->info->read_event_value_new(indio_dev, - this_attr->c, iio_ev_attr_type(this_attr), - iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr), - &val, &val2); - if (ret < 0) - return ret; - return iio_format_value(buf, ret, val, val2); - } + ret = indio_dev->info->read_event_value(indio_dev, + this_attr->c, iio_ev_attr_type(this_attr), + iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr), + &val, &val2); + if (ret < 0) + return ret; + return iio_format_value(buf, ret, val, val2); } static ssize_t iio_ev_value_store(struct device *dev, @@ -310,25 +294,16 @@ static ssize_t iio_ev_value_store(struct device *dev, int val, val2; int ret; - if (!indio_dev->info->write_event_value && - !indio_dev->info->write_event_value_new) + if (!indio_dev->info->write_event_value) return -EINVAL; - if (indio_dev->info->write_event_value) { - ret = kstrtoint(buf, 10, &val); - if (ret) - return ret; - ret = indio_dev->info->write_event_value(indio_dev, - this_attr->address, val); - } else { - ret = iio_str_to_fixpoint(buf, 100000, &val, &val2); - if (ret) - return ret; - ret = indio_dev->info->write_event_value_new(indio_dev, - this_attr->c, iio_ev_attr_type(this_attr), - iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr), - val, val2); - } + ret = iio_str_to_fixpoint(buf, 100000, &val, &val2); + if (ret) + return ret; + ret = indio_dev->info->write_event_value(indio_dev, + this_attr->c, iio_ev_attr_type(this_attr), + iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr), + val, val2); if (ret < 0) return ret; @@ -377,7 +352,7 @@ static int iio_device_add_event(struct iio_dev *indio_dev, return attrcount; } -static int iio_device_add_event_sysfs_new(struct iio_dev *indio_dev, +static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { int ret = 0, i, attrcount = 0; @@ -420,89 +395,6 @@ error_ret: return ret; } -static int iio_device_add_event_sysfs_old(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - int ret = 0, i, attrcount = 0; - u64 mask = 0; - char *postfix; - if (!chan->event_mask) - return 0; - - for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { - postfix = kasprintf(GFP_KERNEL, "%s_%s_en", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - if (chan->modified) - mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel2, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - else if (chan->differential) - mask = IIO_EVENT_CODE(chan->type, - 0, 0, - i%IIO_EV_DIR_MAX, - i/IIO_EV_DIR_MAX, - 0, - chan->channel, - chan->channel2); - else - mask = IIO_UNMOD_EVENT_CODE(chan->type, - chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - - ret = __iio_add_chan_devattr(postfix, - chan, - &iio_ev_state_show, - iio_ev_state_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - postfix = kasprintf(GFP_KERNEL, "%s_%s_value", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - ret = __iio_add_chan_devattr(postfix, chan, - iio_ev_value_show, - iio_ev_value_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - } - ret = attrcount; -error_ret: - return ret; -} - - -static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - if (chan->event_mask) - return iio_device_add_event_sysfs_old(indio_dev, chan); - else - return iio_device_add_event_sysfs_new(indio_dev, chan); -} - static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) { int j, ret, attrcount = 0; @@ -523,8 +415,6 @@ static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) int j; for (j = 0; j < indio_dev->num_channels; j++) { - if (indio_dev->channels[j].event_mask != 0) - return true; if (indio_dev->channels[j].num_event_specs != 0) return true; } diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c index 51097bbd59c9..9ddde0ca9c34 100644 --- a/drivers/iio/light/apds9300.c +++ b/drivers/iio/light/apds9300.c @@ -344,10 +344,10 @@ static const struct iio_info apds9300_info_no_irq = { static const struct iio_info apds9300_info = { .driver_module = THIS_MODULE, .read_raw = apds9300_read_raw, - .read_event_value_new = apds9300_read_thresh, - .write_event_value_new = apds9300_write_thresh, - .read_event_config_new = apds9300_read_interrupt_config, - .write_event_config_new = apds9300_write_interrupt_config, + .read_event_value = apds9300_read_thresh, + .write_event_value = apds9300_write_thresh, + .read_event_config = apds9300_read_interrupt_config, + .write_event_config = apds9300_write_interrupt_config, }; static const struct iio_event_spec apds9300_event_spec[] = { diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 2a0eb8de3396..000cc8eb362d 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -614,10 +614,10 @@ static const struct iio_info cm36651_info = { .driver_module = THIS_MODULE, .read_raw = &cm36651_read_raw, .write_raw = &cm36651_write_raw, - .read_event_value_new = &cm36651_read_prox_thresh, - .write_event_value_new = &cm36651_write_prox_thresh, - .read_event_config_new = &cm36651_read_prox_event_config, - .write_event_config_new = &cm36651_write_prox_event_config, + .read_event_value = &cm36651_read_prox_thresh, + .write_event_value = &cm36651_write_prox_thresh, + .read_event_config = &cm36651_read_prox_event_config, + .write_event_config = &cm36651_write_prox_event_config, .attrs = &cm36651_attribute_group, }; diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index dc79835be308..5ea4a03c7e71 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -1388,10 +1388,10 @@ static const struct iio_chan_spec gp2ap020a00f_channels[] = { static const struct iio_info gp2ap020a00f_info = { .read_raw = &gp2ap020a00f_read_raw, - .read_event_value_new = &gp2ap020a00f_read_event_val, - .read_event_config_new = &gp2ap020a00f_read_event_config, - .write_event_value_new = &gp2ap020a00f_write_event_val, - .write_event_config_new = &gp2ap020a00f_write_event_config, + .read_event_value = &gp2ap020a00f_read_event_val, + .read_event_config = &gp2ap020a00f_read_event_config, + .write_event_value = &gp2ap020a00f_write_event_val, + .write_event_config = &gp2ap020a00f_write_event_config, .driver_module = THIS_MODULE, }; diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 0c6e459c86b1..3d8110157f2d 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -702,10 +702,10 @@ static const struct iio_info tsl2563_info = { .driver_module = THIS_MODULE, .read_raw = &tsl2563_read_raw, .write_raw = &tsl2563_write_raw, - .read_event_value_new = &tsl2563_read_thresh, - .write_event_value_new = &tsl2563_write_thresh, - .read_event_config_new = &tsl2563_read_interrupt_config, - .write_event_config_new = &tsl2563_write_interrupt_config, + .read_event_value = &tsl2563_read_thresh, + .write_event_value = &tsl2563_write_thresh, + .read_event_config = &tsl2563_read_interrupt_config, + .write_event_config = &tsl2563_write_interrupt_config, }; static int tsl2563_probe(struct i2c_client *client, diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 735c0a34fa93..898653c09279 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -676,10 +676,10 @@ static const struct attribute_group lis3l02dq_attribute_group = { static const struct iio_info lis3l02dq_info = { .read_raw = &lis3l02dq_read_raw, .write_raw = &lis3l02dq_write_raw, - .read_event_value_new = &lis3l02dq_read_thresh, - .write_event_value_new = &lis3l02dq_write_thresh, - .write_event_config_new = &lis3l02dq_write_event_config, - .read_event_config_new = &lis3l02dq_read_event_config, + .read_event_value = &lis3l02dq_read_thresh, + .write_event_value = &lis3l02dq_write_thresh, + .write_event_config = &lis3l02dq_write_event_config, + .read_event_config = &lis3l02dq_read_event_config, .driver_module = THIS_MODULE, .attrs = &lis3l02dq_attribute_group, }; diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index c49e6ef9d05f..7f6ccdfaf168 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1126,20 +1126,20 @@ static const struct iio_info sca3000_info = { .attrs = &sca3000_attribute_group, .read_raw = &sca3000_read_raw, .event_attrs = &sca3000_event_attribute_group, - .read_event_value_new = &sca3000_read_thresh, - .write_event_value_new = &sca3000_write_thresh, - .read_event_config_new = &sca3000_read_event_config, - .write_event_config_new = &sca3000_write_event_config, + .read_event_value = &sca3000_read_thresh, + .write_event_value = &sca3000_write_thresh, + .read_event_config = &sca3000_read_event_config, + .write_event_config = &sca3000_write_event_config, .driver_module = THIS_MODULE, }; static const struct iio_info sca3000_info_with_temp = { .attrs = &sca3000_attribute_group_with_temp, .read_raw = &sca3000_read_raw, - .read_event_value_new = &sca3000_read_thresh, - .write_event_value_new = &sca3000_write_thresh, - .read_event_config_new = &sca3000_read_event_config, - .write_event_config_new = &sca3000_write_event_config, + .read_event_value = &sca3000_read_thresh, + .write_event_value = &sca3000_write_thresh, + .read_event_config = &sca3000_read_event_config, + .write_event_config = &sca3000_write_event_config, .driver_module = THIS_MODULE, }; diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index d13f8aeeb62f..357cef2a6f4c 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -452,10 +452,10 @@ static const struct iio_chan_spec ad7291_channels[] = { static const struct iio_info ad7291_info = { .read_raw = &ad7291_read_raw, - .read_event_config_new = &ad7291_read_event_config, - .write_event_config_new = &ad7291_write_event_config, - .read_event_value_new = &ad7291_read_event_value, - .write_event_value_new = &ad7291_write_event_value, + .read_event_config = &ad7291_read_event_config, + .write_event_config = &ad7291_write_event_config, + .read_event_value = &ad7291_read_event_value, + .write_event_value = &ad7291_write_event_value, .driver_module = THIS_MODULE, }; diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 9428be82b655..5ea36410f716 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -377,9 +377,9 @@ static const struct iio_info ad7991_info = { static const struct iio_info ad7993_4_7_8_info = { .read_raw = &ad799x_read_raw, .event_attrs = &ad799x_event_attrs_group, - .read_event_config_new = &ad799x_read_event_config, - .read_event_value_new = &ad799x_read_event_value, - .write_event_value_new = &ad799x_write_event_value, + .read_event_config = &ad799x_read_event_config, + .read_event_value = &ad799x_read_event_value, + .write_event_value = &ad799x_write_event_value, .driver_module = THIS_MODULE, .update_scan_mode = ad7997_8_update_scan_mode, }; diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 7e7f9890a642..047af2376300 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -576,10 +576,10 @@ static const struct iio_info ad7150_info = { .event_attrs = &ad7150_event_attribute_group, .driver_module = THIS_MODULE, .read_raw = &ad7150_read_raw, - .read_event_config_new = &ad7150_read_event_config, - .write_event_config_new = &ad7150_write_event_config, - .read_event_value_new = &ad7150_read_event_value, - .write_event_value_new = &ad7150_write_event_value, + .read_event_config = &ad7150_read_event_config, + .write_event_config = &ad7150_write_event_config, + .read_event_value = &ad7150_read_event_value, + .write_event_value = &ad7150_write_event_value, }; /* diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 1fac9894b18c..fd334a03a49a 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -370,10 +370,10 @@ static const struct iio_info iio_dummy_info = { .read_raw = &iio_dummy_read_raw, .write_raw = &iio_dummy_write_raw, #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS - .read_event_config_new = &iio_simple_dummy_read_event_config, - .write_event_config_new = &iio_simple_dummy_write_event_config, - .read_event_value_new = &iio_simple_dummy_read_event_value, - .write_event_value_new = &iio_simple_dummy_write_event_value, + .read_event_config = &iio_simple_dummy_read_event_config, + .write_event_config = &iio_simple_dummy_write_event_config, + .read_event_value = &iio_simple_dummy_read_event_value, + .write_event_value = &iio_simple_dummy_write_event_value, #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ }; diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 18805029d2a9..1e538086d48b 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -1672,10 +1672,10 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value_new = &tsl2x7x_read_thresh, - .write_event_value_new = &tsl2x7x_write_thresh, - .read_event_config_new = &tsl2x7x_read_interrupt_config, - .write_event_config_new = &tsl2x7x_write_interrupt_config, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, }, [PRX] = { .attrs = &tsl2X7X_device_attr_group_tbl[PRX], @@ -1683,10 +1683,10 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value_new = &tsl2x7x_read_thresh, - .write_event_value_new = &tsl2x7x_write_thresh, - .read_event_config_new = &tsl2x7x_read_interrupt_config, - .write_event_config_new = &tsl2x7x_write_interrupt_config, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, }, [ALSPRX] = { .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX], @@ -1694,10 +1694,10 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value_new = &tsl2x7x_read_thresh, - .write_event_value_new = &tsl2x7x_write_thresh, - .read_event_config_new = &tsl2x7x_read_interrupt_config, - .write_event_config_new = &tsl2x7x_write_interrupt_config, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, }, [PRX2] = { .attrs = &tsl2X7X_device_attr_group_tbl[PRX2], @@ -1705,10 +1705,10 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value_new = &tsl2x7x_read_thresh, - .write_event_value_new = &tsl2x7x_write_thresh, - .read_event_config_new = &tsl2x7x_read_interrupt_config, - .write_event_config_new = &tsl2x7x_write_interrupt_config, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, }, [ALSPRX2] = { .attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX2], @@ -1716,10 +1716,10 @@ static const struct iio_info tsl2X7X_device_info[] = { .driver_module = THIS_MODULE, .read_raw = &tsl2x7x_read_raw, .write_raw = &tsl2x7x_write_raw, - .read_event_value_new = &tsl2x7x_read_thresh, - .write_event_value_new = &tsl2x7x_write_thresh, - .read_event_config_new = &tsl2x7x_read_interrupt_config, - .write_event_config_new = &tsl2x7x_write_interrupt_config, + .read_event_value = &tsl2x7x_read_thresh, + .write_event_value = &tsl2x7x_write_thresh, + .read_event_config = &tsl2x7x_read_interrupt_config, + .write_event_config = &tsl2x7x_write_interrupt_config, }, }; diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h index 5dab2c41031f..8bbd7bc1043d 100644 --- a/include/linux/iio/events.h +++ b/include/linux/iio/events.h @@ -46,10 +46,6 @@ struct iio_event_data { ((u16)chan)) -#define IIO_EV_DIR_MAX 4 -#define IIO_EV_BIT(type, direction) \ - (1 << (type*IIO_EV_DIR_MAX + direction)) - /** * IIO_MOD_EVENT_CODE() - create event identifier for modified channels * @chan_type: Type of the channel. Should be one of enum iio_chan_type. diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 5b125fd554e4..75a8a20c8179 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -185,7 +185,6 @@ struct iio_event_spec { * by all channels of the same direction. * @info_mask_shared_by_all: What information is to be exported that is shared * by all channels. - * @event_mask: What events can this channel produce. * @event_spec: Array of events which should be registered for this * channel. * @num_event_specs: Size of the event_spec array. @@ -226,7 +225,6 @@ struct iio_chan_spec { long info_mask_shared_by_type; long info_mask_shared_by_dir; long info_mask_shared_by_all; - long event_mask; const struct iio_event_spec *event_spec; unsigned int num_event_specs; const struct iio_chan_spec_ext_info *ext_info; @@ -307,16 +305,8 @@ struct iio_dev; * returns IIO_VAL_INT_PLUS_MICRO. * @read_event_config: find out if the event is enabled. * @write_event_config: set if the event is enabled. - * @read_event_value: read a value associated with the event. Meaning - * is event dependant. event_code specifies which event. - * @write_event_value: write the value associated with the event. - * Meaning is event dependent. - * @read_event_config_new: find out if the event is enabled. New style interface. - * @write_event_config_new: set if the event is enabled. New style interface. - * @read_event_value_new: read a configuration value associated with the event. - * New style interface. - * @write_event_value_new: write a configuration value for the event. New style - * interface. + * @read_event_value: read a configuration value associated with the event. + * @write_event_value: write a configuration value for the event. * @validate_trigger: function to validate the trigger when the * current trigger gets changed. * @update_scan_mode: function to configure device and scan buffer when @@ -345,37 +335,23 @@ struct iio_info { long mask); int (*read_event_config)(struct iio_dev *indio_dev, - u64 event_code); - - int (*write_event_config)(struct iio_dev *indio_dev, - u64 event_code, - int state); - - int (*read_event_value)(struct iio_dev *indio_dev, - u64 event_code, - int *val); - int (*write_event_value)(struct iio_dev *indio_dev, - u64 event_code, - int val); - - int (*read_event_config_new)(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir); - int (*write_event_config_new)(struct iio_dev *indio_dev, + int (*write_event_config)(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, int state); - int (*read_event_value_new)(struct iio_dev *indio_dev, + int (*read_event_value)(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int *val, int *val2); - int (*write_event_value_new)(struct iio_dev *indio_dev, + int (*write_event_value)(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, -- cgit v1.2.3 From 42b6a1baa3ec18de2eb15baa250da6203eeb2d39 Mon Sep 17 00:00:00 2001 From: Randy Witt Date: Thu, 17 Oct 2013 16:56:47 -0400 Subject: serial_core: Don't re-initialize a previously initialized spinlock. The uart_set_options() code unconditionally initalizes the spinlock on the port. This can cause a deadlock in some situations. One instance that exposed the problem, was when writing to /sys/module/kgdboc/parameters/kgdboc to use ttyS0 when the console is already running on ttyS0. If the spinlock is re-initialized while the lock is held due to output to the console, there is a deadlock. Assume the spinlock is initialized if the port is a console. Signed-off-by: Randy Witt Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0f02351c9239..ece2049bd270 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1830,9 +1830,13 @@ uart_set_options(struct uart_port *port, struct console *co, /* * Ensure that the serial console lock is initialised * early. + * If this port is a console, then the spinlock is already + * initialised. */ - spin_lock_init(&port->lock); - lockdep_set_class(&port->lock, &port_lock_key); + if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) { + spin_lock_init(&port->lock); + lockdep_set_class(&port->lock, &port_lock_key); + } memset(&termios, 0, sizeof(struct ktermios)); -- cgit v1.2.3 From 8913a316e3f74b800c3a4e0d4c85cab26bbb9c53 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Tue, 26 Nov 2013 10:30:06 +0200 Subject: serial: 8250_dw: remove ACPI ifdef ACPI now provides stubs for the functions the driver uses. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 4658e3e0ec42..816ec88a0d7f 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -272,7 +272,6 @@ static int dw8250_probe_of(struct uart_port *p, return 0; } -#ifdef CONFIG_ACPI static int dw8250_probe_acpi(struct uart_8250_port *up, struct dw8250_data *data) { @@ -300,13 +299,6 @@ static int dw8250_probe_acpi(struct uart_8250_port *up, return 0; } -#else -static inline int dw8250_probe_acpi(struct uart_8250_port *up, - struct dw8250_data *data) -{ - return -ENODEV; -} -#endif /* CONFIG_ACPI */ static int dw8250_probe(struct platform_device *pdev) { -- cgit v1.2.3 From 187094feeb77b5f49513f6a1cfe12749c080bd96 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sun, 3 Nov 2013 18:38:12 +0200 Subject: serial: pl011: remove redundant early amba_ports declaration This early amba_ports declaration was introduced by commit c16d51a32 (amba pl011: workaround for uart registers lockup) for use in the pl011_lockup_wa() routine. This routine was later removed by commit 4fd0690bb (serial: pl011: implement workaround for CTS clear event issue). Signed-off-by: Baruch Siach Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 7203864992a5..742c8bf0c2d2 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -112,8 +112,6 @@ static struct vendor_data vendor_st = { .get_fifosize = get_fifosize_st, }; -static struct uart_amba_port *amba_ports[UART_NR]; - /* Deals with DMA transactions */ struct pl011_sgbuf { -- cgit v1.2.3 From 5c32d12378313e0096ea0d450462aa638a90fb6e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 14:24:41 -0500 Subject: n_tty: Merge .receive_buf() flavors N_TTY's direct and flow-controlled flavors of the .receive_buf() method are nearly identical; fold together. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0f74945af624..cf22bef62c98 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1674,32 +1674,9 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, } } -static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) -{ - int room, n; - - down_read(&tty->termios_rwsem); - - while (1) { - room = receive_room(tty); - n = min(count, room); - if (!n) - break; - __receive_buf(tty, cp, fp, n); - cp += n; - if (fp) - fp += n; - count -= n; - } - - tty->receive_room = room; - n_tty_check_throttle(tty); - up_read(&tty->termios_rwsem); -} - -static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static int +n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count, int flow) { struct n_tty_data *ldata = tty->disc_data; int room, n, rcvd = 0; @@ -1710,7 +1687,7 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, room = receive_room(tty); n = min(count, room); if (!n) { - if (!room) + if (flow && !room) ldata->no_room = 1; break; } @@ -1729,6 +1706,18 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, return rcvd; } +static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + n_tty_receive_buf_common(tty, cp, fp, count, 0); +} + +static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + return n_tty_receive_buf_common(tty, cp, fp, count, 1); +} + int is_ignored(int sig) { return (sigismember(¤t->blocked, sig) || -- cgit v1.2.3 From eb3e4668bd9e0bbda592e830e889f137e44ec9e4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 14:24:42 -0500 Subject: n_tty: Un-inline slow-path n_tty_receive_char() Commit e60d27c4d8b33ba20896b76b6558f061bc6460ff, n_tty: Factor LNEXT processing from per-char i/o path, mistakenly inlined the non-inline alias, n_tty_receive_char(), for the inline function, n_tty_receive_char_inline(). As n_tty_receive_char() is intended for slow-path char processing only, un-inline it. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index cf22bef62c98..8c20a52557ea 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1417,7 +1417,7 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) put_tty_queue(c, ldata); } -static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) +static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { n_tty_receive_char_inline(tty, c); } -- cgit v1.2.3 From 8dc4b25d2325002f716fffe2e35c9af43639c60f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 14:24:43 -0500 Subject: n_tty: Un-inline slow-path n_tty_receive_char_closing() Although n_tty_receive_char_closing() only has one call-site, let the compiler inline instead. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 8c20a52557ea..582a05c012f0 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1442,8 +1442,7 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) put_tty_queue(c, ldata); } -static inline void -n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) +static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) { if (I_ISTRIP(tty)) c &= 0x7f; -- cgit v1.2.3 From 001ba923719bc555552ac4c9fe8df4d8c888df39 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 14:24:44 -0500 Subject: n_tty: Refactor PARMRK doubling checks Perform PARMRK doubling checks explicitly; remove ternary idiom and local variable. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 582a05c012f0..649fd94d1aa6 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1257,7 +1257,6 @@ static int n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; - int parmrk; if (I_IXON(tty)) { if (c == START_CHAR(tty)) { @@ -1342,8 +1341,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) } if ((c == EOL_CHAR(tty)) || (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { - parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) - ? 1 : 0; /* * XXX are EOL_CHAR and EOL2_CHAR echoed?!? */ @@ -1358,7 +1355,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) * XXX does PARMRK doubling happen for * EOL_CHAR and EOL2_CHAR? */ - if (parmrk) + if (c == (unsigned char) '\377' && I_PARMRK(tty)) put_tty_queue(c, ldata); handle_newline: @@ -1372,7 +1369,6 @@ handle_newline: } } - parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (L_ECHO(tty)) { finish_erasing(ldata); if (c == '\n') @@ -1386,7 +1382,8 @@ handle_newline: commit_echoes(tty); } - if (parmrk) + /* PARMRK doubling check */ + if (c == (unsigned char) '\377' && I_PARMRK(tty)) put_tty_queue(c, ldata); put_tty_queue(c, ldata); @@ -1397,7 +1394,6 @@ static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; - int parmrk; if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); @@ -1411,8 +1407,8 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) echo_char(c, tty); commit_echoes(tty); } - parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (parmrk) + /* PARMRK doubling check */ + if (c == (unsigned char) '\377' && I_PARMRK(tty)) put_tty_queue(c, ldata); put_tty_queue(c, ldata); } -- cgit v1.2.3 From eafbe67f84761d787802e5113d895a316b6292fe Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 14:24:45 -0500 Subject: n_tty: Refactor input_available_p() by call site Distinguish if caller is n_tty_poll() or n_tty_read(), and set the read/wakeup threshold accordingly. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 649fd94d1aa6..2caa2936d1b1 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1869,14 +1869,15 @@ err: return -ENOMEM; } -static inline int input_available_p(struct tty_struct *tty, int amt) +static inline int input_available_p(struct tty_struct *tty, int poll) { struct n_tty_data *ldata = tty->disc_data; + int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1; if (ldata->icanon && !L_EXTPROC(tty)) { if (ldata->canon_head != ldata->read_tail) return 1; - } else if (read_cnt(ldata) >= (amt ? amt : 1)) + } else if (read_cnt(ldata) >= amt) return 1; return 0; @@ -2375,7 +2376,7 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, poll_wait(file, &tty->read_wait, wait); poll_wait(file, &tty->write_wait, wait); - if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty))) + if (input_available_p(tty, 1)) mask |= POLLIN | POLLRDNORM; if (tty->packet && tty->link->ctrl_status) mask |= POLLPRI | POLLIN | POLLRDNORM; -- cgit v1.2.3 From 6c67716d64103e5a8e23c45dcdfc76520033d479 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 14:24:46 -0500 Subject: n_tty: Only perform wakeups for waiters Only wakeup the _waiting_ reader, polls and/or writer(s). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 2caa2936d1b1..c7f8f7bc1423 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -274,7 +274,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) return; n_tty_set_room(tty); n_tty_write_wakeup(tty->link); - wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); + if (waitqueue_active(&tty->link->write_wait)) + wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); return; } @@ -349,7 +350,8 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) spin_lock_irqsave(&tty->ctrl_lock, flags); if (tty->link->packet) { tty->ctrl_status |= TIOCPKT_FLUSHREAD; - wake_up_interruptible(&tty->link->read_wait); + if (waitqueue_active(&tty->link->read_wait)) + wake_up_interruptible(&tty->link->read_wait); } spin_unlock_irqrestore(&tty->ctrl_lock, flags); } @@ -1155,7 +1157,8 @@ static void n_tty_receive_break(struct tty_struct *tty) put_tty_queue('\0', ldata); } put_tty_queue('\0', ldata); - wake_up_interruptible(&tty->read_wait); + if (waitqueue_active(&tty->read_wait)) + wake_up_interruptible(&tty->read_wait); } /** @@ -1213,7 +1216,8 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) put_tty_queue('\0', ldata); else put_tty_queue(c, ldata); - wake_up_interruptible(&tty->read_wait); + if (waitqueue_active(&tty->read_wait)) + wake_up_interruptible(&tty->read_wait); } static void @@ -1802,8 +1806,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) start_tty(tty); /* The termios change make the tty ready for I/O */ - wake_up_interruptible(&tty->write_wait); - wake_up_interruptible(&tty->read_wait); + if (waitqueue_active(&tty->write_wait)) + wake_up_interruptible(&tty->write_wait); + if (waitqueue_active(&tty->read_wait)) + wake_up_interruptible(&tty->read_wait); } /** -- cgit v1.2.3 From 82f91fe092b6eacd82e976b8955443f9fd97d07e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 13:56:03 -0500 Subject: tty: Always handle NULL flag ptr Most line disciplines already handle the undocumented NULL flag ptr in their .receive_buf method; however, several don't. Document the NULL flag ptr, and correct handling in the N_MOUSE, N_GSM0710 and N_R394 line disciplines. Signed-off-by: Peter Hurley Acked-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/serport.c | 28 +++++++++++++++------------- drivers/tty/n_gsm.c | 5 +++-- drivers/tty/n_r3964.c | 2 +- include/linux/tty_ldisc.h | 6 ++++-- 4 files changed, 23 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 8755f5f3ad37..0cb7ef59071b 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -124,7 +124,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c { struct serport *serport = (struct serport*) tty->disc_data; unsigned long flags; - unsigned int ch_flags; + unsigned int ch_flags = 0; int i; spin_lock_irqsave(&serport->lock, flags); @@ -133,18 +133,20 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c goto out; for (i = 0; i < count; i++) { - switch (fp[i]) { - case TTY_FRAME: - ch_flags = SERIO_FRAME; - break; - - case TTY_PARITY: - ch_flags = SERIO_PARITY; - break; - - default: - ch_flags = 0; - break; + if (fp) { + switch (fp[i]) { + case TTY_FRAME: + ch_flags = SERIO_FRAME; + break; + + case TTY_PARITY: + ch_flags = SERIO_PARITY; + break; + + default: + ch_flags = 0; + break; + } } serio_interrupt(serport->serio, cp[i], ch_flags); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c0f76da55304..c09db11b8831 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2269,14 +2269,15 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *f; int i; char buf[64]; - char flags; + char flags = TTY_NORMAL; if (debug & 4) print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET, cp, count); for (i = count, dp = cp, f = fp; i; i--, dp++) { - flags = *f++; + if (f) + flags = *f++; switch (flags) { case TTY_NORMAL: gsm->receive(gsm, *dp); diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 1e6405070ce6..8b157d68a03e 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -1244,7 +1244,7 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, { struct r3964_info *pInfo = tty->disc_data; const unsigned char *p; - char *f, flags = 0; + char *f, flags = TTY_NORMAL; int i; for (i = count, p = cp, f = fp; i; i--, p++) { diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index f15c898ff462..b8347c207cb8 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -84,7 +84,8 @@ * processing. is a pointer to the buffer of input * character received by the device. is a pointer to a * pointer of flag bytes which indicate whether a character was - * received with a parity error, etc. + * received with a parity error, etc. may be NULL to indicate + * all data received is TTY_NORMAL. * * void (*write_wakeup)(struct tty_struct *); * @@ -118,7 +119,8 @@ * processing. is a pointer to the buffer of input * character received by the device. is a pointer to a * pointer of flag bytes which indicate whether a character was - * received with a parity error, etc. + * received with a parity error, etc. may be NULL to indicate + * all data received is TTY_NORMAL. * If assigned, prefer this function for automatic flow control. */ -- cgit v1.2.3 From 4d18e6eff81e1d4d81d0942d5b7e96904b3b32df Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 12:09:55 -0500 Subject: tty: Enable configurable tty flip buffer limit Allow driver to configure its maximum flip buffer memory consumption/limit. This is necessary for very-high speed line rates (in excess of 10MB/sec) because the flip buffers can be saturated before the line discipline has a chance to throttle the input. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 24 +++++++++++++++++++++--- include/linux/tty.h | 1 + include/linux/tty_flip.h | 1 + 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index c043136fbe51..57eb34b2ec24 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -26,7 +26,7 @@ * Byte threshold to limit memory consumption for flip buffers. * The actual memory limit is > 2x this amount. */ -#define TTYB_MEM_LIMIT 65536 +#define TTYB_DEFAULT_MEM_LIMIT 65536 /* * We default to dicing tty buffer allocations to this many characters @@ -89,7 +89,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) int tty_buffer_space_avail(struct tty_port *port) { - int space = TTYB_MEM_LIMIT - atomic_read(&port->buf.memory_used); + int space = port->buf.mem_limit - atomic_read(&port->buf.memory_used); return max(space, 0); } @@ -162,7 +162,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) /* Should possibly check if this fails for the largest buffer we have queued and recycle that ? */ - if (atomic_read(&port->buf.memory_used) > TTYB_MEM_LIMIT) + if (atomic_read(&port->buf.memory_used) > port->buf.mem_limit) return NULL; p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); if (p == NULL) @@ -536,4 +536,22 @@ void tty_buffer_init(struct tty_port *port) atomic_set(&buf->memory_used, 0); atomic_set(&buf->priority, 0); INIT_WORK(&buf->work, flush_to_ldisc); + buf->mem_limit = TTYB_DEFAULT_MEM_LIMIT; } + +/** + * tty_buffer_set_limit - change the tty buffer memory limit + * @port: tty port to change + * + * Change the tty buffer memory limit. + * Must be called before the other tty buffer functions are used. + */ + +int tty_buffer_set_limit(struct tty_port *port, int limit) +{ + if (limit < MIN_TTYB_SIZE) + return -EINVAL; + port->buf.mem_limit = limit; + return 0; +} +EXPORT_SYMBOL_GPL(tty_buffer_set_limit); diff --git a/include/linux/tty.h b/include/linux/tty.h index 97d660ed70c1..2225745060d6 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -61,6 +61,7 @@ struct tty_bufhead { struct tty_buffer sentinel; struct llist_head free; /* Free queue head */ atomic_t memory_used; /* In-use buffers excluding free list */ + int mem_limit; struct tty_buffer *tail; /* Active buffer */ }; /* diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 21ddd7d9ea1f..2da8bc2a5486 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -1,6 +1,7 @@ #ifndef _LINUX_TTY_FLIP_H #define _LINUX_TTY_FLIP_H +extern int tty_buffer_set_limit(struct tty_port *port, int limit); extern int tty_buffer_space_avail(struct tty_port *port); extern int tty_buffer_request_room(struct tty_port *port, size_t size); extern int tty_insert_flip_string_flags(struct tty_port *port, -- cgit v1.2.3 From 5dda4ca5585270c7d6854da5f83e8e8d3e157094 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 12:09:56 -0500 Subject: tty: Rename tty buffer memory_used field Trim up the memory_used field name to mem_used. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 12 ++++++------ include/linux/tty.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 57eb34b2ec24..e8f22f833b4e 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -89,7 +89,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) int tty_buffer_space_avail(struct tty_port *port) { - int space = port->buf.mem_limit - atomic_read(&port->buf.memory_used); + int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used); return max(space, 0); } @@ -129,7 +129,7 @@ void tty_buffer_free_all(struct tty_port *port) buf->head = &buf->sentinel; buf->tail = &buf->sentinel; - atomic_set(&buf->memory_used, 0); + atomic_set(&buf->mem_used, 0); } /** @@ -162,7 +162,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) /* Should possibly check if this fails for the largest buffer we have queued and recycle that ? */ - if (atomic_read(&port->buf.memory_used) > port->buf.mem_limit) + if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit) return NULL; p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); if (p == NULL) @@ -170,7 +170,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) found: tty_buffer_reset(p, size); - atomic_add(size, &port->buf.memory_used); + atomic_add(size, &port->buf.mem_used); return p; } @@ -188,7 +188,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) struct tty_bufhead *buf = &port->buf; /* Dumb strategy for now - should keep some stats */ - WARN_ON(atomic_sub_return(b->size, &buf->memory_used) < 0); + WARN_ON(atomic_sub_return(b->size, &buf->mem_used) < 0); if (b->size > MIN_TTYB_SIZE) kfree(b); @@ -533,7 +533,7 @@ void tty_buffer_init(struct tty_port *port) buf->head = &buf->sentinel; buf->tail = &buf->sentinel; init_llist_head(&buf->free); - atomic_set(&buf->memory_used, 0); + atomic_set(&buf->mem_used, 0); atomic_set(&buf->priority, 0); INIT_WORK(&buf->work, flush_to_ldisc); buf->mem_limit = TTYB_DEFAULT_MEM_LIMIT; diff --git a/include/linux/tty.h b/include/linux/tty.h index 2225745060d6..38fcc0574ba9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -60,7 +60,7 @@ struct tty_bufhead { atomic_t priority; struct tty_buffer sentinel; struct llist_head free; /* Free queue head */ - atomic_t memory_used; /* In-use buffers excluding free list */ + atomic_t mem_used; /* In-use buffers excluding free list */ int mem_limit; struct tty_buffer *tail; /* Active buffer */ }; -- cgit v1.2.3 From 7e1e71d1546a28ea0ccc06320987e6c4ab2e1dbe Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 12:09:57 -0500 Subject: tty: Remove tty_prepare_flip_string_flags() There is no in-tree user of tty_prepare_flip_string_flags(); remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 28 ---------------------------- include/linux/tty_flip.h | 2 -- 2 files changed, 30 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index e8f22f833b4e..6a3620e1cc7a 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -373,34 +373,6 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, } EXPORT_SYMBOL_GPL(tty_prepare_flip_string); -/** - * tty_prepare_flip_string_flags - make room for characters - * @port: tty port - * @chars: return pointer for character write area - * @flags: return pointer for status flag write area - * @size: desired size - * - * Prepare a block of space in the buffer for data. Returns the length - * available and buffer pointer to the space which is now allocated and - * accounted for as ready for characters. This is used for drivers - * that need their own block copy routines into the buffer. There is no - * guarantee the buffer is a DMA target! - */ - -int tty_prepare_flip_string_flags(struct tty_port *port, - unsigned char **chars, char **flags, size_t size) -{ - int space = tty_buffer_request_room(port, size); - if (likely(space)) { - struct tty_buffer *tb = port->buf.tail; - *chars = char_buf_ptr(tb, tb->used); - *flags = flag_buf_ptr(tb, tb->used); - tb->used += space; - } - return space; -} -EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); - static int receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 2da8bc2a5486..3f821e98af0f 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -10,8 +10,6 @@ extern int tty_insert_flip_string_fixed_flag(struct tty_port *port, const unsigned char *chars, char flag, size_t size); extern int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, size_t size); -extern int tty_prepare_flip_string_flags(struct tty_port *port, - unsigned char **chars, char **flags, size_t size); extern void tty_flip_buffer_push(struct tty_port *port); void tty_schedule_flip(struct tty_port *port); -- cgit v1.2.3 From c4a8dab5806188fb2a752467b63a7fd19bcbf0ec Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 13:06:08 -0500 Subject: staging/fwserial: Rip out rx buffering Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 128 ++++++++---------------------------- drivers/staging/fwserial/fwserial.h | 16 ----- drivers/tty/tty_buffer.c | 1 + 3 files changed, 28 insertions(+), 117 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 62df009e5ac7..ed7806b8b1dc 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -456,16 +456,27 @@ static int fwtty_write_port_status(struct fwtty_port *port) return err; } -static void __fwtty_throttle(struct fwtty_port *port, struct tty_struct *tty) +static void fwtty_throttle_port(struct fwtty_port *port) { + struct tty_struct *tty; unsigned old; + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + + spin_lock_bh(&port->lock); + old = port->mctrl; port->mctrl |= OOB_RX_THROTTLE; if (C_CRTSCTS(tty)) port->mctrl &= ~TIOCM_RTS; if (~old & OOB_RX_THROTTLE) __fwtty_write_port_status(port); + + spin_unlock_bh(&port->lock); + + tty_kref_put(tty); } /** @@ -532,74 +543,8 @@ static void fwtty_emit_breaks(struct work_struct *work) port->icount.brk += brk; } -static void fwtty_pushrx(struct work_struct *work) -{ - struct fwtty_port *port = to_port(work, push); - struct tty_struct *tty; - struct buffered_rx *buf, *next; - int n, c = 0; - - spin_lock_bh(&port->lock); - list_for_each_entry_safe(buf, next, &port->buf_list, list) { - n = tty_insert_flip_string_fixed_flag(&port->port, buf->data, - TTY_NORMAL, buf->n); - c += n; - port->buffered -= n; - if (n < buf->n) { - if (n > 0) { - memmove(buf->data, buf->data + n, buf->n - n); - buf->n -= n; - } - tty = tty_port_tty_get(&port->port); - if (tty) { - __fwtty_throttle(port, tty); - tty_kref_put(tty); - } - break; - } else { - list_del(&buf->list); - kfree(buf); - } - } - if (c > 0) - tty_flip_buffer_push(&port->port); - - if (list_empty(&port->buf_list)) - clear_bit(BUFFERING_RX, &port->flags); - spin_unlock_bh(&port->lock); -} - -static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n) -{ - struct buffered_rx *buf; - size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF; - - if (port->buffered + n > HIGH_WATERMARK) { - fwtty_err_ratelimited(port, "overflowed rx buffer: buffered: %d new: %zu wtrmk: %d\n", - port->buffered, n, HIGH_WATERMARK); - return 0; - } - buf = kmalloc(size, GFP_ATOMIC); - if (!buf) - return 0; - INIT_LIST_HEAD(&buf->list); - buf->n = n; - memcpy(buf->data, d, n); - - spin_lock_bh(&port->lock); - list_add_tail(&buf->list, &port->buf_list); - port->buffered += n; - if (port->buffered > port->stats.watermark) - port->stats.watermark = port->buffered; - set_bit(BUFFERING_RX, &port->flags); - spin_unlock_bh(&port->lock); - - return n; -} - static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) { - struct tty_struct *tty; int c, n = len; unsigned lsr; int err = 0; @@ -636,31 +581,24 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) goto out; } - if (!test_bit(BUFFERING_RX, &port->flags)) { - c = tty_insert_flip_string_fixed_flag(&port->port, data, - TTY_NORMAL, n); - if (c > 0) - tty_flip_buffer_push(&port->port); - n -= c; - - if (n) { - /* start buffering and throttling */ - n -= fwtty_buffer_rx(port, &data[c], n); - - tty = tty_port_tty_get(&port->port); - if (tty) { - spin_lock_bh(&port->lock); - __fwtty_throttle(port, tty); - spin_unlock_bh(&port->lock); - tty_kref_put(tty); - } - } - } else - n -= fwtty_buffer_rx(port, data, n); + c = tty_insert_flip_string_fixed_flag(&port->port, data, TTY_NORMAL, n); + if (c > 0) + tty_flip_buffer_push(&port->port); + n -= c; if (n) { port->overrun = true; err = -EIO; + fwtty_err_ratelimited(port, "flip buffer overrun\n"); + + } else { + /* throttle the sender if remaining flip buffer space has + * reached high watermark to avoid losing data which may be + * in-flight. Since the AR request context is 32k, that much + * data may have _already_ been acked. + */ + if (tty_buffer_space_avail(&port->port) < HIGH_WATERMARK) + fwtty_throttle_port(port); } out: @@ -1101,20 +1039,13 @@ static int fwtty_port_activate(struct tty_port *tty_port, static void fwtty_port_shutdown(struct tty_port *tty_port) { struct fwtty_port *port = to_port(tty_port, port); - struct buffered_rx *buf, *next; /* TODO: cancel outstanding transactions */ cancel_delayed_work_sync(&port->emit_breaks); cancel_delayed_work_sync(&port->drain); - cancel_work_sync(&port->push); spin_lock_bh(&port->lock); - list_for_each_entry_safe(buf, next, &port->buf_list, list) { - list_del(&buf->list); - kfree(buf); - } - port->buffered = 0; port->flags = 0; port->break_ctl = 0; port->overrun = 0; @@ -1264,8 +1195,6 @@ static void fwtty_unthrottle(struct tty_struct *tty) profile_fifo_avail(port, port->stats.unthrottle); - schedule_work(&port->push); - spin_lock_bh(&port->lock); port->mctrl &= ~OOB_RX_THROTTLE; if (C_CRTSCTS(tty)) @@ -1523,8 +1452,7 @@ static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port) seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped, stats.tx_stall, stats.fifo_errs, stats.lost); - seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled, - stats.watermark); + seq_printf(m, " pkts:%d thr:%d", stats.sent, stats.throttled); if (port->port.console) { seq_puts(m, "\n "); @@ -2302,8 +2230,6 @@ static int fwserial_create(struct fw_unit *unit) INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx); INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks); INIT_WORK(&port->hangup, fwtty_do_hangup); - INIT_WORK(&port->push, fwtty_pushrx); - INIT_LIST_HEAD(&port->buf_list); init_waitqueue_head(&port->wait_tx); port->max_payload = link_speed_to_max_payload(SCODE_100); dma_fifo_init(&port->tx_fifo); diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 24635014a2ac..149b24dd0ba6 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -166,7 +166,6 @@ struct stats { unsigned sent; unsigned lost; unsigned throttled; - unsigned watermark; unsigned reads[DISTRIBUTION_MAX_INDEX + 1]; unsigned writes[DISTRIBUTION_MAX_INDEX + 1]; unsigned txns[DISTRIBUTION_MAX_INDEX + 1]; @@ -183,12 +182,6 @@ struct fwconsole_ops { #define FWCON_NOTIFY_ATTACH 1 #define FWCON_NOTIFY_DETACH 2 -struct buffered_rx { - struct list_head list; - size_t n; - unsigned char data[0]; -}; - /** * fwtty_port: structure used to track/represent underlying tty_port * @port: underlying tty_port @@ -223,11 +216,6 @@ struct buffered_rx { * The work can race with the writer but concurrent sending is * prevented with the IN_TX flag. Scheduled under lock to * limit scheduling when fifo has just been drained. - * @push: work responsible for pushing buffered rx to the ldisc. - * rx can become buffered if the tty buffer is filled before the - * ldisc throttles the sender. - * @buf_list: list of buffered rx yet to be sent to ldisc - * @buffered: byte count of buffered rx * @tx_fifo: fifo used to store & block-up writes for dma to remote * @max_payload: max bytes transmissable per dma (based on peer's max_payload) * @status_mask: UART_LSR_* bitmask significant to rx (based on termios) @@ -267,9 +255,6 @@ struct fwtty_port { spinlock_t lock; unsigned mctrl; struct delayed_work drain; - struct work_struct push; - struct list_head buf_list; - int buffered; struct dma_fifo tx_fifo; int max_payload; unsigned status_mask; @@ -291,7 +276,6 @@ struct fwtty_port { /* bit #s for flags field */ #define IN_TX 0 #define STOP_TX 1 -#define BUFFERING_RX 2 /* bitmasks for special mctrl/mstatus bits */ #define OOB_RX_THROTTLE 0x00010000 diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 6a3620e1cc7a..6454c0a747ef 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -92,6 +92,7 @@ int tty_buffer_space_avail(struct tty_port *port) int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used); return max(space, 0); } +EXPORT_SYMBOL_GPL(tty_buffer_space_avail); static void tty_buffer_reset(struct tty_buffer *p, size_t size) { -- cgit v1.2.3 From 2ead3911e0910f19bf0d9c623ed73f70db8e0c24 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 13:06:09 -0500 Subject: staging/fwserial: Up the tty buffer limit to 128K The firewire driver can overrun the tty buffers before the line discipline can throttle the input; up the buffer limit. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index ed7806b8b1dc..656fdcbd845a 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -2225,6 +2225,7 @@ static int fwserial_create(struct fw_unit *unit) port->index = FWTTY_INVALID_INDEX; port->port.ops = &fwtty_port_ops; port->serial = serial; + tty_buffer_set_limit(&port->port, 128 * 1024); spin_lock_init(&port->lock); INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx); -- cgit v1.2.3 From 49bb8405b4a8d3d357237770f965e7c6be4377c5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 13:06:10 -0500 Subject: staging/fwserial: Rename data profiling functions Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 22 +++++++++++----------- drivers/staging/fwserial/fwserial.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 656fdcbd845a..8af136e9c9dc 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -136,14 +136,14 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card, #ifdef FWTTY_PROFILING -static void profile_fifo_avail(struct fwtty_port *port, unsigned *stat) +static void fwtty_profile_fifo(struct fwtty_port *port, unsigned *stat) { spin_lock_bh(&port->lock); - profile_size_distrib(stat, dma_fifo_avail(&port->tx_fifo)); + fwtty_profile_data(stat, dma_fifo_avail(&port->tx_fifo)); spin_unlock_bh(&port->lock); } -static void dump_profile(struct seq_file *m, struct stats *stats) +static void fwtty_dump_profile(struct seq_file *m, struct stats *stats) { /* for each stat, print sum of 0 to 2^k, then individually */ int k = 4; @@ -183,8 +183,8 @@ static void dump_profile(struct seq_file *m, struct stats *stats) } #else -#define profile_fifo_avail(port, stat) -#define dump_profile(m, stats) +#define fwtty_profile_fifo(port, stat) +#define fwtty_dump_profile(m, stats) #endif /* @@ -550,7 +550,7 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) int err = 0; fwtty_dbg(port, "%d\n", n); - profile_size_distrib(port->stats.reads, n); + fwtty_profile_data(port->stats.reads, n); if (port->write_only) { n = 0; @@ -759,7 +759,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain) if (n == -EAGAIN) ++port->stats.tx_stall; else if (n == -ENODATA) - profile_size_distrib(port->stats.txns, 0); + fwtty_profile_data(port->stats.txns, 0); else { ++port->stats.fifo_errs; fwtty_err_ratelimited(port, "fifo err: %d\n", @@ -768,7 +768,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain) break; } - profile_size_distrib(port->stats.txns, txn->dma_pended.len); + fwtty_profile_data(port->stats.txns, txn->dma_pended.len); fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST, peer->fifo_addr, txn->dma_pended.data, @@ -1115,7 +1115,7 @@ static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c) int n, len; fwtty_dbg(port, "%d\n", c); - profile_size_distrib(port->stats.writes, c); + fwtty_profile_data(port->stats.writes, c); spin_lock_bh(&port->lock); n = dma_fifo_in(&port->tx_fifo, buf, c); @@ -1193,7 +1193,7 @@ static void fwtty_unthrottle(struct tty_struct *tty) fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0)); - profile_fifo_avail(port, port->stats.unthrottle); + fwtty_profile_fifo(port, port->stats.unthrottle); spin_lock_bh(&port->lock); port->mctrl &= ~OOB_RX_THROTTLE; @@ -1459,7 +1459,7 @@ static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port) (*port->fwcon_ops->proc_show)(m, port->con_data); } - dump_profile(m, &port->stats); + fwtty_dump_profile(m, &port->stats); } static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer) diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 149b24dd0ba6..eab85b49293c 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -22,14 +22,14 @@ #ifdef FWTTY_PROFILING #define DISTRIBUTION_MAX_SIZE 8192 #define DISTRIBUTION_MAX_INDEX (ilog2(DISTRIBUTION_MAX_SIZE) + 1) -static inline void profile_size_distrib(unsigned stat[], unsigned val) +static inline void fwtty_profile_data(unsigned stat[], unsigned val) { int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0; ++stat[n]; } #else #define DISTRIBUTION_MAX_INDEX 0 -#define profile_size_distrib(st, n) +#define fwtty_profile_data(st, n) #endif /* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */ -- cgit v1.2.3 From 87a5a0371b7356c99f16363b80107602f110fcda Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 13:06:11 -0500 Subject: staging/fwserial: Add Kconfig options for max ports Allow kernel configuration of max supported ports for TTY-over-Firewire driver. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/Kconfig | 20 ++++++++++++++++++++ drivers/staging/fwserial/fwserial.h | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig index a0812d99136f..9c7c9267d52c 100644 --- a/drivers/staging/fwserial/Kconfig +++ b/drivers/staging/fwserial/Kconfig @@ -9,3 +9,23 @@ config FIREWIRE_SERIAL To compile this driver as a module, say M here: the module will be called firewire-serial. + +if FIREWIRE_SERIAL + +config FWTTY_MAX_TOTAL_PORTS + int "Maximum number of serial ports supported" + default "64" + help + Set this to the maximum number of serial ports you want the + firewire-serial driver to support. + +config FWTTY_MAX_CARD_PORTS + int "Maximum number of serial ports supported per adapter" + range 0 FWTTY_MAX_TOTAL_PORTS + default "32" + help + Set this to the maximum number of serial ports each firewire + adapter supports. The actual number of serial ports registered + is set with the module parameter "ttys". + +endif diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index eab85b49293c..54f7f9b9b212 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -291,8 +291,8 @@ struct fwtty_port { #define FREQ_BREAKS (HZ / 50) /* Ports are allocated in blocks of num_ports for each fw_card */ -#define MAX_CARD_PORTS 32 /* max # of ports per card */ -#define MAX_TOTAL_PORTS 64 /* max # of ports total */ +#define MAX_CARD_PORTS CONFIG_FWTTY_MAX_CARD_PORTS +#define MAX_TOTAL_PORTS CONFIG_FWTTY_MAX_TOTAL_PORTS /* tuning parameters */ #define FWTTY_PORT_TXFIFO_LEN 4096 -- cgit v1.2.3 From 9cfb5e30951e484a403793d67d9ba0e2d4a188fd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 11:19:41 +0900 Subject: serial: pch_uart: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 0aa2b528ef3d..11c862c6bac8 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1853,7 +1853,6 @@ static void pch_uart_exit_port(struct eg20t_port *priv) debugfs_remove(priv->debugfs); #endif uart_remove_one_port(&pch_uart_driver, &priv->port); - pci_set_drvdata(priv->pdev, NULL); free_page((unsigned long)priv->rxbuf.buf); } -- cgit v1.2.3 From f166b4981472baa9af2ae29984ea08e0eb62ca6c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 11:16:33 +0900 Subject: parport_serial: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_serial.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 1b8bdb7e9bf4..ff53314100f6 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -596,13 +596,11 @@ static int parport_serial_pci_probe(struct pci_dev *dev, err = pci_enable_device (dev); if (err) { - pci_set_drvdata (dev, NULL); kfree (priv); return err; } if (parport_register (dev, id)) { - pci_set_drvdata (dev, NULL); kfree (priv); return -ENODEV; } @@ -611,7 +609,6 @@ static int parport_serial_pci_probe(struct pci_dev *dev, int i; for (i = 0; i < priv->num_par; i++) parport_pc_unregister_port (priv->port[i]); - pci_set_drvdata (dev, NULL); kfree (priv); return -ENODEV; } @@ -624,8 +621,6 @@ static void parport_serial_pci_remove(struct pci_dev *dev) struct parport_serial_private *priv = pci_get_drvdata (dev); int i; - pci_set_drvdata(dev, NULL); - // Serial ports if (priv->serial) pciserial_remove_ports(priv->serial); -- cgit v1.2.3 From dfabf7ffa30585fe491341f069df926cc28670ac Mon Sep 17 00:00:00 2001 From: Chao Bi Date: Tue, 26 Nov 2013 12:09:39 +0800 Subject: n_gsm: race between ld close and gsmtty open ttyA has ld associated to n_gsm, when ttyA is closing, it triggers to release gsmttyB's ld data dlci[B], then race would happen if gsmttyB is opening in parallel. (Note: This patch set differs from previous set in that it uses mutex instead of spin lock to avoid race, so that it avoids sleeping in automic context) Here are race cases we found recently in test: CASE #1 ==================================================================== releasing dlci[B] race with gsmtty_install(gsmttyB), then panic in gsmtty_open(gsmttyB), as below: tty_release(ttyA) tty_open(gsmttyB) | | ----- gsmtty_install(gsmttyB) | | ----- gsm_dlci_alloc(gsmttyB) => alloc dlci[B] tty_ldisc_release(ttyA) ----- | | gsm_dlci_release(dlci[B]) ----- | | gsm_dlci_free(dlci[B]) ----- | | ----- gsmtty_open(gsmttyB) gsmtty_open() { struct gsm_dlci *dlci = tty->driver_data; => here it uses dlci[B] ... } In gsmtty_open(gsmttyA), it uses dlci[B] which was release, so hit a panic. ===================================================================== CASE #2 ===================================================================== releasing dlci[0] race with gsmtty_install(gsmttyB), then panic in gsmtty_open(), as below: tty_release(ttyA) tty_open(gsmttyB) | | ----- gsmtty_install(gsmttyB) | | ----- gsm_dlci_alloc(gsmttyB) => alloc dlci[B] | | ----- gsmtty_open(gsmttyB) fail | | ----- tty_release(gsmttyB) | | ----- gsmtty_close(gsmttyB) | | ----- gsmtty_detach_dlci(dlci[B]) | | ----- dlci_put(dlci[B]) | | tty_ldisc_release(ttyA) ----- | | gsm_dlci_release(dlci[0]) ----- | | gsm_dlci_free(dlci[0]) ----- | | ----- dlci_put(dlci[0]) In gsmtty_detach_dlci(dlci[B]), it tries to use dlci[0] which was released, then hit panic. ===================================================================== IMHO, n_gsm tty operations would refer released ldisc, as long as gsm_dlci_release() has chance to release ldisc data when some gsmtty operations are ongoing.. This patch is try to avoid it by: 1) in n_gsm driver, use a global gsm mutex lock to avoid gsm_dlci_release() run in parallel with gsmtty_install(); 2) Increase dlci's ref count in gsmtty_install() instead of in gsmtty_open(), the purpose is to prevent gsm_dlci_release() releasing dlci after gsmtty_install() allocats dlci but before gsmtty_open increases dlci's ref count; 3) Decrease dlci's ref count in gsmtty_remove(), a tty framework API, this is the opposite process of step 2). Signed-off-by: Chao Bi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c09db11b8831..679294b37653 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -194,6 +194,7 @@ struct gsm_control { struct gsm_mux { struct tty_struct *tty; /* The tty our ldisc is bound to */ spinlock_t lock; + struct mutex mutex; unsigned int num; struct kref ref; @@ -2054,9 +2055,11 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) dlci->state == DLCI_CLOSED); } /* Free up any link layer users */ + mutex_lock(&gsm->mutex); for (i = 0; i < NUM_DLCI; i++) if (gsm->dlci[i]) gsm_dlci_release(gsm->dlci[i]); + mutex_unlock(&gsm->mutex); /* Now wipe the queues */ list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) kfree(txq); @@ -2170,6 +2173,7 @@ struct gsm_mux *gsm_alloc_mux(void) return NULL; } spin_lock_init(&gsm->lock); + mutex_init(&gsm->mutex); kref_init(&gsm->ref); INIT_LIST_HEAD(&gsm->tx_list); @@ -2910,23 +2914,33 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) This is ok from a locking perspective as we don't have to worry about this if DLCI0 is lost */ - if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) + mutex_lock(&gsm->mutex); + if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) { + mutex_unlock(&gsm->mutex); return -EL2NSYNC; + } dlci = gsm->dlci[line]; if (dlci == NULL) { alloc = true; dlci = gsm_dlci_alloc(gsm, line); } - if (dlci == NULL) + if (dlci == NULL) { + mutex_unlock(&gsm->mutex); return -ENOMEM; + } ret = tty_port_install(&dlci->port, driver, tty); if (ret) { if (alloc) dlci_put(dlci); + mutex_unlock(&gsm->mutex); return ret; } + dlci_get(dlci); + dlci_get(gsm->dlci[0]); + mux_get(gsm); tty->driver_data = dlci; + mutex_unlock(&gsm->mutex); return 0; } @@ -2937,9 +2951,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) struct tty_port *port = &dlci->port; port->count++; - dlci_get(dlci); - dlci_get(dlci->gsm->dlci[0]); - mux_get(dlci->gsm); tty_port_tty_set(port, tty); dlci->modem_rx = 0; @@ -2966,7 +2977,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&dlci->mutex); gsm = dlci->gsm; if (tty_port_close_start(&dlci->port, tty, filp) == 0) - goto out; + return; gsm_dlci_begin_close(dlci); if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) { if (C_HUPCL(tty)) @@ -2974,10 +2985,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) } tty_port_close_end(&dlci->port, tty); tty_port_tty_set(&dlci->port, NULL); -out: - dlci_put(dlci); - dlci_put(gsm->dlci[0]); - mux_put(gsm); + return; } static void gsmtty_hangup(struct tty_struct *tty) @@ -3154,6 +3162,16 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) return gsmtty_modem_update(dlci, encode); } +static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) +{ + struct gsm_dlci *dlci = tty->driver_data; + struct gsm_mux *gsm = dlci->gsm; + + dlci_put(dlci); + dlci_put(gsm->dlci[0]); + mux_put(gsm); + driver->ttys[tty->index] = NULL; +} /* Virtual ttys for the demux */ static const struct tty_operations gsmtty_ops = { @@ -3173,6 +3191,7 @@ static const struct tty_operations gsmtty_ops = { .tiocmget = gsmtty_tiocmget, .tiocmset = gsmtty_tiocmset, .break_ctl = gsmtty_break_ctl, + .remove = gsmtty_remove, }; -- cgit v1.2.3 From d0ce850d60166e99d5cca011d4b871a7cc1f930c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 3 Dec 2013 11:04:28 +0100 Subject: serial: pl011: Convert to modern PM ops Convert to modern PM ops and use the SIMPLE_DEV_PM_OPS macro to set up the PM callbacks. Cc: Greg Kroah-Hartman Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 742c8bf0c2d2..a183aceb6d15 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2167,10 +2167,10 @@ static int pl011_remove(struct amba_device *dev) return 0; } -#ifdef CONFIG_PM -static int pl011_suspend(struct amba_device *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pl011_suspend(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (!uap) return -EINVAL; @@ -2178,9 +2178,9 @@ static int pl011_suspend(struct amba_device *dev, pm_message_t state) return uart_suspend_port(&amba_reg, &uap->port); } -static int pl011_resume(struct amba_device *dev) +static int pl011_resume(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (!uap) return -EINVAL; @@ -2189,6 +2189,8 @@ static int pl011_resume(struct amba_device *dev) } #endif +static SIMPLE_DEV_PM_OPS(pl011_dev_pm_ops, pl011_suspend, pl011_resume); + static struct amba_id pl011_ids[] = { { .id = 0x00041011, @@ -2208,14 +2210,11 @@ MODULE_DEVICE_TABLE(amba, pl011_ids); static struct amba_driver pl011_driver = { .drv = { .name = "uart-pl011", + .pm = &pl011_dev_pm_ops, }, .id_table = pl011_ids, .probe = pl011_probe, .remove = pl011_remove, -#ifdef CONFIG_PM - .suspend = pl011_suspend, - .resume = pl011_resume, -#endif }; static int __init pl011_init(void) -- cgit v1.2.3 From 17438217a6f5e33d920ed3821a4b857311cc2872 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 28 Nov 2013 10:41:04 +0100 Subject: serial: pl011: use DMA RX polling by default Making DMA RX polling optional when DMA is on was just over-cautious: there is one single system in the kernel tree using this facility, Ux500 and after some testing I turned this on also for Ux500, which means it should simply be on by default if DMA is enabled. Cc: Jongsung Kim Cc: Chanho Min Cc: Russell King Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 +- include/linux/amba/serial.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index a183aceb6d15..c8cc8f02b092 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -325,7 +325,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * dmaengine_slave_config(chan, &rx_conf); uap->dmarx.chan = chan; - if (plat && plat->dma_rx_poll_enable) { + if (plat) { /* Set poll rate if specified. */ if (plat->dma_rx_poll_rate) { uap->dmarx.auto_poll_rate = false; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index 0ddb5c02ad8b..0891ea0458f6 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -203,7 +203,6 @@ struct amba_pl011_data { bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; - bool dma_rx_poll_enable; unsigned int dma_rx_poll_rate; unsigned int dma_rx_poll_timeout; void (*init) (void); -- cgit v1.2.3 From 6b471a9840eefc96abb3fbd9eb71e1eb93399daa Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 29 Nov 2013 17:29:24 +0800 Subject: serial: imx: add support for loopback mode. Add the loopback mode support for imx uart driver. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index b2cfdb661947..d799140e53b6 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -806,6 +806,9 @@ static unsigned int imx_get_mctrl(struct uart_port *port) if (readl(sport->port.membase + UCR2) & UCR2_CTS) tmp |= TIOCM_RTS; + if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP) + tmp |= TIOCM_LOOP; + return tmp; } @@ -821,6 +824,11 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) temp |= UCR2_CTS; writel(temp, sport->port.membase + UCR2); + + temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP; + if (mctrl & TIOCM_LOOP) + temp |= UTS_LOOP; + writel(temp, sport->port.membase + uts_reg(sport)); } /* -- cgit v1.2.3 From 311df74ade503af204ac6b8ee55ce30ff2411398 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:26:37 +0900 Subject: tty: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/rocket.c | 2 +- drivers/tty/serial/pch_uart.c | 2 +- drivers/tty/serial/rp2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 354564ea47c5..383c4c796637 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1744,7 +1744,7 @@ static void rp_flush_buffer(struct tty_struct *tty) #ifdef CONFIG_PCI -static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = { +static const struct pci_device_id rocket_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4QUAD) }, { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8OCTA) }, { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8OCTA) }, diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 11c862c6bac8..9cbd3acaf37f 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1906,7 +1906,7 @@ static int pch_uart_pci_resume(struct pci_dev *pdev) #define pch_uart_pci_resume NULL #endif -static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { +static const struct pci_device_id pch_uart_pci_id[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), .driver_data = pch_et20t_uart0}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812), diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c index 328d6deb6b08..056f91b3a4ca 100644 --- a/drivers/tty/serial/rp2.c +++ b/drivers/tty/serial/rp2.c @@ -810,7 +810,7 @@ static void rp2_remove(struct pci_dev *pdev) rp2_remove_ports(card); } -static DEFINE_PCI_DEVICE_TABLE(rp2_pci_tbl) = { +static const struct pci_device_id rp2_pci_tbl[] = { /* RocketPort INFINITY cards */ -- cgit v1.2.3 From 95468240d833314995e482bd4c75cfe660919e9a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 3 Dec 2013 11:04:27 +0100 Subject: serial: pl010: Convert to modern PM ops Convert to modern PM ops and use the SIMPLE_DEV_PM_OPS macro to set up the PM callbacks. Cc: Greg Kroah-Hartman Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl010.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 33bd8606be62..01c9e72433e1 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -756,9 +756,10 @@ static int pl010_remove(struct amba_device *dev) return 0; } -static int pl010_suspend(struct amba_device *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pl010_suspend(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (uap) uart_suspend_port(&amba_reg, &uap->port); @@ -766,15 +767,18 @@ static int pl010_suspend(struct amba_device *dev, pm_message_t state) return 0; } -static int pl010_resume(struct amba_device *dev) +static int pl010_resume(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (uap) uart_resume_port(&amba_reg, &uap->port); return 0; } +#endif + +static SIMPLE_DEV_PM_OPS(pl010_dev_pm_ops, pl010_suspend, pl010_resume); static struct amba_id pl010_ids[] = { { @@ -789,12 +793,11 @@ MODULE_DEVICE_TABLE(amba, pl010_ids); static struct amba_driver pl010_driver = { .drv = { .name = "uart-pl010", + .pm = &pl010_dev_pm_ops, }, .id_table = pl010_ids, .probe = pl010_probe, .remove = pl010_remove, - .suspend = pl010_suspend, - .resume = pl010_resume, }; static int __init pl010_init(void) -- cgit v1.2.3 From 753023dcdd2da515f991aa0e6a65016713f0c24f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Dec 2013 16:12:02 -0500 Subject: tty: Fix stale tty_buffer_flush() comment Commit d7a68be4f265be10e24be931c257af30ca55566b, 'tty: Only perform flip buffer flush from tty_buffer_flush()', removed buffer flushing from flush_to_ldisc(). Fix function header comment which describes the former behavior. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 6454c0a747ef..08835a6dd022 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -201,9 +201,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) * tty_buffer_flush - flush full tty buffers * @tty: tty to flush * - * flush all the buffers containing receive data. If the buffer is - * being processed by flush_to_ldisc then we defer the processing - * to that function + * flush all the buffers containing receive data. * * Locking: takes buffer lock to ensure single-threaded flip buffer * 'consumer' -- cgit v1.2.3 From 9bbc3dca9d2212f900396ab9642c48279657a8c0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Dec 2013 01:17:58 -0200 Subject: tty: serial: mxs-auart: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mxs-auart.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index d8b6fee77a03..aa97fd845b4d 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -734,9 +734,12 @@ static void mxs_auart_reset(struct uart_port *u) static int mxs_auart_startup(struct uart_port *u) { + int ret; struct mxs_auart_port *s = to_auart_port(u); - clk_prepare_enable(s->clk); + ret = clk_prepare_enable(s->clk); + if (ret) + return ret; writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); @@ -957,7 +960,9 @@ auart_console_setup(struct console *co, char *options) if (!s) return -ENODEV; - clk_prepare_enable(s->clk); + ret = clk_prepare_enable(s->clk); + if (ret) + return ret; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); -- cgit v1.2.3 From 0da3336f19f2a42e9153efa4112d50fd148a8e61 Mon Sep 17 00:00:00 2001 From: Heiko Stübner Date: Thu, 5 Dec 2013 00:54:38 +0100 Subject: serial: samsung: move clock deactivation below uart registration Commit 60e93575476f (serial: samsung: enable clock before clearing pending interrupts during init) added handling of the controller clock during init. On most systems this clock is also one of the baud_clock sources and possibly used by the earlycon and thus already enabled by the bootloader. Therefore a gap exists between s3c24xx_serial_init_port disabling the clock and an attached console reenabling it, making the transition from earlycon to regular console possibly hang the system - as seen on my S3C2442 based Freerunner today. Therefore move the disabling of the clock from s3c24xx_serial_init_port below the uart port registration, effectively creating an overlap and keeping the clock running non-stop if the console wants to grab this port. Signed-off-by: Heiko Stuebner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index c1af04d46682..9cd706df3b33 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1209,7 +1209,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, /* reset the fifos (and setup the uart) */ s3c24xx_serial_resetport(port, cfg); - clk_disable_unprepare(ourport->clk); return 0; } @@ -1287,6 +1286,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); platform_set_drvdata(pdev, &ourport->port); + /* + * Deactivate the clock enabled in s3c24xx_serial_init_port here, + * so that a potential re-enablement through the pm-callback overlaps + * and keeps the clock enabled in this case. + */ + clk_disable_unprepare(ourport->clk); + #ifdef CONFIG_SAMSUNG_CLOCK ret = device_create_file(&pdev->dev, &dev_attr_clock_source); if (ret < 0) -- cgit v1.2.3 From e41c0981213f39ecd421d8c1f7334cf04c2122e3 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 4 Dec 2013 20:52:49 +0100 Subject: tty: serial: pch: don't crash if DMA enabled but not loaded if the DMA driver isn't loaded "on time" then we crash in the irq handler: | pch_uart 0000:02:0a.4: pch_request_dma:dma_request_channel FAILS(Tx) | BUG: unable to handle kernel NULL pointer dereference at (null) | IP: [] pch_uart_interrupt+0x739/0x940 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 0aa2b528ef3d..6bb7e90c8f22 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1508,10 +1508,14 @@ static int pch_uart_verify_port(struct uart_port *port, __func__); return -EOPNOTSUPP; #endif - dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n"); - if (!priv->use_dma) + if (!priv->use_dma) { pch_request_dma(port); - priv->use_dma = 1; + if (priv->chan_rx) + priv->use_dma = 1; + } + dev_info(priv->port.dev, "PCH UART: %s\n", + priv->use_dma ? + "Use DMA Mode" : "No DMA"); } return 0; -- cgit v1.2.3 From 50a22ba07453e242668cfc4f312602cc8165cde5 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 12 Nov 2013 12:11:09 +0200 Subject: serial: 8250_dw: add new ACPI IDs Newer Intel PCHs with LPSS have the same Designware controllers than Haswell but ACPI IDs are different. Add these IDs to the driver list. Signed-off-by: Mika Westerberg Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 4658e3e0ec42..8cf39ad01667 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -455,6 +455,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match); static const struct acpi_device_id dw8250_acpi_match[] = { { "INT33C4", 0 }, { "INT33C5", 0 }, + { "INT3434", 0 }, + { "INT3435", 0 }, { "80860F0A", 0 }, { }, }; -- cgit v1.2.3 From d6a62b3b7eb1a000718f8ecac0c31eaa1e1f1187 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Nov 2013 12:53:48 +0300 Subject: serial: icom: dereference after free in load_code() We use "fw" in the next line after we release it. I've shifted the call to release_firmware() down a couple lines to fix this. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/icom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index d98e43348970..67423805e6d9 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -455,11 +455,11 @@ static void load_code(struct icom_port *icom_port) for (index = 0; index < fw->size; index++) new_page[index] = fw->data[index]; - release_firmware(fw); - writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length); writel(temp_pci, &icom_port->dram->mac_load_addr); + release_firmware(fw); + /*Setting the syncReg to 0x80 causes adapter to start downloading the personality code into adapter instruction RAM. Once code is loaded, it will begin executing and, based on -- cgit v1.2.3 From 6d4fa5bac71f7d83ba78d25a25df4c440a0ae69c Mon Sep 17 00:00:00 2001 From: Jonathan Woithe Date: Thu, 31 Oct 2013 15:43:40 +1030 Subject: serial: 8250: Fix initialisation of Quatech cards with the AMCC PCI chip Fix the initialisation of older Quatech serial cards which are fitted with the AMCC PCI Matchmaker interface chip. Signed-off-by: Jonathan Woithe (jwoithe@just42.net) Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4697a514b80a..6063d1512429 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1259,10 +1259,10 @@ static int pci_quatech_init(struct pci_dev *dev) unsigned long base = pci_resource_start(dev, 0); if (base) { u32 tmp; - outl(inl(base + 0x38), base + 0x38); + outl(inl(base + 0x38) | 0x00002000, base + 0x38); tmp = inl(base + 0x3c); outl(tmp | 0x01000000, base + 0x3c); - outl(tmp, base + 0x3c); + outl(tmp &= ~0x01000000, base + 0x3c); } } return 0; -- cgit v1.2.3 From 39669f3ae1d8a82d407a00e9e0058050997328da Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 2 Dec 2013 11:38:38 -0800 Subject: tty: xuartps: Properly guard sysrq specific code Commit 'tty: xuartps: Implement BREAK detection, add SYSRQ support' (0c0c47bc40a2e358d593b2d7fb93b50027fbfc0c) introduced sysrq support without properly guarding sysrq specific code which results in build errors when sysrq is disabled: DNAME=KBUILD_STR(xilinx_uartps)" -c -o drivers/tty/serial/.tmp_xilinx_uartps.o drivers/tty/serial/xilinx_uartps.c drivers/tty/serial/xilinx_uartps.c: In function 'xuartps_isr': drivers/tty/serial/xilinx_uartps.c:247:5: error: 'struct uart_port' has no member named 'sysrq' drivers/tty/serial/xilinx_uartps.c:247:5: error: 'struct uart_port' has no member named 'sysrq' drivers/tty/serial/xilinx_uartps.c:247:5: error: 'struct uart_port' has no member named 'sysrq' make[3]: *** [drivers/tty/serial/xilinx_uartps.o] Error 1 Reported-by: Masanari Iida Cc: Vlad Lungu Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index e46e9f3f19b9..f619ad5b5eae 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) continue; } +#ifdef SUPPORT_SYSRQ /* * uart_handle_sysrq_char() doesn't work if * spinlocked, for some reason @@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) } spin_lock(&port->lock); } +#endif port->icount.rx++; -- cgit v1.2.3 From 9aaf880ed4ee3c3cb1aa628e76c177035ce000ae Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 29 Nov 2013 08:46:32 -0200 Subject: imx-drm: Add mx6 hdmi transmitter support Add mx6 hdmi transmitter support. Original work has been done by Sascha Hauer and Tony Prisk. Special thanks to Russell King for his carefully review, many bug fixes and testing of the mx6 HDMI driver. Tested on the following boards: - mx6q sabresd - mx6dl sabresd - mx6solo wandboard Signed-off-by: Russell King Signed-off-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/Kconfig | 6 + drivers/staging/imx-drm/Makefile | 1 + drivers/staging/imx-drm/imx-hdmi.c | 1916 +++++++++++++++++++++++++++ drivers/staging/imx-drm/imx-hdmi.h | 1032 +++++++++++++++ include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 1 + 5 files changed, 2956 insertions(+) create mode 100644 drivers/staging/imx-drm/imx-hdmi.c create mode 100644 drivers/staging/imx-drm/imx-hdmi.h (limited to 'drivers') diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig index 5032ff7c2259..78319ad176cd 100644 --- a/drivers/staging/imx-drm/Kconfig +++ b/drivers/staging/imx-drm/Kconfig @@ -53,3 +53,9 @@ config DRM_IMX_IPUV3 depends on DRM_IMX_IPUV3_CORE help Choose this if you have a i.MX5 or i.MX6 processor. + +config DRM_IMX_HDMI + tristate "Freescale i.MX DRM HDMI" + depends on DRM_IMX + help + Choose this if you want to use HDMI on i.MX6. diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile index 8742432d7b01..4677585b5ad5 100644 --- a/drivers/staging/imx-drm/Makefile +++ b/drivers/staging/imx-drm/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/ imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o +obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c new file mode 100644 index 000000000000..f3a1f5e2e492 --- /dev/null +++ b/drivers/staging/imx-drm/imx-hdmi.c @@ -0,0 +1,1916 @@ +/* + * Copyright (C) 2011-2013 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. + * + * SH-Mobile High-Definition Multimedia Interface (HDMI) driver + * for SLISHDMI13T and SLIPHDMIT IP cores + * + * Copyright (C) 2010, Guennadi Liakhovetski + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ipu-v3/imx-ipu-v3.h" +#include "imx-hdmi.h" +#include "imx-drm.h" + +#define HDMI_EDID_LEN 512 + +#define RGB 0 +#define YCBCR444 1 +#define YCBCR422_16BITS 2 +#define YCBCR422_8BITS 3 +#define XVYCC444 4 + +enum hdmi_datamap { + RGB444_8B = 0x01, + RGB444_10B = 0x03, + RGB444_12B = 0x05, + RGB444_16B = 0x07, + YCbCr444_8B = 0x09, + YCbCr444_10B = 0x0B, + YCbCr444_12B = 0x0D, + YCbCr444_16B = 0x0F, + YCbCr422_8B = 0x16, + YCbCr422_10B = 0x14, + YCbCr422_12B = 0x12, +}; + +enum hdmi_colorimetry { + ITU601, + ITU709, +}; + +enum imx_hdmi_devtype { + IMX6Q_HDMI, + IMX6DL_HDMI, +}; + +static const u16 csc_coeff_default[3][4] = { + { 0x2000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x2000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x2000, 0x0000 } +}; + +static const u16 csc_coeff_rgb_out_eitu601[3][4] = { + { 0x2000, 0x6926, 0x74fd, 0x010e }, + { 0x2000, 0x2cdd, 0x0000, 0x7e9a }, + { 0x2000, 0x0000, 0x38b4, 0x7e3b } +}; + +static const u16 csc_coeff_rgb_out_eitu709[3][4] = { + { 0x2000, 0x7106, 0x7a02, 0x00a7 }, + { 0x2000, 0x3264, 0x0000, 0x7e6d }, + { 0x2000, 0x0000, 0x3b61, 0x7e25 } +}; + +static const u16 csc_coeff_rgb_in_eitu601[3][4] = { + { 0x2591, 0x1322, 0x074b, 0x0000 }, + { 0x6535, 0x2000, 0x7acc, 0x0200 }, + { 0x6acd, 0x7534, 0x2000, 0x0200 } +}; + +static const u16 csc_coeff_rgb_in_eitu709[3][4] = { + { 0x2dc5, 0x0d9b, 0x049e, 0x0000 }, + { 0x62f0, 0x2000, 0x7d11, 0x0200 }, + { 0x6756, 0x78ab, 0x2000, 0x0200 } +}; + +struct hdmi_vmode { + bool mdvi; + bool mhsyncpolarity; + bool mvsyncpolarity; + bool minterlaced; + bool mdataenablepolarity; + + unsigned int mpixelclock; + unsigned int mpixelrepetitioninput; + unsigned int mpixelrepetitionoutput; +}; + +struct hdmi_data_info { + unsigned int enc_in_format; + unsigned int enc_out_format; + unsigned int enc_color_depth; + unsigned int colorimetry; + unsigned int pix_repet_factor; + unsigned int hdcp_enable; + struct hdmi_vmode video_mode; +}; + +struct imx_hdmi { + struct drm_connector connector; + struct imx_drm_connector *imx_drm_connector; + struct drm_encoder encoder; + struct imx_drm_encoder *imx_drm_encoder; + + enum imx_hdmi_devtype dev_type; + struct device *dev; + struct clk *isfr_clk; + struct clk *iahb_clk; + + struct hdmi_data_info hdmi_data; + int vic; + + u8 edid[HDMI_EDID_LEN]; + bool cable_plugin; + + bool phy_enabled; + struct drm_display_mode previous_mode; + + struct regmap *regmap; + struct i2c_adapter *ddc; + void __iomem *regs; + + unsigned long pixel_clk_rate; + unsigned int sample_rate; + int ratio; +}; + +static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di) +{ + regmap_update_bits(hdmi->regmap, IOMUXC_GPR3, + IMX6Q_GPR3_HDMI_MUX_CTL_MASK, + ipu_di << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT); +} + +static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset) +{ + writeb(val, hdmi->regs + offset); +} + +static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset) +{ + return readb(hdmi->regs + offset); +} + +static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg, + u8 shift, u8 mask) +{ + u8 value = hdmi_readb(hdmi, reg) & ~mask; + value |= (data << shift) & mask; + hdmi_writeb(hdmi, value, reg); +} + +static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi, + unsigned int value) +{ + u8 val; + + hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1); + hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2); + hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3); + + /* nshift factor = 0 */ + val = hdmi_readb(hdmi, HDMI_AUD_CTS3); + val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK; + hdmi_writeb(hdmi, val, HDMI_AUD_CTS3); +} + +static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts) +{ + u8 val; + + /* Must be set/cleared first */ + val = hdmi_readb(hdmi, HDMI_AUD_CTS3); + val &= ~HDMI_AUD_CTS3_CTS_MANUAL; + hdmi_writeb(hdmi, val, HDMI_AUD_CTS3); + + hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); + hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); + hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | + HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); +} + +static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk, + unsigned int ratio) +{ + unsigned int n = (128 * freq) / 1000; + + switch (freq) { + case 32000: + if (pixel_clk == 25170000) + n = (ratio == 150) ? 9152 : 4576; + else if (pixel_clk == 27020000) + n = (ratio == 150) ? 8192 : 4096; + else if (pixel_clk == 74170000 || pixel_clk == 148350000) + n = 11648; + else + n = 4096; + break; + + case 44100: + if (pixel_clk == 25170000) + n = 7007; + else if (pixel_clk == 74170000) + n = 17836; + else if (pixel_clk == 148350000) + n = (ratio == 150) ? 17836 : 8918; + else + n = 6272; + break; + + case 48000: + if (pixel_clk == 25170000) + n = (ratio == 150) ? 9152 : 6864; + else if (pixel_clk == 27020000) + n = (ratio == 150) ? 8192 : 6144; + else if (pixel_clk == 74170000) + n = 11648; + else if (pixel_clk == 148350000) + n = (ratio == 150) ? 11648 : 5824; + else + n = 6144; + break; + + case 88200: + n = hdmi_compute_n(44100, pixel_clk, ratio) * 2; + break; + + case 96000: + n = hdmi_compute_n(48000, pixel_clk, ratio) * 2; + break; + + case 176400: + n = hdmi_compute_n(44100, pixel_clk, ratio) * 4; + break; + + case 192000: + n = hdmi_compute_n(48000, pixel_clk, ratio) * 4; + break; + + default: + break; + } + + return n; +} + +static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk, + unsigned int ratio) +{ + unsigned int cts = 0; + + pr_debug("%s: freq: %d pixel_clk: %ld ratio: %d\n", __func__, freq, + pixel_clk, ratio); + + switch (freq) { + case 32000: + if (pixel_clk == 297000000) { + cts = 222750; + break; + } + case 48000: + case 96000: + case 192000: + switch (pixel_clk) { + case 25200000: + case 27000000: + case 54000000: + case 74250000: + case 148500000: + cts = pixel_clk / 1000; + break; + case 297000000: + cts = 247500; + break; + /* + * All other TMDS clocks are not supported by + * DWC_hdmi_tx. The TMDS clocks divided or + * multiplied by 1,001 coefficients are not + * supported. + */ + default: + break; + } + break; + case 44100: + case 88200: + case 176400: + switch (pixel_clk) { + case 25200000: + cts = 28000; + break; + case 27000000: + cts = 30000; + break; + case 54000000: + cts = 60000; + break; + case 74250000: + cts = 82500; + break; + case 148500000: + cts = 165000; + break; + case 297000000: + cts = 247500; + break; + default: + break; + } + break; + default: + break; + } + if (ratio == 100) + return cts; + else + return (cts * ratio) / 100; +} + +static void hdmi_get_pixel_clk(struct imx_hdmi *hdmi) +{ + unsigned long rate; + + rate = 65000000; /* FIXME */ + + if (rate) + hdmi->pixel_clk_rate = rate; +} + +static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi) +{ + unsigned int clk_n, clk_cts; + + clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate, + hdmi->ratio); + clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate, + hdmi->ratio); + + if (!clk_cts) { + dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", + __func__, hdmi->pixel_clk_rate); + return; + } + + dev_dbg(hdmi->dev, "%s: samplerate=%d ratio=%d pixelclk=%lu N=%d cts=%d\n", + __func__, hdmi->sample_rate, hdmi->ratio, + hdmi->pixel_clk_rate, clk_n, clk_cts); + + hdmi_set_clock_regenerator_n(hdmi, clk_n); + hdmi_regenerate_cts(hdmi, clk_cts); +} + +static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi) +{ + unsigned int clk_n, clk_cts; + + clk_n = hdmi_compute_n(hdmi->sample_rate, hdmi->pixel_clk_rate, + hdmi->ratio); + clk_cts = hdmi_compute_cts(hdmi->sample_rate, hdmi->pixel_clk_rate, + hdmi->ratio); + + if (!clk_cts) { + dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", + __func__, hdmi->pixel_clk_rate); + return; + } + + dev_dbg(hdmi->dev, "%s: samplerate=%d ratio=%d pixelclk=%lu N=%d cts=%d\n", + __func__, hdmi->sample_rate, hdmi->ratio, + hdmi->pixel_clk_rate, clk_n, clk_cts); + + hdmi_set_clock_regenerator_n(hdmi, clk_n); + hdmi_regenerate_cts(hdmi, clk_cts); +} + +static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi) +{ + /* Get pixel clock from ipu */ + hdmi_get_pixel_clk(hdmi); + hdmi_set_clk_regenerator(hdmi); +} + +/* + * this submodule is responsible for the video data synchronization. + * for example, for RGB 4:4:4 input, the data map is defined as + * pin{47~40} <==> R[7:0] + * pin{31~24} <==> G[7:0] + * pin{15~8} <==> B[7:0] + */ +static void hdmi_video_sample(struct imx_hdmi *hdmi) +{ + int color_format = 0; + u8 val; + + if (hdmi->hdmi_data.enc_in_format == RGB) { + if (hdmi->hdmi_data.enc_color_depth == 8) + color_format = 0x01; + else if (hdmi->hdmi_data.enc_color_depth == 10) + color_format = 0x03; + else if (hdmi->hdmi_data.enc_color_depth == 12) + color_format = 0x05; + else if (hdmi->hdmi_data.enc_color_depth == 16) + color_format = 0x07; + else + return; + } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) { + if (hdmi->hdmi_data.enc_color_depth == 8) + color_format = 0x09; + else if (hdmi->hdmi_data.enc_color_depth == 10) + color_format = 0x0B; + else if (hdmi->hdmi_data.enc_color_depth == 12) + color_format = 0x0D; + else if (hdmi->hdmi_data.enc_color_depth == 16) + color_format = 0x0F; + else + return; + } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) { + if (hdmi->hdmi_data.enc_color_depth == 8) + color_format = 0x16; + else if (hdmi->hdmi_data.enc_color_depth == 10) + color_format = 0x14; + else if (hdmi->hdmi_data.enc_color_depth == 12) + color_format = 0x12; + else + return; + } + + val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE | + ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) & + HDMI_TX_INVID0_VIDEO_MAPPING_MASK); + hdmi_writeb(hdmi, val, HDMI_TX_INVID0); + + /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */ + val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE | + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE | + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE; + hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING); + hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0); + hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1); + hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0); + hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1); + hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0); + hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1); +} + +static int is_color_space_conversion(struct imx_hdmi *hdmi) +{ + return (hdmi->hdmi_data.enc_in_format != + hdmi->hdmi_data.enc_out_format); +} + +static int is_color_space_decimation(struct imx_hdmi *hdmi) +{ + return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) && + (hdmi->hdmi_data.enc_in_format == RGB || + hdmi->hdmi_data.enc_in_format == YCBCR444)); +} + +static int is_color_space_interpolation(struct imx_hdmi *hdmi) +{ + return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) && + (hdmi->hdmi_data.enc_out_format == RGB || + hdmi->hdmi_data.enc_out_format == YCBCR444)); +} + +static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) +{ + const u16 (*csc_coeff)[3][4] = &csc_coeff_default; + u32 csc_scale = 1; + u8 val; + + if (is_color_space_conversion(hdmi)) { + if (hdmi->hdmi_data.enc_out_format == RGB) { + if (hdmi->hdmi_data.colorimetry == ITU601) + csc_coeff = &csc_coeff_rgb_out_eitu601; + else + csc_coeff = &csc_coeff_rgb_out_eitu709; + } else if (hdmi->hdmi_data.enc_in_format == RGB) { + if (hdmi->hdmi_data.colorimetry == ITU601) + csc_coeff = &csc_coeff_rgb_in_eitu601; + else + csc_coeff = &csc_coeff_rgb_in_eitu709; + csc_scale = 0; + } + } + + hdmi_writeb(hdmi, ((*csc_coeff)[0][0] & 0xff), HDMI_CSC_COEF_A1_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][0] >> 8), HDMI_CSC_COEF_A1_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][1] & 0xff), HDMI_CSC_COEF_A2_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][1] >> 8), HDMI_CSC_COEF_A2_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][2] & 0xff), HDMI_CSC_COEF_A3_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][2] >> 8), HDMI_CSC_COEF_A3_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][3] & 0xff), HDMI_CSC_COEF_A4_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[0][3] >> 8), HDMI_CSC_COEF_A4_MSB); + + hdmi_writeb(hdmi, ((*csc_coeff)[1][0] & 0xff), HDMI_CSC_COEF_B1_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][0] >> 8), HDMI_CSC_COEF_B1_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][1] & 0xff), HDMI_CSC_COEF_B2_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][1] >> 8), HDMI_CSC_COEF_B2_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][2] & 0xff), HDMI_CSC_COEF_B3_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][2] >> 8), HDMI_CSC_COEF_B3_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][3] & 0xff), HDMI_CSC_COEF_B4_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[1][3] >> 8), HDMI_CSC_COEF_B4_MSB); + + hdmi_writeb(hdmi, ((*csc_coeff)[2][0] & 0xff), HDMI_CSC_COEF_C1_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][0] >> 8), HDMI_CSC_COEF_C1_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][1] & 0xff), HDMI_CSC_COEF_C2_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][1] >> 8), HDMI_CSC_COEF_C2_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][2] & 0xff), HDMI_CSC_COEF_C3_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][2] >> 8), HDMI_CSC_COEF_C3_MSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][3] & 0xff), HDMI_CSC_COEF_C4_LSB); + hdmi_writeb(hdmi, ((*csc_coeff)[2][3] >> 8), HDMI_CSC_COEF_C4_MSB); + + val = hdmi_readb(hdmi, HDMI_CSC_SCALE); + val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK; + val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK; + hdmi_writeb(hdmi, val, HDMI_CSC_SCALE); +} + +static void hdmi_video_csc(struct imx_hdmi *hdmi) +{ + int color_depth = 0; + int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; + int decimation = 0; + u8 val; + + /* YCC422 interpolation to 444 mode */ + if (is_color_space_interpolation(hdmi)) + interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1; + else if (is_color_space_decimation(hdmi)) + decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3; + + if (hdmi->hdmi_data.enc_color_depth == 8) + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP; + else if (hdmi->hdmi_data.enc_color_depth == 10) + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP; + else if (hdmi->hdmi_data.enc_color_depth == 12) + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP; + else if (hdmi->hdmi_data.enc_color_depth == 16) + color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP; + else + return; + + /* Configure the CSC registers */ + hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG); + val = hdmi_readb(hdmi, HDMI_CSC_SCALE); + val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK; + val |= color_depth; + hdmi_writeb(hdmi, val, HDMI_CSC_SCALE); + + imx_hdmi_update_csc_coeffs(hdmi); +} + +/* + * HDMI video packetizer is used to packetize the data. + * for example, if input is YCC422 mode or repeater is used, + * data should be repacked this module can be bypassed. + */ +static void hdmi_video_packetize(struct imx_hdmi *hdmi) +{ + unsigned int color_depth = 0; + unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit; + unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP; + struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; + u8 val; + + if (hdmi_data->enc_out_format == RGB + || hdmi_data->enc_out_format == YCBCR444) { + if (!hdmi_data->enc_color_depth) + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; + else if (hdmi_data->enc_color_depth == 8) { + color_depth = 4; + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; + } else if (hdmi_data->enc_color_depth == 10) + color_depth = 5; + else if (hdmi_data->enc_color_depth == 12) + color_depth = 6; + else if (hdmi_data->enc_color_depth == 16) + color_depth = 7; + else + return; + } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { + if (!hdmi_data->enc_color_depth || + hdmi_data->enc_color_depth == 8) + remap_size = HDMI_VP_REMAP_YCC422_16bit; + else if (hdmi_data->enc_color_depth == 10) + remap_size = HDMI_VP_REMAP_YCC422_20bit; + else if (hdmi_data->enc_color_depth == 12) + remap_size = HDMI_VP_REMAP_YCC422_24bit; + else + return; + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; + } else + return; + + /* set the packetizer registers */ + val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & + HDMI_VP_PR_CD_COLOR_DEPTH_MASK) | + ((hdmi_data->pix_repet_factor << + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) & + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK); + hdmi_writeb(hdmi, val, HDMI_VP_PR_CD); + + val = hdmi_readb(hdmi, HDMI_VP_STUFF); + val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK; + val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE; + hdmi_writeb(hdmi, val, HDMI_VP_STUFF); + + /* Data from pixel repeater block */ + if (hdmi_data->pix_repet_factor > 1) { + val = hdmi_readb(hdmi, HDMI_VP_CONF); + val &= ~(HDMI_VP_CONF_PR_EN_MASK | + HDMI_VP_CONF_BYPASS_SELECT_MASK); + val |= HDMI_VP_CONF_PR_EN_ENABLE | + HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER; + hdmi_writeb(hdmi, val, HDMI_VP_CONF); + } else { /* data from packetizer block */ + val = hdmi_readb(hdmi, HDMI_VP_CONF); + val &= ~(HDMI_VP_CONF_PR_EN_MASK | + HDMI_VP_CONF_BYPASS_SELECT_MASK); + val |= HDMI_VP_CONF_PR_EN_DISABLE | + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER; + hdmi_writeb(hdmi, val, HDMI_VP_CONF); + } + + val = hdmi_readb(hdmi, HDMI_VP_STUFF); + val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK; + val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET; + hdmi_writeb(hdmi, val, HDMI_VP_STUFF); + + hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP); + + if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) { + val = hdmi_readb(hdmi, HDMI_VP_CONF); + val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK | + HDMI_VP_CONF_PP_EN_ENMASK | + HDMI_VP_CONF_YCC422_EN_MASK); + val |= HDMI_VP_CONF_BYPASS_EN_DISABLE | + HDMI_VP_CONF_PP_EN_ENABLE | + HDMI_VP_CONF_YCC422_EN_DISABLE; + hdmi_writeb(hdmi, val, HDMI_VP_CONF); + } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) { + val = hdmi_readb(hdmi, HDMI_VP_CONF); + val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK | + HDMI_VP_CONF_PP_EN_ENMASK | + HDMI_VP_CONF_YCC422_EN_MASK); + val |= HDMI_VP_CONF_BYPASS_EN_DISABLE | + HDMI_VP_CONF_PP_EN_DISABLE | + HDMI_VP_CONF_YCC422_EN_ENABLE; + hdmi_writeb(hdmi, val, HDMI_VP_CONF); + } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) { + val = hdmi_readb(hdmi, HDMI_VP_CONF); + val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK | + HDMI_VP_CONF_PP_EN_ENMASK | + HDMI_VP_CONF_YCC422_EN_MASK); + val |= HDMI_VP_CONF_BYPASS_EN_ENABLE | + HDMI_VP_CONF_PP_EN_DISABLE | + HDMI_VP_CONF_YCC422_EN_DISABLE; + hdmi_writeb(hdmi, val, HDMI_VP_CONF); + } else { + return; + } + + val = hdmi_readb(hdmi, HDMI_VP_STUFF); + val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK | + HDMI_VP_STUFF_YCC422_STUFFING_MASK); + val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE | + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE; + hdmi_writeb(hdmi, val, HDMI_VP_STUFF); + + val = hdmi_readb(hdmi, HDMI_VP_CONF); + val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK; + val |= output_select; + hdmi_writeb(hdmi, val, HDMI_VP_CONF); +} + +static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi, + unsigned char bit) +{ + u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0); + val &= ~HDMI_PHY_TST0_TSTCLR_MASK; + val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) & + HDMI_PHY_TST0_TSTCLR_MASK; + hdmi_writeb(hdmi, val, HDMI_PHY_TST0); +} + +static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi, + unsigned char bit) +{ + u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0); + val &= ~HDMI_PHY_TST0_TSTEN_MASK; + val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) & + HDMI_PHY_TST0_TSTEN_MASK; + hdmi_writeb(hdmi, val, HDMI_PHY_TST0); +} + +static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi, + unsigned char bit) +{ + u8 val = hdmi_readb(hdmi, HDMI_PHY_TST0); + val &= ~HDMI_PHY_TST0_TSTCLK_MASK; + val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) & + HDMI_PHY_TST0_TSTCLK_MASK; + hdmi_writeb(hdmi, val, HDMI_PHY_TST0); +} + +static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi, + unsigned char bit) +{ + hdmi_writeb(hdmi, bit, HDMI_PHY_TST1); +} + +static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi, + unsigned char bit) +{ + hdmi_writeb(hdmi, bit, HDMI_PHY_TST2); +} + +static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec) +{ + unsigned char val = 0; + val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3; + while (!val) { + udelay(1000); + if (msec-- == 0) + return false; + val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3; + } + return true; +} + +static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, + unsigned char addr) +{ + hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); + hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); + hdmi_writeb(hdmi, (unsigned char)(data >> 8), + HDMI_PHY_I2CM_DATAO_1_ADDR); + hdmi_writeb(hdmi, (unsigned char)(data >> 0), + HDMI_PHY_I2CM_DATAO_0_ADDR); + hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, + HDMI_PHY_I2CM_OPERATION_ADDR); + hdmi_phy_wait_i2c_done(hdmi, 1000); +} + +static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, + unsigned char addr) +{ + __hdmi_phy_i2c_write(hdmi, data, addr); + return 0; +} + +static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable) +{ + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, + HDMI_PHY_CONF0_PDZ_OFFSET, + HDMI_PHY_CONF0_PDZ_MASK); +} + +static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable) +{ + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, + HDMI_PHY_CONF0_ENTMDS_OFFSET, + HDMI_PHY_CONF0_ENTMDS_MASK); +} + +static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable) +{ + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, + HDMI_PHY_CONF0_GEN2_PDDQ_MASK); +} + +static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable) +{ + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); +} + +static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable) +{ + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET, + HDMI_PHY_CONF0_SELDATAENPOL_MASK); +} + +static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable) +{ + hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, + HDMI_PHY_CONF0_SELDIPIF_OFFSET, + HDMI_PHY_CONF0_SELDIPIF_MASK); +} + +static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, + unsigned char res, int cscon) +{ + u8 val, msec; + + /* color resolution 0 is 8 bit colour depth */ + if (!res) + res = 8; + + if (prep) + return -EINVAL; + else if (res != 8 && res != 12) + return -EINVAL; + + /* Enable csc path */ + if (cscon) + val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH; + else + val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS; + + hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL); + + /* gen2 tx power off */ + imx_hdmi_phy_gen2_txpwron(hdmi, 0); + + /* gen2 pddq */ + imx_hdmi_phy_gen2_pddq(hdmi, 1); + + /* PHY reset */ + hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ); + hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ); + + hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); + + hdmi_phy_test_clear(hdmi, 1); + hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, + HDMI_PHY_I2CM_SLAVE_ADDR); + hdmi_phy_test_clear(hdmi, 0); + + if (hdmi->hdmi_data.video_mode.mpixelclock <= 45250000) { + switch (res) { + case 8: + /* PLL/MPLL Cfg */ + hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06); + hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); /* GMPCTRL */ + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x21e1, 0x06); + hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x41e2, 0x06); + hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); + break; + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 92500000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x0140, 0x06); + hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x2141, 0x06); + hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x4142, 0x06); + hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 148500000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06); + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x20a1, 0x06); + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x40a2, 0x06); + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); + default: + return -EINVAL; + } + } else { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06); + hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x2001, 0x06); + hdmi_phy_i2c_write(hdmi, 0x000f, 0x15); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x4002, 0x06); + hdmi_phy_i2c_write(hdmi, 0x000f, 0x15); + default: + return -EINVAL; + } + } + + if (hdmi->hdmi_data.video_mode.mpixelclock <= 54000000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); /* CURRCTRL */ + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 58400000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 72000000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 74250000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 118800000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + default: + return -EINVAL; + } + } else if (hdmi->hdmi_data.video_mode.mpixelclock <= 216000000) { + switch (res) { + case 8: + hdmi_phy_i2c_write(hdmi, 0x06dc, 0x10); + break; + case 10: + hdmi_phy_i2c_write(hdmi, 0x0b5c, 0x10); + break; + case 12: + hdmi_phy_i2c_write(hdmi, 0x091c, 0x10); + break; + default: + return -EINVAL; + } + } else { + dev_err(hdmi->dev, + "Pixel clock %d - unsupported by HDMI\n", + hdmi->hdmi_data.video_mode.mpixelclock); + return -EINVAL; + } + + hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ + hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); + /* RESISTANCE TERM 133Ohm Cfg */ + hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */ + /* PREEMP Cgf 0.00 */ + hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */ + /* TX/CK LVL 10 */ + hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */ + /* REMOVE CLK TERM */ + hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ + + imx_hdmi_phy_enable_power(hdmi, 1); + + /* toggle TMDS enable */ + imx_hdmi_phy_enable_tmds(hdmi, 0); + imx_hdmi_phy_enable_tmds(hdmi, 1); + + /* gen2 tx power on */ + imx_hdmi_phy_gen2_txpwron(hdmi, 1); + imx_hdmi_phy_gen2_pddq(hdmi, 0); + + /*Wait for PHY PLL lock */ + msec = 5; + do { + val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; + if (!val) + break; + + if (msec == 0) { + dev_err(hdmi->dev, "PHY PLL not locked\n"); + return -ETIMEDOUT; + } + + udelay(1000); + msec--; + } while (1); + + return 0; +} + +static int imx_hdmi_phy_init(struct imx_hdmi *hdmi) +{ + int i, ret; + bool cscon = false; + + /*check csc whether needed activated in HDMI mode */ + cscon = (is_color_space_conversion(hdmi) && + !hdmi->hdmi_data.video_mode.mdvi); + + /* HDMI Phy spec says to do the phy initialization sequence twice */ + for (i = 0; i < 2; i++) { + imx_hdmi_phy_sel_data_en_pol(hdmi, 1); + imx_hdmi_phy_sel_interface_control(hdmi, 0); + imx_hdmi_phy_enable_tmds(hdmi, 0); + imx_hdmi_phy_enable_power(hdmi, 0); + + /* Enable CSC */ + ret = hdmi_phy_configure(hdmi, 0, 8, cscon); + if (ret) + return ret; + } + + hdmi->phy_enabled = true; + return 0; +} + +static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi) +{ + u8 de, val; + + if (hdmi->hdmi_data.video_mode.mdataenablepolarity) + de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH; + else + de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW; + + /* disable rx detect */ + val = hdmi_readb(hdmi, HDMI_A_HDCPCFG0); + val &= HDMI_A_HDCPCFG0_RXDETECT_MASK; + val |= HDMI_A_HDCPCFG0_RXDETECT_DISABLE; + hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG0); + + val = hdmi_readb(hdmi, HDMI_A_VIDPOLCFG); + val &= HDMI_A_VIDPOLCFG_DATAENPOL_MASK; + val |= de; + hdmi_writeb(hdmi, val, HDMI_A_VIDPOLCFG); + + val = hdmi_readb(hdmi, HDMI_A_HDCPCFG1); + val &= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK; + val |= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE; + hdmi_writeb(hdmi, val, HDMI_A_HDCPCFG1); +} + +static void hdmi_config_AVI(struct imx_hdmi *hdmi) +{ + u8 val, pix_fmt, under_scan; + u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry; + bool aspect_16_9; + + aspect_16_9 = false; /* FIXME */ + + /* AVI Data Byte 1 */ + if (hdmi->hdmi_data.enc_out_format == YCBCR444) + pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444; + else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) + pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422; + else + pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB; + + under_scan = HDMI_FC_AVICONF0_SCAN_INFO_NODATA; + + /* + * Active format identification data is present in the AVI InfoFrame. + * Under scan info, no bar data + */ + val = pix_fmt | under_scan | + HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT | + HDMI_FC_AVICONF0_BAR_DATA_NO_DATA; + + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0); + + /* AVI Data Byte 2 -Set the Aspect Ratio */ + if (aspect_16_9) { + act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9; + coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9; + } else { + act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3; + coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3; + } + + /* Set up colorimetry */ + if (hdmi->hdmi_data.enc_out_format == XVYCC444) { + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO; + if (hdmi->hdmi_data.colorimetry == ITU601) + ext_colorimetry = + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; + else /* hdmi->hdmi_data.colorimetry == ITU709 */ + ext_colorimetry = + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709; + } else if (hdmi->hdmi_data.enc_out_format != RGB) { + if (hdmi->hdmi_data.colorimetry == ITU601) + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE; + else /* hdmi->hdmi_data.colorimetry == ITU709 */ + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR; + ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; + } else { /* Carries no data */ + colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA; + ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; + } + + val = colorimetry | coded_ratio | act_ratio; + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1); + + /* AVI Data Byte 3 */ + val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry | + HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT | + HDMI_FC_AVICONF2_SCALING_NONE; + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2); + + /* AVI Data Byte 4 */ + hdmi_writeb(hdmi, hdmi->vic, HDMI_FC_AVIVID); + + /* AVI Data Byte 5- set up input and output pixel repetition */ + val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) << + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) & + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) | + ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput << + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) & + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK); + hdmi_writeb(hdmi, val, HDMI_FC_PRCONF); + + /* IT Content and quantization range = don't care */ + val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS | + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED; + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3); + + /* AVI Data Bytes 6-13 */ + hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB0); + hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB1); + hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB0); + hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB1); + hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB0); + hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB1); + hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB0); + hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1); +} + +static void hdmi_av_composer(struct imx_hdmi *hdmi, + const struct drm_display_mode *mode) +{ + u8 inv_val; + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; + int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; + + vmode->mhsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC); + vmode->mvsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC); + vmode->minterlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + vmode->mpixelclock = mode->clock * 1000; + + dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); + + /* Set up HDMI_FC_INVIDCONF */ + inv_val = (hdmi->hdmi_data.hdcp_enable ? + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); + + inv_val |= (vmode->mvsyncpolarity ? + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW); + + inv_val |= (vmode->mhsyncpolarity ? + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW); + + inv_val |= (vmode->mdataenablepolarity ? + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW); + + if (hdmi->vic == 39) + inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH; + else + inv_val |= (vmode->minterlaced ? + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW); + + inv_val |= (vmode->minterlaced ? + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE); + + inv_val |= (vmode->mdvi ? + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE : + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE); + + hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); + + /* Set up horizontal active pixel width */ + hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1); + hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0); + + /* Set up vertical active lines */ + hdmi_writeb(hdmi, mode->vdisplay >> 8, HDMI_FC_INVACTV1); + hdmi_writeb(hdmi, mode->vdisplay, HDMI_FC_INVACTV0); + + /* Set up horizontal blanking pixel region width */ + hblank = mode->htotal - mode->hdisplay; + hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1); + hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0); + + /* Set up vertical blanking pixel region width */ + vblank = mode->vtotal - mode->vdisplay; + hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK); + + /* Set up HSYNC active edge delay width (in pixel clks) */ + h_de_hs = mode->hsync_start - mode->hdisplay; + hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1); + hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0); + + /* Set up VSYNC active edge delay (in lines) */ + v_de_vs = mode->vsync_start - mode->vdisplay; + hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY); + + /* Set up HSYNC active pulse width (in pixel clks) */ + hsync_len = mode->hsync_end - mode->hsync_start; + hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1); + hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0); + + /* Set up VSYNC active edge delay (in lines) */ + vsync_len = mode->vsync_end - mode->vsync_start; + hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); +} + +static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi) +{ + if (!hdmi->phy_enabled) + return; + + imx_hdmi_phy_enable_tmds(hdmi, 0); + imx_hdmi_phy_enable_power(hdmi, 0); + + hdmi->phy_enabled = false; +} + +/* HDMI Initialization Step B.4 */ +static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi) +{ + u8 clkdis; + + /* control period minimum duration */ + hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR); + hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR); + hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC); + + /* Set to fill TMDS data channels */ + hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM); + hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM); + hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM); + + /* Enable pixel clock and tmds data path */ + clkdis = 0x7F; + clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); + + clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); + + /* Enable csc path */ + if (is_color_space_conversion(hdmi)) { + clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); + } +} + +static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi) +{ + u8 clkdis; + + clkdis = hdmi_readb(hdmi, HDMI_MC_CLKDIS); + clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; + hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); +} + +/* Workaround to clear the overflow condition */ +static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi) +{ + int count; + u8 val; + + /* TMDS software reset */ + hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ); + + val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF); + if (hdmi->dev_type == IMX6DL_HDMI) { + hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); + return; + } + + for (count = 0; count < 4; count++) + hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); +} + +static void hdmi_enable_overflow_interrupts(struct imx_hdmi *hdmi) +{ + hdmi_writeb(hdmi, 0, HDMI_FC_MASK2); + hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2); +} + +static void hdmi_disable_overflow_interrupts(struct imx_hdmi *hdmi) +{ + hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK, + HDMI_IH_MUTE_FC_STAT2); +} + +static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) +{ + int ret; + + hdmi_disable_overflow_interrupts(hdmi); + + hdmi->vic = drm_match_cea_mode(mode); + + if (!hdmi->vic) { + dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); + hdmi->hdmi_data.video_mode.mdvi = true; + } else { + dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); + hdmi->hdmi_data.video_mode.mdvi = false; + } + + if ((hdmi->vic == 6) || (hdmi->vic == 7) || + (hdmi->vic == 21) || (hdmi->vic == 22) || + (hdmi->vic == 2) || (hdmi->vic == 3) || + (hdmi->vic == 17) || (hdmi->vic == 18)) + hdmi->hdmi_data.colorimetry = ITU601; + else + hdmi->hdmi_data.colorimetry = ITU709; + + if ((hdmi->vic == 10) || (hdmi->vic == 11) || + (hdmi->vic == 12) || (hdmi->vic == 13) || + (hdmi->vic == 14) || (hdmi->vic == 15) || + (hdmi->vic == 25) || (hdmi->vic == 26) || + (hdmi->vic == 27) || (hdmi->vic == 28) || + (hdmi->vic == 29) || (hdmi->vic == 30) || + (hdmi->vic == 35) || (hdmi->vic == 36) || + (hdmi->vic == 37) || (hdmi->vic == 38)) + hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; + else + hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; + + hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; + + /* TODO: Get input format from IPU (via FB driver interface) */ + hdmi->hdmi_data.enc_in_format = RGB; + + hdmi->hdmi_data.enc_out_format = RGB; + + hdmi->hdmi_data.enc_color_depth = 8; + hdmi->hdmi_data.pix_repet_factor = 0; + hdmi->hdmi_data.hdcp_enable = 0; + hdmi->hdmi_data.video_mode.mdataenablepolarity = true; + + /* HDMI Initialization Step B.1 */ + hdmi_av_composer(hdmi, mode); + + /* HDMI Initializateion Step B.2 */ + ret = imx_hdmi_phy_init(hdmi); + if (ret) + return ret; + + /* HDMI Initialization Step B.3 */ + imx_hdmi_enable_video_path(hdmi); + + /* not for DVI mode */ + if (hdmi->hdmi_data.video_mode.mdvi) + dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); + else { + dev_dbg(hdmi->dev, "%s CEA mode\n", __func__); + + /* HDMI Initialization Step E - Configure audio */ + hdmi_clk_regenerator_update_pixel_clock(hdmi); + hdmi_enable_audio_clk(hdmi); + + /* HDMI Initialization Step F - Configure AVI InfoFrame */ + hdmi_config_AVI(hdmi); + } + + hdmi_video_packetize(hdmi); + hdmi_video_csc(hdmi); + hdmi_video_sample(hdmi); + hdmi_tx_hdcp_config(hdmi); + + imx_hdmi_clear_overflow(hdmi); + if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi) + hdmi_enable_overflow_interrupts(hdmi); + + return 0; +} + +/* Wait until we are registered to enable interrupts */ +static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi) +{ + hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, + HDMI_PHY_I2CM_INT_ADDR); + + hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL | + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL, + HDMI_PHY_I2CM_CTLINT_ADDR); + + /* enable cable hot plug irq */ + hdmi_writeb(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0); + + /* Clear Hotplug interrupts */ + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); + + /* Unmute interrupts */ + hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0); + + return 0; +} + +static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi) +{ + u8 ih_mute; + + /* + * Boot up defaults are: + * HDMI_IH_MUTE = 0x03 (disabled) + * HDMI_IH_MUTE_* = 0x00 (enabled) + * + * Disable top level interrupt bits in HDMI block + */ + ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) | + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT; + + hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); + + /* by default mask all interrupts */ + hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK); + hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0); + hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1); + hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2); + hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0); + hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR); + hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR); + hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT); + hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT); + hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK); + hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK); + hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK); + hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK); + hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT); + hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT); + + /* Disable interrupts in the IH_MUTE_* registers */ + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0); + hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0); + + /* Enable top level interrupt bits in HDMI block */ + ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT); + hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); +} + +static void imx_hdmi_poweron(struct imx_hdmi *hdmi) +{ + imx_hdmi_setup(hdmi, &hdmi->previous_mode); +} + +static void imx_hdmi_poweroff(struct imx_hdmi *hdmi) +{ + imx_hdmi_phy_disable(hdmi); +} + +static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector + *connector, bool force) +{ + /* FIXME */ + return connector_status_connected; +} + +static void imx_hdmi_connector_destroy(struct drm_connector *connector) +{ +} + +static int imx_hdmi_connector_get_modes(struct drm_connector *connector) +{ + struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, + connector); + struct edid *edid; + int ret; + + if (!hdmi->ddc) + return 0; + + edid = drm_get_edid(connector, hdmi->ddc); + if (edid) { + dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", + edid->width_cm, edid->height_cm); + + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + kfree(edid); + } else { + dev_dbg(hdmi->dev, "failed to get edid\n"); + } + + return 0; +} + +static int imx_hdmi_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + + return MODE_OK; +} + +static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector + *connector) +{ + struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, + connector); + + return &hdmi->encoder; +} + +static void imx_hdmi_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); + + imx_hdmi_setup(hdmi, mode); + + /* Store the display mode for plugin/DKMS poweron events */ + memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); +} + +static bool imx_hdmi_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void imx_hdmi_encoder_disable(struct drm_encoder *encoder) +{ +} + +static void imx_hdmi_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); + + if (mode) + imx_hdmi_poweroff(hdmi); + else + imx_hdmi_poweron(hdmi); +} + +static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder) +{ + struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); + + imx_hdmi_poweroff(hdmi); + imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_NONE, + V4L2_PIX_FMT_RGB24); +} + +static void imx_hdmi_encoder_commit(struct drm_encoder *encoder) +{ + struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); + int mux = imx_drm_encoder_get_mux_id(hdmi->imx_drm_encoder, + encoder->crtc); + + imx_hdmi_set_ipu_di_mux(hdmi, mux); + + imx_hdmi_poweron(hdmi); +} + +static void imx_hdmi_encoder_destroy(struct drm_encoder *encoder) +{ + return; +} + +static struct drm_encoder_funcs imx_hdmi_encoder_funcs = { + .destroy = imx_hdmi_encoder_destroy, +}; + +static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = { + .dpms = imx_hdmi_encoder_dpms, + .prepare = imx_hdmi_encoder_prepare, + .commit = imx_hdmi_encoder_commit, + .mode_set = imx_hdmi_encoder_mode_set, + .mode_fixup = imx_hdmi_encoder_mode_fixup, + .disable = imx_hdmi_encoder_disable, +}; + +static struct drm_connector_funcs imx_hdmi_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = imx_hdmi_connector_detect, + .destroy = imx_hdmi_connector_destroy, +}; + +static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = { + .get_modes = imx_hdmi_connector_get_modes, + .mode_valid = imx_hdmi_connector_mode_valid, + .best_encoder = imx_hdmi_connector_best_encoder, +}; + +static irqreturn_t imx_hdmi_irq(int irq, void *dev_id) +{ + struct imx_hdmi *hdmi = dev_id; + u8 intr_stat; + u8 phy_int_pol; + u8 val; + + intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); + + phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); + + if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { + if (phy_int_pol & HDMI_PHY_HPD) { + dev_dbg(hdmi->dev, "EVENT=plugin\n"); + + val = hdmi_readb(hdmi, HDMI_PHY_POL0); + val &= ~HDMI_PHY_HPD; + hdmi_writeb(hdmi, val, HDMI_PHY_POL0); + + imx_hdmi_poweron(hdmi); + } else { + dev_dbg(hdmi->dev, "EVENT=plugout\n"); + + val = hdmi_readb(hdmi, HDMI_PHY_POL0); + val |= HDMI_PHY_HPD; + hdmi_writeb(hdmi, val, HDMI_PHY_POL0); + + imx_hdmi_poweroff(hdmi); + } + } + + hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); + + return IRQ_HANDLED; +} + +static int imx_hdmi_register(struct imx_hdmi *hdmi) +{ + int ret; + + hdmi->connector.funcs = &imx_hdmi_connector_funcs; + hdmi->encoder.funcs = &imx_hdmi_encoder_funcs; + + hdmi->encoder.encoder_type = DRM_MODE_ENCODER_TMDS; + hdmi->connector.connector_type = DRM_MODE_CONNECTOR_HDMIA; + + drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs); + ret = imx_drm_add_encoder(&hdmi->encoder, &hdmi->imx_drm_encoder, + THIS_MODULE); + if (ret) { + dev_err(hdmi->dev, "adding encoder failed: %d\n", ret); + return ret; + } + + drm_connector_helper_add(&hdmi->connector, + &imx_hdmi_connector_helper_funcs); + + ret = imx_drm_add_connector(&hdmi->connector, + &hdmi->imx_drm_connector, THIS_MODULE); + if (ret) { + imx_drm_remove_encoder(hdmi->imx_drm_encoder); + dev_err(hdmi->dev, "adding connector failed: %d\n", ret); + return ret; + } + + hdmi->connector.encoder = &hdmi->encoder; + + drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder); + + return 0; +} + +static struct platform_device_id imx_hdmi_devtype[] = { + { + .name = "imx6q-hdmi", + .driver_data = IMX6Q_HDMI, + }, { + .name = "imx6dl-hdmi", + .driver_data = IMX6DL_HDMI, + }, { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, imx_hdmi_devtype); + +static const struct of_device_id imx_hdmi_dt_ids[] = { +{ .compatible = "fsl,imx6q-hdmi", .data = &imx_hdmi_devtype[IMX6Q_HDMI], }, +{ .compatible = "fsl,imx6dl-hdmi", .data = &imx_hdmi_devtype[IMX6DL_HDMI], }, +{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids); + +static int imx_hdmi_platform_probe(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(imx_hdmi_dt_ids, &pdev->dev); + struct device_node *np = pdev->dev.of_node; + struct device_node *ddc_node; + struct imx_hdmi *hdmi; + struct resource *iores; + int ret, irq; + + hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); + if (!hdmi) + return -ENOMEM; + + hdmi->dev = &pdev->dev; + + if (of_id) { + const struct platform_device_id *device_id = of_id->data; + hdmi->dev_type = device_id->driver_data; + } + + ddc_node = of_parse_phandle(np, "ddc", 0); + if (ddc_node) { + hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); + if (!hdmi->ddc) + dev_dbg(hdmi->dev, "failed to read ddc node\n"); + + of_node_put(ddc_node); + } else { + dev_dbg(hdmi->dev, "no ddc property found\n"); + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -EINVAL; + + ret = devm_request_irq(&pdev->dev, irq, imx_hdmi_irq, 0, + dev_name(&pdev->dev), hdmi); + if (ret) + return ret; + + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hdmi->regs = devm_ioremap_resource(&pdev->dev, iores); + if (IS_ERR(hdmi->regs)) + return PTR_ERR(hdmi->regs); + + hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); + if (IS_ERR(hdmi->regmap)) + return PTR_ERR(hdmi->regmap); + + hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); + if (IS_ERR(hdmi->isfr_clk)) { + ret = PTR_ERR(hdmi->isfr_clk); + dev_err(hdmi->dev, + "Unable to get HDMI isfr clk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(hdmi->isfr_clk); + if (ret) { + dev_err(hdmi->dev, + "Cannot enable HDMI isfr clock: %d\n", ret); + return ret; + } + + hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); + if (IS_ERR(hdmi->iahb_clk)) { + ret = PTR_ERR(hdmi->iahb_clk); + dev_err(hdmi->dev, + "Unable to get HDMI iahb clk: %d\n", ret); + goto err_isfr; + } + + ret = clk_prepare_enable(hdmi->iahb_clk); + if (ret) { + dev_err(hdmi->dev, + "Cannot enable HDMI iahb clock: %d\n", ret); + goto err_isfr; + } + + /* Product and revision IDs */ + dev_info(&pdev->dev, + "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", + hdmi_readb(hdmi, HDMI_DESIGN_ID), + hdmi_readb(hdmi, HDMI_REVISION_ID), + hdmi_readb(hdmi, HDMI_PRODUCT_ID0), + hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); + + initialize_hdmi_ih_mutes(hdmi); + + /* + * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator + * N and cts values before enabling phy + */ + hdmi_init_clk_regenerator(hdmi); + + /* + * Configure registers related to HDMI interrupt + * generation before registering IRQ. + */ + hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0); + + /* Clear Hotplug interrupts */ + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); + + ret = imx_hdmi_fb_registered(hdmi); + if (ret) + goto err_iahb; + + ret = imx_hdmi_register(hdmi); + if (ret) + goto err_iahb; + + imx_drm_encoder_add_possible_crtcs(hdmi->imx_drm_encoder, np); + + platform_set_drvdata(pdev, hdmi); + + return 0; + +err_iahb: + clk_disable_unprepare(hdmi->iahb_clk); +err_isfr: + clk_disable_unprepare(hdmi->isfr_clk); + + return ret; +} + +static int imx_hdmi_platform_remove(struct platform_device *pdev) +{ + struct imx_hdmi *hdmi = platform_get_drvdata(pdev); + struct drm_connector *connector = &hdmi->connector; + struct drm_encoder *encoder = &hdmi->encoder; + + drm_mode_connector_detach_encoder(connector, encoder); + imx_drm_remove_connector(hdmi->imx_drm_connector); + imx_drm_remove_encoder(hdmi->imx_drm_encoder); + + clk_disable_unprepare(hdmi->iahb_clk); + clk_disable_unprepare(hdmi->isfr_clk); + i2c_put_adapter(hdmi->ddc); + + return 0; +} + +static struct platform_driver imx_hdmi_driver = { + .probe = imx_hdmi_platform_probe, + .remove = imx_hdmi_platform_remove, + .driver = { + .name = "imx-hdmi", + .owner = THIS_MODULE, + .of_match_table = imx_hdmi_dt_ids, + }, +}; + +module_platform_driver(imx_hdmi_driver); + +MODULE_AUTHOR("Sascha Hauer "); +MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx-hdmi"); diff --git a/drivers/staging/imx-drm/imx-hdmi.h b/drivers/staging/imx-drm/imx-hdmi.h new file mode 100644 index 000000000000..39b677689db6 --- /dev/null +++ b/drivers/staging/imx-drm/imx-hdmi.h @@ -0,0 +1,1032 @@ +/* + * Copyright (C) 2011 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 __IMX_HDMI_H__ +#define __IMX_HDMI_H__ + +/* Identification Registers */ +#define HDMI_DESIGN_ID 0x0000 +#define HDMI_REVISION_ID 0x0001 +#define HDMI_PRODUCT_ID0 0x0002 +#define HDMI_PRODUCT_ID1 0x0003 +#define HDMI_CONFIG0_ID 0x0004 +#define HDMI_CONFIG1_ID 0x0005 +#define HDMI_CONFIG2_ID 0x0006 +#define HDMI_CONFIG3_ID 0x0007 + +/* Interrupt Registers */ +#define HDMI_IH_FC_STAT0 0x0100 +#define HDMI_IH_FC_STAT1 0x0101 +#define HDMI_IH_FC_STAT2 0x0102 +#define HDMI_IH_AS_STAT0 0x0103 +#define HDMI_IH_PHY_STAT0 0x0104 +#define HDMI_IH_I2CM_STAT0 0x0105 +#define HDMI_IH_CEC_STAT0 0x0106 +#define HDMI_IH_VP_STAT0 0x0107 +#define HDMI_IH_I2CMPHY_STAT0 0x0108 +#define HDMI_IH_AHBDMAAUD_STAT0 0x0109 + +#define HDMI_IH_MUTE_FC_STAT0 0x0180 +#define HDMI_IH_MUTE_FC_STAT1 0x0181 +#define HDMI_IH_MUTE_FC_STAT2 0x0182 +#define HDMI_IH_MUTE_AS_STAT0 0x0183 +#define HDMI_IH_MUTE_PHY_STAT0 0x0184 +#define HDMI_IH_MUTE_I2CM_STAT0 0x0185 +#define HDMI_IH_MUTE_CEC_STAT0 0x0186 +#define HDMI_IH_MUTE_VP_STAT0 0x0187 +#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188 +#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189 +#define HDMI_IH_MUTE 0x01FF + +/* Video Sample Registers */ +#define HDMI_TX_INVID0 0x0200 +#define HDMI_TX_INSTUFFING 0x0201 +#define HDMI_TX_GYDATA0 0x0202 +#define HDMI_TX_GYDATA1 0x0203 +#define HDMI_TX_RCRDATA0 0x0204 +#define HDMI_TX_RCRDATA1 0x0205 +#define HDMI_TX_BCBDATA0 0x0206 +#define HDMI_TX_BCBDATA1 0x0207 + +/* Video Packetizer Registers */ +#define HDMI_VP_STATUS 0x0800 +#define HDMI_VP_PR_CD 0x0801 +#define HDMI_VP_STUFF 0x0802 +#define HDMI_VP_REMAP 0x0803 +#define HDMI_VP_CONF 0x0804 +#define HDMI_VP_STAT 0x0805 +#define HDMI_VP_INT 0x0806 +#define HDMI_VP_MASK 0x0807 +#define HDMI_VP_POL 0x0808 + +/* Frame Composer Registers */ +#define HDMI_FC_INVIDCONF 0x1000 +#define HDMI_FC_INHACTV0 0x1001 +#define HDMI_FC_INHACTV1 0x1002 +#define HDMI_FC_INHBLANK0 0x1003 +#define HDMI_FC_INHBLANK1 0x1004 +#define HDMI_FC_INVACTV0 0x1005 +#define HDMI_FC_INVACTV1 0x1006 +#define HDMI_FC_INVBLANK 0x1007 +#define HDMI_FC_HSYNCINDELAY0 0x1008 +#define HDMI_FC_HSYNCINDELAY1 0x1009 +#define HDMI_FC_HSYNCINWIDTH0 0x100A +#define HDMI_FC_HSYNCINWIDTH1 0x100B +#define HDMI_FC_VSYNCINDELAY 0x100C +#define HDMI_FC_VSYNCINWIDTH 0x100D +#define HDMI_FC_INFREQ0 0x100E +#define HDMI_FC_INFREQ1 0x100F +#define HDMI_FC_INFREQ2 0x1010 +#define HDMI_FC_CTRLDUR 0x1011 +#define HDMI_FC_EXCTRLDUR 0x1012 +#define HDMI_FC_EXCTRLSPAC 0x1013 +#define HDMI_FC_CH0PREAM 0x1014 +#define HDMI_FC_CH1PREAM 0x1015 +#define HDMI_FC_CH2PREAM 0x1016 +#define HDMI_FC_AVICONF3 0x1017 +#define HDMI_FC_GCP 0x1018 +#define HDMI_FC_AVICONF0 0x1019 +#define HDMI_FC_AVICONF1 0x101A +#define HDMI_FC_AVICONF2 0x101B +#define HDMI_FC_AVIVID 0x101C +#define HDMI_FC_AVIETB0 0x101D +#define HDMI_FC_AVIETB1 0x101E +#define HDMI_FC_AVISBB0 0x101F +#define HDMI_FC_AVISBB1 0x1020 +#define HDMI_FC_AVIELB0 0x1021 +#define HDMI_FC_AVIELB1 0x1022 +#define HDMI_FC_AVISRB0 0x1023 +#define HDMI_FC_AVISRB1 0x1024 +#define HDMI_FC_AUDICONF0 0x1025 +#define HDMI_FC_AUDICONF1 0x1026 +#define HDMI_FC_AUDICONF2 0x1027 +#define HDMI_FC_AUDICONF3 0x1028 +#define HDMI_FC_VSDIEEEID0 0x1029 +#define HDMI_FC_VSDSIZE 0x102A +#define HDMI_FC_VSDIEEEID1 0x1030 +#define HDMI_FC_VSDIEEEID2 0x1031 +#define HDMI_FC_VSDPAYLOAD0 0x1032 +#define HDMI_FC_VSDPAYLOAD1 0x1033 +#define HDMI_FC_VSDPAYLOAD2 0x1034 +#define HDMI_FC_VSDPAYLOAD3 0x1035 +#define HDMI_FC_VSDPAYLOAD4 0x1036 +#define HDMI_FC_VSDPAYLOAD5 0x1037 +#define HDMI_FC_VSDPAYLOAD6 0x1038 +#define HDMI_FC_VSDPAYLOAD7 0x1039 +#define HDMI_FC_VSDPAYLOAD8 0x103A +#define HDMI_FC_VSDPAYLOAD9 0x103B +#define HDMI_FC_VSDPAYLOAD10 0x103C +#define HDMI_FC_VSDPAYLOAD11 0x103D +#define HDMI_FC_VSDPAYLOAD12 0x103E +#define HDMI_FC_VSDPAYLOAD13 0x103F +#define HDMI_FC_VSDPAYLOAD14 0x1040 +#define HDMI_FC_VSDPAYLOAD15 0x1041 +#define HDMI_FC_VSDPAYLOAD16 0x1042 +#define HDMI_FC_VSDPAYLOAD17 0x1043 +#define HDMI_FC_VSDPAYLOAD18 0x1044 +#define HDMI_FC_VSDPAYLOAD19 0x1045 +#define HDMI_FC_VSDPAYLOAD20 0x1046 +#define HDMI_FC_VSDPAYLOAD21 0x1047 +#define HDMI_FC_VSDPAYLOAD22 0x1048 +#define HDMI_FC_VSDPAYLOAD23 0x1049 +#define HDMI_FC_SPDVENDORNAME0 0x104A +#define HDMI_FC_SPDVENDORNAME1 0x104B +#define HDMI_FC_SPDVENDORNAME2 0x104C +#define HDMI_FC_SPDVENDORNAME3 0x104D +#define HDMI_FC_SPDVENDORNAME4 0x104E +#define HDMI_FC_SPDVENDORNAME5 0x104F +#define HDMI_FC_SPDVENDORNAME6 0x1050 +#define HDMI_FC_SPDVENDORNAME7 0x1051 +#define HDMI_FC_SDPPRODUCTNAME0 0x1052 +#define HDMI_FC_SDPPRODUCTNAME1 0x1053 +#define HDMI_FC_SDPPRODUCTNAME2 0x1054 +#define HDMI_FC_SDPPRODUCTNAME3 0x1055 +#define HDMI_FC_SDPPRODUCTNAME4 0x1056 +#define HDMI_FC_SDPPRODUCTNAME5 0x1057 +#define HDMI_FC_SDPPRODUCTNAME6 0x1058 +#define HDMI_FC_SDPPRODUCTNAME7 0x1059 +#define HDMI_FC_SDPPRODUCTNAME8 0x105A +#define HDMI_FC_SDPPRODUCTNAME9 0x105B +#define HDMI_FC_SDPPRODUCTNAME10 0x105C +#define HDMI_FC_SDPPRODUCTNAME11 0x105D +#define HDMI_FC_SDPPRODUCTNAME12 0x105E +#define HDMI_FC_SDPPRODUCTNAME13 0x105F +#define HDMI_FC_SDPPRODUCTNAME14 0x1060 +#define HDMI_FC_SPDPRODUCTNAME15 0x1061 +#define HDMI_FC_SPDDEVICEINF 0x1062 +#define HDMI_FC_AUDSCONF 0x1063 +#define HDMI_FC_AUDSSTAT 0x1064 +#define HDMI_FC_DATACH0FILL 0x1070 +#define HDMI_FC_DATACH1FILL 0x1071 +#define HDMI_FC_DATACH2FILL 0x1072 +#define HDMI_FC_CTRLQHIGH 0x1073 +#define HDMI_FC_CTRLQLOW 0x1074 +#define HDMI_FC_ACP0 0x1075 +#define HDMI_FC_ACP28 0x1076 +#define HDMI_FC_ACP27 0x1077 +#define HDMI_FC_ACP26 0x1078 +#define HDMI_FC_ACP25 0x1079 +#define HDMI_FC_ACP24 0x107A +#define HDMI_FC_ACP23 0x107B +#define HDMI_FC_ACP22 0x107C +#define HDMI_FC_ACP21 0x107D +#define HDMI_FC_ACP20 0x107E +#define HDMI_FC_ACP19 0x107F +#define HDMI_FC_ACP18 0x1080 +#define HDMI_FC_ACP17 0x1081 +#define HDMI_FC_ACP16 0x1082 +#define HDMI_FC_ACP15 0x1083 +#define HDMI_FC_ACP14 0x1084 +#define HDMI_FC_ACP13 0x1085 +#define HDMI_FC_ACP12 0x1086 +#define HDMI_FC_ACP11 0x1087 +#define HDMI_FC_ACP10 0x1088 +#define HDMI_FC_ACP9 0x1089 +#define HDMI_FC_ACP8 0x108A +#define HDMI_FC_ACP7 0x108B +#define HDMI_FC_ACP6 0x108C +#define HDMI_FC_ACP5 0x108D +#define HDMI_FC_ACP4 0x108E +#define HDMI_FC_ACP3 0x108F +#define HDMI_FC_ACP2 0x1090 +#define HDMI_FC_ACP1 0x1091 +#define HDMI_FC_ISCR1_0 0x1092 +#define HDMI_FC_ISCR1_16 0x1093 +#define HDMI_FC_ISCR1_15 0x1094 +#define HDMI_FC_ISCR1_14 0x1095 +#define HDMI_FC_ISCR1_13 0x1096 +#define HDMI_FC_ISCR1_12 0x1097 +#define HDMI_FC_ISCR1_11 0x1098 +#define HDMI_FC_ISCR1_10 0x1099 +#define HDMI_FC_ISCR1_9 0x109A +#define HDMI_FC_ISCR1_8 0x109B +#define HDMI_FC_ISCR1_7 0x109C +#define HDMI_FC_ISCR1_6 0x109D +#define HDMI_FC_ISCR1_5 0x109E +#define HDMI_FC_ISCR1_4 0x109F +#define HDMI_FC_ISCR1_3 0x10A0 +#define HDMI_FC_ISCR1_2 0x10A1 +#define HDMI_FC_ISCR1_1 0x10A2 +#define HDMI_FC_ISCR2_15 0x10A3 +#define HDMI_FC_ISCR2_14 0x10A4 +#define HDMI_FC_ISCR2_13 0x10A5 +#define HDMI_FC_ISCR2_12 0x10A6 +#define HDMI_FC_ISCR2_11 0x10A7 +#define HDMI_FC_ISCR2_10 0x10A8 +#define HDMI_FC_ISCR2_9 0x10A9 +#define HDMI_FC_ISCR2_8 0x10AA +#define HDMI_FC_ISCR2_7 0x10AB +#define HDMI_FC_ISCR2_6 0x10AC +#define HDMI_FC_ISCR2_5 0x10AD +#define HDMI_FC_ISCR2_4 0x10AE +#define HDMI_FC_ISCR2_3 0x10AF +#define HDMI_FC_ISCR2_2 0x10B0 +#define HDMI_FC_ISCR2_1 0x10B1 +#define HDMI_FC_ISCR2_0 0x10B2 +#define HDMI_FC_DATAUTO0 0x10B3 +#define HDMI_FC_DATAUTO1 0x10B4 +#define HDMI_FC_DATAUTO2 0x10B5 +#define HDMI_FC_DATMAN 0x10B6 +#define HDMI_FC_DATAUTO3 0x10B7 +#define HDMI_FC_RDRB0 0x10B8 +#define HDMI_FC_RDRB1 0x10B9 +#define HDMI_FC_RDRB2 0x10BA +#define HDMI_FC_RDRB3 0x10BB +#define HDMI_FC_RDRB4 0x10BC +#define HDMI_FC_RDRB5 0x10BD +#define HDMI_FC_RDRB6 0x10BE +#define HDMI_FC_RDRB7 0x10BF +#define HDMI_FC_STAT0 0x10D0 +#define HDMI_FC_INT0 0x10D1 +#define HDMI_FC_MASK0 0x10D2 +#define HDMI_FC_POL0 0x10D3 +#define HDMI_FC_STAT1 0x10D4 +#define HDMI_FC_INT1 0x10D5 +#define HDMI_FC_MASK1 0x10D6 +#define HDMI_FC_POL1 0x10D7 +#define HDMI_FC_STAT2 0x10D8 +#define HDMI_FC_INT2 0x10D9 +#define HDMI_FC_MASK2 0x10DA +#define HDMI_FC_POL2 0x10DB +#define HDMI_FC_PRCONF 0x10E0 + +#define HDMI_FC_GMD_STAT 0x1100 +#define HDMI_FC_GMD_EN 0x1101 +#define HDMI_FC_GMD_UP 0x1102 +#define HDMI_FC_GMD_CONF 0x1103 +#define HDMI_FC_GMD_HB 0x1104 +#define HDMI_FC_GMD_PB0 0x1105 +#define HDMI_FC_GMD_PB1 0x1106 +#define HDMI_FC_GMD_PB2 0x1107 +#define HDMI_FC_GMD_PB3 0x1108 +#define HDMI_FC_GMD_PB4 0x1109 +#define HDMI_FC_GMD_PB5 0x110A +#define HDMI_FC_GMD_PB6 0x110B +#define HDMI_FC_GMD_PB7 0x110C +#define HDMI_FC_GMD_PB8 0x110D +#define HDMI_FC_GMD_PB9 0x110E +#define HDMI_FC_GMD_PB10 0x110F +#define HDMI_FC_GMD_PB11 0x1110 +#define HDMI_FC_GMD_PB12 0x1111 +#define HDMI_FC_GMD_PB13 0x1112 +#define HDMI_FC_GMD_PB14 0x1113 +#define HDMI_FC_GMD_PB15 0x1114 +#define HDMI_FC_GMD_PB16 0x1115 +#define HDMI_FC_GMD_PB17 0x1116 +#define HDMI_FC_GMD_PB18 0x1117 +#define HDMI_FC_GMD_PB19 0x1118 +#define HDMI_FC_GMD_PB20 0x1119 +#define HDMI_FC_GMD_PB21 0x111A +#define HDMI_FC_GMD_PB22 0x111B +#define HDMI_FC_GMD_PB23 0x111C +#define HDMI_FC_GMD_PB24 0x111D +#define HDMI_FC_GMD_PB25 0x111E +#define HDMI_FC_GMD_PB26 0x111F +#define HDMI_FC_GMD_PB27 0x1120 + +#define HDMI_FC_DBGFORCE 0x1200 +#define HDMI_FC_DBGAUD0CH0 0x1201 +#define HDMI_FC_DBGAUD1CH0 0x1202 +#define HDMI_FC_DBGAUD2CH0 0x1203 +#define HDMI_FC_DBGAUD0CH1 0x1204 +#define HDMI_FC_DBGAUD1CH1 0x1205 +#define HDMI_FC_DBGAUD2CH1 0x1206 +#define HDMI_FC_DBGAUD0CH2 0x1207 +#define HDMI_FC_DBGAUD1CH2 0x1208 +#define HDMI_FC_DBGAUD2CH2 0x1209 +#define HDMI_FC_DBGAUD0CH3 0x120A +#define HDMI_FC_DBGAUD1CH3 0x120B +#define HDMI_FC_DBGAUD2CH3 0x120C +#define HDMI_FC_DBGAUD0CH4 0x120D +#define HDMI_FC_DBGAUD1CH4 0x120E +#define HDMI_FC_DBGAUD2CH4 0x120F +#define HDMI_FC_DBGAUD0CH5 0x1210 +#define HDMI_FC_DBGAUD1CH5 0x1211 +#define HDMI_FC_DBGAUD2CH5 0x1212 +#define HDMI_FC_DBGAUD0CH6 0x1213 +#define HDMI_FC_DBGAUD1CH6 0x1214 +#define HDMI_FC_DBGAUD2CH6 0x1215 +#define HDMI_FC_DBGAUD0CH7 0x1216 +#define HDMI_FC_DBGAUD1CH7 0x1217 +#define HDMI_FC_DBGAUD2CH7 0x1218 +#define HDMI_FC_DBGTMDS0 0x1219 +#define HDMI_FC_DBGTMDS1 0x121A +#define HDMI_FC_DBGTMDS2 0x121B + +/* HDMI Source PHY Registers */ +#define HDMI_PHY_CONF0 0x3000 +#define HDMI_PHY_TST0 0x3001 +#define HDMI_PHY_TST1 0x3002 +#define HDMI_PHY_TST2 0x3003 +#define HDMI_PHY_STAT0 0x3004 +#define HDMI_PHY_INT0 0x3005 +#define HDMI_PHY_MASK0 0x3006 +#define HDMI_PHY_POL0 0x3007 + +/* HDMI Master PHY Registers */ +#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020 +#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021 +#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022 +#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023 +#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024 +#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025 +#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026 +#define HDMI_PHY_I2CM_INT_ADDR 0x3027 +#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028 +#define HDMI_PHY_I2CM_DIV_ADDR 0x3029 +#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a +#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b +#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c +#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d +#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e +#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f +#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030 +#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031 +#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032 + +/* Audio Sampler Registers */ +#define HDMI_AUD_CONF0 0x3100 +#define HDMI_AUD_CONF1 0x3101 +#define HDMI_AUD_INT 0x3102 +#define HDMI_AUD_CONF2 0x3103 +#define HDMI_AUD_N1 0x3200 +#define HDMI_AUD_N2 0x3201 +#define HDMI_AUD_N3 0x3202 +#define HDMI_AUD_CTS1 0x3203 +#define HDMI_AUD_CTS2 0x3204 +#define HDMI_AUD_CTS3 0x3205 +#define HDMI_AUD_INPUTCLKFS 0x3206 +#define HDMI_AUD_SPDIFINT 0x3302 +#define HDMI_AUD_CONF0_HBR 0x3400 +#define HDMI_AUD_HBR_STATUS 0x3401 +#define HDMI_AUD_HBR_INT 0x3402 +#define HDMI_AUD_HBR_POL 0x3403 +#define HDMI_AUD_HBR_MASK 0x3404 + +/* + * Generic Parallel Audio Interface Registers + * Not used as GPAUD interface is not enabled in hw + */ +#define HDMI_GP_CONF0 0x3500 +#define HDMI_GP_CONF1 0x3501 +#define HDMI_GP_CONF2 0x3502 +#define HDMI_GP_STAT 0x3503 +#define HDMI_GP_INT 0x3504 +#define HDMI_GP_MASK 0x3505 +#define HDMI_GP_POL 0x3506 + +/* Audio DMA Registers */ +#define HDMI_AHB_DMA_CONF0 0x3600 +#define HDMI_AHB_DMA_START 0x3601 +#define HDMI_AHB_DMA_STOP 0x3602 +#define HDMI_AHB_DMA_THRSLD 0x3603 +#define HDMI_AHB_DMA_STRADDR0 0x3604 +#define HDMI_AHB_DMA_STRADDR1 0x3605 +#define HDMI_AHB_DMA_STRADDR2 0x3606 +#define HDMI_AHB_DMA_STRADDR3 0x3607 +#define HDMI_AHB_DMA_STPADDR0 0x3608 +#define HDMI_AHB_DMA_STPADDR1 0x3609 +#define HDMI_AHB_DMA_STPADDR2 0x360a +#define HDMI_AHB_DMA_STPADDR3 0x360b +#define HDMI_AHB_DMA_BSTADDR0 0x360c +#define HDMI_AHB_DMA_BSTADDR1 0x360d +#define HDMI_AHB_DMA_BSTADDR2 0x360e +#define HDMI_AHB_DMA_BSTADDR3 0x360f +#define HDMI_AHB_DMA_MBLENGTH0 0x3610 +#define HDMI_AHB_DMA_MBLENGTH1 0x3611 +#define HDMI_AHB_DMA_STAT 0x3612 +#define HDMI_AHB_DMA_INT 0x3613 +#define HDMI_AHB_DMA_MASK 0x3614 +#define HDMI_AHB_DMA_POL 0x3615 +#define HDMI_AHB_DMA_CONF1 0x3616 +#define HDMI_AHB_DMA_BUFFSTAT 0x3617 +#define HDMI_AHB_DMA_BUFFINT 0x3618 +#define HDMI_AHB_DMA_BUFFMASK 0x3619 +#define HDMI_AHB_DMA_BUFFPOL 0x361a + +/* Main Controller Registers */ +#define HDMI_MC_SFRDIV 0x4000 +#define HDMI_MC_CLKDIS 0x4001 +#define HDMI_MC_SWRSTZ 0x4002 +#define HDMI_MC_OPCTRL 0x4003 +#define HDMI_MC_FLOWCTRL 0x4004 +#define HDMI_MC_PHYRSTZ 0x4005 +#define HDMI_MC_LOCKONCLOCK 0x4006 +#define HDMI_MC_HEACPHY_RST 0x4007 + +/* Color Space Converter Registers */ +#define HDMI_CSC_CFG 0x4100 +#define HDMI_CSC_SCALE 0x4101 +#define HDMI_CSC_COEF_A1_MSB 0x4102 +#define HDMI_CSC_COEF_A1_LSB 0x4103 +#define HDMI_CSC_COEF_A2_MSB 0x4104 +#define HDMI_CSC_COEF_A2_LSB 0x4105 +#define HDMI_CSC_COEF_A3_MSB 0x4106 +#define HDMI_CSC_COEF_A3_LSB 0x4107 +#define HDMI_CSC_COEF_A4_MSB 0x4108 +#define HDMI_CSC_COEF_A4_LSB 0x4109 +#define HDMI_CSC_COEF_B1_MSB 0x410A +#define HDMI_CSC_COEF_B1_LSB 0x410B +#define HDMI_CSC_COEF_B2_MSB 0x410C +#define HDMI_CSC_COEF_B2_LSB 0x410D +#define HDMI_CSC_COEF_B3_MSB 0x410E +#define HDMI_CSC_COEF_B3_LSB 0x410F +#define HDMI_CSC_COEF_B4_MSB 0x4110 +#define HDMI_CSC_COEF_B4_LSB 0x4111 +#define HDMI_CSC_COEF_C1_MSB 0x4112 +#define HDMI_CSC_COEF_C1_LSB 0x4113 +#define HDMI_CSC_COEF_C2_MSB 0x4114 +#define HDMI_CSC_COEF_C2_LSB 0x4115 +#define HDMI_CSC_COEF_C3_MSB 0x4116 +#define HDMI_CSC_COEF_C3_LSB 0x4117 +#define HDMI_CSC_COEF_C4_MSB 0x4118 +#define HDMI_CSC_COEF_C4_LSB 0x4119 + +/* HDCP Encryption Engine Registers */ +#define HDMI_A_HDCPCFG0 0x5000 +#define HDMI_A_HDCPCFG1 0x5001 +#define HDMI_A_HDCPOBS0 0x5002 +#define HDMI_A_HDCPOBS1 0x5003 +#define HDMI_A_HDCPOBS2 0x5004 +#define HDMI_A_HDCPOBS3 0x5005 +#define HDMI_A_APIINTCLR 0x5006 +#define HDMI_A_APIINTSTAT 0x5007 +#define HDMI_A_APIINTMSK 0x5008 +#define HDMI_A_VIDPOLCFG 0x5009 +#define HDMI_A_OESSWCFG 0x500A +#define HDMI_A_TIMER1SETUP0 0x500B +#define HDMI_A_TIMER1SETUP1 0x500C +#define HDMI_A_TIMER2SETUP0 0x500D +#define HDMI_A_TIMER2SETUP1 0x500E +#define HDMI_A_100MSCFG 0x500F +#define HDMI_A_2SCFG0 0x5010 +#define HDMI_A_2SCFG1 0x5011 +#define HDMI_A_5SCFG0 0x5012 +#define HDMI_A_5SCFG1 0x5013 +#define HDMI_A_SRMVERLSB 0x5014 +#define HDMI_A_SRMVERMSB 0x5015 +#define HDMI_A_SRMCTRL 0x5016 +#define HDMI_A_SFRSETUP 0x5017 +#define HDMI_A_I2CHSETUP 0x5018 +#define HDMI_A_INTSETUP 0x5019 +#define HDMI_A_PRESETUP 0x501A +#define HDMI_A_SRM_BASE 0x5020 + +/* CEC Engine Registers */ +#define HDMI_CEC_CTRL 0x7D00 +#define HDMI_CEC_STAT 0x7D01 +#define HDMI_CEC_MASK 0x7D02 +#define HDMI_CEC_POLARITY 0x7D03 +#define HDMI_CEC_INT 0x7D04 +#define HDMI_CEC_ADDR_L 0x7D05 +#define HDMI_CEC_ADDR_H 0x7D06 +#define HDMI_CEC_TX_CNT 0x7D07 +#define HDMI_CEC_RX_CNT 0x7D08 +#define HDMI_CEC_TX_DATA0 0x7D10 +#define HDMI_CEC_TX_DATA1 0x7D11 +#define HDMI_CEC_TX_DATA2 0x7D12 +#define HDMI_CEC_TX_DATA3 0x7D13 +#define HDMI_CEC_TX_DATA4 0x7D14 +#define HDMI_CEC_TX_DATA5 0x7D15 +#define HDMI_CEC_TX_DATA6 0x7D16 +#define HDMI_CEC_TX_DATA7 0x7D17 +#define HDMI_CEC_TX_DATA8 0x7D18 +#define HDMI_CEC_TX_DATA9 0x7D19 +#define HDMI_CEC_TX_DATA10 0x7D1a +#define HDMI_CEC_TX_DATA11 0x7D1b +#define HDMI_CEC_TX_DATA12 0x7D1c +#define HDMI_CEC_TX_DATA13 0x7D1d +#define HDMI_CEC_TX_DATA14 0x7D1e +#define HDMI_CEC_TX_DATA15 0x7D1f +#define HDMI_CEC_RX_DATA0 0x7D20 +#define HDMI_CEC_RX_DATA1 0x7D21 +#define HDMI_CEC_RX_DATA2 0x7D22 +#define HDMI_CEC_RX_DATA3 0x7D23 +#define HDMI_CEC_RX_DATA4 0x7D24 +#define HDMI_CEC_RX_DATA5 0x7D25 +#define HDMI_CEC_RX_DATA6 0x7D26 +#define HDMI_CEC_RX_DATA7 0x7D27 +#define HDMI_CEC_RX_DATA8 0x7D28 +#define HDMI_CEC_RX_DATA9 0x7D29 +#define HDMI_CEC_RX_DATA10 0x7D2a +#define HDMI_CEC_RX_DATA11 0x7D2b +#define HDMI_CEC_RX_DATA12 0x7D2c +#define HDMI_CEC_RX_DATA13 0x7D2d +#define HDMI_CEC_RX_DATA14 0x7D2e +#define HDMI_CEC_RX_DATA15 0x7D2f +#define HDMI_CEC_LOCK 0x7D30 +#define HDMI_CEC_WKUPCTRL 0x7D31 + +/* I2C Master Registers (E-DDC) */ +#define HDMI_I2CM_SLAVE 0x7E00 +#define HDMI_I2CMESS 0x7E01 +#define HDMI_I2CM_DATAO 0x7E02 +#define HDMI_I2CM_DATAI 0x7E03 +#define HDMI_I2CM_OPERATION 0x7E04 +#define HDMI_I2CM_INT 0x7E05 +#define HDMI_I2CM_CTLINT 0x7E06 +#define HDMI_I2CM_DIV 0x7E07 +#define HDMI_I2CM_SEGADDR 0x7E08 +#define HDMI_I2CM_SOFTRSTZ 0x7E09 +#define HDMI_I2CM_SEGPTR 0x7E0A +#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B +#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C +#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D +#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E +#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F +#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10 +#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11 +#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12 + +enum { +/* IH_FC_INT2 field values */ + HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03, + HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02, + HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01, + +/* IH_FC_STAT2 field values */ + HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03, + HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, + HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, + +/* IH_PHY_STAT0 field values */ + HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20, + HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10, + HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8, + HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4, + HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2, + HDMI_IH_PHY_STAT0_HPD = 0x1, + +/* IH_MUTE_I2CMPHY_STAT0 field values */ + HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2, + HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1, + +/* IH_AHBDMAAUD_STAT0 field values */ + HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20, + HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10, + HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08, + HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04, + HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02, + HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01, + +/* IH_MUTE_FC_STAT2 field values */ + HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03, + HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, + HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, + +/* IH_MUTE_AHBDMAAUD_STAT0 field values */ + HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20, + HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10, + HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08, + HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04, + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02, + HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01, + +/* IH_MUTE field values */ + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2, + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1, + +/* TX_INVID0 field values */ + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80, + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80, + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00, + HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F, + HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0, + +/* TX_INSTUFFING field values */ + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4, + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4, + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0, + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2, + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2, + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0, + HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1, + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1, + HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0, + +/* VP_PR_CD field values */ + HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0, + HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4, + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F, + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0, + +/* VP_STUFF field values */ + HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20, + HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5, + HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10, + HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4, + HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8, + HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3, + HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4, + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4, + HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0, + HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2, + HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2, + HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0, + HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1, + HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1, + HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0, + +/* VP_CONF field values */ + HDMI_VP_CONF_BYPASS_EN_MASK = 0x40, + HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40, + HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00, + HDMI_VP_CONF_PP_EN_ENMASK = 0x20, + HDMI_VP_CONF_PP_EN_ENABLE = 0x20, + HDMI_VP_CONF_PP_EN_DISABLE = 0x00, + HDMI_VP_CONF_PR_EN_MASK = 0x10, + HDMI_VP_CONF_PR_EN_ENABLE = 0x10, + HDMI_VP_CONF_PR_EN_DISABLE = 0x00, + HDMI_VP_CONF_YCC422_EN_MASK = 0x8, + HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8, + HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0, + HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4, + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4, + HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0, + HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3, + HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3, + HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1, + HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0, + +/* VP_REMAP field values */ + HDMI_VP_REMAP_MASK = 0x3, + HDMI_VP_REMAP_YCC422_24bit = 0x2, + HDMI_VP_REMAP_YCC422_20bit = 0x1, + HDMI_VP_REMAP_YCC422_16bit = 0x0, + +/* FC_INVIDCONF field values */ + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80, + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80, + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00, + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40, + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40, + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20, + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20, + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, + HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10, + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10, + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00, + HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8, + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8, + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0, + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2, + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2, + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0, + HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1, + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1, + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0, + +/* FC_AUDICONF0 field values */ + HDMI_FC_AUDICONF0_CC_OFFSET = 4, + HDMI_FC_AUDICONF0_CC_MASK = 0x70, + HDMI_FC_AUDICONF0_CT_OFFSET = 0, + HDMI_FC_AUDICONF0_CT_MASK = 0xF, + +/* FC_AUDICONF1 field values */ + HDMI_FC_AUDICONF1_SS_OFFSET = 3, + HDMI_FC_AUDICONF1_SS_MASK = 0x18, + HDMI_FC_AUDICONF1_SF_OFFSET = 0, + HDMI_FC_AUDICONF1_SF_MASK = 0x7, + +/* FC_AUDICONF3 field values */ + HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5, + HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60, + HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4, + HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10, + HDMI_FC_AUDICONF3_LSV_OFFSET = 0, + HDMI_FC_AUDICONF3_LSV_MASK = 0xF, + +/* FC_AUDSCHNLS0 field values */ + HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4, + HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30, + HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0, + HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01, + +/* FC_AUDSCHNLS3-6 field values */ + HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0, + HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f, + HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4, + HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0, + HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0, + HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f, + HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4, + HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0, + + HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0, + HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f, + HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4, + HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0, + HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0, + HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f, + HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4, + HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0, + +/* HDMI_FC_AUDSCHNLS7 field values */ + HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4, + HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30, + +/* HDMI_FC_AUDSCHNLS8 field values */ + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0, + HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4, + HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f, + HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0, + +/* FC_AUDSCONF field values */ + HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0, + HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4, + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1, + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0, + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1, + HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0, + +/* FC_STAT2 field values */ + HDMI_FC_STAT2_OVERFLOW_MASK = 0x03, + HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02, + HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01, + +/* FC_INT2 field values */ + HDMI_FC_INT2_OVERFLOW_MASK = 0x03, + HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02, + HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01, + +/* FC_MASK2 field values */ + HDMI_FC_MASK2_OVERFLOW_MASK = 0x03, + HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02, + HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01, + +/* FC_PRCONF field values */ + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0, + HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4, + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F, + HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0, + +/* FC_AVICONF0-FC_AVICONF3 field values */ + HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03, + HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00, + HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01, + HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02, + HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40, + HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40, + HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00, + HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C, + HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00, + HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04, + HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08, + HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C, + HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30, + HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10, + HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20, + HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00, + + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20, + HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0, + HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00, + HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40, + HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80, + HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0, + + HDMI_FC_AVICONF2_SCALING_MASK = 0x03, + HDMI_FC_AVICONF2_SCALING_NONE = 0x00, + HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01, + HDMI_FC_AVICONF2_SCALING_VERT = 0x02, + HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03, + HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C, + HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00, + HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04, + HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40, + HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80, + HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00, + HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80, + + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03, + HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C, + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, + HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, + +/* FC_DBGFORCE field values */ + HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, + HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, + +/* PHY_CONF0 field values */ + HDMI_PHY_CONF0_PDZ_MASK = 0x80, + HDMI_PHY_CONF0_PDZ_OFFSET = 7, + HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, + HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, + HDMI_PHY_CONF0_SPARECTRL = 0x20, + HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3, + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4, + HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2, + HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2, + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1, + HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1, + HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0, + +/* PHY_TST0 field values */ + HDMI_PHY_TST0_TSTCLR_MASK = 0x20, + HDMI_PHY_TST0_TSTCLR_OFFSET = 5, + HDMI_PHY_TST0_TSTEN_MASK = 0x10, + HDMI_PHY_TST0_TSTEN_OFFSET = 4, + HDMI_PHY_TST0_TSTCLK_MASK = 0x1, + HDMI_PHY_TST0_TSTCLK_OFFSET = 0, + +/* PHY_STAT0 field values */ + HDMI_PHY_RX_SENSE3 = 0x80, + HDMI_PHY_RX_SENSE2 = 0x40, + HDMI_PHY_RX_SENSE1 = 0x20, + HDMI_PHY_RX_SENSE0 = 0x10, + HDMI_PHY_HPD = 0x02, + HDMI_PHY_TX_PHY_LOCK = 0x01, + +/* PHY_I2CM_SLAVE_ADDR field values */ + HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69, + HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49, + +/* PHY_I2CM_OPERATION_ADDR field values */ + HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10, + HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1, + +/* HDMI_PHY_I2CM_INT_ADDR */ + HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08, + HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04, + +/* HDMI_PHY_I2CM_CTLINT_ADDR */ + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80, + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40, + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08, + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04, + +/* AUD_CTS3 field values */ + HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5, + HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0, + HDMI_AUD_CTS3_N_SHIFT_1 = 0, + HDMI_AUD_CTS3_N_SHIFT_16 = 0x20, + HDMI_AUD_CTS3_N_SHIFT_32 = 0x40, + HDMI_AUD_CTS3_N_SHIFT_64 = 0x60, + HDMI_AUD_CTS3_N_SHIFT_128 = 0x80, + HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0, + /* note that the CTS3 MANUAL bit has been removed + from our part. Can't set it, will read as 0. */ + HDMI_AUD_CTS3_CTS_MANUAL = 0x10, + HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f, + +/* AHB_DMA_CONF0 field values */ + HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7, + HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80, + HDMI_AHB_DMA_CONF0_HBR = 0x10, + HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3, + HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08, + HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1, + HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06, + HDMI_AHB_DMA_CONF0_INCR4 = 0x0, + HDMI_AHB_DMA_CONF0_INCR8 = 0x2, + HDMI_AHB_DMA_CONF0_INCR16 = 0x4, + HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1, + +/* HDMI_AHB_DMA_START field values */ + HDMI_AHB_DMA_START_START_OFFSET = 0, + HDMI_AHB_DMA_START_START_MASK = 0x01, + +/* HDMI_AHB_DMA_STOP field values */ + HDMI_AHB_DMA_STOP_STOP_OFFSET = 0, + HDMI_AHB_DMA_STOP_STOP_MASK = 0x01, + +/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */ + HDMI_AHB_DMA_DONE = 0x80, + HDMI_AHB_DMA_RETRY_SPLIT = 0x40, + HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20, + HDMI_AHB_DMA_ERROR = 0x10, + HDMI_AHB_DMA_FIFO_THREMPTY = 0x04, + HDMI_AHB_DMA_FIFO_FULL = 0x02, + HDMI_AHB_DMA_FIFO_EMPTY = 0x01, + +/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */ + HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02, + HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01, + +/* MC_CLKDIS field values */ + HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40, + HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20, + HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10, + HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8, + HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4, + HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2, + HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1, + +/* MC_SWRSTZ field values */ + HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02, + +/* MC_FLOWCTRL field values */ + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1, + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1, + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0, + +/* MC_PHYRSTZ field values */ + HDMI_MC_PHYRSTZ_ASSERT = 0x0, + HDMI_MC_PHYRSTZ_DEASSERT = 0x1, + +/* MC_HEACPHY_RST field values */ + HDMI_MC_HEACPHY_RST_ASSERT = 0x1, + HDMI_MC_HEACPHY_RST_DEASSERT = 0x0, + +/* CSC_CFG field values */ + HDMI_CSC_CFG_INTMODE_MASK = 0x30, + HDMI_CSC_CFG_INTMODE_OFFSET = 4, + HDMI_CSC_CFG_INTMODE_DISABLE = 0x00, + HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10, + HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20, + HDMI_CSC_CFG_DECMODE_MASK = 0x3, + HDMI_CSC_CFG_DECMODE_OFFSET = 0, + HDMI_CSC_CFG_DECMODE_DISABLE = 0x0, + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1, + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2, + HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3, + +/* CSC_SCALE field values */ + HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70, + HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03, + +/* A_HDCPCFG0 field values */ + HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80, + HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80, + HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00, + HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40, + HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40, + HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00, + HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20, + HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20, + HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00, + HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10, + HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10, + HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00, + HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8, + HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8, + HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0, + HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4, + HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4, + HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0, + HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2, + HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2, + HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0, + HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1, + HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1, + HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0, + +/* A_HDCPCFG1 field values */ + HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8, + HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8, + HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0, + HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4, + HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4, + HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0, + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2, + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2, + HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0, + HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1, + HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0, + +/* A_VIDPOLCFG field values */ + HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60, + HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5, + HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10, + HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10, + HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0, + HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8, + HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8, + HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0, + HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2, + HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2, + HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, +}; +#endif /* __IMX_HDMI_H__ */ diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h index b6d36b38b99c..866e355fa409 100644 --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h @@ -212,6 +212,7 @@ #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI1 (0x1 << 4) #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI0 (0x2 << 4) #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI1 (0x3 << 4) +#define IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT 2 #define IMX6Q_GPR3_HDMI_MUX_CTL_MASK (0x3 << 2) #define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI0 (0x0 << 2) #define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI1 (0x1 << 2) -- cgit v1.2.3 From 9f8144c6ed8f04984ee372a060ad75d228d2b9f0 Mon Sep 17 00:00:00 2001 From: Nick Hudson Date: Fri, 6 Dec 2013 14:01:44 -0800 Subject: staging: dwc2: don't issue traffic to LS devices in FS mode I fell over the problem reported in https://github.com/raspberrypi/linux/pull/390: "Issuing low-speed packets when the root port is in full-speed mode causes the root port to stop responding. Explicitly fail when enqueuing URBs to a LS endpoint on a FS bus." with my dwc2 testing in NetBSD, so I adapted the change to dwc2. Signed-off-by: Nick Hudson [paulz: fixed up the patch to compile under Linux, and tested it] Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 24b57d7952c5..07dfe855dc20 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -355,6 +355,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, unsigned long flags; u32 intr_mask; int retval; + int dev_speed; if (!hsotg->flags.b.port_connect_status) { /* No longer connected */ @@ -362,6 +363,19 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, return -ENODEV; } + dev_speed = dwc2_host_get_speed(hsotg, urb->priv); + + /* Some configurations cannot support LS traffic on a FS root port */ + if ((dev_speed == USB_SPEED_LOW) && + (hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) && + (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI)) { + u32 hprt0 = readl(hsotg->regs + HPRT0); + u32 prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; + + if (prtspd == HPRT0_SPD_FULL_SPEED) + return -ENODEV; + } + qtd = kzalloc(sizeof(*qtd), mem_flags); if (!qtd) return -ENOMEM; -- cgit v1.2.3 From 9b89b04935e73d0e590cc924fea9a2e00040b73a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sat, 7 Dec 2013 11:40:28 +0000 Subject: staging: vt6656: baseband.c clean up BBbVT3184Init White space clean up and remove camel case from variables. pDevice-> priv ntStatus -> status wLength ->length pbyAddr -> addr pbyAgc -> agc wLengthAgc ->length_agc abyArray -> array Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 324 ++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 169 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 468f455e0d26..d3dd1a23d5ca 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -931,191 +931,177 @@ void BBvSetAntennaMode(struct vnt_private *pDevice, u8 byAntennaMode) * */ -int BBbVT3184Init(struct vnt_private *pDevice) +int BBbVT3184Init(struct vnt_private *priv) { - int ntStatus; - u16 wLength; - u8 * pbyAddr; - u8 * pbyAgc; - u16 wLengthAgc; - u8 abyArray[256]; + int status; + u16 lenght; + u8 *addr; + u8 *agc; + u16 lenght_agc; + u8 array[256]; u8 data; - ntStatus = CONTROLnsRequestIn(pDevice, - MESSAGE_TYPE_READ, - 0, - MESSAGE_REQUEST_EEPROM, - EEP_MAX_CONTEXT_SIZE, - pDevice->abyEEPROM); - if (ntStatus != STATUS_SUCCESS) { - return false; - } + status = CONTROLnsRequestIn(priv, MESSAGE_TYPE_READ, 0, + MESSAGE_REQUEST_EEPROM, EEP_MAX_CONTEXT_SIZE, + priv->abyEEPROM); + if (status != STATUS_SUCCESS) + return false; + + /* zonetype initial */ + priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE]; + + if (priv->config_file.ZoneType >= 0) { + if ((priv->config_file.ZoneType == 0) && + (priv->abyEEPROM[EEP_OFS_ZONETYPE] != 0x00)) { + priv->abyEEPROM[EEP_OFS_ZONETYPE] = 0; + priv->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Init Zone Type :USA\n"); + } else if ((priv->config_file.ZoneType == 1) && + (priv->abyEEPROM[EEP_OFS_ZONETYPE] != 0x01)) { + priv->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01; + priv->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Init Zone Type :Japan\n"); + } else if ((priv->config_file.ZoneType == 2) && + (priv->abyEEPROM[EEP_OFS_ZONETYPE] != 0x02)) { + priv->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02; + priv->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Init Zone Type :Europe\n"); + } else { + if (priv->config_file.ZoneType != + priv->abyEEPROM[EEP_OFS_ZONETYPE]) + printk("zonetype in file[%02x]\ + mismatch with in EEPROM[%02x]\n", + priv->config_file.ZoneType, + priv->abyEEPROM[EEP_OFS_ZONETYPE]); + else + printk("Read Zonetype file success,\ + use default zonetype setting[%02x]\n", + priv->config_file.ZoneType); + } + } -// if ((pDevice->abyEEPROM[EEP_OFS_RADIOCTL]&0x06)==0x04) -// return false; - -//zonetype initial - pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; - if(pDevice->config_file.ZoneType >= 0) { //read zonetype file ok! - if ((pDevice->config_file.ZoneType == 0)&& - (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] !=0x00)){ //for USA - pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0; - pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :USA\n"); - } - else if((pDevice->config_file.ZoneType == 1)&& - (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x01)){ //for Japan - pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01; - pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Japan\n"); - } - else if((pDevice->config_file.ZoneType == 2)&& - (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x02)){ //for Europe - pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02; - pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Europe\n"); - } -else { - if(pDevice->config_file.ZoneType !=pDevice->abyEEPROM[EEP_OFS_ZONETYPE]) - printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",pDevice->config_file.ZoneType,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]); - else - printk("Read Zonetype file success,use default zonetype setting[%02x]\n",pDevice->config_file.ZoneType); - } -} + if (!priv->bZoneRegExist) + priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE]; + + priv->byRFType = priv->abyEEPROM[EEP_OFS_RFTYPE]; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Zone Type %x\n", + priv->byZoneType); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RF Type %d\n", priv->byRFType); + + if ((priv->byRFType == RF_AL2230) || + (priv->byRFType == RF_AL2230S)) { + priv->byBBRxConf = abyVT3184_AL2230[10]; + lenght = sizeof(abyVT3184_AL2230); + addr = abyVT3184_AL2230; + agc = abyVT3184_AGC; + lenght_agc = sizeof(abyVT3184_AGC); + + priv->abyBBVGA[0] = 0x1C; + priv->abyBBVGA[1] = 0x10; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->ldBmThreshold[0] = -70; + priv->ldBmThreshold[1] = -48; + priv->ldBmThreshold[2] = 0; + priv->ldBmThreshold[3] = 0; + } else if (priv->byRFType == RF_AIROHA7230) { + priv->byBBRxConf = abyVT3184_AL2230[10]; + lenght = sizeof(abyVT3184_AL2230); + addr = abyVT3184_AL2230; + agc = abyVT3184_AGC; + lenght_agc = sizeof(abyVT3184_AGC); + + addr[0xd7] = 0x06; + + priv->abyBBVGA[0] = 0x1c; + priv->abyBBVGA[1] = 0x10; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->ldBmThreshold[0] = -70; + priv->ldBmThreshold[1] = -48; + priv->ldBmThreshold[2] = 0; + priv->ldBmThreshold[3] = 0; + } else if ((priv->byRFType == RF_VT3226) || + (priv->byRFType == RF_VT3226D0)) { + priv->byBBRxConf = abyVT3184_VT3226D0[10]; + lenght = sizeof(abyVT3184_VT3226D0); + addr = abyVT3184_VT3226D0; + agc = abyVT3184_AGC; + lenght_agc = sizeof(abyVT3184_AGC); + + priv->abyBBVGA[0] = 0x20; + priv->abyBBVGA[1] = 0x10; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->ldBmThreshold[0] = -70; + priv->ldBmThreshold[1] = -48; + priv->ldBmThreshold[2] = 0; + priv->ldBmThreshold[3] = 0; + /* Fix VT3226 DFC system timing issue */ + MACvRegBitsOn(priv, MAC_REG_SOFTPWRCTL2, SOFTPWRCTL_RFLEOPT); + } else if ((priv->byRFType == RF_VT3342A0)) { + priv->byBBRxConf = abyVT3184_VT3226D0[10]; + lenght = sizeof(abyVT3184_VT3226D0); + addr = abyVT3184_VT3226D0; + agc = abyVT3184_AGC; + lenght_agc = sizeof(abyVT3184_AGC); + + priv->abyBBVGA[0] = 0x20; + priv->abyBBVGA[1] = 0x10; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->ldBmThreshold[0] = -70; + priv->ldBmThreshold[1] = -48; + priv->ldBmThreshold[2] = 0; + priv->ldBmThreshold[3] = 0; + /* Fix VT3226 DFC system timing issue */ + MACvRegBitsOn(priv, MAC_REG_SOFTPWRCTL2, SOFTPWRCTL_RFLEOPT); + } else { + return true; + } - if ( !pDevice->bZoneRegExist ) { - pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; - } - pDevice->byRFType = pDevice->abyEEPROM[EEP_OFS_RFTYPE]; - - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Zone Type %x\n", pDevice->byZoneType); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RF Type %d\n", pDevice->byRFType); - - if ((pDevice->byRFType == RF_AL2230) || (pDevice->byRFType == RF_AL2230S)) { - pDevice->byBBRxConf = abyVT3184_AL2230[10]; - wLength = sizeof(abyVT3184_AL2230); - pbyAddr = abyVT3184_AL2230; - pbyAgc = abyVT3184_AGC; - wLengthAgc = sizeof(abyVT3184_AGC); - - pDevice->abyBBVGA[0] = 0x1C; - pDevice->abyBBVGA[1] = 0x10; - pDevice->abyBBVGA[2] = 0x0; - pDevice->abyBBVGA[3] = 0x0; - pDevice->ldBmThreshold[0] = -70; - pDevice->ldBmThreshold[1] = -48; - pDevice->ldBmThreshold[2] = 0; - pDevice->ldBmThreshold[3] = 0; - } - else if (pDevice->byRFType == RF_AIROHA7230) { - pDevice->byBBRxConf = abyVT3184_AL2230[10]; - wLength = sizeof(abyVT3184_AL2230); - pbyAddr = abyVT3184_AL2230; - pbyAgc = abyVT3184_AGC; - wLengthAgc = sizeof(abyVT3184_AGC); - - // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) - //pbyAddr[0x09] = 0x41; - // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) - //pbyAddr[0x0a] = 0x28; - // Select VC1/VC2, CR215 = 0x02->0x06 - pbyAddr[0xd7] = 0x06; - - pDevice->abyBBVGA[0] = 0x1C; - pDevice->abyBBVGA[1] = 0x10; - pDevice->abyBBVGA[2] = 0x0; - pDevice->abyBBVGA[3] = 0x0; - pDevice->ldBmThreshold[0] = -70; - pDevice->ldBmThreshold[1] = -48; - pDevice->ldBmThreshold[2] = 0; - pDevice->ldBmThreshold[3] = 0; - } - else if ( (pDevice->byRFType == RF_VT3226) || (pDevice->byRFType == RF_VT3226D0) ) { - pDevice->byBBRxConf = abyVT3184_VT3226D0[10]; //RobertYu:20060515 - wLength = sizeof(abyVT3184_VT3226D0); //RobertYu:20060515 - pbyAddr = abyVT3184_VT3226D0; //RobertYu:20060515 - pbyAgc = abyVT3184_AGC; - wLengthAgc = sizeof(abyVT3184_AGC); - - pDevice->abyBBVGA[0] = 0x20; //RobertYu:20060104, reguest by Jack - pDevice->abyBBVGA[1] = 0x10; - pDevice->abyBBVGA[2] = 0x0; - pDevice->abyBBVGA[3] = 0x0; - pDevice->ldBmThreshold[0] = -70; - pDevice->ldBmThreshold[1] = -48; - pDevice->ldBmThreshold[2] = 0; - pDevice->ldBmThreshold[3] = 0; - // Fix VT3226 DFC system timing issue - MACvRegBitsOn(pDevice, MAC_REG_SOFTPWRCTL2, SOFTPWRCTL_RFLEOPT); - //}} - //{{RobertYu:20060609 - } else if ( (pDevice->byRFType == RF_VT3342A0) ) { - pDevice->byBBRxConf = abyVT3184_VT3226D0[10]; - wLength = sizeof(abyVT3184_VT3226D0); - pbyAddr = abyVT3184_VT3226D0; - pbyAgc = abyVT3184_AGC; - wLengthAgc = sizeof(abyVT3184_AGC); - - pDevice->abyBBVGA[0] = 0x20; - pDevice->abyBBVGA[1] = 0x10; - pDevice->abyBBVGA[2] = 0x0; - pDevice->abyBBVGA[3] = 0x0; - pDevice->ldBmThreshold[0] = -70; - pDevice->ldBmThreshold[1] = -48; - pDevice->ldBmThreshold[2] = 0; - pDevice->ldBmThreshold[3] = 0; - // Fix VT3226 DFC system timing issue - MACvRegBitsOn(pDevice, MAC_REG_SOFTPWRCTL2, SOFTPWRCTL_RFLEOPT); - //}} - } else { - return true; - } + memcpy(array, addr, lenght); - memcpy(abyArray, pbyAddr, wLength); - CONTROLnsRequestOut(pDevice, - MESSAGE_TYPE_WRITE, - 0, - MESSAGE_REQUEST_BBREG, - wLength, - abyArray - ); - - memcpy(abyArray, pbyAgc, wLengthAgc); - CONTROLnsRequestOut(pDevice, - MESSAGE_TYPE_WRITE, - 0, - MESSAGE_REQUEST_BBAGC, - wLengthAgc, - abyArray - ); - - if ((pDevice->byRFType == RF_VT3226) || //RobertYu:20051116, 20060111 remove VT3226D0 - (pDevice->byRFType == RF_VT3342A0) //RobertYu:20060609 - ) { - ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_ITRTMSET,0x23); - MACvRegBitsOn(pDevice,MAC_REG_PAPEDELAY,0x01); - } - else if (pDevice->byRFType == RF_VT3226D0) - { - ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_ITRTMSET,0x11); - MACvRegBitsOn(pDevice,MAC_REG_PAPEDELAY,0x01); - } + CONTROLnsRequestOut(priv, MESSAGE_TYPE_WRITE, 0, + MESSAGE_REQUEST_BBREG, lenght, array); + + memcpy(array, agc, lenght_agc); + + CONTROLnsRequestOut(priv, MESSAGE_TYPE_WRITE, 0, + MESSAGE_REQUEST_BBAGC, lenght_agc, array); + + if ((priv->byRFType == RF_VT3226) || + (priv->byRFType == RF_VT3342A0)) { + ControlvWriteByte(priv, MESSAGE_REQUEST_MACREG, + MAC_REG_ITRTMSET, 0x23); + MACvRegBitsOn(priv, MAC_REG_PAPEDELAY, 0x01); + } else if (priv->byRFType == RF_VT3226D0) { + ControlvWriteByte(priv, MESSAGE_REQUEST_MACREG, + MAC_REG_ITRTMSET, 0x11); + MACvRegBitsOn(priv, MAC_REG_PAPEDELAY, 0x01); + } + + ControlvWriteByte(priv, MESSAGE_REQUEST_BBREG, 0x04, 0x7f); + ControlvWriteByte(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01); - ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x04,0x7F); - ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x0D,0x01); + RFbRFTableDownload(priv); - RFbRFTableDownload(pDevice); /* Fix for TX USB resets from vendors driver */ - CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, USB_REG4, + CONTROLnsRequestIn(priv, MESSAGE_TYPE_READ, USB_REG4, MESSAGE_REQUEST_MEM, sizeof(data), &data); data |= 0x2; - CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, USB_REG4, + CONTROLnsRequestOut(priv, MESSAGE_TYPE_WRITE, USB_REG4, MESSAGE_REQUEST_MEM, sizeof(data), &data); - return true;//ntStatus; + return true; } /* -- cgit v1.2.3 From 588c31eacdc163b59bef1675295bc4be23112d05 Mon Sep 17 00:00:00 2001 From: Daniel Dodge Date: Sat, 7 Dec 2013 03:36:32 -0500 Subject: Drivers: Staging: ft1000: Fixed C99 // comments styling issue This patch removes C99 style comments from the driver and whenever possible attempts to match coding style of the rest of the driver. Signed-off-by: Daniel Dodge Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ft1000/ft1000-pcmcia/boot.h | 52 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 766 +++++++++++---------- .../staging/ft1000/ft1000-usb/ft1000_download.c | 62 +- 3 files changed, 455 insertions(+), 425 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ft1000/ft1000-pcmcia/boot.h b/drivers/staging/ft1000/ft1000-pcmcia/boot.h index 915165e38704..60c015c1c28a 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/boot.h +++ b/drivers/staging/ft1000/ft1000-pcmcia/boot.h @@ -1,32 +1,32 @@ -//--------------------------------------------------------------------------- -// FT1000 driver for Flarion Flash OFDM NIC Device -// -// Copyright (C) 2002 Flarion Technologies, All rights reserved. -// -// 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. This program is distributed in the hope that it will be useful, -// 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. -//--------------------------------------------------------------------------- -// -// File: boot.h -// -// Description: boatloader -// -// History: -// 1/11/05 Whc Ported to Linux. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + FT1000 driver for Flarion Flash OFDM NIC Device + + Copyright (C) 2002 Flarion Technologies, All rights reserved. + + 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. This program is distributed in the hope that it will be useful, + 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. + --------------------------------------------------------------------------- + + File: boot.h + + Description: boatloader + + History: + 1/11/05 Whc Ported to Linux. + +---------------------------------------------------------------------------*/ #ifndef _BOOTH_ #define _BOOTH_ -// Official bootloader +/* Official bootloader */ static unsigned char bootimage[] = { 0x00, 0x00, 0x01, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD7, diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 29d0a72f0d65..d6421b9b5981 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -15,7 +15,7 @@ License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ------------------------------------------------------------------------------*/ + -------------------------------------------------------------------------*/ #include #include @@ -80,19 +80,19 @@ MODULE_SUPPORTED_DEVICE("FT1000"); #define MAX_RCV_LOOP 100 -//--------------------------------------------------------------------------- -// -// Function: ft1000_read_fifo_len -// Description: This function will read the ASIC Uplink FIFO status register -// which will return the number of bytes remaining in the Uplink FIFO. -// Sixteen bytes are subtracted to make sure that the ASIC does not -// reach its threshold. -// Input: -// dev - network device structure -// Output: -// value - number of bytes available in the ASIC Uplink FIFO. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_read_fifo_len + Description: This function will read the ASIC Uplink FIFO status register + which will return the number of bytes remaining in the Uplink FIFO. + Sixteen bytes are subtracted to make sure that the ASIC does not + reach its threshold. + Input: + dev - network device structure + Output: + value - number of bytes available in the ASIC Uplink FIFO. + + -------------------------------------------------------------------------*/ static inline u16 ft1000_read_fifo_len(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -103,25 +103,25 @@ static inline u16 ft1000_read_fifo_len(struct net_device *dev) return (ft1000_read_reg(dev, FT1000_REG_MAG_UFSR) - 16); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_read_dpram -// Description: This function will read the specific area of dpram -// (Electrabuzz ASIC only) -// Input: -// dev - device structure -// offset - index of dpram -// Output: -// value - value of dpram -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_read_dpram + Description: This function will read the specific area of dpram + (Electrabuzz ASIC only) + Input: + dev - device structure + offset - index of dpram + Output: + value - value of dpram + + -------------------------------------------------------------------------*/ u16 ft1000_read_dpram(struct net_device *dev, int offset) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; u16 data; - // Provide mutual exclusive access while reading ASIC registers. + /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); data = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); @@ -130,54 +130,54 @@ u16 ft1000_read_dpram(struct net_device *dev, int offset) return (data); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_write_dpram -// Description: This function will write to a specific area of dpram -// (Electrabuzz ASIC only) -// Input: -// dev - device structure -// offset - index of dpram -// value - value to write -// Output: -// none. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_write_dpram + Description: This function will write to a specific area of dpram + (Electrabuzz ASIC only) + Input: + dev - device structure + offset - index of dpram + value - value to write + Output: + none. + + -------------------------------------------------------------------------*/ static inline void ft1000_write_dpram(struct net_device *dev, int offset, u16 value) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; - // Provide mutual exclusive access while reading ASIC registers. + /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, value); spin_unlock_irqrestore(&info->dpram_lock, flags); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_read_dpram_mag_16 -// Description: This function will read the specific area of dpram -// (Magnemite ASIC only) -// Input: -// dev - device structure -// offset - index of dpram -// Output: -// value - value of dpram -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_read_dpram_mag_16 + Description: This function will read the specific area of dpram + (Magnemite ASIC only) + Input: + dev - device structure + offset - index of dpram + Output: + value - value of dpram + + -------------------------------------------------------------------------*/ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; u16 data; - // Provide mutual exclusive access while reading ASIC registers. + /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); - // check if we want to read upper or lower 32-bit word + /* check if we want to read upper or lower 32-bit word */ if (Index) { data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL); } else { @@ -188,26 +188,26 @@ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index) return (data); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_write_dpram_mag_16 -// Description: This function will write to a specific area of dpram -// (Magnemite ASIC only) -// Input: -// dev - device structure -// offset - index of dpram -// value - value to write -// Output: -// none. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_write_dpram_mag_16 + Description: This function will write to a specific area of dpram + (Magnemite ASIC only) + Input: + dev - device structure + offset - index of dpram + value - value to write + Output: + none. + + -------------------------------------------------------------------------*/ static inline void ft1000_write_dpram_mag_16(struct net_device *dev, int offset, u16 value, int Index) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; - // Provide mutual exclusive access while reading ASIC registers. + /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); if (Index) { @@ -218,25 +218,25 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev, spin_unlock_irqrestore(&info->dpram_lock, flags); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_read_dpram_mag_32 -// Description: This function will read the specific area of dpram -// (Magnemite ASIC only) -// Input: -// dev - device structure -// offset - index of dpram -// Output: -// value - value of dpram -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_read_dpram_mag_32 + Description: This function will read the specific area of dpram + (Magnemite ASIC only) + Input: + dev - device structure + offset - index of dpram + Output: + value - value of dpram + + -------------------------------------------------------------------------*/ u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; u32 data; - // Provide mutual exclusive access while reading ASIC registers. + /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); data = inl(dev->base_addr + FT1000_REG_MAG_DPDATAL); @@ -245,41 +245,41 @@ u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset) return (data); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_write_dpram_mag_32 -// Description: This function will write to a specific area of dpram -// (Magnemite ASIC only) -// Input: -// dev - device structure -// offset - index of dpram -// value - value to write -// Output: -// none. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_write_dpram_mag_32 + Description: This function will write to a specific area of dpram + (Magnemite ASIC only) + Input: + dev - device structure + offset - index of dpram + value - value to write + Output: + none. + + -------------------------------------------------------------------------*/ void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value) { struct ft1000_info *info = netdev_priv(dev); unsigned long flags; - // Provide mutual exclusive access while reading ASIC registers. + /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); outl(value, dev->base_addr + FT1000_REG_MAG_DPDATAL); spin_unlock_irqrestore(&info->dpram_lock, flags); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_enable_interrupts -// Description: This function will enable interrupts base on the current interrupt mask. -// Input: -// dev - device structure -// Output: -// None. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_enable_interrupts + Description: This function will enable interrupts base on the current interrupt mask. + Input: + dev - device structure + Output: + None. + + -------------------------------------------------------------------------*/ static void ft1000_enable_interrupts(struct net_device *dev) { u16 tempword; @@ -292,16 +292,16 @@ static void ft1000_enable_interrupts(struct net_device *dev) tempword); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_disable_interrupts -// Description: This function will disable all interrupts. -// Input: -// dev - device structure -// Output: -// None. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_disable_interrupts + Description: This function will disable all interrupts. + Input: + dev - device structure + Output: + None. + + -------------------------------------------------------------------------*/ static void ft1000_disable_interrupts(struct net_device *dev) { u16 tempword; @@ -314,17 +314,17 @@ static void ft1000_disable_interrupts(struct net_device *dev) tempword); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_reset_asic -// Description: This function will call the Card Service function to reset the -// ASIC. -// Input: -// dev - device structure -// Output: -// none -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_reset_asic + Description: This function will call the Card Service function to reset the + ASIC. + Input: + dev - device structure + Output: + none + + -------------------------------------------------------------------------*/ static void ft1000_reset_asic(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -335,21 +335,23 @@ static void ft1000_reset_asic(struct net_device *dev) (*info->ft1000_reset) (pcmcia->link); - // Let's use the register provided by the Magnemite ASIC to reset the - // ASIC and DSP. + /* + * Let's use the register provided by the Magnemite ASIC to reset the + * ASIC and DSP. + */ if (info->AsicID == MAGNEMITE_ID) { ft1000_write_reg(dev, FT1000_REG_RESET, (DSP_RESET_BIT | ASIC_RESET_BIT)); } mdelay(1); if (info->AsicID == ELECTRABUZZ_ID) { - // set watermark to -1 in order to not generate an interrupt + /* set watermark to -1 in order to not generate an interrupt */ ft1000_write_reg(dev, FT1000_REG_WATERMARK, 0xffff); } else { - // set watermark to -1 in order to not generate an interrupt + /* set watermark to -1 in order to not generate an interrupt */ ft1000_write_reg(dev, FT1000_REG_MAG_WATERMARK, 0xffff); } - // clear interrupts + /* clear interrupts */ tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword); @@ -358,17 +360,17 @@ static void ft1000_reset_asic(struct net_device *dev) } -//--------------------------------------------------------------------------- -// -// Function: ft1000_reset_card -// Description: This function will reset the card -// Input: -// dev - device structure -// Output: -// status - false (card reset fail) -// true (card reset successful) -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_reset_card + Description: This function will reset the card + Input: + dev - device structure + Output: + status - false (card reset fail) + true (card reset successful) + + -------------------------------------------------------------------------*/ static int ft1000_reset_card(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -384,9 +386,9 @@ static int ft1000_reset_card(struct net_device *dev) info->squeseqnum = 0; ft1000_disable_interrupts(dev); -// del_timer(&poll_timer); + /* del_timer(&poll_timer); */ - // Make sure we free any memory reserve for provisioning + /* Make sure we free any memory reserve for provisioning */ while (list_empty(&info->prov_list) == 0) { DEBUG(0, "ft1000_hw:ft1000_reset_card:deleting provisioning record\n"); @@ -406,7 +408,7 @@ static int ft1000_reset_card(struct net_device *dev) (DSP_RESET_BIT | ASIC_RESET_BIT)); } - // Copy DSP session record into info block if this is not a coldstart + /* Copy DSP session record into info block if this is not a coldstart */ if (ft1000_card_present == 1) { spin_lock_irqsave(&info->dpram_lock, flags); if (info->AsicID == ELECTRABUZZ_ID) { @@ -430,29 +432,29 @@ static int ft1000_reset_card(struct net_device *dev) DEBUG(1, "ft1000_hw:ft1000_reset_card:resetting ASIC\n"); mdelay(10); - //reset ASIC + /* reset ASIC */ ft1000_reset_asic(dev); DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n"); if (info->AsicID == MAGNEMITE_ID) { - // Put dsp in reset and take ASIC out of reset + /* Put dsp in reset and take ASIC out of reset */ DEBUG(0, "ft1000_hw:ft1000_reset_card:Put DSP in reset and take ASIC out of reset\n"); ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT); - // Setting MAGNEMITE ASIC to big endian mode + /* Setting MAGNEMITE ASIC to big endian mode */ ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE); - // Download bootloader + /* Download bootloader */ card_bootload(dev); - // Take DSP out of reset + /* Take DSP out of reset */ ft1000_write_reg(dev, FT1000_REG_RESET, 0); - // FLARION_DSP_ACTIVE; + /* FLARION_DSP_ACTIVE; */ mdelay(10); DEBUG(0, "ft1000_hw:ft1000_reset_card:Take DSP out of reset\n"); - // Wait for 0xfefe indicating dsp ready before starting download + /* Wait for 0xfefe indicating dsp ready before starting download */ for (i = 0; i < 50; i++) { tempword = ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE, @@ -470,7 +472,7 @@ static int ft1000_reset_card(struct net_device *dev) } } else { - // Take DSP out of reset + /* Take DSP out of reset */ ft1000_write_reg(dev, FT1000_REG_RESET, ~DSP_RESET_BIT); mdelay(10); } @@ -485,17 +487,19 @@ static int ft1000_reset_card(struct net_device *dev) mdelay(10); if (info->AsicID == ELECTRABUZZ_ID) { - // Need to initialize the FIFO length counter to zero in order to sync up - // with the DSP + /* + * Need to initialize the FIFO length counter to zero in order to sync up + * with the DSP + */ info->fifo_cnt = 0; ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt); - // Initialize DSP heartbeat area to ho + /* Initialize DSP heartbeat area to ho */ ft1000_write_dpram(dev, FT1000_HI_HO, ho); tempword = ft1000_read_dpram(dev, FT1000_HI_HO); DEBUG(1, "ft1000_hw:ft1000_reset_asic:hi_ho value = 0x%x\n", tempword); } else { - // Initialize DSP heartbeat area to ho + /* Initialize DSP heartbeat area to ho */ ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, ho_mag, FT1000_MAG_HI_HO_INDX); tempword = @@ -509,40 +513,44 @@ static int ft1000_reset_card(struct net_device *dev) ft1000_enable_interrupts(dev); /* Schedule heartbeat process to run every 2 seconds */ -// poll_timer.expires = jiffies + (2*HZ); -// poll_timer.data = (u_long)dev; -// add_timer(&poll_timer); + /* poll_timer.expires = jiffies + (2*HZ); */ + /* poll_timer.data = (u_long)dev; */ + /* add_timer(&poll_timer); */ return true; } -//--------------------------------------------------------------------------- -// -// Function: ft1000_chkcard -// Description: This function will check if the device is presently available on -// the system. -// Input: -// dev - device structure -// Output: -// status - false (device is not present) -// true (device is present) -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_chkcard + Description: This function will check if the device is presently available on + the system. + Input: + dev - device structure + Output: + status - false (device is not present) + true (device is present) + + -------------------------------------------------------------------------*/ static int ft1000_chkcard(struct net_device *dev) { u16 tempword; - // Mask register is used to check for device presence since it is never - // set to zero. + /* + * Mask register is used to check for device presence since it is never + * set to zero. + */ tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK); if (tempword == 0) { DEBUG(1, "ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n"); return false; } - // The system will return the value of 0xffff for the version register - // if the device is not present. + /* + * The system will return the value of 0xffff for the version register + * if the device is not present. + */ tempword = ft1000_read_reg(dev, FT1000_REG_ASIC_ID); if (tempword == 0xffff) { DEBUG(1, @@ -553,17 +561,17 @@ static int ft1000_chkcard(struct net_device *dev) } -//--------------------------------------------------------------------------- -// -// Function: ft1000_hbchk -// Description: This function will perform the heart beat check of the DSP as -// well as the ASIC. -// Input: -// dev - device structure -// Output: -// none -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_hbchk + Description: This function will perform the heart beat check of the DSP as + well as the ASIC. + Input: + dev - device structure + Output: + none + + -------------------------------------------------------------------------*/ static void ft1000_hbchk(u_long data) { struct net_device *dev = (struct net_device *)data; @@ -574,7 +582,7 @@ static void ft1000_hbchk(u_long data) info = netdev_priv(dev); if (info->CardReady == 1) { - // Perform dsp heartbeat check + /* Perform dsp heartbeat check */ if (info->AsicID == ELECTRABUZZ_ID) { tempword = ft1000_read_dpram(dev, FT1000_HI_HO); } else { @@ -585,7 +593,7 @@ static void ft1000_hbchk(u_long data) } DEBUG(1, "ft1000_hw:ft1000_hbchk:hi_ho value = 0x%x\n", tempword); - // Let's perform another check if ho is not detected + /* Let's perform another check if ho is not detected */ if (tempword != ho) { if (info->AsicID == ELECTRABUZZ_ID) { tempword = ft1000_read_dpram(dev, FT1000_HI_HO); @@ -639,7 +647,7 @@ static void ft1000_hbchk(u_long data) } tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - // Let's check doorbell again if fail + /* Let's check doorbell again if fail */ if (tempword & FT1000_DB_HB) { tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); } @@ -686,8 +694,10 @@ static void ft1000_hbchk(u_long data) add_timer(&poll_timer); return; } - // Set dedicated area to hi and ring appropriate doorbell according - // to hi/ho heartbeat protocol + /* + * Set dedicated area to hi and ring appropriate doorbell according + * to hi/ho heartbeat protocol + */ if (info->AsicID == ELECTRABUZZ_ID) { ft1000_write_dpram(dev, FT1000_HI_HO, hi); } else { @@ -703,7 +713,7 @@ static void ft1000_hbchk(u_long data) (dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); } - // Let's write hi again if fail + /* Let's write hi again if fail */ if (tempword != hi) { if (info->AsicID == ELECTRABUZZ_ID) { ft1000_write_dpram(dev, FT1000_HI_HO, hi); @@ -774,14 +784,14 @@ static void ft1000_hbchk(u_long data) add_timer(&poll_timer); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_send_cmd -// Description: -// Input: -// Output: -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_send_cmd + Description: + Input: + Output: + + -------------------------------------------------------------------------*/ static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype) { struct ft1000_info *info = netdev_priv(dev); @@ -790,17 +800,19 @@ static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, unsigned long flags; size += sizeof(struct pseudo_hdr); - // check for odd byte and increment to 16-bit word align value + /* check for odd byte and increment to 16-bit word align value */ if ((size & 0x0001)) { size++; } DEBUG(1, "FT1000:ft1000_send_cmd:total length = %d\n", size); DEBUG(1, "FT1000:ft1000_send_cmd:length = %d\n", ntohs(*ptempbuffer)); - // put message into slow queue area - // All messages are in the form total_len + pseudo header + message body + /* + * put message into slow queue area + * All messages are in the form total_len + pseudo header + message body + */ spin_lock_irqsave(&info->dpram_lock, flags); - // Make sure SLOWQ doorbell is clear + /* Make sure SLOWQ doorbell is clear */ tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); i=0; while (tempword & FT1000_DB_DPRAM_TX) { @@ -816,9 +828,9 @@ static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, if (info->AsicID == ELECTRABUZZ_ID) { ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_TX_BASE); - // Write total length to dpram + /* Write total length to dpram */ ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size); - // Write pseudo header and messgae body + /* Write pseudo header and messgae body */ for (i = 0; i < (size >> 1); i++) { DEBUG(1, "FT1000:ft1000_send_cmd:data %d = 0x%x\n", i, *ptempbuffer); @@ -828,9 +840,9 @@ static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, } else { ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_MAG_TX_BASE); - // Write total length to dpram + /* Write total length to dpram */ ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, htons(size)); - // Write pseudo header and messgae body + /* Write pseudo header and messgae body */ ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_MAG_TX_BASE + 1); for (i = 0; i < (size >> 2); i++) { @@ -850,23 +862,23 @@ static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, } spin_unlock_irqrestore(&info->dpram_lock, flags); - // ring doorbell to notify DSP that we have a message ready + /* ring doorbell to notify DSP that we have a message ready */ ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_DPRAM_TX); } -//--------------------------------------------------------------------------- -// -// Function: ft1000_receive_cmd -// Description: This function will read a message from the dpram area. -// Input: -// dev - network device structure -// pbuffer - caller supply address to buffer -// pnxtph - pointer to next pseudo header -// Output: -// Status = 0 (unsuccessful) -// = 1 (successful) -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_receive_cmd + Description: This function will read a message from the dpram area. + Input: + dev - network device structure + pbuffer - caller supply address to buffer + pnxtph - pointer to next pseudo header + Output: + Status = 0 (unsuccessful) + = 1 (successful) + + -------------------------------------------------------------------------*/ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) { @@ -919,7 +931,7 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, FT1000_REG_MAG_DPDATAH); pbuffer++; } - //copy odd aligned word + /* copy odd aligned word */ *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL); DEBUG(1, "ft1000_hw:received data = 0x%x\n", *pbuffer); pbuffer++; @@ -928,14 +940,16 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, pbuffer++; } if (size & 0x0001) { - //copy odd byte from fifo + /* copy odd byte from fifo */ tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA); *pbuffer = ntohs(tempword); } spin_unlock_irqrestore(&info->dpram_lock, flags); - // Check if pseudo header checksum is good - // Calculate pseudo header checksum + /* + * Check if pseudo header checksum is good + * Calculate pseudo header checksum + */ tempword = *ppseudohdr++; for (i = 1; i < 7; i++) { tempword ^= *ppseudohdr++; @@ -943,24 +957,24 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, if ((tempword != *ppseudohdr)) { DEBUG(1, "FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n"); - // Drop this message + /* Drop this message */ return false; } return true; } } -//--------------------------------------------------------------------------- -// -// Function: ft1000_proc_drvmsg -// Description: This function will process the various driver messages. -// Input: -// dev - device structure -// pnxtph - pointer to next pseudo header -// Output: -// none -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_proc_drvmsg + Description: This function will process the various driver messages. + Input: + dev - device structure + pnxtph - pointer to next pseudo header + Output: + none + + -------------------------------------------------------------------------*/ static void ft1000_proc_drvmsg(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -988,7 +1002,7 @@ static void ft1000_proc_drvmsg(struct net_device *dev) } if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) { - // Get the message type which is total_len + PSEUDO header + msgtype + message body + /* Get the message type which is total_len + PSEUDO header + msgtype + message body */ pdrvmsg = (struct drv_msg *) & cmdbuffer[0]; msgtype = ntohs(pdrvmsg->type); DEBUG(1, "Command message type = 0x%x\n", msgtype); @@ -999,7 +1013,7 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(25); while (list_empty(&info->prov_list) == 0) { DEBUG(0, "Sending a provisioning message\n"); - // Make sure SLOWQ doorbell is clear + /* Make sure SLOWQ doorbell is clear */ tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); i = 0; @@ -1018,10 +1032,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev) pmsg = (u16 *) ptr->pprov_data; ppseudo_hdr = (struct pseudo_hdr *) pmsg; - // Insert slow queue sequence number + /* Insert slow queue sequence number */ ppseudo_hdr->seq_num = info->squeseqnum++; ppseudo_hdr->portsrc = 0; - // Calculate new checksum + /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; DEBUG(1, "checksum = 0x%x\n", ppseudo_hdr->checksum); @@ -1036,8 +1050,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev) kfree(ptr->pprov_data); kfree(ptr); } - // Indicate adapter is ready to take application messages after all - // provisioning messages are sent + /* + * Indicate adapter is ready to take application messages after all + * provisioning messages are sent + */ info->CardReady = 1; break; case MEDIA_STATE: @@ -1118,8 +1134,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev) break; case DSP_GET_INFO: DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n"); - // copy dsp info block to dsp - // allow any outstanding ioctl to finish + /* + * copy dsp info block to dsp + * allow any outstanding ioctl to finish + */ mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); if (tempword & FT1000_DB_DPRAM_TX) { @@ -1132,8 +1150,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev) } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { - // Put message into Slow Queue - // Form Pseudo header + /* + * Put message into Slow Queue + * Form Pseudo header + */ pmsg = (u16 *) info->DSPInfoBlk; ppseudo_hdr = (struct pseudo_hdr *) pmsg; ppseudo_hdr->length = @@ -1147,11 +1167,11 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->rsvd1 = 0; ppseudo_hdr->rsvd2 = 0; ppseudo_hdr->qos_class = 0; - // Insert slow queue sequence number + /* Insert slow queue sequence number */ ppseudo_hdr->seq_num = info->squeseqnum++; - // Insert application id + /* Insert application id */ ppseudo_hdr->portsrc = 0; - // Calculate new checksum + /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; for (i = 1; i < 7; i++) { ppseudo_hdr->checksum ^= *pmsg++; @@ -1165,8 +1185,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev) break; case GET_DRV_ERR_RPT_MSG: DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n"); - // copy driver error message to dsp - // allow any outstanding ioctl to finish + /* + * copy driver error message to dsp + * allow any outstanding ioctl to finish + */ mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); if (tempword & FT1000_DB_DPRAM_TX) { @@ -1179,8 +1201,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev) } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { - // Put message into Slow Queue - // Form Pseudo header + /* + * Put message into Slow Queue + * Form Pseudo header + */ pmsg = (u16 *) & tempbuffer[0]; ppseudo_hdr = (struct pseudo_hdr *) pmsg; ppseudo_hdr->length = htons(0x0012); @@ -1193,11 +1217,11 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->rsvd1 = 0; ppseudo_hdr->rsvd2 = 0; ppseudo_hdr->qos_class = 0; - // Insert slow queue sequence number + /* Insert slow queue sequence number */ ppseudo_hdr->seq_num = info->squeseqnum++; - // Insert application id + /* Insert application id */ ppseudo_hdr->portsrc = 0; - // Calculate new checksum + /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; for (i=1; i<7; i++) { ppseudo_hdr->checksum ^= *pmsg++; @@ -1228,18 +1252,18 @@ static void ft1000_proc_drvmsg(struct net_device *dev) } } -//--------------------------------------------------------------------------- -// -// Function: ft1000_parse_dpram_msg -// Description: This function will parse the message received from the DSP -// via the DPRAM interface. -// Input: -// dev - device structure -// Output: -// status - FAILURE -// SUCCESS -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_parse_dpram_msg + Description: This function will parse the message received from the DSP + via the DPRAM interface. + Input: + dev - device structure + Output: + status - FAILURE + SUCCESS + + -------------------------------------------------------------------------*/ static int ft1000_parse_dpram_msg(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); @@ -1255,7 +1279,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) DEBUG(1, "Doorbell = 0x%x\n", doorbell); if (doorbell & FT1000_ASIC_RESET_REQ) { - // Copy DSP session record from info block + /* Copy DSP session record from info block */ spin_lock_irqsave(&info->dpram_lock, flags); if (info->AsicID == ELECTRABUZZ_ID) { ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, @@ -1274,7 +1298,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) } spin_unlock_irqrestore(&info->dpram_lock, flags); - // clear ASIC RESET request + /* clear ASIC RESET request */ ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_ASIC_RESET_REQ); DEBUG(1, "Got an ASIC RESET Request\n"); @@ -1282,7 +1306,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) FT1000_ASIC_RESET_DSP); if (info->AsicID == MAGNEMITE_ID) { - // Setting MAGNEMITE ASIC to big endian mode + /* Setting MAGNEMITE ASIC to big endian mode */ ft1000_write_reg(dev, FT1000_REG_SUP_CTRL, HOST_INTF_BE); } @@ -1315,8 +1339,10 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) if ((total_len < MAX_CMD_SQSIZE) && (total_len > sizeof(struct pseudo_hdr))) { total_len += nxtph; cnt = 0; - // ft1000_read_reg will return a value that needs to be byteswap - // in order to get DSP_QID_OFFSET. + /* + * ft1000_read_reg will return a value that needs to be byteswap + * in order to get DSP_QID_OFFSET. + */ if (info->AsicID == ELECTRABUZZ_ID) { portid = (ft1000_read_dpram @@ -1332,7 +1358,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) DEBUG(1, "DSP_QID = 0x%x\n", portid); if (portid == DRIVERID) { - // We are assumming one driver message from the DSP at a time. + /* We are assumming one driver message from the DSP at a time. */ ft1000_proc_drvmsg(dev); } } @@ -1340,7 +1366,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) } if (doorbell & FT1000_DB_COND_RESET) { - // Reset ASIC and DSP + /* Reset ASIC and DSP */ if (info->AsicID == ELECTRABUZZ_ID) { info->DSP_TIME[0] = ft1000_read_dpram(dev, FT1000_DSP_TIMER0); @@ -1370,7 +1396,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) ft1000_write_reg(dev, FT1000_REG_DOORBELL, FT1000_DB_COND_RESET); } - // let's clear any unexpected doorbells from DSP + /* let's clear any unexpected doorbells from DSP */ doorbell = doorbell & ~(FT1000_DB_DPRAM_RX | FT1000_ASIC_RESET_REQ | FT1000_DB_COND_RESET | 0xff00); @@ -1383,18 +1409,18 @@ static int ft1000_parse_dpram_msg(struct net_device *dev) } -//--------------------------------------------------------------------------- -// -// Function: ft1000_flush_fifo -// Description: This function will flush one packet from the downlink -// FIFO. -// Input: -// dev - device structure -// drv_err - driver error causing the flush fifo -// Output: -// None. -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_flush_fifo + Description: This function will flush one packet from the downlink + FIFO. + Input: + dev - device structure + drv_err - driver error causing the flush fifo + Output: + None. + + -------------------------------------------------------------------------*/ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) { struct ft1000_info *info = netdev_priv(dev); @@ -1432,7 +1458,7 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) ft1000_reset_card(dev); return; } else { - // Flush corrupted pkt from FIFO + /* Flush corrupted pkt from FIFO */ i = 0; do { if (info->AsicID == ELECTRABUZZ_ID) { @@ -1447,8 +1473,10 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) inw(dev->base_addr + FT1000_REG_MAG_DFSR); } i++; - // This should never happen unless the ASIC is broken. - // We must reset to recover. + /* + * This should never happen unless the ASIC is broken. + * We must reset to recover. + */ if ((i > 2048) || (tempword == 0)) { if (info->AsicID == ELECTRABUZZ_ID) { info->DSP_TIME[0] = @@ -1482,17 +1510,19 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) FT1000_MAG_DSP_TIMER3_INDX); } if (tempword == 0) { - // Let's check if ASIC reads are still ok by reading the Mask register - // which is never zero at this point of the code. + /* + * Let's check if ASIC reads are still ok by reading the Mask register + * which is never zero at this point of the code. + */ tempword = inw(dev->base_addr + FT1000_REG_SUP_IMASK); if (tempword == 0) { - // This indicates that we can not communicate with the ASIC + /* This indicates that we can not communicate with the ASIC */ info->DrvErrNum = FIFO_FLUSH_BADCNT; } else { - // Let's assume that we really flush the FIFO + /* Let's assume that we really flush the FIFO */ pcmcia->PktIntfErr++; return; } @@ -1506,9 +1536,9 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) if (info->AsicID == ELECTRABUZZ_ID) { i++; DEBUG(0, "Flushing FIFO complete = %x\n", tempword); - // Flush last word in FIFO. + /* Flush last word in FIFO. */ tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); - // Update FIFO counter for DSP + /* Update FIFO counter for DSP */ i = i * 2; DEBUG(0, "Flush Data byte count to dsp = %d\n", i); info->fifo_cnt += i; @@ -1516,7 +1546,7 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) info->fifo_cnt); } else { DEBUG(0, "Flushing FIFO complete = %x\n", tempword); - // Flush last word in FIFO + /* Flush last word in FIFO */ templong = inl(dev->base_addr + FT1000_REG_MAG_DFR); tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT); DEBUG(0, "FT1000_REG_SUP_STAT = 0x%x\n", tempword); @@ -1529,19 +1559,19 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) } } -//--------------------------------------------------------------------------- -// -// Function: ft1000_copy_up_pkt -// Description: This function will pull Flarion packets out of the Downlink -// FIFO and convert it to an ethernet packet. The ethernet packet will -// then be deliver to the TCP/IP stack. -// Input: -// dev - device structure -// Output: -// status - FAILURE -// SUCCESS -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_copy_up_pkt + Description: This function will pull Flarion packets out of the Downlink + FIFO and convert it to an ethernet packet. The ethernet packet will + then be deliver to the TCP/IP stack. + Input: + dev - device structure + Output: + status - FAILURE + SUCCESS + + -------------------------------------------------------------------------*/ static int ft1000_copy_up_pkt(struct net_device *dev) { u16 tempword; @@ -1556,7 +1586,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) u32 templong; DEBUG(1, "ft1000_copy_up_pkt\n"); - // Read length + /* Read length */ if (info->AsicID == ELECTRABUZZ_ID) { tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); len = tempword; @@ -1570,7 +1600,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) if (len > ENET_MAX_SIZE) { DEBUG(0, "size of ethernet packet invalid\n"); if (info->AsicID == MAGNEMITE_ID) { - // Read High word to complete 32 bit access + /* Read High word to complete 32 bit access */ tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); } ft1000_flush_fifo(dev, DSP_PKTLEN_INFO); @@ -1582,7 +1612,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) if (skb == NULL) { DEBUG(0, "No Network buffers available\n"); - // Read High word to complete 32 bit access + /* Read High word to complete 32 bit access */ if (info->AsicID == MAGNEMITE_ID) { tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); } @@ -1592,13 +1622,13 @@ static int ft1000_copy_up_pkt(struct net_device *dev) } pbuffer = (u8 *) skb_put(skb, len + 12); - // Pseudo header + /* Pseudo header */ if (info->AsicID == ELECTRABUZZ_ID) { for (i = 1; i < 7; i++) { tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); chksum ^= tempword; } - // read checksum value + /* read checksum value */ tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); } else { tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); @@ -1625,7 +1655,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) DEBUG(1, "Pseudo = 0x%x\n", tempword); chksum ^= tempword; - // read checksum value + /* read checksum value */ tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); DEBUG(1, "Pseudo = 0x%x\n", tempword); } @@ -1638,10 +1668,10 @@ static int ft1000_copy_up_pkt(struct net_device *dev) kfree_skb(skb); return FAILURE; } - //subtract the number of bytes read already + /* subtract the number of bytes read already */ ptemp = pbuffer; - // fake MAC address + /* fake MAC address */ *pbuffer++ = dev->dev_addr[0]; *pbuffer++ = dev->dev_addr[1]; *pbuffer++ = dev->dev_addr[2]; @@ -1666,7 +1696,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) } } - // Need to read one more word if odd byte + /* Need to read one more word if odd byte */ if (len & 0x0001) { tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO); *pbuffer++ = (u8) (tempword >> 8); @@ -1679,7 +1709,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) *ptemplong++ = templong; } - // Need to read one more word if odd align. + /* Need to read one more word if odd align. */ if (len & 0x0003) { templong = inl(dev->base_addr + FT1000_REG_MAG_DFR); DEBUG(1, "Data = 0x%8x\n", templong); @@ -1699,11 +1729,11 @@ static int ft1000_copy_up_pkt(struct net_device *dev) netif_rx(skb); info->stats.rx_packets++; - // Add on 12 bytes for MAC address which was removed + /* Add on 12 bytes for MAC address which was removed */ info->stats.rx_bytes += (len + 12); if (info->AsicID == ELECTRABUZZ_ID) { - // track how many bytes have been read from FIFO - round up to 16 bit word + /* track how many bytes have been read from FIFO - round up to 16 bit word */ tempword = len + 16; if (tempword & 0x01) tempword++; @@ -1715,21 +1745,21 @@ static int ft1000_copy_up_pkt(struct net_device *dev) return SUCCESS; } -//--------------------------------------------------------------------------- -// -// Function: ft1000_copy_down_pkt -// Description: This function will take an ethernet packet and convert it to -// a Flarion packet prior to sending it to the ASIC Downlink -// FIFO. -// Input: -// dev - device structure -// packet - address of ethernet packet -// len - length of IP packet -// Output: -// status - FAILURE -// SUCCESS -// -//--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- + + Function: ft1000_copy_down_pkt + Description: This function will take an ethernet packet and convert it to + a Flarion packet prior to sending it to the ASIC Downlink + FIFO. + Input: + dev - device structure + packet - address of ethernet packet + len - length of IP packet + Output: + status - FAILURE + SUCCESS + + -------------------------------------------------------------------------*/ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) { struct ft1000_info *info = netdev_priv(dev); @@ -1744,7 +1774,7 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) DEBUG(1, "ft1000_hw: copy_down_pkt()\n"); - // Check if there is room on the FIFO + /* Check if there is room on the FIFO */ if (len > ft1000_read_fifo_len(dev)) { udelay(10); if (len > ft1000_read_fifo_len(dev)) { @@ -1769,15 +1799,15 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) return SUCCESS; } } - // Create pseudo header and send pseudo/ip to hardware + /* Create pseudo header and send pseudo/ip to hardware */ if (info->AsicID == ELECTRABUZZ_ID) { pseudo.blk.length = len; } else { pseudo.blk.length = ntohs(len); } - pseudo.blk.source = DSPID; // Need to swap to get in correct order + pseudo.blk.source = DSPID; /* Need to swap to get in correct order */ pseudo.blk.destination = HOSTID; - pseudo.blk.portdest = NETWORKID; // Need to swap to get in correct order + pseudo.blk.portdest = NETWORKID; /* Need to swap to get in correct order */ pseudo.blk.portsrc = DSPAIRID; pseudo.blk.sh_str_id = 0; pseudo.blk.control = 0; @@ -1791,14 +1821,14 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) pseudo.blk.checksum ^= pseudo.buff[i]; } - // Production Mode + /* Production Mode */ if (info->AsicID == ELECTRABUZZ_ID) { - // copy first word to UFIFO_BEG reg + /* copy first word to UFIFO_BEG reg */ ft1000_write_reg(dev, FT1000_REG_UFIFO_BEG, pseudo.buff[0]); DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 0 BEG = 0x%04x\n", pseudo.buff[0]); - // copy subsequent words to UFIFO_MID reg + /* copy subsequent words to UFIFO_MID reg */ ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, pseudo.buff[1]); DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 1 MID = 0x%04x\n", pseudo.buff[1]); @@ -1821,7 +1851,7 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data 7 MID = 0x%04x\n", pseudo.buff[7]); - // Write PPP type + IP Packet into Downlink FIFO + /* Write PPP type + IP Packet into Downlink FIFO */ for (i = 0; i < (len >> 1) - 1; i++) { ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, htons(*packet)); @@ -1831,7 +1861,7 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) packet++; } - // Check for odd byte + /* Check for odd byte */ if (len & 0x0001) { ft1000_write_reg(dev, FT1000_REG_UFIFO_MID, htons(*packet)); @@ -1870,12 +1900,12 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) *(u32 *) & pseudo.buff[6]); plong = (u32 *) packet; - // Write PPP type + IP Packet into Downlink FIFO + /* Write PPP type + IP Packet into Downlink FIFO */ for (i = 0; i < (len >> 2); i++) { outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR); } - // Check for odd alignment + /* Check for odd alignment */ if (len & 0x0003) { DEBUG(1, "ft1000_hw:ft1000_copy_down_pkt:data = 0x%8x\n", @@ -1886,7 +1916,7 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) } info->stats.tx_packets++; - // Add 14 bytes for MAC address plus ethernet type + /* Add 14 bytes for MAC address plus ethernet type */ info->stats.tx_bytes += (len + 14); return SUCCESS; } @@ -1931,7 +1961,7 @@ static int ft1000_close(struct net_device *dev) ft1000_disable_interrupts(dev); ft1000_write_reg(dev, FT1000_REG_RESET, DSP_RESET_BIT); - //reset ASIC + /* reset ASIC */ ft1000_reset_asic(dev); } return 0; @@ -1995,10 +2025,10 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id) ft1000_disable_interrupts(dev); - // Read interrupt type + /* Read interrupt type */ inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); - // Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type + /* Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type */ while (inttype) { if (inttype & ISR_DOORBELL_PEND) ft1000_parse_dpram_msg(dev); @@ -2008,7 +2038,7 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id) cnt = 0; do { - // Check if we have packets in the Downlink FIFO + /* Check if we have packets in the Downlink FIFO */ if (info->AsicID == ELECTRABUZZ_ID) { tempword = ft1000_read_reg(dev, @@ -2027,12 +2057,12 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id) } while (cnt < MAX_RCV_LOOP); } - // clear interrupts + /* clear interrupts */ tempword = ft1000_read_reg(dev, FT1000_REG_SUP_ISR); DEBUG(1, "ft1000_hw: interrupt status register = 0x%x\n", tempword); ft1000_write_reg(dev, FT1000_REG_SUP_ISR, tempword); - // Read interrupt type + /* Read interrupt type */ inttype = ft1000_read_reg (dev, FT1000_REG_SUP_ISR); DEBUG(1,"ft1000_hw: interrupt status register after clear = 0x%x\n",inttype); } @@ -2044,7 +2074,7 @@ void stop_ft1000_card(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); struct prov_record *ptr; -// int cnt; + /* int cnt; */ DEBUG(0, "ft1000_hw: stop_ft1000_card()\n"); @@ -2053,7 +2083,7 @@ void stop_ft1000_card(struct net_device *dev) netif_stop_queue(dev); ft1000_disable_interrupts(dev); - // Make sure we free any memory reserve for provisioning + /* Make sure we free any memory reserve for provisioning */ while (list_empty(&info->prov_list) == 0) { ptr = list_entry(info->prov_list.next, struct prov_record, list); list_del(&ptr->list); @@ -2109,7 +2139,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link, struct ft1000_pcmcia *pcmcia; struct net_device *dev; - static const struct net_device_ops ft1000ops = // Slavius 21.10.2009 due to kernel changes + static const struct net_device_ops ft1000ops = /* Slavius 21.10.2009 due to kernel changes */ { .ndo_open = &ft1000_open, .ndo_stop = &ft1000_close, @@ -2169,12 +2199,12 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link, info->squeseqnum = 0; -// dev->hard_start_xmit = &ft1000_start_xmit; -// dev->get_stats = &ft1000_stats; -// dev->open = &ft1000_open; -// dev->stop = &ft1000_close; + /* dev->hard_start_xmit = &ft1000_start_xmit; */ + /* dev->get_stats = &ft1000_stats; */ + /* dev->open = &ft1000_open; */ + /* dev->stop = &ft1000_close; */ - dev->netdev_ops = &ft1000ops; // Slavius 21.10.2009 due to kernel changes + dev->netdev_ops = &ft1000ops; /* Slavius 21.10.2009 due to kernel changes */ DEBUG(0, "device name = %s\n", dev->name); diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index 21f4a3bbd064..782aa9ed4718 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -55,7 +55,7 @@ #define MAX_LENGTH 0x7f0 -// Temporary download mechanism for Magnemite +/* Temporary download mechanism for Magnemite */ #define DWNLD_MAG_TYPE_LOC 0x00 #define DWNLD_MAG_LEN_LOC 0x01 #define DWNLD_MAG_ADDR_LOC 0x02 @@ -74,35 +74,35 @@ #define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1 -// New Magnemite downloader +/* New Magnemite downloader */ #define DWNLD_MAG1_HANDSHAKE_LOC 0x00 #define DWNLD_MAG1_TYPE_LOC 0x01 #define DWNLD_MAG1_SIZE_LOC 0x02 #define DWNLD_MAG1_PS_HDR_LOC 0x03 struct dsp_file_hdr { - long version_id; // Version ID of this image format. - long package_id; // Package ID of code release. - long build_date; // Date/time stamp when file was built. - long commands_offset; // Offset to attached commands in Pseudo Hdr format. - long loader_offset; // Offset to bootloader code. - long loader_code_address; // Start address of bootloader. - long loader_code_end; // Where bootloader code ends. + long version_id; /* Version ID of this image format. */ + long package_id; /* Package ID of code release. */ + long build_date; /* Date/time stamp when file was built. */ + long commands_offset; /* Offset to attached commands in Pseudo Hdr format. */ + long loader_offset; /* Offset to bootloader code. */ + long loader_code_address; /* Start address of bootloader. */ + long loader_code_end; /* Where bootloader code ends. */ long loader_code_size; - long version_data_offset; // Offset were scrambled version data begins. - long version_data_size; // Size, in words, of scrambled version data. - long nDspImages; // Number of DSP images in file. + long version_data_offset; /* Offset were scrambled version data begins. */ + long version_data_size; /* Size, in words, of scrambled version data. */ + long nDspImages; /* Number of DSP images in file. */ }; #pragma pack(1) struct dsp_image_info { - long coff_date; // Date/time when DSP Coff image was built. - long begin_offset; // Offset in file where image begins. - long end_offset; // Offset in file where image begins. - long run_address; // On chip Start address of DSP code. - long image_size; // Size of image. - long version; // Embedded version # of DSP code. - unsigned short checksum; // DSP File checksum + long coff_date; /* Date/time when DSP Coff image was built. */ + long begin_offset; /* Offset in file where image begins. */ + long end_offset; /* Offset in file where image begins. */ + long run_address; /* On chip Start address of DSP code. */ + long image_size; /* Size of image. */ + long version; /* Embedded version # of DSP code. */ + unsigned short checksum; /* DSP File checksum */ unsigned short pad1; }; @@ -511,7 +511,7 @@ static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, static void usb_dnld_complete(struct urb *urb) { - //DEBUG("****** usb_dnld_complete\n"); + /* DEBUG("****** usb_dnld_complete\n"); */ } /* writes a block of DSP image to DPRAM @@ -651,9 +651,9 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, ft1000dev->usbboot = 0; ft1000dev->dspalive = 0xffff; - // - // Get version id of file, at first 4 bytes of file, for newer files. - // + /* + * Get version id of file, at first 4 bytes of file, for newer files. + */ state = STATE_START_DWNLD; @@ -702,8 +702,8 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, /* Reposition ptrs to beginning of code section */ s_file = (u16 *) (boot_end); c_file = (u8 *) (boot_end); - //DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file); - //DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file); + /* DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file); */ + /* DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file); */ state = STATE_CODE_DWNLD; ft1000dev->fcodeldr = 1; break; @@ -735,7 +735,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, break; case STATE_CODE_DWNLD: - //DEBUG("FT1000:STATE_CODE_DWNLD\n"); + /* DEBUG("FT1000:STATE_CODE_DWNLD\n"); */ ft1000dev->bootmode = 0; if (ft1000dev->usbboot) handshake = @@ -805,7 +805,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, state = STATE_DONE_DWNLD; break; case REQUEST_CODE_SEGMENT: - //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n"); + /* DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n"); */ if (!correct_version) { DEBUG ("FT1000:download:Download error: Got Code Segment request before image offset request.\n"); @@ -823,7 +823,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, case REQUEST_MAILBOX_DATA: DEBUG ("FT1000:download: REQUEST_MAILBOX_DATA\n"); - // Convert length from byte count to word count. Make sure we round up. + /* Convert length from byte count to word count. Make sure we round up. */ word_length = (long)(pft1000info->DSPInfoBlklen + 1) / 2; @@ -939,7 +939,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, } dsp_img_info++; - } //end of for + } /* end of for */ if (!correct_version) { /* @@ -1002,7 +1002,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, (u32) (pseudo_header_len + sizeof(struct pseudo_hdr))); - // link provisioning data + /* link provisioning data */ pprov_record = kmalloc(sizeof(struct prov_record), GFP_ATOMIC); @@ -1013,7 +1013,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, list, &pft1000info-> prov_list); - // Move to next entry if available + /* Move to next entry if available */ c_file = (u8 *) ((unsigned long) c_file + -- cgit v1.2.3 From 99ec297ad6d2391361f9367612463b9fcd685a31 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 8 Dec 2013 17:33:16 -0800 Subject: staging: btmtk_usb: remove driver No one seems to be working on it anymore, and it really should be merged into the already-existing btusb driver. Also, there is not any proper author attribution on the code (it was copied from the in-kernel driver...) If someone wants to pick this back up, we can easily revert this, but for now, delete the driver. Cc: Yu-Chen, Cho Cc: Jay Hung Cc: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/btmtk_usb/Kconfig | 11 - drivers/staging/btmtk_usb/Makefile | 1 - drivers/staging/btmtk_usb/README | 14 - drivers/staging/btmtk_usb/TODO | 10 - drivers/staging/btmtk_usb/btmtk_usb.c | 1810 --------------------------------- drivers/staging/btmtk_usb/btmtk_usb.h | 138 --- 8 files changed, 1987 deletions(-) delete mode 100644 drivers/staging/btmtk_usb/Kconfig delete mode 100644 drivers/staging/btmtk_usb/Makefile delete mode 100644 drivers/staging/btmtk_usb/README delete mode 100644 drivers/staging/btmtk_usb/TODO delete mode 100644 drivers/staging/btmtk_usb/btmtk_usb.c delete mode 100644 drivers/staging/btmtk_usb/btmtk_usb.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index facc025a5106..d2beb07f2403 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -144,8 +144,6 @@ source "drivers/staging/dwc2/Kconfig" source "drivers/staging/lustre/Kconfig" -source "drivers/staging/btmtk_usb/Kconfig" - source "drivers/staging/xillybus/Kconfig" source "drivers/staging/dgnc/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 094aba9419ed..bf62386d6259 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -63,7 +63,6 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_USB_DWC2) += dwc2/ obj-$(CONFIG_LUSTRE_FS) += lustre/ -obj-$(CONFIG_USB_BTMTK) += btmtk_usb/ obj-$(CONFIG_XILLYBUS) += xillybus/ obj-$(CONFIG_DGNC) += dgnc/ obj-$(CONFIG_DGAP) += dgap/ diff --git a/drivers/staging/btmtk_usb/Kconfig b/drivers/staging/btmtk_usb/Kconfig deleted file mode 100644 index a425ebda6c7a..000000000000 --- a/drivers/staging/btmtk_usb/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -config USB_BTMTK - tristate "Mediatek Bluetooth support" - depends on USB && BT && m - ---help--- - Say Y here if you wish to control a MTK USB Bluetooth. - - This option depends on 'USB' support being enabled - - To compile this driver as a module, choose M here: the - module will be called btmtk_usb. - diff --git a/drivers/staging/btmtk_usb/Makefile b/drivers/staging/btmtk_usb/Makefile deleted file mode 100644 index 4d6c9d764621..000000000000 --- a/drivers/staging/btmtk_usb/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_USB_BTMTK) += btmtk_usb.o diff --git a/drivers/staging/btmtk_usb/README b/drivers/staging/btmtk_usb/README deleted file mode 100644 index c046c8e96b2d..000000000000 --- a/drivers/staging/btmtk_usb/README +++ /dev/null @@ -1,14 +0,0 @@ --build driver modules - make - --install driver modules - make install - --remove driver modules - make clean - --dynamic debug message - turn on CONFIG_DYNAMIC_DEBUG compiler flag for current kernel - mount -t debugfs none /sys/kernel/debug/ - echo "module module_name +p" > /sys/kernel/debug/dynamic_debug/control(turn on debug messages, module name such as btmtk_usb) - echo "module module_name -p" > /sys/kernel/debug/dynamic_debug/control(turn off debug messages, module name such as btmtk_usb) diff --git a/drivers/staging/btmtk_usb/TODO b/drivers/staging/btmtk_usb/TODO deleted file mode 100644 index a71d1297942d..000000000000 --- a/drivers/staging/btmtk_usb/TODO +++ /dev/null @@ -1,10 +0,0 @@ -TODO: - - checkpatch.pl clean - - determine if the driver should not be using a duplicate - version of the usb-bluetooth interface code, but should - be merged into the drivers/bluetooth/ directory and - infrastructure instead. - - review by the bluetooth developer community - -Please send any patches for this driver to Yu-Chen, Cho and -jay.hung@mediatek.com diff --git a/drivers/staging/btmtk_usb/btmtk_usb.c b/drivers/staging/btmtk_usb/btmtk_usb.c deleted file mode 100644 index 9a5ebd6cc512..000000000000 --- a/drivers/staging/btmtk_usb/btmtk_usb.c +++ /dev/null @@ -1,1810 +0,0 @@ -/* - * MediaTek Bluetooth USB Driver - * - * Copyright (C) 2013, MediaTek co. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * 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 - * or on the worldwide web at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "btmtk_usb.h" - -#define VERSION "1.0.4" -#define MT7650_FIRMWARE "mt7650.bin" -#define MT7662_FIRMWARE "mt7662.bin" - -static struct usb_driver btmtk_usb_driver; - - -static int btmtk_usb_load_rom_patch(struct btmtk_usb_data *); -static int btmtk_usb_load_fw(struct btmtk_usb_data *); - -static void hex_dump(char *str, u8 *src_buf, u32 src_buf_len) -{ - unsigned char *pt; - int x; - - pt = src_buf; - - BT_DBG("%s: %p, len = %d\n", str, src_buf, src_buf_len); - - for (x = 0; x < src_buf_len; x++) { - if (x % 16 == 0) - BT_DBG("0x%04x : ", x); - BT_DBG("%02x ", ((unsigned char)pt[x])); - if (x % 16 == 15) - BT_DBG("\n"); - } - - BT_DBG("\n"); -} - -static int btmtk_usb_reset(struct usb_device *udev) -{ - int ret; - - BT_DBG("%s\n", __func__); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, - DEVICE_VENDOR_REQUEST_OUT, 0x01, 0x00, - NULL, 0x00, CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) { - BT_ERR("%s error(%d)\n", __func__, ret); - return ret; - } - - if (ret > 0) - ret = 0; - - return ret; -} - -static int btmtk_usb_io_read32(struct btmtk_usb_data *data, u32 reg, u32 *val) -{ - u8 request = data->r_request; - struct usb_device *udev = data->udev; - int ret; - __le32 val_le; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), request, - DEVICE_VENDOR_REQUEST_IN, 0x0, reg, data->io_buf, - 4, CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) { - *val = 0xffffffff; - BT_ERR("%s error(%d), reg=%x, value=%x\n", - __func__, ret, reg, *val); - return ret; - } - - memmove(&val_le, data->io_buf, 4); - - *val = le32_to_cpu(val_le); - - if (ret > 0) - ret = 0; - - return ret; -} - -static int btmtk_usb_io_write32(struct btmtk_usb_data *data, u32 reg, u32 val) -{ - u16 value, index; - u8 request = data->w_request; - struct usb_device *udev = data->udev; - int ret; - - index = (u16)reg; - value = val & 0x0000ffff; - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, - DEVICE_VENDOR_REQUEST_OUT, value, index, - NULL, 0, CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) { - BT_ERR("%s error(%d), reg=%x, value=%x\n", - __func__, ret, reg, val); - return ret; - } - - index = (u16)(reg + 2); - value = (val & 0xffff0000) >> 16; - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - request, DEVICE_VENDOR_REQUEST_OUT, - value, index, NULL, 0, CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) { - BT_ERR("%s error(%d), reg=%x, value=%x\n", - __func__, ret, reg, val); - return ret; - } - - if (ret > 0) - ret = 0; - - return ret; -} - -static int btmtk_usb_switch_iobase(struct btmtk_usb_data *data, int base) -{ - int ret = 0; - - switch (base) { - case SYSCTL: - data->w_request = 0x42; - data->r_request = 0x47; - break; - case WLAN: - data->w_request = 0x02; - data->r_request = 0x07; - break; - - default: - return -EINVAL; - } - - return ret; -} - -static void btmtk_usb_cap_init(struct btmtk_usb_data *data) -{ - const struct firmware *firmware; - struct usb_device *udev = data->udev; - int ret; - - btmtk_usb_io_read32(data, 0x00, &data->chip_id); - - BT_DBG("chip id = %x\n", data->chip_id); - - if (is_mt7630(data) || is_mt7650(data)) { - data->need_load_fw = 1; - data->need_load_rom_patch = 0; - ret = request_firmware(&firmware, MT7650_FIRMWARE, &udev->dev); - if (ret < 0) { - if (ret == -ENOENT) { - BT_ERR("Firmware file \"%s\" not found\n", - MT7650_FIRMWARE); - } else { - BT_ERR("Firmware file \"%s\" request failed (err=%d)\n", - MT7650_FIRMWARE, ret); - } - } else { - BT_DBG("Firmware file \"%s\" Found\n", - MT7650_FIRMWARE); - /* load firmware here */ - data->firmware = firmware; - btmtk_usb_load_fw(data); - } - release_firmware(firmware); - } else if (is_mt7632(data) || is_mt7662(data)) { - data->need_load_fw = 0; - data->need_load_rom_patch = 1; - data->rom_patch_offset = 0x90000; - ret = request_firmware(&firmware, MT7662_FIRMWARE, &udev->dev); - if (ret < 0) { - if (ret == -ENOENT) { - BT_ERR("Firmware file \"%s\" not found\n", - MT7662_FIRMWARE); - } else { - BT_ERR("Firmware file \"%s\" request failed (err=%d)\n", - MT7662_FIRMWARE, ret); - } - } else { - BT_DBG("Firmware file \"%s\" Found\n", MT7662_FIRMWARE); - /* load rom patch here */ - data->firmware = firmware; - data->rom_patch_len = firmware->size; - btmtk_usb_load_rom_patch(data); - } - release_firmware(firmware); - } else { - BT_ERR("unknow chip(%x)\n", data->chip_id); - } -} - -static u16 checksume16(u8 *pData, int len) -{ - int sum = 0; - - while (len > 1) { - sum += *((u16 *)pData); - - pData = pData + 2; - - if (sum & 0x80000000) - sum = (sum & 0xFFFF) + (sum >> 16); - - len -= 2; - } - - if (len) - sum += *((u8 *)pData); - - while (sum >> 16) - sum = (sum & 0xFFFF) + (sum >> 16); - - return ~sum; -} - -static int btmtk_usb_chk_crc(struct btmtk_usb_data *data, u32 checksum_len) -{ - int ret = 0; - struct usb_device *udev = data->udev; - - BT_DBG("%s\n", __func__); - - memmove(data->io_buf, &data->rom_patch_offset, 4); - memmove(&data->io_buf[4], &checksum_len, 4); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1, - DEVICE_VENDOR_REQUEST_IN, 0x20, 0x00, data->io_buf, - 8, CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) - BT_ERR("%s error(%d)\n", __func__, ret); - - return ret; -} - -static u16 btmtk_usb_get_crc(struct btmtk_usb_data *data) -{ - int ret = 0; - struct usb_device *udev = data->udev; - u16 crc, count = 0; - __le16 crc_le; - - BT_DBG("%s\n", __func__); - - while (1) { - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0x01, DEVICE_VENDOR_REQUEST_IN, - 0x21, 0x00, data->io_buf, 2, - CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) { - crc = 0xFFFF; - BT_ERR("%s error(%d)\n", __func__, ret); - } - - memmove(&crc_le, data->io_buf, 2); - - crc = le16_to_cpu(crc_le); - - if (crc != 0xFFFF) - break; - - mdelay(100); - - if (count++ > 100) { - BT_ERR("Query CRC over %d times\n", count); - break; - } - } - - return crc; -} - -static int btmtk_usb_reset_wmt(struct btmtk_usb_data *data) -{ - int ret = 0; - - /* reset command */ - u8 cmd[8] = {0x6F, 0xFC, 0x05, 0x01, 0x07, 0x01, 0x00, 0x04}; - - memmove(data->io_buf, cmd, 8); - - BT_DBG("%s\n", __func__); - - ret = usb_control_msg(data->udev, usb_sndctrlpipe(data->udev, 0), 0x01, - DEVICE_CLASS_REQUEST_OUT, 0x12, 0x00, - data->io_buf, 8, CONTROL_TIMEOUT_JIFFIES); - - if (ret) - BT_ERR("%s:(%d)\n", __func__, ret); - - return ret; -} - -static void load_rom_patch_complete(struct urb *urb) -{ - - struct completion *sent_to_mcu_done = (struct completion *)urb->context; - - complete(sent_to_mcu_done); -} - -static int btmtk_usb_load_rom_patch(struct btmtk_usb_data *data) -{ - u32 loop = 0; - u32 value; - s32 sent_len; - int ret = 0, total_checksum = 0; - struct urb *urb; - u32 patch_len = 0; - u32 cur_len = 0; - dma_addr_t data_dma; - struct completion sent_to_mcu_done; - int first_block = 1; - unsigned char phase; - void *buf; - char *pos; - unsigned int pipe; - pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); - - if (!data->firmware) { - BT_ERR("%s:please assign a rom patch\n", __func__); - return -1; - } - -load_patch_protect: - btmtk_usb_switch_iobase(data, WLAN); - btmtk_usb_io_read32(data, SEMAPHORE_03, &value); - loop++; - - if (((value & 0x01) == 0x00) && (loop < 600)) { - mdelay(1); - goto load_patch_protect; - } - - btmtk_usb_io_write32(data, 0x1004, 0x2c); - - btmtk_usb_switch_iobase(data, SYSCTL); - - btmtk_usb_io_write32(data, 0x1c, 0x30); - - /* Enable USB_DMA_CFG */ - btmtk_usb_io_write32(data, 0x9018, 0x00c00020); - - btmtk_usb_switch_iobase(data, WLAN); - - /* check ROM patch if upgrade */ - btmtk_usb_io_read32(data, COM_REG0, &value); - - if ((value & 0x02) == 0x02) - goto error0; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - - if (!urb) { - ret = -ENOMEM; - goto error0; - } - - buf = usb_alloc_coherent(data->udev, UPLOAD_PATCH_UNIT, - GFP_ATOMIC, &data_dma); - - if (!buf) { - ret = -ENOMEM; - goto error1; - } - - pos = buf; - BT_DBG("loading rom patch"); - - init_completion(&sent_to_mcu_done); - - cur_len = 0x00; - patch_len = data->rom_patch_len - PATCH_INFO_SIZE; - - /* loading rom patch */ - while (1) { - s32 sent_len_max = UPLOAD_PATCH_UNIT - PATCH_HEADER_SIZE; - sent_len = min_t(s32, (patch_len - cur_len), sent_len_max); - - BT_DBG("patch_len = %d\n", patch_len); - BT_DBG("cur_len = %d\n", cur_len); - BT_DBG("sent_len = %d\n", sent_len); - - if (sent_len <= 0) - break; - - if (first_block == 1) { - if (sent_len < sent_len_max) - phase = PATCH_PHASE3; - else - phase = PATCH_PHASE1; - first_block = 0; - } else if (sent_len == sent_len_max) { - phase = PATCH_PHASE2; - } else { - phase = PATCH_PHASE3; - } - - /* prepare HCI header */ - pos[0] = 0x6F; - pos[1] = 0xFC; - pos[2] = (sent_len + 5) & 0xFF; - pos[3] = ((sent_len + 5) >> 8) & 0xFF; - - /* prepare WMT header */ - pos[4] = 0x01; - pos[5] = 0x01; - pos[6] = (sent_len + 1) & 0xFF; - pos[7] = ((sent_len + 1) >> 8) & 0xFF; - - pos[8] = phase; - - memcpy(&pos[9], - data->firmware->data + PATCH_INFO_SIZE + cur_len, - sent_len); - - BT_DBG("sent_len + PATCH_HEADER_SIZE = %d, phase = %d\n", - sent_len + PATCH_HEADER_SIZE, phase); - - usb_fill_bulk_urb(urb, - data->udev, - pipe, - buf, - sent_len + PATCH_HEADER_SIZE, - load_rom_patch_complete, - &sent_to_mcu_done); - - urb->transfer_dma = data_dma; - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - ret = usb_submit_urb(urb, GFP_ATOMIC); - - if (ret) - goto error2; - - if (!wait_for_completion_timeout(&sent_to_mcu_done, - msecs_to_jiffies(1000))) { - usb_kill_urb(urb); - BT_ERR("upload rom_patch timeout\n"); - goto error2; - } - - BT_DBG("."); - - mdelay(200); - - cur_len += sent_len; - - } - - total_checksum = checksume16( - (u8 *)data->firmware->data + PATCH_INFO_SIZE, - patch_len); - - BT_DBG("Send checksum req..\n"); - - btmtk_usb_chk_crc(data, patch_len); - - mdelay(20); - - if (total_checksum != btmtk_usb_get_crc(data)) { - BT_ERR("checksum fail!, local(0x%x) <> fw(0x%x)\n", - total_checksum, btmtk_usb_get_crc(data)); - ret = -1; - goto error2; - } - - mdelay(20); - - ret = btmtk_usb_reset_wmt(data); - - mdelay(20); - -error2: - usb_free_coherent(data->udev, UPLOAD_PATCH_UNIT, buf, data_dma); -error1: - usb_free_urb(urb); -error0: - btmtk_usb_io_write32(data, SEMAPHORE_03, 0x1); - return ret; -} - - -static int load_fw_iv(struct btmtk_usb_data *data) -{ - int ret; - struct usb_device *udev = data->udev; - char *buf = kmalloc(64, GFP_ATOMIC); - - memmove(buf, data->firmware->data + 32, 64); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, - DEVICE_VENDOR_REQUEST_OUT, 0x12, 0x0, buf, 64, - CONTROL_TIMEOUT_JIFFIES); - - if (ret < 0) { - BT_ERR("%s error(%d) step4\n", __func__, ret); - kfree(buf); - return ret; - } - - if (ret > 0) - ret = 0; - - kfree(buf); - - return ret; -} - -static void load_fw_complete(struct urb *urb) -{ - - struct completion *sent_to_mcu_done = (struct completion *)urb->context; - - complete(sent_to_mcu_done); -} - -static int btmtk_usb_load_fw(struct btmtk_usb_data *data) -{ - struct usb_device *udev = data->udev; - struct urb *urb; - void *buf; - u32 cur_len = 0; - u32 packet_header = 0; - __le32 packet_header_le; - u32 value; - u32 ilm_len = 0, dlm_len = 0; - u16 fw_ver, build_ver; - u32 loop = 0; - dma_addr_t data_dma; - int ret = 0, sent_len; - struct completion sent_to_mcu_done; - unsigned int pipe; - pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); - - if (!data->firmware) { - BT_ERR("%s:please assign a fw\n", __func__); - return -1; - } - - BT_DBG("bulk_tx_ep = %x\n", data->bulk_tx_ep->bEndpointAddress); - -loadfw_protect: - btmtk_usb_switch_iobase(data, WLAN); - btmtk_usb_io_read32(data, SEMAPHORE_00, &value); - loop++; - - if (((value & 0x1) == 0) && (loop < 10000)) - goto loadfw_protect; - - /* check MCU if ready */ - btmtk_usb_io_read32(data, COM_REG0, &value); - - if ((value & 0x01) == 0x01) - goto error0; - - /* Enable MPDMA TX and EP2 load FW mode */ - btmtk_usb_io_write32(data, 0x238, 0x1c000000); - - btmtk_usb_reset(udev); - mdelay(100); - - ilm_len = (*(data->firmware->data + 3) << 24) - | (*(data->firmware->data + 2) << 16) - | (*(data->firmware->data + 1) << 8) - | (*data->firmware->data); - - dlm_len = (*(data->firmware->data + 7) << 24) - | (*(data->firmware->data + 6) << 16) - | (*(data->firmware->data + 5) << 8) - | (*(data->firmware->data + 4)); - - fw_ver = (*(data->firmware->data + 11) << 8) | - (*(data->firmware->data + 10)); - - build_ver = (*(data->firmware->data + 9) << 8) | - (*(data->firmware->data + 8)); - - BT_DBG("fw version:%d.%d.%02d ", - (fw_ver & 0xf000) >> 8, - (fw_ver & 0x0f00) >> 8, - (fw_ver & 0x00ff)); - - BT_DBG("build:%x\n", build_ver); - - BT_DBG("build Time ="); - - for (loop = 0; loop < 16; loop++) - BT_DBG("%c", *(data->firmware->data + 16 + loop)); - - BT_DBG("\n"); - - BT_DBG("ILM length = %d(bytes)\n", ilm_len); - BT_DBG("DLM length = %d(bytes)\n", dlm_len); - - btmtk_usb_switch_iobase(data, SYSCTL); - - /* U2M_PDMA rx_ring_base_ptr */ - btmtk_usb_io_write32(data, 0x790, 0x400230); - - /* U2M_PDMA rx_ring_max_cnt */ - btmtk_usb_io_write32(data, 0x794, 0x1); - - /* U2M_PDMA cpu_idx */ - btmtk_usb_io_write32(data, 0x798, 0x1); - - /* U2M_PDMA enable */ - btmtk_usb_io_write32(data, 0x704, 0x44); - - urb = usb_alloc_urb(0, GFP_ATOMIC); - - if (!urb) { - ret = -ENOMEM; - goto error1; - } - - buf = usb_alloc_coherent(udev, 14592, GFP_ATOMIC, &data_dma); - - if (!buf) { - ret = -ENOMEM; - goto error2; - } - - BT_DBG("loading fw"); - - init_completion(&sent_to_mcu_done); - - btmtk_usb_switch_iobase(data, SYSCTL); - - cur_len = 0x40; - - /* Loading ILM */ - while (1) { - sent_len = min_t(s32, (ilm_len - cur_len), 14336); - - if (sent_len > 0) { - packet_header &= ~(0xffffffff); - packet_header |= (sent_len << 16); - packet_header_le = cpu_to_le32(packet_header); - - memmove(buf, &packet_header_le, 4); - memmove(buf + 4, data->firmware->data + 32 + cur_len, - sent_len); - - /* U2M_PDMA descriptor */ - btmtk_usb_io_write32(data, 0x230, cur_len); - - while ((sent_len % 4) != 0) - sent_len++; - - /* U2M_PDMA length */ - btmtk_usb_io_write32(data, 0x234, sent_len << 16); - - usb_fill_bulk_urb(urb, - udev, - pipe, - buf, - sent_len + 4, - load_fw_complete, - &sent_to_mcu_done); - - urb->transfer_dma = data_dma; - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - ret = usb_submit_urb(urb, GFP_ATOMIC); - - if (ret) - goto error3; - - if (!wait_for_completion_timeout(&sent_to_mcu_done, - msecs_to_jiffies(1000))) { - usb_kill_urb(urb); - BT_ERR("upload ilm fw timeout\n"); - goto error3; - } - - BT_DBG("."); - - mdelay(200); - - cur_len += sent_len; - } else { - break; - } - } - - init_completion(&sent_to_mcu_done); - cur_len = 0x00; - - /* Loading DLM */ - while (1) { - sent_len = min_t(s32, (dlm_len - cur_len), 14336); - - if (sent_len <= 0) - break; - - packet_header &= ~(0xffffffff); - packet_header |= (sent_len << 16); - packet_header_le = cpu_to_le32(packet_header); - - memmove(buf, &packet_header_le, 4); - memmove(buf + 4, - data->firmware->data + 32 + ilm_len + cur_len, - sent_len); - - /* U2M_PDMA descriptor */ - btmtk_usb_io_write32(data, 0x230, 0x80000 + cur_len); - - while ((sent_len % 4) != 0) { - BT_DBG("sent_len is not divided by 4\n"); - sent_len++; - } - - /* U2M_PDMA length */ - btmtk_usb_io_write32(data, 0x234, sent_len << 16); - - usb_fill_bulk_urb(urb, - udev, - pipe, - buf, - sent_len + 4, - load_fw_complete, - &sent_to_mcu_done); - - urb->transfer_dma = data_dma; - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - ret = usb_submit_urb(urb, GFP_ATOMIC); - - if (ret) - goto error3; - - if (!wait_for_completion_timeout(&sent_to_mcu_done, - msecs_to_jiffies(1000))) { - usb_kill_urb(urb); - BT_ERR("upload dlm fw timeout\n"); - goto error3; - } - - BT_DBG("."); - - mdelay(500); - - cur_len += sent_len; - - } - - /* upload 64bytes interrupt vector */ - ret = load_fw_iv(data); - mdelay(100); - - btmtk_usb_switch_iobase(data, WLAN); - - /* check MCU if ready */ - loop = 0; - - do { - btmtk_usb_io_read32(data, COM_REG0, &value); - - if (value == 0x01) - break; - - mdelay(10); - loop++; - } while (loop <= 100); - - if (loop > 1000) { - BT_ERR("wait for 100 times\n"); - ret = -ENODEV; - } - -error3: - usb_free_coherent(udev, 14592, buf, data_dma); -error2: - usb_free_urb(urb); -error1: - /* Disbale load fw mode */ - btmtk_usb_io_read32(data, 0x238, &value); - value = value & ~(0x10000000); - btmtk_usb_io_write32(data, 0x238, value); -error0: - btmtk_usb_io_write32(data, SEMAPHORE_00, 0x1); - return ret; -} - -static int inc_tx(struct btmtk_usb_data *data) -{ - unsigned long flags; - int rv; - - spin_lock_irqsave(&data->txlock, flags); - rv = test_bit(BTUSB_SUSPENDING, &data->flags); - if (!rv) - data->tx_in_flight++; - spin_unlock_irqrestore(&data->txlock, flags); - - return rv; -} - -static void btmtk_usb_intr_complete(struct urb *urb) -{ - struct hci_dev *hdev = urb->context; - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - int err; - - BT_DBG("%s: %s urb %p status %d count %d\n", __func__, hdev->name, - urb, urb->status, urb->actual_length); - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - return; - - if (urb->status == 0) { - hdev->stat.byte_rx += urb->actual_length; - - hex_dump("hci event", urb->transfer_buffer, urb->actual_length); - - if (hci_recv_fragment(hdev, HCI_EVENT_PKT, - urb->transfer_buffer, - urb->actual_length) < 0) { - BT_ERR("%s corrupted event packet", hdev->name); - hdev->stat.err_rx++; - } - } - - if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) - return; - - usb_mark_last_busy(data->udev); - usb_anchor_urb(urb, &data->intr_anchor); - - err = usb_submit_urb(urb, GFP_ATOMIC); - - if (err < 0) { - /* -EPERM: urb is being killed; - * -ENODEV: device got disconnected */ - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p failed to resubmit (%d)", - hdev->name, urb, -err); - usb_unanchor_urb(urb); - } -} - -static int btmtk_usb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - struct urb *urb; - unsigned char *buf; - unsigned int pipe; - int err, size; - - BT_DBG("%s\n", __func__); - - if (!data->intr_ep) - return -ENODEV; - - urb = usb_alloc_urb(0, mem_flags); - if (!urb) - return -ENOMEM; - - size = le16_to_cpu(data->intr_ep->wMaxPacketSize); - - buf = kmalloc(size, mem_flags); - if (!buf) { - usb_free_urb(urb); - return -ENOMEM; - } - - pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress); - - usb_fill_int_urb(urb, data->udev, pipe, buf, size, - btmtk_usb_intr_complete, hdev, - data->intr_ep->bInterval); - - urb->transfer_flags |= URB_FREE_BUFFER; - - usb_anchor_urb(urb, &data->intr_anchor); - - err = usb_submit_urb(urb, mem_flags); - if (err < 0) { - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); - usb_unanchor_urb(urb); - } - - usb_free_urb(urb); - - return err; - -} - -static void btmtk_usb_bulk_in_complete(struct urb *urb) -{ - struct hci_dev *hdev = urb->context; - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - int err; - - BT_DBG("%s:%s urb %p status %d count %d", __func__, hdev->name, - urb, urb->status, urb->actual_length); - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - return; - - if (urb->status == 0) { - hdev->stat.byte_rx += urb->actual_length; - - if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, - urb->transfer_buffer, - urb->actual_length) < 0) { - BT_ERR("%s corrupted ACL packet", hdev->name); - hdev->stat.err_rx++; - } - } - - if (!test_bit(BTUSB_BULK_RUNNING, &data->flags)) - return; - - usb_anchor_urb(urb, &data->bulk_anchor); - usb_mark_last_busy(data->udev); - - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - /* -EPERM: urb is being killed; - * -ENODEV: device got disconnected */ - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p failed to resubmit (%d)", - hdev->name, urb, -err); - usb_unanchor_urb(urb); - } -} - -static int btmtk_usb_submit_bulk_in_urb(struct hci_dev *hdev, gfp_t mem_flags) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - struct urb *urb; - unsigned char *buf; - unsigned int pipe; - int err, size = HCI_MAX_FRAME_SIZE; - - BT_DBG("%s:%s\n", __func__, hdev->name); - - if (!data->bulk_rx_ep) - return -ENODEV; - - urb = usb_alloc_urb(0, mem_flags); - if (!urb) - return -ENOMEM; - - buf = kmalloc(size, mem_flags); - if (!buf) { - usb_free_urb(urb); - return -ENOMEM; - } - - pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress); - - usb_fill_bulk_urb(urb, data->udev, pipe, buf, size, - btmtk_usb_bulk_in_complete, hdev); - - urb->transfer_flags |= URB_FREE_BUFFER; - - usb_mark_last_busy(data->udev); - usb_anchor_urb(urb, &data->bulk_anchor); - - err = usb_submit_urb(urb, mem_flags); - if (err < 0) { - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); - usb_unanchor_urb(urb); - } - - usb_free_urb(urb); - - return err; -} - -static void btmtk_usb_isoc_in_complete(struct urb *urb) - -{ - struct hci_dev *hdev = urb->context; - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - int i, err; - - BT_DBG("%s: %s urb %p status %d count %d", __func__, hdev->name, - urb, urb->status, urb->actual_length); - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - return; - - if (urb->status == 0) { - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int offset = urb->iso_frame_desc[i].offset; - unsigned int length; - length = urb->iso_frame_desc[i].actual_length; - - if (urb->iso_frame_desc[i].status) - continue; - - hdev->stat.byte_rx += length; - - if (hci_recv_fragment(hdev, HCI_SCODATA_PKT, - urb->transfer_buffer + offset, - length) < 0) { - BT_ERR("%s corrupted SCO packet", hdev->name); - hdev->stat.err_rx++; - } - } - } - - if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags)) - return; - - usb_anchor_urb(urb, &data->isoc_anchor); - - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - /* -EPERM: urb is being killed; - * -ENODEV: device got disconnected */ - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p failed to resubmit (%d)", - hdev->name, urb, -err); - usb_unanchor_urb(urb); - } -} - -static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu) -{ - int i, offset = 0; - - BT_DBG("len %d mtu %d", len, mtu); - - for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu; - i++, offset += mtu, len -= mtu) { - urb->iso_frame_desc[i].offset = offset; - urb->iso_frame_desc[i].length = mtu; - } - - if (len && i < BTUSB_MAX_ISOC_FRAMES) { - urb->iso_frame_desc[i].offset = offset; - urb->iso_frame_desc[i].length = len; - i++; - } - - urb->number_of_packets = i; -} - -static int btmtk_usb_submit_isoc_in_urb(struct hci_dev *hdev, gfp_t mem_flags) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - struct urb *urb; - unsigned char *buf; - unsigned int pipe; - int err, size; - - BT_DBG("%s\n", __func__); - - if (!data->isoc_rx_ep) - return -ENODEV; - - urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, mem_flags); - if (!urb) - return -ENOMEM; - - size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) * - BTUSB_MAX_ISOC_FRAMES; - - buf = kmalloc(size, mem_flags); - if (!buf) { - usb_free_urb(urb); - return -ENOMEM; - } - - pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress); - - usb_fill_int_urb(urb, data->udev, pipe, buf, size, - btmtk_usb_isoc_in_complete, hdev, - data->isoc_rx_ep->bInterval); - - urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; - - __fill_isoc_descriptor(urb, size, - le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize)); - - usb_anchor_urb(urb, &data->isoc_anchor); - - err = usb_submit_urb(urb, mem_flags); - if (err < 0) { - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); - usb_unanchor_urb(urb); - } - - usb_free_urb(urb); - - return err; -} - -static int btmtk_usb_open(struct hci_dev *hdev) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - int err; - - BT_DBG("%s\n", __func__); - - err = usb_autopm_get_interface(data->intf); - if (err < 0) - return err; - - data->intf->needs_remote_wakeup = 1; - - if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) - goto done; - - if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) - goto done; - - err = btmtk_usb_submit_intr_urb(hdev, GFP_KERNEL); - if (err < 0) - goto failed; - - err = btmtk_usb_submit_bulk_in_urb(hdev, GFP_KERNEL); - if (err < 0) { - usb_kill_anchored_urbs(&data->intr_anchor); - goto failed; - } - - set_bit(BTUSB_BULK_RUNNING, &data->flags); - btmtk_usb_submit_bulk_in_urb(hdev, GFP_KERNEL); - -done: - usb_autopm_put_interface(data->intf); - return 0; - -failed: - clear_bit(BTUSB_INTR_RUNNING, &data->flags); - clear_bit(HCI_RUNNING, &hdev->flags); - usb_autopm_put_interface(data->intf); - return err; -} - -static void btmtk_usb_stop_traffic(struct btmtk_usb_data *data) -{ - BT_DBG("%s\n", __func__); - - usb_kill_anchored_urbs(&data->intr_anchor); - usb_kill_anchored_urbs(&data->bulk_anchor); - usb_kill_anchored_urbs(&data->isoc_anchor); -} - -static int btmtk_usb_close(struct hci_dev *hdev) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - int err; - - BT_DBG("%s\n", __func__); - - if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) - return 0; - - cancel_work_sync(&data->work); - cancel_work_sync(&data->waker); - - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - clear_bit(BTUSB_BULK_RUNNING, &data->flags); - clear_bit(BTUSB_INTR_RUNNING, &data->flags); - - btmtk_usb_stop_traffic(data); - - err = usb_autopm_get_interface(data->intf); - if (err < 0) - goto failed; - - data->intf->needs_remote_wakeup = 0; - usb_autopm_put_interface(data->intf); - -failed: - usb_scuttle_anchored_urbs(&data->deferred); - return 0; -} - -static int btmtk_usb_flush(struct hci_dev *hdev) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - - BT_DBG("%s\n", __func__); - - usb_kill_anchored_urbs(&data->tx_anchor); - - return 0; -} - -static void btmtk_usb_tx_complete(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct hci_dev *hdev = (struct hci_dev *)skb->dev; - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - - BT_DBG("%s: %s urb %p status %d count %d\n", __func__, hdev->name, - urb, urb->status, urb->actual_length); - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - goto done; - - if (!urb->status) - hdev->stat.byte_tx += urb->transfer_buffer_length; - else - hdev->stat.err_tx++; - -done: - spin_lock(&data->txlock); - data->tx_in_flight--; - spin_unlock(&data->txlock); - - kfree(urb->setup_packet); - - kfree_skb(skb); -} - -static void btmtk_usb_isoc_tx_complete(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct hci_dev *hdev = (struct hci_dev *) skb->dev; - - BT_DBG("%s: %s urb %p status %d count %d", __func__, hdev->name, - urb, urb->status, urb->actual_length); - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - goto done; - - if (!urb->status) - hdev->stat.byte_tx += urb->transfer_buffer_length; - else - hdev->stat.err_tx++; - -done: - kfree(urb->setup_packet); - - kfree_skb(skb); -} - -static int btmtk_usb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - struct usb_ctrlrequest *dr; - struct urb *urb; - unsigned int pipe; - int err; - - BT_DBG("%s\n", __func__); - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - return -EBUSY; - - switch (bt_cb(skb)->pkt_type) { - case HCI_COMMAND_PKT: - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) - return -ENOMEM; - - dr = kmalloc(sizeof(*dr), GFP_ATOMIC); - if (!dr) { - usb_free_urb(urb); - return -ENOMEM; - } - - dr->bRequestType = data->cmdreq_type; - dr->bRequest = 0; - dr->wIndex = 0; - dr->wValue = 0; - dr->wLength = __cpu_to_le16(skb->len); - - pipe = usb_sndctrlpipe(data->udev, 0x00); - - if (test_bit(HCI_RUNNING, &hdev->flags)) { - u16 op_code; - memcpy(&op_code, skb->data, 2); - BT_DBG("ogf = %x\n", (op_code & 0xfc00) >> 10); - BT_DBG("ocf = %x\n", op_code & 0x03ff); - hex_dump("hci command", skb->data, skb->len); - - } - - usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, - skb->data, skb->len, - btmtk_usb_tx_complete, skb); - - hdev->stat.cmd_tx++; - break; - - case HCI_ACLDATA_PKT: - if (!data->bulk_tx_ep) - return -ENODEV; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) - return -ENOMEM; - - pipe = usb_sndbulkpipe(data->udev, - data->bulk_tx_ep->bEndpointAddress); - - usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, - skb->len, btmtk_usb_tx_complete, skb); - - hdev->stat.acl_tx++; - BT_DBG("HCI_ACLDATA_PKT:\n"); - break; - - case HCI_SCODATA_PKT: - if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1) - return -ENODEV; - - urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); - if (!urb) - return -ENOMEM; - - pipe = usb_sndisocpipe(data->udev, - data->isoc_tx_ep->bEndpointAddress); - - usb_fill_int_urb(urb, data->udev, pipe, - skb->data, skb->len, btmtk_usb_isoc_tx_complete, - skb, data->isoc_tx_ep->bInterval); - - urb->transfer_flags = URB_ISO_ASAP; - - __fill_isoc_descriptor(urb, skb->len, - le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); - - hdev->stat.sco_tx++; - BT_DBG("HCI_SCODATA_PKT:\n"); - goto skip_waking; - - default: - return -EILSEQ; - } - - err = inc_tx(data); - - if (err) { - usb_anchor_urb(urb, &data->deferred); - schedule_work(&data->waker); - err = 0; - goto done; - } - -skip_waking: - usb_anchor_urb(urb, &data->tx_anchor); - - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - if (err != -EPERM && err != -ENODEV) - BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); - kfree(urb->setup_packet); - usb_unanchor_urb(urb); - } else { - usb_mark_last_busy(data->udev); - } - -done: - usb_free_urb(urb); - return err; -} - -static void btmtk_usb_notify(struct hci_dev *hdev, unsigned int evt) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - - BT_DBG("%s evt %d", hdev->name, evt); - - if (hdev->conn_hash.sco_num != data->sco_num) { - data->sco_num = hdev->conn_hash.sco_num; - schedule_work(&data->work); - } -} - -static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting) -{ - struct btmtk_usb_data *data = hci_get_drvdata(hdev); - struct usb_interface *intf = data->isoc; - struct usb_endpoint_descriptor *ep_desc; - int i, err; - - if (!data->isoc) - return -ENODEV; - - err = usb_set_interface(data->udev, 1, altsetting); - if (err < 0) { - BT_ERR("%s setting interface failed (%d)", hdev->name, -err); - return err; - } - - data->isoc_altsetting = altsetting; - - data->isoc_tx_ep = NULL; - data->isoc_rx_ep = NULL; - - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { - ep_desc = &intf->cur_altsetting->endpoint[i].desc; - - if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) { - data->isoc_tx_ep = ep_desc; - continue; - } - - if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) { - data->isoc_rx_ep = ep_desc; - continue; - } - } - - if (!data->isoc_tx_ep || !data->isoc_rx_ep) { - BT_ERR("%s invalid SCO descriptors", hdev->name); - return -ENODEV; - } - - return 0; -} - -static void btmtk_usb_work(struct work_struct *work) -{ - struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, - work); - struct hci_dev *hdev = data->hdev; - int new_alts; - int err; - - BT_DBG("%s\n", __func__); - - if (hdev->conn_hash.sco_num > 0) { - if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) { - err = usb_autopm_get_interface(data->isoc ? - data->isoc : data->intf); - if (err < 0) { - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->isoc_anchor); - return; - } - - set_bit(BTUSB_DID_ISO_RESUME, &data->flags); - } - - if (hdev->voice_setting & 0x0020) { - static const int alts[3] = { 2, 4, 5 }; - new_alts = alts[hdev->conn_hash.sco_num - 1]; - } else { - new_alts = hdev->conn_hash.sco_num; - } - - if (data->isoc_altsetting != new_alts) { - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->isoc_anchor); - - if (__set_isoc_interface(hdev, new_alts) < 0) - return; - } - - if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { - if (btmtk_usb_submit_isoc_in_urb(hdev, GFP_KERNEL) < 0) - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - else - btmtk_usb_submit_isoc_in_urb(hdev, GFP_KERNEL); - } - } else { - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->isoc_anchor); - - __set_isoc_interface(hdev, 0); - - if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags)) - usb_autopm_put_interface(data->isoc ? - data->isoc : data->intf); - } -} - -static void btmtk_usb_waker(struct work_struct *work) -{ - struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, - waker); - int err; - - err = usb_autopm_get_interface(data->intf); - - if (err < 0) - return; - - usb_autopm_put_interface(data->intf); -} - -static int btmtk_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct btmtk_usb_data *data; - struct usb_endpoint_descriptor *ep_desc; - int i, err; - struct hci_dev *hdev; - - /* interface numbers are hardcoded in the spec */ - if (intf->cur_altsetting->desc.bInterfaceNumber != 0) - return -ENODEV; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - - if (!data) - return -ENOMEM; - - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { - ep_desc = &intf->cur_altsetting->endpoint[i].desc; - - if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) { - data->intr_ep = ep_desc; - continue; - } - - if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) { - data->bulk_tx_ep = ep_desc; - continue; - } - - if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) { - data->bulk_rx_ep = ep_desc; - continue; - } - } - - if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) { - kfree(data); - return -ENODEV; - } - - data->cmdreq_type = USB_TYPE_CLASS; - - data->udev = interface_to_usbdev(intf); - data->intf = intf; - - spin_lock_init(&data->lock); - INIT_WORK(&data->work, btmtk_usb_work); - INIT_WORK(&data->waker, btmtk_usb_waker); - spin_lock_init(&data->txlock); - - init_usb_anchor(&data->tx_anchor); - init_usb_anchor(&data->intr_anchor); - init_usb_anchor(&data->bulk_anchor); - init_usb_anchor(&data->isoc_anchor); - init_usb_anchor(&data->deferred); - - hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); - return -ENOMEM; - } - - hdev->bus = HCI_USB; - - hci_set_drvdata(hdev, data); - - data->hdev = hdev; - - SET_HCIDEV_DEV(hdev, &intf->dev); - - hdev->open = btmtk_usb_open; - hdev->close = btmtk_usb_close; - hdev->flush = btmtk_usb_flush; - hdev->send = btmtk_usb_send_frame; - hdev->notify = btmtk_usb_notify; - - /* Interface numbers are hardcoded in the specification */ - data->isoc = usb_ifnum_to_if(data->udev, 1); - - if (data->isoc) { - err = usb_driver_claim_interface(&btmtk_usb_driver, - data->isoc, data); - if (err < 0) { - hci_free_dev(hdev); - kfree(data); - return err; - } - } - - data->io_buf = kmalloc(256, GFP_KERNEL); - if (!data->io_buf) { - hci_free_dev(hdev); - kfree(data); - return -ENOMEM; - } - - btmtk_usb_switch_iobase(data, WLAN); - - btmtk_usb_cap_init(data); - - err = hci_register_dev(hdev); - if (err < 0) { - hci_free_dev(hdev); - kfree(data); - return err; - } - - usb_set_intfdata(intf, data); - - return 0; -} - -static void btmtk_usb_disconnect(struct usb_interface *intf) -{ - struct btmtk_usb_data *data = usb_get_intfdata(intf); - struct hci_dev *hdev; - - BT_DBG("%s\n", __func__); - - if (!data) - return; - - hdev = data->hdev; - usb_set_intfdata(data->intf, NULL); - - if (data->isoc) - usb_set_intfdata(data->isoc, NULL); - - hci_unregister_dev(hdev); - - if (intf == data->isoc) - usb_driver_release_interface(&btmtk_usb_driver, data->intf); - else if (data->isoc) - usb_driver_release_interface(&btmtk_usb_driver, data->isoc); - - hci_free_dev(hdev); - - kfree(data->io_buf); - - kfree(data); -} - -#ifdef CONFIG_PM -static int btmtk_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct btmtk_usb_data *data = usb_get_intfdata(intf); - - BT_DBG("%s\n", __func__); - - if (data->suspend_count++) - return 0; - - spin_lock_irq(&data->txlock); - if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) { - set_bit(BTUSB_SUSPENDING, &data->flags); - spin_unlock_irq(&data->txlock); - } else { - spin_unlock_irq(&data->txlock); - data->suspend_count--; - return -EBUSY; - } - - cancel_work_sync(&data->work); - - btmtk_usb_stop_traffic(data); - usb_kill_anchored_urbs(&data->tx_anchor); - - return 0; -} - -static void play_deferred(struct btmtk_usb_data *data) -{ - struct urb *urb; - int err; - - while ((urb = usb_get_from_anchor(&data->deferred))) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) - break; - - data->tx_in_flight++; - } - - usb_scuttle_anchored_urbs(&data->deferred); -} - -static int btmtk_usb_resume(struct usb_interface *intf) -{ - struct btmtk_usb_data *data = usb_get_intfdata(intf); - struct hci_dev *hdev = data->hdev; - int err = 0; - - BT_DBG("%s\n", __func__); - - if (--data->suspend_count) - return 0; - - if (!test_bit(HCI_RUNNING, &hdev->flags)) - goto done; - - if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) { - err = btmtk_usb_submit_intr_urb(hdev, GFP_NOIO); - if (err < 0) { - clear_bit(BTUSB_INTR_RUNNING, &data->flags); - goto failed; - } - } - - if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) { - err = btmtk_usb_submit_bulk_in_urb(hdev, GFP_NOIO); - if (err < 0) { - clear_bit(BTUSB_BULK_RUNNING, &data->flags); - goto failed; - } - - btmtk_usb_submit_bulk_in_urb(hdev, GFP_NOIO); - } - - if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) { - if (btmtk_usb_submit_isoc_in_urb(hdev, GFP_NOIO) < 0) - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - else - btmtk_usb_submit_isoc_in_urb(hdev, GFP_NOIO); - } - - spin_lock_irq(&data->txlock); - play_deferred(data); - clear_bit(BTUSB_SUSPENDING, &data->flags); - spin_unlock_irq(&data->txlock); - schedule_work(&data->work); - - return 0; - -failed: - usb_scuttle_anchored_urbs(&data->deferred); -done: - spin_lock_irq(&data->txlock); - clear_bit(BTUSB_SUSPENDING, &data->flags); - spin_unlock_irq(&data->txlock); - - return err; -} -#endif - -static struct usb_device_id btmtk_usb_table[] = { - /* Mediatek MT7650 */ - { USB_DEVICE(0x0e8d, 0x7650) }, - { USB_DEVICE(0x0e8d, 0x7630) }, - { USB_DEVICE(0x0e8d, 0x763e) }, - /* Mediatek MT662 */ - { USB_DEVICE(0x0e8d, 0x7662) }, - { USB_DEVICE(0x0e8d, 0x7632) }, - { } /* Terminating entry */ -}; - -static struct usb_driver btmtk_usb_driver = { - .name = "btmtk_usb", - .probe = btmtk_usb_probe, - .disconnect = btmtk_usb_disconnect, -#ifdef CONFIG_PM - .suspend = btmtk_usb_suspend, - .resume = btmtk_usb_resume, -#endif - .id_table = btmtk_usb_table, - .supports_autosuspend = 1, - .disable_hub_initiated_lpm = 1, -}; - -module_usb_driver(btmtk_usb_driver); - -MODULE_DESCRIPTION("Mediatek Bluetooth USB driver ver " VERSION); -MODULE_VERSION(VERSION); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(MT7650_FIRMWARE); -MODULE_FIRMWARE(MT7662_FIRMWARE); diff --git a/drivers/staging/btmtk_usb/btmtk_usb.h b/drivers/staging/btmtk_usb/btmtk_usb.h deleted file mode 100644 index 12f0d3b27bfe..000000000000 --- a/drivers/staging/btmtk_usb/btmtk_usb.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * MediaTek Bluetooth USB Driver - * - * Copyright (C) 2013, MediaTek co. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * 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 - * or on the worldwide web at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - */ - -#ifndef __BTMTK_USB_H__ -#define __BTMTK_USB_H_ - -/* Memory map for MTK BT */ - -/* SYS Control */ -#define SYSCTL 0x400000 - -/* WLAN */ -#define WLAN 0x410000 - -/* MCUCTL */ -#define INT_LEVEL 0x0718 -#define COM_REG0 0x0730 -#define SEMAPHORE_00 0x07B0 -#define SEMAPHORE_01 0x07B4 -#define SEMAPHORE_02 0x07B8 -#define SEMAPHORE_03 0x07BC - -/* Chip definition */ - -#define CONTROL_TIMEOUT_JIFFIES ((300 * HZ) / 100) -#define DEVICE_VENDOR_REQUEST_OUT 0x40 -#define DEVICE_VENDOR_REQUEST_IN 0xc0 -#define DEVICE_CLASS_REQUEST_OUT 0x20 - -#define BTUSB_MAX_ISOC_FRAMES 10 -#define BTUSB_INTR_RUNNING 0 -#define BTUSB_BULK_RUNNING 1 -#define BTUSB_ISOC_RUNNING 2 -#define BTUSB_SUSPENDING 3 -#define BTUSB_DID_ISO_RESUME 4 - -/* ROM Patch */ -#define PATCH_HCI_HEADER_SIZE 4 -#define PATCH_WMT_HEADER_SIZE 5 -#define PATCH_HEADER_SIZE (PATCH_HCI_HEADER_SIZE + PATCH_WMT_HEADER_SIZE) -#define UPLOAD_PATCH_UNIT 2048 -#define PATCH_INFO_SIZE 30 -#define PATCH_PHASE1 1 -#define PATCH_PHASE2 2 -#define PATCH_PHASE3 3 - -struct btmtk_usb_data { - struct hci_dev *hdev; - struct usb_device *udev; - struct usb_interface *intf; - struct usb_interface *isoc; - - spinlock_t lock; - - unsigned long flags; - struct work_struct work; - struct work_struct waker; - - struct usb_anchor tx_anchor; - struct usb_anchor intr_anchor; - struct usb_anchor bulk_anchor; - struct usb_anchor isoc_anchor; - struct usb_anchor deferred; - int tx_in_flight; - spinlock_t txlock; - - struct usb_endpoint_descriptor *intr_ep; - struct usb_endpoint_descriptor *bulk_tx_ep; - struct usb_endpoint_descriptor *bulk_rx_ep; - struct usb_endpoint_descriptor *isoc_tx_ep; - struct usb_endpoint_descriptor *isoc_rx_ep; - - __u8 cmdreq_type; - - unsigned int sco_num; - int isoc_altsetting; - int suspend_count; - - /* request for different io operation */ - u8 w_request; - u8 r_request; - - /* io buffer for usb control transfer */ - char *io_buf; - - struct semaphore fw_upload_sem; - - /* unsigned char *fw_image; */ - /* unsigned char *rom_patch; */ - const struct firmware *firmware; - u32 chip_id; - u8 need_load_fw; - u8 need_load_rom_patch; - u32 rom_patch_offset; - u32 rom_patch_len; -}; - -static inline int is_mt7630(struct btmtk_usb_data *data) -{ - return ((data->chip_id & 0xffff0000) == 0x76300000); -} - -static inline int is_mt7650(struct btmtk_usb_data *data) -{ - return ((data->chip_id & 0xffff0000) == 0x76500000); -} - -static inline int is_mt7632(struct btmtk_usb_data *data) -{ - return ((data->chip_id & 0xffff0000) == 0x76320000); -} - -static inline int is_mt7662(struct btmtk_usb_data *data) -{ - return ((data->chip_id & 0xffff0000) == 0x76620000); -} - -#endif -- cgit v1.2.3 From c952a8ba7136505cd1ca01735cc748ddc08c7d2f Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 4 Nov 2013 21:11:53 +0800 Subject: usb: usbtest: add a test case to support bos for queue control In Test 10 of usbtest module, it queues multiple control messages and thereby tests control message queuing, protocol stalls, short reads, and fault handling. And this patch add a test case to support queue BOS control request for USB 3.0 SPEC. Signed-off-by: Huang Rui Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index b4152820d655..f3c31363c40a 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -944,7 +944,7 @@ struct ctrl_ctx { int last; }; -#define NUM_SUBCASES 15 /* how many test subcases here? */ +#define NUM_SUBCASES 16 /* how many test subcases here? */ struct subcase { struct usb_ctrlrequest setup; @@ -1218,6 +1218,15 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) } expected = -EREMOTEIO; break; + case 15: + req.wValue = cpu_to_le16(USB_DT_BOS << 8); + if (udev->bos) + len = le16_to_cpu(udev->bos->desc->wTotalLength); + else + len = sizeof(struct usb_bos_descriptor); + if (udev->speed != USB_SPEED_SUPER) + expected = -EPIPE; + break; default: ERROR(dev, "bogus number of ctrl queue testcases!\n"); context.status = -EINVAL; -- cgit v1.2.3 From 875bc23ac041519b24bd2c1faf71822e4b3e4322 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 13 Nov 2013 22:35:14 +0800 Subject: usb: usbtest: fix the bit mask of usb 2.0 extension descriptor USB 2.1 Link PM adds to use bits[1:15] according to USB 2.0 ECN Errata for Link Power Management spec. Bit Encoding 0 Reserved 1 LPM 2 BESL & Altemate HIRD definitions supported 3 Recommended Baseline BESL valid 4 Recommended Deep BESL valid 11:8 Recommended Baseline BESL value 15:12 Recommended Deep BESL value 31:16 Reserved So fix the bit mask from 0x1e to 0xfffe. Reported-by: Sarah Sharp Signed-off-by: Huang Rui Acked-by: Felipe Balbi Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index f3c31363c40a..0b5c3b157530 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -619,8 +619,8 @@ static int is_good_ext(struct usbtest_dev *tdev, u8 *buf) } attr = le32_to_cpu(ext->bmAttributes); - /* bits[1:4] is used and others are reserved */ - if (attr & ~0x1e) { /* reserved == 0 */ + /* bits[1:15] is used and others are reserved */ + if (attr & ~0xfffe) { /* reserved == 0 */ ERROR(tdev, "reserved bits set\n"); return 0; } -- cgit v1.2.3 From f625099f1a504742aef4c6ab20ba0ca981847e3c Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 13 Nov 2013 22:35:13 +0800 Subject: usb: usbtest: update bos test coverage to usb 2.1 device The commit "usb: usbtest: support bos descriptor test for usb 3.0" introduced a test for bos descriptor. And USB 2.1 device also can be checked. So this patch extends the test coverage to support USB 2.1 device. Reported-by: Sarah Sharp Signed-off-by: Huang Rui Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 0b5c3b157530..bff058ea222e 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -763,7 +763,7 @@ static int ch9_postconfig(struct usbtest_dev *dev) * there's always [9.4.3] a bos device descriptor [9.6.2] in USB * 3.0 spec */ - if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0300) { + if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0210) { struct usb_bos_descriptor *bos = NULL; struct usb_dev_cap_header *header = NULL; unsigned total, num, length; -- cgit v1.2.3 From e1bffbf622ebceff411fef4970f0fa6326b45830 Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Wed, 13 Nov 2013 17:40:16 +0530 Subject: USB: OHCI: Properly handle OHCI controller suspend Suspend scenario in case of OHCI was not properly handled in ochi_suspend()routine. Alan Stern suggested, properly handle OHCI suspend scenario. This does generic proper handling of suspend scenario to all OHCI SOC. Signed-off-by: Manjunath Goudar Acked-by: Alan Stern Cc: linux-usb@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index c8e0e7637b7b..3586460fb2a1 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1026,6 +1026,7 @@ int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); unsigned long flags; + int rc = 0; /* Disable irq emission and mark HW unaccessible. Use * the spinlock to properly synchronize with possible pending @@ -1038,7 +1039,13 @@ int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irqrestore (&ohci->lock, flags); - return 0; + synchronize_irq(hcd->irq); + + if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) { + ohci_resume(hcd, false); + rc = -EBUSY; + } + return rc; } EXPORT_SYMBOL_GPL(ohci_suspend); -- cgit v1.2.3 From a9d3840ed3441d5996647b61b6e2ee630242989f Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Wed, 13 Nov 2013 17:40:17 +0530 Subject: USB: OHCI: Properly handle ohci-at91 suspend Suspend scenario in case of ohci-at91 glue was not properly handled as it was not suspending generic part of ohci controller. Alan Stern suggested, properly handle ohci-at91 suspend scenario. Calling explicitly the ohci_suspend() routine in ohci_hcd_at91_drv_suspend() will ensure proper handling of suspend scenario. This task is sugested by Alan Stern. Signed-off-by: Manjunath Goudar Acked-by: Alan Stern Cc: Arnd Bergmann Cc: linux-usb@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 418444ebb1b8..cc9462f19fa5 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -635,10 +635,17 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + bool do_wakeup = device_may_wakeup(&pdev->dev); + int ret; - if (device_may_wakeup(&pdev->dev)) + if (do_wakeup) enable_irq_wake(hcd->irq); + ret = ohci_suspend(hcd, do_wakeup); + if (ret) { + disable_irq_wake(hcd->irq); + return ret; + } /* * The integrated transceivers seem unable to notice disconnect, * reconnect, or wakeup without the 48 MHz clock active. so for @@ -657,7 +664,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) at91_stop_clock(); } - return 0; + return ret; } static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) -- cgit v1.2.3 From 0ded36d91821620e4e8f50fb9e47440988e06366 Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Wed, 13 Nov 2013 17:40:18 +0530 Subject: USB: OHCI: Properly handle ohci-s3c2410 suspend Suspend scenario in case of ohci-s3c2410 glue was not properly handled as it was not suspending generic part of ohci controller. Alan Stern suggested, properly handle ohci-s3c2410 suspend scenario. Calling explicitly the ohci_suspend() routine in ohci_hcd_s3c2410_drv_suspend() will ensure proper handling of suspend scenario. Signed-off-by: Manjunath Goudar Acked-by: Alan Stern Cc: Ben Dooks Cc: Kukjin Kim Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-usb@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-s3c2410.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index f90101b9cdb9..83cd1dcd5145 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -426,28 +426,15 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) static int ohci_hcd_s3c2410_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct platform_device *pdev = to_platform_device(dev); - unsigned long flags; + bool do_wakeup = device_may_wakeup(dev); int rc = 0; - /* - * Root hub was already suspended. Disable irq emission and - * mark HW unaccessible, bail out if RH has been resumed. Use - * the spinlock to properly synchronize with possible pending - * RH suspend or resume activity. - */ - spin_lock_irqsave(&ohci->lock, flags); - if (ohci->rh_state != OHCI_RH_SUSPENDED) { - rc = -EINVAL; - goto bail; - } - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + rc = ohci_suspend(hcd, do_wakeup); + if (rc) + return rc; s3c2410_stop_hc(pdev); -bail: - spin_unlock_irqrestore(&ohci->lock, flags); return rc; } -- cgit v1.2.3 From 933bb1f0442ea1c15e7d9d23894d8dd4937bdf95 Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Wed, 13 Nov 2013 17:40:19 +0530 Subject: USB: OHCI: Properly handle ohci-da8xx suspend Suspend scenario in case of ohci-da8xx glue was not properly handled as it was not suspending generic part of ohci controller. Alan Stern suggested, properly handle ohci-da8xx suspend scenario. Calling explicitly the ohci_suspend() routine in ohci_da8xx_suspend() will ensure proper handling of suspend scenario. Signed-off-by: Manjunath Goudar Acked-by: Alan Stern Cc: Arnd Bergmann Cc: linux-usb@vger.kernel.or Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-da8xx.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 9be59f11e051..71dbd85e9a8d 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -406,19 +406,27 @@ static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev) } #ifdef CONFIG_PM -static int ohci_da8xx_suspend(struct platform_device *dev, pm_message_t message) +static int ohci_da8xx_suspend(struct platform_device *pdev, + pm_message_t message) { - struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + bool do_wakeup = device_may_wakeup(&pdev->dev); + int ret; + if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; + ret = ohci_suspend(hcd, do_wakeup); + if (ret) + return ret; + ohci_da8xx_clock(0); hcd->state = HC_STATE_SUSPENDED; - dev->dev.power.power_state = PMSG_SUSPEND; - return 0; + + return ret; } static int ohci_da8xx_resume(struct platform_device *dev) -- cgit v1.2.3 From 14982e31da83a818d03748a89957e47c139d8f07 Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Wed, 13 Nov 2013 17:40:20 +0530 Subject: USB: OHCI: Properly handle ohci-exynos suspend Suspend scenario in case of ohci-exynos glue was not properly handled as it was not suspending generic part of ohci controller. Alan Stern suggested, properly handle ohci-exynos suspend scenario. Calling explicitly the ohci_suspend() routine in exynos_ohci_suspend() will ensure proper handling of suspend scenario. Signed-off-by: Manjunath Goudar Acked-by: Alan Stern Cc: Arnd Bergmann Cc: Kukjin Kim Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-usb@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-exynos.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 91ec9b2cd378..9897d70e4c15 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -191,23 +191,14 @@ static int exynos_ohci_suspend(struct device *dev) struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct platform_device *pdev = to_platform_device(dev); + bool do_wakeup = device_may_wakeup(dev); unsigned long flags; - int rc = 0; + int rc = ohci_suspend(hcd, do_wakeup); - /* - * Root hub was already suspended. Disable irq emission and - * mark HW unaccessible, bail out if RH has been resumed. Use - * the spinlock to properly synchronize with possible pending - * RH suspend or resume activity. - */ - spin_lock_irqsave(&ohci->lock, flags); - if (ohci->rh_state != OHCI_RH_SUSPENDED && - ohci->rh_state != OHCI_RH_HALTED) { - rc = -EINVAL; - goto fail; - } + if (rc) + return rc; - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + spin_lock_irqsave(&ohci->lock, flags); if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); @@ -216,10 +207,9 @@ static int exynos_ohci_suspend(struct device *dev) clk_disable_unprepare(exynos_ohci->clk); -fail: spin_unlock_irqrestore(&ohci->lock, flags); - return rc; + return 0; } static int exynos_ohci_resume(struct device *dev) -- cgit v1.2.3 From d2e3d2b348bce1bb96cd42db51789f368c3eb974 Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Wed, 13 Nov 2013 17:40:21 +0530 Subject: USB: OHCI: Properly handle ohci-spear suspend Suspend scenario in case of ohci-spear glue was not properly handled as it was not suspending generic part of ohci controller. Alan Stern suggested, properly handle ohci-spear suspend scenario. Calling explicitly the ohci_suspend() routine in spear_ohci_hcd_drv_suspend() will ensure proper handling of suspend scenario. Signed-off-by: Manjunath Goudar Acked-by: Alan Stern Cc: Arnd Bergmann Cc: linux-usb@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-spear.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index 6b02107d281d..e418c192e23a 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -129,20 +129,26 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) } #if defined(CONFIG_PM) -static int spear_ohci_hcd_drv_suspend(struct platform_device *dev, +static int spear_ohci_hcd_drv_suspend(struct platform_device *pdev, pm_message_t message) { - struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct spear_ohci *sohci_p = to_spear_ohci(hcd); + bool do_wakeup = device_may_wakeup(&pdev->dev); + int ret; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; + ret = ohci_suspend(hcd, do_wakeup); + if (ret) + return ret; + clk_disable_unprepare(sohci_p->clk); - return 0; + return ret; } static int spear_ohci_hcd_drv_resume(struct platform_device *dev) -- cgit v1.2.3 From b374487ebe8a91d03c07fe361af375e09285c3b0 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 25 Nov 2013 16:17:16 -0600 Subject: usb: wusbcore: add calls to usb_hcd_link_urb_to_ep, usb_hcd_unlink_urb_from_ep, and Add calls to usb_hcd_link_urb_to_ep, usb_hcd_unlink_urb_from_ep, and usb_hcd_check_unlink_urb in the appropriate locations. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/hwa-hc.c | 2 +- drivers/usb/wusbcore/wa-hc.h | 2 +- drivers/usb/wusbcore/wa-xfer.c | 26 ++++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index ada0a52797b1..a4ec9e6c0f86 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -224,7 +224,7 @@ static int hwahc_op_urb_dequeue(struct usb_hcd *usb_hcd, struct urb *urb, struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - return wa_urb_dequeue(&hwahc->wa, urb); + return wa_urb_dequeue(&hwahc->wa, urb, status); } /* diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h index e614f02f0cf2..5b6ae3a4a755 100644 --- a/drivers/usb/wusbcore/wa-hc.h +++ b/drivers/usb/wusbcore/wa-hc.h @@ -332,7 +332,7 @@ static inline int rpipe_avail_inc(struct wa_rpipe *rpipe) /* Transferring data */ extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *, struct urb *, gfp_t); -extern int wa_urb_dequeue(struct wahc *, struct urb *); +extern int wa_urb_dequeue(struct wahc *, struct urb *, int); extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *); diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index ed5abe87b049..5957e486591a 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -282,6 +282,7 @@ static void wa_xfer_giveback(struct wa_xfer *xfer) spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags); list_del_init(&xfer->list_node); + usb_hcd_unlink_urb_from_ep(&(xfer->wa->wusb->usb_hcd), xfer->urb); spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags); /* FIXME: segmentation broken -- kills DWA */ wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result); @@ -1730,6 +1731,12 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, dump_stack(); } + spin_lock_irqsave(&wa->xfer_list_lock, my_flags); + result = usb_hcd_link_urb_to_ep(&(wa->wusb->usb_hcd), urb); + spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags); + if (result < 0) + goto error_link_urb; + result = -ENOMEM; xfer = kzalloc(sizeof(*xfer), gfp); if (xfer == NULL) @@ -1769,6 +1776,9 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, __func__, result); wa_put(xfer->wa); wa_xfer_put(xfer); + spin_lock_irqsave(&wa->xfer_list_lock, my_flags); + usb_hcd_unlink_urb_from_ep(&(wa->wusb->usb_hcd), urb); + spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags); return result; } } @@ -1777,6 +1787,10 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, error_dequeued: kfree(xfer); error_kmalloc: + spin_lock_irqsave(&wa->xfer_list_lock, my_flags); + usb_hcd_unlink_urb_from_ep(&(wa->wusb->usb_hcd), urb); + spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags); +error_link_urb: return result; } EXPORT_SYMBOL_GPL(wa_urb_enqueue); @@ -1799,7 +1813,7 @@ EXPORT_SYMBOL_GPL(wa_urb_enqueue); * asynch request] and then make sure we cancel each segment. * */ -int wa_urb_dequeue(struct wahc *wa, struct urb *urb) +int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status) { unsigned long flags, flags2; struct wa_xfer *xfer; @@ -1807,6 +1821,14 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb) struct wa_rpipe *rpipe; unsigned cnt, done = 0, xfer_abort_pending; unsigned rpipe_ready = 0; + int result; + + /* check if it is safe to unlink. */ + spin_lock_irqsave(&wa->xfer_list_lock, flags); + result = usb_hcd_check_unlink_urb(&(wa->wusb->usb_hcd), urb, status); + spin_unlock_irqrestore(&wa->xfer_list_lock, flags); + if (result) + return result; xfer = urb->hcpriv; if (xfer == NULL) { @@ -2172,7 +2194,7 @@ error_complete: error_bad_seg: spin_unlock_irqrestore(&xfer->lock, flags); - wa_urb_dequeue(wa, xfer->urb); + wa_urb_dequeue(wa, xfer->urb, -ENOENT); if (printk_ratelimit()) dev_err(dev, "xfer %p#%u: bad segment\n", xfer, seg_idx); if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { -- cgit v1.2.3 From bbfc34201fffd8a41c2ecbad2b8fb3bf00d7ee74 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 25 Nov 2013 16:17:17 -0600 Subject: usb: wusbcore: add more info to debug prints in urb_unlink path Add more info to debug prints in urb_unlink path Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 5957e486591a..3220c62de317 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -373,10 +373,10 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer) seg->result); goto out; case WA_SEG_ABORTED: - dev_dbg(dev, "xfer %p ID %08X#%u ABORTED: result %d\n", - xfer, wa_xfer_id(xfer), seg->index, - urb->status); - xfer->result = urb->status; + xfer->result = seg->result; + dev_dbg(dev, "xfer %p ID %08X#%u: ABORTED result %zu(0x%08zX)\n", + xfer, wa_xfer_id(xfer), seg->index, seg->result, + seg->result); goto out; default: dev_warn(dev, "xfer %p ID %08X#%u: is_done bad state %d\n", @@ -1568,7 +1568,8 @@ static int wa_urb_enqueue_b(struct wa_xfer *xfer) wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); if (wusb_dev == NULL) { mutex_unlock(&wusbhc->mutex); - pr_err("%s: error wusb dev gone\n", __func__); + dev_err(&(urb->dev->dev), "%s: error wusb dev gone\n", + __func__); goto error_dev_gone; } mutex_unlock(&wusbhc->mutex); @@ -1577,18 +1578,18 @@ static int wa_urb_enqueue_b(struct wa_xfer *xfer) xfer->wusb_dev = wusb_dev; result = urb->status; if (urb->status != -EINPROGRESS) { - pr_err("%s: error_dequeued\n", __func__); + dev_err(&(urb->dev->dev), "%s: error_dequeued\n", __func__); goto error_dequeued; } result = __wa_xfer_setup(xfer, urb); if (result < 0) { - pr_err("%s: error_xfer_setup\n", __func__); + dev_err(&(urb->dev->dev), "%s: error_xfer_setup\n", __func__); goto error_xfer_setup; } result = __wa_xfer_submit(xfer); if (result < 0) { - pr_err("%s: error_xfer_submit\n", __func__); + dev_err(&(urb->dev->dev), "%s: error_xfer_submit\n", __func__); goto error_xfer_submit; } spin_unlock_irqrestore(&xfer->lock, flags); @@ -1844,8 +1845,8 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status) pr_debug("%s: DEQUEUE xfer id 0x%08X\n", __func__, wa_xfer_id(xfer)); rpipe = xfer->ep->hcpriv; if (rpipe == NULL) { - pr_debug("%s: xfer id 0x%08X has no RPIPE. %s", - __func__, wa_xfer_id(xfer), + pr_debug("%s: xfer %p id 0x%08X has no RPIPE. %s", + __func__, xfer, wa_xfer_id(xfer), "Probably already aborted.\n" ); goto out_unlock; } -- cgit v1.2.3 From e05a1fd9468bc99bf67bd81601d46d84d93c21c8 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 25 Nov 2013 16:17:18 -0600 Subject: usb: wusbcore: return -ENOENT for unlinked URBs. Return -ENOENT for unlinked URBs. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 3220c62de317..a88b8c68ce78 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -1848,6 +1848,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status) pr_debug("%s: xfer %p id 0x%08X has no RPIPE. %s", __func__, xfer, wa_xfer_id(xfer), "Probably already aborted.\n" ); + result = -ENOENT; goto out_unlock; } /* Check the delayed list -> if there, release and complete */ @@ -1878,6 +1879,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status) * segments will be completed in the DTI interrupt. */ seg->status = WA_SEG_ABORTED; + seg->result = -ENOENT; spin_lock_irqsave(&rpipe->seg_lock, flags2); list_del(&seg->list_node); xfer->segs_done++; @@ -1917,12 +1919,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status) wa_xfer_completion(xfer); if (rpipe_ready) wa_xfer_delayed_run(rpipe); - return 0; + return result; out_unlock: spin_unlock_irqrestore(&xfer->lock, flags); out: - return 0; + return result; dequeue_delayed: list_del_init(&xfer->list_node); @@ -1958,7 +1960,7 @@ static int wa_xfer_status_to_errno(u8 status) [WA_XFER_STATUS_NOT_FOUND] = 0, [WA_XFER_STATUS_INSUFFICIENT_RESOURCE] = -ENOMEM, [WA_XFER_STATUS_TRANSACTION_ERROR] = -EILSEQ, - [WA_XFER_STATUS_ABORTED] = -EINTR, + [WA_XFER_STATUS_ABORTED] = -ENOENT, [WA_XFER_STATUS_RPIPE_NOT_READY] = EINVAL, [WA_XFER_INVALID_FORMAT] = EINVAL, [WA_XFER_UNEXPECTED_SEGMENT_NUMBER] = EINVAL, -- cgit v1.2.3 From e5fc70d5ccc3d005bb038c0275ffdf57a34b1496 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 26 Nov 2013 12:44:13 +0800 Subject: USB: storage: use sg_miter_* APIs to access scsi buffer We have sg_miter_* APIs for accessing scsi sg buffer, so use them to make code clean and bug free. Cc: Matthew Dharm Cc: Alan Stern Cc: Greg Kroah-Hartman Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/protocol.c | 80 ++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 5dfb4c36a1b0..f54e5fea9230 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -135,69 +135,41 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr, unsigned int *offset, enum xfer_buf_dir dir) { - unsigned int cnt; + unsigned int cnt = 0; struct scatterlist *sg = *sgptr; + struct sg_mapping_iter miter; + unsigned int nents = scsi_sg_count(srb); - /* We have to go through the list one entry - * at a time. Each s-g entry contains some number of pages, and - * each page has to be kmap()'ed separately. If the page is already - * in kernel-addressable memory then kmap() will return its address. - * If the page is not directly accessible -- such as a user buffer - * located in high memory -- then kmap() will map it to a temporary - * position in the kernel's virtual address space. - */ - - if (!sg) + if (sg) + nents = sg_nents(sg); + else sg = scsi_sglist(srb); - /* This loop handles a single s-g list entry, which may - * include multiple pages. Find the initial page structure - * and the starting offset within the page, and update - * the *offset and **sgptr values for the next loop. - */ - cnt = 0; - while (cnt < buflen && sg) { - struct page *page = sg_page(sg) + - ((sg->offset + *offset) >> PAGE_SHIFT); - unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1); - unsigned int sglen = sg->length - *offset; - - if (sglen > buflen - cnt) { - - /* Transfer ends within this s-g entry */ - sglen = buflen - cnt; - *offset += sglen; - } else { + sg_miter_start(&miter, sg, nents, dir == FROM_XFER_BUF ? + SG_MITER_FROM_SG: SG_MITER_TO_SG); - /* Transfer continues to next s-g entry */ - *offset = 0; - sg = sg_next(sg); - } + if (!sg_miter_skip(&miter, *offset)) + return cnt; + + while (sg_miter_next(&miter) && cnt < buflen) { + unsigned int len = min(miter.length, buflen - cnt); + + if (dir == FROM_XFER_BUF) + memcpy(buffer + cnt, miter.addr, len); + else + memcpy(miter.addr, buffer + cnt, len); - /* Transfer the data for all the pages in this - * s-g entry. For each page: call kmap(), do the - * transfer, and call kunmap() immediately after. */ - while (sglen > 0) { - unsigned int plen = min(sglen, (unsigned int) - PAGE_SIZE - poff); - unsigned char *ptr = kmap(page); - - if (dir == TO_XFER_BUF) - memcpy(ptr + poff, buffer + cnt, plen); - else - memcpy(buffer + cnt, ptr + poff, plen); - kunmap(page); - - /* Start at the beginning of the next page */ - poff = 0; - ++page; - cnt += plen; - sglen -= plen; + if (*offset + len < miter.piter.sg->length) { + *offset += len; + *sgptr = miter.piter.sg; + } else { + *offset = 0; + *sgptr = sg_next(miter.piter.sg); } + cnt += len; } - *sgptr = sg; + sg_miter_stop(&miter); - /* Return the amount actually transferred */ return cnt; } EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf); -- cgit v1.2.3 From 103e127d1f8f985e8a662da6537ebc5e08902ee3 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Wed, 4 Dec 2013 01:42:21 +0400 Subject: usb: hcd: Remove USB phy if needed This adds remove_phy flag to the HCD structure. If the flag is set and if hcd->phy is valid, the phy is shutdown and released whenever usb_add_hcd fails or usb_hcd_remove is called. This can be used by the HCD drivers to auto-remove the external USB phy when it is no longer needed. Signed-off-by: Valentine Barshak Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 14 +++++++++++++- include/linux/usb/hcd.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6bffb8c87bc9..7527c8e4ec64 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -44,6 +44,7 @@ #include #include +#include #include "usb.h" @@ -2603,7 +2604,7 @@ int usb_add_hcd(struct usb_hcd *hcd, */ if ((retval = hcd_buffer_create(hcd)) != 0) { dev_dbg(hcd->self.controller, "pool alloc failed\n"); - return retval; + goto err_remove_phy; } if ((retval = usb_register_bus(&hcd->self)) < 0) @@ -2734,6 +2735,12 @@ err_allocate_root_hub: usb_deregister_bus(&hcd->self); err_register_bus: hcd_buffer_destroy(hcd); +err_remove_phy: + if (hcd->remove_phy && hcd->phy) { + usb_phy_shutdown(hcd->phy); + usb_put_phy(hcd->phy); + hcd->phy = NULL; + } return retval; } EXPORT_SYMBOL_GPL(usb_add_hcd); @@ -2806,6 +2813,11 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_put_dev(hcd->self.root_hub); usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); + if (hcd->remove_phy && hcd->phy) { + usb_phy_shutdown(hcd->phy); + usb_put_phy(hcd->phy); + hcd->phy = NULL; + } } EXPORT_SYMBOL_GPL(usb_remove_hcd); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index b8aba196f7f1..758ce80d085f 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -134,6 +134,7 @@ struct usb_hcd { unsigned rh_registered:1;/* is root hub registered? */ unsigned rh_pollable:1; /* may we poll the root hub? */ unsigned msix_enabled:1; /* driver has MSI-X enabled? */ + unsigned remove_phy:1; /* auto-remove USB phy */ /* The next flag is a stopgap, to be removed when all the HCDs * support the new root-hub polling mechanism. */ -- cgit v1.2.3 From 1ae5799ef63176cc75ec10e545cb65f620a82747 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Wed, 4 Dec 2013 01:42:22 +0400 Subject: usb: hcd: Initialize USB phy if needed This adds external USB phy support to USB HCD driver that allows to find and initialize external USB phy, bound to the HCD, when the HCD is added. The usb_add_hcd function returns -EPROBE_DEFER if the USB phy, bound to the HCD, is not ready. If no USB phy is bound, the HCD is initialized as usual. Signed-off-by: Valentine Barshak Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 7527c8e4ec64..d3a9bcde53c3 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2589,6 +2589,24 @@ int usb_add_hcd(struct usb_hcd *hcd, int retval; struct usb_device *rhdev; + if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->phy) { + struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0); + + if (IS_ERR(phy)) { + retval = PTR_ERR(phy); + if (retval == -EPROBE_DEFER) + return retval; + } else { + retval = usb_phy_init(phy); + if (retval) { + usb_put_phy(phy); + return retval; + } + hcd->phy = phy; + hcd->remove_phy = 1; + } + } + dev_info(hcd->self.controller, "%s\n", hcd->product_desc); /* Keep old behaviour if authorized_default is not in [0, 1]. */ -- cgit v1.2.3 From 0d4e5bee27dc2f3aa2b0a8a2e0313bfcaf4c5389 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 5 Dec 2013 19:21:42 +0800 Subject: uwb: Use dev_is_pci() to check whether it is pci device Use PCI standard marco dev_is_pci() instead of directly compare pci_bus_type to check whether it is pci device. Signed-off-by: Yijing Wang Signed-off-by: Greg Kroah-Hartman --- drivers/uwb/umc-bus.c | 2 +- include/linux/uwb/umc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index e3ed6ff6a481..88a290f57ea0 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c @@ -85,7 +85,7 @@ int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc) const struct pci_device_id *id_table = umc_drv->match_data; struct pci_dev *pci; - if (umc->dev.parent->bus != &pci_bus_type) + if (!dev_is_pci(umc->dev.parent)) return 0; pci = to_pci_dev(umc->dev.parent); diff --git a/include/linux/uwb/umc.h b/include/linux/uwb/umc.h index 891d1d5f3947..ba82f03d8287 100644 --- a/include/linux/uwb/umc.h +++ b/include/linux/uwb/umc.h @@ -143,7 +143,7 @@ int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc); static inline struct pci_dev *umc_parent_pci_dev(struct umc_dev *umc_dev) { struct pci_dev *pci_dev = NULL; - if (umc_dev->dev.parent->bus == &pci_bus_type) + if (dev_is_pci(umc_dev->dev.parent)) pci_dev = to_pci_dev(umc_dev->dev.parent); return pci_dev; } -- cgit v1.2.3 From e10e6f433f6f737f29dc1cea83e9a03095ac5c09 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 5 Dec 2013 19:21:32 +0800 Subject: usb: Use dev_is_pci() to check whether it is pci device Use PCI standard marco dev_is_pci() instead of directly compare pci_bus_type to check whether it is pci device. Signed-off-by: Yijing Wang Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 9269782a7627..524cbf26d992 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -818,7 +818,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) #ifdef CONFIG_PCI /* EHCI 0.96 and later may have "extended capabilities" */ - if (hcd->self.controller->bus == &pci_bus_type) { + if (dev_is_pci(hcd->self.controller)) { struct pci_dev *pdev; u32 offset, cap, cap2; unsigned count = 256/4; -- cgit v1.2.3 From 9058bdc3a8fbfe1a528019466df62635ef1f7a94 Mon Sep 17 00:00:00 2001 From: Seth Archer Brown Date: Thu, 5 Dec 2013 22:59:23 -0500 Subject: Usb: atm: usbatm: fixed a pointer variable format issue Fixed a pointer variable format issue. Signed-off-by: Seth Archer Brown Acked-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 25a7bfcf666c..dada0146cd7f 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -170,9 +170,9 @@ struct usbatm_control { static void usbatm_atm_dev_close(struct atm_dev *atm_dev); static int usbatm_atm_open(struct atm_vcc *vcc); static void usbatm_atm_close(struct atm_vcc *vcc); -static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg); +static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg); static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); -static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page); +static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page); static struct atmdev_ops usbatm_atm_devops = { .dev_close = usbatm_atm_dev_close, @@ -739,7 +739,7 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev) usbatm_put_instance(instance); /* taken in usbatm_atm_init */ } -static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page) +static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page) { struct usbatm_data *instance = atm_dev->dev_data; int left = *pos; @@ -895,7 +895,7 @@ static void usbatm_atm_close(struct atm_vcc *vcc) } static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, - void __user * arg) + void __user *arg) { struct usbatm_data *instance = atm_dev->dev_data; -- cgit v1.2.3 From aeb2c1210d71c00a4b59d343b0a7df6b1059eb89 Mon Sep 17 00:00:00 2001 From: Chris Ruehl Date: Fri, 6 Dec 2013 16:35:12 +0800 Subject: usb: chipidea: Reallocate regmap only if lpm is detected The regmap only needs to reallocate if the hw_read on the CAP register shows lpm is used. Therefore the if() statement check the change. Signed-off-by: Chris Ruehl Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 5d8981c5235e..50754073fae0 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -208,7 +208,8 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >> __ffs(HCCPARAMS_LEN); ci->hw_bank.lpm = reg; - hw_alloc_regmap(ci, !!reg); + if (reg) + hw_alloc_regmap(ci, !!reg); ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs; ci->hw_bank.size += OP_LAST; ci->hw_bank.size /= sizeof(u32); -- cgit v1.2.3 From 73de93440186c595a031046e266f6caaac106aa0 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 6 Dec 2013 16:35:13 +0800 Subject: usb: chipidea: imx: avoid unnecessary probe defer every time The ci_hdrc_imx's probe needs usbmisc_imx to be loadded beforehand, so it is better we load usbmisc_imx first. Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index a99d980454a6..7345d2115af2 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),) endif ifneq ($(CONFIG_OF),) - obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o + obj-$(CONFIG_USB_CHIPIDEA) += usbmisc_imx.o ci_hdrc_imx.o endif -- cgit v1.2.3 From 9f90e111a6abc472ca9aed9b4a4d27d9a22ecbd3 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 6 Dec 2013 16:35:14 +0800 Subject: usb: chipidea: usbmisc: Add support for i.MX27/i.MX31 CPUs This adds i.MX27 and i.MX31 as the next user of the usbmisc driver. Tested-by: Chris Ruehl Signed-off-by: Alexander Shiyan Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/usbmisc_imx.c | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 8a1094b1182f..4381c5a604d6 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -21,6 +21,10 @@ #define MX25_USB_PHY_CTRL_OFFSET 0x08 #define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23) +#define MX27_H1_PM_BIT BIT(8) +#define MX27_H2_PM_BIT BIT(16) +#define MX27_OTG_PM_BIT BIT(24) + #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08 #define MX53_USB_UH2_CTRL_OFFSET 0x14 #define MX53_USB_UH3_CTRL_OFFSET 0x18 @@ -68,6 +72,36 @@ static int usbmisc_imx25_post(struct imx_usbmisc_data *data) return 0; } +static int usbmisc_imx27_init(struct imx_usbmisc_data *data) +{ + unsigned long flags; + u32 val; + + switch (data->index) { + case 0: + val = MX27_OTG_PM_BIT; + break; + case 1: + val = MX27_H1_PM_BIT; + break; + case 2: + val = MX27_H2_PM_BIT; + break; + default: + return -EINVAL; + }; + + spin_lock_irqsave(&usbmisc->lock, flags); + if (data->disable_oc) + val = readl(usbmisc->base) | val; + else + val = readl(usbmisc->base) & ~val; + writel(val, usbmisc->base); + spin_unlock_irqrestore(&usbmisc->lock, flags); + + return 0; +} + static int usbmisc_imx53_init(struct imx_usbmisc_data *data) { void __iomem *reg = NULL; @@ -128,6 +162,10 @@ static const struct usbmisc_ops imx25_usbmisc_ops = { .post = usbmisc_imx25_post, }; +static const struct usbmisc_ops imx27_usbmisc_ops = { + .init = usbmisc_imx27_init, +}; + static const struct usbmisc_ops imx53_usbmisc_ops = { .init = usbmisc_imx53_init, }; @@ -161,6 +199,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { .compatible = "fsl,imx25-usbmisc", .data = &imx25_usbmisc_ops, }, + { + .compatible = "fsl,imx27-usbmisc", + .data = &imx27_usbmisc_ops, + }, { .compatible = "fsl,imx53-usbmisc", .data = &imx53_usbmisc_ops, -- cgit v1.2.3 From c4962e03f4bbad63c8356e9466db6e0df4144ed9 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 6 Dec 2013 16:35:15 +0800 Subject: usb: chipidea: usbmisc: Add support for i.MX51 CPU This adds i.MX51 as the next user of the usbmisc driver. Functionality is similar to i.MX53, so at this stage simply reuse existing i.MX53 calls. Signed-off-by: Alexander Shiyan Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/usbmisc_imx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 4381c5a604d6..cd061abe3507 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -203,6 +203,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { .compatible = "fsl,imx27-usbmisc", .data = &imx27_usbmisc_ops, }, + { + .compatible = "fsl,imx51-usbmisc", + .data = &imx53_usbmisc_ops, + }, { .compatible = "fsl,imx53-usbmisc", .data = &imx53_usbmisc_ops, -- cgit v1.2.3 From 3c9740a117d40a74412775b5d3fe2b88a7635a0e Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 5 Nov 2013 10:46:02 +0800 Subject: usb: hcd: move controller wakeup setting initialization to individual driver Individual controller driver has different requirement for wakeup setting, so move it from core to itself. In order to align with current etting the default wakeup setting is enabled (except for chipidea host). Pass compile test with below commands: make O=outout/all allmodconfig make -j$CPU_NUM O=outout/all drivers/usb Signed-off-by: Peter Chen Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 2 ++ drivers/staging/octeon-usb/octeon-hcd.c | 1 + drivers/staging/ozwpan/ozhcd.c | 2 ++ drivers/usb/c67x00/c67x00-hcd.c | 2 ++ drivers/usb/core/hcd-pci.c | 1 + drivers/usb/core/hcd.c | 6 ------ drivers/usb/host/ehci-atmel.c | 1 + drivers/usb/host/ehci-exynos.c | 1 + drivers/usb/host/ehci-fsl.c | 1 + drivers/usb/host/ehci-grlib.c | 1 + drivers/usb/host/ehci-mv.c | 1 + drivers/usb/host/ehci-mxc.c | 1 + drivers/usb/host/ehci-octeon.c | 1 + drivers/usb/host/ehci-omap.c | 1 + drivers/usb/host/ehci-orion.c | 1 + drivers/usb/host/ehci-platform.c | 1 + drivers/usb/host/ehci-pmcmsp.c | 4 +++- drivers/usb/host/ehci-ppc-of.c | 1 + drivers/usb/host/ehci-ps3.c | 1 + drivers/usb/host/ehci-sead3.c | 1 + drivers/usb/host/ehci-sh.c | 1 + drivers/usb/host/ehci-spear.c | 1 + drivers/usb/host/ehci-tegra.c | 1 + drivers/usb/host/ehci-tilegx.c | 1 + drivers/usb/host/ehci-w90x900.c | 1 + drivers/usb/host/ehci-xilinx-of.c | 4 +++- drivers/usb/host/fhci-hcd.c | 2 ++ drivers/usb/host/fotg210-hcd.c | 1 + drivers/usb/host/fusbh200-hcd.c | 1 + drivers/usb/host/hwa-hc.c | 1 + drivers/usb/host/imx21-hcd.c | 1 + drivers/usb/host/isp116x-hcd.c | 2 ++ drivers/usb/host/isp1362-hcd.c | 2 ++ drivers/usb/host/isp1760-hcd.c | 1 + drivers/usb/host/ohci-at91.c | 4 +++- drivers/usb/host/ohci-da8xx.c | 2 ++ drivers/usb/host/ohci-exynos.c | 1 + drivers/usb/host/ohci-jz4740.c | 1 + drivers/usb/host/ohci-nxp.c | 4 +++- drivers/usb/host/ohci-octeon.c | 2 ++ drivers/usb/host/ohci-omap.c | 1 + drivers/usb/host/ohci-omap3.c | 1 + drivers/usb/host/ohci-platform.c | 2 ++ drivers/usb/host/ohci-ppc-of.c | 4 +++- drivers/usb/host/ohci-ps3.c | 1 + drivers/usb/host/ohci-pxa27x.c | 4 +++- drivers/usb/host/ohci-s3c2410.c | 1 + drivers/usb/host/ohci-sa1111.c | 4 +++- drivers/usb/host/ohci-sm501.c | 1 + drivers/usb/host/ohci-spear.c | 4 +++- drivers/usb/host/ohci-tilegx.c | 1 + drivers/usb/host/ohci-tmio.c | 1 + drivers/usb/host/oxu210hp-hcd.c | 1 + drivers/usb/host/r8a66597-hcd.c | 1 + drivers/usb/host/sl811-hcd.c | 2 ++ drivers/usb/host/u132-hcd.c | 1 + drivers/usb/host/uhci-grlib.c | 1 + drivers/usb/host/uhci-platform.c | 1 + drivers/usb/host/whci/hcd.c | 1 + drivers/usb/host/xhci-plat.c | 1 + drivers/usb/musb/musb_host.c | 1 + drivers/usb/phy/phy-msm-usb.c | 1 + drivers/usb/phy/phy-mv-usb.c | 6 ++++-- drivers/usb/renesas_usbhs/mod_host.c | 1 + 64 files changed, 92 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 3cfd2d5152c9..078cd9168b1a 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2921,6 +2921,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, if (retval < 0) goto error3; + device_wakeup_enable(hcd->self.controller); + dwc2_hcd_dump_state(hsotg); dwc2_enable_global_interrupts(hsotg); diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index d118952c0a74..47e0a91238a1 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -3498,6 +3498,7 @@ static int octeon_usb_driver_probe(struct device *dev) kfree(hcd); return -1; } + device_wakeup_enable(hcd->self.controller); dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c index d9c43c3282e7..efaf26f734c3 100644 --- a/drivers/staging/ozwpan/ozhcd.c +++ b/drivers/staging/ozwpan/ozhcd.c @@ -2270,6 +2270,8 @@ static int oz_plat_probe(struct platform_device *dev) usb_put_hcd(hcd); return -1; } + device_wakeup_enable(hcd->self.controller); + spin_lock_bh(&g_hcdlock); g_ozhcd = ozhcd; spin_unlock_bh(&g_hcdlock); diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c index 75e47b860a53..20ec4eee1ac8 100644 --- a/drivers/usb/c67x00/c67x00-hcd.c +++ b/drivers/usb/c67x00/c67x00-hcd.c @@ -384,6 +384,8 @@ int c67x00_hcd_probe(struct c67x00_sie *sie) goto err2; } + device_wakeup_enable(hcd->self.controller); + spin_lock_irqsave(&sie->lock, flags); sie->private_data = c67x00; sie->irq = c67x00_hcd_irq; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index dfe9d0f22978..d59d99347d54 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -282,6 +282,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (retval != 0) goto unmap_registers; + device_wakeup_enable(hcd->self.controller); if (pci_dev_run_wake(dev)) pm_runtime_put_noidle(&dev->dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d3a9bcde53c3..6297c9e50de2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2712,12 +2712,6 @@ int usb_add_hcd(struct usb_hcd *hcd, if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) usb_hcd_poll_rh_status(hcd); - /* - * Host controllers don't generate their own wakeup requests; - * they only forward requests from the root hub. Therefore - * controllers should always be enabled for remote wakeup. - */ - device_wakeup_enable(hcd->self.controller); return retval; error_create_attr_group: diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 284f8417eae5..ec9f7b75d497 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -153,6 +153,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval) goto fail_add_hcd; + device_wakeup_enable(hcd->self.controller); return retval; diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index e97c198e052f..d1d8c47777c5 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -166,6 +166,7 @@ skip_phy: dev_err(&pdev->dev, "Failed to add USB HCD\n"); goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); platform_set_drvdata(pdev, hcd); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 87a7426a44f4..854a68fa59a6 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -138,6 +138,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval != 0) goto err4; + device_wakeup_enable(hcd->self.controller); #ifdef CONFIG_USB_OTG if (pdata->operating_mode == FSL_USB2_DR_OTG) { diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index b52a66ce92e8..054792c56271 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -140,6 +140,7 @@ static int ehci_hcd_grlib_probe(struct platform_device *op) if (rv) goto err_ioremap; + device_wakeup_enable(hcd->self.controller); return 0; err_ioremap: diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 6e8afcaa8ff0..bd61612a7251 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -257,6 +257,7 @@ static int mv_ehci_probe(struct platform_device *pdev) "failed to add hcd with err %d\n", retval); goto err_set_vbus; } + device_wakeup_enable(hcd->self.controller); } if (pdata->private_init) diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 0528dc4526c8..dbe5e4eea08d 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -155,6 +155,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (ret) goto err_add; + device_wakeup_enable(hcd->self.controller); return 0; err_add: diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index 4c528b2c033a..c4ad7ed6b3f8 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c @@ -158,6 +158,7 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); goto err3; } + device_wakeup_enable(hcd->self.controller); platform_set_drvdata(pdev, hcd); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 6fa82d6b7661..a24720beb39d 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -215,6 +215,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) dev_err(dev, "failed to add hcd with err %d\n", ret); goto err_pm_runtime; } + device_wakeup_enable(hcd->self.controller); /* * Bring PHYs out of reset for non PHY modes. diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 2ba76730e650..aa8b92bf5361 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -252,6 +252,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) if (err) goto err4; + device_wakeup_enable(hcd->self.controller); return 0; err4: diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 7f30b7168d5a..01536cfd361d 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -132,6 +132,7 @@ static int ehci_platform_probe(struct platform_device *dev) if (err) goto err_put_hcd; + device_wakeup_enable(hcd->self.controller); platform_set_drvdata(dev, hcd); return err; diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 893b707f0000..af3974a5e7c2 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -210,8 +210,10 @@ int usb_hcd_msp_probe(const struct hc_driver *driver, retval = usb_add_hcd(hcd, res->start, IRQF_SHARED); - if (retval == 0) + if (retval == 0) { + device_wakeup_enable(hcd->self.controller); return 0; + } usb_remove_hcd(hcd); err3: diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 875d2fcc9e0e..b0965eb6c0db 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -169,6 +169,7 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op) if (rv) goto err_ioremap; + device_wakeup_enable(hcd->self.controller); return 0; err_ioremap: diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 8188542ba17e..7934ff9b35e1 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -189,6 +189,7 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev) goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); return result; fail_add_hcd: diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index 8a734498079b..cf1267673868 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -126,6 +126,7 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev) IRQF_SHARED); if (ret == 0) { platform_set_drvdata(pdev, hcd); + device_wakeup_enable(hcd->self.controller); return ret; } diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index dc899eb2b861..9b9b9f5b016e 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -151,6 +151,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to add hcd"); goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); priv->hcd = hcd; platform_set_drvdata(pdev, priv); diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index ee6f9ffaa0e7..8bd915b2ae8c 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -130,6 +130,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) if (retval) goto err_stop_ehci; + device_wakeup_enable(hcd->self.controller); return retval; err_stop_ehci: diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index b9fd0396011e..a8f4471dae7b 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -455,6 +455,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to add USB HCD\n"); goto cleanup_otg_set_host; } + device_wakeup_enable(hcd->self.controller); return err; diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c index 67026ffbf9a8..f3713d32c9a1 100644 --- a/drivers/usb/host/ehci-tilegx.c +++ b/drivers/usb/host/ehci-tilegx.c @@ -170,6 +170,7 @@ static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev) ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); if (ret == 0) { platform_set_drvdata(pdev, hcd); + device_wakeup_enable(hcd->self.controller); return ret; } diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index cdad8438c02b..12c1a563c3f2 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -94,6 +94,7 @@ static int usb_w90x900_probe(const struct hc_driver *driver, if (retval != 0) goto err4; + device_wakeup_enable(hcd->self.controller); return retval; err4: iounmap(hcd->regs); diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 95979f9f4381..3cd2efa4e678 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -191,8 +191,10 @@ static int ehci_hcd_xilinx_of_probe(struct platform_device *op) ehci->caps = hcd->regs + 0x100; rv = usb_add_hcd(hcd, irq, 0); - if (rv == 0) + if (rv == 0) { + device_wakeup_enable(hcd->self.controller); return 0; + } err_irq: usb_put_hcd(hcd); diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 0551c0af0fd1..1cf68eaf2ed8 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -754,6 +754,8 @@ static int of_fhci_probe(struct platform_device *ofdev) if (ret < 0) goto err_add_hcd; + device_wakeup_enable(hcd->self.controller); + fhci_dfs_create(fhci); return 0; diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 97d6939189d6..98a89d16cc3e 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -5889,6 +5889,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev) dev_err(dev, "failed to add hcd with err %d\n", retval); goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); return retval; diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c index 9ea85b662a04..ba9499060f63 100644 --- a/drivers/usb/host/fusbh200-hcd.c +++ b/drivers/usb/host/fusbh200-hcd.c @@ -5798,6 +5798,7 @@ static int fusbh200_hcd_probe(struct platform_device *pdev) dev_err(dev, "failed to add hcd with err %d\n", retval); goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); return retval; diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index a4ec9e6c0f86..7fd3f9bd7b83 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -791,6 +791,7 @@ static int hwahc_probe(struct usb_interface *usb_iface, dev_err(dev, "Cannot add HCD: %d\n", result); goto error_add_hcd; } + device_wakeup_enable(usb_hcd->self.controller); result = wusbhc_b_create(&hwahc->wusbhc); if (result < 0) { dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 0122624c7ec1..207bad99301f 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1910,6 +1910,7 @@ static int imx21_probe(struct platform_device *pdev) dev_err(imx21->dev, "usb_add_hcd() returned %d\n", ret); goto failed_add_hcd; } + device_wakeup_enable(hcd->self.controller); return 0; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 7722ec658b87..2740f65936bd 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1645,6 +1645,8 @@ static int isp116x_probe(struct platform_device *pdev) if (ret) goto err6; + device_wakeup_enable(hcd->self.controller); + ret = create_debug_file(isp116x); if (ret) { ERR("Couldn't create debugfs entry\n"); diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index cd94b108b57f..34645ae9313d 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2746,6 +2746,8 @@ static int isp1362_probe(struct platform_device *pdev) retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_SHARED); if (retval != 0) goto err6; + device_wakeup_enable(hcd->self.controller); + pr_info("%s, irq %d\n", hcd->product_desc, irq); create_debug_file(isp1362_hcd); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 2facee53eab1..51a0ae9cdd1d 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2250,6 +2250,7 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, ret = usb_add_hcd(hcd, irq, irqflags); if (ret) goto err_unmap; + device_wakeup_enable(hcd->self.controller); return hcd; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index cc9462f19fa5..29d2093e3cee 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -200,8 +200,10 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, at91_start_hc(pdev); retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); - if (retval == 0) + if (retval == 0) { + device_wakeup_enable(hcd->self.controller); return retval; + } /* Error handling */ at91_stop_hc(pdev); diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 71dbd85e9a8d..f0fe0d26314d 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -348,6 +348,8 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, if (error) goto err4; + device_wakeup_enable(hcd->self.controller); + if (hub->ocic_notify) { error = hub->ocic_notify(ohci_da8xx_ocic_handler); if (!error) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 9897d70e4c15..68588d8a09bb 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -146,6 +146,7 @@ skip_phy: dev_err(&pdev->dev, "Failed to add USB HCD\n"); goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); return 0; fail_add_hcd: diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index d4ef53990d73..efe31f3ab4ea 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c @@ -217,6 +217,7 @@ static int jz4740_ohci_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret); goto err_disable; } + device_wakeup_enable(hcd->self.controller); return 0; diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index e99db8a6d55f..719f28e5e3ac 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -274,8 +274,10 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev) dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); ret = usb_add_hcd(hcd, irq, 0); - if (ret == 0) + if (ret == 0) { + device_wakeup_enable(hcd->self.controller); return ret; + } ohci_nxp_stop_hc(); fail_resource: diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c index 6c16dcef15c6..49b220dc2f9b 100644 --- a/drivers/usb/host/ohci-octeon.c +++ b/drivers/usb/host/ohci-octeon.c @@ -171,6 +171,8 @@ static int ohci_octeon_drv_probe(struct platform_device *pdev) goto err3; } + device_wakeup_enable(hcd->self.controller); + platform_set_drvdata(pdev, hcd); return 0; diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index f253214741ba..a44a4fede1c4 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -367,6 +367,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, if (retval) goto err3; + device_wakeup_enable(hcd->self.controller); return 0; err3: iounmap(hcd->regs); diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 21457417a856..ec15aebe8786 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -130,6 +130,7 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) dev_dbg(dev, "failed to add hcd with err %d\n", ret); goto err_add_hcd; } + device_wakeup_enable(hcd->self.controller); return 0; diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index f351ff5b171f..68f674cd095f 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -108,6 +108,8 @@ static int ohci_platform_probe(struct platform_device *dev) if (err) goto err_put_hcd; + device_wakeup_enable(hcd->self.controller); + platform_set_drvdata(dev, hcd); return err; diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 81f3eba215c1..83e33d464082 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -147,8 +147,10 @@ static int ohci_hcd_ppc_of_probe(struct platform_device *op) ohci_hcd_init(ohci); rv = usb_add_hcd(hcd, irq, 0); - if (rv == 0) + if (rv == 0) { + device_wakeup_enable(hcd->self.controller); return 0; + } /* by now, 440epx is known to show usb_23 erratum */ np = of_find_compatible_node(NULL, NULL, "ibm,usb-ehci-440epx"); diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 7d35cd9e2862..71d8bc4c27f6 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -173,6 +173,7 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev) goto fail_add_hcd; } + device_wakeup_enable(hcd->self.controller); return result; fail_add_hcd: diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e89ac4d4b87e..5343ecfdddfa 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -442,8 +442,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device ohci->num_ports = 3; retval = usb_add_hcd(hcd, irq, 0); - if (retval == 0) + if (retval == 0) { + device_wakeup_enable(hcd->self.controller); return retval; + } pxa27x_stop_hc(pxa_ohci, &pdev->dev); err3: diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 83cd1dcd5145..ff7c8f1c48fb 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -395,6 +395,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, if (retval != 0) goto err_ioremap; + device_wakeup_enable(hcd->self.controller); return 0; err_ioremap: diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index aa9e127bbe71..2ac266d692a2 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -211,8 +211,10 @@ static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev) goto err2; ret = usb_add_hcd(hcd, dev->irq[1], 0); - if (ret == 0) + if (ret == 0) { + device_wakeup_enable(hcd->self.controller); return ret; + } sa1111_stop_hc(dev); err2: diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 2a5de5fecd8f..4e81c804c73e 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -168,6 +168,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval) goto err5; + device_wakeup_enable(hcd->self.controller); /* enable power and unmask interrupts */ diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index e418c192e23a..4cb98abc0bef 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -103,8 +103,10 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) ohci = hcd_to_ohci(hcd); retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); - if (retval == 0) + if (retval == 0) { + device_wakeup_enable(hcd->self.controller); return retval; + } clk_disable_unprepare(sohci_p->clk); err_put_hcd: diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c index 22540ab71f55..0b183e0b0a8a 100644 --- a/drivers/usb/host/ohci-tilegx.c +++ b/drivers/usb/host/ohci-tilegx.c @@ -159,6 +159,7 @@ static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); if (ret == 0) { platform_set_drvdata(pdev, hcd); + device_wakeup_enable(hcd->self.controller); return ret; } diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index ecb09a5ada9c..9c44093b8e1e 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -250,6 +250,7 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev) if (ret) goto err_add_hcd; + device_wakeup_enable(hcd->self.controller); if (ret == 0) return ret; diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 4a05148ee79b..778eeaf2dd14 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -3751,6 +3751,7 @@ static struct usb_hcd *oxu_create(struct platform_device *pdev, if (ret < 0) return ERR_PTR(ret); + device_wakeup_enable(hcd->self.controller); return hcd; } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 3bddfcfafb79..47b1322c7a77 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2514,6 +2514,7 @@ static int r8a66597_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to add hcd\n"); goto clean_up3; } + device_wakeup_enable(hcd->self.controller); return 0; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 79620c39217e..0115e7f51d94 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1732,6 +1732,8 @@ sl811h_probe(struct platform_device *dev) if (retval != 0) goto err6; + device_wakeup_enable(hcd->self.controller); + create_debug_file(sl811); return retval; diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 46236e9fc87f..c0671750671f 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3133,6 +3133,7 @@ static int u132_probe(struct platform_device *pdev) u132_u132_put_kref(u132); return retval; } else { + device_wakeup_enable(hcd->self.controller); u132_monitor_queue_work(u132, 100); return 0; } diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c index 53c23ff7d685..ab25dc397e8b 100644 --- a/drivers/usb/host/uhci-grlib.c +++ b/drivers/usb/host/uhci-grlib.c @@ -141,6 +141,7 @@ static int uhci_hcd_grlib_probe(struct platform_device *op) if (rv) goto err_uhci; + device_wakeup_enable(hcd->self.controller); return 0; err_uhci: diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index 3003fefaa964..44e6c9da8892 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -108,6 +108,7 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev) if (ret) goto err_uhci; + device_wakeup_enable(hcd->self.controller); return 0; err_uhci: diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 1b0888f8da9a..d7b363a418de 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -293,6 +293,7 @@ static int whc_probe(struct umc_dev *umc) dev_err(dev, "cannot add HCD: %d\n", ret); goto error_usb_add_hcd; } + device_wakeup_enable(usb_hcd->self.controller); ret = wusbhc_b_create(wusbhc); if (ret) { diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index d9c169f470d3..9d29aa1b1bc8 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -139,6 +139,7 @@ static int xhci_plat_probe(struct platform_device *pdev) ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto unmap_registers; + device_wakeup_enable(hcd->self.controller); /* USB 2.0 roothub is stored in the platform_device now. */ hcd = platform_get_drvdata(pdev); diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 6582a20bec05..e2083757e87c 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2657,6 +2657,7 @@ int musb_host_setup(struct musb *musb, int power_budget) if (ret < 0) return ret; + device_wakeup_enable(hcd->self.controller); return 0; } diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index e9d4cd960ecd..37752832b770 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -669,6 +669,7 @@ static void msm_otg_start_host(struct usb_phy *phy, int on) pdata->setup_gpio(OTG_STATE_A_HOST); #ifdef CONFIG_USB usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); + device_wakeup_enable(hcd->self.controller); #endif } else { dev_dbg(phy->dev, "host off\n"); diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index 98f6ac6a78ea..44f316e287ef 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -213,10 +213,12 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) hcd = bus_to_hcd(otg->host); - if (on) + if (on) { usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); - else + device_wakeup_enable(hcd->self.controller); + } else { usb_remove_hcd(hcd); + } #endif /* CONFIG_USB */ } diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index e40f565004d0..10e1ded9c9cc 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1469,6 +1469,7 @@ static int usbhsh_start(struct usbhs_priv *priv) ret = usb_add_hcd(hcd, 0, 0); if (ret < 0) return 0; + device_wakeup_enable(hcd->self.controller); /* * pipe initialize and enable DCP -- cgit v1.2.3 From e0e6a356a0b41375b729c511caa99d3ec019640e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Dec 2013 16:09:27 +0100 Subject: Revert "USB: quirks: add touchscreen that is dazzeled by remote wakeup" This reverts commit 614ced91fc6fbb5a1cdd12f0f1b6c9197d9f1350. The units on this was seen were prototypes and the issue is not seen on younger units. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 12924dbfdc2c..8f37063c0a49 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -98,9 +98,6 @@ static const struct usb_device_id usb_quirk_list[] = { /* Alcor Micro Corp. Hub */ { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME }, - /* MicroTouch Systems touchscreen */ - { USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME }, - /* appletouch */ { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v1.2.3 From bba3a87e982ad5992e776ca1fc409326915d6b44 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 2 Dec 2013 15:38:16 +0100 Subject: firmware: Introduce request_firmware_direct() When CONFIG_FW_LOADER_USER_HELPER is set, request_firmware() falls back to the usermode helper for loading via udev when the direct loading fails. But the recent udev takes way too long timeout (60 seconds) for non-existing firmware. This is unacceptable for the drivers like microcode loader where they load firmwares optionally, i.e. it's no error even if no requested file exists. This patch provides a new helper function, request_firmware_direct(). It behaves as same as request_firmware() except for that it doesn't fall back to usermode helper but returns an error immediately if the f/w can't be loaded directly in kernel. Without CONFIG_FW_LOADER_USER_HELPER=y, request_firmware_direct() is just an alias of request_firmware(), due to obvious reason. Tested-by: Prarit Bhargava Acked-by: Ming Lei Acked-by: Borislav Petkov Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 41 ++++++++++++++++++++++++++++++++++------- include/linux/firmware.h | 7 +++++++ 2 files changed, 41 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index eb8fb94ae2c5..1af03648daf8 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1061,7 +1061,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, /* called from request_firmware() and request_firmware_work_func() */ static int _request_firmware(const struct firmware **firmware_p, const char *name, - struct device *device, bool uevent, bool nowait) + struct device *device, bool uevent, bool nowait, bool fallback) { struct firmware *fw; long timeout; @@ -1095,11 +1095,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ret = fw_get_filesystem_firmware(device, fw->priv); if (ret) { - dev_warn(device, "Direct firmware load failed with error %d\n", - ret); - dev_warn(device, "Falling back to user helper\n"); - ret = fw_load_from_user_helper(fw, name, device, + if (fallback) { + dev_warn(device, + "Direct firmware load failed with error %d\n", + ret); + dev_warn(device, "Falling back to user helper\n"); + ret = fw_load_from_user_helper(fw, name, device, uevent, nowait, timeout); + } } /* don't cache firmware handled without uevent */ @@ -1146,12 +1149,36 @@ request_firmware(const struct firmware **firmware_p, const char *name, /* Need to pin this module until return */ __module_get(THIS_MODULE); - ret = _request_firmware(firmware_p, name, device, true, false); + ret = _request_firmware(firmware_p, name, device, true, false, true); module_put(THIS_MODULE); return ret; } EXPORT_SYMBOL(request_firmware); +#ifdef CONFIG_FW_LOADER_USER_HELPER +/** + * request_firmware: - load firmware directly without usermode helper + * @firmware_p: pointer to firmware image + * @name: name of firmware file + * @device: device for which firmware is being loaded + * + * This function works pretty much like request_firmware(), but this doesn't + * fall back to usermode helper even if the firmware couldn't be loaded + * directly from fs. Hence it's useful for loading optional firmwares, which + * aren't always present, without extra long timeouts of udev. + **/ +int request_firmware_direct(const struct firmware **firmware_p, + const char *name, struct device *device) +{ + int ret; + __module_get(THIS_MODULE); + ret = _request_firmware(firmware_p, name, device, true, false, false); + module_put(THIS_MODULE); + return ret; +} +EXPORT_SYMBOL_GPL(request_firmware_direct); +#endif + /** * release_firmware: - release the resource associated with a firmware image * @fw: firmware resource to release @@ -1185,7 +1212,7 @@ static void request_firmware_work_func(struct work_struct *work) fw_work = container_of(work, struct firmware_work, work); _request_firmware(&fw, fw_work->name, fw_work->device, - fw_work->uevent, true); + fw_work->uevent, true, true); fw_work->cont(fw, fw_work->context); put_device(fw_work->device); /* taken in request_firmware_nowait() */ diff --git a/include/linux/firmware.h b/include/linux/firmware.h index e154c1005cd1..59529330efd6 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -68,4 +68,11 @@ static inline void release_firmware(const struct firmware *fw) #endif +#ifdef CONFIG_FW_LOADER_USER_HELPER +int request_firmware_direct(const struct firmware **fw, const char *name, + struct device *device); +#else +#define request_firmware_direct request_firmware +#endif + #endif -- cgit v1.2.3 From 14c4bae77c80bd37f19d95405d42bd0b1fd95add Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 2 Dec 2013 15:38:18 +0100 Subject: firmware: Use bit flags instead of boolean combos More than two boolean arguments to a function are rather confusing and error-prone for callers. Let's make the behavior bit flags instead of triple combos. A nice suggestion by Borislav Petkov. Acked-by: Borislav Petkov Acked-by: Prarit Bhargava Acked-by: Ming Lei Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 51 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 1af03648daf8..65797742c6b6 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -96,6 +96,11 @@ static inline long firmware_loading_timeout(void) return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT; } +/* firmware behavior options */ +#define FW_OPT_UEVENT (1U << 0) +#define FW_OPT_NOWAIT (1U << 1) +#define FW_OPT_FALLBACK (1U << 2) + struct firmware_cache { /* firmware_buf instance will be added into the below list */ spinlock_t lock; @@ -820,7 +825,7 @@ static void firmware_class_timeout_work(struct work_struct *work) static struct firmware_priv * fw_create_instance(struct firmware *firmware, const char *fw_name, - struct device *device, bool uevent, bool nowait) + struct device *device, unsigned int opt_flags) { struct firmware_priv *fw_priv; struct device *f_dev; @@ -832,7 +837,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, goto exit; } - fw_priv->nowait = nowait; + fw_priv->nowait = !!(opt_flags & FW_OPT_NOWAIT); fw_priv->fw = firmware; INIT_DELAYED_WORK(&fw_priv->timeout_work, firmware_class_timeout_work); @@ -848,8 +853,8 @@ exit: } /* load a firmware via user helper */ -static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, - long timeout) +static int _request_firmware_load(struct firmware_priv *fw_priv, + unsigned int opt_flags, long timeout) { int retval = 0; struct device *f_dev = &fw_priv->dev; @@ -885,7 +890,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, goto err_del_bin_attr; } - if (uevent) { + if (opt_flags & FW_OPT_UEVENT) { buf->need_uevent = true; dev_set_uevent_suppress(f_dev, false); dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); @@ -911,16 +916,16 @@ err_put_dev: static int fw_load_from_user_helper(struct firmware *firmware, const char *name, struct device *device, - bool uevent, bool nowait, long timeout) + unsigned int opt_flags, long timeout) { struct firmware_priv *fw_priv; - fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); + fw_priv = fw_create_instance(firmware, name, device, opt_flags); if (IS_ERR(fw_priv)) return PTR_ERR(fw_priv); fw_priv->buf = firmware->priv; - return _request_firmware_load(fw_priv, uevent, timeout); + return _request_firmware_load(fw_priv, opt_flags, timeout); } #ifdef CONFIG_PM_SLEEP @@ -942,7 +947,7 @@ static void kill_requests_without_uevent(void) #else /* CONFIG_FW_LOADER_USER_HELPER */ static inline int fw_load_from_user_helper(struct firmware *firmware, const char *name, - struct device *device, bool uevent, bool nowait, + struct device *device, unsigned int opt_flags, long timeout) { return -ENOENT; @@ -1023,7 +1028,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name, } static int assign_firmware_buf(struct firmware *fw, struct device *device, - bool skip_cache) + unsigned int opt_flags) { struct firmware_buf *buf = fw->priv; @@ -1040,7 +1045,8 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, * device may has been deleted already, but the problem * should be fixed in devres or driver core. */ - if (device && !skip_cache) + /* don't cache firmware handled without uevent */ + if (device && (opt_flags & FW_OPT_UEVENT)) fw_add_devm_name(device, buf->fw_id); /* @@ -1061,7 +1067,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, /* called from request_firmware() and request_firmware_work_func() */ static int _request_firmware(const struct firmware **firmware_p, const char *name, - struct device *device, bool uevent, bool nowait, bool fallback) + struct device *device, unsigned int opt_flags) { struct firmware *fw; long timeout; @@ -1076,7 +1082,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ret = 0; timeout = firmware_loading_timeout(); - if (nowait) { + if (opt_flags & FW_OPT_NOWAIT) { timeout = usermodehelper_read_lock_wait(timeout); if (!timeout) { dev_dbg(device, "firmware: %s loading timed out\n", @@ -1095,19 +1101,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ret = fw_get_filesystem_firmware(device, fw->priv); if (ret) { - if (fallback) { + if (opt_flags & FW_OPT_FALLBACK) { dev_warn(device, "Direct firmware load failed with error %d\n", ret); dev_warn(device, "Falling back to user helper\n"); ret = fw_load_from_user_helper(fw, name, device, - uevent, nowait, timeout); + opt_flags, timeout); } } - /* don't cache firmware handled without uevent */ if (!ret) - ret = assign_firmware_buf(fw, device, !uevent); + ret = assign_firmware_buf(fw, device, opt_flags); usermodehelper_read_unlock(); @@ -1149,7 +1154,8 @@ request_firmware(const struct firmware **firmware_p, const char *name, /* Need to pin this module until return */ __module_get(THIS_MODULE); - ret = _request_firmware(firmware_p, name, device, true, false, true); + ret = _request_firmware(firmware_p, name, device, + FW_OPT_UEVENT | FW_OPT_FALLBACK); module_put(THIS_MODULE); return ret; } @@ -1172,7 +1178,7 @@ int request_firmware_direct(const struct firmware **firmware_p, { int ret; __module_get(THIS_MODULE); - ret = _request_firmware(firmware_p, name, device, true, false, false); + ret = _request_firmware(firmware_p, name, device, FW_OPT_UEVENT); module_put(THIS_MODULE); return ret; } @@ -1201,7 +1207,7 @@ struct firmware_work { struct device *device; void *context; void (*cont)(const struct firmware *fw, void *context); - bool uevent; + unsigned int opt_flags; }; static void request_firmware_work_func(struct work_struct *work) @@ -1212,7 +1218,7 @@ static void request_firmware_work_func(struct work_struct *work) fw_work = container_of(work, struct firmware_work, work); _request_firmware(&fw, fw_work->name, fw_work->device, - fw_work->uevent, true, true); + fw_work->opt_flags); fw_work->cont(fw, fw_work->context); put_device(fw_work->device); /* taken in request_firmware_nowait() */ @@ -1260,7 +1266,8 @@ request_firmware_nowait( fw_work->device = device; fw_work->context = context; fw_work->cont = cont; - fw_work->uevent = uevent; + fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK | + (uevent ? FW_OPT_UEVENT : 0); if (!try_module_get(module)) { kfree(fw_work); -- cgit v1.2.3 From 68aeeaaaf86b61c78dca09879ce262778a9080e4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 2 Dec 2013 15:38:19 +0100 Subject: firmware: Suppress fallback warnings when CONFIG_FW_LOADER_USER_HELPER=n The commit [3e358ac2bb5b: firmware: Be a bit more verbose about direct firmware loading failure] introduced a new warning message about falling back to user helper, but this isn't true when CONFIG_FW_LOADER_USER_HELPER isn't set. In this patch, clear the FW_OPT_FALLBACK flag in the case without userhelper, so that the corresponding code will be disabled. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 65797742c6b6..33b87bf664ab 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -99,7 +99,11 @@ static inline long firmware_loading_timeout(void) /* firmware behavior options */ #define FW_OPT_UEVENT (1U << 0) #define FW_OPT_NOWAIT (1U << 1) +#ifdef CONFIG_FW_LOADER_USER_HELPER #define FW_OPT_FALLBACK (1U << 2) +#else +#define FW_OPT_FALLBACK 0 +#endif struct firmware_cache { /* firmware_buf instance will be added into the below list */ -- cgit v1.2.3 From a61aca2854eaecf2d1bffbaf1fc368fb1a20c850 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Dec 2013 16:46:28 -0700 Subject: firmware: dmi-sysfs: Don't remove dmi-sysfs "raw" file explicitly Removing the dmi-sysfs module causes the following warning: # modprobe -r dmi_sysfs WARNING: CPU: 11 PID: 6785 at fs/sysfs/inode.c:325 sysfs_hash_and_remove+0xa9/0xb0() sysfs: can not remove 'raw', no directory This is because putting the entry kobject, e.g., for "/sys/firmware/dmi/entries/19-0", removes the directory and all its contents. By the time dmi_sysfs_entry_release() runs, the "raw" file inside ".../19-0/" has already been removed. Therefore, we don't need to remove the "raw" bin file at all in dmi_sysfs_entry_release(). Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c index eb26d62e5188..66200ed5e6a1 100644 --- a/drivers/firmware/dmi-sysfs.c +++ b/drivers/firmware/dmi-sysfs.c @@ -553,7 +553,7 @@ static const struct bin_attribute dmi_entry_raw_attr = { static void dmi_sysfs_entry_release(struct kobject *kobj) { struct dmi_sysfs_entry *entry = to_entry(kobj); - sysfs_remove_bin_file(&entry->kobj, &dmi_entry_raw_attr); + spin_lock(&entry_list_lock); list_del(&entry->list); spin_unlock(&entry_list_lock); -- cgit v1.2.3 From d0f80f9aadf60adc4caafed0d2b01e79a315ff80 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 5 Dec 2013 16:46:35 -0700 Subject: firmware: dmi-sysfs: Remove "dmi" directory on module exit With CONFIG_DEBUG_KOBJECT_RELEASE=y, removing and immediately reloading the dmi-sysfs module causes the following warning: sysfs: cannot create duplicate filename '/firmware/dmi' kobject_add_internal failed for dmi with -EEXIST, don't try to register things with the same name in the same directory. The "dmi" directory stays in sysfs until the dmi_kobj is released, and DEBUG_KOBJECT_RELEASE delays that. I don't think we can hit this problem in normal usage because dmi_kobj is static and nothing outside dmi-sysfs can get a reference to it, so the only way to delay the "dmi" release is with DEBUG_KOBJECT_RELEASE. Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi-sysfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c index 66200ed5e6a1..e0f1cb3d3598 100644 --- a/drivers/firmware/dmi-sysfs.c +++ b/drivers/firmware/dmi-sysfs.c @@ -685,6 +685,7 @@ static void __exit dmi_sysfs_exit(void) pr_debug("dmi-sysfs: unloading.\n"); cleanup_entry_list(); kset_unregister(dmi_kset); + kobject_del(dmi_kobj); kobject_put(dmi_kobj); } -- cgit v1.2.3 From bbc780f8bab52fef1784151d3c4982cb1143edd2 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 21 Nov 2013 20:15:48 +0100 Subject: driver core: fix device_create() error path We call put_device() in the error path, which is fine for dev==NULL. However, in case kobject_set_name_vargs() fails, we have dev!=NULL but device_initialized() wasn't called, yet. Fix this by splitting device_register() into explicit calls to device_add() and an early call to device_initialize(). Signed-off-by: David Herrmann Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 67b180d855b2..aab43fbb8336 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1603,6 +1603,7 @@ device_create_groups_vargs(struct class *class, struct device *parent, goto error; } + device_initialize(dev); dev->devt = devt; dev->class = class; dev->parent = parent; @@ -1614,7 +1615,7 @@ device_create_groups_vargs(struct class *class, struct device *parent, if (retval) goto error; - retval = device_register(dev); + retval = device_add(dev); if (retval) goto error; -- cgit v1.2.3 From 36fe66c164a9fdf1ff4ad085b6b68960c6170000 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:03:23 +0900 Subject: char: amd64-agp: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/amd64-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index d79d692d05b8..896413b59aae 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -735,7 +735,7 @@ static struct pci_device_id agp_amd64_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); -static DEFINE_PCI_DEVICE_TABLE(agp_amd64_pci_promisc_table) = { +static const struct pci_device_id agp_amd64_pci_promisc_table[] = { { PCI_DEVICE_CLASS(0, 0) }, { } }; -- cgit v1.2.3 From 5123662adc873f9a37d7898fe3c285a1f1af59c8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 11 Nov 2013 11:23:49 -0800 Subject: lkdtm: clean up sparse warnings Since lkdtm intentionally does "bad" things, we need to convince sparse that we're doing these things on purpose. This adds an explicit cast to the call to copy_to_user() and marks the spin lock as expecting to dead-lock. Reported-by: Fengguang Wu Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index a2edb2ee0921..a9a203d5f8d9 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -334,9 +334,10 @@ static void execute_location(void *dst) static void execute_user_location(void *dst) { + /* Intentionally crossing kernel/user memory boundary. */ void (*func)(void) = dst; - if (copy_to_user(dst, do_nothing, EXEC_SIZE)) + if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE)) return; func(); } @@ -408,6 +409,8 @@ static void lkdtm_do_action(enum ctype which) case CT_SPINLOCKUP: /* Must be called twice to trigger. */ spin_lock(&lock_me_up); + /* Let sparse know we intended to exit holding the lock. */ + __release(&lock_me_up); break; case CT_HUNG_TASK: set_current_state(TASK_UNINTERRUPTIBLE); -- cgit v1.2.3 From a0822637258b9e6132de669ac16dfe445c78e932 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 29 Nov 2013 15:39:28 +0400 Subject: w1: mxc_w1: Remove unused field "clkdiv" from private structure Private field "clkdiv" is not used outside "probe", so there are no reason to keep it in driver. Signed-off-by: Alexander Shiyan Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/mxc_w1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 15c7251b0556..5de3ca9b0fb9 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -46,7 +46,6 @@ struct mxc_w1_device { void __iomem *regs; - unsigned int clkdiv; struct clk *clk; struct w1_bus_master bus_master; }; @@ -107,6 +106,7 @@ static int mxc_w1_probe(struct platform_device *pdev) { struct mxc_w1_device *mdev; struct resource *res; + unsigned int clkdiv; int err = 0; mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device), @@ -118,7 +118,7 @@ static int mxc_w1_probe(struct platform_device *pdev) if (IS_ERR(mdev->clk)) return PTR_ERR(mdev->clk); - mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; + clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mdev->regs = devm_ioremap_resource(&pdev->dev, res); @@ -126,7 +126,7 @@ static int mxc_w1_probe(struct platform_device *pdev) return PTR_ERR(mdev->regs); clk_prepare_enable(mdev->clk); - __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); + __raw_writeb(clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); mdev->bus_master.data = mdev; mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus; -- cgit v1.2.3 From 71531f55a83dcb79b89287f6b11fb2e4eb496d4d Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 29 Nov 2013 15:39:29 +0400 Subject: w1: mxc_w1: Add warning for base frequency calculation Base frequency should be as close as possible to 1 MHz. This patch adds warnings when clock is unreliable, according to i.MX datasheet. Signed-off-by: Alexander Shiyan Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/mxc_w1.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 5de3ca9b0fb9..953168c63392 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -105,6 +105,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) static int mxc_w1_probe(struct platform_device *pdev) { struct mxc_w1_device *mdev; + unsigned long clkrate; struct resource *res; unsigned int clkdiv; int err = 0; @@ -118,7 +119,16 @@ static int mxc_w1_probe(struct platform_device *pdev) if (IS_ERR(mdev->clk)) return PTR_ERR(mdev->clk); - clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; + clkrate = clk_get_rate(mdev->clk); + if (clkrate < 10000000) + dev_warn(&pdev->dev, + "Low clock frequency causes improper function\n"); + + clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000); + clkrate /= clkdiv; + if ((clkrate < 980000) || (clkrate > 1020000)) + dev_warn(&pdev->dev, + "Incorrect time base frequency %lu Hz\n", clkrate); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mdev->regs = devm_ioremap_resource(&pdev->dev, res); @@ -126,7 +136,7 @@ static int mxc_w1_probe(struct platform_device *pdev) return PTR_ERR(mdev->regs); clk_prepare_enable(mdev->clk); - __raw_writeb(clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); + __raw_writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER); mdev->bus_master.data = mdev; mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus; -- cgit v1.2.3 From 001d1953eae7089ab148ec32e13848be8d0b3874 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 29 Nov 2013 15:39:30 +0400 Subject: w1: mxc_w1: Check the clk_prepare_enable() return value Signed-off-by: Alexander Shiyan Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/mxc_w1.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 953168c63392..1e5d94c5afc9 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -108,7 +108,7 @@ static int mxc_w1_probe(struct platform_device *pdev) unsigned long clkrate; struct resource *res; unsigned int clkdiv; - int err = 0; + int err; mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device), GFP_KERNEL); @@ -135,20 +135,23 @@ static int mxc_w1_probe(struct platform_device *pdev) if (IS_ERR(mdev->regs)) return PTR_ERR(mdev->regs); - clk_prepare_enable(mdev->clk); + err = clk_prepare_enable(mdev->clk); + if (err) + return err; + __raw_writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER); mdev->bus_master.data = mdev; mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus; mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit; - err = w1_add_master_device(&mdev->bus_master); + platform_set_drvdata(pdev, mdev); + err = w1_add_master_device(&mdev->bus_master); if (err) - return err; + clk_disable_unprepare(mdev->clk); - platform_set_drvdata(pdev, mdev); - return 0; + return err; } /* -- cgit v1.2.3 From 0f4054df0bf6bad391cec4eaac03bc1127368e77 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:27:13 +0900 Subject: uio: uio_mf624: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_mf624.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/uio/uio_mf624.c b/drivers/uio/uio_mf624.c index f764adbfe036..d1f95a1567bb 100644 --- a/drivers/uio/uio_mf624.c +++ b/drivers/uio/uio_mf624.c @@ -228,7 +228,7 @@ static void mf624_pci_remove(struct pci_dev *dev) kfree(info); } -static DEFINE_PCI_DEVICE_TABLE(mf624_pci_id) = { +static const struct pci_device_id mf624_pci_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF624) }, { 0, } }; -- cgit v1.2.3 From 4455d9fd48093d27c95a802071c9dca9f79d8fff Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:18 +0100 Subject: pcmcia: Remove superfluous name casts device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Cc: Greg Kroah-Hartman Cc: linux-pcmcia@lists.infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/pcmcia/bfin_cf_pcmcia.c | 2 +- drivers/pcmcia/electra_cf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index ed3b522601b3..971991bab975 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c @@ -303,7 +303,7 @@ static int bfin_cf_remove(struct platform_device *pdev) static struct platform_driver bfin_cf_driver = { .driver = { - .name = (char *)driver_name, + .name = driver_name, .owner = THIS_MODULE, }, .probe = bfin_cf_probe, diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index 1b206eac5f93..5ea64d0f61ab 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c @@ -359,7 +359,7 @@ MODULE_DEVICE_TABLE(of, electra_cf_match); static struct platform_driver electra_cf_driver = { .driver = { - .name = (char *)driver_name, + .name = driver_name, .owner = THIS_MODULE, .of_match_table = electra_cf_match, }, -- cgit v1.2.3 From 11e6a09fba446ce799a9de51d2d99586024bbdaa Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Sun, 8 Dec 2013 23:39:04 -0800 Subject: drm/vmwgfx: Add max surface memory param Userspace uses this to workaround overcommit issues by flushing the command stream early. Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 3 +++ include/uapi/drm/vmwgfx_drm.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index a51f48e3e917..45d5b5ab6ca9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -68,6 +68,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, SVGA_FIFO_3D_HWVERSION)); break; } + case DRM_VMW_PARAM_MAX_SURF_MEMORY: + param->value = dev_priv->memory_size; + break; default: DRM_ERROR("Illegal vmwgfx get param request: %d\n", param->param); diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index bcb0912afe7a..f854ca4a1372 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -75,6 +75,7 @@ #define DRM_VMW_PARAM_FIFO_CAPS 4 #define DRM_VMW_PARAM_MAX_FB_SIZE 5 #define DRM_VMW_PARAM_FIFO_HW_VERSION 6 +#define DRM_VMW_PARAM_MAX_SURF_MEMORY 7 /** * struct drm_vmw_getparam_arg -- cgit v1.2.3 From c461562e84d180fb691af57f93a42bd9cc7eb69c Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sun, 8 Dec 2013 13:52:59 +0530 Subject: drm/i915: Remove duplicate intel_uncore_forcewake_reset. Since early sanitize and uncore sanitize are called one after the other, I think, we can remove second forcewake reset which was are calling twice in both the functions. Note that this is merge fallout between commit ef46e0d247da0a7a408573aa15870e231bbd4af2 Author: Daniel Vetter Date: Sat Nov 16 16:00:09 2013 +0100 drm/i915: restore the early forcewake cleanup and commit 521198a2e7095c8c7daa8d7d3a76a110c346be6f Author: Mika Kuoppala Date: Fri Aug 23 16:52:30 2013 +0300 drm/i915: sanitize forcewake registers on reset Signed-off-by: Deepak S [danvet: Explain how this came to be.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index feb2d6692544..e63658e0cfd3 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -340,8 +340,6 @@ void intel_uncore_sanitize(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; u32 reg_val; - intel_uncore_forcewake_reset(dev); - /* BIOS often leaves RC6 enabled, but disable it for hw init */ intel_disable_gt_powersave(dev); -- cgit v1.2.3 From 9fa7c419643b8c291d9c56718804cb8cf4237e97 Mon Sep 17 00:00:00 2001 From: Luis Alves Date: Wed, 13 Nov 2013 15:02:28 -0300 Subject: [media] cx24117: Add complete demod command list This patch adds the complete list of all the commands known for the cx24117 demodulator. Signed-off-by: Luis Alves Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cx24117.c | 98 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 476b422ccf19..a6fe1aff976b 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c @@ -135,15 +135,33 @@ enum cmds { - CMD_SET_VCO = 0x10, - CMD_TUNEREQUEST = 0x11, - CMD_MPEGCONFIG = 0x13, - CMD_TUNERINIT = 0x14, - CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */ - CMD_LNBDCLEVEL = 0x22, - CMD_SET_TONE = 0x23, - CMD_UPDFWVERS = 0x35, - CMD_TUNERSLEEP = 0x36, + CMD_SET_VCOFREQ = 0x10, + CMD_TUNEREQUEST = 0x11, + CMD_GLOBAL_MPEGCFG = 0x13, + CMD_MPEGCFG = 0x14, + CMD_TUNERINIT = 0x15, + CMD_GET_SRATE = 0x18, + CMD_SET_GOLDCODE = 0x19, + CMD_GET_AGCACC = 0x1a, + CMD_DEMODINIT = 0x1b, + CMD_GETCTLACC = 0x1c, + + CMD_LNBCONFIG = 0x20, + CMD_LNBSEND = 0x21, + CMD_LNBDCLEVEL = 0x22, + CMD_LNBPCBCONFIG = 0x23, + CMD_LNBSENDTONEBST = 0x24, + CMD_LNBUPDREPLY = 0x25, + + CMD_SET_GPIOMODE = 0x30, + CMD_SET_GPIOEN = 0x31, + CMD_SET_GPIODIR = 0x32, + CMD_SET_GPIOOUT = 0x33, + CMD_ENABLERSCORR = 0x34, + CMD_FWVERSION = 0x35, + CMD_SET_SLEEPMODE = 0x36, + CMD_BERCTRL = 0x3c, + CMD_EVENTCTRL = 0x3d, }; static LIST_HEAD(hybrid_tuner_instance_list); @@ -619,8 +637,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, cx24117_writereg(state, 0xf7, 0x0c); cx24117_writereg(state, 0xe0, 0x00); - /* CMD 1B */ - cmd.args[0] = 0x1b; + /* Init demodulator */ + cmd.args[0] = CMD_DEMODINIT; cmd.args[1] = 0x00; cmd.args[2] = 0x01; cmd.args[3] = 0x00; @@ -629,8 +647,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, if (ret != 0) goto error; - /* CMD 10 */ - cmd.args[0] = CMD_SET_VCO; + /* Set VCO frequency */ + cmd.args[0] = CMD_SET_VCOFREQ; cmd.args[1] = 0x06; cmd.args[2] = 0x2b; cmd.args[3] = 0xd8; @@ -648,8 +666,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, if (ret != 0) goto error; - /* CMD 15 */ - cmd.args[0] = 0x15; + /* Tuner init */ + cmd.args[0] = CMD_TUNERINIT; cmd.args[1] = 0x00; cmd.args[2] = 0x01; cmd.args[3] = 0x00; @@ -667,8 +685,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, if (ret != 0) goto error; - /* CMD 13 */ - cmd.args[0] = CMD_MPEGCONFIG; + /* Global MPEG config */ + cmd.args[0] = CMD_GLOBAL_MPEGCFG; cmd.args[1] = 0x00; cmd.args[2] = 0x00; cmd.args[3] = 0x00; @@ -679,9 +697,9 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, if (ret != 0) goto error; - /* CMD 14 */ + /* MPEG config for each demod */ for (i = 0; i < 2; i++) { - cmd.args[0] = CMD_TUNERINIT; + cmd.args[0] = CMD_MPEGCFG; cmd.args[1] = (u8) i; cmd.args[2] = 0x00; cmd.args[3] = 0x05; @@ -699,8 +717,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, cx24117_writereg(state, 0xcf, 0x00); cx24117_writereg(state, 0xe5, 0x04); - /* Firmware CMD 35: Get firmware version */ - cmd.args[0] = CMD_UPDFWVERS; + /* Get firmware version */ + cmd.args[0] = CMD_FWVERSION; cmd.len = 2; for (i = 0; i < 4; i++) { cmd.args[1] = i; @@ -779,8 +797,8 @@ static int cx24117_read_signal_strength(struct dvb_frontend *fe, u8 reg = (state->demod == 0) ? CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1; - /* Firmware CMD 1A */ - cmd.args[0] = 0x1a; + /* Read AGC accumulator register */ + cmd.args[0] = CMD_GET_AGCACC; cmd.args[1] = (u8) state->demod; cmd.len = 2; ret = cx24117_cmd_execute(fe, &cmd); @@ -899,8 +917,8 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "SEC_VOLTAGE_OFF"); - /* CMD 32 */ - cmd.args[0] = 0x32; + /* Set GPIO direction */ + cmd.args[0] = CMD_SET_GPIODIR; cmd.args[1] = reg; cmd.args[2] = reg; cmd.len = 3; @@ -910,8 +928,8 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, if ((voltage == SEC_VOLTAGE_13) || (voltage == SEC_VOLTAGE_18)) { - /* CMD 33 */ - cmd.args[0] = 0x33; + /* Set GPIO logic level */ + cmd.args[0] = CMD_SET_GPIOOUT; cmd.args[1] = reg; cmd.args[2] = reg; cmd.len = 3; @@ -926,7 +944,7 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, /* Wait for voltage/min repeat delay */ msleep(100); - /* CMD 22 - CMD_LNBDCLEVEL */ + /* Set 13V/18V select pin */ cmd.args[0] = CMD_LNBDCLEVEL; cmd.args[1] = state->demod ? 0 : 1; cmd.args[2] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00); @@ -935,7 +953,7 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, /* Min delay time before DiSEqC send */ msleep(20); } else { - cmd.args[0] = 0x33; + cmd.args[0] = CMD_SET_GPIOOUT; cmd.args[1] = 0x00; cmd.args[2] = reg; cmd.len = 3; @@ -968,8 +986,7 @@ static int cx24117_set_tone(struct dvb_frontend *fe, msleep(20); /* Set the tone */ - /* CMD 23 - CMD_SET_TONE */ - cmd.args[0] = CMD_SET_TONE; + cmd.args[0] = CMD_LNBPCBCONFIG; cmd.args[1] = (state->demod ? 0 : 1); cmd.args[2] = 0x00; cmd.args[3] = 0x00; @@ -1231,8 +1248,8 @@ static int cx24117_initfe(struct dvb_frontend *fe) mutex_lock(&state->priv->fe_lock); - /* Firmware CMD 36: Power config */ - cmd.args[0] = CMD_TUNERSLEEP; + /* Set sleep mode off */ + cmd.args[0] = CMD_SET_SLEEPMODE; cmd.args[1] = (state->demod ? 1 : 0); cmd.args[2] = 0; cmd.len = 3; @@ -1244,8 +1261,8 @@ static int cx24117_initfe(struct dvb_frontend *fe) if (ret != 0) goto exit; - /* CMD 3C */ - cmd.args[0] = 0x3c; + /* Set BER control */ + cmd.args[0] = CMD_BERCTRL; cmd.args[1] = (state->demod ? 1 : 0); cmd.args[2] = 0x10; cmd.args[3] = 0x10; @@ -1254,8 +1271,8 @@ static int cx24117_initfe(struct dvb_frontend *fe) if (ret != 0) goto exit; - /* CMD 34 */ - cmd.args[0] = 0x34; + /* Set RS correction (enable/disable) */ + cmd.args[0] = CMD_ENABLERSCORR; cmd.args[1] = (state->demod ? 1 : 0); cmd.args[2] = CX24117_OCC; cmd.len = 3; @@ -1278,8 +1295,8 @@ static int cx24117_sleep(struct dvb_frontend *fe) dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n", __func__, state->demod); - /* Firmware CMD 36: Power config */ - cmd.args[0] = CMD_TUNERSLEEP; + /* Set sleep mode on */ + cmd.args[0] = CMD_SET_SLEEPMODE; cmd.args[1] = (state->demod ? 1 : 0); cmd.args[2] = 1; cmd.len = 3; @@ -1558,7 +1575,8 @@ static int cx24117_get_frontend(struct dvb_frontend *fe) u8 buf[0x1f-4]; - cmd.args[0] = 0x1c; + /* Read current tune parameters */ + cmd.args[0] = CMD_GETCTLACC; cmd.args[1] = (u8) state->demod; cmd.len = 2; ret = cx24117_cmd_execute(fe, &cmd); -- cgit v1.2.3 From 71b6aaafd534995255d65d6433cbae7938a8131f Mon Sep 17 00:00:00 2001 From: Luis Alves Date: Wed, 13 Nov 2013 15:06:44 -0300 Subject: [media] cx24117: Fix LNB set_voltage function This patch should fix/enhance the set_voltage function for the cx24117 demodulator. Signed-off-by: Luis Alves Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cx24117.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index a6fe1aff976b..68f768a5422d 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c @@ -917,22 +917,15 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "SEC_VOLTAGE_OFF"); - /* Set GPIO direction */ - cmd.args[0] = CMD_SET_GPIODIR; - cmd.args[1] = reg; - cmd.args[2] = reg; + /* Prepare a set GPIO logic level CMD */ + cmd.args[0] = CMD_SET_GPIOOUT; + cmd.args[2] = reg; /* mask */ cmd.len = 3; - ret = cx24117_cmd_execute(fe, &cmd); - if (ret) - return ret; if ((voltage == SEC_VOLTAGE_13) || (voltage == SEC_VOLTAGE_18)) { - /* Set GPIO logic level */ - cmd.args[0] = CMD_SET_GPIOOUT; + /* power on LNB */ cmd.args[1] = reg; - cmd.args[2] = reg; - cmd.len = 3; ret = cx24117_cmd_execute(fe, &cmd); if (ret != 0) return ret; @@ -949,17 +942,17 @@ static int cx24117_set_voltage(struct dvb_frontend *fe, cmd.args[1] = state->demod ? 0 : 1; cmd.args[2] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00); cmd.len = 3; + ret = cx24117_cmd_execute(fe, &cmd); /* Min delay time before DiSEqC send */ msleep(20); } else { - cmd.args[0] = CMD_SET_GPIOOUT; + /* power off LNB */ cmd.args[1] = 0x00; - cmd.args[2] = reg; - cmd.len = 3; + ret = cx24117_cmd_execute(fe, &cmd); } - return cx24117_cmd_execute(fe, &cmd); + return ret; } static int cx24117_set_tone(struct dvb_frontend *fe, @@ -1277,6 +1270,16 @@ static int cx24117_initfe(struct dvb_frontend *fe) cmd.args[2] = CX24117_OCC; cmd.len = 3; ret = cx24117_cmd_execute_nolock(fe, &cmd); + if (ret != 0) + goto exit; + + /* Set GPIO direction */ + /* Set as output - controls LNB power on/off */ + cmd.args[0] = CMD_SET_GPIODIR; + cmd.args[1] = 0x30; + cmd.args[2] = 0x30; + cmd.len = 3; + ret = cx24117_cmd_execute_nolock(fe, &cmd); exit: mutex_unlock(&state->priv->fe_lock); -- cgit v1.2.3 From 899127b67df098e6d878f27be05dc91401cc6685 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 4 Nov 2013 08:34:42 -0300 Subject: [media] This adds support for the BCM2048 radio module found in Nokia N900 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add suport for Nokia N900 radio. This driver is far from being ready to be added at the main tree, as it creates its own sysfs interface, and violates lots of Coding Style rules, doing even evil things like returning from a function inside a macro. So, it is being added at staging with the condition that it will be soon be fixed. [m.chehab@samsung.com: added a description for the patch] Signed-off-by: Eero Nurkkala Signed-off-by: Nils Faerber Signed-off-by: Joni Lapilainen Signed-off-by: Pali Rohár Signed-off-by: Hans Verkuil [hans.verkuil@cisco.com: moved to staging, added slab.h include] Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/bcm2048/Kconfig | 13 + drivers/staging/media/bcm2048/Makefile | 1 + drivers/staging/media/bcm2048/radio-bcm2048.c | 2745 +++++++++++++++++++++++++ drivers/staging/media/bcm2048/radio-bcm2048.h | 30 + 6 files changed, 2792 insertions(+) create mode 100644 drivers/staging/media/bcm2048/Kconfig create mode 100644 drivers/staging/media/bcm2048/Makefile create mode 100644 drivers/staging/media/bcm2048/radio-bcm2048.c create mode 100644 drivers/staging/media/bcm2048/radio-bcm2048.h (limited to 'drivers') diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index bc4c7982360e..77288796540b 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -21,6 +21,8 @@ if STAGING_MEDIA # Please keep them in alphabetic order source "drivers/staging/media/as102/Kconfig" +source "drivers/staging/media/bcm2048/Kconfig" + source "drivers/staging/media/cxd2099/Kconfig" source "drivers/staging/media/davinci_vpfe/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index a528d3f40105..0bd1a88a27fa 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_DVB_AS102) += as102/ +obj-$(CONFIG_I2C_BCM2048) += bcm2048/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_SOLO6X10) += solo6x10/ diff --git a/drivers/staging/media/bcm2048/Kconfig b/drivers/staging/media/bcm2048/Kconfig new file mode 100644 index 000000000000..a9fc6e186494 --- /dev/null +++ b/drivers/staging/media/bcm2048/Kconfig @@ -0,0 +1,13 @@ +# +# Multimedia Video device configuration +# + +config I2C_BCM2048 + tristate "Broadcom BCM2048 FM Radio Receiver support" + depends on I2C && VIDEO_V4L2 && RADIO_ADAPTERS + ---help--- + Say Y here if you want support to BCM2048 FM Radio Receiver. + This device driver supports only i2c bus. + + To compile this driver as a module, choose M here: the + module will be called radio-bcm2048. diff --git a/drivers/staging/media/bcm2048/Makefile b/drivers/staging/media/bcm2048/Makefile new file mode 100644 index 000000000000..b4f5663d1408 --- /dev/null +++ b/drivers/staging/media/bcm2048/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_I2C_BCM2048) += radio-bcm2048.o diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c new file mode 100644 index 000000000000..782cc11fd037 --- /dev/null +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -0,0 +1,2745 @@ +/* + * drivers/staging/media/radio-bcm2048.c + * + * Driver for I2C Broadcom BCM2048 FM Radio Receiver: + * + * Copyright (C) Nokia Corporation + * Contact: Eero Nurkkala + * + * Copyright (C) Nils Faerber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* + * History: + * Eero Nurkkala + * Version 0.0.1 + * - Initial implementation + * 2010-02-21 Nils Faerber + * Version 0.0.2 + * - Add support for interrupt driven rds data reading + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "radio-bcm2048.h" + +/* driver definitions */ +#define BCM2048_DRIVER_AUTHOR "Eero Nurkkala " +#define BCM2048_DRIVER_NAME BCM2048_NAME +#define BCM2048_DRIVER_VERSION KERNEL_VERSION(0, 0, 1) +#define BCM2048_DRIVER_CARD "Broadcom bcm2048 FM Radio Receiver" +#define BCM2048_DRIVER_DESC "I2C driver for BCM2048 FM Radio Receiver" + +/* I2C Control Registers */ +#define BCM2048_I2C_FM_RDS_SYSTEM 0x00 +#define BCM2048_I2C_FM_CTRL 0x01 +#define BCM2048_I2C_RDS_CTRL0 0x02 +#define BCM2048_I2C_RDS_CTRL1 0x03 +#define BCM2048_I2C_FM_AUDIO_PAUSE 0x04 +#define BCM2048_I2C_FM_AUDIO_CTRL0 0x05 +#define BCM2048_I2C_FM_AUDIO_CTRL1 0x06 +#define BCM2048_I2C_FM_SEARCH_CTRL0 0x07 +#define BCM2048_I2C_FM_SEARCH_CTRL1 0x08 +#define BCM2048_I2C_FM_SEARCH_TUNE_MODE 0x09 +#define BCM2048_I2C_FM_FREQ0 0x0a +#define BCM2048_I2C_FM_FREQ1 0x0b +#define BCM2048_I2C_FM_AF_FREQ0 0x0c +#define BCM2048_I2C_FM_AF_FREQ1 0x0d +#define BCM2048_I2C_FM_CARRIER 0x0e +#define BCM2048_I2C_FM_RSSI 0x0f +#define BCM2048_I2C_FM_RDS_MASK0 0x10 +#define BCM2048_I2C_FM_RDS_MASK1 0x11 +#define BCM2048_I2C_FM_RDS_FLAG0 0x12 +#define BCM2048_I2C_FM_RDS_FLAG1 0x13 +#define BCM2048_I2C_RDS_WLINE 0x14 +#define BCM2048_I2C_RDS_BLKB_MATCH0 0x16 +#define BCM2048_I2C_RDS_BLKB_MATCH1 0x17 +#define BCM2048_I2C_RDS_BLKB_MASK0 0x18 +#define BCM2048_I2C_RDS_BLKB_MASK1 0x19 +#define BCM2048_I2C_RDS_PI_MATCH0 0x1a +#define BCM2048_I2C_RDS_PI_MATCH1 0x1b +#define BCM2048_I2C_RDS_PI_MASK0 0x1c +#define BCM2048_I2C_RDS_PI_MASK1 0x1d +#define BCM2048_I2C_SPARE1 0x20 +#define BCM2048_I2C_SPARE2 0x21 +#define BCM2048_I2C_FM_RDS_REV 0x28 +#define BCM2048_I2C_SLAVE_CONFIGURATION 0x29 +#define BCM2048_I2C_RDS_DATA 0x80 +#define BCM2048_I2C_FM_BEST_TUNE_MODE 0x90 + +/* BCM2048_I2C_FM_RDS_SYSTEM */ +#define BCM2048_FM_ON 0x01 +#define BCM2048_RDS_ON 0x02 + +/* BCM2048_I2C_FM_CTRL */ +#define BCM2048_BAND_SELECT 0x01 +#define BCM2048_STEREO_MONO_AUTO_SELECT 0x02 +#define BCM2048_STEREO_MONO_MANUAL_SELECT 0x04 +#define BCM2048_STEREO_MONO_BLEND_SWITCH 0x08 +#define BCM2048_HI_LO_INJECTION 0x10 + +/* BCM2048_I2C_RDS_CTRL0 */ +#define BCM2048_RBDS_RDS_SELECT 0x01 +#define BCM2048_FLUSH_FIFO 0x02 + +/* BCM2048_I2C_FM_AUDIO_PAUSE */ +#define BCM2048_AUDIO_PAUSE_RSSI_TRESH 0x0f +#define BCM2048_AUDIO_PAUSE_DURATION 0xf0 + +/* BCM2048_I2C_FM_AUDIO_CTRL0 */ +#define BCM2048_RF_MUTE 0x01 +#define BCM2048_MANUAL_MUTE 0x02 +#define BCM2048_DAC_OUTPUT_LEFT 0x04 +#define BCM2048_DAC_OUTPUT_RIGHT 0x08 +#define BCM2048_AUDIO_ROUTE_DAC 0x10 +#define BCM2048_AUDIO_ROUTE_I2S 0x20 +#define BCM2048_DE_EMPHASIS_SELECT 0x40 +#define BCM2048_AUDIO_BANDWIDTH_SELECT 0x80 + +/* BCM2048_I2C_FM_SEARCH_CTRL0 */ +#define BCM2048_SEARCH_RSSI_THRESHOLD 0x7f +#define BCM2048_SEARCH_DIRECTION 0x80 + +/* BCM2048_I2C_FM_SEARCH_TUNE_MODE */ +#define BCM2048_FM_AUTO_SEARCH 0x03 + +/* BCM2048_I2C_FM_RSSI */ +#define BCM2048_RSSI_VALUE 0xff + +/* BCM2048_I2C_FM_RDS_MASK0 */ +/* BCM2048_I2C_FM_RDS_MASK1 */ +#define BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED 0x01 +#define BCM2048_FM_FLAG_SEARCH_TUNE_FAIL 0x02 +#define BCM2048_FM_FLAG_RSSI_LOW 0x04 +#define BCM2048_FM_FLAG_CARRIER_ERROR_HIGH 0x08 +#define BCM2048_FM_FLAG_AUDIO_PAUSE_INDICATION 0x10 +#define BCM2048_FLAG_STEREO_DETECTED 0x20 +#define BCM2048_FLAG_STEREO_ACTIVE 0x40 + +/* BCM2048_I2C_RDS_DATA */ +#define BCM2048_SLAVE_ADDRESS 0x3f +#define BCM2048_SLAVE_ENABLE 0x80 + +/* BCM2048_I2C_FM_BEST_TUNE_MODE */ +#define BCM2048_BEST_TUNE_MODE 0x80 + +#define BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED 0x01 +#define BCM2048_FM_FLAG_SEARCH_TUNE_FAIL 0x02 +#define BCM2048_FM_FLAG_RSSI_LOW 0x04 +#define BCM2048_FM_FLAG_CARRIER_ERROR_HIGH 0x08 +#define BCM2048_FM_FLAG_AUDIO_PAUSE_INDICATION 0x10 +#define BCM2048_FLAG_STEREO_DETECTED 0x20 +#define BCM2048_FLAG_STEREO_ACTIVE 0x40 + +#define BCM2048_RDS_FLAG_FIFO_WLINE 0x02 +#define BCM2048_RDS_FLAG_B_BLOCK_MATCH 0x08 +#define BCM2048_RDS_FLAG_SYNC_LOST 0x10 +#define BCM2048_RDS_FLAG_PI_MATCH 0x20 + +#define BCM2048_RDS_MARK_END_BYTE0 0x7C +#define BCM2048_RDS_MARK_END_BYTEN 0xFF + +#define BCM2048_FM_FLAGS_ALL (FM_FLAG_SEARCH_TUNE_FINISHED | \ + FM_FLAG_SEARCH_TUNE_FAIL | \ + FM_FLAG_RSSI_LOW | \ + FM_FLAG_CARRIER_ERROR_HIGH | \ + FM_FLAG_AUDIO_PAUSE_INDICATION | \ + FLAG_STEREO_DETECTED | FLAG_STEREO_ACTIVE) + +#define BCM2048_RDS_FLAGS_ALL (RDS_FLAG_FIFO_WLINE | \ + RDS_FLAG_B_BLOCK_MATCH | \ + RDS_FLAG_SYNC_LOST | RDS_FLAG_PI_MATCH) + +#define BCM2048_DEFAULT_TIMEOUT 1500 +#define BCM2048_AUTO_SEARCH_TIMEOUT 3000 + + +#define BCM2048_FREQDEV_UNIT 10000 +#define BCM2048_FREQV4L2_MULTI 625 +#define dev_to_v4l2(f) ((f * BCM2048_FREQDEV_UNIT) / BCM2048_FREQV4L2_MULTI) +#define v4l2_to_dev(f) ((f * BCM2048_FREQV4L2_MULTI) / BCM2048_FREQDEV_UNIT) + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) +#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb) + +#define BCM2048_DEFAULT_POWERING_DELAY 20 +#define BCM2048_DEFAULT_REGION 0x02 +#define BCM2048_DEFAULT_MUTE 0x01 +#define BCM2048_DEFAULT_RSSI_THRESHOLD 0x64 +#define BCM2048_DEFAULT_RDS_WLINE 0x7E + +#define BCM2048_FM_SEARCH_INACTIVE 0x00 +#define BCM2048_FM_PRE_SET_MODE 0x01 +#define BCM2048_FM_AUTO_SEARCH_MODE 0x02 +#define BCM2048_FM_AF_JUMP_MODE 0x03 + +#define BCM2048_FREQUENCY_BASE 64000 + +#define BCM2048_POWER_ON 0x01 +#define BCM2048_POWER_OFF 0x00 + +#define BCM2048_ITEM_ENABLED 0x01 +#define BCM2048_SEARCH_DIRECTION_UP 0x01 + +#define BCM2048_DE_EMPHASIS_75us 75 +#define BCM2048_DE_EMPHASIS_50us 50 + +#define BCM2048_SCAN_FAIL 0x00 +#define BCM2048_SCAN_OK 0x01 + +#define BCM2048_FREQ_ERROR_FLOOR -20 +#define BCM2048_FREQ_ERROR_ROOF 20 + +/* -60 dB is reported as full signal strenght */ +#define BCM2048_RSSI_LEVEL_BASE -60 +#define BCM2048_RSSI_LEVEL_ROOF -100 +#define BCM2048_RSSI_LEVEL_ROOF_NEG 100 +#define BCM2048_SIGNAL_MULTIPLIER (0xFFFF / \ + (BCM2048_RSSI_LEVEL_ROOF_NEG + \ + BCM2048_RSSI_LEVEL_BASE)) + +#define BCM2048_RDS_FIFO_DUPLE_SIZE 0x03 +#define BCM2048_RDS_CRC_MASK 0x0F +#define BCM2048_RDS_CRC_NONE 0x00 +#define BCM2048_RDS_CRC_MAX_2BITS 0x04 +#define BCM2048_RDS_CRC_LEAST_2BITS 0x08 +#define BCM2048_RDS_CRC_UNRECOVARABLE 0x0C + +#define BCM2048_RDS_BLOCK_MASK 0xF0 +#define BCM2048_RDS_BLOCK_A 0x00 +#define BCM2048_RDS_BLOCK_B 0x10 +#define BCM2048_RDS_BLOCK_C 0x20 +#define BCM2048_RDS_BLOCK_D 0x30 +#define BCM2048_RDS_BLOCK_C_SCORED 0x40 +#define BCM2048_RDS_BLOCK_E 0x60 + +#define BCM2048_RDS_RT 0x20 +#define BCM2048_RDS_PS 0x00 + +#define BCM2048_RDS_GROUP_AB_MASK 0x08 +#define BCM2048_RDS_GROUP_A 0x00 +#define BCM2048_RDS_GROUP_B 0x08 + +#define BCM2048_RDS_RT_AB_MASK 0x10 +#define BCM2048_RDS_RT_A 0x00 +#define BCM2048_RDS_RT_B 0x10 +#define BCM2048_RDS_RT_INDEX 0x0F + +#define BCM2048_RDS_PS_INDEX 0x03 + +struct rds_info { + u16 rds_pi; +#define BCM2048_MAX_RDS_RT (64 + 1) + u8 rds_rt[BCM2048_MAX_RDS_RT]; + u8 rds_rt_group_b; + u8 rds_rt_ab; +#define BCM2048_MAX_RDS_PS (8 + 1) + u8 rds_ps[BCM2048_MAX_RDS_PS]; + u8 rds_ps_group; + u8 rds_ps_group_cnt; +#define BCM2048_MAX_RDS_RADIO_TEXT 255 + u8 radio_text[BCM2048_MAX_RDS_RADIO_TEXT + 3]; + u8 text_len; +}; + +struct region_info { + u32 bottom_frequency; + u32 top_frequency; + u8 deemphasis; + u8 channel_spacing; + u8 region; +}; + +struct bcm2048_device { + struct i2c_client *client; + struct video_device *videodev; + struct work_struct work; + struct completion compl; + struct mutex mutex; + struct bcm2048_platform_data *platform_data; + struct rds_info rds_info; + struct region_info region_info; + u16 frequency; + u8 cache_fm_rds_system; + u8 cache_fm_ctrl; + u8 cache_fm_audio_ctrl0; + u8 cache_fm_search_ctrl0; + u8 power_state; + u8 rds_state; + u8 fifo_size; + u8 scan_state; + u8 mute_state; + + /* for rds data device read */ + wait_queue_head_t read_queue; + unsigned int users; + unsigned char rds_data_available; + unsigned int rd_index; +}; + +static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */ +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(radio_nr, + "Minor number for radio device (-1 ==> auto assign)"); + +static struct region_info region_configs[] = { + /* USA */ + { + .channel_spacing = 20, + .bottom_frequency = 87500, + .top_frequency = 108000, + .deemphasis = 75, + .region = 0, + }, + /* Australia */ + { + .channel_spacing = 20, + .bottom_frequency = 87500, + .top_frequency = 108000, + .deemphasis = 50, + .region = 1, + }, + /* Europe */ + { + .channel_spacing = 10, + .bottom_frequency = 87500, + .top_frequency = 108000, + .deemphasis = 50, + .region = 2, + }, + /* Japan */ + { + .channel_spacing = 10, + .bottom_frequency = 76000, + .top_frequency = 90000, + .deemphasis = 50, + .region = 3, + }, + /* Japan wide band */ + { + .channel_spacing = 10, + .bottom_frequency = 76000, + .top_frequency = 108000, + .deemphasis = 50, + .region = 4, + }, +}; + +/* + * I2C Interface read / write + */ +static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg, + unsigned int value) +{ + struct i2c_client *client = bdev->client; + u8 data[2]; + + if (!bdev->power_state) { + dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n"); + return -EIO; + } + + data[0] = reg & 0xff; + data[1] = value & 0xff; + + if (i2c_master_send(client, data, 2) == 2) { + return 0; + } else { + dev_err(&bdev->client->dev, "BCM I2C error!\n"); + dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n"); + return -EIO; + } +} + +static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg, + u8 *value) +{ + struct i2c_client *client = bdev->client; + + if (!bdev->power_state) { + dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n"); + return -EIO; + } + + value[0] = i2c_smbus_read_byte_data(client, reg & 0xff); + + return 0; +} + +static int bcm2048_recv_duples(struct bcm2048_device *bdev, unsigned int reg, + u8 *value, u8 duples) +{ + struct i2c_client *client = bdev->client; + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg[2]; + u8 buf; + + if (!bdev->power_state) { + dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n"); + return -EIO; + } + + buf = reg & 0xff; + + msg[0].addr = client->addr; + msg[0].flags = client->flags & I2C_M_TEN; + msg[0].len = 1; + msg[0].buf = &buf; + + msg[1].addr = client->addr; + msg[1].flags = client->flags & I2C_M_TEN; + msg[1].flags |= I2C_M_RD; + msg[1].len = duples; + msg[1].buf = value; + + return i2c_transfer(adap, msg, 2); +} + +/* + * BCM2048 - I2C register programming helpers + */ +static int bcm2048_set_power_state(struct bcm2048_device *bdev, u8 power) +{ + int err = 0; + + mutex_lock(&bdev->mutex); + + if (power) { + bdev->power_state = BCM2048_POWER_ON; + bdev->cache_fm_rds_system |= BCM2048_FM_ON; + } else { + bdev->cache_fm_rds_system &= ~BCM2048_FM_ON; + } + + /* + * Warning! FM cannot be turned off because then + * the I2C communications get ruined! + * Comment off the "if (power)" when the chip works! + */ + if (power) + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, + bdev->cache_fm_rds_system); + msleep(BCM2048_DEFAULT_POWERING_DELAY); + + if (!power) + bdev->power_state = BCM2048_POWER_OFF; + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_power_state(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, &value); + + mutex_unlock(&bdev->mutex); + + if (!err && (value & BCM2048_FM_ON)) + return BCM2048_POWER_ON; + + return err; +} + +static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on) +{ + int err; + u8 flags; + + bdev->cache_fm_rds_system &= ~BCM2048_RDS_ON; + + if (rds_on) { + bdev->cache_fm_rds_system |= BCM2048_RDS_ON; + bdev->rds_state = BCM2048_RDS_ON; + flags = BCM2048_RDS_FLAG_FIFO_WLINE; + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, + flags); + } else { + flags = 0; + bdev->rds_state = 0; + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, + flags); + memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); + } + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, + bdev->cache_fm_rds_system); + + return err; +} + +static int bcm2048_get_rds_no_lock(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, &value); + + if (!err && (value & BCM2048_RDS_ON)) + return BCM2048_ITEM_ENABLED; + + return err; +} + +static int bcm2048_set_rds(struct bcm2048_device *bdev, u8 rds_on) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_set_rds_no_lock(bdev, rds_on); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds(struct bcm2048_device *bdev) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_get_rds_no_lock(bdev); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_pi(struct bcm2048_device *bdev) +{ + return bdev->rds_info.rds_pi; +} + +static int bcm2048_set_fm_automatic_stereo_mono(struct bcm2048_device *bdev, + u8 enabled) +{ + int err; + + mutex_lock(&bdev->mutex); + + bdev->cache_fm_ctrl &= ~BCM2048_STEREO_MONO_AUTO_SELECT; + + if (enabled) + bdev->cache_fm_ctrl |= BCM2048_STEREO_MONO_AUTO_SELECT; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL, + bdev->cache_fm_ctrl); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_set_fm_hi_lo_injection(struct bcm2048_device *bdev, + u8 hi_lo) +{ + int err; + + mutex_lock(&bdev->mutex); + + bdev->cache_fm_ctrl &= ~BCM2048_HI_LO_INJECTION; + + if (hi_lo) + bdev->cache_fm_ctrl |= BCM2048_HI_LO_INJECTION; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL, + bdev->cache_fm_ctrl); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_hi_lo_injection(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_CTRL, &value); + + mutex_unlock(&bdev->mutex); + + if (!err && (value & BCM2048_HI_LO_INJECTION)) + return BCM2048_ITEM_ENABLED; + + return err; +} + +static int bcm2048_set_fm_frequency(struct bcm2048_device *bdev, u32 frequency) +{ + int err; + + if (frequency < bdev->region_info.bottom_frequency || + frequency > bdev->region_info.top_frequency) + return -EDOM; + + frequency -= BCM2048_FREQUENCY_BASE; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ0, lsb(frequency)); + err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ1, + msb(frequency)); + + if (!err) + bdev->frequency = frequency; + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_frequency(struct bcm2048_device *bdev) +{ + int err; + u8 lsb, msb; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_FREQ0, &lsb); + err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_FREQ1, &msb); + + mutex_unlock(&bdev->mutex); + + if (err) + return err; + + err = compose_u16(msb, lsb); + err += BCM2048_FREQUENCY_BASE; + + return err; +} + +static int bcm2048_set_fm_af_frequency(struct bcm2048_device *bdev, + u32 frequency) +{ + int err; + + if (frequency < bdev->region_info.bottom_frequency || + frequency > bdev->region_info.top_frequency) + return -EDOM; + + frequency -= BCM2048_FREQUENCY_BASE; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ0, + lsb(frequency)); + err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ1, + msb(frequency)); + if (!err) + bdev->frequency = frequency; + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_af_frequency(struct bcm2048_device *bdev) +{ + int err; + u8 lsb, msb; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AF_FREQ0, &lsb); + err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_AF_FREQ1, &msb); + + mutex_unlock(&bdev->mutex); + + if (err) + return err; + + err = compose_u16(msb, lsb); + err += BCM2048_FREQUENCY_BASE; + + return err; +} + +static int bcm2048_set_fm_deemphasis(struct bcm2048_device *bdev, int d) +{ + int err; + u8 deemphasis; + + if (d == BCM2048_DE_EMPHASIS_75us) + deemphasis = BCM2048_DE_EMPHASIS_SELECT; + else + deemphasis = 0; + + mutex_lock(&bdev->mutex); + + bdev->cache_fm_audio_ctrl0 &= ~BCM2048_DE_EMPHASIS_SELECT; + bdev->cache_fm_audio_ctrl0 |= deemphasis; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, + bdev->cache_fm_audio_ctrl0); + + if (!err) + bdev->region_info.deemphasis = d; + + mutex_unlock(&bdev->mutex); + + return err; +} + +static int bcm2048_get_fm_deemphasis(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value); + + mutex_unlock(&bdev->mutex); + + if (!err) { + if (value & BCM2048_DE_EMPHASIS_SELECT) + return BCM2048_DE_EMPHASIS_75us; + else + return BCM2048_DE_EMPHASIS_50us; + } + + return err; +} + +static int bcm2048_set_region(struct bcm2048_device *bdev, u8 region) +{ + int err; + u32 new_frequency = 0; + + if (region > ARRAY_SIZE(region_configs)) + return -EINVAL; + + mutex_lock(&bdev->mutex); + memcpy(&bdev->region_info, ®ion_configs[region], + sizeof(struct region_info)); + mutex_unlock(&bdev->mutex); + + if (bdev->frequency < region_configs[region].bottom_frequency || + bdev->frequency > region_configs[region].top_frequency) + new_frequency = region_configs[region].bottom_frequency; + + if (new_frequency > 0) { + err = bcm2048_set_fm_frequency(bdev, new_frequency); + + if (err) + goto done; + } + + err = bcm2048_set_fm_deemphasis(bdev, + region_configs[region].deemphasis); + +done: + return err; +} + +static int bcm2048_get_region(struct bcm2048_device *bdev) +{ + int err; + + mutex_lock(&bdev->mutex); + err = bdev->region_info.region; + mutex_unlock(&bdev->mutex); + + return err; +} + +static int bcm2048_set_mute(struct bcm2048_device *bdev, u16 mute) +{ + int err; + + mutex_lock(&bdev->mutex); + + bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE); + + if (mute) + bdev->cache_fm_audio_ctrl0 |= (BCM2048_RF_MUTE | + BCM2048_MANUAL_MUTE); + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, + bdev->cache_fm_audio_ctrl0); + + if (!err) + bdev->mute_state = mute; + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_mute(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + if (bdev->power_state) { + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, + &value); + if (!err) + err = value & (BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE); + } else { + err = bdev->mute_state; + } + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_set_audio_route(struct bcm2048_device *bdev, u8 route) +{ + int err; + + mutex_lock(&bdev->mutex); + + route &= (BCM2048_AUDIO_ROUTE_DAC | BCM2048_AUDIO_ROUTE_I2S); + bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_AUDIO_ROUTE_DAC | + BCM2048_AUDIO_ROUTE_I2S); + bdev->cache_fm_audio_ctrl0 |= route; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, + bdev->cache_fm_audio_ctrl0); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_audio_route(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value); + + mutex_unlock(&bdev->mutex); + + if (!err) + return value & (BCM2048_AUDIO_ROUTE_DAC | + BCM2048_AUDIO_ROUTE_I2S); + + return err; +} + +static int bcm2048_set_dac_output(struct bcm2048_device *bdev, u8 channels) +{ + int err; + + mutex_lock(&bdev->mutex); + + bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_DAC_OUTPUT_LEFT | + BCM2048_DAC_OUTPUT_RIGHT); + bdev->cache_fm_audio_ctrl0 |= channels; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, + bdev->cache_fm_audio_ctrl0); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_dac_output(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value); + + mutex_unlock(&bdev->mutex); + + if (!err) + return value & (BCM2048_DAC_OUTPUT_LEFT | + BCM2048_DAC_OUTPUT_RIGHT); + + return err; +} + +static int bcm2048_set_fm_search_rssi_threshold(struct bcm2048_device *bdev, + u8 threshold) +{ + int err; + + mutex_lock(&bdev->mutex); + + threshold &= BCM2048_SEARCH_RSSI_THRESHOLD; + bdev->cache_fm_search_ctrl0 &= ~BCM2048_SEARCH_RSSI_THRESHOLD; + bdev->cache_fm_search_ctrl0 |= threshold; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, + bdev->cache_fm_search_ctrl0); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_search_rssi_threshold(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, &value); + + mutex_unlock(&bdev->mutex); + + if (!err) + return value & BCM2048_SEARCH_RSSI_THRESHOLD; + + return err; +} + +static int bcm2048_set_fm_search_mode_direction(struct bcm2048_device *bdev, + u8 direction) +{ + int err; + + mutex_lock(&bdev->mutex); + + bdev->cache_fm_search_ctrl0 &= ~BCM2048_SEARCH_DIRECTION; + + if (direction) + bdev->cache_fm_search_ctrl0 |= BCM2048_SEARCH_DIRECTION; + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, + bdev->cache_fm_search_ctrl0); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_search_mode_direction(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, &value); + + mutex_unlock(&bdev->mutex); + + if (!err && (value & BCM2048_SEARCH_DIRECTION)) + return BCM2048_SEARCH_DIRECTION_UP; + + return err; +} + +static int bcm2048_set_fm_search_tune_mode(struct bcm2048_device *bdev, + u8 mode) +{ + int err, timeout, restart_rds = 0; + u8 value, flags; + + value = mode & BCM2048_FM_AUTO_SEARCH; + + flags = BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED | + BCM2048_FM_FLAG_SEARCH_TUNE_FAIL; + + mutex_lock(&bdev->mutex); + + /* + * If RDS is enabled, and frequency is changed, RDS quits working. + * Thus, always restart RDS if it's enabled. Moreover, RDS must + * not be enabled while changing the frequency because it can + * provide a race to the mutex from the workqueue handler if RDS + * IRQ occurs while waiting for frequency changed IRQ. + */ + if (bcm2048_get_rds_no_lock(bdev)) { + err = bcm2048_set_rds_no_lock(bdev, 0); + if (err) + goto unlock; + restart_rds = 1; + } + + err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK0, flags); + + if (err) + goto unlock; + + bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE, value); + + if (mode != BCM2048_FM_AUTO_SEARCH_MODE) + timeout = BCM2048_DEFAULT_TIMEOUT; + else + timeout = BCM2048_AUTO_SEARCH_TIMEOUT; + + if (!wait_for_completion_timeout(&bdev->compl, + msecs_to_jiffies(timeout))) + dev_err(&bdev->client->dev, "IRQ timeout.\n"); + + if (value) + if (!bdev->scan_state) + err = -EIO; + +unlock: + if (restart_rds) + err |= bcm2048_set_rds_no_lock(bdev, 1); + + mutex_unlock(&bdev->mutex); + + return err; +} + +static int bcm2048_get_fm_search_tune_mode(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE, + &value); + + mutex_unlock(&bdev->mutex); + + if (!err) + return value & BCM2048_FM_AUTO_SEARCH; + + return err; +} + +static int bcm2048_set_rds_b_block_mask(struct bcm2048_device *bdev, u16 mask) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, + BCM2048_I2C_RDS_BLKB_MASK0, lsb(mask)); + err |= bcm2048_send_command(bdev, + BCM2048_I2C_RDS_BLKB_MASK1, msb(mask)); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_b_block_mask(struct bcm2048_device *bdev) +{ + int err; + u8 lsb, msb; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_BLKB_MASK0, &lsb); + err |= bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_BLKB_MASK1, &msb); + + mutex_unlock(&bdev->mutex); + + if (!err) + return compose_u16(msb, lsb); + + return err; +} + +static int bcm2048_set_rds_b_block_match(struct bcm2048_device *bdev, + u16 match) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, + BCM2048_I2C_RDS_BLKB_MATCH0, lsb(match)); + err |= bcm2048_send_command(bdev, + BCM2048_I2C_RDS_BLKB_MATCH1, msb(match)); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_b_block_match(struct bcm2048_device *bdev) +{ + int err; + u8 lsb, msb; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_BLKB_MATCH0, &lsb); + err |= bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_BLKB_MATCH1, &msb); + + mutex_unlock(&bdev->mutex); + + if (!err) + return compose_u16(msb, lsb); + + return err; +} + +static int bcm2048_set_rds_pi_mask(struct bcm2048_device *bdev, u16 mask) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, + BCM2048_I2C_RDS_PI_MASK0, lsb(mask)); + err |= bcm2048_send_command(bdev, + BCM2048_I2C_RDS_PI_MASK1, msb(mask)); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_pi_mask(struct bcm2048_device *bdev) +{ + int err; + u8 lsb, msb; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_PI_MASK0, &lsb); + err |= bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_PI_MASK1, &msb); + + mutex_unlock(&bdev->mutex); + + if (!err) + return compose_u16(msb, lsb); + + return err; +} + +static int bcm2048_set_rds_pi_match(struct bcm2048_device *bdev, u16 match) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, + BCM2048_I2C_RDS_PI_MATCH0, lsb(match)); + err |= bcm2048_send_command(bdev, + BCM2048_I2C_RDS_PI_MATCH1, msb(match)); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_pi_match(struct bcm2048_device *bdev) +{ + int err; + u8 lsb, msb; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_PI_MATCH0, &lsb); + err |= bcm2048_recv_command(bdev, + BCM2048_I2C_RDS_PI_MATCH1, &msb); + + mutex_unlock(&bdev->mutex); + + if (!err) + return compose_u16(msb, lsb); + + return err; +} + +static int bcm2048_set_fm_rds_mask(struct bcm2048_device *bdev, u16 mask) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, + BCM2048_I2C_FM_RDS_MASK0, lsb(mask)); + err |= bcm2048_send_command(bdev, + BCM2048_I2C_FM_RDS_MASK1, msb(mask)); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_rds_mask(struct bcm2048_device *bdev) +{ + int err; + u8 value0, value1; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_MASK0, &value0); + err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_MASK1, &value1); + + mutex_unlock(&bdev->mutex); + + if (!err) + return compose_u16(value1, value0); + + return err; +} + +static int bcm2048_get_fm_rds_flags(struct bcm2048_device *bdev) +{ + int err; + u8 value0, value1; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &value0); + err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG1, &value1); + + mutex_unlock(&bdev->mutex); + + if (!err) + return compose_u16(value1, value0); + + return err; +} + +static int bcm2048_get_region_bottom_frequency(struct bcm2048_device *bdev) +{ + return bdev->region_info.bottom_frequency; +} + +static int bcm2048_get_region_top_frequency(struct bcm2048_device *bdev) +{ + return bdev->region_info.top_frequency; +} + +static int bcm2048_set_fm_best_tune_mode(struct bcm2048_device *bdev, u8 mode) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + /* Perform read as the manual indicates */ + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE, + &value); + value &= ~BCM2048_BEST_TUNE_MODE; + + if (mode) + value |= BCM2048_BEST_TUNE_MODE; + err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE, + value); + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_fm_best_tune_mode(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE, + &value); + + mutex_unlock(&bdev->mutex); + + if (!err && (value & BCM2048_BEST_TUNE_MODE)) + return BCM2048_ITEM_ENABLED; + + return err; +} + +static int bcm2048_get_fm_carrier_error(struct bcm2048_device *bdev) +{ + int err = 0; + s8 value; + + mutex_lock(&bdev->mutex); + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_CARRIER, &value); + mutex_unlock(&bdev->mutex); + + if (!err) + return value; + + return err; +} + +static int bcm2048_get_fm_rssi(struct bcm2048_device *bdev) +{ + int err; + s8 value; + + mutex_lock(&bdev->mutex); + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RSSI, &value); + mutex_unlock(&bdev->mutex); + + if (!err) + return value; + + return err; +} + +static int bcm2048_set_rds_wline(struct bcm2048_device *bdev, u8 wline) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_WLINE, wline); + + if (!err) + bdev->fifo_size = wline; + + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_wline(struct bcm2048_device *bdev) +{ + int err; + u8 value; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_WLINE, &value); + + mutex_unlock(&bdev->mutex); + + if (!err) { + bdev->fifo_size = value; + return value; + } + + return err; +} + +static int bcm2048_checkrev(struct bcm2048_device *bdev) +{ + int err; + u8 version; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_REV, &version); + + mutex_unlock(&bdev->mutex); + + if (!err) { + dev_info(&bdev->client->dev, "BCM2048 Version 0x%x\n", + version); + return version; + } + + return err; +} + +static int bcm2048_get_rds_rt(struct bcm2048_device *bdev, char *data) +{ + int err = 0, i, j = 0, ce = 0, cr = 0; + char data_buffer[BCM2048_MAX_RDS_RT+1]; + + mutex_lock(&bdev->mutex); + + if (!bdev->rds_info.text_len) { + err = -EINVAL; + goto unlock; + } + + for (i = 0; i < BCM2048_MAX_RDS_RT; i++) { + if (bdev->rds_info.rds_rt[i]) { + ce = i; + /* Skip the carriage return */ + if (bdev->rds_info.rds_rt[i] != 0x0d) { + data_buffer[j++] = bdev->rds_info.rds_rt[i]; + } else { + cr = i; + break; + } + } + } + + if (j <= BCM2048_MAX_RDS_RT) + data_buffer[j] = 0; + + for (i = 0; i < BCM2048_MAX_RDS_RT; i++) { + if (!bdev->rds_info.rds_rt[i]) { + if (cr && (i < cr)) { + err = -EBUSY; + goto unlock; + } + if (i < ce) { + if (cr && (i >= cr)) + break; + err = -EBUSY; + goto unlock; + } + } + } + + memcpy(data, data_buffer, sizeof(data_buffer)); + +unlock: + mutex_unlock(&bdev->mutex); + return err; +} + +static int bcm2048_get_rds_ps(struct bcm2048_device *bdev, char *data) +{ + int err = 0, i, j = 0; + char data_buffer[BCM2048_MAX_RDS_PS+1]; + + mutex_lock(&bdev->mutex); + + if (!bdev->rds_info.text_len) { + err = -EINVAL; + goto unlock; + } + + for (i = 0; i < BCM2048_MAX_RDS_PS; i++) { + if (bdev->rds_info.rds_ps[i]) { + data_buffer[j++] = bdev->rds_info.rds_ps[i]; + } else { + if (i < (BCM2048_MAX_RDS_PS - 1)) { + err = -EBUSY; + goto unlock; + } + } + } + + if (j <= BCM2048_MAX_RDS_PS) + data_buffer[j] = 0; + + memcpy(data, data_buffer, sizeof(data_buffer)); + +unlock: + mutex_unlock(&bdev->mutex); + return err; +} + +static void bcm2048_parse_rds_pi(struct bcm2048_device *bdev) +{ + int i, cnt = 0; + u16 pi; + + for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) { + + /* Block A match, only data without crc errors taken */ + if (bdev->rds_info.radio_text[i] == BCM2048_RDS_BLOCK_A) { + + pi = ((bdev->rds_info.radio_text[i+1] << 8) + + bdev->rds_info.radio_text[i+2]); + + if (!bdev->rds_info.rds_pi) { + bdev->rds_info.rds_pi = pi; + return; + } + if (pi != bdev->rds_info.rds_pi) { + cnt++; + if (cnt > 3) { + bdev->rds_info.rds_pi = pi; + cnt = 0; + } + } else { + cnt = 0; + } + } + } +} + +static int bcm2048_rds_block_crc(struct bcm2048_device *bdev, int i) +{ + return bdev->rds_info.radio_text[i] & BCM2048_RDS_CRC_MASK; +} + +static void bcm2048_parse_rds_rt_block(struct bcm2048_device *bdev, int i, + int index, int crc) +{ + /* Good data will overwrite poor data */ + if (crc) { + if (!bdev->rds_info.rds_rt[index]) + bdev->rds_info.rds_rt[index] = + bdev->rds_info.radio_text[i+1]; + if (!bdev->rds_info.rds_rt[index+1]) + bdev->rds_info.rds_rt[index+1] = + bdev->rds_info.radio_text[i+2]; + } else { + bdev->rds_info.rds_rt[index] = bdev->rds_info.radio_text[i+1]; + bdev->rds_info.rds_rt[index+1] = + bdev->rds_info.radio_text[i+2]; + } +} + +static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i) +{ + int crc, rt_id, rt_group_b, rt_ab, index = 0; + + crc = bcm2048_rds_block_crc(bdev, i); + + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + return -EIO; + + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == + BCM2048_RDS_BLOCK_B) { + + rt_id = (bdev->rds_info.radio_text[i+1] & + BCM2048_RDS_BLOCK_MASK); + rt_group_b = bdev->rds_info.radio_text[i+1] & + BCM2048_RDS_GROUP_AB_MASK; + rt_ab = bdev->rds_info.radio_text[i+2] & + BCM2048_RDS_RT_AB_MASK; + + if (rt_group_b != bdev->rds_info.rds_rt_group_b) { + memset(bdev->rds_info.rds_rt, 0, + sizeof(bdev->rds_info.rds_rt)); + bdev->rds_info.rds_rt_group_b = rt_group_b; + } + + if (rt_id == BCM2048_RDS_RT) { + /* A to B or (vice versa), means: clear screen */ + if (rt_ab != bdev->rds_info.rds_rt_ab) { + memset(bdev->rds_info.rds_rt, 0, + sizeof(bdev->rds_info.rds_rt)); + bdev->rds_info.rds_rt_ab = rt_ab; + } + + index = bdev->rds_info.radio_text[i+2] & + BCM2048_RDS_RT_INDEX; + + if (bdev->rds_info.rds_rt_group_b) + index <<= 1; + else + index <<= 2; + + return index; + } + } + + return -EIO; +} + +static int bcm2048_parse_rt_match_c(struct bcm2048_device *bdev, int i, + int index) +{ + int crc; + + crc = bcm2048_rds_block_crc(bdev, i); + + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + return 0; + + BUG_ON((index+2) >= BCM2048_MAX_RDS_RT); + + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == + BCM2048_RDS_BLOCK_C) { + if (bdev->rds_info.rds_rt_group_b) + return 1; + bcm2048_parse_rds_rt_block(bdev, i, index, crc); + return 1; + } + + return 0; +} + +static void bcm2048_parse_rt_match_d(struct bcm2048_device *bdev, int i, + int index) +{ + int crc; + + crc = bcm2048_rds_block_crc(bdev, i); + + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + return; + + BUG_ON((index+4) >= BCM2048_MAX_RDS_RT); + + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == + BCM2048_RDS_BLOCK_D) + bcm2048_parse_rds_rt_block(bdev, i, index+2, crc); +} + +static int bcm2048_parse_rds_rt(struct bcm2048_device *bdev) +{ + int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0; + + for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) { + + if (match_b) { + match_b = 0; + index = bcm2048_parse_rt_match_b(bdev, i); + if (index >= 0 && index <= (BCM2048_MAX_RDS_RT - 5)) + match_c = 1; + continue; + } else if (match_c) { + match_c = 0; + if (bcm2048_parse_rt_match_c(bdev, i, index)) + match_d = 1; + continue; + } else if (match_d) { + match_d = 0; + bcm2048_parse_rt_match_d(bdev, i, index); + continue; + } + + /* Skip erroneous blocks due to messed up A block altogether */ + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) + == BCM2048_RDS_BLOCK_A) { + crc = bcm2048_rds_block_crc(bdev, i); + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + continue; + /* Syncronize to a good RDS PI */ + if (((bdev->rds_info.radio_text[i+1] << 8) + + bdev->rds_info.radio_text[i+2]) == + bdev->rds_info.rds_pi) + match_b = 1; + } + } + + return 0; +} + +static void bcm2048_parse_rds_ps_block(struct bcm2048_device *bdev, int i, + int index, int crc) +{ + /* Good data will overwrite poor data */ + if (crc) { + if (!bdev->rds_info.rds_ps[index]) + bdev->rds_info.rds_ps[index] = + bdev->rds_info.radio_text[i+1]; + if (!bdev->rds_info.rds_ps[index+1]) + bdev->rds_info.rds_ps[index+1] = + bdev->rds_info.radio_text[i+2]; + } else { + bdev->rds_info.rds_ps[index] = bdev->rds_info.radio_text[i+1]; + bdev->rds_info.rds_ps[index+1] = + bdev->rds_info.radio_text[i+2]; + } +} + +static int bcm2048_parse_ps_match_c(struct bcm2048_device *bdev, int i, + int index) +{ + int crc; + + crc = bcm2048_rds_block_crc(bdev, i); + + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + return 0; + + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == + BCM2048_RDS_BLOCK_C) + return 1; + + return 0; +} + +static void bcm2048_parse_ps_match_d(struct bcm2048_device *bdev, int i, + int index) +{ + int crc; + + crc = bcm2048_rds_block_crc(bdev, i); + + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + return; + + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == + BCM2048_RDS_BLOCK_D) + bcm2048_parse_rds_ps_block(bdev, i, index, crc); +} + +static int bcm2048_parse_ps_match_b(struct bcm2048_device *bdev, int i) +{ + int crc, index, ps_id, ps_group; + + crc = bcm2048_rds_block_crc(bdev, i); + + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + return -EIO; + + /* Block B Radio PS match */ + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) == + BCM2048_RDS_BLOCK_B) { + ps_id = bdev->rds_info.radio_text[i+1] & + BCM2048_RDS_BLOCK_MASK; + ps_group = bdev->rds_info.radio_text[i+1] & + BCM2048_RDS_GROUP_AB_MASK; + + /* + * Poor RSSI will lead to RDS data corruption + * So using 3 (same) sequential values to justify major changes + */ + if (ps_group != bdev->rds_info.rds_ps_group) { + if (crc == BCM2048_RDS_CRC_NONE) { + bdev->rds_info.rds_ps_group_cnt++; + if (bdev->rds_info.rds_ps_group_cnt > 2) { + bdev->rds_info.rds_ps_group = ps_group; + bdev->rds_info.rds_ps_group_cnt = 0; + dev_err(&bdev->client->dev, + "RDS PS Group change!\n"); + } else { + return -EIO; + } + } else { + bdev->rds_info.rds_ps_group_cnt = 0; + } + } + + if (ps_id == BCM2048_RDS_PS) { + index = bdev->rds_info.radio_text[i+2] & + BCM2048_RDS_PS_INDEX; + index <<= 1; + return index; + } + } + + return -EIO; +} + +static void bcm2048_parse_rds_ps(struct bcm2048_device *bdev) +{ + int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0; + + for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) { + + if (match_b) { + match_b = 0; + index = bcm2048_parse_ps_match_b(bdev, i); + if (index >= 0 && index < (BCM2048_MAX_RDS_PS - 1)) + match_c = 1; + continue; + } else if (match_c) { + match_c = 0; + if (bcm2048_parse_ps_match_c(bdev, i, index)) + match_d = 1; + continue; + } else if (match_d) { + match_d = 0; + bcm2048_parse_ps_match_d(bdev, i, index); + continue; + } + + /* Skip erroneous blocks due to messed up A block altogether */ + if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) + == BCM2048_RDS_BLOCK_A) { + crc = bcm2048_rds_block_crc(bdev, i); + if (crc == BCM2048_RDS_CRC_UNRECOVARABLE) + continue; + /* Syncronize to a good RDS PI */ + if (((bdev->rds_info.radio_text[i+1] << 8) + + bdev->rds_info.radio_text[i+2]) == + bdev->rds_info.rds_pi) + match_b = 1; + } + } +} + +static void bcm2048_rds_fifo_receive(struct bcm2048_device *bdev) +{ + int err; + + mutex_lock(&bdev->mutex); + + err = bcm2048_recv_duples(bdev, BCM2048_I2C_RDS_DATA, + bdev->rds_info.radio_text, bdev->fifo_size); + if (err != 2) { + dev_err(&bdev->client->dev, "RDS Read problem\n"); + return; + } + + bdev->rds_info.text_len = bdev->fifo_size; + + bcm2048_parse_rds_pi(bdev); + bcm2048_parse_rds_rt(bdev); + bcm2048_parse_rds_ps(bdev); + + mutex_unlock(&bdev->mutex); + + wake_up_interruptible(&bdev->read_queue); +} + +static int bcm2048_get_rds_data(struct bcm2048_device *bdev, char *data) +{ + int err = 0, i, p = 0; + char *data_buffer; + + mutex_lock(&bdev->mutex); + + if (!bdev->rds_info.text_len) { + err = -EINVAL; + goto unlock; + } + + data_buffer = kzalloc(BCM2048_MAX_RDS_RADIO_TEXT*5, GFP_KERNEL); + if (!data_buffer) { + err = -ENOMEM; + goto unlock; + } + + for (i = 0; i < bdev->rds_info.text_len; i++) { + p += sprintf(data_buffer+p, "%x ", + bdev->rds_info.radio_text[i]); + } + + memcpy(data, data_buffer, p); + kfree(data_buffer); + +unlock: + mutex_unlock(&bdev->mutex); + return err; +} + +/* + * BCM2048 default initialization sequence + */ +static int bcm2048_init(struct bcm2048_device *bdev) +{ + int err; + + err = bcm2048_set_power_state(bdev, BCM2048_POWER_ON); + if (err < 0) + goto exit; + + err = bcm2048_set_audio_route(bdev, BCM2048_AUDIO_ROUTE_DAC); + if (err < 0) + goto exit; + + err = bcm2048_set_dac_output(bdev, BCM2048_DAC_OUTPUT_LEFT | + BCM2048_DAC_OUTPUT_RIGHT); + +exit: + return err; +} + +/* + * BCM2048 default deinitialization sequence + */ +static int bcm2048_deinit(struct bcm2048_device *bdev) +{ + int err; + + err = bcm2048_set_audio_route(bdev, 0); + if (err < 0) + goto exit; + + err = bcm2048_set_dac_output(bdev, 0); + if (err < 0) + goto exit; + + err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); + if (err < 0) + goto exit; + +exit: + return err; +} + +/* + * BCM2048 probe sequence + */ +static int bcm2048_probe(struct bcm2048_device *bdev) +{ + int err; + + err = bcm2048_set_power_state(bdev, BCM2048_POWER_ON); + if (err < 0) + goto unlock; + + err = bcm2048_checkrev(bdev); + if (err < 0) + goto unlock; + + err = bcm2048_set_mute(bdev, BCM2048_DEFAULT_MUTE); + if (err < 0) + goto unlock; + + err = bcm2048_set_region(bdev, BCM2048_DEFAULT_REGION); + if (err < 0) + goto unlock; + + err = bcm2048_set_fm_search_rssi_threshold(bdev, + BCM2048_DEFAULT_RSSI_THRESHOLD); + if (err < 0) + goto unlock; + + err = bcm2048_set_fm_automatic_stereo_mono(bdev, BCM2048_ITEM_ENABLED); + if (err < 0) + goto unlock; + + err = bcm2048_get_rds_wline(bdev); + if (err < BCM2048_DEFAULT_RDS_WLINE) + err = bcm2048_set_rds_wline(bdev, BCM2048_DEFAULT_RDS_WLINE); + if (err < 0) + goto unlock; + + err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); + + init_waitqueue_head(&bdev->read_queue); + bdev->rds_data_available = 0; + bdev->rd_index = 0; + bdev->users = 0; + +unlock: + return err; +} + +/* + * BCM2048 workqueue handler + */ +static void bcm2048_work(struct work_struct *work) +{ + struct bcm2048_device *bdev; + u8 flag_lsb, flag_msb, flags; + + bdev = container_of(work, struct bcm2048_device, work); + bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &flag_lsb); + bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG1, &flag_msb); + + if (flag_lsb & (BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED | + BCM2048_FM_FLAG_SEARCH_TUNE_FAIL)) { + + if (flag_lsb & BCM2048_FM_FLAG_SEARCH_TUNE_FAIL) + bdev->scan_state = BCM2048_SCAN_FAIL; + else + bdev->scan_state = BCM2048_SCAN_OK; + + complete(&bdev->compl); + } + + if (flag_msb & BCM2048_RDS_FLAG_FIFO_WLINE) { + bcm2048_rds_fifo_receive(bdev); + if (bdev->rds_state) { + flags = BCM2048_RDS_FLAG_FIFO_WLINE; + bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1, + flags); + } + bdev->rds_data_available = 1; + bdev->rd_index = 0; /* new data, new start */ + } +} + +/* + * BCM2048 interrupt handler + */ +static irqreturn_t bcm2048_handler(int irq, void *dev) +{ + struct bcm2048_device *bdev = dev; + + dev_dbg(&bdev->client->dev, "IRQ called, queuing work\n"); + if (bdev->power_state) + schedule_work(&bdev->work); + + return IRQ_HANDLED; +} + +/* + * BCM2048 sysfs interface definitions + */ +#define property_write(prop, type, mask, check) \ +static ssize_t bcm2048_##prop##_write(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t count) \ +{ \ + struct bcm2048_device *bdev = dev_get_drvdata(dev); \ + type value; \ + int err; \ + \ + if (!bdev) \ + return -ENODEV; \ + \ + sscanf(buf, mask, &value); \ + \ + if (check) \ + return -EDOM; \ + \ + err = bcm2048_set_##prop(bdev, value); \ + \ + return err < 0 ? err : count; \ +} + +#define property_read(prop, size, mask) \ +static ssize_t bcm2048_##prop##_read(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct bcm2048_device *bdev = dev_get_drvdata(dev); \ + size value; \ + \ + if (!bdev) \ + return -ENODEV; \ + \ + value = bcm2048_get_##prop(bdev); \ + \ + if (value >= 0) \ + value = sprintf(buf, mask "\n", value); \ + \ + return value; \ +} + +#define property_signed_read(prop, size, mask) \ +static ssize_t bcm2048_##prop##_read(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct bcm2048_device *bdev = dev_get_drvdata(dev); \ + size value; \ + \ + if (!bdev) \ + return -ENODEV; \ + \ + value = bcm2048_get_##prop(bdev); \ + \ + value = sprintf(buf, mask "\n", value); \ + \ + return value; \ +} + +#define DEFINE_SYSFS_PROPERTY(prop, signal, size, mask, check) \ +property_write(prop, signal size, mask, check) \ +property_read(prop, size, mask) + +#define property_str_read(prop, size) \ +static ssize_t bcm2048_##prop##_read(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct bcm2048_device *bdev = dev_get_drvdata(dev); \ + int count; \ + u8 *out; \ + \ + if (!bdev) \ + return -ENODEV; \ + \ + out = kzalloc(size + 1, GFP_KERNEL); \ + if (!out) \ + return -ENOMEM; \ + \ + bcm2048_get_##prop(bdev, out); \ + count = sprintf(buf, "%s\n", out); \ + \ + kfree(out); \ + \ + return count; \ +} + +DEFINE_SYSFS_PROPERTY(power_state, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(mute, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(audio_route, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(dac_output, unsigned, int, "%u", 0) + +DEFINE_SYSFS_PROPERTY(fm_hi_lo_injection, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_frequency, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_af_frequency, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_deemphasis, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_rds_mask, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_best_tune_mode, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_search_rssi_threshold, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_search_mode_direction, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(fm_search_tune_mode, unsigned, int, "%u", value > 3) + +DEFINE_SYSFS_PROPERTY(rds, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(rds_b_block_mask, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(rds_b_block_match, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(rds_pi_mask, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(rds_pi_match, unsigned, int, "%u", 0) +DEFINE_SYSFS_PROPERTY(rds_wline, unsigned, int, "%u", 0) +property_read(rds_pi, unsigned int, "%x") +property_str_read(rds_rt, (BCM2048_MAX_RDS_RT + 1)) +property_str_read(rds_ps, (BCM2048_MAX_RDS_PS + 1)) + +property_read(fm_rds_flags, unsigned int, "%u") +property_str_read(rds_data, BCM2048_MAX_RDS_RADIO_TEXT*5) + +property_read(region_bottom_frequency, unsigned int, "%u") +property_read(region_top_frequency, unsigned int, "%u") +property_signed_read(fm_carrier_error, int, "%d") +property_signed_read(fm_rssi, int, "%d") +DEFINE_SYSFS_PROPERTY(region, unsigned, int, "%u", 0) + +static struct device_attribute attrs[] = { + __ATTR(power_state, S_IRUGO | S_IWUSR, bcm2048_power_state_read, + bcm2048_power_state_write), + __ATTR(mute, S_IRUGO | S_IWUSR, bcm2048_mute_read, + bcm2048_mute_write), + __ATTR(audio_route, S_IRUGO | S_IWUSR, bcm2048_audio_route_read, + bcm2048_audio_route_write), + __ATTR(dac_output, S_IRUGO | S_IWUSR, bcm2048_dac_output_read, + bcm2048_dac_output_write), + __ATTR(fm_hi_lo_injection, S_IRUGO | S_IWUSR, + bcm2048_fm_hi_lo_injection_read, + bcm2048_fm_hi_lo_injection_write), + __ATTR(fm_frequency, S_IRUGO | S_IWUSR, bcm2048_fm_frequency_read, + bcm2048_fm_frequency_write), + __ATTR(fm_af_frequency, S_IRUGO | S_IWUSR, + bcm2048_fm_af_frequency_read, + bcm2048_fm_af_frequency_write), + __ATTR(fm_deemphasis, S_IRUGO | S_IWUSR, bcm2048_fm_deemphasis_read, + bcm2048_fm_deemphasis_write), + __ATTR(fm_rds_mask, S_IRUGO | S_IWUSR, bcm2048_fm_rds_mask_read, + bcm2048_fm_rds_mask_write), + __ATTR(fm_best_tune_mode, S_IRUGO | S_IWUSR, + bcm2048_fm_best_tune_mode_read, + bcm2048_fm_best_tune_mode_write), + __ATTR(fm_search_rssi_threshold, S_IRUGO | S_IWUSR, + bcm2048_fm_search_rssi_threshold_read, + bcm2048_fm_search_rssi_threshold_write), + __ATTR(fm_search_mode_direction, S_IRUGO | S_IWUSR, + bcm2048_fm_search_mode_direction_read, + bcm2048_fm_search_mode_direction_write), + __ATTR(fm_search_tune_mode, S_IRUGO | S_IWUSR, + bcm2048_fm_search_tune_mode_read, + bcm2048_fm_search_tune_mode_write), + __ATTR(rds, S_IRUGO | S_IWUSR, bcm2048_rds_read, + bcm2048_rds_write), + __ATTR(rds_b_block_mask, S_IRUGO | S_IWUSR, + bcm2048_rds_b_block_mask_read, + bcm2048_rds_b_block_mask_write), + __ATTR(rds_b_block_match, S_IRUGO | S_IWUSR, + bcm2048_rds_b_block_match_read, + bcm2048_rds_b_block_match_write), + __ATTR(rds_pi_mask, S_IRUGO | S_IWUSR, bcm2048_rds_pi_mask_read, + bcm2048_rds_pi_mask_write), + __ATTR(rds_pi_match, S_IRUGO | S_IWUSR, bcm2048_rds_pi_match_read, + bcm2048_rds_pi_match_write), + __ATTR(rds_wline, S_IRUGO | S_IWUSR, bcm2048_rds_wline_read, + bcm2048_rds_wline_write), + __ATTR(rds_pi, S_IRUGO, bcm2048_rds_pi_read, NULL), + __ATTR(rds_rt, S_IRUGO, bcm2048_rds_rt_read, NULL), + __ATTR(rds_ps, S_IRUGO, bcm2048_rds_ps_read, NULL), + __ATTR(fm_rds_flags, S_IRUGO, bcm2048_fm_rds_flags_read, NULL), + __ATTR(region_bottom_frequency, S_IRUGO, + bcm2048_region_bottom_frequency_read, NULL), + __ATTR(region_top_frequency, S_IRUGO, + bcm2048_region_top_frequency_read, NULL), + __ATTR(fm_carrier_error, S_IRUGO, + bcm2048_fm_carrier_error_read, NULL), + __ATTR(fm_rssi, S_IRUGO, + bcm2048_fm_rssi_read, NULL), + __ATTR(region, S_IRUGO | S_IWUSR, bcm2048_region_read, + bcm2048_region_write), + __ATTR(rds_data, S_IRUGO, bcm2048_rds_data_read, NULL), +}; + +static int bcm2048_sysfs_unregister_properties(struct bcm2048_device *bdev, + int size) +{ + int i; + + for (i = 0; i < size; i++) + device_remove_file(&bdev->client->dev, &attrs[i]); + + return 0; +} + +static int bcm2048_sysfs_register_properties(struct bcm2048_device *bdev) +{ + int err = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(attrs); i++) { + if (device_create_file(&bdev->client->dev, &attrs[i]) != 0) { + dev_err(&bdev->client->dev, + "could not register sysfs entry\n"); + err = -EBUSY; + bcm2048_sysfs_unregister_properties(bdev, i); + break; + } + } + + return err; +} + + +static int bcm2048_fops_open(struct file *file) +{ + struct bcm2048_device *bdev = video_drvdata(file); + + bdev->users++; + bdev->rd_index = 0; + bdev->rds_data_available = 0; + + return 0; +} + +static int bcm2048_fops_release(struct file *file) +{ + struct bcm2048_device *bdev = video_drvdata(file); + + bdev->users--; + + return 0; +} + +static unsigned int bcm2048_fops_poll(struct file *file, + struct poll_table_struct *pts) +{ + struct bcm2048_device *bdev = video_drvdata(file); + int retval = 0; + + poll_wait(file, &bdev->read_queue, pts); + + if (bdev->rds_data_available) + retval = POLLIN | POLLRDNORM; + + return retval; +} + +static ssize_t bcm2048_fops_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct bcm2048_device *bdev = video_drvdata(file); + int i; + int retval = 0; + + /* we return at least 3 bytes, one block */ + count = (count / 3) * 3; /* only multiples of 3 */ + if (count < 3) + return -ENOBUFS; + + while (!bdev->rds_data_available) { + if (file->f_flags & O_NONBLOCK) { + retval = -EWOULDBLOCK; + goto done; + } + /* interruptible_sleep_on(&bdev->read_queue); */ + if (wait_event_interruptible(bdev->read_queue, + bdev->rds_data_available) < 0) { + retval = -EINTR; + goto done; + } + } + + mutex_lock(&bdev->mutex); + /* copy data to userspace */ + i = bdev->fifo_size - bdev->rd_index; + if (count > i) + count = (i / 3) * 3; + + i = 0; + while (i < count) { + unsigned char tmpbuf[3]; + tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2]; + tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1]; + tmpbuf[i+2] = ((bdev->rds_info.radio_text[bdev->rd_index+i] + & 0xf0) >> 4); + if ((bdev->rds_info.radio_text[bdev->rd_index+i] & + BCM2048_RDS_CRC_MASK) == BCM2048_RDS_CRC_UNRECOVARABLE) + tmpbuf[i+2] |= 0x80; + if (copy_to_user(buf+i, tmpbuf, 3)) { + retval = -EFAULT; + break; + }; + i += 3; + } + + bdev->rd_index += i; + if (bdev->rd_index >= bdev->fifo_size) + bdev->rds_data_available = 0; + + mutex_unlock(&bdev->mutex); + if (retval == 0) + retval = i; + +done: + return retval; +} + +/* + * bcm2048_fops - file operations interface + */ +static const struct v4l2_file_operations bcm2048_fops = { + .owner = THIS_MODULE, + .ioctl = video_ioctl2, + /* for RDS read support */ + .open = bcm2048_fops_open, + .release = bcm2048_fops_release, + .read = bcm2048_fops_read, + .poll = bcm2048_fops_poll +}; + +/* + * Video4Linux Interface + */ +static struct v4l2_queryctrl bcm2048_v4l2_queryctrl[] = { + { + .id = V4L2_CID_AUDIO_VOLUME, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_BALANCE, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_BASS, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_TREBLE, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_AUDIO_MUTE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, + { + .id = V4L2_CID_AUDIO_LOUDNESS, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, +}; + +static int bcm2048_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + + strlcpy(capability->driver, BCM2048_DRIVER_NAME, + sizeof(capability->driver)); + strlcpy(capability->card, BCM2048_DRIVER_CARD, + sizeof(capability->card)); + snprintf(capability->bus_info, 32, "I2C: 0x%X", bdev->client->addr); + capability->version = BCM2048_DRIVER_VERSION; + capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | + V4L2_CAP_HW_FREQ_SEEK; + + return 0; +} + +static int bcm2048_vidioc_g_input(struct file *filp, void *priv, + unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int bcm2048_vidioc_s_input(struct file *filp, void *priv, + unsigned int i) +{ + if (i) + return -EINVAL; + + return 0; +} + +static int bcm2048_vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bcm2048_v4l2_queryctrl); i++) { + if (qc->id && qc->id == bcm2048_v4l2_queryctrl[i].id) { + memcpy(qc, &(bcm2048_v4l2_queryctrl[i]), sizeof(*qc)); + return 0; + } + } + + return -EINVAL; +} + +static int bcm2048_vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + int err = 0; + + if (!bdev) + return -ENODEV; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + err = bcm2048_get_mute(bdev); + if (err >= 0) + ctrl->value = err; + break; + } + + return err; +} + +static int bcm2048_vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + int err = 0; + + if (!bdev) + return -ENODEV; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + if (bdev->power_state) { + err = bcm2048_set_mute(bdev, ctrl->value); + err |= bcm2048_deinit(bdev); + } + } else { + if (!bdev->power_state) { + err = bcm2048_init(bdev); + err |= bcm2048_set_mute(bdev, ctrl->value); + } + } + break; + } + + return err; +} + +static int bcm2048_vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + if (audio->index > 1) + return -EINVAL; + + strncpy(audio->name, "Radio", 32); + audio->capability = V4L2_AUDCAP_STEREO; + + return 0; +} + +static int bcm2048_vidioc_s_audio(struct file *file, void *priv, + const struct v4l2_audio *audio) +{ + if (audio->index != 0) + return -EINVAL; + + return 0; +} + +static int bcm2048_vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + s8 f_error; + s8 rssi; + + if (!bdev) + return -ENODEV; + + if (tuner->index > 0) + return -EINVAL; + + strncpy(tuner->name, "FM Receiver", 32); + tuner->type = V4L2_TUNER_RADIO; + tuner->rangelow = + dev_to_v4l2(bcm2048_get_region_bottom_frequency(bdev)); + tuner->rangehigh = + dev_to_v4l2(bcm2048_get_region_top_frequency(bdev)); + tuner->rxsubchans = V4L2_TUNER_SUB_STEREO; + tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; + tuner->audmode = V4L2_TUNER_MODE_STEREO; + tuner->afc = 0; + if (bdev->power_state) { + /* + * Report frequencies with high carrier errors to have zero + * signal level + */ + f_error = bcm2048_get_fm_carrier_error(bdev); + if (f_error < BCM2048_FREQ_ERROR_FLOOR || + f_error > BCM2048_FREQ_ERROR_ROOF) { + tuner->signal = 0; + } else { + /* + * RSSI level -60 dB is defined to report full + * signal strenght + */ + rssi = bcm2048_get_fm_rssi(bdev); + if (rssi >= BCM2048_RSSI_LEVEL_BASE) { + tuner->signal = 0xFFFF; + } else if (rssi > BCM2048_RSSI_LEVEL_ROOF) { + tuner->signal = (rssi + + BCM2048_RSSI_LEVEL_ROOF_NEG) + * BCM2048_SIGNAL_MULTIPLIER; + } else { + tuner->signal = 0; + } + } + } else { + tuner->signal = 0; + } + + return 0; +} + +static int bcm2048_vidioc_s_tuner(struct file *file, void *priv, + const struct v4l2_tuner *tuner) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + + if (!bdev) + return -ENODEV; + + if (tuner->index > 0) + return -EINVAL; + + return 0; +} + +static int bcm2048_vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + int err = 0; + int f; + + if (!bdev->power_state) + return -ENODEV; + + freq->type = V4L2_TUNER_RADIO; + f = bcm2048_get_fm_frequency(bdev); + + if (f < 0) + err = f; + else + freq->frequency = dev_to_v4l2(f); + + return err; +} + +static int bcm2048_vidioc_s_frequency(struct file *file, void *priv, + const struct v4l2_frequency *freq) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + int err; + + if (freq->type != V4L2_TUNER_RADIO) + return -EINVAL; + + if (!bdev->power_state) + return -ENODEV; + + err = bcm2048_set_fm_frequency(bdev, v4l2_to_dev(freq->frequency)); + err |= bcm2048_set_fm_search_tune_mode(bdev, BCM2048_FM_PRE_SET_MODE); + + return err; +} + +static int bcm2048_vidioc_s_hw_freq_seek(struct file *file, void *priv, + const struct v4l2_hw_freq_seek *seek) +{ + struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); + int err; + + if (!bdev->power_state) + return -ENODEV; + + if ((seek->tuner != 0) || (seek->type != V4L2_TUNER_RADIO)) + return -EINVAL; + + err = bcm2048_set_fm_search_mode_direction(bdev, seek->seek_upward); + err |= bcm2048_set_fm_search_tune_mode(bdev, + BCM2048_FM_AUTO_SEARCH_MODE); + + return err; +} + +static struct v4l2_ioctl_ops bcm2048_ioctl_ops = { + .vidioc_querycap = bcm2048_vidioc_querycap, + .vidioc_g_input = bcm2048_vidioc_g_input, + .vidioc_s_input = bcm2048_vidioc_s_input, + .vidioc_queryctrl = bcm2048_vidioc_queryctrl, + .vidioc_g_ctrl = bcm2048_vidioc_g_ctrl, + .vidioc_s_ctrl = bcm2048_vidioc_s_ctrl, + .vidioc_g_audio = bcm2048_vidioc_g_audio, + .vidioc_s_audio = bcm2048_vidioc_s_audio, + .vidioc_g_tuner = bcm2048_vidioc_g_tuner, + .vidioc_s_tuner = bcm2048_vidioc_s_tuner, + .vidioc_g_frequency = bcm2048_vidioc_g_frequency, + .vidioc_s_frequency = bcm2048_vidioc_s_frequency, + .vidioc_s_hw_freq_seek = bcm2048_vidioc_s_hw_freq_seek, +}; + +/* + * bcm2048_viddev_template - video device interface + */ +static struct video_device bcm2048_viddev_template = { + .fops = &bcm2048_fops, + .name = BCM2048_DRIVER_NAME, + .release = video_device_release, + .ioctl_ops = &bcm2048_ioctl_ops, +}; + +/* + * I2C driver interface + */ +static int bcm2048_i2c_driver_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct bcm2048_device *bdev; + int err, skip_release = 0; + + bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); + if (!bdev) { + dev_dbg(&client->dev, "Failed to alloc video device.\n"); + err = -ENOMEM; + goto exit; + } + + bdev->videodev = video_device_alloc(); + if (!bdev->videodev) { + dev_dbg(&client->dev, "Failed to alloc video device.\n"); + err = -ENOMEM; + goto free_bdev; + } + + bdev->client = client; + i2c_set_clientdata(client, bdev); + mutex_init(&bdev->mutex); + init_completion(&bdev->compl); + INIT_WORK(&bdev->work, bcm2048_work); + + if (client->irq) { + err = request_irq(client->irq, + bcm2048_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, + client->name, bdev); + if (err < 0) { + dev_err(&client->dev, "Could not request IRQ\n"); + goto free_vdev; + } + dev_dbg(&client->dev, "IRQ requested.\n"); + } else { + dev_dbg(&client->dev, "IRQ not configured. Using timeouts.\n"); + } + + memcpy(bdev->videodev, &bcm2048_viddev_template, + sizeof(bcm2048_viddev_template)); + video_set_drvdata(bdev->videodev, bdev); + if (video_register_device(bdev->videodev, VFL_TYPE_RADIO, radio_nr)) { + dev_dbg(&client->dev, "Could not register video device.\n"); + err = -EIO; + goto free_irq; + } + + err = bcm2048_sysfs_register_properties(bdev); + if (err < 0) { + dev_dbg(&client->dev, "Could not register sysfs interface.\n"); + goto free_registration; + } + + err = bcm2048_probe(bdev); + if (err < 0) { + dev_dbg(&client->dev, "Failed to probe device information.\n"); + goto free_sysfs; + } + + return 0; + +free_sysfs: + bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs)); +free_registration: + video_unregister_device(bdev->videodev); + /* video_unregister_device frees bdev->videodev */ + bdev->videodev = NULL; + skip_release = 1; +free_irq: + if (client->irq) + free_irq(client->irq, bdev); +free_vdev: + if (!skip_release) + video_device_release(bdev->videodev); + i2c_set_clientdata(client, NULL); +free_bdev: + kfree(bdev); +exit: + return err; +} + +static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client) +{ + struct bcm2048_device *bdev = i2c_get_clientdata(client); + struct video_device *vd; + + if (!client->adapter) + return -ENODEV; + + if (bdev) { + vd = bdev->videodev; + + bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs)); + + if (vd) + video_unregister_device(vd); + + if (bdev->power_state) + bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); + + if (client->irq > 0) + free_irq(client->irq, bdev); + + cancel_work_sync(&bdev->work); + + kfree(bdev); + } + + i2c_set_clientdata(client, NULL); + + return 0; +} + +/* + * bcm2048_i2c_driver - i2c driver interface + */ +static const struct i2c_device_id bcm2048_id[] = { + { "bcm2048" , 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, bcm2048_id); + +static struct i2c_driver bcm2048_i2c_driver = { + .driver = { + .name = BCM2048_DRIVER_NAME, + }, + .probe = bcm2048_i2c_driver_probe, + .remove = __exit_p(bcm2048_i2c_driver_remove), + .id_table = bcm2048_id, +}; + +/* + * Module Interface + */ +static int __init bcm2048_module_init(void) +{ + pr_info(BCM2048_DRIVER_DESC "\n"); + + return i2c_add_driver(&bcm2048_i2c_driver); +} +module_init(bcm2048_module_init); + +static void __exit bcm2048_module_exit(void) +{ + i2c_del_driver(&bcm2048_i2c_driver); +} +module_exit(bcm2048_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(BCM2048_DRIVER_AUTHOR); +MODULE_DESCRIPTION(BCM2048_DRIVER_DESC); +MODULE_VERSION("0.0.2"); diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.h b/drivers/staging/media/bcm2048/radio-bcm2048.h new file mode 100644 index 000000000000..4c90a32db795 --- /dev/null +++ b/drivers/staging/media/bcm2048/radio-bcm2048.h @@ -0,0 +1,30 @@ +/* + * drivers/staging/media/radio-bcm2048.h + * + * Property and command definitions for bcm2048 radio receiver chip. + * + * Copyright (C) Nokia Corporation + * Contact: Eero Nurkkala + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef BCM2048_H +#define BCM2048_H + +#define BCM2048_NAME "bcm2048" +#define BCM2048_I2C_ADDR 0x22 + +#endif /* ifndef BCM2048_H */ -- cgit v1.2.3 From d1dd206c2abf678889445e63ecc949e9274f5806 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Mon, 9 Dec 2013 20:08:19 +0800 Subject: crytpo: ccp - fix coccinelle warnings drivers/crypto/ccp/ccp-crypto-aes.c:344:1-7: Replace memcpy with struct assignment drivers/crypto/ccp/ccp-crypto-sha.c:398:1-7: Replace memcpy with struct assignment drivers/crypto/ccp/ccp-dev.c:578:2-3: Unneeded semicolon /c/kernel-tests/src/cocci/drivers/crypto/ccp/ccp-dev.c:565:2-3: Unneeded semicolon Generated by: coccinelle/misc/memcpy-assign.cocci CC: Tom Lendacky Signed-off-by: Fengguang Wu Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes.c | 2 +- drivers/crypto/ccp/ccp-crypto-sha.c | 2 +- drivers/crypto/ccp/ccp-dev.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes.c b/drivers/crypto/ccp/ccp-crypto-aes.c index f302a5b7473b..c0befdb2240b 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes.c +++ b/drivers/crypto/ccp/ccp-crypto-aes.c @@ -341,7 +341,7 @@ static int ccp_register_aes_alg(struct list_head *head, /* Copy the defaults and override as necessary */ alg = &ccp_alg->alg; - memcpy(alg, def->alg_defaults, sizeof(*alg)); + *alg = *def->alg_defaults; snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", def->driver_name); diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index 44ff00a09c8a..a6ef183f0afc 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -395,7 +395,7 @@ static int ccp_register_hmac_alg(struct list_head *head, return -ENOMEM; /* Copy the base algorithm and only change what's necessary */ - memcpy(ccp_alg, base_alg, sizeof(*ccp_alg)); + *ccp_alg = *base_alg; INIT_LIST_HEAD(&ccp_alg->entry); strncpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME); diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index de59df970176..b2038a7e91e1 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -562,7 +562,7 @@ static int __init ccp_mod_init(void) return -ENODEV; return ccp_pci_init(); break; - }; + } return -ENODEV; } @@ -575,7 +575,7 @@ static void __exit ccp_mod_exit(void) case 22: ccp_pci_exit(); break; - }; + } } module_init(ccp_mod_init); -- cgit v1.2.3 From d44250fd17de6dea2b16e23d2767ab0eff48f4d8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 4 Nov 2013 08:37:34 -0300 Subject: [media] bcm2048: add TODO file for this staging driver Describe the tasks to be done for this driver to be promoted to a non-staging one. [m.chehab@samsung.com: Add a patch description; add a note about the CodingStyle issues and make sure that the README lines are not bigger than 80 cols.] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/bcm2048/TODO | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 drivers/staging/media/bcm2048/TODO (limited to 'drivers') diff --git a/drivers/staging/media/bcm2048/TODO b/drivers/staging/media/bcm2048/TODO new file mode 100644 index 000000000000..051f85dbe89e --- /dev/null +++ b/drivers/staging/media/bcm2048/TODO @@ -0,0 +1,24 @@ +TODO: + +From the initial code review: + +The main thing you need to do is to implement all the controls using the +control framework (see Documentation/video4linux/v4l2-controls.txt). +Most drivers are by now converted to the control framework, so you will +find many examples of how to do this in drivers/media/radio. + +The sysfs stuff should be replaced by controls as well. A lot of the RDS +support is now available as controls (although there may well be some +missing features, but that is easy enough to add). Since the RDS data is +actually read() from the device I am not sure whether the RDS +properties/controls should be there at all. + +Correct Coding Style, as this driver also violates several Style +rules, and do evil tricks, like returning from a function inside a +macro. + +Finally this driver should probably be split up into two parts: one +v4l2_subdev-based core driver and one platform driver. See e.g. +radio-si4713/si4713-i2c.c as a good example. But I would wait with that +until the rest of the driver is cleaned up. Then I have a better idea of +whether this is necessary or not. -- cgit v1.2.3 From dc793175c5b532f343fe2224afd9189130da0004 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Wed, 6 Nov 2013 11:21:30 -0300 Subject: [media] smiapp: Fix BUG_ON() on an impossible condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit internal_csi_format_idx and csi_format_idx are unsigned integers, therefore they can never be nevative. CC drivers/media/i2c/smiapp/smiapp-core.o In file included from include/linux/err.h:4:0, from include/linux/clk.h:15, from drivers/media/i2c/smiapp/smiapp-core.c:29: drivers/media/i2c/smiapp/smiapp-core.c: In function ‘smiapp_update_mbus_formats’: include/linux/kernel.h:669:20: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] #define min(x, y) ({ \ ^ include/linux/compiler.h:153:42: note: in definition of macro ‘unlikely’ # define unlikely(x) __builtin_expect(!!(x), 0) ^ drivers/media/i2c/smiapp/smiapp-core.c:402:2: note: in expansion of macro ‘BUG_ON’ BUG_ON(min(internal_csi_format_idx, csi_format_idx) < 0); ^ drivers/media/i2c/smiapp/smiapp-core.c:402:9: note: in expansion of macro ‘min’ BUG_ON(min(internal_csi_format_idx, csi_format_idx) < 0); ^ Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index ae66d91bf713..fbd48f04b5c8 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -399,7 +399,6 @@ static void smiapp_update_mbus_formats(struct smiapp_sensor *sensor) BUG_ON(max(internal_csi_format_idx, csi_format_idx) + pixel_order >= ARRAY_SIZE(smiapp_csi_data_formats)); - BUG_ON(min(internal_csi_format_idx, csi_format_idx) < 0); dev_dbg(&client->dev, "new pixel order %s\n", pixel_order_str[pixel_order]); -- cgit v1.2.3 From e1c759bd3daf7a59f0d6a6fa06ca237307da7879 Mon Sep 17 00:00:00 2001 From: Daniel Jeong Date: Fri, 6 Dec 2013 02:43:27 -0300 Subject: [media] media: i2c: lm3560: fix missing unlock on error, fault handling Correct reference of reading values. (rval -> reg_val) Add the missing unlock before return from function lm3560_get_ctrl() to avoid deadlock. Thank you Dan Carpenter & Sakari. Signed-off-by: Daniel Jeong Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/lm3560.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 3317a9ae3961..ab5857d66f2d 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -172,28 +172,28 @@ static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash, static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no) { struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no); + int rval = -EINVAL; mutex_lock(&flash->lock); if (ctrl->id == V4L2_CID_FLASH_FAULT) { - int rval; s32 fault = 0; unsigned int reg_val; rval = regmap_read(flash->regmap, REG_FLAG, ®_val); if (rval < 0) - return rval; - if (rval & FAULT_SHORT_CIRCUIT) + goto out; + if (reg_val & FAULT_SHORT_CIRCUIT) fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT; - if (rval & FAULT_OVERTEMP) + if (reg_val & FAULT_OVERTEMP) fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE; - if (rval & FAULT_TIMEOUT) + if (reg_val & FAULT_TIMEOUT) fault |= V4L2_FLASH_FAULT_TIMEOUT; ctrl->cur.val = fault; - return 0; } +out: mutex_unlock(&flash->lock); - return -EINVAL; + return rval; } static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no) -- cgit v1.2.3 From ad824783fb23bbc8295cffb6214b3b82d25f7d4a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 3 Dec 2013 12:20:11 +0900 Subject: gpio: better lookup method for platform GPIOs Change the format of the platform GPIO lookup tables to make them less confusing and improve lookup efficiency. The previous format was a single linked-list that required to compare the device name and function ID of every single GPIO defined for each lookup. Switch that to a list of per-device tables, so that the lookup can be done in two steps, omitting the GPIOs that are not relevant for a particular device. The matching rules are now defined as follows: - The device name must match *exactly*, and can be NULL for GPIOs not assigned to a particular device, - If the function ID in the lookup table is NULL, the con_id argument of gpiod_get() will not be used for lookup. However, if it is defined, it must match exactly. - The index must always match. Signed-off-by: Alexandre Courbot Acked-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- Documentation/gpio/board.txt | 28 ++++++----- drivers/gpio/gpiolib.c | 108 +++++++++++++++++++++++-------------------- include/linux/gpio/driver.h | 21 ++++----- 3 files changed, 85 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/Documentation/gpio/board.txt b/Documentation/gpio/board.txt index 0d03506f2cc5..ba169faad5c6 100644 --- a/Documentation/gpio/board.txt +++ b/Documentation/gpio/board.txt @@ -72,10 +72,11 @@ where - chip_label is the label of the gpiod_chip instance providing the GPIO - chip_hwnum is the hardware number of the GPIO within the chip - - dev_id is the identifier of the device that will make use of this GPIO. If - NULL, the GPIO will be available to all devices. + - dev_id is the identifier of the device that will make use of this GPIO. It + can be NULL, in which case it will be matched for calls to gpiod_get() + with a NULL device. - con_id is the name of the GPIO function from the device point of view. It - can be NULL. + can be NULL, in which case it will match any function. - idx is the index of the GPIO within the function. - flags is defined to specify the following properties: * GPIOF_ACTIVE_LOW - to configure the GPIO as active-low @@ -86,18 +87,23 @@ In the future, these flags might be extended to support more properties. Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0. -A lookup table can then be defined as follows: +A lookup table can then be defined as follows, with an empty entry defining its +end: - struct gpiod_lookup gpios_table[] = { - GPIO_LOOKUP_IDX("gpio.0", 15, "foo.0", "led", 0, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("gpio.0", 16, "foo.0", "led", 1, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("gpio.0", 17, "foo.0", "led", 2, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("gpio.0", 1, "foo.0", "power", GPIO_ACTIVE_LOW), - }; +struct gpiod_lookup_table gpios_table = { + .dev_id = "foo.0", + .table = { + GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW), + { }, + }, +}; And the table can be added by the board code as follows: - gpiod_add_table(gpios_table, ARRAY_SIZE(gpios_table)); + gpiod_add_lookup_table(&gpios_table); The driver controlling "foo.0" will then be able to obtain its GPIOs as follows: diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 44a232701179..4eb262a31777 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2260,18 +2260,14 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); /** - * gpiod_add_table() - register GPIO device consumers - * @table: array of consumers to register - * @num: number of consumers in table + * gpiod_add_lookup_table() - register GPIO device consumers + * @table: table of consumers to register */ -void gpiod_add_table(struct gpiod_lookup *table, size_t size) +void gpiod_add_lookup_table(struct gpiod_lookup_table *table) { mutex_lock(&gpio_lookup_lock); - while (size--) { - list_add_tail(&table->list, &gpio_lookup_list); - table++; - } + list_add_tail(&table->list, &gpio_lookup_list); mutex_unlock(&gpio_lookup_lock); } @@ -2327,72 +2323,84 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, return desc; } -static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, - unsigned int idx, - enum gpio_lookup_flags *flags) +static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) { const char *dev_id = dev ? dev_name(dev) : NULL; - struct gpio_desc *desc = ERR_PTR(-ENODEV); - unsigned int match, best = 0; - struct gpiod_lookup *p; + struct gpiod_lookup_table *table; mutex_lock(&gpio_lookup_lock); - list_for_each_entry(p, &gpio_lookup_list, list) { - match = 0; + list_for_each_entry(table, &gpio_lookup_list, list) { + if (table->dev_id && dev_id) { + /* + * Valid strings on both ends, must be identical to have + * a match + */ + if (!strcmp(table->dev_id, dev_id)) + goto found; + } else { + /* + * One of the pointers is NULL, so both must be to have + * a match + */ + if (dev_id == table->dev_id) + goto found; + } + } + table = NULL; - if (p->dev_id) { - if (!dev_id || strcmp(p->dev_id, dev_id)) - continue; +found: + mutex_unlock(&gpio_lookup_lock); + return table; +} - match += 2; - } +static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, + unsigned int idx, + enum gpio_lookup_flags *flags) +{ + struct gpio_desc *desc = ERR_PTR(-ENODEV); + struct gpiod_lookup_table *table; + struct gpiod_lookup *p; - if (p->con_id) { - if (!con_id || strcmp(p->con_id, con_id)) - continue; + table = gpiod_find_lookup_table(dev); + if (!table) + return desc; - match += 1; - } + for (p = &table->table[0]; p->chip_label; p++) { + struct gpio_chip *chip; + /* idx must always match exactly */ if (p->idx != idx) continue; - if (match > best) { - struct gpio_chip *chip; - - chip = find_chip_by_name(p->chip_label); - - if (!chip) { - dev_warn(dev, "cannot find GPIO chip %s\n", - p->chip_label); - continue; - } + /* If the lookup entry has a con_id, require exact match */ + if (p->con_id && (!con_id || strcmp(p->con_id, con_id))) + continue; - if (chip->ngpio <= p->chip_hwnum) { - dev_warn(dev, "GPIO chip %s has %d GPIOs\n", - chip->label, chip->ngpio); - continue; - } + chip = find_chip_by_name(p->chip_label); - desc = gpio_to_desc(chip->base + p->chip_hwnum); - *flags = p->flags; + if (!chip) { + dev_warn(dev, "cannot find GPIO chip %s\n", + p->chip_label); + continue; + } - if (match != 3) - best = match; - else - break; + if (chip->ngpio <= p->chip_hwnum) { + dev_warn(dev, "GPIO chip %s has %d GPIOs\n", + chip->label, chip->ngpio); + continue; } - } - mutex_unlock(&gpio_lookup_lock); + desc = gpiochip_offset_to_desc(chip, p->chip_hwnum); + *flags = p->flags; + } return desc; } /** * gpio_get - obtain a GPIO for a given GPIO function - * @dev: GPIO consumer + * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * * Return the GPIO descriptor corresponding to the function con_id of device diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index c849676c6787..44c66b29a2d9 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -141,7 +141,6 @@ enum gpio_lookup_flags { * platform data. */ struct gpiod_lookup { - struct list_head list; /* * name of the chip the GPIO belongs to */ @@ -150,10 +149,6 @@ struct gpiod_lookup { * hardware number (i.e. relative to the chip) of the GPIO */ u16 chip_hwnum; - /* - * name of device that can claim this GPIO - */ - const char *dev_id; /* * name of the GPIO from the device's point of view */ @@ -168,28 +163,32 @@ struct gpiod_lookup { enum gpio_lookup_flags flags; }; +struct gpiod_lookup_table { + struct list_head list; + const char *dev_id; + struct gpiod_lookup table[]; +}; + /* * Simple definition of a single GPIO under a con_id */ -#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _dev_id, _con_id, _flags) \ - GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _dev_id, _con_id, 0, _flags) +#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _con_id, _flags) \ + GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, 0, _flags) /* * Use this macro if you need to have several GPIOs under the same con_id. * Each GPIO needs to use a different index and can be accessed using * gpiod_get_index() */ -#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _dev_id, _con_id, _idx, \ - _flags) \ +#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, _idx, _flags) \ { \ .chip_label = _chip_label, \ .chip_hwnum = _chip_hwnum, \ - .dev_id = _dev_id, \ .con_id = _con_id, \ .idx = _idx, \ .flags = _flags, \ } -void gpiod_add_table(struct gpiod_lookup *table, size_t size); +void gpiod_add_lookup_table(struct gpiod_lookup_table *table); #endif -- cgit v1.2.3 From 7589e59fc0be799fed069591b83d0e57f11058cc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2013 11:26:23 +0200 Subject: gpiolib: unify pr_* messages format This patch includes the following amendments: 1) use "?" as a label when the last one is not defined in gpiod_*; 2) whenever it's possible gpiod_* are used; 3) print a function name, if it's already used in other messages. Additionally it fixes an indentation in few places. Signed-off-by: Andy Shevchenko Acked-by: Alexandre Courbot Reviewed-by: Alexandre Courbot Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 74 +++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4eb262a31777..2dc3657e99ba 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -85,36 +85,36 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); static void gpiod_free(struct gpio_desc *desc); #ifdef CONFIG_DEBUG_FS -#define gpiod_emerg(desc, fmt, ...) \ - pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_emerg(desc, fmt, ...) \ + pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ ##__VA_ARGS__) -#define gpiod_crit(desc, fmt, ...) \ - pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_crit(desc, fmt, ...) \ + pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_err(desc, fmt, ...) \ - pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_err(desc, fmt, ...) \ + pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_warn(desc, fmt, ...) \ - pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_warn(desc, fmt, ...) \ + pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_info(desc, fmt, ...) \ - pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_info(desc, fmt, ...) \ + pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ ##__VA_ARGS__) -#define gpiod_dbg(desc, fmt, ...) \ - pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \ +#define gpiod_dbg(desc, fmt, ...) \ + pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ ##__VA_ARGS__) #else -#define gpiod_emerg(desc, fmt, ...) \ +#define gpiod_emerg(desc, fmt, ...) \ pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_crit(desc, fmt, ...) \ +#define gpiod_crit(desc, fmt, ...) \ pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_err(desc, fmt, ...) \ +#define gpiod_err(desc, fmt, ...) \ pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_warn(desc, fmt, ...) \ +#define gpiod_warn(desc, fmt, ...) \ pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_info(desc, fmt, ...) \ +#define gpiod_info(desc, fmt, ...) \ pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) -#define gpiod_dbg(desc, fmt, ...) \ +#define gpiod_dbg(desc, fmt, ...) \ pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) #endif @@ -188,7 +188,8 @@ static int gpio_ensure_requested(struct gpio_desc *desc) if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0, "autorequest GPIO-%d\n", gpio)) { if (!try_module_get(chip->owner)) { - pr_err("GPIO-%d: module can't be gotten \n", gpio); + gpiod_err(desc, "%s: module can't be gotten\n", + __func__); clear_bit(FLAG_REQUESTED, &desc->flags); /* lose */ return -EIO; @@ -809,8 +810,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) if (!test_bit(FLAG_REQUESTED, &desc->flags) || test_bit(FLAG_EXPORT, &desc->flags)) { spin_unlock_irqrestore(&gpio_lock, flags); - pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", - __func__, desc_to_gpio(desc), + gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n", + __func__, test_bit(FLAG_REQUESTED, &desc->flags), test_bit(FLAG_EXPORT, &desc->flags)); status = -EPERM; @@ -858,8 +859,7 @@ fail_unregister_device: device_unregister(dev); fail_unlock: mutex_unlock(&sysfs_lock); - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_export); @@ -907,8 +907,7 @@ int gpiod_export_link(struct device *dev, const char *name, mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -952,8 +951,7 @@ unlock: mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -995,8 +993,7 @@ void gpiod_unexport(struct gpio_desc *desc) } if (status) - pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), - status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); } EXPORT_SYMBOL_GPL(gpiod_unexport); @@ -1222,7 +1219,7 @@ int gpiochip_add(struct gpio_chip *chip) if (status) goto fail; - pr_debug("gpiochip_add: registered GPIOs %d to %d on device: %s\n", + pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); @@ -1232,7 +1229,7 @@ unlock: spin_unlock_irqrestore(&gpio_lock, flags); fail: /* failures here can mean systems won't boot... */ - pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", + pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__, chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); return status; @@ -1500,8 +1497,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) } done: if (status) - pr_debug("_gpio_request: gpio-%d (%s) status %d\n", - desc_to_gpio(desc), label ? : "?", status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); spin_unlock_irqrestore(&gpio_lock, flags); return status; } @@ -1702,7 +1698,7 @@ int gpiod_direction_input(struct gpio_desc *desc) if (!chip->get || !chip->direction_input) { gpiod_warn(desc, "%s: missing get() or direction_input() operations\n", - __func__); + __func__); return -EIO; } @@ -1722,7 +1718,8 @@ int gpiod_direction_input(struct gpio_desc *desc) if (status) { status = chip->request(chip, offset); if (status < 0) { - gpiod_dbg(desc, "chip request fail, %d\n", status); + gpiod_dbg(desc, "%s: chip request fail, %d\n", + __func__, status); /* and it's not available to anyone else ... * gpio_request() is the fully clean solution. */ @@ -1740,7 +1737,7 @@ lose: fail: spin_unlock_irqrestore(&gpio_lock, flags); if (status) - gpiod_dbg(desc, "%s status %d\n", __func__, status); + gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } EXPORT_SYMBOL_GPL(gpiod_direction_input); @@ -1807,7 +1804,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (status) { status = chip->request(chip, offset); if (status < 0) { - gpiod_dbg(desc, "chip request fail, %d\n", status); + gpiod_dbg(desc, "%s: chip request fail, %d\n", + __func__, status); /* and it's not available to anyone else ... * gpio_request() is the fully clean solution. */ @@ -2448,8 +2446,10 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, */ if (!desc || IS_ERR(desc)) { struct gpio_desc *pdesc; + dev_dbg(dev, "using lookup tables for GPIO lookup"); pdesc = gpiod_find(dev, con_id, idx, &flags); + /* If used as fallback, do not replace the previous error */ if (!IS_ERR(pdesc) || !desc) desc = pdesc; -- cgit v1.2.3 From 1a2a99c69eaea30da25dede555a3d70d7a412ae2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2013 11:26:24 +0200 Subject: gpiolib: introduce chip_* to print with chip->label prefix In several places we are printing messages with prefix based on chip->label. Introduced macros help us to do this easier and in uniform way. Signed-off-by: Andy Shevchenko Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2dc3657e99ba..30ae38681fef 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -84,6 +84,8 @@ static DEFINE_IDR(dirent_idr); static int gpiod_request(struct gpio_desc *desc, const char *label); static void gpiod_free(struct gpio_desc *desc); +/* With descriptor prefix */ + #ifdef CONFIG_DEBUG_FS #define gpiod_emerg(desc, fmt, ...) \ pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ @@ -118,6 +120,21 @@ static void gpiod_free(struct gpio_desc *desc); pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) #endif +/* With chip prefix */ + +#define chip_emerg(chip, fmt, ...) \ + pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_crit(chip, fmt, ...) \ + pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_err(chip, fmt, ...) \ + pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_warn(chip, fmt, ...) \ + pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_info(chip, fmt, ...) \ + pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_dbg(chip, fmt, ...) \ + pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) + static inline void desc_set_label(struct gpio_desc *d, const char *label) { #ifdef CONFIG_DEBUG_FS @@ -1032,8 +1049,7 @@ static int gpiochip_export(struct gpio_chip *chip) chip->desc[gpio++].chip = NULL; spin_unlock_irqrestore(&gpio_lock, flags); - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); + chip_dbg(chip, "%s: status %d\n", __func__, status); } return status; @@ -1056,8 +1072,7 @@ static void gpiochip_unexport(struct gpio_chip *chip) mutex_unlock(&sysfs_lock); if (status) - pr_debug("%s: chip %s status %d\n", __func__, - chip->label, status); + chip_dbg(chip, "%s: status %d\n", __func__, status); } static int __init gpiolib_sysfs_init(void) @@ -1337,8 +1352,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - pr_err("%s: GPIO chip: failed to allocate pin ranges\n", - chip->label); + chip_err(chip, "failed to allocate pin ranges\n"); return -ENOMEM; } @@ -1359,9 +1373,8 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pinctrl_add_gpio_range(pctldev, &pin_range->range); - pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n", - chip->label, gpio_offset, - gpio_offset + pin_range->range.npins - 1, + chip_dbg(chip, "created GPIO range %d->%d ==> %s PINGRP %s\n", + gpio_offset, gpio_offset + pin_range->range.npins - 1, pinctrl_dev_get_devname(pctldev), pin_group); list_add_tail(&pin_range->node, &chip->pin_ranges); @@ -1388,8 +1401,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - pr_err("%s: GPIO chip: failed to allocate pin ranges\n", - chip->label); + chip_err(chip, "failed to allocate pin ranges\n"); return -ENOMEM; } @@ -1404,13 +1416,12 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, &pin_range->range); if (IS_ERR(pin_range->pctldev)) { ret = PTR_ERR(pin_range->pctldev); - pr_err("%s: GPIO chip: could not create pin range\n", - chip->label); + chip_err(chip, "could not create pin range\n"); kfree(pin_range); return ret; } - pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n", - chip->label, gpio_offset, gpio_offset + npins - 1, + chip_dbg(chip, "created GPIO range %d->%d ==> %s PIN %d->%d\n", + gpio_offset, gpio_offset + npins - 1, pinctl_name, pin_offset, pin_offset + npins - 1); -- cgit v1.2.3 From fdd6a5fe89880f1d97bbf62fea27fd7ca76f2d21 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2013 11:26:26 +0200 Subject: gpiolib: update inline documentation of gpiod_get_index() The patch just accents that @dev could be NULL. There is no functional change. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 30ae38681fef..12e47dfabd8d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2423,7 +2423,7 @@ EXPORT_SYMBOL_GPL(gpiod_get); /** * gpiod_get_index - obtain a GPIO from a multi-index GPIO function - * @dev: GPIO consumer + * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer * -- cgit v1.2.3 From 202dfbdc2b88286463b9e05df4be1c0bce50af4a Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 6 Nov 2013 15:48:38 -0300 Subject: [media] videobuf2-dma-sg: Fix typo on debug message num_pages_from_user and buf->num_pages were swapped. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-dma-sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index 2f860543912c..c13bf95f9f53 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -200,7 +200,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, userptr_fail_alloc_table_from_pages: userptr_fail_get_user_pages: dprintk(1, "get_user_pages requested/got: %d/%d]\n", - num_pages_from_user, buf->num_pages); + buf->num_pages, num_pages_from_user); while (--num_pages_from_user >= 0) put_page(buf->pages[num_pages_from_user]); kfree(buf->pages); -- cgit v1.2.3 From f956035ce70b8da9928aac1424485c3526fccb11 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Fri, 8 Nov 2013 07:08:45 -0300 Subject: [media] vb2: Return 0 when streamon and streamoff are already on/off According to the doc: If VIDIOC_STREAMON is called when streaming is already in progress, or if VIDIOC_STREAMOFF is called when streaming is already stopped, then the ioctl does nothing and 0 is returned. The current implementation was returning -EINVAL instead. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 57ba131f08ad..e949a0e64be9 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1697,8 +1697,8 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) } if (q->streaming) { - dprintk(1, "streamon: already streaming\n"); - return -EBUSY; + dprintk(3, "streamon successful: already streaming\n"); + return 0; } /* @@ -1754,8 +1754,8 @@ int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) } if (!q->streaming) { - dprintk(1, "streamoff: not streaming\n"); - return -EINVAL; + dprintk(3, "streamoff successful: not streaming\n"); + return 0; } /* -- cgit v1.2.3 From 77c0782e9729cee9d1d67cd1343ed7c3f947a36a Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 29 Nov 2013 04:50:29 -0300 Subject: [media] videobuf2: Add log for size checking error in __qbuf_dmabuf __qbuf_dmabuf checks whether size of provided dmabuf is large enough, and it returns error without any log. So this patch adds error log in the case. Signed-off-by: Seung-Woo Kim Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index e949a0e64be9..144caf12fb6c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1116,6 +1116,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b) if (planes[plane].length < planes[plane].data_offset + q->plane_sizes[plane]) { + dprintk(1, "qbuf: invalid dmabuf length for plane %d\n", + plane); ret = -EINVAL; goto err; } -- cgit v1.2.3 From 1380f5754cb0cc4b765629b153fc0e7030b86da2 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Mon, 25 Nov 2013 05:49:02 -0300 Subject: [media] videobuf2: Add missing lock held on vb2_fop_release vb2_fop_release does not hold the lock although it is modifying the queue->owner field. This could lead to race conditions on the vb2_perform_io function when multiple applications are accessing the video device via read/write API: [ 308.297741] BUG: unable to handle kernel NULL pointer dereference at 0000000000000260 [ 308.297759] IP: [] vb2_perform_fileio+0x372/0x610 [videobuf2_core] [ 308.297794] PGD 159719067 PUD 158119067 PMD 0 [ 308.297812] Oops: 0000 #1 SMP [ 308.297826] Modules linked in: qt5023_video videobuf2_dma_sg qtec_xform videobuf2_vmalloc videobuf2_memops videobuf2_core qtec_white qtec_mem gpio_xilinx qtec_cmosis qtec_pcie fglrx(PO) spi_xilinx spi_bitbang qt5023 [ 308.297888] CPU: 1 PID: 2189 Comm: java Tainted: P O 3.11.0-qtec-standard #1 [ 308.297919] Hardware name: QTechnology QT5022/QT5022, BIOS PM_2.1.0.309 X64 05/23/2013 [ 308.297952] task: ffff8801564e1690 ti: ffff88014dc02000 task.ti: ffff88014dc02000 [ 308.297962] RIP: 0010:[] [] vb2_perform_fileio+0x372/0x610 [videobuf2_core] [ 308.297985] RSP: 0018:ffff88014dc03df8 EFLAGS: 00010202 [ 308.297995] RAX: 0000000000000000 RBX: ffff880158a23000 RCX: dead000000100100 [ 308.298003] RDX: 0000000000000000 RSI: dead000000200200 RDI: 0000000000000000 [ 308.298012] RBP: ffff88014dc03e58 R08: 0000000000000000 R09: 0000000000000001 [ 308.298020] R10: ffffea00051e8380 R11: ffff88014dc03fd8 R12: ffff880158a23070 [ 308.298029] R13: ffff8801549040b8 R14: 0000000000198000 R15: 0000000001887e60 [ 308.298040] FS: 00007f65130d5700(0000) GS:ffff88015ed00000(0000) knlGS:0000000000000000 [ 308.298049] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 308.298057] CR2: 0000000000000260 CR3: 0000000159630000 CR4: 00000000000007e0 [ 308.298064] Stack: [ 308.298071] ffff880156416c00 0000000000198000 0000000000000000 ffff880100000001 [ 308.298087] ffff88014dc03f50 00000000810a79ca 0002000000000001 ffff880154904718 [ 308.298101] ffff880156416c00 0000000000198000 ffff880154904338 ffff88014dc03f50 [ 308.298116] Call Trace: [ 308.298143] [] vb2_read+0x14/0x20 [videobuf2_core] [ 308.298198] [] vb2_fop_read+0xc4/0x120 [videobuf2_core] [ 308.298252] [] v4l2_read+0x7e/0xc0 [ 308.298296] [] vfs_read+0xa9/0x160 [ 308.298312] [] SyS_read+0x52/0xb0 [ 308.298328] [] tracesys+0xd0/0xd5 [ 308.298335] Code: e5 d6 ff ff 83 3d be 24 00 00 04 89 c2 4c 8b 45 b0 44 8b 4d b8 0f 8f 20 02 00 00 85 d2 75 32 83 83 78 03 00 00 01 4b 8b 44 c5 48 <8b> 88 60 02 00 00 85 c9 0f 84 b0 00 00 00 8b 40 58 89 c2 41 89 [ 308.298487] RIP [] vb2_perform_fileio+0x372/0x610 [videobuf2_core] [ 308.298507] RSP [ 308.298514] CR2: 0000000000000260 [ 308.298526] ---[ end trace e8f01717c96d1e41 ]--- Signed-off-by: Ricardo Ribalda Acked-by: Hans Verkuil Acked-by: Sylwester Nawrocki Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-capture.c | 2 +- drivers/media/platform/exynos4-is/fimc-lite.c | 2 +- drivers/media/v4l2-core/videobuf2-core.c | 15 ++++++++++++++- include/media/videobuf2-core.h | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index fb27ff7e1e07..8a712ca91d11 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -549,7 +549,7 @@ static int fimc_capture_release(struct file *file) vc->streaming = false; } - ret = vb2_fop_release(file); + ret = _vb2_fop_release(file, NULL); if (close) { clear_bit(ST_CAPT_BUSY, &fimc->state); diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index e5798f70d149..d3b32b6f795d 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -546,7 +546,7 @@ static int fimc_lite_release(struct file *file) mutex_unlock(&entity->parent->graph_mutex); } - vb2_fop_release(file); + _vb2_fop_release(file, NULL); pm_runtime_put(&fimc->pdev->dev); clear_bit(ST_FLITE_SUSPENDED, &fimc->state); diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 144caf12fb6c..f61a79fc1cce 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2632,16 +2632,29 @@ int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) } EXPORT_SYMBOL_GPL(vb2_fop_mmap); -int vb2_fop_release(struct file *file) +int _vb2_fop_release(struct file *file, struct mutex *lock) { struct video_device *vdev = video_devdata(file); if (file->private_data == vdev->queue->owner) { + if (lock) + mutex_lock(lock); vb2_queue_release(vdev->queue); vdev->queue->owner = NULL; + if (lock) + mutex_unlock(lock); } return v4l2_fh_release(file); } +EXPORT_SYMBOL_GPL(_vb2_fop_release); + +int vb2_fop_release(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; + + return _vb2_fop_release(file, lock); +} EXPORT_SYMBOL_GPL(vb2_fop_release); ssize_t vb2_fop_write(struct file *file, const char __user *buf, diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 941055e9d125..0ae974ee8894 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -491,6 +491,7 @@ int vb2_ioctl_expbuf(struct file *file, void *priv, int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma); int vb2_fop_release(struct file *file); +int _vb2_fop_release(struct file *file, struct mutex *lock); ssize_t vb2_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); ssize_t vb2_fop_read(struct file *file, char __user *buf, -- cgit v1.2.3 From 50ac952d2263bd5d7812acf1839d57c34c6f8d9f Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Tue, 26 Nov 2013 09:58:44 -0300 Subject: [media] videobuf2-dma-sg: Support io userptr operations on io memory Memory exported via remap_pfn_range cannot be remapped via get_user_pages. Other videobuf2 methods (like the dma-contig) supports io memory. This patch adds support for this kind of memory. v2: Comments by Marek Szyprowski -Use vb2_get_vma and vb2_put_vma Signed-off-by: Ricardo Ribalda Delgado Acked-by: Marek Szyprowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-dma-sg.c | 51 +++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index c13bf95f9f53..d86bb8cdadd8 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -40,6 +40,7 @@ struct vb2_dma_sg_buf { unsigned int num_pages; atomic_t refcount; struct vb2_vmarea_handler handler; + struct vm_area_struct *vma; }; static void vb2_dma_sg_put(void *buf_priv); @@ -155,12 +156,18 @@ static void vb2_dma_sg_put(void *buf_priv) } } +static inline int vma_is_io(struct vm_area_struct *vma) +{ + return !!(vma->vm_flags & (VM_IO | VM_PFNMAP)); +} + static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, unsigned long size, int write) { struct vb2_dma_sg_buf *buf; unsigned long first, last; int num_pages_from_user; + struct vm_area_struct *vma; buf = kzalloc(sizeof *buf, GFP_KERNEL); if (!buf) @@ -180,7 +187,38 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, if (!buf->pages) return NULL; - num_pages_from_user = get_user_pages(current, current->mm, + vma = find_vma(current->mm, vaddr); + if (!vma) { + dprintk(1, "no vma for address %lu\n", vaddr); + goto userptr_fail_find_vma; + } + + if (vma->vm_end < vaddr + size) { + dprintk(1, "vma at %lu is too small for %lu bytes\n", + vaddr, size); + goto userptr_fail_find_vma; + } + + buf->vma = vb2_get_vma(vma); + if (!buf->vma) { + dprintk(1, "failed to copy vma\n"); + goto userptr_fail_find_vma; + } + + if (vma_is_io(buf->vma)) { + for (num_pages_from_user = 0; + num_pages_from_user < buf->num_pages; + ++num_pages_from_user, vaddr += PAGE_SIZE) { + unsigned long pfn; + + if (follow_pfn(buf->vma, vaddr, &pfn)) { + dprintk(1, "no page for address %lu\n", vaddr); + break; + } + buf->pages[num_pages_from_user] = pfn_to_page(pfn); + } + } else + num_pages_from_user = get_user_pages(current, current->mm, vaddr & PAGE_MASK, buf->num_pages, write, @@ -201,8 +239,11 @@ userptr_fail_alloc_table_from_pages: userptr_fail_get_user_pages: dprintk(1, "get_user_pages requested/got: %d/%d]\n", buf->num_pages, num_pages_from_user); - while (--num_pages_from_user >= 0) - put_page(buf->pages[num_pages_from_user]); + if (!vma_is_io(buf->vma)) + while (--num_pages_from_user >= 0) + put_page(buf->pages[num_pages_from_user]); + vb2_put_vma(buf->vma); +userptr_fail_find_vma: kfree(buf->pages); kfree(buf); return NULL; @@ -225,9 +266,11 @@ static void vb2_dma_sg_put_userptr(void *buf_priv) while (--i >= 0) { if (buf->write) set_page_dirty_lock(buf->pages[i]); - put_page(buf->pages[i]); + if (!vma_is_io(buf->vma)) + put_page(buf->pages[i]); } kfree(buf->pages); + vb2_put_vma(buf->vma); kfree(buf); } -- cgit v1.2.3 From 1d2d8ce61f7d47e418f26b0c657b5d8874b85df4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 3 Dec 2013 15:20:34 +0100 Subject: pinctrl: baytrail: lock IRQs when starting them This uses the new API for tagging GPIO lines as in use by IRQs. This enforces a few semantic checks on how the underlying GPIO line is used. Cc: Andy Shevchenko Cc: Mathias Nyman Tested-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-baytrail.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 1174ea86b6e9..5888066d80c2 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -372,11 +372,33 @@ static void byt_irq_mask(struct irq_data *d) { } +static unsigned int byt_irq_startup(struct irq_data *d) +{ + struct byt_gpio *vg = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&vg->chip, irqd_to_hwirq(d))) + dev_err(vg->chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + byt_irq_unmask(d); + return 0; +} + +static void byt_irq_shutdown(struct irq_data *d) +{ + struct byt_gpio *vg = irq_data_get_irq_chip_data(d); + + byt_irq_mask(d); + gpio_unlock_as_irq(&vg->chip, irqd_to_hwirq(d)); +} + static struct irq_chip byt_irqchip = { .name = "BYT-GPIO", .irq_mask = byt_irq_mask, .irq_unmask = byt_irq_unmask, .irq_set_type = byt_irq_type, + .irq_startup = byt_irq_startup, + .irq_shutdown = byt_irq_shutdown, }; static void byt_gpio_irq_init_hw(struct byt_gpio *vg) -- cgit v1.2.3 From c6d7641470fed467777a886c64329fff8f5abf0b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 7 Dec 2013 11:54:19 -0600 Subject: usb: dwc3: omap: remove unnecessary lock the lock was only taken inside the hardirq handler, which runs with IRQs disabled. There's no chance of any race condition happening, even on SMP machines. It's safe to remove that spinlock. Acked-by: Santosh Shilimkar Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index daab0ad10b25..b269dbd47fc4 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -120,9 +119,6 @@ #define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID (1 << 1) struct dwc3_omap { - /* device lock */ - spinlock_t lock; - struct device *dev; int irq; @@ -280,8 +276,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) struct dwc3_omap *omap = _omap; u32 reg; - spin_lock(&omap->lock); - reg = dwc3_omap_read_irqmisc_status(omap); if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) { @@ -322,8 +316,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) dwc3_omap_write_irq0_status(omap, reg); - spin_unlock(&omap->lock); - return IRQ_HANDLED; } @@ -449,8 +441,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) } } - spin_lock_init(&omap->lock); - omap->dev = dev; omap->irq = irq; omap->base = base; -- cgit v1.2.3 From 356ba0213dca4dd68906bb315f8c7a46e81510ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Dec 2013 14:02:51 -0200 Subject: [media] radio-bcm2048: fix signal of value As value can be initialized with a value lower than zero, change it to int, to avoid those warnings: drivers/staging/media/bcm2048/radio-bcm2048.c: In function 'bcm2048_rds_pi_read': drivers/staging/media/bcm2048/radio-bcm2048.c:1989:9: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] struct bcm2048_device *bdev = dev_get_drvdata(dev); \ ^ drivers/staging/media/bcm2048/radio-bcm2048.c:2070:1: note: in expansion of macro 'property_read' property_read(rds_pi, unsigned int, "%x") ^ drivers/staging/media/bcm2048/radio-bcm2048.c: In function 'bcm2048_fm_rds_flags_read': drivers/staging/media/bcm2048/radio-bcm2048.c:1989:9: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] struct bcm2048_device *bdev = dev_get_drvdata(dev); \ ^ drivers/staging/media/bcm2048/radio-bcm2048.c:2074:1: note: in expansion of macro 'property_read' property_read(fm_rds_flags, unsigned int, "%u") ^ drivers/staging/media/bcm2048/radio-bcm2048.c: In function 'bcm2048_region_bottom_frequency_read': drivers/staging/media/bcm2048/radio-bcm2048.c:1989:9: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] struct bcm2048_device *bdev = dev_get_drvdata(dev); \ ^ drivers/staging/media/bcm2048/radio-bcm2048.c:2077:1: note: in expansion of macro 'property_read' property_read(region_bottom_frequency, unsigned int, "%u") ^ drivers/staging/media/bcm2048/radio-bcm2048.c: In function 'bcm2048_region_top_frequency_read': drivers/staging/media/bcm2048/radio-bcm2048.c:1989:9: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] struct bcm2048_device *bdev = dev_get_drvdata(dev); \ ^ drivers/staging/media/bcm2048/radio-bcm2048.c:2078:1: note: in expansion of macro 'property_read' property_read(region_top_frequency, unsigned int, "%u") Cc: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/bcm2048/radio-bcm2048.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 782cc11fd037..494ec3916ef5 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -1987,7 +1987,7 @@ static ssize_t bcm2048_##prop##_read(struct device *dev, \ char *buf) \ { \ struct bcm2048_device *bdev = dev_get_drvdata(dev); \ - size value; \ + int value; \ \ if (!bdev) \ return -ENODEV; \ -- cgit v1.2.3 From f885135ab6047dd159067d15c9a5de1a67de4e27 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 7 Dec 2013 14:00:40 +0800 Subject: spi: coldfire-qspi: remove redundant return value check of platform_get_resource() Remove unneeded error handling on the result of a call to platform_get_resource() when the value is passed to devm_ioremap_resource(). Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 9ee81a4c7351..cabed8f9119e 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -397,12 +397,6 @@ static int mcfqspi_probe(struct platform_device *pdev) mcfqspi = spi_master_get_devdata(master); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_dbg(&pdev->dev, "platform_get_resource failed\n"); - status = -ENXIO; - goto fail0; - } - mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(mcfqspi->iobase)) { status = PTR_ERR(mcfqspi->iobase); -- cgit v1.2.3 From 87917528cc922d0b91643dabacec01415c792086 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 6 Dec 2013 17:12:13 +0300 Subject: spi: bcm63xx-hsspi: checking for ERR_PTR instead of NULL devm_request_and_ioremap() returns NULL on error, it doesn't return an ERR_PTR(). This patch fixes it by switching to devm_ioremap_resource() which is the prefered function anyway. Fixes: 142168eba9dc ('spi: bcm63xx-hsspi: add bcm63xx HSSPI driver') Signed-off-by: Dan Carpenter Acked-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index bc8d848d33b7..2cfe8eb619fd 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -338,7 +338,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) } res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_request_and_ioremap(dev, res_mem); + regs = devm_ioremap_resource(dev, res_mem); if (IS_ERR(regs)) return PTR_ERR(regs); -- cgit v1.2.3 From 991a645d6b3320c07b8d78c58f8911f0b197e5d5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 6 Dec 2013 16:12:41 +0900 Subject: regulator: stw481x-vmmc: use devm_regulator_register() Use devm_regulator_register() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Reviewed-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/stw481x-vmmc.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c index f78857bd6a15..a7e152696a02 100644 --- a/drivers/regulator/stw481x-vmmc.c +++ b/drivers/regulator/stw481x-vmmc.c @@ -74,7 +74,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev) config.init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); - stw481x->vmmc_regulator = regulator_register(&vmmc_regulator, &config); + stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev, + &vmmc_regulator, &config); if (IS_ERR(stw481x->vmmc_regulator)) { dev_err(&pdev->dev, "error initializing STw481x VMMC regulator\n"); @@ -85,14 +86,6 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev) return 0; } -static int stw481x_vmmc_regulator_remove(struct platform_device *pdev) -{ - struct stw481x *stw481x = dev_get_platdata(&pdev->dev); - - regulator_unregister(stw481x->vmmc_regulator); - return 0; -} - static const struct of_device_id stw481x_vmmc_match[] = { { .compatible = "st,stw481x-vmmc", }, {}, @@ -105,7 +98,6 @@ static struct platform_driver stw481x_vmmc_regulator_driver = { .of_match_table = stw481x_vmmc_match, }, .probe = stw481x_vmmc_regulator_probe, - .remove = stw481x_vmmc_regulator_remove, }; module_platform_driver(stw481x_vmmc_regulator_driver); -- cgit v1.2.3 From bb489841b1312f60b2450b01b1c5fa019872f0d3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 19:21:22 +0900 Subject: spi: orion: Use devm_clk_get() Use devm_clk_get() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Jason Cooper Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 744841e095e4..7f2121fe2622 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -434,7 +434,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi = spi_master_get_devdata(master); spi->master = master; - spi->clk = clk_get(&pdev->dev, NULL); + spi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { status = PTR_ERR(spi->clk); goto out; @@ -465,7 +465,6 @@ static int orion_spi_probe(struct platform_device *pdev) out_rel_clk: clk_disable_unprepare(spi->clk); - clk_put(spi->clk); out: spi_master_put(master); return status; @@ -481,7 +480,6 @@ static int orion_spi_remove(struct platform_device *pdev) spi = spi_master_get_devdata(master); clk_disable_unprepare(spi->clk); - clk_put(spi->clk); return 0; } -- cgit v1.2.3 From baafdc1d20a97c5c243f78981c95eadbd3b40caf Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 6 Dec 2013 16:07:09 +0900 Subject: regulator: ab8500: use devm_regulator_register() Use devm_regulator_register() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 0f86695b737a..c625468c7f2c 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -3005,7 +3005,6 @@ static int ab8500_regulator_register(struct platform_device *pdev, struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_regulator_info *info = NULL; struct regulator_config config = { }; - int err; /* assign per-regulator data */ info = &abx500_regulator.info[id]; @@ -3027,17 +3026,12 @@ static int ab8500_regulator_register(struct platform_device *pdev, } /* register regulator with framework */ - info->regulator = regulator_register(&info->desc, &config); + info->regulator = devm_regulator_register(&pdev->dev, &info->desc, + &config); if (IS_ERR(info->regulator)) { - err = PTR_ERR(info->regulator); dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); - /* when we fail, un-register all earlier regulators */ - while (--id >= 0) { - info = &abx500_regulator.info[id]; - regulator_unregister(info->regulator); - } - return err; + return PTR_ERR(info->regulator); } return 0; @@ -3086,17 +3080,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev) static int ab8500_regulator_remove(struct platform_device *pdev) { - int i, err; - - for (i = 0; i < abx500_regulator.info_size; i++) { - struct ab8500_regulator_info *info = NULL; - info = &abx500_regulator.info[i]; - - dev_vdbg(rdev_get_dev(info->regulator), - "%s-remove\n", info->desc.name); - - regulator_unregister(info->regulator); - } + int err; /* remove regulator debug */ err = ab8500_regulator_debug_exit(pdev); -- cgit v1.2.3 From 92dfbdbcb504beb1d716e500cd20b4780961afd5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 6 Dec 2013 16:08:38 +0900 Subject: regulator: db8500-prcmu: use devm_regulator_register() Use devm_regulator_register() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/db8500-prcmu.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index a53c11a529d5..846acf240e48 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -431,17 +431,11 @@ static int db8500_regulator_register(struct platform_device *pdev, config.of_node = np; /* register with the regulator framework */ - info->rdev = regulator_register(&info->desc, &config); + info->rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); if (IS_ERR(info->rdev)) { err = PTR_ERR(info->rdev); dev_err(&pdev->dev, "failed to register %s: err %i\n", info->desc.name, err); - - /* if failing, unregister all earlier regulators */ - while (--id >= 0) { - info = &dbx500_regulator_info[id]; - regulator_unregister(info->rdev); - } return err; } @@ -530,20 +524,8 @@ static int db8500_regulator_probe(struct platform_device *pdev) static int db8500_regulator_remove(struct platform_device *pdev) { - int i; - ux500_regulator_debug_exit(); - for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { - struct dbx500_regulator_info *info; - info = &dbx500_regulator_info[i]; - - dev_vdbg(rdev_get_dev(info->rdev), - "regulator-%s-remove\n", info->desc.name); - - regulator_unregister(info->rdev); - } - return 0; } -- cgit v1.2.3 From f5247b401ccfbbf062ca1f4d3eef433f406c39ae Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 6 Dec 2013 16:11:58 +0900 Subject: regulator: pfuze100: use devm_regulator_register() Use devm_regulator_register() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Acked-by: Robin Gong Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index ba67b2c4e2e7..1d5ef37918f9 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -402,31 +402,18 @@ static int pfuze100_regulator_probe(struct i2c_client *client, config.driver_data = pfuze_chip; config.of_node = match_of_node(i); - pfuze_chip->regulators[i] = regulator_register(desc, &config); + pfuze_chip->regulators[i] = + devm_regulator_register(&client->dev, desc, &config); if (IS_ERR(pfuze_chip->regulators[i])) { dev_err(&client->dev, "register regulator%s failed\n", pfuze100_regulators[i].desc.name); - ret = PTR_ERR(pfuze_chip->regulators[i]); - while (--i >= 0) - regulator_unregister(pfuze_chip->regulators[i]); - return ret; + return PTR_ERR(pfuze_chip->regulators[i]); } } return 0; } -static int pfuze100_regulator_remove(struct i2c_client *client) -{ - int i; - struct pfuze_chip *pfuze_chip = i2c_get_clientdata(client); - - for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) - regulator_unregister(pfuze_chip->regulators[i]); - - return 0; -} - static struct i2c_driver pfuze_driver = { .id_table = pfuze_device_id, .driver = { @@ -435,7 +422,6 @@ static struct i2c_driver pfuze_driver = { .of_match_table = pfuze_dt_ids, }, .probe = pfuze100_regulator_probe, - .remove = pfuze100_regulator_remove, }; module_i2c_driver(pfuze_driver); -- cgit v1.2.3 From 9e03d05eee4ca45ed12749ef6c26bf616262cdd2 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:13:50 +0900 Subject: spi: rcar: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 19c65c43cbc5..cfdbb422a40a 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -887,7 +887,6 @@ static int rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); - spi_unregister_master(rspi->master); rspi_release_dma(rspi); return 0; @@ -972,7 +971,7 @@ static int rspi_probe(struct platform_device *pdev) goto error2; } - ret = spi_register_master(master); + ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master error.\n"); goto error2; -- cgit v1.2.3 From 48c3fc93803a27bb9d2c79d718cf142974f080c8 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 8 Dec 2013 16:35:09 +0100 Subject: spi: tegra114: use u32 for 32-bit register values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously used “unsigned long” may lead to confusion should the code be compiled for 64-bit machine. This commit also removes some unused fields of the tegra_spi_data structure as well as removes duplicated #defines. Signed-off-by: Michal Nazarewicz Tested-by: Stephen Warren Acked-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 98 ++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index aaecfb3ebf58..47b93cc4bd19 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -54,11 +54,8 @@ #define SPI_CS_SS_VAL (1 << 20) #define SPI_CS_SW_HW (1 << 21) /* SPI_CS_POL_INACTIVE bits are default high */ -#define SPI_CS_POL_INACTIVE 22 -#define SPI_CS_POL_INACTIVE_0 (1 << 22) -#define SPI_CS_POL_INACTIVE_1 (1 << 23) -#define SPI_CS_POL_INACTIVE_2 (1 << 24) -#define SPI_CS_POL_INACTIVE_3 (1 << 25) + /* n from 0 to 3 */ +#define SPI_CS_POL_INACTIVE(n) (1 << (22 + (n))) #define SPI_CS_POL_INACTIVE_MASK (0xF << 22) #define SPI_CS_SEL_0 (0 << 26) @@ -165,9 +162,6 @@ #define MAX_HOLD_CYCLES 16 #define SPI_DEFAULT_SPEED 25000000 -#define MAX_CHIP_SELECT 4 -#define SPI_FIFO_DEPTH 64 - struct tegra_spi_data { struct device *dev; struct spi_master *master; @@ -184,7 +178,6 @@ struct tegra_spi_data { struct spi_device *cur_spi; struct spi_device *cs_control; unsigned cur_pos; - unsigned cur_len; unsigned words_per_32bit; unsigned bytes_per_word; unsigned curr_dma_words; @@ -204,12 +197,10 @@ struct tegra_spi_data { u32 rx_status; u32 status_reg; bool is_packed; - unsigned long packed_size; u32 command1_reg; u32 dma_control_reg; u32 def_command1_reg; - u32 spi_cs_timing; struct completion xfer_completion; struct spi_transfer *curr_xfer; @@ -227,14 +218,14 @@ struct tegra_spi_data { static int tegra_spi_runtime_suspend(struct device *dev); static int tegra_spi_runtime_resume(struct device *dev); -static inline unsigned long tegra_spi_readl(struct tegra_spi_data *tspi, +static inline u32 tegra_spi_readl(struct tegra_spi_data *tspi, unsigned long reg) { return readl(tspi->base + reg); } static inline void tegra_spi_writel(struct tegra_spi_data *tspi, - unsigned long val, unsigned long reg) + u32 val, unsigned long reg) { writel(val, tspi->base + reg); @@ -245,7 +236,7 @@ static inline void tegra_spi_writel(struct tegra_spi_data *tspi, static void tegra_spi_clear_status(struct tegra_spi_data *tspi) { - unsigned long val; + u32 val; /* Write 1 to clear status register */ val = tegra_spi_readl(tspi, SPI_TRANS_STATUS); @@ -296,10 +287,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( { unsigned nbytes; unsigned tx_empty_count; - unsigned long fifo_status; + u32 fifo_status; unsigned max_n_32bit; unsigned i, count; - unsigned long x; unsigned int written_words; unsigned fifo_words_left; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; @@ -313,9 +303,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( nbytes = written_words * tspi->bytes_per_word; max_n_32bit = DIV_ROUND_UP(nbytes, 4); for (count = 0; count < max_n_32bit; count++) { - x = 0; + u32 x = 0; for (i = 0; (i < 4) && nbytes; i++, nbytes--) - x |= (*tx_buf++) << (i*8); + x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } } else { @@ -323,10 +313,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( written_words = max_n_32bit; nbytes = written_words * tspi->bytes_per_word; for (count = 0; count < max_n_32bit; count++) { - x = 0; + u32 x = 0; for (i = 0; nbytes && (i < tspi->bytes_per_word); i++, nbytes--) - x |= ((*tx_buf++) << i*8); + x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } } @@ -338,9 +328,8 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( struct tegra_spi_data *tspi, struct spi_transfer *t) { unsigned rx_full_count; - unsigned long fifo_status; + u32 fifo_status; unsigned i, count; - unsigned long x; unsigned int read_words = 0; unsigned len; u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos; @@ -350,20 +339,16 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( if (tspi->is_packed) { len = tspi->curr_dma_words * tspi->bytes_per_word; for (count = 0; count < rx_full_count; count++) { - x = tegra_spi_readl(tspi, SPI_RX_FIFO); + u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO); for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; read_words += tspi->curr_dma_words; } else { - unsigned int rx_mask; - unsigned int bits_per_word = t->bits_per_word; - - rx_mask = (1 << bits_per_word) - 1; + u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; for (count = 0; count < rx_full_count; count++) { - x = tegra_spi_readl(tspi, SPI_RX_FIFO); - x &= rx_mask; + u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) *rx_buf++ = (x >> (i*8)) & 0xFF; } @@ -376,27 +361,24 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( static void tegra_spi_copy_client_txbuf_to_spi_txbuf( struct tegra_spi_data *tspi, struct spi_transfer *t) { - unsigned len; - /* Make the dma buffer to read by cpu */ dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys, tspi->dma_buf_size, DMA_TO_DEVICE); if (tspi->is_packed) { - len = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); } else { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; - unsigned int x; for (count = 0; count < tspi->curr_dma_words; count++) { - x = 0; + u32 x = 0; for (i = 0; consume && (i < tspi->bytes_per_word); i++, consume--) - x |= ((*tx_buf++) << i * 8); + x |= (u32)(*tx_buf++) << (i * 8); tspi->tx_dma_buf[count] = x; } } @@ -410,27 +392,21 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf( struct tegra_spi_data *tspi, struct spi_transfer *t) { - unsigned len; - /* Make the dma buffer to read by cpu */ dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys, tspi->dma_buf_size, DMA_FROM_DEVICE); if (tspi->is_packed) { - len = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len); } else { unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; - unsigned int x; - unsigned int rx_mask; - unsigned int bits_per_word = t->bits_per_word; + u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; - rx_mask = (1 << bits_per_word) - 1; for (count = 0; count < tspi->curr_dma_words; count++) { - x = tspi->rx_dma_buf[count]; - x &= rx_mask; + u32 x = tspi->rx_dma_buf[count] & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) *rx_buf++ = (x >> (i*8)) & 0xFF; } @@ -490,16 +466,16 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) static int tegra_spi_start_dma_based_transfer( struct tegra_spi_data *tspi, struct spi_transfer *t) { - unsigned long val; + u32 val; unsigned int len; int ret = 0; - unsigned long status; + u32 status; /* Make sure that Rx and Tx fifo are empty */ status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { - dev_err(tspi->dev, - "Rx/Tx fifo are not empty status 0x%08lx\n", status); + dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", + (unsigned)status); return -EIO; } @@ -564,7 +540,7 @@ static int tegra_spi_start_dma_based_transfer( static int tegra_spi_start_cpu_based_transfer( struct tegra_spi_data *tspi, struct spi_transfer *t) { - unsigned long val; + u32 val; unsigned cur_words; if (tspi->cur_direction & DATA_DIR_TX) @@ -677,13 +653,13 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, dma_release_channel(dma_chan); } -static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi, +static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, struct spi_transfer *t, bool is_first_of_msg) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); u32 speed = t->speed_hz; u8 bits_per_word = t->bits_per_word; - unsigned long command1; + u32 command1; int req_mode; if (speed != tspi->cur_speed) { @@ -738,7 +714,7 @@ static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi, } static int tegra_spi_start_transfer_one(struct spi_device *spi, - struct spi_transfer *t, unsigned long command1) + struct spi_transfer *t, u32 command1) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); unsigned total_fifo_words; @@ -763,8 +739,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, tegra_spi_writel(tspi, command1, SPI_COMMAND1); tspi->command1_reg = command1; - dev_dbg(tspi->dev, "The def 0x%x and written 0x%lx\n", - tspi->def_command1_reg, command1); + dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n", + tspi->def_command1_reg, (unsigned)command1); if (total_fifo_words > SPI_FIFO_DEPTH) ret = tegra_spi_start_dma_based_transfer(tspi, t); @@ -776,15 +752,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, static int tegra_spi_setup(struct spi_device *spi) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); - unsigned long val; + u32 val; unsigned long flags; int ret; - unsigned int cs_pol_bit[MAX_CHIP_SELECT] = { - SPI_CS_POL_INACTIVE_0, - SPI_CS_POL_INACTIVE_1, - SPI_CS_POL_INACTIVE_2, - SPI_CS_POL_INACTIVE_3, - }; dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n", spi->bits_per_word, @@ -806,9 +776,9 @@ static int tegra_spi_setup(struct spi_device *spi) spin_lock_irqsave(&tspi->lock, flags); val = tspi->def_command1_reg; if (spi->mode & SPI_CS_HIGH) - val &= ~cs_pol_bit[spi->chip_select]; + val &= ~SPI_CS_POL_INACTIVE(spi->chip_select); else - val |= cs_pol_bit[spi->chip_select]; + val |= SPI_CS_POL_INACTIVE(spi->chip_select); tspi->def_command1_reg = val; tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); spin_unlock_irqrestore(&tspi->lock, flags); @@ -842,7 +812,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, msg->actual_length = 0; list_for_each_entry(xfer, &msg->transfers, transfer_list) { - unsigned long cmd1; + u32 cmd1; reinit_completion(&tspi->xfer_completion); -- cgit v1.2.3 From 5fd38677a48deab4ea480f078a838758a030d3a2 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 8 Dec 2013 16:35:10 +0100 Subject: spi: tegra20-slink: use u32 for 32-bit register values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously used “unsigned long” may lead to confusion should the code be compiled for 64-bit machine. Signed-off-by: Michal Nazarewicz Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-slink.c | 97 +++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index e66715ba37ed..3ce1de8872f0 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -196,7 +196,7 @@ struct tegra_slink_data { u32 rx_status; u32 status_reg; bool is_packed; - unsigned long packed_size; + u32 packed_size; u32 command_reg; u32 command2_reg; @@ -220,14 +220,14 @@ struct tegra_slink_data { static int tegra_slink_runtime_suspend(struct device *dev); static int tegra_slink_runtime_resume(struct device *dev); -static inline unsigned long tegra_slink_readl(struct tegra_slink_data *tspi, +static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi, unsigned long reg) { return readl(tspi->base + reg); } static inline void tegra_slink_writel(struct tegra_slink_data *tspi, - unsigned long val, unsigned long reg) + u32 val, unsigned long reg) { writel(val, tspi->base + reg); @@ -238,38 +238,30 @@ static inline void tegra_slink_writel(struct tegra_slink_data *tspi, static void tegra_slink_clear_status(struct tegra_slink_data *tspi) { - unsigned long val; - unsigned long val_write = 0; + u32 val_write; - val = tegra_slink_readl(tspi, SLINK_STATUS); + tegra_slink_readl(tspi, SLINK_STATUS); /* Write 1 to clear status register */ val_write = SLINK_RDY | SLINK_FIFO_ERROR; tegra_slink_writel(tspi, val_write, SLINK_STATUS); } -static unsigned long tegra_slink_get_packed_size(struct tegra_slink_data *tspi, +static u32 tegra_slink_get_packed_size(struct tegra_slink_data *tspi, struct spi_transfer *t) { - unsigned long val; - switch (tspi->bytes_per_word) { case 0: - val = SLINK_PACK_SIZE_4; - break; + return SLINK_PACK_SIZE_4; case 1: - val = SLINK_PACK_SIZE_8; - break; + return SLINK_PACK_SIZE_8; case 2: - val = SLINK_PACK_SIZE_16; - break; + return SLINK_PACK_SIZE_16; case 4: - val = SLINK_PACK_SIZE_32; - break; + return SLINK_PACK_SIZE_32; default: - val = 0; + return 0; } - return val; } static unsigned tegra_slink_calculate_curr_xfer_param( @@ -312,10 +304,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf( { unsigned nbytes; unsigned tx_empty_count; - unsigned long fifo_status; + u32 fifo_status; unsigned max_n_32bit; unsigned i, count; - unsigned long x; unsigned int written_words; unsigned fifo_words_left; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; @@ -329,9 +320,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf( nbytes = written_words * tspi->bytes_per_word; max_n_32bit = DIV_ROUND_UP(nbytes, 4); for (count = 0; count < max_n_32bit; count++) { - x = 0; + u32 x = 0; for (i = 0; (i < 4) && nbytes; i++, nbytes--) - x |= (*tx_buf++) << (i*8); + x |= (u32)(*tx_buf++) << (i * 8); tegra_slink_writel(tspi, x, SLINK_TX_FIFO); } } else { @@ -339,10 +330,10 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf( written_words = max_n_32bit; nbytes = written_words * tspi->bytes_per_word; for (count = 0; count < max_n_32bit; count++) { - x = 0; + u32 x = 0; for (i = 0; nbytes && (i < tspi->bytes_per_word); i++, nbytes--) - x |= ((*tx_buf++) << i*8); + x |= (u32)(*tx_buf++) << (i * 8); tegra_slink_writel(tspi, x, SLINK_TX_FIFO); } } @@ -354,9 +345,8 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( struct tegra_slink_data *tspi, struct spi_transfer *t) { unsigned rx_full_count; - unsigned long fifo_status; + u32 fifo_status; unsigned i, count; - unsigned long x; unsigned int read_words = 0; unsigned len; u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos; @@ -366,7 +356,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( if (tspi->is_packed) { len = tspi->curr_dma_words * tspi->bytes_per_word; for (count = 0; count < rx_full_count; count++) { - x = tegra_slink_readl(tspi, SLINK_RX_FIFO); + u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO); for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } @@ -374,7 +364,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( read_words += tspi->curr_dma_words; } else { for (count = 0; count < rx_full_count; count++) { - x = tegra_slink_readl(tspi, SLINK_RX_FIFO); + u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO); for (i = 0; (i < tspi->bytes_per_word); i++) *rx_buf++ = (x >> (i*8)) & 0xFF; } @@ -387,27 +377,24 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( static void tegra_slink_copy_client_txbuf_to_spi_txbuf( struct tegra_slink_data *tspi, struct spi_transfer *t) { - unsigned len; - /* Make the dma buffer to read by cpu */ dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys, tspi->dma_buf_size, DMA_TO_DEVICE); if (tspi->is_packed) { - len = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); } else { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; - unsigned int x; for (count = 0; count < tspi->curr_dma_words; count++) { - x = 0; + u32 x = 0; for (i = 0; consume && (i < tspi->bytes_per_word); i++, consume--) - x |= ((*tx_buf++) << i * 8); + x |= (u32)(*tx_buf++) << (i * 8); tspi->tx_dma_buf[count] = x; } } @@ -434,14 +421,10 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf( unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; - unsigned int x; - unsigned int rx_mask, bits_per_word; + u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; - bits_per_word = t->bits_per_word; - rx_mask = (1 << bits_per_word) - 1; for (count = 0; count < tspi->curr_dma_words; count++) { - x = tspi->rx_dma_buf[count]; - x &= rx_mask; + u32 x = tspi->rx_dma_buf[count] & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) *rx_buf++ = (x >> (i*8)) & 0xFF; } @@ -501,17 +484,16 @@ static int tegra_slink_start_rx_dma(struct tegra_slink_data *tspi, int len) static int tegra_slink_start_dma_based_transfer( struct tegra_slink_data *tspi, struct spi_transfer *t) { - unsigned long val; - unsigned long test_val; + u32 val; unsigned int len; int ret = 0; - unsigned long status; + u32 status; /* Make sure that Rx and Tx fifo are empty */ status = tegra_slink_readl(tspi, SLINK_STATUS); if ((status & SLINK_FIFO_EMPTY) != SLINK_FIFO_EMPTY) { - dev_err(tspi->dev, - "Rx/Tx fifo are not empty status 0x%08lx\n", status); + dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", + (unsigned)status); return -EIO; } @@ -551,9 +533,9 @@ static int tegra_slink_start_dma_based_transfer( } /* Wait for tx fifo to be fill before starting slink */ - test_val = tegra_slink_readl(tspi, SLINK_STATUS); - while (!(test_val & SLINK_TX_FULL)) - test_val = tegra_slink_readl(tspi, SLINK_STATUS); + status = tegra_slink_readl(tspi, SLINK_STATUS); + while (!(status & SLINK_TX_FULL)) + status = tegra_slink_readl(tspi, SLINK_STATUS); } if (tspi->cur_direction & DATA_DIR_RX) { @@ -587,7 +569,7 @@ static int tegra_slink_start_dma_based_transfer( static int tegra_slink_start_cpu_based_transfer( struct tegra_slink_data *tspi, struct spi_transfer *t) { - unsigned long val; + u32 val; unsigned cur_words; val = tspi->packed_size; @@ -714,8 +696,8 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, u8 bits_per_word; unsigned total_fifo_words; int ret; - unsigned long command; - unsigned long command2; + u32 command; + u32 command2; bits_per_word = t->bits_per_word; speed = t->speed_hz; @@ -762,17 +744,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, static int tegra_slink_setup(struct spi_device *spi) { - struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master); - unsigned long val; - unsigned long flags; - int ret; - unsigned int cs_pol_bit[MAX_CHIP_SELECT] = { + static const u32 cs_pol_bit[MAX_CHIP_SELECT] = { SLINK_CS_POLARITY, SLINK_CS_POLARITY1, SLINK_CS_POLARITY2, SLINK_CS_POLARITY3, }; + struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master); + u32 val; + unsigned long flags; + int ret; + dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n", spi->bits_per_word, spi->mode & SPI_CPOL ? "" : "~", -- cgit v1.2.3 From a553a31d9f32700ef0d3a1490e222ec15e600140 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 8 Dec 2013 16:35:11 +0100 Subject: spi: tegra20-sflash: use u32 for 32-bit register values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously used “unsigned long” may lead to confusion should the code be compiled for 64-bit machine. Signed-off-by: Michal Nazarewicz Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-sflash.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 4dc8e8129459..af78c17388d2 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -148,14 +148,14 @@ struct tegra_sflash_data { static int tegra_sflash_runtime_suspend(struct device *dev); static int tegra_sflash_runtime_resume(struct device *dev); -static inline unsigned long tegra_sflash_readl(struct tegra_sflash_data *tsd, +static inline u32 tegra_sflash_readl(struct tegra_sflash_data *tsd, unsigned long reg) { return readl(tsd->base + reg); } static inline void tegra_sflash_writel(struct tegra_sflash_data *tsd, - unsigned long val, unsigned long reg) + u32 val, unsigned long reg) { writel(val, tsd->base + reg); } @@ -185,7 +185,7 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf( struct tegra_sflash_data *tsd, struct spi_transfer *t) { unsigned nbytes; - unsigned long status; + u32 status; unsigned max_n_32bit = tsd->curr_xfer_words; u8 *tx_buf = (u8 *)t->tx_buf + tsd->cur_tx_pos; @@ -196,11 +196,11 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf( status = tegra_sflash_readl(tsd, SPI_STATUS); while (!(status & SPI_TXF_FULL)) { int i; - unsigned int x = 0; + u32 x = 0; for (i = 0; nbytes && (i < tsd->bytes_per_word); i++, nbytes--) - x |= ((*tx_buf++) << i*8); + x |= (u32)(*tx_buf++) << (i * 8); tegra_sflash_writel(tsd, x, SPI_TX_FIFO); if (!nbytes) break; @@ -214,16 +214,14 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf( static int tegra_sflash_read_rx_fifo_to_client_rxbuf( struct tegra_sflash_data *tsd, struct spi_transfer *t) { - unsigned long status; + u32 status; unsigned int read_words = 0; u8 *rx_buf = (u8 *)t->rx_buf + tsd->cur_rx_pos; status = tegra_sflash_readl(tsd, SPI_STATUS); while (!(status & SPI_RXF_EMPTY)) { int i; - unsigned long x; - - x = tegra_sflash_readl(tsd, SPI_RX_FIFO); + u32 x = tegra_sflash_readl(tsd, SPI_RX_FIFO); for (i = 0; (i < tsd->bytes_per_word); i++) *rx_buf++ = (x >> (i*8)) & 0xFF; read_words++; @@ -236,7 +234,7 @@ static int tegra_sflash_read_rx_fifo_to_client_rxbuf( static int tegra_sflash_start_cpu_based_transfer( struct tegra_sflash_data *tsd, struct spi_transfer *t) { - unsigned long val = 0; + u32 val = 0; unsigned cur_words; if (tsd->cur_direction & DATA_DIR_TX) @@ -266,7 +264,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi, { struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master); u32 speed; - unsigned long command; + u32 command; speed = t->speed_hz; if (speed != tsd->cur_speed) { @@ -313,7 +311,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi, tegra_sflash_writel(tsd, command, SPI_COMMAND); tsd->command_reg = command; - return tegra_sflash_start_cpu_based_transfer(tsd, t); + return tegra_sflash_start_cpu_based_transfer(tsd, t); } static int tegra_sflash_setup(struct spi_device *spi) -- cgit v1.2.3 From acc0f67f307f52f7aec1cffdc40a786c15dd21d9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 9 Dec 2013 09:23:52 -0500 Subject: tty: Halve flip buffer GFP_ATOMIC memory consumption tty flip buffers use GFP_ATOMIC allocations for received data which is to be processed by the line discipline. For each byte received, an extra byte is used to indicate the error status of that byte. Instead, if the received data is error-free, encode the entire buffer without status bytes. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 45 +++++++++++++++++++++++++++++++++++---------- include/linux/tty.h | 4 ++++ include/linux/tty_flip.h | 8 ++++++-- 3 files changed, 45 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 08835a6dd022..3002e20e10d7 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -101,6 +101,7 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size) p->next = NULL; p->commit = 0; p->read = 0; + p->flags = 0; } /** @@ -229,31 +230,49 @@ void tty_buffer_flush(struct tty_struct *tty) * tty_buffer_request_room - grow tty buffer if needed * @tty: tty structure * @size: size desired + * @flags: buffer flags if new buffer allocated (default = 0) * * Make at least size bytes of linear space available for the tty * buffer. If we fail return the size we managed to find. + * + * Will change over to a new buffer if the current buffer is encoded as + * TTY_NORMAL (so has no flags buffer) and the new buffer requires + * a flags buffer. */ -int tty_buffer_request_room(struct tty_port *port, size_t size) +static int __tty_buffer_request_room(struct tty_port *port, size_t size, + int flags) { struct tty_bufhead *buf = &port->buf; struct tty_buffer *b, *n; - int left; + int left, change; b = buf->tail; - left = b->size - b->used; + if (b->flags & TTYB_NORMAL) + left = 2 * b->size - b->used; + else + left = b->size - b->used; - if (left < size) { + change = (b->flags & TTYB_NORMAL) && (~flags & TTYB_NORMAL); + if (change || left < size) { /* This is the slow path - looking for new buffers to use */ if ((n = tty_buffer_alloc(port, size)) != NULL) { + n->flags = flags; buf->tail = n; b->commit = b->used; smp_mb(); b->next = n; - } else + } else if (change) + size = 0; + else size = left; } return size; } + +int tty_buffer_request_room(struct tty_port *port, size_t size) +{ + return __tty_buffer_request_room(port, size, 0); +} EXPORT_SYMBOL_GPL(tty_buffer_request_room); /** @@ -273,12 +292,14 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, int copied = 0; do { int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); - int space = tty_buffer_request_room(port, goal); + int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0; + int space = __tty_buffer_request_room(port, goal, flags); struct tty_buffer *tb = port->buf.tail; if (unlikely(space == 0)) break; memcpy(char_buf_ptr(tb, tb->used), chars, space); - memset(flag_buf_ptr(tb, tb->used), flag, space); + if (~tb->flags & TTYB_NORMAL) + memset(flag_buf_ptr(tb, tb->used), flag, space); tb->used += space; copied += space; chars += space; @@ -361,11 +382,12 @@ EXPORT_SYMBOL(tty_schedule_flip); int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, size_t size) { - int space = tty_buffer_request_room(port, size); + int space = __tty_buffer_request_room(port, size, TTYB_NORMAL); if (likely(space)) { struct tty_buffer *tb = port->buf.tail; *chars = char_buf_ptr(tb, tb->used); - memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); + if (~tb->flags & TTYB_NORMAL) + memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); tb->used += space; } return space; @@ -378,7 +400,10 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) { struct tty_ldisc *disc = tty->ldisc; unsigned char *p = char_buf_ptr(head, head->read); - char *f = flag_buf_ptr(head, head->read); + char *f = NULL; + + if (~head->flags & TTYB_NORMAL) + f = flag_buf_ptr(head, head->read); if (disc->ops->receive_buf2) count = disc->ops->receive_buf2(tty, p, f, count); diff --git a/include/linux/tty.h b/include/linux/tty.h index 38fcc0574ba9..ad98b4376968 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -39,10 +39,14 @@ struct tty_buffer { int size; int commit; int read; + int flags; /* Data points here */ unsigned long data[0]; }; +/* Values for .flags field of tty_buffer */ +#define TTYB_NORMAL 1 /* buffer has no flags buffer */ + static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs) { return ((unsigned char *)b->data) + ofs; diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 3f821e98af0f..c28dd523f96e 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -17,8 +17,12 @@ static inline int tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) { struct tty_buffer *tb = port->buf.tail; - if (tb && tb->used < tb->size) { - *flag_buf_ptr(tb, tb->used) = flag; + int change; + + change = (tb->flags & TTYB_NORMAL) && (flag != TTY_NORMAL); + if (!change && tb->used < tb->size) { + if (~tb->flags & TTYB_NORMAL) + *flag_buf_ptr(tb, tb->used) = flag; *char_buf_ptr(tb, tb->used++) = ch; return 1; } -- cgit v1.2.3 From 26825cfd90f94f47068519901b3670ae7da320fe Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 9 Dec 2013 10:38:20 +0100 Subject: ARM: 7914/1: amba: Drop legacy PM support and use the pm_generic functions All AMBA drivers have converted to use the modern PM ops thus we can safely drop the legacy PM support from the bus. While using the modern PM ops it also makes sense to convert to use the pm_generic callback functions. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 180 +++-------------------------------------------------- 1 file changed, 7 insertions(+), 173 deletions(-) (limited to 'drivers') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index c4876ac9151a..b90dc1ec109d 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -83,162 +83,6 @@ static struct device_attribute amba_dev_attrs[] = { __ATTR_NULL, }; -#ifdef CONFIG_PM_SLEEP - -static int amba_legacy_suspend(struct device *dev, pm_message_t mesg) -{ - struct amba_driver *adrv = to_amba_driver(dev->driver); - struct amba_device *adev = to_amba_device(dev); - int ret = 0; - - if (dev->driver && adrv->suspend) - ret = adrv->suspend(adev, mesg); - - return ret; -} - -static int amba_legacy_resume(struct device *dev) -{ - struct amba_driver *adrv = to_amba_driver(dev->driver); - struct amba_device *adev = to_amba_device(dev); - int ret = 0; - - if (dev->driver && adrv->resume) - ret = adrv->resume(adev); - - return ret; -} - -#endif /* CONFIG_PM_SLEEP */ - -#ifdef CONFIG_SUSPEND - -static int amba_pm_suspend(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->suspend) - ret = drv->pm->suspend(dev); - } else { - ret = amba_legacy_suspend(dev, PMSG_SUSPEND); - } - - return ret; -} - -static int amba_pm_resume(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->resume) - ret = drv->pm->resume(dev); - } else { - ret = amba_legacy_resume(dev); - } - - return ret; -} - -#else /* !CONFIG_SUSPEND */ - -#define amba_pm_suspend NULL -#define amba_pm_resume NULL - -#endif /* !CONFIG_SUSPEND */ - -#ifdef CONFIG_HIBERNATE_CALLBACKS - -static int amba_pm_freeze(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->freeze) - ret = drv->pm->freeze(dev); - } else { - ret = amba_legacy_suspend(dev, PMSG_FREEZE); - } - - return ret; -} - -static int amba_pm_thaw(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->thaw) - ret = drv->pm->thaw(dev); - } else { - ret = amba_legacy_resume(dev); - } - - return ret; -} - -static int amba_pm_poweroff(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->poweroff) - ret = drv->pm->poweroff(dev); - } else { - ret = amba_legacy_suspend(dev, PMSG_HIBERNATE); - } - - return ret; -} - -static int amba_pm_restore(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->restore) - ret = drv->pm->restore(dev); - } else { - ret = amba_legacy_resume(dev); - } - - return ret; -} - -#else /* !CONFIG_HIBERNATE_CALLBACKS */ - -#define amba_pm_freeze NULL -#define amba_pm_thaw NULL -#define amba_pm_poweroff NULL -#define amba_pm_restore NULL - -#endif /* !CONFIG_HIBERNATE_CALLBACKS */ - #ifdef CONFIG_PM_RUNTIME /* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to @@ -272,15 +116,13 @@ static int amba_pm_runtime_resume(struct device *dev) } #endif -#ifdef CONFIG_PM - static const struct dev_pm_ops amba_pm = { - .suspend = amba_pm_suspend, - .resume = amba_pm_resume, - .freeze = amba_pm_freeze, - .thaw = amba_pm_thaw, - .poweroff = amba_pm_poweroff, - .restore = amba_pm_restore, + .suspend = pm_generic_suspend, + .resume = pm_generic_resume, + .freeze = pm_generic_freeze, + .thaw = pm_generic_thaw, + .poweroff = pm_generic_poweroff, + .restore = pm_generic_restore, SET_RUNTIME_PM_OPS( amba_pm_runtime_suspend, amba_pm_runtime_resume, @@ -288,14 +130,6 @@ static const struct dev_pm_ops amba_pm = { ) }; -#define AMBA_PM (&amba_pm) - -#else /* !CONFIG_PM */ - -#define AMBA_PM NULL - -#endif /* !CONFIG_PM */ - /* * Primecells are part of the Advanced Microcontroller Bus Architecture, * so we call the bus "amba". @@ -305,7 +139,7 @@ struct bus_type amba_bustype = { .dev_attrs = amba_dev_attrs, .match = amba_match, .uevent = amba_uevent, - .pm = AMBA_PM, + .pm = &amba_pm, }; static int __init amba_init(void) -- cgit v1.2.3 From 89a5c985f81a0b60f7522044938f76caf28075a6 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 9 Dec 2013 10:39:13 +0100 Subject: ARM: 7915/1: amba: Convert to clk_prepare_enable and clk_disable_unprepare To simplify code and error handling let's use clk_prepare_enable and clk_disable_unprepare. No functional change. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index b90dc1ec109d..ea1d8357f298 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -151,36 +151,23 @@ postcore_initcall(amba_init); static int amba_get_enable_pclk(struct amba_device *pcdev) { - struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk"); int ret; - pcdev->pclk = pclk; + pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk"); + if (IS_ERR(pcdev->pclk)) + return PTR_ERR(pcdev->pclk); - if (IS_ERR(pclk)) - return PTR_ERR(pclk); - - ret = clk_prepare(pclk); - if (ret) { - clk_put(pclk); - return ret; - } - - ret = clk_enable(pclk); - if (ret) { - clk_unprepare(pclk); - clk_put(pclk); - } + ret = clk_prepare_enable(pcdev->pclk); + if (ret) + clk_put(pcdev->pclk); return ret; } static void amba_put_disable_pclk(struct amba_device *pcdev) { - struct clk *pclk = pcdev->pclk; - - clk_disable(pclk); - clk_unprepare(pclk); - clk_put(pclk); + clk_disable_unprepare(pcdev->pclk); + clk_put(pcdev->pclk); } /* -- cgit v1.2.3 From 5303c0f46c8708fff4148ebcc491f78710356952 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 9 Dec 2013 10:40:22 +0100 Subject: ARM: 7916/1: amba: Add clk_prepare|unprepare in runtime PM callbacks To fully gate the clock and thus potentially also save more power in runtime suspend state, extend clock handling with clk_prepare|unprepare in the runtime PM callbacks. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index ea1d8357f298..9e6029105607 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -95,7 +95,7 @@ static int amba_pm_runtime_suspend(struct device *dev) int ret = pm_generic_runtime_suspend(dev); if (ret == 0 && dev->driver) - clk_disable(pcdev->pclk); + clk_disable_unprepare(pcdev->pclk); return ret; } @@ -106,7 +106,7 @@ static int amba_pm_runtime_resume(struct device *dev) int ret; if (dev->driver) { - ret = clk_enable(pcdev->pclk); + ret = clk_prepare_enable(pcdev->pclk); /* Failure is probably fatal to the system, but... */ if (ret) return ret; -- cgit v1.2.3 From 3961a61aad9b711bcd74aa7ea2c3655046df7b43 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Oct 2013 11:27:55 +0300 Subject: iwlwifi: remove TX_CMD id from transport layer The transport layer doesn't need to know the TX_CMD id. It can be set by the op_mode. The transport layer still needs to know the layout of the Tx command because of alignment issues and because of the scratch pointer. Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/dvm/tx.c | 1 + drivers/net/wireless/iwlwifi/mvm/tx.c | 1 + drivers/net/wireless/iwlwifi/pcie/tx.c | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 1fef5240e6ad..e12b1a63c484 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -368,6 +368,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, goto drop_unlock_priv; memset(dev_cmd, 0, sizeof(*dev_cmd)); + dev_cmd->hdr.cmd = REPLY_TX; tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; /* Total # bytes to be transmitted */ diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 43d97c33a75a..1f1945806421 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -276,6 +276,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, return NULL; memset(dev_cmd, 0, sizeof(*dev_cmd)); + dev_cmd->hdr.cmd = TX_CMD; tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; if (info->control.hw_key) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 0adde919a258..ff977b083411 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1674,7 +1674,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, txq->entries[q->write_ptr].skb = skb; txq->entries[q->write_ptr].cmd = dev_cmd; - dev_cmd->hdr.cmd = REPLY_TX; dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | INDEX_TO_SEQ(q->write_ptr))); -- cgit v1.2.3 From 119663c3603412962f2986c1318950aef7421b1f Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Thu, 17 Oct 2013 14:26:50 +0200 Subject: iwlwifi: mvm: Add debugfs entry to generate NMI to NIC Writting to fw_nmi entry will set DEVICE_SET_NMI_REG (0x00a01c30) generating NMI that halts NIC CPU. Reviewed-by: Johannes Berg Signed-off-by: Alexander Bondar Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-prph.h | 3 +++ drivers/net/wireless/iwlwifi/mvm/debugfs.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index a70c7b9d9bad..f6412dae2659 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -102,6 +102,9 @@ /* Device system time */ #define DEVICE_SYSTEM_TIME_REG 0xA0206C +/* Device NMI register */ +#define DEVICE_SET_NMI_REG 0x00a01c30 + /***************************************************************************** * 7000/3000 series SHR DTS addresses * *****************************************************************************/ diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index a8fe6b41f9a3..342bd1a07ab7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -63,6 +63,7 @@ #include "mvm.h" #include "sta.h" #include "iwl-io.h" +#include "iwl-prph.h" struct iwl_dbgfs_mvm_ctx { struct iwl_mvm *mvm; @@ -804,6 +805,17 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_fw_nmi_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm *mvm = file->private_data; + + iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1); + + return count; +} + static ssize_t iwl_dbgfs_scan_ant_rxchain_read(struct file *file, char __user *user_buf, @@ -1168,6 +1180,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off); MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); +MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain); #ifdef CONFIG_PM_SLEEP @@ -1196,6 +1209,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); + MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, S_IWUSR | S_IRUSR); #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From 6dde8c4837128aa840851bb0b547708868494198 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Oct 2013 18:30:38 +0100 Subject: iwlwifi: pcie: remove useless condition test After wait_event_timeout(), the condition must still be true if it returns >0, in fact almost the last thing in it is checking the condition again. It's therefore not useful to check yet again in our code, clean it up. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/tx.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index ff977b083411..a4ef5cc11100 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1542,30 +1542,24 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, } if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { - struct iwl_txq *txq = - &trans_pcie->txq[trans_pcie->cmd_queue]; - struct iwl_queue *q = &txq->q; + struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; + struct iwl_queue *q = &txq->q; - IWL_ERR(trans, - "Error sending %s: time out after %dms.\n", - get_cmd_string(trans_pcie, cmd->id), - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); + IWL_ERR(trans, "Error sending %s: time out after %dms.\n", + get_cmd_string(trans_pcie, cmd->id), + jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - IWL_ERR(trans, - "Current CMD queue read_ptr %d write_ptr %d\n", - q->read_ptr, q->write_ptr); + IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n", + q->read_ptr, q->write_ptr); - clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); - IWL_DEBUG_INFO(trans, - "Clearing HCMD_ACTIVE for command %s\n", - get_cmd_string(trans_pcie, cmd->id)); - ret = -ETIMEDOUT; + clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); + IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", + get_cmd_string(trans_pcie, cmd->id)); + ret = -ETIMEDOUT; - iwl_nic_error(trans); + iwl_nic_error(trans); - goto cancel; - } + goto cancel; } if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { -- cgit v1.2.3 From 1a61b3477817e1a1473644b87c9c377dc08f74c4 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 9 Nov 2013 02:11:46 +0200 Subject: iwlwifi: mvm: fix and improve printing of rate scale table Info about VHT/HT rates wasn't printed properly when dumping the rate scale table. Fix that and print more info. While at it fix some other minor issues in the printing and prevent overflowing the print buffer. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 91 ++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index a0b4cc8d9c3b..f7ac485f85e1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2566,13 +2566,75 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, return count; } +static int rs_pretty_print_rate(char *buf, const u32 rate) +{ + static const char * const ant_name[] = { + [ANT_NONE] = "None", + [ANT_A] = "A", + [ANT_B] = "B", + [ANT_AB] = "AB", + [ANT_C] = "C", + [ANT_AC] = "AC", + [ANT_BC] = "BC", + [ANT_ABC] = "ABC", + }; + + char *type, *bw; + u8 mcs = 0, nss = 0; + u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; + + if (!(rate & RATE_MCS_HT_MSK) && + !(rate & RATE_MCS_VHT_MSK)) { + int index = iwl_hwrate_to_plcp_idx(rate); + + return sprintf(buf, "Legacy | ANT: %s Rate: %s Mbps\n", + ant_name[ant], iwl_rate_mcs[index].mbps); + } + + if (rate & RATE_MCS_VHT_MSK) { + type = "VHT"; + mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; + nss = ((rate & RATE_VHT_MCS_NSS_MSK) + >> RATE_VHT_MCS_NSS_POS) + 1; + } else if (rate & RATE_MCS_HT_MSK) { + type = "HT"; + mcs = rate & RATE_HT_MCS_INDEX_MSK; + } else { + type = "Unknown"; /* shouldn't happen */ + } + + switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { + case RATE_MCS_CHAN_WIDTH_20: + bw = "20Mhz"; + break; + case RATE_MCS_CHAN_WIDTH_40: + bw = "40Mhz"; + break; + case RATE_MCS_CHAN_WIDTH_80: + bw = "80Mhz"; + break; + case RATE_MCS_CHAN_WIDTH_160: + bw = "160Mhz"; + break; + default: + bw = "BAD BW"; + } + + return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n", + type, ant_name[ant], bw, mcs, nss, + (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", + (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", + (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", + (rate & RATE_MCS_BF_MSK) ? "BF " : "", + (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); +} + static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { char *buff; int desc = 0; int i = 0; - int index = 0; ssize_t ret; struct iwl_lq_sta *lq_sta = file->private_data; @@ -2580,7 +2642,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); mvm = lq_sta->drv; - buff = kmalloc(1024, GFP_KERNEL); + buff = kmalloc(2048, GFP_KERNEL); if (!buff) return -ENOMEM; @@ -2597,7 +2659,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, desc += sprintf(buff+desc, "lq type %s\n", (is_legacy(tbl->lq_type)) ? "legacy" : is_vht(tbl->lq_type) ? "VHT" : "HT"); - if (is_ht(tbl->lq_type)) { + if (!is_legacy(tbl->lq_type)) { desc += sprintf(buff+desc, " %s", (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); desc += sprintf(buff+desc, " %s", @@ -2605,13 +2667,13 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, (is_ht40(tbl)) ? "40MHz" : (is_ht80(tbl)) ? "80Mhz" : "BAD BW"); desc += sprintf(buff+desc, " %s %s\n", - (tbl->is_SGI) ? "SGI" : "", + (tbl->is_SGI) ? "SGI" : "NGI", (lq_sta->is_agg) ? "AGG on" : ""); } desc += sprintf(buff+desc, "last tx rate=0x%X\n", lq_sta->last_rate_n_flags); desc += sprintf(buff+desc, - "general: flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", + "general: flags=0x%X mimo-d=%d s-ant=0x%x d-ant=0x%x\n", lq_sta->lq.flags, lq_sta->lq.mimo_delim, lq_sta->lq.single_stream_ant_msk, @@ -2631,19 +2693,12 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->lq.initial_rate_index[3]); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { - index = iwl_hwrate_to_plcp_idx( - le32_to_cpu(lq_sta->lq.rs_table[i])); - if (is_legacy(tbl->lq_type)) { - desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n", - i, le32_to_cpu(lq_sta->lq.rs_table[i]), - iwl_rate_mcs[index].mbps); - } else { - desc += sprintf(buff+desc, - " rate[%d] 0x%X %smbps (%s)\n", - i, le32_to_cpu(lq_sta->lq.rs_table[i]), - iwl_rate_mcs[index].mbps, - iwl_rate_mcs[index].mcs); - } + u32 rate = le32_to_cpu(lq_sta->lq.rs_table[i]); + desc += sprintf(buff+desc, + " rate[%d] 0x%X ", + i, rate); + + desc += rs_pretty_print_rate(buff+desc, rate); } ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); -- cgit v1.2.3 From 9e680946a48be7f7c074a60d8583b21815526d61 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 9 Nov 2013 00:16:16 +0200 Subject: iwlwifi: mvm: simplify iwl_mvm_send_lq_cmd Remove the flags parameter which should be set to sync or async according to whether this is called during sta init or not. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 +-- drivers/net/wireless/iwlwifi/mvm/rs.c | 12 ++++++------ drivers/net/wireless/iwlwifi/mvm/sta.c | 2 +- drivers/net/wireless/iwlwifi/mvm/utils.c | 8 ++------ 4 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index fed21ef4162d..7992baabb882 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -750,8 +750,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) #endif /* CONFIG_IWLWIFI_DEBUGFS */ /* rate scaling */ -int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, - u8 flags, bool init); +int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); /* power managment */ static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index f7ac485f85e1..0a640891b460 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -298,7 +298,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm, if (lq_sta->dbg_fixed_rate) { rs_fill_link_cmd(NULL, NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); + iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false); } } #endif @@ -855,7 +855,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter++; if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { lq_sta->missed_rate_counter = 0; - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } /* Regardless, ignore this status info for outdated rate */ return; @@ -1667,7 +1667,7 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm, /* Update uCode's rate table. */ rate = rate_n_flags_from_tbl(mvm, tbl, index); rs_fill_link_cmd(mvm, sta, lq_sta, rate); - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } static u8 rs_get_tid(struct iwl_lq_sta *lq_data, @@ -2064,7 +2064,7 @@ lq_update: "Switch current mcs: %X index: %d\n", tbl->current_rate, index); rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } else { done_search = 1; } @@ -2168,7 +2168,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, NULL, lq_sta, rate); /* TODO restore station should remember the lq cmd */ - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_SYNC, true); + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, true); } static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, @@ -2841,5 +2841,5 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, lq->flags &= ~LQ_FLAG_SET_STA_TLC_RTS_MSK; } - return iwl_mvm_send_lq_cmd(mvm, lq, CMD_ASYNC, false); + return iwl_mvm_send_lq_cmd(mvm, lq, false); } diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 329952363a54..c89232c8aa79 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -945,7 +945,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, */ } - return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false); + return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, false); } int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index ed69e9b78e82..56cf819bc0c7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -486,22 +486,18 @@ void iwl_mvm_dump_sram(struct iwl_mvm *mvm) * this case to clear the state indicating that station creation is in * progress. */ -int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, - u8 flags, bool init) +int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init) { struct iwl_host_cmd cmd = { .id = LQ_CMD, .len = { sizeof(struct iwl_lq_cmd), }, - .flags = flags, + .flags = init ? CMD_SYNC : CMD_ASYNC, .data = { lq, }, }; if (WARN_ON(lq->sta_id == IWL_MVM_STATION_COUNT)) return -EINVAL; - if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) - return -EINVAL; - return iwl_mvm_send_cmd(mvm, &cmd); } -- cgit v1.2.3 From 750a1b456fb655614bdf20c9e3b7c0b523822ab2 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 9 Nov 2013 22:48:56 +0200 Subject: iwlwifi: mvm: refactor iwl_mvm_rs_rate_init Refactor setting of VHT enabled rates in preparation of adding some more logic there. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 49 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 0a640891b460..e49bf445fa7f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2242,6 +2242,33 @@ static int rs_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap, return -1; } +static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, + struct ieee80211_sta_vht_cap *vht_cap, + struct iwl_lq_sta *lq_sta) +{ + int i; + int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1); + + if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { + for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { + if (i == IWL_RATE_9M_INDEX) + continue; + + lq_sta->active_siso_rate |= BIT(i); + } + } + + highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2); + if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { + for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { + if (i == IWL_RATE_9M_INDEX) + continue; + + lq_sta->active_mimo2_rate |= BIT(i); + } + } +} + /* * Called after adding a new station to initialize rate scaling */ @@ -2308,27 +2335,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->is_vht = false; } else { - int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1); - if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { - for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { - if (i == IWL_RATE_9M_INDEX) - continue; - - lq_sta->active_siso_rate |= BIT(i); - } - } - - highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2); - if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { - for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { - if (i == IWL_RATE_9M_INDEX) - continue; - - lq_sta->active_mimo2_rate |= BIT(i); - } - } - - /* TODO: avoid MCS9 in 20Mhz which isn't valid for 11ac */ + rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); lq_sta->is_vht = true; } -- cgit v1.2.3 From 4ed80a86da93241c18d0e6c676134c7b9440d4b9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 7 Nov 2013 13:23:21 +0200 Subject: iwlwifi: mvm: enable d3_test even if d3_test_pme_ptr is not available Even if d3_test_pme_ptr is not available, d3_test can still be useful, e.g. by manually triggering resume (with ctrl-c), and reading the wakeup reasons. Signed-off-by: Eliad Peller Reviewed-by: Luciano Coelho Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/d3.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index b9b81e881dd0..12354f844255 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1216,10 +1216,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, if (len >= sizeof(u32) * 2) { mvm->d3_test_pme_ptr = le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); - } else if (test) { - /* in test mode we require the pointer */ - ret = -EIO; - goto out; } #endif iwl_free_resp(&d3_cfg_cmd); @@ -1871,10 +1867,14 @@ static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, u32 pme_asserted; while (true) { - pme_asserted = iwl_trans_read_mem32(mvm->trans, - mvm->d3_test_pme_ptr); - if (pme_asserted) - break; + /* read pme_ptr if available */ + if (mvm->d3_test_pme_ptr) { + pme_asserted = iwl_trans_read_mem32(mvm->trans, + mvm->d3_test_pme_ptr); + if (pme_asserted) + break; + } + if (msleep_interruptible(100)) break; } -- cgit v1.2.3 From 431591ccb3d744851bca76b10de24cfababf639d Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 7 Nov 2013 14:12:09 +0200 Subject: iwlwifi: mvm: disconnect on disconnection wakeup event When waking up from d3 due to disconnection event (e.g. because of beacon loss), we should disconnect immediately. Signed-off-by: Eliad Peller Reviewed-by: Luciano Coelho Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/d3.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 12354f844255..96b09d9d7068 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1533,10 +1533,16 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, struct iwl_mvm_d3_gtk_iter_data gtkdata = { .status = status, }; + u32 disconnection_reasons = + IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | + IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH; if (!status || !vif->bss_conf.bssid) return false; + if (le32_to_cpu(status->wakeup_reasons) & disconnection_reasons) + return false; + /* find last GTK that we used initially, if any */ gtkdata.find_phase = true; ieee80211_iter_keys(mvm->hw, vif, -- cgit v1.2.3 From b87c2179a7d4f0d7d476df289c69cf9ebf8b7163 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 9 Nov 2013 23:37:55 +0200 Subject: iwlwifi: mvm: implement rate_update hook in rs Re-initialize rs when we get a rate_update hook called which happens when remote STA changes bandwidth or sends a VHT opmode notification. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 ++- drivers/net/wireless/iwlwifi/mvm/rs.c | 30 +++++++++++++++++++++++++---- drivers/net/wireless/iwlwifi/mvm/rs.h | 2 +- 3 files changed, 29 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b56c989ad784..eea2f162e90e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1149,7 +1149,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ret = iwl_mvm_update_sta(mvm, vif, sta); if (ret == 0) iwl_mvm_rs_rate_init(mvm, sta, - mvmvif->phy_ctxt->channel->band); + mvmvif->phy_ctxt->channel->band, + true); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { /* enable beacon filtering */ diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index e49bf445fa7f..a85938cb3ab8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2126,7 +2126,8 @@ out: static void rs_initialize_lq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, - enum ieee80211_band band) + enum ieee80211_band band, + bool init) { struct iwl_scale_tbl_info *tbl; int rate_idx; @@ -2168,7 +2169,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, NULL, lq_sta, rate); /* TODO restore station should remember the lq cmd */ - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, true); + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); } static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, @@ -2273,7 +2274,7 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, * Called after adding a new station to initialize rate scaling */ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - enum ieee80211_band band) + enum ieee80211_band band, bool init) { int i, j; struct ieee80211_hw *hw = mvm->hw; @@ -2286,6 +2287,8 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, sta_priv = (struct iwl_mvm_sta *)sta->drv_priv; lq_sta = &sta_priv->lq_sta; + memset(lq_sta, 0, sizeof(*lq_sta)); + sband = hw->wiphy->bands[band]; lq_sta->lq.sta_id = sta_priv->sta_id; @@ -2371,7 +2374,25 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->dbg_fixed_rate = 0; #endif - rs_initialize_lq(mvm, sta, lq_sta, band); + rs_initialize_lq(mvm, sta, lq_sta, band, init); +} + +static void rs_rate_update(void *mvm_r, + struct ieee80211_supported_band *sband, + struct cfg80211_chan_def *chandef, + struct ieee80211_sta *sta, void *priv_sta, + u32 changed) +{ + u8 tid; + struct iwl_op_mode *op_mode = + (struct iwl_op_mode *)mvm_r; + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + /* Stop any ongoing aggregations as rs starts off assuming no agg */ + for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) + ieee80211_stop_tx_ba_session(sta, tid); + + iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); } static void rs_fill_link_cmd(struct iwl_mvm *mvm, @@ -2808,6 +2829,7 @@ static struct rate_control_ops rs_mvm_ops = { .free = rs_free, .alloc_sta = rs_alloc_sta, .free_sta = rs_free_sta, + .rate_update = rs_rate_update, #ifdef CONFIG_MAC80211_DEBUGFS .add_sta_debugfs = rs_add_debugfs, .remove_sta_debugfs = rs_remove_debugfs, diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 5d5344f7070b..8d5dc78086ea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -353,7 +353,7 @@ static inline u8 num_of_ant(u8 mask) /* Initialize station's rate scaling information after adding station */ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - enum ieee80211_band band); + enum ieee80211_band band, bool init); /** * iwl_rate_control_register - Register the rate control algorithm callbacks -- cgit v1.2.3 From 78c9df66c8f1af8577df802f57ce4dbb877fee4b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 7 Nov 2013 14:13:30 +0200 Subject: iwlwifi: mvm: allow keeping connections in d3_test Keeping connection can be useful also when testing d3 using the debugfs file (d3_test). Save the vif to keep connection on, and consider it when iterating over the interfaces. Signed-off-by: Eliad Peller Reviewed-by: Luciano Coelho Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/d3.c | 11 ++++++++++- drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 96b09d9d7068..b9e1f30e33de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1807,6 +1807,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) iwl_mvm_read_d3_sram(mvm); keep = iwl_mvm_query_wakeup_reasons(mvm, vif); +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (keep) + mvm->keep_vif = vif; +#endif /* has unlocked the mutex, so skip that */ goto out; @@ -1863,6 +1867,7 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) return err; } mvm->d3_test_active = true; + mvm->keep_vif = NULL; return 0; } @@ -1891,6 +1896,10 @@ static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { + /* skip the one we keep connection on */ + if (_data == vif) + return; + if (vif->type == NL80211_IFTYPE_STATION) ieee80211_connection_loss(vif); } @@ -1917,7 +1926,7 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_d3_test_disconn_work_iter, NULL); + iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif); ieee80211_wake_queues(mvm->hw); diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 7992baabb882..c002b45e03c9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -531,6 +531,7 @@ struct iwl_mvm { bool store_d3_resume_sram; void *d3_resume_sram; u32 d3_test_pme_ptr; + struct ieee80211_vif *keep_vif; #endif #endif -- cgit v1.2.3 From 8a5e3660c645200ca5d965903c73b97fb86c9518 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Tue, 12 Nov 2013 19:16:03 +0200 Subject: iwlwifi: mvm: fix ht protection flags The HT protection flags have been a mess for a long time, this patch fixes all this. The proper source of information for this is the protection in the HT operation mode IE which is propagated to bss_conf by mac80211. 1) No need to set the HT protection flags when the link doesn't support HT. 2) We need to set the TGG protection when ERP is active. Signed-off-by: Avri Altman Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 51 ++++++++++++++++++++++++----- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 11 +++++++ 2 files changed, 53 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index f41f9b079831..fb93961da750 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -488,6 +488,40 @@ static void iwl_mvm_ack_rates(struct iwl_mvm *mvm, *ofdm_rates = ofdm; } +static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct iwl_mac_ctx_cmd *cmd) +{ + /* for both sta and ap, ht_operation_mode hold the protection_mode */ + u8 protection_mode = vif->bss_conf.ht_operation_mode & + IEEE80211_HT_OP_MODE_PROTECTION; + /* The fw does not distinguish between ht and fat */ + u32 ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT; + + IWL_DEBUG_RATE(mvm, "protection mode set to %d\n", protection_mode); + /* + * See section 9.23.3.1 of IEEE 80211-2012. + * Nongreenfield HT STAs Present is not supported. + */ + switch (protection_mode) { + case IEEE80211_HT_OP_MODE_PROTECTION_NONE: + break; + case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: + case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: + cmd->protection_flags |= cpu_to_le32(ht_flag); + break; + case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: + /* Protect when channel wider than 20MHz */ + if (vif->bss_conf.chandef.width > NL80211_CHAN_WIDTH_20) + cmd->protection_flags |= cpu_to_le32(ht_flag); + break; + default: + IWL_ERR(mvm, "Illegal protection mode %d\n", + protection_mode); + break; + } +} + static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mac_ctx_cmd *cmd, @@ -495,6 +529,8 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_chanctx_conf *chanctx; + bool ht_enabled = !!(vif->bss_conf.ht_operation_mode & + IEEE80211_HT_OP_MODE_PROTECTION); u8 cck_ack_rates, ofdm_ack_rates; int i; @@ -573,16 +609,13 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN); } - - /* - * I think that we should enable these 2 flags regardless the HT PROT - * fields in the HT IE, but I am not sure. Someone knows whom to ask?... - */ - if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { + IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n", + vif->bss_conf.use_cts_prot, + vif->bss_conf.ht_operation_mode); + if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN); - cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_HT_PROT | - MAC_PROT_FLG_FAT_PROT); - } + if (ht_enabled) + iwl_mvm_mac_ctxt_set_ht_flags(mvm, vif, cmd); cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP); } diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index eea2f162e90e..f8bf15c2b2dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -990,6 +990,17 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, struct ieee80211_bss_conf *bss_conf, u32 changes) { + enum ieee80211_bss_change ht_change = BSS_CHANGED_ERP_CTS_PROT | + BSS_CHANGED_HT | + BSS_CHANGED_BANDWIDTH; + int ret; + + if (changes & ht_change) { + ret = iwl_mvm_mac_ctxt_changed(mvm, vif); + if (ret) + IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); + } + /* Need to send a new beacon template to the FW */ if (changes & BSS_CHANGED_BEACON) { if (iwl_mvm_mac_ctxt_beacon_changed(mvm, vif)) -- cgit v1.2.3 From 8a0bd168fa750d7c57d3494b331e9fb2b0bbd928 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 12 Nov 2013 16:48:03 +0100 Subject: iwlwifi: mvm: small debugfs cleanups Just clean up the code a bit, in particular * make all the debugfs writes follow the same pattern with respect to buf/buf_size variables * get rid of useless comments * check return values of all file creations * drop unnecessary parentheses * remove an unused struct definition * fix some whitespace Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 77 +++++++++++------------------- 1 file changed, 27 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 342bd1a07ab7..a34fb80422c0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -65,26 +65,19 @@ #include "iwl-io.h" #include "iwl-prph.h" -struct iwl_dbgfs_mvm_ctx { - struct iwl_mvm *mvm; - struct ieee80211_vif *vif; -}; - static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; - - char buf[16]; - int buf_size, ret; + char buf[16] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); + int ret; u32 scd_q_msk; if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR) return -EIO; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; @@ -106,15 +99,13 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file, { struct iwl_mvm *mvm = file->private_data; struct ieee80211_sta *sta; - - char buf[8]; - int buf_size, sta_id, drain, ret; + char buf[8] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); + int sta_id, drain, ret; if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR) return -EIO; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; @@ -200,12 +191,10 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; - char buf[64]; - int buf_size; + char buf[64] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); u32 offset, len; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; @@ -274,14 +263,14 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file, { struct iwl_mvm *mvm = file->private_data; char buf[64] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); int ret; int val; if (!mvm->ucode_loaded) return -EIO; - count = min_t(size_t, count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, count)) + if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; if (!strncmp("disable_power_off_d0=", buf, 21)) { @@ -319,11 +308,10 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, int dtimper_msec = dtimper * vif->bss_conf.beacon_int; IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val); - if (val * MSEC_PER_SEC < 3 * dtimper_msec) { + if (val * MSEC_PER_SEC < 3 * dtimper_msec) IWL_WARN(mvm, "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n", val * MSEC_PER_SEC, 3 * dtimper_msec); - } dbgfs_pm->keep_alive_seconds = val; break; } @@ -372,11 +360,11 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, struct iwl_mvm *mvm = mvmvif->dbgfs_data; enum iwl_dbgfs_pm_mask param; char buf[32] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); int val; int ret; - count = min_t(size_t, count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, count)) + if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; if (!strncmp("keep_alive=", buf, 11)) { @@ -471,7 +459,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n", vif->bss_conf.bssid); pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n"); - for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) { + for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) pos += scnprintf(buf+pos, bufsz-pos, "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n", i, mvmvif->queue_params[i].txop, @@ -479,7 +467,6 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, mvmvif->queue_params[i].cw_max, mvmvif->queue_params[i].aifs, mvmvif->queue_params[i].uapsd); - } if (vif->type == NL80211_IFTYPE_STATION && ap_sta_id != IWL_MVM_STATION_COUNT) { @@ -496,12 +483,11 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, rcu_read_lock(); chanctx_conf = rcu_dereference(vif->chanctx_conf); - if (chanctx_conf) { + if (chanctx_conf) pos += scnprintf(buf+pos, bufsz-pos, "idle rx chains %d, active rx chains: %d\n", chanctx_conf->rx_chains_static, chanctx_conf->rx_chains_dynamic); - } rcu_read_unlock(); mutex_unlock(&mvm->mutex); @@ -845,14 +831,10 @@ iwl_dbgfs_scan_ant_rxchain_write(struct file *file, size_t count, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; - char buf[8]; - int buf_size; + char buf[8] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); u8 scan_rx_ant; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - - /* get the argument from the user and check if it is valid */ if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; if (sscanf(buf, "%hhx", &scan_rx_ant) != 1) @@ -862,7 +844,6 @@ iwl_dbgfs_scan_ant_rxchain_write(struct file *file, if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw)) return -EINVAL; - /* change the rx antennas for scan command */ mvm->scan_rx_ant = scan_rx_ant; return count; @@ -922,13 +903,10 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->dbgfs_data; enum iwl_dbgfs_bf_mask param; - char buf[256]; - int buf_size; - int value; - int ret = 0; + char buf[256] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); + int value, ret = 0; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; @@ -1012,11 +990,10 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file, mutex_lock(&mvm->mutex); iwl_dbgfs_update_bf(vif, param, value); - if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) { + if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) ret = iwl_mvm_disable_beacon_filter(mvm, vif); - } else { + else ret = iwl_mvm_enable_beacon_filter(mvm, vif); - } mutex_unlock(&mvm->mutex); return ret ?: count; @@ -1078,10 +1055,10 @@ static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, { struct iwl_mvm *mvm = file->private_data; char buf[8] = {}; + size_t buf_size = min(count, sizeof(buf) - 1); int store; - count = min_t(size_t, count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, count)) + if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; if (sscanf(buf, "%d", &store) != 1) @@ -1137,14 +1114,14 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, #endif #define MVM_DEBUGFS_READ_FILE_OPS(name) \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ .read = iwl_dbgfs_##name##_read, \ .open = simple_open, \ .llseek = generic_file_llseek, \ } #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ .write = iwl_dbgfs_##name##_write, \ .read = iwl_dbgfs_##name##_read, \ .open = simple_open, \ @@ -1152,7 +1129,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ }; #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ .write = iwl_dbgfs_##name##_write, \ .open = simple_open, \ .llseek = generic_file_llseek, \ -- cgit v1.2.3 From 820a1a50025550061b0d0ea15a760ecd183886f7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 12 Nov 2013 16:58:41 +0100 Subject: iwlwifi: mvm: move interface-specific debugfs to a new file The debugfs file is getting pretty large and mixed up between code for the hardware and code for each interface (the two aren't even clearly separated in the code). Make it easier to handle by splitting the per-interface code into a separate file called debugfs-vif.c. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/Makefile | 1 + drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 190 ++++++++++ drivers/net/wireless/iwlwifi/mvm/debugfs.c | 505 +------------------------ drivers/net/wireless/iwlwifi/mvm/debugfs.h | 84 ++++ 4 files changed, 276 insertions(+), 504 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c create mode 100644 drivers/net/wireless/iwlwifi/mvm/debugfs.h (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 6d73817850ce..285d8c7486f5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile @@ -5,6 +5,7 @@ iwlmvm-y += scan.o time-event.o rs.o iwlmvm-y += power.o power_legacy.o bt-coex.o iwlmvm-y += led.o tt.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o +iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_PM_SLEEP) += d3.o ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c new file mode 100644 index 000000000000..a90dde0f8d6c --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -0,0 +1,190 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "mvm.h" +#include "debugfs.h" + +static ssize_t iwl_dbgfs_mac_params_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->dbgfs_data; + u8 ap_sta_id; + struct ieee80211_chanctx_conf *chanctx_conf; + char buf[512]; + int bufsz = sizeof(buf); + int pos = 0; + int i; + + mutex_lock(&mvm->mutex); + + ap_sta_id = mvmvif->ap_sta_id; + + pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n", + mvmvif->id, mvmvif->color); + pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n", + vif->bss_conf.bssid); + pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n"); + for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) + pos += scnprintf(buf+pos, bufsz-pos, + "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n", + i, mvmvif->queue_params[i].txop, + mvmvif->queue_params[i].cw_min, + mvmvif->queue_params[i].cw_max, + mvmvif->queue_params[i].aifs, + mvmvif->queue_params[i].uapsd); + + if (vif->type == NL80211_IFTYPE_STATION && + ap_sta_id != IWL_MVM_STATION_COUNT) { + struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvm_sta; + + sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], + lockdep_is_held(&mvm->mutex)); + mvm_sta = (void *)sta->drv_priv; + pos += scnprintf(buf+pos, bufsz-pos, + "ap_sta_id %d - reduced Tx power %d\n", + ap_sta_id, mvm_sta->bt_reduced_txpower); + } + + rcu_read_lock(); + chanctx_conf = rcu_dereference(vif->chanctx_conf); + if (chanctx_conf) + pos += scnprintf(buf+pos, bufsz-pos, + "idle rx chains %d, active rx chains: %d\n", + chanctx_conf->rx_chains_static, + chanctx_conf->rx_chains_dynamic); + rcu_read_unlock(); + + mutex_unlock(&mvm->mutex); + + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + +#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \ + if (!debugfs_create_file(#name, mode, parent, vif, \ + &iwl_dbgfs_##name##_ops)) \ + goto err; \ + } while (0) + +MVM_DEBUGFS_READ_FILE_OPS(mac_params); + +void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +{ + struct dentry *dbgfs_dir = vif->debugfs_dir; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + char buf[100]; + + /* + * Check if debugfs directory already exist before creating it. + * This may happen when, for example, resetting hw or suspend-resume + */ + if (!dbgfs_dir || mvmvif->dbgfs_dir) + return; + + mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); + mvmvif->dbgfs_data = mvm; + + if (!mvmvif->dbgfs_dir) { + IWL_ERR(mvm, "Failed to create debugfs directory under %s\n", + dbgfs_dir->d_name.name); + return; + } + + MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, + S_IRUSR); + + /* + * Create symlink for convenience pointing to interface specific + * debugfs entries for the driver. For example, under + * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/ + * find + * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/ + */ + snprintf(buf, 100, "../../../%s/%s/%s/%s", + dbgfs_dir->d_parent->d_parent->d_name.name, + dbgfs_dir->d_parent->d_name.name, + dbgfs_dir->d_name.name, + mvmvif->dbgfs_dir->d_name.name); + + mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name, + mvm->debugfs_dir, buf); + if (!mvmvif->dbgfs_slink) + IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n", + dbgfs_dir->d_name.name); + return; +err: + IWL_ERR(mvm, "Can't create debugfs entity\n"); +} + +void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + debugfs_remove(mvmvif->dbgfs_slink); + mvmvif->dbgfs_slink = NULL; + + debugfs_remove_recursive(mvmvif->dbgfs_dir); + mvmvif->dbgfs_dir = NULL; +} diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index a34fb80422c0..6850a2d94bcb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -64,6 +64,7 @@ #include "sta.h" #include "iwl-io.h" #include "iwl-prph.h" +#include "debugfs.h" static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, const char __user *user_buf, @@ -292,209 +293,6 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file, return ret ?: count; } -static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - enum iwl_dbgfs_pm_mask param, int val) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm; - - dbgfs_pm->mask |= param; - - switch (param) { - case MVM_DEBUGFS_PM_KEEP_ALIVE: { - struct ieee80211_hw *hw = mvm->hw; - int dtimper = hw->conf.ps_dtim_period ?: 1; - int dtimper_msec = dtimper * vif->bss_conf.beacon_int; - - IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val); - if (val * MSEC_PER_SEC < 3 * dtimper_msec) - IWL_WARN(mvm, - "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n", - val * MSEC_PER_SEC, 3 * dtimper_msec); - dbgfs_pm->keep_alive_seconds = val; - break; - } - case MVM_DEBUGFS_PM_SKIP_OVER_DTIM: - IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n", - val ? "enabled" : "disabled"); - dbgfs_pm->skip_over_dtim = val; - break; - case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS: - IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val); - dbgfs_pm->skip_dtim_periods = val; - break; - case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT: - IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val); - dbgfs_pm->rx_data_timeout = val; - break; - case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT: - IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val); - dbgfs_pm->tx_data_timeout = val; - break; - case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: - IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); - dbgfs_pm->disable_power_off = val; - break; - case MVM_DEBUGFS_PM_LPRX_ENA: - IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); - dbgfs_pm->lprx_ena = val; - break; - case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD: - IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val); - dbgfs_pm->lprx_rssi_threshold = val; - break; - case MVM_DEBUGFS_PM_SNOOZE_ENABLE: - IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val); - dbgfs_pm->snooze_ena = val; - break; - } -} - -static ssize_t iwl_dbgfs_pm_params_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->dbgfs_data; - enum iwl_dbgfs_pm_mask param; - char buf[32] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); - int val; - int ret; - - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - - if (!strncmp("keep_alive=", buf, 11)) { - if (sscanf(buf + 11, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_KEEP_ALIVE; - } else if (!strncmp("skip_over_dtim=", buf, 15)) { - if (sscanf(buf + 15, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM; - } else if (!strncmp("skip_dtim_periods=", buf, 18)) { - if (sscanf(buf + 18, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS; - } else if (!strncmp("rx_data_timeout=", buf, 16)) { - if (sscanf(buf + 16, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT; - } else if (!strncmp("tx_data_timeout=", buf, 16)) { - if (sscanf(buf + 16, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; - } else if (!strncmp("disable_power_off=", buf, 18) && - !(mvm->fw->ucode_capa.flags & - IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) { - if (sscanf(buf + 18, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; - } else if (!strncmp("lprx=", buf, 5)) { - if (sscanf(buf + 5, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_LPRX_ENA; - } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) { - if (sscanf(buf + 20, "%d", &val) != 1) - return -EINVAL; - if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val < - POWER_LPRX_RSSI_THRESHOLD_MIN) - return -EINVAL; - param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD; - } else if (!strncmp("snooze_enable=", buf, 14)) { - if (sscanf(buf + 14, "%d", &val) != 1) - return -EINVAL; - param = MVM_DEBUGFS_PM_SNOOZE_ENABLE; - } else { - return -EINVAL; - } - - mutex_lock(&mvm->mutex); - iwl_dbgfs_update_pm(mvm, vif, param, val); - ret = iwl_mvm_power_update_mode(mvm, vif); - mutex_unlock(&mvm->mutex); - - return ret ?: count; -} - -static ssize_t iwl_dbgfs_pm_params_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->dbgfs_data; - char buf[512]; - int bufsz = sizeof(buf); - int pos; - - pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_mac_params_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->dbgfs_data; - u8 ap_sta_id; - struct ieee80211_chanctx_conf *chanctx_conf; - char buf[512]; - int bufsz = sizeof(buf); - int pos = 0; - int i; - - mutex_lock(&mvm->mutex); - - ap_sta_id = mvmvif->ap_sta_id; - - pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n", - mvmvif->id, mvmvif->color); - pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n", - vif->bss_conf.bssid); - pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n"); - for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) - pos += scnprintf(buf+pos, bufsz-pos, - "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n", - i, mvmvif->queue_params[i].txop, - mvmvif->queue_params[i].cw_min, - mvmvif->queue_params[i].cw_max, - mvmvif->queue_params[i].aifs, - mvmvif->queue_params[i].uapsd); - - if (vif->type == NL80211_IFTYPE_STATION && - ap_sta_id != IWL_MVM_STATION_COUNT) { - struct ieee80211_sta *sta; - struct iwl_mvm_sta *mvm_sta; - - sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], - lockdep_is_held(&mvm->mutex)); - mvm_sta = (void *)sta->drv_priv; - pos += scnprintf(buf+pos, bufsz-pos, - "ap_sta_id %d - reduced Tx power %d\n", - ap_sta_id, mvm_sta->bt_reduced_txpower); - } - - rcu_read_lock(); - chanctx_conf = rcu_dereference(vif->chanctx_conf); - if (chanctx_conf) - pos += scnprintf(buf+pos, bufsz-pos, - "idle rx chains %d, active rx chains: %d\n", - chanctx_conf->rx_chains_static, - chanctx_conf->rx_chains_dynamic); - rcu_read_unlock(); - - mutex_unlock(&mvm->mutex); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - #define BT_MBOX_MSG(_notif, _num, _field) \ ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ >> BT_MBOX##_num##_##_field##_POS) @@ -849,205 +647,6 @@ iwl_dbgfs_scan_ant_rxchain_write(struct file *file, return count; } - -static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, - enum iwl_dbgfs_bf_mask param, int value) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; - - dbgfs_bf->mask |= param; - - switch (param) { - case MVM_DEBUGFS_BF_ENERGY_DELTA: - dbgfs_bf->bf_energy_delta = value; - break; - case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA: - dbgfs_bf->bf_roaming_energy_delta = value; - break; - case MVM_DEBUGFS_BF_ROAMING_STATE: - dbgfs_bf->bf_roaming_state = value; - break; - case MVM_DEBUGFS_BF_TEMP_THRESHOLD: - dbgfs_bf->bf_temp_threshold = value; - break; - case MVM_DEBUGFS_BF_TEMP_FAST_FILTER: - dbgfs_bf->bf_temp_fast_filter = value; - break; - case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER: - dbgfs_bf->bf_temp_slow_filter = value; - break; - case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: - dbgfs_bf->bf_enable_beacon_filter = value; - break; - case MVM_DEBUGFS_BF_DEBUG_FLAG: - dbgfs_bf->bf_debug_flag = value; - break; - case MVM_DEBUGFS_BF_ESCAPE_TIMER: - dbgfs_bf->bf_escape_timer = value; - break; - case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT: - dbgfs_bf->ba_enable_beacon_abort = value; - break; - case MVM_DEBUGFS_BA_ESCAPE_TIMER: - dbgfs_bf->ba_escape_timer = value; - break; - } -} - -static ssize_t iwl_dbgfs_bf_params_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->dbgfs_data; - enum iwl_dbgfs_bf_mask param; - char buf[256] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); - int value, ret = 0; - - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - - if (!strncmp("bf_energy_delta=", buf, 16)) { - if (sscanf(buf+16, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_ENERGY_DELTA_MIN || - value > IWL_BF_ENERGY_DELTA_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_ENERGY_DELTA; - } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) { - if (sscanf(buf+24, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN || - value > IWL_BF_ROAMING_ENERGY_DELTA_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA; - } else if (!strncmp("bf_roaming_state=", buf, 17)) { - if (sscanf(buf+17, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_ROAMING_STATE_MIN || - value > IWL_BF_ROAMING_STATE_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_ROAMING_STATE; - } else if (!strncmp("bf_temp_threshold=", buf, 18)) { - if (sscanf(buf+18, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_TEMP_THRESHOLD_MIN || - value > IWL_BF_TEMP_THRESHOLD_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_TEMP_THRESHOLD; - } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) { - if (sscanf(buf+20, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_TEMP_FAST_FILTER_MIN || - value > IWL_BF_TEMP_FAST_FILTER_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER; - } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) { - if (sscanf(buf+20, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_TEMP_SLOW_FILTER_MIN || - value > IWL_BF_TEMP_SLOW_FILTER_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER; - } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { - if (sscanf(buf+24, "%d", &value) != 1) - return -EINVAL; - if (value < 0 || value > 1) - return -EINVAL; - param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER; - } else if (!strncmp("bf_debug_flag=", buf, 14)) { - if (sscanf(buf+14, "%d", &value) != 1) - return -EINVAL; - if (value < 0 || value > 1) - return -EINVAL; - param = MVM_DEBUGFS_BF_DEBUG_FLAG; - } else if (!strncmp("bf_escape_timer=", buf, 16)) { - if (sscanf(buf+16, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BF_ESCAPE_TIMER_MIN || - value > IWL_BF_ESCAPE_TIMER_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BF_ESCAPE_TIMER; - } else if (!strncmp("ba_escape_timer=", buf, 16)) { - if (sscanf(buf+16, "%d", &value) != 1) - return -EINVAL; - if (value < IWL_BA_ESCAPE_TIMER_MIN || - value > IWL_BA_ESCAPE_TIMER_MAX) - return -EINVAL; - param = MVM_DEBUGFS_BA_ESCAPE_TIMER; - } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) { - if (sscanf(buf+23, "%d", &value) != 1) - return -EINVAL; - if (value < 0 || value > 1) - return -EINVAL; - param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT; - } else { - return -EINVAL; - } - - mutex_lock(&mvm->mutex); - iwl_dbgfs_update_bf(vif, param, value); - if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) - ret = iwl_mvm_disable_beacon_filter(mvm, vif); - else - ret = iwl_mvm_enable_beacon_filter(mvm, vif); - mutex_unlock(&mvm->mutex); - - return ret ?: count; -} - -static ssize_t iwl_dbgfs_bf_params_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct iwl_beacon_filter_cmd cmd = { - IWL_BF_CMD_CONFIG_DEFAULTS, - .bf_enable_beacon_filter = - cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT), - .ba_enable_beacon_abort = - cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT), - }; - - iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); - if (mvmvif->bf_data.bf_enabled) - cmd.bf_enable_beacon_filter = cpu_to_le32(1); - else - cmd.bf_enable_beacon_filter = 0; - - pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", - le32_to_cpu(cmd.bf_energy_delta)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", - le32_to_cpu(cmd.bf_roaming_energy_delta)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", - le32_to_cpu(cmd.bf_roaming_state)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n", - le32_to_cpu(cmd.bf_temp_threshold)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n", - le32_to_cpu(cmd.bf_temp_fast_filter)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n", - le32_to_cpu(cmd.bf_temp_slow_filter)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", - le32_to_cpu(cmd.bf_enable_beacon_filter)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", - le32_to_cpu(cmd.bf_debug_flag)); - pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", - le32_to_cpu(cmd.bf_escape_timer)); - pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", - le32_to_cpu(cmd.ba_escape_timer)); - pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", - le32_to_cpu(cmd.ba_enable_beacon_abort)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - #ifdef CONFIG_PM_SLEEP static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, const char __user *user_buf, @@ -1113,40 +712,12 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, } #endif -#define MVM_DEBUGFS_READ_FILE_OPS(name) \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .read = iwl_dbgfs_##name##_read, \ - .open = simple_open, \ - .llseek = generic_file_llseek, \ -} - -#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .read = iwl_dbgfs_##name##_read, \ - .open = simple_open, \ - .llseek = generic_file_llseek, \ -}; - -#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .open = simple_open, \ - .llseek = generic_file_llseek, \ -}; - #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \ if (!debugfs_create_file(#name, mode, parent, mvm, \ &iwl_dbgfs_##name##_ops)) \ goto err; \ } while (0) -#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, vif, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ - } while (0) - /* Device wide debugfs entries */ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush); MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); @@ -1164,11 +735,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain); MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); #endif -/* Interface specific debugfs entries */ -MVM_DEBUGFS_READ_FILE_OPS(mac_params); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params); - int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) { char buf[100]; @@ -1212,72 +778,3 @@ err: IWL_ERR(mvm, "Can't create the mvm debugfs directory\n"); return -ENOMEM; } - -void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) -{ - struct dentry *dbgfs_dir = vif->debugfs_dir; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[100]; - - /* - * Check if debugfs directory already exist before creating it. - * This may happen when, for example, resetting hw or suspend-resume - */ - if (!dbgfs_dir || mvmvif->dbgfs_dir) - return; - - mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); - mvmvif->dbgfs_data = mvm; - - if (!mvmvif->dbgfs_dir) { - IWL_ERR(mvm, "Failed to create debugfs directory under %s\n", - dbgfs_dir->d_name.name); - return; - } - - if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && - vif->type == NL80211_IFTYPE_STATION && !vif->p2p) - MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | - S_IRUSR); - - MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, - S_IRUSR); - - if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && - mvmvif == mvm->bf_allowed_vif) - MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, - S_IRUSR | S_IWUSR); - - /* - * Create symlink for convenience pointing to interface specific - * debugfs entries for the driver. For example, under - * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/ - * find - * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/ - */ - snprintf(buf, 100, "../../../%s/%s/%s/%s", - dbgfs_dir->d_parent->d_parent->d_name.name, - dbgfs_dir->d_parent->d_name.name, - dbgfs_dir->d_name.name, - mvmvif->dbgfs_dir->d_name.name); - - mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name, - mvm->debugfs_dir, buf); - if (!mvmvif->dbgfs_slink) - IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n", - dbgfs_dir->d_name.name); - return; -err: - IWL_ERR(mvm, "Can't create debugfs entity\n"); -} - -void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - - debugfs_remove(mvmvif->dbgfs_slink); - mvmvif->dbgfs_slink = NULL; - - debugfs_remove_recursive(mvmvif->dbgfs_dir); - mvmvif->dbgfs_dir = NULL; -} diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.h b/drivers/net/wireless/iwlwifi/mvm/debugfs.h new file mode 100644 index 000000000000..faa73b80b624 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#define MVM_DEBUGFS_READ_FILE_OPS(name) \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .read = iwl_dbgfs_##name##_read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +} + +#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .write = iwl_dbgfs_##name##_write, \ + .read = iwl_dbgfs_##name##_read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; + +#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .write = iwl_dbgfs_##name##_write, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; -- cgit v1.2.3 From 7f09d70436729dee9dfa7ab11fda9d384c4bdf9f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 12 Nov 2013 17:16:38 +0100 Subject: iwlwifi: mvm: don't use void pointers in debugfs There's really no reason to use void *dbgfs_data rather than a struct iwl_mvm *mvm, so do that. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 4 ++-- drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index a90dde0f8d6c..67f6a2071653 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -69,7 +69,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, { struct ieee80211_vif *vif = file->private_data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->dbgfs_data; + struct iwl_mvm *mvm = mvmvif->mvm; u8 ap_sta_id; struct ieee80211_chanctx_conf *chanctx_conf; char buf[512]; @@ -144,7 +144,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return; mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); - mvmvif->dbgfs_data = mvm; + mvmvif->mvm = mvm; if (!mvmvif->dbgfs_dir) { IWL_ERR(mvm, "Failed to create debugfs directory under %s\n", diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index c002b45e03c9..e7c97ccec5e8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -323,9 +323,9 @@ struct iwl_mvm_vif { #endif #ifdef CONFIG_IWLWIFI_DEBUGFS + struct iwl_mvm *mvm; struct dentry *dbgfs_dir; struct dentry *dbgfs_slink; - void *dbgfs_data; struct iwl_dbgfs_pm dbgfs_pm; struct iwl_dbgfs_bf dbgfs_bf; #endif -- cgit v1.2.3 From 1fa3f57a1ca19ad45ff5fa248d509fc442e82a63 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Nov 2013 09:10:21 +0100 Subject: iwlwifi: mvm: refactor debugfs copy_from_user() Abstract the copy_from_user() pattern into the macros defining debugfs files, reducing the code and making adding new files safer by avoiding having deal with copy_from_user() directly. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 87 ++++++++---------------------- drivers/net/wireless/iwlwifi/mvm/debugfs.h | 25 +++++++-- 2 files changed, 43 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 6850a2d94bcb..931723a03a43 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -66,22 +66,15 @@ #include "iwl-prph.h" #include "debugfs.h" -static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, - const char __user *user_buf, +static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; - char buf[16] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); int ret; u32 scd_q_msk; if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR) return -EIO; - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x", &scd_q_msk) != 1) return -EINVAL; @@ -94,22 +87,15 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, return ret; } -static ssize_t iwl_dbgfs_sta_drain_write(struct file *file, - const char __user *user_buf, +static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; struct ieee80211_sta *sta; - char buf[8] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); int sta_id, drain, ret; if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR) return -EIO; - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d %d", &sta_id, &drain) != 2) return -EINVAL; if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT) @@ -187,18 +173,11 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, return ret; } -static ssize_t iwl_dbgfs_sram_write(struct file *file, - const char __user *user_buf, size_t count, - loff_t *ppos) +static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf, + size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; - char buf[64] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); u32 offset, len; - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x,%x", &offset, &len) == 2) { if ((offset & 0x3) || (len & 0x3)) return -EINVAL; @@ -258,22 +237,14 @@ static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file, - const char __user *user_buf, +static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; - char buf[64] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); - int ret; - int val; + int ret, val; if (!mvm->ucode_loaded) return -EIO; - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (!strncmp("disable_power_off_d0=", buf, 21)) { if (sscanf(buf + 21, "%d", &val) != 1) return -EINVAL; @@ -568,11 +539,9 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, } #undef PRINT_STAT_LE32 -static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, - const char __user *user_buf, +static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; int ret; mutex_lock(&mvm->mutex); @@ -589,12 +558,9 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, return count; } -static ssize_t iwl_dbgfs_fw_nmi_write(struct file *file, - const char __user *user_buf, +static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; - iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1); return count; @@ -624,17 +590,11 @@ iwl_dbgfs_scan_ant_rxchain_read(struct file *file, } static ssize_t -iwl_dbgfs_scan_ant_rxchain_write(struct file *file, - const char __user *user_buf, +iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; - char buf[8] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); u8 scan_rx_ant; - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; if (sscanf(buf, "%hhx", &scan_rx_ant) != 1) return -EINVAL; if (scan_rx_ant > ANT_ABC) @@ -648,18 +608,11 @@ iwl_dbgfs_scan_ant_rxchain_write(struct file *file, } #ifdef CONFIG_PM_SLEEP -static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, - const char __user *user_buf, +static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm *mvm = file->private_data; - char buf[8] = {}; - size_t buf_size = min(count, sizeof(buf) - 1); int store; - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &store) != 1) return -EINVAL; @@ -712,6 +665,10 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, } #endif +#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ + _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) +#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ + _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \ if (!debugfs_create_file(#name, mode, parent, mvm, \ &iwl_dbgfs_##name##_ops)) \ @@ -719,20 +676,20 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, } while (0) /* Device wide debugfs entries */ -MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush); -MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); +MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); +MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); MVM_DEBUGFS_READ_FILE_OPS(stations); MVM_DEBUGFS_READ_FILE_OPS(bt_notif); MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); -MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); -MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain); +MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); +MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); #ifdef CONFIG_PM_SLEEP -MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); #endif int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.h b/drivers/net/wireless/iwlwifi/mvm/debugfs.h index faa73b80b624..85f9f958bfd2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.h +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.h @@ -68,17 +68,34 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .llseek = generic_file_llseek, \ } -#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \ +#define MVM_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype) \ +static ssize_t _iwl_dbgfs_##name##_write(struct file *file, \ + const char __user *user_buf, \ + size_t count, loff_t *ppos) \ +{ \ + argtype *arg = file->private_data; \ + char buf[buflen] = {}; \ + size_t buf_size = min(count, sizeof(buf) - 1); \ + \ + if (copy_from_user(buf, user_buf, buf_size)) \ + return -EFAULT; \ + \ + return iwl_dbgfs_##name##_write(arg, buf, buf_size, ppos); \ +} \ + +#define _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, buflen, argtype) \ +MVM_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype) \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ + .write = _iwl_dbgfs_##name##_write, \ .read = iwl_dbgfs_##name##_read, \ .open = simple_open, \ .llseek = generic_file_llseek, \ }; -#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ +#define _MVM_DEBUGFS_WRITE_FILE_OPS(name, buflen, argtype) \ +MVM_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype) \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ + .write = _iwl_dbgfs_##name##_write, \ .open = simple_open, \ .llseek = generic_file_llseek, \ }; -- cgit v1.2.3 From d307ec8d112abdc9f2792540b9e364c510461c44 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Mon, 11 Nov 2013 19:56:21 +0200 Subject: iwlwifi: mvm: add LQ flags definitions Add more bit field definitions used in LQ flags. Also rename the first bit to a shorter name. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | 27 +++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/mvm/rs.c | 4 ++-- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index 538f1c7a5966..532312c7b937 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h @@ -281,8 +281,31 @@ enum { /* # entries in rate scale table to support Tx retries */ #define LQ_MAX_RETRY_NUM 16 -/* Link quality command flags, only this one is available */ -#define LQ_FLAG_SET_STA_TLC_RTS_MSK BIT(0) +/* Link quality command flags bit fields */ + +/* Bit 0: (0) Don't use RTS (1) Use RTS */ +#define LQ_FLAG_USE_RTS_POS 0 +#define LQ_FLAG_USE_RTS_MSK (1 << LQ_FLAG_USE_RTS_POS) + +/* Bit 1-3: LQ command color. Used to match responses to LQ commands */ +#define LQ_FLAG_COLOR_POS 1 +#define LQ_FLAG_COLOR_MSK (7 << LQ_FLAG_COLOR_POS) + +/* Bit 4-5: Tx RTS BW Signalling + * (0) No RTS BW signalling + * (1) Static BW signalling + * (2) Dynamic BW signalling + */ +#define LQ_FLAG_RTS_BW_SIG_POS 4 +#define LQ_FLAG_RTS_BW_SIG_NONE (0 << LQ_FLAG_RTS_BW_SIG_POS) +#define LQ_FLAG_RTS_BW_SIG_STATIC (1 << LQ_FLAG_RTS_BW_SIG_POS) +#define LQ_FLAG_RTS_BW_SIG_DYNAMIC (2 << LQ_FLAG_RTS_BW_SIG_POS) + +/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection + * Dyanmic BW selection allows Tx with narrower BW then requested in rates + */ +#define LQ_FLAG_DYNAMIC_BW_POS 6 +#define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS) /** * struct iwl_lq_cmd - link quality command diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index a85938cb3ab8..482b91b80c31 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2862,12 +2862,12 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, if (enable) { if (mvmsta->tx_protection == 0) - lq->flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK; + lq->flags |= LQ_FLAG_USE_RTS_MSK; mvmsta->tx_protection++; } else { mvmsta->tx_protection--; if (mvmsta->tx_protection == 0) - lq->flags &= ~LQ_FLAG_SET_STA_TLC_RTS_MSK; + lq->flags &= ~LQ_FLAG_USE_RTS_MSK; } return iwl_mvm_send_lq_cmd(mvm, lq, false); -- cgit v1.2.3 From c21193516209705c59aa8d9f01021944cf42a0e9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 13 Nov 2013 22:00:30 +0200 Subject: iwlwifi: mvm: BT Coex - fine tune the aggregation size Latest tests have shown that when BT is active and has connections but the traffic is low, the WiFi aggregation can be large up to 4000us without noticeable impact on BT. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 75b72a956552..75c3e0b6e077 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -921,7 +921,7 @@ u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, enum iwl_bt_coex_lut_type lut_type; if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < - BT_LOW_TRAFFIC) + BT_HIGH_TRAFFIC) return LINK_QUAL_AGG_TIME_LIMIT_DEF; lut_type = iwl_get_coex_type(mvm, mvmsta->vif); -- cgit v1.2.3 From 8c21c5386d6e9404b347acf5b13db61ca7b5e037 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 23 Oct 2013 15:44:25 +0300 Subject: iwlwifi: mvm: a few more SKUs for 7260 and 3160 These devices are not sold as discrete modules but are rather soldered down to the board. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 86605027c41d..2e97a3995333 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -297,6 +297,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x5072, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x5170, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x5770, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, @@ -350,6 +353,8 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x1070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x1170, iwl3160_2ac_cfg)}, /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, -- cgit v1.2.3 From 84c317c9b09f757b4c4a4fb38549ac54d1559419 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 10 Nov 2013 20:06:37 +0100 Subject: iwlwifi: pcie: remove minor dead code inta is checked to be zero in a IRQ_NONE branch so afterwards it cannot be zero as it is never modified. Signed-off-by: Michal Nazarewicz [reword the patch title and fix comment] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/rx.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index be3995afa9d0..1d6bf7b98e2d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -1126,7 +1126,6 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) struct iwl_trans *trans = data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 inta, inta_mask; - irqreturn_t ret = IRQ_NONE; lockdep_assert_held(&trans_pcie->irq_lock); @@ -1155,7 +1154,16 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) * or due to sporadic interrupts thrown from our NIC. */ if (!inta) { IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); - goto none; + /* + * Re-enable interrupts here since we don't have anything to + * service, but only in case the handler won't run. Note that + * the handler can be scheduled because of a previous + * interrupt. + */ + if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && + !trans_pcie->inta) + iwl_enable_interrupts(trans); + return IRQ_NONE; } if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { @@ -1173,19 +1181,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) trans_pcie->inta |= inta; /* the thread will service interrupts and re-enable them */ - if (likely(inta)) - return IRQ_WAKE_THREAD; - - ret = IRQ_HANDLED; - -none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); - - return ret; + return IRQ_WAKE_THREAD; } /* interrupt handler using ict table, with this interrupt driver will -- cgit v1.2.3 From a7b8b2ca916ca4ecf248fa12275eeceff510ad22 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 7 Nov 2013 19:38:04 +0200 Subject: iwlwifi: fix check for a single rx antenna valid_rx_ant is a bitmask of available antennas and not the number of Rx antennas. Use num_of_ant and remove duplicate definitions in both dvm and mvm. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/dvm/rs.h | 7 ------- drivers/net/wireless/iwlwifi/iwl-config.h | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 3 ++- drivers/net/wireless/iwlwifi/mvm/rs.h | 8 -------- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h index 26fc550cd68c..41988f4b8a5a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/iwlwifi/dvm/rs.h @@ -389,13 +389,6 @@ struct iwl_lq_sta { u8 last_bt_traffic; }; -static inline u8 num_of_ant(u8 mask) -{ - return !!((mask) & ANT_A) + - !!((mask) & ANT_B) + - !!((mask) & ANT_C); -} - static inline u8 first_antenna(u8 mask) { if (mask & ANT_A) diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 03fd9aa8bfda..0b916249669e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -129,6 +129,12 @@ enum iwl_led_mode { #define ANT_BC (ANT_B | ANT_C) #define ANT_ABC (ANT_A | ANT_B | ANT_C) +static inline u8 num_of_ant(u8 mask) +{ + return !!((mask) & ANT_A) + + !!((mask) & ANT_B) + + !!((mask) & ANT_C); +} /* * @max_ll_items: max number of OTP blocks diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 2fab203d3027..94aef22df73a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -283,7 +283,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); - if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) { + if (num_of_ant(data->valid_rx_ant) == 1 || + cfg->rx_with_siso_diversity) { vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; /* this works because NOT_SUPPORTED == 3 */ diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 8d5dc78086ea..b41686b76721 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -343,14 +343,6 @@ enum iwl_bt_coex_profile_traffic_load { */ }; - -static inline u8 num_of_ant(u8 mask) -{ - return !!((mask) & ANT_A) + - !!((mask) & ANT_B) + - !!((mask) & ANT_C); -} - /* Initialize station's rate scaling information after adding station */ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum ieee80211_band band, bool init); -- cgit v1.2.3 From 5b577a90fb3d86447ee86f8e0c6ddbd5da2ef8c9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Nov 2013 18:20:04 +0100 Subject: iwlwifi: mvm: add iwl_mvm_sta_from_mac80211 This is just a helper function to go from the mac80211 station struct to our internal one, to later allow us to avoid temporary 'mvmsta' variables. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 8 ++++---- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/iwlwifi/mvm/sta.c | 12 ++++++------ drivers/net/wireless/iwlwifi/mvm/sta.h | 6 ++++++ drivers/net/wireless/iwlwifi/mvm/tt.c | 2 +- drivers/net/wireless/iwlwifi/mvm/tx.c | 10 +++++----- 6 files changed, 23 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 75c3e0b6e077..468a4ba49a06 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -514,7 +514,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, if (IS_ERR_OR_NULL(sta)) return 0; - mvmsta = (void *)sta->drv_priv; + mvmsta = iwl_mvm_sta_from_mac80211(sta); /* nothing to do */ if (mvmsta->bt_reduced_txpower == enable) @@ -846,7 +846,7 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, if (IS_ERR_OR_NULL(sta)) return; - mvmsta = (void *)sta->drv_priv; + mvmsta = iwl_mvm_sta_from_mac80211(sta); data->num_bss_ifaces++; @@ -917,7 +917,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, struct ieee80211_sta *sta) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); enum iwl_bt_coex_lut_type lut_type; if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < @@ -936,7 +936,7 @@ u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, struct ieee80211_sta *sta) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f8bf15c2b2dd..6b3273d82157 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1091,7 +1091,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); switch (cmd) { case STA_NOTIFY_SLEEP: diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index c89232c8aa79..7a5b7473eafa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -840,7 +840,7 @@ static const u8 tid_to_ac[] = { int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data; int txq_id; @@ -895,7 +895,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u8 buf_size) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; int queue, fifo, ret; u16 ssn; @@ -951,7 +951,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; u16 txq_id; int err; @@ -1023,7 +1023,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; u16 txq_id; enum iwl_mvm_agg_state old_state; @@ -1416,7 +1416,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, struct ieee80211_sta *sta) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_add_sta_cmd_v6 cmd = { .add_modify = STA_MODE_MODIFY, .sta_id = mvmsta->sta_id, @@ -1438,7 +1438,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, u16 sleep_state_flags = (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_add_sta_cmd_v6 cmd = { .add_modify = STA_MODE_MODIFY, .sta_id = mvmsta->sta_id, diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 4dfc359a4bdd..b34941148a98 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h @@ -298,6 +298,12 @@ struct iwl_mvm_sta { bool tt_tx_protection; }; +static inline struct iwl_mvm_sta * +iwl_mvm_sta_from_mac80211(struct ieee80211_sta *sta) +{ + return (void *)sta->drv_priv; +} + /** * struct iwl_mvm_int_sta - representation of an internal station (auxiliary or * broadcast) diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 1f3282dff513..18be04da8e3f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -388,7 +388,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable) lockdep_is_held(&mvm->mutex)); if (IS_ERR_OR_NULL(sta)) continue; - mvmsta = (void *)sta->drv_priv; + mvmsta = iwl_mvm_sta_from_mac80211(sta); if (enable == mvmsta->tt_tx_protection) continue; err = iwl_mvm_tx_protection(mvm, mvmsta, enable); diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 1f1945806421..d87649ac88e1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -362,7 +362,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, u8 txq_id = info->hw_queue; bool is_data_qos = false, is_ampdu = false; - mvmsta = (void *)sta->drv_priv; + mvmsta = iwl_mvm_sta_from_mac80211(sta); fc = hdr->frame_control; if (WARN_ON_ONCE(!mvmsta)) @@ -433,7 +433,7 @@ drop: static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u8 tid) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; struct ieee80211_vif *vif = mvmsta->vif; @@ -663,7 +663,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); if (!IS_ERR_OR_NULL(sta)) { - mvmsta = (void *)sta->drv_priv; + mvmsta = iwl_mvm_sta_from_mac80211(sta); if (tid != IWL_TID_NON_QOS) { struct iwl_mvm_tid_data *tid_data = @@ -794,7 +794,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); if (!WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) { - struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); mvmsta->tid_data[tid].rate_n_flags = le32_to_cpu(tx_resp->initial_rate); } @@ -850,7 +850,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, return 0; } - mvmsta = (void *)sta->drv_priv; + mvmsta = iwl_mvm_sta_from_mac80211(sta); tid_data = &mvmsta->tid_data[tid]; if (WARN_ONCE(tid_data->txq_id != scd_flow, "Q %d, tid %d, flow %d", -- cgit v1.2.3 From b70ab7278f5e872dec600a6f16c6a8dba4601794 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 19 Nov 2013 22:53:41 +0200 Subject: iwlwifi: mvm: don't restart HW if suspending fails before D3 image is loaded If we haven't loaded the D3 image yet and a failure in the suspend process occurs, we shouldn't restart the HW, because we're still running the D0 image. Signed-off-by: Luciano Coelho Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/d3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index b9e1f30e33de..665f87e788d6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1227,10 +1227,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, mvm->aux_sta.sta_id = old_aux_sta_id; mvm_ap_sta->sta_id = old_ap_sta_id; mvmvif->ap_sta_id = old_ap_sta_id; - out_noreset: - kfree(key_data.rsc_tsc); + if (ret < 0) ieee80211_restart_hw(mvm->hw); + out_noreset: + kfree(key_data.rsc_tsc); mutex_unlock(&mvm->mutex); -- cgit v1.2.3 From 086f7368d4120ff0de376af9b7f9beaec8bf4b4d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 18 Nov 2013 17:00:03 +0200 Subject: iwlwifi: mvm: dump NVM from debugfs This allows to see the content of the NVM the driver reads. Note that the output is in binary, and requires some external user space tool to display the data properly. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 13 +++++++++++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 +++++ drivers/net/wireless/iwlwifi/mvm/nvm.c | 23 +++++++++++++++++++++++ 3 files changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 931723a03a43..e8f62a6a1b57 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -720,6 +720,19 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) goto err; #endif + if (!debugfs_create_blob("nvm_hw", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_hw_blob)) + goto err; + if (!debugfs_create_blob("nvm_sw", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_sw_blob)) + goto err; + if (!debugfs_create_blob("nvm_calib", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_calib_blob)) + goto err; + if (!debugfs_create_blob("nvm_prod", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_prod_blob)) + goto err; + /* * Create a symlink with mac80211. It will be removed when mac80211 * exists (before the opmode exists which removes the target.) diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index e7c97ccec5e8..7dc57cfe5803 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -494,6 +494,11 @@ struct iwl_mvm { u32 dbgfs_sram_offset, dbgfs_sram_len; bool disable_power_off; bool disable_power_off_d3; + + struct debugfs_blob_wrapper nvm_hw_blob; + struct debugfs_blob_wrapper nvm_sw_blob; + struct debugfs_blob_wrapper nvm_calib_blob; + struct debugfs_blob_wrapper nvm_prod_blob; #endif struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 2beffd028b67..48089b1625ff 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -443,6 +443,29 @@ int iwl_nvm_init(struct iwl_mvm *mvm) } mvm->nvm_sections[section].data = temp; mvm->nvm_sections[section].length = ret; + +#ifdef CONFIG_IWLWIFI_DEBUGFS + switch (section) { + case NVM_SECTION_TYPE_HW: + mvm->nvm_hw_blob.data = temp; + mvm->nvm_hw_blob.size = ret; + break; + case NVM_SECTION_TYPE_SW: + mvm->nvm_sw_blob.data = temp; + mvm->nvm_sw_blob.size = ret; + break; + case NVM_SECTION_TYPE_CALIBRATION: + mvm->nvm_calib_blob.data = temp; + mvm->nvm_calib_blob.size = ret; + break; + case NVM_SECTION_TYPE_PRODUCTION: + mvm->nvm_prod_blob.data = temp; + mvm->nvm_prod_blob.size = ret; + break; + default: + WARN(1, "section: %d", section); + } +#endif } kfree(nvm_buffer); if (ret < 0) -- cgit v1.2.3 From de33fb5e80a62a3dfb50ab4d498db9b978c6c07f Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 10 Nov 2013 12:59:46 +0200 Subject: iwlwifi: mvm: fix scan offloading flag definition Bit 0 in the scan offloading flags asks the filter to pass all the results (instead of filtering them, by default), rather than the other way around (like it is defined and used today). Fix the flag name appropriately, and fix its user. Signed-off-by: Eliad Peller Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 5 ++--- drivers/net/wireless/iwlwifi/mvm/scan.c | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index c3782b48ded1..b3ed59237cba 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -530,14 +530,13 @@ struct iwl_scan_offload_schedule { /* * iwl_scan_offload_flags * - * IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID: filter mode - upload every beacon or match - * ssid list. + * IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering. * IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan. * IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan * on A band. */ enum iwl_scan_offload_flags { - IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID = BIT(0), + IWL_SCAN_OFFLOAD_FLAG_PASS_ALL = BIT(0), IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL = BIT(2), IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN = BIT(3), }; diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index e0cd100b40cd..67d7b8defa0d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -817,11 +817,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, IWL_DEBUG_SCAN(mvm, "Sending scheduled scan with filtering, filter len %d\n", req->n_match_sets); - scan_req.flags |= - cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID); } else { IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n"); + scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL); } return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC, -- cgit v1.2.3 From 61f6325d3e453fc3523d5891f9641d0af5e3ceaf Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Sun, 3 Nov 2013 23:02:59 +0200 Subject: iwlwifi: mvm: Implement low-priority scan Advertise driver's support for low priority scan. Notice that this overwrites current setting by mac80211 which depends only on hw scan support. This scan priority can be configured by user space application and it affects scan continuity, low priority scan will be more fragmented scan. Signed-off-by: Haim Dreyfuss Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 +- drivers/net/wireless/iwlwifi/mvm/scan.c | 52 +++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 6b3273d82157..afc4419be46d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -256,7 +256,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | - NL80211_FEATURE_P2P_GO_OPPPS; + NL80211_FEATURE_P2P_GO_OPPPS | + NL80211_FEATURE_LOW_PRIORITY_SCAN; mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 67d7b8defa0d..4ce9bb581144 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -70,6 +70,9 @@ #define IWL_PLCP_QUIET_THRESH 1 #define IWL_ACTIVE_QUIET_TIME 10 +#define LONG_OUT_TIME_PERIOD 600 +#define SHORT_OUT_TIME_PERIOD 200 +#define SUSPEND_TIME_PERIOD 100 static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) { @@ -87,20 +90,22 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) return cpu_to_le16(rx_chain); } -static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif) +static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif, + u32 flags, bool is_assoc) { - if (vif->bss_conf.assoc) - return cpu_to_le32(200 * 1024); - else + if (!is_assoc) return 0; + if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY) + return cpu_to_le32(ieee80211_tu_to_usec(SHORT_OUT_TIME_PERIOD)); + return cpu_to_le32(ieee80211_tu_to_usec(LONG_OUT_TIME_PERIOD)); } -static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif) +static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif, + bool is_assoc) { - if (!vif->bss_conf.assoc) + if (!is_assoc) return 0; - - return cpu_to_le32(ieee80211_tu_to_usec(vif->bss_conf.beacon_int)); + return cpu_to_le32(ieee80211_tu_to_usec(SUSPEND_TIME_PERIOD)); } static inline __le32 @@ -262,6 +267,15 @@ static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, return (u16)len; } +static void iwl_mvm_vif_assoc_iterator(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + bool *is_assoc = data; + + if (vif->bss_conf.assoc) + *is_assoc = true; +} + int iwl_mvm_scan_request(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_scan_request *req) @@ -274,6 +288,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, .dataflags = { IWL_HCMD_DFL_NOCOPY, }, }; struct iwl_scan_cmd *cmd = mvm->scan_cmd; + bool is_assoc = false; int ret; u32 status; int ssid_len = 0; @@ -289,13 +304,17 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, memset(cmd, 0, sizeof(struct iwl_scan_cmd) + mvm->fw->ucode_capa.max_probe_length + (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel))); - + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_vif_assoc_iterator, + &is_assoc); cmd->channel_count = (u8)req->n_channels; cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); - cmd->max_out_time = iwl_mvm_scan_max_out_time(vif); - cmd->suspend_time = iwl_mvm_scan_suspend_time(vif); + cmd->max_out_time = iwl_mvm_scan_max_out_time(vif, req->flags, + is_assoc); + cmd->suspend_time = iwl_mvm_scan_suspend_time(vif, is_assoc); cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | MAC_FILTER_IN_BEACON); @@ -522,6 +541,12 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm, struct cfg80211_sched_scan_request *req, struct iwl_scan_offload_cmd *scan) { + bool is_assoc = false; + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_vif_assoc_iterator, + &is_assoc); scan->channel_count = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; @@ -529,8 +554,9 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm, scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); - scan->max_out_time = cpu_to_le32(200 * 1024); - scan->suspend_time = iwl_mvm_scan_suspend_time(vif); + scan->max_out_time = iwl_mvm_scan_max_out_time(vif, req->flags, + is_assoc); + scan->suspend_time = iwl_mvm_scan_suspend_time(vif, is_assoc); scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | MAC_FILTER_IN_BEACON); scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); -- cgit v1.2.3 From 9470c3700bc4d6071af9091e8a9de17afa7e3115 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Nov 2013 20:36:25 +0100 Subject: iwlwifi: mvm: quota command max_duration should be zero For now, the firmware doesn't really use the field, but it should be set to zero if there's no specific request. Setting it to the max quota doesn't make sense. Signed-off-by: Johannes Berg Reviewed-by: Ilan Peer Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/quota.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 17e2bc827f9a..38165eba2a17 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c @@ -217,8 +217,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) } else { cmd.quotas[idx].quota = cpu_to_le32(quota * data.n_interfaces[i]); - cmd.quotas[idx].max_duration = - cpu_to_le32(IWL_MVM_MAX_QUOTA); + cmd.quotas[idx].max_duration = cpu_to_le32(0); } idx++; } -- cgit v1.2.3 From 393b9e5b821f4a27cd6decb55c866b6b9294c198 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Wed, 13 Nov 2013 16:46:19 +0200 Subject: iwlwifi: mvm: stop using MIMO in case BT doesn't allow it Switch to using the new btcoex decision api regarding MIMO and stop accessing the internal btcoex structs. In case MIMO should be disabled it would detect this upon the next Tx and force a search. The search will switch to SISO on a antenna A which isn't used by BT. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 26 ++++++-------------------- drivers/net/wireless/iwlwifi/mvm/rs.h | 13 ------------- 2 files changed, 6 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 482b91b80c31..95652601cd5a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1499,6 +1499,9 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, u8 update_search_tbl_counter = 0; int ret; + if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) + tbl->action = IWL_MIMO2_SWITCH_SISO_A; + start_action = tbl->action; while (1) { lq_sta->action_counter++; @@ -1970,26 +1973,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, (current_tpt > (100 * tbl->expected_tpt[low])))) scale_action = 0; - if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= - IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) { - if (lq_sta->last_bt_traffic > - le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) { - /* - * don't set scale_action, don't want to scale up if - * the rate scale doesn't otherwise think that is a - * good idea. - */ - } else if (lq_sta->last_bt_traffic <= - le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) { - scale_action = -1; - } - } - lq_sta->last_bt_traffic = - le32_to_cpu(mvm->last_bt_notif.bt_activity_grading); - - if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= - IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) { - /* search for a new modulation */ + /* Force a search in case BT doesn't like us being in MIMO */ + if (is_mimo(tbl->lq_type) && + !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) { rs_stay_in_table(lq_sta, true); goto lq_update; } diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index b41686b76721..5dd30eace42b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -328,19 +328,6 @@ struct iwl_lq_sta { u32 last_rate_n_flags; /* packets destined for this STA are aggregated */ u8 is_agg; - /* BT traffic this sta was last updated in */ - u8 last_bt_traffic; -}; - -enum iwl_bt_coex_profile_traffic_load { - IWL_BT_COEX_TRAFFIC_LOAD_NONE = 0, - IWL_BT_COEX_TRAFFIC_LOAD_LOW = 1, - IWL_BT_COEX_TRAFFIC_LOAD_HIGH = 2, - IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS = 3, -/* - * There are no more even though below is a u8, the - * indication from the BT device only has two bits. - */ }; /* Initialize station's rate scaling information after adding station */ -- cgit v1.2.3 From 271518adff21b48c88caeb7d8847cb94af197994 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 9 Nov 2013 23:25:06 +0200 Subject: iwlwifi: mvm: don't enable VHT MCS9 in 20Mhz MCS9 in NSS=1 or NSS=2 isn't valid for 20Mhz so don't enable it in case we're dealing with a 20Mhz sta. Trying to configure an MCS9 rate with 20Mhz in the LQ rate table would lead to a FW assert. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 95652601cd5a..f1364b7f58e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2241,6 +2241,11 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, if (i == IWL_RATE_9M_INDEX) continue; + /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ + if (i == IWL_RATE_MCS_9_INDEX && + sta->bandwidth == IEEE80211_STA_RX_BW_20) + continue; + lq_sta->active_siso_rate |= BIT(i); } } @@ -2251,6 +2256,11 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, if (i == IWL_RATE_9M_INDEX) continue; + /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ + if (i == IWL_RATE_MCS_9_INDEX && + sta->bandwidth == IEEE80211_STA_RX_BW_20) + continue; + lq_sta->active_mimo2_rate |= BIT(i); } } -- cgit v1.2.3 From ecc90e79e5add903de9f1bb599bdb2384cc762fb Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 9 Nov 2013 23:31:38 +0200 Subject: iwlwifi: mvm: don't configure mimo rates if nss is limited to 1 Remote peer can publish a different number of supported nss via the operating mode notification IE or action frame. If it limits to 1 then we don't want mimo rates configured in the rate table. Signed-off-by: Eyal Shapira Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index f1364b7f58e4..a7efeb31c258 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2250,6 +2250,9 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, } } + if (sta->rx_nss < 2) + return; + highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2); if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { -- cgit v1.2.3 From 4d30ee8247872b7eb7f38342d603963045ed8cba Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Wed, 20 Nov 2013 01:45:38 +0200 Subject: iwlwifi: mvm: rs: improve debug prints Enable better tracking of different decisions made by the rate scale algorithm. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 116 ++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index a7efeb31c258..065520968d29 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -174,7 +174,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); - +static const char *rs_pretty_lq_type(enum iwl_table_type type); #ifdef CONFIG_MAC80211_DEBUGFS static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, @@ -778,9 +778,6 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, struct iwl_scale_tbl_info tbl_type; struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; - IWL_DEBUG_RATE_LIMIT(mvm, - "get frame ack response, update rate scale window\n"); - /* Treat uninitialized rate scaling data same as non-existing. */ if (!lq_sta) { IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n"); @@ -1499,8 +1496,10 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, u8 update_search_tbl_counter = 0; int ret; - if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) + if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) { + IWL_DEBUG_RATE(mvm, "BT COEX force switch to SISO A\n"); tbl->action = IWL_MIMO2_SWITCH_SISO_A; + } start_action = tbl->action; while (1) { @@ -1721,8 +1720,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; struct iwl_mvm_tid_data *tid_data; - IWL_DEBUG_RATE(mvm, "rate scale calculate new rate for skb\n"); - /* Send management frames and NO_ACK data using lowest rate. */ /* TODO: this could probably be improved.. */ if (!ieee80211_is_data(hdr->frame_control) || @@ -1758,14 +1755,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, /* current tx rate */ index = lq_sta->last_txrate_idx; - IWL_DEBUG_RATE(mvm, "Rate scale index %d for type %d\n", index, - tbl->lq_type); - /* rates available for this association, and for modulation mode */ rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); - IWL_DEBUG_RATE(mvm, "mask 0x%04X\n", rate_mask); - /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { if (lq_sta->band == IEEE80211_BAND_5GHZ) @@ -1809,6 +1801,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, index = lq_sta->max_rate_idx; update_lq = 1; window = &(tbl->win[index]); + IWL_DEBUG_RATE(mvm, + "Forcing user max rate %d\n", + index); goto lq_update; } @@ -1825,8 +1820,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if ((fail_count < IWL_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) { IWL_DEBUG_RATE(mvm, - "LQ: still below TH. succ=%d total=%d for index %d\n", - window->success_counter, window->counter, index); + "(%s: %d): Test Window: succ %d total %d\n", + rs_pretty_lq_type(tbl->lq_type), + index, window->success_counter, window->counter); /* Can't calculate this yet; not enough history */ window->average_tpt = IWL_INVALID_VALUE; @@ -1854,7 +1850,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, * continuing to use the setup that we've been trying. */ if (window->average_tpt > lq_sta->last_tpt) { IWL_DEBUG_RATE(mvm, - "LQ: SWITCHING TO NEW TABLE suc=%d cur-tpt=%d old-tpt=%d\n", + "SWITCHING TO NEW TABLE SR: %d " + "cur-tpt %d old-tpt %d\n", window->success_ratio, window->average_tpt, lq_sta->last_tpt); @@ -1868,7 +1865,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, /* Else poor success; go back to mode in "active" table */ } else { IWL_DEBUG_RATE(mvm, - "LQ: GOING BACK TO THE OLD TABLE suc=%d cur-tpt=%d old-tpt=%d\n", + "GOING BACK TO THE OLD TABLE: SR %d " + "cur-tpt %d old-tpt %d\n", window->success_ratio, window->average_tpt, lq_sta->last_tpt); @@ -1916,20 +1914,31 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if (high != IWL_RATE_INVALID) high_tpt = tbl->win[high].average_tpt; + IWL_DEBUG_RATE(mvm, + "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", + rs_pretty_lq_type(tbl->lq_type), index, current_tpt, + sr, low, high, low_tpt, high_tpt); + scale_action = 0; /* Too many failures, decrease rate */ if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { IWL_DEBUG_RATE(mvm, - "decrease rate because of low success_ratio\n"); + "decrease rate because of low SR\n"); scale_action = -1; /* No throughput measured yet for adjacent rates; try increase. */ } else if ((low_tpt == IWL_INVALID_VALUE) && (high_tpt == IWL_INVALID_VALUE)) { - if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) + if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { + IWL_DEBUG_RATE(mvm, + "Good SR and no high rate measurement. " + "Increase rate\n"); scale_action = 1; - else if (low != IWL_RATE_INVALID) + } else if (low != IWL_RATE_INVALID) { + IWL_DEBUG_RATE(mvm, + "Remain in current rate\n"); scale_action = 0; + } } /* Both adjacent throughputs are measured, but neither one has better @@ -1937,8 +1946,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, else if ((low_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && - (high_tpt < current_tpt)) + (high_tpt < current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Both high and low are worse. " + "Maintain rate\n"); scale_action = 0; + } /* At least one adjacent rate's throughput is measured, * and may have better performance. */ @@ -1948,8 +1961,14 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, /* Higher rate has better throughput */ if (high_tpt > current_tpt && sr >= IWL_RATE_INCREASE_TH) { + IWL_DEBUG_RATE(mvm, + "Higher rate is better and good " + "SR. Increate rate\n"); scale_action = 1; } else { + IWL_DEBUG_RATE(mvm, + "Higher rate isn't better OR " + "no good SR. Maintain rate\n"); scale_action = 0; } @@ -1958,9 +1977,13 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, /* Lower rate has better throughput */ if (low_tpt > current_tpt) { IWL_DEBUG_RATE(mvm, - "decrease rate because of low tpt\n"); + "Lower rate is better. " + "Decrease rate\n"); scale_action = -1; } else if (sr >= IWL_RATE_INCREASE_TH) { + IWL_DEBUG_RATE(mvm, + "Lower rate isn't better and " + "good SR. Increase rate\n"); scale_action = 1; } } @@ -1970,12 +1993,17 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, * has been good at old rate. Don't change it. */ if ((scale_action == -1) && (low != IWL_RATE_INVALID) && ((sr > IWL_RATE_HIGH_TH) || - (current_tpt > (100 * tbl->expected_tpt[low])))) + (current_tpt > (100 * tbl->expected_tpt[low])))) { + IWL_DEBUG_RATE(mvm, + "Sanity check failed. Maintain rate\n"); scale_action = 0; + } /* Force a search in case BT doesn't like us being in MIMO */ if (is_mimo(tbl->lq_type) && !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) { + IWL_DEBUG_RATE(mvm, + "BT Coex forbids MIMO. Search for new config\n"); rs_stay_in_table(lq_sta, true); goto lq_update; } @@ -1986,6 +2014,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if (low != IWL_RATE_INVALID) { update_lq = 1; index = low; + } else { + IWL_DEBUG_RATE(mvm, + "At the bottom rate. Can't decrease\n"); } break; @@ -1994,6 +2025,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if (high != IWL_RATE_INVALID) { update_lq = 1; index = high; + } else { + IWL_DEBUG_RATE(mvm, + "At the top rate. Can't increase\n"); } break; @@ -2003,10 +2037,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, break; } - IWL_DEBUG_RATE(mvm, - "choose rate scale index %d action %d low %d high %d type %d\n", - index, scale_action, low, high, tbl->lq_type); - lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) @@ -2025,6 +2055,10 @@ lq_update: /* Save current throughput to compare with "search" throughput*/ lq_sta->last_tpt = current_tpt; + IWL_DEBUG_RATE(mvm, + "Start Search: update_lq %d done_search %d stay_in_tbl %d win->counter %d\n", + update_lq, done_search, lq_sta->stay_in_tbl, + window->counter); /* Select a new "search" modulation mode to try. * If one is found, set up the new "search" table. */ if (is_legacy(tbl->lq_type)) @@ -2047,8 +2081,11 @@ lq_update: index = iwl_hwrate_to_plcp_idx(tbl->current_rate); IWL_DEBUG_RATE(mvm, - "Switch current mcs: %X index: %d\n", - tbl->current_rate, index); + "Switch to SEARCH TABLE: " + "mcs %X (%s: %d)\n", + tbl->current_rate, + rs_pretty_lq_type(tbl->lq_type), + index); rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } else { @@ -2169,8 +2206,6 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = mvm_sta; - IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n"); - /* Get max rate if user set max rate */ if (lq_sta) { lq_sta->max_rate_idx = txrc->max_rate_idx; @@ -2554,7 +2589,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, >> RATE_MCS_ANT_POS); if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) { *rate_n_flags = lq_sta->dbg_fixed_rate; - IWL_DEBUG_RATE(mvm, "Fixed rate ON\n"); } else { lq_sta->dbg_fixed_rate = 0; IWL_ERR(mvm, @@ -2562,8 +2596,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, ant_sel_tx, valid_tx_ant); IWL_DEBUG_RATE(mvm, "Fixed rate OFF\n"); } - } else { - IWL_DEBUG_RATE(mvm, "Fixed rate OFF\n"); } } @@ -2593,6 +2625,24 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, return count; } +static const char *rs_pretty_lq_type(enum iwl_table_type type) +{ + static const char * const lq_type[] = { + [LQ_NONE] = "NONE", + [LQ_LEGACY_A] = "LEGACY_A", + [LQ_LEGACY_G] = "LEGACY_G", + [LQ_HT_SISO] = "HT SISO", + [LQ_HT_MIMO2] = "HT MIMO", + [LQ_VHT_SISO] = "VHT SISO", + [LQ_VHT_MIMO2] = "VHT MIMO", + }; + + if (type < LQ_NONE || type >= LQ_MAX) + return "UNKNOWN"; + + return lq_type[type]; +} + static int rs_pretty_print_rate(char *buf, const u32 rate) { static const char * const ant_name[] = { -- cgit v1.2.3 From d17334c4405951e326d6c393a357d3cb937a090e Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Wed, 20 Nov 2013 02:08:12 +0200 Subject: iwlwifi: mvm: rs: reduce min failures to end test window This terminates a test window of a new rate quicker in case we've hit a bad rate and should recover better. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 065520968d29..ecf24cb6ebf6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -47,7 +47,7 @@ #define IWL_HT_NUMBER_TRY 3 #define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ -#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ +#define IWL_RATE_MIN_FAILURE_TH 3 /* min failures to calc tpt */ #define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ /* max allowed rate miss before sync LQ cmd */ -- cgit v1.2.3 From 9d015a03345d54d8de0339b2137deb96524766e0 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 21 Nov 2013 01:12:11 +0200 Subject: iwlwifi: mvm: rs: update expected TPT tables if aggregation changed Expected TPT table was updated only when switching to a new modulation. This is wrong as toggling aggregation changes the expected TPT signficantly. This leads to scenarios where turning aggregation on after being in MIMO sends us back to SISO despite a perfect success ratio. This occurred because the TPT of the SISO mode was being estimated based on aggregation while the MIMO one wasn't. Also remove an error print which isn't an error anymore since we might be updating the expected TPT table due to aggregation changes. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index ecf24cb6ebf6..882ecd30cf56 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1717,6 +1717,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, u16 high_low; s32 sr; u8 tid = IWL_MAX_TID_COUNT; + u8 prev_agg = lq_sta->is_agg; struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; struct iwl_mvm_tid_data *tid_data; @@ -1752,6 +1753,13 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, tbl = &(lq_sta->lq_info[active_tbl]); + if (prev_agg != lq_sta->is_agg) { + IWL_DEBUG_RATE(mvm, + "Aggregation changed: prev %d current %d. Update expected TPT table\n", + prev_agg, lq_sta->is_agg); + rs_set_expected_tpt_table(lq_sta, tbl); + } + /* current tx rate */ index = lq_sta->last_txrate_idx; @@ -1837,8 +1845,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, * actual average throughput */ if (window->average_tpt != ((window->success_ratio * tbl->expected_tpt[index] + 64) / 128)) { - IWL_ERR(mvm, - "expected_tpt should have been calculated by now\n"); window->average_tpt = ((window->success_ratio * tbl->expected_tpt[index] + 64) / 128); } -- cgit v1.2.3 From c48075d27db571ff1deeb6a0fda7bf1f0abeee4c Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 21 Nov 2013 01:18:47 +0200 Subject: iwlwifi: mvm: rs: rename thresholds defines Rename for clearer names. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 4 ++-- drivers/net/wireless/iwlwifi/mvm/rs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 882ecd30cf56..a289b774ba6b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1107,7 +1107,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, * "active" throughput (under perfect conditions). */ if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) && - ((active_sr > IWL_RATE_DECREASE_TH) && + ((active_sr > RS_SR_FORCE_DECREASE) && (active_sr <= IWL_RATE_HIGH_TH) && (tpt_tbl[rate] <= active_tpt))) || ((active_sr >= IWL_RATE_SCALE_SWITCH) && @@ -1928,7 +1928,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, scale_action = 0; /* Too many failures, decrease rate */ - if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { + if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { IWL_DEBUG_RATE(mvm, "decrease rate because of low SR\n"); scale_action = -1; diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 5dd30eace42b..e5d448c0d1af 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -155,7 +155,7 @@ enum { #define IWL_RATE_SCALE_SWITCH 10880 /* 85% */ #define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */ -#define IWL_RATE_DECREASE_TH 1920 /* 15% */ +#define RS_SR_FORCE_DECREASE 1920 /* 15% */ /* possible actions when in legacy mode */ enum { -- cgit v1.2.3 From 32b01726b944ea21e9c9dacfb34753a8e63ba877 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Fri, 22 Nov 2013 09:41:38 +0200 Subject: iwlwifi: mvm: rs: increase stay in column timeout Remain in the same Tx modulation (i.e. column) for a longer time before starting a search cycle for a better modulation. This has been shown to give better results. Also change the name of the timeout define to better match its description. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index a289b774ba6b..9249e52dafc9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -52,8 +52,8 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 -/* max time to accum history 2 seconds */ -#define IWL_RATE_SCALE_FLUSH_INTVL (3*HZ) +#define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) + static u8 rs_ht_to_legacy[] = { [IWL_RATE_1M_INDEX] = IWL_RATE_6M_INDEX, @@ -1599,7 +1599,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) flush_interval_passed = time_after(jiffies, (unsigned long)(lq_sta->flush_timer + - IWL_RATE_SCALE_FLUSH_INTVL)); + RS_STAY_IN_COLUMN_TIMEOUT)); /* * Check if we should allow search for new modulation mode. -- cgit v1.2.3 From 0c308e97d40f0e8f43336b6076f4b26e71ba59c6 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Fri, 22 Nov 2013 14:27:20 +0200 Subject: iwlwifi: mvm: rs: remove unused timestamp field Remove this as it's unused. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 4 ---- drivers/net/wireless/iwlwifi/mvm/rs.h | 1 - 2 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 9249e52dafc9..0598f26b5da9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -271,7 +271,6 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) window->success_ratio = IWL_INVALID_VALUE; window->counter = 0; window->average_tpt = IWL_INVALID_VALUE; - window->stamp = 0; } static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) @@ -428,9 +427,6 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, else window->average_tpt = IWL_INVALID_VALUE; - /* Tag this window as having been updated */ - window->stamp = jiffies; - return 0; } diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index e5d448c0d1af..ae983bce2172 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -257,7 +257,6 @@ struct iwl_rate_scale_data { s32 success_ratio; /* per-cent * 128 */ s32 counter; /* number of frames attempted */ s32 average_tpt; /* success ratio * expected throughput */ - unsigned long stamp; }; /** -- cgit v1.2.3 From 5aa335537aa27e0d169e98d90d23342434a1cef0 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 23 Nov 2013 01:06:36 +0200 Subject: iwlwifi: mvm: rs: refactor to use rs_rate Introduce rs_rate which represents a rate. Use this structure instead of iwl_scale_tbl_info where we're dealing with a single rate. This avoids allocating the big iwl_scale_tbl_info structure on the stack in several cases like converting to ucode rate format or from ucode rate format. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 568 +++++++++++++++++----------------- drivers/net/wireless/iwlwifi/mvm/rs.h | 60 ++-- 2 files changed, 331 insertions(+), 297 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 0598f26b5da9..3af90620b3de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -175,6 +175,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); static const char *rs_pretty_lq_type(enum iwl_table_type type); +static const char *rs_pretty_ant(u8 ant); #ifdef CONFIG_MAC80211_DEBUGFS static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, @@ -264,6 +265,15 @@ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { #define MCS_INDEX_PER_STREAM (8) +static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, + const char *prefix) +{ + IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d\n", + prefix, rs_pretty_lq_type(rate->type), + rate->index, rs_pretty_ant(rate->ant), + rate->bw, rate->sgi); +} + static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) { window->data = 0; @@ -430,167 +440,160 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, return 0; } -/* - * Fill uCode API rate_n_flags field, based on "search" or "active" table. - */ -/* FIXME:RS:remove this function and put the flags statically in the table */ -static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm, - struct iwl_scale_tbl_info *tbl, int index) +/* Convert rs_rate object into ucode rate bitmask */ +static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, + struct rs_rate *rate) { - u32 rate_n_flags = 0; + u32 ucode_rate = 0; + int index = rate->index; - rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & + ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) & RATE_MCS_ANT_ABC_MSK); - if (is_legacy(tbl->lq_type)) { - rate_n_flags |= iwl_rates[index].plcp; + if (is_legacy(rate)) { + ucode_rate |= iwl_rates[index].plcp; if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) - rate_n_flags |= RATE_MCS_CCK_MSK; - return rate_n_flags; + ucode_rate |= RATE_MCS_CCK_MSK; + return ucode_rate; } - if (is_ht(tbl->lq_type)) { + if (is_ht(rate)) { if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) { IWL_ERR(mvm, "Invalid HT rate index %d\n", index); index = IWL_LAST_HT_RATE; } - rate_n_flags |= RATE_MCS_HT_MSK; + ucode_rate |= RATE_MCS_HT_MSK; - if (is_ht_siso(tbl->lq_type)) - rate_n_flags |= iwl_rates[index].plcp_ht_siso; - else if (is_ht_mimo2(tbl->lq_type)) - rate_n_flags |= iwl_rates[index].plcp_ht_mimo2; + if (is_ht_siso(rate)) + ucode_rate |= iwl_rates[index].plcp_ht_siso; + else if (is_ht_mimo2(rate)) + ucode_rate |= iwl_rates[index].plcp_ht_mimo2; else WARN_ON_ONCE(1); - } else if (is_vht(tbl->lq_type)) { + } else if (is_vht(rate)) { if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) { IWL_ERR(mvm, "Invalid VHT rate index %d\n", index); index = IWL_LAST_VHT_RATE; } - rate_n_flags |= RATE_MCS_VHT_MSK; - if (is_vht_siso(tbl->lq_type)) - rate_n_flags |= iwl_rates[index].plcp_vht_siso; - else if (is_vht_mimo2(tbl->lq_type)) - rate_n_flags |= iwl_rates[index].plcp_vht_mimo2; + ucode_rate |= RATE_MCS_VHT_MSK; + if (is_vht_siso(rate)) + ucode_rate |= iwl_rates[index].plcp_vht_siso; + else if (is_vht_mimo2(rate)) + ucode_rate |= iwl_rates[index].plcp_vht_mimo2; else WARN_ON_ONCE(1); } else { - IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); + IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); } - rate_n_flags |= tbl->bw; - if (tbl->is_SGI) - rate_n_flags |= RATE_MCS_SGI_MSK; + ucode_rate |= rate->bw; + if (rate->sgi) + ucode_rate |= RATE_MCS_SGI_MSK; - return rate_n_flags; + return ucode_rate; } -/* - * Interpret uCode API's rate_n_flags format, - * fill "search" or "active" tx mode table. - */ -static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, - enum ieee80211_band band, - struct iwl_scale_tbl_info *tbl, - int *rate_idx) +/* Convert a ucode rate into an rs_rate object */ +static int rs_rate_from_ucode_rate(const u32 ucode_rate, + enum ieee80211_band band, + struct rs_rate *rate) { - u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); - u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); + u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK; + u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate); u8 nss; - memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); - *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); + memset(rate, 0, sizeof(struct rs_rate)); + rate->index = iwl_hwrate_to_plcp_idx(ucode_rate); - if (*rate_idx == IWL_RATE_INVALID) { - *rate_idx = -1; + if (rate->index == IWL_RATE_INVALID) { + rate->index = -1; return -EINVAL; } - tbl->is_SGI = 0; /* default legacy setup */ - tbl->bw = 0; - tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); - tbl->lq_type = LQ_NONE; - tbl->max_search = IWL_MAX_SEARCH; + + rate->ant = (ant_msk >> RATE_MCS_ANT_POS); /* Legacy */ - if (!(rate_n_flags & RATE_MCS_HT_MSK) && - !(rate_n_flags & RATE_MCS_VHT_MSK)) { + if (!(ucode_rate & RATE_MCS_HT_MSK) && + !(ucode_rate & RATE_MCS_VHT_MSK)) { if (num_of_ant == 1) { if (band == IEEE80211_BAND_5GHZ) - tbl->lq_type = LQ_LEGACY_A; + rate->type = LQ_LEGACY_A; else - tbl->lq_type = LQ_LEGACY_G; + rate->type = LQ_LEGACY_G; } return 0; } /* HT or VHT */ - if (rate_n_flags & RATE_MCS_SGI_MSK) - tbl->is_SGI = 1; + if (ucode_rate & RATE_MCS_SGI_MSK) + rate->sgi = true; - tbl->bw = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK; + rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; - if (rate_n_flags & RATE_MCS_HT_MSK) { - nss = ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >> + if (ucode_rate & RATE_MCS_HT_MSK) { + nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; if (nss == 1) { - tbl->lq_type = LQ_HT_SISO; + rate->type = LQ_HT_SISO; WARN_ON_ONCE(num_of_ant != 1); } else if (nss == 2) { - tbl->lq_type = LQ_HT_MIMO2; + rate->type = LQ_HT_MIMO2; WARN_ON_ONCE(num_of_ant != 2); } else { WARN_ON_ONCE(1); } - } else if (rate_n_flags & RATE_MCS_VHT_MSK) { - nss = ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> + } else if (ucode_rate & RATE_MCS_VHT_MSK) { + nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; if (nss == 1) { - tbl->lq_type = LQ_VHT_SISO; + rate->type = LQ_VHT_SISO; WARN_ON_ONCE(num_of_ant != 1); } else if (nss == 2) { - tbl->lq_type = LQ_VHT_MIMO2; + rate->type = LQ_VHT_MIMO2; WARN_ON_ONCE(num_of_ant != 2); } else { WARN_ON_ONCE(1); } } - WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_160); - WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_80 && - !is_vht(tbl->lq_type)); + WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_160); + WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_80 && + !is_vht(rate)); return 0; } /* switch to another antenna/antennas and return 1 */ /* if no other valid antenna found, return 0 */ -static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, - struct iwl_scale_tbl_info *tbl) +static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate, + struct rs_rate *rate) { u8 new_ant_type; - if (!tbl->ant_type || tbl->ant_type > ANT_ABC) + if (!rate->ant || rate->ant > ANT_ABC) return 0; - if (!rs_is_valid_ant(valid_ant, tbl->ant_type)) + if (!rs_is_valid_ant(valid_ant, rate->ant)) return 0; - new_ant_type = ant_toggle_lookup[tbl->ant_type]; + new_ant_type = ant_toggle_lookup[rate->ant]; - while ((new_ant_type != tbl->ant_type) && + while ((new_ant_type != rate->ant) && !rs_is_valid_ant(valid_ant, new_ant_type)) new_ant_type = ant_toggle_lookup[new_ant_type]; - if (new_ant_type == tbl->ant_type) + if (new_ant_type == rate->ant) return 0; - tbl->ant_type = new_ant_type; - *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK; - *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS; + rate->ant = new_ant_type; + + /* TODO: get rid of ucode_rate here. This should handle only rs_rate */ + *ucode_rate &= ~RATE_MCS_ANT_ABC_MSK; + *ucode_rate |= new_ant_type << RATE_MCS_ANT_POS; return 1; } @@ -603,13 +606,13 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, */ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, struct ieee80211_hdr *hdr, - enum iwl_table_type rate_type) + struct rs_rate *rate) { - if (is_legacy(rate_type)) + if (is_legacy(rate)) return lq_sta->active_legacy_rate; - else if (is_siso(rate_type)) + else if (is_siso(rate)) return lq_sta->active_siso_rate; - else if (is_mimo2(rate_type)) + else if (is_mimo2(rate)) return lq_sta->active_mimo2_rate; WARN_ON_ONCE(1); @@ -624,7 +627,7 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, /* 802.11A or ht walks to the next literal adjacent rate in * the rate table */ - if (is_a_band(rate_type) || !is_legacy(rate_type)) { + if (is_type_a_band(rate_type) || !is_type_legacy(rate_type)) { int i; u32 mask; @@ -673,7 +676,7 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, } static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, + struct rs_rate *rate, u8 scale_index, u8 ht_possible) { s32 low; @@ -685,30 +688,29 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, /* check if we need to switch from HT to legacy rates. * assumption is that mandatory rates (1Mbps or 6Mbps) * are always supported (spec demand) */ - if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { + if (!is_legacy(rate) && (!ht_possible || !scale_index)) { switch_to_legacy = 1; scale_index = rs_ht_to_legacy[scale_index]; if (lq_sta->band == IEEE80211_BAND_5GHZ) - tbl->lq_type = LQ_LEGACY_A; + rate->type = LQ_LEGACY_A; else - tbl->lq_type = LQ_LEGACY_G; + rate->type = LQ_LEGACY_G; - if (num_of_ant(tbl->ant_type) > 1) - tbl->ant_type = + if (num_of_ant(rate->ant) > 1) + rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); - tbl->bw = 0; - tbl->is_SGI = 0; - tbl->max_search = IWL_MAX_SEARCH; + rate->bw = 0; + rate->sgi = false; } - rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); + rate_mask = rs_get_supported_rates(lq_sta, NULL, rate); /* Mask with station rate restriction */ - if (is_legacy(tbl->lq_type)) { + if (is_legacy(rate)) { /* supp_rates has no CCK bits in A mode */ if (lq_sta->band == IEEE80211_BAND_5GHZ) - rate_mask = (u16)(rate_mask & + rate_mask = (u16)(rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); else rate_mask = (u16)(rate_mask & lq_sta->supp_rates); @@ -721,24 +723,22 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, } high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask, - tbl->lq_type); + rate->type); low = high_low & 0xff; if (low == IWL_RATE_INVALID) low = scale_index; out: - return rate_n_flags_from_tbl(lq_sta->drv, tbl, low); + rate->index = low; + return ucode_rate_from_rs_rate(lq_sta->drv, rate); } -/* - * Simple function to compare two rate scale table types - */ -static bool table_type_matches(struct iwl_scale_tbl_info *a, - struct iwl_scale_tbl_info *b) +/* Simple function to compare two rate scale table types */ +static inline bool rs_rate_match(struct rs_rate *a, + struct rs_rate *b) { - return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && - (a->is_SGI == b->is_SGI); + return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi); } static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) @@ -762,7 +762,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, { int legacy_success; int retries; - int rs_index, mac_index, i; + int mac_index, i; struct iwl_lq_sta *lq_sta = priv_sta; struct iwl_lq_cmd *table; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -770,8 +770,8 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); enum mac80211_rate_control_flags mac_flags; - u32 tx_rate; - struct iwl_scale_tbl_info tbl_type; + u32 ucode_rate; + struct rs_rate rate; struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; /* Treat uninitialized rate scaling data same as non-existing. */ @@ -801,10 +801,10 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, * to a new "search" mode (which might become the new "active" mode). */ table = &lq_sta->lq; - tx_rate = le32_to_cpu(table->rs_table[0]); - rs_get_tbl_info_from_mcs(tx_rate, info->band, &tbl_type, &rs_index); + ucode_rate = le32_to_cpu(table->rs_table[0]); + rs_rate_from_ucode_rate(ucode_rate, info->band, &rate); if (info->band == IEEE80211_BAND_5GHZ) - rs_index -= IWL_FIRST_OFDM_RATE; + rate.index -= IWL_FIRST_OFDM_RATE; mac_flags = info->status.rates[0].flags; mac_index = info->status.rates[0].idx; /* For HT packets, map MCS to PLCP */ @@ -827,19 +827,19 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, /* Here we actually compare this rate to the latest LQ command */ if ((mac_index < 0) || - (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || - (tbl_type.bw != rs_ch_width_from_mac_flags(mac_flags)) || - (tbl_type.ant_type != info->status.antenna) || - (!!(tx_rate & RATE_MCS_HT_MSK) != + (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || + (rate.bw != rs_ch_width_from_mac_flags(mac_flags)) || + (rate.ant != info->status.antenna) || + (!!(ucode_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) || - (!!(tx_rate & RATE_MCS_VHT_MSK) != + (!!(ucode_rate & RATE_MCS_VHT_MSK) != !!(mac_flags & IEEE80211_TX_RC_VHT_MCS)) || - (!!(tx_rate & RATE_HT_MCS_GF_MSK) != + (!!(ucode_rate & RATE_HT_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || - (rs_index != mac_index)) { + (rate.index != mac_index)) { IWL_DEBUG_RATE(mvm, "initial rate %d does not match %d (0x%x)\n", - mac_index, rs_index, tx_rate); + mac_index, rate.index, ucode_rate); /* * Since rates mis-match, the last LQ command may have failed. * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with @@ -857,28 +857,23 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter = 0; /* Figure out if rate scale algorithm is in active or search table */ - if (table_type_matches(&tbl_type, - &(lq_sta->lq_info[lq_sta->active_tbl]))) { + if (rs_rate_match(&rate, + &(lq_sta->lq_info[lq_sta->active_tbl].rate))) { curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); - } else if (table_type_matches( - &tbl_type, &lq_sta->lq_info[1 - lq_sta->active_tbl])) { + } else if (rs_rate_match(&rate, + &lq_sta->lq_info[1 - lq_sta->active_tbl].rate)) { curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); } else { IWL_DEBUG_RATE(mvm, "Neither active nor search matches tx rate\n"); tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - IWL_DEBUG_RATE(mvm, "active- lq:%x, ant:%x, SGI:%d\n", - tmp_tbl->lq_type, tmp_tbl->ant_type, - tmp_tbl->is_SGI); + rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE"); tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); - IWL_DEBUG_RATE(mvm, "search- lq:%x, ant:%x, SGI:%d\n", - tmp_tbl->lq_type, tmp_tbl->ant_type, - tmp_tbl->is_SGI); - IWL_DEBUG_RATE(mvm, "actual- lq:%x, ant:%x, SGI:%d\n", - tbl_type.lq_type, tbl_type.ant_type, - tbl_type.is_SGI); + rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH"); + rs_dump_rate(mvm, &rate, "ACTUAL"); + /* * no matching table found, let's by-pass the data collection * and continue to perform rate scale to find the rate table @@ -895,10 +890,9 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, * first index into rate scale table. */ if (info->flags & IEEE80211_TX_STAT_AMPDU) { - tx_rate = le32_to_cpu(table->rs_table[0]); - rs_get_tbl_info_from_mcs(tx_rate, info->band, &tbl_type, - &rs_index); - rs_collect_tx_data(curr_tbl, rs_index, + ucode_rate = le32_to_cpu(table->rs_table[0]); + rs_rate_from_ucode_rate(ucode_rate, info->band, &rate); + rs_collect_tx_data(curr_tbl, rate.index, info->status.ampdu_len, info->status.ampdu_ack_len); @@ -920,20 +914,19 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); /* Collect data for each rate used during failed TX attempts */ for (i = 0; i <= retries; ++i) { - tx_rate = le32_to_cpu(table->rs_table[i]); - rs_get_tbl_info_from_mcs(tx_rate, info->band, - &tbl_type, &rs_index); + ucode_rate = le32_to_cpu(table->rs_table[i]); + rs_rate_from_ucode_rate(ucode_rate, info->band, &rate); /* * Only collect stats if retried rate is in the same RS * table as active/search. */ - if (table_type_matches(&tbl_type, curr_tbl)) + if (rs_rate_match(&rate, &curr_tbl->rate)) tmp_tbl = curr_tbl; - else if (table_type_matches(&tbl_type, other_tbl)) + else if (rs_rate_match(&rate, &other_tbl->rate)) tmp_tbl = other_tbl; else continue; - rs_collect_tx_data(tmp_tbl, rs_index, 1, + rs_collect_tx_data(tmp_tbl, rate.index, 1, i < retries ? 0 : legacy_success); } @@ -944,7 +937,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, } } /* The last TX rate is cached in lq_sta; it's set in if/else above */ - lq_sta->last_rate_n_flags = tx_rate; + lq_sta->last_rate_n_flags = ucode_rate; done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) @@ -988,16 +981,17 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, { /* Used to choose among HT tables */ s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; + struct rs_rate *rate = &tbl->rate; /* Check for invalid LQ type */ - if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_ht(tbl->lq_type) && - !(is_vht(tbl->lq_type)))) { + if (WARN_ON_ONCE(!is_legacy(rate) && !is_ht(rate) && + !(is_vht(rate)))) { tbl->expected_tpt = expected_tpt_legacy; return; } /* Legacy rates have only one table */ - if (is_legacy(tbl->lq_type)) { + if (is_legacy(rate)) { tbl->expected_tpt = expected_tpt_legacy; return; } @@ -1006,8 +1000,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, /* Choose among many HT tables depending on number of streams * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation * status */ - if (is_siso(tbl->lq_type)) { - switch (tbl->bw) { + if (is_siso(rate)) { + switch (rate->bw) { case RATE_MCS_CHAN_WIDTH_20: ht_tbl_pointer = expected_tpt_siso_20MHz; break; @@ -1020,8 +1014,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, default: WARN_ON_ONCE(1); } - } else if (is_mimo2(tbl->lq_type)) { - switch (tbl->bw) { + } else if (is_mimo2(rate)) { + switch (rate->bw) { case RATE_MCS_CHAN_WIDTH_20: ht_tbl_pointer = expected_tpt_mimo2_20MHz; break; @@ -1038,11 +1032,11 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, WARN_ON_ONCE(1); } - if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ + if (!rate->sgi && !lq_sta->is_agg) /* Normal */ tbl->expected_tpt = ht_tbl_pointer[0]; - else if (tbl->is_SGI && !lq_sta->is_agg) /* SGI */ + else if (rate->sgi && !lq_sta->is_agg) /* SGI */ tbl->expected_tpt = ht_tbl_pointer[1]; - else if (!tbl->is_SGI && lq_sta->is_agg) /* AGG */ + else if (!rate->sgi && lq_sta->is_agg) /* AGG */ tbl->expected_tpt = ht_tbl_pointer[2]; else /* AGG+SGI */ tbl->expected_tpt = ht_tbl_pointer[3]; @@ -1082,7 +1076,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, while (1) { high_low = rs_get_adjacent_rate(mvm, rate, rate_mask, - tbl->lq_type); + tbl->rate.type); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -1163,30 +1157,29 @@ static inline void rs_move_next_action(struct iwl_scale_tbl_info *tbl, tbl->action = (tbl->action + 1) % (last_action + 1); } -static void rs_set_bw_from_sta(struct iwl_scale_tbl_info *tbl, - struct ieee80211_sta *sta) +static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) { if (sta->bandwidth >= IEEE80211_STA_RX_BW_80) - tbl->bw = RATE_MCS_CHAN_WIDTH_80; + return RATE_MCS_CHAN_WIDTH_80; else if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) - tbl->bw = RATE_MCS_CHAN_WIDTH_40; - else - tbl->bw = RATE_MCS_CHAN_WIDTH_20; + return RATE_MCS_CHAN_WIDTH_40; + + return RATE_MCS_CHAN_WIDTH_20; } -static bool rs_sgi_allowed(struct iwl_scale_tbl_info *tbl, +static bool rs_sgi_allowed(struct rs_rate *rate, struct ieee80211_sta *sta) { struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; - if (is_ht20(tbl) && (ht_cap->cap & + if (is_ht20(rate) && (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)) return true; - if (is_ht40(tbl) && (ht_cap->cap & + if (is_ht40(rate) && (ht_cap->cap & IEEE80211_HT_CAP_SGI_40)) return true; - if (is_ht80(tbl) && (vht_cap->cap & + if (is_ht80(rate) && (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80)) return true; @@ -1202,7 +1195,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; - s32 rate; + s32 rate_idx; if (!sta->ht_cap.ht_supported) return -1; @@ -1216,24 +1209,26 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); - tbl->lq_type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; + tbl->rate.type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; tbl->action = 0; tbl->max_search = IWL_MAX_SEARCH; rate_mask = lq_sta->active_mimo2_rate; - rs_set_bw_from_sta(tbl, sta); + tbl->rate.bw = rs_bw_from_sta_bw(sta); rs_set_expected_tpt_table(lq_sta, tbl); - rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); + rate_idx = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); IWL_DEBUG_RATE(mvm, "LQ: MIMO2 best rate %d mask %X\n", - rate, rate_mask); - if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { + rate_idx, rate_mask); + if ((rate_idx == IWL_RATE_INVALID) || !((1 << rate_idx) & rate_mask)) { IWL_DEBUG_RATE(mvm, "Can't switch with index %d rate mask %x\n", - rate, rate_mask); + rate_idx, rate_mask); return -1; } - tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate); + + tbl->rate.index = rate_idx; + tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate); IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", tbl->current_rate); @@ -1249,30 +1244,34 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; - s32 rate; + s32 rate_idx; if (!sta->ht_cap.ht_supported) return -1; IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); - tbl->lq_type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; + tbl->rate.type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; tbl->action = 0; tbl->max_search = IWL_MAX_SEARCH; rate_mask = lq_sta->active_siso_rate; - rs_set_bw_from_sta(tbl, sta); + tbl->rate.bw = rs_bw_from_sta_bw(sta); rs_set_expected_tpt_table(lq_sta, tbl); - rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); + rate_idx = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); - IWL_DEBUG_RATE(mvm, "LQ: get best rate %d mask %X\n", rate, rate_mask); - if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { + IWL_DEBUG_RATE(mvm, "LQ: get best rate %d mask %X\n", + rate_idx, rate_mask); + if ((rate_idx == IWL_RATE_INVALID) || !((1 << rate_idx) & rate_mask)) { IWL_DEBUG_RATE(mvm, "can not switch with index %d rate mask %x\n", - rate, rate_mask); + rate_idx, rate_mask); return -1; } - tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate); + + tbl->rate.index = rate_idx; + tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate); + IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", tbl->current_rate); return 0; @@ -1289,6 +1288,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); struct iwl_scale_tbl_info *search_tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct rs_rate *rate = &search_tbl->rate; struct iwl_rate_scale_data *window = &(tbl->win[index]); u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); @@ -1317,7 +1317,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, if (rs_toggle_antenna(valid_tx_ant, &search_tbl->current_rate, - search_tbl)) { + &search_tbl->rate)) { update_search_tbl_counter = 1; rs_set_expected_tpt_table(lq_sta, search_tbl); goto out; @@ -1328,7 +1328,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, /* Set up search table to try SISO */ memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; + rate->sgi = false; ret = rs_switch_to_siso(mvm, lq_sta, sta, search_tbl, index); if (!ret) { @@ -1342,12 +1342,11 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, /* Set up search table to try MIMO */ memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - - search_tbl->ant_type = ANT_AB; + rate->sgi = false; + rate->ant = ANT_AB; if (!rs_is_valid_ant(valid_tx_ant, - search_tbl->ant_type)) + rate->ant)) break; ret = rs_switch_to_mimo2(mvm, lq_sta, sta, @@ -1365,7 +1364,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, if (tbl->action == start_action) break; } - search_tbl->lq_type = LQ_NONE; + rate->type = LQ_NONE; return 0; out: @@ -1386,6 +1385,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); struct iwl_scale_tbl_info *search_tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct rs_rate *rate = &search_tbl->rate; struct iwl_rate_scale_data *window = &(tbl->win[index]); u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); @@ -1416,7 +1416,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, memcpy(search_tbl, tbl, sz); if (rs_toggle_antenna(valid_tx_ant, &search_tbl->current_rate, - search_tbl)) { + rate)) { update_search_tbl_counter = 1; goto out; } @@ -1424,12 +1424,11 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, case IWL_SISO_SWITCH_MIMO2: IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n"); memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - - search_tbl->ant_type = ANT_AB; + rate->sgi = false; + rate->ant = ANT_AB; if (!rs_is_valid_ant(valid_tx_ant, - search_tbl->ant_type)) + rate->ant)) break; ret = rs_switch_to_mimo2(mvm, lq_sta, sta, @@ -1438,21 +1437,22 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, goto out; break; case IWL_SISO_SWITCH_GI: - if (!rs_sgi_allowed(tbl, sta)) + if (!rs_sgi_allowed(rate, sta)) break; IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = !tbl->is_SGI; + rate->sgi = !tbl->rate.sgi; rs_set_expected_tpt_table(lq_sta, search_tbl); - if (tbl->is_SGI) { + if (tbl->rate.sgi) { s32 tpt = lq_sta->last_tpt / 100; if (tpt >= search_tbl->expected_tpt[index]) break; } + rate->index = index; search_tbl->current_rate = - rate_n_flags_from_tbl(mvm, search_tbl, index); + ucode_rate_from_rs_rate(mvm, rate); update_search_tbl_counter = 1; goto out; default: @@ -1463,7 +1463,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, if (tbl->action == start_action) break; } - search_tbl->lq_type = LQ_NONE; + rate->type = LQ_NONE; return 0; out: @@ -1485,6 +1485,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); struct iwl_scale_tbl_info *search_tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct rs_rate *rate = &search_tbl->rate; u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; @@ -1509,12 +1510,12 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, memcpy(search_tbl, tbl, sz); if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) - search_tbl->ant_type = ANT_A; + rate->ant = ANT_A; else /* tbl->action == IWL_MIMO2_SWITCH_SISO_B */ - search_tbl->ant_type = ANT_B; + rate->ant = ANT_B; if (!rs_is_valid_ant(valid_tx_ant, - search_tbl->ant_type)) + rate->ant)) break; ret = rs_switch_to_siso(mvm, lq_sta, sta, @@ -1525,14 +1526,14 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, break; case IWL_MIMO2_SWITCH_GI: - if (!rs_sgi_allowed(tbl, sta)) + if (!rs_sgi_allowed(rate, sta)) break; IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); /* Set up new search table for MIMO2 */ memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = !tbl->is_SGI; + rate->sgi = !tbl->rate.sgi; rs_set_expected_tpt_table(lq_sta, search_tbl); /* * If active table already uses the fastest possible @@ -1540,13 +1541,14 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, * and it's working well, there's no need to look * for a better type of modulation! */ - if (tbl->is_SGI) { + if (tbl->rate.sgi) { s32 tpt = lq_sta->last_tpt / 100; if (tpt >= search_tbl->expected_tpt[index]) break; } + rate->index = index; search_tbl->current_rate = - rate_n_flags_from_tbl(mvm, search_tbl, index); + ucode_rate_from_rs_rate(mvm, rate); update_search_tbl_counter = 1; goto out; default: @@ -1557,7 +1559,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, if (tbl->action == start_action) break; } - search_tbl->lq_type = LQ_NONE; + rate->type = LQ_NONE; return 0; out: lq_sta->search_better_tbl = 1; @@ -1657,14 +1659,12 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) static void rs_update_rate_tbl(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, - int index) + struct rs_rate *rate) { - u32 rate; + u32 ucode_rate; - /* Update uCode's rate table. */ - rate = rate_n_flags_from_tbl(mvm, tbl, index); - rs_fill_link_cmd(mvm, sta, lq_sta, rate); + ucode_rate = ucode_rate_from_rs_rate(mvm, rate); + rs_fill_link_cmd(mvm, sta, lq_sta, ucode_rate); iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } @@ -1716,6 +1716,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, u8 prev_agg = lq_sta->is_agg; struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; struct iwl_mvm_tid_data *tid_data; + struct rs_rate *rate; /* Send management frames and NO_ACK data using lowest rate. */ /* TODO: this could probably be improved.. */ @@ -1748,6 +1749,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, active_tbl = 1 - lq_sta->active_tbl; tbl = &(lq_sta->lq_info[active_tbl]); + rate = &tbl->rate; if (prev_agg != lq_sta->is_agg) { IWL_DEBUG_RATE(mvm, @@ -1760,10 +1762,10 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, index = lq_sta->last_txrate_idx; /* rates available for this association, and for modulation mode */ - rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); + rate_mask = rs_get_supported_rates(lq_sta, hdr, rate); /* mask with station rate restriction */ - if (is_legacy(tbl->lq_type)) { + if (is_legacy(rate)) { if (lq_sta->band == IEEE80211_BAND_5GHZ) /* supp_rates has no CCK bits in A mode */ rate_scale_index_msk = (u16) (rate_mask & @@ -1783,12 +1785,13 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, IWL_ERR(mvm, "Current Rate is not valid\n"); if (lq_sta->search_better_tbl) { /* revert to active table if search table is not valid*/ - tbl->lq_type = LQ_NONE; + rate->type = LQ_NONE; lq_sta->search_better_tbl = 0; tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); /* get "active" rate info */ index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index); + tbl->rate.index = index; + rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate); } return; } @@ -1825,7 +1828,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) { IWL_DEBUG_RATE(mvm, "(%s: %d): Test Window: succ %d total %d\n", - rs_pretty_lq_type(tbl->lq_type), + rs_pretty_lq_type(rate->type), index, window->success_counter, window->counter); /* Can't calculate this yet; not enough history */ @@ -1858,7 +1861,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, window->average_tpt, lq_sta->last_tpt); - if (!is_legacy(tbl->lq_type)) + if (!is_legacy(rate)) lq_sta->enable_counter = 1; /* Swap tables; "search" becomes "active" */ @@ -1874,7 +1877,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, lq_sta->last_tpt); /* Nullify "search" table */ - tbl->lq_type = LQ_NONE; + rate->type = LQ_NONE; /* Revert to "active" table */ active_tbl = lq_sta->active_tbl; @@ -1898,7 +1901,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, /* (Else) not in search of better modulation mode, try for better * starting rate, while staying in this mode. */ high_low = rs_get_adjacent_rate(mvm, index, rate_scale_index_msk, - tbl->lq_type); + rate->type); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -1918,8 +1921,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, IWL_DEBUG_RATE(mvm, "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", - rs_pretty_lq_type(tbl->lq_type), index, current_tpt, - sr, low, high, low_tpt, high_tpt); + rs_pretty_lq_type(rate->type), index, current_tpt, sr, + low, high, low_tpt, high_tpt); scale_action = 0; @@ -2002,7 +2005,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, } /* Force a search in case BT doesn't like us being in MIMO */ - if (is_mimo(tbl->lq_type) && + if (is_mimo(rate) && !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) { IWL_DEBUG_RATE(mvm, "BT Coex forbids MIMO. Search for new config\n"); @@ -2041,8 +2044,10 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, lq_update: /* Replace uCode's rate table for the destination station. */ - if (update_lq) - rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index); + if (update_lq) { + tbl->rate.index = index; + rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate); + } rs_stay_in_table(lq_sta, false); @@ -2063,11 +2068,11 @@ lq_update: window->counter); /* Select a new "search" modulation mode to try. * If one is found, set up the new "search" table. */ - if (is_legacy(tbl->lq_type)) + if (is_legacy(&tbl->rate)) rs_move_legacy_other(mvm, lq_sta, sta, index); - else if (is_siso(tbl->lq_type)) + else if (is_siso(&tbl->rate)) rs_move_siso_to_other(mvm, lq_sta, sta, index); - else if (is_mimo2(tbl->lq_type)) + else if (is_mimo2(&tbl->rate)) rs_move_mimo2_to_other(mvm, lq_sta, sta, index); else WARN_ON_ONCE(1); @@ -2086,7 +2091,7 @@ lq_update: "Switch to SEARCH TABLE: " "mcs %X (%s: %d)\n", tbl->current_rate, - rs_pretty_lq_type(tbl->lq_type), + rs_pretty_lq_type(tbl->rate.type), index); rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); @@ -2102,7 +2107,7 @@ lq_update: * stay with best antenna legacy modulation for a while * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); - if (is_legacy(tbl1->lq_type) && !sta->ht_cap.ht_supported && + if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported && lq_sta->action_counter > tbl1->max_search) { IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); rs_set_stay_in_table(mvm, 1, lq_sta); @@ -2130,7 +2135,8 @@ lq_update: } out: - tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, index); + tbl->rate.index = index; + tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate); lq_sta->last_txrate_idx = index; } @@ -2155,9 +2161,9 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, bool init) { struct iwl_scale_tbl_info *tbl; - int rate_idx; + struct rs_rate *rate; int i; - u32 rate; + u32 ucode_rate; u8 active_tbl = 0; u8 valid_tx_ant; @@ -2174,25 +2180,26 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, active_tbl = 1 - lq_sta->active_tbl; tbl = &(lq_sta->lq_info[active_tbl]); + rate = &tbl->rate; if ((i < 0) || (i >= IWL_RATE_COUNT)) i = 0; - rate = iwl_rates[i].plcp; - tbl->ant_type = first_antenna(valid_tx_ant); - rate |= tbl->ant_type << RATE_MCS_ANT_POS; + ucode_rate = iwl_rates[i].plcp; + rate->ant = first_antenna(valid_tx_ant); + ucode_rate |= rate->ant << RATE_MCS_ANT_POS; if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE) - rate |= RATE_MCS_CCK_MSK; + ucode_rate |= RATE_MCS_CCK_MSK; - rs_get_tbl_info_from_mcs(rate, band, tbl, &rate_idx); - if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) - rs_toggle_antenna(valid_tx_ant, &rate, tbl); + rs_rate_from_ucode_rate(ucode_rate, band, rate); + if (!rs_is_valid_ant(valid_tx_ant, rate->ant)) + rs_toggle_antenna(valid_tx_ant, &ucode_rate, rate); - rate = rate_n_flags_from_tbl(mvm, tbl, rate_idx); - tbl->current_rate = rate; + ucode_rate = ucode_rate_from_rs_rate(mvm, rate); + tbl->current_rate = ucode_rate; rs_set_expected_tpt_table(lq_sta, tbl); - rs_fill_link_cmd(NULL, NULL, lq_sta, rate); + rs_fill_link_cmd(NULL, NULL, lq_sta, ucode_rate); /* TODO restore station should remember the lq cmd */ iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); } @@ -2435,9 +2442,8 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, u32 new_rate) { - struct iwl_scale_tbl_info tbl_type; + struct rs_rate rate; int index = 0; - int rate_idx; int repeat_rate = 0; u8 ant_toggle_cnt = 0; u8 use_ht_possible = 1; @@ -2447,12 +2453,10 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, /* Override starting rate (index 0) if needed for debug purposes */ rs_dbgfs_set_mcs(lq_sta, &new_rate); - /* Interpret new_rate (rate_n_flags) */ - rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, - &tbl_type, &rate_idx); + rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate); /* How many times should we repeat the initial rate? */ - if (is_legacy(tbl_type.lq_type)) { + if (is_legacy(&rate)) { ant_toggle_cnt = 1; repeat_rate = IWL_NUMBER_TRY; } else { @@ -2460,15 +2464,15 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, LINK_QUAL_AGG_DISABLE_START_DEF - 1); } - lq_cmd->mimo_delim = is_mimo(tbl_type.lq_type) ? 1 : 0; + lq_cmd->mimo_delim = is_mimo(&rate) ? 1 : 0; /* Fill 1st table entry (index 0) */ lq_cmd->rs_table[index] = cpu_to_le32(new_rate); - if (num_of_ant(tbl_type.ant_type) == 1) - lq_cmd->single_stream_ant_msk = tbl_type.ant_type; - else if (num_of_ant(tbl_type.ant_type) == 2) - lq_cmd->dual_stream_ant_msk = tbl_type.ant_type; + if (num_of_ant(rate.ant) == 1) + lq_cmd->single_stream_ant_msk = rate.ant; + else if (num_of_ant(rate.ant) == 2) + lq_cmd->dual_stream_ant_msk = rate.ant; /* otherwise we don't modify the existing value */ index++; @@ -2482,12 +2486,12 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { - if (is_legacy(tbl_type.lq_type)) { + if (is_legacy(&rate)) { if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) ant_toggle_cnt++; else if (mvm && rs_toggle_antenna(valid_tx_ant, - &new_rate, &tbl_type)) + &new_rate, &rate)) ant_toggle_cnt = 1; } @@ -2501,26 +2505,25 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, index++; } - rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, - &rate_idx); + rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate); /* Indicate to uCode which entries might be MIMO. * If initial rate was MIMO, this will finally end up * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ - if (is_mimo(tbl_type.lq_type)) + if (is_mimo(&rate)) lq_cmd->mimo_delim = index; /* Get next rate */ - new_rate = rs_get_lower_rate(lq_sta, &tbl_type, rate_idx, + new_rate = rs_get_lower_rate(lq_sta, &rate, rate.index, use_ht_possible); /* How many times should we repeat the next rate? */ - if (is_legacy(tbl_type.lq_type)) { + if (is_legacy(&rate)) { if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) ant_toggle_cnt++; else if (mvm && rs_toggle_antenna(valid_tx_ant, - &new_rate, &tbl_type)) + &new_rate, &rate)) ant_toggle_cnt = 1; repeat_rate = IWL_NUMBER_TRY; @@ -2629,7 +2632,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, static const char *rs_pretty_lq_type(enum iwl_table_type type) { - static const char * const lq_type[] = { + static const char * const lq_types[] = { [LQ_NONE] = "NONE", [LQ_LEGACY_A] = "LEGACY_A", [LQ_LEGACY_G] = "LEGACY_G", @@ -2642,10 +2645,10 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) if (type < LQ_NONE || type >= LQ_MAX) return "UNKNOWN"; - return lq_type[type]; + return lq_types[type]; } -static int rs_pretty_print_rate(char *buf, const u32 rate) +static const char *rs_pretty_ant(u8 ant) { static const char * const ant_name[] = { [ANT_NONE] = "None", @@ -2658,6 +2661,15 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) [ANT_ABC] = "ABC", }; + if (ant > ANT_ABC) + return "UNKNOWN"; + + return ant_name[ant]; +} + +static int rs_pretty_print_rate(char *buf, const u32 rate) +{ + char *type, *bw; u8 mcs = 0, nss = 0; u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; @@ -2667,7 +2679,7 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) int index = iwl_hwrate_to_plcp_idx(rate); return sprintf(buf, "Legacy | ANT: %s Rate: %s Mbps\n", - ant_name[ant], iwl_rate_mcs[index].mbps); + rs_pretty_ant(ant), iwl_rate_mcs[index].mbps); } if (rate & RATE_MCS_VHT_MSK) { @@ -2700,7 +2712,7 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) } return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n", - type, ant_name[ant], bw, mcs, nss, + type, rs_pretty_ant(ant), bw, mcs, nss, (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", @@ -2719,7 +2731,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_mvm *mvm; struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - + struct rs_rate *rate = &tbl->rate; mvm = lq_sta->drv; buff = kmalloc(2048, GFP_KERNEL); if (!buff) @@ -2736,17 +2748,17 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); desc += sprintf(buff+desc, "lq type %s\n", - (is_legacy(tbl->lq_type)) ? "legacy" : - is_vht(tbl->lq_type) ? "VHT" : "HT"); - if (!is_legacy(tbl->lq_type)) { + (is_legacy(rate)) ? "legacy" : + is_vht(rate) ? "VHT" : "HT"); + if (!is_legacy(rate)) { desc += sprintf(buff+desc, " %s", - (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); + (is_siso(rate)) ? "SISO" : "MIMO2"); desc += sprintf(buff+desc, " %s", - (is_ht20(tbl)) ? "20MHz" : - (is_ht40(tbl)) ? "40MHz" : - (is_ht80(tbl)) ? "80Mhz" : "BAD BW"); + (is_ht20(rate)) ? "20MHz" : + (is_ht40(rate)) ? "40MHz" : + (is_ht80(rate)) ? "80Mhz" : "BAD BW"); desc += sprintf(buff+desc, " %s %s\n", - (tbl->is_SGI) ? "SGI" : "NGI", + (rate->sgi) ? "SGI" : "NGI", (lq_sta->is_agg) ? "AGG on" : ""); } desc += sprintf(buff+desc, "last tx rate=0x%X\n", @@ -2799,6 +2811,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, int i, j; ssize_t ret; struct iwl_scale_tbl_info *tbl; + struct rs_rate *rate; struct iwl_lq_sta *lq_sta = file->private_data; buff = kmalloc(1024, GFP_KERNEL); @@ -2807,15 +2820,16 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, for (i = 0; i < LQ_SIZE; i++) { tbl = &(lq_sta->lq_info[i]); + rate = &tbl->rate; desc += sprintf(buff+desc, "%s type=%d SGI=%d BW=%s DUP=0\n" "rate=0x%X\n", lq_sta->active_tbl == i ? "*" : "x", - tbl->lq_type, - tbl->is_SGI, - is_ht20(tbl) ? "20Mhz" : - is_ht40(tbl) ? "40Mhz" : - is_ht80(tbl) ? "80Mhz" : "ERR", + rate->type, + rate->sgi, + is_ht20(rate) ? "20Mhz" : + is_ht40(rate) ? "40Mhz" : + is_ht80(rate) ? "80Mhz" : "ERR", tbl->current_rate); for (j = 0; j < IWL_RATE_COUNT; j++) { desc += sprintf(buff+desc, diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index ae983bce2172..8fa26aff1339 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -224,22 +224,45 @@ enum iwl_table_type { LQ_MAX, }; -#define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A)) -#define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO) -#define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2) -#define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO) -#define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2) -#define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl)) -#define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl)) -#define is_mimo(tbl) (is_mimo2(tbl)) -#define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl)) -#define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl)) -#define is_a_band(tbl) ((tbl) == LQ_LEGACY_A) -#define is_g_band(tbl) ((tbl) == LQ_LEGACY_G) - -#define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20) -#define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40) -#define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80) +struct rs_rate { + int index; + enum iwl_table_type type; + u8 ant; + u32 bw; + bool sgi; +}; + + +#define is_type_legacy(type) (((type) == LQ_LEGACY_G) || \ + ((type) == LQ_LEGACY_A)) +#define is_type_ht_siso(type) ((type) == LQ_HT_SISO) +#define is_type_ht_mimo2(type) ((type) == LQ_HT_MIMO2) +#define is_type_vht_siso(type) ((type) == LQ_VHT_SISO) +#define is_type_vht_mimo2(type) ((type) == LQ_VHT_MIMO2) +#define is_type_siso(type) (is_type_ht_siso(type) || is_type_vht_siso(type)) +#define is_type_mimo2(type) (is_type_ht_mimo2(type) || is_type_vht_mimo2(type)) +#define is_type_mimo(type) (is_type_mimo2(type)) +#define is_type_ht(type) (is_type_ht_siso(type) || is_type_ht_mimo2(type)) +#define is_type_vht(type) (is_type_vht_siso(type) || is_type_vht_mimo2(type)) +#define is_type_a_band(type) ((type) == LQ_LEGACY_A) +#define is_type_g_band(type) ((type) == LQ_LEGACY_G) + +#define is_legacy(rate) is_type_legacy((rate)->type) +#define is_ht_siso(rate) is_type_ht_siso((rate)->type) +#define is_ht_mimo2(rate) is_type_ht_mimo2((rate)->type) +#define is_vht_siso(rate) is_type_vht_siso((rate)->type) +#define is_vht_mimo2(rate) is_type_vht_mimo2((rate)->type) +#define is_siso(rate) is_type_siso((rate)->type) +#define is_mimo2(rate) is_type_mimo2((rate)->type) +#define is_mimo(rate) is_type_mimo((rate)->type) +#define is_ht(rate) is_type_ht((rate)->type) +#define is_vht(rate) is_type_vht((rate)->type) +#define is_a_band(rate) is_type_a_band((rate)->type) +#define is_g_band(rate) is_type_g_band((rate)->type) + +#define is_ht20(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_20) +#define is_ht40(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_40) +#define is_ht80(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_80) #define IWL_MAX_MCS_DISPLAY_SIZE 12 @@ -266,10 +289,7 @@ struct iwl_rate_scale_data { * one for "active", and one for "search". */ struct iwl_scale_tbl_info { - enum iwl_table_type lq_type; - u8 ant_type; - u8 is_SGI; /* 1 = short guard interval */ - u32 bw; /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */ + struct rs_rate rate; u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ u8 max_search; /* maximun number of tables we can search */ s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ -- cgit v1.2.3 From a8ff14f5964a6988fb883ec63de726de2a3bc19e Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 23 Nov 2013 01:30:44 +0200 Subject: iwlwifi: mvm: rs: remove unused parameter to rs_get_supported_rates No use of the ieee80211 header. Drop it. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 3af90620b3de..7beb548fd8dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -597,15 +597,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate, return 1; } -/** - * rs_get_supported_rates - get the available rates - * - * if management frame or broadcast frame only return - * basic available rates. - * - */ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, - struct ieee80211_hdr *hdr, struct rs_rate *rate) { if (is_legacy(rate)) @@ -704,7 +696,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, rate->sgi = false; } - rate_mask = rs_get_supported_rates(lq_sta, NULL, rate); + rate_mask = rs_get_supported_rates(lq_sta, rate); /* Mask with station rate restriction */ if (is_legacy(rate)) { @@ -1762,7 +1754,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, index = lq_sta->last_txrate_idx; /* rates available for this association, and for modulation mode */ - rate_mask = rs_get_supported_rates(lq_sta, hdr, rate); + rate_mask = rs_get_supported_rates(lq_sta, rate); /* mask with station rate restriction */ if (is_legacy(rate)) { -- cgit v1.2.3 From 809bccfa313e4703b64572986fce6321fb0c039f Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 28 Nov 2013 02:25:24 +0200 Subject: iwlwifi: mvm: rs: set dual_stream_ant_msk to ANT_AB always Drop code which was relevant when there were chips with 3 antennas. Setting to ANT_AB should be ok with all mvm supported chips. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 7beb548fd8dd..5c98d462b7c1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2386,15 +2386,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, /* These values will be overridden later */ lq_sta->lq.single_stream_ant_msk = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); - lq_sta->lq.dual_stream_ant_msk = - iwl_fw_valid_tx_ant(mvm->fw) & - ~first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); - if (!lq_sta->lq.dual_stream_ant_msk) { - lq_sta->lq.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) == 2) { - lq_sta->lq.dual_stream_ant_msk = - iwl_fw_valid_tx_ant(mvm->fw); - } + lq_sta->lq.dual_stream_ant_msk = ANT_AB; /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; @@ -2463,8 +2455,6 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, if (num_of_ant(rate.ant) == 1) lq_cmd->single_stream_ant_msk = rate.ant; - else if (num_of_ant(rate.ant) == 2) - lq_cmd->dual_stream_ant_msk = rate.ant; /* otherwise we don't modify the existing value */ index++; -- cgit v1.2.3 From da87d7d5e787d35a85ab821888e2f0e115dc18cc Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 28 Nov 2013 12:27:03 +0200 Subject: iwlwifi: mvm: rs: fix mapping from HT/VHT rates to legacy The table rs_ht_to_legacy is used to get the next legacy rate following the last HT or VHT rate in the LQ rates table. The mapping wasn't correct as well as didn't include entries for MCS8/9 which led to out of bounds access. This didn't trigger a crash but led to legacy rate entries using 1Mbps rate. In 5Ghz this probably caused the Tx to fail completely given that Tx attempt would have reached the legacy entries and 1Mbps isn't valid. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 5c98d462b7c1..ef7126ad5d80 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -56,19 +56,16 @@ static u8 rs_ht_to_legacy[] = { - [IWL_RATE_1M_INDEX] = IWL_RATE_6M_INDEX, - [IWL_RATE_2M_INDEX] = IWL_RATE_6M_INDEX, - [IWL_RATE_5M_INDEX] = IWL_RATE_6M_INDEX, - [IWL_RATE_11M_INDEX] = IWL_RATE_6M_INDEX, - [IWL_RATE_6M_INDEX] = IWL_RATE_6M_INDEX, - [IWL_RATE_9M_INDEX] = IWL_RATE_6M_INDEX, - [IWL_RATE_12M_INDEX] = IWL_RATE_9M_INDEX, - [IWL_RATE_18M_INDEX] = IWL_RATE_12M_INDEX, - [IWL_RATE_24M_INDEX] = IWL_RATE_18M_INDEX, - [IWL_RATE_36M_INDEX] = IWL_RATE_24M_INDEX, - [IWL_RATE_48M_INDEX] = IWL_RATE_36M_INDEX, - [IWL_RATE_54M_INDEX] = IWL_RATE_48M_INDEX, - [IWL_RATE_60M_INDEX] = IWL_RATE_54M_INDEX, + [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, + [IWL_RATE_MCS_1_INDEX] = IWL_RATE_9M_INDEX, + [IWL_RATE_MCS_2_INDEX] = IWL_RATE_12M_INDEX, + [IWL_RATE_MCS_3_INDEX] = IWL_RATE_18M_INDEX, + [IWL_RATE_MCS_4_INDEX] = IWL_RATE_24M_INDEX, + [IWL_RATE_MCS_5_INDEX] = IWL_RATE_36M_INDEX, + [IWL_RATE_MCS_6_INDEX] = IWL_RATE_48M_INDEX, + [IWL_RATE_MCS_7_INDEX] = IWL_RATE_54M_INDEX, + [IWL_RATE_MCS_8_INDEX] = IWL_RATE_54M_INDEX, + [IWL_RATE_MCS_9_INDEX] = IWL_RATE_54M_INDEX, }; static const u8 ant_toggle_lookup[] = { @@ -682,6 +679,8 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, * are always supported (spec demand) */ if (!is_legacy(rate) && (!ht_possible || !scale_index)) { switch_to_legacy = 1; + WARN_ON_ONCE(scale_index < IWL_RATE_MCS_0_INDEX && + scale_index > IWL_RATE_MCS_9_INDEX); scale_index = rs_ht_to_legacy[scale_index]; if (lq_sta->band == IEEE80211_BAND_5GHZ) rate->type = LQ_LEGACY_A; -- cgit v1.2.3 From a56db7d100dc9695dad262e0c7f2ec3d6f6f186b Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 28 Nov 2013 12:35:42 +0200 Subject: iwlwifi: mvm: rs: use the proper channel width define for legacy rate Use the 20Mhz channel width define instead of just the number zero for legacy rates. Note that the define has the same value so this is just a minor cleanup. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index ef7126ad5d80..1bfdde52db5c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -691,7 +691,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); - rate->bw = 0; + rate->bw = RATE_MCS_CHAN_WIDTH_20; rate->sgi = false; } -- cgit v1.2.3 From b3b06a32547fd2b0ba0f3f95ff37fbf94ad997dd Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sun, 24 Nov 2013 21:30:13 +0200 Subject: iwlwifi: mvm: rs: overhaul search cycle state machine Rewrite the search cycle state machine to use a more data oriented approach where the different Tx columns (configs) limitations and next columns to search are reprsented in tables which are easy to change. This overhaul also includes several major fixes: 1. Prevent going back to a specific Tx column in a search cycle if it was already explored. 2. Avoid switching to a Tx column that doesn't have any chance if it performs perfectly to beat the current throughput we're getting. These issues were degrading throughput as they were causing switching to "bad" Tx columns. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 921 ++++++++++++++++------------------ drivers/net/wireless/iwlwifi/mvm/rs.h | 64 ++- 2 files changed, 458 insertions(+), 527 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 1bfdde52db5c..1bb6581f3b25 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -123,6 +123,190 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ }; +enum rs_column_mode { + RS_INVALID = 0, + RS_LEGACY, + RS_SISO, + RS_MIMO2, +}; + +#define MAX_NEXT_COLUMNS 5 +#define MAX_COLUMN_CHECKS 3 + +typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl); + +struct rs_tx_column { + enum rs_column_mode mode; + u8 ant; + bool sgi; + enum rs_column next_columns[MAX_NEXT_COLUMNS]; + allow_column_func_t checks[MAX_COLUMN_CHECKS]; +}; + +static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl) +{ + if (!sta->ht_cap.ht_supported) + return false; + + if (sta->smps_mode == IEEE80211_SMPS_STATIC) + return false; + + if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2) + return false; + + if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) + return false; + + return true; +} + +static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl) +{ + if (!sta->ht_cap.ht_supported) + return false; + + return true; +} + +static bool rs_sgi_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl) +{ + struct rs_rate *rate = &tbl->rate; + struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + + if (is_ht20(rate) && (ht_cap->cap & + IEEE80211_HT_CAP_SGI_20)) + return true; + if (is_ht40(rate) && (ht_cap->cap & + IEEE80211_HT_CAP_SGI_40)) + return true; + if (is_ht80(rate) && (vht_cap->cap & + IEEE80211_VHT_CAP_SHORT_GI_80)) + return true; + + return false; +} + +static const struct rs_tx_column rs_tx_columns[] = { + [RS_COLUMN_LEGACY_ANT_A] = { + .mode = RS_LEGACY, + .ant = ANT_A, + .next_columns = { + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_MIMO2, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + }, + [RS_COLUMN_LEGACY_ANT_B] = { + .mode = RS_LEGACY, + .ant = ANT_B, + .next_columns = { + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_MIMO2, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + }, + [RS_COLUMN_SISO_ANT_A] = { + .mode = RS_SISO, + .ant = ANT_A, + .next_columns = { + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_MIMO2, + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + }, + }, + [RS_COLUMN_SISO_ANT_B] = { + .mode = RS_SISO, + .ant = ANT_B, + .next_columns = { + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_MIMO2, + RS_COLUMN_SISO_ANT_B_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + }, + }, + [RS_COLUMN_SISO_ANT_A_SGI] = { + .mode = RS_SISO, + .ant = ANT_A, + .sgi = true, + .next_columns = { + RS_COLUMN_SISO_ANT_B_SGI, + RS_COLUMN_MIMO2_SGI, + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + rs_sgi_allow, + }, + }, + [RS_COLUMN_SISO_ANT_B_SGI] = { + .mode = RS_SISO, + .ant = ANT_B, + .sgi = true, + .next_columns = { + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_MIMO2_SGI, + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + rs_sgi_allow, + }, + }, + [RS_COLUMN_MIMO2] = { + .mode = RS_MIMO2, + .ant = ANT_AB, + .next_columns = { + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_mimo_allow, + }, + }, + [RS_COLUMN_MIMO2_SGI] = { + .mode = RS_MIMO2, + .ant = ANT_AB, + .sgi = true, + .next_columns = { + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_MIMO2, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_mimo_allow, + rs_sgi_allow, + }, + }, +}; + static inline u8 rs_extract_rate(u32 rate_n_flags) { /* also works for HT because bits 7:6 are zero there */ @@ -839,6 +1023,9 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter++; if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { lq_sta->missed_rate_counter = 0; + IWL_DEBUG_RATE(mvm, + "Too many rates mismatch. Send sync LQ. rs_state %d\n", + lq_sta->rs_state); iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } /* Regardless, ignore this status info for outdated rate */ @@ -888,7 +1075,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, info->status.ampdu_ack_len); /* Update success/fail counts if not searching for new mode */ - if (lq_sta->stay_in_tbl) { + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { lq_sta->total_success += info->status.ampdu_ack_len; lq_sta->total_failed += (info->status.ampdu_len - info->status.ampdu_ack_len); @@ -915,14 +1102,20 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, tmp_tbl = curr_tbl; else if (rs_rate_match(&rate, &other_tbl->rate)) tmp_tbl = other_tbl; - else + else { + IWL_DEBUG_RATE(mvm, + "Tx packet rate doesn't match ACTIVE or SEARCH tables\n"); + rs_dump_rate(mvm, &rate, "Tx PACKET:"); + rs_dump_rate(mvm, &curr_tbl->rate, "CURRENT:"); + rs_dump_rate(mvm, &other_tbl->rate, "OTHER:"); continue; + } rs_collect_tx_data(tmp_tbl, rate.index, 1, i < retries ? 0 : legacy_success); } /* Update success/fail counts if not searching for new mode */ - if (lq_sta->stay_in_tbl) { + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { lq_sta->total_success += legacy_success; lq_sta->total_failed += retries + (1 - legacy_success); } @@ -946,8 +1139,8 @@ done: static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, struct iwl_lq_sta *lq_sta) { - IWL_DEBUG_RATE(mvm, "we are staying in the same table\n"); - lq_sta->stay_in_tbl = 1; /* only place this gets set */ + IWL_DEBUG_RATE(mvm, "Moving to RS_STATE_STAY_IN_COLUMN\n"); + lq_sta->rs_state = RS_STATE_STAY_IN_COLUMN; if (is_legacy) { lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT; lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT; @@ -961,38 +1154,31 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, lq_sta->total_failed = 0; lq_sta->total_success = 0; lq_sta->flush_timer = jiffies; - lq_sta->action_counter = 0; + lq_sta->visited_columns = 0; } -/* - * Find correct throughput table for given mode of modulation - */ -static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl) +static s32 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, + const struct rs_tx_column *column, + u32 bw) { /* Used to choose among HT tables */ s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; - struct rs_rate *rate = &tbl->rate; - /* Check for invalid LQ type */ - if (WARN_ON_ONCE(!is_legacy(rate) && !is_ht(rate) && - !(is_vht(rate)))) { - tbl->expected_tpt = expected_tpt_legacy; - return; - } + if (WARN_ON_ONCE(column->mode != RS_LEGACY && + column->mode != RS_SISO && + column->mode != RS_MIMO2)) + return expected_tpt_legacy; /* Legacy rates have only one table */ - if (is_legacy(rate)) { - tbl->expected_tpt = expected_tpt_legacy; - return; - } + if (column->mode == RS_LEGACY) + return expected_tpt_legacy; ht_tbl_pointer = expected_tpt_mimo2_20MHz; /* Choose among many HT tables depending on number of streams * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation * status */ - if (is_siso(rate)) { - switch (rate->bw) { + if (column->mode == RS_SISO) { + switch (bw) { case RATE_MCS_CHAN_WIDTH_20: ht_tbl_pointer = expected_tpt_siso_20MHz; break; @@ -1005,8 +1191,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, default: WARN_ON_ONCE(1); } - } else if (is_mimo2(rate)) { - switch (rate->bw) { + } else if (column->mode == RS_MIMO2) { + switch (bw) { case RATE_MCS_CHAN_WIDTH_20: ht_tbl_pointer = expected_tpt_mimo2_20MHz; break; @@ -1023,14 +1209,23 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, WARN_ON_ONCE(1); } - if (!rate->sgi && !lq_sta->is_agg) /* Normal */ - tbl->expected_tpt = ht_tbl_pointer[0]; - else if (rate->sgi && !lq_sta->is_agg) /* SGI */ - tbl->expected_tpt = ht_tbl_pointer[1]; - else if (!rate->sgi && lq_sta->is_agg) /* AGG */ - tbl->expected_tpt = ht_tbl_pointer[2]; + if (!column->sgi && !lq_sta->is_agg) /* Normal */ + return ht_tbl_pointer[0]; + else if (column->sgi && !lq_sta->is_agg) /* SGI */ + return ht_tbl_pointer[1]; + else if (!column->sgi && lq_sta->is_agg) /* AGG */ + return ht_tbl_pointer[2]; else /* AGG+SGI */ - tbl->expected_tpt = ht_tbl_pointer[3]; + return ht_tbl_pointer[3]; +} + +static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl) +{ + struct rs_rate *rate = &tbl->rate; + const struct rs_tx_column *column = &rs_tx_columns[tbl->column]; + + tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw); } /* @@ -1135,19 +1330,6 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, return new_rate; } -/* Move to the next action and wrap around to the first action in case - * we're at the last action. Assumes actions start at 0. - */ -static inline void rs_move_next_action(struct iwl_scale_tbl_info *tbl, - u8 last_action) -{ - BUILD_BUG_ON(IWL_LEGACY_FIRST_ACTION != 0); - BUILD_BUG_ON(IWL_SISO_FIRST_ACTION != 0); - BUILD_BUG_ON(IWL_MIMO2_FIRST_ACTION != 0); - - tbl->action = (tbl->action + 1) % (last_action + 1); -} - static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) { if (sta->bandwidth >= IEEE80211_STA_RX_BW_80) @@ -1158,409 +1340,6 @@ static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) return RATE_MCS_CHAN_WIDTH_20; } -static bool rs_sgi_allowed(struct rs_rate *rate, - struct ieee80211_sta *sta) -{ - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; - - if (is_ht20(rate) && (ht_cap->cap & - IEEE80211_HT_CAP_SGI_20)) - return true; - if (is_ht40(rate) && (ht_cap->cap & - IEEE80211_HT_CAP_SGI_40)) - return true; - if (is_ht80(rate) && (vht_cap->cap & - IEEE80211_VHT_CAP_SHORT_GI_80)) - return true; - - return false; -} - -/* - * Set up search table for MIMO2 - */ -static int rs_switch_to_mimo2(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_sta, - struct ieee80211_sta *sta, - struct iwl_scale_tbl_info *tbl, int index) -{ - u16 rate_mask; - s32 rate_idx; - - if (!sta->ht_cap.ht_supported) - return -1; - - if (sta->smps_mode == IEEE80211_SMPS_STATIC) - return -1; - - /* Need both Tx chains/antennas to support MIMO */ - if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2) - return -1; - - IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); - - tbl->rate.type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; - tbl->action = 0; - tbl->max_search = IWL_MAX_SEARCH; - rate_mask = lq_sta->active_mimo2_rate; - - tbl->rate.bw = rs_bw_from_sta_bw(sta); - rs_set_expected_tpt_table(lq_sta, tbl); - - rate_idx = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); - - IWL_DEBUG_RATE(mvm, "LQ: MIMO2 best rate %d mask %X\n", - rate_idx, rate_mask); - if ((rate_idx == IWL_RATE_INVALID) || !((1 << rate_idx) & rate_mask)) { - IWL_DEBUG_RATE(mvm, "Can't switch with index %d rate mask %x\n", - rate_idx, rate_mask); - return -1; - } - - tbl->rate.index = rate_idx; - tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate); - - IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", - tbl->current_rate); - return 0; -} - -/* - * Set up search table for SISO - */ -static int rs_switch_to_siso(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_sta, - struct ieee80211_sta *sta, - struct iwl_scale_tbl_info *tbl, int index) -{ - u16 rate_mask; - s32 rate_idx; - - if (!sta->ht_cap.ht_supported) - return -1; - - IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); - - tbl->rate.type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; - tbl->action = 0; - tbl->max_search = IWL_MAX_SEARCH; - rate_mask = lq_sta->active_siso_rate; - - tbl->rate.bw = rs_bw_from_sta_bw(sta); - rs_set_expected_tpt_table(lq_sta, tbl); - rate_idx = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); - - IWL_DEBUG_RATE(mvm, "LQ: get best rate %d mask %X\n", - rate_idx, rate_mask); - if ((rate_idx == IWL_RATE_INVALID) || !((1 << rate_idx) & rate_mask)) { - IWL_DEBUG_RATE(mvm, - "can not switch with index %d rate mask %x\n", - rate_idx, rate_mask); - return -1; - } - - tbl->rate.index = rate_idx; - tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate); - - IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", - tbl->current_rate); - return 0; -} - -/* - * Try to switch to new modulation mode from legacy - */ -static int rs_move_legacy_other(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_sta, - struct ieee80211_sta *sta, - int index) -{ - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct rs_rate *rate = &search_tbl->rate; - struct iwl_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action; - u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); - u8 tx_chains_num = num_of_ant(valid_tx_ant); - int ret; - u8 update_search_tbl_counter = 0; - - start_action = tbl->action; - while (1) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_LEGACY_SWITCH_ANTENNA: - IWL_DEBUG_RATE(mvm, "LQ: Legacy toggle Antenna\n"); - - if (tx_chains_num <= 1) - break; - - /* Don't change antenna if success has been great */ - if (window->success_ratio >= IWL_RS_GOOD_RATIO) - break; - - /* Set up search table to try other antenna */ - memcpy(search_tbl, tbl, sz); - - if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, - &search_tbl->rate)) { - update_search_tbl_counter = 1; - rs_set_expected_tpt_table(lq_sta, search_tbl); - goto out; - } - break; - case IWL_LEGACY_SWITCH_SISO: - IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to SISO\n"); - - /* Set up search table to try SISO */ - memcpy(search_tbl, tbl, sz); - rate->sgi = false; - ret = rs_switch_to_siso(mvm, lq_sta, sta, - search_tbl, index); - if (!ret) { - lq_sta->action_counter = 0; - goto out; - } - - break; - case IWL_LEGACY_SWITCH_MIMO2: - IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO2\n"); - - /* Set up search table to try MIMO */ - memcpy(search_tbl, tbl, sz); - rate->sgi = false; - rate->ant = ANT_AB; - - if (!rs_is_valid_ant(valid_tx_ant, - rate->ant)) - break; - - ret = rs_switch_to_mimo2(mvm, lq_sta, sta, - search_tbl, index); - if (!ret) { - lq_sta->action_counter = 0; - goto out; - } - break; - default: - WARN_ON_ONCE(1); - } - rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION); - - if (tbl->action == start_action) - break; - } - rate->type = LQ_NONE; - return 0; - -out: - lq_sta->search_better_tbl = 1; - rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION); - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - return 0; -} - -/* - * Try to switch to new modulation mode from SISO - */ -static int rs_move_siso_to_other(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_sta, - struct ieee80211_sta *sta, int index) -{ - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct rs_rate *rate = &search_tbl->rate; - struct iwl_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action; - u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); - u8 tx_chains_num = num_of_ant(valid_tx_ant); - u8 update_search_tbl_counter = 0; - int ret; - - if (tbl->action == IWL_SISO_SWITCH_MIMO2 && - !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) - tbl->action = IWL_SISO_SWITCH_ANTENNA; - - start_action = tbl->action; - while (1) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_SISO_SWITCH_ANTENNA: - IWL_DEBUG_RATE(mvm, "LQ: SISO toggle Antenna\n"); - if (tx_chains_num <= 1) - break; - - if (window->success_ratio >= IWL_RS_GOOD_RATIO && - BT_MBOX_MSG(&mvm->last_bt_notif, 3, - TRAFFIC_LOAD) == 0) - break; - - memcpy(search_tbl, tbl, sz); - if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, - rate)) { - update_search_tbl_counter = 1; - goto out; - } - break; - case IWL_SISO_SWITCH_MIMO2: - IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n"); - memcpy(search_tbl, tbl, sz); - rate->sgi = false; - rate->ant = ANT_AB; - - if (!rs_is_valid_ant(valid_tx_ant, - rate->ant)) - break; - - ret = rs_switch_to_mimo2(mvm, lq_sta, sta, - search_tbl, index); - if (!ret) - goto out; - break; - case IWL_SISO_SWITCH_GI: - if (!rs_sgi_allowed(rate, sta)) - break; - - IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); - - memcpy(search_tbl, tbl, sz); - rate->sgi = !tbl->rate.sgi; - rs_set_expected_tpt_table(lq_sta, search_tbl); - if (tbl->rate.sgi) { - s32 tpt = lq_sta->last_tpt / 100; - if (tpt >= search_tbl->expected_tpt[index]) - break; - } - rate->index = index; - search_tbl->current_rate = - ucode_rate_from_rs_rate(mvm, rate); - update_search_tbl_counter = 1; - goto out; - default: - WARN_ON_ONCE(1); - } - rs_move_next_action(tbl, IWL_SISO_LAST_ACTION); - - if (tbl->action == start_action) - break; - } - rate->type = LQ_NONE; - return 0; - - out: - lq_sta->search_better_tbl = 1; - rs_move_next_action(tbl, IWL_SISO_LAST_ACTION); - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - - return 0; -} - -/* - * Try to switch to new modulation mode from MIMO2 - */ -static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_sta, - struct ieee80211_sta *sta, int index) -{ - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct rs_rate *rate = &search_tbl->rate; - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action; - u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); - u8 update_search_tbl_counter = 0; - int ret; - - if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) { - IWL_DEBUG_RATE(mvm, "BT COEX force switch to SISO A\n"); - tbl->action = IWL_MIMO2_SWITCH_SISO_A; - } - - start_action = tbl->action; - while (1) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_MIMO2_SWITCH_SISO_A: - case IWL_MIMO2_SWITCH_SISO_B: - IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); - - /* Set up new search table for SISO */ - memcpy(search_tbl, tbl, sz); - - if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) - rate->ant = ANT_A; - else /* tbl->action == IWL_MIMO2_SWITCH_SISO_B */ - rate->ant = ANT_B; - - if (!rs_is_valid_ant(valid_tx_ant, - rate->ant)) - break; - - ret = rs_switch_to_siso(mvm, lq_sta, sta, - search_tbl, index); - if (!ret) - goto out; - - break; - - case IWL_MIMO2_SWITCH_GI: - if (!rs_sgi_allowed(rate, sta)) - break; - - IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); - - /* Set up new search table for MIMO2 */ - memcpy(search_tbl, tbl, sz); - rate->sgi = !tbl->rate.sgi; - rs_set_expected_tpt_table(lq_sta, search_tbl); - /* - * If active table already uses the fastest possible - * modulation (dual stream with short guard interval), - * and it's working well, there's no need to look - * for a better type of modulation! - */ - if (tbl->rate.sgi) { - s32 tpt = lq_sta->last_tpt / 100; - if (tpt >= search_tbl->expected_tpt[index]) - break; - } - rate->index = index; - search_tbl->current_rate = - ucode_rate_from_rs_rate(mvm, rate); - update_search_tbl_counter = 1; - goto out; - default: - WARN_ON_ONCE(1); - } - rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION); - - if (tbl->action == start_action) - break; - } - rate->type = LQ_NONE; - return 0; - out: - lq_sta->search_better_tbl = 1; - rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION); - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - - return 0; -} - /* * Check whether we should continue using same modulation mode, or * begin search for a new mode, based on: @@ -1582,7 +1361,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) tbl = &(lq_sta->lq_info[active_tbl]); /* If we've been disallowing search, see if we should now allow it */ - if (lq_sta->stay_in_tbl) { + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { /* Elapsed time using current modulation mode */ if (lq_sta->flush_timer) flush_interval_passed = @@ -1610,10 +1389,14 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) flush_interval_passed); /* Allow search for new mode */ - lq_sta->stay_in_tbl = 0; /* only place reset */ + lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_STARTED; + IWL_DEBUG_RATE(mvm, + "Moving to RS_STATE_SEARCH_CYCLE_STARTED\n"); lq_sta->total_failed = 0; lq_sta->total_success = 0; lq_sta->flush_timer = 0; + /* mark the current column as visited */ + lq_sta->visited_columns = BIT(tbl->column); /* * Else if we've used this modulation mode enough repetitions * (regardless of elapsed time or success/failure), reset @@ -1637,7 +1420,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) /* If transitioning to allow "search", reset all history * bitmaps and stats in active table (this will become the new * "search" table). */ - if (!lq_sta->stay_in_tbl) { + if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { + IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&(tbl->win[i])); } @@ -1675,6 +1459,162 @@ static u8 rs_get_tid(struct iwl_lq_sta *lq_data, return tid; } +static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, + struct iwl_lq_sta *lq_sta, + struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl) +{ + int i, j, n; + enum rs_column next_col_id; + const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; + const struct rs_tx_column *next_col; + allow_column_func_t allow_func; + u8 valid_ants = iwl_fw_valid_tx_ant(mvm->fw); + s32 *expected_tpt_tbl; + s32 tpt, max_expected_tpt; + + for (i = 0; i < MAX_NEXT_COLUMNS; i++) { + next_col_id = curr_col->next_columns[i]; + + if (next_col_id == RS_COLUMN_INVALID) + continue; + + if (lq_sta->visited_columns & BIT(next_col_id)) { + IWL_DEBUG_RATE(mvm, "Skip already visited column %d\n", + next_col_id); + continue; + } + + next_col = &rs_tx_columns[next_col_id]; + + if (!rs_is_valid_ant(valid_ants, next_col->ant)) { + IWL_DEBUG_RATE(mvm, + "Skip column %d as ANT config isn't supported by chip. valid_ants 0x%x column ant 0x%x\n", + next_col_id, valid_ants, next_col->ant); + continue; + } + + for (j = 0; j < MAX_COLUMN_CHECKS; j++) { + allow_func = next_col->checks[j]; + if (allow_func && !allow_func(mvm, sta, tbl)) + break; + } + + if (j != MAX_COLUMN_CHECKS) { + IWL_DEBUG_RATE(mvm, + "Skip column %d: not allowed (check %d failed)\n", + next_col_id, j); + + continue; + } + + tpt = lq_sta->last_tpt / 100; + expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col, + tbl->rate.bw); + if (WARN_ON_ONCE(!expected_tpt_tbl)) + continue; + + max_expected_tpt = 0; + for (n = 0; n < IWL_RATE_COUNT; n++) + if (expected_tpt_tbl[n] > max_expected_tpt) + max_expected_tpt = expected_tpt_tbl[n]; + + if (tpt >= max_expected_tpt) { + IWL_DEBUG_RATE(mvm, + "Skip column %d: can't beat current TPT. Max expected %d current %d\n", + next_col_id, max_expected_tpt, tpt); + continue; + } + + break; + } + + if (i == MAX_NEXT_COLUMNS) + return RS_COLUMN_INVALID; + + IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); + + return next_col_id; +} + +static int rs_switch_to_column(struct iwl_mvm *mvm, + struct iwl_lq_sta *lq_sta, + struct ieee80211_sta *sta, + enum rs_column col_id) +{ + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct rs_rate *rate = &search_tbl->rate; + const struct rs_tx_column *column = &rs_tx_columns[col_id]; + const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); + u16 rate_mask = 0; + u32 rate_idx = 0; + + memcpy(search_tbl, tbl, sz); + + rate->sgi = column->sgi; + rate->ant = column->ant; + + if (column->mode == RS_LEGACY) { + if (lq_sta->band == IEEE80211_BAND_5GHZ) + rate->type = LQ_LEGACY_A; + else + rate->type = LQ_LEGACY_G; + + rate_mask = lq_sta->active_legacy_rate; + } else if (column->mode == RS_SISO) { + rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; + rate_mask = lq_sta->active_siso_rate; + } else if (column->mode == RS_MIMO2) { + rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; + rate_mask = lq_sta->active_mimo2_rate; + } else { + WARN_ON_ONCE("Bad column mode"); + } + + rate->bw = rs_bw_from_sta_bw(sta); + search_tbl->column = col_id; + rs_set_expected_tpt_table(lq_sta, search_tbl); + + /* Get the best matching rate if we're changing modes. e.g. + * SISO->MIMO, LEGACY->SISO, MIMO->SISO + */ + if (curr_column->mode != column->mode) { + rate_idx = rs_get_best_rate(mvm, lq_sta, search_tbl, + rate_mask, rate->index); + + if ((rate_idx == IWL_RATE_INVALID) || + !(BIT(rate_idx) & rate_mask)) { + IWL_DEBUG_RATE(mvm, + "can not switch with index %d" + " rate mask %x\n", + rate_idx, rate_mask); + + goto err; + } + + rate->index = rate_idx; + } + + /* TODO: remove current_rate and keep using rs_rate all the way until + * we need to fill in the rs_table in the LQ command + */ + search_tbl->current_rate = ucode_rate_from_rs_rate(mvm, rate); + IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n", + col_id, rate->index); + + lq_sta->visited_columns |= BIT(col_id); + return 0; + +err: + rate->type = LQ_NONE; + return -1; +} + + /* * Do rate scaling and search for new modulation mode. */ @@ -1772,7 +1712,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if (!rate_scale_index_msk) rate_scale_index_msk = rate_mask; - if (!((1 << index) & rate_scale_index_msk)) { + if (!((BIT(index) & rate_scale_index_msk))) { IWL_ERR(mvm, "Current Rate is not valid\n"); if (lq_sta->search_better_tbl) { /* revert to active table if search table is not valid*/ @@ -1852,9 +1792,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, window->average_tpt, lq_sta->last_tpt); - if (!is_legacy(rate)) - lq_sta->enable_counter = 1; - /* Swap tables; "search" becomes "active" */ lq_sta->active_tbl = active_tbl; current_tpt = window->average_tpt; @@ -2049,24 +1986,29 @@ lq_update: * 3) Allowing a new search */ if (!update_lq && !done_search && - !lq_sta->stay_in_tbl && window->counter) { + lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED + && window->counter) { + enum rs_column next_column; + /* Save current throughput to compare with "search" throughput*/ lq_sta->last_tpt = current_tpt; IWL_DEBUG_RATE(mvm, - "Start Search: update_lq %d done_search %d stay_in_tbl %d win->counter %d\n", - update_lq, done_search, lq_sta->stay_in_tbl, + "Start Search: update_lq %d done_search %d rs_state %d win->counter %d\n", + update_lq, done_search, lq_sta->rs_state, window->counter); - /* Select a new "search" modulation mode to try. - * If one is found, set up the new "search" table. */ - if (is_legacy(&tbl->rate)) - rs_move_legacy_other(mvm, lq_sta, sta, index); - else if (is_siso(&tbl->rate)) - rs_move_siso_to_other(mvm, lq_sta, sta, index); - else if (is_mimo2(&tbl->rate)) - rs_move_mimo2_to_other(mvm, lq_sta, sta, index); - else - WARN_ON_ONCE(1); + + next_column = rs_get_next_column(mvm, lq_sta, sta, tbl); + if (next_column != RS_COLUMN_INVALID) { + int ret = rs_switch_to_column(mvm, lq_sta, sta, + next_column); + if (!ret) + lq_sta->search_better_tbl = 1; + } else { + IWL_DEBUG_RATE(mvm, + "No more columns to explore in search cycle. Go to RS_STATE_SEARCH_CYCLE_ENDED\n"); + lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_ENDED; + } /* If new "search" mode was selected, set up in uCode table */ if (lq_sta->search_better_tbl) { @@ -2078,12 +2020,8 @@ lq_update: /* Use new "search" start rate */ index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - IWL_DEBUG_RATE(mvm, - "Switch to SEARCH TABLE: " - "mcs %X (%s: %d)\n", - tbl->current_rate, - rs_pretty_lq_type(tbl->rate.type), - index); + rs_dump_rate(mvm, &tbl->rate, + "Switch to SEARCH TABLE:"); rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } else { @@ -2091,24 +2029,20 @@ lq_update: } } - if (done_search && !lq_sta->stay_in_tbl) { + if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) { /* If the "active" (non-search) mode was legacy, * and we've tried switching antennas, * but we haven't been able to try HT modes (not available), * stay with best antenna legacy modulation for a while * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); - if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported && - lq_sta->action_counter > tbl1->max_search) { + if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) { IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); rs_set_stay_in_table(mvm, 1, lq_sta); - } - + } else { /* If we're in an HT mode, and all 3 mode switch actions * have been tried and compared, stay in this best modulation * mode for a while before next round of mode comparisons. */ - if (lq_sta->enable_counter && - (lq_sta->action_counter >= tbl1->max_search)) { if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && (tid != IWL_MAX_TID_COUNT)) { @@ -2176,19 +2110,24 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, if ((i < 0) || (i >= IWL_RATE_COUNT)) i = 0; - ucode_rate = iwl_rates[i].plcp; + rate->index = i; rate->ant = first_antenna(valid_tx_ant); - ucode_rate |= rate->ant << RATE_MCS_ANT_POS; - - if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE) - ucode_rate |= RATE_MCS_CCK_MSK; - - rs_rate_from_ucode_rate(ucode_rate, band, rate); - if (!rs_is_valid_ant(valid_tx_ant, rate->ant)) - rs_toggle_antenna(valid_tx_ant, &ucode_rate, rate); + rate->sgi = false; + rate->bw = RATE_MCS_CHAN_WIDTH_20; + if (band == IEEE80211_BAND_5GHZ) + rate->type = LQ_LEGACY_A; + else + rate->type = LQ_LEGACY_G; ucode_rate = ucode_rate_from_rs_rate(mvm, rate); tbl->current_rate = ucode_rate; + + WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B); + if (rate->ant == ANT_A) + tbl->column = RS_COLUMN_LEGACY_ANT_A; + else + tbl->column = RS_COLUMN_LEGACY_ANT_B; + rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, NULL, lq_sta, ucode_rate); /* TODO restore station should remember the lq cmd */ diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 8fa26aff1339..b32960796384 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -157,37 +157,6 @@ enum { #define IWL_RATE_INCREASE_TH 6400 /* 50% */ #define RS_SR_FORCE_DECREASE 1920 /* 15% */ -/* possible actions when in legacy mode */ -enum { - IWL_LEGACY_SWITCH_ANTENNA, - IWL_LEGACY_SWITCH_SISO, - IWL_LEGACY_SWITCH_MIMO2, - IWL_LEGACY_FIRST_ACTION = IWL_LEGACY_SWITCH_ANTENNA, - IWL_LEGACY_LAST_ACTION = IWL_LEGACY_SWITCH_MIMO2, -}; - -/* possible actions when in siso mode */ -enum { - IWL_SISO_SWITCH_ANTENNA, - IWL_SISO_SWITCH_MIMO2, - IWL_SISO_SWITCH_GI, - IWL_SISO_FIRST_ACTION = IWL_SISO_SWITCH_ANTENNA, - IWL_SISO_LAST_ACTION = IWL_SISO_SWITCH_GI, -}; - -/* possible actions when in mimo mode */ -enum { - IWL_MIMO2_SWITCH_SISO_A, - IWL_MIMO2_SWITCH_SISO_B, - IWL_MIMO2_SWITCH_GI, - IWL_MIMO2_FIRST_ACTION = IWL_MIMO2_SWITCH_SISO_A, - IWL_MIMO2_LAST_ACTION = IWL_MIMO2_SWITCH_GI, -}; - -#define IWL_MAX_SEARCH IWL_MIMO2_LAST_ACTION - -#define IWL_ACTION_LIMIT 3 /* # possible actions */ - #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) #define LINK_QUAL_AGG_TIME_LIMIT_MIN (100) @@ -282,6 +251,23 @@ struct iwl_rate_scale_data { s32 average_tpt; /* success ratio * expected throughput */ }; +/* Possible Tx columns + * Tx Column = a combo of legacy/siso/mimo x antenna x SGI + */ +enum rs_column { + RS_COLUMN_LEGACY_ANT_A = 0, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_SISO_ANT_B_SGI, + RS_COLUMN_MIMO2, + RS_COLUMN_MIMO2_SGI, + + RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, +}; + /** * struct iwl_scale_tbl_info -- tx params and success history for all rates * @@ -290,13 +276,18 @@ struct iwl_rate_scale_data { */ struct iwl_scale_tbl_info { struct rs_rate rate; - u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ - u8 max_search; /* maximun number of tables we can search */ + enum rs_column column; s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ u32 current_rate; /* rate_n_flags, uCode API format */ struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ }; +enum { + RS_STATE_SEARCH_CYCLE_STARTED, + RS_STATE_SEARCH_CYCLE_ENDED, + RS_STATE_STAY_IN_COLUMN, +}; + /** * struct iwl_lq_sta -- driver's rate scaling private structure * @@ -304,8 +295,7 @@ struct iwl_scale_tbl_info { */ struct iwl_lq_sta { u8 active_tbl; /* index of active table, range 0-1 */ - u8 enable_counter; /* indicates HT mode */ - u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ + u8 rs_state; /* RS_STATE_* */ u8 search_better_tbl; /* 1: currently trying alternate mode */ s32 last_tpt; @@ -318,7 +308,9 @@ struct iwl_lq_sta { u32 total_success; /* total successful frames, any/all rates */ u64 flush_timer; /* time staying in mode before new search */ - u8 action_counter; /* # mode-switch actions tried */ + u32 visited_columns; /* Bitmask marking which Tx columns were + * explored during a search cycle + */ bool is_vht; enum ieee80211_band band; -- cgit v1.2.3 From b9c509cc994f11799174a8a94ac5c4c09cf773a6 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 28 Nov 2013 14:58:20 +0200 Subject: iwlwifi: mvm: BT Coex - enable Sync to SCO Sync to SCO is a feature that allows to synchronise the wifi activity with the predictable BT activity in SCO profile. This allows to reduce the collisions and improve overall quality. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 3 ++- drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 468a4ba49a06..d126245c48de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -396,7 +396,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) BT_VALID_ANT_ISOLATION | BT_VALID_ANT_ISOLATION_THRS | BT_VALID_TXTX_DELTA_FREQ_THRS | - BT_VALID_TXRX_MAX_FREQ_0); + BT_VALID_TXRX_MAX_FREQ_0 | + BT_VALID_SYNC_TO_SCO); if (mvm->cfg->bt_shared_single_ant) memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h index 4ea5e24ca92d..af500996bbf1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h @@ -127,6 +127,7 @@ enum iwl_bt_coex_valid_bit_msk { BT_VALID_ANT_ISOLATION_THRS = BIT(15), BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), + BT_VALID_SYNC_TO_SCO = BIT(18), }; /** -- cgit v1.2.3 From 9d10849e4ea8bf9d8da80afa73918a9fe45c09ef Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 3 Dec 2013 11:50:30 +0200 Subject: iwlwifi: mvm: rs: fix compilation without CONFIG_MAC80211_DEBUGFS This fixes compilation issues with CONFIG_MAC80211_DEBUGFS not enabled. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 128 +++++++++++++++++----------------- 1 file changed, 63 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 1bb6581f3b25..bf6e29f5b4d0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -355,8 +355,6 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); -static const char *rs_pretty_lq_type(enum iwl_table_type type); -static const char *rs_pretty_ant(u8 ant); #ifdef CONFIG_MAC80211_DEBUGFS static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, @@ -446,6 +444,43 @@ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { #define MCS_INDEX_PER_STREAM (8) +static const char *rs_pretty_ant(u8 ant) +{ + static const char * const ant_name[] = { + [ANT_NONE] = "None", + [ANT_A] = "A", + [ANT_B] = "B", + [ANT_AB] = "AB", + [ANT_C] = "C", + [ANT_AC] = "AC", + [ANT_BC] = "BC", + [ANT_ABC] = "ABC", + }; + + if (ant > ANT_ABC) + return "UNKNOWN"; + + return ant_name[ant]; +} + +static const char *rs_pretty_lq_type(enum iwl_table_type type) +{ + static const char * const lq_types[] = { + [LQ_NONE] = "NONE", + [LQ_LEGACY_A] = "LEGACY_A", + [LQ_LEGACY_G] = "LEGACY_G", + [LQ_HT_SISO] = "HT SISO", + [LQ_HT_MIMO2] = "HT MIMO", + [LQ_VHT_SISO] = "VHT SISO", + [LQ_VHT_MIMO2] = "VHT MIMO", + }; + + if (type < LQ_NONE || type >= LQ_MAX) + return "UNKNOWN"; + + return lq_types[type]; +} + static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, const char *prefix) { @@ -2524,69 +2559,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, } } -static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, - const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_mvm *mvm; - char buf[64]; - size_t buf_size; - u32 parsed_rate; - - - mvm = lq_sta->drv; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - - if (sscanf(buf, "%x", &parsed_rate) == 1) - lq_sta->dbg_fixed_rate = parsed_rate; - else - lq_sta->dbg_fixed_rate = 0; - - rs_program_fix_rate(mvm, lq_sta); - - return count; -} - -static const char *rs_pretty_lq_type(enum iwl_table_type type) -{ - static const char * const lq_types[] = { - [LQ_NONE] = "NONE", - [LQ_LEGACY_A] = "LEGACY_A", - [LQ_LEGACY_G] = "LEGACY_G", - [LQ_HT_SISO] = "HT SISO", - [LQ_HT_MIMO2] = "HT MIMO", - [LQ_VHT_SISO] = "VHT SISO", - [LQ_VHT_MIMO2] = "VHT MIMO", - }; - - if (type < LQ_NONE || type >= LQ_MAX) - return "UNKNOWN"; - - return lq_types[type]; -} - -static const char *rs_pretty_ant(u8 ant) -{ - static const char * const ant_name[] = { - [ANT_NONE] = "None", - [ANT_A] = "A", - [ANT_B] = "B", - [ANT_AB] = "AB", - [ANT_C] = "C", - [ANT_AC] = "AC", - [ANT_BC] = "BC", - [ANT_ABC] = "ABC", - }; - - if (ant > ANT_ABC) - return "UNKNOWN"; - - return ant_name[ant]; -} - static int rs_pretty_print_rate(char *buf, const u32 rate) { @@ -2640,6 +2612,32 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); } +static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct iwl_lq_sta *lq_sta = file->private_data; + struct iwl_mvm *mvm; + char buf[64]; + size_t buf_size; + u32 parsed_rate; + + + mvm = lq_sta->drv; + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + if (sscanf(buf, "%x", &parsed_rate) == 1) + lq_sta->dbg_fixed_rate = parsed_rate; + else + lq_sta->dbg_fixed_rate = 0; + + rs_program_fix_rate(mvm, lq_sta); + + return count; +} + static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { -- cgit v1.2.3 From 710e4d08f2ab6eed7950884ab30e684704e325ca Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 28 Nov 2013 15:25:21 +0200 Subject: iwlwifi: mvm: don't send SMPS action frame with single RX antenna Products that have only 1 antenna in Rx don't support MIMO in RX. As a consequence, they will be in STATIC always. Don't tell mac80211 to update SMPS in that case. mac80211 would send an action frame to the AP which is clearly bogus. As a matter of fact, we have seen that some APs send a deauth when that happens. Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/utils.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 56cf819bc0c7..f4aff56a36da 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -518,6 +518,11 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int i; lockdep_assert_held(&mvm->mutex); + + /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */ + if (num_of_ant(iwl_fw_valid_rx_ant(mvm->fw)) == 1) + return; + mvmvif = iwl_mvm_vif_from_mac80211(vif); mvmvif->smps_requests[req_type] = smps_request; for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { -- cgit v1.2.3 From 342a11e1459bb5a053b60ae248e3b78d4da79395 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 08:00:27 +0900 Subject: bcma: pci: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: John W. Linville --- drivers/bcma/host_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 12a4ff751359..e333305363aa 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -269,7 +269,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, #endif /* CONFIG_PM_SLEEP */ -static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { +static const struct pci_device_id bcma_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, -- cgit v1.2.3 From 4348d085b8ef9067e32ccc1a9e90e33c0e4b4e66 Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Mon, 2 Dec 2013 23:17:48 -0800 Subject: mwifiex: use little-endian variables in firmware structures The firmware expects the command structure members in little endianness. Signed-off-by: Ujjal Roy Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 4 ++-- drivers/net/wireless/mwifiex/fw.h | 28 ++++++++++++++-------------- drivers/net/wireless/mwifiex/sta_cmd.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index e47f4e3012b8..1ddc8b2e3722 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -312,14 +312,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) } if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) == MWIFIEX_BSS_ROLE_STA) { - if (!sleep_cfm_buf->resp_ctrl) + if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) /* Response is not needed for sleep confirm command */ adapter->ps_state = PS_STATE_SLEEP; else adapter->ps_state = PS_STATE_SLEEP_CFM; - if (!sleep_cfm_buf->resp_ctrl && + if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && (adapter->is_hs_configured && !adapter->sleep_period.period)) { adapter->pm_wakeup_card_req = true; diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index c8385ec77a86..6998413c8881 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -610,12 +610,12 @@ struct mwifiex_ie_types_tsf_timestamp { struct mwifiex_cf_param_set { u8 cfp_cnt; u8 cfp_period; - u16 cfp_max_duration; - u16 cfp_duration_remaining; + __le16 cfp_max_duration; + __le16 cfp_duration_remaining; } __packed; struct mwifiex_ibss_param_set { - u16 atim_window; + __le16 atim_window; } __packed; struct mwifiex_ie_types_ss_param_set { @@ -627,7 +627,7 @@ struct mwifiex_ie_types_ss_param_set { } __packed; struct mwifiex_fh_param_set { - u16 dwell_time; + __le16 dwell_time; u8 hop_set; u8 hop_pattern; u8 hop_index; @@ -684,10 +684,10 @@ struct host_cmd_ds_802_11_key_material { } __packed; struct host_cmd_ds_gen { - u16 command; - u16 size; - u16 seq_num; - u16 result; + __le16 command; + __le16 size; + __le16 seq_num; + __le16 result; }; #define S_DS_GEN sizeof(struct host_cmd_ds_gen) @@ -820,8 +820,8 @@ struct ieee_types_cf_param_set { u8 len; u8 cfp_cnt; u8 cfp_period; - u16 cfp_max_duration; - u16 cfp_duration_remaining; + __le16 cfp_max_duration; + __le16 cfp_duration_remaining; } __packed; struct ieee_types_ibss_param_set { @@ -957,7 +957,7 @@ struct mwifiex_hs_config_param { } __packed; struct hs_activate_param { - u16 resp_ctrl; + __le16 resp_ctrl; } __packed; struct host_cmd_ds_802_11_hs_cfg_enh { @@ -1131,7 +1131,7 @@ struct host_cmd_ds_802_11_bg_scan_query { } __packed; struct host_cmd_ds_802_11_bg_scan_query_rsp { - u32 report_condition; + __le32 report_condition; struct host_cmd_ds_802_11_scan_rsp scan_resp; } __packed; @@ -1230,7 +1230,7 @@ struct mwifiex_ie_types_wmm_queue_status { struct mwifiex_ie_types_header header; u8 queue_index; u8 disabled; - u16 medium_time; + __le16 medium_time; u8 flow_required; u8 flow_created; u32 reserved; @@ -1310,7 +1310,7 @@ struct mwifiex_ie_types_vht_oper { u8 chan_center_freq_1; u8 chan_center_freq_2; /* Basic MCS set map, each 2 bits stands for a NSS */ - u16 basic_mcs_map; + __le16 basic_mcs_map; } __packed; struct mwifiex_ie_types_wmmcap { diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 2181ee283d82..1efa43ec1c6e 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -354,7 +354,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, } if (hs_activate) { hs_cfg->action = cpu_to_le16(HS_ACTIVATE); - hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED; + hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED); } else { hs_cfg->action = cpu_to_le16(HS_CONFIGURE); hs_cfg->params.hs_config.conditions = hscfg_param->conditions; -- cgit v1.2.3 From a6efc5b7f8e737c8e7c97b3c671ae211c5ece3d8 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 2 Dec 2013 23:17:49 -0800 Subject: mwifiex: declare snap_type as __be16 variable Actually we are updating snap_type with h_proto (__be16 variable) in ethernet frame header. Hence endianness conversion is not required. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_aggr.c | 6 +++--- drivers/net/wireless/mwifiex/fw.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 1214c587fd08..63211707f939 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -69,9 +69,9 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset); /* Copy SNAP header */ - snap.snap_type = - le16_to_cpu(*(__le16 *) ((u8 *)skb_src->data + dt_offset)); - dt_offset += sizeof(u16); + snap.snap_type = ((struct ethhdr *)skb_src->data)->h_proto; + + dt_offset += sizeof(__be16); memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr)); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 6998413c8881..8fcb500fa09b 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -30,7 +30,7 @@ struct rfc_1042_hdr { u8 llc_ssap; u8 llc_ctrl; u8 snap_oui[3]; - u16 snap_type; + __be16 snap_type; }; struct rx_packet_hdr { -- cgit v1.2.3 From 1bf947a79177643f33b875586642b61cb175782a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 2 Dec 2013 23:17:50 -0800 Subject: mwifiex: remove rfc1042_eth_hdr variable Use 'rfc1042_header' available in net/wireless/util.c Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_rx.c | 5 ++--- drivers/net/wireless/mwifiex/uap_txrx.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index bb22664923ef..241c0e5fc8ff 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -88,15 +88,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, struct rxpd *local_rx_pd; int hdr_chop; struct ethhdr *eth_hdr; - u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; local_rx_pd = (struct rxpd *) (skb->data); rx_pkt_hdr = (void *)local_rx_pd + le16_to_cpu(local_rx_pd->rx_pkt_offset); - if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { + if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header))) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 92f76d655e6c..0d4b7d62ebcc 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -98,7 +98,6 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, int hdr_chop; struct timeval tv; struct ethhdr *p_ethhdr; - u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; uap_rx_pd = (struct uap_rxpd *)(skb->data); rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); @@ -112,8 +111,8 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, return; } - if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { + if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header))) { /* Replace the 803 header and rfc1042 header (llc/snap) with * an Ethernet II header, keep the src/dst and snap_type * (ethertype). -- cgit v1.2.3 From c613d16fa77fb7738a436ba23979ecf60ec82494 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 2 Dec 2013 23:17:51 -0800 Subject: mwifiex: fix an issue with Appletalk devices SNAP/LLC header in the AARP packet is being stripped off while preparing an EthernetII header. Annex M, Table M.3 in 802.11 spec says that some header (ex. AppleTalk AARP(2)) should pass through untouched. This patch modifies the check to exclude/include EthernetII header translation for special cases. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_rx.c | 8 ++++++-- drivers/net/wireless/mwifiex/uap_txrx.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 241c0e5fc8ff..452389959520 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -94,8 +94,12 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, rx_pkt_hdr = (void *)local_rx_pd + le16_to_cpu(local_rx_pd->rx_pkt_offset); - if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, - sizeof(rfc1042_header))) { + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, + sizeof(bridge_tunnel_header))) || + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header)) && + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 0d4b7d62ebcc..a0bd954b3ab2 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -111,8 +111,12 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, return; } - if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, - sizeof(rfc1042_header))) { + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, + sizeof(bridge_tunnel_header))) || + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header)) && + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { /* Replace the 803 header and rfc1042 header (llc/snap) with * an Ethernet II header, keep the src/dst and snap_type * (ethertype). -- cgit v1.2.3 From f8eb5ee5f56f09278b80100e65df08975867f03c Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Mon, 2 Dec 2013 23:17:52 -0800 Subject: mwifiex: avoid using variable name eth_hdr eth_hdr is defined in kernel. Use a different variable name in our functions. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_rx.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 452389959520..d74192d62653 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -36,12 +36,12 @@ mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv, struct sk_buff *skb) { const struct mwifiex_arp_eth_header *arp; - struct ethhdr *eth_hdr; + struct ethhdr *eth; struct ipv6hdr *ipv6; struct icmp6hdr *icmpv6; - eth_hdr = (struct ethhdr *)skb->data; - switch (ntohs(eth_hdr->h_proto)) { + eth = (struct ethhdr *)skb->data; + switch (ntohs(eth->h_proto)) { case ETH_P_ARP: arp = (void *)(skb->data + sizeof(struct ethhdr)); if (arp->hdr.ar_op == htons(ARPOP_REPLY) || @@ -87,7 +87,7 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, struct rx_packet_hdr *rx_pkt_hdr; struct rxpd *local_rx_pd; int hdr_chop; - struct ethhdr *eth_hdr; + struct ethhdr *eth; local_rx_pd = (struct rxpd *) (skb->data); @@ -109,7 +109,7 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, * To create the Ethernet II, just move the src, dst address * right before the snap_type. */ - eth_hdr = (struct ethhdr *) + eth = (struct ethhdr *) ((u8 *) &rx_pkt_hdr->eth803_hdr + sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rx_pkt_hdr->rfc1042_hdr) @@ -117,14 +117,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, - sizeof(rx_pkt_hdr->eth803_hdr.h_source) - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); - memcpy(eth_hdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, - sizeof(eth_hdr->h_source)); - memcpy(eth_hdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, - sizeof(eth_hdr->h_dest)); + memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source, + sizeof(eth->h_source)); + memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, + sizeof(eth->h_dest)); /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header that was removed. */ - hdr_chop = (u8 *) eth_hdr - (u8 *) local_rx_pd; + hdr_chop = (u8 *) eth - (u8 *) local_rx_pd; } else { /* Chop off the rxpd */ hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr - -- cgit v1.2.3 From ca8d6dfc929ad6e59eb523e7c057804b55e5673e Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Mon, 2 Dec 2013 23:17:53 -0800 Subject: mwifiex: fix rx_pending count imbalance RX packets are handled in different paths. Not all paths have decrement of rx_pending counter. This patch fixes the counter imbalance. Signed-off-by: Ujjal Roy Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 3 ++- drivers/net/wireless/mwifiex/main.h | 2 +- drivers/net/wireless/mwifiex/sta_rx.c | 15 +++------------ drivers/net/wireless/mwifiex/txrx.c | 11 +++++++++-- drivers/net/wireless/mwifiex/uap_txrx.c | 15 +++------------ drivers/net/wireless/mwifiex/usb.c | 4 +--- 6 files changed, 19 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 6499117fce43..1d0a817f2bf0 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -643,7 +643,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) if (priv) priv->stats.rx_dropped++; - adapter->if_ops.data_complete(adapter, skb); + dev_kfree_skb_any(skb); + adapter->if_ops.data_complete(adapter); } } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 1d72f13adb9d..dc34457557f3 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -615,7 +615,7 @@ struct mwifiex_if_ops { void (*cleanup_mpa_buf) (struct mwifiex_adapter *); int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); - int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *); + int (*data_complete) (struct mwifiex_adapter *); int (*init_fw_port) (struct mwifiex_adapter *); int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); void (*card_reset) (struct mwifiex_adapter *); diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index d74192d62653..0bb510de8071 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -188,12 +188,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, rx_pkt_offset, rx_pkt_length); priv->stats.rx_dropped++; - - if (adapter->if_ops.data_complete) - adapter->if_ops.data_complete(adapter, skb); - else - dev_kfree_skb_any(skb); - + dev_kfree_skb_any(skb); return ret; } @@ -247,12 +242,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority, ta, (u8) rx_pkt_type, skb); - if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { - if (adapter->if_ops.data_complete) - adapter->if_ops.data_complete(adapter, skb); - else - dev_kfree_skb_any(skb); - } + if (ret || (rx_pkt_type == PKT_TYPE_BAR)) + dev_kfree_skb_any(skb); if (ret) priv->stats.rx_dropped++; diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 8f923d0d2ba6..8dd145cf8030 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -40,6 +40,7 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); struct rxpd *local_rx_pd; struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + int ret; local_rx_pd = (struct rxpd *) (skb->data); /* Get the BSS number from rxpd, get corresponding priv */ @@ -58,9 +59,15 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, rx_info->bss_type = priv->bss_type; if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - return mwifiex_process_uap_rx_packet(priv, skb); + ret = mwifiex_process_uap_rx_packet(priv, skb); + else + ret = mwifiex_process_sta_rx_packet(priv, skb); + + /* Decrement RX pending counter for each packet */ + if (adapter->if_ops.data_complete) + adapter->if_ops.data_complete(adapter); - return mwifiex_process_sta_rx_packet(priv, skb); + return ret; } EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index a0bd954b3ab2..6c0a31a8df91 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -267,12 +267,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset), le16_to_cpu(uap_rx_pd->rx_pkt_length)); priv->stats.rx_dropped++; - - if (adapter->if_ops.data_complete) - adapter->if_ops.data_complete(adapter, skb); - else - dev_kfree_skb_any(skb); - + dev_kfree_skb_any(skb); return 0; } @@ -326,12 +321,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, uap_rx_pd->priority, ta, pkt_type, skb); - if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { - if (adapter->if_ops.data_complete) - adapter->if_ops.data_complete(adapter, skb); - else - dev_kfree_skb_any(skb); - } + if (ret || (rx_pkt_type == PKT_TYPE_BAR)) + dev_kfree_skb_any(skb); if (ret) priv->stats.rx_dropped++; diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index edf5b7a24900..a9240a2083f2 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -938,11 +938,9 @@ static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter, return 0; } -static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb) +static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter) { atomic_dec(&adapter->rx_pending); - dev_kfree_skb_any(skb); return 0; } -- cgit v1.2.3 From f49c6e814274a12295dbd13e1c8ef2b7edd5ab87 Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Mon, 2 Dec 2013 23:17:54 -0800 Subject: mwifiex: correct RX byte count statistics The skb is modified in processing the RX packet. Save the original packet length to a variable so that we can get the correct statistics update. Signed-off-by: Ujjal Roy Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 5d9e150f4111..9b82e225880c 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -191,6 +191,9 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) if (!skb) return -1; + priv->stats.rx_bytes += skb->len; + priv->stats.rx_packets++; + skb->dev = priv->netdev; skb->protocol = eth_type_trans(skb, priv->netdev); skb->ip_summed = CHECKSUM_NONE; @@ -217,8 +220,6 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; if (in_interrupt()) netif_rx(skb); else -- cgit v1.2.3 From a1ed484960066c413712cd9c4d50a350cf67eba3 Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Mon, 2 Dec 2013 23:17:55 -0800 Subject: mwifiex: correct TX byte count statistics The skb is modified in sending the TX packet. Save the original packet length to a variable so that we can get the correct statistics update. Signed-off-by: Ujjal Roy Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 1 + drivers/net/wireless/mwifiex/decl.h | 1 + drivers/net/wireless/mwifiex/main.c | 1 + drivers/net/wireless/mwifiex/sta_tx.c | 1 + drivers/net/wireless/mwifiex/txrx.c | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index d9b7330c902f..4d23647faef0 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -222,6 +222,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, tx_info = MWIFIEX_SKB_TXCB(skb); tx_info->bss_num = priv->bss_num; tx_info->bss_type = priv->bss_type; + tx_info->pkt_len = pkt_len; mwifiex_form_mgmt_frame(skb, buf, len); mwifiex_queue_tx_pkt(priv, skb); diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 5c85d7803d00..3a21bd03d6db 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -130,6 +130,7 @@ struct mwifiex_txinfo { u8 flags; u8 bss_num; u8 bss_type; + u32 pkt_len; }; enum mwifiex_wmm_ac_e { diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 78e8a6666cc6..36c79cff4924 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -648,6 +648,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_info = MWIFIEX_SKB_TXCB(skb); tx_info->bss_num = priv->bss_num; tx_info->bss_type = priv->bss_type; + tx_info->pkt_len = skb->len; /* Record the current time the packet was queued; used to * determine the amount of time the packet was queued in diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 7b581af24f5f..354d64c9606f 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -148,6 +148,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) tx_info = MWIFIEX_SKB_TXCB(skb); tx_info->bss_num = priv->bss_num; tx_info->bss_type = priv->bss_type; + tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN); skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN); skb_push(skb, sizeof(struct txpd)); diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 8dd145cf8030..3446da6792c9 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -175,7 +175,7 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, mwifiex_set_trans_start(priv->netdev); if (!status) { priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; + priv->stats.tx_bytes += tx_info->pkt_len; if (priv->tx_timeout_cnt) priv->tx_timeout_cnt = 0; } else { -- cgit v1.2.3 From f7b598532f3dccfb7b57f57b1163a0e1b3bc50cf Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Mon, 2 Dec 2013 23:17:56 -0800 Subject: mwifiex: update statistics for bridged packets on AP interface The bridged packets are updated to statistics on both TX and RX paths. Also fix a typo in the comment. Signed-off-by: Ujjal Roy Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/uap_txrx.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 6c0a31a8df91..3c74eb254927 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -147,7 +147,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd; } - /* Chop off the leading header bytes so the it points + /* Chop off the leading header bytes so that it points * to the start of either the reconstructed EthII frame * or the 802.2/llc/snap frame. */ @@ -179,6 +179,19 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, tx_info->bss_type = priv->bss_type; tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; + if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) { + /* Update bridge packet statistics as the + * packet is not going to kernel/upper layer. + */ + priv->stats.rx_bytes += skb->len; + priv->stats.rx_packets++; + + /* Sending bridge packet to TX queue, so save the packet + * length in TXCB to update statistics in TX complete. + */ + tx_info->pkt_len = skb->len; + } + do_gettimeofday(&tv); skb->tstamp = timeval_to_ktime(tv); mwifiex_wmm_add_buf_txqueue(priv, skb); -- cgit v1.2.3 From c2868adebdb1c3233562e152d99a834f084cc07e Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 2 Dec 2013 23:17:57 -0800 Subject: mwifiex: remove redundant goto exit_remove statement The check for 'priv' pointer is redundant. 'priv' won't be used later in this routine. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/main.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 36c79cff4924..6bf58aba51d2 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -992,12 +992,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) rtnl_unlock(); } - priv = adapter->priv[0]; - if (!priv || !priv->wdev) - goto exit_remove; - - wiphy_unregister(priv->wdev->wiphy); - wiphy_free(priv->wdev->wiphy); + wiphy_unregister(adapter->wiphy); + wiphy_free(adapter->wiphy); mwifiex_terminate_workqueue(adapter); -- cgit v1.2.3 From bd2a864a14ebd0ffa2166c0d8005e44437436713 Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Mon, 2 Dec 2013 23:17:59 -0800 Subject: mwifiex: do not flood kmsg/dmesg with USB debug messages When TX data URB reaches high water mark the message "data: -ENOSR is returned" is printed. This is not an error case, so change it to debug print. Signed-off-by: Ujjal Roy Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 3446da6792c9..37f26afd4314 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -112,7 +112,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, switch (ret) { case -ENOSR: - dev_err(adapter->dev, "data: -ENOSR is returned\n"); + dev_dbg(adapter->dev, "data: -ENOSR is returned\n"); break; case -EBUSY: if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && -- cgit v1.2.3 From 997b179ba3d4da8a25d28cf4f1de8962a32e588a Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Wed, 4 Dec 2013 18:46:54 +0800 Subject: ath9k: enable dfs for mesh mode Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 8f4c1674b76e..5a0b7e82c85f 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -856,6 +856,9 @@ static const struct ieee80211_iface_limit if_limits[] = { static const struct ieee80211_iface_limit if_dfs_limits[] = { { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_ADHOC) }, }; -- cgit v1.2.3 From fa643ae2ce4e75413623a51845a2fd5c9fae4ec0 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Fri, 6 Dec 2013 11:28:02 +0800 Subject: wcn36xx: enable the beaconing in mesh mode Enable the beaconing in wnc36xx by tweaking the tim offset and force the use of AP-style beaconing. Otherwise, beaconing is not working. The tim offset is set to 256. Otherwise, this will overwrite mesh beacon submitted by mac80211. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wcn36xx/smd.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 823631cdb872..8f37562e0b11 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1151,14 +1151,14 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, /* STA */ bss->oper_mode = 1; bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; - } else if (vif->type == NL80211_IFTYPE_AP) { + } else if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT) { bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; /* AP */ bss->oper_mode = 0; bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; - } else if (vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT) { + } else if (vif->type == NL80211_IFTYPE_ADHOC) { bss->bss_type = WCN36XX_HAL_IBSS_MODE; /* STA */ @@ -1309,7 +1309,11 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, memcpy(msg_body.bssid, vif->addr, ETH_ALEN); /* TODO need to find out why this is needed? */ - msg_body.tim_ie_offset = tim_off+4; + if (vif->type == NL80211_IFTYPE_MESH_POINT) + /* mesh beacon don't need this, so push further down */ + msg_body.tim_ie_offset = 256; + else + msg_body.tim_ie_offset = tim_off+4; msg_body.p2p_ie_offset = p2p_off; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); -- cgit v1.2.3 From 7f3dbb563658f6f24ba52ba336f652d9f9b5fca4 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 5 Dec 2013 22:07:12 -0600 Subject: rtlwifi: rtl8192c-common: Fix sparse warning Sparse reports the following: CHECK drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c:570:34: warning: dubious: !x & y There should be a parens around the expression. Reported-by: Dan Carpenter Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index fd7e4a7c94de..eb78fd8607f7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -567,7 +567,7 @@ static void rtl92c_dm_dig(struct ieee80211_hw *hw) if (rtlpriv->dm.dm_initialgain_enable == false) return; - if (!rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG) + if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG)) return; rtl92c_dm_ctrl_initgain_by_twoport(hw); -- cgit v1.2.3 From 98b2e1fdf1603f30db195a11cc1ffcc2170d42a8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:39 +0530 Subject: ath9k: Add initval arrays for DFS channels Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 7 +++++++ drivers/net/wireless/ath/ath9k/ar9340_initvals.h | 2 ++ drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h | 13 +++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index e7cdf1100f56..97b4bd1e2e13 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1745,4 +1745,11 @@ static const u32 ar9300_2p2_baseband_core_txfir_coeff_japan_2484[][2] = { {0x0000a3a0, 0xca9228ee}, }; +static const u32 ar9300_2p2_baseband_postamble_dfs_channel[][3] = { + /* Addr 5G 2G */ + {0x00009824, 0x5ac668d0, 0x5ac668d0}, + {0x00009e0c, 0x6d4000e2, 0x6d4000e2}, + {0x00009e14, 0x37b9625e, 0x37b9625e}, +}; + #endif /* INITVALS_9003_2P2_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index 7f22cb2a4941..a01f0edb6518 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h @@ -30,6 +30,8 @@ #define ar9340_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 +#define ar9340_1p0_baseband_postamble_dfs_channel ar9300_2p2_baseband_postamble_dfs_channel + static const u32 ar9340_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index 75bef1179d0d..e6aec2c0207f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -57,8 +57,6 @@ static const u32 ar9580_1p0_baseband_core[][2] = { {0x00009804, 0xfd14e000}, {0x00009808, 0x9c0a9f6b}, {0x0000980c, 0x04900000}, - {0x00009814, 0x3280c00a}, - {0x00009818, 0x00000000}, {0x0000981c, 0x00020028}, {0x00009834, 0x6400a190}, {0x00009838, 0x0108ecff}, @@ -1133,6 +1131,8 @@ static const u32 ar9580_1p0_rx_gain_table[][2] = { static const u32 ar9580_1p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, + {0x00009814, 0x3280c00a, 0x3280c00a, 0x3280c00a, 0x3280c00a}, + {0x00009818, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, @@ -1207,4 +1207,13 @@ static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = { {0x00004044, 0x00000000}, }; +static const u32 ar9580_1p0_baseband_postamble_dfs_channel[][3] = { + /* Addr 5G 2G */ + {0x00009814, 0x3400c00f, 0x3400c00f}, + {0x00009824, 0x5ac668d0, 0x5ac668d0}, + {0x00009828, 0x06903080, 0x06903080}, + {0x00009e0c, 0x6d4000e2, 0x6d4000e2}, + {0x00009e14, 0x37b9625e, 0x37b9625e}, +}; + #endif /* INITVALS_9580_1P0_H */ -- cgit v1.2.3 From 4a878b9f8916eaeb5f8cea1379956b485e32450f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:40 +0530 Subject: ath9k: Initialize baseband for DFS channels Certain baseband registers require different values to be programmed when operating in a DFS channel to ensure that radar detection works correctly. This is required for AR9300, AR9340 and AR9580. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 6 ++++++ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 6 ++++++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index d8c1eee8ea53..4e8ae4a79dc0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -152,6 +152,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9340Modes_fast_clock_1p0); INIT_INI_ARRAY(&ah->iniCckfirJapan2484, ar9340_1p0_baseband_core_txfir_coeff_japan_2484); + INIT_INI_ARRAY(&ah->ini_dfs, + ar9340_1p0_baseband_postamble_dfs_channel); if (!ah->is_clk_25mhz) INIT_INI_ARRAY(&ah->iniAdditional, @@ -340,6 +342,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9580_1p0_modes_fast_clock); INIT_INI_ARRAY(&ah->iniCckfirJapan2484, ar9580_1p0_baseband_core_txfir_coeff_japan_2484); + INIT_INI_ARRAY(&ah->ini_dfs, + ar9580_1p0_baseband_postamble_dfs_channel); } else if (AR_SREV_9565_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9565_1p1_mac_core); @@ -458,6 +462,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) ar9300Modes_fast_clock_2p2); INIT_INI_ARRAY(&ah->iniCckfirJapan2484, ar9300_2p2_baseband_core_txfir_coeff_japan_2484); + INIT_INI_ARRAY(&ah->ini_dfs, + ar9300_2p2_baseband_postamble_dfs_channel); } } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 39b71b3d6919..9f051a08e143 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1332,6 +1332,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) static void ar9003_hw_set_radar_params(struct ath_hw *ah, struct ath_hw_radar_conf *conf) { + unsigned int regWrites = 0; u32 radar_0 = 0, radar_1 = 0; if (!conf) { @@ -1358,6 +1359,11 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); else REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); + + if (AR_SREV_9300(ah) || AR_SREV_9340(ah) || AR_SREV_9580(ah)) { + REG_WRITE_ARRAY(&ah->ini_dfs, + IS_CHAN_HT40(ah->curchan) ? 2 : 1, regWrites); + } } static void ar9003_hw_set_radar_conf(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e50843600989..7490047acd11 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -864,6 +864,7 @@ struct ath_hw { u32 gpio_mask; u32 gpio_val; + struct ar5416IniArray ini_dfs; struct ar5416IniArray iniModes; struct ar5416IniArray iniCommon; struct ar5416IniArray iniBB_RfGain; -- cgit v1.2.3 From bc73902a031d9a9bf5123b3c11889d85ce8fc6ad Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:41 +0530 Subject: ath9k: Update mac_postamble for AR9003 family Enable the ALWAYS_KEYSEARCH bit in the initvals. Currently this is done in the driver, but adding this to the initvals makes it easier to be in sync with the INI files given by the systems engineering team. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 97b4bd1e2e13..724367446152 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -303,7 +303,7 @@ static const u32 ar9300_2p2_mac_postamble[][5] = { {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x00008120, 0x18f04800, 0x18f04800, 0x18f04810, 0x18f04810}, {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, }; -- cgit v1.2.3 From 11295126e3cfb1cd64a2fa8a4134956ab4dc26d3 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:42 +0530 Subject: ath9k: Remove AR955x INI duplicates Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar955x_1p0_initvals.h | 540 +-------------------- 1 file changed, 8 insertions(+), 532 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index ccc5b6c99add..74d8bc05b317 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h @@ -20,6 +20,14 @@ /* AR955X 1.0 */ +#define ar955x_1p0_soc_postamble ar9300_2p2_soc_postamble + +#define ar955x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2 + +#define ar955x_1p0_common_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 + +#define ar955x_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 + static const u32 ar955x_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330}, @@ -37,13 +45,6 @@ static const u32 ar955x_1p0_radio_postamble[][5] = { {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, }; -static const u32 ar955x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - static const u32 ar955x_1p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, @@ -473,266 +474,6 @@ static const u32 ar955x_1p0_mac_core[][2] = { {0x000083d0, 0x8c7901ff}, }; -static const u32 ar955x_1p0_common_rx_gain_table[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x23232323}, - {0x0000b084, 0x21232323}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - static const u32 ar955x_1p0_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, @@ -891,266 +632,6 @@ static const u32 ar955x_1p0_baseband_core[][2] = { {0x0000c420, 0x00000000}, }; -static const u32 ar955x_1p0_common_wo_xlna_rx_gain_table[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - static const u32 ar955x_1p0_soc_preamble[][2] = { /* Addr allmodes */ {0x00007000, 0x00000000}, @@ -1263,11 +744,6 @@ static const u32 ar955x_1p0_modes_no_xpa_tx_gain_table[][9] = { {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, }; -static const u32 ar955x_1p0_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, -}; - static const u32 ar955x_1p0_modes_fast_clock[][3] = { /* Addr 5G_HT20 5G_HT40 */ {0x00001030, 0x00000268, 0x000004d0}, -- cgit v1.2.3 From 367ba05f3ef31abca9a06939a4fd633c8147ce7f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:43 +0530 Subject: ath9k: Update AR9331 v1.1 initvals * Update radio/baseband/gain tables. * Mark ar9331_modes_high_power_tx_gain_1p1 as a duplicate * ar9331_1p1_mac_postamble is not a duplicate. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9330_1p1_initvals.h | 128 ++++----------------- 1 file changed, 24 insertions(+), 104 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h index 6e1756bc3833..f76139bbb74f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h @@ -18,6 +18,10 @@ #ifndef INITVALS_9330_1P1_H #define INITVALS_9330_1P1_H +#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 + +#define ar9331_modes_high_power_tx_gain_1p1 ar9331_modes_lowest_ob_db_tx_gain_1p1 + static const u32 ar9331_1p1_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, @@ -55,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -252,7 +256,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = { {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84}, {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000}, {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000}, - {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0}, + {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d4, 0x000050d4}, {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, @@ -337,8 +341,6 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = { {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, }; -#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 - static const u32 ar9331_1p1_xtal_25M[][2] = { /* Addr allmodes */ {0x00007038, 0x000002f8}, @@ -373,17 +375,17 @@ static const u32 ar9331_1p1_radio_core[][2] = { {0x000160b4, 0x92480040}, {0x000160c0, 0x006db6db}, {0x000160c4, 0x0186db60}, - {0x000160c8, 0x6db4db6c}, + {0x000160c8, 0x6db6db6c}, {0x000160cc, 0x6de6c300}, {0x000160d0, 0x14500820}, {0x00016100, 0x04cb0001}, {0x00016104, 0xfff80015}, {0x00016108, 0x00080010}, {0x0001610c, 0x00170000}, - {0x00016140, 0x10800000}, + {0x00016140, 0x50804000}, {0x00016144, 0x01884080}, {0x00016148, 0x000080c0}, - {0x00016280, 0x01000015}, + {0x00016280, 0x01001015}, {0x00016284, 0x14d20000}, {0x00016288, 0x00318000}, {0x0001628c, 0x50000000}, @@ -622,12 +624,12 @@ static const u32 ar9331_1p1_baseband_core[][2] = { {0x0000a370, 0x00000000}, {0x0000a390, 0x00000001}, {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, + {0x0000a398, 0x00000000}, + {0x0000a39c, 0x210d0401}, + {0x0000a3a0, 0xab9a7144}, + {0x0000a3a4, 0x00000011}, + {0x0000a3a8, 0x3c3c003d}, + {0x0000a3ac, 0x30310030}, {0x0000a3c0, 0x20202020}, {0x0000a3c4, 0x22222220}, {0x0000a3c8, 0x20200020}, @@ -686,100 +688,18 @@ static const u32 ar9331_1p1_baseband_core[][2] = { {0x0000a7dc, 0x00000001}, }; -static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = { +static const u32 ar9331_1p1_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, - {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52}, - {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84}, - {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000}, - {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000}, - {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0}, - {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, - {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, - {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, - {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, - {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, - {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, - {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, - {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, - {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20}, - {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22}, - {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24}, - {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43}, - {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42}, - {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44}, - {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64}, - {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66}, - {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6}, - {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6}, - {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6}, - {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, - {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, - {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, - {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, - {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, - {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, - {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, - {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, - {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, - {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, - {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, - {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, - {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, - {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, - {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, - {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, - {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, - {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, - {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, - {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, - {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, - {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, - {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, - {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, - {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, - {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, - {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, - {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, - {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, - {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, - {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802}, - {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03}, - {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, - {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, - {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, - {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, - {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, - {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, - {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db}, - {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, }; -#define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble - static const u32 ar9331_1p1_soc_preamble[][2] = { /* Addr allmodes */ {0x00007020, 0x00000000}, -- cgit v1.2.3 From 492f478d89b28c97166e4540aa13ac0e7abaa29f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:44 +0530 Subject: ath9k: Update AR9331 v1.2 initvals Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9330_1p2_initvals.h | 401 +++++++++++++++++---- 1 file changed, 333 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h index 57ed8a112173..0ac8be96097f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h @@ -18,6 +18,28 @@ #ifndef INITVALS_9330_1P2_H #define INITVALS_9330_1P2_H +#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2 + +#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2 + +#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2 + +#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484 + +#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M + +#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M + +#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble + +#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble + +#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble + +#define ar9331_1p2_mac_core ar9331_1p1_mac_core + +#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1 + static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7}, @@ -103,57 +125,6 @@ static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = { {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, }; -#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2 - -#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_power_tx_gain_1p2 - -#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_low_ob_db_tx_gain_1p2 - -static const u32 ar9331_1p2_baseband_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, - {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, - {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, - {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, - {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4}, - {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e}, - {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, - {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, - {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, - {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, - {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, - {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff}, - {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, - {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, - {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, - {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, - {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981}, - {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, - {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, - {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -}; - static const u32 ar9331_1p2_radio_core[][2] = { /* Addr allmodes */ {0x00016000, 0x36db6db6}, @@ -219,24 +190,318 @@ static const u32 ar9331_1p2_radio_core[][2] = { {0x000163d4, 0x00000000}, }; -#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484 - -#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M - -#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M - -#define ar9331_1p2_baseband_core ar9331_1p1_baseband_core - -#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble - -#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble - -#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble - -#define ar9331_1p2_mac_core ar9331_1p1_mac_core +static const u32 ar9331_1p2_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a8f6b}, + {0x0000980c, 0x04800000}, + {0x00009814, 0x9280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x5f3ca3de}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x14750600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x32840bbe}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0x00000000}, + {0x00009c08, 0x03200000}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x1883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c00400}, + {0x00009d18, 0x00000000}, + {0x00009e08, 0x0038233c}, + {0x00009e24, 0x9927b515}, + {0x00009e28, 0x12ef0200}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009fc0, 0x803e4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x0000a20c, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2dc, 0x00000000}, + {0x0000a2e0, 0x00000000}, + {0x0000a2e4, 0x00000000}, + {0x0000a2e8, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000006}, + {0x0000a3f8, 0x0cdbd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d001dce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00000000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x04000000}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a640, 0x00000000}, + {0x0000a644, 0x3fad9d74}, + {0x0000a648, 0x0048060a}, + {0x0000a64c, 0x00003c37}, + {0x0000a670, 0x03020100}, + {0x0000a674, 0x09080504}, + {0x0000a678, 0x0d0c0b0a}, + {0x0000a67c, 0x13121110}, + {0x0000a680, 0x31301514}, + {0x0000a684, 0x35343332}, + {0x0000a688, 0x00000036}, + {0x0000a690, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000001}, +}; -#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1 +static const u32 ar9331_1p2_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, + {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, + {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, + {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4}, + {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e}, + {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, + {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, + {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981}, + {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, + {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; -#define ar9331_common_rx_gain_1p2 ar9485_common_rx_gain_1_1 +static const u32 ar9331_common_rx_gain_1p2[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x03850384}, + {0x0000a030, 0x03890388}, + {0x0000a034, 0x038b038a}, + {0x0000a038, 0x038d038c}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x28282828}, + {0x0000a088, 0x28282828}, + {0x0000a08c, 0x28282828}, + {0x0000a090, 0x28282828}, + {0x0000a094, 0x21212128}, + {0x0000a098, 0x171c1c1c}, + {0x0000a09c, 0x02020212}, + {0x0000a0a0, 0x00000202}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x111f1100}, + {0x0000a0c8, 0x111d111e}, + {0x0000a0cc, 0x111b111c}, + {0x0000a0d0, 0x22032204}, + {0x0000a0d4, 0x22012202}, + {0x0000a0d8, 0x221f2200}, + {0x0000a0dc, 0x221d221e}, + {0x0000a0e0, 0x33013302}, + {0x0000a0e4, 0x331f3300}, + {0x0000a0e8, 0x4402331e}, + {0x0000a0ec, 0x44004401}, + {0x0000a0f0, 0x441e441f}, + {0x0000a0f4, 0x55015502}, + {0x0000a0f8, 0x551f5500}, + {0x0000a0fc, 0x6602551e}, + {0x0000a100, 0x66006601}, + {0x0000a104, 0x661e661f}, + {0x0000a108, 0x7703661d}, + {0x0000a10c, 0x77017702}, + {0x0000a110, 0x00007700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x111f1100}, + {0x0000a148, 0x111d111e}, + {0x0000a14c, 0x111b111c}, + {0x0000a150, 0x22032204}, + {0x0000a154, 0x22012202}, + {0x0000a158, 0x221f2200}, + {0x0000a15c, 0x221d221e}, + {0x0000a160, 0x33013302}, + {0x0000a164, 0x331f3300}, + {0x0000a168, 0x4402331e}, + {0x0000a16c, 0x44004401}, + {0x0000a170, 0x441e441f}, + {0x0000a174, 0x55015502}, + {0x0000a178, 0x551f5500}, + {0x0000a17c, 0x6602551e}, + {0x0000a180, 0x66006601}, + {0x0000a184, 0x661e661f}, + {0x0000a188, 0x7703661d}, + {0x0000a18c, 0x77017702}, + {0x0000a190, 0x00007700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000296}, +}; #endif /* INITVALS_9330_1P2_H */ -- cgit v1.2.3 From 0f978bfaf2600040f9826f394eb12e023bef3068 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:45 +0530 Subject: ath9k: Use a separate TX gain table for WZR-HP-G450H The Buffalo device WZR-HP-G450H uses the index 3 for TX gain, which is set to the high_power table currently. Later variants of the router use the same index, but instead refer to the low_ob_db gain table. This is not handled in the driver since there is no way to distinguish board revisions and the high_power table is used (incorrectly) for the newer variants. By default, devices based on AR9300 using the TX gain index 3 have to use the high_power table. To make sure that WZR-HP-G450H is not broken when the high_power table is updated, use a separate array based on information obtained from the platform data. The current situation where only the original variant of WZR-HP-G450H works properly stays unchanged. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../wireless/ath/ath9k/ar9003_buffalo_initvals.h | 126 +++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_hw.c | 12 +- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 36 ++++-- include/linux/ath9k_platform.h | 2 + 5 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h new file mode 100644 index 000000000000..59cf738f70df --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9003_BUFFALO_H +#define INITVALS_9003_BUFFALO_H + +static const u32 ar9300Modes_high_power_tx_gain_table_buffalo[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, + {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +#endif /* INITVALS_9003_BUFFALO_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 4e8ae4a79dc0..29613ebbc5d7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -17,6 +17,7 @@ #include "hw.h" #include "ar9003_mac.h" #include "ar9003_2p2_initvals.h" +#include "ar9003_buffalo_initvals.h" #include "ar9485_initvals.h" #include "ar9340_initvals.h" #include "ar9330_1p1_initvals.h" @@ -592,9 +593,14 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah) else if (AR_SREV_9565(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9565_1p0_modes_high_power_tx_gain_table); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_high_power_tx_gain_table_2p2); + else { + if (ah->config.tx_gain_buffalo) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_power_tx_gain_table_buffalo); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_power_tx_gain_table_2p2); + } } static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7490047acd11..b1ff54631dca 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -316,6 +316,7 @@ struct ath9k_ops_config { bool xatten_margin_cfg; bool alt_mingainidx; bool no_pll_pwrsave; + bool tx_gain_buffalo; }; enum ath9k_int { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5a0b7e82c85f..609b7e13f3f0 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -554,7 +554,7 @@ static void ath9k_init_misc(struct ath_softc *sc) sc->spec_config.fft_period = 0xF; } -static void ath9k_init_platform(struct ath_softc *sc) +static void ath9k_init_pcoem_platform(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; struct ath9k_hw_capabilities *pCap = &ah->caps; @@ -664,6 +664,27 @@ static void ath9k_eeprom_release(struct ath_softc *sc) release_firmware(sc->sc_ah->eeprom_blob); } +static int ath9k_init_soc_platform(struct ath_softc *sc) +{ + struct ath9k_platform_data *pdata = sc->dev->platform_data; + struct ath_hw *ah = sc->sc_ah; + int ret = 0; + + if (!pdata) + return 0; + + if (pdata->eeprom_name) { + ret = ath9k_eeprom_request(sc, pdata->eeprom_name); + if (ret) + return ret; + } + + if (pdata->tx_gain_buffalo) + ah->config.tx_gain_buffalo = true; + + return ret; +} + static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { @@ -717,7 +738,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, /* * Platform quirks. */ - ath9k_init_platform(sc); + ath9k_init_pcoem_platform(sc); + + ret = ath9k_init_soc_platform(sc); + if (ret) + return ret; /* * Enable WLAN/BT RX Antenna diversity only when: @@ -731,7 +756,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common->bt_ant_diversity = 1; spin_lock_init(&common->cc_lock); - spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); @@ -753,12 +777,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ath_read_cachesize(common, &csz); common->cachelsz = csz << 2; /* convert to bytes */ - if (pdata && pdata->eeprom_name) { - ret = ath9k_eeprom_request(sc, pdata->eeprom_name); - if (ret) - return ret; - } - /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index fcdd81bd5314..8598f8eacb20 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h @@ -32,6 +32,8 @@ struct ath9k_platform_data { u32 gpio_val; bool is_clk_25mhz; + bool tx_gain_buffalo; + int (*get_mac_revision)(void); int (*external_reset)(void); }; -- cgit v1.2.3 From 98d7401dbbebec3da608697a77f9ca507fd8afc3 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:46 +0530 Subject: ath9k: Update high power gain table for AR9300 Now that the Buffalo-specific initvals have been moved to a separate array, update the default high power TX gain table for all AR9300 v2.2 devices. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 182 ++++++++++----------- 1 file changed, 91 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 724367446152..0a6163e9248c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, + {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, + {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, + {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, + {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, + {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, + {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, + {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, + {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, + {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5e88442e, 0x5e88442e, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x628a4431, 0x628a4431, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, - {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, - {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, - {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, - {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, + {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, + {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, + {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, + {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, + {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -- cgit v1.2.3 From 4b0ec82818758892dc2d4cb6934ac385024258f8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:47 +0530 Subject: ath9k: Identify duplicate AR9485 initvals Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9485_initvals.h | 117 +---------------------- 1 file changed, 5 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index 7c1845221e1c..ce83ce47a1ca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -20,17 +20,11 @@ /* AR9485 1.1 */ -static const u32 ar9485_1_1_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; +#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1 + +#define ar9485_1_1_mac_postamble ar9331_1p1_mac_postamble + +#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = { /* Addr allmodes */ @@ -546,100 +540,6 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, }; -static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, - {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a}, - {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, - {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, - {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, - {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, - {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, - {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, - {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, - {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, - {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, - {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, - {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, - {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, - {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, - {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, - {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, - {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, - {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20}, - {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21}, - {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, - {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, - {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, - {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, - {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, - {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, - {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, - {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, - {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, - {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, - {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, - {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501}, - {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, - {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, - {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803}, - {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04}, - {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, - {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, - {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, - {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, - {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, - {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, - {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, -}; - static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, @@ -1323,13 +1223,6 @@ static const u32 ar9485_1_1_mac_core[][2] = { {0x000083d0, 0x000301ff}, }; -static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x18013e5e}, -- cgit v1.2.3 From ceb1512ffc2529eba731e2407b02421f22c0025e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:48 +0530 Subject: ath9k: Identify duplicate AR9462 v2.0 initvals Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 697 +++------------------ 1 file changed, 83 insertions(+), 614 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 739094384369..1cc13569b17b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -20,6 +20,14 @@ /* AR9462 2.0 */ +#define ar9462_2p0_mac_postamble ar9331_1p1_mac_postamble + +#define ar9462_2p0_common_wo_xlna_rx_gain ar9300Common_wo_xlna_rx_gain_table_2p2 + +#define ar9462_2p0_common_5g_xlna_only_rxgain ar9462_2p0_common_mixed_rx_gain + +#define ar9462_2p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 + static const u32 ar9462_2p0_modes_fast_clock[][3] = { /* Addr 5G_HT20 5G_HT40 */ {0x00001030, 0x00000268, 0x000004d0}, @@ -366,348 +374,81 @@ static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, }; -static const u32 ar9462_2p0_common_wo_xlna_rx_gain[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - -static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, - {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, - {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, - {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, - {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060}, - {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, - {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, - {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000}, - {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, -}; - -static const u32 ar9462_2p0_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033}, -}; - -static const u32 ar9462_2p0_baseband_core[][2] = { +static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, + {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060}, + {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, + {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, + {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000}, + {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, +}; + +static const u32 ar9462_2p0_soc_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033}, +}; + +static const u32 ar9462_2p0_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, {0x00009804, 0xfd14e000}, @@ -1226,18 +967,6 @@ static const u32 ar9462_2p0_mac_core[][2] = { {0x000083d0, 0x000301ff}, }; -static const u32 ar9462_2p0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - static const u32 ar9462_2p0_common_mixed_rx_gain[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, @@ -1503,266 +1232,6 @@ static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = { {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, }; -static const u32 ar9462_2p0_common_5g_xlna_only_rxgain[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x2a2d2f32}, - {0x0000b084, 0x21232328}, - {0x0000b088, 0x19191c1e}, - {0x0000b08c, 0x12141417}, - {0x0000b090, 0x07070e0e}, - {0x0000b094, 0x03030305}, - {0x0000b098, 0x00000003}, - {0x0000b09c, 0x00000000}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - static const u32 ar9462_2p0_baseband_core_mix_rxgain[][2] = { /* Addr allmodes */ {0x00009fd0, 0x0a2d6b93}, -- cgit v1.2.3 From ca488b921e98951217f1f9fdc7629febef19ccba Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:49 +0530 Subject: ath9k: Identify duplicate AR9565 v1.0 initvals Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9565_1p0_initvals.h | 85 ++-------------------- 1 file changed, 6 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index a8c757b6124f..10d4a6cb1c3b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h @@ -20,6 +20,12 @@ /* AR9565 1.0 */ +#define ar9565_1p0_mac_postamble ar9331_1p1_mac_postamble + +#define ar9565_1p0_Modes_lowest_ob_db_tx_gain_table ar9565_1p0_modes_low_ob_db_tx_gain_table + +#define ar9565_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 + static const u32 ar9565_1p0_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, @@ -182,18 +188,6 @@ static const u32 ar9565_1p0_mac_core[][2] = { {0x000083d0, 0x800301ff}, }; -static const u32 ar9565_1p0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - static const u32 ar9565_1p0_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, @@ -711,66 +705,6 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { {0x0000b1fc, 0x00000196}, }; -static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0xfc0a9380, 0xfc0a9380, 0xfdab5b52, 0xfdab5b52}, - {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, - {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, - {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a618, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a61c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a620, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a624, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a628, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a62c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a630, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a634, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a638, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a63c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, - {0x00016048, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -}; - static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x18212ede}, @@ -1231,11 +1165,4 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = { {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; -static const u32 ar9565_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { - /* Addr allmodes */ - {0x0000a398, 0x00000000}, - {0x0000a39c, 0x6f7f0301}, - {0x0000a3a0, 0xca9228ee}, -}; - #endif /* INITVALS_9565_1P0_H */ -- cgit v1.2.3 From 0c7c2bb4daebb23b08b86c24fe70189c3c049f78 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:50 +0530 Subject: ath9k: Fix regulatory compliance Adjusting the CCA registers for maximum permissible noise floor in ETSI/Japan domains has to be done for all AR9003 family chips. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 5 +++-- drivers/net/wireless/ath/ath9k/hw.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 2af667beb273..bbbfc4dc59eb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -341,14 +341,15 @@ #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100 +#define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ -95 +#define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ -100 + #define AR_PHY_CCA_NOM_VAL_9462_2GHZ -127 #define AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ -127 #define AR_PHY_CCA_MAX_GOOD_VAL_9462_2GHZ -60 -#define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ -95 #define AR_PHY_CCA_NOM_VAL_9462_5GHZ -127 #define AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ -127 #define AR_PHY_CCA_MAX_GOOD_VAL_9462_5GHZ -60 -#define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ -100 #define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118 diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 779d38a98a0e..4ee24b1eec38 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -548,11 +548,11 @@ static int ath9k_hw_post_init(struct ath_hw *ah) * EEPROM needs to be initialized before we do this. * This is required for regulatory compliance. */ - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + if (AR_SREV_9300_20_OR_LATER(ah)) { u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0); if ((regdmn & 0xF0) == CTL_FCC) { - ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ; - ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ; + ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ; + ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ; } } -- cgit v1.2.3 From 6b416d0511153916a140feeabe58cd5443c97fd8 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:51 +0530 Subject: ath9k: Remove AR9330 v1.0 macro as it's not supported Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 259a4b307707..9ad007312c9d 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -883,9 +883,6 @@ #define AR_SREV_9330(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330)) -#define AR_SREV_9330_10(_ah) \ - (AR_SREV_9330((_ah)) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10)) #define AR_SREV_9330_11(_ah) \ (AR_SREV_9330((_ah)) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11)) -- cgit v1.2.3 From bb46662894c24dce9be1414400b4ce969dafc1dd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:52 +0530 Subject: ath9k: Enable manual peak calibration for AR9331 v1.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 29 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index aa0127265746..97e09d5f3a42 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -898,7 +898,7 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) { - int offset[8], total = 0, test; + int offset[8] = {0}, total = 0, test; int agc_out, i; REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), @@ -923,12 +923,18 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1); REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1); - if (is_2g) - REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), - AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0); - else + + if (AR_SREV_9330_11(ah)) { REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), - AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0); + AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); + } else { + if (is_2g) + REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), + AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0); + else + REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), + AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0); + } for (i = 6; i > 0; i--) { offset[i] = BIT(i - 1); @@ -964,9 +970,9 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); } -static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, - struct ath9k_channel *chan, - bool run_rtt_cal) +static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah, + struct ath9k_channel *chan, + bool run_rtt_cal) { struct ath9k_hw_cal_data *caldata = ah->caldata; int i; @@ -1145,7 +1151,7 @@ skip_tx_iqcal: AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT); - ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal); + ar9003_hw_do_pcoem_manual_peak_cal(ah, chan, run_rtt_cal); } if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { @@ -1267,6 +1273,9 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, skip_tx_iqcal: if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { + if (AR_SREV_9330_11(ah)) + ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); + /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | -- cgit v1.2.3 From e6d53bdcc38d451fa6afbe412a759f132d44f361 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:53 +0530 Subject: ath9k: Fix internal regulator for AR955x The internal regulator needs to be programmed correctly for AR955x. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 130657db5c43..2845ace0d9ec 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4122,7 +4122,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_xlna_bias_strength_apply(ah, is2ghz); ar9003_hw_atten_apply(ah, chan); ar9003_hw_quick_drop_apply(ah, chan->channel); - if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah)) + if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) ar9003_hw_internal_regulator_apply(ah); ar9003_hw_apply_tuning_caps(ah); ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); -- cgit v1.2.3 From d6b5075d73adbc10fac873ca86798e30c115a018 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 6 Dec 2013 16:28:54 +0530 Subject: ath9k: Apply tuning caps for AR9330 and AR9485 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 2845ace0d9ec..ec317d6937d6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3965,7 +3965,7 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah) struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0]; - if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) + if (AR_SREV_9340(ah)) return; if (eep->baseEepHeader.featureEnable & 0x40) { -- cgit v1.2.3 From c3e5d2985ef720cbbdc63546a5c545ac4450d96e Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Mon, 9 Dec 2013 23:40:33 +0400 Subject: usb: phy: r-car gen2: use usb_add_phy_dev Use usb_add_phy_dev instead of usb_add_phy, so that devices can be bound to the phy. This is needed to set up USB phy for some internal PCI USB host controllers on R-Car Gen2. Signed-off-by: Valentine Barshak Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-rcar-gen2-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c index a99a6953f11c..9f57091bc9e0 100644 --- a/drivers/usb/phy/phy-rcar-gen2-usb.c +++ b/drivers/usb/phy/phy-rcar-gen2-usb.c @@ -213,7 +213,7 @@ static int rcar_gen2_usb_phy_probe(struct platform_device *pdev) priv->phy.shutdown = rcar_gen2_usb_phy_shutdown; priv->phy.set_suspend = rcar_gen2_usb_phy_set_suspend; - retval = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2); + retval = usb_add_phy_dev(&priv->phy); if (retval < 0) { dev_err(dev, "Failed to add USB phy\n"); return retval; -- cgit v1.2.3 From 4144bc861ed7934d56f16d2acd808d44af0fcc90 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Fri, 29 Nov 2013 20:17:45 +0100 Subject: usb: cdc-wdm: manage_power should always set needs_remote_wakeup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: stable Reported-by: Oliver Neukum Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 4d387596f3f0..0b23a8639311 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -854,13 +854,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on) { /* need autopm_get/put here to ensure the usbcore sees the new value */ int rv = usb_autopm_get_interface(intf); - if (rv < 0) - goto err; intf->needs_remote_wakeup = on; - usb_autopm_put_interface(intf); -err: - return rv; + if (!rv) + usb_autopm_put_interface(intf); + return 0; } static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) -- cgit v1.2.3 From 52d0dc7597c89b2ab779f3dcb9b9bf0800dd9218 Mon Sep 17 00:00:00 2001 From: Dmitry Kunilov Date: Tue, 3 Dec 2013 12:11:30 -0800 Subject: usb: serial: zte_ev: move support for ZTE AC2726 from zte_ev back to option ZTE AC2726 EVDO modem drops ppp connection every minute when driven by zte_ev but works fine when driven by option. Move the support for AC2726 back to option driver. Signed-off-by: Dmitry Kunilov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ drivers/usb/serial/zte_ev.c | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 496b7e39d5be..cc7a24154490 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -251,6 +251,7 @@ static void option_instat_callback(struct urb *urb); #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_MC2718 0xffe8 +#define ZTE_PRODUCT_AC2726 0xfff1 #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -1453,6 +1454,7 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c index fca4c752a4ed..eae2c873b39f 100644 --- a/drivers/usb/serial/zte_ev.c +++ b/drivers/usb/serial/zte_ev.c @@ -281,8 +281,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x19d2, 0xfffd) }, { USB_DEVICE(0x19d2, 0xfffc) }, { USB_DEVICE(0x19d2, 0xfffb) }, - /* AC2726, AC8710_V3 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) }, + /* AC8710_V3 */ { USB_DEVICE(0x19d2, 0xfff6) }, { USB_DEVICE(0x19d2, 0xfff7) }, { USB_DEVICE(0x19d2, 0xfff8) }, -- cgit v1.2.3 From cc5c9eb67f912cb2c349b04063ff9f444affbc59 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 5 Dec 2013 15:20:49 +0800 Subject: usb: chipidea: host: Only disable the vbus regulator if it is not NULL Commit 40ed51a4b (usb: chipidea: host: add vbus regulator control) introduced a smatch complaint because regulator_disable() is called without checking whether ci->platdata->reg_vbus is not NULL. Fix this by adding the check. This patch is needed for 3.12 stable Cc: stable Reported-by: Dan Carpenter Signed-off-by: Fabio Estevam Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 59e6020ea753..526cd77563d8 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci) return ret; disable_reg: - regulator_disable(ci->platdata->reg_vbus); + if (ci->platdata->reg_vbus) + regulator_disable(ci->platdata->reg_vbus); put_hcd: usb_put_hcd(hcd); -- cgit v1.2.3 From 5a1e1456fc633da5291285b1fff75d2a7507375b Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Thu, 5 Dec 2013 15:20:50 +0800 Subject: usb: chipidea: fix nobody cared IRQ when booting with host role If we connect Male-A-To-Male-A cable between otg-host and host pc, the ci->vbus_active is set wrongly, and cause the controller run at peripheral mode when we load gadget module (ci_udc_start will be run), but the software runs at host mode due to id = 0. The ehci_irq can't handle suspend (USBi_SLI) interrupt which is enabled for peripheral mode, it causes no one will handle irq error. This patch is needed for 3.12 stable Cc: stable Acked-by: Michael Grzeschik Reported-by: Marc Kleine-Budde Tested-by: Marc Kleine-Budde Signed-off-by: Marc Kleine-Budde Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/core.c | 4 ++++ drivers/usb/chipidea/udc.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 5d8981c5235e..6e73f8cd60e5 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -642,6 +642,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) : CI_ROLE_GADGET; } + /* only update vbus status for peripheral */ + if (ci->role == CI_ROLE_GADGET) + ci_handle_vbus_change(ci); + ret = ci_role_start(ci, ci->role); if (ret) { dev_err(dev, "can't start %s role\n", ci_role(ci)->name); diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b34c81969cba..69d20fbb38a2 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1795,9 +1795,6 @@ static int udc_start(struct ci_hdrc *ci) pm_runtime_no_callbacks(&ci->gadget.dev); pm_runtime_enable(&ci->gadget.dev); - /* Update ci->vbus_active */ - ci_handle_vbus_change(ci); - return retval; destroy_eps: -- cgit v1.2.3 From 7005234c18f233d3613b09e9ce4b6ce6977bf246 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 9 Dec 2013 13:10:41 -0600 Subject: usb: wusbcore: fix short transfers If a URB is broken up into multiple transfer segments and a short transfer occurs in any segment other than the last, the URB will currently get stuck in the driver forever. This patch adds a check for a short transfer and cleans up any pending segments so the URB can complete properly. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 128 ++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index a88b8c68ce78..673ad80c1b55 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -1993,7 +1993,7 @@ static int wa_xfer_status_to_errno(u8 status) * the xfer will complete cleanly. */ static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer, - struct wa_seg *incoming_seg) + struct wa_seg *incoming_seg, enum wa_seg_status status) { int index; struct wa_rpipe *rpipe = xfer->ep->hcpriv; @@ -2015,7 +2015,7 @@ static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer, */ case WA_SEG_DELAYED: xfer->segs_done++; - current_seg->status = incoming_seg->status; + current_seg->status = status; break; case WA_SEG_ABORTED: break; @@ -2028,6 +2028,58 @@ static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer, } } +/* Populate the wa->buf_in_urb based on the current transfer state. */ +static int wa_populate_buf_in_urb(struct wahc *wa, struct wa_xfer *xfer, + unsigned int seg_idx, unsigned int bytes_transferred) +{ + int result = 0; + struct wa_seg *seg = xfer->seg[seg_idx]; + + BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); + /* this should always be 0 before a resubmit. */ + wa->buf_in_urb->num_mapped_sgs = 0; + + if (xfer->is_dma) { + wa->buf_in_urb->transfer_dma = xfer->urb->transfer_dma + + (seg_idx * xfer->seg_size); + wa->buf_in_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + wa->buf_in_urb->transfer_buffer = NULL; + wa->buf_in_urb->sg = NULL; + wa->buf_in_urb->num_sgs = 0; + } else { + /* do buffer or SG processing. */ + wa->buf_in_urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP; + + if (xfer->urb->transfer_buffer) { + wa->buf_in_urb->transfer_buffer = + xfer->urb->transfer_buffer + + (seg_idx * xfer->seg_size); + wa->buf_in_urb->sg = NULL; + wa->buf_in_urb->num_sgs = 0; + } else { + /* allocate an SG list to store seg_size bytes + and copy the subset of the xfer->urb->sg + that matches the buffer subset we are + about to read. */ + wa->buf_in_urb->sg = wa_xfer_create_subset_sg( + xfer->urb->sg, + seg_idx * xfer->seg_size, + bytes_transferred, + &(wa->buf_in_urb->num_sgs)); + + if (!(wa->buf_in_urb->sg)) { + wa->buf_in_urb->num_sgs = 0; + result = -ENOMEM; + } + wa->buf_in_urb->transfer_buffer = NULL; + } + } + wa->buf_in_urb->transfer_buffer_length = bytes_transferred; + wa->buf_in_urb->context = seg; + + return result; +} + /* * Process a xfer result completion message * @@ -2041,12 +2093,13 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer, int result; struct device *dev = &wa->usb_iface->dev; unsigned long flags; - u8 seg_idx; + unsigned int seg_idx; struct wa_seg *seg; struct wa_rpipe *rpipe; unsigned done = 0; u8 usb_status; unsigned rpipe_ready = 0; + unsigned bytes_transferred = le32_to_cpu(xfer_result->dwTransferLength); spin_lock_irqsave(&xfer->lock, flags); seg_idx = xfer_result->bTransferSegment & 0x7f; @@ -2079,66 +2132,33 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer, /* FIXME: we ignore warnings, tally them for stats */ if (usb_status & 0x40) /* Warning?... */ usb_status = 0; /* ... pass */ + /* + * If the last segment bit is set, complete the remaining segments. + * When the current segment is completed, either in wa_buf_in_cb for + * transfers with data or below for no data, the xfer will complete. + */ + if (xfer_result->bTransferSegment & 0x80) + wa_complete_remaining_xfer_segs(xfer, seg, WA_SEG_DONE); if (usb_pipeisoc(xfer->urb->pipe)) { /* set up WA state to read the isoc packet status next. */ wa->dti_isoc_xfer_in_progress = wa_xfer_id(xfer); wa->dti_isoc_xfer_seg = seg_idx; wa->dti_state = WA_DTI_ISOC_PACKET_STATUS_PENDING; - } else if (xfer->is_inbound) { /* IN data phase: read to buffer */ + } else if ((xfer->is_inbound) + && (bytes_transferred > 0)) { + /* IN data phase: read to buffer */ seg->status = WA_SEG_DTI_PENDING; - BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); - /* this should always be 0 before a resubmit. */ - wa->buf_in_urb->num_mapped_sgs = 0; - - if (xfer->is_dma) { - wa->buf_in_urb->transfer_dma = - xfer->urb->transfer_dma - + (seg_idx * xfer->seg_size); - wa->buf_in_urb->transfer_flags - |= URB_NO_TRANSFER_DMA_MAP; - wa->buf_in_urb->transfer_buffer = NULL; - wa->buf_in_urb->sg = NULL; - wa->buf_in_urb->num_sgs = 0; - } else { - /* do buffer or SG processing. */ - wa->buf_in_urb->transfer_flags - &= ~URB_NO_TRANSFER_DMA_MAP; - - if (xfer->urb->transfer_buffer) { - wa->buf_in_urb->transfer_buffer = - xfer->urb->transfer_buffer - + (seg_idx * xfer->seg_size); - wa->buf_in_urb->sg = NULL; - wa->buf_in_urb->num_sgs = 0; - } else { - /* allocate an SG list to store seg_size bytes - and copy the subset of the xfer->urb->sg - that matches the buffer subset we are - about to read. */ - wa->buf_in_urb->sg = wa_xfer_create_subset_sg( - xfer->urb->sg, - seg_idx * xfer->seg_size, - le32_to_cpu( - xfer_result->dwTransferLength), - &(wa->buf_in_urb->num_sgs)); - - if (!(wa->buf_in_urb->sg)) { - wa->buf_in_urb->num_sgs = 0; - goto error_sg_alloc; - } - wa->buf_in_urb->transfer_buffer = NULL; - } - } - wa->buf_in_urb->transfer_buffer_length = - le32_to_cpu(xfer_result->dwTransferLength); - wa->buf_in_urb->context = seg; + result = wa_populate_buf_in_urb(wa, xfer, seg_idx, + bytes_transferred); + if (result < 0) + goto error_buf_in_populate; result = usb_submit_urb(wa->buf_in_urb, GFP_ATOMIC); if (result < 0) goto error_submit_buf_in; } else { - /* OUT data phase, complete it -- */ + /* OUT data phase or no data, complete it -- */ seg->status = WA_SEG_DONE; - seg->result = le32_to_cpu(xfer_result->dwTransferLength); + seg->result = bytes_transferred; xfer->segs_done++; rpipe_ready = rpipe_avail_inc(rpipe); done = __wa_xfer_is_done(xfer); @@ -2162,13 +2182,13 @@ error_submit_buf_in: seg->result = result; kfree(wa->buf_in_urb->sg); wa->buf_in_urb->sg = NULL; -error_sg_alloc: +error_buf_in_populate: __wa_xfer_abort(xfer); seg->status = WA_SEG_ERROR; error_complete: xfer->segs_done++; rpipe_ready = rpipe_avail_inc(rpipe); - wa_complete_remaining_xfer_segs(xfer, seg); + wa_complete_remaining_xfer_segs(xfer, seg, seg->status); done = __wa_xfer_is_done(xfer); /* * queue work item to clear STALL for control endpoints. -- cgit v1.2.3 From a2cd612dc9be768b516541b2164c843849bc3bb3 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 9 Dec 2013 13:45:43 -0600 Subject: usb: core: allow isoc URBs for wireless devices with an interval < 6 In usb_submit_urb, do not fail if an isoc URB for a wireless USB device has an interval < 6. Per WUSB spec, isoc endpoints can support values from 1-16. Valid values for interrupt URBs for wireless USB devices are still 6-16. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index e62208356c89..07c58af6b5c0 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -492,9 +492,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* too small? */ switch (dev->speed) { case USB_SPEED_WIRELESS: - if (urb->interval < 6) + if ((urb->interval < 6) + && (xfertype == USB_ENDPOINT_XFER_INT)) return -EINVAL; - break; default: if (urb->interval <= 0) return -EINVAL; -- cgit v1.2.3 From 83e83ecb79a8225e79bc8e54e9aff3e0e27658a2 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 9 Dec 2013 13:40:29 -0600 Subject: usb: core: get config and string descriptors for unauthorized devices There is no need to skip querying the config and string descriptors for unauthorized WUSB devices when usb_new_device is called. It is allowed by WUSB spec. The only action that needs to be delayed until authorization time is the set config. This change allows user mode tools to see the config and string descriptors earlier in enumeration which is needed for some WUSB devices to function properly on Android systems. It also reduces the amount of divergent code paths needed for WUSB devices. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 7 ------- drivers/usb/core/hub.c | 39 +++++++-------------------------------- 2 files changed, 7 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index a6b2cabe7930..548d1996590f 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -651,10 +651,6 @@ void usb_destroy_configuration(struct usb_device *dev) * * hub-only!! ... and only in reset path, or usb_new_device() * (used by real hubs and virtual root hubs) - * - * NOTE: if this is a WUSB device and is not authorized, we skip the - * whole thing. A non-authorized USB device has no - * configurations. */ int usb_get_configuration(struct usb_device *dev) { @@ -666,8 +662,6 @@ int usb_get_configuration(struct usb_device *dev) struct usb_config_descriptor *desc; cfgno = 0; - if (dev->authorized == 0) /* Not really an error */ - goto out_not_authorized; result = -ENOMEM; if (ncfg > USB_MAXCONFIG) { dev_warn(ddev, "too many configurations: %d, " @@ -751,7 +745,6 @@ int usb_get_configuration(struct usb_device *dev) err: kfree(desc); -out_not_authorized: dev->descriptor.bNumConfigurations = cfgno; err2: if (result == -ENOMEM) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a7c04e24ca48..32e1035d4f59 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2235,17 +2235,13 @@ static int usb_enumerate_device(struct usb_device *udev) return err; } } - if (udev->wusb == 1 && udev->authorized == 0) { - udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); - udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); - udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); - } else { - /* read the standard strings and cache them if present */ - udev->product = usb_cache_string(udev, udev->descriptor.iProduct); - udev->manufacturer = usb_cache_string(udev, - udev->descriptor.iManufacturer); - udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); - } + + /* read the standard strings and cache them if present */ + udev->product = usb_cache_string(udev, udev->descriptor.iProduct); + udev->manufacturer = usb_cache_string(udev, + udev->descriptor.iManufacturer); + udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); + err = usb_enumerate_device_otg(udev); if (err < 0) return err; @@ -2427,16 +2423,6 @@ int usb_deauthorize_device(struct usb_device *usb_dev) usb_dev->authorized = 0; usb_set_configuration(usb_dev, -1); - kfree(usb_dev->product); - usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->manufacturer); - usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->serial); - usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); - - usb_destroy_configuration(usb_dev); - usb_dev->descriptor.bNumConfigurations = 0; - out_unauthorized: usb_unlock_device(usb_dev); return 0; @@ -2464,17 +2450,7 @@ int usb_authorize_device(struct usb_device *usb_dev) goto error_device_descriptor; } - kfree(usb_dev->product); - usb_dev->product = NULL; - kfree(usb_dev->manufacturer); - usb_dev->manufacturer = NULL; - kfree(usb_dev->serial); - usb_dev->serial = NULL; - usb_dev->authorized = 1; - result = usb_enumerate_device(usb_dev); - if (result < 0) - goto error_enumerate; /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. */ @@ -2490,7 +2466,6 @@ int usb_authorize_device(struct usb_device *usb_dev) } dev_info(&usb_dev->dev, "authorized to connect\n"); -error_enumerate: error_device_descriptor: usb_autosuspend_device(usb_dev); error_autoresume: -- cgit v1.2.3 From 7b3e3740f2d0faca9351db88974be534009a3d8d Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 9 Dec 2013 13:19:08 -0600 Subject: usb: wusbcore: use USB_CTRL_SET_TIMEOUT and USB_CTRL_GET_TIMEOUT Use USB_CTRL_SET_TIMEOUT and USB_CTRL_GET_TIMEOUT for USB control messages instead of an arbitrary 1s timeout value. This is particularly useful for WUSB since in the worst case RF scanario, a WUSB device can be unresponsive for up to 4s and still be connected. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/hwa-hc.c | 20 ++++++++++---------- drivers/usb/wusbcore/cbaf.c | 8 ++++---- drivers/usb/wusbcore/security.c | 22 ++++++++++++---------- drivers/usb/wusbcore/wa-hc.h | 5 ++--- drivers/usb/wusbcore/wa-rpipe.c | 10 +++++----- 5 files changed, 33 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 7fd3f9bd7b83..f0b97bb08791 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -86,7 +86,7 @@ static int __hwahc_set_cluster_id(struct hwahc *hwahc, u8 cluster_id) USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, cluster_id, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) dev_err(dev, "Cannot set WUSB Cluster ID to 0x%02x: %d\n", cluster_id, result); @@ -106,7 +106,7 @@ static int __hwahc_op_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots) USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, interval << 8 | slots, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); } /* @@ -281,7 +281,7 @@ static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay) USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, delay * 1000, iface_no, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); if (ret == 0) msleep(delay); @@ -310,7 +310,7 @@ static int __hwahc_op_bwa_set(struct wusbhc *wusbhc, s8 stream_index, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, stream_index, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "Cannot set WUSB stream index: %d\n", result); goto out; @@ -321,7 +321,7 @@ static int __hwahc_op_bwa_set(struct wusbhc *wusbhc, s8 stream_index, WUSB_REQ_SET_WUSB_MAS, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - mas_le, 32, 1000 /* FIXME: arbitrary */); + mas_le, 32, USB_CTRL_SET_TIMEOUT); if (result < 0) dev_err(dev, "Cannot set WUSB MAS allocation: %d\n", result); out: @@ -355,7 +355,7 @@ static int __hwahc_op_mmcie_add(struct wusbhc *wusbhc, u8 interval, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, interval << 8 | repeat_cnt, handle << 8 | iface_no, - wuie, wuie->bLength, 1000 /* FIXME: arbitrary */); + wuie, wuie->bLength, USB_CTRL_SET_TIMEOUT); } /* @@ -372,7 +372,7 @@ static int __hwahc_op_mmcie_rm(struct wusbhc *wusbhc, u8 handle) WUSB_REQ_REMOVE_MMC_IE, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, handle << 8 | iface_no, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); } /* @@ -415,7 +415,7 @@ static int __hwahc_op_dev_info_set(struct wusbhc *wusbhc, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, wusb_dev->port_idx << 8 | iface_no, dev_info, sizeof(struct hwa_dev_info), - 1000 /* FIXME: arbitrary */); + USB_CTRL_SET_TIMEOUT); kfree(dev_info); return ret; } @@ -455,7 +455,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_DT_KEY << 8 | key_idx, port_idx << 8 | iface_no, - keyd, keyd_len, 1000 /* FIXME: arbitrary */); + keyd, keyd_len, USB_CTRL_SET_TIMEOUT); kzfree(keyd); /* clear keys etc. */ return result; @@ -497,7 +497,7 @@ static int __hwahc_op_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, USB_REQ_SET_ENCRYPTION, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, encryption_value, port_idx << 8 | iface_no, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) dev_err(wusbhc->dev, "Can't set host's WUSB encryption for " "port index %u to %s (value %d): %d\n", port_idx, diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index f06ed82e63d1..56310fc9b9c3 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c @@ -144,7 +144,7 @@ static int cbaf_check(struct cbaf *cbaf) CBAF_REQ_GET_ASSOCIATION_INFORMATION, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - cbaf->buffer, cbaf->buffer_size, 1000 /* FIXME: arbitrary */); + cbaf->buffer, cbaf->buffer_size, USB_CTRL_GET_TIMEOUT); if (result < 0) { dev_err(dev, "Cannot get available association types: %d\n", result); @@ -265,7 +265,7 @@ static int cbaf_send_host_info(struct cbaf *cbaf) USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0x0101, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - hi, hi_size, 1000 /* FIXME: arbitrary */); + hi, hi_size, USB_CTRL_SET_TIMEOUT); } /* @@ -288,7 +288,7 @@ static int cbaf_cdid_get(struct cbaf *cbaf) CBAF_REQ_GET_ASSOCIATION_REQUEST, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0x0200, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - di, cbaf->buffer_size, 1000 /* FIXME: arbitrary */); + di, cbaf->buffer_size, USB_CTRL_GET_TIMEOUT); if (result < 0) { dev_err(dev, "Cannot request device information: %d\n", result); return result; @@ -536,7 +536,7 @@ static int cbaf_cc_upload(struct cbaf *cbaf) CBAF_REQ_SET_ASSOCIATION_RESPONSE, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - ccd, sizeof(*ccd), 1000 /* FIXME: arbitrary */); + ccd, sizeof(*ccd), USB_CTRL_SET_TIMEOUT); return result; } diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index dd88441c8f78..66655e8f2308 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -168,7 +168,7 @@ static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value) result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), USB_REQ_SET_ENCRYPTION, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - value, 0, NULL, 0, 1000 /* FIXME: arbitrary */); + value, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) dev_err(dev, "Can't set device's WUSB encryption to " "%s (value %d): %d\n", @@ -192,7 +192,7 @@ static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, USB_DT_KEY << 8 | wusbhc->gtk_index, 0, &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, - 1000); + USB_CTRL_SET_TIMEOUT); } @@ -302,8 +302,9 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) /* Set address 0 */ result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_ADDRESS, 0, - 0, 0, NULL, 0, 1000 /* FIXME: arbitrary */); + USB_REQ_SET_ADDRESS, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "auth failed: can't set address 0: %d\n", result); @@ -317,9 +318,10 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) /* Set new (authenticated) address. */ result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_ADDRESS, 0, - new_address, 0, NULL, 0, - 1000 /* FIXME: arbitrary */); + USB_REQ_SET_ADDRESS, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + new_address, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "auth failed: can't set address %u: %d\n", new_address, result); @@ -382,7 +384,7 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, usb_dev, usb_sndctrlpipe(usb_dev, 0), USB_REQ_SET_HANDSHAKE, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 1, 0, &hs[0], sizeof(hs[0]), 1000 /* FIXME: arbitrary */); + 1, 0, &hs[0], sizeof(hs[0]), USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "Handshake1: request failed: %d\n", result); goto error_hs1; @@ -393,7 +395,7 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, usb_dev, usb_rcvctrlpipe(usb_dev, 0), USB_REQ_GET_HANDSHAKE, USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 2, 0, &hs[1], sizeof(hs[1]), 1000 /* FIXME: arbitrary */); + 2, 0, &hs[1], sizeof(hs[1]), USB_CTRL_GET_TIMEOUT); if (result < 0) { dev_err(dev, "Handshake2: request failed: %d\n", result); goto error_hs2; @@ -470,7 +472,7 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, usb_dev, usb_sndctrlpipe(usb_dev, 0), USB_REQ_SET_HANDSHAKE, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 3, 0, &hs[2], sizeof(hs[2]), 1000 /* FIXME: arbitrary */); + 3, 0, &hs[2], sizeof(hs[2]), USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "Handshake3: request failed: %d\n", result); goto error_hs3; diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h index 5b6ae3a4a755..b93d2cbdf33f 100644 --- a/drivers/usb/wusbcore/wa-hc.h +++ b/drivers/usb/wusbcore/wa-hc.h @@ -366,7 +366,7 @@ static inline int __wa_feature(struct wahc *wa, unsigned op, u16 feature) USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, feature, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); + NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -400,8 +400,7 @@ s32 __wa_get_status(struct wahc *wa) USB_REQ_GET_STATUS, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - &wa->status, sizeof(wa->status), - 1000 /* FIXME: arbitrary */); + &wa->status, sizeof(wa->status), USB_CTRL_GET_TIMEOUT); if (result >= 0) result = wa->status; return result; diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index b48e74cc54d7..accdd15f5393 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c @@ -80,7 +80,7 @@ static int __rpipe_get_descr(struct wahc *wa, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_RPIPE, USB_DT_RPIPE<<8, index, descr, sizeof(*descr), - 1000 /* FIXME: arbitrary */); + USB_CTRL_GET_TIMEOUT); if (result < 0) { dev_err(dev, "rpipe %u: get descriptor failed: %d\n", index, (int)result); @@ -118,7 +118,7 @@ static int __rpipe_set_descr(struct wahc *wa, USB_REQ_SET_DESCRIPTOR, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, USB_DT_RPIPE<<8, index, descr, sizeof(*descr), - HZ / 10); + USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "rpipe %u: set descriptor failed: %d\n", index, (int)result); @@ -237,7 +237,7 @@ static int __rpipe_reset(struct wahc *wa, unsigned index) wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), USB_REQ_RPIPE_RESET, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); + 0, index, NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) dev_err(dev, "rpipe %u: reset failed: %d\n", index, result); @@ -527,7 +527,7 @@ void rpipe_ep_disable(struct wahc *wa, struct usb_host_endpoint *ep) wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), USB_REQ_RPIPE_ABORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); + 0, index, NULL, 0, USB_CTRL_SET_TIMEOUT); rpipe_put(rpipe); } mutex_unlock(&wa->rpipe_mutex); @@ -548,7 +548,7 @@ void rpipe_clear_feature_stalled(struct wahc *wa, struct usb_host_endpoint *ep) wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), USB_REQ_CLEAR_FEATURE, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - RPIPE_STALL, index, NULL, 0, 1000); + RPIPE_STALL, index, NULL, 0, USB_CTRL_SET_TIMEOUT); } mutex_unlock(&wa->rpipe_mutex); } -- cgit v1.2.3 From ea1af42d3d4da73c9d75984f24e569515261b3fd Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 9 Dec 2013 14:15:14 -0600 Subject: usb: wusbcore: move isoc_frame_index from wa_xfer to wa_seg If multiple segments belonging to an isoc transfer are submitted concurrently, the isoc_frame_index field in struct wa_xfer can get corrupted. This patch moves the isoc_frame_index field from struct wa_xfer to struct wa_seg to prevent this from happening. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 673ad80c1b55..6aeb52cdc3fb 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -124,6 +124,8 @@ struct wa_seg { u8 index; /* which segment we are */ int isoc_frame_count; /* number of isoc frames in this segment. */ int isoc_frame_offset; /* starting frame offset in the xfer URB. */ + /* Isoc frame that the current transfer buffer corresponds to. */ + int isoc_frame_index; int isoc_size; /* size of all isoc frames sent by this seg. */ enum wa_seg_status status; ssize_t result; /* bytes xfered or error */ @@ -158,8 +160,6 @@ struct wa_xfer { unsigned is_dma:1; size_t seg_size; int result; - /* Isoc frame that the current transfer buffer corresponds to. */ - int dto_isoc_frame_index; gfp_t gfp; /* allocation mask */ @@ -701,23 +701,23 @@ static void wa_seg_dto_cb(struct urb *urb) if (usb_pipeisoc(xfer->urb->pipe)) { /* Alereon HWA sends all isoc frames in a single transfer. */ if (wa->quirks & WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC) - xfer->dto_isoc_frame_index += seg->isoc_frame_count; + seg->isoc_frame_index += seg->isoc_frame_count; else - xfer->dto_isoc_frame_index += 1; - if (xfer->dto_isoc_frame_index < seg->isoc_frame_count) { + seg->isoc_frame_index += 1; + if (seg->isoc_frame_index < seg->isoc_frame_count) { data_send_done = 0; holding_dto = 1; /* checked in error cases. */ /* * if this is the last isoc frame of the segment, we * can release DTO after sending this frame. */ - if ((xfer->dto_isoc_frame_index + 1) >= + if ((seg->isoc_frame_index + 1) >= seg->isoc_frame_count) release_dto = 1; } dev_dbg(dev, "xfer 0x%08X#%u: isoc frame = %d, holding_dto = %d, release_dto = %d.\n", - wa_xfer_id(xfer), seg->index, - xfer->dto_isoc_frame_index, holding_dto, release_dto); + wa_xfer_id(xfer), seg->index, seg->isoc_frame_index, + holding_dto, release_dto); } spin_unlock_irqrestore(&xfer->lock, flags); @@ -737,8 +737,7 @@ static void wa_seg_dto_cb(struct urb *urb) * send the URB and release DTO if we no longer need it. */ __wa_populate_dto_urb_isoc(xfer, seg, - seg->isoc_frame_offset + - xfer->dto_isoc_frame_index); + seg->isoc_frame_offset + seg->isoc_frame_index); /* resubmit the URB with the next isoc frame. */ result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC); @@ -1324,12 +1323,12 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer, struct wahc *wa = xfer->wa; result = usb_submit_urb(seg->isoc_pack_desc_urb, GFP_ATOMIC); + seg->isoc_frame_index = 0; if (result < 0) { pr_err("%s: xfer %p#%u: ISO packet descriptor submit failed: %d\n", __func__, xfer, seg->index, result); goto error_iso_pack_desc_submit; } - xfer->dto_isoc_frame_index = 0; /* * If this segment contains more than one isoc frame, hold * onto the dto resource until we send all frames. -- cgit v1.2.3 From 756a2eed67e61e9596c2b49a787441c2e0daf1e1 Mon Sep 17 00:00:00 2001 From: Thomas Pugliese Date: Mon, 9 Dec 2013 14:15:15 -0600 Subject: usb: wusbcore: set packet count correctly on isoc transfers This patch correctly sets the dwNumOfPackets field of the HWA transfer request for isochronous transfers with multiple segments. Previously all segments used the value that was set for the first segment which may not be correct. Signed-off-by: Thomas Pugliese Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 6aeb52cdc3fb..a70e142da330 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -1259,8 +1259,11 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb) for (cnt = 1; cnt < xfer->segs; cnt++) { struct wa_xfer_packet_info_hwaiso *packet_desc; struct wa_seg *seg = xfer->seg[cnt]; + struct wa_xfer_hwaiso *xfer_iso; xfer_hdr = &seg->xfer_hdr; + xfer_iso = container_of(xfer_hdr, + struct wa_xfer_hwaiso, hdr); packet_desc = ((void *)xfer_hdr) + xfer_hdr_size; /* * Copy values from the 0th header. Segment specific @@ -1270,6 +1273,8 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb) xfer_hdr->bTransferSegment = cnt; xfer_hdr->dwTransferLength = cpu_to_le32(seg->isoc_size); + xfer_iso->dwNumOfPackets = + cpu_to_le32(seg->isoc_frame_count); __wa_setup_isoc_packet_descr(packet_desc, xfer, seg); seg->status = WA_SEG_READY; } -- cgit v1.2.3 From ebb034a4ce9fc37877b3df2b85b9c33d43349586 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Dec 2013 01:39:34 -0200 Subject: PCI: imx6: Remove unneeded check of platform_get_resource() When using devm_ioremap_resource(), we do not need to check the return value of platform_get_resource(), so just remove it. Signed-off-by: Fabio Estevam Signed-off-by: Bjorn Helgaas Acked-by: Marek Vasut --- drivers/pci/host/pci-imx6.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index bd70af8f31ac..5002e2381588 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -426,11 +426,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "imprecise external abort"); dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!dbi_base) { - dev_err(&pdev->dev, "dbi_base memory resource not found\n"); - return -ENODEV; - } - pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base); if (IS_ERR(pp->dbi_base)) { ret = PTR_ERR(pp->dbi_base); -- cgit v1.2.3 From be3f48cb21c1ca4907a0822eea406c8dd4a73ddb Mon Sep 17 00:00:00 2001 From: Bjørn Erik Nilsen Date: Fri, 29 Nov 2013 14:35:24 +0100 Subject: PCI: designware: Fix crash in dw_msi_teardown_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 904d0e788993 ("PCI: designware: Add irq_create_mapping()") resulted in pre-allocated irq descs. Problem was that in assign_irq() these descs were explicitly allocated and hence also freed, resulting in a crash. We also need to clear the entire irq range in teardown. With this commit the teardown basically does exactly the opposite of what was done in setup. The crash this fixes looks like: Unable to handle kernel NULL pointer dereference at virtual address 00000020 PC is at dw_msi_teardown_irq+0x40/0x118 LR is at trace_hardirqs_on_caller+0xf4/0x1c0 Backtrace: [<802c401c>] (dw_msi_teardown_irq+0x0/0x118) from [<802c1844>] (arch_teardown_msi_irq+0x3c/0x40) [<802c1808>] (arch_teardown_msi_irq+0x0/0x40) from [<802c1a08>] (default_teardown_msi_irqs+0x68/0x84) [<802c19a0>] (default_teardown_msi_irqs+0x0/0x84) from [<802c1a34>] (arch_teardown_msi_irqs+0x10/0x14) [<802c1a24>] (arch_teardown_msi_irqs+0x0/0x14) from [<802c1ad0>] (free_msi_irqs+0x98/0x144) [<802c1a38>] (free_msi_irqs+0x0/0x144) from [<802c2570>] (pci_disable_msi+0x48/0x60) [<802c2528>] (pci_disable_msi+0x0/0x60) from [<7f0057d4>] (sxdma_irq_free+0x44/0x48 [sxdma]) [bhelgaas: add crash info] Tested-by: Mohit Kumar Signed-off-by: Bjørn Erik Nilsen Signed-off-by: Bjorn Helgaas Acked-by: Marek Vasut Acked-by: Jingoo Han --- drivers/pci/host/pcie-designware.c | 49 ++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index e33b68be0391..61345a18a6d1 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -209,6 +209,25 @@ static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0) return 0; } +static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, + unsigned int nvec, unsigned int pos) +{ + unsigned int i, res, bit, val; + + i = 0; + while (i < nvec) { + irq_set_msi_desc_off(irq_base, i, NULL); + clear_bit(pos + i, pp->msi_irq_in_use); + /* Disable corresponding interrupt on MSI interrupt controller */ + res = ((pos + i) / 32) * 12; + bit = (pos + i) % 32; + dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); + val &= ~(1 << bit); + dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); + ++i; + } +} + static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) { int res, bit, irq, pos0, pos1, i; @@ -242,11 +261,20 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) if (!irq) goto no_valid_irq; + /* + * irq_create_mapping (called from dw_pcie_host_init) pre-allocates + * descs so there is no need to allocate descs here. We can therefore + * assume that if irq_find_mapping above returns non-zero, then the + * descs are also successfully allocated. + */ + i = 0; while (i < no_irqs) { + if (irq_set_msi_desc_off(irq, i, desc) != 0) { + clear_irq_range(pp, irq, i, pos0); + goto no_valid_irq; + } set_bit(pos0 + i, pp->msi_irq_in_use); - irq_alloc_descs((irq + i), (irq + i), 1, 0); - irq_set_msi_desc(irq + i, desc); /*Enable corresponding interrupt in MSI interrupt controller */ res = ((pos0 + i) / 32) * 12; bit = (pos0 + i) % 32; @@ -266,7 +294,7 @@ no_valid_irq: static void clear_irq(unsigned int irq) { - int res, bit, val, pos; + unsigned int pos, nvec; struct irq_desc *desc; struct msi_desc *msi; struct pcie_port *pp; @@ -281,18 +309,15 @@ static void clear_irq(unsigned int irq) return; } + /* undo what was done in assign_irq */ pos = data->hwirq; + nvec = 1 << msi->msi_attrib.multiple; - irq_free_desc(irq); - - clear_bit(pos, pp->msi_irq_in_use); + clear_irq_range(pp, irq, nvec, pos); - /* Disable corresponding interrupt on MSI interrupt controller */ - res = (pos / 32) * 12; - bit = pos % 32; - dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); - val &= ~(1 << bit); - dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); + /* all irqs cleared; reset attributes */ + msi->irq = 0; + msi->msi_attrib.multiple = 0; } static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, -- cgit v1.2.3 From 64989e7399f09b72689e25fb40f2d0d5e073b13a Mon Sep 17 00:00:00 2001 From: Bjørn Erik Nilsen Date: Fri, 29 Nov 2013 14:35:25 +0100 Subject: PCI: designware: Remove redundant call to pci_write_config_word() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit write_msi_msg() does exactly the same so there is no need to explicitly call pci_write_config_word() and do the same twice. Tested-by: Mohit Kumar Signed-off-by: Bjørn Erik Nilsen Signed-off-by: Bjorn Helgaas Acked-by: Marek Vasut Acked-by: Jingoo Han --- drivers/pci/host/pcie-designware.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 61345a18a6d1..5274085ecd4b 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -345,10 +345,10 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, if (irq < 0) return irq; - msg_ctr &= ~PCI_MSI_FLAGS_QSIZE; - msg_ctr |= msgvec << 4; - pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS, - msg_ctr); + /* + * write_msi_msg() will update PCI_MSI_FLAGS so there is + * no need to explicitly call pci_write_config_word(). + */ desc->msi_attrib.multiple = msgvec; msg.address_lo = virt_to_phys((void *)pp->msi_data); -- cgit v1.2.3 From 0b8cfb6aa3aabc96177b1e68ef13d2eb5c686606 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 9 Dec 2013 15:11:25 -0700 Subject: PCI: designware: Use typical "for" loop idiom It's conventional to use "for" rather than "while" for simple iteration. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-designware.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 5274085ecd4b..1c92833a4ed3 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -214,8 +214,7 @@ static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, { unsigned int i, res, bit, val; - i = 0; - while (i < nvec) { + for (i = 0; i < nvec; i++) { irq_set_msi_desc_off(irq_base, i, NULL); clear_bit(pos + i, pp->msi_irq_in_use); /* Disable corresponding interrupt on MSI interrupt controller */ @@ -224,7 +223,6 @@ static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); val &= ~(1 << bit); dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); - ++i; } } @@ -268,8 +266,7 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) * descs are also successfully allocated. */ - i = 0; - while (i < no_irqs) { + for (i = 0; i < no_irqs; i++) { if (irq_set_msi_desc_off(irq, i, desc) != 0) { clear_irq_range(pp, irq, i, pos0); goto no_valid_irq; @@ -281,7 +278,6 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); val |= 1 << bit; dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); - i++; } *pos = pos0; -- cgit v1.2.3 From b391bf31584d879d7455e882a5e200388c8be9ac Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Dec 2013 01:39:35 -0200 Subject: PCI: imx6: Remove unneeded 'goto err' There is no need to use 'goto err' as we can directly return the errors. No functional change. Signed-off-by: Fabio Estevam Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 5002e2381588..9fc1cb66c64e 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -427,10 +427,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base); - if (IS_ERR(pp->dbi_base)) { - ret = PTR_ERR(pp->dbi_base); - goto err; - } + if (IS_ERR(pp->dbi_base)) + return PTR_ERR(pp->dbi_base); /* Fetch GPIOs */ imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); @@ -444,7 +442,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "PCIe reset"); if (ret) { dev_err(&pdev->dev, "unable to get reset gpio\n"); - goto err; + return ret; } imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); @@ -455,7 +453,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "PCIe power enable"); if (ret) { dev_err(&pdev->dev, "unable to get power-on gpio\n"); - goto err; + return ret; } } @@ -467,7 +465,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "PCIe wake up"); if (ret) { dev_err(&pdev->dev, "unable to get wake-up gpio\n"); - goto err; + return ret; } } @@ -479,7 +477,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "PCIe disable endpoint"); if (ret) { dev_err(&pdev->dev, "unable to get disable-ep gpio\n"); - goto err; + return ret; } } @@ -488,32 +486,28 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) if (IS_ERR(imx6_pcie->lvds_gate)) { dev_err(&pdev->dev, "lvds_gate clock select missing or invalid\n"); - ret = PTR_ERR(imx6_pcie->lvds_gate); - goto err; + return PTR_ERR(imx6_pcie->lvds_gate); } imx6_pcie->sata_ref_100m = devm_clk_get(&pdev->dev, "sata_ref_100m"); if (IS_ERR(imx6_pcie->sata_ref_100m)) { dev_err(&pdev->dev, "sata_ref_100m clock source missing or invalid\n"); - ret = PTR_ERR(imx6_pcie->sata_ref_100m); - goto err; + return PTR_ERR(imx6_pcie->sata_ref_100m); } imx6_pcie->pcie_ref_125m = devm_clk_get(&pdev->dev, "pcie_ref_125m"); if (IS_ERR(imx6_pcie->pcie_ref_125m)) { dev_err(&pdev->dev, "pcie_ref_125m clock source missing or invalid\n"); - ret = PTR_ERR(imx6_pcie->pcie_ref_125m); - goto err; + return PTR_ERR(imx6_pcie->pcie_ref_125m); } imx6_pcie->pcie_axi = devm_clk_get(&pdev->dev, "pcie_axi"); if (IS_ERR(imx6_pcie->pcie_axi)) { dev_err(&pdev->dev, "pcie_axi clock source missing or invalid\n"); - ret = PTR_ERR(imx6_pcie->pcie_axi); - goto err; + return PTR_ERR(imx6_pcie->pcie_axi); } /* Grab GPR config register range */ @@ -521,19 +515,15 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); if (IS_ERR(imx6_pcie->iomuxc_gpr)) { dev_err(&pdev->dev, "unable to find iomuxc registers\n"); - ret = PTR_ERR(imx6_pcie->iomuxc_gpr); - goto err; + return PTR_ERR(imx6_pcie->iomuxc_gpr); } ret = imx6_add_pcie_port(pp, pdev); if (ret < 0) - goto err; + return ret; platform_set_drvdata(pdev, imx6_pcie); return 0; - -err: - return ret; } static const struct of_device_id imx6_pcie_of_match[] = { -- cgit v1.2.3 From 3166950070ce6b9d1443758d82c0a42779a02153 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:24:07 +0900 Subject: net: sfc: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 958d8c7fa02f..12f60e782868 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2643,7 +2643,6 @@ static void efx_pci_remove(struct pci_dev *pci_dev) netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n"); efx_fini_struct(efx); - pci_set_drvdata(pci_dev, NULL); free_netdev(efx->net_dev); pci_disable_pcie_error_reporting(pci_dev); @@ -2837,7 +2836,6 @@ static int efx_pci_probe(struct pci_dev *pci_dev, fail2: efx_fini_struct(efx); fail1: - pci_set_drvdata(pci_dev, NULL); WARN_ON(rc > 0); netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc); free_netdev(net_dev); -- cgit v1.2.3 From e104637e35501a91d61f0434f3b9a7bbacd2b70a Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:25:44 +0900 Subject: net: sis900: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/sis/sis900.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 975dc2d8e548..ff57a46388ee 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -576,7 +576,6 @@ err_unmap_tx: err_out_unmap: pci_iounmap(pci_dev, ioaddr); err_out_cleardev: - pci_set_drvdata(pci_dev, NULL); pci_release_regions(pci_dev); err_out: free_netdev(net_dev); @@ -2427,7 +2426,6 @@ static void sis900_remove(struct pci_dev *pci_dev) pci_iounmap(pci_dev, sis_priv->ioaddr); free_netdev(net_dev); pci_release_regions(pci_dev); - pci_set_drvdata(pci_dev, NULL); } #ifdef CONFIG_PM -- cgit v1.2.3 From add0cdb43a421239c1ca6ebe6fc2b591b37dbc00 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:26:44 +0900 Subject: net: bna: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bnad.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 248bc37cb41b..3d151bd1635e 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3262,7 +3262,6 @@ bnad_uninit(struct bnad *bnad) if (bnad->bar0) iounmap(bnad->bar0); - pci_set_drvdata(bnad->pcidev, NULL); } /* -- cgit v1.2.3 From e28f4d595186cc02beaffd1952b82d3d8147c556 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:27:27 +0900 Subject: net: ns83820: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/ns83820.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 5213e73f0ea5..dbccf1de49ec 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -2235,7 +2235,6 @@ out_disable: pci_disable_device(pci_dev); out_free: free_netdev(ndev); - pci_set_drvdata(pci_dev, NULL); out: return err; } @@ -2259,7 +2258,6 @@ static void ns83820_remove_one(struct pci_dev *pci_dev) dev->rx_info.descs, dev->rx_info.phy_descs); pci_disable_device(dev->pci_dev); free_netdev(ndev); - pci_set_drvdata(pci_dev, NULL); } static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = { -- cgit v1.2.3 From 3722c1b094f33322da55b69fdfafa9cbeb1a3177 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:27:50 +0900 Subject: net: forcedeth: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/nvidia/forcedeth.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index ab67babbfdd1..d8bdaf6d82d2 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -6017,7 +6017,6 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) out_error: if (phystate_orig) writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl); - pci_set_drvdata(pci_dev, NULL); out_freering: free_rings(dev); out_unmap: @@ -6088,7 +6087,6 @@ static void nv_remove(struct pci_dev *pci_dev) pci_release_regions(pci_dev); pci_disable_device(pci_dev); free_netdev(dev); - pci_set_drvdata(pci_dev, NULL); } #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From 12c51e13a1e54a2604e311b6fba01cb61636210b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:28:28 +0900 Subject: irda: via-ircc: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/irda/via-ircc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 26cb45d59702..2900af091c2d 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -407,7 +407,6 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id) err_out2: release_region(self->io.fir_base, self->io.fir_ext); err_out1: - pci_set_drvdata(pdev, NULL); free_netdev(dev); return err; } @@ -441,7 +440,6 @@ static void via_remove_one(struct pci_dev *pdev) if (self->rx_buff.head) dma_free_coherent(&pdev->dev, self->rx_buff.truesize, self->rx_buff.head, self->rx_buff_dma); - pci_set_drvdata(pdev, NULL); free_netdev(self->netdev); -- cgit v1.2.3 From 825d15de0e6698ba23790870edb031a5c120819b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:29:08 +0900 Subject: irda: vlsi_ir: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/irda/vlsi_ir.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index cc9b8665e73c..485006604bbc 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1693,7 +1693,6 @@ out_freedev: out_disable: pci_disable_device(pdev); out: - pci_set_drvdata(pdev, NULL); return -ENODEV; } @@ -1719,8 +1718,6 @@ static void vlsi_irda_remove(struct pci_dev *pdev) free_netdev(ndev); - pci_set_drvdata(pdev, NULL); - IRDA_MESSAGE("%s: %s removed\n", drivername, pci_name(pdev)); } -- cgit v1.2.3 From 3c0d6d32eacf0f331636b804188ff8a2c9d740eb Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:29:46 +0900 Subject: wan: dscc4: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wan/dscc4.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 851dc7b7e8b0..288610df205c 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -699,8 +699,6 @@ static void dscc4_free1(struct pci_dev *pdev) for (i = 0; i < dev_per_card; i++) unregister_hdlc_device(dscc4_to_dev(root + i)); - pci_set_drvdata(pdev, NULL); - for (i = 0; i < dev_per_card; i++) free_netdev(root[i].dev); kfree(root); -- cgit v1.2.3 From 94d6b538c7d2b273c34f36b2c55a332074b4940d Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:30:41 +0900 Subject: wan: lmc: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wan/lmc/lmc_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 7ef435bab425..c59b91f03660 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -973,7 +973,6 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err_hdlcdev: - pci_set_drvdata(pdev, NULL); kfree(sc); err_kzalloc: pci_release_regions(pdev); @@ -995,7 +994,6 @@ static void lmc_remove_one(struct pci_dev *pdev) free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); } } -- cgit v1.2.3 From 06bbd681904d80aa76ed132fcc37d8887799b1cd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:31:12 +0900 Subject: wan: pc300too: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wan/pc300too.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index 53efc57fcace..5b72f7f8c516 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -281,7 +281,6 @@ static void pc300_pci_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); if (card->ports[0].netdev) free_netdev(card->ports[0].netdev); if (card->ports[1].netdev) -- cgit v1.2.3 From 9e2c921f1dd2fa7695cbfebe6adad1b65fef67b5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:31:46 +0900 Subject: wan: pci200syn: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wan/pci200syn.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index ddbce54040e2..fe4e3ece3c42 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -260,7 +260,6 @@ static void pci200_pci_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); if (card->ports[0].netdev) free_netdev(card->ports[0].netdev); if (card->ports[1].netdev) -- cgit v1.2.3 From 42cd36abdf686264f25e6cb44e318fece3ab8805 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 12:32:10 +0900 Subject: wan: wanxl: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wan/wanxl.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 4c0a69779b89..f76aa9081585 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -542,7 +542,6 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); kfree(card); } -- cgit v1.2.3 From fb178d8b2fab3f2a9f203c13ffe80cfd6e01bdf1 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Wed, 4 Dec 2013 20:33:35 +0400 Subject: PCI: rcar: Add runtime PM support If runtime PM is enabled in the kernel config, the PCI clocks are not forced on at start-up, and thus, are never enabled. Use pm_runtime_get_sync() to enable the clocks. While at it, use dev_info() instead of pr_info() since now we have the device pointer available in the PCI setup callback. Signed-off-by: Valentine Barshak Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-rcar-gen2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index 96d118242ae2..ceec147baec3 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* AHB-PCI Bridge PCI communication registers */ @@ -77,6 +78,7 @@ #define RCAR_PCI_NR_CONTROLLERS 3 struct rcar_pci_priv { + struct device *dev; void __iomem *reg; struct resource io_res; struct resource mem_res; @@ -169,8 +171,11 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) void __iomem *reg = priv->reg; u32 val; + pm_runtime_enable(priv->dev); + pm_runtime_get_sync(priv->dev); + val = ioread32(reg + RCAR_PCI_UNIT_REV_REG); - pr_info("PCI: bus%u revision %x\n", sys->busnr, val); + dev_info(priv->dev, "PCI: bus%u revision %x\n", sys->busnr, val); /* Disable Direct Power Down State and assert reset */ val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD; @@ -301,6 +306,7 @@ static int __init rcar_pci_probe(struct platform_device *pdev) priv->irq = platform_get_irq(pdev, 0); priv->reg = reg; + priv->dev = &pdev->dev; return rcar_pci_add_controller(priv); } -- cgit v1.2.3 From 84f47190d6be1cb99cd4a680e1018080d93800a8 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 4 Dec 2013 18:30:41 +0100 Subject: PCI: mvebu: Remove duplicate of_clk_get_by_name() call Probably due to a merge conflict resolution gone bad, the PCI clock is got twice. Remove the redundant call of of_clk_get_by_name(). Signed-off-by: Andrew Lunn Signed-off-by: Bjorn Helgaas Reviewed-by: Jingoo Han Acked-by: Jason Cooper --- drivers/pci/host/pci-mvebu.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index abd560e46757..6f35df5fedce 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -981,14 +981,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev) mvebu_pcie_set_local_dev_nr(port, 1); - port->clk = of_clk_get_by_name(child, NULL); - if (IS_ERR(port->clk)) { - dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", - port->port, port->lane); - iounmap(port->base); - continue; - } - port->dn = child; spin_lock_init(&port->conf_lock); mvebu_sw_pci_bridge_init(port); -- cgit v1.2.3 From 40c368c1ef6379db08d2ebd36f5a45efb93cff73 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 5 Dec 2013 19:52:53 +0800 Subject: PCI: Use dev_is_pci() to identify PCI devices Use dev_is_pci() instead of checking bus type directly. Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/pci-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 577074efbe62..e0431f1af33b 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -358,7 +358,7 @@ static void pci_acpi_cleanup(struct device *dev) static bool pci_acpi_bus_match(struct device *dev) { - return dev->bus == &pci_bus_type; + return dev_is_pci(dev); } static struct acpi_bus_type acpi_pci_bus = { -- cgit v1.2.3 From ca2f09f2b2c6c25047cfc545d057c4edfcfe561c Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Fri, 6 Dec 2013 16:36:07 +0000 Subject: xen-netback: improve guest-receive-side flow control The way that flow control works without this patch is that, in start_xmit() the code uses xenvif_count_skb_slots() to predict how many slots xenvif_gop_skb() will consume and then adds this to a 'req_cons_peek' counter which it then uses to determine if the shared ring has that amount of space available by checking whether 'req_prod' has passed that value. If the ring doesn't have space the tx queue is stopped. xenvif_gop_skb() will then consume slots and update 'req_cons' and issue responses, updating 'rsp_prod' as it goes. The frontend will consume those responses and post new requests, by updating req_prod. So, req_prod chases req_cons which chases rsp_prod, and can never exceed that value. Thus if xenvif_count_skb_slots() ever returns a number of slots greater than xenvif_gop_skb() uses, req_cons_peek will get to a value that req_prod cannot possibly achieve (since it's limited by the 'real' req_cons) and, if this happens enough times, req_cons_peek gets more than a ring size ahead of req_cons and the tx queue then remains stopped forever waiting for an unachievable amount of space to become available in the ring. Having two routines trying to calculate the same value is always going to be fragile, so this patch does away with that. All we essentially need to do is make sure that we have 'enough stuff' on our internal queue without letting it build up uncontrollably. So start_xmit() makes a cheap optimistic check of how much space is needed for an skb and only turns the queue off if that is unachievable. net_rx_action() is the place where we could do with an accurate predicition but, since that has proven tricky to calculate, a cheap worse-case (but not too bad) estimate is all we really need since the only thing we *must* prevent is xenvif_gop_skb() consuming more slots than are available. Without this patch I can trivially stall netback permanently by just doing a large guest to guest file copy between two Windows Server 2008R2 VMs on a single host. Patch tested with frontends in: - Windows Server 2008R2 - CentOS 6.0 - Debian Squeeze - Debian Wheezy - SLES11 Signed-off-by: Paul Durrant Cc: Wei Liu Cc: Ian Campbell Cc: David Vrabel Cc: Annie Li Cc: Konrad Rzeszutek Wilk Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 27 ++--- drivers/net/xen-netback/interface.c | 47 ++++---- drivers/net/xen-netback/netback.c | 217 ++++++++++++------------------------ 3 files changed, 106 insertions(+), 185 deletions(-) (limited to 'drivers') diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 08ae01b41c83..ba30a6d9fefa 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -136,12 +136,10 @@ struct xenvif { char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ struct xen_netif_rx_back_ring rx; struct sk_buff_head rx_queue; - - /* Allow xenvif_start_xmit() to peek ahead in the rx request - * ring. This is a prediction of what rx_req_cons will be - * once all queued skbs are put on the ring. + /* Set when the RX interrupt is triggered by the frontend. + * The worker thread may need to wake the queue. */ - RING_IDX rx_req_cons_peek; + bool rx_event; /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each * head/fragment page uses 2 copy operations because it @@ -198,8 +196,6 @@ void xenvif_xenbus_fini(void); int xenvif_schedulable(struct xenvif *vif); -int xenvif_rx_ring_full(struct xenvif *vif); - int xenvif_must_stop_queue(struct xenvif *vif); /* (Un)Map communication rings. */ @@ -211,21 +207,20 @@ int xenvif_map_frontend_rings(struct xenvif *vif, /* Check for SKBs from frontend and schedule backend processing */ void xenvif_check_rx_xenvif(struct xenvif *vif); -/* Queue an SKB for transmission to the frontend */ -void xenvif_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); -/* Notify xenvif that ring now has space to send an skb to the frontend */ -void xenvif_notify_tx_completion(struct xenvif *vif); - /* Prevent the device from generating any further traffic. */ void xenvif_carrier_off(struct xenvif *vif); -/* Returns number of ring slots required to send an skb to the frontend */ -unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); - int xenvif_tx_action(struct xenvif *vif, int budget); -void xenvif_rx_action(struct xenvif *vif); int xenvif_kthread(void *data); +void xenvif_kick_thread(struct xenvif *vif); + +/* Determine whether the needed number of slots (req) are available, + * and set req_event if not. + */ +bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed); + +void xenvif_stop_queue(struct xenvif *vif); extern bool separate_tx_rx_irq; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 870f1fa58370..1dcb9606e6e0 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -46,11 +46,6 @@ int xenvif_schedulable(struct xenvif *vif) return netif_running(vif->dev) && netif_carrier_ok(vif->dev); } -static int xenvif_rx_schedulable(struct xenvif *vif) -{ - return xenvif_schedulable(vif) && !xenvif_rx_ring_full(vif); -} - static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id) { struct xenvif *vif = dev_id; @@ -104,8 +99,8 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) { struct xenvif *vif = dev_id; - if (xenvif_rx_schedulable(vif)) - netif_wake_queue(vif->dev); + vif->rx_event = true; + xenvif_kick_thread(vif); return IRQ_HANDLED; } @@ -121,24 +116,35 @@ static irqreturn_t xenvif_interrupt(int irq, void *dev_id) static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); + int min_slots_needed; BUG_ON(skb->dev != dev); /* Drop the packet if vif is not ready */ - if (vif->task == NULL) + if (vif->task == NULL || !xenvif_schedulable(vif)) goto drop; - /* Drop the packet if the target domain has no receive buffers. */ - if (!xenvif_rx_schedulable(vif)) - goto drop; + /* At best we'll need one slot for the header and one for each + * frag. + */ + min_slots_needed = 1 + skb_shinfo(skb)->nr_frags; - /* Reserve ring slots for the worst-case number of fragments. */ - vif->rx_req_cons_peek += xenvif_count_skb_slots(vif, skb); + /* If the skb is GSO then we'll also need an extra slot for the + * metadata. + */ + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || + skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + min_slots_needed++; - if (vif->can_queue && xenvif_must_stop_queue(vif)) - netif_stop_queue(dev); + /* If the skb can't possibly fit in the remaining slots + * then turn off the queue to give the ring a chance to + * drain. + */ + if (!xenvif_rx_ring_slots_available(vif, min_slots_needed)) + xenvif_stop_queue(vif); - xenvif_queue_tx_skb(vif, skb); + skb_queue_tail(&vif->rx_queue, skb); + xenvif_kick_thread(vif); return NETDEV_TX_OK; @@ -148,12 +154,6 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -void xenvif_notify_tx_completion(struct xenvif *vif) -{ - if (netif_queue_stopped(vif->dev) && xenvif_rx_schedulable(vif)) - netif_wake_queue(vif->dev); -} - static struct net_device_stats *xenvif_get_stats(struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); @@ -378,6 +378,8 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, if (err < 0) goto err; + init_waitqueue_head(&vif->wq); + if (tx_evtchn == rx_evtchn) { /* feature-split-event-channels == 0 */ err = bind_interdomain_evtchn_to_irqhandler( @@ -410,7 +412,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, disable_irq(vif->rx_irq); } - init_waitqueue_head(&vif->wq); task = kthread_create(xenvif_kthread, (void *)vif, "%s", vif->dev->name); if (IS_ERR(task)) { diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index acf13920e6d1..43341b82649c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -138,36 +138,26 @@ static inline pending_ring_idx_t nr_pending_reqs(struct xenvif *vif) vif->pending_prod + vif->pending_cons; } -static int max_required_rx_slots(struct xenvif *vif) +bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed) { - int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE); + RING_IDX prod, cons; - /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */ - if (vif->can_sg || vif->gso_mask || vif->gso_prefix_mask) - max += MAX_SKB_FRAGS + 1; /* extra_info + frags */ - - return max; -} - -int xenvif_rx_ring_full(struct xenvif *vif) -{ - RING_IDX peek = vif->rx_req_cons_peek; - RING_IDX needed = max_required_rx_slots(vif); + do { + prod = vif->rx.sring->req_prod; + cons = vif->rx.req_cons; - return ((vif->rx.sring->req_prod - peek) < needed) || - ((vif->rx.rsp_prod_pvt + XEN_NETIF_RX_RING_SIZE - peek) < needed); -} + if (prod - cons >= needed) + return true; -int xenvif_must_stop_queue(struct xenvif *vif) -{ - if (!xenvif_rx_ring_full(vif)) - return 0; + vif->rx.sring->req_event = prod + 1; - vif->rx.sring->req_event = vif->rx_req_cons_peek + - max_required_rx_slots(vif); - mb(); /* request notification /then/ check the queue */ + /* Make sure event is visible before we check prod + * again. + */ + mb(); + } while (vif->rx.sring->req_prod != prod); - return xenvif_rx_ring_full(vif); + return false; } /* @@ -210,93 +200,6 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head) return false; } -struct xenvif_count_slot_state { - unsigned long copy_off; - bool head; -}; - -unsigned int xenvif_count_frag_slots(struct xenvif *vif, - unsigned long offset, unsigned long size, - struct xenvif_count_slot_state *state) -{ - unsigned count = 0; - - offset &= ~PAGE_MASK; - - while (size > 0) { - unsigned long bytes; - - bytes = PAGE_SIZE - offset; - - if (bytes > size) - bytes = size; - - if (start_new_rx_buffer(state->copy_off, bytes, state->head)) { - count++; - state->copy_off = 0; - } - - if (state->copy_off + bytes > MAX_BUFFER_OFFSET) - bytes = MAX_BUFFER_OFFSET - state->copy_off; - - state->copy_off += bytes; - - offset += bytes; - size -= bytes; - - if (offset == PAGE_SIZE) - offset = 0; - - state->head = false; - } - - return count; -} - -/* - * Figure out how many ring slots we're going to need to send @skb to - * the guest. This function is essentially a dry run of - * xenvif_gop_frag_copy. - */ -unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) -{ - struct xenvif_count_slot_state state; - unsigned int count; - unsigned char *data; - unsigned i; - - state.head = true; - state.copy_off = 0; - - /* Slot for the first (partial) page of data. */ - count = 1; - - /* Need a slot for the GSO prefix for GSO extra data? */ - if (skb_shinfo(skb)->gso_size) - count++; - - data = skb->data; - while (data < skb_tail_pointer(skb)) { - unsigned long offset = offset_in_page(data); - unsigned long size = PAGE_SIZE - offset; - - if (data + size > skb_tail_pointer(skb)) - size = skb_tail_pointer(skb) - data; - - count += xenvif_count_frag_slots(vif, offset, size, &state); - - data += size; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; - - count += xenvif_count_frag_slots(vif, offset, size, &state); - } - return count; -} - struct netrx_pending_operations { unsigned copy_prod, copy_cons; unsigned meta_prod, meta_cons; @@ -557,12 +460,12 @@ struct skb_cb_overlay { int meta_slots_used; }; -static void xenvif_kick_thread(struct xenvif *vif) +void xenvif_kick_thread(struct xenvif *vif) { wake_up(&vif->wq); } -void xenvif_rx_action(struct xenvif *vif) +static void xenvif_rx_action(struct xenvif *vif) { s8 status; u16 flags; @@ -571,8 +474,6 @@ void xenvif_rx_action(struct xenvif *vif) struct sk_buff *skb; LIST_HEAD(notify); int ret; - int nr_frags; - int count; unsigned long offset; struct skb_cb_overlay *sco; int need_to_notify = 0; @@ -584,29 +485,44 @@ void xenvif_rx_action(struct xenvif *vif) skb_queue_head_init(&rxq); - count = 0; - while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) { - vif = netdev_priv(skb->dev); - nr_frags = skb_shinfo(skb)->nr_frags; + int max_slots_needed; + int i; + + /* We need a cheap worse case estimate for the number of + * slots we'll use. + */ + + max_slots_needed = DIV_ROUND_UP(offset_in_page(skb->data) + + skb_headlen(skb), + PAGE_SIZE); + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + unsigned int size; + size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE); + } + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || + skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + max_slots_needed++; + + /* If the skb may not fit then bail out now */ + if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) { + skb_queue_head(&vif->rx_queue, skb); + need_to_notify = 1; + break; + } sco = (struct skb_cb_overlay *)skb->cb; sco->meta_slots_used = xenvif_gop_skb(skb, &npo); - - count += nr_frags + 1; + BUG_ON(sco->meta_slots_used > max_slots_needed); __skb_queue_tail(&rxq, skb); - - /* Filled the batch queue? */ - /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */ - if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE) - break; } BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta)); if (!npo.copy_prod) - return; + goto done; BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op)); gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod); @@ -614,8 +530,6 @@ void xenvif_rx_action(struct xenvif *vif) while ((skb = __skb_dequeue(&rxq)) != NULL) { sco = (struct skb_cb_overlay *)skb->cb; - vif = netdev_priv(skb->dev); - if ((1 << vif->meta[npo.meta_cons].gso_type) & vif->gso_prefix_mask) { resp = RING_GET_RESPONSE(&vif->rx, @@ -681,25 +595,13 @@ void xenvif_rx_action(struct xenvif *vif) if (ret) need_to_notify = 1; - xenvif_notify_tx_completion(vif); - npo.meta_cons += sco->meta_slots_used; dev_kfree_skb(skb); } +done: if (need_to_notify) notify_remote_via_irq(vif->rx_irq); - - /* More work to do? */ - if (!skb_queue_empty(&vif->rx_queue)) - xenvif_kick_thread(vif); -} - -void xenvif_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb) -{ - skb_queue_tail(&vif->rx_queue, skb); - - xenvif_kick_thread(vif); } void xenvif_check_rx_xenvif(struct xenvif *vif) @@ -1804,7 +1706,7 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif, static inline int rx_work_todo(struct xenvif *vif) { - return !skb_queue_empty(&vif->rx_queue); + return !skb_queue_empty(&vif->rx_queue) || vif->rx_event; } static inline int tx_work_todo(struct xenvif *vif) @@ -1854,8 +1756,6 @@ int xenvif_map_frontend_rings(struct xenvif *vif, rxs = (struct xen_netif_rx_sring *)addr; BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE); - vif->rx_req_cons_peek = 0; - return 0; err: @@ -1863,9 +1763,24 @@ err: return err; } +void xenvif_stop_queue(struct xenvif *vif) +{ + if (!vif->can_queue) + return; + + netif_stop_queue(vif->dev); +} + +static void xenvif_start_queue(struct xenvif *vif) +{ + if (xenvif_schedulable(vif)) + netif_wake_queue(vif->dev); +} + int xenvif_kthread(void *data) { struct xenvif *vif = data; + struct sk_buff *skb; while (!kthread_should_stop()) { wait_event_interruptible(vif->wq, @@ -1874,12 +1789,22 @@ int xenvif_kthread(void *data) if (kthread_should_stop()) break; - if (rx_work_todo(vif)) + if (!skb_queue_empty(&vif->rx_queue)) xenvif_rx_action(vif); + vif->rx_event = false; + + if (skb_queue_empty(&vif->rx_queue) && + netif_queue_stopped(vif->dev)) + xenvif_start_queue(vif); + cond_resched(); } + /* Bin any remaining skbs */ + while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) + dev_kfree_skb(skb); + return 0; } -- cgit v1.2.3 From 41e4af69a5984a3193ba3108fb4e067b0e34dc73 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 7 Dec 2013 04:54:59 +0800 Subject: macvtap: remove useless codes in macvtap_aio_read() and macvtap_recvmsg() By checking related codes, it is impossible that ret > len or total_len, so we should remove some useless coeds in both above functions. Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 4a34bcb6549f..2aa5e973ef17 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -871,7 +871,6 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK); - ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ if (ret > 0) iocb->ki_pos = ret; out: @@ -1106,10 +1105,6 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, return -EINVAL; ret = macvtap_do_read(q, m->msg_iov, total_len, flags & MSG_DONTWAIT); - if (ret > total_len) { - m->msg_flags |= MSG_TRUNC; - ret = flags & MSG_TRUNC ? ret : total_len; - } return ret; } -- cgit v1.2.3 From 73713357ab58aacda1af715bb5a623528dbbfd79 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sat, 7 Dec 2013 04:55:00 +0800 Subject: tun: remove useless codes in tun_chr_aio_read() and tun_recvmsg() By checking related codes, it is impossible that ret > len or total_len, so we should remove some useless codes in both above functions. Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller --- drivers/net/tun.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3c5a8d8cde50..bbb693512918 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1354,7 +1354,6 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, ret = tun_do_read(tun, tfile, iv, len, file->f_flags & O_NONBLOCK); - ret = min_t(ssize_t, ret, len); if (ret > 0) iocb->ki_pos = ret; out: @@ -1455,10 +1454,6 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, } ret = tun_do_read(tun, tfile, m->msg_iov, total_len, flags & MSG_DONTWAIT); - if (ret > total_len) { - m->msg_flags |= MSG_TRUNC; - ret = flags & MSG_TRUNC ? ret : total_len; - } out: tun_put(tun); return ret; -- cgit v1.2.3 From 114002bc1af6c63de4c003f8c5d3ca0bb430d987 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:30 -0800 Subject: net: phy: report link partner features through ethtool The PHY library already reads the MII_STAT1000 and MII_LPA registers in genphy_read_status(), so extend it to also populate the PHY device link partner advertised features such that we can feed this back into ethtool when asked for it in phy_ethtool_gset(). Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 1 + drivers/net/phy/phy_device.c | 6 ++++++ include/linux/phy.h | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 36c6994436b7..05cb8fe742f9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -289,6 +289,7 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) cmd->supported = phydev->supported; cmd->advertising = phydev->advertising; + cmd->lp_advertising = phydev->lp_advertising; ethtool_cmd_speed_set(cmd, phydev->speed); cmd->duplex = phydev->duplex; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index d6447b3f7409..6db36595eac9 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -839,6 +839,8 @@ int genphy_read_status(struct phy_device *phydev) if (err) return err; + phydev->lp_advertising = 0; + if (AUTONEG_ENABLE == phydev->autoneg) { if (phydev->supported & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)) { @@ -852,6 +854,8 @@ int genphy_read_status(struct phy_device *phydev) if (adv < 0) return adv; + phydev->lp_advertising = + mii_stat1000_to_ethtool_lpa_t(lpagb); lpagb &= adv << 2; } @@ -860,6 +864,8 @@ int genphy_read_status(struct phy_device *phydev) if (lpa < 0) return lpa; + phydev->lp_advertising |= mii_lpa_to_ethtool_lpa_t(lpa); + adv = phy_read(phydev, MII_ADVERTISE); if (adv < 0) diff --git a/include/linux/phy.h b/include/linux/phy.h index 7ff751ae6f0a..90a666e0884b 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -287,8 +287,8 @@ struct phy_c45_device_ids { * adjust_state: Callback for the enet driver to respond to * changes in the state machine. * - * speed, duplex, pause, supported, advertising, and - * autoneg are used like in mii_if_info + * speed, duplex, pause, supported, advertising, lp_advertising, + * and autoneg are used like in mii_if_info * * interrupts currently only supports enabled or disabled, * but could be changed in the future to support enabling @@ -340,6 +340,7 @@ struct phy_device { /* See mii.h for more info */ u32 supported; u32 advertising; + u32 lp_advertising; int autoneg; -- cgit v1.2.3 From 2613f95f614b39681f77a5036046ea395e306e28 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:31 -0800 Subject: net: phy: use phy_init_hw instead of open-coding it Use phy_init_hw() instead of open-coding it in phy_mii_ioctl(), this improves consistenty and makes sure that we will not duplicate the same routine somewhere else. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 05cb8fe742f9..5d7101b3b604 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -361,11 +361,8 @@ int phy_mii_ioctl(struct phy_device *phydev, mii_data->reg_num, val); if (mii_data->reg_num == MII_BMCR && - val & BMCR_RESET && - phydev->drv->config_init) { - phy_scan_fixups(phydev); - phydev->drv->config_init(phydev); - } + val & BMCR_RESET) + phy_init_hw(phydev); break; case SIOCSHWTSTAMP: -- cgit v1.2.3 From f0528ce7a43d51090b45cf27c53e4b343facaade Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:32 -0800 Subject: net: greth: use phy_read_status() In case the greth driver is bound to anything but the Generic PHY driver or the PHY has a special read_status callback implemented, unexpected things will happen. Make sure we that we use phy_read_status() which does the proper abstraction of calling the driver specific read_status() callback for a given PHY. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/aeroflex/greth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index e06694555144..b20cbf0323e0 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1361,7 +1361,7 @@ static int greth_mdio_init(struct greth_private *greth) timeout = jiffies + 6*HZ; while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) { } - genphy_read_status(greth->phy); + phy_read_status(greth->phy); greth_link_change(greth->netdev); } -- cgit v1.2.3 From 06d87cec73d883690f690e72da498e7f0334f9bc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:33 -0800 Subject: net: bfin_mac: do not reset PHY after phy_start() The PHY is already reset during driver probing, and this manual reset after calling phy_start() will wipe out board-specific PHY fixups and driver specific configuration initialization. Remove that explicit PHY reset. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/adi/bfin_mac.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index 0d4f29579879..c0f68dcd1dc1 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -1557,7 +1557,6 @@ static int bfin_mac_open(struct net_device *dev) return ret; phy_start(lp->phydev); - phy_write(lp->phydev, MII_BMCR, BMCR_RESET); setup_system_regs(dev); setup_mac_addr(dev->dev_addr); -- cgit v1.2.3 From 87aa9f9c61ad56d505641681812e92ad976f8608 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:34 -0800 Subject: net: phy: consolidate PHY reset in phy_init_hw() There are quite a lot of drivers touching a PHY device MII_BMCR register to reset the PHY without taking care of: 1) ensuring that BMCR_RESET is cleared after a given timeout 2) the PHY state machine resuming to the proper state and re-applying potentially changed settings such as auto-negotiation Introduce phy_poll_reset() which will take care of polling the MII_BMCR for the BMCR_RESET bit to be cleared after a given timeout or return a timeout error code. In order to make sure the PHY is in a correct state, phy_init_hw() first issues a software reset through MII_BMCR and then applies any fixups. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/phy.txt | 3 ++- drivers/net/phy/phy.c | 5 ++-- drivers/net/phy/phy_device.c | 56 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt index d5b1a3935245..ebf270719402 100644 --- a/Documentation/networking/phy.txt +++ b/Documentation/networking/phy.txt @@ -255,7 +255,8 @@ Writing a PHY driver config_init: configures PHY into a sane state after a reset. For instance, a Davicom PHY requires descrambling disabled. - probe: Does any setup needed by the driver + probe: Allocate phy->priv, optionally refuse to bind. + PHY may not have been reset or had fixups run yet. suspend/resume: power management config_aneg: Changes the speed/duplex/negotiation settings read_status: Reads the current speed/duplex/negotiation settings diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 5d7101b3b604..e3dd69100da8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -318,6 +318,7 @@ int phy_mii_ioctl(struct phy_device *phydev, { struct mii_ioctl_data *mii_data = if_mii(ifr); u16 val = mii_data->val_in; + int ret = 0; switch (cmd) { case SIOCGMIIPHY: @@ -362,7 +363,7 @@ int phy_mii_ioctl(struct phy_device *phydev, if (mii_data->reg_num == MII_BMCR && val & BMCR_RESET) - phy_init_hw(phydev); + ret = phy_init_hw(phydev); break; case SIOCSHWTSTAMP: @@ -374,7 +375,7 @@ int phy_mii_ioctl(struct phy_device *phydev, return -EOPNOTSUPP; } - return 0; + return ret; } EXPORT_SYMBOL(phy_mii_ioctl); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 6db36595eac9..5a619f0dcf73 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -364,7 +364,11 @@ int phy_device_register(struct phy_device *phydev) phydev->bus->phy_map[phydev->addr] = phydev; /* Run all of the fixups for this PHY */ - phy_scan_fixups(phydev); + err = phy_init_hw(phydev); + if (err) { + pr_err("PHY %d failed to initialize\n", phydev->addr); + goto out; + } err = device_add(&phydev->dev); if (err) { @@ -497,6 +501,47 @@ void phy_disconnect(struct phy_device *phydev) } EXPORT_SYMBOL(phy_disconnect); +/** + * phy_poll_reset - Safely wait until a PHY reset has properly completed + * @phydev: The PHY device to poll + * + * Description: According to IEEE 802.3, Section 2, Subsection 22.2.4.1.1, as + * published in 2008, a PHY reset may take up to 0.5 seconds. The MII BMCR + * register must be polled until the BMCR_RESET bit clears. + * + * Furthermore, any attempts to write to PHY registers may have no effect + * or even generate MDIO bus errors until this is complete. + * + * Some PHYs (such as the Marvell 88E1111) don't entirely conform to the + * standard and do not fully reset after the BMCR_RESET bit is set, and may + * even *REQUIRE* a soft-reset to properly restart autonegotiation. In an + * effort to support such broken PHYs, this function is separate from the + * standard phy_init_hw() which will zero all the other bits in the BMCR + * and reapply all driver-specific and board-specific fixups. + */ +static int phy_poll_reset(struct phy_device *phydev) +{ + /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ + unsigned int retries = 12; + int ret; + + do { + msleep(50); + ret = phy_read(phydev, MII_BMCR); + if (ret < 0) + return ret; + } while (ret & BMCR_RESET && --retries); + if (ret & BMCR_RESET) + return -ETIMEDOUT; + + /* + * Some chips (smsc911x) may still need up to another 1ms after the + * BMCR_RESET bit is cleared before they are usable. + */ + msleep(1); + return 0; +} + int phy_init_hw(struct phy_device *phydev) { int ret; @@ -504,12 +549,21 @@ int phy_init_hw(struct phy_device *phydev) if (!phydev->drv || !phydev->drv->config_init) return 0; + ret = phy_write(phydev, MII_BMCR, BMCR_RESET); + if (ret < 0) + return ret; + + ret = phy_poll_reset(phydev); + if (ret < 0) + return ret; + ret = phy_scan_fixups(phydev); if (ret < 0) return ret; return phydev->drv->config_init(phydev); } +EXPORT_SYMBOL(phy_init_hw); /** * phy_attach_direct - attach a network device to a given PHY device pointer -- cgit v1.2.3 From 7cd1463664c2a15721ff4ccfb61d4d970815cb3d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:35 -0800 Subject: net: mv643xx_eth: use phy_init_hw to reset PHY Instead of open-coding a PHY reset through the MII BMCR register, use phy_init_hw() which does that for us and will also make sure that PHY fixups are applied if required. We also remove a call to phy_reset() due to the following sequence of calls in the driver: phy_scan() -> phy_connect() -> phy_connect_direct() -> phy_attach_direct() -> phy_init_hw() and we only have a call to phy_init() after phy_scan(). Signed-off-by: Florian Fainelli Tested-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index fa905052fbf4..b3d9327f78b9 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2066,23 +2066,6 @@ static inline void oom_timer_wrapper(unsigned long data) napi_schedule(&mp->napi); } -static void phy_reset(struct mv643xx_eth_private *mp) -{ - int data; - - data = phy_read(mp->phy, MII_BMCR); - if (data < 0) - return; - - data |= BMCR_RESET; - if (phy_write(mp->phy, MII_BMCR, data) < 0) - return; - - do { - data = phy_read(mp->phy, MII_BMCR); - } while (data >= 0 && data & BMCR_RESET); -} - static void port_start(struct mv643xx_eth_private *mp) { u32 pscr; @@ -2095,7 +2078,7 @@ static void port_start(struct mv643xx_eth_private *mp) struct ethtool_cmd cmd; mv643xx_eth_get_settings(mp->dev, &cmd); - phy_reset(mp); + phy_init_hw(mp->phy); mv643xx_eth_set_settings(mp->dev, &cmd); } @@ -2763,8 +2746,6 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) { struct phy_device *phy = mp->phy; - phy_reset(mp); - if (speed == 0) { phy->autoneg = AUTONEG_ENABLE; phy->speed = 0; -- cgit v1.2.3 From 78de53f05c58784e366b9115575058a5815c89d6 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:36 -0800 Subject: net: pxa168_eth: use phy_init_hw for PHY reset Instead of open-coding a PHY reset through the MII BMCR register, use phy_init_hw() which does this for us and ensures that PHY device fixups are also applied. We also remove a call to ethernet_phy_reset() which is now unncessary since phy_attach() calls phy_attach_direct() which in turns calls phy_init_hw(). Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/pxa168_eth.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 2ad32417a52c..452e81de33de 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -320,23 +320,6 @@ static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr) wrl(pep, PHY_ADDRESS, reg_data); } -static void ethernet_phy_reset(struct pxa168_eth_private *pep) -{ - int data; - - data = phy_read(pep->phy, MII_BMCR); - if (data < 0) - return; - - data |= BMCR_RESET; - if (phy_write(pep->phy, MII_BMCR, data) < 0) - return; - - do { - data = phy_read(pep->phy, MII_BMCR); - } while (data >= 0 && data & BMCR_RESET); -} - static void rxq_refill(struct net_device *dev) { struct pxa168_eth_private *pep = netdev_priv(dev); @@ -645,7 +628,7 @@ static void eth_port_start(struct net_device *dev) struct ethtool_cmd cmd; pxa168_get_settings(pep->dev, &cmd); - ethernet_phy_reset(pep); + phy_init_hw(pep->phy); pxa168_set_settings(pep->dev, &cmd); } @@ -1382,7 +1365,6 @@ static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr) static void phy_init(struct pxa168_eth_private *pep, int speed, int duplex) { struct phy_device *phy = pep->phy; - ethernet_phy_reset(pep); phy_attach(pep->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_MII); -- cgit v1.2.3 From 01b0114e068480226bc22fea18c3bccbd815ce8b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:37 -0800 Subject: net: tc35815: use phy_init_hw for PHY reset Instead of open-coding the PHY reset through MII BMCR, use phy_init_hw() which does that for us and also makes sure that any PHY specific fixups are applied. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/toshiba/tc35815.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index 1322546d92ac..f6b3212ec339 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -1170,19 +1170,12 @@ static int tc35815_tx_full(struct net_device *dev) static void tc35815_restart(struct net_device *dev) { struct tc35815_local *lp = netdev_priv(dev); + int ret; if (lp->phy_dev) { - int timeout; - - phy_write(lp->phy_dev, MII_BMCR, BMCR_RESET); - timeout = 100; - while (--timeout) { - if (!(phy_read(lp->phy_dev, MII_BMCR) & BMCR_RESET)) - break; - udelay(1); - } - if (!timeout) - printk(KERN_ERR "%s: BMCR reset failed.\n", dev->name); + ret = phy_init_hw(lp->phy_dev); + if (ret) + printk(KERN_ERR "%s: PHY init failed.\n", dev->name); } spin_lock_bh(&lp->rx_lock); -- cgit v1.2.3 From 0c9eb5b931c3da3a79faa889b903dc7bd318203c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 6 Dec 2013 13:01:38 -0800 Subject: net: sh_eth: do not issue a wild PHY reset through BMCR The sh_eth driver issues an uncontrolled PHY reset through the MII register BMCR but fails to wait for the reset to complete, and will also implicitely wipe out all possible PHY fixups applied. Use phy_init_hw() which remedies both problems. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d256ce19d4de..6761dde7007a 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1704,7 +1704,10 @@ static int sh_eth_phy_start(struct net_device *ndev) return ret; /* reset phy - this also wakes it from PDOWN */ - phy_write(mdp->phydev, MII_BMCR, BMCR_RESET); + ret = phy_init_hw(mdp->phydev); + if (ret) + return ret; + phy_start(mdp->phydev); return 0; -- cgit v1.2.3 From 5824d2d16d39a9c57aa3bacf955fbd0c2134061f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 7 Dec 2013 00:53:55 +0100 Subject: bgmac: connect to PHY and make use of PHY device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were already registering MDIO bus, but we were not connecting bgmac to the PHY. Add proper call and implement adjust link function to switch MAC into requested state. At the same time it's possible to drop our internal PHY management. This is a "standard" PHY, so the "Generic PHY" driver works perfectly fine with this. Don't duplicate the code. Finally make use of phy_ethtool_[gs]set functions instead implementing them from scratch. This change was successfully tested on BCM5357. I was able to autonegotiate 1000Mb/s full duplex, as well as force any of the 10/100/1000 half/full modes. Signed-off-by: Rafał Miłecki Acked-by: Florian Fainelli Acked-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 190 +++++++++++----------------------- drivers/net/ethernet/broadcom/bgmac.h | 12 +-- 2 files changed, 64 insertions(+), 138 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index e2aa09ce6af7..0452937227ff 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -682,70 +682,6 @@ static int bgmac_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value) return 0; } -/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyforce */ -static void bgmac_phy_force(struct bgmac *bgmac) -{ - u16 ctl; - u16 mask = ~(BGMAC_PHY_CTL_SPEED | BGMAC_PHY_CTL_SPEED_MSB | - BGMAC_PHY_CTL_ANENAB | BGMAC_PHY_CTL_DUPLEX); - - if (bgmac->phyaddr == BGMAC_PHY_NOREGS) - return; - - if (bgmac->autoneg) - return; - - ctl = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL); - ctl &= mask; - if (bgmac->full_duplex) - ctl |= BGMAC_PHY_CTL_DUPLEX; - if (bgmac->speed == BGMAC_SPEED_100) - ctl |= BGMAC_PHY_CTL_SPEED_100; - else if (bgmac->speed == BGMAC_SPEED_1000) - ctl |= BGMAC_PHY_CTL_SPEED_1000; - bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL, ctl); -} - -/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyadvertise */ -static void bgmac_phy_advertise(struct bgmac *bgmac) -{ - u16 adv; - - if (bgmac->phyaddr == BGMAC_PHY_NOREGS) - return; - - if (!bgmac->autoneg) - return; - - /* Adv selected 10/100 speeds */ - adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV); - adv &= ~(BGMAC_PHY_ADV_10HALF | BGMAC_PHY_ADV_10FULL | - BGMAC_PHY_ADV_100HALF | BGMAC_PHY_ADV_100FULL); - if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10) - adv |= BGMAC_PHY_ADV_10HALF; - if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100) - adv |= BGMAC_PHY_ADV_100HALF; - if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10) - adv |= BGMAC_PHY_ADV_10FULL; - if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100) - adv |= BGMAC_PHY_ADV_100FULL; - bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV, adv); - - /* Adv selected 1000 speeds */ - adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2); - adv &= ~(BGMAC_PHY_ADV2_1000HALF | BGMAC_PHY_ADV2_1000FULL); - if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000) - adv |= BGMAC_PHY_ADV2_1000HALF; - if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000) - adv |= BGMAC_PHY_ADV2_1000FULL; - bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2, adv); - - /* Restart */ - bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL, - bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL) | - BGMAC_PHY_CTL_RESTART); -} - /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */ static void bgmac_phy_init(struct bgmac *bgmac) { @@ -876,19 +812,28 @@ static void bgmac_clear_mib(struct bgmac *bgmac) } /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_speed */ -static void bgmac_speed(struct bgmac *bgmac, int speed) +static void bgmac_mac_speed(struct bgmac *bgmac) { u32 mask = ~(BGMAC_CMDCFG_ES_MASK | BGMAC_CMDCFG_HD); u32 set = 0; - if (speed & BGMAC_SPEED_10) + switch (bgmac->mac_speed) { + case SPEED_10: set |= BGMAC_CMDCFG_ES_10; - if (speed & BGMAC_SPEED_100) + break; + case SPEED_100: set |= BGMAC_CMDCFG_ES_100; - if (speed & BGMAC_SPEED_1000) + break; + case SPEED_1000: set |= BGMAC_CMDCFG_ES_1000; - if (!bgmac->full_duplex) + break; + default: + bgmac_err(bgmac, "Unsupported speed: %d\n", bgmac->mac_speed); + } + + if (bgmac->mac_duplex == DUPLEX_HALF) set |= BGMAC_CMDCFG_HD; + bgmac_cmdcfg_maskset(bgmac, mask, set, true); } @@ -897,10 +842,9 @@ static void bgmac_miiconfig(struct bgmac *bgmac) u8 imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >> BGMAC_DS_MM_SHIFT; if (imode == 0 || imode == 1) { - if (bgmac->autoneg) - bgmac_speed(bgmac, BGMAC_SPEED_100); - else - bgmac_speed(bgmac, bgmac->speed); + bgmac->mac_speed = SPEED_100; + bgmac->mac_duplex = DUPLEX_FULL; + bgmac_mac_speed(bgmac); } } @@ -1108,13 +1052,6 @@ static void bgmac_chip_init(struct bgmac *bgmac, bool full_init) bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN); - if (!bgmac->autoneg) { - bgmac_speed(bgmac, bgmac->speed); - bgmac_phy_force(bgmac); - } else if (bgmac->speed) { /* if there is anything to adv */ - bgmac_phy_advertise(bgmac); - } - if (full_init) { bgmac_dma_init(bgmac); if (1) /* FIXME: is there any case we don't want IRQs? */ @@ -1294,61 +1231,16 @@ static int bgmac_get_settings(struct net_device *net_dev, { struct bgmac *bgmac = netdev_priv(net_dev); - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg; - - if (bgmac->autoneg) { - WARN_ON(cmd->advertising); - if (bgmac->full_duplex) { - if (bgmac->speed & BGMAC_SPEED_10) - cmd->advertising |= ADVERTISED_10baseT_Full; - if (bgmac->speed & BGMAC_SPEED_100) - cmd->advertising |= ADVERTISED_100baseT_Full; - if (bgmac->speed & BGMAC_SPEED_1000) - cmd->advertising |= ADVERTISED_1000baseT_Full; - } else { - if (bgmac->speed & BGMAC_SPEED_10) - cmd->advertising |= ADVERTISED_10baseT_Half; - if (bgmac->speed & BGMAC_SPEED_100) - cmd->advertising |= ADVERTISED_100baseT_Half; - if (bgmac->speed & BGMAC_SPEED_1000) - cmd->advertising |= ADVERTISED_1000baseT_Half; - } - } else { - switch (bgmac->speed) { - case BGMAC_SPEED_10: - ethtool_cmd_speed_set(cmd, SPEED_10); - break; - case BGMAC_SPEED_100: - ethtool_cmd_speed_set(cmd, SPEED_100); - break; - case BGMAC_SPEED_1000: - ethtool_cmd_speed_set(cmd, SPEED_1000); - break; - } - } - - cmd->duplex = bgmac->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - - cmd->autoneg = bgmac->autoneg; - - return 0; + return phy_ethtool_gset(bgmac->phy_dev, cmd); } -#if 0 static int bgmac_set_settings(struct net_device *net_dev, struct ethtool_cmd *cmd) { struct bgmac *bgmac = netdev_priv(net_dev); - return -1; + return phy_ethtool_sset(bgmac->phy_dev, cmd); } -#endif static void bgmac_get_drvinfo(struct net_device *net_dev, struct ethtool_drvinfo *info) @@ -1359,6 +1251,7 @@ static void bgmac_get_drvinfo(struct net_device *net_dev, static const struct ethtool_ops bgmac_ethtool_ops = { .get_settings = bgmac_get_settings, + .set_settings = bgmac_set_settings, .get_drvinfo = bgmac_get_drvinfo, }; @@ -1377,9 +1270,35 @@ static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum, return bgmac_phy_write(bus->priv, mii_id, regnum, value); } +static void bgmac_adjust_link(struct net_device *net_dev) +{ + struct bgmac *bgmac = netdev_priv(net_dev); + struct phy_device *phy_dev = bgmac->phy_dev; + bool update = false; + + if (phy_dev->link) { + if (phy_dev->speed != bgmac->mac_speed) { + bgmac->mac_speed = phy_dev->speed; + update = true; + } + + if (phy_dev->duplex != bgmac->mac_duplex) { + bgmac->mac_duplex = phy_dev->duplex; + update = true; + } + } + + if (update) { + bgmac_mac_speed(bgmac); + phy_print_status(phy_dev); + } +} + static int bgmac_mii_register(struct bgmac *bgmac) { struct mii_bus *mii_bus; + struct phy_device *phy_dev; + char bus_id[MII_BUS_ID_SIZE + 3]; int i, err = 0; mii_bus = mdiobus_alloc(); @@ -1411,8 +1330,22 @@ static int bgmac_mii_register(struct bgmac *bgmac) bgmac->mii_bus = mii_bus; + /* Connect to the PHY */ + snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id, + bgmac->phyaddr); + phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(phy_dev)) { + bgmac_err(bgmac, "PHY connecton failed\n"); + err = PTR_ERR(phy_dev); + goto err_unregister_bus; + } + bgmac->phy_dev = phy_dev; + return err; +err_unregister_bus: + mdiobus_unregister(mii_bus); err_free_irq: kfree(mii_bus->irq); err_free_bus: @@ -1467,9 +1400,6 @@ static int bgmac_probe(struct bcma_device *core) bcma_set_drvdata(core, bgmac); /* Defaults */ - bgmac->autoneg = true; - bgmac->full_duplex = true; - bgmac->speed = BGMAC_SPEED_10 | BGMAC_SPEED_100 | BGMAC_SPEED_1000; memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN); /* On BCM4706 we need common core to access PHY */ diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h index 66c8afbdc8c7..550f2a8e85a9 100644 --- a/drivers/net/ethernet/broadcom/bgmac.h +++ b/drivers/net/ethernet/broadcom/bgmac.h @@ -342,10 +342,6 @@ #define BGMAC_CHIPCTL_1_SW_TYPE_RGMII 0x000000C0 #define BGMAC_CHIPCTL_1_RXC_DLL_BYPASS 0x00010000 -#define BGMAC_SPEED_10 0x0001 -#define BGMAC_SPEED_100 0x0002 -#define BGMAC_SPEED_1000 0x0004 - #define BGMAC_WEIGHT 64 #define ETHER_MAX_LEN 1518 @@ -402,6 +398,7 @@ struct bgmac { struct net_device *net_dev; struct napi_struct napi; struct mii_bus *mii_bus; + struct phy_device *phy_dev; /* DMA */ struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS]; @@ -416,10 +413,9 @@ struct bgmac { u32 int_mask; u32 int_status; - /* Speed-related */ - int speed; - bool autoneg; - bool full_duplex; + /* Current MAC state */ + int mac_speed; + int mac_duplex; u8 phyaddr; bool has_robosw; -- cgit v1.2.3 From 7c6d74d23a33a946bcf08ba2d3e52d31943b7342 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 8 Dec 2013 16:50:17 +0200 Subject: mlx4_core: Roll back round robin bitmap allocation commit for CQs, SRQs, and MPTs Commit f4ec9e9 "mlx4_core: Change bitmap allocator to work in round-robin fashion" introduced round-robin allocation (via bitmap) for all resources which allocate via a bitmap. Round robin allocation is desirable for mcgs, counters, pd's, UARs, and xrcds. These are simply numbers, with no involvement of ICM memory mapping. Round robin is required for QPs, since we had a problem with immediate reuse of a 24-bit QP number (commit f4ec9e9). However, for other resources which use the bitmap allocator and involve mapping ICM memory -- MPTs, CQs, SRQs -- round-robin is not desirable. What happens in these cases is the following: ICM memory is allocated and mapped in chunks of 256K. Since the resource allocation index goes up monotonically, the allocator will eventually require mapping a new chunk. Now, chunks are also unmapped when their reference count goes back to zero. Thus, if a single app is running and starts/exits frequently we will have the following situation: When the app starts, a new chunk must be allocated and mapped. When the app exits, the chunk reference count goes back to zero, and the chunk is unmapped and freed. Therefore, the app must pay the cost of allocation and mapping of ICM memory each time it runs (although the price is paid only when allocating the initial entry in the new chunk). For apps which allocate MPTs/SRQs/CQs and which operate as described above, this presented a performance problem. We therefore roll back the round-robin allocator modification for MPTs, CQs, SRQs. Reported-by: Matthew Finlay Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/alloc.c | 12 +++++++++--- drivers/net/ethernet/mellanox/mlx4/cq.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/eq.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/main.c | 2 +- drivers/net/ethernet/mellanox/mlx4/mcg.c | 6 +++--- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 10 ++++++++-- drivers/net/ethernet/mellanox/mlx4/mr.c | 2 +- drivers/net/ethernet/mellanox/mlx4/pd.c | 6 +++--- drivers/net/ethernet/mellanox/mlx4/qp.c | 2 +- drivers/net/ethernet/mellanox/mlx4/srq.c | 4 ++-- 10 files changed, 32 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index 06fef5b44f77..c3ad464d0627 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -71,9 +71,9 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) return obj; } -void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) +void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr) { - mlx4_bitmap_free_range(bitmap, obj, 1); + mlx4_bitmap_free_range(bitmap, obj, 1, use_rr); } u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) @@ -118,11 +118,17 @@ u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap) return bitmap->avail; } -void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) +void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt, + int use_rr) { obj &= bitmap->max + bitmap->reserved_top - 1; spin_lock(&bitmap->lock); + if (!use_rr) { + bitmap->last = min(bitmap->last, obj); + bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) + & bitmap->mask; + } bitmap_clear(bitmap->table, obj, cnt); bitmap->avail += cnt; spin_unlock(&bitmap->lock); diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 22fcbe78311c..34c5b87a1c2a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -187,7 +187,7 @@ err_put: mlx4_table_put(dev, &cq_table->table, *cqn); err_out: - mlx4_bitmap_free(&cq_table->bitmap, *cqn); + mlx4_bitmap_free(&cq_table->bitmap, *cqn, MLX4_NO_RR); return err; } @@ -217,7 +217,7 @@ void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) mlx4_table_put(dev, &cq_table->cmpt_table, cqn); mlx4_table_put(dev, &cq_table->table, cqn); - mlx4_bitmap_free(&cq_table->bitmap, cqn); + mlx4_bitmap_free(&cq_table->bitmap, cqn, MLX4_NO_RR); } static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index c9cdb2a2c596..ae5212f8f090 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -963,7 +963,7 @@ err_out_free_mtt: mlx4_mtt_cleanup(dev, &eq->mtt); err_out_free_eq: - mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn); + mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR); err_out_free_pages: for (i = 0; i < npages; ++i) @@ -1018,7 +1018,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev, eq->page_list[i].map); kfree(eq->page_list); - mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn); + mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR); mlx4_free_cmd_mailbox(dev, mailbox); } diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 01fc6515384d..b37478db9851 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1654,7 +1654,7 @@ EXPORT_SYMBOL_GPL(mlx4_counter_alloc); void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx) { - mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx); + mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx, MLX4_USE_RR); return; } diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index acf9d5f1f922..40594055b831 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -996,7 +996,7 @@ out: index, dev->caps.num_mgms); else mlx4_bitmap_free(&priv->mcg_table.bitmap, - index - dev->caps.num_mgms); + index - dev->caps.num_mgms, MLX4_USE_RR); } mutex_unlock(&priv->mcg_table.mutex); @@ -1087,7 +1087,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], index, amgm_index, dev->caps.num_mgms); else mlx4_bitmap_free(&priv->mcg_table.bitmap, - amgm_index - dev->caps.num_mgms); + amgm_index - dev->caps.num_mgms, MLX4_USE_RR); } } else { /* Remove entry from AMGM */ @@ -1107,7 +1107,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], prev, index, dev->caps.num_mgms); else mlx4_bitmap_free(&priv->mcg_table.bitmap, - index - dev->caps.num_mgms); + index - dev->caps.num_mgms, MLX4_USE_RR); } out: diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index e582a41a802b..6ed9dfa5f05b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -783,6 +783,11 @@ enum { MLX4_PCI_DEV_FORCE_SENSE_PORT = 1 << 1, }; +enum { + MLX4_NO_RR = 0, + MLX4_USE_RR = 1, +}; + struct mlx4_priv { struct mlx4_dev dev; @@ -844,9 +849,10 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) extern struct workqueue_struct *mlx4_wq; u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); -void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj); +void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr); u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align); -void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt); +void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt, + int use_rr); u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap); int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved_bot, u32 resetrved_top); diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index b3ee9bafff5e..0558dddd81e5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -346,7 +346,7 @@ void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index) { struct mlx4_priv *priv = mlx4_priv(dev); - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); + mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index, MLX4_NO_RR); } static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index) diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c index 84cfb40bf451..c6af9619ce6d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/pd.c +++ b/drivers/net/ethernet/mellanox/mlx4/pd.c @@ -59,7 +59,7 @@ EXPORT_SYMBOL_GPL(mlx4_pd_alloc); void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) { - mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn); + mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn, MLX4_USE_RR); } EXPORT_SYMBOL_GPL(mlx4_pd_free); @@ -96,7 +96,7 @@ EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc); void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) { - mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn); + mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn, MLX4_USE_RR); } void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) @@ -164,7 +164,7 @@ EXPORT_SYMBOL_GPL(mlx4_uar_alloc); void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar) { - mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index); + mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index, MLX4_USE_RR); } EXPORT_SYMBOL_GPL(mlx4_uar_free); diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 2715e61dbb74..06b2d13d5310 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -250,7 +250,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) if (mlx4_is_qp_reserved(dev, (u32) base_qpn)) return; - mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt); + mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, MLX4_USE_RR); } void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) diff --git a/drivers/net/ethernet/mellanox/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c index 8fdf23753779..1d2f9d3862a7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/srq.c +++ b/drivers/net/ethernet/mellanox/mlx4/srq.c @@ -117,7 +117,7 @@ err_put: mlx4_table_put(dev, &srq_table->table, *srqn); err_out: - mlx4_bitmap_free(&srq_table->bitmap, *srqn); + mlx4_bitmap_free(&srq_table->bitmap, *srqn, MLX4_NO_RR); return err; } @@ -145,7 +145,7 @@ void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) mlx4_table_put(dev, &srq_table->cmpt_table, srqn); mlx4_table_put(dev, &srq_table->table, srqn); - mlx4_bitmap_free(&srq_table->bitmap, srqn); + mlx4_bitmap_free(&srq_table->bitmap, srqn, MLX4_NO_RR); } static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) -- cgit v1.2.3 From 7fa6803483ed215f9c73780194d49719a060bf1c Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 9 Dec 2013 15:55:36 -0800 Subject: usb: gadget: f_fs: remove loop from I/O function When endpoint changes (due to it being disabled or alt setting changed), mimic the action as if the change happened after the request has been queued, instead of retrying with the new endpoint. Signed-off-by: Michal Nazarewicz Cc: David Cohen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 94 ++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 774e8b89cdb5..1222cf9b62d3 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -758,73 +758,59 @@ static ssize_t ffs_epfile_io(struct file *file, ssize_t ret; int halt; - goto first_try; - do { - spin_unlock_irq(&epfile->ffs->eps_lock); - mutex_unlock(&epfile->mutex); + /* Are we still active? */ + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { + ret = -ENODEV; + goto error; + } -first_try: - /* Are we still active? */ - if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { - ret = -ENODEV; + /* Wait for endpoint to be enabled */ + ep = epfile->ep; + if (!ep) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; goto error; } - /* Wait for endpoint to be enabled */ - ep = epfile->ep; - if (!ep) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto error; - } - - if (wait_event_interruptible(epfile->wait, - (ep = epfile->ep))) { - ret = -EINTR; - goto error; - } - } - - /* Do we halt? */ - halt = !read == !epfile->in; - if (halt && epfile->isoc) { - ret = -EINVAL; + ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); + if (ret) { + ret = -EINTR; goto error; } + } - /* Allocate & copy */ - if (!halt && !data) { - data = kzalloc(len, GFP_KERNEL); - if (unlikely(!data)) - return -ENOMEM; + /* Do we halt? */ + halt = !read == !epfile->in; + if (halt && epfile->isoc) { + ret = -EINVAL; + goto error; + } - if (!read && - unlikely(__copy_from_user(data, buf, len))) { - ret = -EFAULT; - goto error; - } - } + /* Allocate & copy */ + if (!halt) { + data = kmalloc(len, GFP_KERNEL); + if (unlikely(!data)) + return -ENOMEM; - /* We will be using request */ - ret = ffs_mutex_lock(&epfile->mutex, - file->f_flags & O_NONBLOCK); - if (unlikely(ret)) + if (!read && unlikely(copy_from_user(data, buf, len))) { + ret = -EFAULT; goto error; + } + } - /* - * We're called from user space, we can use _irq rather then - * _irqsave - */ - spin_lock_irq(&epfile->ffs->eps_lock); + /* We will be using request */ + ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK); + if (unlikely(ret)) + goto error; - /* - * While we were acquiring mutex endpoint got disabled - * or changed? - */ - } while (unlikely(epfile->ep != ep)); + spin_lock_irq(&epfile->ffs->eps_lock); - /* Halt */ - if (unlikely(halt)) { + if (epfile->ep != ep) { + /* In the meantime, endpoint got disabled or changed. */ + ret = -ESHUTDOWN; + spin_unlock_irq(&epfile->ffs->eps_lock); + } else if (halt) { + /* Halt */ if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep)) usb_ep_set_halt(ep->ep); spin_unlock_irq(&epfile->ffs->eps_lock); -- cgit v1.2.3 From 219580e64f035bb9018dbb08d340f90b0ac50f8c Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 9 Dec 2013 15:55:37 -0800 Subject: usb: f_fs: check quirk to pad epout buf size when not aligned to maxpacketsize Check gadget.quirk_ep_out_aligned_size to decide if buffer size requires to be aligned to maxpacketsize of an out endpoint. ffs_epfile_io() needs to pad epout buffer to match above condition if quirk is found. Signed-off-by: Michal Nazarewicz Signed-off-by: David Cohen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 1222cf9b62d3..34940439bb18 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -753,9 +753,10 @@ static ssize_t ffs_epfile_io(struct file *file, char __user *buf, size_t len, int read) { struct ffs_epfile *epfile = file->private_data; + struct usb_gadget *gadget = epfile->ffs->gadget; struct ffs_ep *ep; char *data = NULL; - ssize_t ret; + ssize_t ret, data_len; int halt; /* Are we still active? */ @@ -788,7 +789,13 @@ static ssize_t ffs_epfile_io(struct file *file, /* Allocate & copy */ if (!halt) { - data = kmalloc(len, GFP_KERNEL); + /* + * Controller may require buffer size to be aligned to + * maxpacketsize of an out endpoint. + */ + data_len = read ? usb_ep_align_maybe(gadget, ep->ep, len) : len; + + data = kmalloc(data_len, GFP_KERNEL); if (unlikely(!data)) return -ENOMEM; @@ -823,7 +830,7 @@ static ssize_t ffs_epfile_io(struct file *file, req->context = &done; req->complete = ffs_epfile_io_complete; req->buf = data; - req->length = len; + req->length = data_len; ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); @@ -835,9 +842,17 @@ static ssize_t ffs_epfile_io(struct file *file, ret = -EINTR; usb_ep_dequeue(ep->ep, req); } else { + /* + * XXX We may end up silently droping data here. + * Since data_len (i.e. req->length) may be bigger + * than len (after being rounded up to maxpacketsize), + * we may end up with more data then user space has + * space for. + */ ret = ep->status; if (read && ret > 0 && - unlikely(copy_to_user(buf, data, ret))) + unlikely(copy_to_user(buf, data, + min_t(size_t, ret, len)))) ret = -EFAULT; } } -- cgit v1.2.3 From a4b9d94b3dc8e65951c1819d37f213b3c6815adc Mon Sep 17 00:00:00 2001 From: David Cohen Date: Mon, 9 Dec 2013 15:55:38 -0800 Subject: usb: dwc3: set gadget's quirk ep_out_align_size DWC3 requires epout to have buffer size aligned to MaxPacketSize value. This patch sets necessary quirk for it. Signed-off-by: David Cohen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5452c0fce360..b85ec110d6a0 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2599,6 +2599,12 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.sg_supported = true; dwc->gadget.name = "dwc3-gadget"; + /* + * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize + * on ep out. + */ + dwc->gadget.quirk_ep_out_aligned_size = true; + /* * REVISIT: Here we should clear all pending IRQs to be * sure we're starting from a well known location. -- cgit v1.2.3 From ad071acb53110c8efd26ff1e5b5d57449b43833b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 9 Dec 2013 10:37:24 +0000 Subject: drm/i915: Repeat eviction search after idling the GPU With the advent of hw context support, we gained some objects that are pinned for the duration of their request. That is we can make aperture space available by idling the GPU and in the process performing a context switch back to the always-pinned default context. As such, we should not conclude that there is no space in the aperture for the current object until we have unpinned any such context objects. Note that we also have the problem of outstanding pageflips preventing eviction of their framebuffer objects to resolve. Testcase: igt/gem_ctx_exec/eviction Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=72507 Signed-off-by: Chris Wilson Tested-by: lu hua Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_evict.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index b7376533633d..8f3adc7d0dc8 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -88,6 +88,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, } else drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level); +search_again: /* First see if there is a large enough contiguous idle region... */ list_for_each_entry(vma, &vm->inactive_list, mm_list) { if (mark_free(vma, &unwind_list)) @@ -115,10 +116,17 @@ none: list_del_init(&vma->exec_list); } - /* We expect the caller to unpin, evict all and try again, or give up. - * So calling i915_gem_evict_vm() is unnecessary. + /* Can we unpin some objects such as idle hw contents, + * or pending flips? */ - return -ENOSPC; + ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev); + if (ret) + return ret; + + /* Only idle the GPU and repeat the search once */ + i915_gem_retire_requests(dev); + nonblocking = true; + goto search_again; found: /* drm_mm doesn't allow any other other operations while -- cgit v1.2.3 From 40fcd88b8d49fd911518190c985112097d3a8a17 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 10 Dec 2013 15:01:42 +0800 Subject: USB: storage: fix compile warning This patch should fix the below compile warning: drivers/usb/storage/protocol.c: In function 'usb_stor_access_xfer_buf': drivers/usb/storage/protocol.c:155:22: warning: comparison of distinct pointer types lacks a cast [enabled by default] Reported-by: kbuild test robot Reported-by: Stephen Rothwell Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/protocol.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index f54e5fea9230..12e3c2fac642 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -152,7 +152,8 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, return cnt; while (sg_miter_next(&miter) && cnt < buflen) { - unsigned int len = min(miter.length, buflen - cnt); + unsigned int len = min_t(unsigned int, miter.length, + buflen - cnt); if (dir == FROM_XFER_BUF) memcpy(buffer + cnt, miter.addr, len); -- cgit v1.2.3 From bf98c1eac1d4a6bcf00532e4fa41d8126cd6c187 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 9 Nov 2013 13:33:48 +0100 Subject: ARM: Rename ARCH_SHMOBILE to ARCH_SHMOBILE_LEGACY SH-Mobile platforms are transitioning from non-multiplatform to multiplatform kernel. A new ARCH_SHMOBILE_MULTI configuration symbol has been created to group all multiplatform-enabled SH-Mobile SoCs. The existing ARCH_SHMOBILE configuration symbol groups SoCs that haven't been converted yet. This arrangement works fine for the arch/ code, but lots of drivers needed on both ARCH_SHMOBILE and ARCH_SHMOBILE_MULTI depend on ARCH_SHMOBILE only. In order to avoid changing them, rename ARCH_SHMOBILE to ARCH_SHMOBILE_LEGACY, and create a new boolean ARCH_SHMOBILE configuration symbol that is selected by both ARCH_SHMOBILE_LEGACY and ARCH_SHMOBILE_MULTI. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/Kconfig | 14 ++++++++------ arch/arm/Makefile | 1 - arch/arm/boot/compressed/Makefile | 2 +- arch/arm/boot/dts/Makefile | 2 +- arch/arm/configs/ape6evm_defconfig | 2 +- arch/arm/configs/armadillo800eva_defconfig | 2 +- arch/arm/configs/bockw_defconfig | 2 +- arch/arm/configs/koelsch_defconfig | 2 +- arch/arm/configs/kzm9d_defconfig | 2 +- arch/arm/configs/kzm9g_defconfig | 2 +- arch/arm/configs/lager_defconfig | 2 +- arch/arm/configs/mackerel_defconfig | 2 +- arch/arm/configs/marzen_defconfig | 2 +- arch/arm/mach-shmobile/Kconfig | 8 ++++++-- drivers/Makefile | 2 +- 15 files changed, 26 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee953..483d316543ad 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -644,8 +644,9 @@ config ARCH_MSM stack and controls some vital subsystems (clock and power control, etc). -config ARCH_SHMOBILE - bool "Renesas SH-Mobile / R-Mobile" +config ARCH_SHMOBILE_LEGACY + bool "Renesas SH-Mobile / R-Mobile (non-multiplatform)" + select ARCH_SHMOBILE select ARM_PATCH_PHYS_VIRT select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS @@ -660,7 +661,8 @@ config ARCH_SHMOBILE select PM_GENERIC_DOMAINS if PM select SPARSE_IRQ help - Support for Renesas's SH-Mobile and R-Mobile ARM platforms. + Support for Renesas's SH-Mobile and R-Mobile ARM platforms using + a non-multiplatform kernel. config ARCH_RPC bool "RiscPC" @@ -1611,7 +1613,7 @@ config HZ_FIXED default 200 if ARCH_EBSA110 || ARCH_S3C24XX || ARCH_S5P64X0 || \ ARCH_S5PV210 || ARCH_EXYNOS4 default AT91_TIMER_HZ if ARCH_AT91 - default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE + default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE_LEGACY default 0 choice @@ -1796,8 +1798,8 @@ config ARCH_WANT_GENERAL_HUGETLB source "mm/Kconfig" config FORCE_MAX_ZONEORDER - int "Maximum zone order" if ARCH_SHMOBILE - range 11 64 if ARCH_SHMOBILE + int "Maximum zone order" if ARCH_SHMOBILE_LEGACY + range 11 64 if ARCH_SHMOBILE_LEGACY default "12" if SOC_AM33XX default "9" if SA1111 default "11" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c99b1086d83d..1edf8ebd8494 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -190,7 +190,6 @@ machine-$(CONFIG_ARCH_S5PC100) += s5pc100 machine-$(CONFIG_ARCH_S5PV210) += s5pv210 machine-$(CONFIG_ARCH_SA1100) += sa1100 machine-$(CONFIG_ARCH_SHMOBILE) += shmobile -machine-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile machine-$(CONFIG_ARCH_SIRF) += prima2 machine-$(CONFIG_ARCH_SOCFPGA) += socfpga machine-$(CONFIG_ARCH_STI) += sti diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index e7190bb5998e..f54d5a25c7ee 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -64,7 +64,7 @@ else endif endif -ifeq ($(CONFIG_ARCH_SHMOBILE),y) +ifeq ($(CONFIG_ARCH_SHMOBILE_LEGACY),y) OBJS += head-shmobile.o endif diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d57c1a65b24f..5839077fac91 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -216,7 +216,7 @@ dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \ s3c6410-smdk6410.dtb -dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \ +dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += emev2-kzm9d.dtb \ r7s72100-genmai.dtb \ r8a7740-armadillo800eva.dtb \ r8a7778-bockw.dtb \ diff --git a/arch/arm/configs/ape6evm_defconfig b/arch/arm/configs/ape6evm_defconfig index 1ce39940795d..cb26c62dc722 100644 --- a/arch/arm/configs/ape6evm_defconfig +++ b/arch/arm/configs/ape6evm_defconfig @@ -13,7 +13,7 @@ CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y CONFIG_SLAB=y # CONFIG_BLOCK is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_R8A73A4=y CONFIG_MACH_APE6EVM=y # CONFIG_ARM_THUMB is not set diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig index fae939d3d7f0..5abf1a2e3160 100644 --- a/arch/arm/configs/armadillo800eva_defconfig +++ b/arch/arm/configs/armadillo800eva_defconfig @@ -15,7 +15,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_R8A7740=y CONFIG_MACH_ARMADILLO800EVA=y # CONFIG_SH_TIMER_TMU is not set diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig index b38cd107f82d..1dd39716d7cb 100644 --- a/arch/arm/configs/bockw_defconfig +++ b/arch/arm/configs/bockw_defconfig @@ -8,7 +8,7 @@ CONFIG_SYSCTL_SYSCALL=y CONFIG_EMBEDDED=y CONFIG_SLAB=y # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_R8A7778=y CONFIG_MACH_BOCKW=y CONFIG_MEMORY_START=0x60000000 diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig index 825c16dee8a0..7fd65a01ec7e 100644 --- a/arch/arm/configs/koelsch_defconfig +++ b/arch/arm/configs/koelsch_defconfig @@ -9,7 +9,7 @@ CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y CONFIG_SLAB=y # CONFIG_BLOCK is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_R8A7791=y CONFIG_MACH_KOELSCH=y # CONFIG_SWP_EMULATE is not set diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig index 6c37f4a98eb8..217f1dda2965 100644 --- a/arch/arm/configs/kzm9d_defconfig +++ b/arch/arm/configs/kzm9d_defconfig @@ -13,7 +13,7 @@ CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_EMEV2=y CONFIG_MACH_KZM9D=y CONFIG_MEMORY_START=0x40000000 diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig index 1ad028023a64..9934dbc23d64 100644 --- a/arch/arm/configs/kzm9g_defconfig +++ b/arch/arm/configs/kzm9g_defconfig @@ -22,7 +22,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_SH73A0=y CONFIG_MACH_KZM9G=y CONFIG_MEMORY_START=0x41000000 diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig index 35bff5e0d57a..35dc8b2be47f 100644 --- a/arch/arm/configs/lager_defconfig +++ b/arch/arm/configs/lager_defconfig @@ -12,7 +12,7 @@ CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_R8A7790=y CONFIG_MACH_LAGER=y # CONFIG_SH_TIMER_TMU is not set diff --git a/arch/arm/configs/mackerel_defconfig b/arch/arm/configs/mackerel_defconfig index 9fb11895b2e2..a61e1653fc5e 100644 --- a/arch/arm/configs/mackerel_defconfig +++ b/arch/arm/configs/mackerel_defconfig @@ -14,7 +14,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_SH7372=y CONFIG_MACH_MACKEREL=y CONFIG_MEMORY_SIZE=0x10000000 diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig index 5cc6360340b1..6981338cd08d 100644 --- a/arch/arm/configs/marzen_defconfig +++ b/arch/arm/configs/marzen_defconfig @@ -9,7 +9,7 @@ CONFIG_SYSCTL_SYSCALL=y CONFIG_EMBEDDED=y CONFIG_SLAB=y # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_SHMOBILE_LEGACY=y CONFIG_ARCH_R8A7779=y CONFIG_MACH_MARZEN=y CONFIG_MEMORY_START=0x60000000 diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 180b71fd86f8..1b7df173db0e 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -1,6 +1,10 @@ +config ARCH_SHMOBILE + bool + config ARCH_SHMOBILE_MULTI bool "SH-Mobile Series" if ARCH_MULTI_V7 depends on MMU + select ARCH_SHMOBILE select CPU_V7 select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP @@ -30,7 +34,7 @@ config MACH_KZM9D comment "SH-Mobile System Configuration" endif -if ARCH_SHMOBILE +if ARCH_SHMOBILE_LEGACY comment "SH-Mobile System Type" @@ -272,7 +276,7 @@ source "drivers/sh/Kconfig" endif -if ARCH_SHMOBILE || ARCH_SHMOBILE_MULTI +if ARCH_SHMOBILE menu "Timer and clock configuration" diff --git a/drivers/Makefile b/drivers/Makefile index 3cc8214f9b26..8e3b8b06c0b2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -118,7 +118,7 @@ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ -obj-$(CONFIG_ARCH_SHMOBILE) += sh/ +obj-$(CONFIG_ARCH_SHMOBILE_LEGACY) += sh/ ifndef CONFIG_ARCH_USES_GETTIMEOFFSET obj-y += clocksource/ endif -- cgit v1.2.3 From 903cbb83d22a4c22acb48c2ed2580cc0bffaa772 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 30 Oct 2013 00:09:44 -0300 Subject: [media] v4l: ti-vpe: use module_platform_driver to simplify the code module_platform_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Wei Yongjun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpe.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 4e58069e24ff..89658a3ab23e 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -2081,18 +2081,7 @@ static struct platform_driver vpe_pdrv = { }, }; -static void __exit vpe_exit(void) -{ - platform_driver_unregister(&vpe_pdrv); -} - -static int __init vpe_init(void) -{ - return platform_driver_register(&vpe_pdrv); -} - -module_init(vpe_init); -module_exit(vpe_exit); +module_platform_driver(vpe_pdrv); MODULE_DESCRIPTION("TI VPE driver"); MODULE_AUTHOR("Dale Farnsworth, "); -- cgit v1.2.3 From 6676cafe6bb69898cdb94937651249d0999e4b59 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 30 Oct 2013 00:10:45 -0300 Subject: [media] v4l: ti-vpe: fix error return code in vpe_probe() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Reviewed-by: Archit Taneja Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 89658a3ab23e..1a31c8585a1b 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -2007,8 +2007,10 @@ static int vpe_probe(struct platform_device *pdev) vpe_top_vpdma_reset(dev); dev->vpdma = vpdma_create(pdev); - if (IS_ERR(dev->vpdma)) + if (IS_ERR(dev->vpdma)) { + ret = PTR_ERR(dev->vpdma); goto runtime_put; + } vfd = &dev->vfd; *vfd = vpe_videodev; -- cgit v1.2.3 From b68231a1b5e95a532f4d5135cdbd0fe6b0bfcb3b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 30 Oct 2013 00:15:13 -0300 Subject: [media] v4l: ti-vpe: fix return value check in vpe_probe() In case of error, the function devm_kzalloc() and devm_ioremap() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Reviewed-by: Archit Taneja Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpe.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 1a31c8585a1b..f949ef57a54c 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -1942,8 +1942,8 @@ static int vpe_probe(struct platform_device *pdev) int ret, irq, func; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); - if (IS_ERR(dev)) - return PTR_ERR(dev); + if (!dev) + return -ENOMEM; spin_lock_init(&dev->lock); @@ -1962,8 +1962,8 @@ static int vpe_probe(struct platform_device *pdev) * registers based on the sub block base addresses */ dev->base = devm_ioremap(&pdev->dev, res->start, SZ_32K); - if (IS_ERR(dev->base)) { - ret = PTR_ERR(dev->base); + if (!dev->base) { + ret = -ENOMEM; goto v4l2_dev_unreg; } -- cgit v1.2.3 From 18334c8e18b2cea1c5c1ad4103ea1bf359a21775 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Dec 2013 09:26:01 +0100 Subject: pinctrl: make the MSM SoC driver depend on OF We had a compilation failure on x86_64 due to missing OF support as this was an implicit dependency. Add an explicit dependency on OF and OF_IRQ on the SoC driver. Cc: Bjorn Andersson Signed-off-by: Linus Walleij --- ChangeLog v2->v3: - Total failure with older approaches: what we need to do is have the *SoC subdriver* depend on OF and OF_IRQ. This is because the placeholder bool PINCTRL_MSM cannot cascade its dependencies when a subdriver selects it, Kconfig is smart but not that smart. ChangeLog v1->v2: - OK so "depends on OF" did not work here let's try to simply select OF and OF_IRQ for this then? It's one of those "warning: (PINCTRL_MSM8X74) selects PINCTRL_MSM which has unmet direct dependencies (PINCTRL && OF)" that I simply cannot find my way out of :-/ --- drivers/pinctrl/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 06e057bb3376..30fcb897eb99 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -211,6 +211,7 @@ config PINCTRL_MSM config PINCTRL_MSM8X74 bool "Qualcomm 8x74 pin controller driver" + depends on OF && OF_IRQ select PINCTRL_MSM config PINCTRL_NOMADIK -- cgit v1.2.3 From 431cb350187c6bf1ed083622d633418a298a7216 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Sat, 2 Nov 2013 16:49:32 -0300 Subject: [media] az6007: support Technisat Cablestar Combo HDCI (minus remote) This is similar to the Terratec H7. It works with the same az6007 firmware as the former, however the drx-k firmware of the H7 will NOT work. Hence use a different firmware name. The firmware does not need to exist as the one in the eeprom is just fine as long as the h7 one doesn't get loaded, but maybe some day someone wants to load it (the one from the h5 would work too). Also since the config entry is now different anyway disable support for rc. AFAIK the Technisat remote (TS35) is RC5 and the code (which a code comment claims doesn't work anyway) only would handle NEC hence it's pointless creating a device and polling it if we already know it can't work. CI is untested. Originally based on idea found on http://www.linuxtv.org/wiki/index.php/TechniSat_CableStar_Combo_HD_CI claiming only id needs to be added (but failed to mention it only worked because the driver couldn't find the h7 drx-k firmware...). Signed-off-by: Roland Scheidegger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb-v2/az6007.c | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 419a2d6b4349..4a5345476c21 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -365,6 +365,7 @@ #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001 #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 +#define USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI 0x0003 #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 #define USB_PID_CPYTO_REDI_PC50A 0xa803 diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 44c64ef361bf..c1051c347744 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -68,6 +68,19 @@ static struct drxk_config terratec_h7_drxk = { .microcode_name = "dvb-usb-terratec-h7-drxk.fw", }; +static struct drxk_config cablestar_hdci_drxk = { + .adr = 0x29, + .parallel_ts = true, + .dynamic_clk = true, + .single_master = true, + .enable_merr_cfg = true, + .no_i2c_bridge = false, + .chunk_size = 64, + .mpeg_out_clk_strength = 0x02, + .qam_demod_parameter_count = 2, + .microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw", +}; + static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct az6007_device_state *st = fe_to_priv(fe); @@ -630,6 +643,27 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) return 0; } +static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct az6007_device_state *st = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); + + pr_debug("attaching demod drxk\n"); + + adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk, + &d->i2c_adap); + if (!adap->fe[0]) + return -EINVAL; + + adap->fe[0]->sec_priv = adap; + st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; + adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; + + az6007_ci_init(adap); + + return 0; +} + static int az6007_tuner_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap_to_d(adap); @@ -868,6 +902,29 @@ static struct dvb_usb_device_properties az6007_props = { } }; +static struct dvb_usb_device_properties az6007_cablestar_hdci_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .firmware = AZ6007_FIRMWARE, + + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct az6007_device_state), + .i2c_algo = &az6007_i2c_algo, + .tuner_attach = az6007_tuner_attach, + .frontend_attach = az6007_cablestar_hdci_frontend_attach, + .streaming_ctrl = az6007_streaming_ctrl, +/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */ + .get_rc_config = NULL, + .read_mac_address = az6007_read_mac_addr, + .download_firmware = az6007_download_firmware, + .identify_state = az6007_identify_state, + .power_ctrl = az6007_power_ctrl, + .num_adapters = 1, + .adapter = { + { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } + } +}; + static struct usb_device_id az6007_usb_table[] = { {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, @@ -875,6 +932,8 @@ static struct usb_device_id az6007_usb_table[] = { &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, + {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI, + &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)}, {0}, }; -- cgit v1.2.3 From b03aaa9c733e15d0d13f4f80987f6b93fc6a9e03 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 20 Nov 2013 10:03:06 +0000 Subject: i40e: restrict diag test messages Use the netif_info() macro to restrict messaging to when the HW bit is enabled in the msglvl netdev message mask. Change-Id: I83030d4402991cfb7da100da00f05ce502ada4ae Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index f0bab1704dd1..b04e4337df47 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -711,7 +711,7 @@ static int i40e_link_test(struct net_device *netdev, u64 *data) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; - netdev_info(netdev, "link test\n"); + netif_info(pf, hw, netdev, "link test\n"); if (i40e_get_link_status(&pf->hw)) *data = 0; else @@ -725,7 +725,7 @@ static int i40e_reg_test(struct net_device *netdev, u64 *data) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; - netdev_info(netdev, "register test\n"); + netif_info(pf, hw, netdev, "register test\n"); *data = i40e_diag_reg_test(&pf->hw); i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); @@ -737,7 +737,7 @@ static int i40e_eeprom_test(struct net_device *netdev, u64 *data) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; - netdev_info(netdev, "eeprom test\n"); + netif_info(pf, hw, netdev, "eeprom test\n"); *data = i40e_diag_eeprom_test(&pf->hw); return *data; @@ -749,7 +749,7 @@ static int i40e_intr_test(struct net_device *netdev, u64 *data) struct i40e_pf *pf = np->vsi->back; u16 swc_old = pf->sw_int_count; - netdev_info(netdev, "interrupt test\n"); + netif_info(pf, hw, netdev, "interrupt test\n"); wr32(&pf->hw, I40E_PFINT_DYN_CTL0, (I40E_PFINT_DYN_CTL0_INTENA_MASK | I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK)); @@ -761,7 +761,10 @@ static int i40e_intr_test(struct net_device *netdev, u64 *data) static int i40e_loopback_test(struct net_device *netdev, u64 *data) { - netdev_info(netdev, "loopback test not implemented\n"); + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; + + netif_info(pf, hw, netdev, "loopback test not implemented\n"); *data = 0; return *data; @@ -776,8 +779,7 @@ static void i40e_diag_test(struct net_device *netdev, set_bit(__I40E_TESTING, &pf->state); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ - - netdev_info(netdev, "offline testing starting\n"); + netif_info(pf, drv, netdev, "offline testing starting\n"); /* Link test performed before hardware reset * so autoneg doesn't interfere with test result @@ -798,8 +800,9 @@ static void i40e_diag_test(struct net_device *netdev, eth_test->flags |= ETH_TEST_FL_FAILED; } else { - netdev_info(netdev, "online test starting\n"); /* Online tests */ + netif_info(pf, drv, netdev, "online testing starting\n"); + if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -811,7 +814,7 @@ static void i40e_diag_test(struct net_device *netdev, } clear_bit(__I40E_TESTING, &pf->state); - netdev_info(netdev, "testing finished\n"); + netif_info(pf, drv, netdev, "testing finished\n"); } static void i40e_get_wol(struct net_device *netdev, -- cgit v1.2.3 From 639dc3777f2539183d6d1e0d84c992cedff598be Mon Sep 17 00:00:00 2001 From: Kamil Krawczyk Date: Wed, 20 Nov 2013 10:03:07 +0000 Subject: i40e: loopback info and set loopback fix Add information about current loopback mode to data returned from get_link_info function. Minor fix in set_loopback function and update in loopback types enum. Change-Id: I9d1c540a84ab18eef5ea6429be6331f33fc06aca Signed-off-by: Kamil Krawczyk Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 1 + drivers/net/ethernet/intel/i40e/i40e_diag.h | 8 ++++---- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 0b52fbc7d56d..e526d40e9cf8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -562,6 +562,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, hw_link_info->link_info = resp->link_info; hw_link_info->an_info = resp->an_info; hw_link_info->ext_info = resp->ext_info; + hw_link_info->loopback = resp->loopback; if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE)) hw_link_info->lse_enable = true; diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.h b/drivers/net/ethernet/intel/i40e/i40e_diag.h index 3d98277f4526..d1fc68cd6c94 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.h +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.h @@ -31,10 +31,10 @@ #include "i40e_type.h" enum i40e_lb_mode { - I40E_LB_MODE_NONE = 0, - I40E_LB_MODE_PHY_LOCAL, - I40E_LB_MODE_PHY_REMOTE, - I40E_LB_MODE_MAC_LOCAL, + I40E_LB_MODE_NONE = 0x0, + I40E_LB_MODE_PHY_LOCAL = I40E_AQ_LB_PHY_LOCAL, + I40E_LB_MODE_PHY_REMOTE = I40E_AQ_LB_PHY_REMOTE, + I40E_LB_MODE_MAC_LOCAL = I40E_AQ_LB_MAC_LOCAL, }; struct i40e_diag_reg_test_info { diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 88b37e07b255..8ae644570263 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -172,6 +172,7 @@ struct i40e_link_status { u8 link_info; u8 an_info; u8 ext_info; + u8 loopback; /* is Link Status Event notification to SW enabled */ bool lse_enable; }; -- cgit v1.2.3 From 1fa18370e4cd88669f2d1569d314b05f45b3538e Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 20 Nov 2013 10:03:08 +0000 Subject: i40e: complain about out-of-range descriptor request Instead of silently clamping the descriptor change request into the proper range, fail the request and complain in the log file. Change-Id: Id55ef59255d93c04bedffa8e25fe7ea796c90f32 Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index b04e4337df47..fd3e379de6da 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -422,15 +422,19 @@ static int i40e_set_ringparam(struct net_device *netdev, if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; - new_tx_count = clamp_t(u32, ring->tx_pending, - I40E_MIN_NUM_DESCRIPTORS, - I40E_MAX_NUM_DESCRIPTORS); - new_tx_count = ALIGN(new_tx_count, I40E_REQ_DESCRIPTOR_MULTIPLE); - - new_rx_count = clamp_t(u32, ring->rx_pending, - I40E_MIN_NUM_DESCRIPTORS, - I40E_MAX_NUM_DESCRIPTORS); - new_rx_count = ALIGN(new_rx_count, I40E_REQ_DESCRIPTOR_MULTIPLE); + if (ring->tx_pending > I40E_MAX_NUM_DESCRIPTORS || + ring->tx_pending < I40E_MIN_NUM_DESCRIPTORS || + ring->rx_pending > I40E_MAX_NUM_DESCRIPTORS || + ring->rx_pending < I40E_MIN_NUM_DESCRIPTORS) { + netdev_info(netdev, + "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d]\n", + ring->tx_pending, ring->rx_pending, + I40E_MIN_NUM_DESCRIPTORS, I40E_MAX_NUM_DESCRIPTORS); + return -EINVAL; + } + + new_tx_count = ALIGN(ring->tx_pending, I40E_REQ_DESCRIPTOR_MULTIPLE); + new_rx_count = ALIGN(ring->rx_pending, I40E_REQ_DESCRIPTOR_MULTIPLE); /* if nothing to do return success */ if ((new_tx_count == vsi->tx_rings[0]->count) && -- cgit v1.2.3 From 0319577f8902cd420d3159ac6dd134f1de10b52e Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 20 Nov 2013 10:03:09 +0000 Subject: i40e: remove and fix confusing define name I40E_ITR_NONE was being used as an ITRN register index by accident because it was easily associated with the I40E_RX_ITR and friends defines. Change the name slightly in order to make it clear that I40E_ITR_NONE is really associated with the DYN_CTL register sets. Change-Id: I04702c027c7495b90a8bf2db85d3e085a2c7d02a Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index db55d9947f15..faabf22fbd20 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -49,10 +49,23 @@ #define I40E_QUEUE_END_OF_LIST 0x7FF -#define I40E_ITR_NONE 3 -#define I40E_RX_ITR 0 -#define I40E_TX_ITR 1 -#define I40E_PE_ITR 2 +/* this enum matches hardware bits and is meant to be used by DYN_CTLN + * registers and QINT registers or more generally anywhere in the manual + * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any + * register but instead is a special value meaning "don't update" ITR0/1/2. + */ +enum i40e_dyn_idx_t { + I40E_IDX_ITR0 = 0, + I40E_IDX_ITR1 = 1, + I40E_IDX_ITR2 = 2, + I40E_ITR_NONE = 3 /* ITR_NONE must not be used as an index */ +}; + +/* these are indexes into ITRN registers */ +#define I40E_RX_ITR I40E_IDX_ITR0 +#define I40E_TX_ITR I40E_IDX_ITR1 +#define I40E_PE_ITR I40E_IDX_ITR2 + /* Supported Rx Buffer Sizes */ #define I40E_RXBUFFER_512 512 /* Used for packet split */ #define I40E_RXBUFFER_2048 2048 -- cgit v1.2.3 From 893238ac136d40d3321f02f4d4702fce4d265f4e Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 20 Nov 2013 10:03:10 +0000 Subject: i40e: Bump version number Version updated to 0.3.13-k Signed-off-by: Catherine Sullivan Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d2b48bb237fd..a6291e23fe5f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -36,7 +36,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 0 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 12 +#define DRV_VERSION_BUILD 13 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN -- cgit v1.2.3 From c0832b2c105d3b666bab325e2790267157df6290 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 22 Nov 2013 05:58:15 +0000 Subject: ixgbevf: update Kconfig description This patch updates the ixgbevf Kconfig description, as the VF driver supports more than just the 82599 device. This patch renames the config menu item, as well as updates the help description to make it more obvious that the driver supports more than just a single device group. Signed-off-by: Jacob Keller Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 149ac85b5f9e..41a2fa2fc67d 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -220,12 +220,12 @@ config IXGBE_DCB If unsure, say N. config IXGBEVF - tristate "Intel(R) 82599 Virtual Function Ethernet support" + tristate "Intel(R) 10GbE PCI Express Virtual Function Ethernet support" depends on PCI_MSI ---help--- - This driver supports Intel(R) 82599 virtual functions. For more - information on how to identify your adapter, go to the Adapter & - Driver ID Guide at: + This driver supports Intel(R) PCI Express virtual functions for the + Intel(R) ixgbe driver. For more information on how to identify your + adapter, go to the Adapter & Driver ID Guide at: -- cgit v1.2.3 From 5cdab2f620de9cb14de297326e30e3dd7ea769de Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 30 Oct 2013 07:45:39 +0000 Subject: ixgbe: Focus config of head, tail ntc, and ntu all into a single function This patch makes it so that head, tail, next to clean, and next to use are all reset in a single function for the Tx or Rx path. Previously the code for this was spread out over several areas which could make it difficult to track what the values for these were. Signed-off-by: Alexander Duyck Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 4 +- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 55 ++++++++--------------- 2 files changed, 19 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 8971e2d0a984..eaaa3ecacfd7 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -86,9 +86,7 @@ struct ixgbevf_ring { u64 bp_misses; u64 bp_cleaned; #endif - - u16 head; - u16 tail; + u8 __iomem *tail; u16 reg_idx; /* holds the special value that gets the hardware register * offset associated with this ring, which is different diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 92ef4cb5a8e8..84b55fe71546 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -98,10 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector); static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter); -static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, - struct ixgbevf_ring *rx_ring, +static inline void ixgbevf_release_rx_desc(struct ixgbevf_ring *rx_ring, u32 val) { + rx_ring->next_to_use = val; + /* * Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only @@ -109,7 +110,7 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, * such as IA-64). */ wmb(); - IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rx_ring->reg_idx), val); + writel(val, rx_ring->tail); } /** @@ -406,10 +407,8 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, } no_buffers: - if (rx_ring->next_to_use != i) { - rx_ring->next_to_use = i; - ixgbevf_release_rx_desc(&adapter->hw, rx_ring, i); - } + if (rx_ring->next_to_use != i) + ixgbevf_release_rx_desc(rx_ring, i); } static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter, @@ -1110,8 +1109,9 @@ static void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(j), tdlen); IXGBE_WRITE_REG(hw, IXGBE_VFTDH(j), 0); IXGBE_WRITE_REG(hw, IXGBE_VFTDT(j), 0); - adapter->tx_ring[i].head = IXGBE_VFTDH(j); - adapter->tx_ring[i].tail = IXGBE_VFTDT(j); + ring->tail = hw->hw_addr + IXGBE_VFTDT(j); + ring->next_to_clean = 0; + ring->next_to_use = 0; /* Disable Tx Head Writeback RO bit, since this hoses * bookkeeping if things aren't delivered in order. */ @@ -1208,20 +1208,22 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) /* set_rx_buffer_len must be called before ring initialization */ ixgbevf_set_rx_buffer_len(adapter); - rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc); /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ for (i = 0; i < adapter->num_rx_queues; i++) { - rdba = adapter->rx_ring[i].dma; - j = adapter->rx_ring[i].reg_idx; + struct ixgbevf_ring *ring = &adapter->rx_ring[i]; + rdba = ring->dma; + j = ring->reg_idx; + rdlen = ring->count * sizeof(union ixgbe_adv_rx_desc); IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(j), (rdba & DMA_BIT_MASK(32))); IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(j), (rdba >> 32)); IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(j), rdlen); IXGBE_WRITE_REG(hw, IXGBE_VFRDH(j), 0); IXGBE_WRITE_REG(hw, IXGBE_VFRDT(j), 0); - adapter->rx_ring[i].head = IXGBE_VFRDH(j); - adapter->rx_ring[i].tail = IXGBE_VFRDT(j); + ring->tail = hw->hw_addr + IXGBE_VFRDT(j); + ring->next_to_clean = 0; + ring->next_to_use = 0; ixgbevf_configure_srrctl(adapter, j); } @@ -1402,7 +1404,7 @@ static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, hw_dbg(hw, "RXDCTL.ENABLE queue %d not set while polling\n", rxr); - ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr], + ixgbevf_release_rx_desc(&adapter->rx_ring[rxr], (adapter->rx_ring[rxr].count - 1)); } @@ -1680,14 +1682,6 @@ static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter, /* Zero out the descriptor ring */ memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - - if (rx_ring->head) - writel(0, adapter->hw.hw_addr + rx_ring->head); - if (rx_ring->tail) - writel(0, adapter->hw.hw_addr + rx_ring->tail); } /** @@ -1715,14 +1709,6 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter, memset(tx_ring->tx_buffer_info, 0, size); memset(tx_ring->desc, 0, tx_ring->size); - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - if (tx_ring->head) - writel(0, adapter->hw.hw_addr + tx_ring->head); - if (tx_ring->tail) - writel(0, adapter->hw.hw_addr + tx_ring->tail); } /** @@ -2473,8 +2459,6 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter, if (!tx_ring->desc) goto err; - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; return 0; err: @@ -2542,9 +2526,6 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter, goto alloc_failed; } - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - return 0; alloc_failed: return -ENOMEM; @@ -3181,7 +3162,7 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ixgbevf_tx_map(tx_ring, skb, tx_flags), first, skb->len, hdr_len); - writel(tx_ring->next_to_use, adapter->hw.hw_addr + tx_ring->tail); + writel(tx_ring->next_to_use, tx_ring->tail); ixgbevf_maybe_stop_tx(tx_ring, DESC_NEEDED); -- cgit v1.2.3 From 2bdfc4e271c290be448ae5df580be1163b998508 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 17 Oct 2013 05:23:01 +0000 Subject: igb: Add media switching feature for i354 PHY's This patch adds a new feature which is supported in some PHY's on some i354 devices. This feature is Auto Media Detect and allows which ever media is detected first by the PHY to be the media used and configured by the device. This is a media swapping feature that is wholly contained in the Marvell PHY. Signed-off-by: Carolyn Wyborny Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/e1000_82575.c | 76 ++++++++++++++++++++++++++ drivers/net/ethernet/intel/igb/e1000_defines.h | 11 ++++ drivers/net/ethernet/intel/igb/e1000_hw.h | 2 + drivers/net/ethernet/intel/igb/igb.h | 1 + drivers/net/ethernet/intel/igb/igb_main.c | 6 ++ 5 files changed, 96 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 47c2d10df826..fe9db48f9084 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -112,6 +112,59 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw) return ext_mdio; } +/** + * igb_check_for_link_media_swap - Check which M88E1112 interface linked + * @hw: pointer to the HW structure + * + * Poll the M88E1112 interfaces to see which interface achieved link. + */ +static s32 igb_check_for_link_media_swap(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + u8 port = 0; + + /* Check the copper medium. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; + + ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); + if (ret_val) + return ret_val; + + if (data & E1000_M88E1112_STATUS_LINK) + port = E1000_MEDIA_PORT_COPPER; + + /* Check the other medium. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); + if (ret_val) + return ret_val; + + ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); + if (ret_val) + return ret_val; + + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; + + if (data & E1000_M88E1112_STATUS_LINK) + port = E1000_MEDIA_PORT_OTHER; + + /* Determine if a swap needs to happen. */ + if (port && (hw->dev_spec._82575.media_port != port)) { + hw->dev_spec._82575.media_port = port; + hw->dev_spec._82575.media_changed = true; + } else { + ret_val = igb_check_for_link_82575(hw); + } + + return E1000_SUCCESS; +} + /** * igb_init_phy_params_82575 - Init PHY func ptrs. * @hw: pointer to the HW structure @@ -189,6 +242,29 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) else phy->ops.get_cable_length = igb_get_cable_length_m88; phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; + /* Check if this PHY is confgured for media swap. */ + if (phy->id == M88E1112_E_PHY_ID) { + u16 data; + + ret_val = phy->ops.write_reg(hw, + E1000_M88E1112_PAGE_ADDR, + 2); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, + E1000_M88E1112_MAC_CTRL_1, + &data); + if (ret_val) + goto out; + + data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> + E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; + if (data == E1000_M88E1112_AUTO_COPPER_SGMII || + data == E1000_M88E1112_AUTO_COPPER_BASEX) + hw->mac.ops.check_for_link = + igb_check_for_link_media_swap; + } break; case IGP03E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 978eca31ceda..378ca21aa647 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -532,6 +532,17 @@ #define E1000_MDICNFG_PHY_MASK 0x03E00000 #define E1000_MDICNFG_PHY_SHIFT 21 +#define E1000_MEDIA_PORT_COPPER 1 +#define E1000_MEDIA_PORT_OTHER 2 +#define E1000_M88E1112_AUTO_COPPER_SGMII 0x2 +#define E1000_M88E1112_AUTO_COPPER_BASEX 0x3 +#define E1000_M88E1112_STATUS_LINK 0x0004 /* Interface Link Bit */ +#define E1000_M88E1112_MAC_CTRL_1 0x10 +#define E1000_M88E1112_MAC_CTRL_1_MODE_MASK 0x0380 /* Mode Select */ +#define E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT 7 +#define E1000_M88E1112_PAGE_ADDR 0x16 +#define E1000_M88E1112_STATUS 0x01 + /* PCI Express Control */ #define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 #define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 2e166b22d52b..5f9758f3206e 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h @@ -533,6 +533,8 @@ struct e1000_dev_spec_82575 { bool clear_semaphore_once; struct e1000_sfp_flags eth_flags; bool module_plugged; + u8 media_port; + bool media_changed; }; struct e1000_hw { diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 5e9ed89403aa..6c807927171f 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -462,6 +462,7 @@ struct igb_adapter { #define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 7) #define IGB_FLAG_WOL_SUPPORTED (1 << 8) #define IGB_FLAG_NEED_LINK_UPDATE (1 << 9) +#define IGB_FLAG_MEDIA_RESET (1 << 10) /* DMA Coalescing defines */ #define IGB_MIN_TXPBSIZE 20408 diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 025e5f4b7481..6da479b365c2 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3946,6 +3946,12 @@ static void igb_watchdog_task(struct work_struct *work) } if (link) { + /* Perform a reset if the media type changed. */ + if (hw->dev_spec._82575.media_changed) { + hw->dev_spec._82575.media_changed = false; + adapter->flags |= IGB_FLAG_MEDIA_RESET; + igb_reset(adapter); + } /* Cancel scheduled suspend requests. */ pm_runtime_resume(netdev->dev.parent); -- cgit v1.2.3 From 89dbefb213a0b3e53fe1a99ec9c1a230aad5f404 Mon Sep 17 00:00:00 2001 From: Aaron Sierra Date: Thu, 31 Oct 2013 00:32:34 +0000 Subject: igb: Support ports mapped in 64-bit PCI space This patch resolves an issue with 64-bit PCI addresses being truncated because the return values of pci_resource_start() and pci_resource_end() were being cast to unsigned long. Signed-off-by: Aaron Sierra Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 6da479b365c2..ed129f1c5c3e 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2022,7 +2022,6 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) s32 ret_val; static int global_quad_port_a; /* global quad port a indication */ const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; - unsigned long mmio_start, mmio_len; int err, pci_using_dac; u8 part_str[E1000_PBANUM_LENGTH]; @@ -2079,11 +2078,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->back = adapter; adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - mmio_start = pci_resource_start(pdev, 0); - mmio_len = pci_resource_len(pdev, 0); - err = -EIO; - hw->hw_addr = ioremap(mmio_start, mmio_len); + hw->hw_addr = pci_iomap(pdev, 0, 0); if (!hw->hw_addr) goto err_ioremap; @@ -2093,8 +2089,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len; + netdev->mem_start = pci_resource_start(pdev, 0); + netdev->mem_end = pci_resource_end(pdev, 0); /* PCI config space info */ hw->vendor_id = pdev->vendor; -- cgit v1.2.3 From 56cec249167b44ee2ba7a3cbf4431bee937e08e3 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 17 Oct 2013 05:36:26 +0000 Subject: igb: Add new feature Media Auto Sense for 82580 devices only This patch adds support for the hardware feature Media Auto Sense. This feature requires a custom EEPROM image provided by our customer support team. The feature allows hardware designed with dual PHY's, fiber and copper to be used with either media without additional EEPROM changes. Fiber is preferred and driver will swap and configure for fiber media if sensed by the device at any time. Device will swap back to copper if it is the only media detected. Signed-off-by: Carolyn Wyborny Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/e1000_82575.c | 13 ++ drivers/net/ethernet/intel/igb/e1000_defines.h | 5 + drivers/net/ethernet/intel/igb/e1000_hw.h | 1 + drivers/net/ethernet/intel/igb/igb.h | 10 ++ drivers/net/ethernet/intel/igb/igb_ethtool.c | 4 + drivers/net/ethernet/intel/igb/igb_main.c | 193 +++++++++++++++++++++++++ 6 files changed, 226 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index fe9db48f9084..06df6928f44c 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -441,6 +441,19 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw) ? igb_setup_copper_link_82575 : igb_setup_serdes_link_82575; + if (mac->type == e1000_82580) { + switch (hw->device_id) { + /* feature not supported on these id's */ + case E1000_DEV_ID_DH89XXCC_SGMII: + case E1000_DEV_ID_DH89XXCC_SERDES: + case E1000_DEV_ID_DH89XXCC_BACKPLANE: + case E1000_DEV_ID_DH89XXCC_SFP: + break; + default: + hw->dev_spec._82575.mas_capable = true; + break; + } + } return 0; } diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 378ca21aa647..0571b973be80 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -205,6 +205,11 @@ */ #define E1000_CONNSW_ENRGSRC 0x4 +#define E1000_CONNSW_PHYSD 0x400 +#define E1000_CONNSW_PHY_PDN 0x800 +#define E1000_CONNSW_SERDESD 0x200 +#define E1000_CONNSW_AUTOSENSE_CONF 0x2 +#define E1000_CONNSW_AUTOSENSE_EN 0x1 #define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_100 2 diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 5f9758f3206e..ab99e2b582a8 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h @@ -535,6 +535,7 @@ struct e1000_dev_spec_82575 { bool module_plugged; u8 media_port; bool media_changed; + bool mas_capable; }; struct e1000_hw { diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 6c807927171f..11173f46f436 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -450,6 +450,8 @@ struct igb_adapter { u8 rss_indir_tbl[IGB_RETA_SIZE]; unsigned long link_check_timeout; + int copper_tries; + struct e1000_info ei; }; #define IGB_FLAG_HAS_MSI (1 << 0) @@ -463,6 +465,14 @@ struct igb_adapter { #define IGB_FLAG_WOL_SUPPORTED (1 << 8) #define IGB_FLAG_NEED_LINK_UPDATE (1 << 9) #define IGB_FLAG_MEDIA_RESET (1 << 10) +#define IGB_FLAG_MAS_CAPABLE (1 << 11) +#define IGB_FLAG_MAS_ENABLE (1 << 12) + +/* Media Auto Sense */ +#define IGB_MAS_ENABLE_0 0X0001 +#define IGB_MAS_ENABLE_1 0X0002 +#define IGB_MAS_ENABLE_2 0X0004 +#define IGB_MAS_ENABLE_3 0X0008 /* DMA Coalescing defines */ #define IGB_MIN_TXPBSIZE 20408 diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index c3143da497c8..1c7d2381af8c 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -1983,6 +1983,10 @@ static void igb_diag_test(struct net_device *netdev, bool if_running = netif_running(netdev); set_bit(__IGB_TESTING, &adapter->state); + + /* can't do offline tests on media switching devices */ + if (adapter->hw.dev_spec._82575.mas_capable) + eth_test->flags &= ~ETH_TEST_FL_OFFLINE; if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index ed129f1c5c3e..3bc10bd5bbc1 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -1606,6 +1606,73 @@ static void igb_power_down_link(struct igb_adapter *adapter) igb_shutdown_serdes_link_82575(&adapter->hw); } +/** + * Detect and switch function for Media Auto Sense + * @adapter: address of the board private structure + **/ +static void igb_check_swap_media(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl_ext, connsw; + bool swap_now = false; + + ctrl_ext = rd32(E1000_CTRL_EXT); + connsw = rd32(E1000_CONNSW); + + /* need to live swap if current media is copper and we have fiber/serdes + * to go to. + */ + + if ((hw->phy.media_type == e1000_media_type_copper) && + (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) { + swap_now = true; + } else if (!(connsw & E1000_CONNSW_SERDESD)) { + /* copper signal takes time to appear */ + if (adapter->copper_tries < 4) { + adapter->copper_tries++; + connsw |= E1000_CONNSW_AUTOSENSE_CONF; + wr32(E1000_CONNSW, connsw); + return; + } else { + adapter->copper_tries = 0; + if ((connsw & E1000_CONNSW_PHYSD) && + (!(connsw & E1000_CONNSW_PHY_PDN))) { + swap_now = true; + connsw &= ~E1000_CONNSW_AUTOSENSE_CONF; + wr32(E1000_CONNSW, connsw); + } + } + } + + if (!swap_now) + return; + + switch (hw->phy.media_type) { + case e1000_media_type_copper: + netdev_info(adapter->netdev, + "MAS: changing media to fiber/serdes\n"); + ctrl_ext |= + E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + adapter->flags |= IGB_FLAG_MEDIA_RESET; + adapter->copper_tries = 0; + break; + case e1000_media_type_internal_serdes: + case e1000_media_type_fiber: + netdev_info(adapter->netdev, + "MAS: changing media to copper\n"); + ctrl_ext &= + ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + adapter->flags |= IGB_FLAG_MEDIA_RESET; + break; + default: + /* shouldn't get here during regular operation */ + netdev_err(adapter->netdev, + "AMS: Invalid media type found, returning\n"); + break; + } + wr32(E1000_CTRL_EXT, ctrl_ext); +} + /** * igb_up - Open the interface and prepare it to handle traffic * @adapter: board private structure @@ -1719,6 +1786,37 @@ void igb_reinit_locked(struct igb_adapter *adapter) clear_bit(__IGB_RESETTING, &adapter->state); } +/** igb_enable_mas - Media Autosense re-enable after swap + * + * @adapter: adapter struct + **/ +static s32 igb_enable_mas(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 connsw; + s32 ret_val = 0; + + connsw = rd32(E1000_CONNSW); + if (!(hw->phy.media_type == e1000_media_type_copper)) + return ret_val; + + /* configure for SerDes media detect */ + if (!(connsw & E1000_CONNSW_SERDESD)) { + connsw |= E1000_CONNSW_ENRGSRC; + connsw |= E1000_CONNSW_AUTOSENSE_EN; + wr32(E1000_CONNSW, connsw); + wrfl(); + } else if (connsw & E1000_CONNSW_SERDESD) { + /* already SerDes, no need to enable anything */ + return ret_val; + } else { + netdev_info(adapter->netdev, + "MAS: Unable to configure feature, disabling..\n"); + adapter->flags &= ~IGB_FLAG_MAS_ENABLE; + } + return ret_val; +} + void igb_reset(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; @@ -1830,6 +1928,16 @@ void igb_reset(struct igb_adapter *adapter) hw->mac.ops.reset_hw(hw); wr32(E1000_WUC, 0); + if (adapter->flags & IGB_FLAG_MEDIA_RESET) { + /* need to resetup here after media swap */ + adapter->ei.get_invariants(hw); + adapter->flags &= ~IGB_FLAG_MEDIA_RESET; + } + if (adapter->flags & IGB_FLAG_MAS_ENABLE) { + if (igb_enable_mas(adapter)) + dev_err(&pdev->dev, + "Error enabling Media Auto Sense\n"); + } if (hw->mac.ops.init_hw(hw)) dev_err(&pdev->dev, "Hardware Error\n"); @@ -1975,6 +2083,58 @@ void igb_set_fw_version(struct igb_adapter *adapter) return; } +/** + * igb_init_mas - init Media Autosense feature if enabled in the NVM + * + * @adapter: adapter struct + **/ +static void igb_init_mas(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u16 eeprom_data; + + hw->nvm.ops.read(hw, NVM_COMPAT, 1, &eeprom_data); + switch (hw->bus.func) { + case E1000_FUNC_0: + if (eeprom_data & IGB_MAS_ENABLE_0) { + adapter->flags |= IGB_FLAG_MAS_ENABLE; + netdev_info(adapter->netdev, + "MAS: Enabling Media Autosense for port %d\n", + hw->bus.func); + } + break; + case E1000_FUNC_1: + if (eeprom_data & IGB_MAS_ENABLE_1) { + adapter->flags |= IGB_FLAG_MAS_ENABLE; + netdev_info(adapter->netdev, + "MAS: Enabling Media Autosense for port %d\n", + hw->bus.func); + } + break; + case E1000_FUNC_2: + if (eeprom_data & IGB_MAS_ENABLE_2) { + adapter->flags |= IGB_FLAG_MAS_ENABLE; + netdev_info(adapter->netdev, + "MAS: Enabling Media Autosense for port %d\n", + hw->bus.func); + } + break; + case E1000_FUNC_3: + if (eeprom_data & IGB_MAS_ENABLE_3) { + adapter->flags |= IGB_FLAG_MAS_ENABLE; + netdev_info(adapter->netdev, + "MAS: Enabling Media Autosense for port %d\n", + hw->bus.func); + } + break; + default: + /* Shouldn't get here */ + netdev_err(adapter->netdev, + "MAS: Invalid port configuration, returning\n"); + break; + } +} + /** * igb_init_i2c - Init I2C interface * @adapter: pointer to adapter structure @@ -2346,6 +2506,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ets = false; } #endif + /* Check if Media Autosense is enabled */ + adapter->ei = *ei; + if (hw->dev_spec._82575.mas_capable) + igb_init_mas(adapter); + /* do hw tstamp init after resetting */ igb_ptp_init(adapter); @@ -3931,6 +4096,7 @@ static void igb_watchdog_task(struct work_struct *work) struct net_device *netdev = adapter->netdev; u32 link; int i; + u32 connsw; link = igb_has_link(adapter); @@ -3941,6 +4107,14 @@ static void igb_watchdog_task(struct work_struct *work) link = false; } + /* Force link down if we have fiber to swap to */ + if (adapter->flags & IGB_FLAG_MAS_ENABLE) { + if (hw->phy.media_type == e1000_media_type_copper) { + connsw = rd32(E1000_CONNSW); + if (!(connsw & E1000_CONNSW_AUTOSENSE_EN)) + link = 0; + } + } if (link) { /* Perform a reset if the media type changed. */ if (hw->dev_spec._82575.media_changed) { @@ -4028,8 +4202,27 @@ static void igb_watchdog_task(struct work_struct *work) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); + /* link is down, time to check for alternate media */ + if (adapter->flags & IGB_FLAG_MAS_ENABLE) { + igb_check_swap_media(adapter); + if (adapter->flags & IGB_FLAG_MEDIA_RESET) { + schedule_work(&adapter->reset_task); + /* return immediately */ + return; + } + } pm_schedule_suspend(netdev->dev.parent, MSEC_PER_SEC * 5); + + /* also check for alternate media here */ + } else if (!netif_carrier_ok(netdev) && + (adapter->flags & IGB_FLAG_MAS_ENABLE)) { + igb_check_swap_media(adapter); + if (adapter->flags & IGB_FLAG_MEDIA_RESET) { + schedule_work(&adapter->reset_task); + /* return immediately */ + return; + } } } -- cgit v1.2.3 From e3670b81954ab1247341a08514aa4df09f0b495e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 26 Nov 2013 07:15:23 +0000 Subject: igb: Convert to use devm_hwmon_device_register_with_groups Simplify the code. Attach hwmon sysfs attributes to hwmon device instead of pci device. Avoid race conditions caused by attributes being created after registration and provide mandatory 'name' attribute by using new hwmon API. Other cleanup: Instead of allocating memory for hwmon attributes, move attributes and all other hwmon related data into struct hwmon_buff and allocate the entire structure using devm_kzalloc. Check return value from calls to igb_add_hwmon_attr() one by one instead of logically combining them all together. Signed-off-by: Guenter Roeck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb.h | 8 ++- drivers/net/ethernet/intel/igb/igb_hwmon.c | 100 ++++++++++++++--------------- 2 files changed, 53 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 11173f46f436..8aaca0a1dca0 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -337,8 +337,10 @@ struct hwmon_attr { }; struct hwmon_buff { - struct device *device; - struct hwmon_attr *hwmon_list; + struct attribute_group group; + const struct attribute_group *groups[2]; + struct attribute *attrs[E1000_MAX_SENSORS * 4 + 1]; + struct hwmon_attr hwmon_list[E1000_MAX_SENSORS * 4]; unsigned int n_hwmon; }; #endif @@ -440,7 +442,7 @@ struct igb_adapter { char fw_version[32]; #ifdef CONFIG_IGB_HWMON - struct hwmon_buff igb_hwmon_buff; + struct hwmon_buff *igb_hwmon_buff; bool ets; #endif struct i2c_algo_bit_data i2c_algo; diff --git a/drivers/net/ethernet/intel/igb/igb_hwmon.c b/drivers/net/ethernet/intel/igb/igb_hwmon.c index 58f1ce967aeb..2e7ef2d0711f 100644 --- a/drivers/net/ethernet/intel/igb/igb_hwmon.c +++ b/drivers/net/ethernet/intel/igb/igb_hwmon.c @@ -117,8 +117,8 @@ static int igb_add_hwmon_attr(struct igb_adapter *adapter, unsigned int n_attr; struct hwmon_attr *igb_attr; - n_attr = adapter->igb_hwmon_buff.n_hwmon; - igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr]; + n_attr = adapter->igb_hwmon_buff->n_hwmon; + igb_attr = &adapter->igb_hwmon_buff->hwmon_list[n_attr]; switch (type) { case IGB_HWMON_TYPE_LOC: @@ -154,30 +154,16 @@ static int igb_add_hwmon_attr(struct igb_adapter *adapter, igb_attr->dev_attr.attr.mode = S_IRUGO; igb_attr->dev_attr.attr.name = igb_attr->name; sysfs_attr_init(&igb_attr->dev_attr.attr); - rc = device_create_file(&adapter->pdev->dev, - &igb_attr->dev_attr); - if (rc == 0) - ++adapter->igb_hwmon_buff.n_hwmon; - return rc; + adapter->igb_hwmon_buff->attrs[n_attr] = &igb_attr->dev_attr.attr; + + ++adapter->igb_hwmon_buff->n_hwmon; + + return 0; } static void igb_sysfs_del_adapter(struct igb_adapter *adapter) { - int i; - - if (adapter == NULL) - return; - - for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) { - device_remove_file(&adapter->pdev->dev, - &adapter->igb_hwmon_buff.hwmon_list[i].dev_attr); - } - - kfree(adapter->igb_hwmon_buff.hwmon_list); - - if (adapter->igb_hwmon_buff.device) - hwmon_device_unregister(adapter->igb_hwmon_buff.device); } /* called from igb_main.c */ @@ -189,11 +175,11 @@ void igb_sysfs_exit(struct igb_adapter *adapter) /* called from igb_main.c */ int igb_sysfs_init(struct igb_adapter *adapter) { - struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff; + struct hwmon_buff *igb_hwmon; + struct i2c_client *client; + struct device *hwmon_dev; unsigned int i; - int n_attrs; int rc = 0; - struct i2c_client *client = NULL; /* If this method isn't defined we don't support thermals */ if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) @@ -201,34 +187,16 @@ int igb_sysfs_init(struct igb_adapter *adapter) /* Don't create thermal hwmon interface if no sensors present */ rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)); - if (rc) - goto exit; - - /* init i2c_client */ - client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); - if (client == NULL) { - dev_info(&adapter->pdev->dev, - "Failed to create new i2c device..\n"); + if (rc) goto exit; - } - adapter->i2c_client = client; - /* Allocation space for max attributes - * max num sensors * values (loc, temp, max, caution) - */ - n_attrs = E1000_MAX_SENSORS * 4; - igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr), - GFP_KERNEL); - if (!igb_hwmon->hwmon_list) { + igb_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*igb_hwmon), + GFP_KERNEL); + if (!igb_hwmon) { rc = -ENOMEM; - goto err; - } - - igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev); - if (IS_ERR(igb_hwmon->device)) { - rc = PTR_ERR(igb_hwmon->device); - goto err; + goto exit; } + adapter->igb_hwmon_buff = igb_hwmon; for (i = 0; i < E1000_MAX_SENSORS; i++) { @@ -240,11 +208,39 @@ int igb_sysfs_init(struct igb_adapter *adapter) /* Bail if any hwmon attr struct fails to initialize */ rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION); - rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC); - rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP); - rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX); if (rc) - goto err; + goto exit; + rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC); + if (rc) + goto exit; + rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP); + if (rc) + goto exit; + rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX); + if (rc) + goto exit; + } + + /* init i2c_client */ + client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); + if (client == NULL) { + dev_info(&adapter->pdev->dev, + "Failed to create new i2c device.\n"); + rc = -ENODEV; + goto exit; + } + adapter->i2c_client = client; + + igb_hwmon->groups[0] = &igb_hwmon->group; + igb_hwmon->group.attrs = igb_hwmon->attrs; + + hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev, + client->name, + igb_hwmon, + igb_hwmon->groups); + if (IS_ERR(hwmon_dev)) { + rc = PTR_ERR(hwmon_dev); + goto err; } goto exit; -- cgit v1.2.3 From e6e25bba9b8a343af6b5e281a0378d3c8ae52165 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 26 Nov 2013 07:15:34 +0000 Subject: igb: Start temperature sensor attribute index with 1 Per hwmon ABI, temperature sensor attribute index starts with 1, not 0. Signed-off-by: Guenter Roeck Reviewed-by: Jean Delvare Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_hwmon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb_hwmon.c b/drivers/net/ethernet/intel/igb/igb_hwmon.c index 2e7ef2d0711f..e0af5bc61613 100644 --- a/drivers/net/ethernet/intel/igb/igb_hwmon.c +++ b/drivers/net/ethernet/intel/igb/igb_hwmon.c @@ -124,22 +124,22 @@ static int igb_add_hwmon_attr(struct igb_adapter *adapter, case IGB_HWMON_TYPE_LOC: igb_attr->dev_attr.show = igb_hwmon_show_location; snprintf(igb_attr->name, sizeof(igb_attr->name), - "temp%u_label", offset); + "temp%u_label", offset + 1); break; case IGB_HWMON_TYPE_TEMP: igb_attr->dev_attr.show = igb_hwmon_show_temp; snprintf(igb_attr->name, sizeof(igb_attr->name), - "temp%u_input", offset); + "temp%u_input", offset + 1); break; case IGB_HWMON_TYPE_CAUTION: igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh; snprintf(igb_attr->name, sizeof(igb_attr->name), - "temp%u_max", offset); + "temp%u_max", offset + 1); break; case IGB_HWMON_TYPE_MAX: igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh; snprintf(igb_attr->name, sizeof(igb_attr->name), - "temp%u_crit", offset); + "temp%u_crit", offset + 1); break; default: rc = -EPERM; -- cgit v1.2.3 From 73beb63d290f961c299526852884846b0d868840 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Dec 2013 12:20:36 +0100 Subject: mfd: rtsx_pcr: Disable interrupts before cancelling delayed works This fixes a kernel panic when resuming from suspend to RAM. Without this fix an interrupt hits after the delayed work is canceled and thus requeues it. So we end up freeing an armed timer. Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner Signed-off-by: Samuel Ortiz --- drivers/mfd/rtsx_pcr.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 11e20afbdcac..705698fd2c7e 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -1228,8 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev) pcr->remove_pci = true; - cancel_delayed_work(&pcr->carddet_work); - cancel_delayed_work(&pcr->idle_work); + /* Disable interrupts at the pcr level */ + spin_lock_irq(&pcr->lock); + rtsx_pci_writel(pcr, RTSX_BIER, 0); + pcr->bier = 0; + spin_unlock_irq(&pcr->lock); + + cancel_delayed_work_sync(&pcr->carddet_work); + cancel_delayed_work_sync(&pcr->idle_work); mfd_remove_devices(&pcidev->dev); -- cgit v1.2.3 From 215c65a067ccf5dc22e68f1f159ee83678e63ca9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Nov 2013 22:18:28 -0300 Subject: [media] v4l: sh_vou: Enable driver compilation with COMPILE_TEST This helps increasing build testing coverage. Cc: Guennadi Liakhovetski Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index d7f0249e4050..7f6ea6570122 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -36,7 +36,8 @@ source "drivers/media/platform/blackfin/Kconfig" config VIDEO_SH_VOU tristate "SuperH VOU video output driver" depends on MEDIA_CAMERA_SUPPORT - depends on VIDEO_DEV && ARCH_SHMOBILE && I2C + depends on VIDEO_DEV && I2C + depends on ARCH_SHMOBILE || COMPILE_TEST select VIDEOBUF_DMA_CONTIG help Support for the Video Output Unit (VOU) on SuperH SoCs. -- cgit v1.2.3 From fe9a2bd881d96b1491b283483d7346abb52111f9 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 6 Nov 2013 16:25:06 -0300 Subject: [media] af9035: add [0413:6a05] Leadtek WinFast DTV Dongle Dual It is IT9135 dual design. Thanks to Michael Piko for reporting that! Reported-by: Michael Piko Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index c8fcd78425bd..798565c4bb3e 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -1534,6 +1534,8 @@ static const struct usb_device_id af9035_id_table[] = { /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */ { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099, &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05, + &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, af9035_id_table); -- cgit v1.2.3 From 8620f394c4f9abd13e4fdf927d9c2bbeda74cde7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Nov 2013 02:45:34 +0100 Subject: sh-pfc: Fix PINMUX_GPIO macro Commit 7cbb0e55e27e ("sh-pfc: Don't duplicate argument to PINMUX_GPIO macro") erronesouly modified the PINMUX_GPIO macro in a way that resulted in all pins being named "name". Fix the macro to name the pins correctly. Cc: stable@vger.kernel.org Signed-off-by: Laurent Pinchart Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/sh_pfc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 11bd0d970a52..e2142956a8e5 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -254,7 +254,7 @@ struct sh_pfc_soc_info { #define PINMUX_GPIO(_pin) \ [GPIO_##_pin] = { \ .pin = (u16)-1, \ - .name = __stringify(name), \ + .name = __stringify(GPIO_##_pin), \ .enum_id = _pin##_DATA, \ } -- cgit v1.2.3 From 0ad7c00057dc1640647c1dc81ccbd009de17a767 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 26 Nov 2013 10:04:22 -0700 Subject: dma: add channel request API that supports deferred probe dma_request_slave_channel() simply returns NULL whenever DMA channel lookup fails. Lookup could fail for two distinct reasons: a) No DMA specification exists for the channel name. This includes situations where no DMA specifications exist at all, or other general lookup problems. b) A DMA specification does exist, yet the driver for that channel is not yet registered. Case (b) should trigger deferred probe in client drivers. However, since they have no way to differentiate the two situations, it cannot. Implement new function dma_request_slave_channel_reason(), which performs identically to dma_request_slave_channel(), except that it returns an error-pointer rather than NULL, which allows callers to detect when deferred probe should occur. Eventually, all drivers should be converted to this new API, the old API removed, and the new API renamed to the more desirable name. This patch doesn't convert the existing API and all drivers in one go, since some drivers call dma_request_slave_channel() then dma_request_channel() if that fails. That would require either modifying dma_request_channel() in the same way, or adding extra error-handling code to all affected drivers, and there are close to 100 drivers using the other API, rather than just the 15-20 or so that use dma_request_slave_channel(), which might be tenable in a single patch. acpi_dma_request_slave_chan_by_name() doesn't currently implement deferred probe. It should, but this will be addressed later. Acked-by: Dan Williams Signed-off-by: Stephen Warren Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 35 +++++++++++++++++++++++++++++++---- drivers/dma/of-dma.c | 15 +++++++++------ include/linux/dmaengine.h | 8 ++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index ea806bdc12ef..e17e9b22d85e 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -540,6 +540,8 @@ EXPORT_SYMBOL_GPL(dma_get_slave_channel); * @mask: capabilities that the channel must satisfy * @fn: optional callback to disposition available channels * @fn_param: opaque parameter to pass to dma_filter_fn + * + * Returns pointer to appropriate DMA channel on success or NULL. */ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param) @@ -591,18 +593,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel); * dma_request_slave_channel - try to allocate an exclusive slave channel * @dev: pointer to client device structure * @name: slave channel name + * + * Returns pointer to appropriate DMA channel on success or an error pointer. */ -struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name) +struct dma_chan *dma_request_slave_channel_reason(struct device *dev, + const char *name) { + struct dma_chan *chan; + /* If device-tree is present get slave info from here */ if (dev->of_node) return of_dma_request_slave_channel(dev->of_node, name); /* If device was enumerated by ACPI get slave info from here */ - if (ACPI_HANDLE(dev)) - return acpi_dma_request_slave_chan_by_name(dev, name); + if (ACPI_HANDLE(dev)) { + chan = acpi_dma_request_slave_chan_by_name(dev, name); + if (chan) + return chan; + } - return NULL; + return ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason); + +/** + * dma_request_slave_channel - try to allocate an exclusive slave channel + * @dev: pointer to client device structure + * @name: slave channel name + * + * Returns pointer to appropriate DMA channel on success or NULL. + */ +struct dma_chan *dma_request_slave_channel(struct device *dev, + const char *name) +{ + struct dma_chan *ch = dma_request_slave_channel_reason(dev, name); + if (IS_ERR(ch)) + return NULL; + return ch; } EXPORT_SYMBOL_GPL(dma_request_slave_channel); diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index 0b88dd3d05f4..e8fe9dc455f4 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c @@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name, * @np: device node to get DMA request from * @name: name of desired channel * - * Returns pointer to appropriate dma channel on success or NULL on error. + * Returns pointer to appropriate DMA channel on success or an error pointer. */ struct dma_chan *of_dma_request_slave_channel(struct device_node *np, const char *name) @@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np, struct of_dma *ofdma; struct dma_chan *chan; int count, i; + int ret_no_channel = -ENODEV; if (!np || !name) { pr_err("%s: not enough information provided\n", __func__); - return NULL; + return ERR_PTR(-ENODEV); } count = of_property_count_strings(np, "dma-names"); if (count < 0) { pr_err("%s: dma-names property of node '%s' missing or empty\n", __func__, np->full_name); - return NULL; + return ERR_PTR(-ENODEV); } for (i = 0; i < count; i++) { @@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np, mutex_lock(&of_dma_lock); ofdma = of_dma_find_controller(&dma_spec); - if (ofdma) + if (ofdma) { chan = ofdma->of_dma_xlate(&dma_spec, ofdma); - else + } else { + ret_no_channel = -EPROBE_DEFER; chan = NULL; + } mutex_unlock(&of_dma_lock); @@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np, return chan; } - return NULL; + return ERR_PTR(ret_no_channel); } /** diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 41cf0c399288..ed92b30a02fd 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -22,6 +22,7 @@ #define LINUX_DMAENGINE_H #include +#include #include #include #include @@ -1040,6 +1041,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); void dma_issue_pending_all(void); struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); +struct dma_chan *dma_request_slave_channel_reason(struct device *dev, + const char *name); struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name); void dma_release_channel(struct dma_chan *chan); #else @@ -1063,6 +1066,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, { return NULL; } +static inline struct dma_chan *dma_request_slave_channel_reason( + struct device *dev, const char *name) +{ + return ERR_PTR(-ENODEV); +} static inline struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name) { -- cgit v1.2.3 From f5837ec11f8cfa6d53ebc5806582771b2c9988c6 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 5 Dec 2013 11:23:35 +0200 Subject: gpio: twl4030: Fix regression for twl gpio LED output Commit 0b2aa8be introduced a regression that causes failure in setting LED GPO direction to OUT. This causes USB host probe failures for Beagleboard C4. platform usb_phy_gen_xceiv.2: Driver usb_phy_gen_xceiv requests probe deferral hsusb2_vcc: Failed to request enable GPIO510: -22 reg-fixed-voltage reg-fixed-voltage.0.auto: Failed to register regulator: -22 reg-fixed-voltage: probe of reg-fixed-voltage.0.auto failed with error -22 direction_out/direction_in must return 0 if the operation succeeded. Also, don't update direction flag and output data if twl4030_set_gpio_direction() failed inside twl_direction_out(); Cc: stable@vger.kernel.org Signed-off-by: Roger Quadros Acked-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/gpio/gpio-twl4030.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index b97d6a6577b9..f9996899c1f2 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset) if (offset < TWL4030_GPIO_MAX) ret = twl4030_set_gpio_direction(offset, 1); else - ret = -EINVAL; + ret = -EINVAL; /* LED outputs can't be set as input */ if (!ret) priv->direction &= ~BIT(offset); @@ -354,11 +354,20 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value) static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) { struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); - int ret = -EINVAL; + int ret = 0; mutex_lock(&priv->mutex); - if (offset < TWL4030_GPIO_MAX) + if (offset < TWL4030_GPIO_MAX) { ret = twl4030_set_gpio_direction(offset, 0); + if (ret) { + mutex_unlock(&priv->mutex); + return ret; + } + } + + /* + * LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output + */ priv->direction |= BIT(offset); mutex_unlock(&priv->mutex); -- cgit v1.2.3 From 8010dad55a0ab0e829f3733854e5235eef4e2734 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 26 Nov 2013 12:40:51 -0700 Subject: dma: add dma_get_any_slave_channel(), for use in of_xlate() mmp_pdma.c implements a custom of_xlate() function that is 95% identical to what Tegra will need. Create a function to implement the common part, so everyone doesn't just cut/paste the implementation. Cc: Dan Williams Cc: Vinod Koul Cc: Lars-Peter Clausen Cc: dmaengine@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Stephen Warren Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 28 ++++++++++++++++++++++++++++ drivers/dma/mmp_pdma.c | 30 +++++++----------------------- include/linux/dmaengine.h | 1 + 3 files changed, 36 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index ea806bdc12ef..4f08ee8c17b4 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -535,6 +535,34 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan) } EXPORT_SYMBOL_GPL(dma_get_slave_channel); +struct dma_chan *dma_get_any_slave_channel(struct dma_device *device) +{ + dma_cap_mask_t mask; + struct dma_chan *chan; + int err; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* lock against __dma_request_channel */ + mutex_lock(&dma_list_mutex); + + chan = private_candidate(&mask, device, NULL, NULL); + if (chan) { + err = dma_chan_get(chan); + if (err) { + pr_debug("%s: failed to get %s: (%d)\n", + __func__, dma_chan_name(chan), err); + chan = NULL; + } + } + + mutex_unlock(&dma_list_mutex); + + return chan; +} +EXPORT_SYMBOL_GPL(dma_get_any_slave_channel); + /** * __dma_request_channel - try to allocate an exclusive channel * @mask: capabilities that the channel must satisfy diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index dcb1e05149a7..2998f1bffac1 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -893,33 +893,17 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct mmp_pdma_device *d = ofdma->of_dma_data; - struct dma_chan *chan, *candidate; + struct dma_chan *chan; + struct mmp_pdma_chan *c; -retry: - candidate = NULL; - - /* walk the list of channels registered with the current instance and - * find one that is currently unused */ - list_for_each_entry(chan, &d->device.channels, device_node) - if (chan->client_count == 0) { - candidate = chan; - break; - } - - if (!candidate) + chan = dma_get_any_slave_channel(&d->device); + if (!chan) return NULL; - /* dma_get_slave_channel will return NULL if we lost a race between - * the lookup and the reservation */ - chan = dma_get_slave_channel(candidate); - - if (chan) { - struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan); - c->drcmr = dma_spec->args[0]; - return chan; - } + c = to_mmp_pdma_chan(chan); + c->drcmr = dma_spec->args[0]; - goto retry; + return chan; } static int mmp_pdma_probe(struct platform_device *op) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 41cf0c399288..09ef23ee8bce 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1079,6 +1079,7 @@ int dma_async_device_register(struct dma_device *device); void dma_async_device_unregister(struct dma_device *device); void dma_run_dependencies(struct dma_async_tx_descriptor *tx); struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); +struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); struct dma_chan *net_dma_find_channel(void); #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) #define dma_request_slave_channel_compat(mask, x, y, dev, name) \ -- cgit v1.2.3 From ec9ed1976c256333567932b4acced34c072b57a7 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 10 Dec 2013 13:37:36 +0530 Subject: drm/i915: Make downclock deduction common for all panels If one mode of a internal panel has more than one refresh rate, then a reduced clock is found for the LFP (LVDS/eDP). This enables switching between low and high frequency dynamically. Moving downclock calculation to intel_panel so that it is common for LVDS and eDP. Signed-off-by: Vandana Kannan Signed-off-by: Pradeep Bhat Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 6 +++- drivers/gpu/drm/i915/intel_lvds.c | 69 +++++++++----------------------------- drivers/gpu/drm/i915/intel_panel.c | 57 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5dea38967523..9f8b46574956 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -155,6 +155,7 @@ struct intel_encoder { struct intel_panel { struct drm_display_mode *fixed_mode; + struct drm_display_mode *downclock_mode; int fitting_mode; /* backlight */ @@ -823,7 +824,10 @@ void intel_panel_disable_backlight(struct intel_connector *connector); void intel_panel_destroy_backlight(struct drm_connector *connector); void intel_panel_init_backlight_funcs(struct drm_device *dev); enum drm_connector_status intel_panel_detect(struct drm_device *dev); - +extern struct drm_display_mode *intel_find_panel_downclock( + struct drm_device *dev, + struct drm_display_mode *fixed_mode, + struct drm_connector *connector); /* intel_pm.c */ void intel_init_clock_gating(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4c8553ea82f7..8bcb93a2a9f6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -755,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = { { } /* terminating entry */ }; -/** - * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID - * @dev: drm device - * @connector: LVDS connector - * - * Find the reduced downclock for LVDS in EDID. - */ -static void intel_find_lvds_downclock(struct drm_device *dev, - struct drm_display_mode *fixed_mode, - struct drm_connector *connector) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_display_mode *scan; - int temp_downclock; - - temp_downclock = fixed_mode->clock; - list_for_each_entry(scan, &connector->probed_modes, head) { - /* - * If one mode has the same resolution with the fixed_panel - * mode while they have the different refresh rate, it means - * that the reduced downclock is found for the LVDS. In such - * case we can set the different FPx0/1 to dynamically select - * between low and high frequency. - */ - if (scan->hdisplay == fixed_mode->hdisplay && - scan->hsync_start == fixed_mode->hsync_start && - scan->hsync_end == fixed_mode->hsync_end && - scan->htotal == fixed_mode->htotal && - scan->vdisplay == fixed_mode->vdisplay && - scan->vsync_start == fixed_mode->vsync_start && - scan->vsync_end == fixed_mode->vsync_end && - scan->vtotal == fixed_mode->vtotal) { - if (scan->clock < temp_downclock) { - /* - * The downclock is already found. But we - * expect to find the lower downclock. - */ - temp_downclock = scan->clock; - } - } - } - if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) { - /* We found the downclock for LVDS. */ - dev_priv->lvds_downclock_avail = 1; - dev_priv->lvds_downclock = temp_downclock; - DRM_DEBUG_KMS("LVDS downclock is found in EDID. " - "Normal clock %dKhz, downclock %dKhz\n", - fixed_mode->clock, temp_downclock); - } -} - /* * Enumerate the child dev array parsed from VBT to check whether * the LVDS is present. @@ -1083,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev) fixed_mode = drm_mode_duplicate(dev, scan); if (fixed_mode) { - intel_find_lvds_downclock(dev, fixed_mode, - connector); + intel_connector->panel.downclock_mode = + intel_find_panel_downclock(dev, + fixed_mode, connector); + if (intel_connector->panel.downclock_mode != + NULL && i915_lvds_downclock) { + /* We found the downclock for LVDS. */ + dev_priv->lvds_downclock_avail = true; + dev_priv->lvds_downclock = + intel_connector->panel. + downclock_mode->clock; + DRM_DEBUG_KMS("LVDS downclock is found" + " in EDID. Normal clock %dKhz, " + "downclock %dKhz\n", + fixed_mode->clock, + dev_priv->lvds_downclock); + } goto out; } } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e480cf41c536..b0f6e6cc4354 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1104,6 +1104,59 @@ void intel_panel_destroy_backlight(struct drm_connector *connector) intel_backlight_device_unregister(intel_connector); } +/** + * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID + * @dev: drm device + * @fixed_mode : panel native mode + * @connector: LVDS/eDP connector + * + * Return downclock_avail + * Find the reduced downclock for LVDS/eDP in EDID. + */ +struct drm_display_mode * +intel_find_panel_downclock(struct drm_device *dev, + struct drm_display_mode *fixed_mode, + struct drm_connector *connector) +{ + struct drm_display_mode *scan, *tmp_mode; + int temp_downclock; + + temp_downclock = fixed_mode->clock; + tmp_mode = NULL; + + list_for_each_entry(scan, &connector->probed_modes, head) { + /* + * If one mode has the same resolution with the fixed_panel + * mode while they have the different refresh rate, it means + * that the reduced downclock is found. In such + * case we can set the different FPx0/1 to dynamically select + * between low and high frequency. + */ + if (scan->hdisplay == fixed_mode->hdisplay && + scan->hsync_start == fixed_mode->hsync_start && + scan->hsync_end == fixed_mode->hsync_end && + scan->htotal == fixed_mode->htotal && + scan->vdisplay == fixed_mode->vdisplay && + scan->vsync_start == fixed_mode->vsync_start && + scan->vsync_end == fixed_mode->vsync_end && + scan->vtotal == fixed_mode->vtotal) { + if (scan->clock < temp_downclock) { + /* + * The downclock is already found. But we + * expect to find the lower downclock. + */ + temp_downclock = scan->clock; + tmp_mode = scan; + } + } + } + + if (temp_downclock < fixed_mode->clock) + return drm_mode_duplicate(dev, tmp_mode); + else + return NULL; +} + /* Set up chip specific backlight functions */ void intel_panel_init_backlight_funcs(struct drm_device *dev) { @@ -1157,4 +1210,8 @@ void intel_panel_fini(struct intel_panel *panel) if (panel->fixed_mode) drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); + + if (panel->downclock_mode) + drm_mode_destroy(intel_connector->base.dev, + panel->downclock_mode); } -- cgit v1.2.3 From eed8c3eebce72fe4fc766f9a23e4324b04bd86cf Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 7 Nov 2013 09:44:42 -0300 Subject: [media] media: i2c: lm3560: fix missing unlock on error in lm3560_set_ctrl() Add the missing unlock before return from function lm3560_set_ctrl() in the error handling case. Signed-off-by: Wei Yongjun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/lm3560.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index ab5857d66f2d..e728d9fb08d1 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -219,15 +219,19 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no) break; case V4L2_CID_FLASH_STROBE: - if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) - return -EBUSY; + if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) { + rval = -EBUSY; + goto err_out; + } flash->led_mode = V4L2_FLASH_LED_MODE_FLASH; rval = lm3560_mode_ctrl(flash); break; case V4L2_CID_FLASH_STROBE_STOP: - if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) - return -EBUSY; + if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) { + rval = -EBUSY; + goto err_out; + } flash->led_mode = V4L2_FLASH_LED_MODE_NONE; rval = lm3560_mode_ctrl(flash); break; @@ -247,8 +251,8 @@ static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no) break; } - mutex_unlock(&flash->lock); err_out: + mutex_unlock(&flash->lock); return rval; } -- cgit v1.2.3 From cc58f4db5173f5cd039de4681ec4778b5cd71182 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 8 Nov 2013 21:24:18 -0300 Subject: [media] media: i2c: lm3560: use correct clientdata in lm3560_remove() We had set the i2c clientdata to &flash->subdev_led[LM3560_LED1] after call lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1"), but the container_of() in lm3560_remove() return the wrong pointer to flash.(should be container_of(subdev, struct lm3560_flash, subdev_led[LM3560_LED_MAX-1]) This patch fix to set i2c clientdata to flash so we can get flash from clientdata directly. Signed-off-by: Wei Yongjun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/lm3560.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index e728d9fb08d1..d98ca3aebe23 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -448,14 +448,14 @@ static int lm3560_probe(struct i2c_client *client, if (rval < 0) return rval; + i2c_set_clientdata(client, flash); + return 0; } static int lm3560_remove(struct i2c_client *client) { - struct v4l2_subdev *subdev = i2c_get_clientdata(client); - struct lm3560_flash *flash = container_of(subdev, struct lm3560_flash, - subdev_led[LM3560_LED_MAX]); + struct lm3560_flash *flash = i2c_get_clientdata(client); unsigned int i; for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) { -- cgit v1.2.3 From fff6386766fc846f19d5628878a4638fa7ece0a4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2013 15:19:08 +0200 Subject: drm/i915: Don't cast away const from infoframe buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't modify the packed infoframe data, so we should keep the const qualifier in place. Just pass the buffer as 'const void *' instead of 'const uint8_t *' and we can drop the cast entirely. v2: Do intel_sdvo_write_infoframe() as well Reviewed-by: Damien Lespiau Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 20 ++++++++++---------- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9f8b46574956..79585cddc2cd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -455,7 +455,7 @@ struct intel_hdmi { bool rgb_quant_range_selectable; void (*write_infoframe)(struct drm_encoder *encoder, enum hdmi_infoframe_type type, - const uint8_t *frame, ssize_t len); + const void *frame, ssize_t len); void (*set_infoframes)(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode); }; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 6a6ad0c78dc7..6db0d9d17f47 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -130,9 +130,9 @@ static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, static void g4x_write_infoframe(struct drm_encoder *encoder, enum hdmi_infoframe_type type, - const uint8_t *frame, ssize_t len) + const void *frame, ssize_t len) { - uint32_t *data = (uint32_t *)frame; + const uint32_t *data = frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val = I915_READ(VIDEO_DIP_CTL); @@ -167,9 +167,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, static void ibx_write_infoframe(struct drm_encoder *encoder, enum hdmi_infoframe_type type, - const uint8_t *frame, ssize_t len) + const void *frame, ssize_t len) { - uint32_t *data = (uint32_t *)frame; + const uint32_t *data = frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); @@ -205,9 +205,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, static void cpt_write_infoframe(struct drm_encoder *encoder, enum hdmi_infoframe_type type, - const uint8_t *frame, ssize_t len) + const void *frame, ssize_t len) { - uint32_t *data = (uint32_t *)frame; + const uint32_t *data = frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); @@ -246,9 +246,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, static void vlv_write_infoframe(struct drm_encoder *encoder, enum hdmi_infoframe_type type, - const uint8_t *frame, ssize_t len) + const void *frame, ssize_t len) { - uint32_t *data = (uint32_t *)frame; + const uint32_t *data = frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); @@ -284,9 +284,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, static void hsw_write_infoframe(struct drm_encoder *encoder, enum hdmi_infoframe_type type, - const uint8_t *frame, ssize_t len) + const void *frame, ssize_t len) { - uint32_t *data = (uint32_t *)frame; + const uint32_t *data = frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 2abeab09e883..95bdfb3c431c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -952,7 +952,7 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, unsigned if_index, uint8_t tx_rate, - uint8_t *data, unsigned length) + const uint8_t *data, unsigned length) { uint8_t set_buf_index[2] = { if_index, 0 }; uint8_t hbuf_size, tmp[8]; -- cgit v1.2.3 From 3f9c1268159917932fcefe9b3abd5eabb4ed5a29 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Oct 2013 13:02:18 +0100 Subject: sh-pfc: Share common PORTCR macro definition The macro is defined identically in four different locations. Share it. Signed-off-by: Laurent Pinchart Reviewed-by: Simon Horman Acked-by: Linus Walleij --- drivers/pinctrl/sh-pfc/pfc-r8a73a4.c | 11 ----------- drivers/pinctrl/sh-pfc/pfc-r8a7740.c | 11 ----------- drivers/pinctrl/sh-pfc/pfc-sh7372.c | 11 ----------- drivers/pinctrl/sh-pfc/pfc-sh73a0.c | 10 ---------- drivers/pinctrl/sh-pfc/sh_pfc.h | 3 +-- 5 files changed, 1 insertion(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c index d25fd4ea0a1d..d76cc343a82a 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c @@ -2061,17 +2061,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(sdhi2), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } - static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xe6050000), PORTCR(1, 0xe6050001), diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c index 009174d07767..7ac006583558 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c @@ -3234,17 +3234,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(tpu0), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } - static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xe6050000), /* PORT0CR */ PORTCR(1, 0xe6050001), /* PORT1CR */ diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c index 70b522d34821..4fea6ceb2dbf 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c @@ -2118,17 +2118,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(usb1), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } - static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xE6051000), /* PORT0CR */ PORTCR(1, 0xE6051001), /* PORT1CR */ diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index 7e278a97e411..b81b56eae0c9 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3138,16 +3138,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(usb), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xe6050000), /* PORT0CR */ PORTCR(1, 0xe6050001), /* PORT1CR */ diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 11bd0d970a52..8a494e557b43 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -304,8 +304,7 @@ struct sh_pfc_soc_info { #define PORTCR(nr, reg) \ { \ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, PORT##nr##_IN_PD, \ - PORT##nr##_IN_PU, PORT##nr##_OUT), \ + _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ PORT##nr##_FN0, PORT##nr##_FN1, \ PORT##nr##_FN2, PORT##nr##_FN3, \ PORT##nr##_FN4, PORT##nr##_FN5, \ -- cgit v1.2.3 From 1d7b59a07740712b46dd0271abf7dd4013badf49 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 19:01:27 -0800 Subject: sh-pfc: r8a7790: Add SSI pin support Signed-off-by: Kuninori Morimoto Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 239 +++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 72786fc93958..a6903de2eb12 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -2961,6 +2961,189 @@ static const unsigned int sdhi3_wp_pins[] = { static const unsigned int sdhi3_wp_mux[] = { SD3_WP_MARK, }; +/* - SSI -------------------------------------------------------------------- */ +static const unsigned int ssi0_data_pins[] = { + /* SDATA0 */ + RCAR_GP_PIN(4, 5), +}; +static const unsigned int ssi0_data_mux[] = { + SSI_SDATA0_MARK, +}; +static const unsigned int ssi0129_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 4), +}; +static const unsigned int ssi0129_ctrl_mux[] = { + SSI_SCK0129_MARK, SSI_WS0129_MARK, +}; +static const unsigned int ssi1_data_pins[] = { + /* SDATA1 */ + RCAR_GP_PIN(4, 6), +}; +static const unsigned int ssi1_data_mux[] = { + SSI_SDATA1_MARK, +}; +static const unsigned int ssi1_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 24), +}; +static const unsigned int ssi1_ctrl_mux[] = { + SSI_SCK1_MARK, SSI_WS1_MARK, +}; +static const unsigned int ssi2_data_pins[] = { + /* SDATA2 */ + RCAR_GP_PIN(4, 7), +}; +static const unsigned int ssi2_data_mux[] = { + SSI_SDATA2_MARK, +}; +static const unsigned int ssi2_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 17), +}; +static const unsigned int ssi2_ctrl_mux[] = { + SSI_SCK2_MARK, SSI_WS2_MARK, +}; +static const unsigned int ssi3_data_pins[] = { + /* SDATA3 */ + RCAR_GP_PIN(4, 10), +}; +static const unsigned int ssi3_data_mux[] = { + SSI_SDATA3_MARK +}; +static const unsigned int ssi34_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 8), RCAR_GP_PIN(4, 9), +}; +static const unsigned int ssi34_ctrl_mux[] = { + SSI_SCK34_MARK, SSI_WS34_MARK, +}; +static const unsigned int ssi4_data_pins[] = { + /* SDATA4 */ + RCAR_GP_PIN(4, 13), +}; +static const unsigned int ssi4_data_mux[] = { + SSI_SDATA4_MARK, +}; +static const unsigned int ssi4_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12), +}; +static const unsigned int ssi4_ctrl_mux[] = { + SSI_SCK4_MARK, SSI_WS4_MARK, +}; +static const unsigned int ssi5_pins[] = { + /* SDATA5, SCK, WS */ + RCAR_GP_PIN(4, 16), RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 15), +}; +static const unsigned int ssi5_mux[] = { + SSI_SDATA5_MARK, SSI_SCK5_MARK, SSI_WS5_MARK, +}; +static const unsigned int ssi5_b_pins[] = { + /* SDATA5, SCK, WS */ + RCAR_GP_PIN(0, 26), RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), +}; +static const unsigned int ssi5_b_mux[] = { + SSI_SDATA5_B_MARK, SSI_SCK5_B_MARK, SSI_WS5_B_MARK +}; +static const unsigned int ssi5_c_pins[] = { + /* SDATA5, SCK, WS */ + RCAR_GP_PIN(4, 24), RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12), +}; +static const unsigned int ssi5_c_mux[] = { + SSI_SDATA5_C_MARK, SSI_SCK5_C_MARK, SSI_WS5_C_MARK, +}; +static const unsigned int ssi6_pins[] = { + /* SDATA6, SCK, WS */ + RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 18), +}; +static const unsigned int ssi6_mux[] = { + SSI_SDATA6_MARK, SSI_SCK6_MARK, SSI_WS6_MARK, +}; +static const unsigned int ssi6_b_pins[] = { + /* SDATA6, SCK, WS */ + RCAR_GP_PIN(1, 29), RCAR_GP_PIN(1, 25), RCAR_GP_PIN(1, 27), +}; +static const unsigned int ssi6_b_mux[] = { + SSI_SDATA6_B_MARK, SSI_SCK6_B_MARK, SSI_WS6_B_MARK, +}; +static const unsigned int ssi7_data_pins[] = { + /* SDATA7 */ + RCAR_GP_PIN(4, 22), +}; +static const unsigned int ssi7_data_mux[] = { + SSI_SDATA7_MARK, +}; +static const unsigned int ssi7_b_data_pins[] = { + /* SDATA7 */ + RCAR_GP_PIN(4, 22), +}; +static const unsigned int ssi7_b_data_mux[] = { + SSI_SDATA7_B_MARK, +}; +static const unsigned int ssi7_c_data_pins[] = { + /* SDATA7 */ + RCAR_GP_PIN(1, 26), +}; +static const unsigned int ssi7_c_data_mux[] = { + SSI_SDATA7_C_MARK, +}; +static const unsigned int ssi78_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 21), +}; +static const unsigned int ssi78_ctrl_mux[] = { + SSI_SCK78_MARK, SSI_WS78_MARK, +}; +static const unsigned int ssi78_b_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 24), +}; +static const unsigned int ssi78_b_ctrl_mux[] = { + SSI_SCK78_B_MARK, SSI_WS78_B_MARK, +}; +static const unsigned int ssi78_c_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 25), +}; +static const unsigned int ssi78_c_ctrl_mux[] = { + SSI_SCK78_C_MARK, SSI_WS78_C_MARK, +}; +static const unsigned int ssi8_data_pins[] = { + /* SDATA8 */ + RCAR_GP_PIN(4, 23), +}; +static const unsigned int ssi8_data_mux[] = { + SSI_SDATA8_MARK, +}; +static const unsigned int ssi8_b_data_pins[] = { + /* SDATA8 */ + RCAR_GP_PIN(4, 23), +}; +static const unsigned int ssi8_b_data_mux[] = { + SSI_SDATA8_B_MARK, +}; +static const unsigned int ssi8_c_data_pins[] = { + /* SDATA8 */ + RCAR_GP_PIN(1, 27), +}; +static const unsigned int ssi8_c_data_mux[] = { + SSI_SDATA8_C_MARK, +}; +static const unsigned int ssi9_data_pins[] = { + /* SDATA9 */ + RCAR_GP_PIN(4, 24), +}; +static const unsigned int ssi9_data_mux[] = { + SSI_SDATA9_MARK, +}; +static const unsigned int ssi9_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(5, 10), RCAR_GP_PIN(5, 11), +}; +static const unsigned int ssi9_ctrl_mux[] = { + SSI_SCK9_MARK, SSI_WS9_MARK, +}; /* - TPU0 ------------------------------------------------------------------- */ static const unsigned int tpu0_to0_pins[] = { /* TO */ @@ -3259,6 +3442,32 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ctrl), SH_PFC_PIN_GROUP(sdhi3_cd), SH_PFC_PIN_GROUP(sdhi3_wp), + SH_PFC_PIN_GROUP(ssi0_data), + SH_PFC_PIN_GROUP(ssi0129_ctrl), + SH_PFC_PIN_GROUP(ssi1_data), + SH_PFC_PIN_GROUP(ssi1_ctrl), + SH_PFC_PIN_GROUP(ssi2_data), + SH_PFC_PIN_GROUP(ssi2_ctrl), + SH_PFC_PIN_GROUP(ssi3_data), + SH_PFC_PIN_GROUP(ssi34_ctrl), + SH_PFC_PIN_GROUP(ssi4_data), + SH_PFC_PIN_GROUP(ssi4_ctrl), + SH_PFC_PIN_GROUP(ssi5), + SH_PFC_PIN_GROUP(ssi5_b), + SH_PFC_PIN_GROUP(ssi5_c), + SH_PFC_PIN_GROUP(ssi6), + SH_PFC_PIN_GROUP(ssi6_b), + SH_PFC_PIN_GROUP(ssi7_data), + SH_PFC_PIN_GROUP(ssi7_b_data), + SH_PFC_PIN_GROUP(ssi7_c_data), + SH_PFC_PIN_GROUP(ssi78_ctrl), + SH_PFC_PIN_GROUP(ssi78_b_ctrl), + SH_PFC_PIN_GROUP(ssi78_c_ctrl), + SH_PFC_PIN_GROUP(ssi8_data), + SH_PFC_PIN_GROUP(ssi8_b_data), + SH_PFC_PIN_GROUP(ssi8_c_data), + SH_PFC_PIN_GROUP(ssi9_data), + SH_PFC_PIN_GROUP(ssi9_ctrl), SH_PFC_PIN_GROUP(tpu0_to0), SH_PFC_PIN_GROUP(tpu0_to1), SH_PFC_PIN_GROUP(tpu0_to2), @@ -3533,6 +3742,35 @@ static const char * const sdhi3_groups[] = { "sdhi3_wp", }; +static const char * const ssi_groups[] = { + "ssi0_data", + "ssi0129_ctrl", + "ssi1_data", + "ssi1_ctrl", + "ssi2_data", + "ssi2_ctrl", + "ssi3_data", + "ssi34_ctrl", + "ssi4_data", + "ssi4_ctrl", + "ssi5", + "ssi5_b", + "ssi5_c", + "ssi6", + "ssi6_b", + "ssi7_data", + "ssi7_b_data", + "ssi7_c_data", + "ssi78_ctrl", + "ssi78_b_ctrl", + "ssi78_c_ctrl", + "ssi8_data", + "ssi8_b_data", + "ssi8_c_data", + "ssi9_data", + "ssi9_ctrl", +}; + static const char * const tpu0_groups[] = { "tpu0_to0", "tpu0_to1", @@ -3599,6 +3837,7 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(sdhi1), SH_PFC_FUNCTION(sdhi2), SH_PFC_FUNCTION(sdhi3), + SH_PFC_FUNCTION(ssi), SH_PFC_FUNCTION(tpu0), SH_PFC_FUNCTION(usb0), SH_PFC_FUNCTION(usb1), -- cgit v1.2.3 From fcec5b2254c9b7c99d31afb4c390f301b7ad201e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 19:01:37 -0800 Subject: sh-pfc: r8a7790: Add Audio pin support Signed-off-by: Kuninori Morimoto Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index a6903de2eb12..1375709422c7 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -1739,6 +1739,56 @@ static struct sh_pfc_pin pinmux_pins[] = { SH_PFC_PIN_NAMED(ROW_GROUP_A('H'), 15, AH15), }; +/* - AUDIO CLOCK ------------------------------------------------------------ */ +static const unsigned int audio_clk_a_pins[] = { + /* CLK A */ + RCAR_GP_PIN(4, 25), +}; +static const unsigned int audio_clk_a_mux[] = { + AUDIO_CLKA_MARK, +}; +static const unsigned int audio_clk_b_pins[] = { + /* CLK B */ + RCAR_GP_PIN(4, 26), +}; +static const unsigned int audio_clk_b_mux[] = { + AUDIO_CLKB_MARK, +}; +static const unsigned int audio_clk_c_pins[] = { + /* CLK C */ + RCAR_GP_PIN(5, 27), +}; +static const unsigned int audio_clk_c_mux[] = { + AUDIO_CLKC_MARK, +}; +static const unsigned int audio_clkout_pins[] = { + /* CLK OUT */ + RCAR_GP_PIN(5, 16), +}; +static const unsigned int audio_clkout_mux[] = { + AUDIO_CLKOUT_MARK, +}; +static const unsigned int audio_clkout_b_pins[] = { + /* CLK OUT B */ + RCAR_GP_PIN(0, 23), +}; +static const unsigned int audio_clkout_b_mux[] = { + AUDIO_CLKOUT_B_MARK, +}; +static const unsigned int audio_clkout_c_pins[] = { + /* CLK OUT C */ + RCAR_GP_PIN(5, 27), +}; +static const unsigned int audio_clkout_c_mux[] = { + AUDIO_CLKOUT_C_MARK, +}; +static const unsigned int audio_clkout_d_pins[] = { + /* CLK OUT D */ + RCAR_GP_PIN(5, 20), +}; +static const unsigned int audio_clkout_d_mux[] = { + AUDIO_CLKOUT_D_MARK, +}; /* - DU RGB ----------------------------------------------------------------- */ static const unsigned int du_rgb666_pins[] = { /* R[7:2], G[7:2], B[7:2] */ @@ -3277,6 +3327,13 @@ static const unsigned int vin1_clk_mux[] = { }; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(audio_clk_a), + SH_PFC_PIN_GROUP(audio_clk_b), + SH_PFC_PIN_GROUP(audio_clk_c), + SH_PFC_PIN_GROUP(audio_clkout), + SH_PFC_PIN_GROUP(audio_clkout_b), + SH_PFC_PIN_GROUP(audio_clkout_c), + SH_PFC_PIN_GROUP(audio_clkout_d), SH_PFC_PIN_GROUP(du_rgb666), SH_PFC_PIN_GROUP(du_rgb888), SH_PFC_PIN_GROUP(du_clk_out_0), @@ -3487,6 +3544,16 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(vin1_clk), }; +static const char * const audio_clk_groups[] = { + "audio_clk_a", + "audio_clk_b", + "audio_clk_c", + "audio_clkout", + "audio_clkout_b", + "audio_clkout_c", + "audio_clkout_d", +}; + static const char * const du_groups[] = { "du_rgb666", "du_rgb888", @@ -3807,6 +3874,7 @@ static const char * const vin1_groups[] = { }; static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(du), SH_PFC_FUNCTION(du0), SH_PFC_FUNCTION(du1), -- cgit v1.2.3 From 2ef3967ef5b7e37af5b87beae67cdb24a318f324 Mon Sep 17 00:00:00 2001 From: Takashi Yoshii Date: Mon, 2 Dec 2013 03:19:12 +0900 Subject: sh-pfc: r8a7791: Fix msiof groups to follow GROUP SH_PFC_PIN_GROUP(), pins[], mux[], defines clk, sync, ss1, ss2, rx, tx But, msiof?_groups[] defines clk, ctrl, data Fix msiof[012]_groups members to be consistent to PIN_GROUP. Signed-off-by: Takashi Yoshii Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index d26c16360161..ea02d37bab7c 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -2858,20 +2858,29 @@ static const char * const mmc_groups[] = { static const char * const msiof0_groups[] = { "msiof0_clk", - "msiof0_ctrl", - "msiof0_data", + "msiof0_sync", + "msiof0_ss1", + "msiof0_ss2", + "msiof0_rx", + "msiof0_tx", }; static const char * const msiof1_groups[] = { "msiof1_clk", - "msiof1_ctrl", - "msiof1_data", + "msiof1_sync", + "msiof1_ss1", + "msiof1_ss2", + "msiof1_rx", + "msiof1_tx", }; static const char * const msiof2_groups[] = { "msiof2_clk", - "msiof2_ctrl", - "msiof2_data", + "msiof2_sync", + "msiof2_ss1", + "msiof2_ss2", + "msiof2_rx", + "msiof2_tx", }; static const char * const scif0_groups[] = { -- cgit v1.2.3 From dbb4e67fe7088f963007453ee07e453c4e1fab28 Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Sat, 23 Nov 2013 16:26:52 -0500 Subject: clk: keystone: use clkod register bits for postdiv DDR3A/B, ARM and PA PLL controllers have clkod register bits for configuring postdiv values. So use it instead of using fixed post dividers for these pll controllers. Assume that if fixed-postdiv attribute is not present, use clkod register value for pistdiv. Also update the Documentation of bindings to reflect the same. Cc: Mike Turquette Signed-off-by: Santosh Shilimkar --- .../devicetree/bindings/clock/keystone-pll.txt | 8 ++++---- drivers/clk/keystone/pll.c | 24 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/keystone-pll.txt b/Documentation/devicetree/bindings/clock/keystone-pll.txt index 12bd72605a31..225990f79b7c 100644 --- a/Documentation/devicetree/bindings/clock/keystone-pll.txt +++ b/Documentation/devicetree/bindings/clock/keystone-pll.txt @@ -17,13 +17,14 @@ Required properties: - reg - pll control0 and pll multipler registers - reg-names : control and multiplier. The multiplier is applicable only for main pll clock -- fixed-postdiv : fixed post divider value +- fixed-postdiv : fixed post divider value. If absent, use clkod register bits + for postdiv Example: mainpllclk: mainpllclk@2310110 { #clock-cells = <0>; compatible = "ti,keystone,main-pll-clock"; - clocks = <&refclkmain>; + clocks = <&refclksys>; reg = <0x02620350 4>, <0x02310110 4>; reg-names = "control", "multiplier"; fixed-postdiv = <2>; @@ -32,11 +33,10 @@ Example: papllclk: papllclk@2620358 { #clock-cells = <0>; compatible = "ti,keystone,pll-clock"; - clocks = <&refclkmain>; + clocks = <&refclkpass>; clock-output-names = "pa-pll-clk"; reg = <0x02620358 4>; reg-names = "control"; - fixed-postdiv = <6>; }; Required properties: diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c index 47a1bd9f1726..0dd8a4b12747 100644 --- a/drivers/clk/keystone/pll.c +++ b/drivers/clk/keystone/pll.c @@ -24,6 +24,8 @@ #define MAIN_PLLM_HIGH_MASK 0x7f000 #define PLLM_HIGH_SHIFT 6 #define PLLD_MASK 0x3f +#define CLKOD_MASK 0x780000 +#define CLKOD_SHIFT 19 /** * struct clk_pll_data - pll data structure @@ -41,7 +43,10 @@ * @pllm_upper_mask: multiplier upper mask * @pllm_upper_shift: multiplier upper shift * @plld_mask: divider mask - * @postdiv: Post divider + * @clkod_mask: output divider mask + * @clkod_shift: output divider shift + * @plld_mask: divider mask + * @postdiv: Fixed post divider */ struct clk_pll_data { bool has_pllctrl; @@ -53,6 +58,8 @@ struct clk_pll_data { u32 pllm_upper_mask; u32 pllm_upper_shift; u32 plld_mask; + u32 clkod_mask; + u32 clkod_shift; u32 postdiv; }; @@ -90,7 +97,13 @@ static unsigned long clk_pllclk_recalc(struct clk_hw *hw, mult |= ((val & pll_data->pllm_upper_mask) >> pll_data->pllm_upper_shift); prediv = (val & pll_data->plld_mask); - postdiv = pll_data->postdiv; + + if (!pll_data->has_pllctrl) + /* read post divider from od bits*/ + postdiv = ((val & pll_data->clkod_mask) >> + pll_data->clkod_shift) + 1; + else + postdiv = pll_data->postdiv; rate /= (prediv + 1); rate = (rate * (mult + 1)); @@ -155,8 +168,11 @@ static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl) } parent_name = of_clk_get_parent_name(node, 0); - if (of_property_read_u32(node, "fixed-postdiv", &pll_data->postdiv)) - goto out; + if (of_property_read_u32(node, "fixed-postdiv", &pll_data->postdiv)) { + /* assume the PLL has output divider register bits */ + pll_data->clkod_mask = CLKOD_MASK; + pll_data->clkod_shift = CLKOD_SHIFT; + } i = of_property_match_string(node, "reg-names", "control"); pll_data->pll_ctl0 = of_iomap(node, i); -- cgit v1.2.3 From e0c223ec67a98f70770eec85e625015f5af69f10 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Sat, 23 Nov 2013 16:31:12 -0500 Subject: clk: keystone: gate: fix error handling on init This patch fixes Keystone gate control clock driver initialization path: 1) clk_register_psc() returns error code and not a pure pointer, hence its return value need to be checked using IS_ERR(clk) macro. 2) Mapped IO memory isn't unmapped in case of errors, hence fix it. Cc: Mike Turquette Signed-off-by: Santosh Shilimkar --- drivers/clk/keystone/gate.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c index 1f333bcfc22e..17a598398a53 100644 --- a/drivers/clk/keystone/gate.c +++ b/drivers/clk/keystone/gate.c @@ -223,8 +223,7 @@ static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock) data->domain_base = of_iomap(node, i); if (!data->domain_base) { pr_err("%s: domain ioremap failed\n", __func__); - iounmap(data->control_base); - goto out; + goto unmap_ctrl; } of_property_read_u32(node, "domain-id", &data->domain_id); @@ -237,16 +236,21 @@ static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock) parent_name = of_clk_get_parent_name(node, 0); if (!parent_name) { pr_err("%s: Parent clock not found\n", __func__); - goto out; + goto unmap_domain; } clk = clk_register_psc(NULL, clk_name, parent_name, data, lock); - if (clk) { + if (!IS_ERR(clk)) { of_clk_add_provider(node, of_clk_src_simple_get, clk); return; } pr_err("%s: error registering clk %s\n", __func__, node->name); + +unmap_domain: + iounmap(data->domain_base); +unmap_ctrl: + iounmap(data->control_base); out: kfree(data); return; -- cgit v1.2.3 From 51d882edb2fc691bdb0e5c768084c90b6435656f Mon Sep 17 00:00:00 2001 From: Evgeny Plehov Date: Wed, 13 Nov 2013 20:53:59 -0300 Subject: [media] dw2102: Geniatech T220 support Support for Geniatech T220 DVB-T/T2/C USB stick. Signed-off-by: Evgeny Plehov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 113 ++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index c1a63b2a6baa..241c73701eaf 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -2,7 +2,7 @@ * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, * TeVii S600, S630, S650, S660, S480, S421, S632 * Prof 1100, 7500, - * Geniatech SU3000 Cards + * Geniatech SU3000, T220 Cards * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by) * * This program is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ #include "stb6100.h" #include "stb6100_proc.h" #include "m88rs2000.h" +#include "tda18271.h" +#include "cxd2820r.h" /* Max transfer size done by I2C transfer functions */ #define MAX_XFER_SIZE 64 @@ -1095,6 +1097,16 @@ static struct ds3000_config su3000_ds3000_config = { .set_lock_led = dw210x_led_ctrl, }; +static struct cxd2820r_config cxd2820r_config = { + .i2c_address = 0x6c, /* (0xd8 >> 1) */ + .ts_mode = 0x38, +}; + +static struct tda18271_config tda18271_config = { + .output_opt = TDA18271_OUTPUT_LT_OFF, + .gate = TDA18271_GATE_DIGITAL, +}; + static u8 m88rs2000_inittab[] = { DEMOD_WRITE, 0x9a, 0x30, DEMOD_WRITE, 0x00, 0x01, @@ -1364,6 +1376,49 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d) return -EIO; } +static int t220_frontend_attach(struct dvb_usb_adapter *d) +{ + u8 obuf[3] = { 0xe, 0x80, 0 }; + u8 ibuf[] = { 0 }; + + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) + err("command 0x0e transfer failed."); + + obuf[0] = 0xe; + obuf[1] = 0x83; + obuf[2] = 0; + + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) + err("command 0x0e transfer failed."); + + msleep(100); + + obuf[0] = 0xe; + obuf[1] = 0x80; + obuf[2] = 1; + + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) + err("command 0x0e transfer failed."); + + obuf[0] = 0x51; + + if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0) + err("command 0x51 transfer failed."); + + d->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config, + &d->dev->i2c_adap, NULL); + if (d->fe_adap[0].fe != NULL) { + if (dvb_attach(tda18271_attach, d->fe_adap[0].fe, 0x60, + &d->dev->i2c_adap, &tda18271_config)) { + info("Attached TDA18271HD/CXD2820R!\n"); + return 0; + } + } + + info("Failed to attach TDA18271HD/CXD2820R!\n"); + return -EIO; +} + static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d) { u8 obuf[] = { 0x51 }; @@ -1630,6 +1685,7 @@ enum dw2102_table_entry { TEVII_S632, TERRATEC_CINERGY_S2_R2, GOTVIEW_SAT_HD, + GENIATECH_T220, }; static struct usb_device_id dw2102_table[] = { @@ -1652,6 +1708,7 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, + [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, { } }; @@ -2077,6 +2134,54 @@ static struct dvb_usb_device_properties su3000_properties = { } }; +static struct dvb_usb_device_properties t220_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .size_of_priv = sizeof(struct su3000_state), + .power_ctrl = su3000_power_ctrl, + .num_adapters = 1, + .identify_state = su3000_identify_state, + .i2c_algo = &su3000_i2c_algo, + + .rc.legacy = { + .rc_map_table = rc_map_su3000_table, + .rc_map_size = ARRAY_SIZE(rc_map_su3000_table), + .rc_interval = 150, + .rc_query = dw2102_rc_query, + }, + + .read_mac_address = su3000_read_mac_address, + + .generic_bulk_ctrl_endpoint = 0x01, + + .adapter = { + { + .num_frontends = 1, + .fe = { { + .streaming_ctrl = su3000_streaming_ctrl, + .frontend_attach = t220_frontend_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + } + } }, + } + }, + .num_device_descs = 1, + .devices = { + { "Geniatech T220 DVB-T/T2 USB2.0", + { &dw2102_table[GENIATECH_T220], NULL }, + { NULL }, + }, + } +}; + static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -2149,7 +2254,9 @@ static int dw2102_probe(struct usb_interface *intf, 0 == dvb_usb_device_init(intf, s421, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &su3000_properties, - THIS_MODULE, NULL, adapter_nr)) + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &t220_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -ENODEV; @@ -2169,7 +2276,7 @@ MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," " DVB-C 3101 USB2.0," " TeVii S600, S630, S650, S660, S480, S421, S632" " Prof 1100, 7500 USB2.0," - " Geniatech SU3000 devices"); + " Geniatech SU3000, T220 devices"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(DW2101_FIRMWARE); -- cgit v1.2.3 From a49de26a0ef565cc466a80b0140c56256e7f3f7b Mon Sep 17 00:00:00 2001 From: Evgeny Plehov Date: Fri, 15 Nov 2013 16:43:33 -0300 Subject: [media] dw2102: Use RC Core instead of the legacy RC (second edition) Use RC Core instead of the legacy RC. DVBWorld, TBS, TeVii, Prof hardware decode only NEC remotes (one byte code). Geniatech hardware decode only RC5 (two bytes). + New keymap for Geniatech HDStar (SU3000). Signed-off-by: Evgeny Plehov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 3 +- drivers/media/rc/keymaps/rc-su3000.c | 75 +++++++++ drivers/media/usb/dvb-usb/dw2102.c | 298 +++++++++-------------------------- include/media/rc-map.h | 1 + 4 files changed, 152 insertions(+), 225 deletions(-) create mode 100644 drivers/media/rc/keymaps/rc-su3000.c (limited to 'drivers') diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index b1cde8c0422b..0b8c54919010 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -98,4 +98,5 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-videomate-s350.o \ rc-videomate-tv-pvr.o \ rc-winfast.o \ - rc-winfast-usbii-deluxe.o + rc-winfast-usbii-deluxe.o \ + rc-su3000.o diff --git a/drivers/media/rc/keymaps/rc-su3000.c b/drivers/media/rc/keymaps/rc-su3000.c new file mode 100644 index 000000000000..8dbd3e9bc951 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-su3000.c @@ -0,0 +1,75 @@ +/* rc-su3000.h - Keytable for Geniatech HDStar Remote Controller + * + * Copyright (c) 2013 by Evgeny Plehov + * + * 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 + +static struct rc_map_table su3000[] = { + { 0x25, KEY_POWER }, /* right-bottom Red */ + { 0x0a, KEY_MUTE }, /* -/-- */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x00, KEY_0 }, + { 0x20, KEY_UP }, /* CH+ */ + { 0x21, KEY_DOWN }, /* CH+ */ + { 0x12, KEY_VOLUMEUP }, /* Brightness Up */ + { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */ + { 0x1f, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x16, KEY_PAUSE }, + { 0x0b, KEY_STOP }, + { 0x27, KEY_FASTFORWARD },/* >> */ + { 0x26, KEY_REWIND }, /* << */ + { 0x0d, KEY_OK }, /* Mute */ + { 0x11, KEY_LEFT }, /* VOL- */ + { 0x10, KEY_RIGHT }, /* VOL+ */ + { 0x29, KEY_BACK }, /* button under 9 */ + { 0x2c, KEY_MENU }, /* TTX */ + { 0x2b, KEY_EPG }, /* EPG */ + { 0x1e, KEY_RED }, /* OSD */ + { 0x0e, KEY_GREEN }, /* Window */ + { 0x2d, KEY_YELLOW }, /* button under << */ + { 0x0f, KEY_BLUE }, /* bottom yellow button */ + { 0x14, KEY_AUDIO }, /* Snapshot */ + { 0x38, KEY_TV }, /* TV/Radio */ + { 0x0c, KEY_ESC } /* upper Red button */ +}; + +static struct rc_map_list su3000_map = { + .map = { + .scan = su3000, + .size = ARRAY_SIZE(su3000), + .rc_type = RC_TYPE_RC5, + .name = RC_MAP_SU3000, + } +}; + +static int __init init_rc_map_su3000(void) +{ + return rc_map_register(&su3000_map); +} + +static void __exit exit_rc_map_su3000(void) +{ + rc_map_unregister(&su3000_map); +} + +module_init(init_rc_map_su3000) +module_exit(exit_rc_map_su3000) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeny Plehov "); diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 241c73701eaf..172a8554bc94 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -112,11 +112,6 @@ "Please see linux/Documentation/dvb/ for more details " \ "on firmware-problems." -struct rc_map_dvb_usb_table_table { - struct rc_map_table *rc_keys; - int rc_keys_size; -}; - struct su3000_state { u8 initialized; }; @@ -131,12 +126,6 @@ module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))." DVB_USB_DEBUG_STATUS); -/* keymaps */ -static int ir_keymap; -module_param_named(keymap, ir_keymap, int, 0644); -MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..." - " 256=none"); - /* demod probe */ static int demod_probe = 1; module_param_named(demod, demod_probe, int, 0644); @@ -1459,174 +1448,29 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static struct rc_map_table rc_map_dw210x_table[] = { - { 0xf80a, KEY_POWER2 }, /*power*/ - { 0xf80c, KEY_MUTE }, /*mute*/ - { 0xf811, KEY_1 }, - { 0xf812, KEY_2 }, - { 0xf813, KEY_3 }, - { 0xf814, KEY_4 }, - { 0xf815, KEY_5 }, - { 0xf816, KEY_6 }, - { 0xf817, KEY_7 }, - { 0xf818, KEY_8 }, - { 0xf819, KEY_9 }, - { 0xf810, KEY_0 }, - { 0xf81c, KEY_CHANNELUP }, /*ch+*/ - { 0xf80f, KEY_CHANNELDOWN }, /*ch-*/ - { 0xf81a, KEY_VOLUMEUP }, /*vol+*/ - { 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/ - { 0xf804, KEY_RECORD }, /*rec*/ - { 0xf809, KEY_FAVORITES }, /*fav*/ - { 0xf808, KEY_REWIND }, /*rewind*/ - { 0xf807, KEY_FASTFORWARD }, /*fast*/ - { 0xf80b, KEY_PAUSE }, /*pause*/ - { 0xf802, KEY_ESC }, /*cancel*/ - { 0xf803, KEY_TAB }, /*tab*/ - { 0xf800, KEY_UP }, /*up*/ - { 0xf81f, KEY_OK }, /*ok*/ - { 0xf801, KEY_DOWN }, /*down*/ - { 0xf805, KEY_CAMERA }, /*cap*/ - { 0xf806, KEY_STOP }, /*stop*/ - { 0xf840, KEY_ZOOM }, /*full*/ - { 0xf81e, KEY_TV }, /*tvmode*/ - { 0xf81b, KEY_LAST }, /*recall*/ -}; - -static struct rc_map_table rc_map_tevii_table[] = { - { 0xf80a, KEY_POWER }, - { 0xf80c, KEY_MUTE }, - { 0xf811, KEY_1 }, - { 0xf812, KEY_2 }, - { 0xf813, KEY_3 }, - { 0xf814, KEY_4 }, - { 0xf815, KEY_5 }, - { 0xf816, KEY_6 }, - { 0xf817, KEY_7 }, - { 0xf818, KEY_8 }, - { 0xf819, KEY_9 }, - { 0xf810, KEY_0 }, - { 0xf81c, KEY_MENU }, - { 0xf80f, KEY_VOLUMEDOWN }, - { 0xf81a, KEY_LAST }, - { 0xf80e, KEY_OPEN }, - { 0xf804, KEY_RECORD }, - { 0xf809, KEY_VOLUMEUP }, - { 0xf808, KEY_CHANNELUP }, - { 0xf807, KEY_PVR }, - { 0xf80b, KEY_TIME }, - { 0xf802, KEY_RIGHT }, - { 0xf803, KEY_LEFT }, - { 0xf800, KEY_UP }, - { 0xf81f, KEY_OK }, - { 0xf801, KEY_DOWN }, - { 0xf805, KEY_TUNER }, - { 0xf806, KEY_CHANNELDOWN }, - { 0xf840, KEY_PLAYPAUSE }, - { 0xf81e, KEY_REWIND }, - { 0xf81b, KEY_FAVORITES }, - { 0xf81d, KEY_BACK }, - { 0xf84d, KEY_FASTFORWARD }, - { 0xf844, KEY_EPG }, - { 0xf84c, KEY_INFO }, - { 0xf841, KEY_AB }, - { 0xf843, KEY_AUDIO }, - { 0xf845, KEY_SUBTITLE }, - { 0xf84a, KEY_LIST }, - { 0xf846, KEY_F1 }, - { 0xf847, KEY_F2 }, - { 0xf85e, KEY_F3 }, - { 0xf85c, KEY_F4 }, - { 0xf852, KEY_F5 }, - { 0xf85a, KEY_F6 }, - { 0xf856, KEY_MODE }, - { 0xf858, KEY_SWITCHVIDEOMODE }, -}; - -static struct rc_map_table rc_map_tbs_table[] = { - { 0xf884, KEY_POWER }, - { 0xf894, KEY_MUTE }, - { 0xf887, KEY_1 }, - { 0xf886, KEY_2 }, - { 0xf885, KEY_3 }, - { 0xf88b, KEY_4 }, - { 0xf88a, KEY_5 }, - { 0xf889, KEY_6 }, - { 0xf88f, KEY_7 }, - { 0xf88e, KEY_8 }, - { 0xf88d, KEY_9 }, - { 0xf892, KEY_0 }, - { 0xf896, KEY_CHANNELUP }, - { 0xf891, KEY_CHANNELDOWN }, - { 0xf893, KEY_VOLUMEUP }, - { 0xf88c, KEY_VOLUMEDOWN }, - { 0xf883, KEY_RECORD }, - { 0xf898, KEY_PAUSE }, - { 0xf899, KEY_OK }, - { 0xf89a, KEY_SHUFFLE }, - { 0xf881, KEY_UP }, - { 0xf890, KEY_LEFT }, - { 0xf882, KEY_RIGHT }, - { 0xf888, KEY_DOWN }, - { 0xf895, KEY_FAVORITES }, - { 0xf897, KEY_SUBTITLE }, - { 0xf89d, KEY_ZOOM }, - { 0xf89f, KEY_EXIT }, - { 0xf89e, KEY_MENU }, - { 0xf89c, KEY_EPG }, - { 0xf880, KEY_PREVIOUS }, - { 0xf89b, KEY_MODE } -}; +static int dw2102_rc_query(struct dvb_usb_device *d) +{ + u8 key[2]; + struct i2c_msg msg = { + .addr = DW2102_RC_QUERY, + .flags = I2C_M_RD, + .buf = key, + .len = 2 + }; -static struct rc_map_table rc_map_su3000_table[] = { - { 0x25, KEY_POWER }, /* right-bottom Red */ - { 0x0a, KEY_MUTE }, /* -/-- */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x00, KEY_0 }, - { 0x20, KEY_UP }, /* CH+ */ - { 0x21, KEY_DOWN }, /* CH+ */ - { 0x12, KEY_VOLUMEUP }, /* Brightness Up */ - { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */ - { 0x1f, KEY_RECORD }, - { 0x17, KEY_PLAY }, - { 0x16, KEY_PAUSE }, - { 0x0b, KEY_STOP }, - { 0x27, KEY_FASTFORWARD },/* >> */ - { 0x26, KEY_REWIND }, /* << */ - { 0x0d, KEY_OK }, /* Mute */ - { 0x11, KEY_LEFT }, /* VOL- */ - { 0x10, KEY_RIGHT }, /* VOL+ */ - { 0x29, KEY_BACK }, /* button under 9 */ - { 0x2c, KEY_MENU }, /* TTX */ - { 0x2b, KEY_EPG }, /* EPG */ - { 0x1e, KEY_RED }, /* OSD */ - { 0x0e, KEY_GREEN }, /* Window */ - { 0x2d, KEY_YELLOW }, /* button under << */ - { 0x0f, KEY_BLUE }, /* bottom yellow button */ - { 0x14, KEY_AUDIO }, /* Snapshot */ - { 0x38, KEY_TV }, /* TV/Radio */ - { 0x0c, KEY_ESC } /* upper Red button */ -}; + if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { + if (msg.buf[0] != 0xff) { + deb_rc("%s: rc code: %x, %x\n", + __func__, key[0], key[1]); + rc_keydown(d->rc_dev, key[0], 1); + } + } -static struct rc_map_dvb_usb_table_table keys_tables[] = { - { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) }, - { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) }, - { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) }, - { rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) }, -}; + return 0; +} -static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int prof_rc_query(struct dvb_usb_device *d) { - struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; - int keymap_size = d->props.rc.legacy.rc_map_size; u8 key[2]; struct i2c_msg msg = { .addr = DW2102_RC_QUERY, @@ -1634,32 +1478,34 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) .buf = key, .len = 2 }; - int i; - /* override keymap */ - if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) { - keymap = keys_tables[ir_keymap - 1].rc_keys ; - keymap_size = keys_tables[ir_keymap - 1].rc_keys_size; - } else if (ir_keymap > ARRAY_SIZE(keys_tables)) - return 0; /* none */ - - *state = REMOTE_NO_KEY_PRESSED; - if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { - for (i = 0; i < keymap_size ; i++) { - if (rc5_data(&keymap[i]) == msg.buf[0]) { - *state = REMOTE_KEY_PRESSED; - *event = keymap[i].keycode; - break; - } + if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { + if (msg.buf[0] != 0xff) { + deb_rc("%s: rc code: %x, %x\n", + __func__, key[0], key[1]); + rc_keydown(d->rc_dev, key[0]^0xff, 1); } + } - if ((*state) == REMOTE_KEY_PRESSED) - deb_rc("%s: found rc key: %x, %x, event: %x\n", - __func__, key[0], key[1], (*event)); - else if (key[0] != 0xff) - deb_rc("%s: unknown rc key: %x, %x\n", - __func__, key[0], key[1]); + return 0; +} + +static int su3000_rc_query(struct dvb_usb_device *d) +{ + u8 key[2]; + struct i2c_msg msg = { + .addr = DW2102_RC_QUERY, + .flags = I2C_M_RD, + .buf = key, + .len = 2 + }; + if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { + if (msg.buf[0] != 0xff) { + deb_rc("%s: rc code: %x, %x\n", + __func__, key[0], key[1]); + rc_keydown(d->rc_dev, key[1] << 8 | key[0], 1); + } } return 0; @@ -1768,9 +1614,7 @@ static int dw2102_load_firmware(struct usb_device *dev, /* init registers */ switch (dev->descriptor.idProduct) { case USB_PID_TEVII_S650: - dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table; - dw2104_properties.rc.legacy.rc_map_size = - ARRAY_SIZE(rc_map_tevii_table); + dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC; case USB_PID_DW2104: reset = 1; dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, @@ -1834,10 +1678,11 @@ static struct dvb_usb_device_properties dw2102_properties = { .i2c_algo = &dw2102_serit_i2c_algo, - .rc.legacy = { - .rc_map_table = rc_map_dw210x_table, - .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), + .rc.core = { .rc_interval = 150, + .rc_codes = RC_MAP_DM1105_NEC, + .module_name = "dw2102", + .allowed_protos = RC_BIT_NEC, .rc_query = dw2102_rc_query, }, @@ -1888,10 +1733,11 @@ static struct dvb_usb_device_properties dw2104_properties = { .no_reconnect = 1, .i2c_algo = &dw2104_i2c_algo, - .rc.legacy = { - .rc_map_table = rc_map_dw210x_table, - .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), + .rc.core = { .rc_interval = 150, + .rc_codes = RC_MAP_DM1105_NEC, + .module_name = "dw2102", + .allowed_protos = RC_BIT_NEC, .rc_query = dw2102_rc_query, }, @@ -1938,10 +1784,11 @@ static struct dvb_usb_device_properties dw3101_properties = { .no_reconnect = 1, .i2c_algo = &dw3101_i2c_algo, - .rc.legacy = { - .rc_map_table = rc_map_dw210x_table, - .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), + .rc.core = { .rc_interval = 150, + .rc_codes = RC_MAP_DM1105_NEC, + .module_name = "dw2102", + .allowed_protos = RC_BIT_NEC, .rc_query = dw2102_rc_query, }, @@ -1986,10 +1833,11 @@ static struct dvb_usb_device_properties s6x0_properties = { .no_reconnect = 1, .i2c_algo = &s6x0_i2c_algo, - .rc.legacy = { - .rc_map_table = rc_map_tevii_table, - .rc_map_size = ARRAY_SIZE(rc_map_tevii_table), + .rc.core = { .rc_interval = 150, + .rc_codes = RC_MAP_TEVII_NEC, + .module_name = "dw2102", + .allowed_protos = RC_BIT_NEC, .rc_query = dw2102_rc_query, }, @@ -2079,11 +1927,12 @@ static struct dvb_usb_device_properties su3000_properties = { .identify_state = su3000_identify_state, .i2c_algo = &su3000_i2c_algo, - .rc.legacy = { - .rc_map_table = rc_map_su3000_table, - .rc_map_size = ARRAY_SIZE(rc_map_su3000_table), + .rc.core = { .rc_interval = 150, - .rc_query = dw2102_rc_query, + .rc_codes = RC_MAP_SU3000, + .module_name = "dw2102", + .allowed_protos = RC_BIT_RC5, + .rc_query = su3000_rc_query, }, .read_mac_address = su3000_read_mac_address, @@ -2143,11 +1992,12 @@ static struct dvb_usb_device_properties t220_properties = { .identify_state = su3000_identify_state, .i2c_algo = &su3000_i2c_algo, - .rc.legacy = { - .rc_map_table = rc_map_su3000_table, - .rc_map_size = ARRAY_SIZE(rc_map_su3000_table), + .rc.core = { .rc_interval = 150, - .rc_query = dw2102_rc_query, + .rc_codes = RC_MAP_SU3000, + .module_name = "dw2102", + .allowed_protos = RC_BIT_RC5, + .rc_query = su3000_rc_query, }, .read_mac_address = su3000_read_mac_address, @@ -2193,8 +2043,8 @@ static int dw2102_probe(struct usb_interface *intf, /* fill only different fields */ p1100->firmware = P1100_FIRMWARE; p1100->devices[0] = d1100; - p1100->rc.legacy.rc_map_table = rc_map_tbs_table; - p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table); + p1100->rc.core.rc_query = prof_rc_query; + p1100->rc.core.rc_codes = RC_MAP_TBS_NEC; p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach; s660 = kmemdup(&s6x0_properties, @@ -2219,8 +2069,8 @@ static int dw2102_probe(struct usb_interface *intf, } p7500->firmware = P7500_FIRMWARE; p7500->devices[0] = d7500; - p7500->rc.legacy.rc_map_table = rc_map_tbs_table; - p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table); + p7500->rc.core.rc_query = prof_rc_query; + p7500->rc.core.rc_codes = RC_MAP_TBS_NEC; p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach; diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 6628f5d01f52..a20ed97d7d8a 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -193,6 +193,7 @@ void rc_map_init(void); #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" #define RC_MAP_WINFAST "rc-winfast" #define RC_MAP_WINFAST_USBII_DELUXE "rc-winfast-usbii-deluxe" +#define RC_MAP_SU3000 "rc-su3000" /* * Please, do not just append newer Remote Controller names at the end. -- cgit v1.2.3 From cd86e3b535eea2e2685f65f4318a8b13e62b11c3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 21 Nov 2013 00:38:44 -0300 Subject: [media] cx88: use correct pci drvdata type in cx88_audio_finidev() We had set the pci drvdata in cx88_audio_initdev() as a type of struct snd_card, so cx88_audio_finidev() should used it as the same type too. Signed-off-by: Wei Yongjun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx88/cx88-alsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index 400eb1c42d3f..d014206e7176 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -931,9 +931,9 @@ error: */ static void cx88_audio_finidev(struct pci_dev *pci) { - struct cx88_audio_dev *card = pci_get_drvdata(pci); + struct snd_card *card = pci_get_drvdata(pci); - snd_card_free((void *)card); + snd_card_free(card); devno--; } -- cgit v1.2.3 From eda9dfd6752e58c5c075076654007311da6b5268 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Thu, 21 Nov 2013 17:26:42 -0300 Subject: [media] mceusb: Add Hauppauge WinTV-HVR-930C HD Add usb id of Hauppauge WinTV-HVR-930C HD to mceusb RC driver. This device has no IR transmitter (according to eeprom content decoded by tveeprom). Set the rc mapping to Hauppauge, every key of the deliviered remote control works correctly. [m.chehab@samsung.com: fix merge conflicts and unmangled whitespace] Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 3c761014d3ce..a25bb1581e46 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -199,6 +199,7 @@ static bool debug; #define VENDOR_TIVO 0x105a #define VENDOR_CONEXANT 0x0572 #define VENDOR_TWISTEDMELON 0x2596 +#define VENDOR_HAUPPAUGE 0x2040 enum mceusb_model_type { MCE_GEN2 = 0, /* Most boards */ @@ -210,6 +211,7 @@ enum mceusb_model_type { MULTIFUNCTION, TIVO_KIT, MCE_GEN2_NO_TX, + HAUPPAUGE_CX_HYBRID_TV, }; struct mceusb_model { @@ -258,6 +260,11 @@ static const struct mceusb_model mceusb_model[] = { .no_tx = 1, /* tx isn't wired up at all */ .name = "Conexant Hybrid TV (cx231xx) MCE IR", }, + [HAUPPAUGE_CX_HYBRID_TV] = { + .rc_map = RC_MAP_HAUPPAUGE, + .no_tx = 1, /* eeprom says it has no tx */ + .name = "Conexant Hybrid TV (cx231xx) MCE IR no TX", + }, [MULTIFUNCTION] = { .mce_gen2 = 1, .ir_intfnum = 2, @@ -399,6 +406,9 @@ static struct usb_device_id mceusb_dev_table[] = { { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8016) }, /* Twisted Melon Inc. - Manta Transceiver */ { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8042) }, + /* Hauppauge WINTV-HVR-HVR 930C-HD - based on cx231xx */ + { USB_DEVICE(VENDOR_HAUPPAUGE, 0xb130), + .driver_info = HAUPPAUGE_CX_HYBRID_TV }, /* Terminating entry */ { } }; -- cgit v1.2.3 From e351bf25fa373a3de0be2141b962c5c3c27006a2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Nov 2013 04:51:47 -0300 Subject: [media] cx18: check for allocation failure in cx18_read_eeprom() It upsets static checkers when we don't check for allocation failure. I moved the memset() of "tv" earlier so we don't use uninitialized data on error. Fixes: 1d212cf0c2d8 ('[media] cx18: struct i2c_client is too big for stack') Signed-off-by: Dan Carpenter Acked-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-driver.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index c1f8cc6f14b2..716bdc57fac6 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -327,13 +327,16 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) struct i2c_client *c; u8 eedata[256]; + memset(tv, 0, sizeof(*tv)); + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return; strlcpy(c->name, "cx18 tveeprom tmp", sizeof(c->name)); c->adapter = &cx->i2c_adap[0]; c->addr = 0xa0 >> 1; - memset(tv, 0, sizeof(*tv)); if (tveeprom_read(c, eedata, sizeof(eedata))) goto ret; -- cgit v1.2.3 From 1cdbcc5db4e6d51ce9bb1313195167cada9aa6e9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Nov 2013 04:55:43 -0300 Subject: [media] cxusb: unlock on error in cxusb_i2c_xfer() We recently introduced some new error paths which are missing their unlocks. Fixes: 64f7ef8afbf8 ('[media] cxusb: Don't use dynamic static allocation') Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/cxusb.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 20e345d9fe8f..a1c641e18362 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -149,6 +149,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret; int i; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) @@ -173,7 +174,8 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (1 + msg[i].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[i].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = 0; obuf[1] = msg[i].len; @@ -193,12 +195,14 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (3 + msg[i].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[i].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } if (1 + msg[i + 1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[i + 1].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[i].len; obuf[1] = msg[i+1].len; @@ -223,7 +227,8 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (2 + msg[i].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[i].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[i].addr; obuf[1] = msg[i].len; @@ -237,8 +242,14 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } } + if (i == num) + ret = num; + else + ret = -EREMOTEIO; + +unlock: mutex_unlock(&d->i2c_mutex); - return i == num ? num : -EREMOTEIO; + return ret; } static u32 cxusb_i2c_func(struct i2c_adapter *adapter) -- cgit v1.2.3 From 324ed533bf0b23c309b805272c4ffcc5d51493a6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Nov 2013 04:56:33 -0300 Subject: [media] dw2102: some missing unlocks on error We recently introduced some new error paths but the unlocks are missing. Fixes: 0065a79a8698 ('[media] dw2102: Don't use dynamic static allocation') Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 52 ++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 172a8554bc94..ae0f56a32e4d 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -292,6 +292,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret; if (!d) return -ENODEV; @@ -307,7 +308,8 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms if (2 + msg[1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[1].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[0].addr << 1; @@ -331,7 +333,8 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms if (2 + msg[0].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[1].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[0].addr << 1; @@ -348,7 +351,8 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms if (2 + msg[0].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[1].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[0].addr << 1; @@ -377,15 +381,17 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms break; } + ret = num; +unlock: mutex_unlock(&d->i2c_mutex); - return num; + return ret; } static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - int len, i, j; + int len, i, j, ret; if (!d) return -ENODEV; @@ -421,7 +427,8 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i if (2 + msg[j].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[j].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } dw210x_op_rw(d->udev, 0xc3, @@ -457,7 +464,8 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i if (2 + msg[j].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[j].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[j].addr << 1; @@ -472,15 +480,18 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i } } + ret = num; +unlock: mutex_unlock(&d->i2c_mutex); - return num; + return ret; } static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret; int i; if (!d) @@ -497,7 +508,8 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (2 + msg[1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[1].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; @@ -521,7 +533,8 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (2 + msg[0].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[0].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; @@ -547,9 +560,11 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], msg[i].flags == 0 ? ">>>" : "<<<"); debug_dump(msg[i].buf, msg[i].len, deb_xfer); } + ret = num; +unlock: mutex_unlock(&d->i2c_mutex); - return num; + return ret; } static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], @@ -557,7 +572,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], { struct dvb_usb_device *d = i2c_get_adapdata(adap); struct usb_device *udev; - int len, i, j; + int len, i, j, ret; if (!d) return -ENODEV; @@ -609,7 +624,8 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (msg[j].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[j].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } dw210x_op_rw(d->udev, 0x91, 0, 0, @@ -643,7 +659,8 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (2 + msg[j].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[j].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[j + 1].len; @@ -662,7 +679,8 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (2 + msg[j].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[j].len); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto unlock; } obuf[0] = msg[j].len + 1; obuf[1] = (msg[j].addr << 1); @@ -676,9 +694,11 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], } } } + ret = num; +unlock: mutex_unlock(&d->i2c_mutex); - return num; + return ret; } static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], -- cgit v1.2.3 From 2d01237389dc64b37745ce87e64d6808b6eed582 Mon Sep 17 00:00:00 2001 From: Wade Farnsworth Date: Fri, 22 Nov 2013 16:48:28 -0300 Subject: [media] v4l2-dev: Add tracepoints for QBUF and DQBUF Add tracepoints to the QBUF and DQBUF ioctls to enable rudimentary performance measurements using standard kernel tracers. [m.chehab@samsung.com: CodingStyle fixes (whitespacing)] Signed-off-by: Wade Farnsworth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 9 +++ include/trace/events/v4l2.h | 157 +++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 include/trace/events/v4l2.h (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index b5aaaac427ad..1cc17496b202 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -31,6 +31,10 @@ #include #include + +#define CREATE_TRACE_POINTS +#include + #define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" @@ -391,6 +395,11 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } else ret = -ENOTTY; + if (cmd == VIDIOC_DQBUF) + trace_v4l2_dqbuf(vdev->minor, (struct v4l2_buffer *)arg); + else if (cmd == VIDIOC_QBUF) + trace_v4l2_qbuf(vdev->minor, (struct v4l2_buffer *)arg); + return ret; } diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h new file mode 100644 index 000000000000..ef94ecad1c94 --- /dev/null +++ b/include/trace/events/v4l2.h @@ -0,0 +1,157 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM v4l2 + +#if !defined(_TRACE_V4L2_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_V4L2_H + +#include + +#define show_type(type) \ + __print_symbolic(type, \ + { V4L2_BUF_TYPE_VIDEO_CAPTURE, "VIDEO_CAPTURE" }, \ + { V4L2_BUF_TYPE_VIDEO_OUTPUT, "VIDEO_OUTPUT" }, \ + { V4L2_BUF_TYPE_VIDEO_OVERLAY, "VIDEO_OVERLAY" }, \ + { V4L2_BUF_TYPE_VBI_CAPTURE, "VBI_CAPTURE" }, \ + { V4L2_BUF_TYPE_VBI_OUTPUT, "VBI_OUTPUT" }, \ + { V4L2_BUF_TYPE_SLICED_VBI_CAPTURE, "SLICED_VBI_CAPTURE" }, \ + { V4L2_BUF_TYPE_SLICED_VBI_OUTPUT, "SLICED_VBI_OUTPUT" }, \ + { V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, "VIDEO_OUTPUT_OVERLAY" },\ + { V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, "VIDEO_CAPTURE_MPLANE" },\ + { V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, "VIDEO_OUTPUT_MPLANE" }, \ + { V4L2_BUF_TYPE_PRIVATE, "PRIVATE" }) + +#define show_field(field) \ + __print_symbolic(field, \ + { V4L2_FIELD_ANY, "ANY" }, \ + { V4L2_FIELD_NONE, "NONE" }, \ + { V4L2_FIELD_TOP, "TOP" }, \ + { V4L2_FIELD_BOTTOM, "BOTTOM" }, \ + { V4L2_FIELD_INTERLACED, "INTERLACED" }, \ + { V4L2_FIELD_SEQ_TB, "SEQ_TB" }, \ + { V4L2_FIELD_SEQ_BT, "SEQ_BT" }, \ + { V4L2_FIELD_ALTERNATE, "ALTERNATE" }, \ + { V4L2_FIELD_INTERLACED_TB, "INTERLACED_TB" }, \ + { V4L2_FIELD_INTERLACED_BT, "INTERLACED_BT" }) + +#define show_timecode_type(type) \ + __print_symbolic(type, \ + { V4L2_TC_TYPE_24FPS, "24FPS" }, \ + { V4L2_TC_TYPE_25FPS, "25FPS" }, \ + { V4L2_TC_TYPE_30FPS, "30FPS" }, \ + { V4L2_TC_TYPE_50FPS, "50FPS" }, \ + { V4L2_TC_TYPE_60FPS, "60FPS" }) + +#define show_flags(flags) \ + __print_flags(flags, "|", \ + { V4L2_BUF_FLAG_MAPPED, "MAPPED" }, \ + { V4L2_BUF_FLAG_QUEUED, "QUEUED" }, \ + { V4L2_BUF_FLAG_DONE, "DONE" }, \ + { V4L2_BUF_FLAG_KEYFRAME, "KEYFRAME" }, \ + { V4L2_BUF_FLAG_PFRAME, "PFRAME" }, \ + { V4L2_BUF_FLAG_BFRAME, "BFRAME" }, \ + { V4L2_BUF_FLAG_ERROR, "ERROR" }, \ + { V4L2_BUF_FLAG_TIMECODE, "TIMECODE" }, \ + { V4L2_BUF_FLAG_PREPARED, "PREPARED" }, \ + { V4L2_BUF_FLAG_NO_CACHE_INVALIDATE, "NO_CACHE_INVALIDATE" }, \ + { V4L2_BUF_FLAG_NO_CACHE_CLEAN, "NO_CACHE_CLEAN" }, \ + { V4L2_BUF_FLAG_TIMESTAMP_MASK, "TIMESTAMP_MASK" }, \ + { V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN, "TIMESTAMP_UNKNOWN" }, \ + { V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, "TIMESTAMP_MONOTONIC" }, \ + { V4L2_BUF_FLAG_TIMESTAMP_COPY, "TIMESTAMP_COPY" }) + +#define show_timecode_flags(flags) \ + __print_flags(flags, "|", \ + { V4L2_TC_FLAG_DROPFRAME, "DROPFRAME" }, \ + { V4L2_TC_FLAG_COLORFRAME, "COLORFRAME" }, \ + { V4L2_TC_USERBITS_USERDEFINED, "USERBITS_USERDEFINED" }, \ + { V4L2_TC_USERBITS_8BITCHARS, "USERBITS_8BITCHARS" }) + +#define V4L2_TRACE_EVENT(event_name) \ + TRACE_EVENT(event_name, \ + TP_PROTO(int minor, struct v4l2_buffer *buf), \ + \ + TP_ARGS(minor, buf), \ + \ + TP_STRUCT__entry( \ + __field(int, minor) \ + __field(u32, index) \ + __field(u32, type) \ + __field(u32, bytesused) \ + __field(u32, flags) \ + __field(u32, field) \ + __field(s64, timestamp) \ + __field(u32, timecode_type) \ + __field(u32, timecode_flags) \ + __field(u8, timecode_frames) \ + __field(u8, timecode_seconds) \ + __field(u8, timecode_minutes) \ + __field(u8, timecode_hours) \ + __field(u8, timecode_userbits0) \ + __field(u8, timecode_userbits1) \ + __field(u8, timecode_userbits2) \ + __field(u8, timecode_userbits3) \ + __field(u32, sequence) \ + ), \ + \ + TP_fast_assign( \ + __entry->minor = minor; \ + __entry->index = buf->index; \ + __entry->type = buf->type; \ + __entry->bytesused = buf->bytesused; \ + __entry->flags = buf->flags; \ + __entry->field = buf->field; \ + __entry->timestamp = \ + timeval_to_ns(&buf->timestamp); \ + __entry->timecode_type = buf->timecode.type; \ + __entry->timecode_flags = buf->timecode.flags; \ + __entry->timecode_frames = \ + buf->timecode.frames; \ + __entry->timecode_seconds = \ + buf->timecode.seconds; \ + __entry->timecode_minutes = \ + buf->timecode.minutes; \ + __entry->timecode_hours = buf->timecode.hours; \ + __entry->timecode_userbits0 = \ + buf->timecode.userbits[0]; \ + __entry->timecode_userbits1 = \ + buf->timecode.userbits[1]; \ + __entry->timecode_userbits2 = \ + buf->timecode.userbits[2]; \ + __entry->timecode_userbits3 = \ + buf->timecode.userbits[3]; \ + __entry->sequence = buf->sequence; \ + ), \ + \ + TP_printk("minor = %d, index = %u, type = %s, " \ + "bytesused = %u, flags = %s, " \ + "field = %s, timestamp = %llu, timecode = { " \ + "type = %s, flags = %s, frames = %u, " \ + "seconds = %u, minutes = %u, hours = %u, " \ + "userbits = { %u %u %u %u } }, " \ + "sequence = %u", __entry->minor, \ + __entry->index, show_type(__entry->type), \ + __entry->bytesused, \ + show_flags(__entry->flags), \ + show_field(__entry->field), \ + __entry->timestamp, \ + show_timecode_type(__entry->timecode_type), \ + show_timecode_flags(__entry->timecode_flags), \ + __entry->timecode_frames, \ + __entry->timecode_seconds, \ + __entry->timecode_minutes, \ + __entry->timecode_hours, \ + __entry->timecode_userbits0, \ + __entry->timecode_userbits1, \ + __entry->timecode_userbits2, \ + __entry->timecode_userbits3, \ + __entry->sequence \ + ) \ + ) + +V4L2_TRACE_EVENT(v4l2_dqbuf); +V4L2_TRACE_EVENT(v4l2_qbuf); + +#endif /* if !defined(_TRACE_V4L2_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#include -- cgit v1.2.3 From f1ff7c49f494bdfa49ca58c3c0b70b844f1f7d08 Mon Sep 17 00:00:00 2001 From: Mauro Dreissig Date: Tue, 26 Nov 2013 11:15:20 -0300 Subject: [media] staging: as102: Declare local variables as static As pointed out by sparse: drivers/staging/media/as102/as102_fw.c:29:6: warning: symbol 'as102_st_fw1' was not declared. Should it be static? drivers/staging/media/as102/as102_fw.c:30:6: warning: symbol 'as102_st_fw2' was not declared. Should it be static? drivers/staging/media/as102/as102_fw.c:31:6: warning: symbol 'as102_dt_fw1' was not declared. Should it be static? drivers/staging/media/as102/as102_fw.c:32:6: warning: symbol 'as102_dt_fw2' was not declared. Should it be static? drivers/staging/media/as102/as102_usb_drv.c:194:25: warning: symbol 'as102_priv_ops' was not declared. Should it be static? Also use the const qualifier on the firmware name strings. Signed-off-by: Mauro Dreissig Acked-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/as102/as102_fw.c | 10 +++++----- drivers/staging/media/as102/as102_usb_drv.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index b9670ee41b4e..9e7c6d735746 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -26,10 +26,10 @@ #include "as102_drv.h" #include "as102_fw.h" -char as102_st_fw1[] = "as102_data1_st.hex"; -char as102_st_fw2[] = "as102_data2_st.hex"; -char as102_dt_fw1[] = "as102_data1_dt.hex"; -char as102_dt_fw2[] = "as102_data2_dt.hex"; +static const char as102_st_fw1[] = "as102_data1_st.hex"; +static const char as102_st_fw2[] = "as102_data2_st.hex"; +static const char as102_dt_fw1[] = "as102_data1_dt.hex"; +static const char as102_dt_fw2[] = "as102_data2_dt.hex"; static unsigned char atohx(unsigned char *dst, char *src) { @@ -167,7 +167,7 @@ int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap) int errno = -EFAULT; const struct firmware *firmware = NULL; unsigned char *cmd_buf = NULL; - char *fw1, *fw2; + const char *fw1, *fw2; struct usb_device *dev = bus_adap->usb_dev; ENTER(); diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 9f275f020150..0eaced3926f0 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -191,7 +191,7 @@ static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap, return ret ? ret : actual_len; } -struct as102_priv_ops_t as102_priv_ops = { +static struct as102_priv_ops_t as102_priv_ops = { .upload_fw_pkt = as102_send_ep1, .xfer_cmd = as102_usb_xfer_cmd, .as102_read_ep2 = as102_read_ep2, -- cgit v1.2.3 From cdfe3e352b6d93d74a46453d28138e5a5bc95aee Mon Sep 17 00:00:00 2001 From: Mauro Dreissig Date: Tue, 26 Nov 2013 11:15:21 -0300 Subject: [media] staging: as102: Remove ENTER/LEAVE debugging macros Too much noise, also does not cover every possible code paths. Signed-off-by: Mauro Dreissig Acked-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/as102/as102_drv.c | 10 ---------- drivers/staging/media/as102/as102_drv.h | 8 -------- drivers/staging/media/as102/as102_fe.c | 26 -------------------------- drivers/staging/media/as102/as102_fw.c | 6 ------ drivers/staging/media/as102/as102_usb_drv.c | 25 ------------------------- drivers/staging/media/as102/as10x_cmd.c | 21 --------------------- drivers/staging/media/as102/as10x_cmd_cfg.c | 9 --------- drivers/staging/media/as102/as10x_cmd_stream.c | 12 ------------ 8 files changed, 117 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index ac92eaf6c74b..62218db6b940 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -112,8 +112,6 @@ static int as10x_pid_filter(struct as102_dev_t *dev, struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap; int ret = -EFAULT; - ENTER(); - if (mutex_lock_interruptible(&dev->bus_adap.lock)) { dprintk(debug, "mutex_lock_interruptible(lock) failed !\n"); return -EBUSY; @@ -141,8 +139,6 @@ static int as10x_pid_filter(struct as102_dev_t *dev, } mutex_unlock(&dev->bus_adap.lock); - - LEAVE(); return ret; } @@ -152,8 +148,6 @@ static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct as102_dev_t *as102_dev = demux->priv; - ENTER(); - if (mutex_lock_interruptible(&as102_dev->sem)) return -ERESTARTSYS; @@ -165,7 +159,6 @@ static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) ret = as102_start_stream(as102_dev); mutex_unlock(&as102_dev->sem); - LEAVE(); return ret; } @@ -174,8 +167,6 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct as102_dev_t *as102_dev = demux->priv; - ENTER(); - if (mutex_lock_interruptible(&as102_dev->sem)) return -ERESTARTSYS; @@ -187,7 +178,6 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) dvbdmxfeed->pid, 0); mutex_unlock(&as102_dev->sem); - LEAVE(); return 0; } diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index b0e5a23bd532..a06837dcc05d 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -38,14 +38,6 @@ extern int elna_enable; printk(args); \ } } while (0) -#ifdef TRACE -#define ENTER() pr_debug(">> enter %s\n", __func__) -#define LEAVE() pr_debug("<< leave %s\n", __func__) -#else -#define ENTER() -#define LEAVE() -#endif - #define AS102_DEVICE_MAJOR 192 #define AS102_USB_BUF_SIZE 512 diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c index 9ce8c9daa2e7..72b2c4813430 100644 --- a/drivers/staging/media/as102/as102_fe.c +++ b/drivers/staging/media/as102/as102_fe.c @@ -34,8 +34,6 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe) struct as102_dev_t *dev; struct as10x_tune_args tune_args = { 0 }; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; @@ -52,7 +50,6 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe) mutex_unlock(&dev->bus_adap.lock); - LEAVE(); return (ret < 0) ? -EINVAL : 0; } @@ -63,8 +60,6 @@ static int as102_fe_get_frontend(struct dvb_frontend *fe) struct as102_dev_t *dev; struct as10x_tps tps = { 0 }; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -EINVAL; @@ -80,13 +75,11 @@ static int as102_fe_get_frontend(struct dvb_frontend *fe) mutex_unlock(&dev->bus_adap.lock); - LEAVE(); return (ret < 0) ? -EINVAL : 0; } static int as102_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *settings) { - ENTER(); #if 0 dprintk(debug, "step_size = %d\n", settings->step_size); @@ -97,7 +90,6 @@ static int as102_fe_get_tune_settings(struct dvb_frontend *fe, settings->min_delay_ms = 1000; - LEAVE(); return 0; } @@ -108,8 +100,6 @@ static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) struct as102_dev_t *dev; struct as10x_tune_status tstate = { 0 }; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; @@ -168,7 +158,6 @@ static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) out: mutex_unlock(&dev->bus_adap.lock); - LEAVE(); return ret; } @@ -183,15 +172,12 @@ static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr) { struct as102_dev_t *dev; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; *snr = dev->demod_stats.mer; - LEAVE(); return 0; } @@ -199,15 +185,12 @@ static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber) { struct as102_dev_t *dev; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; *ber = dev->ber; - LEAVE(); return 0; } @@ -216,15 +199,12 @@ static int as102_fe_read_signal_strength(struct dvb_frontend *fe, { struct as102_dev_t *dev; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; *strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2); - LEAVE(); return 0; } @@ -232,8 +212,6 @@ static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { struct as102_dev_t *dev; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; @@ -243,7 +221,6 @@ static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) else *ucblocks = 0; - LEAVE(); return 0; } @@ -252,8 +229,6 @@ static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) struct as102_dev_t *dev; int ret; - ENTER(); - dev = (struct as102_dev_t *) fe->tuner_priv; if (dev == NULL) return -ENODEV; @@ -272,7 +247,6 @@ static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) mutex_unlock(&dev->bus_adap.lock); - LEAVE(); return ret; } diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index 9e7c6d735746..f33f752c0aad 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -109,8 +109,6 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, int total_read_bytes = 0, errno = 0; unsigned char addr_has_changed = 0; - ENTER(); - for (total_read_bytes = 0; total_read_bytes < firmware->size; ) { int read_bytes = 0, data_len = 0; @@ -158,7 +156,6 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, } } error: - LEAVE(); return (errno == 0) ? total_read_bytes : errno; } @@ -170,8 +167,6 @@ int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap) const char *fw1, *fw2; struct usb_device *dev = bus_adap->usb_dev; - ENTER(); - /* select fw file to upload */ if (dual_tuner) { fw1 = as102_dt_fw1; @@ -233,6 +228,5 @@ error: kfree(cmd_buf); release_firmware(firmware); - LEAVE(); return errno; } diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 0eaced3926f0..8759553decac 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -92,7 +92,6 @@ static int as102_usb_xfer_cmd(struct as10x_bus_adapter_t *bus_adap, unsigned char *recv_buf, int recv_buf_len) { int ret = 0; - ENTER(); if (send_buf != NULL) { ret = usb_control_msg(bus_adap->usb_dev, @@ -140,7 +139,6 @@ static int as102_usb_xfer_cmd(struct as10x_bus_adapter_t *bus_adap, #endif } - LEAVE(); return ret; } @@ -240,8 +238,6 @@ static void as102_free_usb_stream_buffer(struct as102_dev_t *dev) { int i; - ENTER(); - for (i = 0; i < MAX_STREAM_URB; i++) usb_free_urb(dev->stream_urb[i]); @@ -249,15 +245,12 @@ static void as102_free_usb_stream_buffer(struct as102_dev_t *dev) MAX_STREAM_URB * AS102_USB_BUF_SIZE, dev->stream, dev->dma_addr); - LEAVE(); } static int as102_alloc_usb_stream_buffer(struct as102_dev_t *dev) { int i, ret = 0; - ENTER(); - dev->stream = usb_alloc_coherent(dev->bus_adap.usb_dev, MAX_STREAM_URB * AS102_USB_BUF_SIZE, GFP_KERNEL, @@ -287,7 +280,6 @@ static int as102_alloc_usb_stream_buffer(struct as102_dev_t *dev) dev->stream_urb[i] = urb; } - LEAVE(); return ret; } @@ -318,23 +310,17 @@ static void as102_usb_release(struct kref *kref) { struct as102_dev_t *as102_dev; - ENTER(); - as102_dev = container_of(kref, struct as102_dev_t, kref); if (as102_dev != NULL) { usb_put_dev(as102_dev->bus_adap.usb_dev); kfree(as102_dev); } - - LEAVE(); } static void as102_usb_disconnect(struct usb_interface *intf) { struct as102_dev_t *as102_dev; - ENTER(); - /* extract as102_dev_t from usb_device private data */ as102_dev = usb_get_intfdata(intf); @@ -353,8 +339,6 @@ static void as102_usb_disconnect(struct usb_interface *intf) kref_put(&as102_dev->kref, as102_usb_release); pr_info("%s: device has been disconnected\n", DRIVER_NAME); - - LEAVE(); } static int as102_usb_probe(struct usb_interface *intf, @@ -364,8 +348,6 @@ static int as102_usb_probe(struct usb_interface *intf, struct as102_dev_t *as102_dev; int i; - ENTER(); - /* This should never actually happen */ if (ARRAY_SIZE(as102_usb_id_table) != (sizeof(as102_device_names) / sizeof(const char *))) { @@ -424,7 +406,6 @@ static int as102_usb_probe(struct usb_interface *intf, /* register dvb layer */ ret = as102_dvb_register(as102_dev); - LEAVE(); return ret; failed: @@ -439,8 +420,6 @@ static int as102_open(struct inode *inode, struct file *file) struct usb_interface *intf = NULL; struct as102_dev_t *dev = NULL; - ENTER(); - /* read minor from inode */ minor = iminor(inode); @@ -467,7 +446,6 @@ static int as102_open(struct inode *inode, struct file *file) kref_get(&dev->kref); exit: - LEAVE(); return ret; } @@ -476,15 +454,12 @@ static int as102_release(struct inode *inode, struct file *file) int ret = 0; struct as102_dev_t *dev = NULL; - ENTER(); - dev = file->private_data; if (dev != NULL) { /* decrement the count on our device */ kref_put(&dev->kref, as102_usb_release); } - LEAVE(); return ret; } diff --git a/drivers/staging/media/as102/as10x_cmd.c b/drivers/staging/media/as102/as10x_cmd.c index a73df10982d0..9e49f15a7c9f 100644 --- a/drivers/staging/media/as102/as10x_cmd.c +++ b/drivers/staging/media/as102/as10x_cmd.c @@ -34,8 +34,6 @@ int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap) int error = AS10X_CMD_ERROR; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -63,7 +61,6 @@ int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap) error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP); out: - LEAVE(); return error; } @@ -78,8 +75,6 @@ int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap) int error = AS10X_CMD_ERROR; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -106,7 +101,6 @@ int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap) error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP); out: - LEAVE(); return error; } @@ -123,8 +117,6 @@ int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap, int error = AS10X_CMD_ERROR; struct as10x_cmd_t *preq, *prsp; - ENTER(); - preq = adap->cmd; prsp = adap->rsp; @@ -164,7 +156,6 @@ int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap, error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP); out: - LEAVE(); return error; } @@ -181,8 +172,6 @@ int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap, int error = AS10X_CMD_ERROR; struct as10x_cmd_t *preq, *prsp; - ENTER(); - preq = adap->cmd; prsp = adap->rsp; @@ -220,7 +209,6 @@ int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap, pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER); out: - LEAVE(); return error; } @@ -236,8 +224,6 @@ int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps) int error = AS10X_CMD_ERROR; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -281,7 +267,6 @@ int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps) ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID); out: - LEAVE(); return error; } @@ -298,8 +283,6 @@ int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap, int error = AS10X_CMD_ERROR; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -343,7 +326,6 @@ int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap, prsp->body.get_demod_stats.rsp.stats.has_started; out: - LEAVE(); return error; } @@ -361,8 +343,6 @@ int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap, int error = AS10X_CMD_ERROR; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -397,7 +377,6 @@ int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap, *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready; out: - LEAVE(); return error; } diff --git a/drivers/staging/media/as102/as10x_cmd_cfg.c b/drivers/staging/media/as102/as10x_cmd_cfg.c index 4a2bbd766655..b1e300d88753 100644 --- a/drivers/staging/media/as102/as10x_cmd_cfg.c +++ b/drivers/staging/media/as102/as10x_cmd_cfg.c @@ -40,8 +40,6 @@ int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag, int error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -81,7 +79,6 @@ int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag, } out: - LEAVE(); return error; } @@ -99,8 +96,6 @@ int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag, int error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -136,7 +131,6 @@ int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag, error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP); out: - LEAVE(); return error; } @@ -156,8 +150,6 @@ int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode) int error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -188,7 +180,6 @@ int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode) error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP); out: - LEAVE(); return error; } diff --git a/drivers/staging/media/as102/as10x_cmd_stream.c b/drivers/staging/media/as102/as10x_cmd_stream.c index 6d000f60fb0e..1088ca1fe92f 100644 --- a/drivers/staging/media/as102/as10x_cmd_stream.c +++ b/drivers/staging/media/as102/as10x_cmd_stream.c @@ -34,8 +34,6 @@ int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap, int error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -77,7 +75,6 @@ int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap, } out: - LEAVE(); return error; } @@ -94,8 +91,6 @@ int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap, int error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -126,7 +121,6 @@ int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap, error = as10x_rsp_parse(prsp, CONTROL_PROC_REMOVEFILTER_RSP); out: - LEAVE(); return error; } @@ -141,8 +135,6 @@ int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap) int error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -172,7 +164,6 @@ int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap) error = as10x_rsp_parse(prsp, CONTROL_PROC_START_STREAMING_RSP); out: - LEAVE(); return error; } @@ -187,8 +178,6 @@ int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap) int8_t error; struct as10x_cmd_t *pcmd, *prsp; - ENTER(); - pcmd = adap->cmd; prsp = adap->rsp; @@ -218,6 +207,5 @@ int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap) error = as10x_rsp_parse(prsp, CONTROL_PROC_STOP_STREAMING_RSP); out: - LEAVE(); return error; } -- cgit v1.2.3 From 7b2f25c0b073479fa1afea3ae65dd9d9f0da5586 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 29 Nov 2013 20:01:34 -0300 Subject: [media] v4l: vs6624: Fix warning due to unused function vs6624_read() is only called in the conditionally-compiled vs6624_g_register() function. Make the former conditionally-compiled as well to silence build warnings. Signed-off-by: Laurent Pinchart Acked-by: Scott Jiang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/vs6624.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index 25bdd9312fea..23f4f65fccd7 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -503,6 +503,7 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) return &container_of(ctrl->handler, struct vs6624, hdl)->sd; } +#ifdef CONFIG_VIDEO_ADV_DEBUG static int vs6624_read(struct v4l2_subdev *sd, u16 index) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -515,6 +516,7 @@ static int vs6624_read(struct v4l2_subdev *sd, u16 index) return buf[0]; } +#endif static int vs6624_write(struct v4l2_subdev *sd, u16 index, u8 value) -- cgit v1.2.3 From 07e4de3004ecedd67c72708d6c0fe69c51317f79 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 1 Dec 2013 18:06:51 -0300 Subject: [media] em28xx: add support for GPO controlled analog capturing LEDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices are equipped with a capturing status LED that needs to be switched on/off explicitly via a GPO port. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 69 ++++++++++++++++++---------------- drivers/media/usb/em28xx/em28xx.h | 9 +++++ 2 files changed, 46 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index fc157af5234a..31d6ab2555f2 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -608,46 +608,51 @@ int em28xx_capture_start(struct em28xx *dev, int start) dev->chip_id == CHIP_ID_EM2884 || dev->chip_id == CHIP_ID_EM28174) { /* The Transport Stream Enable Register moved in em2874 */ - if (!start) { - rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, - 0x00, - EM2874_TS1_CAPTURE_ENABLE); - return rc; - } - - /* Enable Transport Stream */ rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, - EM2874_TS1_CAPTURE_ENABLE, + start ? + EM2874_TS1_CAPTURE_ENABLE : 0x00, EM2874_TS1_CAPTURE_ENABLE); - return rc; - } - + } else { + /* FIXME: which is the best order? */ + /* video registers are sampled by VREF */ + rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP, + start ? 0x10 : 0x00, 0x10); + if (rc < 0) + return rc; - /* FIXME: which is the best order? */ - /* video registers are sampled by VREF */ - rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP, - start ? 0x10 : 0x00, 0x10); - if (rc < 0) - return rc; + if (start) { + if (dev->board.is_webcam) + rc = em28xx_write_reg(dev, 0x13, 0x0c); - if (!start) { - /* disable video capture */ - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27); - return rc; - } + /* Enable video capture */ + rc = em28xx_write_reg(dev, 0x48, 0x00); - if (dev->board.is_webcam) - rc = em28xx_write_reg(dev, 0x13, 0x0c); + if (dev->mode == EM28XX_ANALOG_MODE) + rc = em28xx_write_reg(dev, + EM28XX_R12_VINENABLE, 0x67); + else + rc = em28xx_write_reg(dev, + EM28XX_R12_VINENABLE, 0x37); - /* enable video capture */ - rc = em28xx_write_reg(dev, 0x48, 0x00); + msleep(6); + } else { + /* disable video capture */ + rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27); + } + } - if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); - else - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); + if (rc < 0) + return rc; - msleep(6); + /* Switch (explicitly controlled) analog capturing LED on/off */ + if ((dev->mode == EM28XX_ANALOG_MODE) + && dev->board.analog_capturing_led) { + struct em28xx_led *led = dev->board.analog_capturing_led; + em28xx_write_reg_bits(dev, led->gpio_reg, + (!start ^ led->inverted) ? + ~led->gpio_mask : led->gpio_mask, + led->gpio_mask); + } return rc; } diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index f8726ad5d0a8..8003c2f7bb96 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -374,6 +374,12 @@ enum em28xx_adecoder { EM28XX_TVAUDIO, }; +struct em28xx_led { + u8 gpio_reg; + u8 gpio_mask; + bool inverted; +}; + struct em28xx_board { char *name; int vchannels; @@ -410,6 +416,9 @@ struct em28xx_board { struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; char *ir_codes; + + /* LEDs that need to be controlled explicitly */ + struct em28xx_led *analog_capturing_led; }; struct em28xx_eeprom { -- cgit v1.2.3 From f522260993822d82e2c480aa676aa4ca1230d235 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 1 Dec 2013 18:06:52 -0300 Subject: [media] em28xx: extend the support for device buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code supports only a single snapshot button assigned to register 0x0c bit 5. But devices may be equipped with multiple buttons with different functionalities and they can also be assigned to the various GPI-ports. Extend the em28xx-input code to handle multiple buttons assigned to different GPI-ports / register addresses and bits. Also make easier to extend the code with further button types. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 20 ++++- drivers/media/usb/em28xx/em28xx-input.c | 150 ++++++++++++++++++++++++-------- drivers/media/usb/em28xx/em28xx.h | 27 +++++- 3 files changed, 154 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index a5196697627f..ebb112c17109 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -412,6 +412,20 @@ static struct em28xx_reg_seq pctv_520e[] = { { -1, -1, -1, -1}, }; +/* + * Button definitions + */ +static struct em28xx_button std_snapshot_button[] = { + { + .role = EM28XX_BUTTON_SNAPSHOT, + .reg_r = EM28XX_R0C_USBSUSP, + .reg_clearing = EM28XX_R0C_USBSUSP, + .mask = EM28XX_R0C_USBSUSP_SNAPSHOT, + .inverted = 0, + }, + {-1, 0, 0, 0, 0}, +}; + /* * Board definitions */ @@ -1391,7 +1405,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { .name = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0", - .has_snapshot_button = 1, + .buttons = std_snapshot_button, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, .decoder = EM28XX_SAA711X, @@ -1413,7 +1427,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = { .name = "EM2860/SAA711X Reference Design", - .has_snapshot_button = 1, + .buttons = std_snapshot_button, .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { @@ -2841,7 +2855,7 @@ static void request_module_async(struct work_struct *work) if (dev->board.has_dvb) request_module("em28xx-dvb"); - if (dev->board.has_snapshot_button || + if (dev->board.buttons || ((dev->board.ir_codes || dev->board.has_ir_i2c) && !disable_ir)) request_module("em28xx-rc"); #endif /* CONFIG_MODULES */ diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index ea181e4b68c5..20c6a8ae1462 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -31,7 +31,7 @@ #include "em28xx.h" #define EM28XX_SNAPSHOT_KEY KEY_CAMERA -#define EM28XX_SBUTTON_QUERY_INTERVAL 500 +#define EM28XX_BUTTONS_QUERY_INTERVAL 500 static unsigned int ir_debug; module_param(ir_debug, int, 0644); @@ -470,38 +470,69 @@ static int em28xx_probe_i2c_ir(struct em28xx *dev) } /********************************************************** - Handle Webcam snapshot button + Handle buttons **********************************************************/ -static void em28xx_query_sbutton(struct work_struct *work) +static void em28xx_query_buttons(struct work_struct *work) { - /* Poll the register and see if the button is depressed */ struct em28xx *dev = - container_of(work, struct em28xx, sbutton_query_work.work); - int ret; - - ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP); - - if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) { - u8 cleared; - /* Button is depressed, clear the register */ - cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT; - em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1); - - /* Not emulate the keypress */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 1); - /* Now unpress the key */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 0); + container_of(work, struct em28xx, buttons_query_work.work); + u8 i, j; + int regval; + bool pressed; + + /* Poll and evaluate all addresses */ + for (i = 0; i < dev->num_button_polling_addresses; i++) { + /* Read value from register */ + regval = em28xx_read_reg(dev, dev->button_polling_addresses[i]); + if (regval < 0) + continue; + /* Check states of the buttons and act */ + j = 0; + while (dev->board.buttons[j].role >= 0 && + dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) { + struct em28xx_button *button = &dev->board.buttons[j]; + /* Check if button uses the current address */ + if (button->reg_r != dev->button_polling_addresses[i]) { + j++; + continue; + } + /* Determine if button is pressed */ + pressed = regval & button->mask; + if (button->inverted) + pressed = !pressed; + /* Handle button state */ + if (!pressed) { + j++; + continue; + } + switch (button->role) { + case EM28XX_BUTTON_SNAPSHOT: + /* Emulate the keypress */ + input_report_key(dev->sbutton_input_dev, + EM28XX_SNAPSHOT_KEY, 1); + /* Unpress the key */ + input_report_key(dev->sbutton_input_dev, + EM28XX_SNAPSHOT_KEY, 0); + break; + default: + WARN_ONCE(1, "BUG: unhandled button role."); + } + /* Clear button state (if needed) */ + if (button->reg_clearing) + em28xx_write_reg(dev, button->reg_clearing, + (~regval & button->mask) + | (regval & ~button->mask)); + /* Next button */ + j++; + } } - /* Schedule next poll */ - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); + schedule_delayed_work(&dev->buttons_query_work, + msecs_to_jiffies(EM28XX_BUTTONS_QUERY_INTERVAL)); } -static void em28xx_register_snapshot_button(struct em28xx *dev) +static int em28xx_register_snapshot_button(struct em28xx *dev) { struct input_dev *input_dev; int err; @@ -510,14 +541,13 @@ static void em28xx_register_snapshot_button(struct em28xx *dev) input_dev = input_allocate_device(); if (!input_dev) { em28xx_errdev("input_allocate_device failed\n"); - return; + return -ENOMEM; } usb_make_path(dev->udev, dev->snapshot_button_path, sizeof(dev->snapshot_button_path)); strlcat(dev->snapshot_button_path, "/sbutton", sizeof(dev->snapshot_button_path)); - INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton); input_dev->name = "em28xx snapshot button"; input_dev->phys = dev->snapshot_button_path; @@ -535,25 +565,71 @@ static void em28xx_register_snapshot_button(struct em28xx *dev) if (err) { em28xx_errdev("input_register_device failed\n"); input_free_device(input_dev); - return; + return err; } dev->sbutton_input_dev = input_dev; - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); - return; + return 0; +} +static void em28xx_init_buttons(struct em28xx *dev) +{ + u8 i = 0, j = 0; + bool addr_new = 0; + + while (dev->board.buttons[i].role >= 0 && + dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) { + struct em28xx_button *button = &dev->board.buttons[i]; + /* Check if polling address is already on the list */ + addr_new = 1; + for (j = 0; j < dev->num_button_polling_addresses; j++) { + if (button->reg_r == dev->button_polling_addresses[j]) { + addr_new = 0; + break; + } + } + /* Check if max. number of polling addresses is exceeded */ + if (addr_new && dev->num_button_polling_addresses + >= EM28XX_NUM_BUTTON_ADDRESSES_MAX) { + WARN_ONCE(1, "BUG: maximum number of button polling addresses exceeded."); + addr_new = 0; + } + /* Register input device (if needed) */ + if (button->role == EM28XX_BUTTON_SNAPSHOT) { + if (em28xx_register_snapshot_button(dev) < 0) + addr_new = 0; + } + /* Add read address to list of polling addresses */ + if (addr_new) { + unsigned int index = dev->num_button_polling_addresses; + dev->button_polling_addresses[index] = button->reg_r; + dev->num_button_polling_addresses++; + } + /* Next button */ + i++; + } + + /* Start polling */ + if (dev->num_button_polling_addresses) { + INIT_DELAYED_WORK(&dev->buttons_query_work, + em28xx_query_buttons); + schedule_delayed_work(&dev->buttons_query_work, + msecs_to_jiffies(EM28XX_BUTTONS_QUERY_INTERVAL)); + } } -static void em28xx_deregister_snapshot_button(struct em28xx *dev) +static void em28xx_shutdown_buttons(struct em28xx *dev) { + /* Cancel polling */ + cancel_delayed_work_sync(&dev->buttons_query_work); + /* Clear polling addresses list */ + dev->num_button_polling_addresses = 0; + /* Deregister input devices */ if (dev->sbutton_input_dev != NULL) { em28xx_info("Deregistering snapshot button\n"); - cancel_delayed_work_sync(&dev->sbutton_query_work); input_unregister_device(dev->sbutton_input_dev); dev->sbutton_input_dev = NULL; } - return; } static int em28xx_ir_init(struct em28xx *dev) @@ -564,8 +640,8 @@ static int em28xx_ir_init(struct em28xx *dev) u64 rc_type; u16 i2c_rc_dev_addr = 0; - if (dev->board.has_snapshot_button) - em28xx_register_snapshot_button(dev); + if (dev->board.buttons) + em28xx_init_buttons(dev); if (dev->board.has_ir_i2c) { i2c_rc_dev_addr = em28xx_probe_i2c_ir(dev); @@ -688,7 +764,7 @@ static int em28xx_ir_fini(struct em28xx *dev) { struct em28xx_IR *ir = dev->ir; - em28xx_deregister_snapshot_button(dev); + em28xx_shutdown_buttons(dev); /* skip detach on non attached boards */ if (!ir) diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 8003c2f7bb96..e185d00e9044 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -181,6 +181,9 @@ /* time in msecs to wait for i2c writes to finish */ #define EM2800_I2C_XFER_TIMEOUT 20 +/* max. number of button state polling addresses */ +#define EM28XX_NUM_BUTTON_ADDRESSES_MAX 5 + enum em28xx_mode { EM28XX_SUSPEND, EM28XX_ANALOG_MODE, @@ -380,6 +383,19 @@ struct em28xx_led { bool inverted; }; +enum em28xx_button_role { + EM28XX_BUTTON_SNAPSHOT = 0, + EM28XX_NUM_BUTTON_ROLES, /* must be the last */ +}; + +struct em28xx_button { + enum em28xx_button_role role; + u8 reg_r; + u8 reg_clearing; + u8 mask; + bool inverted; +}; + struct em28xx_board { char *name; int vchannels; @@ -401,7 +417,6 @@ struct em28xx_board { unsigned int mts_firmware:1; unsigned int max_range_640_480:1; unsigned int has_dvb:1; - unsigned int has_snapshot_button:1; unsigned int is_webcam:1; unsigned int valid:1; unsigned int has_ir_i2c:1; @@ -419,6 +434,9 @@ struct em28xx_board { /* LEDs that need to be controlled explicitly */ struct em28xx_led *analog_capturing_led; + + /* Buttons */ + struct em28xx_button *buttons; }; struct em28xx_eeprom { @@ -648,10 +666,13 @@ struct em28xx { enum em28xx_mode mode; - /* Snapshot button */ + /* Button state polling */ + struct delayed_work buttons_query_work; + u8 button_polling_addresses[EM28XX_NUM_BUTTON_ADDRESSES_MAX]; + u8 num_button_polling_addresses; + /* Snapshot button input device */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; - struct delayed_work sbutton_query_work; struct em28xx_dvb *dvb; }; -- cgit v1.2.3 From 7763481a97488f201e7b6a42ddce1d163cd6297a Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 1 Dec 2013 18:06:53 -0300 Subject: [media] em28xx: add debouncing mechanism for GPI-connected buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far, the driver only supports a snapshot button which is assigned to register 0x0c bit 5. This special port has a built-in debouncing mechanism. For buttons connected to ordinary GPI ports, this patch implements a software debouncing mechanism. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 30 +++++++++++++++++++----------- drivers/media/usb/em28xx/em28xx.h | 1 + 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 20c6a8ae1462..ebc538730e07 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -479,7 +479,7 @@ static void em28xx_query_buttons(struct work_struct *work) container_of(work, struct em28xx, buttons_query_work.work); u8 i, j; int regval; - bool pressed; + bool is_pressed, was_pressed; /* Poll and evaluate all addresses */ for (i = 0; i < dev->num_button_polling_addresses; i++) { @@ -497,12 +497,21 @@ static void em28xx_query_buttons(struct work_struct *work) j++; continue; } - /* Determine if button is pressed */ - pressed = regval & button->mask; - if (button->inverted) - pressed = !pressed; + /* Determine if button is and was pressed last time */ + is_pressed = regval & button->mask; + was_pressed = dev->button_polling_last_values[i] + & button->mask; + if (button->inverted) { + is_pressed = !is_pressed; + was_pressed = !was_pressed; + } + /* Clear button state (if needed) */ + if (is_pressed && button->reg_clearing) + em28xx_write_reg(dev, button->reg_clearing, + (~regval & button->mask) + | (regval & ~button->mask)); /* Handle button state */ - if (!pressed) { + if (!is_pressed || was_pressed) { j++; continue; } @@ -518,14 +527,11 @@ static void em28xx_query_buttons(struct work_struct *work) default: WARN_ONCE(1, "BUG: unhandled button role."); } - /* Clear button state (if needed) */ - if (button->reg_clearing) - em28xx_write_reg(dev, button->reg_clearing, - (~regval & button->mask) - | (regval & ~button->mask)); /* Next button */ j++; } + /* Save current value for comparison during the next polling */ + dev->button_polling_last_values[i] = regval; } /* Schedule next poll */ schedule_delayed_work(&dev->buttons_query_work, @@ -611,6 +617,8 @@ static void em28xx_init_buttons(struct em28xx *dev) /* Start polling */ if (dev->num_button_polling_addresses) { + memset(dev->button_polling_last_values, 0, + EM28XX_NUM_BUTTON_ADDRESSES_MAX); INIT_DELAYED_WORK(&dev->buttons_query_work, em28xx_query_buttons); schedule_delayed_work(&dev->buttons_query_work, diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index e185d00e9044..df828c68ef44 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -669,6 +669,7 @@ struct em28xx { /* Button state polling */ struct delayed_work buttons_query_work; u8 button_polling_addresses[EM28XX_NUM_BUTTON_ADDRESSES_MAX]; + u8 button_polling_last_values[EM28XX_NUM_BUTTON_ADDRESSES_MAX]; u8 num_button_polling_addresses; /* Snapshot button input device */ char snapshot_button_path[30]; /* path of the input dev */ -- cgit v1.2.3 From 6b8a3170c9984be58e50e23c78e2eb7833f33c4c Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 1 Dec 2013 18:06:55 -0300 Subject: [media] em28xx: prepare for supporting multiple LEDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a LED role and store all LEDs in an array. Also provide a helper function to retrieve a specific LED. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 31 ++++++++++++++++++++++++------- drivers/media/usb/em28xx/em28xx.h | 10 +++++++++- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 31d6ab2555f2..4a8179aafc4d 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -600,6 +600,22 @@ int em28xx_colorlevels_set_default(struct em28xx *dev) return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00); } +const struct em28xx_led *em28xx_find_led(struct em28xx *dev, + enum em28xx_led_role role) +{ + if (dev->board.leds) { + u8 k = 0; + while (dev->board.leds[k].role >= 0 && + dev->board.leds[k].role < EM28XX_NUM_LED_ROLES) { + if (dev->board.leds[k].role == role) + return &dev->board.leds[k]; + k++; + } + } + return NULL; +} +EXPORT_SYMBOL_GPL(em28xx_find_led); + int em28xx_capture_start(struct em28xx *dev, int start) { int rc; @@ -645,13 +661,14 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; /* Switch (explicitly controlled) analog capturing LED on/off */ - if ((dev->mode == EM28XX_ANALOG_MODE) - && dev->board.analog_capturing_led) { - struct em28xx_led *led = dev->board.analog_capturing_led; - em28xx_write_reg_bits(dev, led->gpio_reg, - (!start ^ led->inverted) ? - ~led->gpio_mask : led->gpio_mask, - led->gpio_mask); + if (dev->mode == EM28XX_ANALOG_MODE) { + const struct em28xx_led *led; + led = em28xx_find_led(dev, EM28XX_LED_ANALOG_CAPTURING); + if (led) + em28xx_write_reg_bits(dev, led->gpio_reg, + (!start ^ led->inverted) ? + ~led->gpio_mask : led->gpio_mask, + led->gpio_mask); } return rc; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index df828c68ef44..f60f236a245f 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -377,7 +377,13 @@ enum em28xx_adecoder { EM28XX_TVAUDIO, }; +enum em28xx_led_role { + EM28XX_LED_ANALOG_CAPTURING = 0, + EM28XX_NUM_LED_ROLES, /* must be the last */ +}; + struct em28xx_led { + enum em28xx_led_role role; u8 gpio_reg; u8 gpio_mask; bool inverted; @@ -433,7 +439,7 @@ struct em28xx_board { char *ir_codes; /* LEDs that need to be controlled explicitly */ - struct em28xx_led *analog_capturing_led; + struct em28xx_led *leds; /* Buttons */ struct em28xx_button *buttons; @@ -711,6 +717,8 @@ int em28xx_audio_analog_set(struct em28xx *dev); int em28xx_audio_setup(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev); +const struct em28xx_led *em28xx_find_led(struct em28xx *dev, + enum em28xx_led_role role); int em28xx_capture_start(struct em28xx *dev, int start); int em28xx_vbi_supported(struct em28xx *dev); int em28xx_set_outfmt(struct em28xx *dev); -- cgit v1.2.3 From 6063d07785b7059d276cb1a39c76186804f5938e Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 1 Dec 2013 18:06:56 -0300 Subject: [media] em28xx: add support for illumination button and LED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SpeedLink VAD Laplace webcam is equipped with an illumination button and an illumination LED. When the button is pressed, the driver must toggle the LED state via the corresponding GPO port. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 19 +++++++++++++++++++ drivers/media/usb/em28xx/em28xx-input.c | 19 ++++++++++++++++++- drivers/media/usb/em28xx/em28xx.h | 3 +++ 3 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 4a8179aafc4d..fc8254035278 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -225,6 +225,25 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, } EXPORT_SYMBOL_GPL(em28xx_write_reg_bits); +/* + * em28xx_toggle_reg_bits() + * toggles/inverts the bits (specified by bitmask) of a register + */ +int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask) +{ + int oldval; + u8 newval; + + oldval = em28xx_read_reg(dev, reg); + if (oldval < 0) + return oldval; + + newval = (~oldval & bitmask) | (oldval & ~bitmask); + + return em28xx_write_reg(dev, reg, newval); +} +EXPORT_SYMBOL_GPL(em28xx_toggle_reg_bits); + /* * em28xx_is_ac97_ready() * Checks if ac97 is ready diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index ebc538730e07..e0acc92f0dfd 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -480,6 +480,7 @@ static void em28xx_query_buttons(struct work_struct *work) u8 i, j; int regval; bool is_pressed, was_pressed; + const struct em28xx_led *led; /* Poll and evaluate all addresses */ for (i = 0; i < dev->num_button_polling_addresses; i++) { @@ -524,6 +525,15 @@ static void em28xx_query_buttons(struct work_struct *work) input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, 0); break; + case EM28XX_BUTTON_ILLUMINATION: + led = em28xx_find_led(dev, + EM28XX_LED_ILLUMINATION); + /* Switch illumination LED on/off */ + if (led) + em28xx_toggle_reg_bits(dev, + led->gpio_reg, + led->gpio_mask); + break; default: WARN_ONCE(1, "BUG: unhandled button role."); } @@ -600,10 +610,17 @@ static void em28xx_init_buttons(struct em28xx *dev) WARN_ONCE(1, "BUG: maximum number of button polling addresses exceeded."); addr_new = 0; } - /* Register input device (if needed) */ + /* Button role specific checks and actions */ if (button->role == EM28XX_BUTTON_SNAPSHOT) { + /* Register input device */ if (em28xx_register_snapshot_button(dev) < 0) addr_new = 0; + } else if (button->role == EM28XX_BUTTON_ILLUMINATION) { + /* Check sanity */ + if (!em28xx_find_led(dev, EM28XX_LED_ILLUMINATION)) { + em28xx_errdev("BUG: illumination button defined, but no illumination LED.\n"); + addr_new = 0; + } } /* Add read address to list of polling addresses */ if (addr_new) { diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index f60f236a245f..43e29683eb6a 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -379,6 +379,7 @@ enum em28xx_adecoder { enum em28xx_led_role { EM28XX_LED_ANALOG_CAPTURING = 0, + EM28XX_LED_ILLUMINATION, EM28XX_NUM_LED_ROLES, /* must be the last */ }; @@ -391,6 +392,7 @@ struct em28xx_led { enum em28xx_button_role { EM28XX_BUTTON_SNAPSHOT = 0, + EM28XX_BUTTON_ILLUMINATION, EM28XX_NUM_BUTTON_ROLES, /* must be the last */ }; @@ -709,6 +711,7 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, u8 bitmask); +int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask); int em28xx_read_ac97(struct em28xx *dev, u8 reg); int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); -- cgit v1.2.3 From 0c37e736cb869a3a7cc95a2486be73ffc1e1ee7d Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 1 Dec 2013 18:06:57 -0300 Subject: [media] em28xx: add support for the SpeedLink Vicious And Devine Laplace webcams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SpeedLink Vicious And Devine Laplace webcam is using an EM2765 bridge and an OV2640 sensor. It has a built-in microphone (USB standard device class) and provides 3 buttons (snapshot, illumination, mute) and 2 LEDs (capturing/mute and illumination/flash). It is also equipped with an eeprom. The device is available in two colors: white (1ae7:9003) and black (1ae7:9004). For further details see http://linuxtv.org/wiki/index.php/VAD_Laplace. Please note the following limitations that need to be addressed later: - resolution limited to 640x480 (sensor supports 1600x1200) - picture quality needs to be improved - AV-mute button doesn't work yet Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 72 +++++++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx.h | 1 + 2 files changed, 73 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ebb112c17109..64543098e8a6 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -412,6 +412,21 @@ static struct em28xx_reg_seq pctv_520e[] = { { -1, -1, -1, -1}, }; +/* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam + * reg 0x80/0x84: + * GPIO_0: capturing LED, 0=on, 1=off + * GPIO_2: AV mute button, 0=pressed, 1=unpressed + * GPIO 3: illumination button, 0=pressed, 1=unpressed + * GPIO_6: illumination/flash LED, 0=on, 1=off + * reg 0x81/0x85: + * GPIO_7: snapshot button, 0=pressed, 1=unpressed + */ +static struct em28xx_reg_seq speedlink_vad_laplace_reg_seq[] = { + {EM2820_R08_GPIO_CTRL, 0xf7, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xb2, 10}, + { -1, -1, -1, -1}, +}; + /* * Button definitions */ @@ -426,6 +441,41 @@ static struct em28xx_button std_snapshot_button[] = { {-1, 0, 0, 0, 0}, }; +static struct em28xx_button speedlink_vad_laplace_buttons[] = { + { + .role = EM28XX_BUTTON_SNAPSHOT, + .reg_r = EM2874_R85_GPIO_P1_STATE, + .mask = 0x80, + .inverted = 1, + }, + { + .role = EM28XX_BUTTON_ILLUMINATION, + .reg_r = EM2874_R84_GPIO_P0_STATE, + .mask = 0x08, + .inverted = 1, + }, + {-1, 0, 0, 0, 0}, +}; + +/* + * LED definitions + */ +static struct em28xx_led speedlink_vad_laplace_leds[] = { + { + .role = EM28XX_LED_ANALOG_CAPTURING, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = 0x01, + .inverted = 1, + }, + { + .role = EM28XX_LED_ILLUMINATION, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = 0x40, + .inverted = 1, + }, + {-1, 0, 0, 0}, +}; + /* * Board definitions */ @@ -2057,6 +2107,24 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .def_i2c_bus = 1, }, + /* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam + * Empia EM2765 + OmniVision OV2640 */ + [EM2765_BOARD_SPEEDLINK_VAD_LAPLACE] = { + .name = "SpeedLink Vicious And Devine Laplace webcam", + .xclk = EM28XX_XCLK_FREQUENCY_24MHZ, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ, + .def_i2c_bus = 1, + .tuner_type = TUNER_ABSENT, + .is_webcam = 1, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .amux = EM28XX_AMUX_VIDEO, + .gpio = speedlink_vad_laplace_reg_seq, + } }, + .buttons = speedlink_vad_laplace_buttons, + .leds = speedlink_vad_laplace_leds, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -2222,6 +2290,10 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2884_BOARD_PCTV_520E }, { USB_DEVICE(0x1b80, 0xe1cc), .driver_info = EM2874_BOARD_DELOCK_61959 }, + { USB_DEVICE(0x1ae7, 0x9003), + .driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE }, + { USB_DEVICE(0x1ae7, 0x9004), + .driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 43e29683eb6a..6e26fba094c8 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -132,6 +132,7 @@ #define EM2884_BOARD_C3TECH_DIGITAL_DUO 88 #define EM2874_BOARD_DELOCK_61959 89 #define EM2874_BOARD_KWORLD_UB435Q_V2 90 +#define EM2765_BOARD_SPEEDLINK_VAD_LAPLACE 91 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From f1b84d365af6d5ce1898fb7956e2053db14cc96e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 2 Dec 2013 20:15:04 -0300 Subject: [media] media: pci: remove DEFINE_PCI_DEVICE_TABLE macro Don't use DEFINE_PCI_DEVICE_TABLE macro, because this macro is not preferred. Signed-off-by: Jingoo Han Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/cx25821-alsa.c | 2 +- drivers/media/pci/cx25821/cx25821-core.c | 2 +- drivers/media/pci/sta2x11/sta2x11_vip.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 6e91e84d6bf9..b1e08c3e55cd 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -618,7 +618,7 @@ static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device, * Only boards with eeprom and byte 1 at eeprom=1 have it */ -static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = { +static const struct pci_device_id cx25821_audio_pci_tbl[] = { {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,} }; diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index b762c5b2ca10..e81173c41e5a 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -1361,7 +1361,7 @@ static void cx25821_finidev(struct pci_dev *pci_dev) kfree(dev); } -static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = { +static const struct pci_device_id cx25821_pci_tbl[] = { { /* CX25821 Athena */ .vendor = 0x14f1, diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 77edc113e485..e5cfb6cfa18d 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -1303,7 +1303,7 @@ static int sta2x11_vip_resume(struct pci_dev *pdev) #endif -static DEFINE_PCI_DEVICE_TABLE(sta2x11_vip_pci_tbl) = { +static const struct pci_device_id sta2x11_vip_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIP)}, {0,} }; -- cgit v1.2.3 From 09ca27579ee5a1b6f537b82165080b85c1febac8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 20 Nov 2013 10:15:11 +0800 Subject: clocksource: time-efm32: Select CLKSRC_MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The time-efm32 driver uses the clocksource MMIO functions. Thus it needs to select CLKSRC_MMIO in Kconfig. Signed-off-by: Axel Lin Signed-off-by: Daniel Lezcano Acked-by: Uwe Kleine-König --- drivers/clocksource/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 5c07a56962db..634c4d6dd45a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -75,6 +75,7 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK config CLKSRC_EFM32 bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32 depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST) + select CLKSRC_MMIO default ARCH_EFM32 help Support to use the timers of EFM32 SoCs as clock source and clock -- cgit v1.2.3 From c813eff078588733a3d1a46c033c2d59d66a263b Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 26 Nov 2013 18:20:14 -0300 Subject: clocksource: armada-370-xp: Register sched_clock after the counter reset This commit registers the sched_clock _after_ the counter reset (instead of before). This removes the timestamp 'jump' in kernel log messages. Before this change: [ 0.000000] sched_clock: 32 bits at 25MHz, resolution 40ns, wraps every 171798691800ns [ 0.000000] Initializing Coherency fabric [ 0.000000] Aurora cache controller enabled [ 0.000000] l2x0: 16 ways, CACHE_ID 0x00000100, AUX_CTRL 0x1a696b12, Cache size: 1024 kB [ 163.507447] Calibrating delay loop... 1325.05 BogoMIPS (lpj=662528) [ 163.521419] pid_max: default: 32768 minimum: 301 [ 163.526185] Mount-cache hash table entries: 512 [ 163.531095] CPU: Testing write buffer coherency: ok After this change: [ 0.000000] sched_clock: 32 bits at 25MHz, resolution 40ns, wraps every 171798691800ns [ 0.000000] Initializing Coherency fabric [ 0.000000] Aurora cache controller enabled [ 0.000000] l2x0: 16 ways, CACHE_ID 0x00000100, AUX_CTRL 0x1a696b12, Cache size: 1024 kB [ 0.016849] Calibrating delay loop... 1325.05 BogoMIPS (lpj=662528) [ 0.030820] pid_max: default: 32768 minimum: 301 [ 0.035588] Mount-cache hash table entries: 512 [ 0.040500] CPU: Testing write buffer coherency: ok Signed-off-by: Ezequiel Garcia Signed-off-by: Daniel Lezcano Acked-by: Jason Cooper --- drivers/clocksource/time-armada-370-xp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index d8e47e502785..4e7f6802e840 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -255,11 +255,6 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; - /* - * Set scale and timer for sched_clock. - */ - sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); - /* * Setup free-running clocksource timer (interrupts * disabled). @@ -270,6 +265,11 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT)); + /* + * Set scale and timer for sched_clock. + */ + sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); + clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "armada_370_xp_clocksource", timer_clk, 300, 32, clocksource_mmio_readl_down); -- cgit v1.2.3 From 4c4b053235fa73db1ea241aa5a6b021afb0ed8db Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Sat, 19 Oct 2013 00:49:48 +0200 Subject: clocksource: clksrc-of: Do not drop unheld reference on device node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When booting a recent kernel on ARM with OF_DYNAMIC enabled, the kernel warns about the following: [ 0.000000] ERROR: Bad of_node_put() on /timer@50004600 [ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.12.0-rc5-next-20131017-00077-gedfd827-dirty #406 [ 0.000000] [] (unwind_backtrace+0x0/0xf4) from [] (show_stack+0x10/0x14) [ 0.000000] [] (show_stack+0x10/0x14) from [] (dump_stack+0x9c/0xc8) [ 0.000000] [] (dump_stack+0x9c/0xc8) from [] (of_node_release+0x90/0x9c) [ 0.000000] [] (of_node_release+0x90/0x9c) from [] (of_find_matching_node_and_match+0x78/0xb4) [ 0.000000] [] (of_find_matching_node_and_match+0x78/0xb4) from [] (clocksource_of_init+0x60/0x70) [ 0.000000] [] (clocksource_of_init+0x60/0x70) from [] (start_kernel+0x1f4/0x33c) [ 0.000000] [] (start_kernel+0x1f4/0x33c) from [<80008074>] (0x80008074) This is caused by clocksource_of_init() dropping a reference on the device node that it never took. The reference taken by the loop is implicitly dropped on subsequent iterations. See the implementation of and the comment on top of the of_find_matching_node_and_match() function for reference (no pun intended). Signed-off-by: Thierry Reding Signed-off-by: Daniel Lezcano Cc: Uwe Kleine-König --- drivers/clocksource/clksrc-of.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c index 35639cf4e5a2..b9ddd9e3a2f5 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-of.c @@ -35,6 +35,5 @@ void __init clocksource_of_init(void) init_func = match->data; init_func(np); - of_node_put(np); } } -- cgit v1.2.3 From 6db50bb67598668c525f12e2f7191f5d03ca46f2 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 2 Dec 2013 09:29:35 +0000 Subject: clocksource: sunxi: Stop timer from ticking before enabling interrupts The sun4i timer can still be ticking when we enable the interrupt. If another timer is actually used (A7 architected timer, for example), odds are that the interrupt will eventually fire with the event_handler pointer being NULL. The obvious fix it to stop the timer before registering the interrupt. Observed and tested on sun7i (cubietruck). Cc: Daniel Lezcano Acked-by: Maxime Ripard Signed-off-by: Marc Zyngier Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 2fb4695a28d8..a4f6119aafd8 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -179,6 +179,9 @@ static void __init sun4i_timer_init(struct device_node *node) writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), timer_base + TIMER_CTL_REG(0)); + /* Make sure timer is stopped before playing with interrupts */ + sun4i_clkevt_time_stop(0); + ret = setup_irq(irq, &sun4i_timer_irq); if (ret) pr_warn("failed to setup irq %d\n", irq); -- cgit v1.2.3 From fe104a9b61ac8856e7973058b71f33224a7d5ed7 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 3 Dec 2013 08:51:12 -0300 Subject: [media] v4l: ti-vpe: Fix the data_type value for UYVY VPDMA format The data_type value to be programmed in the data descriptors to fetch/write a UYVY buffer was not mentioned correctly in the older DRA7x documentation. This caused VPE to fail with UYVY color formats. Update the data_type value to fix functionality when UYVY format is used. Signed-off-by: Archit Taneja Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpdma_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpdma_priv.h b/drivers/media/platform/ti-vpe/vpdma_priv.h index f0e9a8038c1b..c1a6ce1884f3 100644 --- a/drivers/media/platform/ti-vpe/vpdma_priv.h +++ b/drivers/media/platform/ti-vpe/vpdma_priv.h @@ -78,7 +78,7 @@ #define DATA_TYPE_C420 0x6 #define DATA_TYPE_YC422 0x7 #define DATA_TYPE_YC444 0x8 -#define DATA_TYPE_CY422 0x23 +#define DATA_TYPE_CY422 0x27 #define DATA_TYPE_RGB16_565 0x0 #define DATA_TYPE_ARGB_1555 0x1 -- cgit v1.2.3 From 85dc6ee1237c8a4a7742e6abab96a20389b7d682 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 10 Dec 2013 19:49:18 +0100 Subject: clocksource: dw_apb_timer_of: Fix read_sched_clock The read_sched_clock should return the ~value because the clock is a countdown implementation. read_sched_clock() should be the same as __apbt_read_clocksource(). Signed-off-by: Dinh Nguyen Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer_of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index 45ba8aecc729..b29d7cdadd82 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -108,7 +108,7 @@ static void __init add_clocksource(struct device_node *source_timer) static u64 read_sched_clock(void) { - return __raw_readl(sched_io_base); + return ~__raw_readl(sched_io_base); } static const struct of_device_id sptimer_ids[] __initconst = { -- cgit v1.2.3 From 9ab4727c1d41e50b67aecde4bf11879560a3ca78 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 10 Dec 2013 19:49:18 +0100 Subject: clocksource: dw_apb_timer_of: Fix support for dts binding "snps,dw-apb-timer" In commit 620f5e1cbf (dts: Rename DW APB timer compatible strings), both "snps,dw-apb-timer-sp" and "snps,dw-apb-timer-osc" were deprecated in place of "snps,dw-apb-timer". But the driver also needs to be udpated in order to support this new binding "snps,dw-apb-timer". Signed-off-by: Dinh Nguyen Signed-off-by: Daniel Lezcano --- drivers/clocksource/dw_apb_timer_of.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index b29d7cdadd82..2a2ea2717f3a 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -113,7 +113,6 @@ static u64 read_sched_clock(void) static const struct of_device_id sptimer_ids[] __initconst = { { .compatible = "picochip,pc3x2-rtc" }, - { .compatible = "snps,dw-apb-timer-sp" }, { /* Sentinel */ }, }; @@ -151,4 +150,6 @@ static void __init dw_apb_timer_init(struct device_node *timer) num_called++; } CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init); -CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init); +CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init); +CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init); +CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init); -- cgit v1.2.3 From a51cd8f5d0a21ccc8d313a9992293ab2541b40a8 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 3 Dec 2013 08:51:13 -0300 Subject: [media] v4l: ti-vpe: make sure VPDMA line stride constraints are met When VPDMA fetches or writes to an image buffer, the line stride must be a multiple of 16 bytes. If it isn't, VPDMA HW will write/fetch until the next 16 byte boundry. This causes VPE to work incorrectly for source or destination widths which don't satisfy the above alignment requirement. In order to prevent this, we now make sure that when we set pix format for the input and output buffers, the VPE source and destination image line strides are 16 byte aligned. Also, the motion vector buffers for the de-interlacer are allocated in such a way that it ensures the same alignment. Signed-off-by: Archit Taneja Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/vpdma.c | 4 +-- drivers/media/platform/ti-vpe/vpdma.h | 5 +++- drivers/media/platform/ti-vpe/vpe.c | 53 ++++++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/ti-vpe/vpdma.c b/drivers/media/platform/ti-vpe/vpdma.c index af0a5ffcaa98..f97253f6699f 100644 --- a/drivers/media/platform/ti-vpe/vpdma.c +++ b/drivers/media/platform/ti-vpe/vpdma.c @@ -602,7 +602,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, if (fmt->data_type == DATA_TYPE_C420) depth = 8; - stride = (depth * c_rect->width) >> 3; + stride = ALIGN((depth * c_rect->width) >> 3, VPDMA_STRIDE_ALIGN); dma_addr += (c_rect->left * depth) >> 3; dtd = list->next; @@ -655,7 +655,7 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, depth = 8; } - stride = (depth * c_rect->width) >> 3; + stride = ALIGN((depth * c_rect->width) >> 3, VPDMA_STRIDE_ALIGN); dma_addr += (c_rect->left * depth) >> 3; dtd = list->next; diff --git a/drivers/media/platform/ti-vpe/vpdma.h b/drivers/media/platform/ti-vpe/vpdma.h index eaa2a71a5db9..62dd14305e81 100644 --- a/drivers/media/platform/ti-vpe/vpdma.h +++ b/drivers/media/platform/ti-vpe/vpdma.h @@ -45,7 +45,10 @@ struct vpdma_data_format { }; #define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */ - +#define VPDMA_STRIDE_ALIGN 16 /* + * line stride of source and dest + * buffers should be 16 byte aligned + */ #define VPDMA_DTD_DESC_SIZE 32 /* 8 words */ #define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */ diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index f949ef57a54c..669777052a16 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -54,10 +55,6 @@ /* required alignments */ #define S_ALIGN 0 /* multiple of 1 */ #define H_ALIGN 1 /* multiple of 2 */ -#define W_ALIGN 1 /* multiple of 2 */ - -/* multiple of 128 bits, line stride, 16 bytes */ -#define L_ALIGN 4 /* flags that indicate a format can be used for capture/output */ #define VPE_FMT_TYPE_CAPTURE (1 << 0) @@ -780,12 +777,21 @@ static int set_srcdst_params(struct vpe_ctx *ctx) if ((s_q_data->flags & Q_DATA_INTERLACED) && !(d_q_data->flags & Q_DATA_INTERLACED)) { + int bytes_per_line; const struct vpdma_data_format *mv = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; ctx->deinterlacing = 1; - mv_buf_size = - (s_q_data->width * s_q_data->height * mv->depth) >> 3; + /* + * we make sure that the source image has a 16 byte aligned + * stride, we need to do the same for the motion vector buffer + * by aligning it's stride to the next 16 byte boundry. this + * extra space will not be used by the de-interlacer, but will + * ensure that vpdma operates correctly + */ + bytes_per_line = ALIGN((s_q_data->width * mv->depth) >> 3, + VPDMA_STRIDE_ALIGN); + mv_buf_size = bytes_per_line * s_q_data->height; } else { ctx->deinterlacing = 0; mv_buf_size = 0; @@ -1352,7 +1358,8 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; struct v4l2_plane_pix_format *plane_fmt; - int i; + unsigned int w_align; + int i, depth, depth_bytes; if (!fmt || !(fmt->types & type)) { vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n", @@ -1363,7 +1370,31 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE) pix->field = V4L2_FIELD_NONE; - v4l_bound_align_image(&pix->width, MIN_W, MAX_W, W_ALIGN, + depth = fmt->vpdma_fmt[VPE_LUMA]->depth; + + /* + * the line stride should 16 byte aligned for VPDMA to work, based on + * the bytes per pixel, figure out how much the width should be aligned + * to make sure line stride is 16 byte aligned + */ + depth_bytes = depth >> 3; + + if (depth_bytes == 3) + /* + * if bpp is 3(as in some RGB formats), the pixel width doesn't + * really help in ensuring line stride is 16 byte aligned + */ + w_align = 4; + else + /* + * for the remainder bpp(4, 2 and 1), the pixel width alignment + * can ensure a line stride alignment of 16 bytes. For example, + * if bpp is 2, then the line stride can be 16 byte aligned if + * the width is 8 byte aligned + */ + w_align = order_base_2(VPDMA_DESC_ALIGN / depth_bytes); + + v4l_bound_align_image(&pix->width, MIN_W, MAX_W, w_align, &pix->height, MIN_H, MAX_H, H_ALIGN, S_ALIGN); @@ -1383,15 +1414,11 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, } for (i = 0; i < pix->num_planes; i++) { - int depth; - plane_fmt = &pix->plane_fmt[i]; depth = fmt->vpdma_fmt[i]->depth; if (i == VPE_LUMA) - plane_fmt->bytesperline = - round_up((pix->width * depth) >> 3, - 1 << L_ALIGN); + plane_fmt->bytesperline = (pix->width * depth) >> 3; else plane_fmt->bytesperline = pix->width; -- cgit v1.2.3 From 8212d56329b223a106d3d4f7dda95f571b1fa044 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2013 14:06:45 +0200 Subject: drm/i915: Move VLV PHY CRI clock enable into intel_init_dpio() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CRI clock is related to the display PHY, so the setup belongs in intel_init_dpio(). Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 596ad09f0e51..10a803f69360 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1367,6 +1367,10 @@ static void intel_init_dpio(struct drm_device *dev) if (!IS_VALLEYVIEW(dev)) return; + /* Enable the CRI clock source so we can get at the display */ + I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | + DPLL_INTEGRATED_CRI_CLK_VLV); + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; /* * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - @@ -10788,17 +10792,10 @@ static void i915_disable_vga(struct drm_device *dev) void intel_modeset_init_hw(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - intel_prepare_ddi(dev); intel_init_clock_gating(dev); - /* Enable the CRI clock source so we can get at the display */ - if (IS_VALLEYVIEW(dev)) - I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | - DPLL_INTEGRATED_CRI_CLK_VLV); - intel_init_dpio(dev); mutex_lock(&dev->struct_mutex); -- cgit v1.2.3 From 7a57be873ae02aa956f453450a6903c6c8970896 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Tue, 10 Dec 2013 22:20:22 +0400 Subject: pinctrl: sh-pfc: pfc-r8a7790: Rename VIN pin groups This drops superfluous "signal" word from the pin group names and renames data_enable group to clkenb as in the h/w manual. Signed-off-by: Valentine Barshak Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 1375709422c7..5a45ab0877e5 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -3278,28 +3278,28 @@ static const unsigned int vin0_data_b_mux[] = { VI0_DATA3_VI0_B3_MARK, VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, }; -static const unsigned int vin0_hsync_signal_pins[] = { +static const unsigned int vin0_hsync_pins[] = { RCAR_GP_PIN(0, 12), }; -static const unsigned int vin0_hsync_signal_mux[] = { +static const unsigned int vin0_hsync_mux[] = { VI0_HSYNC_N_MARK, }; -static const unsigned int vin0_vsync_signal_pins[] = { +static const unsigned int vin0_vsync_pins[] = { RCAR_GP_PIN(0, 13), }; -static const unsigned int vin0_vsync_signal_mux[] = { +static const unsigned int vin0_vsync_mux[] = { VI0_VSYNC_N_MARK, }; -static const unsigned int vin0_field_signal_pins[] = { +static const unsigned int vin0_field_pins[] = { RCAR_GP_PIN(0, 15), }; -static const unsigned int vin0_field_signal_mux[] = { +static const unsigned int vin0_field_mux[] = { VI0_FIELD_MARK, }; -static const unsigned int vin0_data_enable_pins[] = { +static const unsigned int vin0_clkenb_pins[] = { RCAR_GP_PIN(0, 14), }; -static const unsigned int vin0_data_enable_mux[] = { +static const unsigned int vin0_clkenb_mux[] = { VI0_CLKENB_MARK, }; static const unsigned int vin0_clk_pins[] = { @@ -3535,10 +3535,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(vin0_data_g), SH_PFC_PIN_GROUP(vin0_data_r), SH_PFC_PIN_GROUP(vin0_data_b), - SH_PFC_PIN_GROUP(vin0_hsync_signal), - SH_PFC_PIN_GROUP(vin0_vsync_signal), - SH_PFC_PIN_GROUP(vin0_field_signal), - SH_PFC_PIN_GROUP(vin0_data_enable), + SH_PFC_PIN_GROUP(vin0_hsync), + SH_PFC_PIN_GROUP(vin0_vsync), + SH_PFC_PIN_GROUP(vin0_field), + SH_PFC_PIN_GROUP(vin0_clkenb), SH_PFC_PIN_GROUP(vin0_clk), SH_PFC_PIN_GROUP(vin1_data), SH_PFC_PIN_GROUP(vin1_clk), @@ -3861,10 +3861,10 @@ static const char * const vin0_groups[] = { "vin0_data_g", "vin0_data_r", "vin0_data_b", - "vin0_hsync_signal", - "vin0_vsync_signal", - "vin0_field_signal", - "vin0_data_enable", + "vin0_hsync", + "vin0_vsync", + "vin0_field", + "vin0_clkenb", "vin0_clk", }; -- cgit v1.2.3 From a9e4c7bb466b34b19ca71ee7383ca23bd37a88c5 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Tue, 10 Dec 2013 22:20:23 +0400 Subject: pinctrl: sh-pfc: pfc-r8a7790: Group VIN0 HSYNC and VSYNC together This groups VIN0 HSYNC and VSYNC pins together since one cannot be used without another. Signed-off-by: Valentine Barshak Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 5a45ab0877e5..81ff4bf72264 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -3278,16 +3278,12 @@ static const unsigned int vin0_data_b_mux[] = { VI0_DATA3_VI0_B3_MARK, VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, }; -static const unsigned int vin0_hsync_pins[] = { - RCAR_GP_PIN(0, 12), +static const unsigned int vin0_sync_pins[] = { + RCAR_GP_PIN(0, 12), /* HSYNC */ + RCAR_GP_PIN(0, 13), /* VSYNC */ }; -static const unsigned int vin0_hsync_mux[] = { +static const unsigned int vin0_sync_mux[] = { VI0_HSYNC_N_MARK, -}; -static const unsigned int vin0_vsync_pins[] = { - RCAR_GP_PIN(0, 13), -}; -static const unsigned int vin0_vsync_mux[] = { VI0_VSYNC_N_MARK, }; static const unsigned int vin0_field_pins[] = { @@ -3535,8 +3531,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(vin0_data_g), SH_PFC_PIN_GROUP(vin0_data_r), SH_PFC_PIN_GROUP(vin0_data_b), - SH_PFC_PIN_GROUP(vin0_hsync), - SH_PFC_PIN_GROUP(vin0_vsync), + SH_PFC_PIN_GROUP(vin0_sync), SH_PFC_PIN_GROUP(vin0_field), SH_PFC_PIN_GROUP(vin0_clkenb), SH_PFC_PIN_GROUP(vin0_clk), @@ -3861,8 +3856,7 @@ static const char * const vin0_groups[] = { "vin0_data_g", "vin0_data_r", "vin0_data_b", - "vin0_hsync", - "vin0_vsync", + "vin0_sync", "vin0_field", "vin0_clkenb", "vin0_clk", -- cgit v1.2.3 From 64fe8abc7336e17f977bb38c4c261d24bfc5da17 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Tue, 10 Dec 2013 22:20:24 +0400 Subject: pinctrl: sh-pfc: pfc-r8a7790: Reorganize VIN0 data pins This reorganizes and renames VIN0 data pin groups to cover all possible configurations. There's total of eight data pin groups, one per each configuration. Most of the groups share the same pin/mux array. Only the 18-bit configuration needs a separate pin/mux array since in combines interleaved data pins. Signed-off-by: Valentine Barshak Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 125 ++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 81ff4bf72264..11e12d61de9b 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -3247,36 +3247,91 @@ static const unsigned int usb2_pins[] = { static const unsigned int usb2_mux[] = { USB2_PWEN_MARK, USB2_OVC_MARK, }; -/* - VIN0 ------------------------------------------------------------------- */ -static const unsigned int vin0_data_g_pins[] = { - RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10), - RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), - RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), -}; -static const unsigned int vin0_data_g_mux[] = { - VI0_G0_MARK, VI0_G1_MARK, VI0_G2_MARK, - VI0_G3_MARK, VI0_G4_MARK, VI0_G5_MARK, - VI0_G6_MARK, VI0_G7_MARK, + +union vin_data { + unsigned int data24[24]; + unsigned int data20[20]; + unsigned int data16[16]; + unsigned int data12[12]; + unsigned int data10[10]; + unsigned int data8[8]; + unsigned int data4[4]; }; -static const unsigned int vin0_data_r_pins[] = { - RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 6), - RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), - RCAR_GP_PIN(0, 26), RCAR_GP_PIN(1, 11), + +#define VIN_DATA_PIN_GROUP(n, s) \ + { \ + .name = #n#s, \ + .pins = n##_pins.data##s, \ + .mux = n##_mux.data##s, \ + .nr_pins = ARRAY_SIZE(n##_pins.data##s), \ + } + +/* - VIN0 ------------------------------------------------------------------- */ +static const union vin_data vin0_data_pins = { + .data24 = { + /* B */ + RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), + RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4), + RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6), + RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), + /* G */ + RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), + RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), + /* R */ + RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), + RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), + RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), + RCAR_GP_PIN(0, 26), RCAR_GP_PIN(1, 11), + }, }; -static const unsigned int vin0_data_r_mux[] = { - VI0_R0_MARK, VI0_R1_MARK, VI0_R2_MARK, - VI0_R3_MARK, VI0_R4_MARK, VI0_R5_MARK, - VI0_R6_MARK, VI0_R7_MARK, +static const union vin_data vin0_data_mux = { + .data24 = { + /* B */ + VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK, + VI0_DATA2_VI0_B2_MARK, VI0_DATA3_VI0_B3_MARK, + VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, + VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, + /* G */ + VI0_G0_MARK, VI0_G1_MARK, + VI0_G2_MARK, VI0_G3_MARK, + VI0_G4_MARK, VI0_G5_MARK, + VI0_G6_MARK, VI0_G7_MARK, + /* R */ + VI0_R0_MARK, VI0_R1_MARK, + VI0_R2_MARK, VI0_R3_MARK, + VI0_R4_MARK, VI0_R5_MARK, + VI0_R6_MARK, VI0_R7_MARK, + }, }; -static const unsigned int vin0_data_b_pins[] = { - RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3), - RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6), +static const unsigned int vin0_data18_pins[] = { + /* B */ + RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4), + RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), + /* G */ + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), + RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), + /* R */ + RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), + RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), + RCAR_GP_PIN(0, 26), RCAR_GP_PIN(1, 11), }; -static const unsigned int vin0_data_b_mux[] = { - VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK, VI0_DATA2_VI0_B2_MARK, - VI0_DATA3_VI0_B3_MARK, VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, +static const unsigned int vin0_data18_mux[] = { + /* B */ + VI0_DATA2_VI0_B2_MARK, VI0_DATA3_VI0_B3_MARK, + VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, + /* G */ + VI0_G2_MARK, VI0_G3_MARK, + VI0_G4_MARK, VI0_G5_MARK, + VI0_G6_MARK, VI0_G7_MARK, + /* R */ + VI0_R2_MARK, VI0_R3_MARK, + VI0_R4_MARK, VI0_R5_MARK, + VI0_R6_MARK, VI0_R7_MARK, }; static const unsigned int vin0_sync_pins[] = { RCAR_GP_PIN(0, 12), /* HSYNC */ @@ -3528,9 +3583,14 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(usb0), SH_PFC_PIN_GROUP(usb1), SH_PFC_PIN_GROUP(usb2), - SH_PFC_PIN_GROUP(vin0_data_g), - SH_PFC_PIN_GROUP(vin0_data_r), - SH_PFC_PIN_GROUP(vin0_data_b), + VIN_DATA_PIN_GROUP(vin0_data, 24), + VIN_DATA_PIN_GROUP(vin0_data, 20), + SH_PFC_PIN_GROUP(vin0_data18), + VIN_DATA_PIN_GROUP(vin0_data, 16), + VIN_DATA_PIN_GROUP(vin0_data, 12), + VIN_DATA_PIN_GROUP(vin0_data, 10), + VIN_DATA_PIN_GROUP(vin0_data, 8), + VIN_DATA_PIN_GROUP(vin0_data, 4), SH_PFC_PIN_GROUP(vin0_sync), SH_PFC_PIN_GROUP(vin0_field), SH_PFC_PIN_GROUP(vin0_clkenb), @@ -3853,9 +3913,14 @@ static const char * const usb2_groups[] = { }; static const char * const vin0_groups[] = { - "vin0_data_g", - "vin0_data_r", - "vin0_data_b", + "vin0_data24", + "vin0_data20", + "vin0_data18", + "vin0_data16", + "vin0_data12", + "vin0_data10", + "vin0_data8", + "vin0_data4", "vin0_sync", "vin0_field", "vin0_clkenb", -- cgit v1.2.3 From 317a03a9cb925a5566b852dff85f6aaa4aff7e3e Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Tue, 10 Dec 2013 22:20:25 +0400 Subject: pinctrl: sh-pfc: pfc-r8a7790: Add missing VIN1 pins Both VIN0 and VIN1 channels support identical input interfaces. Add missing VIN1 pins here and organize them in the same pin groups as VIN0. Signed-off-by: Valentine Barshak Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 112 ++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 11e12d61de9b..2194ea6374ca 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -3360,15 +3360,91 @@ static const unsigned int vin0_clk_mux[] = { VI0_CLK_MARK, }; /* - VIN1 ------------------------------------------------------------------- */ -static const unsigned int vin1_data_pins[] = { - RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 12), - RCAR_GP_PIN(2, 13), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), +static const union vin_data vin1_data_pins = { + .data24 = { + /* B */ + RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), + RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), + RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17), + /* G */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 15), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 12), + RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(0, 27), RCAR_GP_PIN(0, 28), + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 4), + RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), + RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 8), + }, +}; +static const union vin_data vin1_data_mux = { + .data24 = { + /* B */ + VI1_DATA0_VI1_B0_MARK, VI1_DATA1_VI1_B1_MARK, + VI1_DATA2_VI1_B2_MARK, VI1_DATA3_VI1_B3_MARK, + VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK, + VI1_DATA6_VI1_B6_MARK, VI1_DATA7_VI1_B7_MARK, + /* G */ + VI1_G0_MARK, VI1_G1_MARK, + VI1_G2_MARK, VI1_G3_MARK, + VI1_G4_MARK, VI1_G5_MARK, + VI1_G6_MARK, VI1_G7_MARK, + /* R */ + VI1_R0_MARK, VI1_R1_MARK, + VI1_R2_MARK, VI1_R3_MARK, + VI1_R4_MARK, VI1_R5_MARK, + VI1_R6_MARK, VI1_R7_MARK, + }, +}; +static const unsigned int vin1_data18_pins[] = { + /* B */ + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), + RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17), + /* G */ + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 12), + RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 4), + RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), + RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 8), }; -static const unsigned int vin1_data_mux[] = { - VI1_DATA0_VI1_B0_MARK, VI1_DATA1_VI1_B1_MARK, VI1_DATA2_VI1_B2_MARK, - VI1_DATA3_VI1_B3_MARK, VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK, +static const unsigned int vin1_data18_mux[] = { + /* B */ + VI1_DATA2_VI1_B2_MARK, VI1_DATA3_VI1_B3_MARK, + VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK, VI1_DATA6_VI1_B6_MARK, VI1_DATA7_VI1_B7_MARK, + /* G */ + VI1_G2_MARK, VI1_G3_MARK, + VI1_G4_MARK, VI1_G5_MARK, + VI1_G6_MARK, VI1_G7_MARK, + /* R */ + VI1_R2_MARK, VI1_R3_MARK, + VI1_R4_MARK, VI1_R5_MARK, + VI1_R6_MARK, VI1_R7_MARK, +}; +static const unsigned int vin1_sync_pins[] = { + RCAR_GP_PIN(1, 24), /* HSYNC */ + RCAR_GP_PIN(1, 25), /* VSYNC */ +}; +static const unsigned int vin1_sync_mux[] = { + VI1_HSYNC_N_MARK, + VI1_VSYNC_N_MARK, +}; +static const unsigned int vin1_field_pins[] = { + RCAR_GP_PIN(1, 13), +}; +static const unsigned int vin1_field_mux[] = { + VI1_FIELD_MARK, +}; +static const unsigned int vin1_clkenb_pins[] = { + RCAR_GP_PIN(1, 26), +}; +static const unsigned int vin1_clkenb_mux[] = { + VI1_CLKENB_MARK, }; static const unsigned int vin1_clk_pins[] = { RCAR_GP_PIN(2, 9), @@ -3595,7 +3671,17 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(vin0_field), SH_PFC_PIN_GROUP(vin0_clkenb), SH_PFC_PIN_GROUP(vin0_clk), - SH_PFC_PIN_GROUP(vin1_data), + VIN_DATA_PIN_GROUP(vin1_data, 24), + VIN_DATA_PIN_GROUP(vin1_data, 20), + SH_PFC_PIN_GROUP(vin1_data18), + VIN_DATA_PIN_GROUP(vin1_data, 16), + VIN_DATA_PIN_GROUP(vin1_data, 12), + VIN_DATA_PIN_GROUP(vin1_data, 10), + VIN_DATA_PIN_GROUP(vin1_data, 8), + VIN_DATA_PIN_GROUP(vin1_data, 4), + SH_PFC_PIN_GROUP(vin1_sync), + SH_PFC_PIN_GROUP(vin1_field), + SH_PFC_PIN_GROUP(vin1_clkenb), SH_PFC_PIN_GROUP(vin1_clk), }; @@ -3928,7 +4014,17 @@ static const char * const vin0_groups[] = { }; static const char * const vin1_groups[] = { - "vin1_data", + "vin1_data24", + "vin1_data20", + "vin1_data18", + "vin1_data16", + "vin1_data12", + "vin1_data10", + "vin1_data8", + "vin1_data4", + "vin1_sync", + "vin1_field", + "vin1_clkenb", "vin1_clk", }; -- cgit v1.2.3 From 054d4259091a52be0d8ed3e3febf07cf263d294d Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Tue, 10 Dec 2013 22:20:26 +0400 Subject: pinctrl: sh-pfc: pfc-r8a7790: Add VIN2 and VIN3 pins There are VIN2 and VIN3 channels available on the R8A7790 SoC. VIN2 supports 4/8/16/18/24-bit data, while VIN3 supports 8-bit. Add both here, covering all possible data pin configurations. Signed-off-by: Valentine Barshak Signed-off-by: Laurent Pinchart --- drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 168 +++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 2194ea6374ca..293a51a7434e 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -3452,6 +3452,138 @@ static const unsigned int vin1_clk_pins[] = { static const unsigned int vin1_clk_mux[] = { VI1_CLK_MARK, }; +/* - VIN2 ----------------------------------------------------------------- */ +static const union vin_data vin2_data_pins = { + .data24 = { + /* B */ + RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13), + RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15), + /* G */ + RCAR_GP_PIN(0, 27), RCAR_GP_PIN(0, 28), + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 10), + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 5), + RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 13), + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 15), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 24), + }, +}; +static const union vin_data vin2_data_mux = { + .data24 = { + /* B */ + VI2_DATA0_VI2_B0_MARK, VI2_DATA1_VI2_B1_MARK, + VI2_DATA2_VI2_B2_MARK, VI2_DATA3_VI2_B3_MARK, + VI2_DATA4_VI2_B4_MARK, VI2_DATA5_VI2_B5_MARK, + VI2_DATA6_VI2_B6_MARK, VI2_DATA7_VI2_B7_MARK, + /* G */ + VI2_G0_MARK, VI2_G1_MARK, + VI2_G2_MARK, VI2_G3_MARK, + VI2_G4_MARK, VI2_G5_MARK, + VI2_G6_MARK, VI2_G7_MARK, + /* R */ + VI2_R0_MARK, VI2_R1_MARK, + VI2_R2_MARK, VI2_R3_MARK, + VI2_R4_MARK, VI2_R5_MARK, + VI2_R6_MARK, VI2_R7_MARK, + }, +}; +static const unsigned int vin2_data18_pins[] = { + /* B */ + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13), + RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15), + /* G */ + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 10), + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 5), + RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 15), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 24), +}; +static const unsigned int vin2_data18_mux[] = { + /* B */ + VI2_DATA2_VI2_B2_MARK, VI2_DATA3_VI2_B3_MARK, + VI2_DATA4_VI2_B4_MARK, VI2_DATA5_VI2_B5_MARK, + VI2_DATA6_VI2_B6_MARK, VI2_DATA7_VI2_B7_MARK, + /* G */ + VI2_G2_MARK, VI2_G3_MARK, + VI2_G4_MARK, VI2_G5_MARK, + VI2_G6_MARK, VI2_G7_MARK, + /* R */ + VI2_R2_MARK, VI2_R3_MARK, + VI2_R4_MARK, VI2_R5_MARK, + VI2_R6_MARK, VI2_R7_MARK, +}; +static const unsigned int vin2_sync_pins[] = { + RCAR_GP_PIN(1, 16), /* HSYNC */ + RCAR_GP_PIN(1, 21), /* VSYNC */ +}; +static const unsigned int vin2_sync_mux[] = { + VI2_HSYNC_N_MARK, + VI2_VSYNC_N_MARK, +}; +static const unsigned int vin2_field_pins[] = { + RCAR_GP_PIN(1, 9), +}; +static const unsigned int vin2_field_mux[] = { + VI2_FIELD_MARK, +}; +static const unsigned int vin2_clkenb_pins[] = { + RCAR_GP_PIN(1, 8), +}; +static const unsigned int vin2_clkenb_mux[] = { + VI2_CLKENB_MARK, +}; +static const unsigned int vin2_clk_pins[] = { + RCAR_GP_PIN(1, 11), +}; +static const unsigned int vin2_clk_mux[] = { + VI2_CLK_MARK, +}; +/* - VIN3 ----------------------------------------------------------------- */ +static const unsigned int vin3_data8_pins[] = { + RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), + RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), + RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), + RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), +}; +static const unsigned int vin3_data8_mux[] = { + VI3_DATA0_MARK, VI3_DATA1_MARK, + VI3_DATA2_MARK, VI3_DATA3_MARK, + VI3_DATA4_MARK, VI3_DATA5_MARK, + VI3_DATA6_MARK, VI3_DATA7_MARK, +}; +static const unsigned int vin3_sync_pins[] = { + RCAR_GP_PIN(1, 16), /* HSYNC */ + RCAR_GP_PIN(1, 17), /* VSYNC */ +}; +static const unsigned int vin3_sync_mux[] = { + VI3_HSYNC_N_MARK, + VI2_VSYNC_N_MARK, +}; +static const unsigned int vin3_field_pins[] = { + RCAR_GP_PIN(1, 15), +}; +static const unsigned int vin3_field_mux[] = { + VI3_FIELD_MARK, +}; +static const unsigned int vin3_clkenb_pins[] = { + RCAR_GP_PIN(1, 14), +}; +static const unsigned int vin3_clkenb_mux[] = { + VI3_CLKENB_MARK, +}; +static const unsigned int vin3_clk_pins[] = { + RCAR_GP_PIN(1, 23), +}; +static const unsigned int vin3_clk_mux[] = { + VI3_CLK_MARK, +}; static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(audio_clk_a), @@ -3683,6 +3815,20 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(vin1_field), SH_PFC_PIN_GROUP(vin1_clkenb), SH_PFC_PIN_GROUP(vin1_clk), + VIN_DATA_PIN_GROUP(vin2_data, 24), + SH_PFC_PIN_GROUP(vin2_data18), + VIN_DATA_PIN_GROUP(vin2_data, 16), + VIN_DATA_PIN_GROUP(vin2_data, 8), + VIN_DATA_PIN_GROUP(vin2_data, 4), + SH_PFC_PIN_GROUP(vin2_sync), + SH_PFC_PIN_GROUP(vin2_field), + SH_PFC_PIN_GROUP(vin2_clkenb), + SH_PFC_PIN_GROUP(vin2_clk), + SH_PFC_PIN_GROUP(vin3_data8), + SH_PFC_PIN_GROUP(vin3_sync), + SH_PFC_PIN_GROUP(vin3_field), + SH_PFC_PIN_GROUP(vin3_clkenb), + SH_PFC_PIN_GROUP(vin3_clk), }; static const char * const audio_clk_groups[] = { @@ -4028,6 +4174,26 @@ static const char * const vin1_groups[] = { "vin1_clk", }; +static const char * const vin2_groups[] = { + "vin2_data24", + "vin2_data18", + "vin2_data16", + "vin2_data8", + "vin2_data4", + "vin2_sync", + "vin2_field", + "vin2_clkenb", + "vin2_clk", +}; + +static const char * const vin3_groups[] = { + "vin3_data8", + "vin3_sync", + "vin3_field", + "vin3_clkenb", + "vin3_clk", +}; + static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(du), @@ -4067,6 +4233,8 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(usb2), SH_PFC_FUNCTION(vin0), SH_PFC_FUNCTION(vin1), + SH_PFC_FUNCTION(vin2), + SH_PFC_FUNCTION(vin3), }; static struct pinmux_cfg_reg pinmux_config_regs[] = { -- cgit v1.2.3 From 6962d914f317b119e0db7189199b21ec77a4b3e0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Dec 2013 14:53:36 +0100 Subject: xhci: Limit the spurious wakeup fix only to HP machines We've got regression reports that my previous fix for spurious wakeups after S5 on HP Haswell machines leads to the automatic reboot at shutdown on some machines. It turned out that the fix for one side triggers another BIOS bug in other side. So, it's exclusive. Since the original S5 wakeups have been confirmed only on HP machines, it'd be safer to apply it only to limited machines. As a wild guess, limiting to machines with HP PCI SSID should suffice. This patch should be backported to kernels as old as 3.12, that contain the commit 638298dc66ea36623dbc2757a24fc2c4ab41b016 "xhci: Fix spurious wakeups after S5 on Haswell". Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=66171 Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai Signed-off-by: Sarah Sharp Tested-by: Reported-by: Niklas Schnelle Reported-by: Giorgos Reported-by: --- drivers/usb/host/xhci-pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index b8dffd59eb25..73f5208714a4 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -128,7 +128,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) * any other sleep) on Haswell machines with LPT and LPT-LP * with the new Intel BIOS */ - xhci->quirks |= XHCI_SPURIOUS_WAKEUP; + /* Limit the quirk to only known vendors, as this triggers + * yet another BIOS bug on some other machines + * https://bugzilla.kernel.org/show_bug.cgi?id=66171 + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP) + xhci->quirks |= XHCI_SPURIOUS_WAKEUP; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { -- cgit v1.2.3 From 2f5ae4901acc6fdee939718658fa9f59c4f2217b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 27 Oct 2013 15:26:33 +0000 Subject: DRM: Armada: implement lastclose() for fbhelper Call drm_fb_helper_restore_fbdev_mode() upon last close so that in the event of the X server crashing, we have some kind of mode restored. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_drm.h | 1 + drivers/gpu/drm/armada/armada_drv.c | 7 ++++++- drivers/gpu/drm/armada/armada_fbdev.c | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index eef09ec9a5ff..a72cae03b99b 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -103,6 +103,7 @@ void armada_drm_queue_unref_work(struct drm_device *, extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs; int armada_fbdev_init(struct drm_device *); +void armada_fbdev_lastclose(struct drm_device *); void armada_fbdev_fini(struct drm_device *); int armada_overlay_plane_create(struct drm_device *, unsigned long); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 7aede900a221..15425d23c9cc 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -321,6 +321,11 @@ static struct drm_ioctl_desc armada_ioctls[] = { DRM_UNLOCKED), }; +static void armada_drm_lastclose(struct drm_device *dev) +{ + armada_fbdev_lastclose(dev); +} + static const struct file_operations armada_drm_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -337,7 +342,7 @@ static struct drm_driver armada_drm_driver = { .open = NULL, .preclose = NULL, .postclose = NULL, - .lastclose = NULL, + .lastclose = armada_drm_lastclose, .unload = armada_drm_unload, .get_vblank_counter = drm_vblank_count, .enable_vblank = armada_drm_enable_vblank, diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index dd5ea77dac96..743570e99f90 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -177,6 +177,16 @@ int armada_fbdev_init(struct drm_device *dev) return ret; } +void armada_fbdev_lastclose(struct drm_device *dev) +{ + struct armada_private *priv = dev->dev_private; + + drm_modeset_lock_all(dev); + if (priv->fbdev) + drm_fb_helper_restore_fbdev_mode(priv->fbdev); + drm_modeset_unlock_all(dev); +} + void armada_fbdev_fini(struct drm_device *dev) { struct armada_private *priv = dev->dev_private; -- cgit v1.2.3 From 077acbab67a785b5f5ae60e8932fcf6028072359 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 27 Oct 2013 15:35:27 +0000 Subject: DRM: Armada: destroy framebuffer after helper Destroy the framebuffer only after the helper, since the helper may still be referencing the framebufer at this point. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_fbdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 743570e99f90..b348b16f81e2 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -202,11 +202,11 @@ void armada_fbdev_fini(struct drm_device *dev) framebuffer_release(info); } + drm_fb_helper_fini(fbh); + if (fbh->fb) fbh->fb->funcs->destroy(fbh->fb); - drm_fb_helper_fini(fbh); - priv->fbdev = NULL; } } -- cgit v1.2.3 From 7513e09596374bb7fbbecfee945fecb5b357c0e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 27 Nov 2013 15:46:55 +0000 Subject: DRM: Armada: fix printing of phys_addr_t/dma_addr_t These can be 64-bit quantities, so fix them up appropriately. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_fbdev.c | 6 +++--- drivers/gpu/drm/armada/armada_gem.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index b348b16f81e2..948cb14c561e 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -105,9 +105,9 @@ static int armada_fb_create(struct drm_fb_helper *fbh, drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth); drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); - DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n", - dfb->fb.width, dfb->fb.height, - dfb->fb.bits_per_pixel, obj->phys_addr); + DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n", + dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel, + (unsigned long long)obj->phys_addr); return 0; diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 9f2356bae7fd..adc7c2da75bb 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -172,8 +172,9 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) obj->dev_addr = obj->linear->start; } - DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n", - obj, obj->phys_addr, obj->dev_addr); + DRM_DEBUG_DRIVER("obj %p phys %#llx dev %#llx\n", obj, + (unsigned long long)obj->phys_addr, + (unsigned long long)obj->dev_addr); return 0; } -- cgit v1.2.3 From 5cd5268806435b6476184430b2806db988c903f0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 7 Dec 2013 16:28:39 +0000 Subject: DRM: Armada: prime refcounting bug fix Commit 011c2282c74d changed the way refcounting on imported dma_bufs works, and this hadn't been spotted while forward-porting Armada. Reflect the changes in that commit into the Armada driver. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index adc7c2da75bb..887816f43476 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -558,7 +558,6 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf) * refcount on the gem object itself. */ drm_gem_object_reference(obj); - dma_buf_put(buf); return obj; } } @@ -574,6 +573,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf) } dobj->obj.import_attach = attach; + get_dma_buf(buf); /* * Don't call dma_buf_map_attachment() here - it maps the -- cgit v1.2.3 From c1b1731d2002b93857810aa5da856b43f46bb470 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 6 Dec 2013 17:51:18 +0530 Subject: drivers: phy: Fix memory leak 'phy' was not being freed upon error in one of the cases. Adjust the 'goto's to fix this. Signed-off-by: Sachin Kamat Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 03cf8fb81554..712b358a5756 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -453,7 +453,7 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, if (id < 0) { dev_err(dev, "unable to get id\n"); ret = id; - goto err0; + goto err1; } device_initialize(&phy->dev); @@ -468,11 +468,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id); if (ret) - goto err1; + goto err2; ret = device_add(&phy->dev); if (ret) - goto err1; + goto err2; if (pm_runtime_enabled(dev)) { pm_runtime_enable(&phy->dev); @@ -481,11 +481,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, return phy; -err1: +err2: ida_remove(&phy_ida, phy->id); put_device(&phy->dev); +err1: kfree(phy); - err0: return ERR_PTR(ret); } -- cgit v1.2.3 From 52797d293287f5a98bd686616527b102b077ac39 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 6 Dec 2013 17:51:19 +0530 Subject: drivers: phy: tweaks to phy_create() If this was called with a NULL "dev" then it lead to a NULL dereference when we called dev_WARN(). I have changed it to WARN_ON() so that we get a stack dump and can fix the caller. The rest of this patch is just cleanup like returning directly instead of having do-nothing gotos. Using descriptive labels instead of GW-BASIC style "err0" and "err1". I also flipped the order of put_device() and ida_remove() so they are a mirror reflection of the order they were allocated. Signed-off-by: Dan Carpenter Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-core.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 712b358a5756..58e0e9739028 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -437,23 +437,18 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, int id; struct phy *phy; - if (!dev) { - dev_WARN(dev, "no device provided for PHY\n"); - ret = -EINVAL; - goto err0; - } + if (WARN_ON(!dev)) + return ERR_PTR(-EINVAL); phy = kzalloc(sizeof(*phy), GFP_KERNEL); - if (!phy) { - ret = -ENOMEM; - goto err0; - } + if (!phy) + return ERR_PTR(-ENOMEM); id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL); if (id < 0) { dev_err(dev, "unable to get id\n"); ret = id; - goto err1; + goto free_phy; } device_initialize(&phy->dev); @@ -468,11 +463,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id); if (ret) - goto err2; + goto put_dev; ret = device_add(&phy->dev); if (ret) - goto err2; + goto put_dev; if (pm_runtime_enabled(dev)) { pm_runtime_enable(&phy->dev); @@ -481,12 +476,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, return phy; -err2: - ida_remove(&phy_ida, phy->id); +put_dev: put_device(&phy->dev); -err1: + ida_remove(&phy_ida, phy->id); +free_phy: kfree(phy); -err0: return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(phy_create); -- cgit v1.2.3 From 8820784203ac24279be23a6e3d85d216c46d65ee Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Fri, 6 Dec 2013 17:51:20 +0530 Subject: phy: kconfig: add depends on "USB_PHY" to OMAP_USB2 and TWL4030_USB Fixes warning: (OMAP_USB2 && TWL4030_USB) selects USB_PHY which has unmet direct dependencies (USB_SUPPORT) that shows up while disabling USB_SUPPORT from menuconfig. Reported-by: Russell King Signed-off-by: Kishon Vijay Abraham I Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/phy/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index a344f3d52361..330ef2d06567 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -24,8 +24,8 @@ config PHY_EXYNOS_MIPI_VIDEO config OMAP_USB2 tristate "OMAP USB2 PHY Driver" depends on ARCH_OMAP2PLUS + depends on USB_PHY select GENERIC_PHY - select USB_PHY select OMAP_CONTROL_USB help Enable this to support the transceiver that is part of SOC. This @@ -36,8 +36,8 @@ config OMAP_USB2 config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS + depends on USB_PHY select GENERIC_PHY - select USB_PHY help Enable this to support the USB OTG transceiver on TWL4030 family chips (including the TWL5030 and TPS659x0 devices). -- cgit v1.2.3 From 7125ecb8297a122d60b2b4be9490f49bfadff8e0 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Nov 2013 13:47:15 -0200 Subject: drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8 We already have some checks and shouldn't be reaching these places on !HAS_PC8 platforms, but add a WARN, just in case. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 10a803f69360..895759b5569f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6638,6 +6638,8 @@ void hsw_enable_pc8_work(struct work_struct *__work) struct drm_device *dev = dev_priv->dev; uint32_t val; + WARN_ON(!HAS_PC8(dev)); + if (dev_priv->pc8.enabled) return; @@ -6683,6 +6685,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv) if (dev_priv->pc8.disable_count != 1) return; + WARN_ON(!HAS_PC8(dev)); + cancel_delayed_work_sync(&dev_priv->pc8.enable_work); if (!dev_priv->pc8.enabled) return; -- cgit v1.2.3 From d62292c8f778772d1b6ec125d461c8c16fdc0417 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 27 Nov 2013 17:59:22 -0200 Subject: drm/i915: get a PC8 reference when enabling the power well In the current code, at haswell_modeset_global_resources, first we decide if we want to enable/disable the power well, then we decide if we want to enable/disable PC8. On the case where we're enabling PC8 this works fine, but on the case where we disable PC8 due to a non-eDP monitor being enabled, we first enable the power well and then disable PC8. Although wrong, this doesn't seem to be causing any problems now, and we don't even see anything in dmesg. But the patches for runtime D3 turn this problem into a real bug, so we need to fix it. This fixes the "modeset-non-lpsp" subtest from the "pm_pc8" test from intel-gpu-tools. v2: - Rebase (i915_disable_power_well). v3: - More reabase. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 41b6e080e362..cd3f511847ec 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5688,6 +5688,8 @@ static void hsw_set_power_well(struct drm_device *dev, unsigned long irqflags; uint32_t tmp; + WARN_ON(dev_priv->pc8.enabled); + tmp = I915_READ(HSW_PWR_WELL_DRIVER); is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED; enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST; @@ -5747,17 +5749,26 @@ static void hsw_set_power_well(struct drm_device *dev, static void __intel_power_well_get(struct drm_device *dev, struct i915_power_well *power_well) { - if (!power_well->count++ && power_well->set) + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!power_well->count++ && power_well->set) { + hsw_disable_package_c8(dev_priv); power_well->set(dev, power_well, true); + } } static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { + struct drm_i915_private *dev_priv = dev->dev_private; + WARN_ON(!power_well->count); - if (!--power_well->count && power_well->set && i915_disable_power_well) + if (!--power_well->count && power_well->set && + i915_disable_power_well) { power_well->set(dev, power_well, false); + hsw_enable_package_c8(dev_priv); + } } void intel_display_power_get(struct drm_device *dev, -- cgit v1.2.3 From 8a1874559f222efcae0c0c41b180f6e1af6b9d2e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 20:32:13 -0200 Subject: drm/i915: add initial Runtime PM functions This patch adds the initial infrastructure to allow a Runtime PM implementation that sets the device to its D3 state. The patch just adds the necessary callbacks and the initial infrastructure. We still don't have any platform that actually uses this infrastructure, we still don't call get/put in all the places we need to, and we don't have any function to save/restore the state of the registers. This is not a problem since no platform uses the code added by this patch. We have a few people simultaneously working on runtime PM, so this initial code could help everybody make their plans. V2: - Move some functions to intel_pm.c - Remove useless pm_runtime_allow() call at init - Remove useless pm_runtime_mark_last_busy() call at get - Use pm_runtime_get_sync() instead of 2 calls - Add a WARN to check if we're really awake V3: - Rebase. V4: - Don't need to call pci_{save,restore}_state and pci_set_power_sate, since they're already called by the PCI layer - Remove wrong pm_runtime_enable() call at init_runtime_pm Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 6 ++++ drivers/gpu/drm/i915/i915_drv.c | 36 ++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 7 +++++ drivers/gpu/drm/i915/intel_drv.h | 4 +++ drivers/gpu/drm/i915/intel_pm.c | 55 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_uncore.c | 9 ++++++ 6 files changed, 117 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a5d010c86368..b49571df555f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS]) @@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (IS_GEN5(dev)) intel_gpu_ips_init(dev_priv); + intel_init_runtime_pm(dev_priv); + return 0; out_power_well: @@ -1708,6 +1712,8 @@ int i915_driver_unload(struct drm_device *dev) return ret; } + intel_fini_runtime_pm(dev_priv); + intel_gpu_ips_teardown(); /* The i915.ko module is still not prepared to be loaded when diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 13076db65eb9..7d2136170293 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; + intel_runtime_pm_get(dev_priv); + /* ignore lid events during suspend */ mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_SUSPENDED; @@ -686,6 +688,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_DONE; mutex_unlock(&dev_priv->modeset_restore_lock); + + intel_runtime_pm_put(dev_priv); return error; } @@ -900,6 +904,36 @@ static int i915_pm_poweroff(struct device *dev) return i915_drm_freeze(drm_dev); } +static int i915_runtime_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_i915_private *dev_priv = dev->dev_private; + + WARN_ON(!HAS_RUNTIME_PM(dev)); + + DRM_DEBUG_KMS("Suspending device\n"); + + dev_priv->pm.suspended = true; + + return 0; +} + +static int i915_runtime_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_i915_private *dev_priv = dev->dev_private; + + WARN_ON(!HAS_RUNTIME_PM(dev)); + + DRM_DEBUG_KMS("Resuming device\n"); + + dev_priv->pm.suspended = false; + + return 0; +} + static const struct dev_pm_ops i915_pm_ops = { .suspend = i915_pm_suspend, .resume = i915_pm_resume, @@ -907,6 +941,8 @@ static const struct dev_pm_ops i915_pm_ops = { .thaw = i915_pm_thaw, .poweroff = i915_pm_poweroff, .restore = i915_pm_resume, + .runtime_suspend = i915_runtime_suspend, + .runtime_resume = i915_runtime_resume, }; static const struct vm_operations_struct i915_gem_vm_ops = { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 780f815b6c9f..98fd1c043777 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1289,6 +1289,10 @@ struct i915_package_c8 { } regsave; }; +struct i915_runtime_pm { + bool suspended; +}; + enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_NONE, INTEL_PIPE_CRC_SOURCE_PLANE1, @@ -1519,6 +1523,8 @@ typedef struct drm_i915_private { struct i915_package_c8 pc8; + struct i915_runtime_pm pm; + /* Old dri1 support infrastructure, beware the dragons ya fools entering * here! */ struct i915_dri1_state dri1; @@ -1843,6 +1849,7 @@ struct drm_i915_file_private { #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */ +#define HAS_RUNTIME_PM(dev) false #define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 79585cddc2cd..4a4effba134b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -862,6 +862,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv); void gen6_rps_boost(struct drm_i915_private *dev_priv); void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); +void intel_runtime_pm_get(struct drm_i915_private *dev_priv); +void intel_runtime_pm_put(struct drm_i915_private *dev_priv); +void intel_init_runtime_pm(struct drm_i915_private *dev_priv); +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv); void ilk_wm_get_hw_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cd3f511847ec..2590a5c90725 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -31,6 +31,7 @@ #include "../../../platform/x86/intel_ips.h" #include #include +#include /** * RC6 is a special power stage which allows the GPU to enter an very @@ -5961,6 +5962,60 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv) hsw_enable_package_c8(dev_priv); } +void intel_runtime_pm_get(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct device *device = &dev->pdev->dev; + + if (!HAS_RUNTIME_PM(dev)) + return; + + pm_runtime_get_sync(device); + WARN(dev_priv->pm.suspended, "Device still suspended.\n"); +} + +void intel_runtime_pm_put(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct device *device = &dev->pdev->dev; + + if (!HAS_RUNTIME_PM(dev)) + return; + + pm_runtime_mark_last_busy(device); + pm_runtime_put_autosuspend(device); +} + +void intel_init_runtime_pm(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct device *device = &dev->pdev->dev; + + dev_priv->pm.suspended = false; + + if (!HAS_RUNTIME_PM(dev)) + return; + + pm_runtime_set_active(device); + + pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */ + pm_runtime_mark_last_busy(device); + pm_runtime_use_autosuspend(device); +} + +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct device *device = &dev->pdev->dev; + + if (!HAS_RUNTIME_PM(dev)) + return; + + /* Make sure we're not suspended first. */ + pm_runtime_get_sync(device); + pm_runtime_disable(device); +} + /* Set up chip specific power management-related functions */ void intel_init_pm(struct drm_device *dev) { diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index e63658e0cfd3..0c4c302aa38c 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -437,6 +437,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg) } } +static void +assert_device_not_suspended(struct drm_i915_private *dev_priv) +{ + WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, + "Device suspended\n"); +} + #define REG_READ_HEADER(x) \ unsigned long irqflags; \ u##x val = 0; \ @@ -568,6 +575,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ + assert_device_not_suspended(dev_priv); \ __raw_i915_write##x(dev_priv, reg, val); \ if (unlikely(__fifo_ret)) { \ gen6_gt_check_fifodbg(dev_priv); \ @@ -583,6 +591,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ + assert_device_not_suspended(dev_priv); \ hsw_unclaimed_reg_clear(dev_priv, reg); \ __raw_i915_write##x(dev_priv, reg, val); \ if (unlikely(__fifo_ret)) { \ -- cgit v1.2.3 From cd2e9e908a86c44c83026acd95520a2761f0d64c Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 20:34:21 -0200 Subject: drm/i915: do adapter power state notification at runtime PM Now that we are actually setting the device to the D3 state, we should issue the notification. The opregion spec says we should send the message before the adapter is about to be placed in a lower power state, and after the adapter is placed in a higher power state. Jani originally wrote a similar patch for PC8, but then we discovered that we were not really changing the PCI D states when enabling/disabling PC8, so we had to postpone his patch. v2: - Improve commit message, explaining the expected state. v3: - Rebase. Cc: Jani Nikula Credits-to: Jani Nikula Reviewed-by: Rodrigo Vivi (v2) Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7d2136170293..2137a33d5bb2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -915,6 +915,7 @@ static int i915_runtime_suspend(struct device *device) DRM_DEBUG_KMS("Suspending device\n"); dev_priv->pm.suspended = true; + intel_opregion_notify_adapter(dev, PCI_D3cold); return 0; } @@ -929,6 +930,7 @@ static int i915_runtime_resume(struct device *device) DRM_DEBUG_KMS("Resuming device\n"); + intel_opregion_notify_adapter(dev, PCI_D0); dev_priv->pm.suspended = false; return 0; -- cgit v1.2.3 From f65c9168983926962b25ae19073474d60dea0442 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 27 Nov 2013 18:20:34 -0200 Subject: drm/i915: add runtime put/get calls at the basic places If I add code to enable runtime PM on my Haswell machine, start a desktop environment, then enable runtime PM, these functions will complain that they're trying to read/write registers while the graphics card is suspended. v2: - Simplify i915_gem_fault changes. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi [danvet: Drop the hunk in i915_hangcheck_elapsed, it's the wrong thing to do.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 27 +++++++++++++++++++++------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 ++++++ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 92149bcabe98..df83fec174e9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) int ret = 0; bool write = !!(vmf->flags & FAULT_FLAG_WRITE); + intel_runtime_pm_get(dev_priv); + /* We don't use vmf->pgoff since that has the fake offset */ page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT; @@ -1427,8 +1429,10 @@ out: /* If this -EIO is due to a gpu hang, give the reset code a * chance to clean up the mess. Otherwise return the proper * SIGBUS. */ - if (i915_terminally_wedged(&dev_priv->gpu_error)) - return VM_FAULT_SIGBUS; + if (i915_terminally_wedged(&dev_priv->gpu_error)) { + ret = VM_FAULT_SIGBUS; + break; + } case -EAGAIN: /* * EAGAIN means the gpu is hung and we'll wait for the error @@ -1443,15 +1447,22 @@ out: * EBUSY is ok: this just means that another thread * already did the job. */ - return VM_FAULT_NOPAGE; + ret = VM_FAULT_NOPAGE; + break; case -ENOMEM: - return VM_FAULT_OOM; + ret = VM_FAULT_OOM; + break; case -ENOSPC: - return VM_FAULT_SIGBUS; + ret = VM_FAULT_SIGBUS; + break; default: WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret); - return VM_FAULT_SIGBUS; + ret = VM_FAULT_SIGBUS; + break; } + + intel_runtime_pm_put(dev_priv); + return ret; } /** @@ -4169,6 +4180,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) drm_i915_private_t *dev_priv = dev->dev_private; struct i915_vma *vma, *next; + intel_runtime_pm_get(dev_priv); + trace_i915_gem_object_destroy(obj); if (obj->phys_obj) @@ -4213,6 +4226,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) kfree(obj->bit_17); i915_gem_object_free(obj); + + intel_runtime_pm_put(dev_priv); } struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 9282b4c411f6..bceddf5a04bc 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1108,6 +1108,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, } } + intel_runtime_pm_get(dev_priv); + ret = i915_mutex_lock_interruptible(dev); if (ret) goto pre_mutex_err; @@ -1237,6 +1239,10 @@ err: pre_mutex_err: kfree(cliprects); + + /* intel_gpu_busy should also get a ref, so it will free when the device + * is really idle. */ + intel_runtime_pm_put(dev_priv); return ret; } -- cgit v1.2.3 From c8c8fb33b37766acf6474784b0d5245dab9a1690 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 27 Nov 2013 18:21:54 -0200 Subject: drm/i915: add some runtime PM get/put calls These are needed when we cat the debugfs and sysfs files. V2: - Rebase V3: - Rebase V4: - Rebase Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_sysfs.c | 14 ++++++++++-- drivers/gpu/drm/i915/intel_dp.c | 11 +++++++-- drivers/gpu/drm/i915/intel_panel.c | 3 +++ drivers/gpu/drm/i915/intel_uncore.c | 4 ++++ 5 files changed, 70 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 13accf795548..6badc1596ceb 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); for_each_ring(ring, dev_priv, i) i915_ring_seqno_info(m, ring); + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return 0; @@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); if (INTEL_INFO(dev)->gen >= 8) { int i; @@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) } i915_ring_seqno_info(m, ring); } + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return 0; @@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); crstanddelay = I915_READ16(CRSTANDVID); + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f)); @@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - int ret; + int ret = 0; + + intel_runtime_pm_get(dev_priv); flush_delayed_work(&dev_priv->rps.delayed_resume_work); @@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) /* RPSTAT1 is in the GT power well */ ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) - return ret; + goto out; gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); @@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) seq_puts(m, "no P-state info available\n"); } - return 0; +out: + intel_runtime_pm_put(dev_priv); + return ret; } static int i915_delayfreq_table(struct seq_file *m, void *unused) @@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); for (i = 0; i < 16; i++) { delayfreq = I915_READ(PXVFREQ_BASE + i * 4); @@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused) (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT); } + intel_runtime_pm_put(dev_priv); + mutex_unlock(&dev->struct_mutex); return 0; @@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); for (i = 1; i <= 32; i++) { inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4); seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext); } + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return 0; @@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); rgvmodectl = I915_READ(MEMMODECTL); rstdbyctl = I915_READ(RSTDBYCTL); crstandvid = I915_READ16(CRSTANDVID); + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ? @@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); spin_lock_irq(&dev_priv->uncore.lock); forcewake_count = dev_priv->uncore.forcewake_count; @@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m) sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); mutex_unlock(&dev_priv->rps.hw_lock); + intel_runtime_pm_put(dev_priv); + seq_printf(m, "Video Turbo Mode: %s\n", yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO)); seq_printf(m, "HW control enabled: %s\n", @@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); if (ret) return ret; + intel_runtime_pm_get(dev_priv); seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n"); @@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) ((ia_freq >> 8) & 0xff) * 100); } + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev_priv->rps.hw_lock); return 0; @@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4)); + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); seq_printf(m, "bit6 swizzle for X-tiling = %s\n", swizzle_string(dev_priv->mm.bit_6_swizzle_x)); @@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) seq_printf(m, "DISP_ARB_CTL = 0x%08x\n", I915_READ(DISP_ARB_CTL)); } + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return 0; @@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; int ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); if (INTEL_INFO(dev)->gen >= 8) gen8_ppgtt_info(m, dev); else if (INTEL_INFO(dev)->gen >= 6) gen6_ppgtt_info(m, dev); + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return 0; @@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) u32 psrperf = 0; bool enabled = false; + intel_runtime_pm_get(dev_priv); + seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support)); seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok)); @@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) EDP_PSR_PERF_CNT_MASK; seq_printf(m, "Performance_Counter: %u\n", psrperf); + intel_runtime_pm_put(dev_priv); return 0; } @@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val) ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); + + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev_priv->dev->struct_mutex); *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT; @@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val) if (val > 3) return -EINVAL; + intel_runtime_pm_get(dev_priv); DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val); /* Update the cache sharing policy here as well */ @@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val) snpcr |= (val << GEN6_MBC_SNPCR_SHIFT); I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); + intel_runtime_pm_put(dev_priv); return 0; } @@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file) if (INTEL_INFO(dev)->gen < 6) return 0; + intel_runtime_pm_get(dev_priv); gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); return 0; @@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file) return 0; gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); + intel_runtime_pm_put(dev_priv); return 0; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 05d8b1680c22..33bcae314bf8 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg) struct drm_i915_private *dev_priv = dev->dev_private; u64 raw_time; /* 32b value may overflow during fixed point math */ u64 units = 128ULL, div = 100000ULL, bias = 100ULL; + u32 ret; if (!intel_enable_rc6(dev)) return 0; + intel_runtime_pm_get(dev_priv); + /* On VLV, residency time is in CZ units rather than 1.28us */ if (IS_VALLEYVIEW(dev)) { u32 clkctl2; @@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg) CLK_CTL2_CZCOUNT_30NS_SHIFT; if (!clkctl2) { WARN(!clkctl2, "bogus CZ count value"); - return 0; + ret = 0; + goto out; } units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2); if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) @@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg) } raw_time = I915_READ(reg) * units; - return DIV_ROUND_UP_ULL(raw_time, div); + ret = DIV_ROUND_UP_ULL(raw_time, div); + +out: + intel_runtime_pm_put(dev_priv); + return ret; } static ssize_t @@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; + intel_runtime_pm_get(dev_priv); rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); if (attr == &dev_attr_gt_RP0_freq_mhz) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f3b17b11b270..a01264234bf0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3072,9 +3072,12 @@ intel_dp_detect(struct drm_connector *connector, bool force) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *intel_encoder = &intel_dig_port->base; struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; enum drm_connector_status status; struct edid *edid = NULL; + intel_runtime_pm_get(dev_priv); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, drm_get_connector_name(connector)); @@ -3086,7 +3089,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) status = g4x_dp_detect(intel_dp); if (status != connector_status_connected) - return status; + goto out; intel_dp_probe_oui(intel_dp); @@ -3102,7 +3105,11 @@ intel_dp_detect(struct drm_connector *connector, bool force) if (intel_encoder->type != INTEL_OUTPUT_EDP) intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; - return connector_status_connected; + status = connector_status_connected; + +out: + intel_runtime_pm_put(dev_priv); + return status; } static int intel_dp_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index b0f6e6cc4354..20ebc3e83d39 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; int ret; + intel_runtime_pm_get(dev_priv); mutex_lock(&dev->mode_config.mutex); ret = intel_panel_get_backlight(connector); mutex_unlock(&dev->mode_config.mutex); + intel_runtime_pm_put(dev_priv); return ret; } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0c4c302aa38c..8102af9a178d 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -370,6 +370,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) if (!dev_priv->uncore.funcs.force_wake_get) return; + intel_runtime_pm_get(dev_priv); + /* Redirect to VLV specific routine */ if (IS_VALLEYVIEW(dev_priv->dev)) return vlv_force_wake_get(dev_priv, fw_engine); @@ -403,6 +405,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) 1); } spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + intel_runtime_pm_put(dev_priv); } /* We give fast paths for the really cool registers */ -- cgit v1.2.3 From e9cb81a22841908b1c075156b409a538d09c8466 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Nov 2013 13:47:23 -0200 Subject: drm/i915: get a runtime PM reference when the panel VDD is on And put it when it's off. Otherwise, when you run pm_pc8 from intel-gpu-tools, and the delayed function that disables VDD runs, we'll get some messages saying we're touching registers while the HW is suspended. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a01264234bf0..ba5a59c9129f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1094,6 +1094,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) if (ironlake_edp_have_panel_vdd(intel_dp)) return; + intel_runtime_pm_get(dev_priv); + DRM_DEBUG_KMS("Turning eDP VDD on\n"); if (!ironlake_edp_have_panel_power(intel_dp)) @@ -1143,6 +1145,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg)); msleep(intel_dp->panel_power_down_delay); + + intel_runtime_pm_put(dev_priv); } } @@ -1250,6 +1254,9 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp) intel_dp->want_panel_vdd = false; ironlake_wait_panel_off(intel_dp); + + /* We got a reference when we enabled the VDD. */ + intel_runtime_pm_put(dev_priv); } void ironlake_edp_backlight_on(struct intel_dp *intel_dp) -- cgit v1.2.3 From 48fc7dbd52c0559647291f33a10ccdc6cdbe4c72 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 5 Dec 2013 17:07:27 -0800 Subject: usb: xhci: change enumeration scheme to 'new scheme' by default Change the default enumeration scheme for xhci attached non-SuperSpeed devices from: Reset SetAddress [xhci address-device BSR = 0] GetDescriptor(8) GetDescriptor(18) ...to: Reset [xhci address-device BSR = 1] GetDescriptor(64) Reset SetAddress [xhci address-device BSR = 0] GetDescriptor(18) ...as some devices misbehave when encountering a SetAddress command prior to GetDescriptor. There are known legacy devices that require this scheme, but testing has found at least one USB3 device that fails enumeration when presented with this ordering. For now, follow the ehci case and enable 'new scheme' by default for non-SuperSpeed devices. To support this enumeration scheme on xhci the AddressDevice operation needs to be performed twice. The first instance of the command enables the HC's device and slot context info for the device, but omits sending the device a SetAddress command (BSR == block set address request). Then, after GetDescriptor completes, follow up with the full AddressDevice+SetAddress operation. As mentioned before, this ordering of events with USB3 devices causes an extra state transition to be exposed to xhci. Previously USB3 devices would transition directly from 'enabled' to 'addressed' and never need to underrun responses to 'get descriptor'. We do see the 64-byte descriptor fetch the correct data, but the following 18-byte descriptor read after the reset gets: bLength = 0 bDescriptorType = 0 bcdUSB = 0 bDeviceClass = 0 bDeviceSubClass = 0 bDeviceProtocol = 0 bMaxPacketSize0 = 9 instead of: bLength = 12 bDescriptorType = 1 bcdUSB = 300 bDeviceClass = 0 bDeviceSubClass = 0 bDeviceProtocol = 0 bMaxPacketSize0 = 9 which results in the discovery process looping until falling back to 'old scheme' enumeration. Acked-by: Alan Stern Reported-by: David Moore Suggested-by: Sarah Sharp Reported-by: Dan Carpenter Signed-off-by: Dan Williams Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 46 +++++++++++++++++++++++++++++++++++++++++--- drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci-plat.c | 1 + drivers/usb/host/xhci-ring.c | 6 +++--- drivers/usb/host/xhci.c | 19 ++++++++++++++---- drivers/usb/host/xhci.h | 11 ++++++++++- include/linux/usb/hcd.h | 2 ++ 7 files changed, 75 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 32e1035d4f59..6a11eff74d3c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2498,6 +2498,21 @@ static unsigned hub_is_wusb(struct usb_hub *hub) #define HUB_LONG_RESET_TIME 200 #define HUB_RESET_TIMEOUT 800 +/* + * "New scheme" enumeration causes an extra state transition to be + * exposed to an xhci host and causes USB3 devices to receive control + * commands in the default state. This has been seen to cause + * enumeration failures, so disable this enumeration scheme for USB3 + * devices. + */ +static bool use_new_scheme(struct usb_device *udev, int retry) +{ + if (udev->speed == USB_SPEED_SUPER) + return false; + + return USE_NEW_SCHEME(retry); +} + static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm); @@ -3956,6 +3971,20 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev) } } +static int hub_enable_device(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!hcd->driver->enable_device) + return 0; + if (udev->state == USB_STATE_ADDRESS) + return 0; + if (udev->state != USB_STATE_DEFAULT) + return -EINVAL; + + return hcd->driver->enable_device(hcd, udev); +} + /* Reset device, (re)assign address, get device descriptor. * Device connection must be stable, no more debouncing needed. * Returns device in USB_STATE_ADDRESS, except on error. @@ -4068,7 +4097,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * this area, and this is how Linux has done it for ages. * Change it cautiously. * - * NOTE: If USE_NEW_SCHEME() is true we will start by issuing + * NOTE: If use_new_scheme() is true we will start by issuing * a 64-byte GET_DESCRIPTOR request. This is what Windows does, * so it may help with some non-standards-compliant devices. * Otherwise we start with SET_ADDRESS and then try to read the @@ -4076,10 +4105,17 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * value. */ for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { - if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) { + bool did_new_scheme = false; + + if (use_new_scheme(udev, retry_counter)) { struct usb_device_descriptor *buf; int r = 0; + did_new_scheme = true; + retval = hub_enable_device(udev); + if (retval < 0) + goto fail; + #define GET_DESCRIPTOR_BUFSIZE 64 buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); if (!buf) { @@ -4168,7 +4204,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * - read ep0 maxpacket even for high and low speed, */ msleep(10); - if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) + /* use_new_scheme() checks the speed which may have + * changed since the initial look so we cache the result + * in did_new_scheme + */ + if (did_new_scheme) break; } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index b8dffd59eb25..4221dee924b5 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -331,6 +331,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth, .address_device = xhci_address_device, + .enable_device = xhci_enable_device, .update_hub_device = xhci_update_hub_device, .reset_device = xhci_discover_or_reset_device, diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 9d29aa1b1bc8..8abda5c73ca1 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -69,6 +69,7 @@ static const struct hc_driver xhci_plat_xhci_driver = { .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth, .address_device = xhci_address_device, + .enable_device = xhci_enable_device, .update_hub_device = xhci_update_hub_device, .reset_device = xhci_discover_or_reset_device, diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fe9208a5d103..d26cd9474aa6 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -4004,12 +4004,12 @@ int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id) /* Queue an address device command TRB */ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, - u32 slot_id) + u32 slot_id, enum xhci_setup_dev setup) { return queue_command(xhci, lower_32_bits(in_ctx_ptr), upper_32_bits(in_ctx_ptr), 0, - TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id), - false); + TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id) + | (setup == SETUP_CONTEXT_ONLY ? TRB_BSR : 0), false); } int xhci_queue_vendor_command(struct xhci_hcd *xhci, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7fe6f664054f..6598f7ee7938 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3709,12 +3709,13 @@ disable_slot: } /* - * Issue an Address Device command (which will issue a SetAddress request to - * the device). + * Issue an Address Device command and optionally send a corresponding + * SetAddress request to the device. * We should be protected by the usb_address0_mutex in khubd's hub_port_init, so * we should only issue and wait on one address command at the same time. */ -int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) +static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, + enum xhci_setup_dev setup) { unsigned long flags; int timeleft; @@ -3773,7 +3774,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) spin_lock_irqsave(&xhci->lock, flags); cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring); ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, - udev->slot_id); + udev->slot_id, setup); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); xhci_dbg_trace(xhci, trace_xhci_dbg_address, @@ -3868,6 +3869,16 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return 0; } +int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS); +} + +int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY); +} + /* * Transfer the port index into real index in the HW port status * registers. Caculate offset between the port's PORTSC register diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 7807f621a713..24344aab2107 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1108,6 +1108,14 @@ struct xhci_event_cmd { }; /* flags bitmasks */ + +/* Address device - disable SetAddress */ +#define TRB_BSR (1<<9) +enum xhci_setup_dev { + SETUP_CONTEXT_ONLY, + SETUP_CONTEXT_ADDRESS, +}; + /* bits 16:23 are the virtual function ID */ /* bits 24:31 are the slot ID */ #define TRB_TO_SLOT_ID(p) (((p) & (0xff<<24)) >> 24) @@ -1760,6 +1768,7 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint **eps, unsigned int num_eps, gfp_t mem_flags); int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); +int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev); int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev); int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, struct usb_device *udev, int enable); @@ -1783,7 +1792,7 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); void xhci_ring_cmd_db(struct xhci_hcd *xhci); int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, - u32 slot_id); + u32 slot_id, enum xhci_setup_dev); int xhci_queue_vendor_command(struct xhci_hcd *xhci, u32 field1, u32 field2, u32 field3, u32 field4); int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 758ce80d085f..efe8d8a7c7ad 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -353,6 +353,8 @@ struct hc_driver { void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); /* Returns the hardware-chosen device address */ int (*address_device)(struct usb_hcd *, struct usb_device *udev); + /* prepares the hardware to send commands to the device */ + int (*enable_device)(struct usb_hcd *, struct usb_device *udev); /* Notifies the HCD after a hub descriptor is fetched. * Will block. */ -- cgit v1.2.3 From 6806e63f48f819754f39e1f796e790b377fb6a89 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Nov 2013 13:47:24 -0200 Subject: drm/i915: do not assert DE_PCH_EVENT_IVB enabled The current code was checking if all bits of "val" were enabled and DE_PCH_EVENT_IVB was disabled. The new code doesn't care about the state of DE_PCH_EVENT_IVB: it just checks if everything else is 1. The goal is that future patches may completely disable interrupts, and the LCPLL-disabling code shouldn't care about the state of DE_PCH_EVENT_IVB. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi [danvet: I think the commit message is actually wrong in it's description of what the old test checked, but the new one seems sane. So meh.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 895759b5569f..d3a3fba64361 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6514,7 +6514,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); val = I915_READ(DEIMR); - WARN((val & ~DE_PCH_EVENT_IVB) != val, + WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff, "Unexpected DEIMR bits enabled: 0x%x\n", val); val = I915_READ(SDEIMR); WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff, -- cgit v1.2.3 From 6f8ffc0b43c1043481306ffb8a4b8f53fa1f5ead Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 22 Nov 2013 01:20:01 -0800 Subject: xhci: clarify logging in xhci_setup_device Specify whether we are only performing the context setup portion of the 'address device' command, or the full operation issuing 'SetAddress' on the wire. Signed-off-by: Dan Williams Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6598f7ee7938..d68ec1aa473d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3717,6 +3717,7 @@ disable_slot: static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, enum xhci_setup_dev setup) { + const char *act = setup == SETUP_CONTEXT_ONLY ? "context" : "address"; unsigned long flags; int timeleft; struct xhci_virt_device *virt_dev; @@ -3792,8 +3793,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, * command on a timeout. */ if (timeleft <= 0) { - xhci_warn(xhci, "%s while waiting for address device command\n", - timeleft == 0 ? "Timeout" : "Signal"); + xhci_warn(xhci, "%s while waiting for setup %s command\n", + timeleft == 0 ? "Timeout" : "Signal", act); /* cancel the address device command */ ret = xhci_cancel_cmd(xhci, NULL, cmd_trb); if (ret < 0) @@ -3804,26 +3805,27 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, switch (virt_dev->cmd_status) { case COMP_CTX_STATE: case COMP_EBADSLT: - xhci_err(xhci, "Setup ERROR: address device command for slot %d.\n", - udev->slot_id); + xhci_err(xhci, "Setup ERROR: setup %s command for slot %d.\n", + act, udev->slot_id); ret = -EINVAL; break; case COMP_TX_ERR: - dev_warn(&udev->dev, "Device not responding to set address.\n"); + dev_warn(&udev->dev, "Device not responding to setup %s.\n", act); ret = -EPROTO; break; case COMP_DEV_ERR: - dev_warn(&udev->dev, "ERROR: Incompatible device for address " - "device command.\n"); + dev_warn(&udev->dev, + "ERROR: Incompatible device for setup %s command\n", act); ret = -ENODEV; break; case COMP_SUCCESS: xhci_dbg_trace(xhci, trace_xhci_dbg_address, - "Successful Address Device command"); + "Successful setup %s command", act); break; default: - xhci_err(xhci, "ERROR: unexpected command completion " - "code 0x%x.\n", virt_dev->cmd_status); + xhci_err(xhci, + "ERROR: unexpected setup %s command completion code 0x%x.\n", + act, virt_dev->cmd_status); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); trace_xhci_address_ctx(xhci, virt_dev->out_ctx, 1); -- cgit v1.2.3 From 1f2d45319922cdcf1f2a6f1f32f3afb206fdaaf7 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Nov 2013 13:47:25 -0200 Subject: drm/i915: disable interrupts when enabling PC8 The plan is to merge PC8 and D3 into a single feature, and when we're in D3 we won't get any hotplug interrupt anyway, so leaving them enable doesn't make sense, and it also brings us a problem. The problem is that we get a hotplug interrupt right when we we wake up from D3, when we're still waking up everything. If we fully disable interrupts we won't get this hotplug interrupt, so we won't have problems. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 74918e7afeb5..1d44c793bdf4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3900,8 +3900,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev) dev_priv->pc8.regsave.gtier = I915_READ(GTIER); dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR); - ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB); - ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT); + ironlake_disable_display_irq(dev_priv, 0xffffffff); + ibx_disable_display_interrupt(dev_priv, 0xffffffff); ilk_disable_gt_irq(dev_priv, 0xffffffff); snb_disable_pm_irq(dev_priv, 0xffffffff); @@ -3915,34 +3915,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; unsigned long irqflags; - uint32_t val, expected; + uint32_t val; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); val = I915_READ(DEIMR); - expected = ~DE_PCH_EVENT_IVB; - WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected); + WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val); - val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT; - expected = ~SDE_HOTPLUG_MASK_CPT; - WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n", - val, expected); + val = I915_READ(SDEIMR); + WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val); val = I915_READ(GTIMR); - expected = 0xffffffff; - WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected); + WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val); val = I915_READ(GEN6_PMIMR); - expected = 0xffffffff; - WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val, - expected); + WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val); dev_priv->pc8.irqs_disabled = false; ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr); - ibx_enable_display_interrupt(dev_priv, - ~dev_priv->pc8.regsave.sdeimr & - ~SDE_HOTPLUG_MASK_CPT); + ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr); ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr); snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr); I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier); -- cgit v1.2.3 From 8771a7f80289bc08eac12c7d4f72627ff6552295 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Nov 2013 13:47:28 -0200 Subject: drm/i915: add runtime PM support on Haswell The code to enable/disable PC8 already takes care of saving and restoring all the registers we need to save/restore, so do a put() call when we enable PC8 and a get() call when we disable it. Ideally, in order to make it easier to add runtime PM support to other platforms, we should move some things from the PC8 code to the runtime PM code, but let's do this later, since we can make Haswell work right now. V2: - Rebase Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi [danvet: Don't actually enable runtime pm since I didn't merge all patches.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d3a3fba64361..7b1b18d8f45c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6656,6 +6656,8 @@ void hsw_enable_pc8_work(struct work_struct *__work) lpt_disable_clkout_dp(dev); hsw_pc8_disable_interrupts(dev); hsw_disable_lcpll(dev_priv, true, true); + + intel_runtime_pm_put(dev_priv); } static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv) @@ -6693,6 +6695,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Disabling package C8+\n"); + intel_runtime_pm_get(dev_priv); + hsw_restore_lcpll(dev_priv); hsw_pc8_restore_interrupts(dev); lpt_init_pch_refclk(dev); -- cgit v1.2.3 From 9b33600d52fab54df1aa82ea0d70c113060c293a Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 17:32:40 -0200 Subject: drm/i915: don't enable VDD just to enable the panel We just don't need this. This saves 250ms from every modeset on my machine. Reviewed-by: Rodrigo Vivi Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 86dc6ecd357f..a75ceb5132ed 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1122,9 +1122,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_panel_on(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, true); } WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE); -- cgit v1.2.3 From 4e34da4d4252f93a7bc66017a7577afb03c3cb8e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 10 Dec 2013 17:19:39 +0100 Subject: bgmac: start/stop PHY on netdev open/stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've realized that I need to call ethtool command to get Ethernet working after booting. Ex call: ethtool -s eth0 autoneg on It was fixing Ethernet even if auto-negotiation was already on. Adding calls to phy_start and phy_stop look like a real solution. Signed-off-by: Rafał Miłecki Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 0452937227ff..fd6a22e3dd75 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1141,6 +1141,8 @@ static int bgmac_open(struct net_device *net_dev) } napi_enable(&bgmac->napi); + phy_start(bgmac->phy_dev); + netif_carrier_on(net_dev); err_out: @@ -1153,6 +1155,8 @@ static int bgmac_stop(struct net_device *net_dev) netif_carrier_off(net_dev); + phy_stop(bgmac->phy_dev); + napi_disable(&bgmac->napi); bgmac_chip_intrs_off(bgmac); free_irq(bgmac->core->irq, net_dev); -- cgit v1.2.3 From 1b945aeef0b9cb5e98d682c310272b08198e54b5 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Wed, 11 Dec 2013 11:04:36 +0900 Subject: zsmalloc: add Kconfig for enabling page table method Zsmalloc has two methods 1) copy-based and 2) pte based to access objects that span two pages. You can see history why we supported two approach from [1]. But it was bad choice that adding hard coding to select arch which want to use pte based method because there are lots of SoC in an architecure and they can have different cache size, CPU speed and so on so it would be better to expose it to user as selectable Kconfig option like Andrew Morton suggested. [1] https://lkml.org/lkml/2012/7/11/58 Acked-by: Nitin Gupta Reviewed-by: Konrad Rzeszutek Wilk Signed-off-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/Kconfig | 13 +++++++++++++ drivers/staging/zsmalloc/zsmalloc-main.c | 19 ++++--------------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig index 0ae13cd0908e..9d1f2a24ad62 100644 --- a/drivers/staging/zsmalloc/Kconfig +++ b/drivers/staging/zsmalloc/Kconfig @@ -9,3 +9,16 @@ config ZSMALLOC non-standard allocator interface where a handle, not a pointer, is returned by an alloc(). This handle must be mapped in order to access the allocated space. + +config PGTABLE_MAPPING + bool "Use page table mapping to access object in zsmalloc" + depends on ZSMALLOC + help + By default, zsmalloc uses a copy-based object mapping method to + access allocations that span two pages. However, if a particular + architecture (ex, ARM) performs VM mapping faster than copying, + then you should select this. This causes zsmalloc to use page table + mapping rather than copying for object mapping. + + You can check speed with zsmalloc benchmark[1]. + [1] https://github.com/spartacus06/zsmalloc diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 3b950e5a918f..5bd53a835f6d 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -218,19 +218,8 @@ struct zs_pool { #define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1) #define FULLNESS_MASK ((1 << FULLNESS_BITS) - 1) -/* - * By default, zsmalloc uses a copy-based object mapping method to access - * allocations that span two pages. However, if a particular architecture - * performs VM mapping faster than copying, then it should be added here - * so that USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use - * page table mapping rather than copying for object mapping. - */ -#if defined(CONFIG_ARM) && !defined(MODULE) -#define USE_PGTABLE_MAPPING -#endif - struct mapping_area { -#ifdef USE_PGTABLE_MAPPING +#ifdef CONFIG_PGTABLE_MAPPING struct vm_struct *vm; /* vm area for mapping object that span pages */ #else char *vm_buf; /* copy buffer for objects that span pages */ @@ -631,7 +620,7 @@ static struct page *find_get_zspage(struct size_class *class) return page; } -#ifdef USE_PGTABLE_MAPPING +#ifdef CONFIG_PGTABLE_MAPPING static inline int __zs_cpu_up(struct mapping_area *area) { /* @@ -669,7 +658,7 @@ static inline void __zs_unmap_object(struct mapping_area *area, unmap_kernel_range(addr, PAGE_SIZE * 2); } -#else /* USE_PGTABLE_MAPPING */ +#else /* CONFIG_PGTABLE_MAPPING */ static inline int __zs_cpu_up(struct mapping_area *area) { @@ -747,7 +736,7 @@ out: pagefault_enable(); } -#endif /* USE_PGTABLE_MAPPING */ +#endif /* CONFIG_PGTABLE_MAPPING */ static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) -- cgit v1.2.3 From c3e3e88adccb3119b69484c56798ec616307a94f Mon Sep 17 00:00:00 2001 From: Nitin Cupta Date: Wed, 11 Dec 2013 11:04:37 +0900 Subject: zsmalloc: add more comment This patch adds lots of comments and it will help others to review and enhance. Signed-off-by: Seth Jennings Signed-off-by: Nitin Gupta Signed-off-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 66 +++++++++++++++++++++++++++----- drivers/staging/zsmalloc/zsmalloc.h | 9 ++++- 2 files changed, 64 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 5bd53a835f6d..b453d84af7b5 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -10,16 +10,14 @@ * Released under the terms of GNU General Public License Version 2.0 */ - /* - * This allocator is designed for use with zcache and zram. Thus, the - * allocator is supposed to work well under low memory conditions. In - * particular, it never attempts higher order page allocation which is - * very likely to fail under memory pressure. On the other hand, if we - * just use single (0-order) pages, it would suffer from very high - * fragmentation -- any object of size PAGE_SIZE/2 or larger would occupy - * an entire page. This was one of the major issues with its predecessor - * (xvmalloc). + * This allocator is designed for use with zram. Thus, the allocator is + * supposed to work well under low memory conditions. In particular, it + * never attempts higher order page allocation which is very likely to + * fail under memory pressure. On the other hand, if we just use single + * (0-order) pages, it would suffer from very high fragmentation -- + * any object of size PAGE_SIZE/2 or larger would occupy an entire page. + * This was one of the major issues with its predecessor (xvmalloc). * * To overcome these issues, zsmalloc allocates a bunch of 0-order pages * and links them together using various 'struct page' fields. These linked @@ -27,6 +25,21 @@ * page boundaries. The code refers to these linked pages as a single entity * called zspage. * + * For simplicity, zsmalloc can only allocate objects of size up to PAGE_SIZE + * since this satisfies the requirements of all its current users (in the + * worst case, page is incompressible and is thus stored "as-is" i.e. in + * uncompressed form). For allocation requests larger than this size, failure + * is returned (see zs_malloc). + * + * Additionally, zs_malloc() does not return a dereferenceable pointer. + * Instead, it returns an opaque handle (unsigned long) which encodes actual + * location of the allocated object. The reason for this indirection is that + * zsmalloc does not keep zspages permanently mapped since that would cause + * issues on 32-bit systems where the VA region for kernel space mappings + * is very small. So, before using the allocating memory, the object has to + * be mapped using zs_map_object() to get a usable pointer and subsequently + * unmapped using zs_unmap_object(). + * * Following is how we use various fields and flags of underlying * struct page(s) to form a zspage. * @@ -98,7 +111,7 @@ /* * Object location (, ) is encoded as - * as single (void *) handle value. + * as single (unsigned long) handle value. * * Note that object index is relative to system * page it is stored in, so for each sub-page belonging @@ -264,6 +277,13 @@ static void set_zspage_mapping(struct page *page, unsigned int class_idx, page->mapping = (struct address_space *)m; } +/* + * zsmalloc divides the pool into various size classes where each + * class maintains a list of zspages where each zspage is divided + * into equal sized chunks. Each allocation falls into one of these + * classes depending on its size. This function returns index of the + * size class which has chunk size big enough to hold the give size. + */ static int get_size_class_index(int size) { int idx = 0; @@ -275,6 +295,13 @@ static int get_size_class_index(int size) return idx; } +/* + * For each size class, zspages are divided into different groups + * depending on how "full" they are. This was done so that we could + * easily find empty or nearly empty zspages when we try to shrink + * the pool (not yet implemented). This function returns fullness + * status of the given page. + */ static enum fullness_group get_fullness_group(struct page *page) { int inuse, max_objects; @@ -296,6 +323,12 @@ static enum fullness_group get_fullness_group(struct page *page) return fg; } +/* + * Each size class maintains various freelists and zspages are assigned + * to one of these freelists based on the number of live objects they + * have. This functions inserts the given zspage into the freelist + * identified by . + */ static void insert_zspage(struct page *page, struct size_class *class, enum fullness_group fullness) { @@ -313,6 +346,10 @@ static void insert_zspage(struct page *page, struct size_class *class, *head = page; } +/* + * This function removes the given zspage from the freelist identified + * by . + */ static void remove_zspage(struct page *page, struct size_class *class, enum fullness_group fullness) { @@ -334,6 +371,15 @@ static void remove_zspage(struct page *page, struct size_class *class, list_del_init(&page->lru); } +/* + * Each size class maintains zspages in different fullness groups depending + * on the number of live objects they contain. When allocating or freeing + * objects, the fullness status of the page can change, say, from ALMOST_FULL + * to ALMOST_EMPTY when freeing an object. This function checks if such + * a status change has occurred for the given page and accordingly moves the + * page from the freelist of the old fullness group to that of the new + * fullness group. + */ static enum fullness_group fix_fullness_group(struct zs_pool *pool, struct page *page) { diff --git a/drivers/staging/zsmalloc/zsmalloc.h b/drivers/staging/zsmalloc/zsmalloc.h index fbe6bec421aa..c2eb174b97ee 100644 --- a/drivers/staging/zsmalloc/zsmalloc.h +++ b/drivers/staging/zsmalloc/zsmalloc.h @@ -18,12 +18,19 @@ /* * zsmalloc mapping modes * - * NOTE: These only make a difference when a mapped object spans pages + * NOTE: These only make a difference when a mapped object spans pages. + * They also have no effect when PGTABLE_MAPPING is selected. */ enum zs_mapmode { ZS_MM_RW, /* normal read-write mapping */ ZS_MM_RO, /* read-only (no copy-out at unmap time) */ ZS_MM_WO /* write-only (no copy-in at map time) */ + /* + * NOTE: ZS_MM_WO should only be used for initializing new + * (uninitialized) allocations. Partial writes to already + * initialized allocations should use ZS_MM_RW to preserve the + * existing data. + */ }; struct zs_pool; -- cgit v1.2.3 From 32d3b6de6817359311eb6b5a2de0173f3357321f Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 9 Dec 2013 22:56:53 +0800 Subject: staging/lustre: remove server macros from lustre_net.h These macros are only used on server side. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_net.h | 234 --------------------- 1 file changed, 234 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 6c5479b2d715..d8d088035428 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -264,241 +264,7 @@ #define LDLM_MAXREQSIZE (5 * 1024) #define LDLM_MAXREPSIZE (1024) - /* - * MDS threads constants: - * - * Please see examples in "Thread Constants", MDS threads number will be at - * the comparable level of old versions, unless the server has many cores. - */ -#ifndef MDS_MAX_THREADS -#define MDS_MAX_THREADS 1024 -#define MDS_MAX_OTHR_THREADS 256 - -#else /* MDS_MAX_THREADS */ -#if MDS_MAX_THREADS < PTLRPC_NTHRS_INIT -#undef MDS_MAX_THREADS -#define MDS_MAX_THREADS PTLRPC_NTHRS_INIT -#endif -#define MDS_MAX_OTHR_THREADS max(PTLRPC_NTHRS_INIT, MDS_MAX_THREADS / 2) -#endif - -/* default service */ -#define MDS_THR_FACTOR 8 -#define MDS_NTHRS_INIT PTLRPC_NTHRS_INIT -#define MDS_NTHRS_MAX MDS_MAX_THREADS -#define MDS_NTHRS_BASE min(64, MDS_NTHRS_MAX) - -/* read-page service */ -#define MDS_RDPG_THR_FACTOR 4 -#define MDS_RDPG_NTHRS_INIT PTLRPC_NTHRS_INIT -#define MDS_RDPG_NTHRS_MAX MDS_MAX_OTHR_THREADS -#define MDS_RDPG_NTHRS_BASE min(48, MDS_RDPG_NTHRS_MAX) - -/* these should be removed when we remove setattr service in the future */ -#define MDS_SETA_THR_FACTOR 4 -#define MDS_SETA_NTHRS_INIT PTLRPC_NTHRS_INIT -#define MDS_SETA_NTHRS_MAX MDS_MAX_OTHR_THREADS -#define MDS_SETA_NTHRS_BASE min(48, MDS_SETA_NTHRS_MAX) - -/* non-affinity threads */ -#define MDS_OTHR_NTHRS_INIT PTLRPC_NTHRS_INIT -#define MDS_OTHR_NTHRS_MAX MDS_MAX_OTHR_THREADS - -#define MDS_NBUFS 64 - -/** - * Assume file name length = FNAME_MAX = 256 (true for ext3). - * path name length = PATH_MAX = 4096 - * LOV MD size max = EA_MAX = 24 * 2000 - * (NB: 24 is size of lov_ost_data) - * LOV LOGCOOKIE size max = 32 * 2000 - * (NB: 32 is size of llog_cookie) - * symlink: FNAME_MAX + PATH_MAX <- largest - * link: FNAME_MAX + PATH_MAX (mds_rec_link < mds_rec_create) - * rename: FNAME_MAX + FNAME_MAX - * open: FNAME_MAX + EA_MAX - * - * MDS_MAXREQSIZE ~= 4736 bytes = - * lustre_msg + ldlm_request + mdt_body + mds_rec_create + FNAME_MAX + PATH_MAX - * MDS_MAXREPSIZE ~= 8300 bytes = lustre_msg + llog_header - * - * Realistic size is about 512 bytes (20 character name + 128 char symlink), - * except in the open case where there are a large number of OSTs in a LOV. - */ -#define MDS_MAXREQSIZE (5 * 1024) /* >= 4736 */ -#define MDS_MAXREPSIZE (9 * 1024) /* >= 8300 */ - -/** - * MDS incoming request with LOV EA - * 24 = sizeof(struct lov_ost_data), i.e: replay of opencreate - */ -#define MDS_LOV_MAXREQSIZE max(MDS_MAXREQSIZE, \ - 362 + LOV_MAX_STRIPE_COUNT * 24) -/** - * MDS outgoing reply with LOV EA - * - * NB: max reply size Lustre 2.4+ client can get from old MDS is: - * LOV_MAX_STRIPE_COUNT * (llog_cookie + lov_ost_data) + extra bytes - * - * but 2.4 or later MDS will never send reply with llog_cookie to any - * version client. This macro is defined for server side reply buffer size. - */ -#define MDS_LOV_MAXREPSIZE MDS_LOV_MAXREQSIZE - -/** - * This is the size of a maximum REINT_SETXATTR request: - * - * lustre_msg 56 (32 + 4 x 5 + 4) - * ptlrpc_body 184 - * mdt_rec_setxattr 136 - * lustre_capa 120 - * name 256 (XATTR_NAME_MAX) - * value 65536 (XATTR_SIZE_MAX) - */ -#define MDS_EA_MAXREQSIZE 66288 - -/** - * These are the maximum request and reply sizes (rounded up to 1 KB - * boundaries) for the "regular" MDS_REQUEST_PORTAL and MDS_REPLY_PORTAL. - */ -#define MDS_REG_MAXREQSIZE (((max(MDS_EA_MAXREQSIZE, \ - MDS_LOV_MAXREQSIZE) + 1023) >> 10) << 10) -#define MDS_REG_MAXREPSIZE MDS_REG_MAXREQSIZE - -/** - * The update request includes all of updates from the create, which might - * include linkea (4K maxim), together with other updates, we set it to 9K: - * lustre_msg + ptlrpc_body + UPDATE_BUF_SIZE (8K) - */ -#define MDS_OUT_MAXREQSIZE (9 * 1024) -#define MDS_OUT_MAXREPSIZE MDS_MAXREPSIZE - -/** MDS_BUFSIZE = max_reqsize (w/o LOV EA) + max sptlrpc payload size */ -#define MDS_BUFSIZE max(MDS_MAXREQSIZE + SPTLRPC_MAX_PAYLOAD, \ - 8 * 1024) - -/** - * MDS_REG_BUFSIZE should at least be MDS_REG_MAXREQSIZE + SPTLRPC_MAX_PAYLOAD. - * However, we need to allocate a much larger buffer for it because LNet - * requires each MD(rqbd) has at least MDS_REQ_MAXREQSIZE bytes left to avoid - * dropping of maximum-sized incoming request. So if MDS_REG_BUFSIZE is only a - * little larger than MDS_REG_MAXREQSIZE, then it can only fit in one request - * even there are about MDS_REG_MAX_REQSIZE bytes left in a rqbd, and memory - * utilization is very low. - * - * In the meanwhile, size of rqbd can't be too large, because rqbd can't be - * reused until all requests fit in it have been processed and released, - * which means one long blocked request can prevent the rqbd be reused. - * Now we set request buffer size to 160 KB, so even each rqbd is unlinked - * from LNet with unused 65 KB, buffer utilization will be about 59%. - * Please check LU-2432 for details. - */ -#define MDS_REG_BUFSIZE max(MDS_REG_MAXREQSIZE + SPTLRPC_MAX_PAYLOAD, \ - 160 * 1024) - -/** - * MDS_OUT_BUFSIZE = max_out_reqsize + max sptlrpc payload (~1K) which is - * about 10K, for the same reason as MDS_REG_BUFSIZE, we also give some - * extra bytes to each request buffer to improve buffer utilization rate. - */ -#define MDS_OUT_BUFSIZE max(MDS_OUT_MAXREQSIZE + SPTLRPC_MAX_PAYLOAD, \ - 24 * 1024) - -/** FLD_MAXREQSIZE == lustre_msg + __u32 padding + ptlrpc_body + opc */ -#define FLD_MAXREQSIZE (160) - -/** FLD_MAXREPSIZE == lustre_msg + ptlrpc_body */ -#define FLD_MAXREPSIZE (152) -#define FLD_BUFSIZE (1 << 12) - -/** - * SEQ_MAXREQSIZE == lustre_msg + __u32 padding + ptlrpc_body + opc + lu_range + - * __u32 padding */ -#define SEQ_MAXREQSIZE (160) - -/** SEQ_MAXREPSIZE == lustre_msg + ptlrpc_body + lu_range */ -#define SEQ_MAXREPSIZE (152) -#define SEQ_BUFSIZE (1 << 12) - -/** MGS threads must be >= 3, see bug 22458 comment #28 */ -#define MGS_NTHRS_INIT (PTLRPC_NTHRS_INIT + 1) -#define MGS_NTHRS_MAX 32 - -#define MGS_NBUFS 64 -#define MGS_BUFSIZE (8 * 1024) -#define MGS_MAXREQSIZE (7 * 1024) -#define MGS_MAXREPSIZE (9 * 1024) - - /* - * OSS threads constants: - * - * Given 8 as factor and 64 as base threads number - * - * example 1): - * On 8-core server configured to 2 partitions, we will have - * 64 + 8 * 4 = 96 threads for each partition, 192 total threads. - * - * example 2): - * On 32-core machine configured to 4 partitions, we will have - * 64 + 8 * 8 = 112 threads for each partition, so total threads number - * will be 112 * 4 = 448. - * - * example 3): - * On 64-core machine configured to 4 partitions, we will have - * 64 + 16 * 8 = 192 threads for each partition, so total threads number - * will be 192 * 4 = 768 which is above limit OSS_NTHRS_MAX(512), so we - * cut off the value to OSS_NTHRS_MAX(512) / 4 which is 128 threads - * for each partition. - * - * So we can see that with these constants, threads number wil be at the - * similar level of old versions, unless the server has many cores. - */ - /* depress threads factor for VM with small memory size */ -#define OSS_THR_FACTOR min_t(int, 8, \ - NUM_CACHEPAGES >> (28 - PAGE_CACHE_SHIFT)) -#define OSS_NTHRS_INIT (PTLRPC_NTHRS_INIT + 1) -#define OSS_NTHRS_BASE 64 -#define OSS_NTHRS_MAX 512 - -/* threads for handling "create" request */ -#define OSS_CR_THR_FACTOR 1 -#define OSS_CR_NTHRS_INIT PTLRPC_NTHRS_INIT -#define OSS_CR_NTHRS_BASE 8 -#define OSS_CR_NTHRS_MAX 64 - -/** - * OST_IO_MAXREQSIZE ~= - * lustre_msg + ptlrpc_body + obdo + obd_ioobj + - * DT_MAX_BRW_PAGES * niobuf_remote - * - * - single object with 16 pages is 512 bytes - * - OST_IO_MAXREQSIZE must be at least 1 page of cookies plus some spillover - * - Must be a multiple of 1024 - * - actual size is about 18K - */ -#define _OST_MAXREQSIZE_SUM (sizeof(struct lustre_msg) + \ - sizeof(struct ptlrpc_body) + \ - sizeof(struct obdo) + \ - sizeof(struct obd_ioobj) + \ - sizeof(struct niobuf_remote) * DT_MAX_BRW_PAGES) -/** - * FIEMAP request can be 4K+ for now - */ #define OST_MAXREQSIZE (5 * 1024) -#define OST_IO_MAXREQSIZE max_t(int, OST_MAXREQSIZE, \ - (((_OST_MAXREQSIZE_SUM - 1) | (1024 - 1)) + 1)) - -#define OST_MAXREPSIZE (9 * 1024) -#define OST_IO_MAXREPSIZE OST_MAXREPSIZE - -#define OST_NBUFS 64 -/** OST_BUFSIZE = max_reqsize + max sptlrpc payload size */ -#define OST_BUFSIZE max_t(int, OST_MAXREQSIZE + 1024, 16 * 1024) -/** - * OST_IO_MAXREQSIZE is 18K, giving extra 46K can increase buffer utilization - * rate of request buffer, please check comment of MDS_LOV_BUFSIZE for details. - */ -#define OST_IO_BUFSIZE max_t(int, OST_IO_MAXREQSIZE + 1024, 64 * 1024) /* Macro to hide a typecast. */ #define ptlrpc_req_async_args(req) ((void *)&req->rq_async_args) -- cgit v1.2.3 From e75fb87f861192ed0fac5d2758bcc752e85ca6e7 Mon Sep 17 00:00:00 2001 From: Doug Oucharek Date: Mon, 9 Dec 2013 22:56:54 +0800 Subject: staging/lustre/lnet: Add LNet Router Priority parameter This change adds a priority parameter to the route module settings. This paramter can be >= 0. Like hops, the lower the prioirty number the higher the priority. So lower numbered priorities will be selected over higher numbers. Lustre-change: http://review.whamcloud.com/5663 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2934 Signed-off-by: Doug Oucharek Reviewed-by: Andreas Dilger Reviewed-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_ioctl.h | 1 + .../staging/lustre/include/linux/lnet/lib-lnet.h | 5 +-- .../staging/lustre/include/linux/lnet/lib-types.h | 2 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 5 +-- drivers/staging/lustre/lnet/lnet/config.c | 39 +++++++++++++++++++++- drivers/staging/lustre/lnet/lnet/lib-move.c | 6 ++++ drivers/staging/lustre/lnet/lnet/router.c | 19 ++++++----- drivers/staging/lustre/lnet/lnet/router_proc.c | 16 +++++---- 8 files changed, 72 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index dd1a1f1ef1f6..74dda57b98a8 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -69,6 +69,7 @@ struct libcfs_ioctl_data { char ioc_bulk[0]; }; +#define ioc_priority ioc_u32[0] struct libcfs_ioctl_hdr { __u32 ioc_len; diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index bf301048c7ab..3ac2bb5fd2db 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -650,12 +650,13 @@ extern lnet_ni_t *lnet_net2ni(__u32 net); int lnet_notify(lnet_ni_t *ni, lnet_nid_t peer, int alive, cfs_time_t when); void lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, cfs_time_t when); -int lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway_nid); +int lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway_nid, + unsigned int priority); int lnet_check_routes(void); int lnet_del_route(__u32 net, lnet_nid_t gw_nid); void lnet_destroy_routes(void); int lnet_get_route(int idx, __u32 *net, __u32 *hops, - lnet_nid_t *gateway, __u32 *alive); + lnet_nid_t *gateway, __u32 *alive, __u32 *priority); void lnet_proc_init(void); void lnet_proc_fini(void); int lnet_rtrpools_alloc(int im_a_router); diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index e579e7ed5070..dd8edcf1b5c0 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -478,7 +478,6 @@ typedef struct lnet_peer { lnet_rc_data_t *lp_rcd; /* router checker state */ } lnet_peer_t; - /* peer hash size */ #define LNET_PEER_HASH_BITS 9 #define LNET_PEER_HASH_SIZE (1 << LNET_PEER_HASH_BITS) @@ -504,6 +503,7 @@ typedef struct { int lr_seq; /* sequence for round-robin */ unsigned int lr_downis; /* number of down NIs */ unsigned int lr_hops; /* how far I am */ + unsigned int lr_priority; /* route priority */ } lnet_route_t; #define LNET_REMOTE_NETS_HASH_DEFAULT (1U << 7) diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 5719959c8005..c562ff3e9283 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1436,7 +1436,7 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_ADD_ROUTE: rc = lnet_add_route(data->ioc_net, data->ioc_count, - data->ioc_nid); + data->ioc_nid, data->ioc_priority); return (rc != 0) ? rc : lnet_check_routes(); case IOC_LIBCFS_DEL_ROUTE: @@ -1445,7 +1445,8 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_GET_ROUTE: return lnet_get_route(data->ioc_count, &data->ioc_net, &data->ioc_count, - &data->ioc_nid, &data->ioc_flags); + &data->ioc_nid, &data->ioc_flags, + &data->ioc_priority); case IOC_LIBCFS_NOTIFY_ROUTER: return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, cfs_time_current() - diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index de323f779db8..6a07b0a65d12 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -603,6 +603,37 @@ lnet_parse_hops(char *str, unsigned int *hops) *hops > 0 && *hops < 256); } +#define LNET_PRIORITY_SEPARATOR (':') + +int +lnet_parse_priority(char *str, unsigned int *priority, char **token) +{ + int nob; + char *sep; + int len; + + sep = strchr(str, LNET_PRIORITY_SEPARATOR); + if (sep == NULL) { + *priority = 0; + return 0; + } + len = strlen(sep + 1); + + if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) { + /* Update the caller's token pointer so it treats the found + priority as the token to report in the error message. */ + *token += sep - str + 1; + return -1; + } + + CDEBUG(D_NET, "gateway %s, priority %d, nob %d\n", str, *priority, nob); + + /* + * Change priority separator to \0 to be able to parse NID + */ + *sep = '\0'; + return 0; +} int lnet_parse_route(char *str, int *im_a_router) @@ -624,6 +655,7 @@ lnet_parse_route(char *str, int *im_a_router) int myrc = -1; unsigned int hops; int got_hops = 0; + unsigned int priority = 0; INIT_LIST_HEAD(&gateways); INIT_LIST_HEAD(&nets); @@ -691,6 +723,11 @@ lnet_parse_route(char *str, int *im_a_router) LNET_NETTYP(net) == LOLND) goto token_error; } else { + rc = lnet_parse_priority(ltb->ltb_text, + &priority, &token); + if (rc < 0) + goto token_error; + nid = libcfs_str2nid(ltb->ltb_text); if (nid == LNET_NID_ANY || LNET_NETTYP(LNET_NIDNET(nid)) == LOLND) @@ -720,7 +757,7 @@ lnet_parse_route(char *str, int *im_a_router) continue; } - rc = lnet_add_route(net, hops, nid); + rc = lnet_add_route(net, hops, nid, priority); if (rc != 0) { CERROR("Can't create route to %s via %s\n", libcfs_net2str(net), diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 2d611136da8f..bbf43ae04ed0 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -1074,6 +1074,12 @@ lnet_compare_routes(lnet_route_t *r1, lnet_route_t *r2) lnet_peer_t *p1 = r1->lr_gateway; lnet_peer_t *p2 = r2->lr_gateway; + if (r1->lr_priority < r2->lr_priority) + return 1; + + if (r1->lr_priority > r2->lr_priority) + return -1; + if (r1->lr_hops < r2->lr_hops) return 1; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 80b5ed1e9d64..d1ee44232eef 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -301,7 +301,8 @@ lnet_add_route_to_rnet (lnet_remotenet_t *rnet, lnet_route_t *route) } int -lnet_add_route (__u32 net, unsigned int hops, lnet_nid_t gateway) +lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, + unsigned int priority) { struct list_head *e; lnet_remotenet_t *rnet; @@ -311,8 +312,8 @@ lnet_add_route (__u32 net, unsigned int hops, lnet_nid_t gateway) int add_route; int rc; - CDEBUG(D_NET, "Add route: net %s hops %u gw %s\n", - libcfs_net2str(net), hops, libcfs_nid2str(gateway)); + CDEBUG(D_NET, "Add route: net %s hops %u priority %u gw %s\n", + libcfs_net2str(net), hops, priority, libcfs_nid2str(gateway)); if (gateway == LNET_NID_ANY || LNET_NETTYP(LNET_NIDNET(gateway)) == LOLND || @@ -342,6 +343,7 @@ lnet_add_route (__u32 net, unsigned int hops, lnet_nid_t gateway) rnet->lrn_net = net; route->lr_hops = hops; route->lr_net = net; + route->lr_priority = priority; lnet_net_lock(LNET_LOCK_EX); @@ -552,7 +554,7 @@ lnet_destroy_routes (void) int lnet_get_route(int idx, __u32 *net, __u32 *hops, - lnet_nid_t *gateway, __u32 *alive) + lnet_nid_t *gateway, __u32 *alive, __u32 *priority) { struct list_head *e1; struct list_head *e2; @@ -574,10 +576,11 @@ lnet_get_route(int idx, __u32 *net, __u32 *hops, lr_list); if (idx-- == 0) { - *net = rnet->lrn_net; - *hops = route->lr_hops; - *gateway = route->lr_gateway->lp_nid; - *alive = route->lr_gateway->lp_alive; + *net = rnet->lrn_net; + *hops = route->lr_hops; + *priority = route->lr_priority; + *gateway = route->lr_gateway->lp_nid; + *alive = route->lr_gateway->lp_alive; lnet_net_unlock(cpt); return 0; } diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index e4fe7a116fb5..20d53e08705e 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -174,8 +174,8 @@ int LL_PROC_PROTO(proc_lnet_routes) the_lnet.ln_routing ? "enabled" : "disabled"); LASSERT(tmpstr + tmpsiz - s > 0); - s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4s %7s %s\n", - "net", "hops", "state", "router"); + s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4s %8s %7s %s\n", + "net", "hops", "priority", "state", "router"); LASSERT(tmpstr + tmpsiz - s > 0); lnet_net_lock(0); @@ -229,14 +229,16 @@ int LL_PROC_PROTO(proc_lnet_routes) } if (route != NULL) { - __u32 net = rnet->lrn_net; - unsigned int hops = route->lr_hops; - lnet_nid_t nid = route->lr_gateway->lp_nid; - int alive = route->lr_gateway->lp_alive; + __u32 net = rnet->lrn_net; + unsigned int hops = route->lr_hops; + unsigned int priority = route->lr_priority; + lnet_nid_t nid = route->lr_gateway->lp_nid; + int alive = route->lr_gateway->lp_alive; s += snprintf(s, tmpstr + tmpsiz - s, - "%-8s %4u %7s %s\n", + "%-8s %4u %8u %7s %s\n", libcfs_net2str(net), hops, + priority, alive ? "up" : "down", libcfs_nid2str(nid)); LASSERT(tmpstr + tmpsiz - s > 0); -- cgit v1.2.3 From a720b790627c2e840f7eb58cf53fefc0428cc758 Mon Sep 17 00:00:00 2001 From: JC Lafoucriere Date: Mon, 9 Dec 2013 22:56:55 +0800 Subject: staging/lustre/api: HSM import uses new released pattern Import creates a released file using new RAID pattern flag Import used a new ioctl() to implement the import in the client kernel. Lustre-change: http://review.whamcloud.com/6536 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3363 Signed-off-by: JC Lafoucriere Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong [Fix up kuid_t/guid_t conversion in llite/file.c -- Peng Tao] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_user.h | 17 ++- drivers/staging/lustre/lustre/llite/file.c | 118 +++++++++++++++++---- .../staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 24 +++-- drivers/staging/lustre/lustre/ptlrpc/wiretest.c | 58 ++++++++++ 5 files changed, 187 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index c7abb802a789..6b6c0240e824 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -244,9 +244,9 @@ struct ost_id { #define LL_IOC_LMV_SETSTRIPE _IOWR('f', 240, struct lmv_user_md) #define LL_IOC_LMV_GETSTRIPE _IOWR('f', 241, struct lmv_user_md) #define LL_IOC_REMOVE_ENTRY _IOWR('f', 242, __u64) - #define LL_IOC_SET_LEASE _IOWR('f', 243, long) #define LL_IOC_GET_LEASE _IO('f', 244) +#define LL_IOC_HSM_IMPORT _IOWR('f', 245, struct hsm_user_import) #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 @@ -1130,6 +1130,21 @@ static inline int hal_size(struct hsm_action_list *hal) return sz; } +/* HSM file import + * describe the attributes to be set on imported file + */ +struct hsm_user_import { + __u64 hui_size; + __u64 hui_atime; + __u64 hui_mtime; + __u32 hui_atime_ns; + __u32 hui_mtime_ns; + __u32 hui_uid; + __u32 hui_gid; + __u32 hui_mode; + __u32 hui_archive_id; +}; + /* Copytool progress reporting */ #define HP_FLAG_COMPLETED 0x01 #define HP_FLAG_RETRY 0x02 diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 996c19d7370c..c12821aedc2f 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2085,6 +2085,86 @@ free: return rc; } +static int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss) +{ + struct md_op_data *op_data; + int rc; + + /* Non-root users are forbidden to set or clear flags which are + * NOT defined in HSM_USER_MASK. */ + if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) && + !cfs_capable(CFS_CAP_SYS_ADMIN)) + return -EPERM; + + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, + LUSTRE_OPC_ANY, hss); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + + rc = obd_iocontrol(LL_IOC_HSM_STATE_SET, ll_i2mdexp(inode), + sizeof(*op_data), op_data, NULL); + + ll_finish_md_op_data(op_data); + + return rc; +} + +static int ll_hsm_import(struct inode *inode, struct file *file, + struct hsm_user_import *hui) +{ + struct hsm_state_set *hss = NULL; + struct iattr *attr = NULL; + int rc; + + + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + + /* set HSM flags */ + OBD_ALLOC_PTR(hss); + if (hss == NULL) + GOTO(out, rc = -ENOMEM); + + hss->hss_valid = HSS_SETMASK | HSS_ARCHIVE_ID; + hss->hss_archive_id = hui->hui_archive_id; + hss->hss_setmask = HS_ARCHIVED | HS_EXISTS | HS_RELEASED; + rc = ll_hsm_state_set(inode, hss); + if (rc != 0) + GOTO(out, rc); + + OBD_ALLOC_PTR(attr); + if (attr == NULL) + GOTO(out, rc = -ENOMEM); + + attr->ia_mode = hui->hui_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + attr->ia_mode |= S_IFREG; + attr->ia_uid = make_kuid(&init_user_ns, hui->hui_uid); + attr->ia_gid = make_kgid(&init_user_ns, hui->hui_gid); + attr->ia_size = hui->hui_size; + attr->ia_mtime.tv_sec = hui->hui_mtime; + attr->ia_mtime.tv_nsec = hui->hui_mtime_ns; + attr->ia_atime.tv_sec = hui->hui_atime; + attr->ia_atime.tv_nsec = hui->hui_atime_ns; + + attr->ia_valid = ATTR_SIZE | ATTR_MODE | ATTR_FORCE | + ATTR_UID | ATTR_GID | + ATTR_MTIME | ATTR_MTIME_SET | + ATTR_ATIME | ATTR_ATIME_SET; + + rc = ll_setattr_raw(file->f_dentry, attr, true); + if (rc == -ENODATA) + rc = 0; + +out: + if (hss != NULL) + OBD_FREE_PTR(hss); + + if (attr != NULL) + OBD_FREE_PTR(attr); + + return rc; +} + long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct inode *inode = file->f_dentry->d_inode; @@ -2246,37 +2326,19 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return rc; } case LL_IOC_HSM_STATE_SET: { - struct md_op_data *op_data; struct hsm_state_set *hss; int rc; OBD_ALLOC_PTR(hss); if (hss == NULL) return -ENOMEM; + if (copy_from_user(hss, (char *)arg, sizeof(*hss))) { OBD_FREE_PTR(hss); return -EFAULT; } - /* Non-root users are forbidden to set or clear flags which are - * NOT defined in HSM_USER_MASK. */ - if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) - && !cfs_capable(CFS_CAP_SYS_ADMIN)) { - OBD_FREE_PTR(hss); - return -EPERM; - } - - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, hss); - if (IS_ERR(op_data)) { - OBD_FREE_PTR(hss); - return PTR_ERR(op_data); - } - - rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), - op_data, NULL); - - ll_finish_md_op_data(op_data); + rc = ll_hsm_state_set(inode, hss); OBD_FREE_PTR(hss); return rc; @@ -2389,7 +2451,23 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } } mutex_unlock(&lli->lli_och_mutex); + return rc; + } + case LL_IOC_HSM_IMPORT: { + struct hsm_user_import *hui; + + OBD_ALLOC_PTR(hui); + if (hui == NULL) + return -ENOMEM; + + if (copy_from_user(hui, (void *)arg, sizeof(*hui))) { + OBD_FREE_PTR(hui); + return -EFAULT; + } + + rc = ll_hsm_import(inode, file, hui); + OBD_FREE_PTR(hui); return rc; } default: { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 61bb69a80438..7ee5c02783f9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -851,7 +851,7 @@ void ll_kill_super(struct super_block *sb); struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock); struct inode *ll_inode_from_lock(struct ldlm_lock *lock); void ll_clear_inode(struct inode *inode); -int ll_setattr_raw(struct dentry *dentry, struct iattr *attr); +int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import); int ll_setattr(struct dentry *de, struct iattr *attr); int ll_statfs(struct dentry *de, struct kstatfs *sfs); int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 1a9678625af5..6cfdb9e4b74b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1364,8 +1364,10 @@ static int ll_setattr_ost(struct inode *inode, struct iattr *attr) * to the OST with the punch RPC, otherwise we do an explicit setattr RPC. * I don't believe it is possible to get e.g. ATTR_MTIME_SET and ATTR_SIZE * at the same time. + * + * In case of HSMimport, we only set attr on MDS. */ -int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) +int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) { struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); @@ -1374,10 +1376,12 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) bool file_is_released = false; int rc = 0, rc1 = 0; - CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, " - "valid %x\n", ll_get_fsname(inode->i_sb, NULL, 0), inode, + CDEBUG(D_VFSTRACE, + "%s: setattr inode %p/fid:"DFID + " from %llu to %llu, valid %x, hsm_import %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), inode, PFID(&lli->lli_fid), i_size_read(inode), attr->ia_size, - attr->ia_valid); + attr->ia_valid, hsm_import); if (attr->ia_valid & ATTR_SIZE) { /* Check new size against VFS/VM file size limit and rlimit */ @@ -1470,20 +1474,20 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) ccc_inode_lsm_put(inode, lsm); } - /* clear size attr for released file + /* if not in HSM import mode, clear size attr for released file * we clear the attribute send to MDT in op_data, not the original * received from caller in attr which is used later to * decide return code */ - if (file_is_released && (attr->ia_valid & ATTR_SIZE)) + if (file_is_released && (attr->ia_valid & ATTR_SIZE) && !hsm_import) op_data->op_attr.ia_valid &= ~ATTR_SIZE; rc = ll_md_setattr(dentry, op_data, &mod); if (rc) GOTO(out, rc); - /* truncate failed, others succeed */ + /* truncate failed (only when non HSM import), others succeed */ if (file_is_released) { - if (attr->ia_valid & ATTR_SIZE) + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) GOTO(out, rc = -ENODATA); else GOTO(out, rc = 0); @@ -1522,7 +1526,7 @@ out: if (!S_ISDIR(inode->i_mode)) { up_write(&lli->lli_trunc_sem); mutex_lock(&inode->i_mutex); - if (attr->ia_valid & ATTR_SIZE) + if ((attr->ia_valid & ATTR_SIZE) && !hsm_import) inode_dio_wait(inode); } @@ -1557,7 +1561,7 @@ int ll_setattr(struct dentry *de, struct iattr *attr) !(attr->ia_valid & ATTR_KILL_SGID)) attr->ia_valid |= ATTR_KILL_SGID; - return ll_setattr_raw(de, attr); + return ll_setattr_raw(de, attr, false); } int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index c2efd118ddf9..3aa445952024 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -4422,6 +4422,64 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct hsm_user_request *)0)->hur_user_item) == 0, "found %lld\n", (long long)(int)sizeof(((struct hsm_user_request *)0)->hur_user_item)); + /* Checks for struct hsm_user_import */ + LASSERTF(sizeof(struct hsm_user_import) == 48, "found %lld\n", + (long long)sizeof(struct hsm_user_import)); + LASSERTF(offsetof(struct hsm_user_import, hui_size) == 0, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_size)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_size) == 8, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_size)); + LASSERTF(offsetof(struct hsm_user_import, hui_uid) == 32, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_uid)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_uid) == 4, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_uid)); + LASSERTF(offsetof(struct hsm_user_import, hui_gid) == 36, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_gid)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_gid) == 4, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_gid)); + LASSERTF(offsetof(struct hsm_user_import, hui_mode) == 40, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_mode)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_mode) == 4, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_mode)); + LASSERTF(offsetof(struct hsm_user_import, hui_atime) == 8, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_atime)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_atime) == 8, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_atime)); + LASSERTF(offsetof(struct hsm_user_import, hui_atime_ns) == 24, + "found %lld\n", + (long long)(int)offsetof(struct hsm_user_import, hui_atime_ns)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_atime_ns) == 4, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_atime_ns)); + LASSERTF(offsetof(struct hsm_user_import, hui_mtime) == 16, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_mtime)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_mtime) == 8, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_mtime)); + LASSERTF(offsetof(struct hsm_user_import, hui_mtime_ns) == 28, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_mtime_ns)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_mtime_ns) == 4, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_mtime_ns)); + LASSERTF(offsetof(struct hsm_user_import, hui_archive_id) == 44, + "found %lld\n", + (long long)offsetof(struct hsm_user_import, hui_archive_id)); + LASSERTF(sizeof(((struct hsm_user_import *)0)->hui_archive_id) == 4, + "found %lld\n", + (long long)sizeof(((struct hsm_user_import *)0)->hui_archive_id)); + /* Checks for struct update_buf */ LASSERTF((int)sizeof(struct update_buf) == 8, "found %lld\n", (long long)(int)sizeof(struct update_buf)); -- cgit v1.2.3 From a7c6d5a6e7e50be7287c31a06c866b7853c6f80f Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Mon, 9 Dec 2013 22:56:56 +0800 Subject: staging/lustre/target: move OUT to the unified target code - Move OUT handler to the unified target code, so it can be used by both MDS and OST. Lustre-change: http://review.whamcloud.com/6763 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3467 Signed-off-by: Mikhail Pershin Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger [pick client side of change. target is mostly server side code -- PengTao] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_request.c | 32 +------------------------ 1 file changed, 1 insertion(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 0b432517afaf..d1ad91c34ddc 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2076,15 +2076,6 @@ int mdc_set_info_async(const struct lu_env *env, sptlrpc_import_flush_my_ctx(imp); return 0; } - if (KEY_IS(KEY_MDS_CONN)) { - /* mds-mds import */ - spin_lock(&imp->imp_lock); - imp->imp_server_timeout = 1; - spin_unlock(&imp->imp_lock); - imp->imp_client->cli_request_portal = MDS_MDS_PORTAL; - CDEBUG(D_OTHER, "%s: timeout / 2\n", exp->exp_obd->obd_name); - return 0; - } if (KEY_IS(KEY_CHANGELOG_CLEAR)) { rc = do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION, keylen, key, vallen, val, set); @@ -2594,27 +2585,6 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc, return 0; } -static int mdc_connect(const struct lu_env *env, - struct obd_export **exp, - struct obd_device *obd, struct obd_uuid *cluuid, - struct obd_connect_data *data, - void *localdata) -{ - struct obd_import *imp = obd->u.cli.cl_import; - - /* mds-mds import features */ - if (data && (data->ocd_connect_flags & OBD_CONNECT_MDS_MDS)) { - spin_lock(&imp->imp_lock); - imp->imp_server_timeout = 1; - spin_unlock(&imp->imp_lock); - imp->imp_client->cli_request_portal = MDS_MDS_PORTAL; - CDEBUG(D_OTHER, "%s: Set 'mds' portal and timeout\n", - obd->obd_name); - } - - return client_connect_import(env, exp, obd, cluuid, data, NULL); -} - struct obd_ops mdc_obd_ops = { .o_owner = THIS_MODULE, .o_setup = mdc_setup, @@ -2622,7 +2592,7 @@ struct obd_ops mdc_obd_ops = { .o_cleanup = mdc_cleanup, .o_add_conn = client_import_add_conn, .o_del_conn = client_import_del_conn, - .o_connect = mdc_connect, + .o_connect = client_connect_import, .o_disconnect = client_disconnect_export, .o_iocontrol = mdc_iocontrol, .o_set_info_async = mdc_set_info_async, -- cgit v1.2.3 From 97a062b419894851104f46aca8335dd4fa35eb2e Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Mon, 9 Dec 2013 22:56:57 +0800 Subject: staging/lustre/seq: remove seq_{query,handle} This is only part of the original Lustre tree commit. Main part of the original commit modifies server side code. Lustre-change: http://review.whamcloud.com/6765 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3467 Signed-off-by: Mikhail Pershin Reviewed-by: Alex Zhuravlev Reviewed-by: wangdi Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_fid.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index ff119532dafb..84a897eed1df 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -431,12 +431,6 @@ struct lu_server_seq { struct seq_server_site *lss_site; }; -struct com_thread_info; -int seq_query(struct com_thread_info *info); - -struct ptlrpc_request; -int seq_handle(struct ptlrpc_request *req); - /* Server methods */ int seq_server_init(struct lu_server_seq *seq, -- cgit v1.2.3 From 94a12b15e4c575e0aa0ba5e24a4f213163a823d0 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 8 Dec 2013 02:59:18 +0300 Subject: sh_eth: add R8A7791 support Add support for yet another ARM member of the R-Car family, R-Car M2, also known as R8A7791 -- it will share the code and data with previously added R8A7790. Despite the Ether devices in these SoCs are indistinguishable at least from the driver's point of view, we do introduce a new platform device ID "r8a7791-ether" unlike the wildcard ID used for R8A7778/9 SoCs, due to newly established policy for the Renesas SoCs. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/Kconfig | 2 +- drivers/net/ethernet/renesas/sh_eth.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index a30c4395b232..9e757c792d84 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -13,4 +13,4 @@ config SH_ETH Renesas SuperH Ethernet device driver. This driver supporting CPUs are: - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, - R8A7740, R8A777x and R8A7790. + R8A7740, R8A777x and R8A779x. diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 6761dde7007a..8601d0c638cc 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -395,8 +395,8 @@ static struct sh_eth_cpu_data r8a777x_data = { .hw_swap = 1, }; -/* R8A7790 */ -static struct sh_eth_cpu_data r8a7790_data = { +/* R8A7790/1 */ +static struct sh_eth_cpu_data r8a779x_data = { .set_duplex = sh_eth_set_duplex, .set_rate = sh_eth_set_rate_r8a777x, @@ -2810,7 +2810,8 @@ static struct platform_device_id sh_eth_id_table[] = { { "sh7763-gether", (kernel_ulong_t)&sh7763_data }, { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data }, { "r8a777x-ether", (kernel_ulong_t)&r8a777x_data }, - { "r8a7790-ether", (kernel_ulong_t)&r8a7790_data }, + { "r8a7790-ether", (kernel_ulong_t)&r8a779x_data }, + { "r8a7791-ether", (kernel_ulong_t)&r8a779x_data }, { } }; MODULE_DEVICE_TABLE(platform, sh_eth_id_table); -- cgit v1.2.3 From 42404c09151029689659818e2196ee2fd97142aa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 10 Dec 2013 22:05:45 -0500 Subject: Revert "tun: remove useless codes in tun_chr_aio_read() and tun_recvmsg()" This reverts commit 73713357ab58aacda1af715bb5a623528dbbfd79. MSG_TRUNC handling was broken and is going to be fixed in the 'net' tree, so revert this. Signed-off-by: David S. Miller --- drivers/net/tun.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index bbb693512918..3c5a8d8cde50 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1354,6 +1354,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, ret = tun_do_read(tun, tfile, iv, len, file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); if (ret > 0) iocb->ki_pos = ret; out: @@ -1454,6 +1455,10 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, } ret = tun_do_read(tun, tfile, m->msg_iov, total_len, flags & MSG_DONTWAIT); + if (ret > total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } out: tun_put(tun); return ret; -- cgit v1.2.3 From de2aa4760b45262cf25eac6d4c0e461703b7b64b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 10 Dec 2013 22:06:18 -0500 Subject: Revert "macvtap: remove useless codes in macvtap_aio_read() and macvtap_recvmsg()" This reverts commit 41e4af69a5984a3193ba3108fb4e067b0e34dc73. MSG_TRUNC handling was broken and is going to be fixed in the 'net' tree, so revert this. Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 2aa5e973ef17..4a34bcb6549f 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -871,6 +871,7 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ if (ret > 0) iocb->ki_pos = ret; out: @@ -1105,6 +1106,10 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, return -EINVAL; ret = macvtap_do_read(q, m->msg_iov, total_len, flags & MSG_DONTWAIT); + if (ret > total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } return ret; } -- cgit v1.2.3 From d24bae32fa9b541eb87edf1b3439f590c3b2dda5 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 9 Dec 2013 16:17:40 -0800 Subject: virtio_net: remove unused parameter to send_command All the code passes NULL for the last sg list (in). Simplify by just removing it. Signed-off-by: Stephen Hemminger Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 56c2229d28fd..d26f695ee64d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -876,13 +876,12 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) * never fail unless improperly formated. */ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, - struct scatterlist *out, - struct scatterlist *in) + struct scatterlist *out) { struct scatterlist *sgs[4], hdr, stat; struct virtio_net_ctrl_hdr ctrl; virtio_net_ctrl_ack status = ~0; - unsigned out_num = 0, in_num = 0, tmp; + unsigned out_num = 0, tmp; /* Caller should know better */ BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); @@ -895,16 +894,13 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, if (out) sgs[out_num++] = out; - if (in) - sgs[out_num + in_num++] = in; /* Add return status. */ sg_init_one(&stat, &status, sizeof(status)); - sgs[out_num + in_num++] = &stat; + sgs[out_num] = &stat; - BUG_ON(out_num + in_num > ARRAY_SIZE(sgs)); - BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC) - < 0); + BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); + BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC) < 0); if (unlikely(!virtqueue_kick(vi->cvq))) return status == VIRTIO_NET_OK; @@ -934,8 +930,7 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p) if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR)) { sg_init_one(&sg, addr->sa_data, dev->addr_len); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, - VIRTIO_NET_CTRL_MAC_ADDR_SET, - &sg, NULL)) { + VIRTIO_NET_CTRL_MAC_ADDR_SET, &sg)) { dev_warn(&vdev->dev, "Failed to set mac address by vq command.\n"); return -EINVAL; @@ -1008,7 +1003,7 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi) { rtnl_lock(); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE, - VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL, NULL)) + VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL)) dev_warn(&vi->dev->dev, "Failed to ack link announce.\n"); rtnl_unlock(); } @@ -1026,7 +1021,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) sg_init_one(&sg, &s, sizeof(s)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg, NULL)) { + VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg)) { dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n", queue_pairs); return -EINVAL; @@ -1076,16 +1071,14 @@ static void virtnet_set_rx_mode(struct net_device *dev) sg_init_one(sg, &promisc, sizeof(promisc)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, - VIRTIO_NET_CTRL_RX_PROMISC, - sg, NULL)) + VIRTIO_NET_CTRL_RX_PROMISC, sg)) dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", promisc ? "en" : "dis"); sg_init_one(sg, &allmulti, sizeof(allmulti)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, - VIRTIO_NET_CTRL_RX_ALLMULTI, - sg, NULL)) + VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", allmulti ? "en" : "dis"); @@ -1121,8 +1114,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, - VIRTIO_NET_CTRL_MAC_TABLE_SET, - sg, NULL)) + VIRTIO_NET_CTRL_MAC_TABLE_SET, sg)) dev_warn(&dev->dev, "Failed to set MAC filter table.\n"); kfree(buf); @@ -1137,7 +1129,7 @@ static int virtnet_vlan_rx_add_vid(struct net_device *dev, sg_init_one(&sg, &vid, sizeof(vid)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, - VIRTIO_NET_CTRL_VLAN_ADD, &sg, NULL)) + VIRTIO_NET_CTRL_VLAN_ADD, &sg)) dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); return 0; } @@ -1151,7 +1143,7 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, sg_init_one(&sg, &vid, sizeof(vid)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, - VIRTIO_NET_CTRL_VLAN_DEL, &sg, NULL)) + VIRTIO_NET_CTRL_VLAN_DEL, &sg)) dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); return 0; } -- cgit v1.2.3 From 788a8b6dd3a28e02af5581923a14667f550009b5 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 9 Dec 2013 16:18:45 -0800 Subject: virtio_net: spelling fixes Signed-off-by: Stephen Hemminger Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d26f695ee64d..c51a98867a40 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -873,7 +873,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) /* * Send command via the control virtqueue and check status. Commands * supported by the hypervisor, as indicated by feature bits, should - * never fail unless improperly formated. + * never fail unless improperly formatted. */ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, struct scatterlist *out) @@ -1061,7 +1061,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) void *buf; int i; - /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ + /* We can't dynamically set ndo_set_rx_mode, so return gracefully */ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) return; -- cgit v1.2.3 From 79ac7c941124866a72f000bb1fbb65dc1d1cf8cb Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:48:38 +0900 Subject: net: hippi: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/hippi/rrunner.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index 00ed75155ce8..cd85f24637e1 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -213,10 +213,8 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rrpriv->tx_ring_dma); if (rrpriv->regs) pci_iounmap(pdev, rrpriv->regs); - if (pdev) { + if (pdev) pci_release_regions(pdev); - pci_set_drvdata(pdev, NULL); - } out2: free_netdev(dev); out3: @@ -244,7 +242,6 @@ static void rr_remove_one(struct pci_dev *pdev) pci_iounmap(pdev, rr->regs); pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); free_netdev(dev); } -- cgit v1.2.3 From 49f74ed6da4d70adc81be36f4dde22fa23f28171 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:49:34 +0900 Subject: net: fddi: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/skfddi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c index 713d303a06a9..d5f58121b2e2 100644 --- a/drivers/net/fddi/skfp/skfddi.c +++ b/drivers/net/fddi/skfp/skfddi.c @@ -351,7 +351,6 @@ static void skfp_remove_one(struct pci_dev *pdev) free_netdev(p); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); } /* -- cgit v1.2.3 From 5535ec7600ab2fc316512d6fb15e8ec077878934 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:50:09 +0900 Subject: net: vmxnet3: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Shreyas N Bhatewara Acked-by: Dmitry Torokhov Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 7e2788c488ed..a300a18c550a 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -3132,7 +3132,6 @@ err_alloc_queue_desc: err_alloc_shared: dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa, sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE); - pci_set_drvdata(pdev, NULL); free_netdev(netdev); return err; } -- cgit v1.2.3 From 6d4bebebe20e18c565143b8852c0f5bd50a64f34 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:50:42 +0900 Subject: net: phy: spi_ks8995: remove unnecessary spi_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index f3bea1346021..98fb9f360d83 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -325,7 +325,6 @@ static int ks8995_probe(struct spi_device *spi) return 0; err_drvdata: - spi_set_drvdata(spi, NULL); kfree(ks); return err; } @@ -337,7 +336,6 @@ static int ks8995_remove(struct spi_device *spi) ks8995 = spi_get_drvdata(spi); sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr); - spi_set_drvdata(spi, NULL); kfree(ks8995); return 0; -- cgit v1.2.3 From 40706af0b246f416a35fc3e12dc695deca8da3ff Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:51:09 +0900 Subject: net: ieee802154: remove unnecessary spi_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ieee802154/at86rf230.c | 2 -- drivers/net/ieee802154/mrf24j40.c | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 2cbe1c249996..ab31544bc254 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -987,7 +987,6 @@ err_gpio_dir: err_slp_tr: gpio_free(lp->rstn); err_rstn: - spi_set_drvdata(spi, NULL); mutex_destroy(&lp->bmux); ieee802154_free_device(lp->dev); return rc; @@ -1006,7 +1005,6 @@ static int at86rf230_remove(struct spi_device *spi) gpio_free(lp->slp_tr); gpio_free(lp->rstn); - spi_set_drvdata(spi, NULL); mutex_destroy(&lp->bmux); ieee802154_free_device(lp->dev); diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index c6e46d6e9f75..246befa4ba05 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -715,7 +715,6 @@ static int mrf24j40_remove(struct spi_device *spi) * complete? */ /* Clean up the SPI stuff. */ - spi_set_drvdata(spi, NULL); kfree(devrec->buf); kfree(devrec); return 0; -- cgit v1.2.3 From 57c5bca9f4f8d0be378a115c5ed939bd43932f8e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:51:46 +0900 Subject: atm: he: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/atm/he.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 8557adcd34ee..aa6be2698669 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -419,7 +419,6 @@ static void he_remove_one(struct pci_dev *pci_dev) atm_dev_deregister(atm_dev); kfree(he_dev); - pci_set_drvdata(pci_dev, NULL); pci_disable_device(pci_dev); } -- cgit v1.2.3 From 109744c7cff0320790f3afa60bebe05994be9ec3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 10 Dec 2013 12:52:14 +0900 Subject: atm: solos-pci: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/atm/solos-pci.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 32784d18d1f7..e3fb496c7163 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1335,7 +1335,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) out_unmap_both: kfree(card->dma_bounce); - pci_set_drvdata(dev, NULL); pci_iounmap(dev, card->buffers); out_unmap_config: pci_iounmap(dev, card->config_regs); @@ -1457,7 +1456,6 @@ static void fpga_remove(struct pci_dev *dev) pci_release_regions(dev); pci_disable_device(dev); - pci_set_drvdata(dev, NULL); kfree(card); } -- cgit v1.2.3 From 4ed296ef28c63c0b05949c232c55fa60920fb9ab Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 10 Dec 2013 15:36:50 -0500 Subject: lustre: delete pointless wait queue related casts. These serve no purpose at all, and can only mask real type clash issues that one would want to actually see. Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c index cc9829ffbdcb..c7bc7fcccb8e 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c @@ -46,13 +46,10 @@ #include #endif -#define LINUX_WAITQ(w) ((wait_queue_t *) w) -#define LINUX_WAITQ_HEAD(w) ((wait_queue_head_t *) w) - void init_waitqueue_entry_current(wait_queue_t *link) { - init_waitqueue_entry(LINUX_WAITQ(link), current); + init_waitqueue_entry(link, current); } EXPORT_SYMBOL(init_waitqueue_entry_current); @@ -74,9 +71,9 @@ add_wait_queue_exclusive_head(wait_queue_head_t *waitq, wait_queue_t *link) { unsigned long flags; - spin_lock_irqsave(&LINUX_WAITQ_HEAD(waitq)->lock, flags); - __add_wait_queue_exclusive(LINUX_WAITQ_HEAD(waitq), LINUX_WAITQ(link)); - spin_unlock_irqrestore(&LINUX_WAITQ_HEAD(waitq)->lock, flags); + spin_lock_irqsave(&waitq->lock, flags); + __add_wait_queue_exclusive(waitq, link); + spin_unlock_irqrestore(&waitq->lock, flags); } EXPORT_SYMBOL(add_wait_queue_exclusive_head); -- cgit v1.2.3 From 0dfc3e1862f5e7fe369d7c20c1a1e37633b45573 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 10 Dec 2013 16:07:19 -0800 Subject: net: macb: Migrate to dev_pm_ops Migrate the suspend/resume functions to use the dev_pm_ops PM interface. Signed-off-by: Soren Brinkmann Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 92578690f6de..389ccf1362d5 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1946,8 +1946,9 @@ static int __exit macb_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int macb_suspend(struct platform_device *pdev, pm_message_t state) +static int macb_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct net_device *netdev = platform_get_drvdata(pdev); struct macb *bp = netdev_priv(netdev); @@ -1960,8 +1961,9 @@ static int macb_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int macb_resume(struct platform_device *pdev) +static int macb_resume(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct net_device *netdev = platform_get_drvdata(pdev); struct macb *bp = netdev_priv(netdev); @@ -1972,19 +1974,17 @@ static int macb_resume(struct platform_device *pdev) return 0; } -#else -#define macb_suspend NULL -#define macb_resume NULL #endif +static SIMPLE_DEV_PM_OPS(macb_pm_ops, macb_suspend, macb_resume); + static struct platform_driver macb_driver = { .remove = __exit_p(macb_remove), - .suspend = macb_suspend, - .resume = macb_resume, .driver = { .name = "macb", .owner = THIS_MODULE, .of_match_table = of_match_ptr(macb_dt_ids), + .pm = &macb_pm_ops, }, }; -- cgit v1.2.3 From b48e0bab142fdfa16b52fc63f43acf0784c80ee7 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 10 Dec 2013 16:07:20 -0800 Subject: net: macb: Migrate to devm clock interface Migrate to using the device managed interface for clocks and clean up the associated error paths. Signed-off-by: Soren Brinkmann Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 389ccf1362d5..62aa136889a4 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1790,19 +1790,31 @@ static int __init macb_probe(struct platform_device *pdev) spin_lock_init(&bp->lock); INIT_WORK(&bp->tx_error_task, macb_tx_error_task); - bp->pclk = clk_get(&pdev->dev, "pclk"); + bp->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(bp->pclk)) { - dev_err(&pdev->dev, "failed to get macb_clk\n"); + err = PTR_ERR(bp->pclk); + dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err); goto err_out_free_dev; } - clk_prepare_enable(bp->pclk); - bp->hclk = clk_get(&pdev->dev, "hclk"); + bp->hclk = devm_clk_get(&pdev->dev, "hclk"); if (IS_ERR(bp->hclk)) { - dev_err(&pdev->dev, "failed to get hclk\n"); - goto err_out_put_pclk; + err = PTR_ERR(bp->hclk); + dev_err(&pdev->dev, "failed to get hclk (%u)\n", err); + goto err_out_free_dev; + } + + err = clk_prepare_enable(bp->pclk); + if (err) { + dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err); + goto err_out_free_dev; + } + + err = clk_prepare_enable(bp->hclk); + if (err) { + dev_err(&pdev->dev, "failed to enable hclk (%u)\n", err); + goto err_out_disable_pclk; } - clk_prepare_enable(bp->hclk); bp->regs = ioremap(regs->start, resource_size(regs)); if (!bp->regs) { @@ -1908,10 +1920,8 @@ err_out_iounmap: iounmap(bp->regs); err_out_disable_clocks: clk_disable_unprepare(bp->hclk); - clk_put(bp->hclk); +err_out_disable_pclk: clk_disable_unprepare(bp->pclk); -err_out_put_pclk: - clk_put(bp->pclk); err_out_free_dev: free_netdev(dev); err_out: @@ -1936,9 +1946,7 @@ static int __exit macb_remove(struct platform_device *pdev) free_irq(dev->irq, dev); iounmap(bp->regs); clk_disable_unprepare(bp->hclk); - clk_put(bp->hclk); clk_disable_unprepare(bp->pclk); - clk_put(bp->pclk); free_netdev(dev); } -- cgit v1.2.3 From 60fe716f005a0add0447796c38821b22ef379856 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 10 Dec 2013 16:07:21 -0800 Subject: net: macb: Use devm_ioremap() Use the device managed version of ioremap to remap IO memory, simplifying error paths. Signed-off-by: Soren Brinkmann Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 62aa136889a4..436aecc31732 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1816,7 +1817,7 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out_disable_pclk; } - bp->regs = ioremap(regs->start, resource_size(regs)); + bp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!bp->regs) { dev_err(&pdev->dev, "failed to map registers, aborting.\n"); err = -ENOMEM; @@ -1828,7 +1829,7 @@ static int __init macb_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", dev->irq, err); - goto err_out_iounmap; + goto err_out_disable_clocks; } dev->netdev_ops = &macb_netdev_ops; @@ -1916,8 +1917,6 @@ err_out_unregister_netdev: unregister_netdev(dev); err_out_free_irq: free_irq(dev->irq, dev); -err_out_iounmap: - iounmap(bp->regs); err_out_disable_clocks: clk_disable_unprepare(bp->hclk); err_out_disable_pclk: @@ -1944,7 +1943,6 @@ static int __exit macb_remove(struct platform_device *pdev) mdiobus_free(bp->mii_bus); unregister_netdev(dev); free_irq(dev->irq, dev); - iounmap(bp->regs); clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); free_netdev(dev); -- cgit v1.2.3 From 0a4acf08ea62d8c8a7ed394bb075f0e1f10ac021 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 10 Dec 2013 16:07:22 -0800 Subject: net: macb: Use devm_request_irq() Use the device managed interface to request the IRQ, simplifying error paths. Signed-off-by: Soren Brinkmann Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 436aecc31732..603844b1d483 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1825,7 +1825,8 @@ static int __init macb_probe(struct platform_device *pdev) } dev->irq = platform_get_irq(pdev, 0); - err = request_irq(dev->irq, macb_interrupt, 0, dev->name, dev); + err = devm_request_irq(&pdev->dev, dev->irq, macb_interrupt, 0, + dev->name, dev); if (err) { dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", dev->irq, err); @@ -1892,7 +1893,7 @@ static int __init macb_probe(struct platform_device *pdev) err = register_netdev(dev); if (err) { dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); - goto err_out_free_irq; + goto err_out_disable_clocks; } err = macb_mii_init(bp); @@ -1915,8 +1916,6 @@ static int __init macb_probe(struct platform_device *pdev) err_out_unregister_netdev: unregister_netdev(dev); -err_out_free_irq: - free_irq(dev->irq, dev); err_out_disable_clocks: clk_disable_unprepare(bp->hclk); err_out_disable_pclk: @@ -1942,7 +1941,6 @@ static int __exit macb_remove(struct platform_device *pdev) kfree(bp->mii_bus->irq); mdiobus_free(bp->mii_bus); unregister_netdev(dev); - free_irq(dev->irq, dev); clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); free_netdev(dev); -- cgit v1.2.3 From e1824dfe0d8e6bae55859eb016ce21b61d1b8c85 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 10 Dec 2013 16:07:23 -0800 Subject: net: macb: Adjust tx_clk when link speed changes Adjust the ethernet clock according to the negotiated link speed. Signed-off-by: Soren Brinkmann Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 64 +++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/cadence/macb.h | 1 + 2 files changed, 65 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 603844b1d483..419529a9309d 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -204,6 +204,47 @@ static int macb_mdio_reset(struct mii_bus *bus) return 0; } +/** + * macb_set_tx_clk() - Set a clock to a new frequency + * @clk Pointer to the clock to change + * @rate New frequency in Hz + * @dev Pointer to the struct net_device + */ +static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) +{ + long ferr, rate, rate_rounded; + + switch (speed) { + case SPEED_10: + rate = 2500000; + break; + case SPEED_100: + rate = 25000000; + break; + case SPEED_1000: + rate = 125000000; + break; + default: + break; + } + + rate_rounded = clk_round_rate(clk, rate); + if (rate_rounded < 0) + return; + + /* RGMII allows 50 ppm frequency error. Test and warn if this limit + * is not satisfied. + */ + ferr = abs(rate_rounded - rate); + ferr = DIV_ROUND_UP(ferr, rate / 100000); + if (ferr > 5) + netdev_warn(dev, "unable to generate target frequency: %ld Hz\n", + rate); + + if (clk_set_rate(clk, rate_rounded)) + netdev_err(dev, "adjusting tx_clk failed.\n"); +} + static void macb_handle_link_change(struct net_device *dev) { struct macb *bp = netdev_priv(dev); @@ -251,6 +292,9 @@ static void macb_handle_link_change(struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); + if (!IS_ERR(bp->tx_clk)) + macb_set_tx_clk(bp->tx_clk, phydev->speed, dev); + if (status_change) { if (phydev->link) { netif_carrier_on(dev); @@ -1805,6 +1849,8 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out_free_dev; } + bp->tx_clk = devm_clk_get(&pdev->dev, "tx_clk"); + err = clk_prepare_enable(bp->pclk); if (err) { dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err); @@ -1817,6 +1863,15 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out_disable_pclk; } + if (!IS_ERR(bp->tx_clk)) { + err = clk_prepare_enable(bp->tx_clk); + if (err) { + dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", + err); + goto err_out_disable_hclk; + } + } + bp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!bp->regs) { dev_err(&pdev->dev, "failed to map registers, aborting.\n"); @@ -1917,6 +1972,9 @@ static int __init macb_probe(struct platform_device *pdev) err_out_unregister_netdev: unregister_netdev(dev); err_out_disable_clocks: + if (!IS_ERR(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); +err_out_disable_hclk: clk_disable_unprepare(bp->hclk); err_out_disable_pclk: clk_disable_unprepare(bp->pclk); @@ -1941,6 +1999,8 @@ static int __exit macb_remove(struct platform_device *pdev) kfree(bp->mii_bus->irq); mdiobus_free(bp->mii_bus); unregister_netdev(dev); + if (!IS_ERR(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); free_netdev(dev); @@ -1959,6 +2019,8 @@ static int macb_suspend(struct device *dev) netif_carrier_off(netdev); netif_device_detach(netdev); + if (!IS_ERR(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); @@ -1973,6 +2035,8 @@ static int macb_resume(struct device *dev) clk_prepare_enable(bp->pclk); clk_prepare_enable(bp->hclk); + if (!IS_ERR(bp->tx_clk)) + clk_prepare_enable(bp->tx_clk); netif_device_attach(netdev); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index f4076155bed7..51c02442160a 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -572,6 +572,7 @@ struct macb { struct platform_device *pdev; struct clk *pclk; struct clk *hclk; + struct clk *tx_clk; struct net_device *dev; struct napi_struct napi; struct work_struct tx_error_task; -- cgit v1.2.3 From 9319e47c18c41f2748c4140b0ac32097a56f36c1 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 10 Dec 2013 20:57:57 -0800 Subject: net: macb: Fix build warning When adjusting the link speed, the target frequency is determined by a 'swith (LINK_SPEED)' statement, that assigns the target rate only for valid and expected LINK_SPEED values. This incomplete switch statement leads to the following build warning: drivers/net/ethernet/cadence/macb.c: In function 'macb_handle_link_change': >> drivers/net/ethernet/cadence/macb.c:241:14: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized] netdev_warn(dev, "unable to generate target frequency: %ld Hz\n", ^ drivers/net/ethernet/cadence/macb.c:215:13: note: 'rate' was declared here long ferr, rate, rate_rounded; Fixing this by bailing out of that function in the switch's default case before the rate variable is used. Reported-by: kbuild test robot Signed-off-by: Soren Brinkmann Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 419529a9309d..3190d38e16fb 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -225,7 +225,7 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) rate = 125000000; break; default: - break; + return; } rate_rounded = clk_round_rate(clk, rate); -- cgit v1.2.3 From 2b6a6a90c31c550f839e905484f5253b9d24e33d Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 5 Dec 2013 06:53:41 +0100 Subject: ath10k: fix WEP Shared authentication Frames received from FW were treated incorrectly. This led to stations being unable to associate to WEP Shared ath10k AP. This was indicated by a bizarre hostapd message: Unsupported authentication algorithm (36088) Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 1260a8d15dc3..9ea333a7789c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -937,7 +937,11 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control); - if (fc & IEEE80211_FCTL_PROTECTED) { + /* FW delivers WEP Shared Auth frame with Protected Bit set and + * encrypted payload. However in case of PMF it delivers decrypted + * frames with Protected Bit set. */ + if (ieee80211_has_protected(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) { status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; hdr->frame_control = __cpu_to_le16(fc & -- cgit v1.2.3 From 3f6e48597b2ad8e81852407319fabd6ed4665add Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 4 Dec 2013 21:08:55 +0100 Subject: parport: parport_pc: fix id print of a device Since commit 7106b4e3 ("8250: Oxford Semiconductor Devices") the debug print of the device id does no longer match the real device if it is located in the "enum" behind oxsemi_pcie_pport. The reason is that the code assumes that each id contains one entry in the PCI table. The fix is to lookup the currently used id from the id-> parameter. Cc: Lee Howard Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_pc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 963761526229..4b03dc5d571b 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2827,16 +2827,12 @@ static int parport_pc_pci_probe(struct pci_dev *dev, if (irq == IRQ_NONE) { printk(KERN_DEBUG "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx)\n", - parport_pc_pci_tbl[i + last_sio].vendor, - parport_pc_pci_tbl[i + last_sio].device, - io_lo, io_hi); + id->vendor, id->device, io_lo, io_hi); irq = PARPORT_IRQ_NONE; } else { printk(KERN_DEBUG "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx), IRQ %d\n", - parport_pc_pci_tbl[i + last_sio].vendor, - parport_pc_pci_tbl[i + last_sio].device, - io_lo, io_hi, irq); + id->vendor, id->device, io_lo, io_hi, irq); } data->ports[count] = parport_pc_probe_port(io_lo, io_hi, irq, -- cgit v1.2.3 From 0463f07ccf0f339231f6cf6e873484ef320cb1a5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 25 Nov 2013 11:17:57 +0900 Subject: parport_pc: remove unnecessary pci_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_pc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 4b03dc5d571b..a62d13155a86 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2862,8 +2862,6 @@ static void parport_pc_pci_remove(struct pci_dev *dev) struct pci_parport_data *data = pci_get_drvdata(dev); int i; - pci_set_drvdata(dev, NULL); - if (data) { for (i = data->num - 1; i >= 0; i--) parport_pc_unregister_port(data->ports[i]); -- cgit v1.2.3 From d6a484520c5572a4170fa915109ccfc0c38f5008 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 27 Nov 2013 17:43:43 +0100 Subject: parport: parport_pc: remove double PCI ID for NetMos In commit 85747f ("PATCH] parport: add NetMOS 9805 support") Max added the PCI ID for NetMOS 9805 based on a Debian bug report from 2k4 which was at the v2.4.26 time frame. The patch made into 2.6.14. Shortly before that patch akpm merged commit 296d3c783b ("[PATCH] Support NetMOS based PCI cards providing serial and parallel ports") which made into v2.6.9-rc1. Now we have two different entries for the same PCI id. I have here the NetMos 9805 which claims to support SPP/EPP/ECP mode. This patch takes Max's entry for titan_1284p1 (base != -1 specifies the ioport for ECP mode) and replaces akpm's entry for netmos_9805 which specified -1 (=none). Both share the same PCI-ID (my card has subsystem 0x1000 / 0x0020 so it should match PCI_ANY). While here I also drop the entry for titan_1284p2 which is the same as netmos_9815. Cc: Maximilian Attems Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/parport/parport_pc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index a62d13155a86..76ee7750bc5e 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2600,8 +2600,6 @@ enum parport_pc_pci_cards { syba_2p_epp, syba_1p_ecp, titan_010l, - titan_1284p1, - titan_1284p2, avlab_1p, avlab_2p, oxsemi_952, @@ -2660,8 +2658,6 @@ static struct parport_pc_pci { /* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, /* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } }, /* titan_010l */ { 1, { { 3, -1 }, } }, - /* titan_1284p1 */ { 1, { { 0, 1 }, } }, - /* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } }, /* avlab_1p */ { 1, { { 0, 1}, } }, /* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} }, /* The Oxford Semi cards are unusual: 954 doesn't support ECP, @@ -2677,8 +2673,8 @@ static struct parport_pc_pci { /* netmos_9705 */ { 1, { { 0, -1 }, } }, /* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, - /* netmos_9805 */ { 1, { { 0, -1 }, } }, - /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, + /* netmos_9805 */ { 1, { { 0, 1 }, } }, + /* netmos_9815 */ { 2, { { 0, 1 }, { 2, 3 }, } }, /* netmos_9901 */ { 1, { { 0, -1 }, } }, /* netmos_9865 */ { 1, { { 0, -1 }, } }, /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, @@ -2722,8 +2718,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L, PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l }, - { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 }, - { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 }, /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ /* AFAVLAB_TK9902 */ { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, -- cgit v1.2.3 From df5e4e8b576108f88f79e5b4c984d51d460d2360 Mon Sep 17 00:00:00 2001 From: Dasaratharaman Chandramouli Date: Tue, 10 Dec 2013 09:51:12 -0800 Subject: misc: mic: bug fix for interrupt acknowledgement in MSI/INTx case. The interrupt handler (mic_interrupt), called in the MSI/INTx mode, writes to the interrupt sources register to acknowledge the interrupt and then calls the corresponding callback handlers to handle the same. These callback handlers acknowledge the interrupts again leading to missed interrupts. This patch fixes the issue by removing the interrupt acknowlegment code from the callback handlers. Reviewed-by: Sudeep Dutt Reviewed-by: Nikhil Rao Reviewed-by: Siva Krishna Kumar Reddy Yerramreddy Signed-off-by: Dasaratharaman Chandramouli Cc: stable # 3.13 Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/host/mic_device.h | 3 +++ drivers/misc/mic/host/mic_main.c | 2 +- drivers/misc/mic/host/mic_virtio.c | 2 +- drivers/misc/mic/host/mic_x100.c | 36 ++++++++++++++++++++---------------- 4 files changed, 25 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 3574cc375bb9..b2da289320c9 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -134,6 +134,8 @@ struct mic_device { * @send_intr: Send an interrupt for a particular doorbell on the card. * @ack_interrupt: Hardware specific operations to ack the h/w on * receipt of an interrupt. + * @intr_workarounds: Hardware specific workarounds needed after + * handling an interrupt. * @reset: Reset the remote processor. * @reset_fw_ready: Reset firmware ready field. * @is_fw_ready: Check if firmware is ready for OS download. @@ -149,6 +151,7 @@ struct mic_hw_ops { void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val); void (*send_intr)(struct mic_device *mdev, int doorbell); u32 (*ack_interrupt)(struct mic_device *mdev); + void (*intr_workarounds)(struct mic_device *mdev); void (*reset)(struct mic_device *mdev); void (*reset_fw_ready)(struct mic_device *mdev); bool (*is_fw_ready)(struct mic_device *mdev); diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index ad838c7651c4..c04a021e20c7 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c @@ -115,7 +115,7 @@ static irqreturn_t mic_shutdown_db(int irq, void *data) struct mic_device *mdev = data; struct mic_bootparam *bootparam = mdev->dp; - mdev->ops->ack_interrupt(mdev); + mdev->ops->intr_workarounds(mdev); switch (bootparam->shutdown_status) { case MIC_HALTED: diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c index 5b8494bd1e00..8d3c21cd1d9c 100644 --- a/drivers/misc/mic/host/mic_virtio.c +++ b/drivers/misc/mic/host/mic_virtio.c @@ -369,7 +369,7 @@ static irqreturn_t mic_virtio_intr_handler(int irq, void *data) struct mic_vdev *mvdev = data; struct mic_device *mdev = mvdev->mdev; - mdev->ops->ack_interrupt(mdev); + mdev->ops->intr_workarounds(mdev); schedule_work(&mvdev->virtio_bh_work); return IRQ_HANDLED; } diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c index 81e9541b784c..6fccb13493a5 100644 --- a/drivers/misc/mic/host/mic_x100.c +++ b/drivers/misc/mic/host/mic_x100.c @@ -174,35 +174,38 @@ static void mic_x100_send_intr(struct mic_device *mdev, int doorbell) } /** - * mic_ack_interrupt - Device specific interrupt handling. - * @mdev: pointer to mic_device instance + * mic_x100_ack_interrupt - Read the interrupt sources register and + * clear it. This function will be called in the MSI/INTx case. + * @mdev: Pointer to mic_device instance. * - * Returns: bitmask of doorbell events triggered. + * Returns: bitmask of interrupt sources triggered. */ static u32 mic_x100_ack_interrupt(struct mic_device *mdev) { - u32 reg = 0; - struct mic_mw *mw = &mdev->mmio; u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0; + u32 reg = mic_mmio_read(&mdev->mmio, sicr0); + mic_mmio_write(&mdev->mmio, reg, sicr0); + return reg; +} + +/** + * mic_x100_intr_workarounds - These hardware specific workarounds are + * to be invoked everytime an interrupt is handled. + * @mdev: Pointer to mic_device instance. + * + * Returns: none + */ +static void mic_x100_intr_workarounds(struct mic_device *mdev) +{ + struct mic_mw *mw = &mdev->mmio; /* Clear pending bit array. */ if (MIC_A0_STEP == mdev->stepping) mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_MSIXPBACR); - if (mdev->irq_info.num_vectors <= 1) { - reg = mic_mmio_read(mw, sicr0); - - if (unlikely(!reg)) - goto done; - - mic_mmio_write(mw, reg, sicr0); - } - if (mdev->stepping >= MIC_B0_STEP) mdev->intr_ops->enable_interrupts(mdev); -done: - return reg; } /** @@ -553,6 +556,7 @@ struct mic_hw_ops mic_x100_ops = { .write_spad = mic_x100_write_spad, .send_intr = mic_x100_send_intr, .ack_interrupt = mic_x100_ack_interrupt, + .intr_workarounds = mic_x100_intr_workarounds, .reset = mic_x100_hw_reset, .reset_fw_ready = mic_x100_reset_fw_ready, .is_fw_ready = mic_x100_is_fw_ready, -- cgit v1.2.3 From efc5681747de099a76bfcf7973adb0784c6e96e1 Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:24 +0800 Subject: staging: et131x: reduce split lines in et131x_config_rx_dma_regs Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 5dd217062096..d16ac57a544d 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1781,6 +1781,7 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) u32 __iomem *min_des; u32 __iomem *base_hi; u32 __iomem *base_lo; + struct fbr_lookup *fbr = rx_local->fbr[id]; if (id == 0) { num_des = &rx_dma->fbr0_num_des; @@ -1797,12 +1798,10 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) } /* Now's the best time to initialize FBR contents */ - fbr_entry = - (struct fbr_desc *) rx_local->fbr[id]->ring_virtaddr; - for (entry = 0; - entry < rx_local->fbr[id]->num_entries; entry++) { - fbr_entry->addr_hi = rx_local->fbr[id]->bus_high[entry]; - fbr_entry->addr_lo = rx_local->fbr[id]->bus_low[entry]; + fbr_entry = (struct fbr_desc *) fbr->ring_virtaddr; + for (entry = 0; entry < fbr->num_entries; entry++) { + fbr_entry->addr_hi = fbr->bus_high[entry]; + fbr_entry->addr_lo = fbr->bus_low[entry]; fbr_entry->word2 = entry; fbr_entry++; } @@ -1810,19 +1809,16 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) /* Set the address and parameters of Free buffer ring 1 and 0 * into the 1310's registers */ - writel(upper_32_bits(rx_local->fbr[id]->ring_physaddr), - base_hi); - writel(lower_32_bits(rx_local->fbr[id]->ring_physaddr), - base_lo); - writel(rx_local->fbr[id]->num_entries - 1, num_des); + writel(upper_32_bits(fbr->ring_physaddr), base_hi); + writel(lower_32_bits(fbr->ring_physaddr), base_lo); + writel(fbr->num_entries - 1, num_des); writel(ET_DMA10_WRAP, full_offset); /* This variable tracks the free buffer ring 1 full position, * so it has to match the above. */ - rx_local->fbr[id]->local_full = ET_DMA10_WRAP; - writel(((rx_local->fbr[id]->num_entries * - LO_MARK_PERCENT_FOR_RX) / 100) - 1, + fbr->local_full = ET_DMA10_WRAP; + writel(((fbr->num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, min_des); } -- cgit v1.2.3 From bad5d26f2222ec02e32c2cf71c2bd5b82528ebad Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:25 +0800 Subject: staging: et131x: reduce split lines in et131x_rx_dma_memory_alloc Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 48 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index d16ac57a544d..92725483b113 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -2127,6 +2127,7 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) u32 pktstat_ringsize; u32 fbr_chunksize; struct rx_ring *rx_ring; + struct fbr_lookup *fbr; /* Setup some convenience pointers */ rx_ring = &adapter->rx_ring; @@ -2170,20 +2171,18 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) rx_ring->fbr[1]->num_entries = 128; } - adapter->rx_ring.psr_num_entries = - adapter->rx_ring.fbr[0]->num_entries + - adapter->rx_ring.fbr[1]->num_entries; + rx_ring->psr_num_entries = rx_ring->fbr[0]->num_entries + + rx_ring->fbr[1]->num_entries; for (id = 0; id < NUM_FBRS; id++) { + fbr = rx_ring->fbr[id]; /* Allocate an area of memory for Free Buffer Ring */ - bufsize = - (sizeof(struct fbr_desc) * rx_ring->fbr[id]->num_entries); - rx_ring->fbr[id]->ring_virtaddr = - dma_alloc_coherent(&adapter->pdev->dev, - bufsize, - &rx_ring->fbr[id]->ring_physaddr, - GFP_KERNEL); - if (!rx_ring->fbr[id]->ring_virtaddr) { + bufsize = sizeof(struct fbr_desc) * fbr->num_entries; + fbr->ring_virtaddr = dma_alloc_coherent(&adapter->pdev->dev, + bufsize, + &fbr->ring_physaddr, + GFP_KERNEL); + if (!fbr->ring_virtaddr) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Free Buffer Ring %d\n", id); return -ENOMEM; @@ -2191,25 +2190,25 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) } for (id = 0; id < NUM_FBRS; id++) { - fbr_chunksize = (FBR_CHUNKS * rx_ring->fbr[id]->buffsize); + fbr = rx_ring->fbr[id]; + fbr_chunksize = (FBR_CHUNKS * fbr->buffsize); - for (i = 0; - i < (rx_ring->fbr[id]->num_entries / FBR_CHUNKS); i++) { + for (i = 0; i < fbr->num_entries / FBR_CHUNKS; i++) { dma_addr_t fbr_tmp_physaddr; - rx_ring->fbr[id]->mem_virtaddrs[i] = dma_alloc_coherent( + fbr->mem_virtaddrs[i] = dma_alloc_coherent( &adapter->pdev->dev, fbr_chunksize, - &rx_ring->fbr[id]->mem_physaddrs[i], + &fbr->mem_physaddrs[i], GFP_KERNEL); - if (!rx_ring->fbr[id]->mem_virtaddrs[i]) { + if (!fbr->mem_virtaddrs[i]) { dev_err(&adapter->pdev->dev, "Could not alloc memory\n"); return -ENOMEM; } /* See NOTE in "Save Physical Address" comment above */ - fbr_tmp_physaddr = rx_ring->fbr[id]->mem_physaddrs[i]; + fbr_tmp_physaddr = fbr->mem_physaddrs[i]; for (j = 0; j < FBR_CHUNKS; j++) { u32 index = (i * FBR_CHUNKS) + j; @@ -2217,26 +2216,25 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) /* Save the Virtual address of this index for * quick access later */ - rx_ring->fbr[id]->virt[index] = - (u8 *) rx_ring->fbr[id]->mem_virtaddrs[i] + - (j * rx_ring->fbr[id]->buffsize); + fbr->virt[index] = (u8 *)fbr->mem_virtaddrs[i] + + (j * fbr->buffsize); /* now store the physical address in the * descriptor so the device can access it */ - rx_ring->fbr[id]->bus_high[index] = + fbr->bus_high[index] = upper_32_bits(fbr_tmp_physaddr); - rx_ring->fbr[id]->bus_low[index] = + fbr->bus_low[index] = lower_32_bits(fbr_tmp_physaddr); - fbr_tmp_physaddr += rx_ring->fbr[id]->buffsize; + fbr_tmp_physaddr += fbr->buffsize; } } } /* Allocate an area of memory for FIFO of Packet Status ring entries */ pktstat_ringsize = - sizeof(struct pkt_stat_desc) * adapter->rx_ring.psr_num_entries; + sizeof(struct pkt_stat_desc) * rx_ring->psr_num_entries; rx_ring->ps_ring_virtaddr = dma_alloc_coherent(&adapter->pdev->dev, pktstat_ringsize, -- cgit v1.2.3 From f876f59e4515a94b277d01c6e61ef4cf0733af15 Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:26 +0800 Subject: staging: et131x: reduce split lines in et131x_rx_dma_memory_free Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 92725483b113..5a4546553a3c 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -2281,6 +2281,7 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) u32 pktstat_ringsize; struct rfd *rfd; struct rx_ring *rx_ring; + struct fbr_lookup *fbr; /* Setup some convenience pointers */ rx_ring = &adapter->rx_ring; @@ -2299,34 +2300,35 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) /* Free Free Buffer Rings */ for (id = 0; id < NUM_FBRS; id++) { - if (!rx_ring->fbr[id]->ring_virtaddr) + fbr = rx_ring->fbr[id]; + + if (!fbr->ring_virtaddr) continue; /* First the packet memory */ for (index = 0; - index < (rx_ring->fbr[id]->num_entries / FBR_CHUNKS); + index < fbr->num_entries / FBR_CHUNKS; index++) { - if (rx_ring->fbr[id]->mem_virtaddrs[index]) { - bufsize = - rx_ring->fbr[id]->buffsize * FBR_CHUNKS; + if (fbr->mem_virtaddrs[index]) { + bufsize = fbr->buffsize * FBR_CHUNKS; dma_free_coherent(&adapter->pdev->dev, - bufsize, - rx_ring->fbr[id]->mem_virtaddrs[index], - rx_ring->fbr[id]->mem_physaddrs[index]); + bufsize, + fbr->mem_virtaddrs[index], + fbr->mem_physaddrs[index]); - rx_ring->fbr[id]->mem_virtaddrs[index] = NULL; + fbr->mem_virtaddrs[index] = NULL; } } - bufsize = - sizeof(struct fbr_desc) * rx_ring->fbr[id]->num_entries; + bufsize = sizeof(struct fbr_desc) * fbr->num_entries; - dma_free_coherent(&adapter->pdev->dev, bufsize, - rx_ring->fbr[id]->ring_virtaddr, - rx_ring->fbr[id]->ring_physaddr); + dma_free_coherent(&adapter->pdev->dev, + bufsize, + fbr->ring_virtaddr, + fbr->ring_physaddr); - rx_ring->fbr[id]->ring_virtaddr = NULL; + fbr->ring_virtaddr = NULL; } /* Free Packet Status Ring */ -- cgit v1.2.3 From 39bdb4a02ba85ea159e58c086816e97f0a158adb Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:27 +0800 Subject: staging: et131x: reduce split lines in nic_return_rfd Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 5a4546553a3c..f498eec07bb5 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -2412,11 +2412,13 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd) u16 buff_index = rfd->bufferindex; u8 ring_index = rfd->ringindex; unsigned long flags; + struct fbr_lookup *fbr = rx_local->fbr[ring_index]; /* We don't use any of the OOB data besides status. Otherwise, we * need to clean up OOB data */ - if (buff_index < rx_local->fbr[ring_index]->num_entries) { + if (buff_index < fbr->num_entries) { + u32 free_buff_ring; u32 __iomem *offset; struct fbr_desc *next; @@ -2427,22 +2429,20 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd) else offset = &rx_dma->fbr1_full_offset; - next = (struct fbr_desc *) - (rx_local->fbr[ring_index]->ring_virtaddr) + - INDEX10(rx_local->fbr[ring_index]->local_full); + next = (struct fbr_desc *)(fbr->ring_virtaddr) + + INDEX10(fbr->local_full); /* Handle the Free Buffer Ring advancement here. Write * the PA / Buffer Index for the returned buffer into * the oldest (next to be freed)FBR entry */ - next->addr_hi = rx_local->fbr[ring_index]->bus_high[buff_index]; - next->addr_lo = rx_local->fbr[ring_index]->bus_low[buff_index]; + next->addr_hi = fbr->bus_high[buff_index]; + next->addr_lo = fbr->bus_low[buff_index]; next->word2 = buff_index; - writel(bump_free_buff_ring( - &rx_local->fbr[ring_index]->local_full, - rx_local->fbr[ring_index]->num_entries - 1), - offset); + free_buff_ring = bump_free_buff_ring(&fbr->local_full, + fbr->num_entries - 1); + writel(free_buff_ring, offset); spin_unlock_irqrestore(&adapter->fbr_lock, flags); } else { -- cgit v1.2.3 From 297bb9dbc830a12f62b3ccfdd422e5ee9d639b72 Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:28 +0800 Subject: staging: et131x: reduce split lines in nic_rx_pkts Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index f498eec07bb5..89bd8ca00126 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -2486,6 +2486,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) u32 word0; u32 word1; struct sk_buff *skb; + struct fbr_lookup *fbr; /* RX Status block is written by the DMA engine prior to every * interrupt. It contains the next to be used entry in the Packet @@ -2507,6 +2508,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) */ len = psr->word1 & 0xFFFF; ring_index = (psr->word1 >> 26) & 0x03; + fbr = rx_local->fbr[ring_index]; buff_index = (psr->word1 >> 16) & 0x3FF; word0 = psr->word0; @@ -2522,8 +2524,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) writel(rx_local->local_psr_full, &adapter->regs->rxdma.psr_full_offset); - if (ring_index > 1 || - buff_index > rx_local->fbr[ring_index]->num_entries - 1) { + if (ring_index > 1 || buff_index > fbr->num_entries - 1) { /* Illegal buffer or ring index cannot be used by S/W*/ dev_err(&adapter->pdev->dev, "NICRxPkts PSR Entry %d indicates length of %d and/or bad bi(%d)\n", @@ -2576,7 +2577,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) && !(adapter->packet_filter & ET131X_PACKET_TYPE_PROMISCUOUS) && !(adapter->packet_filter & ET131X_PACKET_TYPE_ALL_MULTICAST)) { - buf = rx_local->fbr[ring_index]->virt[buff_index]; + buf = fbr->virt[buff_index]; /* Loop through our list to see if the destination * address of this packet matches one in our list. @@ -2629,9 +2630,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) adapter->net_stats.rx_bytes += rfd->len; - memcpy(skb_put(skb, rfd->len), - rx_local->fbr[ring_index]->virt[buff_index], - rfd->len); + memcpy(skb_put(skb, rfd->len), fbr->virt[buff_index], rfd->len); skb->protocol = eth_type_trans(skb, adapter->netdev); skb->ip_summed = CHECKSUM_NONE; -- cgit v1.2.3 From c31c135e7a779214acb9ad66385bb2bbfe65434b Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:29 +0800 Subject: staging: et131x: remove item that have been done in TODO file Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/README | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/README b/drivers/staging/et131x/README index 8da96a6d2c92..3befc45fab8a 100644 --- a/drivers/staging/et131x/README +++ b/drivers/staging/et131x/README @@ -13,10 +13,6 @@ TODO: - Implement NAPI support - In et131x_tx(), don't return NETDEV_TX_BUSY, just drop the packet with kfree_skb(). - Reduce the number of split lines by careful consideration of variable names etc. - - Do this in et131x.c: - struct fbr_lookup *fbr; - fbr = rx_local->fbr[id]; - Then replace all the instances of "rx_local->fbr[id]" with fbr. Please send patches to: Greg Kroah-Hartman -- cgit v1.2.3 From 57cc0279f59da295ea6d98c31fccf2c3a4547e09 Mon Sep 17 00:00:00 2001 From: ZHAO Gang Date: Mon, 9 Dec 2013 19:38:30 +0800 Subject: staging: et131x: remove unnecessary pointer typecast Signed-off-by: ZHAO Gang Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 89bd8ca00126..fdb19df0268d 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -1798,7 +1798,7 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) } /* Now's the best time to initialize FBR contents */ - fbr_entry = (struct fbr_desc *) fbr->ring_virtaddr; + fbr_entry = fbr->ring_virtaddr; for (entry = 0; entry < fbr->num_entries; entry++) { fbr_entry->addr_hi = fbr->bus_high[entry]; fbr_entry->addr_lo = fbr->bus_low[entry]; @@ -2290,8 +2290,8 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) WARN_ON(rx_ring->num_ready_recv != rx_ring->num_rfd); while (!list_empty(&rx_ring->recv_list)) { - rfd = (struct rfd *) list_entry(rx_ring->recv_list.next, - struct rfd, list_node); + rfd = list_entry(rx_ring->recv_list.next, + struct rfd, list_node); list_del(&rfd->list_node); rfd->skb = NULL; @@ -2536,7 +2536,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) spin_lock_irqsave(&adapter->rcv_lock, flags); element = rx_local->recv_list.next; - rfd = (struct rfd *) list_entry(element, struct rfd, list_node); + rfd = list_entry(element, struct rfd, list_node); if (!rfd) { spin_unlock_irqrestore(&adapter->rcv_lock, flags); @@ -2713,11 +2713,10 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) return -ENOMEM; desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX); - tx_ring->tx_desc_ring = - (struct tx_desc *) dma_alloc_coherent(&adapter->pdev->dev, - desc_size, - &tx_ring->tx_desc_ring_pa, - GFP_KERNEL); + tx_ring->tx_desc_ring = dma_alloc_coherent(&adapter->pdev->dev, + desc_size, + &tx_ring->tx_desc_ring_pa, + GFP_KERNEL); if (!adapter->tx_ring.tx_desc_ring) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Tx Ring\n"); @@ -3090,9 +3089,8 @@ static inline void free_send_packet(struct et131x_adapter *adapter, * they point to */ do { - desc = (struct tx_desc *) - (adapter->tx_ring.tx_desc_ring + - INDEX10(tcb->index_start)); + desc = adapter->tx_ring.tx_desc_ring + + INDEX10(tcb->index_start); dma_addr = desc->addr_lo; dma_addr |= (u64)desc->addr_hi << 32; -- cgit v1.2.3 From ae27b1428e874097d530f368d64c784f8701a0b4 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 9 Dec 2013 22:23:19 +0000 Subject: staging: vt6656: Remove STAvUpdateTDStatCounter and apply directly to stats Apply directly to net_device_stats and wireless stats. tx_bytes are relayed from s_vSaveTxPktInfo via scStatistic, so collect them there. All other statistics in STAvUpdateTDStatCounter are dead code and don't reach user. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 45 ++++++++++----------- drivers/staging/vt6656/iwctl.c | 1 - drivers/staging/vt6656/mib.c | 89 ------------------------------------------ drivers/staging/vt6656/mib.h | 3 -- drivers/staging/vt6656/rxtx.c | 3 ++ 5 files changed, 26 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index a2b4ba6d4f01..abbffa1577dd 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -86,10 +86,11 @@ void INTnsProcessData(struct vnt_private *pDevice) pINTData = (PSINTData) pDevice->intBuf.pDataBuf; if (pINTData->byTSR0 & TSR_VALID) { - STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (u8)(pINTData->byPkt0 & 0x0F), - (u8)(pINTData->byPkt0>>4), - pINTData->byTSR0); + if (pINTData->byTSR0 & (TSR_TMO | TSR_RETRYTMO)) + pDevice->wstats.discard.retries++; + else + pStats->tx_packets++; + BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), pINTData->byTSR0, @@ -97,10 +98,12 @@ void INTnsProcessData(struct vnt_private *pDevice) /*DBG_PRN_GRP01(("TSR0 %02x\n", pINTData->byTSR0));*/ } if (pINTData->byTSR1 & TSR_VALID) { - STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (u8)(pINTData->byPkt1 & 0x0F), - (u8)(pINTData->byPkt1>>4), - pINTData->byTSR1); + if (pINTData->byTSR1 & (TSR_TMO | TSR_RETRYTMO)) + pDevice->wstats.discard.retries++; + else + pStats->tx_packets++; + + BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), pINTData->byTSR1, @@ -108,10 +111,11 @@ void INTnsProcessData(struct vnt_private *pDevice) /*DBG_PRN_GRP01(("TSR1 %02x\n", pINTData->byTSR1));*/ } if (pINTData->byTSR2 & TSR_VALID) { - STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (u8)(pINTData->byPkt2 & 0x0F), - (u8)(pINTData->byPkt2>>4), - pINTData->byTSR2); + if (pINTData->byTSR2 & (TSR_TMO | TSR_RETRYTMO)) + pDevice->wstats.discard.retries++; + else + pStats->tx_packets++; + BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), pINTData->byTSR2, @@ -119,10 +123,11 @@ void INTnsProcessData(struct vnt_private *pDevice) /*DBG_PRN_GRP01(("TSR2 %02x\n", pINTData->byTSR2));*/ } if (pINTData->byTSR3 & TSR_VALID) { - STAvUpdateTDStatCounter(&(pDevice->scStatistic), - (u8)(pINTData->byPkt3 & 0x0F), - (u8)(pINTData->byPkt3>>4), - pINTData->byTSR3); + if (pINTData->byTSR3 & (TSR_TMO | TSR_RETRYTMO)) + pDevice->wstats.discard.retries++; + else + pStats->tx_packets++; + BSSvUpdateNodeTxCounter(pDevice, &(pDevice->scStatistic), pINTData->byTSR3, @@ -193,10 +198,6 @@ void INTnsProcessData(struct vnt_private *pDevice) pDevice->intBuf.uDataLen = 0; pDevice->intBuf.bInUse = false; - pStats->tx_packets = pDevice->scStatistic.ullTsrOK; - pStats->tx_bytes = pDevice->scStatistic.ullTxDirectedBytes + - pDevice->scStatistic.ullTxMulticastBytes + - pDevice->scStatistic.ullTxBroadcastBytes; - pStats->tx_errors = pDevice->scStatistic.dwTsrErr; - pStats->tx_dropped = pDevice->scStatistic.dwTsrErr; + pStats->tx_errors = pDevice->wstats.discard.retries; + pStats->tx_dropped = pDevice->wstats.discard.retries; } diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 63917abbbd00..183c5a2f57e1 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -68,7 +68,6 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) pDevice->wstats.discard.nwid = 0; pDevice->wstats.discard.code = 0; pDevice->wstats.discard.fragment = 0; - pDevice->wstats.discard.retries = pDevice->scStatistic.dwTsrErr; pDevice->wstats.discard.misc = 0; pDevice->wstats.miss.beacon = 0; return &pDevice->wstats; diff --git a/drivers/staging/vt6656/mib.c b/drivers/staging/vt6656/mib.c index 12333cdcbc6a..002f2b29a636 100644 --- a/drivers/staging/vt6656/mib.c +++ b/drivers/staging/vt6656/mib.c @@ -333,95 +333,6 @@ void STAvUpdateRDStatCounter(PSStatCounter pStatistic, } } -/* - * Description: Update Tx Statistic Counter - * - * Parameters: - * In: - * pStatistic - Pointer to Statistic Counter Data Structure - * byTSR0 - Tx Status - * byTSR1 - Tx Status - * pbyBuffer - Tx Buffer - * cbFrameLength - Tx Length - * uIdx - Index of Tx DMA - * Out: - * none - * - * Return Value: none - * - */ -void -STAvUpdateTDStatCounter ( - PSStatCounter pStatistic, - u8 byPktNum, - u8 byRate, - u8 byTSR - ) -{ - u8 byRetyCnt; - // increase tx packet count - pStatistic->dwTsrTxPacket++; - - byRetyCnt = (byTSR & 0xF0) >> 4; - if (byRetyCnt != 0) { - pStatistic->dwTsrRetry++; - pStatistic->dwTsrTotalRetry += byRetyCnt; - pStatistic->dwTxFail[byRate]+= byRetyCnt; - pStatistic->dwTxFail[MAX_RATE] += byRetyCnt; - - if ( byRetyCnt == 0x1) - pStatistic->dwTsrOnceRetry++; - else - pStatistic->dwTsrMoreThanOnceRetry++; - - if (byRetyCnt <= 8) - pStatistic->dwTxRetryCount[byRetyCnt-1]++; - - } - if ( !(byTSR & (TSR_TMO | TSR_RETRYTMO))) { - - if (byRetyCnt < 2) - pStatistic->TxNoRetryOkCount ++; - else - pStatistic->TxRetryOkCount ++; - - pStatistic->ullTsrOK++; - pStatistic->CustomStat.ullTsrAllOK++; - // update counters in case that successful transmit - pStatistic->dwTxOk[byRate]++; - pStatistic->dwTxOk[MAX_RATE]++; - - if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_BROAD ) { - pStatistic->ullTxBroadcastFrames++; - pStatistic->ullTxBroadcastBytes += pStatistic->abyTxPktInfo[byPktNum].wLength; - } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_MULTI ) { - pStatistic->ullTxMulticastFrames++; - pStatistic->ullTxMulticastBytes += pStatistic->abyTxPktInfo[byPktNum].wLength; - } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_UNI ) { - pStatistic->ullTxDirectedFrames++; - pStatistic->ullTxDirectedBytes += pStatistic->abyTxPktInfo[byPktNum].wLength; - } - } - else { - - pStatistic->TxFailCount ++; - - pStatistic->dwTsrErr++; - if (byTSR & TSR_RETRYTMO) - pStatistic->dwTsrRetryTimeout++; - if (byTSR & TSR_TMO) - pStatistic->dwTsrTransmitTimeout++; - } - - if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_BROAD ) { - pStatistic->dwTsrBroadcast++; - } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_MULTI ) { - pStatistic->dwTsrMulticast++; - } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_UNI ) { - pStatistic->dwTsrDirected++; - } -} - /* * Description: Update 802.11 mib counter * diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h index 35375325a777..5616b9a19735 100644 --- a/drivers/staging/vt6656/mib.h +++ b/drivers/staging/vt6656/mib.h @@ -360,9 +360,6 @@ void STAvUpdateRDStatCounter(PSStatCounter pStatistic, u8 byRxRate, u8 * pbyBuffer, unsigned int cbFrameLength); -void STAvUpdateTDStatCounter(PSStatCounter pStatistic, u8 byPktNum, - u8 byRate, u8 byTSR); - void STAvUpdate802_11Counter( PSDot11Counters p802_11Counter, diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 2db03d6d4c20..06290be36db7 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -166,6 +166,7 @@ static struct vnt_usb_send_context static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl) { + struct net_device_stats *stats = &pDevice->stats; PSStatCounter pStatistic = &pDevice->scStatistic; if (is_broadcast_ether_addr(pbyDestAddr)) @@ -180,6 +181,8 @@ static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, memcpy(pStatistic->abyTxPktInfo[byPktNum].abyDestAddr, pbyDestAddr, ETH_ALEN); + + stats->tx_bytes += wPktLength; } static void s_vFillTxKey(struct vnt_private *pDevice, -- cgit v1.2.3 From 854f775a12d387bcd203b70b62b4feb4aeb3c5eb Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 9 Dec 2013 22:25:48 +0000 Subject: staging: vt6656: Get wireless stats qual.qual directly from s_uCalculateLinkQual Calculate the qual from the tx_packets and wstats.discard.retries and apply to wstats.qual.qual Discard pDevice->scStatistic.LinkQuality. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/bssdb.c | 59 +++++++++++++++++++++++------------------- drivers/staging/vt6656/iwctl.c | 3 --- 2 files changed, 32 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index 1c3cbc54ce18..4c32b12f5e66 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -1384,39 +1384,44 @@ static void s_vCheckSensitivity(struct vnt_private *pDevice) static void s_uCalculateLinkQual(struct vnt_private *pDevice) { + struct net_device_stats *stats = &pDevice->stats; unsigned long TxOkRatio, TxCnt; unsigned long RxOkRatio, RxCnt; unsigned long RssiRatio; + unsigned long qual; long ldBm; -TxCnt = pDevice->scStatistic.TxNoRetryOkCount + - pDevice->scStatistic.TxRetryOkCount + - pDevice->scStatistic.TxFailCount; -RxCnt = pDevice->scStatistic.RxFcsErrCnt + + TxCnt = stats->tx_packets + pDevice->wstats.discard.retries; + + RxCnt = pDevice->scStatistic.RxFcsErrCnt + pDevice->scStatistic.RxOkCnt; -TxOkRatio = (TxCnt < 6) ? 4000:((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt); -RxOkRatio = (RxCnt < 6) ? 2000:((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); -//decide link quality -if(pDevice->bLinkPass !=true) -{ - pDevice->scStatistic.LinkQuality = 0; - pDevice->scStatistic.SignalStren = 0; -} -else -{ - RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); - if(-ldBm < 50) { - RssiRatio = 4000; - } - else if(-ldBm > 90) { - RssiRatio = 0; - } - else { - RssiRatio = (40-(-ldBm-50))*4000/40; - } - pDevice->scStatistic.SignalStren = RssiRatio/40; - pDevice->scStatistic.LinkQuality = (RssiRatio+TxOkRatio+RxOkRatio)/100; -} + + TxOkRatio = (TxCnt < 6) ? 4000:((stats->tx_packets * 4000) / TxCnt); + + RxOkRatio = (RxCnt < 6) ? 2000 : + ((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); + + /* decide link quality */ + if (pDevice->bLinkPass != true) { + pDevice->wstats.qual.qual = 0; + pDevice->scStatistic.SignalStren = 0; + } else { + RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); + if (-ldBm < 50) + RssiRatio = 4000; + else if (-ldBm > 90) + RssiRatio = 0; + else + RssiRatio = (40-(-ldBm-50)) * 4000 / 40; + + pDevice->scStatistic.SignalStren = RssiRatio / 40; + qual = (RssiRatio + TxOkRatio + RxOkRatio) / 100; + if (qual < 100) + pDevice->wstats.qual.qual = (u8)qual; + else + pDevice->wstats.qual.qual = 100; + } + pDevice->scStatistic.RxFcsErrCnt = 0; pDevice->scStatistic.RxOkCnt = 0; pDevice->scStatistic.TxFailCount = 0; diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 183c5a2f57e1..058df6516784 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -58,9 +58,6 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) long ldBm; pDevice->wstats.status = pDevice->eOPMode; - if (pDevice->scStatistic.LinkQuality > 100) - pDevice->scStatistic.LinkQuality = 100; - pDevice->wstats.qual.qual = (u8)pDevice->scStatistic.LinkQuality; RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); pDevice->wstats.qual.level = ldBm; pDevice->wstats.qual.noise = 0; -- cgit v1.2.3 From 9a450f9a7a1257ec7ec72e6397a4f9980eab68d8 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 9 Dec 2013 22:28:24 +0000 Subject: staging: vt6656: s_uCalculateLinkQual use netstats rx values Use netstats rx_packets and rx_frame_errors. Add frame errors to RXbBulkInProcessData The current scStatistic.RxFcsErrCnt only records USB errors not frame errors. The scStatistic.RxOkCnt only recorded successful USB transfers not actual successfully received packets. So a more accurate reading is to use netstats rx_packets and rx_frame_errors. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/bssdb.c | 5 ++--- drivers/staging/vt6656/dpc.c | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index 4c32b12f5e66..a0655a9e9fe5 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -1393,13 +1393,12 @@ static void s_uCalculateLinkQual(struct vnt_private *pDevice) TxCnt = stats->tx_packets + pDevice->wstats.discard.retries; - RxCnt = pDevice->scStatistic.RxFcsErrCnt + - pDevice->scStatistic.RxOkCnt; + RxCnt = stats->rx_packets + stats->rx_frame_errors; TxOkRatio = (TxCnt < 6) ? 4000:((stats->tx_packets * 4000) / TxCnt); RxOkRatio = (RxCnt < 6) ? 2000 : - ((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); + ((stats->rx_packets * 2000) / RxCnt); /* decide link quality */ if (pDevice->bLinkPass != true) { diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 2bed31b741c0..84901c1e3b59 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -291,12 +291,14 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB, if (BytesToIndicate != FrameSize) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n"); + pStats->rx_frame_errors++; return false; } if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) { // Frame Size error drop this packet. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n"); + pStats->rx_frame_errors++; return false; } @@ -314,6 +316,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB, (BytesToIndicate < (*pwPLCP_Length)) ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length); + pStats->rx_frame_errors++; return false; } for ( ii=RATE_1M;ii Date: Mon, 9 Dec 2013 22:30:14 +0000 Subject: staging: vt6656: Replace pStatistic->abyTxPktInfo with struct vnt_tx_pkt_info Change s_vSaveTxPktInfo and BSSvUpdateNodeTxCounter to use vnt_tx_pkt_info relayed to BSSvUpdateNodeTxCounter via INTnsProcessData. pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni is unused and discarded. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/bssdb.c | 8 ++++---- drivers/staging/vt6656/bssdb.h | 3 +-- drivers/staging/vt6656/device.h | 7 +++++++ drivers/staging/vt6656/int.c | 4 ---- drivers/staging/vt6656/rxtx.c | 18 ++++-------------- 5 files changed, 16 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index a0655a9e9fe5..c3fab7b7b5b6 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -1160,10 +1160,10 @@ else { * -*/ -void BSSvUpdateNodeTxCounter(struct vnt_private *pDevice, - PSStatCounter pStatistic, u8 byTSR, u8 byPktNO) +void BSSvUpdateNodeTxCounter(struct vnt_private *pDevice, u8 byTSR, u8 byPktNO) { struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_tx_pkt_info *pkt_info = pDevice->pkt_info; u32 uNodeIndex = 0; u8 byTxRetry; u16 wRate; @@ -1177,8 +1177,8 @@ void BSSvUpdateNodeTxCounter(struct vnt_private *pDevice, byPktNum = (byPktNO & 0x0F) >> 4; byTxRetry = (byTSR & 0xF0) >> 4; wRate = (u16) (byPktNO & 0xF0) >> 4; - wFIFOCtl = pStatistic->abyTxPktInfo[byPktNum].wFIFOCtl; - pbyDestAddr = (u8 *) &( pStatistic->abyTxPktInfo[byPktNum].abyDestAddr[0]); + wFIFOCtl = pkt_info[byPktNum].fifo_ctl; + pbyDestAddr = pkt_info[byPktNum].dest_addr; if (wFIFOCtl & FIFOCTL_AUTO_FB_0) { byFallBack = AUTO_FB_0; diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index fc418555bc4d..8b28ef6bd98f 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -264,8 +264,7 @@ void BSSvUpdateAPNode(struct vnt_private *, u16 *pwCapInfo, void BSSvSecondCallBack(struct work_struct *work); -void BSSvUpdateNodeTxCounter(struct vnt_private *, PSStatCounter pStatistic, - u8 byTSR, u8 byPktNO); +void BSSvUpdateNodeTxCounter(struct vnt_private *, u8 byTSR, u8 byPktNO); void BSSvRemoveOneNode(struct vnt_private *, u32 uNodeIndex); diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 82e1e6d695d1..c58c69a3170b 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -189,6 +189,12 @@ struct vnt_usb_send_context { unsigned char Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS]; }; +/* tx packet info for rxtx */ +struct vnt_tx_pkt_info { + u16 fifo_ctl; + u8 dest_addr[ETH_ALEN]; +}; + /* structure got from configuration file as user-desired default settings */ typedef struct _DEFAULT_CONFIG { signed int ZoneType; @@ -430,6 +436,7 @@ struct vnt_private { /* Variables to track resources for the BULK Out Pipe */ struct vnt_usb_send_context *apTD[CB_MAX_TX_DESC]; u32 cbTD; + struct vnt_tx_pkt_info pkt_info[16]; /* Variables to track resources for the Interrupt In Pipe */ INT_BUFFER intBuf; diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index abbffa1577dd..512bb5d8d3e4 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -92,7 +92,6 @@ void INTnsProcessData(struct vnt_private *pDevice) pStats->tx_packets++; BSSvUpdateNodeTxCounter(pDevice, - &(pDevice->scStatistic), pINTData->byTSR0, pINTData->byPkt0); /*DBG_PRN_GRP01(("TSR0 %02x\n", pINTData->byTSR0));*/ @@ -105,7 +104,6 @@ void INTnsProcessData(struct vnt_private *pDevice) BSSvUpdateNodeTxCounter(pDevice, - &(pDevice->scStatistic), pINTData->byTSR1, pINTData->byPkt1); /*DBG_PRN_GRP01(("TSR1 %02x\n", pINTData->byTSR1));*/ @@ -117,7 +115,6 @@ void INTnsProcessData(struct vnt_private *pDevice) pStats->tx_packets++; BSSvUpdateNodeTxCounter(pDevice, - &(pDevice->scStatistic), pINTData->byTSR2, pINTData->byPkt2); /*DBG_PRN_GRP01(("TSR2 %02x\n", pINTData->byTSR2));*/ @@ -129,7 +126,6 @@ void INTnsProcessData(struct vnt_private *pDevice) pStats->tx_packets++; BSSvUpdateNodeTxCounter(pDevice, - &(pDevice->scStatistic), pINTData->byTSR3, pINTData->byPkt3); /*DBG_PRN_GRP01(("TSR3 %02x\n", pINTData->byTSR3));*/ diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 06290be36db7..3186971eaa3f 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -167,20 +167,10 @@ static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl) { struct net_device_stats *stats = &pDevice->stats; - PSStatCounter pStatistic = &pDevice->scStatistic; - - if (is_broadcast_ether_addr(pbyDestAddr)) - pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_BROAD; - else if (is_multicast_ether_addr(pbyDestAddr)) - pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_MULTI; - else - pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_UNI; - - pStatistic->abyTxPktInfo[byPktNum].wLength = wPktLength; - pStatistic->abyTxPktInfo[byPktNum].wFIFOCtl = wFIFOCtl; - memcpy(pStatistic->abyTxPktInfo[byPktNum].abyDestAddr, - pbyDestAddr, - ETH_ALEN); + struct vnt_tx_pkt_info *pkt_info = pDevice->pkt_info; + + pkt_info[byPktNum].fifo_ctl = wFIFOCtl; + memcpy(pkt_info[byPktNum].dest_addr, pbyDestAddr, ETH_ALEN); stats->tx_bytes += wPktLength; } -- cgit v1.2.3 From 8f248dae133668bfb8e9379b4b3f0571c858b24a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 8 Dec 2013 09:11:30 +0000 Subject: staging: vt6656: [BUG] BBvUpdatePreEDThreshold Always set sensitivity on bScanning byBBPreEDIndex value is initially 0, this means that from cold BBvUpdatePreEDThreshold is never set. This means that sensitivity may be in an ambiguous state, failing to scan any wireless points or at least distant ones. Signed-off-by: Malcolm Priestley Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index d3dd1a23d5ca..3d4610e25fca 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -1450,7 +1450,6 @@ void BBvUpdatePreEDThreshold(struct vnt_private *pDevice, int bScanning) if( bScanning ) { // need Max sensitivity //RSSI -69, -70,.... - if(pDevice->byBBPreEDIndex == 0) break; pDevice->byBBPreEDIndex = 0; ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) @@ -1593,7 +1592,6 @@ void BBvUpdatePreEDThreshold(struct vnt_private *pDevice, int bScanning) if( bScanning ) { // need Max sensitivity //RSSI -69, -70, ... - if(pDevice->byBBPreEDIndex == 0) break; pDevice->byBBPreEDIndex = 0; ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x24); //CR206(0xCE) @@ -1745,7 +1743,6 @@ void BBvUpdatePreEDThreshold(struct vnt_private *pDevice, int bScanning) case RF_VT3342A0: //RobertYu:20060627, testing table if( bScanning ) { // need Max sensitivity //RSSI -67, -68, ... - if(pDevice->byBBPreEDIndex == 0) break; pDevice->byBBPreEDIndex = 0; ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x38); //CR206(0xCE) -- cgit v1.2.3 From c995c2f9ef67fda7740f571090894ea2ca2660eb Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 9 Dec 2013 23:08:35 +0000 Subject: staging: vt6656: Move double definition of MAX_RATE to device_cfg.h Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/datarate.h | 1 - drivers/staging/vt6656/device_cfg.h | 2 ++ drivers/staging/vt6656/mib.h | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/datarate.h b/drivers/staging/vt6656/datarate.h index 43cb77894b66..96252adf1ea6 100644 --- a/drivers/staging/vt6656/datarate.h +++ b/drivers/staging/vt6656/datarate.h @@ -52,7 +52,6 @@ #define RATE_48M 10 #define RATE_54M 11 #define RATE_AUTO 12 -#define MAX_RATE 12 void RATEvParseMaxRate(struct vnt_private *, PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pItemExtRates, int bUpdateBasicRate, diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h index a97f7bb13db8..0b9d8349c2e4 100644 --- a/drivers/staging/vt6656/device_cfg.h +++ b/drivers/staging/vt6656/device_cfg.h @@ -65,6 +65,8 @@ struct _version { #define DEVICE_VERSION "1.19_12" #endif +#define MAX_RATE 12 + /* config file */ #include #include diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h index 5616b9a19735..c342dadf2546 100644 --- a/drivers/staging/vt6656/mib.h +++ b/drivers/staging/vt6656/mib.h @@ -222,7 +222,6 @@ typedef struct tagSTxPktInfo { u8 abyDestAddr[ETH_ALEN]; } STxPktInfo, *PSTxPktInfo; -#define MAX_RATE 12 // // statistic counter // -- cgit v1.2.3 From b774930e0862fae23b0fe3e13cba01ad8954d270 Mon Sep 17 00:00:00 2001 From: Eli Billauer Date: Mon, 9 Dec 2013 10:16:52 +0200 Subject: staging: xillybus: Removed force to be a module The driver was forced to "module only" following a previous failure to build into the kernel. The problem was resolved several months ago. This has been successfully tested with "make allyesconfig" on x86_64. Reported-by: Stephen Rothwell Signed-off-by: Eli Billauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xillybus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/xillybus/Kconfig b/drivers/staging/xillybus/Kconfig index b15f778b4c68..75c38c8c26eb 100644 --- a/drivers/staging/xillybus/Kconfig +++ b/drivers/staging/xillybus/Kconfig @@ -4,7 +4,7 @@ config XILLYBUS tristate "Xillybus generic FPGA interface" - depends on PCI || (OF_ADDRESS && OF_IRQ) && m + depends on PCI || (OF_ADDRESS && OF_IRQ) help Xillybus is a generic interface for peripherals designed on programmable logic (FPGA). The driver probes the hardware for -- cgit v1.2.3 From 530376bfb7c82f50f20f9d28acd017194894eb66 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 9 Dec 2013 11:32:58 -0700 Subject: staging: comedi: ni_at_a2150: fix an always true condition test As pointed out by the kbuild test robot, and Ian Abbott, the dma >= 0 test is always true because dma is unsigned. This generates a warn message: drivers/staging/comedi/drivers/ni_at_a2150.c:715 a2150_attach() warn: always true condition '(dma >= 0) => (0-u32max >= 0)' Fix the test as suggested by Ian Abbott. Signed-off-by: H Hartley Sweeten Reported-by: kbuild test robot Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_at_a2150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 0876bc5c0209..0c71fdfecac2 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -712,7 +712,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - if (dev->irq && ((dma >= 0 && dma <= 4) || (dma >= 5 && dma <= 7))) { + if (dev->irq && dma <= 7 && dma != 4) { ret = request_dma(dma, dev->board_name); if (ret == 0) { devpriv->dma = dma; -- cgit v1.2.3 From 5e39edd48543c2cc80a28e265b83003737088929 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 11 Dec 2013 10:30:29 +0800 Subject: clk: hi3620: fix wrong flags on divider The flags on dividers should be CLK_DIVIDER_HIWORD_MASK, not CLK_MUX_HIWORD_MASK. Signed-off-by: Haojian Zhuang --- drivers/clk/hisilicon/clk-hi3620.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index b66b074fbda5..f0e779f11f3e 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -60,8 +60,8 @@ static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", }; static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", }; static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", }; -static const char *sd_mux_p[] __initdata = { "armpll3", "armpll2", }; -static const char *mmc1_mux_p[] __initdata = { "armpll3", "armpll2", }; +static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", }; static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", }; static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", }; static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", }; @@ -74,8 +74,8 @@ static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", }; static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4", "armpll3", "armpll5", }; static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", }; -static const char *mmc2_mux_p[] __initdata = { "armpll3", "armpll2", }; -static const char *mmc3_mux_p[] __initdata = { "armpll3", "armpll2", }; +static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", }; +static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", }; /* fixed rate clocks */ @@ -137,13 +137,13 @@ static struct hisi_mux_clock hi3620_mux_clks[] __initdata = { }; static struct hisi_divider_clock hi3620_div_clks[] __initdata = { - { HI3620_SHAREAXI_DIV, "saxi_div", "saxi_mux", 0, 0x100, 0, 5, CLK_MUX_HIWORD_MASK, NULL, }, - { HI3620_CFGAXI_DIV, "cfgaxi_div", "saxi_div", 0, 0x100, 5, 2, CLK_MUX_HIWORD_MASK, NULL, }, - { HI3620_SD_DIV, "sd_div", "sd_mux", 0, 0x108, 0, 4, CLK_MUX_HIWORD_MASK, NULL, }, - { HI3620_MMC1_DIV, "mmc1_div", "mmc1_mux", 0, 0x108, 5, 4, CLK_MUX_HIWORD_MASK, NULL, }, - { HI3620_HSIC_DIV, "hsic_div", "rclk_hsic", 0, 0x130, 0, 2, CLK_MUX_HIWORD_MASK, NULL, }, - { HI3620_MMC2_DIV, "mmc2_div", "mmc2_mux", 0, 0x140, 0, 4, CLK_MUX_HIWORD_MASK, NULL, }, - { HI3620_MMC3_DIV, "mmc3_div", "mmc3_mux", 0, 0x140, 5, 4, CLK_MUX_HIWORD_MASK, NULL, }, + { HI3620_SHAREAXI_DIV, "saxi_div", "saxi_mux", 0, 0x100, 0, 5, CLK_DIVIDER_HIWORD_MASK, NULL, }, + { HI3620_CFGAXI_DIV, "cfgaxi_div", "saxi_div", 0, 0x100, 5, 2, CLK_DIVIDER_HIWORD_MASK, NULL, }, + { HI3620_SD_DIV, "sd_div", "sd_mux", 0, 0x108, 0, 4, CLK_DIVIDER_HIWORD_MASK, NULL, }, + { HI3620_MMC1_DIV, "mmc1_div", "mmc1_mux", 0, 0x108, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, }, + { HI3620_HSIC_DIV, "hsic_div", "rclk_hsic", 0, 0x130, 0, 2, CLK_DIVIDER_HIWORD_MASK, NULL, }, + { HI3620_MMC2_DIV, "mmc2_div", "mmc2_mux", 0, 0x140, 0, 4, CLK_DIVIDER_HIWORD_MASK, NULL, }, + { HI3620_MMC3_DIV, "mmc3_div", "mmc3_mux", 0, 0x140, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, }, }; static struct hisi_gate_clock hi3620_seperated_gate_clks[] __initdata = { -- cgit v1.2.3 From ea010e5188dab61b64c1ad0221adc271039e7775 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 11 Dec 2013 13:07:55 +0800 Subject: clk: hi3620: add gate clock flag Add missing CLK_SET_RATE_PARENT flag for gate clock. Signed-off-by: Haojian Zhuang --- drivers/clk/hisilicon/clk-hi3620.c | 118 ++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index f0e779f11f3e..f24ad6a3a797 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -147,65 +147,65 @@ static struct hisi_divider_clock hi3620_div_clks[] __initdata = { }; static struct hisi_gate_clock hi3620_seperated_gate_clks[] __initdata = { - { HI3620_TIMERCLK01, "timerclk01", "timer_rclk01", 0, 0x20, 0, 0, }, - { HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo", 0, 0x20, 1, 0, }, - { HI3620_TIMERCLK23, "timerclk23", "timer_rclk23", 0, 0x20, 2, 0, }, - { HI3620_TIMER_RCLK23, "timer_rclk23", "rclk_tcxo", 0, 0x20, 3, 0, }, - { HI3620_RTCCLK, "rtcclk", "pclk", 0, 0x20, 5, 0, }, - { HI3620_KPC_CLK, "kpc_clk", "pclk", 0, 0x20, 6, 0, }, - { HI3620_GPIOCLK0, "gpioclk0", "pclk", 0, 0x20, 8, 0, }, - { HI3620_GPIOCLK1, "gpioclk1", "pclk", 0, 0x20, 9, 0, }, - { HI3620_GPIOCLK2, "gpioclk2", "pclk", 0, 0x20, 10, 0, }, - { HI3620_GPIOCLK3, "gpioclk3", "pclk", 0, 0x20, 11, 0, }, - { HI3620_GPIOCLK4, "gpioclk4", "pclk", 0, 0x20, 12, 0, }, - { HI3620_GPIOCLK5, "gpioclk5", "pclk", 0, 0x20, 13, 0, }, - { HI3620_GPIOCLK6, "gpioclk6", "pclk", 0, 0x20, 14, 0, }, - { HI3620_GPIOCLK7, "gpioclk7", "pclk", 0, 0x20, 15, 0, }, - { HI3620_GPIOCLK8, "gpioclk8", "pclk", 0, 0x20, 16, 0, }, - { HI3620_GPIOCLK9, "gpioclk9", "pclk", 0, 0x20, 17, 0, }, - { HI3620_GPIOCLK10, "gpioclk10", "pclk", 0, 0x20, 18, 0, }, - { HI3620_GPIOCLK11, "gpioclk11", "pclk", 0, 0x20, 19, 0, }, - { HI3620_GPIOCLK12, "gpioclk12", "pclk", 0, 0x20, 20, 0, }, - { HI3620_GPIOCLK13, "gpioclk13", "pclk", 0, 0x20, 21, 0, }, - { HI3620_GPIOCLK14, "gpioclk14", "pclk", 0, 0x20, 22, 0, }, - { HI3620_GPIOCLK15, "gpioclk15", "pclk", 0, 0x20, 23, 0, }, - { HI3620_GPIOCLK16, "gpioclk16", "pclk", 0, 0x20, 24, 0, }, - { HI3620_GPIOCLK17, "gpioclk17", "pclk", 0, 0x20, 25, 0, }, - { HI3620_GPIOCLK18, "gpioclk18", "pclk", 0, 0x20, 26, 0, }, - { HI3620_GPIOCLK19, "gpioclk19", "pclk", 0, 0x20, 27, 0, }, - { HI3620_GPIOCLK20, "gpioclk20", "pclk", 0, 0x20, 28, 0, }, - { HI3620_GPIOCLK21, "gpioclk21", "pclk", 0, 0x20, 29, 0, }, - { HI3620_DPHY0_CLK, "dphy0_clk", "osc26m", 0, 0x30, 15, 0, }, - { HI3620_DPHY1_CLK, "dphy1_clk", "osc26m", 0, 0x30, 16, 0, }, - { HI3620_DPHY2_CLK, "dphy2_clk", "osc26m", 0, 0x30, 17, 0, }, - { HI3620_USBPHY_CLK, "usbphy_clk", "rclk_pico", 0, 0x30, 24, 0, }, - { HI3620_ACP_CLK, "acp_clk", "rclk_cfgaxi", 0, 0x30, 28, 0, }, - { HI3620_TIMERCLK45, "timerclk45", "rclk_tcxo", 0, 0x40, 3, 0, }, - { HI3620_TIMERCLK67, "timerclk67", "rclk_tcxo", 0, 0x40, 4, 0, }, - { HI3620_TIMERCLK89, "timerclk89", "rclk_tcxo", 0, 0x40, 5, 0, }, - { HI3620_PWMCLK0, "pwmclk0", "pwm0_mux", 0, 0x40, 7, 0, }, - { HI3620_PWMCLK1, "pwmclk1", "pwm1_mux", 0, 0x40, 8, 0, }, - { HI3620_UARTCLK0, "uartclk0", "uart0_mux", 0, 0x40, 16, 0, }, - { HI3620_UARTCLK1, "uartclk1", "uart1_mux", 0, 0x40, 17, 0, }, - { HI3620_UARTCLK2, "uartclk2", "uart2_mux", 0, 0x40, 18, 0, }, - { HI3620_UARTCLK3, "uartclk3", "uart3_mux", 0, 0x40, 19, 0, }, - { HI3620_UARTCLK4, "uartclk4", "uart4_mux", 0, 0x40, 20, 0, }, - { HI3620_SPICLK0, "spiclk0", "spi0_mux", 0, 0x40, 21, 0, }, - { HI3620_SPICLK1, "spiclk1", "spi1_mux", 0, 0x40, 22, 0, }, - { HI3620_SPICLK2, "spiclk2", "spi2_mux", 0, 0x40, 23, 0, }, - { HI3620_I2CCLK0, "i2cclk0", "pclk", 0, 0x40, 24, 0, }, - { HI3620_I2CCLK1, "i2cclk1", "pclk", 0, 0x40, 25, 0, }, - { HI3620_SCI_CLK, "sci_clk", "osc26m", 0, 0x40, 26, 0, }, - { HI3620_I2CCLK2, "i2cclk2", "pclk", 0, 0x40, 28, 0, }, - { HI3620_I2CCLK3, "i2cclk3", "pclk", 0, 0x40, 29, 0, }, - { HI3620_DDRC_PER_CLK, "ddrc_per_clk", "rclk_cfgaxi", 0, 0x50, 9, 0, }, - { HI3620_DMAC_CLK, "dmac_clk", "rclk_cfgaxi", 0, 0x50, 10, 0, }, - { HI3620_USB2DVC_CLK, "usb2dvc_clk", "rclk_cfgaxi", 0, 0x50, 17, 0, }, - { HI3620_SD_CLK, "sd_clk", "sd_div", 0, 0x50, 20, 0, }, - { HI3620_MMC_CLK1, "mmc_clk1", "mmc1_mux2", 0, 0x50, 21, 0, }, - { HI3620_MMC_CLK2, "mmc_clk2", "mmc2_div", 0, 0x50, 22, 0, }, - { HI3620_MMC_CLK3, "mmc_clk3", "mmc3_div", 0, 0x50, 23, 0, }, - { HI3620_MCU_CLK, "mcu_clk", "acp_clk", 0, 0x50, 24, 0, }, + { HI3620_TIMERCLK01, "timerclk01", "timer_rclk01", CLK_SET_RATE_PARENT, 0x20, 0, 0, }, + { HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x20, 1, 0, }, + { HI3620_TIMERCLK23, "timerclk23", "timer_rclk23", CLK_SET_RATE_PARENT, 0x20, 2, 0, }, + { HI3620_TIMER_RCLK23, "timer_rclk23", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x20, 3, 0, }, + { HI3620_RTCCLK, "rtcclk", "pclk", CLK_SET_RATE_PARENT, 0x20, 5, 0, }, + { HI3620_KPC_CLK, "kpc_clk", "pclk", CLK_SET_RATE_PARENT, 0x20, 6, 0, }, + { HI3620_GPIOCLK0, "gpioclk0", "pclk", CLK_SET_RATE_PARENT, 0x20, 8, 0, }, + { HI3620_GPIOCLK1, "gpioclk1", "pclk", CLK_SET_RATE_PARENT, 0x20, 9, 0, }, + { HI3620_GPIOCLK2, "gpioclk2", "pclk", CLK_SET_RATE_PARENT, 0x20, 10, 0, }, + { HI3620_GPIOCLK3, "gpioclk3", "pclk", CLK_SET_RATE_PARENT, 0x20, 11, 0, }, + { HI3620_GPIOCLK4, "gpioclk4", "pclk", CLK_SET_RATE_PARENT, 0x20, 12, 0, }, + { HI3620_GPIOCLK5, "gpioclk5", "pclk", CLK_SET_RATE_PARENT, 0x20, 13, 0, }, + { HI3620_GPIOCLK6, "gpioclk6", "pclk", CLK_SET_RATE_PARENT, 0x20, 14, 0, }, + { HI3620_GPIOCLK7, "gpioclk7", "pclk", CLK_SET_RATE_PARENT, 0x20, 15, 0, }, + { HI3620_GPIOCLK8, "gpioclk8", "pclk", CLK_SET_RATE_PARENT, 0x20, 16, 0, }, + { HI3620_GPIOCLK9, "gpioclk9", "pclk", CLK_SET_RATE_PARENT, 0x20, 17, 0, }, + { HI3620_GPIOCLK10, "gpioclk10", "pclk", CLK_SET_RATE_PARENT, 0x20, 18, 0, }, + { HI3620_GPIOCLK11, "gpioclk11", "pclk", CLK_SET_RATE_PARENT, 0x20, 19, 0, }, + { HI3620_GPIOCLK12, "gpioclk12", "pclk", CLK_SET_RATE_PARENT, 0x20, 20, 0, }, + { HI3620_GPIOCLK13, "gpioclk13", "pclk", CLK_SET_RATE_PARENT, 0x20, 21, 0, }, + { HI3620_GPIOCLK14, "gpioclk14", "pclk", CLK_SET_RATE_PARENT, 0x20, 22, 0, }, + { HI3620_GPIOCLK15, "gpioclk15", "pclk", CLK_SET_RATE_PARENT, 0x20, 23, 0, }, + { HI3620_GPIOCLK16, "gpioclk16", "pclk", CLK_SET_RATE_PARENT, 0x20, 24, 0, }, + { HI3620_GPIOCLK17, "gpioclk17", "pclk", CLK_SET_RATE_PARENT, 0x20, 25, 0, }, + { HI3620_GPIOCLK18, "gpioclk18", "pclk", CLK_SET_RATE_PARENT, 0x20, 26, 0, }, + { HI3620_GPIOCLK19, "gpioclk19", "pclk", CLK_SET_RATE_PARENT, 0x20, 27, 0, }, + { HI3620_GPIOCLK20, "gpioclk20", "pclk", CLK_SET_RATE_PARENT, 0x20, 28, 0, }, + { HI3620_GPIOCLK21, "gpioclk21", "pclk", CLK_SET_RATE_PARENT, 0x20, 29, 0, }, + { HI3620_DPHY0_CLK, "dphy0_clk", "osc26m", CLK_SET_RATE_PARENT, 0x30, 15, 0, }, + { HI3620_DPHY1_CLK, "dphy1_clk", "osc26m", CLK_SET_RATE_PARENT, 0x30, 16, 0, }, + { HI3620_DPHY2_CLK, "dphy2_clk", "osc26m", CLK_SET_RATE_PARENT, 0x30, 17, 0, }, + { HI3620_USBPHY_CLK, "usbphy_clk", "rclk_pico", CLK_SET_RATE_PARENT, 0x30, 24, 0, }, + { HI3620_ACP_CLK, "acp_clk", "rclk_cfgaxi", CLK_SET_RATE_PARENT, 0x30, 28, 0, }, + { HI3620_TIMERCLK45, "timerclk45", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x40, 3, 0, }, + { HI3620_TIMERCLK67, "timerclk67", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x40, 4, 0, }, + { HI3620_TIMERCLK89, "timerclk89", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x40, 5, 0, }, + { HI3620_PWMCLK0, "pwmclk0", "pwm0_mux", CLK_SET_RATE_PARENT, 0x40, 7, 0, }, + { HI3620_PWMCLK1, "pwmclk1", "pwm1_mux", CLK_SET_RATE_PARENT, 0x40, 8, 0, }, + { HI3620_UARTCLK0, "uartclk0", "uart0_mux", CLK_SET_RATE_PARENT, 0x40, 16, 0, }, + { HI3620_UARTCLK1, "uartclk1", "uart1_mux", CLK_SET_RATE_PARENT, 0x40, 17, 0, }, + { HI3620_UARTCLK2, "uartclk2", "uart2_mux", CLK_SET_RATE_PARENT, 0x40, 18, 0, }, + { HI3620_UARTCLK3, "uartclk3", "uart3_mux", CLK_SET_RATE_PARENT, 0x40, 19, 0, }, + { HI3620_UARTCLK4, "uartclk4", "uart4_mux", CLK_SET_RATE_PARENT, 0x40, 20, 0, }, + { HI3620_SPICLK0, "spiclk0", "spi0_mux", CLK_SET_RATE_PARENT, 0x40, 21, 0, }, + { HI3620_SPICLK1, "spiclk1", "spi1_mux", CLK_SET_RATE_PARENT, 0x40, 22, 0, }, + { HI3620_SPICLK2, "spiclk2", "spi2_mux", CLK_SET_RATE_PARENT, 0x40, 23, 0, }, + { HI3620_I2CCLK0, "i2cclk0", "pclk", CLK_SET_RATE_PARENT, 0x40, 24, 0, }, + { HI3620_I2CCLK1, "i2cclk1", "pclk", CLK_SET_RATE_PARENT, 0x40, 25, 0, }, + { HI3620_SCI_CLK, "sci_clk", "osc26m", CLK_SET_RATE_PARENT, 0x40, 26, 0, }, + { HI3620_I2CCLK2, "i2cclk2", "pclk", CLK_SET_RATE_PARENT, 0x40, 28, 0, }, + { HI3620_I2CCLK3, "i2cclk3", "pclk", CLK_SET_RATE_PARENT, 0x40, 29, 0, }, + { HI3620_DDRC_PER_CLK, "ddrc_per_clk", "rclk_cfgaxi", CLK_SET_RATE_PARENT, 0x50, 9, 0, }, + { HI3620_DMAC_CLK, "dmac_clk", "rclk_cfgaxi", CLK_SET_RATE_PARENT, 0x50, 10, 0, }, + { HI3620_USB2DVC_CLK, "usb2dvc_clk", "rclk_cfgaxi", CLK_SET_RATE_PARENT, 0x50, 17, 0, }, + { HI3620_SD_CLK, "sd_clk", "sd_div", CLK_SET_RATE_PARENT, 0x50, 20, 0, }, + { HI3620_MMC_CLK1, "mmc_clk1", "mmc1_mux2", CLK_SET_RATE_PARENT, 0x50, 21, 0, }, + { HI3620_MMC_CLK2, "mmc_clk2", "mmc2_div", CLK_SET_RATE_PARENT, 0x50, 22, 0, }, + { HI3620_MMC_CLK3, "mmc_clk3", "mmc3_div", CLK_SET_RATE_PARENT, 0x50, 23, 0, }, + { HI3620_MCU_CLK, "mcu_clk", "acp_clk", CLK_SET_RATE_PARENT, 0x50, 24, 0, }, }; static void __init hi3620_clk_init(struct device_node *np) -- cgit v1.2.3 From 4cd89e91bb8dbefe54743df6a5c4437812c96e3a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 3 Dec 2013 21:25:13 -0300 Subject: [media] v4l: omap4iss: Replace printk by dev_err dev_err is preferred over printk(KERN_ERR) when a device pointer is available. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 8 ++++---- drivers/staging/media/omap4iss/iss_csi2.c | 7 ++++--- drivers/staging/media/omap4iss/iss_csiphy.c | 2 +- drivers/staging/media/omap4iss/iss_video.c | 3 ++- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index b7c8a6bc7d80..3ac986e6289c 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1108,7 +1108,7 @@ static int iss_register_entities(struct iss_device *iss) iss->media_dev.link_notify = iss_pipeline_link_notify; ret = media_device_register(&iss->media_dev); if (ret < 0) { - printk(KERN_ERR "%s: Media device registration failed (%d)\n", + dev_err(iss->dev, "%s: Media device registration failed (%d)\n", __func__, ret); return ret; } @@ -1116,7 +1116,7 @@ static int iss_register_entities(struct iss_device *iss) iss->v4l2_dev.mdev = &iss->media_dev; ret = v4l2_device_register(iss->dev, &iss->v4l2_dev); if (ret < 0) { - printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n", + dev_err(iss->dev, "%s: V4L2 device registration failed (%d)\n", __func__, ret); goto done; } @@ -1175,8 +1175,8 @@ static int iss_register_entities(struct iss_device *iss) break; default: - printk(KERN_ERR "%s: invalid interface type %u\n", - __func__, subdevs->interface); + dev_err(iss->dev, "%s: invalid interface type %u\n", + __func__, subdevs->interface); ret = -EINVAL; goto done; } diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index 0ee8381c738d..9ced9ce5c201 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -517,7 +517,8 @@ int omap4iss_csi2_reset(struct iss_csi2_device *csi2) } while (soft_reset_retries < 5); if (soft_reset_retries == 5) { - printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n"); + dev_err(csi2->iss->dev, + "CSI2: Soft reset try count exceeded!\n"); return -EBUSY; } @@ -535,8 +536,8 @@ int omap4iss_csi2_reset(struct iss_csi2_device *csi2) } while (--i > 0); if (i == 0) { - printk(KERN_ERR - "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n"); + dev_err(csi2->iss->dev, + "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n"); return -EBUSY; } diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c index 2afea98106a6..e0d02473d964 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -78,7 +78,7 @@ static int csiphy_set_power(struct iss_csiphy *phy, u32 power) } while ((reg != power >> 2) && (retry_count < 250)); if (retry_count == 250) { - printk(KERN_ERR "CSI2 CIO set power failed!\n"); + dev_err(phy->iss->dev, "CSI2 CIO set power failed!\n"); return -EBUSY; } diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 766491e6a8d0..5a92bac70bd6 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -1116,7 +1116,8 @@ int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev) ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1); if (ret < 0) - printk(KERN_ERR "%s: could not register video device (%d)\n", + dev_err(video->iss->dev, + "%s: could not register video device (%d)\n", __func__, ret); return ret; -- cgit v1.2.3 From 499226fb196fef838fa38700b96448a2ec41b704 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 3 Dec 2013 21:26:37 -0300 Subject: [media] v4l: omap4iss: Don't split log strings on multiple lines Non-split strings help grepping for messages. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 6 +++--- drivers/staging/media/omap4iss/iss_csi2.c | 13 ++++--------- drivers/staging/media/omap4iss/iss_resizer.c | 5 +---- drivers/staging/media/omap4iss/iss_video.c | 4 ++-- 4 files changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 3ac986e6289c..53dcb5488a7e 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1073,9 +1073,9 @@ iss_register_subdev_group(struct iss_device *iss, adapter = i2c_get_adapter(board_info->i2c_adapter_id); if (adapter == NULL) { - dev_err(iss->dev, "%s: Unable to get I2C adapter %d for " - "device %s\n", __func__, - board_info->i2c_adapter_id, + dev_err(iss->dev, + "%s: Unable to get I2C adapter %d for device %s\n", + __func__, board_info->i2c_adapter_id, board_info->board_info->type); continue; } diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index 9ced9ce5c201..c3a5fcaa02b0 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -754,8 +754,8 @@ void omap4iss_csi2_isr(struct iss_csi2_device *csi2) CSI2_COMPLEXIO_IRQSTATUS); writel(cpxio1_irqstatus, csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS); - dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ " - "%x\n", cpxio1_irqstatus); + dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ %x\n", + cpxio1_irqstatus); pipe->error = true; } @@ -764,13 +764,8 @@ void omap4iss_csi2_isr(struct iss_csi2_device *csi2) CSI2_IRQ_ECC_NO_CORRECTION | CSI2_IRQ_COMPLEXIO_ERR | CSI2_IRQ_FIFO_OVF)) { - dev_dbg(iss->dev, "CSI2 Err:" - " OCP:%d," - " Short_pack:%d," - " ECC:%d," - " CPXIO:%d," - " FIFO_OVF:%d," - "\n", + dev_dbg(iss->dev, + "CSI2 Err: OCP:%d SHORT:%d ECC:%d CPXIO:%d OVF:%d\n", (csi2_irqstatus & CSI2_IRQ_OCP_ERR) ? 1 : 0, (csi2_irqstatus & diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index cb5df52e45a6..e5a3a8cfbf2c 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -321,10 +321,7 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK | ISP5_IRQ_RSZ_FIFO_OVF)) { - dev_dbg(iss->dev, "RSZ Err:" - " FIFO_IN_BLK:%d," - " FIFO_OVF:%d," - "\n", + dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n", (events & ISP5_IRQ_RSZ_FIFO_IN_BLK) ? 1 : 0, (events & diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 5a92bac70bd6..3e543d92c8d8 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -324,8 +324,8 @@ static int iss_video_buf_prepare(struct vb2_buffer *vb) addr = vb2_dma_contig_plane_dma_addr(vb, 0); if (!IS_ALIGNED(addr, 32)) { - dev_dbg(video->iss->dev, "Buffer address must be " - "aligned to 32 bytes boundary.\n"); + dev_dbg(video->iss->dev, + "Buffer address must be aligned to 32 bytes boundary.\n"); return -EINVAL; } -- cgit v1.2.3 From a0fe029ccc648fb7f5dfcba5d4345040db574a53 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 3 Dec 2013 21:28:37 -0300 Subject: [media] v4l: omap4iss: Restrict line lengths to 80 characters where possible Pure CodingStyle fixes. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csiphy.c | 6 ++- drivers/staging/media/omap4iss/iss_ipipeif.c | 63 ++++++++++++++++------------ drivers/staging/media/omap4iss/iss_resizer.c | 47 ++++++++++++--------- drivers/staging/media/omap4iss/iss_video.c | 11 +++-- 4 files changed, 74 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c index e0d02473d964..25e6f8990242 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -178,7 +178,8 @@ int omap4iss_csiphy_config(struct iss_device *iss, if (lanes->data[i].pos == 0) continue; - if (lanes->data[i].pol > 1 || lanes->data[i].pos > (csi2->phy->max_data_lanes + 1)) + if (lanes->data[i].pol > 1 || + lanes->data[i].pos > (csi2->phy->max_data_lanes + 1)) return -EINVAL; if (used_lanes & (1 << lanes->data[i].pos)) @@ -188,7 +189,8 @@ int omap4iss_csiphy_config(struct iss_device *iss, csi2->phy->used_data_lanes++; } - if (lanes->clk.pol > 1 || lanes->clk.pos > (csi2->phy->max_data_lanes + 1)) + if (lanes->clk.pol > 1 || + lanes->clk.pos > (csi2->phy->max_data_lanes + 1)) return -EINVAL; if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos)) diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index acc6005dfacf..eee6891106be 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -23,10 +23,6 @@ #include "iss_regs.h" #include "iss_ipipeif.h" -static struct v4l2_mbus_framefmt * -__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh, - unsigned int pad, enum v4l2_subdev_format_whence which); - static const unsigned int ipipeif_fmts[] = { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, @@ -274,7 +270,8 @@ static void ipipeif_isif0_isr(struct iss_ipipeif_device *ipipeif) */ void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) { - if (omap4iss_module_sync_is_stopping(&ipipeif->wait, &ipipeif->stopping)) + if (omap4iss_module_sync_is_stopping(&ipipeif->wait, + &ipipeif->stopping)) return; if (events & ISP5_IRQ_ISIF0) @@ -285,7 +282,8 @@ void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) * ISP video operations */ -static int ipipeif_video_queue(struct iss_video *video, struct iss_buffer *buffer) +static int ipipeif_video_queue(struct iss_video *video, + struct iss_buffer *buffer) { struct iss_ipipeif_device *ipipeif = container_of(video, struct iss_ipipeif_device, video_out); @@ -385,8 +383,9 @@ static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) } static struct v4l2_mbus_framefmt * -__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh, - unsigned int pad, enum v4l2_subdev_format_whence which) +__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, + struct v4l2_subdev_fh *fh, unsigned int pad, + enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) return v4l2_subdev_get_try_format(fh, pad); @@ -402,9 +401,10 @@ __ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh * * @fmt: Format */ static void -ipipeif_try_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) +ipipeif_try_format(struct iss_ipipeif_device *ipipeif, + struct v4l2_subdev_fh *fh, unsigned int pad, + struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) { struct v4l2_mbus_framefmt *format; unsigned int width = fmt->width; @@ -413,8 +413,8 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh switch (pad) { case IPIPEIF_PAD_SINK: - /* TODO: If the IPIPEIF output formatter pad is connected directly - * to the resizer, only YUV formats can be used. + /* TODO: If the IPIPEIF output formatter pad is connected + * directly to the resizer, only YUV formats can be used. */ for (i = 0; i < ARRAY_SIZE(ipipeif_fmts); i++) { if (fmt->code == ipipeif_fmts[i]) @@ -431,7 +431,8 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh break; case IPIPEIF_PAD_SOURCE_ISIF_SF: - format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, which); + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, + which); memcpy(fmt, format, sizeof(*fmt)); /* The data formatter truncates the number of horizontal output @@ -445,7 +446,8 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh break; case IPIPEIF_PAD_SOURCE_VP: - format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, which); + format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, + which); memcpy(fmt, format, sizeof(*fmt)); fmt->width = clamp_t(u32, width, 32, fmt->width); @@ -514,7 +516,8 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = 1; format.height = 1; - ipipeif_try_format(ipipeif, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + ipipeif_try_format(ipipeif, fh, fse->pad, &format, + V4L2_SUBDEV_FORMAT_TRY); fse->min_width = format.width; fse->min_height = format.height; @@ -524,7 +527,8 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = -1; format.height = -1; - ipipeif_try_format(ipipeif, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + ipipeif_try_format(ipipeif, fh, fse->pad, &format, + V4L2_SUBDEV_FORMAT_TRY); fse->max_width = format.width; fse->max_height = format.height; @@ -578,14 +582,16 @@ static int ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, /* Propagate the format from sink to source */ if (fmt->pad == IPIPEIF_PAD_SINK) { - format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF, - fmt->which); + format = __ipipeif_get_format(ipipeif, fh, + IPIPEIF_PAD_SOURCE_ISIF_SF, + fmt->which); *format = fmt->format; - ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF, format, - fmt->which); + ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF, + format, fmt->which); - format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP, - fmt->which); + format = __ipipeif_get_format(ipipeif, fh, + IPIPEIF_PAD_SOURCE_VP, + fmt->which); *format = fmt->format; ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP, format, fmt->which); @@ -594,7 +600,8 @@ static int ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return 0; } -static int ipipeif_link_validate(struct v4l2_subdev *sd, struct media_link *link, +static int ipipeif_link_validate(struct v4l2_subdev *sd, + struct media_link *link, struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt) { @@ -618,7 +625,8 @@ static int ipipeif_link_validate(struct v4l2_subdev *sd, struct media_link *link * formats are initialized on the file handle. Otherwise active formats are * initialized on the device. */ -static int ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +static int ipipeif_init_formats(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) { struct v4l2_subdev_format format; @@ -778,8 +786,9 @@ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) return ret; /* Connect the IPIPEIF subdev to the video node. */ - ret = media_entity_create_link(&ipipeif->subdev.entity, IPIPEIF_PAD_SOURCE_ISIF_SF, - &ipipeif->video_out.video.entity, 0, 0); + ret = media_entity_create_link(&ipipeif->subdev.entity, + IPIPEIF_PAD_SOURCE_ISIF_SF, + &ipipeif->video_out.video.entity, 0, 0); if (ret < 0) return ret; diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index e5a3a8cfbf2c..08b2505c6666 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -23,10 +23,6 @@ #include "iss_regs.h" #include "iss_resizer.h" -static struct v4l2_mbus_framefmt * -__resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh, - unsigned int pad, enum v4l2_subdev_format_whence which); - static const unsigned int resizer_fmts[] = { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, @@ -329,7 +325,8 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) pipe->error = true; } - if (omap4iss_module_sync_is_stopping(&resizer->wait, &resizer->stopping)) + if (omap4iss_module_sync_is_stopping(&resizer->wait, + &resizer->stopping)) return; if (events & ISP5_IRQ_RSZ_INT_DMA) @@ -340,7 +337,8 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) * ISS video operations */ -static int resizer_video_queue(struct iss_video *video, struct iss_buffer *buffer) +static int resizer_video_queue(struct iss_video *video, + struct iss_buffer *buffer) { struct iss_resizer_device *resizer = container_of(video, struct iss_resizer_device, video_out); @@ -453,8 +451,9 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable) } static struct v4l2_mbus_framefmt * -__resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh, - unsigned int pad, enum v4l2_subdev_format_whence which) +__resizer_get_format(struct iss_resizer_device *resizer, + struct v4l2_subdev_fh *fh, unsigned int pad, + enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) return v4l2_subdev_get_try_format(fh, pad); @@ -470,9 +469,10 @@ __resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh * * @fmt: Format */ static void -resizer_try_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) +resizer_try_format(struct iss_resizer_device *resizer, + struct v4l2_subdev_fh *fh, unsigned int pad, + struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) { enum v4l2_mbus_pixelcode pixelcode; struct v4l2_mbus_framefmt *format; @@ -498,7 +498,8 @@ resizer_try_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh case RESIZER_PAD_SOURCE_MEM: pixelcode = fmt->code; - format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK, which); + format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK, + which); memcpy(fmt, format, sizeof(*fmt)); if ((pixelcode == V4L2_MBUS_FMT_YUYV8_1_5X8) && @@ -586,7 +587,8 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = 1; format.height = 1; - resizer_try_format(resizer, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + resizer_try_format(resizer, fh, fse->pad, &format, + V4L2_SUBDEV_FORMAT_TRY); fse->min_width = format.width; fse->min_height = format.height; @@ -596,7 +598,8 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd, format.code = fse->code; format.width = -1; format.height = -1; - resizer_try_format(resizer, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY); + resizer_try_format(resizer, fh, fse->pad, &format, + V4L2_SUBDEV_FORMAT_TRY); fse->max_width = format.width; fse->max_height = format.height; @@ -650,8 +653,9 @@ static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, /* Propagate the format from sink to source */ if (fmt->pad == RESIZER_PAD_SINK) { - format = __resizer_get_format(resizer, fh, RESIZER_PAD_SOURCE_MEM, - fmt->which); + format = __resizer_get_format(resizer, fh, + RESIZER_PAD_SOURCE_MEM, + fmt->which); *format = fmt->format; resizer_try_format(resizer, fh, RESIZER_PAD_SOURCE_MEM, format, fmt->which); @@ -660,7 +664,8 @@ static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return 0; } -static int resizer_link_validate(struct v4l2_subdev *sd, struct media_link *link, +static int resizer_link_validate(struct v4l2_subdev *sd, + struct media_link *link, struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt) { @@ -684,7 +689,8 @@ static int resizer_link_validate(struct v4l2_subdev *sd, struct media_link *link * formats are initialized on the file handle. Otherwise active formats are * initialized on the device. */ -static int resizer_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +static int resizer_init_formats(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) { struct v4l2_subdev_format format; @@ -833,8 +839,9 @@ static int resizer_init_entities(struct iss_resizer_device *resizer) return ret; /* Connect the RESIZER subdev to the video node. */ - ret = media_entity_create_link(&resizer->subdev.entity, RESIZER_PAD_SOURCE_MEM, - &resizer->video_out.video.entity, 0, 0); + ret = media_entity_create_link(&resizer->subdev.entity, + RESIZER_PAD_SOURCE_MEM, + &resizer->video_out.video.entity, 0, 0); if (ret < 0) return ret; diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 3e543d92c8d8..0a7137bcdcd2 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -282,7 +282,8 @@ iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh) * Video queue operations */ -static int iss_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +static int iss_video_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { @@ -298,7 +299,7 @@ static int iss_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format alloc_ctxs[0] = video->alloc_ctx; - *count = min(*count, (unsigned int)(video->capture_mem / PAGE_ALIGN(sizes[0]))); + *count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0])); return 0; } @@ -425,11 +426,13 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video) * first, so the input number might lag behind by 1 in some cases. */ if (video == pipe->output && !pipe->do_propagation) - buf->vb.v4l2_buf.sequence = atomic_inc_return(&pipe->frame_number); + buf->vb.v4l2_buf.sequence = + atomic_inc_return(&pipe->frame_number); else buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number); - vb2_buffer_done(&buf->vb, pipe->error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb, pipe->error ? + VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); pipe->error = false; spin_lock_irqsave(&video->qlock, flags); -- cgit v1.2.3 From 29ee62616348d7c7680728ad7df8d52fa5e67c0c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 3 Dec 2013 21:29:06 -0300 Subject: [media] v4l: omap4iss: Remove double semicolon at end of line Pure CodingStyle fixes. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 0a7137bcdcd2..7763b8dc9f6e 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -1039,7 +1039,7 @@ static int iss_video_mmap(struct file *file, struct vm_area_struct *vma) { struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); - return vb2_mmap(&vfh->queue, vma);; + return vb2_mmap(&vfh->queue, vma); } static struct v4l2_file_operations iss_video_fops = { -- cgit v1.2.3 From ade1ec3736c432981fefaa07b20e818c8501a44e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Aug 2013 12:03:50 -0300 Subject: [media] v4l: omap4iss: Define more ISS and ISP IRQ register bits Add more register definitions at iss_regs.h and improve some register names. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 26 ++++++++++---------- drivers/staging/media/omap4iss/iss_ipipeif.c | 2 +- drivers/staging/media/omap4iss/iss_regs.h | 36 +++++++++++++++++++++------- drivers/staging/media/omap4iss/iss_resizer.c | 4 ++-- 4 files changed, 43 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 53dcb5488a7e..815b09b991eb 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -40,9 +40,9 @@ static void iss_print_status(struct iss_device *iss) ISS_PRINT_REGISTER(iss, HL_REVISION); ISS_PRINT_REGISTER(iss, HL_SYSCONFIG); - ISS_PRINT_REGISTER(iss, HL_IRQSTATUS_5); - ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_SET); - ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_CLR); + ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5)); + ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5)); + ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5)); ISS_PRINT_REGISTER(iss, CTRL); ISS_PRINT_REGISTER(iss, CLKCTRL); ISS_PRINT_REGISTER(iss, CLKSTAT); @@ -75,8 +75,8 @@ static void iss_enable_interrupts(struct iss_device *iss) static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB | ISS_HL_IRQ_ISP(0); /* Enable HL interrupts */ - writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); - writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_SET); + writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS(5)); + writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_SET(5)); } @@ -86,7 +86,7 @@ static void iss_enable_interrupts(struct iss_device *iss) */ static void iss_disable_interrupts(struct iss_device *iss) { - writel(-1, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_CLR); + writel(-1, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_CLR(5)); } /* @@ -96,10 +96,10 @@ static void iss_disable_interrupts(struct iss_device *iss) void omap4iss_isp_enable_interrupts(struct iss_device *iss) { static const u32 isp_irq = ISP5_IRQ_OCP_ERR | - ISP5_IRQ_RSZ_FIFO_IN_BLK | + ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | ISP5_IRQ_RSZ_FIFO_OVF | ISP5_IRQ_RSZ_INT_DMA | - ISP5_IRQ_ISIF0; + ISP5_IRQ_ISIF_INT(0); /* Enable ISP interrupts */ writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQSTATUS(0)); @@ -256,16 +256,16 @@ static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) */ static irqreturn_t iss_isr(int irq, void *_iss) { - static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF | - ISP5_IRQ_ISIF0; - static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK | + static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ | + ISP5_IRQ_ISIF_INT(0); + static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | ISP5_IRQ_RSZ_FIFO_OVF | ISP5_IRQ_RSZ_INT_DMA; struct iss_device *iss = _iss; u32 irqstatus; - irqstatus = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); - writel(irqstatus, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); + irqstatus = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS(5)); + writel(irqstatus, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS(5)); if (irqstatus & ISS_HL_IRQ_CSIA) omap4iss_csi2_isr(&iss->csi2a); diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index eee6891106be..e96040fe0b95 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -274,7 +274,7 @@ void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events) &ipipeif->stopping)) return; - if (events & ISP5_IRQ_ISIF0) + if (events & ISP5_IRQ_ISIF_INT(0)) ipipeif_isif0_isr(ipipeif); } diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h index 7327d0c1ae37..16975ca44246 100644 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -24,12 +24,16 @@ #define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE 0x2 #define ISS_HL_SYSCONFIG_SOFTRESET (1 << 0) -#define ISS_HL_IRQSTATUS_5 (0x24 + (0x10 * 5)) -#define ISS_HL_IRQENABLE_5_SET (0x28 + (0x10 * 5)) -#define ISS_HL_IRQENABLE_5_CLR (0x2C + (0x10 * 5)) +#define ISS_HL_IRQSTATUS_RAW(i) (0x20 + (0x10 * (i))) +#define ISS_HL_IRQSTATUS(i) (0x24 + (0x10 * (i))) +#define ISS_HL_IRQENABLE_SET(i) (0x28 + (0x10 * (i))) +#define ISS_HL_IRQENABLE_CLR(i) (0x2c + (0x10 * (i))) +#define ISS_HL_IRQ_HS_VS (1 << 17) +#define ISS_HL_IRQ_SIMCOP(i) (1 << (12 + (i))) #define ISS_HL_IRQ_BTE (1 << 11) #define ISS_HL_IRQ_CBUFF (1 << 10) +#define ISS_HL_IRQ_CCP2(i) (1 << ((i) > 3 ? 16 : 14 + (i))) #define ISS_HL_IRQ_CSIB (1 << 5) #define ISS_HL_IRQ_CSIA (1 << 4) #define ISS_HL_IRQ_ISP(i) (1 << (i)) @@ -267,16 +271,30 @@ /* Bits shared for ISP5_IRQ* registers */ #define ISP5_IRQ_OCP_ERR (1 << 31) +#define ISP5_IRQ_IPIPE_INT_DPC_RNEW1 (1 << 29) +#define ISP5_IRQ_IPIPE_INT_DPC_RNEW0 (1 << 28) +#define ISP5_IRQ_IPIPE_INT_DPC_INIT (1 << 27) +#define ISP5_IRQ_IPIPE_INT_EOF (1 << 25) +#define ISP5_IRQ_H3A_INT_EOF (1 << 24) +#define ISP5_IRQ_RSZ_INT_EOF1 (1 << 23) #define ISP5_IRQ_RSZ_INT_EOF0 (1 << 22) -#define ISP5_IRQ_RSZ_FIFO_IN_BLK (1 << 19) +#define ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR (1 << 19) #define ISP5_IRQ_RSZ_FIFO_OVF (1 << 18) +#define ISP5_IRQ_RSZ_INT_CYC_RSZB (1 << 17) #define ISP5_IRQ_RSZ_INT_CYC_RSZA (1 << 16) #define ISP5_IRQ_RSZ_INT_DMA (1 << 15) -#define ISP5_IRQ_IPIPEIF (1 << 9) -#define ISP5_IRQ_ISIF3 (1 << 3) -#define ISP5_IRQ_ISIF2 (1 << 2) -#define ISP5_IRQ_ISIF1 (1 << 1) -#define ISP5_IRQ_ISIF0 (1 << 0) +#define ISP5_IRQ_RSZ_INT_LAST_PIX (1 << 14) +#define ISP5_IRQ_RSZ_INT_REG (1 << 13) +#define ISP5_IRQ_H3A_INT (1 << 12) +#define ISP5_IRQ_AF_INT (1 << 11) +#define ISP5_IRQ_AEW_INT (1 << 10) +#define ISP5_IRQ_IPIPEIF_IRQ (1 << 9) +#define ISP5_IRQ_IPIPE_INT_HST (1 << 8) +#define ISP5_IRQ_IPIPE_INT_BSC (1 << 7) +#define ISP5_IRQ_IPIPE_INT_DMA (1 << 6) +#define ISP5_IRQ_IPIPE_INT_LAST_PIX (1 << 5) +#define ISP5_IRQ_IPIPE_INT_REG (1 << 4) +#define ISP5_IRQ_ISIF_INT(i) (1 << (i)) #define ISP5_CTRL (0x006C) #define ISP5_CTRL_MSTANDBY (1 << 24) diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 08b2505c6666..272b92ad38dd 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -315,11 +315,11 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) struct iss_pipeline *pipe = to_iss_pipeline(&resizer->subdev.entity); - if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK | + if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | ISP5_IRQ_RSZ_FIFO_OVF)) { dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n", (events & - ISP5_IRQ_RSZ_FIFO_IN_BLK) ? 1 : 0, + ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR) ? 1 : 0, (events & ISP5_IRQ_RSZ_FIFO_OVF) ? 1 : 0); pipe->error = true; -- cgit v1.2.3 From 54d0059c7bbc26b10d11148f507c3a3a56d2bdd5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Aug 2013 12:03:50 -0300 Subject: [media] v4l: omap4iss: isif: Define more VDINT registers Use a macro to get the VDINT indexed registers. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_ipipeif.c | 4 ++-- drivers/staging/media/omap4iss/iss_regs.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index e96040fe0b95..5464742e76ff 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -67,7 +67,7 @@ static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif) ISIF_PRINT_REGISTER(iss, SPH); ISIF_PRINT_REGISTER(iss, LNH); ISIF_PRINT_REGISTER(iss, LNV); - ISIF_PRINT_REGISTER(iss, VDINT0); + ISIF_PRINT_REGISTER(iss, VDINT(0)); ISIF_PRINT_REGISTER(iss, HSIZE); ISP5_PRINT_REGISTER(iss, SYSCONFIG); @@ -213,7 +213,7 @@ cont_raw: /* Generate ISIF0 on the last line of the image */ writel(format->height - 1, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_VDINT0); + iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_VDINT(0)); /* IPIPEIF_PAD_SOURCE_ISIF_SF */ format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF]; diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h index 16975ca44246..d9693519b625 100644 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -363,8 +363,8 @@ #define ISIF_CCOLP_CP3_F0_B (3 << 0) #define ISIF_CCOLP_CP3_F0_GB (2 << 0) -#define ISIF_VDINT0 (0x0070) -#define ISIF_VDINT0_MASK (0x7FFF) +#define ISIF_VDINT(i) (0x0070 + (i) * 4) +#define ISIF_VDINT_MASK (0x7fff) #define ISIF_CGAMMAWD (0x0080) #define ISIF_CGAMMAWD_GWDI_MASK (0xF << 1) -- cgit v1.2.3 From 5122f6a26d4e706653e1677708594b82b1ec7cd3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Aug 2013 12:48:36 -0300 Subject: [media] v4l: omap4iss: Enhance IRQ debugging Add a pretty print function for ISP IRQs and remove the _INT suffix from interrupt names to enhance readability. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 121 +++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 815b09b991eb..65a16803949f 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -197,43 +197,44 @@ void omap4iss_configure_bridge(struct iss_device *iss, writel(isp5ctrl_val, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); } +#if defined(DEBUG) && defined(ISS_ISR_DEBUG) static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) { - static const char *name[] = { - "ISP_IRQ0", - "ISP_IRQ1", - "ISP_IRQ2", - "ISP_IRQ3", - "CSIA_IRQ", - "CSIB_IRQ", - "CCP2_IRQ0", - "CCP2_IRQ1", - "CCP2_IRQ2", - "CCP2_IRQ3", - "CBUFF_IRQ", - "BTE_IRQ", - "SIMCOP_IRQ0", - "SIMCOP_IRQ1", - "SIMCOP_IRQ2", - "SIMCOP_IRQ3", - "CCP2_IRQ8", - "HS_VS_IRQ", - "res18", - "res19", - "res20", - "res21", - "res22", - "res23", - "res24", - "res25", - "res26", - "res27", - "res28", - "res29", - "res30", - "res31", + static const char * const name[] = { + "ISP_0", + "ISP_1", + "ISP_2", + "ISP_3", + "CSIA", + "CSIB", + "CCP2_0", + "CCP2_1", + "CCP2_2", + "CCP2_3", + "CBUFF", + "BTE", + "SIMCOP_0", + "SIMCOP_1", + "SIMCOP_2", + "SIMCOP_3", + "CCP2_8", + "HS_VS", + "18", + "19", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "30", + "31", }; - int i; + unsigned int i; dev_dbg(iss->dev, "ISS IRQ: "); @@ -244,6 +245,54 @@ static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) pr_cont("\n"); } +static inline void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus) +{ + static const char * const name[] = { + "ISIF_0", + "ISIF_1", + "ISIF_2", + "ISIF_3", + "IPIPEREQ", + "IPIPELAST_PIX", + "IPIPEDMA", + "IPIPEBSC", + "IPIPEHST", + "IPIPEIF", + "AEW", + "AF", + "H3A", + "RSZ_REG", + "RSZ_LAST_PIX", + "RSZ_DMA", + "RSZ_CYC_RZA", + "RSZ_CYC_RZB", + "RSZ_FIFO_OVF", + "RSZ_FIFO_IN_BLK_ERR", + "20", + "21", + "RSZ_EOF0", + "RSZ_EOF1", + "H3A_EOF", + "IPIPE_EOF", + "26", + "IPIPE_DPC_INI", + "IPIPE_DPC_RNEW0", + "IPIPE_DPC_RNEW1", + "30", + "OCP_ERR", + }; + unsigned int i; + + dev_dbg(iss->dev, "ISP IRQ: "); + + for (i = 0; i < ARRAY_SIZE(name); i++) { + if ((1 << i) & irqstatus) + pr_cont("%s ", name[i]); + } + pr_cont("\n"); +} +#endif + /* * iss_isr - Interrupt Service Routine for ISS module. * @irq: Not used currently. @@ -290,6 +339,10 @@ static irqreturn_t iss_isr(int irq, void *_iss) if (isp_irqstatus & resizer_events) omap4iss_resizer_isr(&iss->resizer, isp_irqstatus & resizer_events); + +#if defined(DEBUG) && defined(ISS_ISR_DEBUG) + iss_isp_isr_dbg(iss, isp_irqstatus); +#endif } omap4iss_flush(iss); -- cgit v1.2.3 From 380df42b5730541a740735052d61e9d2ee09d0ce Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Aug 2013 12:51:03 -0300 Subject: [media] v4l: omap4iss: Don't make IRQ debugging functions inline Let the compiler decide. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 65a16803949f..e6528fa7a619 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -198,7 +198,7 @@ void omap4iss_configure_bridge(struct iss_device *iss, } #if defined(DEBUG) && defined(ISS_ISR_DEBUG) -static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) +static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) { static const char * const name[] = { "ISP_0", @@ -245,7 +245,7 @@ static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) pr_cont("\n"); } -static inline void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus) +static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus) { static const char * const name[] = { "ISIF_0", -- cgit v1.2.3 From cd782f9d6d6c4a713b5cc5ccc0bb65f86e294b2f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 28 Aug 2013 13:40:57 -0300 Subject: [media] v4l: omap4iss: Fix operators precedence in ternary operators The ternary operator ? : has a low precedence. Use parenthesis where needed. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csi2.c | 20 +++++++------------- drivers/staging/media/omap4iss/iss_ipipe.c | 2 +- drivers/staging/media/omap4iss/iss_ipipeif.c | 4 ++-- drivers/staging/media/omap4iss/iss_resizer.c | 12 +++++------- 4 files changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index c3a5fcaa02b0..ac5868acb489 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -274,7 +274,7 @@ static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr) */ static inline int is_usr_def_mapping(u32 format_id) { - return ((format_id & 0xF0) == 0x40) ? 1 : 0; + return (format_id & 0xF0) == 0x40 ? 1 : 0; } /* @@ -766,16 +766,11 @@ void omap4iss_csi2_isr(struct iss_csi2_device *csi2) CSI2_IRQ_FIFO_OVF)) { dev_dbg(iss->dev, "CSI2 Err: OCP:%d SHORT:%d ECC:%d CPXIO:%d OVF:%d\n", - (csi2_irqstatus & - CSI2_IRQ_OCP_ERR) ? 1 : 0, - (csi2_irqstatus & - CSI2_IRQ_SHORT_PACKET) ? 1 : 0, - (csi2_irqstatus & - CSI2_IRQ_ECC_NO_CORRECTION) ? 1 : 0, - (csi2_irqstatus & - CSI2_IRQ_COMPLEXIO_ERR) ? 1 : 0, - (csi2_irqstatus & - CSI2_IRQ_FIFO_OVF) ? 1 : 0); + csi2_irqstatus & CSI2_IRQ_OCP_ERR ? 1 : 0, + csi2_irqstatus & CSI2_IRQ_SHORT_PACKET ? 1 : 0, + csi2_irqstatus & CSI2_IRQ_ECC_NO_CORRECTION ? 1 : 0, + csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR ? 1 : 0, + csi2_irqstatus & CSI2_IRQ_FIFO_OVF ? 1 : 0); pipe->error = true; } @@ -1209,8 +1204,7 @@ static int csi2_link_setup(struct media_entity *entity, return -EINVAL; } - ctrl->vp_only_enable = - (csi2->output & CSI2_OUTPUT_MEMORY) ? false : true; + ctrl->vp_only_enable = csi2->output & CSI2_OUTPUT_MEMORY ? false : true; ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_IPIPEIF); return 0; diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c index fc38a5c5c8f5..bdafd78926a7 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ b/drivers/staging/media/omap4iss/iss_ipipe.c @@ -75,7 +75,7 @@ static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable) writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN) & ~IPIPE_SRC_EN_EN) | - enable ? IPIPE_SRC_EN_EN : 0, + (enable ? IPIPE_SRC_EN_EN : 0), iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN); } diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 5464742e76ff..3d6cc88a3ddd 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -85,7 +85,7 @@ static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable) writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) & ~ISIF_SYNCEN_DWEN) | - enable ? ISIF_SYNCEN_DWEN : 0, + (enable ? ISIF_SYNCEN_DWEN : 0), iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN); } @@ -100,7 +100,7 @@ static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable) writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) & ~ISIF_SYNCEN_SYEN) | - enable ? ISIF_SYNCEN_SYEN : 0, + (enable ? ISIF_SYNCEN_SYEN : 0), iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN); } diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 272b92ad38dd..68eb2a704cea 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -118,13 +118,13 @@ static void resizer_enable(struct iss_resizer_device *resizer, u8 enable) writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN) & ~RSZ_SRC_EN_SRC_EN) | - enable ? RSZ_SRC_EN_SRC_EN : 0, + (enable ? RSZ_SRC_EN_SRC_EN : 0), iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN); /* TODO: Enable RSZB */ writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) & ~RSZ_EN_EN) | - enable ? RSZ_EN_EN : 0, + (enable ? RSZ_EN_EN : 0), iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); } @@ -202,7 +202,7 @@ static void resizer_configure(struct iss_resizer_device *resizer) /* Select RSZ input */ writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) & ~RSZ_SRC_FMT0_SEL) | - (resizer->input == RESIZER_INPUT_IPIPEIF) ? RSZ_SRC_FMT0_SEL : 0, + (resizer->input == RESIZER_INPUT_IPIPEIF ? RSZ_SRC_FMT0_SEL : 0), iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0); /* RSZ ignores WEN signal from IPIPE/IPIPEIF */ @@ -318,10 +318,8 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | ISP5_IRQ_RSZ_FIFO_OVF)) { dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n", - (events & - ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR) ? 1 : 0, - (events & - ISP5_IRQ_RSZ_FIFO_OVF) ? 1 : 0); + events & ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR ? 1 : 0, + events & ISP5_IRQ_RSZ_FIFO_OVF ? 1 : 0); pipe->error = true; } -- cgit v1.2.3 From 74536b2ff073ed53d9c449d838938d6e500819f6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 29 Aug 2013 07:40:37 -0300 Subject: [media] v4l: omap4iss: isif: Ignore VD0 interrupts when no buffer is available The ISIF generates VD0 interrupts even when writes are disabled. Disabling the ISIF when no buffer is available is thus not be enough, we need to handle the situation explicitly. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_ipipeif.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 3d6cc88a3ddd..47fb1d6f9444 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -235,6 +235,13 @@ static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif) { struct iss_buffer *buffer; + /* The ISIF generates VD0 interrupts even when writes are disabled. + * deal with it anyway). Disabling the ISIF when no buffer is available + * is thus not be enough, we need to handle the situation explicitly. + */ + if (list_empty(&ipipeif->video_out.dmaqueue)) + return; + ipipeif_write_enable(ipipeif, 0); buffer = omap4iss_video_buffer_next(&ipipeif->video_out); -- cgit v1.2.3 From 86efc5043269df417d6145d912c87aafbed0c5c9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 30 Aug 2013 19:23:31 -0300 Subject: [media] v4l: omap4iss: ipipeif: Shift input data according to the input format Input samples must be left-aligned on the ISIF 16-bit data bus. Configure the 16-to-16-bit selector to shift data according to the input format. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_ipipeif.c | 4 +++- drivers/staging/media/omap4iss/iss_regs.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 47fb1d6f9444..28538512d043 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -129,6 +129,7 @@ static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr) static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) { struct iss_device *iss = to_iss_device(ipipeif); + const struct iss_format_info *info; struct v4l2_mbus_framefmt *format; u32 isif_ccolp = 0; @@ -194,9 +195,10 @@ cont_raw: ISIF_MODESET_INPMOD_RAW | ISIF_MODESET_CCDW_2BIT, iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET); + info = omap4iss_video_format_info(format->code); writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD) & ~ISIF_CGAMMAWD_GWDI_MASK) | - ISIF_CGAMMAWD_GWDI_BIT11, + ISIF_CGAMMAWD_GWDI(info->bpp), iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD); /* Set RAW Bayer pattern */ diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h index d9693519b625..5995e62d3e02 100644 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -368,7 +368,7 @@ #define ISIF_CGAMMAWD (0x0080) #define ISIF_CGAMMAWD_GWDI_MASK (0xF << 1) -#define ISIF_CGAMMAWD_GWDI_BIT11 (0x4 << 1) +#define ISIF_CGAMMAWD_GWDI(bpp) ((16 - (bpp)) << 1) #define ISIF_CCDCFG (0x0088) #define ISIF_CCDCFG_Y8POS (1 << 11) -- cgit v1.2.3 From 1be9ba20e1b3dccc7fb972f0f370ae27c0187718 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 29 Aug 2013 08:36:22 -0300 Subject: [media] v4l: omap4iss: csi2: Enable automatic ULP mode transition Automatically switch between ULP and ON states based on ULPM signal from complex I/O. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csiphy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c index 25e6f8990242..d5c7cec9b997 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -63,8 +63,8 @@ static int csiphy_set_power(struct iss_csiphy *phy, u32 power) writel((readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) & ~CSI2_COMPLEXIO_CFG_PWD_CMD_MASK) | - power, - phy->cfg_regs + CSI2_COMPLEXIO_CFG); + power | CSI2_COMPLEXIO_CFG_PWR_AUTO, + phy->cfg_regs + CSI2_COMPLEXIO_CFG); retry_count = 0; do { -- cgit v1.2.3 From 11abbfd30f74f79fe78d9ff79cc3fcfa86a975c5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 30 Aug 2013 22:23:17 -0300 Subject: [media] v4l: omap4iss: Create and use register access functions Replace the direct readl/writel calls with helper functions that take an ISS pointer and compute the register memory address. Also add bit clear, set and update helpers. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 96 ++++++++-------- drivers/staging/media/omap4iss/iss.h | 80 +++++++++++++ drivers/staging/media/omap4iss/iss_ipipe.c | 53 ++++----- drivers/staging/media/omap4iss/iss_ipipeif.c | 94 +++++++-------- drivers/staging/media/omap4iss/iss_resizer.c | 166 ++++++++++++--------------- 5 files changed, 265 insertions(+), 224 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index e6528fa7a619..ba8460dc8d28 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -32,7 +32,7 @@ #define ISS_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name)) static void iss_print_status(struct iss_device *iss) { @@ -62,8 +62,8 @@ static void iss_print_status(struct iss_device *iss) */ void omap4iss_flush(struct iss_device *iss) { - writel(0, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); - readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0); + iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); } /* @@ -75,8 +75,8 @@ static void iss_enable_interrupts(struct iss_device *iss) static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB | ISS_HL_IRQ_ISP(0); /* Enable HL interrupts */ - writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS(5)); - writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_SET(5)); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq); } @@ -86,7 +86,7 @@ static void iss_enable_interrupts(struct iss_device *iss) */ static void iss_disable_interrupts(struct iss_device *iss) { - writel(-1, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_CLR(5)); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), -1); } /* @@ -102,8 +102,9 @@ void omap4iss_isp_enable_interrupts(struct iss_device *iss) ISP5_IRQ_ISIF_INT(0); /* Enable ISP interrupts */ - writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQSTATUS(0)); - writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_SET(0)); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0), + isp_irq); } /* @@ -112,7 +113,7 @@ void omap4iss_isp_enable_interrupts(struct iss_device *iss) */ void omap4iss_isp_disable_interrupts(struct iss_device *iss) { - writel(-1, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_CLR(0)); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), -1); } int omap4iss_get_external_info(struct iss_pipeline *pipe, @@ -169,11 +170,11 @@ void omap4iss_configure_bridge(struct iss_device *iss, u32 issctrl_val; u32 isp5ctrl_val; - issctrl_val = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); + issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL); issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK; issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK; - isp5ctrl_val = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL); switch (input) { case IPIPEIF_INPUT_CSI2A: @@ -193,8 +194,8 @@ void omap4iss_configure_bridge(struct iss_device *iss, isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL | ISP5_CTRL_SYNC_ENABLE; - writel(issctrl_val, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); - writel(isp5ctrl_val, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val); } #if defined(DEBUG) && defined(ISS_ISR_DEBUG) @@ -313,8 +314,8 @@ static irqreturn_t iss_isr(int irq, void *_iss) struct iss_device *iss = _iss; u32 irqstatus; - irqstatus = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS(5)); - writel(irqstatus, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS(5)); + irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5)); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus); if (irqstatus & ISS_HL_IRQ_CSIA) omap4iss_csi2_isr(&iss->csi2a); @@ -323,10 +324,10 @@ static irqreturn_t iss_isr(int irq, void *_iss) omap4iss_csi2_isr(&iss->csi2b); if (irqstatus & ISS_HL_IRQ_ISP(0)) { - u32 isp_irqstatus = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + - ISP5_IRQSTATUS(0)); - writel(isp_irqstatus, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + - ISP5_IRQSTATUS(0)); + u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, + ISP5_IRQSTATUS(0)); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), + isp_irqstatus); if (isp_irqstatus & ISP5_IRQ_OCP_ERR) dev_dbg(iss->dev, "ISP5 OCP Error!\n"); @@ -689,12 +690,11 @@ static int iss_reset(struct iss_device *iss) { unsigned long timeout = 0; - writel(readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) | - ISS_HL_SYSCONFIG_SOFTRESET, - iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG); + iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG, + ISS_HL_SYSCONFIG_SOFTRESET); - while (readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) & - ISS_HL_SYSCONFIG_SOFTRESET) { + while (iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) & + ISS_HL_SYSCONFIG_SOFTRESET) { if (timeout++ > 100) { dev_alert(iss->dev, "cannot reset ISS\n"); return -ETIMEDOUT; @@ -710,18 +710,15 @@ static int iss_isp_reset(struct iss_device *iss) unsigned long timeout = 0; /* Fist, ensure that the ISP is IDLE (no transactions happening) */ - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) & - ~ISP5_SYSCONFIG_STANDBYMODE_MASK) | - ISP5_SYSCONFIG_STANDBYMODE_SMART, - iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, + ISP5_SYSCONFIG_STANDBYMODE_MASK, + ISP5_SYSCONFIG_STANDBYMODE_SMART); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) | - ISP5_CTRL_MSTANDBY, - iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY); for (;;) { - if (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & - ISP5_CTRL_MSTANDBY_WAIT) + if (iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) & + ISP5_CTRL_MSTANDBY_WAIT) break; if (timeout++ > 1000) { dev_alert(iss->dev, "cannot set ISP5 to standby\n"); @@ -731,13 +728,12 @@ static int iss_isp_reset(struct iss_device *iss) } /* Now finally, do the reset */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) | - ISP5_SYSCONFIG_SOFTRESET, - iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG); + iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, + ISP5_SYSCONFIG_SOFTRESET); timeout = 0; - while (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) & - ISP5_SYSCONFIG_SOFTRESET) { + while (iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) & + ISP5_SYSCONFIG_SOFTRESET) { if (timeout++ > 1000) { dev_alert(iss->dev, "cannot reset ISP5\n"); return -ETIMEDOUT; @@ -848,15 +844,14 @@ static int __iss_subclk_update(struct iss_device *iss) if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP) clk |= ISS_CLKCTRL_ISP; - writel((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL) & - ~ISS_CLKCTRL_MASK) | clk, - iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL); + iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL, + ISS_CLKCTRL_MASK, clk); /* Wait for HW assertion */ while (--timeout > 0) { udelay(1); - if ((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKSTAT) & - ISS_CLKCTRL_MASK) == clk) + if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) & + ISS_CLKCTRL_MASK) == clk) break; } @@ -911,9 +906,8 @@ static void __iss_isp_subclk_update(struct iss_device *iss) if (clk) clk |= ISP5_CTRL_BL_CLK_ENABLE; - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & - ~ISS_ISP5_CLKCTRL_MASK) | clk, - iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, + ISS_ISP5_CLKCTRL_MASK, clk); } void omap4iss_isp_subclk_enable(struct iss_device *iss, @@ -1380,7 +1374,7 @@ static int iss_probe(struct platform_device *pdev) if (ret < 0) goto error_iss; - iss->revision = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); + iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); dev_info(iss->dev, "Revision %08x found\n", iss->revision); for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) { @@ -1390,9 +1384,9 @@ static int iss_probe(struct platform_device *pdev) } /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */ - writel((readl(iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL) & ~BTE_CTRL_BW_LIMITER_MASK) | - (18 << BTE_CTRL_BW_LIMITER_SHIFT), - iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL); + iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL, + BTE_CTRL_BW_LIMITER_MASK, + 18 << BTE_CTRL_BW_LIMITER_SHIFT); /* Perform ISP reset */ ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP); @@ -1404,7 +1398,7 @@ static int iss_probe(struct platform_device *pdev) goto error_iss; dev_info(iss->dev, "ISP Revision %08x found\n", - readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_REVISION)); + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION)); /* Interrupt */ iss->irq_num = platform_get_irq(pdev, 0); diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index f33664d1d7cf..660809e27e00 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -150,4 +150,84 @@ int omap4iss_register_entities(struct platform_device *pdev, struct v4l2_device *v4l2_dev); void omap4iss_unregister_entities(struct platform_device *pdev); +/* + * iss_reg_read - Read the value of an OMAP4 ISS register + * @iss: the ISS device + * @res: memory resource in which the register is located + * @offset: register offset in the memory resource + * + * Return the register value. + */ +static inline +u32 iss_reg_read(struct iss_device *iss, enum iss_mem_resources res, + u32 offset) +{ + return readl(iss->regs[res] + offset); +} + +/* + * iss_reg_write - Write a value to an OMAP4 ISS register + * @iss: the ISS device + * @res: memory resource in which the register is located + * @offset: register offset in the memory resource + * @value: value to be written + */ +static inline +void iss_reg_write(struct iss_device *iss, enum iss_mem_resources res, + u32 offset, u32 value) +{ + writel(value, iss->regs[res] + offset); +} + +/* + * iss_reg_clr - Clear bits in an OMAP4 ISS register + * @iss: the ISS device + * @res: memory resource in which the register is located + * @offset: register offset in the memory resource + * @clr: bit mask to be cleared + */ +static inline +void iss_reg_clr(struct iss_device *iss, enum iss_mem_resources res, + u32 offset, u32 clr) +{ + u32 v = iss_reg_read(iss, res, offset); + + iss_reg_write(iss, res, offset, v & ~clr); +} + +/* + * iss_reg_set - Set bits in an OMAP4 ISS register + * @iss: the ISS device + * @res: memory resource in which the register is located + * @offset: register offset in the memory resource + * @set: bit mask to be set + */ +static inline +void iss_reg_set(struct iss_device *iss, enum iss_mem_resources res, + u32 offset, u32 set) +{ + u32 v = iss_reg_read(iss, res, offset); + + iss_reg_write(iss, res, offset, v | set); +} + +/* + * iss_reg_update - Clear and set bits in an OMAP4 ISS register + * @iss: the ISS device + * @res: memory resource in which the register is located + * @offset: register offset in the memory resource + * @clr: bit mask to be cleared + * @set: bit mask to be set + * + * Clear the clr mask first and then set the set mask. + */ +static inline +void iss_reg_update(struct iss_device *iss, enum iss_mem_resources res, + u32 offset, u32 clr, u32 set) +{ + u32 v = iss_reg_read(iss, res, offset); + + iss_reg_write(iss, res, offset, (v & ~clr) | set); +} + #endif /* _OMAP4_ISS_H_ */ diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c index bdafd78926a7..d0b9f8c512fc 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ b/drivers/staging/media/omap4iss/iss_ipipe.c @@ -42,7 +42,7 @@ static const unsigned int ipipe_fmts[] = { */ #define IPIPE_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_##name)) static void ipipe_print_status(struct iss_ipipe_device *ipipe) { @@ -73,10 +73,8 @@ static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable) { struct iss_device *iss = to_iss_device(ipipe); - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN) & - ~IPIPE_SRC_EN_EN) | - (enable ? IPIPE_SRC_EN_EN : 0), - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_EN, + IPIPE_SRC_EN_EN, enable ? IPIPE_SRC_EN_EN : 0); } /* ----------------------------------------------------------------------------- @@ -92,31 +90,28 @@ static void ipipe_configure(struct iss_ipipe_device *ipipe) format = &ipipe->formats[IPIPE_PAD_SINK]; /* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */ - writel(IPIPE_SRC_FMT_RAW2YUV, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_FMT); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_FMT, + IPIPE_SRC_FMT_RAW2YUV); /* Enable YUV444 -> YUV422 conversion */ - writel(IPIPE_YUV_PHS_LPF, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_YUV_PHS); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_YUV_PHS, + IPIPE_YUV_PHS_LPF); - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_VPS); - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_HPS); - writel((format->height - 2) & IPIPE_SRC_VSZ_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_VSZ); - writel((format->width - 1) & IPIPE_SRC_HSZ_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_HSZ); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VPS, 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HPS, 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VSZ, + (format->height - 2) & IPIPE_SRC_VSZ_MASK); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HSZ, + (format->width - 1) & IPIPE_SRC_HSZ_MASK); /* Ignore ipipeif_wrt signal, and operate on-the-fly. */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_MODE) & - ~(IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST), - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_MODE); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_MODE, + IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST); /* HACK: Values tuned for Ducati SW (OV) */ - writel(IPIPE_SRC_COL_EE_B | - IPIPE_SRC_COL_EO_GB | - IPIPE_SRC_COL_OE_GR | - IPIPE_SRC_COL_OO_R, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_COL); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_COL, + IPIPE_SRC_COL_EE_B | IPIPE_SRC_COL_EO_GB | + IPIPE_SRC_COL_OE_GR | IPIPE_SRC_COL_OO_R); /* IPIPE_PAD_SOURCE_VP */ format = &ipipe->formats[IPIPE_PAD_SOURCE_VP]; @@ -147,15 +142,13 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); /* Enable clk_arm_g0 */ - writel(IPIPE_GCK_MMR_REG, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_GCK_MMR); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_MMR, + IPIPE_GCK_MMR_REG); /* Enable clk_pix_g[3:0] */ - writel(IPIPE_GCK_PIX_G3 | - IPIPE_GCK_PIX_G2 | - IPIPE_GCK_PIX_G1 | - IPIPE_GCK_PIX_G0, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_GCK_PIX); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_PIX, + IPIPE_GCK_PIX_G3 | IPIPE_GCK_PIX_G2 | + IPIPE_GCK_PIX_G1 | IPIPE_GCK_PIX_G0); } switch (enable) { diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 28538512d043..2d11f62d0b12 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -40,15 +40,15 @@ static const unsigned int ipipeif_fmts[] = { */ #define IPIPEIF_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###IPIPEIF " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_##name)) #define ISIF_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###ISIF " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_##name)) #define ISP5_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###ISP5 " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_##name)) static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif) { @@ -83,10 +83,8 @@ static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable) { struct iss_device *iss = to_iss_device(ipipeif); - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) & - ~ISIF_SYNCEN_DWEN) | - (enable ? ISIF_SYNCEN_DWEN : 0), - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN, + ISIF_SYNCEN_DWEN, enable ? ISIF_SYNCEN_DWEN : 0); } /* @@ -98,10 +96,8 @@ static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable) { struct iss_device *iss = to_iss_device(ipipeif); - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) & - ~ISIF_SYNCEN_SYEN) | - (enable ? ISIF_SYNCEN_SYEN : 0), - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SYNCEN, + ISIF_SYNCEN_SYEN, enable ? ISIF_SYNCEN_SYEN : 0); } /* ----------------------------------------------------------------------------- @@ -120,10 +116,10 @@ static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr) struct iss_device *iss = to_iss_device(ipipeif); /* Save address splitted in Base Address H & L */ - writel((addr >> (16 + 5)) & ISIF_CADU_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CADU); - writel((addr >> 5) & ISIF_CADL_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CADL); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADU, + (addr >> (16 + 5)) & ISIF_CADU_MASK); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CADL, + (addr >> 5) & ISIF_CADL_MASK); } static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) @@ -139,25 +135,20 @@ static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) format = &ipipeif->formats[IPIPEIF_PAD_SINK]; /* IPIPEIF with YUV422 input from ISIF */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG1) & - ~(IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK), - iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG1); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG1, + IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK); /* Select ISIF/IPIPEIF input format */ switch (format->code) { case V4L2_MBUS_FMT_UYVY8_1X16: case V4L2_MBUS_FMT_YUYV8_1X16: - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET) & - ~(ISIF_MODESET_CCDMD | - ISIF_MODESET_INPMOD_MASK | - ISIF_MODESET_CCDW_MASK)) | - ISIF_MODESET_INPMOD_YCBCR16, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET); - - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2) & - ~IPIPEIF_CFG2_YUV8) | - IPIPEIF_CFG2_YUV16, - iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, + ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | + ISIF_MODESET_CCDW_MASK, + ISIF_MODESET_INPMOD_YCBCR16); + + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, + IPIPEIF_CFG2_YUV8, IPIPEIF_CFG2_YUV16); break; case V4L2_MBUS_FMT_SGRBG10_1X10: @@ -184,44 +175,41 @@ static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) ISIF_CCOLP_CP2_F0_R | ISIF_CCOLP_CP3_F0_GR; cont_raw: - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2) & - ~IPIPEIF_CFG2_YUV16), - iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, + IPIPEIF_CFG2_YUV16); - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET) & - ~(ISIF_MODESET_CCDMD | - ISIF_MODESET_INPMOD_MASK | - ISIF_MODESET_CCDW_MASK)) | - ISIF_MODESET_INPMOD_RAW | ISIF_MODESET_CCDW_2BIT, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, + ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | + ISIF_MODESET_CCDW_MASK, ISIF_MODESET_INPMOD_RAW | + ISIF_MODESET_CCDW_2BIT); info = omap4iss_video_format_info(format->code); - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD) & - ~ISIF_CGAMMAWD_GWDI_MASK) | - ISIF_CGAMMAWD_GWDI(info->bpp), - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CGAMMAWD, + ISIF_CGAMMAWD_GWDI_MASK, + ISIF_CGAMMAWD_GWDI(info->bpp)); /* Set RAW Bayer pattern */ - writel(isif_ccolp, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CCOLP); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CCOLP, + isif_ccolp); break; } - writel(0 & ISIF_SPH_MASK, iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SPH); - writel((format->width - 1) & ISIF_LNH_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_LNH); - writel((format->height - 1) & ISIF_LNV_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_LNV); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SPH, 0 & ISIF_SPH_MASK); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNH, + (format->width - 1) & ISIF_LNH_MASK); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNV, + (format->height - 1) & ISIF_LNV_MASK); /* Generate ISIF0 on the last line of the image */ - writel(format->height - 1, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_VDINT(0)); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_VDINT(0), + format->height - 1); /* IPIPEIF_PAD_SOURCE_ISIF_SF */ format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF]; - writel((ipipeif->video_out.bpl_value >> 5) & ISIF_HSIZE_HSIZE_MASK, - iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_HSIZE); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_HSIZE, + (ipipeif->video_out.bpl_value >> 5) & + ISIF_HSIZE_HSIZE_MASK); /* IPIPEIF_PAD_SOURCE_VP */ /* Do nothing? */ diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 68eb2a704cea..793325c33f81 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -36,11 +36,11 @@ static const unsigned int resizer_fmts[] = { */ #define RSZ_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###RSZ " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_##name)) #define RZA_PRINT_REGISTER(iss, name)\ dev_dbg(iss->dev, "###RZA " #name "=0x%08x\n", \ - readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_##name)) + iss_reg_read(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_##name)) static void resizer_print_status(struct iss_resizer_device *resizer) { @@ -116,16 +116,12 @@ static void resizer_enable(struct iss_resizer_device *resizer, u8 enable) { struct iss_device *iss = to_iss_device(resizer); - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN) & - ~RSZ_SRC_EN_SRC_EN) | - (enable ? RSZ_SRC_EN_SRC_EN : 0), - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_EN, + RSZ_SRC_EN_SRC_EN, enable ? RSZ_SRC_EN_SRC_EN : 0); /* TODO: Enable RSZB */ - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) & - ~RSZ_EN_EN) | - (enable ? RSZ_EN_EN : 0), - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN, + enable ? RSZ_EN_EN : 0); } /* ----------------------------------------------------------------------------- @@ -148,16 +144,16 @@ static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr) outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; /* Save address splitted in Base Address H & L */ - writel((addr >> 16) & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_BAD_H); - writel(addr & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_BAD_L); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_H, + (addr >> 16) & 0xffff); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_BAD_L, + addr & 0xffff); /* SAD = BAD */ - writel((addr >> 16) & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_SAD_H); - writel(addr & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_SAD_L); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_H, + (addr >> 16) & 0xffff); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_SAD_L, + addr & 0xffff); /* Program UV buffer address... Hardcoded to be contiguous! */ if ((informat->code == V4L2_MBUS_FMT_UYVY8_1X16) && @@ -173,16 +169,16 @@ static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr) } /* Save address splitted in Base Address H & L */ - writel((c_addr >> 16) & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_BAD_H); - writel(c_addr & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_BAD_L); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_H, + (c_addr >> 16) & 0xffff); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_BAD_L, + c_addr & 0xffff); /* SAD = BAD */ - writel((c_addr >> 16) & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_SAD_H); - writel(c_addr & 0xffff, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_SAD_L); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_H, + (c_addr >> 16) & 0xffff); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_SAD_L, + c_addr & 0xffff); } } @@ -195,70 +191,70 @@ static void resizer_configure(struct iss_resizer_device *resizer) outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; /* Make sure we don't bypass the resizer */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) & - ~RSZ_SRC_FMT0_BYPASS, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, + RSZ_SRC_FMT0_BYPASS); /* Select RSZ input */ - writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) & - ~RSZ_SRC_FMT0_SEL) | - (resizer->input == RESIZER_INPUT_IPIPEIF ? RSZ_SRC_FMT0_SEL : 0), - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0); + iss_reg_update(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, + RSZ_SRC_FMT0_SEL, + resizer->input == RESIZER_INPUT_IPIPEIF ? + RSZ_SRC_FMT0_SEL : 0); /* RSZ ignores WEN signal from IPIPE/IPIPEIF */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE) & - ~RSZ_SRC_MODE_WRT, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE, + RSZ_SRC_MODE_WRT); /* Set Resizer in free-running mode */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE) & - ~RSZ_SRC_MODE_OST, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_MODE, + RSZ_SRC_MODE_OST); /* Init Resizer A */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_MODE) & - ~RZA_MODE_ONE_SHOT, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_MODE); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_MODE, + RZA_MODE_ONE_SHOT); /* Set size related things now */ - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_VPS); - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_HPS); - writel(informat->height - 2, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_VSZ); - writel(informat->width - 1, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_HSZ); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VPS, 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HPS, 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_VSZ, + informat->height - 2); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_HSZ, + informat->width - 1); - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_I_VPS); - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_I_HPS); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_VPS, 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_I_HPS, 0); - writel(outformat->height - 2, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_O_VSZ); - writel(outformat->width - 1, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_O_HSZ); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_VSZ, + outformat->height - 2); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_O_HSZ, + outformat->width - 1); - writel(0x100, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_V_DIF); - writel(0x100, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_H_DIF); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_V_DIF, 0x100); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_H_DIF, 0x100); /* Buffer output settings */ - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_PTR_S); - writel(outformat->height - 1, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_PTR_E); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_S, 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_PTR_E, + outformat->height - 1); - writel(resizer->video_out.bpl_value, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_OFT); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_Y_OFT, + resizer->video_out.bpl_value); /* UYVY -> NV12 conversion */ if ((informat->code == V4L2_MBUS_FMT_UYVY8_1X16) && (outformat->code == V4L2_MBUS_FMT_YUYV8_1_5X8)) { - writel(RSZ_420_CEN | RSZ_420_YEN, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_420); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, + RSZ_420_CEN | RSZ_420_YEN); /* UV Buffer output settings */ - writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_PTR_S); - writel(outformat->height - 1, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_PTR_E); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_S, + 0); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_PTR_E, + outformat->height - 1); - writel(resizer->video_out.bpl_value, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_OFT); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_SDR_C_OFT, + resizer->video_out.bpl_value); } else { - writel(0, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_420); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, 0); } omap4iss_isp_enable_interrupts(iss); @@ -273,9 +269,7 @@ static void resizer_isr_buffer(struct iss_resizer_device *resizer) struct iss_device *iss = to_iss_device(resizer); struct iss_buffer *buffer; - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) & - ~RSZ_EN_EN, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN); buffer = omap4iss_video_buffer_next(&resizer->video_out); if (buffer == NULL) @@ -283,9 +277,7 @@ static void resizer_isr_buffer(struct iss_resizer_device *resizer) resizer_set_outaddr(resizer, buffer->iss_addr); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) | - RSZ_EN_EN, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN); + iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN); } /* @@ -386,17 +378,14 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable) omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR) | - RSZ_GCK_MMR_MMR, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR) | - RSZ_GCK_SDR_CORE, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR); + iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR, + RSZ_GCK_MMR_MMR); + iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, + RSZ_GCK_SDR_CORE); /* FIXME: Enable RSZB also */ - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG) | - RSZ_SYSCONFIG_RSZA_CLK_EN, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG); + iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, + RSZ_SYSCONFIG_RSZA_CLK_EN); } switch (enable) { @@ -430,15 +419,12 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable) resizer_enable(resizer, 0); omap4iss_isp_disable_interrupts(iss); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG) & - ~RSZ_SYSCONFIG_RSZA_CLK_EN, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR) & - ~RSZ_GCK_SDR_CORE, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR); - writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR) & - ~RSZ_GCK_MMR_MMR, - iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, + RSZ_SYSCONFIG_RSZA_CLK_EN); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, + RSZ_GCK_SDR_CORE); + iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_MMR, + RSZ_GCK_MMR_MMR); omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ); iss_video_dmaqueue_flags_clr(video_out); break; -- cgit v1.2.3 From 97059524ba6fd6c7dc77fa97e6957501b85af3be Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 30 Aug 2013 22:23:17 -0300 Subject: [media] v4l: omap4iss: csi: Create and use register access functions Replace the direct readl/writel calls with helper functions. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csi2.c | 122 +++++++++++++--------------- drivers/staging/media/omap4iss/iss_csi2.h | 6 +- drivers/staging/media/omap4iss/iss_csiphy.c | 27 +++--- drivers/staging/media/omap4iss/iss_csiphy.h | 6 +- 4 files changed, 76 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index ac5868acb489..f8d6472aa8bd 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -29,9 +29,8 @@ static void csi2_if_enable(struct iss_csi2_device *csi2, u8 enable) { struct iss_csi2_ctrl_cfg *currctrl = &csi2->ctrl; - writel((readl(csi2->regs1 + CSI2_CTRL) & ~CSI2_CTRL_IF_EN) | - (enable ? CSI2_CTRL_IF_EN : 0), - csi2->regs1 + CSI2_CTRL); + iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTRL, CSI2_CTRL_IF_EN, + enable ? CSI2_CTRL_IF_EN : 0); currctrl->if_enable = enable; } @@ -90,7 +89,7 @@ static void csi2_recv_config(struct iss_csi2_device *csi2, */ reg |= CSI2_CTRL_ENDIANNESS; - writel(reg, csi2->regs1 + CSI2_CTRL); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTRL, reg); } static const unsigned int csi2_input_fmts[] = { @@ -260,10 +259,10 @@ static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr) ctx->ping_addr = addr; ctx->pong_addr = addr; - writel(ctx->ping_addr, - csi2->regs1 + CSI2_CTX_PING_ADDR(ctx->ctxnum)); - writel(ctx->pong_addr, - csi2->regs1 + CSI2_CTX_PONG_ADDR(ctx->ctxnum)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum), + ctx->ping_addr); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum), + ctx->pong_addr); } /* @@ -288,7 +287,7 @@ static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable) struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum]; u32 reg; - reg = readl(csi2->regs1 + CSI2_CTX_CTRL1(ctxnum)); + reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum)); if (enable) { unsigned int skip = 0; @@ -306,7 +305,7 @@ static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable) reg &= ~CSI2_CTX_CTRL1_CTX_EN; } - writel(reg, csi2->regs1 + CSI2_CTX_CTRL1(ctxnum)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum), reg); ctx->enabled = enable; } @@ -330,7 +329,7 @@ static void csi2_ctx_config(struct iss_csi2_device *csi2, if (ctx->checksum_enabled) reg |= CSI2_CTX_CTRL1_CS_EN; - writel(reg, csi2->regs1 + CSI2_CTX_CTRL1(ctx->ctxnum)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctx->ctxnum), reg); /* Set up CSI2_CTx_CTRL2 */ reg = ctx->virtual_id << CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT; @@ -342,23 +341,20 @@ static void csi2_ctx_config(struct iss_csi2_device *csi2, if (is_usr_def_mapping(ctx->format_id)) reg |= 2 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT; - writel(reg, csi2->regs1 + CSI2_CTX_CTRL2(ctx->ctxnum)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL2(ctx->ctxnum), reg); /* Set up CSI2_CTx_CTRL3 */ - writel(ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT, - csi2->regs1 + CSI2_CTX_CTRL3(ctx->ctxnum)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL3(ctx->ctxnum), + ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT); /* Set up CSI2_CTx_DAT_OFST */ - reg = readl(csi2->regs1 + CSI2_CTX_DAT_OFST(ctx->ctxnum)); - reg &= ~CSI2_CTX_DAT_OFST_MASK; - reg |= ctx->data_offset; - writel(reg, csi2->regs1 + CSI2_CTX_DAT_OFST(ctx->ctxnum)); + iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTX_DAT_OFST(ctx->ctxnum), + CSI2_CTX_DAT_OFST_MASK, ctx->data_offset); - writel(ctx->ping_addr, - csi2->regs1 + CSI2_CTX_PING_ADDR(ctx->ctxnum)); - - writel(ctx->pong_addr, - csi2->regs1 + CSI2_CTX_PONG_ADDR(ctx->ctxnum)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum), + ctx->ping_addr); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum), + ctx->pong_addr); } /* @@ -370,7 +366,7 @@ static void csi2_timing_config(struct iss_csi2_device *csi2, { u32 reg; - reg = readl(csi2->regs1 + CSI2_TIMING); + reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_TIMING); if (timing->force_rx_mode) reg |= CSI2_TIMING_FORCE_RX_MODE_IO1; @@ -391,7 +387,7 @@ static void csi2_timing_config(struct iss_csi2_device *csi2, reg |= timing->stop_state_counter << CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT; - writel(reg, csi2->regs1 + CSI2_TIMING); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_TIMING, reg); } /* @@ -407,14 +403,14 @@ static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) reg |= CSI2_CTX_IRQ_FS; for (i = 0; i < 8; i++) { - writel(reg, csi2->regs1 + CSI2_CTX_IRQSTATUS(i)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i), + reg); if (enable) - writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) | reg, - csi2->regs1 + CSI2_CTX_IRQENABLE(i)); + iss_reg_set(csi2->iss, csi2->regs1, + CSI2_CTX_IRQENABLE(i), reg); else - writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) & - ~reg, - csi2->regs1 + CSI2_CTX_IRQENABLE(i)); + iss_reg_clr(csi2->iss, csi2->regs1, + CSI2_CTX_IRQENABLE(i), reg); } } @@ -452,12 +448,13 @@ static void csi2_irq_complexio1_set(struct iss_csi2_device *csi2, int enable) CSI2_COMPLEXIO_IRQ_ERRESC1 | CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 | CSI2_COMPLEXIO_IRQ_ERRSOTHS1; - writel(reg, csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, reg); if (enable) - reg |= readl(csi2->regs1 + CSI2_COMPLEXIO_IRQENABLE); + iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE, + reg); else - reg = 0; - writel(reg, csi2->regs1 + CSI2_COMPLEXIO_IRQENABLE); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE, + 0); } /* @@ -474,13 +471,11 @@ static void csi2_irq_status_set(struct iss_csi2_device *csi2, int enable) CSI2_IRQ_COMPLEXIO_ERR | CSI2_IRQ_FIFO_OVF | CSI2_IRQ_CONTEXT0; - writel(reg, csi2->regs1 + CSI2_IRQSTATUS); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, reg); if (enable) - reg |= readl(csi2->regs1 + CSI2_IRQENABLE); + iss_reg_set(csi2->iss, csi2->regs1, CSI2_IRQENABLE, reg); else - reg = 0; - - writel(reg, csi2->regs1 + CSI2_IRQENABLE); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQENABLE, 0); } /* @@ -502,13 +497,12 @@ int omap4iss_csi2_reset(struct iss_csi2_device *csi2) if (csi2->phy->phy_in_use) return -EBUSY; - writel(readl(csi2->regs1 + CSI2_SYSCONFIG) | - CSI2_SYSCONFIG_SOFT_RESET, - csi2->regs1 + CSI2_SYSCONFIG); + iss_reg_set(csi2->iss, csi2->regs1, CSI2_SYSCONFIG, + CSI2_SYSCONFIG_SOFT_RESET); do { - reg = readl(csi2->regs1 + CSI2_SYSSTATUS) & - CSI2_SYSSTATUS_RESET_DONE; + reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_SYSSTATUS) + & CSI2_SYSSTATUS_RESET_DONE; if (reg == CSI2_SYSSTATUS_RESET_DONE) break; soft_reset_retries++; @@ -522,13 +516,12 @@ int omap4iss_csi2_reset(struct iss_csi2_device *csi2) return -EBUSY; } - writel(readl(csi2->regs1 + CSI2_COMPLEXIO_CFG) | - CSI2_COMPLEXIO_CFG_RESET_CTRL, - csi2->regs1 + CSI2_COMPLEXIO_CFG); + iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_CFG, + CSI2_COMPLEXIO_CFG_RESET_CTRL); i = 100; do { - reg = readl(csi2->phy->phy_regs + REGISTER1) + reg = iss_reg_read(csi2->iss, csi2->phy->phy_regs, REGISTER1) & REGISTER1_RESET_DONE_CTRLCLK; if (reg == REGISTER1_RESET_DONE_CTRLCLK) break; @@ -541,11 +534,10 @@ int omap4iss_csi2_reset(struct iss_csi2_device *csi2) return -EBUSY; } - writel((readl(csi2->regs1 + CSI2_SYSCONFIG) & - ~(CSI2_SYSCONFIG_MSTANDBY_MODE_MASK | - CSI2_SYSCONFIG_AUTO_IDLE)) | - CSI2_SYSCONFIG_MSTANDBY_MODE_NO, - csi2->regs1 + CSI2_SYSCONFIG); + iss_reg_update(csi2->iss, csi2->regs1, CSI2_SYSCONFIG, + CSI2_SYSCONFIG_MSTANDBY_MODE_MASK | + CSI2_SYSCONFIG_AUTO_IDLE, + CSI2_SYSCONFIG_MSTANDBY_MODE_NO); return 0; } @@ -627,7 +619,7 @@ static int csi2_configure(struct iss_csi2_device *csi2) */ #define CSI2_PRINT_REGISTER(iss, regs, name)\ dev_dbg(iss->dev, "###CSI2 " #name "=0x%08x\n", \ - readl(regs + CSI2_##name)) + iss_reg_read(iss, regs, CSI2_##name)) static void csi2_print_status(struct iss_csi2_device *csi2) { @@ -695,8 +687,8 @@ static void csi2_isr_ctx(struct iss_csi2_device *csi2, unsigned int n = ctx->ctxnum; u32 status; - status = readl(csi2->regs1 + CSI2_CTX_IRQSTATUS(n)); - writel(status, csi2->regs1 + CSI2_CTX_IRQSTATUS(n)); + status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n)); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status); /* Propagate frame number */ if (status & CSI2_CTX_IRQ_FS) { @@ -745,15 +737,15 @@ void omap4iss_csi2_isr(struct iss_csi2_device *csi2) if (!csi2->available) return; - csi2_irqstatus = readl(csi2->regs1 + CSI2_IRQSTATUS); - writel(csi2_irqstatus, csi2->regs1 + CSI2_IRQSTATUS); + csi2_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, CSI2_IRQSTATUS); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, csi2_irqstatus); /* Failure Cases */ if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) { - cpxio1_irqstatus = readl(csi2->regs1 + - CSI2_COMPLEXIO_IRQSTATUS); - writel(cpxio1_irqstatus, - csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS); + cpxio1_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, + CSI2_COMPLEXIO_IRQSTATUS); + iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, + cpxio1_irqstatus); dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ %x\n", cpxio1_irqstatus); pipe->error = true; @@ -1319,7 +1311,7 @@ int omap4iss_csi2_init(struct iss_device *iss) csi2a->iss = iss; csi2a->available = 1; - csi2a->regs1 = iss->regs[OMAP4_ISS_MEM_CSI2_A_REGS1]; + csi2a->regs1 = OMAP4_ISS_MEM_CSI2_A_REGS1; csi2a->phy = &iss->csiphy1; csi2a->state = ISS_PIPELINE_STREAM_STOPPED; init_waitqueue_head(&csi2a->wait); @@ -1330,7 +1322,7 @@ int omap4iss_csi2_init(struct iss_device *iss) csi2b->iss = iss; csi2b->available = 1; - csi2b->regs1 = iss->regs[OMAP4_ISS_MEM_CSI2_B_REGS1]; + csi2b->regs1 = OMAP4_ISS_MEM_CSI2_B_REGS1; csi2b->phy = &iss->csiphy2; csi2b->state = ISS_PIPELINE_STREAM_STOPPED; init_waitqueue_head(&csi2b->wait); diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h index d1d077b18a1b..69a6263f6cb0 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.h +++ b/drivers/staging/media/omap4iss/iss_csi2.h @@ -128,9 +128,9 @@ struct iss_csi2_device { u8 available; /* Is the IP present on the silicon? */ - /* Pointer to register remaps into kernel space */ - void __iomem *regs1; - void __iomem *regs2; + /* memory resources, as defined in enum iss_mem_resources */ + unsigned int regs1; + unsigned int regs2; u32 output; /* output to IPIPEIF, memory or both? */ bool dpcm_decompress; diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c index d5c7cec9b997..902391af6440 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -31,7 +31,7 @@ static void csiphy_lanes_config(struct iss_csiphy *phy) unsigned int i; u32 reg; - reg = readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG); + reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG); for (i = 0; i < phy->max_data_lanes; i++) { reg &= ~(CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) | @@ -47,7 +47,7 @@ static void csiphy_lanes_config(struct iss_csiphy *phy) reg |= phy->lanes.clk.pol ? CSI2_COMPLEXIO_CFG_CLOCK_POL : 0; reg |= phy->lanes.clk.pos << CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT; - writel(reg, phy->cfg_regs + CSI2_COMPLEXIO_CFG); + iss_reg_write(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, reg); } /* @@ -61,16 +61,15 @@ static int csiphy_set_power(struct iss_csiphy *phy, u32 power) u32 reg; u8 retry_count; - writel((readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) & - ~CSI2_COMPLEXIO_CFG_PWD_CMD_MASK) | - power | CSI2_COMPLEXIO_CFG_PWR_AUTO, - phy->cfg_regs + CSI2_COMPLEXIO_CFG); + iss_reg_update(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG, + CSI2_COMPLEXIO_CFG_PWD_CMD_MASK, + power | CSI2_COMPLEXIO_CFG_PWR_AUTO); retry_count = 0; do { udelay(1); - reg = readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) & - CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK; + reg = iss_reg_read(phy->iss, phy->cfg_regs, CSI2_COMPLEXIO_CFG) + & CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK; if (reg != power >> 2) retry_count++; @@ -98,7 +97,7 @@ static void csiphy_dphy_config(struct iss_csiphy *phy) reg = phy->dphy.ths_term << REGISTER0_THS_TERM_SHIFT; reg |= phy->dphy.ths_settle << REGISTER0_THS_SETTLE_SHIFT; - writel(reg, phy->phy_regs + REGISTER0); + iss_reg_write(phy->iss, phy->phy_regs, REGISTER0, reg); /* Set up REGISTER1 */ reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT; @@ -106,7 +105,7 @@ static void csiphy_dphy_config(struct iss_csiphy *phy) reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT; reg |= 0xB8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT; - writel(reg, phy->phy_regs + REGISTER1); + iss_reg_write(phy->iss, phy->phy_regs, REGISTER1, reg); } /* @@ -264,16 +263,16 @@ int omap4iss_csiphy_init(struct iss_device *iss) phy1->csi2 = &iss->csi2a; phy1->max_data_lanes = ISS_CSIPHY1_NUM_DATA_LANES; phy1->used_data_lanes = 0; - phy1->cfg_regs = iss->regs[OMAP4_ISS_MEM_CSI2_A_REGS1]; - phy1->phy_regs = iss->regs[OMAP4_ISS_MEM_CAMERARX_CORE1]; + phy1->cfg_regs = OMAP4_ISS_MEM_CSI2_A_REGS1; + phy1->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE1; mutex_init(&phy1->mutex); phy2->iss = iss; phy2->csi2 = &iss->csi2b; phy2->max_data_lanes = ISS_CSIPHY2_NUM_DATA_LANES; phy2->used_data_lanes = 0; - phy2->cfg_regs = iss->regs[OMAP4_ISS_MEM_CSI2_B_REGS1]; - phy2->phy_regs = iss->regs[OMAP4_ISS_MEM_CAMERARX_CORE2]; + phy2->cfg_regs = OMAP4_ISS_MEM_CSI2_B_REGS1; + phy2->phy_regs = OMAP4_ISS_MEM_CAMERARX_CORE2; mutex_init(&phy2->mutex); return 0; diff --git a/drivers/staging/media/omap4iss/iss_csiphy.h b/drivers/staging/media/omap4iss/iss_csiphy.h index df63edaf9778..e9ca43955654 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.h +++ b/drivers/staging/media/omap4iss/iss_csiphy.h @@ -32,9 +32,9 @@ struct iss_csiphy { u8 phy_in_use; struct iss_csi2_device *csi2; - /* Pointer to register remaps into kernel space */ - void __iomem *cfg_regs; - void __iomem *phy_regs; + /* memory resources, as defined in enum iss_mem_resources */ + unsigned int cfg_regs; + unsigned int phy_regs; u8 max_data_lanes; /* number of CSI2 Data Lanes supported */ u8 used_data_lanes; /* number of CSI2 Data Lanes used */ -- cgit v1.2.3 From 82043ff6af1300ba6cdc868adbafbc5ee6965a89 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 4 Sep 2013 09:48:20 -0300 Subject: [media] v4l: omap4iss: resizer: Stop the whole resizer to avoid FIFO overflows When stopping the resizer due to a buffer underrun, disabling RZA only produces input FIFO overflows, most probably when the next frame is received. Disable the whole resizer to work around the problem. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_resizer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 793325c33f81..5bf50808acc3 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -266,10 +266,12 @@ static void resizer_configure(struct iss_resizer_device *resizer) static void resizer_isr_buffer(struct iss_resizer_device *resizer) { - struct iss_device *iss = to_iss_device(resizer); struct iss_buffer *buffer; - iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN); + /* The whole resizer needs to be stopped. Disabling RZA only produces + * input FIFO overflows, most probably when the next frame is received. + */ + resizer_enable(resizer, 0); buffer = omap4iss_video_buffer_next(&resizer->video_out); if (buffer == NULL) @@ -277,7 +279,7 @@ static void resizer_isr_buffer(struct iss_resizer_device *resizer) resizer_set_outaddr(resizer, buffer->iss_addr); - iss_reg_set(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_EN, RSZ_EN_EN); + resizer_enable(resizer, 1); } /* -- cgit v1.2.3 From 3c4ee96b5fd5bb0223965fda97918fdd353d240c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 4 Sep 2013 12:32:12 -0300 Subject: [media] v4l: omap4iss: Convert hexadecimal constants to lower case The Linux kernel recommends lower case for hexadecimal constants. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csi2.c | 4 +- drivers/staging/media/omap4iss/iss_csiphy.c | 4 +- drivers/staging/media/omap4iss/iss_regs.h | 458 ++++++++++++++-------------- 3 files changed, 233 insertions(+), 233 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index f8d6472aa8bd..077545ffa54f 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -273,7 +273,7 @@ static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr) */ static inline int is_usr_def_mapping(u32 format_id) { - return (format_id & 0xF0) == 0x40 ? 1 : 0; + return (format_id & 0xf0) == 0x40 ? 1 : 0; } /* @@ -572,7 +572,7 @@ static int csi2_configure(struct iss_csi2_device *csi2) timing->force_rx_mode = 1; timing->stop_state_16x = 1; timing->stop_state_4x = 1; - timing->stop_state_counter = 0x1FF; + timing->stop_state_counter = 0x1ff; /* * The CSI2 receiver can't do any format conversion except DPCM diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c index 902391af6440..7c3d55d811ef 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -103,7 +103,7 @@ static void csiphy_dphy_config(struct iss_csiphy *phy) reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT; reg |= phy->dphy.tclk_miss << REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT; reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT; - reg |= 0xB8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT; + reg |= 0xb8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT; iss_reg_write(phy->iss, phy->phy_regs, REGISTER1, reg); } @@ -150,7 +150,7 @@ int omap4iss_csiphy_config(struct iss_device *iss, /* NOTE: Leave CSIPHY1 config to 0x0: D-PHY mode */ /* Enable all lanes for now */ cam_rx_ctrl |= - 0x1F << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT; + 0x1f << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT; /* Enable CTRLCLK */ cam_rx_ctrl |= OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK; } diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h index 5995e62d3e02..efd0291a86f7 100644 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -65,7 +65,7 @@ #define ISS_CLKSTAT_ISP (1 << 1) #define ISS_CLKSTAT_SIMCOP (1 << 0) -#define ISS_PM_STATUS 0x8C +#define ISS_PM_STATUS 0x8c #define ISS_PM_STATUS_CBUFF_PM_MASK (3 << 12) #define ISS_PM_STATUS_BTE_PM_MASK (3 << 10) #define ISS_PM_STATUS_SIMCOP_PM_MASK (3 << 8) @@ -76,20 +76,20 @@ #define REGISTER0 0x0 #define REGISTER0_HSCLOCKCONFIG (1 << 24) -#define REGISTER0_THS_TERM_MASK (0xFF << 8) +#define REGISTER0_THS_TERM_MASK (0xff << 8) #define REGISTER0_THS_TERM_SHIFT 8 -#define REGISTER0_THS_SETTLE_MASK (0xFF << 0) +#define REGISTER0_THS_SETTLE_MASK (0xff << 0) #define REGISTER0_THS_SETTLE_SHIFT 0 #define REGISTER1 0x4 #define REGISTER1_RESET_DONE_CTRLCLK (1 << 29) #define REGISTER1_CLOCK_MISS_DETECTOR_STATUS (1 << 25) -#define REGISTER1_TCLK_TERM_MASK (0x3F << 18) +#define REGISTER1_TCLK_TERM_MASK (0x3f << 18) #define REGISTER1_TCLK_TERM_SHIFT 18 #define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT 10 #define REGISTER1_CTRLCLK_DIV_FACTOR_MASK (0x3 << 8) #define REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT 8 -#define REGISTER1_TCLK_SETTLE_MASK (0xFF << 0) +#define REGISTER1_TCLK_SETTLE_MASK (0xff << 0) #define REGISTER1_TCLK_SETTLE_SHIFT 0 #define REGISTER2 0x8 @@ -106,7 +106,7 @@ #define CSI2_SYSSTATUS_RESET_DONE (1 << 0) #define CSI2_IRQSTATUS 0x18 -#define CSI2_IRQENABLE 0x1C +#define CSI2_IRQENABLE 0x1c /* Shared bits across CSI2_IRQENABLE and IRQSTATUS */ @@ -159,7 +159,7 @@ #define CSI2_COMPLEXIO_IRQSTATUS 0x54 -#define CSI2_SHORT_PACKET 0x5C +#define CSI2_SHORT_PACKET 0x5c #define CSI2_COMPLEXIO_IRQENABLE 0x60 @@ -194,18 +194,18 @@ #define CSI2_DBG_P 0x68 -#define CSI2_TIMING 0x6C +#define CSI2_TIMING 0x6c #define CSI2_TIMING_FORCE_RX_MODE_IO1 (1 << 15) #define CSI2_TIMING_STOP_STATE_X16_IO1 (1 << 14) #define CSI2_TIMING_STOP_STATE_X4_IO1 (1 << 13) -#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1FFF << 0) +#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK (0x1fff << 0) #define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT 0 #define CSI2_CTX_CTRL1(i) (0x70 + (0x20 * i)) #define CSI2_CTX_CTRL1_GENERIC (1 << 30) -#define CSI2_CTX_CTRL1_TRANSCODE (0xF << 24) -#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xFF << 16) -#define CSI2_CTX_CTRL1_COUNT_MASK (0xFF << 8) +#define CSI2_CTX_CTRL1_TRANSCODE (0xf << 24) +#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK (0xff << 16) +#define CSI2_CTX_CTRL1_COUNT_MASK (0xff << 8) #define CSI2_CTX_CTRL1_COUNT_SHIFT 8 #define CSI2_CTX_CTRL1_EOF_EN (1 << 7) #define CSI2_CTX_CTRL1_EOL_EN (1 << 6) @@ -221,14 +221,14 @@ #define CSI2_CTX_CTRL2_VIRTUAL_ID_MASK (3 << 11) #define CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11 #define CSI2_CTX_CTRL2_DPCM_PRED (1 << 10) -#define CSI2_CTX_CTRL2_FORMAT_MASK (0x3FF << 0) +#define CSI2_CTX_CTRL2_FORMAT_MASK (0x3ff << 0) #define CSI2_CTX_CTRL2_FORMAT_SHIFT 0 #define CSI2_CTX_DAT_OFST(i) (0x78 + (0x20 * i)) -#define CSI2_CTX_DAT_OFST_MASK (0xFFF << 5) +#define CSI2_CTX_DAT_OFST_MASK (0xfff << 5) -#define CSI2_CTX_PING_ADDR(i) (0x7C + (0x20 * i)) -#define CSI2_CTX_PING_ADDR_MASK 0xFFFFFFE0 +#define CSI2_CTX_PING_ADDR(i) (0x7c + (0x20 * i)) +#define CSI2_CTX_PING_ADDR_MASK 0xffffffe0 #define CSI2_CTX_PONG_ADDR(i) (0x80 + (0x20 * i)) #define CSI2_CTX_PONG_ADDR_MASK CSI2_CTX_PING_ADDR_MASK @@ -236,7 +236,7 @@ #define CSI2_CTX_IRQENABLE(i) (0x84 + (0x20 * i)) #define CSI2_CTX_IRQSTATUS(i) (0x88 + (0x20 * i)) -#define CSI2_CTX_CTRL3(i) (0x8C + (0x20 * i)) +#define CSI2_CTX_CTRL3(i) (0x8c + (0x20 * i)) #define CSI2_CTX_CTRL3_ALPHA_SHIFT 5 #define CSI2_CTX_CTRL3_ALPHA_MASK \ (0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT) @@ -253,7 +253,7 @@ /* ISS BTE */ #define BTE_CTRL (0x0030) -#define BTE_CTRL_BW_LIMITER_MASK (0x3FF << 22) +#define BTE_CTRL_BW_LIMITER_MASK (0x3ff << 22) #define BTE_CTRL_BW_LIMITER_SHIFT 22 /* ISS ISP_SYS1 */ @@ -266,7 +266,7 @@ #define ISP5_SYSCONFIG_SOFTRESET (1 << 1) #define ISP5_IRQSTATUS(i) (0x0028 + (0x10 * (i))) -#define ISP5_IRQENABLE_SET(i) (0x002C + (0x10 * (i))) +#define ISP5_IRQENABLE_SET(i) (0x002c + (0x10 * (i))) #define ISP5_IRQENABLE_CLR(i) (0x0030 + (0x10 * (i))) /* Bits shared for ISP5_IRQ* registers */ @@ -296,7 +296,7 @@ #define ISP5_IRQ_IPIPE_INT_REG (1 << 4) #define ISP5_IRQ_ISIF_INT(i) (1 << (i)) -#define ISP5_CTRL (0x006C) +#define ISP5_CTRL (0x006c) #define ISP5_CTRL_MSTANDBY (1 << 24) #define ISP5_CTRL_VD_PULSE_EXT (1 << 23) #define ISP5_CTRL_MSTANDBY_WAIT (1 << 20) @@ -327,25 +327,25 @@ #define ISIF_MODESET_VDPOL (1 << 2) #define ISIF_SPH (0x0018) -#define ISIF_SPH_MASK (0x7FFF) +#define ISIF_SPH_MASK (0x7fff) -#define ISIF_LNH (0x001C) -#define ISIF_LNH_MASK (0x7FFF) +#define ISIF_LNH (0x001c) +#define ISIF_LNH_MASK (0x7fff) #define ISIF_LNV (0x0028) -#define ISIF_LNV_MASK (0x7FFF) +#define ISIF_LNV_MASK (0x7fff) #define ISIF_HSIZE (0x0034) #define ISIF_HSIZE_ADCR (1 << 12) -#define ISIF_HSIZE_HSIZE_MASK (0xFFF) +#define ISIF_HSIZE_HSIZE_MASK (0xfff) -#define ISIF_CADU (0x003C) -#define ISIF_CADU_MASK (0x7FF) +#define ISIF_CADU (0x003c) +#define ISIF_CADU_MASK (0x7ff) #define ISIF_CADL (0x0040) -#define ISIF_CADL_MASK (0xFFFF) +#define ISIF_CADL_MASK (0xffff) -#define ISIF_CCOLP (0x004C) +#define ISIF_CCOLP (0x004c) #define ISIF_CCOLP_CP0_F0_R (0 << 6) #define ISIF_CCOLP_CP0_F0_GR (1 << 6) #define ISIF_CCOLP_CP0_F0_B (3 << 6) @@ -367,7 +367,7 @@ #define ISIF_VDINT_MASK (0x7fff) #define ISIF_CGAMMAWD (0x0080) -#define ISIF_CGAMMAWD_GWDI_MASK (0xF << 1) +#define ISIF_CGAMMAWD_GWDI_MASK (0xf << 1) #define ISIF_CGAMMAWD_GWDI(bpp) ((16 - (bpp)) << 1) #define ISIF_CCDCFG (0x0088) @@ -412,7 +412,7 @@ #define IPIPE_SRC_FMT_RAW2STATS (2 << 0) #define IPIPE_SRC_FMT_YUV2YUV (3 << 0) -#define IPIPE_SRC_COL (0x000C) +#define IPIPE_SRC_COL (0x000c) #define IPIPE_SRC_COL_OO_R (0 << 6) #define IPIPE_SRC_COL_OO_GR (1 << 6) #define IPIPE_SRC_COL_OO_B (3 << 6) @@ -431,16 +431,16 @@ #define IPIPE_SRC_COL_EE_GB (2 << 0) #define IPIPE_SRC_VPS (0x0010) -#define IPIPE_SRC_VPS_MASK (0xFFFF) +#define IPIPE_SRC_VPS_MASK (0xffff) #define IPIPE_SRC_VSZ (0x0014) -#define IPIPE_SRC_VSZ_MASK (0x1FFF) +#define IPIPE_SRC_VSZ_MASK (0x1fff) #define IPIPE_SRC_HPS (0x0018) -#define IPIPE_SRC_HPS_MASK (0xFFFF) +#define IPIPE_SRC_HPS_MASK (0xffff) -#define IPIPE_SRC_HSZ (0x001C) -#define IPIPE_SRC_HSZ_MASK (0x1FFE) +#define IPIPE_SRC_HSZ (0x001c) +#define IPIPE_SRC_HSZ_MASK (0x1ffe) #define IPIPE_SEL_SBU (0x0020) @@ -449,7 +449,7 @@ #define IPIPE_GCK_MMR (0x0028) #define IPIPE_GCK_MMR_REG (1 << 0) -#define IPIPE_GCK_PIX (0x002C) +#define IPIPE_GCK_PIX (0x002c) #define IPIPE_GCK_PIX_G3 (1 << 3) #define IPIPE_GCK_PIX_G2 (1 << 2) #define IPIPE_GCK_PIX_G1 (1 << 1) @@ -457,277 +457,277 @@ #define IPIPE_DPC_LUT_EN (0x0034) #define IPIPE_DPC_LUT_SEL (0x0038) -#define IPIPE_DPC_LUT_ADR (0x003C) +#define IPIPE_DPC_LUT_ADR (0x003c) #define IPIPE_DPC_LUT_SIZ (0x0040) #define IPIPE_DPC_OTF_EN (0x0044) #define IPIPE_DPC_OTF_TYP (0x0048) -#define IPIPE_DPC_OTF_2_D_THR_R (0x004C) +#define IPIPE_DPC_OTF_2_D_THR_R (0x004c) #define IPIPE_DPC_OTF_2_D_THR_GR (0x0050) #define IPIPE_DPC_OTF_2_D_THR_GB (0x0054) #define IPIPE_DPC_OTF_2_D_THR_B (0x0058) -#define IPIPE_DPC_OTF_2_C_THR_R (0x005C) +#define IPIPE_DPC_OTF_2_C_THR_R (0x005c) #define IPIPE_DPC_OTF_2_C_THR_GR (0x0060) #define IPIPE_DPC_OTF_2_C_THR_GB (0x0064) #define IPIPE_DPC_OTF_2_C_THR_B (0x0068) -#define IPIPE_DPC_OTF_3_SHF (0x006C) +#define IPIPE_DPC_OTF_3_SHF (0x006c) #define IPIPE_DPC_OTF_3_D_THR (0x0070) #define IPIPE_DPC_OTF_3_D_SPL (0x0074) #define IPIPE_DPC_OTF_3_D_MIN (0x0078) -#define IPIPE_DPC_OTF_3_D_MAX (0x007C) +#define IPIPE_DPC_OTF_3_D_MAX (0x007c) #define IPIPE_DPC_OTF_3_C_THR (0x0080) #define IPIPE_DPC_OTF_3_C_SLP (0x0084) #define IPIPE_DPC_OTF_3_C_MIN (0x0088) -#define IPIPE_DPC_OTF_3_C_MAX (0x008C) +#define IPIPE_DPC_OTF_3_C_MAX (0x008c) #define IPIPE_LSC_VOFT (0x0090) #define IPIPE_LSC_VA2 (0x0094) #define IPIPE_LSC_VA1 (0x0098) -#define IPIPE_LSC_VS (0x009C) -#define IPIPE_LSC_HOFT (0x00A0) -#define IPIPE_LSC_HA2 (0x00A4) -#define IPIPE_LSC_HA1 (0x00A8) -#define IPIPE_LSC_HS (0x00AC) -#define IPIPE_LSC_GAN_R (0x00B0) -#define IPIPE_LSC_GAN_GR (0x00B4) -#define IPIPE_LSC_GAN_GB (0x00B8) -#define IPIPE_LSC_GAN_B (0x00BC) -#define IPIPE_LSC_OFT_R (0x00C0) -#define IPIPE_LSC_OFT_GR (0x00C4) -#define IPIPE_LSC_OFT_GB (0x00C8) -#define IPIPE_LSC_OFT_B (0x00CC) -#define IPIPE_LSC_SHF (0x00D0) -#define IPIPE_LSC_MAX (0x00D4) - -#define IPIPE_D2F_1ST_EN (0x00D8) -#define IPIPE_D2F_1ST_TYP (0x00DC) -#define IPIPE_D2F_1ST_THR_00 (0x00E0) -#define IPIPE_D2F_1ST_THR_01 (0x00E4) -#define IPIPE_D2F_1ST_THR_02 (0x00E8) -#define IPIPE_D2F_1ST_THR_03 (0x00EC) -#define IPIPE_D2F_1ST_THR_04 (0x00F0) -#define IPIPE_D2F_1ST_THR_05 (0x00F4) -#define IPIPE_D2F_1ST_THR_06 (0x00F8) -#define IPIPE_D2F_1ST_THR_07 (0x00FC) +#define IPIPE_LSC_VS (0x009c) +#define IPIPE_LSC_HOFT (0x00a0) +#define IPIPE_LSC_HA2 (0x00a4) +#define IPIPE_LSC_HA1 (0x00a8) +#define IPIPE_LSC_HS (0x00ac) +#define IPIPE_LSC_GAN_R (0x00b0) +#define IPIPE_LSC_GAN_GR (0x00b4) +#define IPIPE_LSC_GAN_GB (0x00b8) +#define IPIPE_LSC_GAN_B (0x00bc) +#define IPIPE_LSC_OFT_R (0x00c0) +#define IPIPE_LSC_OFT_GR (0x00c4) +#define IPIPE_LSC_OFT_GB (0x00c8) +#define IPIPE_LSC_OFT_B (0x00cc) +#define IPIPE_LSC_SHF (0x00d0) +#define IPIPE_LSC_MAX (0x00d4) + +#define IPIPE_D2F_1ST_EN (0x00d8) +#define IPIPE_D2F_1ST_TYP (0x00dc) +#define IPIPE_D2F_1ST_THR_00 (0x00e0) +#define IPIPE_D2F_1ST_THR_01 (0x00e4) +#define IPIPE_D2F_1ST_THR_02 (0x00e8) +#define IPIPE_D2F_1ST_THR_03 (0x00ec) +#define IPIPE_D2F_1ST_THR_04 (0x00f0) +#define IPIPE_D2F_1ST_THR_05 (0x00f4) +#define IPIPE_D2F_1ST_THR_06 (0x00f8) +#define IPIPE_D2F_1ST_THR_07 (0x00fc) #define IPIPE_D2F_1ST_STR_00 (0x0100) #define IPIPE_D2F_1ST_STR_01 (0x0104) #define IPIPE_D2F_1ST_STR_02 (0x0108) -#define IPIPE_D2F_1ST_STR_03 (0x010C) +#define IPIPE_D2F_1ST_STR_03 (0x010c) #define IPIPE_D2F_1ST_STR_04 (0x0110) #define IPIPE_D2F_1ST_STR_05 (0x0114) #define IPIPE_D2F_1ST_STR_06 (0x0118) -#define IPIPE_D2F_1ST_STR_07 (0x011C) +#define IPIPE_D2F_1ST_STR_07 (0x011c) #define IPIPE_D2F_1ST_SPR_00 (0x0120) #define IPIPE_D2F_1ST_SPR_01 (0x0124) #define IPIPE_D2F_1ST_SPR_02 (0x0128) -#define IPIPE_D2F_1ST_SPR_03 (0x012C) +#define IPIPE_D2F_1ST_SPR_03 (0x012c) #define IPIPE_D2F_1ST_SPR_04 (0x0130) #define IPIPE_D2F_1ST_SPR_05 (0x0134) #define IPIPE_D2F_1ST_SPR_06 (0x0138) -#define IPIPE_D2F_1ST_SPR_07 (0x013C) +#define IPIPE_D2F_1ST_SPR_07 (0x013c) #define IPIPE_D2F_1ST_EDG_MIN (0x0140) #define IPIPE_D2F_1ST_EDG_MAX (0x0144) #define IPIPE_D2F_2ND_EN (0x0148) -#define IPIPE_D2F_2ND_TYP (0x014C) +#define IPIPE_D2F_2ND_TYP (0x014c) #define IPIPE_D2F_2ND_THR00 (0x0150) #define IPIPE_D2F_2ND_THR01 (0x0154) #define IPIPE_D2F_2ND_THR02 (0x0158) -#define IPIPE_D2F_2ND_THR03 (0x015C) +#define IPIPE_D2F_2ND_THR03 (0x015c) #define IPIPE_D2F_2ND_THR04 (0x0160) #define IPIPE_D2F_2ND_THR05 (0x0164) #define IPIPE_D2F_2ND_THR06 (0x0168) -#define IPIPE_D2F_2ND_THR07 (0x016C) +#define IPIPE_D2F_2ND_THR07 (0x016c) #define IPIPE_D2F_2ND_STR_00 (0x0170) #define IPIPE_D2F_2ND_STR_01 (0x0174) #define IPIPE_D2F_2ND_STR_02 (0x0178) -#define IPIPE_D2F_2ND_STR_03 (0x017C) +#define IPIPE_D2F_2ND_STR_03 (0x017c) #define IPIPE_D2F_2ND_STR_04 (0x0180) #define IPIPE_D2F_2ND_STR_05 (0x0184) #define IPIPE_D2F_2ND_STR_06 (0x0188) -#define IPIPE_D2F_2ND_STR_07 (0x018C) +#define IPIPE_D2F_2ND_STR_07 (0x018c) #define IPIPE_D2F_2ND_SPR_00 (0x0190) #define IPIPE_D2F_2ND_SPR_01 (0x0194) #define IPIPE_D2F_2ND_SPR_02 (0x0198) -#define IPIPE_D2F_2ND_SPR_03 (0x019C) -#define IPIPE_D2F_2ND_SPR_04 (0x01A0) -#define IPIPE_D2F_2ND_SPR_05 (0x01A4) -#define IPIPE_D2F_2ND_SPR_06 (0x01A8) -#define IPIPE_D2F_2ND_SPR_07 (0x01AC) -#define IPIPE_D2F_2ND_EDG_MIN (0x01B0) -#define IPIPE_D2F_2ND_EDG_MAX (0x01B4) - -#define IPIPE_GIC_EN (0x01B8) -#define IPIPE_GIC_TYP (0x01BC) -#define IPIPE_GIC_GAN (0x01C0) -#define IPIPE_GIC_NFGAIN (0x01C4) -#define IPIPE_GIC_THR (0x01C8) -#define IPIPE_GIC_SLP (0x01CC) - -#define IPIPE_WB2_OFT_R (0x01D0) -#define IPIPE_WB2_OFT_GR (0x01D4) -#define IPIPE_WB2_OFT_GB (0x01D8) -#define IPIPE_WB2_OFT_B (0x01DC) - -#define IPIPE_WB2_WGN_R (0x01E0) -#define IPIPE_WB2_WGN_GR (0x01E4) -#define IPIPE_WB2_WGN_GB (0x01E8) -#define IPIPE_WB2_WGN_B (0x01EC) - -#define IPIPE_CFA_MODE (0x01F0) -#define IPIPE_CFA_2DIR_HPF_THR (0x01F4) -#define IPIPE_CFA_2DIR_HPF_SLP (0x01F8) -#define IPIPE_CFA_2DIR_MIX_THR (0x01FC) +#define IPIPE_D2F_2ND_SPR_03 (0x019c) +#define IPIPE_D2F_2ND_SPR_04 (0x01a0) +#define IPIPE_D2F_2ND_SPR_05 (0x01a4) +#define IPIPE_D2F_2ND_SPR_06 (0x01a8) +#define IPIPE_D2F_2ND_SPR_07 (0x01ac) +#define IPIPE_D2F_2ND_EDG_MIN (0x01b0) +#define IPIPE_D2F_2ND_EDG_MAX (0x01b4) + +#define IPIPE_GIC_EN (0x01b8) +#define IPIPE_GIC_TYP (0x01bc) +#define IPIPE_GIC_GAN (0x01c0) +#define IPIPE_GIC_NFGAIN (0x01c4) +#define IPIPE_GIC_THR (0x01c8) +#define IPIPE_GIC_SLP (0x01cc) + +#define IPIPE_WB2_OFT_R (0x01d0) +#define IPIPE_WB2_OFT_GR (0x01d4) +#define IPIPE_WB2_OFT_GB (0x01d8) +#define IPIPE_WB2_OFT_B (0x01dc) + +#define IPIPE_WB2_WGN_R (0x01e0) +#define IPIPE_WB2_WGN_GR (0x01e4) +#define IPIPE_WB2_WGN_GB (0x01e8) +#define IPIPE_WB2_WGN_B (0x01ec) + +#define IPIPE_CFA_MODE (0x01f0) +#define IPIPE_CFA_2DIR_HPF_THR (0x01f4) +#define IPIPE_CFA_2DIR_HPF_SLP (0x01f8) +#define IPIPE_CFA_2DIR_MIX_THR (0x01fc) #define IPIPE_CFA_2DIR_MIX_SLP (0x0200) #define IPIPE_CFA_2DIR_DIR_TRH (0x0204) #define IPIPE_CFA_2DIR_DIR_SLP (0x0208) -#define IPIPE_CFA_2DIR_NDWT (0x020C) +#define IPIPE_CFA_2DIR_NDWT (0x020c) #define IPIPE_CFA_MONO_HUE_FRA (0x0210) #define IPIPE_CFA_MONO_EDG_THR (0x0214) #define IPIPE_CFA_MONO_THR_MIN (0x0218) -#define IPIPE_CFA_MONO_THR_SLP (0x021C) +#define IPIPE_CFA_MONO_THR_SLP (0x021c) #define IPIPE_CFA_MONO_SLP_MIN (0x0220) #define IPIPE_CFA_MONO_SLP_SLP (0x0224) #define IPIPE_CFA_MONO_LPWT (0x0228) -#define IPIPE_RGB1_MUL_RR (0x022C) +#define IPIPE_RGB1_MUL_RR (0x022c) #define IPIPE_RGB1_MUL_GR (0x0230) #define IPIPE_RGB1_MUL_BR (0x0234) #define IPIPE_RGB1_MUL_RG (0x0238) -#define IPIPE_RGB1_MUL_GG (0x023C) +#define IPIPE_RGB1_MUL_GG (0x023c) #define IPIPE_RGB1_MUL_BG (0x0240) #define IPIPE_RGB1_MUL_RB (0x0244) #define IPIPE_RGB1_MUL_GB (0x0248) -#define IPIPE_RGB1_MUL_BB (0x024C) +#define IPIPE_RGB1_MUL_BB (0x024c) #define IPIPE_RGB1_OFT_OR (0x0250) #define IPIPE_RGB1_OFT_OG (0x0254) #define IPIPE_RGB1_OFT_OB (0x0258) -#define IPIPE_GMM_CFG (0x025C) +#define IPIPE_GMM_CFG (0x025c) #define IPIPE_RGB2_MUL_RR (0x0260) #define IPIPE_RGB2_MUL_GR (0x0264) #define IPIPE_RGB2_MUL_BR (0x0268) -#define IPIPE_RGB2_MUL_RG (0x026C) +#define IPIPE_RGB2_MUL_RG (0x026c) #define IPIPE_RGB2_MUL_GG (0x0270) #define IPIPE_RGB2_MUL_BG (0x0274) #define IPIPE_RGB2_MUL_RB (0x0278) -#define IPIPE_RGB2_MUL_GB (0x027C) +#define IPIPE_RGB2_MUL_GB (0x027c) #define IPIPE_RGB2_MUL_BB (0x0280) #define IPIPE_RGB2_OFT_OR (0x0284) #define IPIPE_RGB2_OFT_OG (0x0288) -#define IPIPE_RGB2_OFT_OB (0x028C) +#define IPIPE_RGB2_OFT_OB (0x028c) #define IPIPE_YUV_ADJ (0x0294) #define IPIPE_YUV_MUL_RY (0x0298) -#define IPIPE_YUV_MUL_GY (0x029C) -#define IPIPE_YUV_MUL_BY (0x02A0) -#define IPIPE_YUV_MUL_RCB (0x02A4) -#define IPIPE_YUV_MUL_GCB (0x02A8) -#define IPIPE_YUV_MUL_BCB (0x02AC) -#define IPIPE_YUV_MUL_RCR (0x02B0) -#define IPIPE_YUV_MUL_GCR (0x02B4) -#define IPIPE_YUV_MUL_BCR (0x02B8) -#define IPIPE_YUV_OFT_Y (0x02BC) -#define IPIPE_YUV_OFT_CB (0x02C0) -#define IPIPE_YUV_OFT_CR (0x02C4) - -#define IPIPE_YUV_PHS (0x02C8) +#define IPIPE_YUV_MUL_GY (0x029c) +#define IPIPE_YUV_MUL_BY (0x02a0) +#define IPIPE_YUV_MUL_RCB (0x02a4) +#define IPIPE_YUV_MUL_GCB (0x02a8) +#define IPIPE_YUV_MUL_BCB (0x02ac) +#define IPIPE_YUV_MUL_RCR (0x02b0) +#define IPIPE_YUV_MUL_GCR (0x02b4) +#define IPIPE_YUV_MUL_BCR (0x02b8) +#define IPIPE_YUV_OFT_Y (0x02bc) +#define IPIPE_YUV_OFT_CB (0x02c0) +#define IPIPE_YUV_OFT_CR (0x02c4) + +#define IPIPE_YUV_PHS (0x02c8) #define IPIPE_YUV_PHS_LPF (1 << 1) #define IPIPE_YUV_PHS_POS (1 << 0) -#define IPIPE_YEE_EN (0x02D4) -#define IPIPE_YEE_TYP (0x02D8) -#define IPIPE_YEE_SHF (0x02DC) -#define IPIPE_YEE_MUL_00 (0x02E0) -#define IPIPE_YEE_MUL_01 (0x02E4) -#define IPIPE_YEE_MUL_02 (0x02E8) -#define IPIPE_YEE_MUL_10 (0x02EC) -#define IPIPE_YEE_MUL_11 (0x02F0) -#define IPIPE_YEE_MUL_12 (0x02F4) -#define IPIPE_YEE_MUL_20 (0x02F8) -#define IPIPE_YEE_MUL_21 (0x02FC) +#define IPIPE_YEE_EN (0x02d4) +#define IPIPE_YEE_TYP (0x02d8) +#define IPIPE_YEE_SHF (0x02dc) +#define IPIPE_YEE_MUL_00 (0x02e0) +#define IPIPE_YEE_MUL_01 (0x02e4) +#define IPIPE_YEE_MUL_02 (0x02e8) +#define IPIPE_YEE_MUL_10 (0x02ec) +#define IPIPE_YEE_MUL_11 (0x02f0) +#define IPIPE_YEE_MUL_12 (0x02f4) +#define IPIPE_YEE_MUL_20 (0x02f8) +#define IPIPE_YEE_MUL_21 (0x02fc) #define IPIPE_YEE_MUL_22 (0x0300) #define IPIPE_YEE_THR (0x0304) #define IPIPE_YEE_E_GAN (0x0308) -#define IPIPE_YEE_E_THR_1 (0x030C) +#define IPIPE_YEE_E_THR_1 (0x030c) #define IPIPE_YEE_E_THR_2 (0x0310) #define IPIPE_YEE_G_GAN (0x0314) #define IPIPE_YEE_G_OFT (0x0318) -#define IPIPE_CAR_EN (0x031C) +#define IPIPE_CAR_EN (0x031c) #define IPIPE_CAR_TYP (0x0320) #define IPIPE_CAR_SW (0x0324) #define IPIPE_CAR_HPF_TYP (0x0328) -#define IPIPE_CAR_HPF_SHF (0x032C) +#define IPIPE_CAR_HPF_SHF (0x032c) #define IPIPE_CAR_HPF_THR (0x0330) #define IPIPE_CAR_GN1_GAN (0x0334) #define IPIPE_CAR_GN1_SHF (0x0338) -#define IPIPE_CAR_GN1_MIN (0x033C) +#define IPIPE_CAR_GN1_MIN (0x033c) #define IPIPE_CAR_GN2_GAN (0x0340) #define IPIPE_CAR_GN2_SHF (0x0344) #define IPIPE_CAR_GN2_MIN (0x0348) -#define IPIPE_CGS_EN (0x034C) +#define IPIPE_CGS_EN (0x034c) #define IPIPE_CGS_GN1_L_THR (0x0350) #define IPIPE_CGS_GN1_L_GAIN (0x0354) #define IPIPE_CGS_GN1_L_SHF (0x0358) -#define IPIPE_CGS_GN1_L_MIN (0x035C) +#define IPIPE_CGS_GN1_L_MIN (0x035c) #define IPIPE_CGS_GN1_H_THR (0x0360) #define IPIPE_CGS_GN1_H_GAIN (0x0364) #define IPIPE_CGS_GN1_H_SHF (0x0368) -#define IPIPE_CGS_GN1_H_MIN (0x036C) +#define IPIPE_CGS_GN1_H_MIN (0x036c) #define IPIPE_CGS_GN2_L_THR (0x0370) #define IPIPE_CGS_GN2_L_GAIN (0x0374) #define IPIPE_CGS_GN2_L_SHF (0x0378) -#define IPIPE_CGS_GN2_L_MIN (0x037C) +#define IPIPE_CGS_GN2_L_MIN (0x037c) #define IPIPE_BOX_EN (0x0380) #define IPIPE_BOX_MODE (0x0384) #define IPIPE_BOX_TYP (0x0388) -#define IPIPE_BOX_SHF (0x038C) +#define IPIPE_BOX_SHF (0x038c) #define IPIPE_BOX_SDR_SAD_H (0x0390) #define IPIPE_BOX_SDR_SAD_L (0x0394) -#define IPIPE_HST_EN (0x039C) -#define IPIPE_HST_MODE (0x03A0) -#define IPIPE_HST_SEL (0x03A4) -#define IPIPE_HST_PARA (0x03A8) -#define IPIPE_HST_0_VPS (0x03AC) -#define IPIPE_HST_0_VSZ (0x03B0) -#define IPIPE_HST_0_HPS (0x03B4) -#define IPIPE_HST_0_HSZ (0x03B8) -#define IPIPE_HST_1_VPS (0x03BC) -#define IPIPE_HST_1_VSZ (0x03C0) -#define IPIPE_HST_1_HPS (0x03C4) -#define IPIPE_HST_1_HSZ (0x03C8) -#define IPIPE_HST_2_VPS (0x03CC) -#define IPIPE_HST_2_VSZ (0x03D0) -#define IPIPE_HST_2_HPS (0x03D4) -#define IPIPE_HST_2_HSZ (0x03D8) -#define IPIPE_HST_3_VPS (0x03DC) -#define IPIPE_HST_3_VSZ (0x03E0) -#define IPIPE_HST_3_HPS (0x03E4) -#define IPIPE_HST_3_HSZ (0x03E8) -#define IPIPE_HST_TBL (0x03EC) -#define IPIPE_HST_MUL_R (0x03F0) -#define IPIPE_HST_MUL_GR (0x03F4) -#define IPIPE_HST_MUL_GB (0x03F8) -#define IPIPE_HST_MUL_B (0x03FC) +#define IPIPE_HST_EN (0x039c) +#define IPIPE_HST_MODE (0x03a0) +#define IPIPE_HST_SEL (0x03a4) +#define IPIPE_HST_PARA (0x03a8) +#define IPIPE_HST_0_VPS (0x03ac) +#define IPIPE_HST_0_VSZ (0x03b0) +#define IPIPE_HST_0_HPS (0x03b4) +#define IPIPE_HST_0_HSZ (0x03b8) +#define IPIPE_HST_1_VPS (0x03bc) +#define IPIPE_HST_1_VSZ (0x03c0) +#define IPIPE_HST_1_HPS (0x03c4) +#define IPIPE_HST_1_HSZ (0x03c8) +#define IPIPE_HST_2_VPS (0x03cc) +#define IPIPE_HST_2_VSZ (0x03d0) +#define IPIPE_HST_2_HPS (0x03d4) +#define IPIPE_HST_2_HSZ (0x03d8) +#define IPIPE_HST_3_VPS (0x03dc) +#define IPIPE_HST_3_VSZ (0x03e0) +#define IPIPE_HST_3_HPS (0x03e4) +#define IPIPE_HST_3_HSZ (0x03e8) +#define IPIPE_HST_TBL (0x03ec) +#define IPIPE_HST_MUL_R (0x03f0) +#define IPIPE_HST_MUL_GR (0x03f4) +#define IPIPE_HST_MUL_GB (0x03f8) +#define IPIPE_HST_MUL_B (0x03fc) #define IPIPE_BSC_EN (0x0400) #define IPIPE_BSC_MODE (0x0404) #define IPIPE_BSC_TYP (0x0408) -#define IPIPE_BSC_ROW_VCT (0x040C) +#define IPIPE_BSC_ROW_VCT (0x040c) #define IPIPE_BSC_ROW_SHF (0x0410) #define IPIPE_BSC_ROW_VPO (0x0414) #define IPIPE_BSC_ROW_VNU (0x0418) -#define IPIPE_BSC_ROW_VSKIP (0x041C) +#define IPIPE_BSC_ROW_VSKIP (0x041c) #define IPIPE_BSC_ROW_HPO (0x0420) #define IPIPE_BSC_ROW_HNU (0x0424) #define IPIPE_BSC_ROW_HSKIP (0x0428) -#define IPIPE_BSC_COL_VCT (0x042C) +#define IPIPE_BSC_COL_VCT (0x042c) #define IPIPE_BSC_COL_SHF (0x0430) #define IPIPE_BSC_COL_VPO (0x0434) #define IPIPE_BSC_COL_VNU (0x0438) -#define IPIPE_BSC_COL_VSKIP (0x043C) +#define IPIPE_BSC_COL_VSKIP (0x043c) #define IPIPE_BSC_COL_HPO (0x0440) #define IPIPE_BSC_COL_HNU (0x0444) #define IPIPE_BSC_COL_HSKIP (0x0448) @@ -740,14 +740,14 @@ #define RSZ_SYSCONFIG_RSZB_CLK_EN (1 << 9) #define RSZ_SYSCONFIG_RSZA_CLK_EN (1 << 8) -#define RSZ_IN_FIFO_CTRL (0x000C) -#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1FF << 16) +#define RSZ_IN_FIFO_CTRL (0x000c) +#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK (0x1ff << 16) #define RSZ_IN_FIFO_CTRL_THRLD_LOW_SHIFT 16 -#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK (0x1FF << 0) +#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK (0x1ff << 0) #define RSZ_IN_FIFO_CTRL_THRLD_HIGH_SHIFT 0 #define RSZ_FRACDIV (0x0008) -#define RSZ_FRACDIV_MASK (0xFFFF) +#define RSZ_FRACDIV_MASK (0xffff) #define RSZ_SRC_EN (0x0020) #define RSZ_SRC_EN_SRC_EN (1 << 0) @@ -760,80 +760,80 @@ #define RSZ_SRC_FMT0_BYPASS (1 << 1) #define RSZ_SRC_FMT0_SEL (1 << 0) -#define RSZ_SRC_FMT1 (0x002C) +#define RSZ_SRC_FMT1 (0x002c) #define RSZ_SRC_FMT1_IN420 (1 << 1) #define RSZ_SRC_VPS (0x0030) #define RSZ_SRC_VSZ (0x0034) #define RSZ_SRC_HPS (0x0038) -#define RSZ_SRC_HSZ (0x003C) +#define RSZ_SRC_HSZ (0x003c) #define RSZ_DMA_RZA (0x0040) #define RSZ_DMA_RZB (0x0044) #define RSZ_DMA_STA (0x0048) -#define RSZ_GCK_MMR (0x004C) +#define RSZ_GCK_MMR (0x004c) #define RSZ_GCK_MMR_MMR (1 << 0) #define RSZ_GCK_SDR (0x0054) #define RSZ_GCK_SDR_CORE (1 << 0) #define RSZ_IRQ_RZA (0x0058) -#define RSZ_IRQ_RZA_MASK (0x1FFF) +#define RSZ_IRQ_RZA_MASK (0x1fff) -#define RSZ_IRQ_RZB (0x005C) -#define RSZ_IRQ_RZB_MASK (0x1FFF) +#define RSZ_IRQ_RZB (0x005c) +#define RSZ_IRQ_RZB_MASK (0x1fff) #define RSZ_YUV_Y_MIN (0x0060) #define RSZ_YUV_Y_MAX (0x0064) #define RSZ_YUV_C_MIN (0x0068) -#define RSZ_YUV_C_MAX (0x006C) +#define RSZ_YUV_C_MAX (0x006c) #define RSZ_SEQ (0x0074) #define RSZ_SEQ_HRVB (1 << 2) #define RSZ_SEQ_HRVA (1 << 0) #define RZA_EN (0x0078) -#define RZA_MODE (0x007C) +#define RZA_MODE (0x007c) #define RZA_MODE_ONE_SHOT (1 << 0) #define RZA_420 (0x0080) #define RZA_I_VPS (0x0084) #define RZA_I_HPS (0x0088) -#define RZA_O_VSZ (0x008C) +#define RZA_O_VSZ (0x008c) #define RZA_O_HSZ (0x0090) #define RZA_V_PHS_Y (0x0094) #define RZA_V_PHS_C (0x0098) -#define RZA_V_DIF (0x009C) -#define RZA_V_TYP (0x00A0) -#define RZA_V_LPF (0x00A4) -#define RZA_H_PHS (0x00A8) -#define RZA_H_DIF (0x00B0) -#define RZA_H_TYP (0x00B4) -#define RZA_H_LPF (0x00B8) -#define RZA_DWN_EN (0x00BC) -#define RZA_SDR_Y_BAD_H (0x00D0) -#define RZA_SDR_Y_BAD_L (0x00D4) -#define RZA_SDR_Y_SAD_H (0x00D8) -#define RZA_SDR_Y_SAD_L (0x00DC) -#define RZA_SDR_Y_OFT (0x00E0) -#define RZA_SDR_Y_PTR_S (0x00E4) -#define RZA_SDR_Y_PTR_E (0x00E8) -#define RZA_SDR_C_BAD_H (0x00EC) -#define RZA_SDR_C_BAD_L (0x00F0) -#define RZA_SDR_C_SAD_H (0x00F4) -#define RZA_SDR_C_SAD_L (0x00F8) -#define RZA_SDR_C_OFT (0x00FC) +#define RZA_V_DIF (0x009c) +#define RZA_V_TYP (0x00a0) +#define RZA_V_LPF (0x00a4) +#define RZA_H_PHS (0x00a8) +#define RZA_H_DIF (0x00b0) +#define RZA_H_TYP (0x00b4) +#define RZA_H_LPF (0x00b8) +#define RZA_DWN_EN (0x00bc) +#define RZA_SDR_Y_BAD_H (0x00d0) +#define RZA_SDR_Y_BAD_L (0x00d4) +#define RZA_SDR_Y_SAD_H (0x00d8) +#define RZA_SDR_Y_SAD_L (0x00dc) +#define RZA_SDR_Y_OFT (0x00e0) +#define RZA_SDR_Y_PTR_S (0x00e4) +#define RZA_SDR_Y_PTR_E (0x00e8) +#define RZA_SDR_C_BAD_H (0x00ec) +#define RZA_SDR_C_BAD_L (0x00f0) +#define RZA_SDR_C_SAD_H (0x00f4) +#define RZA_SDR_C_SAD_L (0x00f8) +#define RZA_SDR_C_OFT (0x00fc) #define RZA_SDR_C_PTR_S (0x0100) #define RZA_SDR_C_PTR_E (0x0104) #define RZB_EN (0x0108) -#define RZB_MODE (0x010C) +#define RZB_MODE (0x010c) #define RZB_420 (0x0110) #define RZB_I_VPS (0x0114) #define RZB_I_HPS (0x0118) -#define RZB_O_VSZ (0x011C) +#define RZB_O_VSZ (0x011c) #define RZB_O_HSZ (0x0120) -#define RZB_V_DIF (0x012C) +#define RZB_V_DIF (0x012c) #define RZB_V_TYP (0x0130) #define RZB_V_LPF (0x0134) @@ -844,11 +844,11 @@ #define RZB_SDR_Y_BAD_H (0x0160) #define RZB_SDR_Y_BAD_L (0x0164) #define RZB_SDR_Y_SAD_H (0x0168) -#define RZB_SDR_Y_SAD_L (0x016C) +#define RZB_SDR_Y_SAD_L (0x016c) #define RZB_SDR_Y_OFT (0x0170) #define RZB_SDR_Y_PTR_S (0x0174) #define RZB_SDR_Y_PTR_E (0x0178) -#define RZB_SDR_C_BAD_H (0x017C) +#define RZB_SDR_C_BAD_H (0x017c) #define RZB_SDR_C_BAD_L (0x0180) #define RZB_SDR_C_SAD_H (0x0184) #define RZB_SDR_C_SAD_L (0x0188) @@ -862,38 +862,38 @@ #define RSZ_420_CEN (1 << 1) #define RSZ_420_YEN (1 << 0) -#define RSZ_I_VPS_MASK (0x1FFF) +#define RSZ_I_VPS_MASK (0x1fff) -#define RSZ_I_HPS_MASK (0x1FFF) +#define RSZ_I_HPS_MASK (0x1fff) -#define RSZ_O_VSZ_MASK (0x1FFF) +#define RSZ_O_VSZ_MASK (0x1fff) -#define RSZ_O_HSZ_MASK (0x1FFE) +#define RSZ_O_HSZ_MASK (0x1ffe) -#define RSZ_V_PHS_Y_MASK (0x3FFF) +#define RSZ_V_PHS_Y_MASK (0x3fff) -#define RSZ_V_PHS_C_MASK (0x3FFF) +#define RSZ_V_PHS_C_MASK (0x3fff) -#define RSZ_V_DIF_MASK (0x3FFF) +#define RSZ_V_DIF_MASK (0x3fff) #define RSZ_V_TYP_C (1 << 1) #define RSZ_V_TYP_Y (1 << 0) -#define RSZ_V_LPF_C_MASK (0x3F << 6) +#define RSZ_V_LPF_C_MASK (0x3f << 6) #define RSZ_V_LPF_C_SHIFT 6 -#define RSZ_V_LPF_Y_MASK (0x3F << 0) +#define RSZ_V_LPF_Y_MASK (0x3f << 0) #define RSZ_V_LPF_Y_SHIFT 0 -#define RSZ_H_PHS_MASK (0x3FFF) +#define RSZ_H_PHS_MASK (0x3fff) -#define RSZ_H_DIF_MASK (0x3FFF) +#define RSZ_H_DIF_MASK (0x3fff) #define RSZ_H_TYP_C (1 << 1) #define RSZ_H_TYP_Y (1 << 0) -#define RSZ_H_LPF_C_MASK (0x3F << 6) +#define RSZ_H_LPF_C_MASK (0x3f << 6) #define RSZ_H_LPF_C_SHIFT 6 -#define RSZ_H_LPF_Y_MASK (0x3F << 0) +#define RSZ_H_LPF_Y_MASK (0x3f << 0) #define RSZ_H_LPF_Y_SHIFT 0 #define RSZ_DWN_EN_DWN_EN (1 << 0) -- cgit v1.2.3 From a1d4eab06d6777c8bbd46f83e8a495722bb37a84 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 9 Sep 2013 08:19:21 -0300 Subject: [media] v4l: omap4iss: Add description field to iss_format_info structure The field stores the format description in a human-readable form. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 38 +++++++++++++++--------------- drivers/staging/media/omap4iss/iss_video.h | 2 ++ 2 files changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 7763b8dc9f6e..b4ffde87a415 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -33,61 +33,61 @@ static struct iss_format_info formats[] = { { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, - V4L2_PIX_FMT_GREY, 8, }, + V4L2_PIX_FMT_GREY, 8, "Greyscale 8 bpp", }, { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y10, 10, }, + V4L2_PIX_FMT_Y10, 10, "Greyscale 10 bpp", }, { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y12, 12, }, + V4L2_PIX_FMT_Y12, 12, "Greyscale 12 bpp", }, { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR8, 8, }, + V4L2_PIX_FMT_SBGGR8, 8, "BGGR Bayer 8 bpp", }, { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG8, 8, }, + V4L2_PIX_FMT_SGBRG8, 8, "GBRG Bayer 8 bpp", }, { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG8, 8, }, + V4L2_PIX_FMT_SGRBG8, 8, "GRBG Bayer 8 bpp", }, { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB8, 8, }, + V4L2_PIX_FMT_SRGGB8, 8, "RGGB Bayer 8 bpp", }, { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_1X10, 0, - V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, + V4L2_PIX_FMT_SGRBG10DPCM8, 8, "GRBG Bayer 10 bpp DPCM8", }, { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR10, 10, }, + V4L2_PIX_FMT_SBGGR10, 10, "BGGR Bayer 10 bpp", }, { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG10, 10, }, + V4L2_PIX_FMT_SGBRG10, 10, "GBRG Bayer 10 bpp", }, { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG10, 10, }, + V4L2_PIX_FMT_SGRBG10, 10, "GRBG Bayer 10 bpp", }, { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB10, 10, }, + V4L2_PIX_FMT_SRGGB10, 10, "RGGB Bayer 10 bpp", }, { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR12, 12, }, + V4L2_PIX_FMT_SBGGR12, 12, "BGGR Bayer 12 bpp", }, { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG12, 12, }, + V4L2_PIX_FMT_SGBRG12, 12, "GBRG Bayer 12 bpp", }, { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG12, 12, }, + V4L2_PIX_FMT_SGRBG12, 12, "GRBG Bayer 12 bpp", }, { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB12, 12, }, + V4L2_PIX_FMT_SRGGB12, 12, "RGGB Bayer 12 bpp", }, { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16, 0, - V4L2_PIX_FMT_UYVY, 16, }, + V4L2_PIX_FMT_UYVY, 16, "YUV 4:2:2 (UYVY)", }, { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, 0, - V4L2_PIX_FMT_YUYV, 16, }, + V4L2_PIX_FMT_YUYV, 16, "YUV 4:2:2 (YUYV)", }, { V4L2_MBUS_FMT_YUYV8_1_5X8, V4L2_MBUS_FMT_YUYV8_1_5X8, V4L2_MBUS_FMT_YUYV8_1_5X8, 0, - V4L2_PIX_FMT_NV12, 8, }, + V4L2_PIX_FMT_NV12, 8, "YUV 4:2:0 (NV12)", }, }; const struct iss_format_info * diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index 35f14d84330b..2c8d256a87c5 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -40,6 +40,7 @@ struct v4l2_pix_format; * shifted to be 8 bits per pixel. =0 if format is not shiftable. * @pixelformat: V4L2 pixel format FCC identifier * @bpp: Bits per pixel + * @description: Human-readable format description */ struct iss_format_info { enum v4l2_mbus_pixelcode code; @@ -48,6 +49,7 @@ struct iss_format_info { enum v4l2_mbus_pixelcode flavor; u32 pixelformat; unsigned int bpp; + const char *description; }; enum iss_pipeline_stream_state { -- cgit v1.2.3 From cc3c2ac29152b07ce58c8c7b34a8a8e8f321335a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 9 Sep 2013 08:20:16 -0300 Subject: [media] v4l: omap4iss: Make __iss_video_get_format() return a v4l2_mbus_framefmt The function will be used by a caller that needs the media bus format instead of the pixel format currently returned. Move the media bus format to pixel format conversion to the existing caller. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index b4ffde87a415..5dbd774aaa0a 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -232,7 +232,8 @@ iss_video_far_end(struct iss_video *video) } static int -__iss_video_get_format(struct iss_video *video, struct v4l2_format *format) +__iss_video_get_format(struct iss_video *video, + struct v4l2_mbus_framefmt *format) { struct v4l2_subdev_format fmt; struct v4l2_subdev *subdev; @@ -243,6 +244,7 @@ __iss_video_get_format(struct iss_video *video, struct v4l2_format *format) if (subdev == NULL) return -EINVAL; + memset(&fmt, 0, sizeof(fmt)); fmt.pad = pad; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; @@ -253,26 +255,29 @@ __iss_video_get_format(struct iss_video *video, struct v4l2_format *format) if (ret) return ret; - format->type = video->type; - return iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); + *format = fmt.format; + return 0; } static int iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh) { - struct v4l2_format format; + struct v4l2_mbus_framefmt format; + struct v4l2_pix_format pixfmt; int ret; - memcpy(&format, &vfh->format, sizeof(format)); ret = __iss_video_get_format(video, &format); if (ret < 0) return ret; - if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat || - vfh->format.fmt.pix.height != format.fmt.pix.height || - vfh->format.fmt.pix.width != format.fmt.pix.width || - vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline || - vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage) + pixfmt.bytesperline = 0; + ret = iss_video_mbus_to_pix(video, &format, &pixfmt); + + if (vfh->format.fmt.pix.pixelformat != pixfmt.pixelformat || + vfh->format.fmt.pix.height != pixfmt.height || + vfh->format.fmt.pix.width != pixfmt.width || + vfh->format.fmt.pix.bytesperline != pixfmt.bytesperline || + vfh->format.fmt.pix.sizeimage != pixfmt.sizeimage) return -EINVAL; return ret; -- cgit v1.2.3 From 0b1d4249660fbb0c558a096ce72914b7f5fa82a8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 12 Jul 2013 11:25:36 -0300 Subject: [media] v4l: omap4iss: Add enum_fmt_vid_cap ioctl support List the pixel formats compatible with the active format currently configured on the connected pad. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_video.c | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 5dbd774aaa0a..68eab6e6dc36 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -495,6 +495,41 @@ iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) return 0; } +static int +iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) +{ + struct iss_video *video = video_drvdata(file); + struct v4l2_mbus_framefmt format; + unsigned int index = f->index; + unsigned int i; + int ret; + + if (f->type != video->type) + return -EINVAL; + + ret = __iss_video_get_format(video, &format); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + const struct iss_format_info *info = &formats[i]; + + if (format.code != info->code) + continue; + + if (index == 0) { + f->pixelformat = info->pixelformat; + strlcpy(f->description, info->description, + sizeof(f->description)); + return 0; + } + + index--; + } + + return -EINVAL; +} + static int iss_video_get_format(struct file *file, void *fh, struct v4l2_format *format) { @@ -918,6 +953,7 @@ iss_video_s_input(struct file *file, void *fh, unsigned int input) static const struct v4l2_ioctl_ops iss_video_ioctl_ops = { .vidioc_querycap = iss_video_querycap, + .vidioc_enum_fmt_vid_cap = iss_video_enum_format, .vidioc_g_fmt_vid_cap = iss_video_get_format, .vidioc_s_fmt_vid_cap = iss_video_set_format, .vidioc_try_fmt_vid_cap = iss_video_try_format, -- cgit v1.2.3 From 6016498f2b9d72b4f813d7349f0621ccc92c4f5a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Oct 2013 11:52:45 -0300 Subject: [media] v4l: omap4iss: Propagate stop timeouts from submodules to the driver core Return an error from the s_stream handlers when stopping the stream failed instead of just logging the error and ignoring it. While we're at it, move the logging code from submodules to the driver code. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 11 +++++++++-- drivers/staging/media/omap4iss/iss_csi2.c | 8 +++----- drivers/staging/media/omap4iss/iss_ipipe.c | 3 +-- drivers/staging/media/omap4iss/iss_ipipeif.c | 3 +-- drivers/staging/media/omap4iss/iss_resizer.c | 3 +-- 5 files changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index ba8460dc8d28..a0bf2f3cbd72 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -614,6 +614,8 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe) struct media_entity *entity; struct media_pad *pad; struct v4l2_subdev *subdev; + int failure = 0; + int ret; entity = &pipe->output->video.entity; while (1) { @@ -629,10 +631,15 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe) entity = pad->entity; subdev = media_entity_to_v4l2_subdev(entity); - v4l2_subdev_call(subdev, video, s_stream, 0); + ret = v4l2_subdev_call(subdev, video, s_stream, 0); + if (ret < 0) { + dev_dbg(iss->dev, "%s: module stop timeout.\n", + subdev->name); + failure = -ETIMEDOUT; + } } - return 0; + return failure; } /* diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index 077545ffa54f..7e7e955d4be6 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -1056,6 +1056,7 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) struct iss_device *iss = csi2->iss; struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); struct iss_video *video_out = &csi2->video_out; + int ret = 0; if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) { if (enable == ISS_PIPELINE_STREAM_STOPPED) @@ -1069,8 +1070,6 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) switch (enable) { case ISS_PIPELINE_STREAM_CONTINUOUS: { - int ret; - ret = omap4iss_csiphy_config(iss, sd); if (ret < 0) return ret; @@ -1102,8 +1101,7 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) return 0; if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait, &csi2->stopping)) - dev_dbg(iss->dev, "%s: module stop timeout.\n", - sd->name); + ret = -ETIMEDOUT; csi2_ctx_enable(csi2, 0, 0); csi2_if_enable(csi2, 0); csi2_irq_ctx_set(csi2, 0); @@ -1117,7 +1115,7 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) } csi2->state = enable; - return 0; + return ret; } /* subdev video operations */ diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c index d0b9f8c512fc..c013f839146a 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ b/drivers/staging/media/omap4iss/iss_ipipe.c @@ -166,8 +166,7 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) return 0; if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait, &ipipe->stopping)) - dev_dbg(iss->dev, "%s: module stop timeout.\n", - sd->name); + ret = -ETIMEDOUT; ipipe_enable(ipipe, 0); omap4iss_isp_disable_interrupts(iss); diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 2d11f62d0b12..00bc937aa20d 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -363,8 +363,7 @@ static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) return 0; if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait, &ipipeif->stopping)) - dev_dbg(iss->dev, "%s: module stop timeout.\n", - sd->name); + ret = -ETIMEDOUT; if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) ipipeif_write_enable(ipipeif, 0); diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 5bf50808acc3..9dbf0185a86d 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -416,8 +416,7 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable) return 0; if (omap4iss_module_sync_idle(&sd->entity, &resizer->wait, &resizer->stopping)) - dev_dbg(iss->dev, "%s: module stop timeout.\n", - sd->name); + ret = -ETIMEDOUT; resizer_enable(resizer, 0); omap4iss_isp_disable_interrupts(iss); -- cgit v1.2.3 From af15d025ecdf35ad1eb438595727d80155d8d28e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Oct 2013 10:40:02 -0300 Subject: [media] v4l: omap4iss: Enable/disabling the ISP interrupts globally ISP interrupts are enabled/disabled when starting/stopping the IPIPEIF or resizer. This doesn't permit using the two modules in separate pipelines. Fix it by enabling/disabling the ISP interrupts at the same time as the ISS interrupts, in the ISS device get/put operations. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 54 +++++++++++++++------------- drivers/staging/media/omap4iss/iss.h | 3 -- drivers/staging/media/omap4iss/iss_ipipe.c | 3 -- drivers/staging/media/omap4iss/iss_ipipeif.c | 3 -- drivers/staging/media/omap4iss/iss_resizer.c | 3 -- 5 files changed, 30 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index a0bf2f3cbd72..dffa31e274d6 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -67,53 +67,59 @@ void omap4iss_flush(struct iss_device *iss) } /* - * iss_enable_interrupts - Enable ISS interrupts. + * iss_isp_enable_interrupts - Enable ISS ISP interrupts. * @iss: OMAP4 ISS device */ -static void iss_enable_interrupts(struct iss_device *iss) +static void omap4iss_isp_enable_interrupts(struct iss_device *iss) { - static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB | ISS_HL_IRQ_ISP(0); - - /* Enable HL interrupts */ - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq); - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq); + static const u32 isp_irq = ISP5_IRQ_OCP_ERR | + ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | + ISP5_IRQ_RSZ_FIFO_OVF | + ISP5_IRQ_RSZ_INT_DMA | + ISP5_IRQ_ISIF_INT(0); + /* Enable ISP interrupts */ + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0), + isp_irq); } /* - * iss_disable_interrupts - Disable ISS interrupts. + * iss_isp_disable_interrupts - Disable ISS interrupts. * @iss: OMAP4 ISS device */ -static void iss_disable_interrupts(struct iss_device *iss) +static void omap4iss_isp_disable_interrupts(struct iss_device *iss) { - iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), -1); + iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0); } /* - * iss_isp_enable_interrupts - Enable ISS ISP interrupts. + * iss_enable_interrupts - Enable ISS interrupts. * @iss: OMAP4 ISS device */ -void omap4iss_isp_enable_interrupts(struct iss_device *iss) +static void iss_enable_interrupts(struct iss_device *iss) { - static const u32 isp_irq = ISP5_IRQ_OCP_ERR | - ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | - ISP5_IRQ_RSZ_FIFO_OVF | - ISP5_IRQ_RSZ_INT_DMA | - ISP5_IRQ_ISIF_INT(0); + static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB + | ISS_HL_IRQ_ISP(0); - /* Enable ISP interrupts */ - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq); - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0), - isp_irq); + /* Enable HL interrupts */ + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq); + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq); + + if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) + omap4iss_isp_enable_interrupts(iss); } /* - * iss_isp_disable_interrupts - Disable ISS interrupts. + * iss_disable_interrupts - Disable ISS interrupts. * @iss: OMAP4 ISS device */ -void omap4iss_isp_disable_interrupts(struct iss_device *iss) +static void iss_disable_interrupts(struct iss_device *iss) { - iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), -1); + if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) + omap4iss_isp_disable_interrupts(iss); + + iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0); } int omap4iss_get_external_info(struct iss_pipeline *pipe, diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index 660809e27e00..f63caaf90f33 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -141,9 +141,6 @@ void omap4iss_isp_subclk_enable(struct iss_device *iss, void omap4iss_isp_subclk_disable(struct iss_device *iss, enum iss_isp_subclk_resource res); -void omap4iss_isp_enable_interrupts(struct iss_device *iss); -void omap4iss_isp_disable_interrupts(struct iss_device *iss); - int omap4iss_pipeline_pm_use(struct media_entity *entity, int use); int omap4iss_register_entities(struct platform_device *pdev, diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c index c013f839146a..6eaafc5e2eea 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ b/drivers/staging/media/omap4iss/iss_ipipe.c @@ -116,8 +116,6 @@ static void ipipe_configure(struct iss_ipipe_device *ipipe) /* IPIPE_PAD_SOURCE_VP */ format = &ipipe->formats[IPIPE_PAD_SOURCE_VP]; /* Do nothing? */ - - omap4iss_isp_enable_interrupts(iss); } /* ----------------------------------------------------------------------------- @@ -169,7 +167,6 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) ret = -ETIMEDOUT; ipipe_enable(ipipe, 0); - omap4iss_isp_disable_interrupts(iss); omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE); break; } diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 00bc937aa20d..7bc145762499 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -213,8 +213,6 @@ cont_raw: /* IPIPEIF_PAD_SOURCE_VP */ /* Do nothing? */ - - omap4iss_isp_enable_interrupts(iss); } /* ----------------------------------------------------------------------------- @@ -368,7 +366,6 @@ static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY) ipipeif_write_enable(ipipeif, 0); ipipeif_enable(ipipeif, 0); - omap4iss_isp_disable_interrupts(iss); omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK); iss_video_dmaqueue_flags_clr(video_out); break; diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 9dbf0185a86d..4673c0577886 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -256,8 +256,6 @@ static void resizer_configure(struct iss_resizer_device *resizer) } else { iss_reg_write(iss, OMAP4_ISS_MEM_ISP_RESIZER, RZA_420, 0); } - - omap4iss_isp_enable_interrupts(iss); } /* ----------------------------------------------------------------------------- @@ -419,7 +417,6 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable) ret = -ETIMEDOUT; resizer_enable(resizer, 0); - omap4iss_isp_disable_interrupts(iss); iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SYSCONFIG, RSZ_SYSCONFIG_RSZA_CLK_EN); iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_GCK_SDR, -- cgit v1.2.3 From 247f325aaddb8b6117959f70c26ba735360c4160 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Oct 2013 12:16:10 +0100 Subject: clockevent: sun4i: Fill the irq field in the clockevent structure The clock event structure irq field was not filled previously to the interrupt we're using. This was resulting in the timer not being used at all when using a configuration with SMP enabled on a system with several CPUs, and with the cpumask set to the cpu_possible_mask. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano Reviewed-by: Stephen Boyd --- drivers/clocksource/sun4i_timer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 2fb4695a28d8..a7f492e0c7fc 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -188,6 +188,7 @@ static void __init sun4i_timer_init(struct device_node *node) writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); sun4i_clockevent.cpumask = cpumask_of(0); + sun4i_clockevent.irq = irq; clockevents_config_and_register(&sun4i_clockevent, rate, TIMER_SYNC_TICKS, 0xffffffff); -- cgit v1.2.3 From 2c28f32ca4c98b41ad95f62fa27f59f3117931d4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Oct 2013 12:16:11 +0100 Subject: clocksource: sun4i: Change CPU mask to cpu_possible_mask The interrupt for the timer is a shared processor interrupt, so any CPU found in the system can handle it. Switch to our cpumask to cpu_possible_mask instead of cpumask_of(0). Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano Reviewed-by: Stephen Boyd --- drivers/clocksource/sun4i_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index a7f492e0c7fc..6a76b4ec3470 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -187,7 +187,7 @@ static void __init sun4i_timer_init(struct device_node *node) val = readl(timer_base + TIMER_IRQ_EN_REG); writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); - sun4i_clockevent.cpumask = cpumask_of(0); + sun4i_clockevent.cpumask = cpu_possible_mask; sun4i_clockevent.irq = irq; clockevents_config_and_register(&sun4i_clockevent, rate, -- cgit v1.2.3 From 5df9affb50a09e0cb571c4fa3e2d577db85c7475 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 7 Nov 2013 12:01:48 +0100 Subject: clocksource: sun4i: Increase a bit the clock event and sources rating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to keep this driver as the default provider of the clock events and source, yet some other driver might fit in the "desired" category of ratings. Hence, we need to increase a bit the rating so that we can have more flexibility in the ratings we choose. Signed-off-by: Maxime Ripard Tested-by: Emilio López Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 6a76b4ec3470..d7a1a1ad8f05 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -114,7 +114,7 @@ static int sun4i_clkevt_next_event(unsigned long evt, static struct clock_event_device sun4i_clockevent = { .name = "sun4i_tick", - .rating = 300, + .rating = 350, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = sun4i_clkevt_mode, .set_next_event = sun4i_clkevt_next_event, @@ -172,7 +172,7 @@ static void __init sun4i_timer_init(struct device_node *node) setup_sched_clock(sun4i_timer_sched_read, 32, rate); clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, - rate, 300, 32, clocksource_mmio_readl_down); + rate, 350, 32, clocksource_mmio_readl_down); ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); -- cgit v1.2.3 From 67905540e8b8eaf51e621cfd2ef15641d6d5b9a7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 7 Nov 2013 12:01:48 +0100 Subject: clocksource: Add Allwinner SoCs HS timers driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the Allwinner SoCs (at this time, all but the A10) also have a High Speed timers that are not using the 24MHz oscillator as a source but rather the AHB clock running much faster. The IP is slightly different between the A10s/A13 and the one used in the A20/A31, since the latter have 4 timers available, while the former have only 2 of them. [dlezcano] : Fixed conflict with b788beda "Order Kconfig options alphabetically" Signed-off-by: Maxime Ripard Tested-by: Emilio López Signed-off-by: Daniel Lezcano --- .../bindings/timer/allwinner,sun5i-a13-hstimer.txt | 22 +++ arch/arm/mach-sunxi/Kconfig | 1 + drivers/clocksource/Kconfig | 4 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-sun5i.c | 192 +++++++++++++++++++++ 5 files changed, 220 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt create mode 100644 drivers/clocksource/timer-sun5i.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt new file mode 100644 index 000000000000..7c26154b8bbb --- /dev/null +++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt @@ -0,0 +1,22 @@ +Allwinner SoCs High Speed Timer Controller + +Required properties: + +- compatible : should be "allwinner,sun5i-a13-hstimer" or + "allwinner,sun7i-a20-hstimer" +- reg : Specifies base physical address and size of the registers. +- interrupts : The interrupts of these timers (2 for the sun5i IP, 4 for the sun7i + one) +- clocks: phandle to the source clock (usually the AHB clock) + +Example: + +timer@01c60000 { + compatible = "allwinner,sun7i-a20-hstimer"; + reg = <0x01c60000 0x1000>; + interrupts = <0 51 1>, + <0 52 1>, + <0 53 1>, + <0 54 1>; + clocks = <&ahb1_gates 19>; +}; diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index c9e72c89066a..bce0d4277f71 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -12,3 +12,4 @@ config ARCH_SUNXI select PINCTRL_SUNXI select SPARSE_IRQ select SUN4I_TIMER + select SUN5I_HSTIMER diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index bdb953e15d2a..884eeff8e32d 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -37,6 +37,10 @@ config SUN4I_TIMER select CLKSRC_MMIO bool +config SUN5I_HSTIMER + select CLKSRC_MMIO + bool + config VT8500_TIMER bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 33621efb9148..358358d87b6d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o obj-$(CONFIG_ARCH_MXS) += mxs_timer.o obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o +obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c new file mode 100644 index 000000000000..bddc52233d2a --- /dev/null +++ b/drivers/clocksource/timer-sun5i.c @@ -0,0 +1,192 @@ +/* + * Allwinner SoCs hstimer driver. + * + * Copyright (C) 2013 Maxime Ripard + * + * Maxime Ripard + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_IRQ_EN_REG 0x00 +#define TIMER_IRQ_EN(val) BIT(val) +#define TIMER_IRQ_ST_REG 0x04 +#define TIMER_CTL_REG(val) (0x20 * (val) + 0x10) +#define TIMER_CTL_ENABLE BIT(0) +#define TIMER_CTL_RELOAD BIT(1) +#define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) +#define TIMER_CTL_ONESHOT BIT(7) +#define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14) +#define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18) +#define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c) +#define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20) + +#define TIMER_SYNC_TICKS 3 + +static void __iomem *timer_base; +static u32 ticks_per_jiffy; + +/* + * When we disable a timer, we need to wait at least for 2 cycles of + * the timer source clock. We will use for that the clocksource timer + * that is already setup and runs at the same frequency than the other + * timers, and we never will be disabled. + */ +static void sun5i_clkevt_sync(void) +{ + u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1)); + + while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) + cpu_relax(); +} + +static void sun5i_clkevt_time_stop(u8 timer) +{ + u32 val = readl(timer_base + TIMER_CTL_REG(timer)); + writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); + + sun5i_clkevt_sync(); +} + +static void sun5i_clkevt_time_setup(u8 timer, u32 delay) +{ + writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer)); +} + +static void sun5i_clkevt_time_start(u8 timer, bool periodic) +{ + u32 val = readl(timer_base + TIMER_CTL_REG(timer)); + + if (periodic) + val &= ~TIMER_CTL_ONESHOT; + else + val |= TIMER_CTL_ONESHOT; + + writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, + timer_base + TIMER_CTL_REG(timer)); +} + +static void sun5i_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + sun5i_clkevt_time_stop(0); + sun5i_clkevt_time_setup(0, ticks_per_jiffy); + sun5i_clkevt_time_start(0, true); + break; + case CLOCK_EVT_MODE_ONESHOT: + sun5i_clkevt_time_stop(0); + sun5i_clkevt_time_start(0, false); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + sun5i_clkevt_time_stop(0); + break; + } +} + +static int sun5i_clkevt_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + sun5i_clkevt_time_stop(0); + sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS); + sun5i_clkevt_time_start(0, false); + + return 0; +} + +static struct clock_event_device sun5i_clockevent = { + .name = "sun5i_tick", + .rating = 340, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = sun5i_clkevt_mode, + .set_next_event = sun5i_clkevt_next_event, +}; + + +static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + + writel(0x1, timer_base + TIMER_IRQ_ST_REG); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction sun5i_timer_irq = { + .name = "sun5i_timer0", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = sun5i_timer_interrupt, + .dev_id = &sun5i_clockevent, +}; + +static u32 sun5i_timer_sched_read(void) +{ + return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1)); +} + +static void __init sun5i_timer_init(struct device_node *node) +{ + unsigned long rate; + struct clk *clk; + int ret, irq; + u32 val; + + timer_base = of_iomap(node, 0); + if (!timer_base) + panic("Can't map registers"); + + irq = irq_of_parse_and_map(node, 0); + if (irq <= 0) + panic("Can't parse IRQ"); + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) + panic("Can't get timer clock"); + clk_prepare_enable(clk); + rate = clk_get_rate(clk); + + writel(~0, timer_base + TIMER_INTVAL_LO_REG(1)); + writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, + timer_base + TIMER_CTL_REG(1)); + + setup_sched_clock(sun5i_timer_sched_read, 32, rate); + clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name, + rate, 340, 32, clocksource_mmio_readl_down); + + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + + ret = setup_irq(irq, &sun5i_timer_irq); + if (ret) + pr_warn("failed to setup irq %d\n", irq); + + /* Enable timer0 interrupt */ + val = readl(timer_base + TIMER_IRQ_EN_REG); + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); + + sun5i_clockevent.cpumask = cpu_possible_mask; + sun5i_clockevent.irq = irq; + + clockevents_config_and_register(&sun5i_clockevent, rate, + TIMER_SYNC_TICKS, 0xffffffff); +} +CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", + sun5i_timer_init); +CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", + sun5i_timer_init); -- cgit v1.2.3 From af066fce5fa6b615588732cad6909c450a9eb616 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 20 Nov 2013 00:47:32 +0100 Subject: clocksource: arm_global_timer: Switch to sched_clock_register() The 32 bit sched_clock interface now supports 64 bits. Upgrade to the 64 bit function to allow us to remove the 32 bit registration interface. While we're here increase the number of bits that sched_clock can handle to 64 to make full use of the counter. Cc: Stuart Menefy Cc: Srinivas Kandagatla Acked-by: Srinivas Kandagatla Acked-by: Stuart Menefy Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano --- drivers/clocksource/arm_global_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index c639b1a9e996..0fc31d029e52 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -202,7 +202,7 @@ static struct clocksource gt_clocksource = { }; #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK -static u32 notrace gt_sched_clock_read(void) +static u64 notrace gt_sched_clock_read(void) { return gt_counter_read(); } @@ -217,7 +217,7 @@ static void __init gt_clocksource_init(void) writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK - setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate); + sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate); #endif clocksource_register_hz(>_clocksource, gt_clk_rate); } -- cgit v1.2.3 From dfded00902d7437963870accbcf4b39114e85f59 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 20 Nov 2013 00:47:32 +0100 Subject: clocksource: cadence_ttc_timer: Switch to sched_clock_register() The 32 bit sched_clock interface now supports 64 bits. Upgrade to the 64 bit function to allow us to remove the 32 bit registration interface. Cc: Soren Brinkmann Cc: Michal Simek Tested-by: Soren Brinkmann Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano --- drivers/clocksource/cadence_ttc_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index b2bb3a4bc205..b865b4e3d67b 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -158,7 +158,7 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs) TTC_COUNT_VAL_OFFSET); } -static u32 notrace ttc_sched_clock_read(void) +static u64 notrace ttc_sched_clock_read(void) { return __raw_readl(ttc_sched_clock_val_reg); } @@ -306,7 +306,7 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) } ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; - setup_sched_clock(ttc_sched_clock_read, 16, + sched_clock_register(ttc_sched_clock_read, 16, clk_get_rate(ttccs->ttc.clk) / PRESCALE); } -- cgit v1.2.3 From 662e7230ee16951e6858c01e72db87c5dc46150e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 20 Nov 2013 00:47:32 +0100 Subject: clocksource: sun4i: Switch to sched_clock_register() The 32 bit sched_clock interface now supports 64 bits. Upgrade to the 64 bit function to allow us to remove the 32 bit registration interface. While we're here, mark the sched_clock function as notrace to prevent ftrace recursion crashes. Cc: Maxime Ripard Acked-by: Maxime Ripard Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index d7a1a1ad8f05..191187470aa6 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -138,7 +138,7 @@ static struct irqaction sun4i_timer_irq = { .dev_id = &sun4i_clockevent, }; -static u32 sun4i_timer_sched_read(void) +static u64 notrace sun4i_timer_sched_read(void) { return ~readl(timer_base + TIMER_CNTVAL_REG(1)); } @@ -170,7 +170,7 @@ static void __init sun4i_timer_init(struct device_node *node) TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), timer_base + TIMER_CTL_REG(1)); - setup_sched_clock(sun4i_timer_sched_read, 32, rate); + sched_clock_register(sun4i_timer_sched_read, 32, rate); clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, rate, 350, 32, clocksource_mmio_readl_down); -- cgit v1.2.3 From 2e8bac532f8bcd3834853e0a22b130b9fd59270d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 20 Nov 2013 00:47:32 +0100 Subject: clocksource: orion: Switch to sched_clock_register() The 32 bit sched_clock interface now supports 64 bits. Upgrade to the 64 bit function to allow us to remove the 32 bit registration interface. Cc: Sebastian Hesselbarth Tested-by: Sebastian Hesselbarth Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano --- drivers/clocksource/time-orion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 9c7f018a67ca..20066222f3f2 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -53,7 +53,7 @@ EXPORT_SYMBOL(orion_timer_ctrl_clrset); /* * Free-running clocksource handling. */ -static u32 notrace orion_read_sched_clock(void) +static u64 notrace orion_read_sched_clock(void) { return ~readl(timer_base + TIMER0_VAL); } @@ -135,7 +135,7 @@ static void __init orion_timer_init(struct device_node *np) clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", clk_get_rate(clk), 300, 32, clocksource_mmio_readl_down); - setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk)); + sched_clock_register(orion_read_sched_clock, 32, clk_get_rate(clk)); /* setup timer1 as clockevent timer */ if (setup_irq(irq, &orion_clkevt_irq)) -- cgit v1.2.3 From fdca679d87bb4ac0fdc882dbf3deb47a1f58b813 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 20 Nov 2013 09:58:56 +0100 Subject: clocksource: clksrc-of: Warn if no clock sources are found Many platforms rely on clocksource_of_init() being implicitly called for registering clock sources and will get zero warnings if no working clock source is available. Let's print a critical error message if no clock source is found. Acked-by: Lee Jones Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- drivers/clocksource/clksrc-of.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c index 35639cf4e5a2..a30b42c3ac3b 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-of.c @@ -28,6 +28,7 @@ void __init clocksource_of_init(void) struct device_node *np; const struct of_device_id *match; clocksource_of_init_fn init_func; + unsigned clocksources = 0; for_each_matching_node_and_match(np, __clksrc_of_table, &match) { if (!of_device_is_available(np)) @@ -36,5 +37,8 @@ void __init clocksource_of_init(void) init_func = match->data; init_func(np); of_node_put(np); + clocksources++; } + if (!clocksources) + pr_crit("%s: no matching clocksources found\n", __func__); } -- cgit v1.2.3 From 08cb8e460956489fcfbfab5a7d33e62acd190b9a Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 2 Dec 2013 11:39:56 +0100 Subject: clocksource: armada-370-xp: Enable timer divider only when needed The current code sets the timer divider bits always. However, when the 25 MHz timer is enabled, this is not needed and has no effect. As this causes some confusion, rework the code so the divider is set only when needed, i.e. when the 25 MHz timer is not in use. Acked-by: Gregory CLEMENT Signed-off-by: Ezequiel Garcia Signed-off-by: Daniel Lezcano --- drivers/clocksource/time-armada-370-xp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index d8e47e502785..0450f6b69ade 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -76,6 +76,7 @@ static void __iomem *timer_base, *local_base; static unsigned int timer_clk; static bool timer25Mhz = true; +static u32 enable_mask; /* * Number of timer ticks per jiffy. @@ -121,8 +122,7 @@ armada_370_xp_clkevt_next_event(unsigned long delta, /* * Enable the timer. */ - local_timer_ctrl_clrset(TIMER0_RELOAD_EN, - TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT)); + local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); return 0; } @@ -141,9 +141,7 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, /* * Enable timer. */ - local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | - TIMER0_EN | - TIMER0_DIV(TIMER_DIVIDER_SHIFT)); + local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); } else { /* * Disable timer. @@ -240,10 +238,13 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) WARN_ON(!timer_base); local_base = of_iomap(np, 1); - if (timer25Mhz) + if (timer25Mhz) { set = TIMER0_25MHZ; - else + enable_mask = TIMER0_EN; + } else { clr = TIMER0_25MHZ; + enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); + } timer_ctrl_clrset(clr, set); local_timer_ctrl_clrset(clr, set); @@ -267,8 +268,7 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) writel(0xffffffff, timer_base + TIMER0_VAL_OFF); writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); - timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN | - TIMER0_DIV(TIMER_DIVIDER_SHIFT)); + timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "armada_370_xp_clocksource", -- cgit v1.2.3 From 5707f18c28f4df0f993d965aff1c168b69637d63 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 15:50:09 +0900 Subject: clocksource: sh_tmu: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Simon Horman Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_tmu.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 78b8dae49628..54ab47553701 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -509,7 +509,6 @@ static int sh_tmu_probe(struct platform_device *pdev) ret = sh_tmu_setup(p, pdev); if (ret) { kfree(p); - platform_set_drvdata(pdev, NULL); pm_runtime_idle(&pdev->dev); return ret; } -- cgit v1.2.3 From 87d4bb9fced08054afb83af2d85f5cf0ba0e21e4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 3 Dec 2013 15:51:06 +0900 Subject: clocksource: sh_mtu2: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Simon Horman Signed-off-by: Daniel Lezcano --- drivers/clocksource/sh_mtu2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 4aac9ee0d0c0..f02648e27f7e 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -346,7 +346,6 @@ static int sh_mtu2_probe(struct platform_device *pdev) ret = sh_mtu2_setup(p, pdev); if (ret) { kfree(p); - platform_set_drvdata(pdev, NULL); pm_runtime_idle(&pdev->dev); return ret; } -- cgit v1.2.3 From 38c30a8421ce8b06492121deee422ba7ecfaeef2 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Mon, 9 Dec 2013 10:12:10 +0100 Subject: clocksource: misc drivers: Remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag It's a NOOP since 2.6.35 and it will be removed one day. [dlezcano] : slightly changed the changelog Signed-off-by: Michael Opdenacker Signed-off-by: Daniel Lezcano --- drivers/clocksource/cadence_ttc_timer.c | 3 +-- drivers/clocksource/cs5535-clockevt.c | 2 +- drivers/clocksource/dw_apb_timer.c | 3 +-- drivers/clocksource/nomadik-mtu.c | 2 +- drivers/clocksource/samsung_pwm_timer.c | 2 +- drivers/clocksource/sh_cmt.c | 3 +-- drivers/clocksource/sh_mtu2.c | 3 +-- drivers/clocksource/sh_tmu.c | 3 +-- 8 files changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index b865b4e3d67b..8c7382bf260c 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -388,8 +388,7 @@ static void __init ttc_setup_clockevent(struct clk *clk, __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); err = request_irq(irq, ttc_clock_event_interrupt, - IRQF_DISABLED | IRQF_TIMER, - ttcce->ce.name, ttcce); + IRQF_TIMER, ttcce->ce.name, ttcce); if (WARN_ON(err)) { kfree(ttcce); return; diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index ea210482dd20..db2105290898 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -131,7 +131,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) static struct irqaction mfgptirq = { .handler = mfgpt_tick, - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, + .flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, .name = DRV_NAME, }; diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index e54ca1062d8e..f3656a6b0382 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -243,8 +243,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, dw_ced->irqaction.dev_id = &dw_ced->ced; dw_ced->irqaction.irq = irq; dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | - IRQF_NOBALANCING | - IRQF_DISABLED; + IRQF_NOBALANCING; dw_ced->eoi = apbt_eoi; err = setup_irq(irq, &dw_ced->irqaction); diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index ed7b73b508e0..152a3f3875ee 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -187,7 +187,7 @@ static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) static struct irqaction nmdk_timer_irq = { .name = "Nomadik Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .handler = nmdk_timer_interrupt, .dev_id = &nmdk_clkevt, }; diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 85082e8d3052..5645cfc90c41 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -264,7 +264,7 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id) static struct irqaction samsung_clock_event_irq = { .name = "samsung_time_irq", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = samsung_clock_event_isr, .dev_id = &time_event_device, }; diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 0965e9848b3d..c6186339dd52 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -726,8 +726,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ - IRQF_IRQPOLL | IRQF_NOBALANCING; + p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "cmt_fck"); diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index f02648e27f7e..b6a56b1c8947 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -302,8 +302,7 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) p->irqaction.handler = sh_mtu2_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ - IRQF_IRQPOLL | IRQF_NOBALANCING; + p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 54ab47553701..fc752f7b2719 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -462,8 +462,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) p->irqaction.handler = sh_tmu_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ - IRQF_IRQPOLL | IRQF_NOBALANCING; + p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "tmu_fck"); -- cgit v1.2.3 From 39304fad8f31b2114492e9a09fe0bd1ac7eb1834 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Mon, 9 Dec 2013 10:35:45 +0100 Subject: clocksource: tegra: Remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag. It's a NOOP since 2.6.35 and it will be removed one day. [dlezcano] : slightly changed the changelog Signed-off-by: Michael Opdenacker Signed-off-by: Daniel Lezcano --- drivers/clocksource/tegra20_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 642849256d82..d1869f02051c 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -149,7 +149,7 @@ static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) static struct irqaction tegra_timer_irq = { .name = "timer0", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, + .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH, .handler = tegra_timer_interrupt, .dev_id = &tegra_clockevent, }; -- cgit v1.2.3 From 39039eb31c6e5252e25ec6336d92ddef938ccafa Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Mon, 9 Dec 2013 10:38:50 +0100 Subject: clocksource: vt8500: Remove deprecated IRQF_DISABLED This patch removes the use of the IRQF_DISABLED flag. It's a NOOP since 2.6.35 and it will be removed one day. [dlezcano] : slightly changed the changelog Signed-off-by: Michael Opdenacker Signed-off-by: Daniel Lezcano --- drivers/clocksource/vt8500_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index ad3c0e83a779..1098ed3b9b89 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -124,7 +124,7 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) static struct irqaction irq = { .name = "vt8500_timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = vt8500_timer_interrupt, .dev_id = &clockevent, }; -- cgit v1.2.3 From 6d19944bd2609a1d7d48149605aa9f62ca8bf640 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 25 Nov 2013 09:54:45 +0800 Subject: clocksource: bcm_kona_timer: Remove unused bcm_timer_ids bcm_timer_ids is no longer used after converting to CLOCKSOURCE_OF_DECLARE. Signed-off-by: Axel Lin Signed-off-by: Daniel Lezcano --- drivers/clocksource/bcm_kona_timer.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 0d7d8c3ed6b2..5176e761166b 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -98,12 +98,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw) return; } -static const struct of_device_id bcm_timer_ids[] __initconst = { - {.compatible = "brcm,kona-timer"}, - {.compatible = "bcm,kona-timer"}, /* deprecated name */ - {}, -}; - static void __init kona_timers_init(struct device_node *node) { u32 freq; -- cgit v1.2.3 From f3632ba850c70bf24a80295621857166e0c0b14c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Oct 2013 11:52:45 -0300 Subject: [media] v4l: omap4iss: Reset the ISS when the pipeline can't be stopped When a failure to stop a module in the pipeline is detected, the only way to recover is to reset the ISS. However, as other users can be using a different pipeline with other modules, the ISS can't be reset synchronously with the error detection. Keep track of modules that have failed to stop, and reset the ISS accordingly when the last user releases the last reference to the ISS. Refuse to start streaming on a pipeline that contains a crashed module, as the hardware wouldn't work anyway. Modify the omap4iss_pipeline_set_stream() function to record the new ISS pipeline state only when no error occurs, except when stopping the pipeline in which case the pipeline is still marked as stopped. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 24 ++++++++++++++++++++++++ drivers/staging/media/omap4iss/iss.h | 5 +++++ drivers/staging/media/omap4iss/iss_video.c | 8 ++++++++ drivers/staging/media/omap4iss/iss_video.h | 2 ++ 4 files changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index dffa31e274d6..5ad604d0d16b 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -573,12 +573,22 @@ static int iss_pipeline_link_notify(struct media_link *link, u32 flags, static int iss_pipeline_enable(struct iss_pipeline *pipe, enum iss_pipeline_stream_state mode) { + struct iss_device *iss = pipe->output->iss; struct media_entity *entity; struct media_pad *pad; struct v4l2_subdev *subdev; unsigned long flags; int ret; + /* If one of the entities in the pipeline has crashed it will not work + * properly. Refuse to start streaming in that case. This check must be + * performed before the loop below to avoid starting entities if the + * pipeline won't start anyway (those entities would then likely fail to + * stop, making the problem worse). + */ + if (pipe->entities & iss->crashed) + return -EIO; + spin_lock_irqsave(&pipe->lock, flags); pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT); spin_unlock_irqrestore(&pipe->lock, flags); @@ -617,6 +627,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe, */ static int iss_pipeline_disable(struct iss_pipeline *pipe) { + struct iss_device *iss = pipe->output->iss; struct media_entity *entity; struct media_pad *pad; struct v4l2_subdev *subdev; @@ -641,6 +652,11 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe) if (ret < 0) { dev_dbg(iss->dev, "%s: module stop timeout.\n", subdev->name); + /* If the entity failed to stopped, assume it has + * crashed. Mark it as such, the ISS will be reset when + * applications will release it. + */ + iss->crashed |= 1U << subdev->entity.id; failure = -ETIMEDOUT; } } @@ -715,6 +731,7 @@ static int iss_reset(struct iss_device *iss) usleep_range(10, 10); } + iss->crashed = 0; return 0; } @@ -1058,6 +1075,13 @@ void omap4iss_put(struct iss_device *iss) BUG_ON(iss->ref_count == 0); if (--iss->ref_count == 0) { iss_disable_interrupts(iss); + /* Reset the ISS if an entity has failed to stop. This is the + * only way to recover from such conditions, although it would + * be worth investigating whether resetting the ISP only can't + * fix the problem in some cases. + */ + if (iss->crashed) + iss_reset(iss); iss_disable_clocks(iss); } mutex_unlock(&iss->iss_mutex); diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index f63caaf90f33..3c1e92024513 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -77,6 +77,10 @@ struct iss_reg { u32 val; }; +/* + * struct iss_device - ISS device structure. + * @crashed: Bitmask of crashed entities (indexed by entity ID) + */ struct iss_device { struct v4l2_device v4l2_dev; struct media_device media_dev; @@ -93,6 +97,7 @@ struct iss_device { u64 raw_dmamask; struct mutex iss_mutex; /* For handling ref_count field */ + bool crashed; int has_context; int ref_count; diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 68eab6e6dc36..910648766e6c 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -772,6 +772,8 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct iss_video_fh *vfh = to_iss_video_fh(fh); struct iss_video *video = video_drvdata(file); + struct media_entity_graph graph; + struct media_entity *entity; enum iss_pipeline_state state; struct iss_pipeline *pipe; struct iss_video *far_end; @@ -791,6 +793,7 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) pipe->external = NULL; pipe->external_rate = 0; pipe->external_bpp = 0; + pipe->entities = 0; if (video->iss->pdata->set_constraints) video->iss->pdata->set_constraints(video->iss, true); @@ -799,6 +802,11 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_media_entity_pipeline_start; + entity = &video->video.entity; + media_entity_graph_walk_start(&graph, entity); + while ((entity = media_entity_graph_walk_next(&graph))) + pipe->entities |= 1 << entity->id; + /* Verify that the currently configured format matches the output of * the connected subdev. */ diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index 2c8d256a87c5..73e1a3419b01 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -77,6 +77,7 @@ enum iss_pipeline_state { /* * struct iss_pipeline - An OMAP4 ISS hardware pipeline + * @entities: Bitmask of entities in the pipeline (indexed by entity ID) * @error: A hardware error occurred during capture */ struct iss_pipeline { @@ -86,6 +87,7 @@ struct iss_pipeline { enum iss_pipeline_stream_state stream_state; struct iss_video *input; struct iss_video *output; + unsigned int entities; atomic_t frame_number; bool do_propagation; /* of frame number */ bool error; -- cgit v1.2.3 From 216814fb0167673c6417b5db83ade84e58031e2c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Oct 2013 09:06:27 -0300 Subject: [media] v4l: omap4iss: csi2: Replace manual if statement with a subclk field Instead of manually checking whether the CSI2 module is CSI2a or CSI2b in order to select the right subclock to enable/disable, add a subclk field to the iss_csi2 structure, initialize it with the corresponding subclock value and use it at runtime. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_csi2.c | 12 ++++-------- drivers/staging/media/omap4iss/iss_csi2.h | 2 ++ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index 7e7e955d4be6..e4fc4a0b69db 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -1062,10 +1062,7 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) if (enable == ISS_PIPELINE_STREAM_STOPPED) return 0; - if (csi2 == &iss->csi2a) - omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_A); - else if (csi2 == &iss->csi2b) - omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_B); + omap4iss_subclk_enable(iss, csi2->subclk); } switch (enable) { @@ -1106,10 +1103,7 @@ static int csi2_set_stream(struct v4l2_subdev *sd, int enable) csi2_if_enable(csi2, 0); csi2_irq_ctx_set(csi2, 0); omap4iss_csiphy_release(csi2->phy); - if (csi2 == &iss->csi2a) - omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_A); - else if (csi2 == &iss->csi2b) - omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_B); + omap4iss_subclk_disable(iss, csi2->subclk); iss_video_dmaqueue_flags_clr(video_out); break; } @@ -1311,6 +1305,7 @@ int omap4iss_csi2_init(struct iss_device *iss) csi2a->available = 1; csi2a->regs1 = OMAP4_ISS_MEM_CSI2_A_REGS1; csi2a->phy = &iss->csiphy1; + csi2a->subclk = OMAP4_ISS_SUBCLK_CSI2_A; csi2a->state = ISS_PIPELINE_STREAM_STOPPED; init_waitqueue_head(&csi2a->wait); @@ -1322,6 +1317,7 @@ int omap4iss_csi2_init(struct iss_device *iss) csi2b->available = 1; csi2b->regs1 = OMAP4_ISS_MEM_CSI2_B_REGS1; csi2b->phy = &iss->csiphy2; + csi2b->subclk = OMAP4_ISS_SUBCLK_CSI2_B; csi2b->state = ISS_PIPELINE_STREAM_STOPPED; init_waitqueue_head(&csi2b->wait); diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h index 69a6263f6cb0..971aa7b08013 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.h +++ b/drivers/staging/media/omap4iss/iss_csi2.h @@ -131,6 +131,8 @@ struct iss_csi2_device { /* memory resources, as defined in enum iss_mem_resources */ unsigned int regs1; unsigned int regs2; + /* ISP subclock, as defined in enum iss_isp_subclk_resource */ + unsigned int subclk; u32 output; /* output to IPIPEIF, memory or both? */ bool dpcm_decompress; -- cgit v1.2.3 From 112da08512bb0c58c169ec8bda0166f627250a2c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 5 Nov 2013 12:32:05 -0300 Subject: [media] v4l: omap4iss: Cancel streaming when a fatal error occurs When a fatal error that prevents any further video streaming occurs in a pipeline, all queued buffers must be marked as erroneous and new buffers must be prevented from being queued. Implement this behaviour with a new omap4iss_pipeline_cancel_stream() function that can be used by submodules to cancel streaming. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss.c | 17 ++++++++++ drivers/staging/media/omap4iss/iss.h | 1 + drivers/staging/media/omap4iss/iss_resizer.c | 2 +- drivers/staging/media/omap4iss/iss_video.c | 47 +++++++++++++++++++++++++++- drivers/staging/media/omap4iss/iss_video.h | 4 ++- 5 files changed, 68 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 5ad604d0d16b..61fbfcd13582 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -692,6 +692,23 @@ int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, return ret; } +/* + * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline + * @pipe: ISS pipeline + * + * Cancelling a stream mark all buffers on all video nodes in the pipeline as + * erroneous and makes sure no new buffer can be queued. This function is called + * when a fatal error that prevents any further operation on the pipeline + * occurs. + */ +void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe) +{ + if (pipe->input) + omap4iss_video_cancel_stream(pipe->input); + if (pipe->output) + omap4iss_video_cancel_stream(pipe->output); +} + /* * iss_pipeline_is_last - Verify if entity has an enabled link to the output * video node diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index 3c1e92024513..346db9233171 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -131,6 +131,7 @@ int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, enum iss_pipeline_stream_state state); +void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe); void omap4iss_configure_bridge(struct iss_device *iss, enum ipipeif_input_entity input); diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 4673c0577886..c6225d805d1a 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -312,7 +312,7 @@ void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events) dev_dbg(iss->dev, "RSZ Err: FIFO_IN_BLK:%d, FIFO_OVF:%d\n", events & ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR ? 1 : 0, events & ISP5_IRQ_RSZ_FIFO_OVF ? 1 : 0); - pipe->error = true; + omap4iss_pipeline_cancel_stream(pipe); } if (omap4iss_module_sync_is_stopping(&resizer->wait, diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 910648766e6c..482b72fb819f 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -328,6 +328,15 @@ static int iss_video_buf_prepare(struct vb2_buffer *vb) if (vb2_plane_size(vb, 0) < size) return -ENOBUFS; + /* Refuse to prepare the buffer is the video node has registered an + * error. We don't need to take any lock here as the operation is + * inherently racy. The authoritative check will be performed in the + * queue handler, which can't return an error, this check is just a best + * effort to notify userspace as early as possible. + */ + if (unlikely(video->error)) + return -EIO; + addr = vb2_dma_contig_plane_dma_addr(vb, 0); if (!IS_ALIGNED(addr, 32)) { dev_dbg(video->iss->dev, @@ -346,12 +355,20 @@ static void iss_video_buf_queue(struct vb2_buffer *vb) struct iss_video *video = vfh->video; struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb); struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity); - unsigned int empty; unsigned long flags; + bool empty; spin_lock_irqsave(&video->qlock, flags); + + if (unlikely(video->error)) { + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + spin_unlock_irqrestore(&video->qlock, flags); + return; + } + empty = list_empty(&video->dmaqueue); list_add_tail(&buffer->list, &video->dmaqueue); + spin_unlock_irqrestore(&video->qlock, flags); if (empty) { @@ -471,6 +488,33 @@ struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video) return buf; } +/* + * omap4iss_video_cancel_stream - Cancel stream on a video node + * @video: ISS video object + * + * Cancelling a stream mark all buffers on the video node as erroneous and makes + * sure no new buffer can be queued. + */ +void omap4iss_video_cancel_stream(struct iss_video *video) +{ + unsigned long flags; + + spin_lock_irqsave(&video->qlock, flags); + + while (!list_empty(&video->dmaqueue)) { + struct iss_buffer *buf; + + buf = list_first_entry(&video->dmaqueue, struct iss_buffer, + list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } + + video->error = true; + + spin_unlock_irqrestore(&video->qlock, flags); +} + /* ----------------------------------------------------------------------------- * V4L2 ioctls */ @@ -852,6 +896,7 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) video->queue = &vfh->queue; INIT_LIST_HEAD(&video->dmaqueue); spin_lock_init(&video->qlock); + video->error = false; atomic_set(&pipe->frame_number, -1); ret = vb2_streamon(&vfh->queue, type); diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index 73e1a3419b01..878e4a3082e7 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -163,10 +163,11 @@ struct iss_video { /* Pipeline state */ struct iss_pipeline pipe; struct mutex stream_lock; /* pipeline and stream states */ + bool error; /* Video buffers queue */ struct vb2_queue *queue; - spinlock_t qlock; /* Spinlock for dmaqueue */ + spinlock_t qlock; /* protects dmaqueue and error */ struct list_head dmaqueue; enum iss_video_dmaqueue_flags dmaqueue_flags; struct vb2_alloc_ctx *alloc_ctx; @@ -194,6 +195,7 @@ int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev); void omap4iss_video_unregister(struct iss_video *video); struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video); +void omap4iss_video_cancel_stream(struct iss_video *video); struct media_pad *omap4iss_video_remote_pad(struct iss_video *video); const struct iss_format_info * -- cgit v1.2.3 From bea7791529375230261c24a2c249e58b7111e885 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 13 Nov 2013 19:54:32 -0300 Subject: [media] v4l: omap4iss: resizer: Fix comment regarding bypass mode The comment explaining the usage of the bypass bit is wrong, fix it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/omap4iss/iss_resizer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index c6225d805d1a..ae831b8985c9 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -190,7 +190,9 @@ static void resizer_configure(struct iss_resizer_device *resizer) informat = &resizer->formats[RESIZER_PAD_SINK]; outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM]; - /* Make sure we don't bypass the resizer */ + /* Disable pass-through more. Despite its name, the BYPASS bit controls + * pass-through mode, not bypass mode. + */ iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_RESIZER, RSZ_SRC_FMT0, RSZ_SRC_FMT0_BYPASS); -- cgit v1.2.3 From 7227cd18934276eb6d7cf758f79f8c6feacdc421 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Wed, 11 Dec 2013 13:09:40 +0800 Subject: spi/fsl-espi: fix the return value judgment of irq_of_parse_and_map. Signed-off-by: Hou Zhiqiang Acked-by: Grant Likely Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 80d8f40f7e05..8106006cdc39 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -705,7 +705,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) goto err; irq = irq_of_parse_and_map(np, 0); - if (!ret) { + if (!irq) { ret = -EINVAL; goto err; } -- cgit v1.2.3 From 4d88550a9a370e6fe6733d5c9424c10f20c0580f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Dec 2013 17:16:20 -0300 Subject: [media] mt9v032: Remove unused macro The EXT_CLK macro is unused, remove it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 2c50effaa334..205582030735 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -215,8 +215,6 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032) max_t(s32, mt9v032->hblank, 660 - crop->width)); } -#define EXT_CLK 25000000 - static int mt9v032_power_on(struct mt9v032 *mt9v032) { struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); -- cgit v1.2.3 From 2b9e9f779cb29f25102d4e7f14df557ead58e659 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Dec 2013 11:52:44 -0300 Subject: [media] mt9v032: Fix pixel array size The active pixel array size is 753x481 with 4 additional black rows at the top. Fix the driver accordingly. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 205582030735..12360e475739 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -27,8 +27,9 @@ #include #include -#define MT9V032_PIXEL_ARRAY_HEIGHT 492 -#define MT9V032_PIXEL_ARRAY_WIDTH 782 +/* The first four rows are black rows. The active area spans 753x481 pixels. */ +#define MT9V032_PIXEL_ARRAY_HEIGHT 485 +#define MT9V032_PIXEL_ARRAY_WIDTH 753 #define MT9V032_SYSCLK_FREQ_DEF 26600000 -- cgit v1.2.3 From 637f005e455739c8128dadb73dfbe67a4db26f45 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Dec 2013 16:39:18 -0300 Subject: [media] mt9v032: Fix binning configuration The sensor can scale the image down using binning by 1, 2 or 4 in both directions. Update size enumeration and ratio and binning factor computation accordingly. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 68 ++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 12360e475739..38bf66436c6e 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -127,6 +127,8 @@ struct mt9v032 { struct v4l2_mbus_framefmt format; struct v4l2_rect crop; + unsigned int hratio; + unsigned int vratio; struct v4l2_ctrl_handler ctrls; struct { @@ -311,22 +313,20 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable) | MT9V032_CHIP_CONTROL_SEQUENTIAL; struct i2c_client *client = v4l2_get_subdevdata(subdev); struct mt9v032 *mt9v032 = to_mt9v032(subdev); - struct v4l2_mbus_framefmt *format = &mt9v032->format; struct v4l2_rect *crop = &mt9v032->crop; - unsigned int hratio; - unsigned int vratio; + unsigned int hbin; + unsigned int vbin; int ret; if (!enable) return mt9v032_set_chip_control(mt9v032, mode, 0); /* Configure the window size and row/column bin */ - hratio = DIV_ROUND_CLOSEST(crop->width, format->width); - vratio = DIV_ROUND_CLOSEST(crop->height, format->height); - + hbin = fls(mt9v032->hratio) - 1; + vbin = fls(mt9v032->vratio) - 1; ret = mt9v032_write(client, MT9V032_READ_MODE, - (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT | - (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT); + hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT | + vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT); if (ret < 0) return ret; @@ -369,12 +369,12 @@ static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_frame_size_enum *fse) { - if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10) + if (fse->index >= 3 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10) return -EINVAL; - fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index; + fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index); fse->max_width = fse->min_width; - fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index; + fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / (1 << fse->index); fse->max_height = fse->min_height; return 0; @@ -391,18 +391,30 @@ static int mt9v032_get_format(struct v4l2_subdev *subdev, return 0; } -static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032, - unsigned int hratio) +static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032) { struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); int ret; ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, - mt9v032->sysclk / hratio); + mt9v032->sysclk / mt9v032->hratio); if (ret < 0) dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); } +static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output) +{ + /* Compute the power-of-two binning factor closest to the input size to + * output size ratio. Given that the output size is bounded by input/4 + * and input, a generic implementation would be an ineffective luxury. + */ + if (output * 3 > input * 2) + return 1; + if (output * 3 > input) + return 2; + return 4; +} + static int mt9v032_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format) @@ -420,21 +432,25 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev, /* Clamp the width and height to avoid dividing by zero. */ width = clamp_t(unsigned int, ALIGN(format->format.width, 2), - max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN), + max(__crop->width / 4, MT9V032_WINDOW_WIDTH_MIN), __crop->width); height = clamp_t(unsigned int, ALIGN(format->format.height, 2), - max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN), + max(__crop->height / 4, MT9V032_WINDOW_HEIGHT_MIN), __crop->height); - hratio = DIV_ROUND_CLOSEST(__crop->width, width); - vratio = DIV_ROUND_CLOSEST(__crop->height, height); + hratio = mt9v032_calc_ratio(__crop->width, width); + vratio = mt9v032_calc_ratio(__crop->height, height); __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad, format->which); __format->width = __crop->width / hratio; __format->height = __crop->height / vratio; - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) - mt9v032_configure_pixel_rate(mt9v032, hratio); + + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + mt9v032->hratio = hratio; + mt9v032->vratio = vratio; + mt9v032_configure_pixel_rate(mt9v032); + } format->format = *__format; @@ -490,8 +506,11 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev, crop->which); __format->width = rect.width; __format->height = rect.height; - if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) - mt9v032_configure_pixel_rate(mt9v032, 1); + if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + mt9v032->hratio = 1; + mt9v032->vratio = 1; + mt9v032_configure_pixel_rate(mt9v032); + } } *__crop = rect; @@ -665,7 +684,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n", client->addr); - mt9v032_configure_pixel_rate(mt9v032, 1); + mt9v032_configure_pixel_rate(mt9v032); return ret; } @@ -824,6 +843,9 @@ static int mt9v032_probe(struct i2c_client *client, mt9v032->format.field = V4L2_FIELD_NONE; mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; + mt9v032->hratio = 1; + mt9v032->vratio = 1; + mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF; mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF; -- cgit v1.2.3 From 220ddc7f1d19de71cbe1fe29dbf97548efbb5fa9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 4 Dec 2013 15:31:13 -0300 Subject: [media] mt9v032: Add support for monochrome models Identify the model based on the I2C device name and configure formats accordingly. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 38bf66436c6e..a31d6d18d1e5 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -121,6 +121,24 @@ #define MT9V032_AGC_ENABLE (1 << 1) #define MT9V032_THERMAL_INFO 0xc1 +enum mt9v032_model { + MT9V032_MODEL_COLOR, + MT9V032_MODEL_MONO, +}; + +struct mt9v032_model_info { + bool color; +}; + +static const struct mt9v032_model_info mt9v032_models[] = { + [MT9V032_MODEL_COLOR] = { + .color = true, + }, + [MT9V032_MODEL_MONO] = { + .color = false, + }, +}; + struct mt9v032 { struct v4l2_subdev subdev; struct media_pad pad; @@ -142,6 +160,7 @@ struct mt9v032 { struct clk *clk; struct mt9v032_platform_data *pdata; + const struct mt9v032_model_info *model; u32 sysclk; u16 chip_control; @@ -691,6 +710,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) { + struct mt9v032 *mt9v032 = to_mt9v032(subdev); struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; @@ -701,7 +721,12 @@ static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) crop->height = MT9V032_WINDOW_HEIGHT_DEF; format = v4l2_subdev_get_try_format(fh, 0); - format->code = V4L2_MBUS_FMT_SGRBG10_1X10; + + if (mt9v032->model->color) + format->code = V4L2_MBUS_FMT_SGRBG10_1X10; + else + format->code = V4L2_MBUS_FMT_Y10_1X10; + format->width = MT9V032_WINDOW_WIDTH_DEF; format->height = MT9V032_WINDOW_HEIGHT_DEF; format->field = V4L2_FIELD_NONE; @@ -773,6 +798,7 @@ static int mt9v032_probe(struct i2c_client *client, mutex_init(&mt9v032->power_lock); mt9v032->pdata = pdata; + mt9v032->model = (const void *)did->driver_data; v4l2_ctrl_handler_init(&mt9v032->ctrls, 10); @@ -837,7 +863,11 @@ static int mt9v032_probe(struct i2c_client *client, mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF; mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF; - mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10; + if (mt9v032->model->color) + mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10; + else + mt9v032->format.code = V4L2_MBUS_FMT_Y10_1X10; + mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF; mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF; mt9v032->format.field = V4L2_FIELD_NONE; @@ -876,7 +906,8 @@ static int mt9v032_remove(struct i2c_client *client) } static const struct i2c_device_id mt9v032_id[] = { - { "mt9v032", 0 }, + { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_COLOR] }, + { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_MONO] }, { } }; MODULE_DEVICE_TABLE(i2c, mt9v032_id); -- cgit v1.2.3 From 0a466b600d03e8c4a90ac8aa9e9e0aa382976003 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Dec 2013 11:59:52 -0300 Subject: [media] mt9v032: Add support for model-specific parameters To prepare support of the MT9V034, add the necessary infrastructure to support model-specific parameters. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 82 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index a31d6d18d1e5..62db26b0b4f0 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -126,15 +126,51 @@ enum mt9v032_model { MT9V032_MODEL_MONO, }; +struct mt9v032_model_version { + unsigned int version; + const char *name; +}; + +struct mt9v032_model_data { + unsigned int min_row_time; + unsigned int min_hblank; + unsigned int min_vblank; + unsigned int max_vblank; + unsigned int min_shutter; + unsigned int max_shutter; + unsigned int pclk_reg; +}; + struct mt9v032_model_info { + const struct mt9v032_model_data *data; bool color; }; +static const struct mt9v032_model_version mt9v032_versions[] = { + { MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" }, + { MT9V032_CHIP_ID_REV3, "MT9V032 rev3" }, +}; + +static const struct mt9v032_model_data mt9v032_model_data[] = { + { + /* MT9V032 revisions 1/2/3 */ + .min_row_time = 660, + .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN, + .min_vblank = MT9V032_VERTICAL_BLANKING_MIN, + .max_vblank = MT9V032_VERTICAL_BLANKING_MAX, + .min_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MIN, + .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX, + .pclk_reg = MT9V032_PIXEL_CLOCK, + }, +}; + static const struct mt9v032_model_info mt9v032_models[] = { [MT9V032_MODEL_COLOR] = { + .data = &mt9v032_model_data[0], .color = true, }, [MT9V032_MODEL_MONO] = { + .data = &mt9v032_model_data[0], .color = false, }, }; @@ -161,6 +197,7 @@ struct mt9v032 { struct mt9v032_platform_data *pdata; const struct mt9v032_model_info *model; + const struct mt9v032_model_version *version; u32 sysclk; u16 chip_control; @@ -232,9 +269,11 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032) { struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); struct v4l2_rect *crop = &mt9v032->crop; + unsigned int hblank; - return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, - max_t(s32, mt9v032->hblank, 660 - crop->width)); + hblank = max_t(s32, mt9v032->hblank, + mt9v032->model->data->min_row_time - crop->width); + return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank); } static int mt9v032_power_on(struct mt9v032 *mt9v032) @@ -279,7 +318,7 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) /* Configure the pixel clock polarity */ if (mt9v032->pdata && mt9v032->pdata->clk_pol) { - ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK, + ret = mt9v032_write(client, mt9v032->model->data->pclk_reg, MT9V032_PIXEL_CLOCK_INV_PXL_CLK); if (ret < 0) return ret; @@ -678,7 +717,8 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) { struct i2c_client *client = v4l2_get_subdevdata(subdev); struct mt9v032 *mt9v032 = to_mt9v032(subdev); - s32 data; + unsigned int i; + s32 version; int ret; dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", @@ -691,17 +731,29 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) } /* Read and check the sensor version */ - data = mt9v032_read(client, MT9V032_CHIP_VERSION); - if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) { - dev_err(&client->dev, "MT9V032 not detected, wrong version " - "0x%04x\n", data); + version = mt9v032_read(client, MT9V032_CHIP_VERSION); + if (version < 0) { + dev_err(&client->dev, "Failed reading chip version\n"); + return version; + } + + for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) { + if (mt9v032_versions[i].version == version) { + mt9v032->version = &mt9v032_versions[i]; + break; + } + } + + if (mt9v032->version == NULL) { + dev_err(&client->dev, "Unsupported chip version 0x%04x\n", + version); return -ENODEV; } mt9v032_power_off(mt9v032); - dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n", - client->addr); + dev_info(&client->dev, "%s detected at address 0x%02x\n", + mt9v032->version->name, client->addr); mt9v032_configure_pixel_rate(mt9v032); @@ -811,16 +863,16 @@ static int mt9v032_probe(struct i2c_client *client, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO); v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, - V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, - MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, + V4L2_CID_EXPOSURE, mt9v032->model->data->min_shutter, + mt9v032->model->data->max_shutter, 1, MT9V032_TOTAL_SHUTTER_WIDTH_DEF); v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, - V4L2_CID_HBLANK, MT9V032_HORIZONTAL_BLANKING_MIN, + V4L2_CID_HBLANK, mt9v032->model->data->min_hblank, MT9V032_HORIZONTAL_BLANKING_MAX, 1, MT9V032_HORIZONTAL_BLANKING_DEF); v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, - V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN, - MT9V032_VERTICAL_BLANKING_MAX, 1, + V4L2_CID_VBLANK, mt9v032->model->data->min_vblank, + mt9v032->model->data->max_vblank, 1, MT9V032_VERTICAL_BLANKING_DEF); mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls, &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN, -- cgit v1.2.3 From daecfebcb8847ae759efdd1637857b2108000844 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Dec 2013 12:01:03 -0300 Subject: [media] mt9v032: Add support for the MT9V034 The MT9V034 sensor is very similar to the MT9V032, with a couple of different registers and parameters. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 54 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 62db26b0b4f0..0d2b4a8cf911 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -36,6 +36,7 @@ #define MT9V032_CHIP_VERSION 0x00 #define MT9V032_CHIP_ID_REV1 0x1311 #define MT9V032_CHIP_ID_REV3 0x1313 +#define MT9V034_CHIP_ID_REV1 0X1324 #define MT9V032_COLUMN_START 0x01 #define MT9V032_COLUMN_START_MIN 1 #define MT9V032_COLUMN_START_DEF 1 @@ -54,12 +55,15 @@ #define MT9V032_WINDOW_WIDTH_MAX 752 #define MT9V032_HORIZONTAL_BLANKING 0x05 #define MT9V032_HORIZONTAL_BLANKING_MIN 43 +#define MT9V034_HORIZONTAL_BLANKING_MIN 61 #define MT9V032_HORIZONTAL_BLANKING_DEF 94 #define MT9V032_HORIZONTAL_BLANKING_MAX 1023 #define MT9V032_VERTICAL_BLANKING 0x06 #define MT9V032_VERTICAL_BLANKING_MIN 4 +#define MT9V034_VERTICAL_BLANKING_MIN 2 #define MT9V032_VERTICAL_BLANKING_DEF 45 #define MT9V032_VERTICAL_BLANKING_MAX 3000 +#define MT9V034_VERTICAL_BLANKING_MAX 32288 #define MT9V032_CHIP_CONTROL 0x07 #define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3) #define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7) @@ -69,8 +73,10 @@ #define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a #define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b #define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1 +#define MT9V034_TOTAL_SHUTTER_WIDTH_MIN 0 #define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480 #define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767 +#define MT9V034_TOTAL_SHUTTER_WIDTH_MAX 32765 #define MT9V032_RESET 0x0c #define MT9V032_READ_MODE 0x0d #define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0) @@ -82,6 +88,8 @@ #define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6) #define MT9V032_READ_MODE_DARK_ROWS (1 << 7) #define MT9V032_PIXEL_OPERATION_MODE 0x0f +#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0) +#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1) #define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2) #define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6) #define MT9V032_ANALOG_GAIN 0x35 @@ -97,9 +105,12 @@ #define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8) #define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8 #define MT9V032_ROW_NOISE_CORR_CONTROL 0x70 +#define MT9V034_ROW_NOISE_CORR_ENABLE (1 << 0) +#define MT9V034_ROW_NOISE_CORR_USE_BLK_AVG (1 << 1) #define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5) #define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7) #define MT9V032_PIXEL_CLOCK 0x74 +#define MT9V034_PIXEL_CLOCK 0x72 #define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0) #define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1) #define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2) @@ -122,8 +133,10 @@ #define MT9V032_THERMAL_INFO 0xc1 enum mt9v032_model { - MT9V032_MODEL_COLOR, - MT9V032_MODEL_MONO, + MT9V032_MODEL_V032_COLOR, + MT9V032_MODEL_V032_MONO, + MT9V032_MODEL_V034_COLOR, + MT9V032_MODEL_V034_MONO, }; struct mt9v032_model_version { @@ -149,6 +162,7 @@ struct mt9v032_model_info { static const struct mt9v032_model_version mt9v032_versions[] = { { MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" }, { MT9V032_CHIP_ID_REV3, "MT9V032 rev3" }, + { MT9V034_CHIP_ID_REV1, "MT9V034 rev1" }, }; static const struct mt9v032_model_data mt9v032_model_data[] = { @@ -161,18 +175,35 @@ static const struct mt9v032_model_data mt9v032_model_data[] = { .min_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MIN, .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX, .pclk_reg = MT9V032_PIXEL_CLOCK, + }, { + /* MT9V034 */ + .min_row_time = 690, + .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN, + .min_vblank = MT9V034_VERTICAL_BLANKING_MIN, + .max_vblank = MT9V034_VERTICAL_BLANKING_MAX, + .min_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MIN, + .max_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MAX, + .pclk_reg = MT9V034_PIXEL_CLOCK, }, }; static const struct mt9v032_model_info mt9v032_models[] = { - [MT9V032_MODEL_COLOR] = { + [MT9V032_MODEL_V032_COLOR] = { .data = &mt9v032_model_data[0], .color = true, }, - [MT9V032_MODEL_MONO] = { + [MT9V032_MODEL_V032_MONO] = { .data = &mt9v032_model_data[0], .color = false, }, + [MT9V032_MODEL_V034_COLOR] = { + .data = &mt9v032_model_data[1], + .color = true, + }, + [MT9V032_MODEL_V034_MONO] = { + .data = &mt9v032_model_data[1], + .color = false, + }, }; struct mt9v032 { @@ -269,10 +300,15 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032) { struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); struct v4l2_rect *crop = &mt9v032->crop; + unsigned int min_hblank = mt9v032->model->data->min_hblank; unsigned int hblank; - hblank = max_t(s32, mt9v032->hblank, - mt9v032->model->data->min_row_time - crop->width); + if (mt9v032->version->version == MT9V034_CHIP_ID_REV1) + min_hblank += (mt9v032->hratio - 1) * 10; + min_hblank = max((int)mt9v032->model->data->min_row_time - crop->width, + (int)min_hblank); + hblank = max_t(unsigned int, mt9v032->hblank, min_hblank); + return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank); } @@ -958,8 +994,10 @@ static int mt9v032_remove(struct i2c_client *client) } static const struct i2c_device_id mt9v032_id[] = { - { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_COLOR] }, - { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_MONO] }, + { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] }, + { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] }, + { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] }, + { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] }, { } }; MODULE_DEVICE_TABLE(i2c, mt9v032_id); -- cgit v1.2.3 From 3299ba5c0b213be5d911752d40251c1abc1004f7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 15 Oct 2013 18:58:43 -0300 Subject: [media] v4l: vsp1: Supply frames to the DU continuously When operating in DU output mode (deep pipeline to the DU through the LIF), the VSP1 needs to constantly supply frames to the display. To ensure reuse the last queued buffer instead of returning it to the user. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 714c53ef6c11..eb1225dd06ad 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -488,11 +488,17 @@ static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) * This function completes the current buffer by filling its sequence number, * time stamp and payload size, and hands it back to the videobuf core. * + * When operating in DU output mode (deep pipeline to the DU through the LIF), + * the VSP1 needs to constantly supply frames to the display. In that case, if + * no other buffer is queued, reuse the one that has just been processed instead + * of handing it back to the videobuf core. + * * Return the next queued buffer or NULL if the queue is empty. */ static struct vsp1_video_buffer * vsp1_video_complete_buffer(struct vsp1_video *video) { + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); struct vsp1_video_buffer *next = NULL; struct vsp1_video_buffer *done; unsigned long flags; @@ -507,6 +513,13 @@ vsp1_video_complete_buffer(struct vsp1_video *video) done = list_first_entry(&video->irqqueue, struct vsp1_video_buffer, queue); + + /* In DU output mode reuse the buffer if the list is singular. */ + if (pipe->lif && list_is_singular(&video->irqqueue)) { + spin_unlock_irqrestore(&video->irqlock, flags); + return done; + } + list_del(&done->queue); if (!list_empty(&video->irqqueue)) -- cgit v1.2.3 From e5ad37b64de975463c51f9ed4e4c55dc6e442ba5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 24 Aug 2013 20:49:58 -0300 Subject: [media] v4l: vsp1: Add cropping support Implement the get and set selection operations on the RPF and WPF entities. Only the crop targets are currently available. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_rpf.c | 34 ++++++++---- drivers/media/platform/vsp1/vsp1_rwpf.c | 96 +++++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_rwpf.h | 10 ++++ drivers/media/platform/vsp1/vsp1_wpf.c | 17 +++--- 4 files changed, 141 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 254871d3423e..bce2be5466b9 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -47,25 +47,36 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) struct vsp1_rwpf *rpf = to_rwpf(subdev); const struct vsp1_format_info *fmtinfo = rpf->video.fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->video.format; + const struct v4l2_rect *crop = &rpf->crop; u32 pstride; u32 infmt; if (!enable) return 0; - /* Source size and stride. Cropping isn't supported yet. */ + /* Source size, stride and crop offsets. + * + * The crop offsets correspond to the location of the crop rectangle top + * left corner in the plane buffer. Only two offsets are needed, as + * planes 2 and 3 always have identical strides. + */ vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, - (format->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | - (format->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); + (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | + (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE, - (format->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | - (format->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); + (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | + (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); + rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline + + crop->left * fmtinfo->bpp[0] / 8; pstride = format->plane_fmt[0].bytesperline << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; - if (format->num_planes > 1) + if (format->num_planes > 1) { + rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline + + crop->left * fmtinfo->bpp[1] / 8; pstride |= format->plane_fmt[1].bytesperline << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; + } vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); @@ -113,6 +124,8 @@ static struct v4l2_subdev_pad_ops rpf_pad_ops = { .enum_frame_size = vsp1_rwpf_enum_frame_size, .get_fmt = vsp1_rwpf_get_format, .set_fmt = vsp1_rwpf_set_format, + .get_selection = vsp1_rwpf_get_selection, + .set_selection = vsp1_rwpf_set_selection, }; static struct v4l2_subdev_ops rpf_ops = { @@ -129,11 +142,14 @@ static void rpf_vdev_queue(struct vsp1_video *video, { struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video); - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, buf->addr[0]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, + buf->addr[0] + rpf->offsets[0]); if (buf->buf.num_planes > 1) - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, buf->addr[1]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, + buf->addr[1] + rpf->offsets[1]); if (buf->buf.num_planes > 2) - vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, buf->addr[2]); + vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, + buf->addr[2] + rpf->offsets[1]); } static const struct vsp1_video_operations rpf_vdev_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 9752d5516ceb..782f770daee5 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -71,6 +71,19 @@ int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, return 0; } +static struct v4l2_rect * +vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_fh *fh, u32 which) +{ + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + return v4l2_subdev_get_try_crop(fh, RWPF_PAD_SINK); + case V4L2_SUBDEV_FORMAT_ACTIVE: + return &rwpf->crop; + default: + return NULL; + } +} + int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) { @@ -87,6 +100,7 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_mbus_framefmt *format; + struct v4l2_rect *crop; /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 && @@ -115,6 +129,13 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, fmt->format = *format; + /* Update the sink crop rectangle. */ + crop = vsp1_rwpf_get_crop(rwpf, fh, fmt->which); + crop->left = 0; + crop->top = 0; + crop->width = fmt->format.width; + crop->height = fmt->format.height; + /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE, fmt->which); @@ -122,3 +143,78 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, return 0; } + +int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) +{ + struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_mbus_framefmt *format; + + /* Cropping is implemented on the sink pad. */ + if (sel->pad != RWPF_PAD_SINK) + return -EINVAL; + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *vsp1_rwpf_get_crop(rwpf, fh, sel->which); + break; + + case V4L2_SEL_TGT_CROP_BOUNDS: + format = vsp1_entity_get_pad_format(&rwpf->entity, fh, + RWPF_PAD_SINK, sel->which); + sel->r.left = 0; + sel->r.top = 0; + sel->r.width = format->width; + sel->r.height = format->height; + break; + + default: + return -EINVAL; + } + + return 0; +} + +int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel) +{ + struct vsp1_rwpf *rwpf = to_rwpf(subdev); + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *crop; + + /* Cropping is implemented on the sink pad. */ + if (sel->pad != RWPF_PAD_SINK) + return -EINVAL; + + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + /* Make sure the crop rectangle is entirely contained in the image. The + * WPF top and left offsets are limited to 255. + */ + format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SINK, + sel->which); + sel->r.left = min_t(unsigned int, sel->r.left, format->width - 2); + sel->r.top = min_t(unsigned int, sel->r.top, format->height - 2); + if (rwpf->entity.type == VSP1_ENTITY_WPF) { + sel->r.left = min_t(unsigned int, sel->r.left, 255); + sel->r.top = min_t(unsigned int, sel->r.top, 255); + } + sel->r.width = min_t(unsigned int, sel->r.width, + format->width - sel->r.left); + sel->r.height = min_t(unsigned int, sel->r.height, + format->height - sel->r.top); + + crop = vsp1_rwpf_get_crop(rwpf, fh, sel->which); + *crop = sel->r; + + /* Propagate the format to the source pad. */ + format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE, + sel->which); + format->width = crop->width; + format->height = crop->height; + + return 0; +} diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index c182d85f36b3..6cbdb547470b 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -29,6 +29,10 @@ struct vsp1_rwpf { unsigned int max_width; unsigned int max_height; + + struct v4l2_rect crop; + + unsigned int offsets[2]; }; static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) @@ -49,5 +53,11 @@ int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt); int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt); +int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel); +int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel); #endif /* __VSP1_RWPF_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index db4b85ee05fc..7baed81ff005 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -48,8 +48,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) struct vsp1_pipeline *pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); struct vsp1_device *vsp1 = wpf->entity.vsp1; - const struct v4l2_mbus_framefmt *format = - &wpf->entity.formats[RWPF_PAD_SOURCE]; + const struct v4l2_rect *crop = &wpf->crop; unsigned int i; u32 srcrpf = 0; u32 outfmt = 0; @@ -68,7 +67,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); - /* Destination stride. Cropping isn't supported yet. */ + /* Destination stride. */ if (!pipe->lif) { struct v4l2_pix_format_mplane *format = &wpf->video.format; @@ -79,10 +78,12 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) format->plane_fmt[1].bytesperline); } - vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, - format->width << VI6_WPF_SZCLIP_SIZE_SHIFT); - vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, - format->height << VI6_WPF_SZCLIP_SIZE_SHIFT); + vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | + (crop->left << VI6_WPF_SZCLIP_OFST_SHIFT) | + (crop->width << VI6_WPF_SZCLIP_SIZE_SHIFT)); + vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | + (crop->top << VI6_WPF_SZCLIP_OFST_SHIFT) | + (crop->height << VI6_WPF_SZCLIP_SIZE_SHIFT)); /* Format */ if (!pipe->lif) { @@ -130,6 +131,8 @@ static struct v4l2_subdev_pad_ops wpf_pad_ops = { .enum_frame_size = vsp1_rwpf_enum_frame_size, .get_fmt = vsp1_rwpf_get_format, .set_fmt = vsp1_rwpf_set_format, + .get_selection = vsp1_rwpf_get_selection, + .set_selection = vsp1_rwpf_set_selection, }; static struct v4l2_subdev_ops wpf_ops = { -- cgit v1.2.3 From 5cdf5741d6529f3c04dcd117b4c9b9039d101602 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Jul 2013 17:30:14 -0300 Subject: [media] v4l: vsp1: Add HST and HSI support The Hue Saturation value Transform and Hue Saturation value Inverse transform entities convert from RGB to HSV and back. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 3 + drivers/media/platform/vsp1/vsp1_drv.c | 17 +++ drivers/media/platform/vsp1/vsp1_entity.c | 2 + drivers/media/platform/vsp1/vsp1_entity.h | 2 + drivers/media/platform/vsp1/vsp1_hsit.c | 222 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_hsit.h | 38 +++++ drivers/media/platform/vsp1/vsp1_regs.h | 2 + 8 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/vsp1/vsp1_hsit.c create mode 100644 drivers/media/platform/vsp1/vsp1_hsit.h (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 4da226169e15..587b8009b357 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,5 +1,5 @@ vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o -vsp1-y += vsp1_lif.o vsp1_uds.o +vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_uds.o obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index d6c6ecd039ff..275286e0bf42 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -28,6 +28,7 @@ struct clk; struct device; struct vsp1_platform_data; +struct vsp1_hsit; struct vsp1_lif; struct vsp1_rwpf; struct vsp1_uds; @@ -47,6 +48,8 @@ struct vsp1_device { struct mutex lock; int ref_count; + struct vsp1_hsit *hsi; + struct vsp1_hsit *hst; struct vsp1_lif *lif; struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; struct vsp1_uds *uds[VPS1_MAX_UDS]; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index d16bf0f41e24..bcede46c4a95 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -20,6 +20,7 @@ #include #include "vsp1.h" +#include "vsp1_hsit.h" #include "vsp1_lif.h" #include "vsp1_rwpf.h" #include "vsp1_uds.h" @@ -152,6 +153,22 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) } /* Instantiate all the entities. */ + vsp1->hsi = vsp1_hsit_create(vsp1, true); + if (IS_ERR(vsp1->hsi)) { + ret = PTR_ERR(vsp1->hsi); + goto done; + } + + list_add_tail(&vsp1->hsi->entity.list_dev, &vsp1->entities); + + vsp1->hst = vsp1_hsit_create(vsp1, false); + if (IS_ERR(vsp1->hst)) { + ret = PTR_ERR(vsp1->hst); + goto done; + } + + list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities); + if (vsp1->pdata->features & VSP1_HAS_LIF) { vsp1->lif = vsp1_lif_create(vsp1); if (IS_ERR(vsp1->lif)) { diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 9028f9d524f4..3798ef4a272b 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -122,6 +122,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, unsigned int id; unsigned int reg; } routes[] = { + { VI6_DPR_NODE_HSI, VI6_DPR_HSI_ROUTE }, + { VI6_DPR_NODE_HST, VI6_DPR_HST_ROUTE }, { VI6_DPR_NODE_LIF, 0 }, { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) }, { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) }, diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index c4feab2cbb81..0d617467066b 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -20,6 +20,8 @@ struct vsp1_device; enum vsp1_entity_type { + VSP1_ENTITY_HSI, + VSP1_ENTITY_HST, VSP1_ENTITY_LIF, VSP1_ENTITY_RPF, VSP1_ENTITY_UDS, diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c new file mode 100644 index 000000000000..285485350d82 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -0,0 +1,222 @@ +/* + * vsp1_hsit.c -- R-Car VSP1 Hue Saturation value (Inverse) Transform + * + * Copyright (C) 2013 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 "vsp1.h" +#include "vsp1_hsit.h" + +#define HSIT_MIN_SIZE 4U +#define HSIT_MAX_SIZE 8190U + +/* ----------------------------------------------------------------------------- + * Device Access + */ + +static inline u32 vsp1_hsit_read(struct vsp1_hsit *hsit, u32 reg) +{ + return vsp1_read(hsit->entity.vsp1, reg); +} + +static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) +{ + vsp1_write(hsit->entity.vsp1, reg, data); +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Core Operations + */ + +static int hsit_s_stream(struct v4l2_subdev *subdev, int enable) +{ + struct vsp1_hsit *hsit = to_hsit(subdev); + + if (!enable) + return 0; + + if (hsit->inverse) + vsp1_hsit_write(hsit, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); + else + vsp1_hsit_write(hsit, VI6_HST_CTRL, VI6_HST_CTRL_EN); + + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Pad Operations + */ + +static int hsit_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct vsp1_hsit *hsit = to_hsit(subdev); + + if (code->index > 0) + return -EINVAL; + + if ((code->pad == HSIT_PAD_SINK && !hsit->inverse) | + (code->pad == HSIT_PAD_SOURCE && hsit->inverse)) + code->code = V4L2_MBUS_FMT_ARGB8888_1X32; + else + code->code = V4L2_MBUS_FMT_AHSV8888_1X32; + + return 0; +} + +static int hsit_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct v4l2_mbus_framefmt *format; + + format = v4l2_subdev_get_try_format(fh, fse->pad); + + if (fse->index || fse->code != format->code) + return -EINVAL; + + if (fse->pad == HSIT_PAD_SINK) { + fse->min_width = HSIT_MIN_SIZE; + fse->max_width = HSIT_MAX_SIZE; + fse->min_height = HSIT_MIN_SIZE; + fse->max_height = HSIT_MAX_SIZE; + } else { + /* The size on the source pad are fixed and always identical to + * the size on the sink pad. + */ + fse->min_width = format->width; + fse->max_width = format->width; + fse->min_height = format->height; + fse->max_height = format->height; + } + + return 0; +} + +static int hsit_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_hsit *hsit = to_hsit(subdev); + + fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad, + fmt->which); + + return 0; +} + +static int hsit_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_hsit *hsit = to_hsit(subdev); + struct v4l2_mbus_framefmt *format; + + format = vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad, + fmt->which); + + if (fmt->pad == HSIT_PAD_SOURCE) { + /* The HST and HSI output format code and resolution can't be + * modified. + */ + fmt->format = *format; + return 0; + } + + format->code = hsit->inverse ? V4L2_MBUS_FMT_AHSV8888_1X32 + : V4L2_MBUS_FMT_ARGB8888_1X32; + format->width = clamp_t(unsigned int, fmt->format.width, + HSIT_MIN_SIZE, HSIT_MAX_SIZE); + format->height = clamp_t(unsigned int, fmt->format.height, + HSIT_MIN_SIZE, HSIT_MAX_SIZE); + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_SRGB; + + fmt->format = *format; + + /* Propagate the format to the source pad. */ + format = vsp1_entity_get_pad_format(&hsit->entity, fh, HSIT_PAD_SOURCE, + fmt->which); + *format = fmt->format; + format->code = hsit->inverse ? V4L2_MBUS_FMT_ARGB8888_1X32 + : V4L2_MBUS_FMT_AHSV8888_1X32; + + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Operations + */ + +static struct v4l2_subdev_video_ops hsit_video_ops = { + .s_stream = hsit_s_stream, +}; + +static struct v4l2_subdev_pad_ops hsit_pad_ops = { + .enum_mbus_code = hsit_enum_mbus_code, + .enum_frame_size = hsit_enum_frame_size, + .get_fmt = hsit_get_format, + .set_fmt = hsit_set_format, +}; + +static struct v4l2_subdev_ops hsit_ops = { + .video = &hsit_video_ops, + .pad = &hsit_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * Initialization and Cleanup + */ + +struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) +{ + struct v4l2_subdev *subdev; + struct vsp1_hsit *hsit; + int ret; + + hsit = devm_kzalloc(vsp1->dev, sizeof(*hsit), GFP_KERNEL); + if (hsit == NULL) + return ERR_PTR(-ENOMEM); + + hsit->inverse = inverse; + + if (inverse) { + hsit->entity.type = VSP1_ENTITY_HSI; + hsit->entity.id = VI6_DPR_NODE_HSI; + } else { + hsit->entity.type = VSP1_ENTITY_HST; + hsit->entity.id = VI6_DPR_NODE_HST; + } + + ret = vsp1_entity_init(vsp1, &hsit->entity, 2); + if (ret < 0) + return ERR_PTR(ret); + + /* Initialize the V4L2 subdev. */ + subdev = &hsit->entity.subdev; + v4l2_subdev_init(subdev, &hsit_ops); + + subdev->entity.ops = &vsp1_media_ops; + subdev->internal_ops = &vsp1_subdev_internal_ops; + snprintf(subdev->name, sizeof(subdev->name), "%s %s", + dev_name(vsp1->dev), inverse ? "hsi" : "hst"); + v4l2_set_subdevdata(subdev, hsit); + subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + vsp1_entity_init_formats(subdev, NULL); + + return hsit; +} diff --git a/drivers/media/platform/vsp1/vsp1_hsit.h b/drivers/media/platform/vsp1/vsp1_hsit.h new file mode 100644 index 000000000000..82f1c8426900 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_hsit.h @@ -0,0 +1,38 @@ +/* + * vsp1_hsit.h -- R-Car VSP1 Hue Saturation value (Inverse) Transform + * + * Copyright (C) 2013 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 __VSP1_HSIT_H__ +#define __VSP1_HSIT_H__ + +#include +#include + +#include "vsp1_entity.h" + +struct vsp1_device; + +#define HSIT_PAD_SINK 0 +#define HSIT_PAD_SOURCE 1 + +struct vsp1_hsit { + struct vsp1_entity entity; + bool inverse; +}; + +static inline struct vsp1_hsit *to_hsit(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct vsp1_hsit, entity.subdev); +} + +struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse); + +#endif /* __VSP1_HSIT_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 1d3304f1365b..0b93f8827916 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -424,12 +424,14 @@ */ #define VI6_HST_CTRL 0x2a00 +#define VI6_HST_CTRL_EN (1 << 0) /* ----------------------------------------------------------------------------- * HSI Control Registers */ #define VI6_HSI_CTRL 0x2b00 +#define VI6_HSI_CTRL_EN (1 << 0) /* ----------------------------------------------------------------------------- * BRU Control Registers -- cgit v1.2.3 From a626e64e0bee4fb26848dbed92223dde488f3d93 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Jul 2013 12:03:30 -0300 Subject: [media] v4l: vsp1: Add SRU support The Super Resolution Unit performs super resolution processing with optional upscaling by a factor of two. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 3 +- drivers/media/platform/vsp1/vsp1.h | 2 + drivers/media/platform/vsp1/vsp1_drv.c | 11 + drivers/media/platform/vsp1/vsp1_entity.c | 4 + drivers/media/platform/vsp1/vsp1_entity.h | 1 + drivers/media/platform/vsp1/vsp1_regs.h | 13 ++ drivers/media/platform/vsp1/vsp1_sru.c | 356 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_sru.h | 41 ++++ include/linux/platform_data/vsp1.h | 1 + 9 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/vsp1/vsp1_sru.c create mode 100644 drivers/media/platform/vsp1/vsp1_sru.h (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 587b8009b357..45621cb8b2a6 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,5 +1,6 @@ vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o -vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_uds.o +vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_sru.o +vsp1-y += vsp1_uds.o obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 275286e0bf42..2ab13f53b2a4 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -31,6 +31,7 @@ struct vsp1_platform_data; struct vsp1_hsit; struct vsp1_lif; struct vsp1_rwpf; +struct vsp1_sru; struct vsp1_uds; #define VPS1_MAX_RPF 5 @@ -52,6 +53,7 @@ struct vsp1_device { struct vsp1_hsit *hst; struct vsp1_lif *lif; struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; + struct vsp1_sru *sru; struct vsp1_uds *uds[VPS1_MAX_UDS]; struct vsp1_rwpf *wpf[VPS1_MAX_WPF]; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index bcede46c4a95..6f8295128704 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -23,6 +23,7 @@ #include "vsp1_hsit.h" #include "vsp1_lif.h" #include "vsp1_rwpf.h" +#include "vsp1_sru.h" #include "vsp1_uds.h" /* ----------------------------------------------------------------------------- @@ -192,6 +193,16 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&rpf->entity.list_dev, &vsp1->entities); } + if (vsp1->pdata->features & VSP1_HAS_SRU) { + vsp1->sru = vsp1_sru_create(vsp1); + if (IS_ERR(vsp1->sru)) { + ret = PTR_ERR(vsp1->sru); + goto done; + } + + list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities); + } + for (i = 0; i < vsp1->pdata->uds_count; ++i) { struct vsp1_uds *uds; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 3798ef4a272b..b11e5a6ffe04 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -15,6 +15,7 @@ #include #include +#include #include #include "vsp1.h" @@ -130,6 +131,7 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, { VI6_DPR_NODE_RPF(2), VI6_DPR_RPF_ROUTE(2) }, { VI6_DPR_NODE_RPF(3), VI6_DPR_RPF_ROUTE(3) }, { VI6_DPR_NODE_RPF(4), VI6_DPR_RPF_ROUTE(4) }, + { VI6_DPR_NODE_SRU, VI6_DPR_SRU_ROUTE }, { VI6_DPR_NODE_UDS(0), VI6_DPR_UDS_ROUTE(0) }, { VI6_DPR_NODE_UDS(1), VI6_DPR_UDS_ROUTE(1) }, { VI6_DPR_NODE_UDS(2), VI6_DPR_UDS_ROUTE(2) }, @@ -179,5 +181,7 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, void vsp1_entity_destroy(struct vsp1_entity *entity) { + if (entity->subdev.ctrl_handler) + v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); media_entity_cleanup(&entity->subdev.entity); } diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 0d617467066b..08e44801ec9d 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -24,6 +24,7 @@ enum vsp1_entity_type { VSP1_ENTITY_HST, VSP1_ENTITY_LIF, VSP1_ENTITY_RPF, + VSP1_ENTITY_SRU, VSP1_ENTITY_UDS, VSP1_ENTITY_WPF, }; diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 0b93f8827916..530cc61cfcd5 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -336,8 +336,21 @@ */ #define VI6_SRU_CTRL0 0x2200 +#define VI6_SRU_CTRL0_PARAM0_SHIFT 16 +#define VI6_SRU_CTRL0_PARAM1_SHIFT 8 +#define VI6_SRU_CTRL0_MODE_UPSCALE (4 << 4) +#define VI6_SRU_CTRL0_PARAM2 (1 << 3) +#define VI6_SRU_CTRL0_PARAM3 (1 << 2) +#define VI6_SRU_CTRL0_PARAM4 (1 << 1) +#define VI6_SRU_CTRL0_EN (1 << 0) + #define VI6_SRU_CTRL1 0x2204 +#define VI6_SRU_CTRL1_PARAM5 0x7ff + #define VI6_SRU_CTRL2 0x2208 +#define VI6_SRU_CTRL2_PARAM6_SHIFT 16 +#define VI6_SRU_CTRL2_PARAM7_SHIFT 8 +#define VI6_SRU_CTRL2_PARAM8_SHIFT 0 /* ----------------------------------------------------------------------------- * UDS Control Registers diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c new file mode 100644 index 000000000000..7ab1a0b2d656 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -0,0 +1,356 @@ +/* + * vsp1_sru.c -- R-Car VSP1 Super Resolution Unit + * + * Copyright (C) 2013 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 "vsp1.h" +#include "vsp1_sru.h" + +#define SRU_MIN_SIZE 4U +#define SRU_MAX_SIZE 8190U + +/* ----------------------------------------------------------------------------- + * Device Access + */ + +static inline u32 vsp1_sru_read(struct vsp1_sru *sru, u32 reg) +{ + return vsp1_read(sru->entity.vsp1, reg); +} + +static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data) +{ + vsp1_write(sru->entity.vsp1, reg, data); +} + +/* ----------------------------------------------------------------------------- + * Controls + */ + +#define V4L2_CID_VSP1_SRU_INTENSITY (V4L2_CID_USER_BASE + 1) + +static int sru_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vsp1_sru *sru = + container_of(ctrl->handler, struct vsp1_sru, ctrls); + + switch (ctrl->id) { + case V4L2_CID_VSP1_SRU_INTENSITY: + sru->intensity = ctrl->val; + break; + } + + return 0; +} + +static const struct v4l2_ctrl_ops sru_ctrl_ops = { + .s_ctrl = sru_s_ctrl, +}; + +static const struct v4l2_ctrl_config sru_intensity_control = { + .ops = &sru_ctrl_ops, + .id = V4L2_CID_VSP1_SRU_INTENSITY, + .name = "Intensity", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 1, + .max = 6, + .step = 1, +}; + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Core Operations + */ + +struct vsp1_sru_param { + u32 ctrl0; + u32 ctrl2; +}; + +#define VI6_SRU_CTRL0_PARAMS(p0, p1) \ + (((p0) << VI6_SRU_CTRL0_PARAM0_SHIFT) | \ + ((p1) << VI6_SRU_CTRL0_PARAM1_SHIFT)) + +#define VI6_SRU_CTRL2_PARAMS(p6, p7, p8) \ + (((p6) << VI6_SRU_CTRL2_PARAM6_SHIFT) | \ + ((p7) << VI6_SRU_CTRL2_PARAM7_SHIFT) | \ + ((p8) << VI6_SRU_CTRL2_PARAM8_SHIFT)) + +static const struct vsp1_sru_param vsp1_sru_params[] = { + { + .ctrl0 = VI6_SRU_CTRL0_PARAMS(256, 4) | VI6_SRU_CTRL0_EN, + .ctrl2 = VI6_SRU_CTRL2_PARAMS(24, 40, 255), + }, { + .ctrl0 = VI6_SRU_CTRL0_PARAMS(256, 4) | VI6_SRU_CTRL0_EN, + .ctrl2 = VI6_SRU_CTRL2_PARAMS(8, 16, 255), + }, { + .ctrl0 = VI6_SRU_CTRL0_PARAMS(384, 5) | VI6_SRU_CTRL0_EN, + .ctrl2 = VI6_SRU_CTRL2_PARAMS(36, 60, 255), + }, { + .ctrl0 = VI6_SRU_CTRL0_PARAMS(384, 5) | VI6_SRU_CTRL0_EN, + .ctrl2 = VI6_SRU_CTRL2_PARAMS(12, 27, 255), + }, { + .ctrl0 = VI6_SRU_CTRL0_PARAMS(511, 6) | VI6_SRU_CTRL0_EN, + .ctrl2 = VI6_SRU_CTRL2_PARAMS(48, 80, 255), + }, { + .ctrl0 = VI6_SRU_CTRL0_PARAMS(511, 6) | VI6_SRU_CTRL0_EN, + .ctrl2 = VI6_SRU_CTRL2_PARAMS(16, 36, 255), + }, +}; + +static int sru_s_stream(struct v4l2_subdev *subdev, int enable) +{ + struct vsp1_sru *sru = to_sru(subdev); + const struct vsp1_sru_param *param; + struct v4l2_mbus_framefmt *input; + struct v4l2_mbus_framefmt *output; + bool upscale; + u32 ctrl0; + + if (!enable) + return 0; + + input = &sru->entity.formats[SRU_PAD_SINK]; + output = &sru->entity.formats[SRU_PAD_SOURCE]; + upscale = input->width != output->width; + param = &vsp1_sru_params[sru->intensity]; + + if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32) + ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3 + | VI6_SRU_CTRL0_PARAM4; + else + ctrl0 = VI6_SRU_CTRL0_PARAM3; + + vsp1_sru_write(sru, VI6_SRU_CTRL0, param->ctrl0 | ctrl0 | + (upscale ? VI6_SRU_CTRL0_MODE_UPSCALE : 0)); + vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5); + vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2); + + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Pad Operations + */ + +static int sru_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + static const unsigned int codes[] = { + V4L2_MBUS_FMT_ARGB8888_1X32, + V4L2_MBUS_FMT_AYUV8_1X32, + }; + struct v4l2_mbus_framefmt *format; + + if (code->pad == SRU_PAD_SINK) { + if (code->index >= ARRAY_SIZE(codes)) + return -EINVAL; + + code->code = codes[code->index]; + } else { + /* The SRU can't perform format conversion, the sink format is + * always identical to the source format. + */ + if (code->index) + return -EINVAL; + + format = v4l2_subdev_get_try_format(fh, SRU_PAD_SINK); + code->code = format->code; + } + + return 0; +} + +static int sru_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct v4l2_mbus_framefmt *format; + + format = v4l2_subdev_get_try_format(fh, SRU_PAD_SINK); + + if (fse->index || fse->code != format->code) + return -EINVAL; + + if (fse->pad == SRU_PAD_SINK) { + fse->min_width = SRU_MIN_SIZE; + fse->max_width = SRU_MAX_SIZE; + fse->min_height = SRU_MIN_SIZE; + fse->max_height = SRU_MAX_SIZE; + } else { + fse->min_width = format->width; + fse->min_height = format->height; + if (format->width <= SRU_MAX_SIZE / 2 && + format->height <= SRU_MAX_SIZE / 2) { + fse->max_width = format->width * 2; + fse->max_height = format->height * 2; + } else { + fse->max_width = format->width; + fse->max_height = format->height; + } + } + + return 0; +} + +static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_sru *sru = to_sru(subdev); + + fmt->format = *vsp1_entity_get_pad_format(&sru->entity, fh, fmt->pad, + fmt->which); + + return 0; +} + +static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_fh *fh, + unsigned int pad, struct v4l2_mbus_framefmt *fmt, + enum v4l2_subdev_format_whence which) +{ + struct v4l2_mbus_framefmt *format; + unsigned int input_area; + unsigned int output_area; + + switch (pad) { + case SRU_PAD_SINK: + /* Default to YUV if the requested format is not supported. */ + if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 && + fmt->code != V4L2_MBUS_FMT_AYUV8_1X32) + fmt->code = V4L2_MBUS_FMT_AYUV8_1X32; + + fmt->width = clamp(fmt->width, SRU_MIN_SIZE, SRU_MAX_SIZE); + fmt->height = clamp(fmt->height, SRU_MIN_SIZE, SRU_MAX_SIZE); + break; + + case SRU_PAD_SOURCE: + /* The SRU can't perform format conversion. */ + format = vsp1_entity_get_pad_format(&sru->entity, fh, + SRU_PAD_SINK, which); + fmt->code = format->code; + + /* We can upscale by 2 in both direction, but not independently. + * Compare the input and output rectangles areas (avoiding + * integer overflows on the output): if the requested output + * area is larger than 1.5^2 the input area upscale by two, + * otherwise don't scale. + */ + input_area = format->width * format->height; + output_area = min(fmt->width, SRU_MAX_SIZE) + * min(fmt->height, SRU_MAX_SIZE); + + if (fmt->width <= SRU_MAX_SIZE / 2 && + fmt->height <= SRU_MAX_SIZE / 2 && + output_area > input_area * 9 / 4) { + fmt->width = format->width * 2; + fmt->height = format->height * 2; + } else { + fmt->width = format->width; + fmt->height = format->height; + } + break; + } + + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_SRGB; +} + +static int sru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_sru *sru = to_sru(subdev); + struct v4l2_mbus_framefmt *format; + + sru_try_format(sru, fh, fmt->pad, &fmt->format, fmt->which); + + format = vsp1_entity_get_pad_format(&sru->entity, fh, fmt->pad, + fmt->which); + *format = fmt->format; + + if (fmt->pad == SRU_PAD_SINK) { + /* Propagate the format to the source pad. */ + format = vsp1_entity_get_pad_format(&sru->entity, fh, + SRU_PAD_SOURCE, fmt->which); + *format = fmt->format; + + sru_try_format(sru, fh, SRU_PAD_SOURCE, format, fmt->which); + } + + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Operations + */ + +static struct v4l2_subdev_video_ops sru_video_ops = { + .s_stream = sru_s_stream, +}; + +static struct v4l2_subdev_pad_ops sru_pad_ops = { + .enum_mbus_code = sru_enum_mbus_code, + .enum_frame_size = sru_enum_frame_size, + .get_fmt = sru_get_format, + .set_fmt = sru_set_format, +}; + +static struct v4l2_subdev_ops sru_ops = { + .video = &sru_video_ops, + .pad = &sru_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * Initialization and Cleanup + */ + +struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) +{ + struct v4l2_subdev *subdev; + struct vsp1_sru *sru; + int ret; + + sru = devm_kzalloc(vsp1->dev, sizeof(*sru), GFP_KERNEL); + if (sru == NULL) + return ERR_PTR(-ENOMEM); + + sru->entity.type = VSP1_ENTITY_SRU; + sru->entity.id = VI6_DPR_NODE_SRU; + + ret = vsp1_entity_init(vsp1, &sru->entity, 2); + if (ret < 0) + return ERR_PTR(ret); + + /* Initialize the V4L2 subdev. */ + subdev = &sru->entity.subdev; + v4l2_subdev_init(subdev, &sru_ops); + + subdev->entity.ops = &vsp1_media_ops; + subdev->internal_ops = &vsp1_subdev_internal_ops; + snprintf(subdev->name, sizeof(subdev->name), "%s sru", + dev_name(vsp1->dev)); + v4l2_set_subdevdata(subdev, sru); + subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + vsp1_entity_init_formats(subdev, NULL); + + /* Initialize the control handler. */ + v4l2_ctrl_handler_init(&sru->ctrls, 1); + v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL); + v4l2_ctrl_handler_setup(&sru->ctrls); + sru->entity.subdev.ctrl_handler = &sru->ctrls; + + return sru; +} diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h new file mode 100644 index 000000000000..381870b74780 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_sru.h @@ -0,0 +1,41 @@ +/* + * vsp1_sru.h -- R-Car VSP1 Super Resolution Unit + * + * Copyright (C) 2013 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 __VSP1_SRU_H__ +#define __VSP1_SRU_H__ + +#include +#include +#include + +#include "vsp1_entity.h" + +struct vsp1_device; + +#define SRU_PAD_SINK 0 +#define SRU_PAD_SOURCE 1 + +struct vsp1_sru { + struct vsp1_entity entity; + + struct v4l2_ctrl_handler ctrls; + unsigned int intensity; +}; + +static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct vsp1_sru, entity.subdev); +} + +struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1); + +#endif /* __VSP1_SRU_H__ */ diff --git a/include/linux/platform_data/vsp1.h b/include/linux/platform_data/vsp1.h index a73a456d7f11..27c0ede1a53f 100644 --- a/include/linux/platform_data/vsp1.h +++ b/include/linux/platform_data/vsp1.h @@ -14,6 +14,7 @@ #define __PLATFORM_VSP1_H__ #define VSP1_HAS_LIF (1 << 0) +#define VSP1_HAS_SRU (1 << 1) struct vsp1_platform_data { unsigned int features; -- cgit v1.2.3 From 989af88339db26345e23271dae1089d949c4a0f1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Jul 2013 12:03:30 -0300 Subject: [media] v4l: vsp1: Add LUT support The Look-Up Table looks up values in 8-bit indexed tables separately for each color component. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/Makefile | 4 +- drivers/media/platform/vsp1/vsp1.h | 2 + drivers/media/platform/vsp1/vsp1_drv.c | 11 ++ drivers/media/platform/vsp1/vsp1_entity.c | 1 + drivers/media/platform/vsp1/vsp1_entity.h | 1 + drivers/media/platform/vsp1/vsp1_lut.c | 252 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_lut.h | 38 +++++ drivers/media/platform/vsp1/vsp1_regs.h | 1 + include/linux/platform_data/vsp1.h | 3 +- include/uapi/linux/vsp1.h | 34 ++++ 10 files changed, 344 insertions(+), 3 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_lut.c create mode 100644 drivers/media/platform/vsp1/vsp1_lut.h create mode 100644 include/uapi/linux/vsp1.h (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 45621cb8b2a6..151cecd0ea25 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -1,6 +1,6 @@ vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o -vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_sru.o -vsp1-y += vsp1_uds.o +vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o +vsp1-y += vsp1_sru.o vsp1_uds.o obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 2ab13f53b2a4..94d1b02680c5 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -30,6 +30,7 @@ struct device; struct vsp1_platform_data; struct vsp1_hsit; struct vsp1_lif; +struct vsp1_lut; struct vsp1_rwpf; struct vsp1_sru; struct vsp1_uds; @@ -52,6 +53,7 @@ struct vsp1_device { struct vsp1_hsit *hsi; struct vsp1_hsit *hst; struct vsp1_lif *lif; + struct vsp1_lut *lut; struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; struct vsp1_sru *sru; struct vsp1_uds *uds[VPS1_MAX_UDS]; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 6f8295128704..0df0a994e575 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -22,6 +22,7 @@ #include "vsp1.h" #include "vsp1_hsit.h" #include "vsp1_lif.h" +#include "vsp1_lut.h" #include "vsp1_rwpf.h" #include "vsp1_sru.h" #include "vsp1_uds.h" @@ -180,6 +181,16 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities); } + if (vsp1->pdata->features & VSP1_HAS_LUT) { + vsp1->lut = vsp1_lut_create(vsp1); + if (IS_ERR(vsp1->lut)) { + ret = PTR_ERR(vsp1->lut); + goto done; + } + + list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities); + } + for (i = 0; i < vsp1->pdata->rpf_count; ++i) { struct vsp1_rwpf *rpf; diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index b11e5a6ffe04..0226e47df6d9 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -126,6 +126,7 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, { VI6_DPR_NODE_HSI, VI6_DPR_HSI_ROUTE }, { VI6_DPR_NODE_HST, VI6_DPR_HST_ROUTE }, { VI6_DPR_NODE_LIF, 0 }, + { VI6_DPR_NODE_LUT, VI6_DPR_LUT_ROUTE }, { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) }, { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) }, { VI6_DPR_NODE_RPF(2), VI6_DPR_RPF_ROUTE(2) }, diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 08e44801ec9d..e152798d7f38 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -23,6 +23,7 @@ enum vsp1_entity_type { VSP1_ENTITY_HSI, VSP1_ENTITY_HST, VSP1_ENTITY_LIF, + VSP1_ENTITY_LUT, VSP1_ENTITY_RPF, VSP1_ENTITY_SRU, VSP1_ENTITY_UDS, diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c new file mode 100644 index 000000000000..4e9dc7c86ef8 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -0,0 +1,252 @@ +/* + * vsp1_lut.c -- R-Car VSP1 Look-Up Table + * + * Copyright (C) 2013 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 "vsp1.h" +#include "vsp1_lut.h" + +#define LUT_MIN_SIZE 4U +#define LUT_MAX_SIZE 8190U + +/* ----------------------------------------------------------------------------- + * Device Access + */ + +static inline u32 vsp1_lut_read(struct vsp1_lut *lut, u32 reg) +{ + return vsp1_read(lut->entity.vsp1, reg); +} + +static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data) +{ + vsp1_write(lut->entity.vsp1, reg, data); +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Core Operations + */ + +static void lut_configure(struct vsp1_lut *lut, struct vsp1_lut_config *config) +{ + memcpy_toio(lut->entity.vsp1->mmio + VI6_LUT_TABLE, config->lut, + sizeof(config->lut)); +} + +static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) +{ + struct vsp1_lut *lut = to_lut(subdev); + + switch (cmd) { + case VIDIOC_VSP1_LUT_CONFIG: + lut_configure(lut, arg); + return 0; + + default: + return -ENOIOCTLCMD; + } +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Video Operations + */ + +static int lut_s_stream(struct v4l2_subdev *subdev, int enable) +{ + struct vsp1_lut *lut = to_lut(subdev); + + if (!enable) + return 0; + + vsp1_lut_write(lut, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); + + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Pad Operations + */ + +static int lut_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + static const unsigned int codes[] = { + V4L2_MBUS_FMT_ARGB8888_1X32, + V4L2_MBUS_FMT_AHSV8888_1X32, + V4L2_MBUS_FMT_AYUV8_1X32, + }; + struct v4l2_mbus_framefmt *format; + + if (code->pad == LUT_PAD_SINK) { + if (code->index >= ARRAY_SIZE(codes)) + return -EINVAL; + + code->code = codes[code->index]; + } else { + /* The LUT can't perform format conversion, the sink format is + * always identical to the source format. + */ + if (code->index) + return -EINVAL; + + format = v4l2_subdev_get_try_format(fh, LUT_PAD_SINK); + code->code = format->code; + } + + return 0; +} + +static int lut_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct v4l2_mbus_framefmt *format; + + format = v4l2_subdev_get_try_format(fh, fse->pad); + + if (fse->index || fse->code != format->code) + return -EINVAL; + + if (fse->pad == LUT_PAD_SINK) { + fse->min_width = LUT_MIN_SIZE; + fse->max_width = LUT_MAX_SIZE; + fse->min_height = LUT_MIN_SIZE; + fse->max_height = LUT_MAX_SIZE; + } else { + /* The size on the source pad are fixed and always identical to + * the size on the sink pad. + */ + fse->min_width = format->width; + fse->max_width = format->width; + fse->min_height = format->height; + fse->max_height = format->height; + } + + return 0; +} + +static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_lut *lut = to_lut(subdev); + + fmt->format = *vsp1_entity_get_pad_format(&lut->entity, fh, fmt->pad, + fmt->which); + + return 0; +} + +static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct vsp1_lut *lut = to_lut(subdev); + struct v4l2_mbus_framefmt *format; + + /* Default to YUV if the requested format is not supported. */ + if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 && + fmt->format.code != V4L2_MBUS_FMT_AHSV8888_1X32 && + fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32) + fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32; + + format = vsp1_entity_get_pad_format(&lut->entity, fh, fmt->pad, + fmt->which); + + if (fmt->pad == LUT_PAD_SOURCE) { + /* The LUT output format can't be modified. */ + fmt->format = *format; + return 0; + } + + format->width = clamp_t(unsigned int, fmt->format.width, + LUT_MIN_SIZE, LUT_MAX_SIZE); + format->height = clamp_t(unsigned int, fmt->format.height, + LUT_MIN_SIZE, LUT_MAX_SIZE); + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_SRGB; + + fmt->format = *format; + + /* Propagate the format to the source pad. */ + format = vsp1_entity_get_pad_format(&lut->entity, fh, LUT_PAD_SOURCE, + fmt->which); + *format = fmt->format; + + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Operations + */ + +static struct v4l2_subdev_core_ops lut_core_ops = { + .ioctl = lut_ioctl, +}; + +static struct v4l2_subdev_video_ops lut_video_ops = { + .s_stream = lut_s_stream, +}; + +static struct v4l2_subdev_pad_ops lut_pad_ops = { + .enum_mbus_code = lut_enum_mbus_code, + .enum_frame_size = lut_enum_frame_size, + .get_fmt = lut_get_format, + .set_fmt = lut_set_format, +}; + +static struct v4l2_subdev_ops lut_ops = { + .core = &lut_core_ops, + .video = &lut_video_ops, + .pad = &lut_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * Initialization and Cleanup + */ + +struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) +{ + struct v4l2_subdev *subdev; + struct vsp1_lut *lut; + int ret; + + lut = devm_kzalloc(vsp1->dev, sizeof(*lut), GFP_KERNEL); + if (lut == NULL) + return ERR_PTR(-ENOMEM); + + lut->entity.type = VSP1_ENTITY_LUT; + lut->entity.id = VI6_DPR_NODE_LUT; + + ret = vsp1_entity_init(vsp1, &lut->entity, 2); + if (ret < 0) + return ERR_PTR(ret); + + /* Initialize the V4L2 subdev. */ + subdev = &lut->entity.subdev; + v4l2_subdev_init(subdev, &lut_ops); + + subdev->entity.ops = &vsp1_media_ops; + subdev->internal_ops = &vsp1_subdev_internal_ops; + snprintf(subdev->name, sizeof(subdev->name), "%s lut", + dev_name(vsp1->dev)); + v4l2_set_subdevdata(subdev, lut); + subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + vsp1_entity_init_formats(subdev, NULL); + + return lut; +} diff --git a/drivers/media/platform/vsp1/vsp1_lut.h b/drivers/media/platform/vsp1/vsp1_lut.h new file mode 100644 index 000000000000..f92ffb867350 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_lut.h @@ -0,0 +1,38 @@ +/* + * vsp1_lut.h -- R-Car VSP1 Look-Up Table + * + * Copyright (C) 2013 Renesas Corporation + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + * + * 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 __VSP1_LUT_H__ +#define __VSP1_LUT_H__ + +#include +#include + +#include "vsp1_entity.h" + +struct vsp1_device; + +#define LUT_PAD_SINK 0 +#define LUT_PAD_SOURCE 1 + +struct vsp1_lut { + struct vsp1_entity entity; + u32 lut[256]; +}; + +static inline struct vsp1_lut *to_lut(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct vsp1_lut, entity.subdev); +} + +struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1); + +#endif /* __VSP1_LUT_H__ */ diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 530cc61cfcd5..28650806c20f 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -425,6 +425,7 @@ */ #define VI6_LUT_CTRL 0x2800 +#define VI6_LUT_CTRL_EN (1 << 0) /* ----------------------------------------------------------------------------- * CLU Control Registers diff --git a/include/linux/platform_data/vsp1.h b/include/linux/platform_data/vsp1.h index 27c0ede1a53f..63170e2614b3 100644 --- a/include/linux/platform_data/vsp1.h +++ b/include/linux/platform_data/vsp1.h @@ -14,7 +14,8 @@ #define __PLATFORM_VSP1_H__ #define VSP1_HAS_LIF (1 << 0) -#define VSP1_HAS_SRU (1 << 1) +#define VSP1_HAS_LUT (1 << 1) +#define VSP1_HAS_SRU (1 << 2) struct vsp1_platform_data { unsigned int features; diff --git a/include/uapi/linux/vsp1.h b/include/uapi/linux/vsp1.h new file mode 100644 index 000000000000..e18858f6e865 --- /dev/null +++ b/include/uapi/linux/vsp1.h @@ -0,0 +1,34 @@ +/* + * vsp1.h + * + * Renesas R-Car VSP1 - User-space API + * + * Copyright (C) 2013 Renesas Corporation + * + * Contacts: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __VSP1_USER_H__ +#define __VSP1_USER_H__ + +#include +#include + +/* + * Private IOCTLs + * + * VIDIOC_VSP1_LUT_CONFIG - Configure the lookup table + */ + +#define VIDIOC_VSP1_LUT_CONFIG \ + _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct vsp1_lut_config) + +struct vsp1_lut_config { + u32 lut[256]; +}; + +#endif /* __VSP1_USER_H__ */ -- cgit v1.2.3 From f57f98a6c0f4f3cb4d2ec9f9566b8e3f21843f03 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Dec 2013 13:36:11 -0700 Subject: gpio: tegra: add missing error handling to probe The call to gpiochip_add() is not currently error-checked. Add the missing checking. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index cfd3b9037bc7..2b49f878b56c 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -425,6 +425,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) struct tegra_gpio_soc_config *config; struct resource *res; struct tegra_gpio_bank *bank; + int ret; int gpio; int i; int j; @@ -494,7 +495,11 @@ static int tegra_gpio_probe(struct platform_device *pdev) tegra_gpio_chip.of_node = pdev->dev.of_node; - gpiochip_add(&tegra_gpio_chip); + ret = gpiochip_add(&tegra_gpio_chip); + if (ret < 0) { + irq_domain_remove(irq_domain); + return ret; + } for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { int irq = irq_create_mapping(irq_domain, gpio); -- cgit v1.2.3 From 6c719faca2aceca72f1bf5b1645c1734ed3e9447 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 10 Dec 2013 13:20:59 +0100 Subject: drm/i915: don't update the dri1 breadcrumb with modesetting The update is horribly racy since it doesn't protect at all against concurrent closing of the master fd. And it can't really since that requires us to grab a mutex. Instead of jumping through hoops and offloading this to a worker thread just block this bit of code for the modesetting driver. Note that the race is fairly easy to hit since we call the breadcrumb function for any interrupt. So the vblank interrupt (which usually keeps going for a bit) is enough. But even if we'd block this and only update the breadcrumb for user interrupts from the CS we could hit this race with kms/gem userspace: If a non-master is waiting somewhere (and hence has interrupts enabled) and the master closes its fd (probably due to crashing). v2: Add a code comment to explain why fixing this for real isn't really worth it. Also improve the commit message a bit. v3: Fix the spelling in the comment. Reported-by: Eugene Shatokhin Cc: Eugene Shatokhin Cc: stable@vger.kernel.org Acked-by: Chris Wilson Tested-by: Eugene Shatokhin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 197db0993a24..5c648425c1e0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -83,6 +83,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; + /* + * The dri breadcrumb update races against the drm master disappearing. + * Instead of trying to fix this (this is by far not the only ums issue) + * just don't do the update in kms mode. + */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + if (dev->primary->master) { master_priv = dev->primary->master->driver_priv; if (master_priv->sarea_priv) -- cgit v1.2.3 From 6f041e99fc7ba00e7e65a431527f9235d6b16463 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 21 Nov 2013 13:44:14 +0000 Subject: of: Fix NULL dereference in unflatten_and_copy() Check whether initial_boot_params is NULL before dereferencing it in unflatten_and_copy_device_tree() for the case where no device tree is available but the arch can still boot to a minimal usable system without it. In this case also log a warning for when the kernel log buffer is obtainable. Signed-off-by: James Hogan Cc: Rob Herring Signed-off-by: Grant Likely --- drivers/of/fdt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 2fa024b97c43..758b4f8b30b7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -922,8 +922,16 @@ void __init unflatten_device_tree(void) */ void __init unflatten_and_copy_device_tree(void) { - int size = __be32_to_cpu(initial_boot_params->totalsize); - void *dt = early_init_dt_alloc_memory_arch(size, + int size; + void *dt; + + if (!initial_boot_params) { + pr_warn("No valid device tree found, continuing without\n"); + return; + } + + size = __be32_to_cpu(initial_boot_params->totalsize); + dt = early_init_dt_alloc_memory_arch(size, __alignof__(struct boot_param_header)); if (dt) { -- cgit v1.2.3 From f47cdae42aacf24d5632be5fd8eb9ccd7fe59906 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 03:32:10 -0800 Subject: zd1211rw: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: linux-wireless@vger.kernel.org CC: Daniel Drake CC: Ulrich Kunitz Signed-off-by: Jeff Kirsher Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 3 +-- drivers/net/wireless/zd1211rw/zd_chip.h | 3 +-- drivers/net/wireless/zd1211rw/zd_def.h | 3 +-- drivers/net/wireless/zd1211rw/zd_mac.c | 3 +-- drivers/net/wireless/zd1211rw/zd_mac.h | 3 +-- drivers/net/wireless/zd1211rw/zd_rf.c | 3 +-- drivers/net/wireless/zd1211rw/zd_rf.h | 3 +-- drivers/net/wireless/zd1211rw/zd_rf_al2230.c | 3 +-- drivers/net/wireless/zd1211rw/zd_rf_al7230b.c | 3 +-- drivers/net/wireless/zd1211rw/zd_rf_rf2959.c | 3 +-- drivers/net/wireless/zd1211rw/zd_rf_uw2453.c | 3 +-- drivers/net/wireless/zd1211rw/zd_usb.c | 3 +-- drivers/net/wireless/zd1211rw/zd_usb.h | 3 +-- 13 files changed, 13 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 71ab320fae82..73a49b868035 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ /* This file implements all the hardware specific functions for the ZD1211 diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 7ab922209b25..b03786c9f3aa 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _ZD_CHIP_H diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h index 9a1b013f81be..41bd755bc135 100644 --- a/drivers/net/wireless/zd1211rw/zd_def.h +++ b/drivers/net/wireless/zd1211rw/zd_def.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _ZD_DEF_H diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index c6208a7988e4..eff79a37bc2a 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index c01eca859f95..5a484235308f 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _ZD_MAC_H diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c index c875ee05e22e..dc179c414518 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.c +++ b/drivers/net/wireless/zd1211rw/zd_rf.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h index 725b7c99b23d..8f14e25e1041 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/drivers/net/wireless/zd1211rw/zd_rf.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _ZD_RF_H diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 12babcb633c3..99aed7d78952 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c index 385c670d1293..5fea485be574 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c index 784d9ccb8fef..a93f657a41c7 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c index c4d324e19c24..61b924027356 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 84d94f572a46..a912dc051111 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -15,8 +15,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index 45e3bb28a01c..a9075f225178 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _ZD_USB_H -- cgit v1.2.3 From a05b8c580c83a7bd4fce81f8d6af044e97e4a7a4 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 03:32:11 -0800 Subject: rt2x00: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: linux-wireless@vger.kernel.org CC: Ivo van Doorn CC: Gertjan van Wingerde CC: Helmut Schaa Signed-off-by: Jeff Kirsher Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 +--- drivers/net/wireless/rt2x00/rt2400pci.h | 4 +--- drivers/net/wireless/rt2x00/rt2500pci.c | 4 +--- drivers/net/wireless/rt2x00/rt2500pci.h | 4 +--- drivers/net/wireless/rt2x00/rt2500usb.c | 4 +--- drivers/net/wireless/rt2x00/rt2500usb.h | 4 +--- drivers/net/wireless/rt2x00/rt2800.h | 4 +--- drivers/net/wireless/rt2x00/rt2800lib.c | 4 +--- drivers/net/wireless/rt2x00/rt2800lib.h | 4 +--- drivers/net/wireless/rt2x00/rt2800mmio.c | 4 +--- drivers/net/wireless/rt2x00/rt2800mmio.h | 4 +--- drivers/net/wireless/rt2x00/rt2800pci.c | 4 +--- drivers/net/wireless/rt2x00/rt2800pci.h | 4 +--- drivers/net/wireless/rt2x00/rt2800soc.c | 4 +--- drivers/net/wireless/rt2x00/rt2800usb.c | 4 +--- drivers/net/wireless/rt2x00/rt2800usb.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00config.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00crypto.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00debug.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00debug.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00dump.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00firmware.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00leds.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00leds.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00lib.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00link.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00mmio.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00mmio.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00pci.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00pci.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00queue.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00queue.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00reg.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00soc.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00soc.h | 4 +--- drivers/net/wireless/rt2x00/rt2x00usb.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00usb.h | 4 +--- drivers/net/wireless/rt2x00/rt61pci.c | 4 +--- drivers/net/wireless/rt2x00/rt61pci.h | 4 +--- drivers/net/wireless/rt2x00/rt73usb.c | 4 +--- drivers/net/wireless/rt2x00/rt73usb.h | 4 +--- 44 files changed, 44 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 38ed9a3e44c8..4ad0de9d1d08 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index e4b07f0aa3cc..0fd3a9d01a60 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0ac5c589ddce..4f61ffbcd2f1 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index 9c10068e4987..573e87bcc553 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 85acc79f68b8..1bb76935da71 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 1b91a4cef965..afba0739c3b8 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index aab6b5e4f5dd..a394a9a95919 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -21,9 +21,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 5ee5b296ad28..b8f5b06006c4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -24,9 +24,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index a94ba447e63c..3019db637a4b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -14,9 +14,7 @@ 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. + along with this program; if not, see . */ #ifndef RT2800LIB_H diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c index a8cc736b5063..de4790b41be7 100644 --- a/drivers/net/wireless/rt2x00/rt2800mmio.c +++ b/drivers/net/wireless/rt2x00/rt2800mmio.c @@ -19,9 +19,7 @@ * 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. + * along with this program; if not, see . */ /* Module: rt2800mmio diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h index 6a10de3eee3e..b63312ce3f27 100644 --- a/drivers/net/wireless/rt2x00/rt2800mmio.h +++ b/drivers/net/wireless/rt2x00/rt2800mmio.h @@ -19,9 +19,7 @@ * 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. + * along with this program; if not, see . */ /* Module: rt2800mmio diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b504455b4fec..a5b32ca2cf0f 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -20,9 +20,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index a81c9ee281c0..9dfef4607d6b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h @@ -20,9 +20,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c index 1359227ca411..f6d1bf5be006 100644 --- a/drivers/net/wireless/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/rt2x00/rt2800soc.c @@ -19,9 +19,7 @@ * 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. + * along with this program; if not, see . */ /* Module: rt2800soc diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a81ceb61d746..49ff178a0b46 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -18,9 +18,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 671ea3592610..ea7cac095997 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -17,9 +17,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index e4ba2ce0f212..e3b885d8f7db 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -15,9 +15,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 8cb43f8f3efc..1122dc44c9fd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 3db0d99d9da7..a2fd05ba25ca 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 7f7baae5ae02..2e3d1645e68b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h index e11d39bdfef7..e65712c235bd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ b/drivers/net/wireless/rt2x00/rt2x00debug.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9dd92a700442..00c3fae6fa3c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -14,9 +14,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 063ebcce97f8..4c0e01b5d515 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 1b4254b4272d..fbae2799e3ee 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -14,9 +14,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 997a6c89e66e..c681d04b506c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h index 3b46f0c3332a..b2c5269570da 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.h +++ b/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 7f40ab8e1bd8..fb7c349ccc9c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -14,9 +14,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index c2b3b6629188..9b941c0c1264 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 2183e7978399..ddeb5a709aa3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c index 64b06c6abe58..6f236ea180aa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mmio.c +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h index cda3dbcf7ead..701c3127efb9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mmio.h +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index af721831dcbc..d93db4b0371b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 60d90b20f8b9..bc0ca5f58f38 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a5d38e8ad9e4..5642ccceca7c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -15,9 +15,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index ebe117224979..c48125be0e34 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 6f867eec49cc..3cc541d13d67 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 9271a5fce0a8..69a0cdadb07f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -14,9 +14,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 474cbfc1efc7..9948d355e9a4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 4e121627925d..10572452cc21 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -14,9 +14,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 323ca7b2b095..e7bcf62347d5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index a5b69cb49012..b76f6049ad9a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 9bc6b6044e34..1442075a8382 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1baf9c896dcd..ade88d7e089c 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 7577e0ba3877..4a4f235466d1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -13,9 +13,7 @@ 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. + along with this program; if not, see . */ /* -- cgit v1.2.3 From 4280db9d00f96d51789b5b77980173f0491fa594 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 03:32:12 -0800 Subject: prism54: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: linux-wireless@vger.kernel.org CC: "Luis R. Rodriguez" Signed-off-by: Jeff Kirsher Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_38xx.c | 3 +-- drivers/net/wireless/prism54/isl_38xx.h | 3 +-- drivers/net/wireless/prism54/isl_ioctl.c | 3 +-- drivers/net/wireless/prism54/isl_ioctl.h | 3 +-- drivers/net/wireless/prism54/isl_oid.h | 3 +-- drivers/net/wireless/prism54/islpci_dev.c | 3 +-- drivers/net/wireless/prism54/islpci_dev.h | 3 +-- drivers/net/wireless/prism54/islpci_eth.c | 3 +-- drivers/net/wireless/prism54/islpci_eth.h | 3 +-- drivers/net/wireless/prism54/islpci_hotplug.c | 3 +-- drivers/net/wireless/prism54/islpci_mgt.c | 3 +-- drivers/net/wireless/prism54/islpci_mgt.h | 3 +-- drivers/net/wireless/prism54/oid_mgt.c | 3 +-- drivers/net/wireless/prism54/oid_mgt.h | 3 +-- drivers/net/wireless/prism54/prismcompat.h | 3 +-- 15 files changed, 15 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 02fc67bccbd0..333c1a2f882e 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -12,8 +12,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h index 19c33d313734..547ab885610b 100644 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ b/drivers/net/wireless/prism54/isl_38xx.h @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 8863a6cb2388..df784fefb8e3 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index a34bceb6e3cd..842a2549facc 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index 59e31258d450..83fec557997e 100644 --- a/drivers/net/wireless/prism54/isl_oid.h +++ b/drivers/net/wireless/prism54/isl_oid.h @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 7fa2898d0619..931cf440ff18 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index c40403877f97..f6f088e05fe4 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 799e148d0370..674658f2e6ef 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h index 6ca30a5b7bfb..80f50f1bc6f2 100644 --- a/drivers/net/wireless/prism54/islpci_eth.h +++ b/drivers/net/wireless/prism54/islpci_eth.h @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index d7b9e6376424..1105a12dbde8 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -12,8 +12,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 9f19cceab487..0de14dfa68cc 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -12,8 +12,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h index 0db93db9b675..700c434c8803 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.h +++ b/drivers/net/wireless/prism54/islpci_mgt.h @@ -12,8 +12,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index 056af38e72e3..47b34bfe890a 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h index 92c8a2d4acd8..cf5141df8474 100644 --- a/drivers/net/wireless/prism54/oid_mgt.h +++ b/drivers/net/wireless/prism54/oid_mgt.h @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h index aa1d1747784f..bc1401eb4b9d 100644 --- a/drivers/net/wireless/prism54/prismcompat.h +++ b/drivers/net/wireless/prism54/prismcompat.h @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . * */ -- cgit v1.2.3 From 36769159a99063ba4d3cb0a20ed0b3095a334c8c Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 03:32:13 -0800 Subject: drivers/net/wireless: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: linux-wireless@vger.kernel.org CC: Simon Kelley CC: Christian Lamparter CC: Jussi Kivilinna Signed-off-by: Jeff Kirsher Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 7 +++---- drivers/net/wireless/atmel.h | 4 ++-- drivers/net/wireless/atmel_cs.c | 4 ++-- drivers/net/wireless/atmel_pci.c | 4 ++-- drivers/net/wireless/libertas/README | 5 ++--- drivers/net/wireless/p54/net2280.h | 3 +-- drivers/net/wireless/ray_cs.c | 3 +-- drivers/net/wireless/rndis_wlan.c | 3 +-- 8 files changed, 14 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 0d950f209dae..b73b7e3e2196 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -28,8 +28,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with Atmel wireless lan drivers; if not, see + . For all queries about this code, please contact the current author, Simon Kelley and not Atmel Corporation. @@ -4278,8 +4278,7 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data) GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with AtmelMACFW; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with AtmelMACFW; if not, see . ****************************************************************************/ /* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E */ diff --git a/drivers/net/wireless/atmel.h b/drivers/net/wireless/atmel.h index b9b3e5b76544..96f7318cbb04 100644 --- a/drivers/net/wireless/atmel.h +++ b/drivers/net/wireless/atmel.h @@ -15,8 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with Atmel wireless lan drivers; if not, see + . ******************************************************************************/ diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 522572219217..5e2749dd1124 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -24,8 +24,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with Atmel wireless lan drivers; if not, see + . ******************************************************************************/ diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index c1b159ebcffe..64d5973ec28b 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c @@ -15,8 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with Atmel wireless lan drivers; if not, see + . ******************************************************************************/ #include diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index 91f2ca90c70f..1a554a685e91 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -8,9 +8,8 @@ Ltd. under the terms of the GNU General Public License Version 2, June 1991 (the "License"). You may use, redistribute and/or modify this File in accordance with the terms and conditions of the License, a copy of which - is available along with the File in the license.txt file or by writing to - the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + is available along with the File in the license.txt file or on the worldwide + web at http://www.gnu.org/licenses/gpl.txt. THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h index e3ed893b5aaf..aedfaf24f386 100644 --- a/drivers/net/wireless/p54/net2280.h +++ b/drivers/net/wireless/p54/net2280.h @@ -20,8 +20,7 @@ * 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 + * along with this program; if not, see . */ /*-------------------------------------------------------------------------*/ diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 9b557a1bb7f8..cbf0a589d32a 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -17,8 +17,7 @@ * 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 + * along with this program; if not, see . * * Changes: * Arnaldo Carvalho de Melo - 08/08/2000 diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 8169a85c4498..c3cdda1252de 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -15,8 +15,7 @@ * 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 + * along with this program; if not, see . * * Portions of this file are based on NDISwrapper project, * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani -- cgit v1.2.3 From 98b32decc83ed3137e3ddbc918b102f8fc406b6d Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 08:56:16 -0800 Subject: nfc: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: linux-wireless@vger.kernel.org CC: Lauro Ramos Venancio CC: Aloisio Almeida Jr CC: Samuel Ortiz Signed-off-by: Jeff Kirsher Signed-off-by: John W. Linville --- drivers/nfc/mei_phy.c | 4 +--- drivers/nfc/microread/i2c.c | 4 +--- drivers/nfc/microread/mei.c | 4 +--- drivers/nfc/microread/microread.c | 4 +--- drivers/nfc/microread/microread.h | 4 +--- drivers/nfc/nfcwilink.c | 3 +-- drivers/nfc/pn533.c | 4 +--- drivers/nfc/pn544/i2c.c | 4 +--- drivers/nfc/pn544/mei.c | 4 +--- drivers/nfc/pn544/pn544.c | 4 +--- drivers/nfc/pn544/pn544.h | 4 +--- include/linux/platform_data/pn544.h | 3 +-- net/nfc/af_nfc.c | 4 +--- net/nfc/core.c | 4 +--- net/nfc/hci/command.c | 4 +--- net/nfc/hci/core.c | 4 +--- net/nfc/hci/hci.h | 4 +--- net/nfc/hci/hcp.c | 4 +--- net/nfc/hci/llc.c | 4 +--- net/nfc/hci/llc.h | 4 +--- net/nfc/hci/llc_nop.c | 4 +--- net/nfc/hci/llc_shdlc.c | 4 +--- net/nfc/llcp.h | 4 +--- net/nfc/llcp_commands.c | 4 +--- net/nfc/llcp_core.c | 4 +--- net/nfc/llcp_sock.c | 4 +--- net/nfc/nci/core.c | 3 +-- net/nfc/nci/data.c | 3 +-- net/nfc/nci/lib.c | 3 +-- net/nfc/nci/ntf.c | 3 +-- net/nfc/nci/rsp.c | 3 +-- net/nfc/netlink.c | 4 +--- net/nfc/nfc.h | 4 +--- net/nfc/rawsock.c | 4 +--- 34 files changed, 34 insertions(+), 95 deletions(-) (limited to 'drivers') diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 85f90090cc1d..1d7860551985 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c index 696e3467eccc..df85cd3d9db0 100644 --- a/drivers/nfc/microread/i2c.c +++ b/drivers/nfc/microread/i2c.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index 72fafec3d460..2d1395be64ae 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c index 970ded6bfcf5..f868333271aa 100644 --- a/drivers/nfc/microread/microread.c +++ b/drivers/nfc/microread/microread.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/nfc/microread/microread.h b/drivers/nfc/microread/microread.h index 64b447a1c5bf..f538641431a2 100644 --- a/drivers/nfc/microread/microread.h +++ b/drivers/nfc/microread/microread.h @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #ifndef __LOCAL_MICROREAD_H_ diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 71308645593f..683671a71c7e 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -22,8 +22,7 @@ * 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 + * along with this program; if not, see . * */ #include diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 2daf04c07338..3df19e657bc1 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index b158ee1c2ac6..d6185ff2f87b 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c index ee67de50c36f..330cd4031009 100644 --- a/drivers/nfc/pn544/mei.c +++ b/drivers/nfc/pn544/mei.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 74cfa0a88b9e..51e21a87cd84 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/nfc/pn544/pn544.h b/drivers/nfc/pn544/pn544.h index 01020e585443..491bf45da358 100644 --- a/drivers/nfc/pn544/pn544.h +++ b/drivers/nfc/pn544/pn544.h @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #ifndef __LOCAL_PN544_H_ diff --git a/include/linux/platform_data/pn544.h b/include/linux/platform_data/pn544.h index 713bfd703342..5ce1ab983f44 100644 --- a/include/linux/platform_data/pn544.h +++ b/include/linux/platform_data/pn544.h @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #ifndef _PN544_H_ diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c index 9d68441e2a5a..2277276f52bc 100644 --- a/net/nfc/af_nfc.c +++ b/net/nfc/af_nfc.c @@ -16,9 +16,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/net/nfc/core.c b/net/nfc/core.c index 872529105abc..02ab34132157 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -16,9 +16,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 64f922be9281..a9f4d2e62d8d 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "hci: %s: " fmt, __func__ diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index d07ca4c5cf8c..3b9610031baa 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "hci: %s: " fmt, __func__ diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h index b274d12c18ac..c3d2e2c1394c 100644 --- a/net/nfc/hci/hci.h +++ b/net/nfc/hci/hci.h @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #ifndef __LOCAL_HCI_H diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c index b6b4109f2343..e9de1514656e 100644 --- a/net/nfc/hci/hcp.c +++ b/net/nfc/hci/hcp.c @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "hci: %s: " fmt, __func__ diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c index fe5e966e5b88..a07d2b818487 100644 --- a/net/nfc/hci/llc.c +++ b/net/nfc/hci/llc.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/net/nfc/hci/llc.h b/net/nfc/hci/llc.h index 7be0b7f3ceb6..5dad4c57ffb3 100644 --- a/net/nfc/hci/llc.h +++ b/net/nfc/hci/llc.h @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #ifndef __LOCAL_LLC_H_ diff --git a/net/nfc/hci/llc_nop.c b/net/nfc/hci/llc_nop.c index 87b10291b40f..d0435d5a197b 100644 --- a/net/nfc/hci/llc_nop.c +++ b/net/nfc/hci/llc_nop.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index 27b313befc35..719ad0ac40de 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c @@ -13,9 +13,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "shdlc: %s: " fmt, __func__ diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index f4d48b57ea11..de1789e3cc82 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ enum llcp_state { diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index 1017894807c0..693cd1aad582 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 81cd3416c7d4..1349074e1ffc 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 824c6056bf82..69fbc8dadba7 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -12,9 +12,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index b943d46a1644..f0e955e3a385 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -20,8 +20,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c index 2a9399dd6c68..6c3aef852876 100644 --- a/net/nfc/nci/data.c +++ b/net/nfc/nci/data.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/net/nfc/nci/lib.c b/net/nfc/nci/lib.c index 6b7fd26c68d9..ed774a2e989a 100644 --- a/net/nfc/nci/lib.c +++ b/net/nfc/nci/lib.c @@ -20,8 +20,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index b2aa98ef0927..1e905097456b 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c @@ -20,8 +20,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index dd072f38ad00..041de51ccdbe 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c @@ -20,8 +20,7 @@ * 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 + * along with this program; if not, see . * */ diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index a9b2342d5253..ebbf6fb88b35 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -16,9 +16,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index aaf606fc1faa..9d6e74f7e6b3 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -16,9 +16,7 @@ * 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. + * along with this program; if not, see . */ #ifndef __LOCAL_NFC_H diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 66bcd2eb5773..c27a6e86cae4 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -16,9 +16,7 @@ * 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. + * along with this program; if not, see . */ #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ -- cgit v1.2.3 From cb161cda634ae5fdb4de797096ba9028171507d2 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sat, 7 Dec 2013 02:17:40 +0000 Subject: ath5k: Reset Tx interrupt bits also on PISR Some cards don't update the PISR properly when all SISR bits for Tx interrupts are being cleared and as a result we get interrupt storm. Since we handle all tx queues all together (so we don't really use the SISR bits to do per-queue interrupt handling), we can manualy update PISR by doing a write-to-clear on its Tx interrupt bits. Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/dma.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index ba200b24be64..e6c52f7c26e7 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -616,7 +616,16 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) * SISRs will also clear PISR so no need to worry here. */ - pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS; + /* XXX: There seems to be an issue on some cards + * with tx interrupt flags not being updated + * on PISR despite that all Tx interrupt bits + * are cleared on SISRs. Since we handle all + * Tx queues all together it shouldn't be an + * issue if we clear Tx interrupt flags also + * on PISR to avoid that. + */ + pisr_clear = (pisr & ~AR5K_ISR_BITS_FROM_SISRS) | + (pisr & AR5K_INT_TX_ALL); /* * Write to clear them... -- cgit v1.2.3 From 55957fb7a0b61d8ab6ff3f04e279b8fc22b738fa Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 9 Dec 2013 23:37:49 +0100 Subject: ath9k: initialize retry chain flags in tx99 code Initialize first chain flags in ath9k_build_tx99_skb() according to configured channel mode and channel width Signed-off-by: Lorenzo Bianconi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/tx99.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 57d775783ec8..b686a7498450 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -48,7 +48,9 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; u32 len = 1200; + struct ieee80211_tx_rate *rate; struct ieee80211_hw *hw = sc->hw; + struct ath_hw *ah = sc->sc_ah; struct ieee80211_hdr *hdr; struct ieee80211_tx_info *tx_info; struct sk_buff *skb; @@ -73,10 +75,16 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) tx_info = IEEE80211_SKB_CB(skb); memset(tx_info, 0, sizeof(*tx_info)); + rate = &tx_info->control.rates[0]; tx_info->band = hw->conf.chandef.chan->band; tx_info->flags = IEEE80211_TX_CTL_NO_ACK; tx_info->control.vif = sc->tx99_vif; - tx_info->control.rates[0].count = 1; + rate->count = 1; + if (ah->curchan && IS_CHAN_HT(ah->curchan)) { + rate->flags |= IEEE80211_TX_RC_MCS; + if (IS_CHAN_HT40(ah->curchan)) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + } memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); -- cgit v1.2.3 From c700f013adb0ec57518a7fe0163e3117659ce249 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 6 Dec 2013 01:17:08 -0500 Subject: EDAC: Add an edac_report parameter to EDAC This new parameter is used to control how to report HW error reporting, especially for newer Intel platform, like Ivybridge-EX, which contains an enhanced error decoding functionality in the firmware, i.e. eMCA. Signed-off-by: Chen, Gong Acked-by: Tony Luck Link: http://lkml.kernel.org/r/1386310630-12529-2-git-send-email-gong.chen@linux.intel.com [ Boris: massage commit message. ] Signed-off-by: Borislav Petkov --- Documentation/kernel-parameters.txt | 8 ++++++++ drivers/edac/edac_stub.c | 19 +++++++++++++++++++ include/linux/edac.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) (limited to 'drivers') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 50680a59a2ff..453092c822f1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -881,6 +881,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. The xen output can only be used by Xen PV guests. + edac_report= [HW,EDAC] Control how to report EDAC event + Format: {"on" | "off" | "force"} + on: enable EDAC to report H/W event. May be overridden + by other higher priority error reporting module. + off: disable H/W event reporting through EDAC. + force: enforce the use of EDAC to report H/W event. + default: on. + ekgdboc= [X86,KGDB] Allow early kernel console debugging ekgdboc=kbd diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c index 351945fa2ecd..9d9e18aefaaa 100644 --- a/drivers/edac/edac_stub.c +++ b/drivers/edac/edac_stub.c @@ -29,6 +29,25 @@ EXPORT_SYMBOL_GPL(edac_err_assert); static atomic_t edac_subsys_valid = ATOMIC_INIT(0); +int edac_report_status = EDAC_REPORTING_ENABLED; +EXPORT_SYMBOL_GPL(edac_report_status); + +static int __init edac_report_setup(char *str) +{ + if (!str) + return -EINVAL; + + if (!strncmp(str, "on", 2)) + set_edac_report_status(EDAC_REPORTING_ENABLED); + else if (!strncmp(str, "off", 3)) + set_edac_report_status(EDAC_REPORTING_DISABLED); + else if (!strncmp(str, "force", 5)) + set_edac_report_status(EDAC_REPORTING_FORCE); + + return 0; +} +__setup("edac_report=", edac_report_setup); + /* * called to determine if there is an EDAC driver interested in * knowing an event (such as NMI) occurred diff --git a/include/linux/edac.h b/include/linux/edac.h index dbdffe8d4469..8e6c20af11a2 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -35,6 +35,34 @@ extern void edac_atomic_assert_error(void); extern struct bus_type *edac_get_sysfs_subsys(void); extern void edac_put_sysfs_subsys(void); +enum { + EDAC_REPORTING_ENABLED, + EDAC_REPORTING_DISABLED, + EDAC_REPORTING_FORCE +}; + +extern int edac_report_status; +#ifdef CONFIG_EDAC +static inline int get_edac_report_status(void) +{ + return edac_report_status; +} + +static inline void set_edac_report_status(int new) +{ + edac_report_status = new; +} +#else +static inline int get_edac_report_status(void) +{ + return EDAC_REPORTING_DISABLED; +} + +static inline void set_edac_report_status(int new) +{ +} +#endif + static inline void opstate_init(void) { switch (edac_op_state) { -- cgit v1.2.3 From fd521039666529a4674b9822f1cc873672f57ee6 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 6 Dec 2013 01:17:09 -0500 Subject: EDAC, sb_edac: Modify H/W event reporting policy Newer Intel platforms support more than one method to report H/W event. On this kind of platform, H/W event report can adopt new method and traditional EDAC method should be disabled. Moreover, if EDAC event report method is set to *force*, it means event must be reported via EDAC interface. IOW, it overrides the default event report policy. Signed-off-by: Chen, Gong Acked-by: Tony Luck Link: http://lkml.kernel.org/r/1386310630-12529-3-git-send-email-gong.chen@linux.intel.com [ Boris: massage commit and error messages ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 8472405c5586..e2e2cb365764 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1829,6 +1829,9 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, struct mem_ctl_info *mci; struct sbridge_pvt *pvt; + if (get_edac_report_status() == EDAC_REPORTING_DISABLED) + return NOTIFY_DONE; + mci = get_mci_for_node_id(mce->socketid); if (!mci) return NOTIFY_BAD; @@ -2142,9 +2145,10 @@ static int __init sbridge_init(void) opstate_init(); pci_rc = pci_register_driver(&sbridge_driver); - if (pci_rc >= 0) { mce_register_decode_chain(&sbridge_mce_dec); + if (get_edac_report_status() == EDAC_REPORTING_DISABLED) + sbridge_printk(KERN_WARNING, "Loading driver, error reporting disabled.\n"); return 0; } -- cgit v1.2.3 From 42139eb356e3384759ca143ae04d82376346eb4c Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Fri, 6 Dec 2013 01:17:10 -0500 Subject: ACPI, eMCA: Combine eMCA/EDAC event reporting priority eMCA has higher H/W event reporting priority. Once it is loaded, EDAC event reporting should be disabled, unless EDAC overrides eMCA priority via command line parameter "edac_report=force". Signed-off-by: Chen, Gong Acked-by: Tony Luck Link: http://lkml.kernel.org/r/1386310630-12529-4-git-send-email-gong.chen@linux.intel.com [ Boris: massage printk message. ] Signed-off-by: Borislav Petkov --- drivers/acpi/acpi_extlog.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index a6869e110ce5..5d33c5415405 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,8 @@ struct extlog_l1_head { u8 rev1[12]; }; +static int old_edac_report_status; + static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295"; /* L1 table related physical address */ @@ -150,7 +153,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); - return NOTIFY_DONE; + return NOTIFY_STOP; } static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret) @@ -231,8 +234,12 @@ static int __init extlog_init(void) u64 cap; int rc; - rc = -ENODEV; + if (get_edac_report_status() == EDAC_REPORTING_FORCE) { + pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n"); + return -EPERM; + } + rc = -ENODEV; rdmsrl(MSR_IA32_MCG_CAP, cap); if (!(cap & MCG_ELOG_P)) return rc; @@ -287,6 +294,12 @@ static int __init extlog_init(void) if (elog_buf == NULL) goto err_release_elog; + /* + * eMCA event report method has higher priority than EDAC method, + * unless EDAC event report method is mandatory. + */ + old_edac_report_status = get_edac_report_status(); + set_edac_report_status(EDAC_REPORTING_DISABLED); mce_register_decode_chain(&extlog_mce_dec); /* enable OS to be involved to take over management from BIOS */ ((struct extlog_l1_head *)extlog_l1_addr)->flags |= FLAG_OS_OPTIN; @@ -308,6 +321,7 @@ err: static void __exit extlog_exit(void) { + set_edac_report_status(old_edac_report_status); mce_unregister_decode_chain(&extlog_mce_dec); ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; if (extlog_l1_addr) -- cgit v1.2.3 From d469962f858b71ec43112c256e3df4a60b00beeb Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 11 Dec 2013 07:44:14 +0100 Subject: bgmac: reset cached MAC state during chip reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this bgmac_adjust_link didn't know it should re-initialize MAC state. This led to the MAC not working after if down & up routine. Signed-off-by: Rafał Miłecki Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index fd6a22e3dd75..273b9f97da49 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -953,6 +953,8 @@ static void bgmac_chip_reset(struct bgmac *bgmac) BGMAC_CMDCFG_CFE | BGMAC_CMDCFG_SR, false); + bgmac->mac_speed = SPEED_UNKNOWN; + bgmac->mac_duplex = DUPLEX_UNKNOWN; bgmac_clear_mib(bgmac); if (core->id.id == BCMA_CORE_4706_MAC_GBIT) -- cgit v1.2.3 From 1a0ab7675d27542ab30f2fc6af8c3385cc7f708e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 11 Dec 2013 08:44:37 +0100 Subject: bgmac: replace some magic values with defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 21 +++++++++++++-------- drivers/net/ethernet/broadcom/bgmac.h | 6 +++++- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 273b9f97da49..b665a6aa7e14 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -877,9 +877,9 @@ static void bgmac_chip_reset(struct bgmac *bgmac) } iost = bcma_aread32(core, BCMA_IOST); - if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 10) || + if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) || (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) || - (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9)) + (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) iost &= ~BGMAC_BCMA_IOST_ATTACHED; if (iost & BGMAC_BCMA_IOST_ATTACHED) { @@ -891,12 +891,16 @@ static void bgmac_chip_reset(struct bgmac *bgmac) bcma_core_enable(core, flags); if (core->id.rev > 2) { - bgmac_set(bgmac, BCMA_CLKCTLST, 1 << 8); - bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, 1 << 24, 1 << 24, + bgmac_set(bgmac, BCMA_CLKCTLST, + BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ); + bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, + BGMAC_BCMA_CLKCTLST_MISC_PLL_ST, + BGMAC_BCMA_CLKCTLST_MISC_PLL_ST, 1000); } - if (ci->id == BCMA_CHIP_ID_BCM5357 || ci->id == BCMA_CHIP_ID_BCM4749 || + if (ci->id == BCMA_CHIP_ID_BCM5357 || + ci->id == BCMA_CHIP_ID_BCM4749 || ci->id == BCMA_CHIP_ID_BCM53572) { struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc; u8 et_swtype = 0; @@ -911,10 +915,11 @@ static void bgmac_chip_reset(struct bgmac *bgmac) et_swtype &= 0x0f; et_swtype <<= 4; sw_type = et_swtype; - } else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 9) { + } else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358) { sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII; - } else if ((ci->id != BCMA_CHIP_ID_BCM53572 && ci->pkg == 10) || - (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9)) { + } else if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) || + (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) || + (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) { sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII | BGMAC_CHIPCTL_1_SW_TYPE_RGMII; } diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h index 550f2a8e85a9..2d44119a7648 100644 --- a/drivers/net/ethernet/broadcom/bgmac.h +++ b/drivers/net/ethernet/broadcom/bgmac.h @@ -95,7 +95,11 @@ #define BGMAC_RXQ_CTL_MDP_SHIFT 24 #define BGMAC_GPIO_SELECT 0x194 #define BGMAC_GPIO_OUTPUT_EN 0x198 -/* For 0x1e0 see BCMA_CLKCTLST */ + +/* For 0x1e0 see BCMA_CLKCTLST. Below are BGMAC specific bits */ +#define BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ 0x00000100 +#define BGMAC_BCMA_CLKCTLST_MISC_PLL_ST 0x01000000 + #define BGMAC_HW_WAR 0x1e4 #define BGMAC_PWR_CTL 0x1e8 #define BGMAC_DMA_BASE0 0x200 /* Tx and Rx controller */ -- cgit v1.2.3 From 2306bfb208b9c403592a0513b08f2e6ad53056d5 Mon Sep 17 00:00:00 2001 From: Eric Seppanen Date: Thu, 21 Nov 2013 14:49:56 -0800 Subject: iscsi-target: return -EINVAL on oversized configfs parameter The iSCSI CHAP auth parameters are already copied with respect for the destination buffer size. Return -EINVAL instead of silently truncating the input. Signed-off-by: Eric Seppanen Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index e3318edb233d..1c0088fe9e99 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -474,7 +474,8 @@ static ssize_t __iscsi_##prefix##_store_##name( \ \ if (!capable(CAP_SYS_ADMIN)) \ return -EPERM; \ - \ + if (count >= sizeof(auth->name)) \ + return -EINVAL; \ snprintf(auth->name, sizeof(auth->name), "%s", page); \ if (!strncmp("NULL", auth->name, 4)) \ auth->naf_flags &= ~flags; \ -- cgit v1.2.3 From a51d5229d10dd3a337b674ce8603437d2996c5c3 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sat, 23 Nov 2013 10:35:58 -0800 Subject: target: Remove write-only stats fields and lock from struct se_node_acl Commit 04f3b31bff72 ("iscsi-target: Convert iscsi_session statistics to atomic_long_t") removed the updating of these fields in iscsi (the only fabric driver that ever touched these counters), and the core has no way to report or otherwise use the values. Remove the last remnants of these counters. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tpg.c | 2 -- include/target/target_core_base.h | 4 ---- 2 files changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index f697f8baec54..f755712a9a0d 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -278,7 +278,6 @@ struct se_node_acl *core_tpg_check_initiator_node_acl( snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); acl->se_tpg = tpg; acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); - spin_lock_init(&acl->stats_lock); acl->dynamic_node_acl = 1; tpg->se_tpg_tfo->set_default_node_attributes(acl); @@ -406,7 +405,6 @@ struct se_node_acl *core_tpg_add_initiator_node_acl( snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); acl->se_tpg = tpg; acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); - spin_lock_init(&acl->stats_lock); tpg->se_tpg_tfo->set_default_node_attributes(acl); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 45412a6afa69..9f1dda659c5a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -517,10 +517,6 @@ struct se_node_acl { u32 acl_index; #define MAX_ACL_TAG_SIZE 64 char acl_tag[MAX_ACL_TAG_SIZE]; - u64 num_cmds; - u64 read_bytes; - u64 write_bytes; - spinlock_t stats_lock; /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ atomic_t acl_pr_ref_count; struct se_dev_entry **device_list; -- cgit v1.2.3 From 4454b66cb67f14c33cd70ddcf0ff4985b26324b7 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 25 Nov 2013 14:53:57 -0800 Subject: iscsi-target: Fix-up all zero data-length CDBs with R/W_BIT set This patch changes special case handling for ISCSI_OP_SCSI_CMD where an initiator sends a zero length Expected Data Transfer Length (EDTL), but still sets the WRITE and/or READ flag bits when no payload transfer is requested. Many, many moons ago two special cases where added for an ancient version of ESX that has long since been fixed, so instead of adding a new special case for the reported bug with a Broadcom 57800 NIC, go ahead and always strip off the incorrect WRITE + READ flag bits. Also, avoid sending a reject here, as RFC-3720 does mandate this case be handled without protocol error. Reported-by: Witold Bazakbal <865perl@wp.pl> Tested-by: Witold Bazakbal <865perl@wp.pl> Cc: #3.1+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d70e9119e906..02182ab017b1 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -823,24 +823,22 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (((hdr->flags & ISCSI_FLAG_CMD_READ) || (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) { /* - * Vmware ESX v3.0 uses a modified Cisco Initiator (v3.4.2) - * that adds support for RESERVE/RELEASE. There is a bug - * add with this new functionality that sets R/W bits when - * neither CDB carries any READ or WRITE datapayloads. + * From RFC-3720 Section 10.3.1: + * + * "Either or both of R and W MAY be 1 when either the + * Expected Data Transfer Length and/or Bidirectional Read + * Expected Data Transfer Length are 0" + * + * For this case, go ahead and clear the unnecssary bits + * to avoid any confusion with ->data_direction. */ - if ((hdr->cdb[0] == 0x16) || (hdr->cdb[0] == 0x17)) { - hdr->flags &= ~ISCSI_FLAG_CMD_READ; - hdr->flags &= ~ISCSI_FLAG_CMD_WRITE; - goto done; - } + hdr->flags &= ~ISCSI_FLAG_CMD_READ; + hdr->flags &= ~ISCSI_FLAG_CMD_WRITE; - pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" + pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" " set when Expected Data Transfer Length is 0 for" - " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); - return iscsit_add_reject_cmd(cmd, - ISCSI_REASON_BOOKMARK_INVALID, buf); + " CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]); } -done: if (!(hdr->flags & ISCSI_FLAG_CMD_READ) && !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) { -- cgit v1.2.3 From 79d4a94fab0a9cc1b55db45a98277a68ff1febd8 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Tue, 10 Dec 2013 16:37:32 +0800 Subject: vxlan: remove vxlan_group_used in vxlan_open In vxlan_open, vxlan_group_used always returns true, because the state of the vxlan deivces which we want to open has alreay been running. and it has already in vxlan_list. Since ip_mc_join_group takes care of the reference of struct ip_mc_list. removing vxlan_group_used here is safe. Signed-off-by: Gao feng Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 0358c07f7669..43dc9ee4758f 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1935,7 +1935,6 @@ static void vxlan_uninit(struct net_device *dev) /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) { - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_sock *vs = vxlan->vn_sock; @@ -1943,8 +1942,7 @@ static int vxlan_open(struct net_device *dev) if (!vs) return -ENOTCONN; - if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && - vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) { + if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { vxlan_sock_hold(vs); dev_hold(dev); queue_work(vxlan_wq, &vxlan->igmp_join); -- cgit v1.2.3 From 95ab09917a8187a02b518e22587c7f035edc7465 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Tue, 10 Dec 2013 16:37:33 +0800 Subject: vxlan: leave multicast group when vxlan device down vxlan_group_used only allows device to leave multicast group when the remote_ip of this vxlan device is difference from other vxlan devices' remote_ip. this will cause device not leave multicast group untile the vn_sock of this vxlan deivce being released. The check in vxlan_group_used is not quite precise. since even the remote_ip is same, but these vxlan devices may use different lower devices, and they may use different vn_socks. Only when some vxlan devices use the same vn_sock,same lower device and same remote_ip, the mc_list of the vn_sock should not be changed. Signed-off-by: Gao feng Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 43dc9ee4758f..58f6a0c02b17 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -916,17 +916,32 @@ static bool vxlan_snoop(struct net_device *dev, } /* See if multicast group is already in use by other ID */ -static bool vxlan_group_used(struct vxlan_net *vn, union vxlan_addr *remote_ip) +static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev) { struct vxlan_dev *vxlan; + /* The vxlan_sock is only used by dev, leaving group has + * no effect on other vxlan devices. + */ + if (atomic_read(&dev->vn_sock->refcnt) == 1) + return false; + list_for_each_entry(vxlan, &vn->vxlan_list, next) { - if (!netif_running(vxlan->dev)) + if (!netif_running(vxlan->dev) || vxlan == dev) continue; - if (vxlan_addr_equal(&vxlan->default_dst.remote_ip, - remote_ip)) - return true; + if (vxlan->vn_sock != dev->vn_sock) + continue; + + if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip, + &dev->default_dst.remote_ip)) + continue; + + if (vxlan->default_dst.remote_ifindex != + dev->default_dst.remote_ifindex) + continue; + + return true; } return false; @@ -1981,7 +1996,7 @@ static int vxlan_stop(struct net_device *dev) struct vxlan_sock *vs = vxlan->vn_sock; if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && - ! vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) { + !vxlan_group_used(vn, vxlan)) { vxlan_sock_hold(vs); dev_hold(dev); queue_work(vxlan_wq, &vxlan->igmp_leave); -- cgit v1.2.3 From b601fa197fff265bf60eaf6950d4c194da080f4a Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 10 Dec 2013 15:02:40 +0100 Subject: ipv4: fix wildcard search with inet_confirm_addr() Help of this function says: "in_dev: only on this interface, 0=any interface", but since commit 39a6d0630012 ("[NETNS]: Process inet_confirm_addr in the correct namespace."), the code supposes that it will never be NULL. This function is never called with in_dev == NULL, but it's exported and may be used by an external module. Because this patch restore the ability to call inet_confirm_addr() with in_dev == NULL, I partially revert the above commit, as suggested by Julian. CC: Julian Anastasov Signed-off-by: Nicolas Dichtel Reviewed-by: Julian Anastasov Signed-off-by: David S. Miller --- drivers/net/bonding/bonding.h | 4 ++-- include/linux/inetdevice.h | 5 ++--- net/ipv4/arp.c | 4 +++- net/ipv4/devinet.c | 9 ++++----- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index a9f4f9f4d8ce..a74c92c83ead 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -394,8 +394,8 @@ static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be3 in_dev = __in_dev_get_rcu(dev); if (in_dev) - addr = inet_confirm_addr(in_dev, dst, local, RT_SCOPE_HOST); - + addr = inet_confirm_addr(dev_net(dev), in_dev, dst, local, + RT_SCOPE_HOST); rcu_read_unlock(); return addr; } diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 562e5c7c5d35..0068708161ff 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -164,11 +164,10 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *); void devinet_init(void); struct in_device *inetdev_by_index(struct net *, int); __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); -__be32 inet_confirm_addr(struct in_device *in_dev, __be32 dst, __be32 local, - int scope); +__be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, __be32 dst, + __be32 local, int scope); struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask); - static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa) { return !((addr^ifa->ifa_address)&ifa->ifa_mask); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index f04185863940..b67cf805910e 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -381,6 +381,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) { + struct net *net = dev_net(in_dev->dev); int scope; switch (IN_DEV_ARP_IGNORE(in_dev)) { @@ -399,6 +400,7 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) case 3: /* Do not reply for scope host addresses */ sip = 0; scope = RT_SCOPE_LINK; + in_dev = NULL; break; case 4: /* Reserved */ case 5: @@ -410,7 +412,7 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) default: return 0; } - return !inet_confirm_addr(in_dev, sip, tip, scope); + return !inet_confirm_addr(net, in_dev, sip, tip, scope); } static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 6f49efc9d4b7..84956f5f0135 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1240,22 +1240,21 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, /* * Confirm that local IP address exists using wildcards: - * - in_dev: only on this interface, 0=any interface + * - net: netns to check, cannot be NULL + * - in_dev: only on this interface, NULL=any interface * - dst: only in the same subnet as dst, 0=any dst * - local: address, 0=autoselect the local address * - scope: maximum allowed scope value for the local address */ -__be32 inet_confirm_addr(struct in_device *in_dev, +__be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, __be32 dst, __be32 local, int scope) { __be32 addr = 0; struct net_device *dev; - struct net *net; - if (scope != RT_SCOPE_LINK) + if (in_dev != NULL) return confirm_addr_indev(in_dev, dst, local, scope); - net = dev_net(in_dev->dev); rcu_read_lock(); for_each_netdev_rcu(net, dev) { in_dev = __in_dev_get_rcu(dev); -- cgit v1.2.3 From 94a7111043d99819cd0a72d9b3174c7054adb2a0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 29 Oct 2013 09:56:34 +0800 Subject: iser-target: fix error return code in isert_create_device_ib_res() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Cc: #3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 6be57c38638d..78f6e92c571f 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -264,21 +264,29 @@ isert_create_device_ib_res(struct isert_device *device) isert_cq_event_callback, (void *)&cq_desc[i], ISER_MAX_RX_CQ_LEN, i); - if (IS_ERR(device->dev_rx_cq[i])) + if (IS_ERR(device->dev_rx_cq[i])) { + ret = PTR_ERR(device->dev_rx_cq[i]); + device->dev_rx_cq[i] = NULL; goto out_cq; + } device->dev_tx_cq[i] = ib_create_cq(device->ib_device, isert_cq_tx_callback, isert_cq_event_callback, (void *)&cq_desc[i], ISER_MAX_TX_CQ_LEN, i); - if (IS_ERR(device->dev_tx_cq[i])) + if (IS_ERR(device->dev_tx_cq[i])) { + ret = PTR_ERR(device->dev_tx_cq[i]); + device->dev_tx_cq[i] = NULL; goto out_cq; + } - if (ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP)) + ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP); + if (ret) goto out_cq; - if (ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP)) + ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP); + if (ret) goto out_cq; } -- cgit v1.2.3 From c45f812f0280c13f1b7992be5e0de512312a9e8f Mon Sep 17 00:00:00 2001 From: Matthew Whitehead Date: Wed, 11 Dec 2013 17:00:59 -0500 Subject: 8390 : Replace ei_debug with msg_enable/NETIF_MSG_* feature Removed the shared ei_debug variable. Replaced it by adding u32 msg_enable to the private struct ei_device. Now each 8390 ethernet instance has a per-device logging variable. Changed older style printk() calls to more canonical forms. Tested on: ne, ne2k-pci, smc-ultra, and wd hardware. V4.0 - Substituted pr_info() and pr_debug() for printk() KERN_INFO and KERN_DEBUG V3.0 - Checked for cases where pr_cont() was most appropriate choice. - Changed module parameter from 'debug' to 'msg_enable' because debug was no longer the best description. V2.0 - Changed netif_msg_(drv|probe|ifdown|rx_err|tx_err|tx_queued|intr|rx_status|hw) to netif_(dbg|info|warn|err) where possible. Signed-off-by: Matthew Whitehead Signed-off-by: David S. Miller --- drivers/net/ethernet/8390/8390.h | 7 +- drivers/net/ethernet/8390/apne.c | 62 ++++++++++-------- drivers/net/ethernet/8390/ax88796.c | 22 ++++++- drivers/net/ethernet/8390/axnet_cs.c | 119 ++++++++++++++++------------------ drivers/net/ethernet/8390/etherh.c | 51 +++++++++------ drivers/net/ethernet/8390/hydra.c | 11 +++- drivers/net/ethernet/8390/lib8390.c | 77 ++++++++++++---------- drivers/net/ethernet/8390/mac8390.c | 19 ++++-- drivers/net/ethernet/8390/mcf8390.c | 8 ++- drivers/net/ethernet/8390/ne.c | 96 +++++++++++++++------------ drivers/net/ethernet/8390/ne2k-pci.c | 54 ++++++++++----- drivers/net/ethernet/8390/pcnet_cs.c | 62 ++++++++++-------- drivers/net/ethernet/8390/smc-ultra.c | 48 ++++++++------ drivers/net/ethernet/8390/stnic.c | 28 +++++--- drivers/net/ethernet/8390/wd.c | 42 +++++++----- drivers/net/ethernet/8390/zorro8390.c | 22 +++++-- 16 files changed, 426 insertions(+), 302 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/8390/8390.h b/drivers/net/ethernet/8390/8390.h index 2923c51bb351..3e2f2c2e7b58 100644 --- a/drivers/net/ethernet/8390/8390.h +++ b/drivers/net/ethernet/8390/8390.h @@ -21,12 +21,6 @@ struct e8390_pkt_hdr { unsigned short count; /* header + packet length in bytes */ }; -#ifdef notdef -extern int ei_debug; -#else -#define ei_debug 1 -#endif - #ifdef CONFIG_NET_POLL_CONTROLLER void ei_poll(struct net_device *dev); void eip_poll(struct net_device *dev); @@ -99,6 +93,7 @@ struct ei_device { u32 *reg_offset; /* Register mapping table */ spinlock_t page_lock; /* Page register locks */ unsigned long priv; /* Private field to store bus IDs etc. */ + u32 msg_enable; /* debug message level */ #ifdef AX88796_PLATFORM unsigned char rxcr_base; /* default value for RXCR */ #endif diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c index 912ed7a5f33a..811fa5d5c697 100644 --- a/drivers/net/ethernet/8390/apne.c +++ b/drivers/net/ethernet/8390/apne.c @@ -116,9 +116,15 @@ static const char version[] = static int apne_owned; /* signal if card already owned */ +static u32 apne_msg_enable; +module_param_named(msg_enable, apne_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); + struct net_device * __init apne_probe(int unit) { struct net_device *dev; + struct ei_device *ei_local; + #ifndef MANUAL_CONFIG char tuple[8]; #endif @@ -133,11 +139,11 @@ struct net_device * __init apne_probe(int unit) if ( !(AMIGAHW_PRESENT(PCMCIA)) ) return ERR_PTR(-ENODEV); - printk("Looking for PCMCIA ethernet card : "); + pr_info("Looking for PCMCIA ethernet card : "); /* check if a card is inserted */ if (!(PCMCIA_INSERTED)) { - printk("NO PCMCIA card inserted\n"); + pr_cont("NO PCMCIA card inserted\n"); return ERR_PTR(-ENODEV); } @@ -148,6 +154,8 @@ struct net_device * __init apne_probe(int unit) sprintf(dev->name, "eth%d", unit); netdev_boot_setup_check(dev); } + ei_local = netdev_priv(dev); + ei_local->msg_enable = apne_msg_enable; /* disable pcmcia irq for readtuple */ pcmcia_disable_irq(); @@ -155,14 +163,14 @@ struct net_device * __init apne_probe(int unit) #ifndef MANUAL_CONFIG if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) || (tuple[2] != CISTPL_FUNCID_NETWORK)) { - printk("not an ethernet card\n"); + pr_cont("not an ethernet card\n"); /* XXX: shouldn't we re-enable irq here? */ free_netdev(dev); return ERR_PTR(-ENODEV); } #endif - printk("ethernet PCMCIA card inserted\n"); + pr_cont("ethernet PCMCIA card inserted\n"); if (!init_pcmcia()) { /* XXX: shouldn't we re-enable irq here? */ @@ -204,11 +212,12 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) int neX000, ctron; #endif static unsigned version_printed; + struct ei_device *ei_local = netdev_priv(dev); - if (ei_debug && version_printed++ == 0) - printk(version); + if ((apne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0)) + netdev_info(dev, version); - printk("PCMCIA NE*000 ethercard probe"); + netdev_info(dev, "PCMCIA NE*000 ethercard probe"); /* Reset card. Who knows what dain-bramaged state it was left in. */ { unsigned long reset_start_time = jiffies; @@ -217,7 +226,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) if (time_after(jiffies, reset_start_time + 2*HZ/100)) { - printk(" not found (no reset ack).\n"); + pr_cont(" not found (no reset ack).\n"); return -ENODEV; } @@ -288,7 +297,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) start_page = 0x01; stop_page = (wordlength == 2) ? 0x40 : 0x20; } else { - printk(" not found.\n"); + pr_cont(" not found.\n"); return -ENXIO; } @@ -320,9 +329,9 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) for (i = 0; i < ETH_ALEN; i++) dev->dev_addr[i] = SA_prom[i]; - printk(" %pM\n", dev->dev_addr); + pr_cont(" %pM\n", dev->dev_addr); - printk("%s: %s found.\n", dev->name, name); + netdev_info(dev, "%s found.\n", name); ei_status.name = name; ei_status.tx_start_page = start_page; @@ -352,10 +361,11 @@ static void apne_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; + struct ei_device *ei_local = netdev_priv(dev); init_pcmcia(); - if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies); + netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies); outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); @@ -365,8 +375,8 @@ apne_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0) if (time_after(jiffies, reset_start_time + 2*HZ/100)) { - printk("%s: ne_reset_8390() did not complete.\n", dev->name); - break; + netdev_err(dev, "ne_reset_8390() did not complete.\n"); + break; } outb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */ } @@ -386,9 +396,9 @@ apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_pa /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); + netdev_err(dev, "DMAing conflict in ne_get_8390_hdr " + "[DMAstat:%d][irqlock:%d][intr:%d].\n", + ei_status.dmaing, ei_status.irqlock, dev->irq); return; } @@ -433,9 +443,9 @@ apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int rin /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); + netdev_err(dev, "DMAing conflict in ne_block_input " + "[DMAstat:%d][irqlock:%d][intr:%d].\n", + ei_status.dmaing, ei_status.irqlock, dev->irq); return; } ei_status.dmaing |= 0x01; @@ -481,9 +491,9 @@ apne_block_output(struct net_device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d][intr:%d]\n", - dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); + netdev_err(dev, "DMAing conflict in ne_block_output." + "[DMAstat:%d][irqlock:%d][intr:%d]\n", + ei_status.dmaing, ei_status.irqlock, dev->irq); return; } ei_status.dmaing |= 0x01; @@ -513,7 +523,7 @@ apne_block_output(struct net_device *dev, int count, while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ - printk("%s: timeout waiting for Tx RDC.\n", dev->name); + netdev_warn(dev, "timeout waiting for Tx RDC.\n"); apne_reset_8390(dev); NS8390_init(dev,1); break; @@ -536,8 +546,8 @@ static irqreturn_t apne_interrupt(int irq, void *dev_id) pcmcia_ack_int(pcmcia_intreq); return IRQ_NONE; } - if (ei_debug > 3) - printk("pcmcia intreq = %x\n", pcmcia_intreq); + if (apne_msg_enable & NETIF_MSG_INTR) + pr_debug("pcmcia intreq = %x\n", pcmcia_intreq); pcmcia_disable_irq(); /* to get rid of the sti() within ei_interrupt */ ei_interrupt(irq, dev_id); pcmcia_ack_int(pcmcia_get_intreq()); diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index 36fa577970bb..8ed5b34d7553 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -78,6 +78,8 @@ static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electron #define AX_GPOC_PPDSET BIT(6) +static u32 ax_msg_enable; + /* device private data */ struct ax_device { @@ -147,8 +149,7 @@ static void ax_reset_8390(struct net_device *dev) unsigned long reset_start_time = jiffies; void __iomem *addr = (void __iomem *)dev->base_addr; - if (ei_debug > 1) - netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies); + netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies); ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET); @@ -496,12 +497,28 @@ static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return phy_ethtool_sset(phy_dev, cmd); } +static u32 ax_get_msglevel(struct net_device *dev) +{ + struct ei_device *ei_local = netdev_priv(dev); + + return ei_local->msg_enable; +} + +static void ax_set_msglevel(struct net_device *dev, u32 v) +{ + struct ei_device *ei_local = netdev_priv(dev); + + ei_local->msg_enable = v; +} + static const struct ethtool_ops ax_ethtool_ops = { .get_drvinfo = ax_get_drvinfo, .get_settings = ax_get_settings, .set_settings = ax_set_settings, .get_link = ethtool_op_get_link, .get_ts_info = ethtool_op_get_ts_info, + .get_msglevel = ax_get_msglevel, + .set_msglevel = ax_set_msglevel, }; #ifdef CONFIG_AX88796_93CX6 @@ -763,6 +780,7 @@ static int ax_init_dev(struct net_device *dev) ei_local->block_output = &ax_block_output; ei_local->get_8390_hdr = &ax_get_8390_hdr; ei_local->priv = 0; + ei_local->msg_enable = ax_msg_enable; dev->netdev_ops = &ax_netdev_ops; dev->ethtool_ops = &ax_ethtool_ops; diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c index d801c1410fb0..5698a4c85d8e 100644 --- a/drivers/net/ethernet/8390/axnet_cs.c +++ b/drivers/net/ethernet/8390/axnet_cs.c @@ -105,6 +105,7 @@ static void AX88190_init(struct net_device *dev, int startp); static int ax_open(struct net_device *dev); static int ax_close(struct net_device *dev); static irqreturn_t ax_interrupt(int irq, void *dev_id); +static u32 axnet_msg_enable; /*====================================================================*/ @@ -152,6 +153,7 @@ static int axnet_probe(struct pcmcia_device *link) return -ENOMEM; ei_local = netdev_priv(dev); + ei_local->msg_enable = axnet_msg_enable; spin_lock_init(&ei_local->page_lock); info = PRIV(dev); @@ -650,11 +652,12 @@ static void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) { unsigned int nic_base = dev->base_addr; + struct ei_device *ei_local = netdev_priv(dev); int xfer_count = count; char *buf = skb->data; - if ((ei_debug > 4) && (count != 4)) - pr_debug("%s: [bi=%d]\n", dev->name, count+4); + if ((netif_msg_rx_status(ei_local)) && (count != 4)) + netdev_dbg(dev, "[bi=%d]\n", count+4); outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD); @@ -810,11 +813,6 @@ module_pcmcia_driver(axnet_cs_driver); #define ei_block_input (ei_local->block_input) #define ei_get_8390_hdr (ei_local->get_8390_hdr) -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef ei_debug -int ei_debug = 1; -#endif - /* Index to functions. */ static void ei_tx_intr(struct net_device *dev); static void ei_tx_err(struct net_device *dev); @@ -925,11 +923,10 @@ static void axnet_tx_timeout(struct net_device *dev) isr = inb(e8390_base+EN0_ISR); spin_unlock_irqrestore(&ei_local->page_lock, flags); - netdev_printk(KERN_DEBUG, dev, - "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", - (txsr & ENTSR_ABT) ? "excess collisions." : - (isr) ? "lost interrupt?" : "cable problem?", - txsr, isr, tickssofar); + netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", + (txsr & ENTSR_ABT) ? "excess collisions." : + (isr) ? "lost interrupt?" : "cable problem?", + txsr, isr, tickssofar); if (!isr && !dev->stats.tx_packets) { @@ -998,29 +995,30 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, { output_page = ei_local->tx_start_page; ei_local->tx1 = send_length; - if (ei_debug && ei_local->tx2 > 0) - netdev_printk(KERN_DEBUG, dev, - "idle transmitter tx2=%d, lasttx=%d, txing=%d\n", - ei_local->tx2, ei_local->lasttx, - ei_local->txing); + if ((netif_msg_tx_queued(ei_local)) && + ei_local->tx2 > 0) + netdev_dbg(dev, + "idle transmitter tx2=%d, lasttx=%d, txing=%d\n", + ei_local->tx2, ei_local->lasttx, + ei_local->txing); } else if (ei_local->tx2 == 0) { output_page = ei_local->tx_start_page + TX_PAGES/2; ei_local->tx2 = send_length; - if (ei_debug && ei_local->tx1 > 0) - netdev_printk(KERN_DEBUG, dev, - "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n", - ei_local->tx1, ei_local->lasttx, - ei_local->txing); + if ((netif_msg_tx_queued(ei_local)) && + ei_local->tx1 > 0) + netdev_dbg(dev, + "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n", + ei_local->tx1, ei_local->lasttx, + ei_local->txing); } else { /* We should never get here. */ - if (ei_debug) - netdev_printk(KERN_DEBUG, dev, - "No Tx buffers free! tx1=%d tx2=%d last=%d\n", - ei_local->tx1, ei_local->tx2, - ei_local->lasttx); + netif_dbg(ei_local, tx_err, dev, + "No Tx buffers free! tx1=%d tx2=%d last=%d\n", + ei_local->tx1, ei_local->tx2, + ei_local->lasttx); ei_local->irqlock = 0; netif_stop_queue(dev); outb_p(ENISR_ALL, e8390_base + EN0_IMR); @@ -1124,10 +1122,9 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&ei_local->page_lock, flags); return IRQ_NONE; } - - if (ei_debug > 3) - netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n", - inb_p(e8390_base + EN0_ISR)); + + netif_dbg(ei_local, intr, dev, "interrupt(isr=%#2.2x)\n", + inb_p(e8390_base + EN0_ISR)); outb_p(0x00, e8390_base + EN0_ISR); ei_local->irqlock = 1; @@ -1137,9 +1134,8 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id) ++nr_serviced < MAX_SERVICE) { if (!netif_running(dev) || (interrupts == 0xff)) { - if (ei_debug > 1) - netdev_warn(dev, - "interrupt from stopped card\n"); + netif_warn(ei_local, intr, dev, + "interrupt from stopped card\n"); outb_p(interrupts, e8390_base + EN0_ISR); interrupts = 0; break; @@ -1175,14 +1171,15 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id) } } - if (interrupts && ei_debug > 3) + if (interrupts && (netif_msg_intr(ei_local))) { handled = 1; if (nr_serviced >= MAX_SERVICE) { /* 0xFF is valid for a card removal */ - if(interrupts!=0xFF) - netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n", + if (interrupts != 0xFF) + netdev_warn(dev, + "Too much work at interrupt, status %#2.2x\n", interrupts); outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ } else { @@ -1221,8 +1218,7 @@ static void ei_tx_err(struct net_device *dev) unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); #ifdef VERBOSE_ERROR_DUMP - netdev_printk(KERN_DEBUG, dev, - "transmitter error (%#2x):", txsr); + netdev_dbg(dev, "transmitter error (%#2x):", txsr); if (txsr & ENTSR_ABT) pr_cont(" excess-collisions"); if (txsr & ENTSR_ND) @@ -1287,9 +1283,9 @@ static void ei_tx_intr(struct net_device *dev) else if (ei_local->tx2 < 0) { if (ei_local->lasttx != 2 && ei_local->lasttx != -2) - netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n", - ei_local->name, ei_local->lasttx, - ei_local->tx2); + netdev_err(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n", + ei_local->name, ei_local->lasttx, + ei_local->tx2); ei_local->tx2 = 0; if (ei_local->tx1 > 0) { @@ -1366,9 +1362,11 @@ static void ei_receive(struct net_device *dev) Keep quiet if it looks like a card removal. One problem here is that some clones crash in roughly the same way. */ - if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF)) - netdev_err(dev, "mismatched read page pointers %2x vs %2x\n", - this_frame, ei_local->current_page); + if ((netif_msg_rx_err(ei_local)) && + this_frame != ei_local->current_page && + (this_frame != 0x0 || rxing_page != 0xFF)) + netdev_err(dev, "mismatched read page pointers %2x vs %2x\n", + this_frame, ei_local->current_page); if (this_frame == rxing_page) /* Read all the frames? */ break; /* Done for now */ @@ -1383,11 +1381,10 @@ static void ei_receive(struct net_device *dev) if (pkt_len < 60 || pkt_len > 1518) { - if (ei_debug) - netdev_printk(KERN_DEBUG, dev, - "bogus packet size: %d, status=%#2x nxpg=%#2x\n", - rx_frame.count, rx_frame.status, - rx_frame.next); + netif_err(ei_local, rx_err, dev, + "bogus packet size: %d, status=%#2x nxpg=%#2x\n", + rx_frame.count, rx_frame.status, + rx_frame.next); dev->stats.rx_errors++; dev->stats.rx_length_errors++; } @@ -1398,10 +1395,9 @@ static void ei_receive(struct net_device *dev) skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { - if (ei_debug > 1) - netdev_printk(KERN_DEBUG, dev, - "Couldn't allocate a sk_buff of size %d\n", - pkt_len); + netif_err(ei_local, rx_err, dev, + "Couldn't allocate a sk_buff of size %d\n", + pkt_len); dev->stats.rx_dropped++; break; } @@ -1420,11 +1416,10 @@ static void ei_receive(struct net_device *dev) } else { - if (ei_debug) - netdev_printk(KERN_DEBUG, dev, - "bogus packet: status=%#2x nxpg=%#2x size=%d\n", - rx_frame.status, rx_frame.next, - rx_frame.count); + netif_err(ei_local, rx_err, dev, + "bogus packet: status=%#2x nxpg=%#2x size=%d\n", + rx_frame.status, rx_frame.next, + rx_frame.count); dev->stats.rx_errors++; /* NB: The NIC counts CRC, frame and missed errors. */ if (pkt_stat & ENRSR_FO) @@ -1461,6 +1456,7 @@ static void ei_rx_overrun(struct net_device *dev) axnet_dev_t *info = PRIV(dev); long e8390_base = dev->base_addr; unsigned char was_txing, must_resend = 0; + struct ei_device *ei_local = netdev_priv(dev); /* * Record whether a Tx was in progress and then issue the @@ -1468,9 +1464,8 @@ static void ei_rx_overrun(struct net_device *dev) */ was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS; outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - - if (ei_debug > 1) - netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n"); + + netif_dbg(ei_local, rx_err, dev, "Receiver overrun\n"); dev->stats.rx_over_errors++; /* diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c index 78c6fb4b1143..b15e482a7c63 100644 --- a/drivers/net/ethernet/8390/etherh.c +++ b/drivers/net/ethernet/8390/etherh.c @@ -56,9 +56,6 @@ #define ei_inb_p(_p) readb((void __iomem *)_p) #define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p) -#define NET_DEBUG 0 -#define DEBUG_INIT 2 - #define DRV_NAME "etherh" #define DRV_VERSION "1.11" @@ -67,7 +64,7 @@ static char version[] __initdata = #include "lib8390.c" -static unsigned int net_debug = NET_DEBUG; +static u32 etherh_msg_enable; struct etherh_priv { void __iomem *ioc_fast; @@ -317,9 +314,9 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf void __iomem *dma_base, *addr; if (ei_local->dmaing) { - printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " - " DMAstat %d irqlock %d\n", dev->name, - ei_local->dmaing, ei_local->irqlock); + netdev_err(dev, "DMAing conflict in etherh_block_input: " + " DMAstat %d irqlock %d\n", + ei_local->dmaing, ei_local->irqlock); return; } @@ -361,8 +358,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0) if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ - printk(KERN_ERR "%s: timeout waiting for TX RDC\n", - dev->name); + netdev_warn(dev, "timeout waiting for TX RDC\n"); etherh_reset (dev); __NS8390_init (dev, 1); break; @@ -383,9 +379,9 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int void __iomem *dma_base, *addr; if (ei_local->dmaing) { - printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " - " DMAstat %d irqlock %d\n", dev->name, - ei_local->dmaing, ei_local->irqlock); + netdev_err(dev, "DMAing conflict in etherh_block_input: " + " DMAstat %d irqlock %d\n", + ei_local->dmaing, ei_local->irqlock); return; } @@ -423,9 +419,9 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p void __iomem *dma_base, *addr; if (ei_local->dmaing) { - printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: " - " DMAstat %d irqlock %d\n", dev->name, - ei_local->dmaing, ei_local->irqlock); + netdev_err(dev, "DMAing conflict in etherh_get_header: " + " DMAstat %d irqlock %d\n", + ei_local->dmaing, ei_local->irqlock); return; } @@ -513,8 +509,8 @@ static void __init etherh_banner(void) { static int version_printed; - if (net_debug && version_printed++ == 0) - printk(KERN_INFO "%s", version); + if ((etherh_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0)) + pr_info("%s", version); } /* @@ -625,11 +621,27 @@ static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return 0; } +static u32 etherh_get_msglevel(struct net_device *dev) +{ + struct ei_device *ei_local = netdev_priv(dev); + + return ei_local->msg_enable; +} + +static void etherh_set_msglevel(struct net_device *dev, u32 v) +{ + struct ei_device *ei_local = netdev_priv(dev); + + ei_local->msg_enable = v; +} + static const struct ethtool_ops etherh_ethtool_ops = { .get_settings = etherh_get_settings, .set_settings = etherh_set_settings, .get_drvinfo = etherh_get_drvinfo, .get_ts_info = ethtool_op_get_ts_info, + .get_msglevel = etherh_get_msglevel, + .set_msglevel = etherh_set_msglevel, }; static const struct net_device_ops etherh_netdev_ops = { @@ -746,6 +758,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ei_local->block_output = etherh_block_output; ei_local->get_8390_hdr = etherh_get_header; ei_local->interface_num = 0; + ei_local->msg_enable = etherh_msg_enable; etherh_reset(dev); __NS8390_init(dev, 0); @@ -754,8 +767,8 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) if (ret) goto free; - printk(KERN_INFO "%s: %s in slot %d, %pM\n", - dev->name, data->name, ec->slot_no, dev->dev_addr); + netdev_info(dev, "%s in slot %d, %pM\n", + data->name, ec->slot_no, dev->dev_addr); ecard_set_drvdata(ec, dev); diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c index fb3dd4399cf3..d8b86c83dd15 100644 --- a/drivers/net/ethernet/8390/hydra.c +++ b/drivers/net/ethernet/8390/hydra.c @@ -66,6 +66,7 @@ static void hydra_block_input(struct net_device *dev, int count, static void hydra_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); static void hydra_remove_one(struct zorro_dev *z); +static u32 hydra_msg_enable; static struct zorro_device_id hydra_zorro_tbl[] = { { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, @@ -119,6 +120,7 @@ static int hydra_init(struct zorro_dev *z) int start_page, stop_page; int j; int err; + struct ei_device *ei_local; static u32 hydra_offsets[16] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, @@ -137,6 +139,8 @@ static int hydra_init(struct zorro_dev *z) start_page = NESM_START_PG; stop_page = NESM_STOP_PG; + ei_local = netdev_priv(dev); + ei_local->msg_enable = hydra_msg_enable; dev->base_addr = ioaddr; dev->irq = IRQ_AMIGA_PORTS; @@ -187,15 +191,16 @@ static int hydra_open(struct net_device *dev) static int hydra_close(struct net_device *dev) { - if (ei_debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); + struct ei_device *ei_local = netdev_priv(dev); + + netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n"); __ei_close(dev); return 0; } static void hydra_reset_8390(struct net_device *dev) { - printk(KERN_INFO "Hydra hw reset not there\n"); + netdev_info(dev, "Hydra hw reset not there\n"); } static void hydra_get_8390_hdr(struct net_device *dev, diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c index b329f5c0d62b..d2cd80444ade 100644 --- a/drivers/net/ethernet/8390/lib8390.c +++ b/drivers/net/ethernet/8390/lib8390.c @@ -99,11 +99,6 @@ #define ei_block_input (ei_local->block_input) #define ei_get_8390_hdr (ei_local->get_8390_hdr) -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef ei_debug -int ei_debug = 1; -#endif - /* Index to functions. */ static void ei_tx_intr(struct net_device *dev); static void ei_tx_err(struct net_device *dev); @@ -116,6 +111,11 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, static void do_set_multicast_list(struct net_device *dev); static void __NS8390_init(struct net_device *dev, int startp); +static unsigned version_printed; +static u32 msg_enable; +module_param(msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); + /* * SMP and the 8390 setup. * @@ -345,19 +345,23 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb, if (ei_local->tx1 == 0) { output_page = ei_local->tx_start_page; ei_local->tx1 = send_length; - if (ei_debug && ei_local->tx2 > 0) - netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n", + if ((netif_msg_tx_queued(ei_local)) && + ei_local->tx2 > 0) + netdev_dbg(dev, + "idle transmitter tx2=%d, lasttx=%d, txing=%d\n", ei_local->tx2, ei_local->lasttx, ei_local->txing); } else if (ei_local->tx2 == 0) { output_page = ei_local->tx_start_page + TX_PAGES/2; ei_local->tx2 = send_length; - if (ei_debug && ei_local->tx1 > 0) - netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n", + if ((netif_msg_tx_queued(ei_local)) && + ei_local->tx1 > 0) + netdev_dbg(dev, + "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n", ei_local->tx1, ei_local->lasttx, ei_local->txing); } else { /* We should never get here. */ - if (ei_debug) - netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n", - ei_local->tx1, ei_local->tx2, ei_local->lasttx); + netif_dbg(ei_local, tx_err, dev, + "No Tx buffers free! tx1=%d tx2=%d last=%d\n", + ei_local->tx1, ei_local->tx2, ei_local->lasttx); ei_local->irqlock = 0; netif_stop_queue(dev); ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR); @@ -388,7 +392,7 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb, } else ei_local->txqueue++; - if (ei_local->tx1 && ei_local->tx2) + if (ei_local->tx1 && ei_local->tx2) netif_stop_queue(dev); else netif_start_queue(dev); @@ -445,9 +449,8 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id) /* Change to page 0 and read the intr status reg. */ ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); - if (ei_debug > 3) - netdev_dbg(dev, "interrupt(isr=%#2.2x)\n", - ei_inb_p(e8390_base + EN0_ISR)); + netif_dbg(ei_local, intr, dev, "interrupt(isr=%#2.2x)\n", + ei_inb_p(e8390_base + EN0_ISR)); /* !!Assumption!! -- we stay in page 0. Don't break this. */ while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 && @@ -485,7 +488,7 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id) ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); } - if (interrupts && ei_debug) { + if (interrupts && (netif_msg_intr(ei_local))) { ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); if (nr_serviced >= MAX_SERVICE) { /* 0xFF is valid for a card removal */ @@ -676,10 +679,11 @@ static void ei_receive(struct net_device *dev) Keep quiet if it looks like a card removal. One problem here is that some clones crash in roughly the same way. */ - if (ei_debug > 0 && + if ((netif_msg_rx_status(ei_local)) && this_frame != ei_local->current_page && (this_frame != 0x0 || rxing_page != 0xFF)) - netdev_err(dev, "mismatched read page pointers %2x vs %2x\n", + netdev_err(dev, + "mismatched read page pointers %2x vs %2x\n", this_frame, ei_local->current_page); if (this_frame == rxing_page) /* Read all the frames? */ @@ -707,10 +711,10 @@ static void ei_receive(struct net_device *dev) } if (pkt_len < 60 || pkt_len > 1518) { - if (ei_debug) - netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n", - rx_frame.count, rx_frame.status, - rx_frame.next); + netif_dbg(ei_local, rx_status, dev, + "bogus packet size: %d, status=%#2x nxpg=%#2x\n", + rx_frame.count, rx_frame.status, + rx_frame.next); dev->stats.rx_errors++; dev->stats.rx_length_errors++; } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) { @@ -718,9 +722,9 @@ static void ei_receive(struct net_device *dev) skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { - if (ei_debug > 1) - netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n", - pkt_len); + netif_err(ei_local, rx_err, dev, + "Couldn't allocate a sk_buff of size %d\n", + pkt_len); dev->stats.rx_dropped++; break; } else { @@ -736,10 +740,10 @@ static void ei_receive(struct net_device *dev) dev->stats.multicast++; } } else { - if (ei_debug) - netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n", - rx_frame.status, rx_frame.next, - rx_frame.count); + netif_err(ei_local, rx_err, dev, + "bogus packet: status=%#2x nxpg=%#2x size=%d\n", + rx_frame.status, rx_frame.next, + rx_frame.count); dev->stats.rx_errors++; /* NB: The NIC counts CRC, frame and missed errors. */ if (pkt_stat & ENRSR_FO) @@ -789,8 +793,7 @@ static void ei_rx_overrun(struct net_device *dev) was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS; ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - if (ei_debug > 1) - netdev_dbg(dev, "Receiver overrun\n"); + netif_dbg(ei_local, rx_err, dev, "Receiver overrun\n"); dev->stats.rx_over_errors++; /* @@ -965,8 +968,9 @@ static void __ei_set_multicast_list(struct net_device *dev) static void ethdev_setup(struct net_device *dev) { struct ei_device *ei_local = netdev_priv(dev); - if (ei_debug > 1) - printk(version); + + if ((msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0)) + pr_info("%s", version); ether_setup(dev); @@ -1035,9 +1039,10 @@ static void __NS8390_init(struct net_device *dev, int startp) ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ for (i = 0; i < 6; i++) { ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); - if (ei_debug > 1 && + if ((netif_msg_probe(ei_local)) && ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i]) - netdev_err(dev, "Hw. address read/write mismap %d\n", i); + netdev_err(dev, + "Hw. address read/write mismap %d\n", i); } ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index 88ccc8b14f0a..90e825e8abfe 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c @@ -167,6 +167,7 @@ static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); static void word_memcpy_tocard(unsigned long tp, const void *fp, int count); static void word_memcpy_fromcard(void *tp, unsigned long fp, int count); +static u32 mac8390_msg_enable; static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) { @@ -402,6 +403,7 @@ struct net_device * __init mac8390_probe(int unit) struct net_device *dev; struct nubus_dev *ndev = NULL; int err = -ENODEV; + struct ei_device *ei_local; static unsigned int slots; @@ -440,6 +442,10 @@ struct net_device * __init mac8390_probe(int unit) if (!ndev) goto out; + + ei_local = netdev_priv(dev); + ei_local->msg_enable = mac8390_msg_enable; + err = register_netdev(dev); if (err) goto out; @@ -660,19 +666,22 @@ static int mac8390_close(struct net_device *dev) static void mac8390_no_reset(struct net_device *dev) { + struct ei_device *ei_local = netdev_priv(dev); + ei_status.txing = 0; - if (ei_debug > 1) - pr_info("reset not supported\n"); + netif_info(ei_local, hw, dev, "reset not supported\n"); } static void interlan_reset(struct net_device *dev) { unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq)); - if (ei_debug > 1) - pr_info("Need to reset the NS8390 t=%lu...", jiffies); + struct ei_device *ei_local = netdev_priv(dev); + + netif_info(ei_local, hw, dev, "Need to reset the NS8390 t=%lu...", + jiffies); ei_status.txing = 0; target[0xC0000] = 0; - if (ei_debug > 1) + if (netif_msg_hw(ei_local)) pr_cont("reset complete\n"); } diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c index 230efd6fa5d5..df0ffca91c1c 100644 --- a/drivers/net/ethernet/8390/mcf8390.c +++ b/drivers/net/ethernet/8390/mcf8390.c @@ -39,6 +39,7 @@ static const char version[] = #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ +static u32 mcf8390_msg_enable; #ifdef NE2000_ODDOFFSET /* @@ -153,9 +154,9 @@ static void mcf8390_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; u32 addr = dev->base_addr; + struct ei_device *ei_local = netdev_priv(dev); - if (ei_debug > 1) - netdev_dbg(dev, "resetting the 8390 t=%ld...\n", jiffies); + netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies); ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET); @@ -288,7 +289,7 @@ static void mcf8390_block_output(struct net_device *dev, int count, dma_start = jiffies; while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RDC) == 0) { if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */ - netdev_err(dev, "timeout waiting for Tx RDC\n"); + netdev_warn(dev, "timeout waiting for Tx RDC\n"); mcf8390_reset_8390(dev); __NS8390_init(dev, 1); break; @@ -437,6 +438,7 @@ static int mcf8390_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, &pdev->dev); platform_set_drvdata(pdev, dev); ei_local = netdev_priv(dev); + ei_local->msg_enable = mcf8390_msg_enable; dev->irq = irq->start; dev->base_addr = mem->start; diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index b2e840513735..58eaa8f34942 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -71,14 +71,17 @@ static struct platform_device *pdev_ne[MAX_NE_CARDS]; static int io[MAX_NE_CARDS]; static int irq[MAX_NE_CARDS]; static int bad[MAX_NE_CARDS]; +static u32 ne_msg_enable; #ifdef MODULE module_param_array(io, int, NULL, 0); module_param_array(irq, int, NULL, 0); module_param_array(bad, int, NULL, 0); +module_param_named(msg_enable, ne_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); MODULE_PARM_DESC(io, "I/O base address(es),required"); MODULE_PARM_DESC(irq, "IRQ number(s)"); MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures"); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver"); MODULE_LICENSE("GPL"); #endif /* MODULE */ @@ -214,8 +217,8 @@ static int __init do_ne_probe(struct net_device *dev) if (base_addr > 0x1ff) { /* Check a single specified location. */ int ret = ne_probe1(dev, base_addr); if (ret) - printk(KERN_WARNING "ne.c: No NE*000 card found at " - "i/o = %#lx\n", base_addr); + netdev_warn(dev, "ne.c: No NE*000 card found at " + "i/o = %#lx\n", base_addr); return ret; } else if (base_addr != 0) /* Don't probe at all. */ @@ -264,11 +267,14 @@ static int __init ne_probe_isapnp(struct net_device *dev) /* found it */ dev->base_addr = pnp_port_start(idev, 0); dev->irq = pnp_irq(idev, 0); - printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", - (char *) isapnp_clone_list[i].driver_data, - dev->base_addr, dev->irq); + netdev_info(dev, + "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", + (char *) isapnp_clone_list[i].driver_data, + dev->base_addr, dev->irq); if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); + netdev_err(dev, + "ne.c: Probe of ISAPnP card at %#lx failed.\n", + dev->base_addr); pnp_device_detach(idev); return -ENXIO; } @@ -293,6 +299,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) int neX000, ctron, copam, bad_card; int reg0, ret; static unsigned version_printed; + struct ei_device *ei_local = netdev_priv(dev); if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; @@ -319,10 +326,10 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) } } - if (ei_debug && version_printed++ == 0) - printk(KERN_INFO "%s%s", version1, version2); + if ((ne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0)) + netdev_info(dev, "%s%s", version1, version2); - printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr); + netdev_info(dev, "NE*000 ethercard probe at %#3lx:", ioaddr); /* A user with a poor card that fails to ack the reset, or that does not have a valid 0x57,0x57 signature can still use this @@ -343,10 +350,10 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) if (time_after(jiffies, reset_start_time + 2*HZ/100)) { if (bad_card) { - printk(" (warning: no reset ack)"); + pr_cont(" (warning: no reset ack)"); break; } else { - printk(" not found (no reset ack).\n"); + pr_cont(" not found (no reset ack).\n"); ret = -ENODEV; goto err_out; } @@ -454,13 +461,13 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) } if (bad_clone_list[i].name8 == NULL) { - printk(" not found (invalid signature %2.2x %2.2x).\n", + pr_cont(" not found (invalid signature %2.2x %2.2x).\n", SA_prom[14], SA_prom[15]); ret = -ENXIO; goto err_out; } #else - printk(" not found.\n"); + pr_cont(" not found.\n"); ret = -ENXIO; goto err_out; #endif @@ -476,15 +483,15 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) mdelay(10); /* wait 10ms for interrupt to propagate */ outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ dev->irq = probe_irq_off(cookie); - if (ei_debug > 2) - printk(" autoirq is %d\n", dev->irq); + if (netif_msg_probe(ei_local)) + pr_cont(" autoirq is %d", dev->irq); } else if (dev->irq == 2) /* Fixup for users that don't know that IRQ 2 is really IRQ 9, or don't know which one to set. */ dev->irq = 9; if (! dev->irq) { - printk(" failed to detect IRQ line.\n"); + pr_cont(" failed to detect IRQ line.\n"); ret = -EAGAIN; goto err_out; } @@ -493,7 +500,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) share and the board will usually be enabled. */ ret = request_irq(dev->irq, eip_interrupt, 0, name, dev); if (ret) { - printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); + pr_cont(" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); goto err_out; } @@ -512,7 +519,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) } #endif - printk("%pM\n", dev->dev_addr); + pr_cont("%pM\n", dev->dev_addr); ei_status.name = name; ei_status.tx_start_page = start_page; @@ -536,11 +543,12 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) dev->netdev_ops = &eip_netdev_ops; NS8390p_init(dev, 0); + ei_local->msg_enable = ne_msg_enable; ret = register_netdev(dev); if (ret) goto out_irq; - printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n", - dev->name, name, ioaddr, dev->irq); + netdev_info(dev, "%s found at %#lx, using IRQ %d.\n", + name, ioaddr, dev->irq); return 0; out_irq: @@ -556,9 +564,9 @@ err_out: static void ne_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; + struct ei_device *ei_local = netdev_priv(dev); - if (ei_debug > 1) - printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); + netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies); /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); @@ -569,7 +577,7 @@ static void ne_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) if (time_after(jiffies, reset_start_time + 2*HZ/100)) { - printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); + netdev_err(dev, "ne_reset_8390() did not complete.\n"); break; } outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ @@ -587,9 +595,9 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, i if (ei_status.dmaing) { - printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + netdev_err(dev, "DMAing conflict in ne_get_8390_hdr " + "[DMAstat:%d][irqlock:%d].\n", + ei_status.dmaing, ei_status.irqlock); return; } @@ -621,6 +629,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk { #ifdef NE_SANITY_CHECK int xfer_count = count; + struct ei_device *ei_local = netdev_priv(dev); #endif int nic_base = dev->base_addr; char *buf = skb->data; @@ -628,9 +637,9 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk(KERN_EMERG "%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + netdev_err(dev, "DMAing conflict in ne_block_input " + "[DMAstat:%d][irqlock:%d].\n", + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -660,7 +669,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk this message you either 1) have a slightly incompatible clone or 2) have noise/speed problems with your bus. */ - if (ei_debug > 1) + if (netif_msg_rx_status(ei_local)) { /* DMA termination address check... */ int addr, tries = 20; @@ -674,9 +683,9 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk break; } while (--tries > 0); if (tries <= 0) - printk(KERN_WARNING "%s: RX transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, ring_offset + xfer_count, addr); + netdev_warn(dev, "RX transfer address mismatch," + "%#4.4x (expected) vs. %#4.4x (actual).\n", + ring_offset + xfer_count, addr); } #endif outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ @@ -690,6 +699,7 @@ static void ne_block_output(struct net_device *dev, int count, unsigned long dma_start; #ifdef NE_SANITY_CHECK int retries = 0; + struct ei_device *ei_local = netdev_priv(dev); #endif /* Round the count up for word writes. Do we need to do this? @@ -702,9 +712,9 @@ static void ne_block_output(struct net_device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + netdev_err(dev, "DMAing conflict in ne_block_output." + "[DMAstat:%d][irqlock:%d]\n", + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -751,7 +761,7 @@ retry: /* This was for the ALPHA version only, but enough people have been encountering problems so it is still here. */ - if (ei_debug > 1) + if (netif_msg_tx_queued(ei_local)) { /* DMA termination address check... */ int addr, tries = 20; @@ -765,9 +775,9 @@ retry: if (tries <= 0) { - printk(KERN_WARNING "%s: Tx packet transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, (start_page << 8) + count, addr); + netdev_warn(dev, "Tx packet transfer address mismatch," + "%#4.4x (expected) vs. %#4.4x (actual).\n", + (start_page << 8) + count, addr); if (retries++ == 0) goto retry; } @@ -776,7 +786,7 @@ retry: while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ - printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); + netdev_warn(dev, "timeout waiting for Tx RDC.\n"); ne_reset_8390(dev); NS8390p_init(dev, 1); break; @@ -936,8 +946,8 @@ int __init init_module(void) retval = platform_driver_probe(&ne_driver, ne_drv_probe); if (retval) { if (io[0] == 0) - printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\"" - " value(s) for ISA cards.\n"); + pr_notice("ne.c: You must supply \"io=0xNNN\"" + " value(s) for ISA cards.\n"); ne_loop_rm_unreg(1); return retval; } diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index fc14a85e4d5f..f395c967262e 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -33,8 +33,6 @@ /* The user-configurable values. These may be modified when a driver module is loaded.*/ -static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ - #define MAX_UNITS 8 /* More are supported, limit only on options */ /* Used to pass the full-duplex flag, etc. */ static int full_duplex[MAX_UNITS]; @@ -60,6 +58,8 @@ static int options[MAX_UNITS]; #include "8390.h" +static u32 ne2k_msg_enable; + /* These identify the driver base version and may not be removed. */ static const char version[] = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE @@ -76,10 +76,10 @@ MODULE_AUTHOR("Donald Becker / Paul Gortmaker"); MODULE_DESCRIPTION("PCI NE2000 clone driver"); MODULE_LICENSE("GPL"); -module_param(debug, int, 0); +module_param_named(msg_enable, ne2k_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); module_param_array(options, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); -MODULE_PARM_DESC(debug, "debug level (1-2)"); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); MODULE_PARM_DESC(options, "Bit 5: full duplex"); MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)"); @@ -226,6 +226,7 @@ static int ne2k_pci_init_one(struct pci_dev *pdev, static unsigned int fnd_cnt; long ioaddr; int flags = pci_clone_list[chip_idx].flags; + struct ei_device *ei_local; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -280,6 +281,8 @@ static int ne2k_pci_init_one(struct pci_dev *pdev, goto err_out_free_res; } dev->netdev_ops = &ne2k_netdev_ops; + ei_local = netdev_priv(dev); + ei_local->msg_enable = ne2k_msg_enable; SET_NETDEV_DEV(dev, &pdev->dev); @@ -379,9 +382,9 @@ static int ne2k_pci_init_one(struct pci_dev *pdev, if (i) goto err_out_free_netdev; - printk("%s: %s found at %#lx, IRQ %d, %pM.\n", - dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq, - dev->dev_addr); + netdev_info(dev, "%s found at %#lx, IRQ %d, %pM.\n", + pci_clone_list[chip_idx].name, ioaddr, dev->irq, + dev->dev_addr); return 0; @@ -450,9 +453,10 @@ static int ne2k_pci_close(struct net_device *dev) static void ne2k_pci_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; + struct ei_device *ei_local = netdev_priv(dev); - if (debug > 1) printk("%s: Resetting the 8390 t=%ld...", - dev->name, jiffies); + netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", + jiffies); outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); @@ -462,7 +466,7 @@ static void ne2k_pci_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2) { - printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name); + netdev_err(dev, "ne2k_pci_reset_8390() did not complete.\n"); break; } outb(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ @@ -479,9 +483,9 @@ static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr * /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr " + netdev_err(dev, "DMAing conflict in ne2k_pci_get_8390_hdr " "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + ei_status.dmaing, ei_status.irqlock); return; } @@ -517,9 +521,9 @@ static void ne2k_pci_block_input(struct net_device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne2k_pci_block_input " + netdev_err(dev, "DMAing conflict in ne2k_pci_block_input " "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -572,9 +576,9 @@ static void ne2k_pci_block_output(struct net_device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne2k_pci_block_output." + netdev_err(dev, "DMAing conflict in ne2k_pci_block_output." "[DMAstat:%d][irqlock:%d]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -619,7 +623,7 @@ static void ne2k_pci_block_output(struct net_device *dev, int count, while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ - printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); + netdev_warn(dev, "timeout waiting for Tx RDC.\n"); ne2k_pci_reset_8390(dev); NS8390_init(dev,1); break; @@ -640,8 +644,24 @@ static void ne2k_pci_get_drvinfo(struct net_device *dev, strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info)); } +static u32 ne2k_pci_get_msglevel(struct net_device *dev) +{ + struct ei_device *ei_local = netdev_priv(dev); + + return ei_local->msg_enable; +} + +static void ne2k_pci_set_msglevel(struct net_device *dev, u32 v) +{ + struct ei_device *ei_local = netdev_priv(dev); + + ei_local->msg_enable = v; +} + static const struct ethtool_ops ne2k_pci_ethtool_ops = { .get_drvinfo = ne2k_pci_get_drvinfo, + .get_msglevel = ne2k_pci_get_msglevel, + .set_msglevel = ne2k_pci_set_msglevel, }; static void ne2k_pci_remove_one(struct pci_dev *pdev) diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 46c5aadaca8e..eea33d667fb0 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c @@ -67,7 +67,7 @@ #define PCNET_RDC_TIMEOUT (2*HZ/100) /* Max wait in jiffies for Tx RDC */ static const char *if_names[] = { "auto", "10baseT", "10base2"}; - +static u32 pcnet_msg_enable; /*====================================================================*/ @@ -558,6 +558,7 @@ static int pcnet_config(struct pcmcia_device *link) int start_pg, stop_pg, cm_offset; int has_shmem = 0; hw_info_t *local_hw_info; + struct ei_device *ei_local; dev_dbg(&link->dev, "pcnet_config\n"); @@ -607,6 +608,8 @@ static int pcnet_config(struct pcmcia_device *link) mii_phy_probe(dev); SET_NETDEV_DEV(dev, &link->dev); + ei_local = netdev_priv(dev); + ei_local->msg_enable = pcnet_msg_enable; if (register_netdev(dev) != 0) { pr_notice("register_netdev() failed\n"); @@ -616,7 +619,7 @@ static int pcnet_config(struct pcmcia_device *link) if (info->flags & (IS_DL10019|IS_DL10022)) { u_char id = inb(dev->base_addr + 0x1a); netdev_info(dev, "NE2000 (DL100%d rev %02x): ", - (info->flags & IS_DL10022) ? 22 : 19, id); + (info->flags & IS_DL10022) ? 22 : 19, id); if (info->pna_phy) pr_cont("PNA, "); } else { @@ -1063,9 +1066,9 @@ static void ei_watchdog(u_long arg) if (info->phy_id == info->eth_phy) { if (p) netdev_info(dev, "autonegotiation complete: " - "%sbaseT-%cD selected\n", - ((p & 0x0180) ? "100" : "10"), - ((p & 0x0140) ? 'F' : 'H')); + "%sbaseT-%cD selected\n", + ((p & 0x0180) ? "100" : "10"), + ((p & 0x0140) ? 'F' : 'H')); else netdev_info(dev, "link partner did not autonegotiate\n"); } @@ -1081,7 +1084,7 @@ static void ei_watchdog(u_long arg) mdio_write(mii_addr, info->phy_id, 0, 0x0400); info->phy_id ^= info->pna_phy ^ info->eth_phy; netdev_info(dev, "switched to %s transceiver\n", - (info->phy_id == info->eth_phy) ? "ethernet" : "PNA"); + (info->phy_id == info->eth_phy) ? "ethernet" : "PNA"); mdio_write(mii_addr, info->phy_id, 0, (info->phy_id == info->eth_phy) ? 0x1000 : 0); info->link_status = 0; @@ -1128,9 +1131,9 @@ static void dma_get_8390_hdr(struct net_device *dev, unsigned int nic_base = dev->base_addr; if (ei_status.dmaing) { - netdev_notice(dev, "DMAing conflict in dma_block_input." - "[DMAstat:%1x][irqlock:%1x]\n", - ei_status.dmaing, ei_status.irqlock); + netdev_err(dev, "DMAing conflict in dma_block_input." + "[DMAstat:%1x][irqlock:%1x]\n", + ei_status.dmaing, ei_status.irqlock); return; } @@ -1159,13 +1162,14 @@ static void dma_block_input(struct net_device *dev, int count, unsigned int nic_base = dev->base_addr; int xfer_count = count; char *buf = skb->data; + struct ei_device *ei_local = netdev_priv(dev); - if ((ei_debug > 4) && (count != 4)) + if ((netif_msg_rx_status(ei_local)) && (count != 4)) netdev_dbg(dev, "[bi=%d]\n", count+4); if (ei_status.dmaing) { - netdev_notice(dev, "DMAing conflict in dma_block_input." - "[DMAstat:%1x][irqlock:%1x]\n", - ei_status.dmaing, ei_status.irqlock); + netdev_err(dev, "DMAing conflict in dma_block_input." + "[DMAstat:%1x][irqlock:%1x]\n", + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -1183,7 +1187,8 @@ static void dma_block_input(struct net_device *dev, int count, /* This was for the ALPHA version only, but enough people have been encountering problems that it is still here. */ #ifdef PCMCIA_DEBUG - if (ei_debug > 4) { /* DMA termination address check... */ + /* DMA termination address check... */ + if (netif_msg_rx_status(ei_local)) { int addr, tries = 20; do { /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here @@ -1196,8 +1201,8 @@ static void dma_block_input(struct net_device *dev, int count, } while (--tries > 0); if (tries <= 0) netdev_notice(dev, "RX transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - ring_offset + xfer_count, addr); + "%#4.4x (expected) vs. %#4.4x (actual).\n", + ring_offset + xfer_count, addr); } #endif outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ @@ -1213,12 +1218,12 @@ static void dma_block_output(struct net_device *dev, int count, pcnet_dev_t *info = PRIV(dev); #ifdef PCMCIA_DEBUG int retries = 0; + struct ei_device *ei_local = netdev_priv(dev); #endif u_long dma_start; #ifdef PCMCIA_DEBUG - if (ei_debug > 4) - netdev_dbg(dev, "[bo=%d]\n", count); + netif_dbg(ei_local, tx_queued, dev, "[bo=%d]\n", count); #endif /* Round the count up for word writes. Do we need to do this? @@ -1227,9 +1232,9 @@ static void dma_block_output(struct net_device *dev, int count, if (count & 0x01) count++; if (ei_status.dmaing) { - netdev_notice(dev, "DMAing conflict in dma_block_output." - "[DMAstat:%1x][irqlock:%1x]\n", - ei_status.dmaing, ei_status.irqlock); + netdev_err(dev, "DMAing conflict in dma_block_output." + "[DMAstat:%1x][irqlock:%1x]\n", + ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -1256,7 +1261,8 @@ static void dma_block_output(struct net_device *dev, int count, #ifdef PCMCIA_DEBUG /* This was for the ALPHA version only, but enough people have been encountering problems that it is still here. */ - if (ei_debug > 4) { /* DMA termination address check... */ + /* DMA termination address check... */ + if (netif_msg_tx_queued(ei_local)) { int addr, tries = 20; do { int high = inb_p(nic_base + EN0_RSARHI); @@ -1267,8 +1273,8 @@ static void dma_block_output(struct net_device *dev, int count, } while (--tries > 0); if (tries <= 0) { netdev_notice(dev, "Tx packet transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - (start_page << 8) + count, addr); + "%#4.4x (expected) vs. %#4.4x (actual).\n", + (start_page << 8) + count, addr); if (retries++ == 0) goto retry; } @@ -1277,10 +1283,10 @@ static void dma_block_output(struct net_device *dev, int count, while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) { - netdev_notice(dev, "timeout waiting for Tx RDC.\n"); - pcnet_reset_8390(dev); - NS8390_init(dev, 1); - break; + netdev_warn(dev, "timeout waiting for Tx RDC.\n"); + pcnet_reset_8390(dev); + NS8390_init(dev, 1); + break; } outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c index b0fbce39661a..139385dcdaa7 100644 --- a/drivers/net/ethernet/8390/smc-ultra.c +++ b/drivers/net/ethernet/8390/smc-ultra.c @@ -111,6 +111,7 @@ static struct isapnp_device_id ultra_device_ids[] __initdata = { MODULE_DEVICE_TABLE(isapnp, ultra_device_ids); #endif +static u32 ultra_msg_enable; #define START_PG 0x00 /* First page of TX buffer */ @@ -211,6 +212,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) unsigned char num_pages, irqreg, addr, piomode; unsigned char idreg = inb(ioaddr + 7); unsigned char reg4 = inb(ioaddr + 4) & 0x7f; + struct ei_device *ei_local = netdev_priv(dev); if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) return -EBUSY; @@ -232,16 +234,16 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) goto out; } - if (ei_debug && version_printed++ == 0) - printk(version); + if ((ultra_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0)) + netdev_info(dev, version); model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ"; for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(ioaddr + 8 + i); - printk("%s: %s at %#3x, %pM", dev->name, model_name, - ioaddr, dev->dev_addr); + netdev_info(dev, "%s at %#3x, %pM", model_name, + ioaddr, dev->dev_addr); /* Switch from the station address to the alternate register set and read the useful registers there. */ @@ -265,7 +267,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)]; if (irq == 0) { - printk(", failed to detect IRQ line.\n"); + pr_cont(", failed to detect IRQ line.\n"); retval = -EAGAIN; goto out; } @@ -296,7 +298,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256); if (!ei_status.mem) { - printk(", failed to ioremap.\n"); + pr_cont(", failed to ioremap.\n"); retval = -ENOMEM; goto out; } @@ -304,14 +306,15 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256; if (piomode) { - printk(",%s IRQ %d programmed-I/O mode.\n", - eeprom_irq ? "EEPROM" : "assigned ", dev->irq); + pr_cont(", %s IRQ %d programmed-I/O mode.\n", + eeprom_irq ? "EEPROM" : "assigned ", dev->irq); ei_status.block_input = &ultra_pio_input; ei_status.block_output = &ultra_pio_output; ei_status.get_8390_hdr = &ultra_pio_get_hdr; } else { - printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ", - dev->irq, dev->mem_start, dev->mem_end-1); + pr_cont(", %s IRQ %d memory %#lx-%#lx.\n", + eeprom_irq ? "" : "assigned ", dev->irq, dev->mem_start, + dev->mem_end-1); ei_status.block_input = &ultra_block_input; ei_status.block_output = &ultra_block_output; ei_status.get_8390_hdr = &ultra_get_8390_hdr; @@ -320,6 +323,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) dev->netdev_ops = &ultra_netdev_ops; NS8390_init(dev, 0); + ei_local->msg_enable = ultra_msg_enable; retval = register_netdev(dev); if (retval) @@ -356,12 +360,15 @@ static int __init ultra_probe_isapnp(struct net_device *dev) /* found it */ dev->base_addr = pnp_port_start(idev, 0); dev->irq = pnp_irq(idev, 0); - printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", - (char *) ultra_device_ids[i].driver_data, - dev->base_addr, dev->irq); + netdev_info(dev, + "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", + (char *) ultra_device_ids[i].driver_data, + dev->base_addr, dev->irq); if (ultra_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); - pnp_device_detach(idev); + netdev_err(dev, + "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", + dev->base_addr); + pnp_device_detach(idev); return -ENXIO; } ei_status.priv = (unsigned long)idev; @@ -412,9 +419,10 @@ static void ultra_reset_8390(struct net_device *dev) { int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */ + struct ei_device *ei_local = netdev_priv(dev); outb(ULTRA_RESET, cmd_port); - if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies); + netif_dbg(ei_local, hw, dev, "resetting Ultra, t=%ld...\n", jiffies); ei_status.txing = 0; outb(0x00, cmd_port); /* Disable shared memory for safety. */ @@ -424,7 +432,7 @@ ultra_reset_8390(struct net_device *dev) else outb(0x01, cmd_port + 6); /* Enable interrupts and memory. */ - if (ei_debug > 1) printk("reset done\n"); + netif_dbg(ei_local, hw, dev, "reset done\n"); } /* Grab the 8390 specific header. Similar to the block_input routine, but @@ -530,11 +538,11 @@ static int ultra_close_card(struct net_device *dev) { int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */ + struct ei_device *ei_local = netdev_priv(dev); netif_stop_queue(dev); - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); + netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n"); outb(0x00, ioaddr + 6); /* Disable interrupts. */ free_irq(dev->irq, dev); @@ -556,8 +564,10 @@ static int irq[MAX_ULTRA_CARDS]; module_param_array(io, int, NULL, 0); module_param_array(irq, int, NULL, 0); +module_param_named(msg_enable, ultra_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); MODULE_DESCRIPTION("SMC Ultra/EtherEZ ISA/PnP Ethernet driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c index 8df4c4157230..aca957d4e121 100644 --- a/drivers/net/ethernet/8390/stnic.c +++ b/drivers/net/ethernet/8390/stnic.c @@ -69,6 +69,11 @@ static void stnic_block_output (struct net_device *dev, int count, static void stnic_init (struct net_device *dev); +static u32 stnic_msg_enable; + +module_param_named(msg_enable, stnic_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); + /* SH7750 specific read/write io. */ static inline void STNIC_DELAY (void) @@ -100,6 +105,7 @@ static int __init stnic_probe(void) { struct net_device *dev; int i, err; + struct ei_device *ei_local; /* If we are not running on a SolutionEngine, give up now */ if (! MACH_SE) @@ -125,10 +131,10 @@ static int __init stnic_probe(void) share and the board will usually be enabled. */ err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (err) { - printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq); - free_netdev(dev); - return err; - } + netdev_emerg(dev, " unable to get IRQ %d.\n", dev->irq); + free_netdev(dev); + return err; + } ei_status.name = dev->name; ei_status.word16 = 1; @@ -147,6 +153,8 @@ static int __init stnic_probe(void) ei_status.block_output = &stnic_block_output; stnic_init (dev); + ei_local = netdev_priv(dev); + ei_local->msg_enable = stnic_msg_enable; err = register_netdev(dev); if (err) { @@ -156,7 +164,7 @@ static int __init stnic_probe(void) } stnic_dev = dev; - printk (KERN_INFO "NS ST-NIC 83902A\n"); + netdev_info(dev, "NS ST-NIC 83902A\n"); return 0; } @@ -164,10 +172,11 @@ static int __init stnic_probe(void) static void stnic_reset (struct net_device *dev) { + struct ei_device *ei_local = netdev_priv(dev); + *(vhalf *) PA_83902_RST = 0; udelay (5); - if (ei_debug > 1) - printk (KERN_WARNING "8390 reset done (%ld).\n", jiffies); + netif_warn(ei_local, hw, dev, "8390 reset done (%ld).\n", jiffies); *(vhalf *) PA_83902_RST = ~0; udelay (5); } @@ -176,6 +185,8 @@ static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { + struct ei_device *ei_local = netdev_priv(dev); + half buf[2]; STNIC_WRITE (PG0_RSAR0, 0); @@ -196,8 +207,7 @@ stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr, hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8); #endif - if (ei_debug > 1) - printk (KERN_DEBUG "ring %x status %02x next %02x count %04x.\n", + netif_dbg(ei_local, probe, dev, "ring %x status %02x next %02x count %04x.\n", ring_page, hdr->status, hdr->next, hdr->count); STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c index 03eb3eed49fa..dd7d816bde52 100644 --- a/drivers/net/ethernet/8390/wd.c +++ b/drivers/net/ethernet/8390/wd.c @@ -60,6 +60,7 @@ static void wd_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); static int wd_close(struct net_device *dev); +static u32 wd_msg_enable; #define WD_START_PG 0x00 /* First page of TX buffer */ #define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */ @@ -170,6 +171,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */ const char *model_name; static unsigned version_printed; + struct ei_device *ei_local = netdev_priv(dev); for (i = 0; i < 8; i++) checksum += inb(ioaddr + 8 + i); @@ -180,19 +182,19 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) /* Check for semi-valid mem_start/end values if supplied. */ if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) { - printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n"); + netdev_warn(dev, + "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n"); dev->mem_start = 0; dev->mem_end = 0; } - if (ei_debug && version_printed++ == 0) - printk(version); + if ((wd_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0)) + netdev_info(dev, version); for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(ioaddr + 8 + i); - printk("%s: WD80x3 at %#3x, %pM", - dev->name, ioaddr, dev->dev_addr); + netdev_info(dev, "WD80x3 at %#3x, %pM", ioaddr, dev->dev_addr); /* The following PureData probe code was contributed by Mike Jagdis . Puredata does software @@ -244,8 +246,9 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) } #ifndef final_version if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01)) - printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).", - word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8); + pr_cont("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).", + word16 ? 16 : 8, + (inb(ioaddr+1) & 0x01) ? 16 : 8); #endif } @@ -259,7 +262,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) if (reg0 == 0xff || reg0 == 0) { /* Future plan: this could check a few likely locations first. */ dev->mem_start = 0xd0000; - printk(" assigning address %#lx", dev->mem_start); + pr_cont(" assigning address %#lx", dev->mem_start); } else { int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f; /* Some boards don't have the register 5 -- it returns 0xff. */ @@ -297,8 +300,8 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */ - if (ei_debug > 2) - printk(" autoirq is %d", dev->irq); + if (netif_msg_drv(ei_local)) + pr_cont(" autoirq is %d", dev->irq); if (dev->irq < 2) dev->irq = word16 ? 10 : 5; } else @@ -310,7 +313,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) share and the board will usually be enabled. */ i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (i) { - printk (" unable to get IRQ %d.\n", dev->irq); + pr_cont(" unable to get IRQ %d.\n", dev->irq); return i; } @@ -338,8 +341,8 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) return -ENOMEM; } - printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n", - model_name, dev->irq, dev->mem_start, dev->mem_end-1); + pr_cont(" %s, IRQ %d, shared memory at %#lx-%#lx.\n", + model_name, dev->irq, dev->mem_start, dev->mem_end-1); ei_status.reset_8390 = wd_reset_8390; ei_status.block_input = wd_block_input; @@ -348,6 +351,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) dev->netdev_ops = &wd_netdev_ops; NS8390_init(dev, 0); + ei_local->msg_enable = wd_msg_enable; #if 1 /* Enable interrupt generation on softconfig cards -- M.U */ @@ -385,9 +389,11 @@ static void wd_reset_8390(struct net_device *dev) { int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + struct ei_device *ei_local = netdev_priv(dev); outb(WD_RESET, wd_cmd_port); - if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies); + netif_dbg(ei_local, hw, dev, "resetting the WD80x3 t=%lu...\n", + jiffies); ei_status.txing = 0; /* Set up the ASIC registers, just in case something changed them. */ @@ -395,7 +401,7 @@ wd_reset_8390(struct net_device *dev) if (ei_status.word16) outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5); - if (ei_debug > 1) printk("reset done\n"); + netif_dbg(ei_local, hw, dev, "reset done\n"); } /* Grab the 8390 specific header. Similar to the block_input routine, but @@ -474,9 +480,9 @@ static int wd_close(struct net_device *dev) { int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + struct ei_device *ei_local = netdev_priv(dev); - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); + netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n"); ei_close(dev); /* Change from 16-bit to 8-bit shared memory so reboot works. */ @@ -502,10 +508,12 @@ module_param_array(io, int, NULL, 0); module_param_array(irq, int, NULL, 0); module_param_array(mem, int, NULL, 0); module_param_array(mem_end, int, NULL, 0); +module_param_named(msg_enable, wd_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH)); MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)"); MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)"); MODULE_PARM_DESC(mem_end, "memory end address(es)"); +MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c index 85ec4c2d2645..7b373e65f377 100644 --- a/drivers/net/ethernet/8390/zorro8390.c +++ b/drivers/net/ethernet/8390/zorro8390.c @@ -44,6 +44,8 @@ static const char version[] = "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +static u32 zorro8390_msg_enable; + #include "lib8390.c" #define DRV_NAME "zorro8390" @@ -86,9 +88,9 @@ static struct card_info { static void zorro8390_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; + struct ei_device *ei_local = netdev_priv(dev); - if (ei_debug > 1) - netdev_dbg(dev, "resetting - t=%ld...\n", jiffies); + netif_dbg(ei_local, hw, dev, "resetting - t=%ld...\n", jiffies); z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); @@ -119,8 +121,9 @@ static void zorro8390_get_8390_hdr(struct net_device *dev, * If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n", - __func__, ei_status.dmaing, ei_status.irqlock); + netdev_warn(dev, + "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n", + __func__, ei_status.dmaing, ei_status.irqlock); return; } @@ -230,7 +233,7 @@ static void zorro8390_block_output(struct net_device *dev, int count, while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */ - netdev_err(dev, "timeout waiting for Tx RDC\n"); + netdev_warn(dev, "timeout waiting for Tx RDC\n"); zorro8390_reset_8390(dev); __NS8390_init(dev, 1); break; @@ -248,8 +251,9 @@ static int zorro8390_open(struct net_device *dev) static int zorro8390_close(struct net_device *dev) { - if (ei_debug > 1) - netdev_dbg(dev, "Shutting down ethercard\n"); + struct ei_device *ei_local = netdev_priv(dev); + + netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard\n"); __ei_close(dev); return 0; } @@ -293,6 +297,7 @@ static int zorro8390_init(struct net_device *dev, unsigned long board, int err; unsigned char SA_prom[32]; int start_page, stop_page; + struct ei_device *ei_local = netdev_priv(dev); static u32 zorro8390_offsets[16] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, @@ -383,6 +388,9 @@ static int zorro8390_init(struct net_device *dev, unsigned long board, dev->netdev_ops = &zorro8390_netdev_ops; __NS8390_init(dev, 0); + + ei_local->msg_enable = zorro8390_msg_enable; + err = register_netdev(dev); if (err) { free_irq(IRQ_AMIGA_PORTS, dev); -- cgit v1.2.3 From 79b53d199b83a44811cd57091751ef122351ae85 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 10 Dec 2013 10:09:42 +0100 Subject: regulator: s5m8767: Define symbol for buck control mask Replace hard-coded value for mask used in BUCKX_CTRL registers (for BUCKX_EN field) with a symbol. This also removes two local variables. Signed-off-by: Krzysztof Kozlowski Acked-by: Lee Jones Reviewed-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 11 ++++++----- include/linux/mfd/samsung/s5m8767.h | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index cbf91e25cf7f..ef4da4442fa7 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -217,7 +217,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; - int mask = 0xc0, enable_ctrl; + int enable_ctrl; unsigned int val; ret = s5m8767_get_register(rdev, ®, &enable_ctrl); @@ -230,27 +230,28 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) if (ret) return ret; - return (val & mask) == enable_ctrl; + return (val & S5M8767_ENCTRL_MASK) == enable_ctrl; } static int s5m8767_reg_enable(struct regulator_dev *rdev) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; - int mask = 0xc0, enable_ctrl; + int enable_ctrl; ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret) return ret; - return sec_reg_update(s5m8767->iodev, reg, enable_ctrl, mask); + return sec_reg_update(s5m8767->iodev, reg, enable_ctrl, + S5M8767_ENCTRL_MASK); } static int s5m8767_reg_disable(struct regulator_dev *rdev) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; - int mask = 0xc0, enable_ctrl; + int mask = S5M8767_ENCTRL_MASK, enable_ctrl; ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret) diff --git a/include/linux/mfd/samsung/s5m8767.h b/include/linux/mfd/samsung/s5m8767.h index 306a95fc558c..9198377ee859 100644 --- a/include/linux/mfd/samsung/s5m8767.h +++ b/include/linux/mfd/samsung/s5m8767.h @@ -183,6 +183,7 @@ enum s5m8767_regulators { S5M8767_REG_MAX, }; -#define S5M8767_ENCTRL_SHIFT 6 +#define S5M8767_ENCTRL_SHIFT 6 +#define S5M8767_ENCTRL_MASK (0x3 << S5M8767_ENCTRL_SHIFT) #endif /* __LINUX_MFD_S5M8767_H */ -- cgit v1.2.3 From 463616ea3f4c4ff27019ffcf8f09a25712c1f4c1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 10 Dec 2013 10:09:43 +0100 Subject: regulator: s5m8767: Implement voltage setting for BUCK7/8 regulators Voltage setting for BUCK7 and BUCK8 was not supported by s5m8767 driver. If they were configured in DTS then the driver probing would fail with EINVAL: [ 0.288474] VCC_SUB_1.35V: failed to apply 1350000uV constraint [ 0.288671] s5m8767-pmic s5m8767-pmic: regulator init failed for 35 [ 0.294931] s5m8767-pmic: probe of s5m8767-pmic failed with error -22 This patch adds support for BUCK7 and BUCK8 regulators using standard regmap get/set voltage sel functions. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index ef4da4442fa7..9b14faa3bf91 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -120,8 +120,8 @@ static const struct sec_voltage_desc *reg_voltage_map[] = { [S5M8767_BUCK4] = &buck_voltage_val2, [S5M8767_BUCK5] = &buck_voltage_val1, [S5M8767_BUCK6] = &buck_voltage_val1, - [S5M8767_BUCK7] = NULL, - [S5M8767_BUCK8] = NULL, + [S5M8767_BUCK7] = &buck_voltage_val3, + [S5M8767_BUCK8] = &buck_voltage_val3, [S5M8767_BUCK9] = &buck_voltage_val3, }; @@ -418,9 +418,12 @@ static struct regulator_ops s5m8767_ops = { }; static struct regulator_ops s5m8767_buck78_ops = { + .list_voltage = regulator_list_voltage_linear, .is_enabled = s5m8767_reg_is_enabled, .enable = s5m8767_reg_enable, .disable = s5m8767_reg_disable, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, }; #define s5m8767_regulator_desc(_name) { \ -- cgit v1.2.3 From dff392dbd258381a6c3164f38420593f2d291e3b Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 17:32:41 -0200 Subject: drm/i915: don't touch the VDD when disabling the panel I don't see a reason to touch VDD when we're disabling the panel: since the panel is enabled, we don't need VDD. This saves a few sleep calls from the vdd_on and vdd_off functions at every modeset. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69693 Reviewed-by: Rodrigo Vivi Signed-off-by: Paulo Zanoni [danvet: Fix the patch mangle wiggle has done ... Spotted by Paulo. Also drop the runtime_pm_put call which now has to go due to different patch ordering. Also from Paul.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index a75ceb5132ed..8b0e96ff76c9 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1165,7 +1165,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - ironlake_edp_panel_vdd_on(intel_dp); + ironlake_edp_panel_off(intel_dp); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ba5a59c9129f..948892d18ff7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1239,24 +1239,17 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp) DRM_DEBUG_KMS("Turn eDP power off\n"); - WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); - pp = ironlake_get_pp_control(intel_dp); /* We need to switch off panel power _and_ force vdd, for otherwise some * panels get very unhappy and cease to work. */ - pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); + pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); pp_ctrl_reg = _pp_ctrl_reg(intel_dp); I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); - intel_dp->want_panel_vdd = false; - ironlake_wait_panel_off(intel_dp); - - /* We got a reference when we enabled the VDD. */ - intel_runtime_pm_put(dev_priv); } void ironlake_edp_backlight_on(struct intel_dp *intel_dp) @@ -1781,7 +1774,6 @@ static void intel_disable_dp(struct intel_encoder *encoder) /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ - ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); ironlake_edp_panel_off(intel_dp); -- cgit v1.2.3 From 90791a5c644e2e06cadfe4f37de8ca81483e3a72 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 17:32:42 -0200 Subject: drm/i915: fix VDD override off wait If we're disabling the VDD override bit and the panel is enabled, we don't need to wait for anything. If the panel is disabled, then we need to actually wait for panel_power_cycle_delay, not panel_power_down_delay, because the power down delay was already respected when we disabled the panel. Signed-off-by: Paulo Zanoni Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 948892d18ff7..8f17f8fbd0b1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1144,7 +1144,9 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) /* Make sure sequencer is idle before allowing subsequent activity */ DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg)); - msleep(intel_dp->panel_power_down_delay); + + if ((pp & POWER_TARGET_ON) == 0) + msleep(intel_dp->panel_power_cycle_delay); intel_runtime_pm_put(dev_priv); } -- cgit v1.2.3 From 0476190e107f398cfe0b50101bee4f8bd8e0fe30 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2013 20:47:44 +0200 Subject: drm/i915: Use 32bit read for BB_ADDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BB_ADDR register is documented to be 32bits at least since SNB. Prior to that the high 32bits were listed as MBZ, so using a 64bit read doesn't seem worth anything. Also the simulator doesn't like the 64bit read. So just switch to using a 32bit read instead. Signed-off-by: Ville Syrjälä Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 79dcb8f896c6..9a642921182b 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -726,7 +726,7 @@ static void i915_record_ring_state(struct drm_device *dev, error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base)); error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); if (ring->id == RCS) - error->bbaddr = I915_READ64(BB_ADDR); + error->bbaddr = I915_READ(BB_ADDR); error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base)); } else { error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); -- cgit v1.2.3 From 3dda20a974e013a4985560904c0e491a70a25251 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2013 21:44:43 +0200 Subject: drm/i915: Record BB_ADDR for every ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every ring seems to have a BB_ADDR registers, so include them all in the error state. v2: Also include the _UDW on BDW Signed-off-by: Ville Syrjälä Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 12 ++++++------ drivers/gpu/drm/i915/i915_reg.h | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 98fd1c043777..a3804b29ef90 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -323,7 +323,7 @@ struct drm_i915_error_state { u32 instps[I915_NUM_RINGS]; u32 extra_instdone[I915_NUM_INSTDONE_REG]; u32 seqno[I915_NUM_RINGS]; - u64 bbaddr; + u64 bbaddr[I915_NUM_RINGS]; u32 fault_reg[I915_NUM_RINGS]; u32 done_reg; u32 faddr[I915_NUM_RINGS]; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 9a642921182b..a707cca692e4 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -247,12 +247,11 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, err_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); err_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); - if (ring == RCS && INTEL_INFO(dev)->gen >= 4) - err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); - if (INTEL_INFO(dev)->gen >= 4) + if (INTEL_INFO(dev)->gen >= 4) { + err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr[ring]); err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]); - if (INTEL_INFO(dev)->gen >= 4) err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); + } err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); err_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]); if (INTEL_INFO(dev)->gen >= 6) { @@ -725,8 +724,9 @@ static void i915_record_ring_state(struct drm_device *dev, error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base)); error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base)); error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); - if (ring->id == RCS) - error->bbaddr = I915_READ(BB_ADDR); + error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base)); + if (INTEL_INFO(dev)->gen >= 8) + error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32; error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base)); } else { error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2d203905bd70..8828ee4eabec 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -734,6 +734,8 @@ #define HWSTAM 0x02098 #define DMA_FADD_I8XX 0x020d0 #define RING_BBSTATE(base) ((base)+0x110) +#define RING_BBADDR(base) ((base)+0x140) +#define RING_BBADDR_UDW(base) ((base)+0x168) /* gen8+ */ #define ERROR_GEN6 0x040a0 #define GEN7_ERR_INT 0x44040 @@ -924,7 +926,6 @@ #define CM0_COLOR_EVICT_DISABLE (1<<3) #define CM0_DEPTH_WRITE_DISABLE (1<<1) #define CM0_RC_OP_FLUSH_DISABLE (1<<0) -#define BB_ADDR 0x02140 /* 8 bytes */ #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ #define GFX_FLSH_CNTL_GEN6 0x101008 #define GFX_FLSH_CNTL_EN (1<<0) -- cgit v1.2.3 From b1c560d13d1aab194b467ca33d0be6ca6e829ee5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 9 Dec 2013 18:54:13 +0200 Subject: drm/i915: Extract p2 divider correctly for gen2 LVDS dual channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to determine the correct p2 divider for LVDS on gen2, we need to check the CLKB mode from the LVDS port register to determine if we're dealing with single or dual channel LVDS. Cc: Bruno Prémont Signed-off-by: Ville Syrjälä Tested-by: Bruno Prémont Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7b1b18d8f45c..8c4e384b8ae1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7951,12 +7951,17 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, else i9xx_clock(refclk, &clock); } else { - bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); + u32 lvds = I915_READ(LVDS); + bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN); if (is_lvds) { clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> DPLL_FPA01_P1_POST_DIV_SHIFT); - clock.p2 = 14; + + if (lvds & LVDS_CLKB_POWER_UP) + clock.p2 = 7; + else + clock.p2 = 14; } else { if (dpll & PLL_P1_DIVIDE_BY_TWO) clock.p1 = 2; -- cgit v1.2.3 From 91dbe5fb77a2afea04a52b432cfb4529d72096d1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 9 Dec 2013 18:54:14 +0200 Subject: drm/i915: Change N divider minimum from 3 to 2 for gen2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bruno Prémont has a 855 machine with a 1400x1050 LVDS screen. The VBT mode is as follows: 0:"1400x1050" 0 108000 1400 1416 1528 1688 1050 1051 1054 1066 0x8 0xa The BIOS uses the following DPLL settings: DPLL = 0x90020000 FP0 = 0x2140e FP1 = 0x21207 We can't generate that pixel clock currently as we're limiting the N divider to at least 3, whereas the BIOS uses a value of 2. Let's reduce the N minimum to 2 and see what happens. Cc: Bruno Prémont Signed-off-by: Ville Syrjälä Tested-by: Bruno Prémont Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8c4e384b8ae1..efc3391dfac5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -91,7 +91,7 @@ intel_fdi_link_freq(struct drm_device *dev) static const intel_limit_t intel_limits_i8xx_dac = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 930000, .max = 1400000 }, - .n = { .min = 3, .max = 16 }, + .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, .m2 = { .min = 6, .max = 16 }, @@ -104,7 +104,7 @@ static const intel_limit_t intel_limits_i8xx_dac = { static const intel_limit_t intel_limits_i8xx_dvo = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 930000, .max = 1400000 }, - .n = { .min = 3, .max = 16 }, + .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, .m2 = { .min = 6, .max = 16 }, @@ -117,7 +117,7 @@ static const intel_limit_t intel_limits_i8xx_dvo = { static const intel_limit_t intel_limits_i8xx_lvds = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 930000, .max = 1400000 }, - .n = { .min = 3, .max = 16 }, + .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, .m2 = { .min = 6, .max = 16 }, -- cgit v1.2.3 From c7721d3266c71b122f7a6c2b40b0800985b53ce0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 9 Dec 2013 18:54:15 +0200 Subject: drm/i915: Increase gen2 vco frequency limit to 1512 MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bruno Prémont has a 855 machine with a 1400x1050 LVDS screen. The VBT mode is as follows: 0:"1400x1050" 0 108000 1400 1416 1528 1688 1050 1051 1054 1066 0x8 0xa The BIOS uses the following DPLL settings: DPLL = 0x90020000 FP0 = 0x2140e FP1 = 0x21207 That puts the BIOS generated VCO frequency at 1512 MHz, which is higher than the 1400 MHz limit we have currently. Let's bump the VCO limit to 1512 MHz and see what happens. Cc: Bruno Prémont Signed-off-by: Ville Syrjälä Tested-by: Bruno Prémont Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index efc3391dfac5..14e0b80c5641 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -90,7 +90,7 @@ intel_fdi_link_freq(struct drm_device *dev) static const intel_limit_t intel_limits_i8xx_dac = { .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1400000 }, + .vco = { .min = 930000, .max = 1512000 }, .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, @@ -103,7 +103,7 @@ static const intel_limit_t intel_limits_i8xx_dac = { static const intel_limit_t intel_limits_i8xx_dvo = { .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1400000 }, + .vco = { .min = 930000, .max = 1512000 }, .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, @@ -116,7 +116,7 @@ static const intel_limit_t intel_limits_i8xx_dvo = { static const intel_limit_t intel_limits_i8xx_lvds = { .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1400000 }, + .vco = { .min = 930000, .max = 1512000 }, .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, -- cgit v1.2.3 From e91e941bd566ae94ed576424c9e8b31bdfc55512 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 9 Dec 2013 18:54:16 +0200 Subject: drm/i915: Fix 66 MHz LVDS SSC freq for gen2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store the SSC refclock frequency in kHz to get more accuracy. Currently we're pretending that 66 MHz is ~66000 kHz, when in fact it is actually ~66667 kHz. By storing the less rounded kHz value we get a much better accuracy for out pixel clock calculations. Cc: Bruno Prémont Signed-off-by: Ville Syrjälä Tested-by: Bruno Prémont Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 8 ++++---- drivers/gpu/drm/i915/intel_display.c | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index e4fba39631a5..f88e5079a3f5 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -327,12 +327,12 @@ static int intel_bios_ssc_frequency(struct drm_device *dev, { switch (INTEL_INFO(dev)->gen) { case 2: - return alternate ? 66 : 48; + return alternate ? 66667 : 48000; case 3: case 4: - return alternate ? 100 : 96; + return alternate ? 100000 : 96000; default: - return alternate ? 100 : 120; + return alternate ? 100000 : 120000; } } @@ -796,7 +796,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) */ dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, !HAS_PCH_SPLIT(dev)); - DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); + DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq); for (port = PORT_A; port < I915_MAX_PORTS; port++) { struct ddi_vbt_port_info *info = diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 14e0b80c5641..9404b50ee8c4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4761,9 +4761,8 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) refclk = 100000; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { - refclk = dev_priv->vbt.lvds_ssc_freq * 1000; - DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", - refclk / 1000); + refclk = dev_priv->vbt.lvds_ssc_freq; + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); } else if (!IS_GEN2(dev)) { refclk = 96000; } else { @@ -5909,9 +5908,9 @@ static int ironlake_get_refclk(struct drm_crtc *crtc) } if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { - DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", dev_priv->vbt.lvds_ssc_freq); - return dev_priv->vbt.lvds_ssc_freq * 1000; + return dev_priv->vbt.lvds_ssc_freq; } return 120000; @@ -6173,7 +6172,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, factor = 21; if (is_lvds) { if ((intel_panel_use_ssc(dev_priv) && - dev_priv->vbt.lvds_ssc_freq == 100) || + dev_priv->vbt.lvds_ssc_freq == 100000) || (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev))) factor = 25; } else if (intel_crtc->config.sdvo_tv_clock) @@ -7888,7 +7887,7 @@ static int i9xx_pll_refclk(struct drm_device *dev, u32 dpll = pipe_config->dpll_hw_state.dpll; if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) - return dev_priv->vbt.lvds_ssc_freq * 1000; + return dev_priv->vbt.lvds_ssc_freq; else if (HAS_PCH_SPLIT(dev)) return 120000; else if (!IS_GEN2(dev)) -- cgit v1.2.3 From 9c333719ae95b7c974aa15c6dcc618918b7479c7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 9 Dec 2013 18:54:17 +0200 Subject: drm/i915: Decrease gen2 vco frequency minimum to 908 MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On my 855 machine the BIOS uses the following DPLL settings: DPLL 0x90016000 FP0 = 0x61207 FP1 = 0x21207 With the 66MHz SSC refclock, that puts the BIOS generated VCO frequency at ~908 MHz, which is lower than the 930 MHz limit we have currently. This also results in the pixel clock coming out significantly higher than the requested 65 MHz when we try to recompute it. Reduce the the VCO limit to 908 MHz. Combined with the earlier SSC reference clock accuracy fix, this results in the pixel clock coming out as 65.08 MHz which is quite close to the target. For some reason the BIOS uses 64.881 MHz, which isn't quite as close. This makes kms_flip wf_vblank-ts-check pass for the first time on this machine \o/ Cc: Bruno Prémont Signed-off-by: Ville Syrjälä Tested-by: Bruno Prémont Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9404b50ee8c4..c01aff8a36bb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -90,7 +90,7 @@ intel_fdi_link_freq(struct drm_device *dev) static const intel_limit_t intel_limits_i8xx_dac = { .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1512000 }, + .vco = { .min = 908000, .max = 1512000 }, .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, @@ -103,7 +103,7 @@ static const intel_limit_t intel_limits_i8xx_dac = { static const intel_limit_t intel_limits_i8xx_dvo = { .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1512000 }, + .vco = { .min = 908000, .max = 1512000 }, .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, @@ -116,7 +116,7 @@ static const intel_limit_t intel_limits_i8xx_dvo = { static const intel_limit_t intel_limits_i8xx_lvds = { .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1512000 }, + .vco = { .min = 908000, .max = 1512000 }, .n = { .min = 2, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, -- cgit v1.2.3 From b9f5e07d0245ff0ddaca453d146fcad056ac12c3 Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 10 Dec 2013 12:14:54 +0530 Subject: drm/i915: Add more dev ops for MIPI sub encoder Some panels require one time programming if they do not contain their own eeprom for basic register initialization. The sequence is Panel Reset --> Send OTP --> Enable Pixel Stream --> Enable the panel v2: Based on review comments from Jani and Ville - Updated the commit message with more details - Move the new parameters out of this patch Signed-off-by: Yogesh Mohan Marimuthu Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 9 ++++++++- drivers/gpu/drm/i915/intel_dsi.h | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 7b9b350d29ae..42ed28a309f5 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -147,6 +147,9 @@ static void intel_dsi_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); + if (intel_dsi->dev.dev_ops->panel_reset) + intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev); + temp = I915_READ(MIPI_DEVICE_READY(pipe)); if ((temp & DEVICE_READY) == 0) { temp &= ~ULPS_STATE_MASK; @@ -162,6 +165,9 @@ static void intel_dsi_enable(struct intel_encoder *encoder) I915_WRITE(MIPI_DEVICE_READY(pipe), temp); } + if (intel_dsi->dev.dev_ops->send_otp_cmds) + intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev); + if (is_cmd_mode(intel_dsi)) I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); @@ -176,7 +182,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) POSTING_READ(MIPI_PORT_CTRL(pipe)); } - intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); + if (intel_dsi->dev.dev_ops->enable) + intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); } static void intel_dsi_disable(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index c7765f33d524..14509d65f78d 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -39,6 +39,11 @@ struct intel_dsi_device { struct intel_dsi_dev_ops { bool (*init)(struct intel_dsi_device *dsi); + void (*panel_reset)(struct intel_dsi_device *dsi); + + /* one time programmable commands if needed */ + void (*send_otp_cmds)(struct intel_dsi_device *dsi); + /* This callback must be able to assume DSI commands can be sent */ void (*enable)(struct intel_dsi_device *dsi); -- cgit v1.2.3 From e9fe51c6656f7fd4fad38869cb70a42e65ec0ba9 Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 10 Dec 2013 12:14:55 +0530 Subject: drm/i915: Use FLISDSI interface for band gap reset v2: Rebased on latest code Signed-off-by: Shobhit Kumar Signed-off-by: Yogesh Mohan Marimuthu Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_dsi.c | 47 ++++++----------------------------- drivers/gpu/drm/i915/intel_sideband.c | 14 +++++++++++ 4 files changed, 25 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a3804b29ef90..709b20e0e3f0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2475,6 +2475,8 @@ u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg, enum intel_sbi_destination destination); void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, enum intel_sbi_destination destination); +u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg); +void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val); int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8828ee4eabec..e8cc27cd9494 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -362,6 +362,7 @@ #define IOSF_PORT_CCK 0x14 #define IOSF_PORT_CCU 0xA9 #define IOSF_PORT_GPS_CORE 0x48 +#define IOSF_PORT_FLISDSI 0x1B #define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 42ed28a309f5..1016e7b0337e 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -37,49 +37,18 @@ static const struct intel_dsi_device intel_dsi_devices[] = { }; - -static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val, - u32 mask) -{ - u32 tmp = vlv_cck_read(dev_priv, reg); - tmp &= ~mask; - tmp |= val; - vlv_cck_write(dev_priv, reg, tmp); -} - -static void band_gap_wa(struct drm_i915_private *dev_priv) +static void band_gap_reset(struct drm_i915_private *dev_priv) { mutex_lock(&dev_priv->dpio_lock); - /* Enable bandgap fix in GOP driver */ - vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000); - msleep(20); - vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000); - msleep(20); - - /* Turn Display Trunk on */ - vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000); - msleep(20); - - vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000); - msleep(20); - - vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000); + vlv_flisdsi_write(dev_priv, 0x08, 0x0001); + vlv_flisdsi_write(dev_priv, 0x0F, 0x0005); + vlv_flisdsi_write(dev_priv, 0x0F, 0x0025); + udelay(150); + vlv_flisdsi_write(dev_priv, 0x0F, 0x0000); + vlv_flisdsi_write(dev_priv, 0x08, 0x0000); mutex_unlock(&dev_priv->dpio_lock); - - /* Need huge delay, otherwise clock is not stable */ - msleep(100); } static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector) @@ -364,7 +333,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) vlv_enable_dsi_pll(intel_encoder); /* XXX: Location of the call */ - band_gap_wa(dev_priv); + band_gap_reset(dev_priv); /* escape clock divider, 20MHz, shared for A and C. device ready must be * off when doing this! txclkesc? */ diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index cc6fbcde7d3d..0954f132726e 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -249,3 +249,17 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, return; } } + +u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg) +{ + u32 val = 0; + vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI, + DPIO_OPCODE_REG_READ, reg, &val); + return val; +} + +void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) +{ + vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI, + DPIO_OPCODE_REG_WRITE, reg, &val); +} -- cgit v1.2.3 From 44d4c6eebb2ef04f698c292bb6eda5f2e80c663b Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 10 Dec 2013 12:14:56 +0530 Subject: drm/i915: Compute dsi_clk from pixel clock Pixel clock based calculation is recommended in the MIPI host controller documentation v2: Based on review comments from Jani and Ville - Use dsi_clk in KHz rather than converting in Hz and back to MHz - RR formula is retained though not used but return dsi_clk in KHz now - Moved the m-n-p changes into a separate patch - Removed the parameter check for intel_dsi->dsi_clock_freq. This will be bought back in if needed when appropriate panel drivers are done v3: Removed the unused mnp calculation from static table Signed-off-by: Vijayakumar Balakrishnan Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_pll.c | 89 +++++++++++++----------------------- 1 file changed, 31 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 44279b2ade88..0d1b17fee018 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = { 71, 35 /* 91 - 92 */ }; +#ifdef DSI_CLK_FROM_RR + static u32 dsi_rr_formula(const struct drm_display_mode *mode, int pixel_format, int video_mode_format, int lane_count, bool eotp) @@ -121,7 +123,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode, /* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */ dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8; - dsi_clk = dsi_bit_clock_hz / (1000 * 1000); + dsi_clk = dsi_bit_clock_hz / 1000; if (eotp && video_mode_format == VIDEO_MODE_BURST) dsi_clk *= 2; @@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode, return dsi_clk; } -#ifdef MNP_FROM_TABLE - -struct dsi_clock_table { - u32 freq; - u8 m; - u8 p; -}; - -static const struct dsi_clock_table dsi_clk_tbl[] = { - {300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6}, - {343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6}, - {383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5}, - {401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5}, - {405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5}, - {409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5}, - {413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5}, - {417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5}, - {430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5}, - {470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4}, - {510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4}, - {550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3}, - {590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3}, - {630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3}, - {670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3}, - {710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3}, - {750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2}, - {790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2}, - {1000, 80, 2}, /* dsi clock frequency in Mhz*/ -}; +#else -static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) +/* Get DSI clock from pixel clock */ +static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode, + int pixel_format, int lane_count) { - unsigned int i; - u8 m; - u8 n; - u8 p; - u32 m_seed; - - if (dsi_clk < 300 || dsi_clk > 1000) - return -ECHRNG; + u32 dsi_clk_khz; + u32 bpp; - for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) { - if (dsi_clk_tbl[i].freq > dsi_clk) - break; + switch (pixel_format) { + default: + case VID_MODE_FORMAT_RGB888: + case VID_MODE_FORMAT_RGB666_LOOSE: + bpp = 24; + break; + case VID_MODE_FORMAT_RGB666: + bpp = 18; + break; + case VID_MODE_FORMAT_RGB565: + bpp = 16; + break; } - m = dsi_clk_tbl[i].m; - p = dsi_clk_tbl[i].p; - m_seed = lfsr_converts[m - 62]; - n = 1; - dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2); - dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT | - m_seed << DSI_PLL_M1_DIV_SHIFT; + /* DSI data rate = pixel clock * bits per pixel / lane count + pixel clock is converted from KHz to Hz */ + dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count); - return 0; + return dsi_clk_khz; } -#else +#endif static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) { @@ -200,13 +175,14 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) u32 calc_p; u32 m_seed; - if (dsi_clk < 300 || dsi_clk > 1150) { + /* dsi_clk is expected in KHZ */ + if (dsi_clk < 300000 || dsi_clk > 1150000) { DRM_ERROR("DSI CLK Out of Range\n"); return -ECHRNG; } ref_clk = 25000; - target_dsi_clk = dsi_clk * 1000; + target_dsi_clk = dsi_clk; error = 0xFFFFFFFF; calc_m = 0; calc_p = 0; @@ -235,8 +211,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) return 0; } -#endif - /* * XXX: The muxing and gating is hard coded for now. Need to add support for * sharing PLLs with two DSI outputs. @@ -251,9 +225,8 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder) struct dsi_mnp dsi_mnp; u32 dsi_clk; - dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format, - intel_dsi->video_mode_format, - intel_dsi->lane_count, !intel_dsi->eot_disable); + dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format, + intel_dsi->lane_count); ret = dsi_calc_mnp(dsi_clk, &dsi_mnp); if (ret) { -- cgit v1.2.3 From 8e1eed5aa8fe6cdd2c445b7aded42498523ad4dd Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 10 Dec 2013 12:14:57 +0530 Subject: drm/i915: Try harder to get best m, n, p values with minimal error Basically check for both +ive and -ive deviation from target clock and pick the one with minimal error. If we get a direct match, break from loop to acheive some optimization. v2: Use signed variable for target and calculated dsi clock values Signed-off-by: Vijayakumar Balakrishnan Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_pll.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 0d1b17fee018..ba79ec19da3b 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -169,8 +169,8 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) u32 ref_clk; u32 error; u32 tmp_error; - u32 target_dsi_clk; - u32 calc_dsi_clk; + int target_dsi_clk; + int calc_dsi_clk; u32 calc_m; u32 calc_p; u32 m_seed; @@ -184,22 +184,32 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) ref_clk = 25000; target_dsi_clk = dsi_clk; error = 0xFFFFFFFF; + tmp_error = 0xFFFFFFFF; calc_m = 0; calc_p = 0; for (m = 62; m <= 92; m++) { for (p = 2; p <= 6; p++) { - + /* Find the optimal m and p divisors + with minimal error +/- the required clock */ calc_dsi_clk = (m * ref_clk) / p; - if (calc_dsi_clk >= target_dsi_clk) { - tmp_error = calc_dsi_clk - target_dsi_clk; - if (tmp_error < error) { - error = tmp_error; - calc_m = m; - calc_p = p; - } + if (calc_dsi_clk == target_dsi_clk) { + calc_m = m; + calc_p = p; + error = 0; + break; + } else + tmp_error = abs(target_dsi_clk - calc_dsi_clk); + + if (tmp_error < error) { + error = tmp_error; + calc_m = m; + calc_p = p; } } + + if (error == 0) + break; } m_seed = lfsr_converts[calc_m - 62]; -- cgit v1.2.3 From 1dbd7cb256913e5b8d6a4837185b45e3467dff42 Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Wed, 11 Dec 2013 17:52:05 +0530 Subject: drm/i915: Reorganize the DSI enable/disable sequence Basically ULPS handling during enable/disable has been moved to pre_enable and post_disable phases. PLL and panel power disable also has been moved to post_disable phase. The ULPS entry/exit sequneces as suggested by HW team is as follows - During enable time - set DEVICE_READY --> Clear DEVICE_READY --> set DEVICE_READY And during disable time to flush all FIFOs - set ENTER_SLEEP --> EXIT_SLEEP --> ENTER_SLEEP Also during disbale sequnece sub-encoder disable is moved to the end after port is disabled. v2: Based on comments from Ville - Detailed epxlaination in the commit messgae - Moved parameter changes out into another patch - Backlight enabling will be a new patch v3: Updated as per Jani's comments - Removed the I915_WRITE_BITS as it is not needed - Moved panel_reset and send_otp_cmds hooks to dsi_pre_enable - Moved disable_panel_power hook to dsi_post_disable - Replace hardcoding with AFE_LATCHOUT v4: Make intel_dsi_device_ready and intel_dsi_clear_device_ready static Signed-off-by: Yogesh Mohan Marimuthu Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 110 +++++++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_dsi.h | 2 + 2 files changed, 79 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 1016e7b0337e..e9bcb46dba5f 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -101,46 +101,57 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) vlv_enable_dsi_pll(encoder); } -static void intel_dsi_pre_enable(struct intel_encoder *encoder) +static void intel_dsi_device_ready(struct intel_encoder *encoder) { + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + int pipe = intel_crtc->pipe; + u32 val; + DRM_DEBUG_KMS("\n"); -} -static void intel_dsi_enable(struct intel_encoder *encoder) + val = I915_READ(MIPI_PORT_CTRL(pipe)); + I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD); + usleep_range(1000, 1500); + I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT); + usleep_range(2000, 2500); + I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); + usleep_range(2000, 2500); + I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00); + usleep_range(2000, 2500); + I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); + usleep_range(2000, 2500); +} +static void intel_dsi_pre_enable(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - int pipe = intel_crtc->pipe; - u32 temp; DRM_DEBUG_KMS("\n"); if (intel_dsi->dev.dev_ops->panel_reset) intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev); - temp = I915_READ(MIPI_DEVICE_READY(pipe)); - if ((temp & DEVICE_READY) == 0) { - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY); - } else if (temp & ULPS_STATE_MASK) { - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT); - /* - * We need to ensure that there is a minimum of 1 ms time - * available before clearing the UPLS exit state. - */ - msleep(2); - I915_WRITE(MIPI_DEVICE_READY(pipe), temp); - } + /* put device in ready state */ + intel_dsi_device_ready(encoder); if (intel_dsi->dev.dev_ops->send_otp_cmds) intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev); +} + +static void intel_dsi_enable(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + int pipe = intel_crtc->pipe; + u32 temp; + + DRM_DEBUG_KMS("\n"); if (is_cmd_mode(intel_dsi)) I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); - - if (is_vid_mode(intel_dsi)) { + else { msleep(20); /* XXX */ dpi_send_cmd(intel_dsi, TURN_ON); msleep(100); @@ -157,7 +168,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) static void intel_dsi_disable(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; @@ -165,8 +177,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); - intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); - if (is_vid_mode(intel_dsi)) { dpi_send_cmd(intel_dsi, SHUTDOWN); msleep(10); @@ -179,20 +189,54 @@ static void intel_dsi_disable(struct intel_encoder *encoder) msleep(2); } - temp = I915_READ(MIPI_DEVICE_READY(pipe)); - if (temp & DEVICE_READY) { - temp &= ~DEVICE_READY; - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp); - } + /* if disable packets are sent before sending shutdown packet then in + * some next enable sequence send turn on packet error is observed */ + if (intel_dsi->dev.dev_ops->disable) + intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); } -static void intel_dsi_post_disable(struct intel_encoder *encoder) +static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + int pipe = intel_crtc->pipe; + u32 val; + DRM_DEBUG_KMS("\n"); + I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); + usleep_range(2000, 2500); + + I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT); + usleep_range(2000, 2500); + + I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); + usleep_range(2000, 2500); + + val = I915_READ(MIPI_PORT_CTRL(pipe)); + I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD); + usleep_range(1000, 1500); + + if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT) + == 0x00000), 30)) + DRM_ERROR("DSI LP not going Low\n"); + + I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00); + usleep_range(2000, 2500); + vlv_disable_dsi_pll(encoder); } +static void intel_dsi_post_disable(struct intel_encoder *encoder) +{ + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + + DRM_DEBUG_KMS("\n"); + + intel_dsi_clear_device_ready(encoder); + + if (intel_dsi->dev.dev_ops->disable_panel_power) + intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev); +} static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 14509d65f78d..387dfe13cd9b 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -41,6 +41,8 @@ struct intel_dsi_dev_ops { void (*panel_reset)(struct intel_dsi_device *dsi); + void (*disable_panel_power)(struct intel_dsi_device *dsi); + /* one time programmable commands if needed */ void (*send_otp_cmds)(struct intel_dsi_device *dsi); -- cgit v1.2.3 From a4a593be5dcb39ac565fd2dd5a359456070328ac Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 10 Dec 2013 12:14:59 +0530 Subject: drm/i915: Remove redundant DSI PLL enabling DSI PLL will get configured during crtc_enable using ->pre_pll_enable and no need to do in ->mode_set Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index e9bcb46dba5f..604fa6cee289 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -373,9 +373,6 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); - /* Update the DSI PLL */ - vlv_enable_dsi_pll(intel_encoder); - /* XXX: Location of the call */ band_gap_reset(dev_priv); -- cgit v1.2.3 From f6da28429a90c87c8329425297a36b85345a3f75 Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 10 Dec 2013 12:15:00 +0530 Subject: drm/i915: Parametrize the dphy and other spec specific parameters The values of these parameters will be different for differnet panel based on dsi rate, lane count, etc. Remove the hardcodings and make these as parameters whch will be initialized in panel specific sub-encoder implementaion. This will also form groundwork for planned generic panel sub-encoder implemntation based on VBT design enhancments to support multiple panels v2: Mask away the port_bits before use Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 29 ++++++++++++++--------------- drivers/gpu/drm/i915/intel_dsi.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 604fa6cee289..fabbf0d895cf 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -157,7 +157,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) msleep(100); /* assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(pipe)); + temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK; + temp = temp | intel_dsi->port_bits; I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE); POSTING_READ(MIPI_PORT_CTRL(pipe)); } @@ -391,11 +392,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff); I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff); - I915_WRITE(MIPI_DPHY_PARAM(pipe), - 0x3c << EXIT_ZERO_COUNT_SHIFT | - 0x1f << TRAIL_COUNT_SHIFT | - 0xc5 << CLK_ZERO_COUNT_SHIFT | - 0x1f << PREPARE_COUNT_SHIFT); + I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg); I915_WRITE(MIPI_DPI_RESOLUTION(pipe), adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT | @@ -443,9 +440,9 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) adjusted_mode->htotal, bpp, intel_dsi->lane_count) + 1); } - I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */ - I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */ - I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */ + I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout); + I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val); + I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val); /* dphy stuff */ @@ -460,29 +457,31 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) * * XXX: write MIPI_STOP_STATE_STALL? */ - I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46); + I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), + intel_dsi->hs_to_lp_count); /* XXX: low power clock equivalence in terms of byte clock. the number * of byte clocks occupied in one low power clock. based on txbyteclkhs * and txclkesc. txclkesc time / txbyteclk time * (105 + * MIPI_STOP_STATE_STALL) / 105.??? */ - I915_WRITE(MIPI_LP_BYTECLK(pipe), 4); + I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk); /* the bw essential for transmitting 16 long packets containing 252 * bytes meant for dcs write memory command is programmed in this * register in terms of byte clocks. based on dsi transfer rate and the * number of lanes configured the time taken to transmit 16 long packets * in a dsi stream varies. */ - I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820); + I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer); I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe), - 0xa << LP_HS_SSW_CNT_SHIFT | - 0x14 << HS_LP_PWR_SW_CNT_SHIFT); + intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT | + intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT); if (is_vid_mode(intel_dsi)) I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe), - intel_dsi->video_mode_format); + intel_dsi->video_frmt_cfg_bits | + intel_dsi->video_mode_format); } static enum drm_connector_status diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 387dfe13cd9b..b4a27cec882f 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -96,6 +96,20 @@ struct intel_dsi { /* eot for MIPI_EOT_DISABLE register */ u32 eot_disable; + + u32 port_bits; + u32 bw_timer; + u32 dphy_reg; + u32 video_frmt_cfg_bits; + u16 lp_byte_clk; + + /* timeouts in byte clocks */ + u16 lp_rx_timeout; + u16 turn_arnd_val; + u16 rst_timer_val; + u16 hs_to_lp_count; + u16 clk_lp_to_hs_count; + u16 clk_hs_to_lp_count; }; static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) -- cgit v1.2.3 From 324a56e16e44baecac3ca799fd216154145c14bf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:53 -0500 Subject: kernfs: s/sysfs_dirent/kernfs_node/ and rename its friends accordingly kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. This patch performs the following renames. * s/sysfs_elem_dir/kernfs_elem_dir/ * s/sysfs_elem_symlink/kernfs_elem_symlink/ * s/sysfs_elem_attr/kernfs_elem_file/ * s/sysfs_dirent/kernfs_node/ * s/sd/kn/ in kernfs proper * s/parent_sd/parent/ * s/target_sd/target/ * s/dir_sd/parent/ * s/to_sysfs_dirent()/rb_to_kn()/ * misc renames of local vars when they conflict with the above Because md, mic and gpio dig into sysfs details, this patch ends up modifying them. All are sysfs_dirent renames and trivial. While we can avoid these by introducing a dummy wrapping struct sysfs_dirent around kernfs_node, given the limited usage outside kernfs and sysfs proper, I don't think such workaround is called for. This patch is strictly rename only and doesn't introduce any functional difference. - mic / gpio renames were missing. Spotted by kbuild test robot. Signed-off-by: Tejun Heo Cc: Neil Brown Cc: Linus Walleij Cc: Ashutosh Dixit Cc: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib.c | 4 +- drivers/md/bitmap.c | 2 +- drivers/md/bitmap.h | 2 +- drivers/md/md.h | 10 +- drivers/misc/mic/host/mic_device.h | 2 +- fs/kernfs/dir.c | 542 ++++++++++++++++++------------------- fs/kernfs/file.c | 186 ++++++------- fs/kernfs/inode.c | 123 ++++----- fs/kernfs/kernfs-internal.h | 40 +-- fs/kernfs/mount.c | 12 +- fs/kernfs/symlink.c | 64 ++--- fs/sysfs/dir.c | 66 ++--- fs/sysfs/file.c | 122 ++++----- fs/sysfs/group.c | 96 +++---- fs/sysfs/mount.c | 4 +- fs/sysfs/symlink.c | 72 ++--- fs/sysfs/sysfs.h | 10 +- include/linux/kernfs.h | 166 ++++++------ include/linux/kobject.h | 2 +- include/linux/sysfs.h | 20 +- lib/kobject.c | 2 +- 21 files changed, 774 insertions(+), 773 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 85f772c0b26a..c8a7c810bade 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -393,7 +393,7 @@ static const DEVICE_ATTR(value, 0644, static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { - struct sysfs_dirent *value_sd = priv; + struct kernfs_node *value_sd = priv; sysfs_notify_dirent(value_sd); return IRQ_HANDLED; @@ -402,7 +402,7 @@ static irqreturn_t gpio_sysfs_irq(int irq, void *priv) static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, unsigned long gpio_flags) { - struct sysfs_dirent *value_sd; + struct kernfs_node *value_sd; unsigned long irq_flags; int ret, irq, id; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 12dc29ba7399..4195a01b1535 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1635,7 +1635,7 @@ int bitmap_create(struct mddev *mddev) sector_t blocks = mddev->resync_max_sectors; struct file *file = mddev->bitmap_info.file; int err; - struct sysfs_dirent *bm = NULL; + struct kernfs_node *bm = NULL; BUILD_BUG_ON(sizeof(bitmap_super_t) != 256); diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index df4aeb6ac6f0..30210b9c4ef9 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -225,7 +225,7 @@ struct bitmap { wait_queue_head_t overflow_wait; wait_queue_head_t behind_wait; - struct sysfs_dirent *sysfs_can_clear; + struct kernfs_node *sysfs_can_clear; }; /* the bitmap API */ diff --git a/drivers/md/md.h b/drivers/md/md.h index 2f5cc8a7ef3e..389a3c93cdb7 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -106,7 +106,7 @@ struct md_rdev { */ struct work_struct del_work; /* used for delayed sysfs removal */ - struct sysfs_dirent *sysfs_state; /* handle for 'state' + struct kernfs_node *sysfs_state; /* handle for 'state' * sysfs entry */ struct badblocks { @@ -376,10 +376,10 @@ struct mddev { sector_t resync_max; /* resync should pause * when it gets here */ - struct sysfs_dirent *sysfs_state; /* handle for 'array_state' + struct kernfs_node *sysfs_state; /* handle for 'array_state' * file in sysfs. */ - struct sysfs_dirent *sysfs_action; /* handle for 'sync_action' */ + struct kernfs_node *sysfs_action; /* handle for 'sync_action' */ struct work_struct del_work; /* used for delayed sysfs removal */ @@ -498,13 +498,13 @@ struct md_sysfs_entry { }; extern struct attribute_group md_bitmap_group; -static inline struct sysfs_dirent *sysfs_get_dirent_safe(struct sysfs_dirent *sd, char *name) +static inline struct kernfs_node *sysfs_get_dirent_safe(struct kernfs_node *sd, char *name) { if (sd) return sysfs_get_dirent(sd, name); return sd; } -static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd) +static inline void sysfs_notify_dirent_safe(struct kernfs_node *sd) { if (sd) sysfs_notify_dirent(sd); diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 3574cc375bb9..538e3d3d3c8c 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -112,7 +112,7 @@ struct mic_device { struct work_struct shutdown_work; u8 state; u8 shutdown_status; - struct sysfs_dirent *state_sysfs; + struct kernfs_node *state_sysfs; struct completion reset_wait; void *log_buf_addr; int *log_buf_len; diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index a441e3be8052..800ebf521472 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -19,7 +19,7 @@ DEFINE_MUTEX(sysfs_mutex); -#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb) +#define rb_to_kn(X) rb_entry((X), struct kernfs_node, s_rb) /** * sysfs_name_hash @@ -45,28 +45,28 @@ static unsigned int sysfs_name_hash(const char *name, const void *ns) } static int sysfs_name_compare(unsigned int hash, const char *name, - const void *ns, const struct sysfs_dirent *sd) + const void *ns, const struct kernfs_node *kn) { - if (hash != sd->s_hash) - return hash - sd->s_hash; - if (ns != sd->s_ns) - return ns - sd->s_ns; - return strcmp(name, sd->s_name); + if (hash != kn->s_hash) + return hash - kn->s_hash; + if (ns != kn->s_ns) + return ns - kn->s_ns; + return strcmp(name, kn->s_name); } -static int sysfs_sd_compare(const struct sysfs_dirent *left, - const struct sysfs_dirent *right) +static int sysfs_sd_compare(const struct kernfs_node *left, + const struct kernfs_node *right) { return sysfs_name_compare(left->s_hash, left->s_name, left->s_ns, right); } /** - * sysfs_link_sibling - link sysfs_dirent into sibling rbtree - * @sd: sysfs_dirent of interest + * sysfs_link_sibling - link kernfs_node into sibling rbtree + * @kn: kernfs_node of interest * - * Link @sd into its sibling rbtree which starts from - * sd->s_parent->s_dir.children. + * Link @kn into its sibling rbtree which starts from + * @kn->s_parent->s_dir.children. * * Locking: * mutex_lock(sysfs_mutex) @@ -74,21 +74,21 @@ static int sysfs_sd_compare(const struct sysfs_dirent *left, * RETURNS: * 0 on susccess -EEXIST on failure. */ -static int sysfs_link_sibling(struct sysfs_dirent *sd) +static int sysfs_link_sibling(struct kernfs_node *kn) { - struct rb_node **node = &sd->s_parent->s_dir.children.rb_node; + struct rb_node **node = &kn->s_parent->s_dir.children.rb_node; struct rb_node *parent = NULL; - if (sysfs_type(sd) == SYSFS_DIR) - sd->s_parent->s_dir.subdirs++; + if (sysfs_type(kn) == SYSFS_DIR) + kn->s_parent->s_dir.subdirs++; while (*node) { - struct sysfs_dirent *pos; + struct kernfs_node *pos; int result; - pos = to_sysfs_dirent(*node); + pos = rb_to_kn(*node); parent = *node; - result = sysfs_sd_compare(sd, pos); + result = sysfs_sd_compare(kn, pos); if (result < 0) node = &pos->s_rb.rb_left; else if (result > 0) @@ -97,168 +97,169 @@ static int sysfs_link_sibling(struct sysfs_dirent *sd) return -EEXIST; } /* add new node and rebalance the tree */ - rb_link_node(&sd->s_rb, parent, node); - rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children); + rb_link_node(&kn->s_rb, parent, node); + rb_insert_color(&kn->s_rb, &kn->s_parent->s_dir.children); return 0; } /** - * sysfs_unlink_sibling - unlink sysfs_dirent from sibling rbtree - * @sd: sysfs_dirent of interest + * sysfs_unlink_sibling - unlink kernfs_node from sibling rbtree + * @kn: kernfs_node of interest * - * Unlink @sd from its sibling rbtree which starts from - * sd->s_parent->s_dir.children. + * Unlink @kn from its sibling rbtree which starts from + * kn->s_parent->s_dir.children. * * Locking: * mutex_lock(sysfs_mutex) */ -static void sysfs_unlink_sibling(struct sysfs_dirent *sd) +static void sysfs_unlink_sibling(struct kernfs_node *kn) { - if (sysfs_type(sd) == SYSFS_DIR) - sd->s_parent->s_dir.subdirs--; + if (sysfs_type(kn) == SYSFS_DIR) + kn->s_parent->s_dir.subdirs--; - rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); + rb_erase(&kn->s_rb, &kn->s_parent->s_dir.children); } /** - * sysfs_get_active - get an active reference to sysfs_dirent - * @sd: sysfs_dirent to get an active reference to + * sysfs_get_active - get an active reference to kernfs_node + * @kn: kernfs_node to get an active reference to * - * Get an active reference of @sd. This function is noop if @sd + * Get an active reference of @kn. This function is noop if @kn * is NULL. * * RETURNS: - * Pointer to @sd on success, NULL on failure. + * Pointer to @kn on success, NULL on failure. */ -struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) +struct kernfs_node *sysfs_get_active(struct kernfs_node *kn) { - if (unlikely(!sd)) + if (unlikely(!kn)) return NULL; - if (!atomic_inc_unless_negative(&sd->s_active)) + if (!atomic_inc_unless_negative(&kn->s_active)) return NULL; - if (sd->s_flags & SYSFS_FLAG_LOCKDEP) - rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); - return sd; + if (kn->s_flags & SYSFS_FLAG_LOCKDEP) + rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_); + return kn; } /** - * sysfs_put_active - put an active reference to sysfs_dirent - * @sd: sysfs_dirent to put an active reference to + * sysfs_put_active - put an active reference to kernfs_node + * @kn: kernfs_node to put an active reference to * - * Put an active reference to @sd. This function is noop if @sd + * Put an active reference to @kn. This function is noop if @kn * is NULL. */ -void sysfs_put_active(struct sysfs_dirent *sd) +void sysfs_put_active(struct kernfs_node *kn) { int v; - if (unlikely(!sd)) + if (unlikely(!kn)) return; - if (sd->s_flags & SYSFS_FLAG_LOCKDEP) - rwsem_release(&sd->dep_map, 1, _RET_IP_); - v = atomic_dec_return(&sd->s_active); + if (kn->s_flags & SYSFS_FLAG_LOCKDEP) + rwsem_release(&kn->dep_map, 1, _RET_IP_); + v = atomic_dec_return(&kn->s_active); if (likely(v != SD_DEACTIVATED_BIAS)) return; - /* atomic_dec_return() is a mb(), we'll always see the updated - * sd->u.completion. + /* + * atomic_dec_return() is a mb(), we'll always see the updated + * kn->u.completion. */ - complete(sd->u.completion); + complete(kn->u.completion); } /** - * sysfs_deactivate - deactivate sysfs_dirent - * @sd: sysfs_dirent to deactivate + * sysfs_deactivate - deactivate kernfs_node + * @kn: kernfs_node to deactivate * * Deny new active references and drain existing ones. */ -static void sysfs_deactivate(struct sysfs_dirent *sd) +static void sysfs_deactivate(struct kernfs_node *kn) { DECLARE_COMPLETION_ONSTACK(wait); int v; - BUG_ON(!(sd->s_flags & SYSFS_FLAG_REMOVED)); + BUG_ON(!(kn->s_flags & SYSFS_FLAG_REMOVED)); - if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF)) + if (!(sysfs_type(kn) & SYSFS_ACTIVE_REF)) return; - sd->u.completion = (void *)&wait; + kn->u.completion = (void *)&wait; - rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); + rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); /* atomic_add_return() is a mb(), put_active() will always see - * the updated sd->u.completion. + * the updated kn->u.completion. */ - v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active); + v = atomic_add_return(SD_DEACTIVATED_BIAS, &kn->s_active); if (v != SD_DEACTIVATED_BIAS) { - lock_contended(&sd->dep_map, _RET_IP_); + lock_contended(&kn->dep_map, _RET_IP_); wait_for_completion(&wait); } - lock_acquired(&sd->dep_map, _RET_IP_); - rwsem_release(&sd->dep_map, 1, _RET_IP_); + lock_acquired(&kn->dep_map, _RET_IP_); + rwsem_release(&kn->dep_map, 1, _RET_IP_); } /** - * kernfs_get - get a reference count on a sysfs_dirent - * @sd: the target sysfs_dirent + * kernfs_get - get a reference count on a kernfs_node + * @kn: the target kernfs_node */ -void kernfs_get(struct sysfs_dirent *sd) +void kernfs_get(struct kernfs_node *kn) { - if (sd) { - WARN_ON(!atomic_read(&sd->s_count)); - atomic_inc(&sd->s_count); + if (kn) { + WARN_ON(!atomic_read(&kn->s_count)); + atomic_inc(&kn->s_count); } } EXPORT_SYMBOL_GPL(kernfs_get); /** - * kernfs_put - put a reference count on a sysfs_dirent - * @sd: the target sysfs_dirent + * kernfs_put - put a reference count on a kernfs_node + * @kn: the target kernfs_node * - * Put a reference count of @sd and destroy it if it reached zero. + * Put a reference count of @kn and destroy it if it reached zero. */ -void kernfs_put(struct sysfs_dirent *sd) +void kernfs_put(struct kernfs_node *kn) { - struct sysfs_dirent *parent_sd; + struct kernfs_node *parent; struct kernfs_root *root; - if (!sd || !atomic_dec_and_test(&sd->s_count)) + if (!kn || !atomic_dec_and_test(&kn->s_count)) return; - root = kernfs_root(sd); + root = kernfs_root(kn); repeat: /* Moving/renaming is always done while holding reference. - * sd->s_parent won't change beneath us. + * kn->s_parent won't change beneath us. */ - parent_sd = sd->s_parent; + parent = kn->s_parent; - WARN(!(sd->s_flags & SYSFS_FLAG_REMOVED), + WARN(!(kn->s_flags & SYSFS_FLAG_REMOVED), "sysfs: free using entry: %s/%s\n", - parent_sd ? parent_sd->s_name : "", sd->s_name); - - if (sysfs_type(sd) == SYSFS_KOBJ_LINK) - kernfs_put(sd->s_symlink.target_sd); - if (sysfs_type(sd) & SYSFS_COPY_NAME) - kfree(sd->s_name); - if (sd->s_iattr) { - if (sd->s_iattr->ia_secdata) - security_release_secctx(sd->s_iattr->ia_secdata, - sd->s_iattr->ia_secdata_len); - simple_xattrs_free(&sd->s_iattr->xattrs); + parent ? parent->s_name : "", kn->s_name); + + if (sysfs_type(kn) == SYSFS_KOBJ_LINK) + kernfs_put(kn->s_symlink.target_kn); + if (sysfs_type(kn) & SYSFS_COPY_NAME) + kfree(kn->s_name); + if (kn->s_iattr) { + if (kn->s_iattr->ia_secdata) + security_release_secctx(kn->s_iattr->ia_secdata, + kn->s_iattr->ia_secdata_len); + simple_xattrs_free(&kn->s_iattr->xattrs); } - kfree(sd->s_iattr); - ida_simple_remove(&root->ino_ida, sd->s_ino); - kmem_cache_free(sysfs_dir_cachep, sd); + kfree(kn->s_iattr); + ida_simple_remove(&root->ino_ida, kn->s_ino); + kmem_cache_free(sysfs_dir_cachep, kn); - sd = parent_sd; - if (sd) { - if (atomic_dec_and_test(&sd->s_count)) + kn = parent; + if (kn) { + if (atomic_dec_and_test(&kn->s_count)) goto repeat; } else { - /* just released the root sd, free @root too */ + /* just released the root kn, free @root too */ ida_destroy(&root->ino_ida); kfree(root); } @@ -267,35 +268,35 @@ EXPORT_SYMBOL_GPL(kernfs_put); static int sysfs_dentry_delete(const struct dentry *dentry) { - struct sysfs_dirent *sd = dentry->d_fsdata; - return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED)); + struct kernfs_node *kn = dentry->d_fsdata; + return !(kn && !(kn->s_flags & SYSFS_FLAG_REMOVED)); } static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; if (flags & LOOKUP_RCU) return -ECHILD; - sd = dentry->d_fsdata; + kn = dentry->d_fsdata; mutex_lock(&sysfs_mutex); /* The sysfs dirent has been deleted */ - if (sd->s_flags & SYSFS_FLAG_REMOVED) + if (kn->s_flags & SYSFS_FLAG_REMOVED) goto out_bad; /* The sysfs dirent has been moved? */ - if (dentry->d_parent->d_fsdata != sd->s_parent) + if (dentry->d_parent->d_fsdata != kn->s_parent) goto out_bad; /* The sysfs dirent has been renamed */ - if (strcmp(dentry->d_name.name, sd->s_name) != 0) + if (strcmp(dentry->d_name.name, kn->s_name) != 0) goto out_bad; /* The sysfs dirent has been moved to a different namespace */ - if (sd->s_parent && kernfs_ns_enabled(sd->s_parent) && - sysfs_info(dentry->d_sb)->ns != sd->s_ns) + if (kn->s_parent && kernfs_ns_enabled(kn->s_parent) && + sysfs_info(dentry->d_sb)->ns != kn->s_ns) goto out_bad; mutex_unlock(&sysfs_mutex); @@ -335,11 +336,11 @@ const struct dentry_operations sysfs_dentry_ops = { .d_release = sysfs_dentry_release, }; -struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root, - const char *name, umode_t mode, int type) +struct kernfs_node *sysfs_new_dirent(struct kernfs_root *root, + const char *name, umode_t mode, int type) { char *dup_name = NULL; - struct sysfs_dirent *sd; + struct kernfs_node *kn; int ret; if (type & SYSFS_COPY_NAME) { @@ -348,38 +349,38 @@ struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root, return NULL; } - sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); - if (!sd) + kn = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); + if (!kn) goto err_out1; ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL); if (ret < 0) goto err_out2; - sd->s_ino = ret; + kn->s_ino = ret; - atomic_set(&sd->s_count, 1); - atomic_set(&sd->s_active, 0); + atomic_set(&kn->s_count, 1); + atomic_set(&kn->s_active, 0); - sd->s_name = name; - sd->s_mode = mode; - sd->s_flags = type | SYSFS_FLAG_REMOVED; + kn->s_name = name; + kn->s_mode = mode; + kn->s_flags = type | SYSFS_FLAG_REMOVED; - return sd; + return kn; err_out2: - kmem_cache_free(sysfs_dir_cachep, sd); + kmem_cache_free(sysfs_dir_cachep, kn); err_out1: kfree(dup_name); return NULL; } /** - * sysfs_addrm_start - prepare for sysfs_dirent add/remove + * sysfs_addrm_start - prepare for kernfs_node add/remove * @acxt: pointer to sysfs_addrm_cxt to be used * * This function is called when the caller is about to add or remove - * sysfs_dirent. This function acquires sysfs_mutex. @acxt is used - * to keep and pass context to other addrm functions. + * kernfs_node. This function acquires sysfs_mutex. @acxt is used to + * keep and pass context to other addrm functions. * * LOCKING: * Kernel thread context (may sleep). sysfs_mutex is locked on @@ -394,13 +395,13 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt) } /** - * sysfs_add_one - add sysfs_dirent to parent without warning + * sysfs_add_one - add kernfs_node to parent without warning * @acxt: addrm context to use - * @sd: sysfs_dirent to be added - * @parent_sd: the parent sysfs_dirent to add @sd to + * @kn: kernfs_node to be added + * @parent: the parent kernfs_node to add @kn to * - * Get @parent_sd and set @sd->s_parent to it and increment nlink of - * the parent inode if @sd is a directory and link into the children + * Get @parent and set @kn->s_parent to it and increment nlink of + * the parent inode if @kn is a directory and link into the children * list of the parent. * * This function should be called between calls to @@ -414,51 +415,51 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt) * 0 on success, -EEXIST if entry with the given name already * exists. */ -int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, - struct sysfs_dirent *parent_sd) +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct kernfs_node *kn, + struct kernfs_node *parent) { - bool has_ns = kernfs_ns_enabled(parent_sd); + bool has_ns = kernfs_ns_enabled(parent); struct sysfs_inode_attrs *ps_iattr; int ret; - if (has_ns != (bool)sd->s_ns) { + if (has_ns != (bool)kn->s_ns) { WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", has_ns ? "required" : "invalid", - parent_sd->s_name, sd->s_name); + parent->s_name, kn->s_name); return -EINVAL; } - if (sysfs_type(parent_sd) != SYSFS_DIR) + if (sysfs_type(parent) != SYSFS_DIR) return -EINVAL; - sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); - sd->s_parent = parent_sd; - kernfs_get(parent_sd); + kn->s_hash = sysfs_name_hash(kn->s_name, kn->s_ns); + kn->s_parent = parent; + kernfs_get(parent); - ret = sysfs_link_sibling(sd); + ret = sysfs_link_sibling(kn); if (ret) return ret; /* Update timestamps on the parent */ - ps_iattr = parent_sd->s_iattr; + ps_iattr = parent->s_iattr; if (ps_iattr) { struct iattr *ps_iattrs = &ps_iattr->ia_iattr; ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; } /* Mark the entry added into directory tree */ - sd->s_flags &= ~SYSFS_FLAG_REMOVED; + kn->s_flags &= ~SYSFS_FLAG_REMOVED; return 0; } /** - * sysfs_remove_one - remove sysfs_dirent from parent + * sysfs_remove_one - remove kernfs_node from parent * @acxt: addrm context to use - * @sd: sysfs_dirent to be removed + * @kn: kernfs_node to be removed * - * Mark @sd removed and drop nlink of parent inode if @sd is a - * directory. @sd is unlinked from the children list. + * Mark @kn removed and drop nlink of parent inode if @kn is a + * directory. @kn is unlinked from the children list. * * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be @@ -468,7 +469,7 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, * Determined by sysfs_addrm_start(). */ static void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, - struct sysfs_dirent *sd) + struct kernfs_node *kn) { struct sysfs_inode_attrs *ps_iattr; @@ -476,31 +477,31 @@ static void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, * Removal can be called multiple times on the same node. Only the * first invocation is effective and puts the base ref. */ - if (sd->s_flags & SYSFS_FLAG_REMOVED) + if (kn->s_flags & SYSFS_FLAG_REMOVED) return; - if (sd->s_parent) { - sysfs_unlink_sibling(sd); + if (kn->s_parent) { + sysfs_unlink_sibling(kn); /* Update timestamps on the parent */ - ps_iattr = sd->s_parent->s_iattr; + ps_iattr = kn->s_parent->s_iattr; if (ps_iattr) { ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; } } - sd->s_flags |= SYSFS_FLAG_REMOVED; - sd->u.removed_list = acxt->removed; - acxt->removed = sd; + kn->s_flags |= SYSFS_FLAG_REMOVED; + kn->u.removed_list = acxt->removed; + acxt->removed = kn; } /** - * sysfs_addrm_finish - finish up sysfs_dirent add/remove + * sysfs_addrm_finish - finish up kernfs_node add/remove * @acxt: addrm context to finish up * - * Finish up sysfs_dirent add/remove. Resources acquired by - * sysfs_addrm_start() are released and removed sysfs_dirents are + * Finish up kernfs_node add/remove. Resources acquired by + * sysfs_addrm_start() are released and removed kernfs_nodes are * cleaned up. * * LOCKING: @@ -512,30 +513,30 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) /* release resources acquired by sysfs_addrm_start() */ mutex_unlock(&sysfs_mutex); - /* kill removed sysfs_dirents */ + /* kill removed kernfs_nodes */ while (acxt->removed) { - struct sysfs_dirent *sd = acxt->removed; + struct kernfs_node *kn = acxt->removed; - acxt->removed = sd->u.removed_list; + acxt->removed = kn->u.removed_list; - sysfs_deactivate(sd); - sysfs_unmap_bin_file(sd); - kernfs_put(sd); + sysfs_deactivate(kn); + sysfs_unmap_bin_file(kn); + kernfs_put(kn); } } /** - * kernfs_find_ns - find sysfs_dirent with the given name - * @parent: sysfs_dirent to search under + * kernfs_find_ns - find kernfs_node with the given name + * @parent: kernfs_node to search under * @name: name to look for * @ns: the namespace tag to use * - * Look for sysfs_dirent with name @name under @parent. Returns pointer to - * the found sysfs_dirent on success, %NULL on failure. + * Look for kernfs_node with name @name under @parent. Returns pointer to + * the found kernfs_node on success, %NULL on failure. */ -static struct sysfs_dirent *kernfs_find_ns(struct sysfs_dirent *parent, - const unsigned char *name, - const void *ns) +static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent, + const unsigned char *name, + const void *ns) { struct rb_node *node = parent->s_dir.children.rb_node; bool has_ns = kernfs_ns_enabled(parent); @@ -552,42 +553,42 @@ static struct sysfs_dirent *kernfs_find_ns(struct sysfs_dirent *parent, hash = sysfs_name_hash(name, ns); while (node) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; int result; - sd = to_sysfs_dirent(node); - result = sysfs_name_compare(hash, name, ns, sd); + kn = rb_to_kn(node); + result = sysfs_name_compare(hash, name, ns, kn); if (result < 0) node = node->rb_left; else if (result > 0) node = node->rb_right; else - return sd; + return kn; } return NULL; } /** - * kernfs_find_and_get_ns - find and get sysfs_dirent with the given name - * @parent: sysfs_dirent to search under + * kernfs_find_and_get_ns - find and get kernfs_node with the given name + * @parent: kernfs_node to search under * @name: name to look for * @ns: the namespace tag to use * - * Look for sysfs_dirent with name @name under @parent and get a reference + * Look for kernfs_node with name @name under @parent and get a reference * if found. This function may sleep and returns pointer to the found - * sysfs_dirent on success, %NULL on failure. + * kernfs_node on success, %NULL on failure. */ -struct sysfs_dirent *kernfs_find_and_get_ns(struct sysfs_dirent *parent, - const char *name, const void *ns) +struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, + const char *name, const void *ns) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; mutex_lock(&sysfs_mutex); - sd = kernfs_find_ns(parent, name, ns); - kernfs_get(sd); + kn = kernfs_find_ns(parent, name, ns); + kernfs_get(kn); mutex_unlock(&sysfs_mutex); - return sd; + return kn; } EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns); @@ -601,7 +602,7 @@ EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns); struct kernfs_root *kernfs_create_root(void *priv) { struct kernfs_root *root; - struct sysfs_dirent *sd; + struct kernfs_node *kn; root = kzalloc(sizeof(*root), GFP_KERNEL); if (!root) @@ -609,18 +610,18 @@ struct kernfs_root *kernfs_create_root(void *priv) ida_init(&root->ino_ida); - sd = sysfs_new_dirent(root, "", S_IFDIR | S_IRUGO | S_IXUGO, SYSFS_DIR); - if (!sd) { + kn = sysfs_new_dirent(root, "", S_IFDIR | S_IRUGO | S_IXUGO, SYSFS_DIR); + if (!kn) { ida_destroy(&root->ino_ida); kfree(root); return ERR_PTR(-ENOMEM); } - sd->s_flags &= ~SYSFS_FLAG_REMOVED; - sd->priv = priv; - sd->s_dir.root = root; + kn->s_flags &= ~SYSFS_FLAG_REMOVED; + kn->priv = priv; + kn->s_dir.root = root; - root->sd = sd; + root->kn = kn; return root; } @@ -634,7 +635,7 @@ struct kernfs_root *kernfs_create_root(void *priv) */ void kernfs_destroy_root(struct kernfs_root *root) { - kernfs_remove(root->sd); /* will also free @root */ + kernfs_remove(root->kn); /* will also free @root */ } /** @@ -646,33 +647,33 @@ void kernfs_destroy_root(struct kernfs_root *root) * * Returns the created node on success, ERR_PTR() value on failure. */ -struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent, - const char *name, void *priv, - const void *ns) +struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, + const char *name, void *priv, + const void *ns) { umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; struct sysfs_addrm_cxt acxt; - struct sysfs_dirent *sd; + struct kernfs_node *kn; int rc; /* allocate */ - sd = sysfs_new_dirent(kernfs_root(parent), name, mode, SYSFS_DIR); - if (!sd) + kn = sysfs_new_dirent(kernfs_root(parent), name, mode, SYSFS_DIR); + if (!kn) return ERR_PTR(-ENOMEM); - sd->s_dir.root = parent->s_dir.root; - sd->s_ns = ns; - sd->priv = priv; + kn->s_dir.root = parent->s_dir.root; + kn->s_ns = ns; + kn->priv = priv; /* link in */ sysfs_addrm_start(&acxt); - rc = sysfs_add_one(&acxt, sd, parent); + rc = sysfs_add_one(&acxt, kn, parent); sysfs_addrm_finish(&acxt); if (!rc) - return sd; + return kn; - kernfs_put(sd); + kernfs_put(kn); return ERR_PTR(rc); } @@ -680,29 +681,28 @@ static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct dentry *ret = NULL; - struct dentry *parent = dentry->d_parent; - struct sysfs_dirent *parent_sd = parent->d_fsdata; - struct sysfs_dirent *sd; + struct kernfs_node *parent = dentry->d_parent->d_fsdata; + struct kernfs_node *kn; struct inode *inode; const void *ns = NULL; mutex_lock(&sysfs_mutex); - if (kernfs_ns_enabled(parent_sd)) + if (kernfs_ns_enabled(parent)) ns = sysfs_info(dir->i_sb)->ns; - sd = kernfs_find_ns(parent_sd, dentry->d_name.name, ns); + kn = kernfs_find_ns(parent, dentry->d_name.name, ns); /* no such entry */ - if (!sd) { + if (!kn) { ret = ERR_PTR(-ENOENT); goto out_unlock; } - kernfs_get(sd); - dentry->d_fsdata = sd; + kernfs_get(kn); + dentry->d_fsdata = kn; /* attach dentry and inode */ - inode = sysfs_get_inode(dir->i_sb, sd); + inode = sysfs_get_inode(dir->i_sb, kn); if (!inode) { ret = ERR_PTR(-ENOMEM); goto out_unlock; @@ -726,9 +726,9 @@ const struct inode_operations sysfs_dir_inode_operations = { .listxattr = sysfs_listxattr, }; -static struct sysfs_dirent *sysfs_leftmost_descendant(struct sysfs_dirent *pos) +static struct kernfs_node *sysfs_leftmost_descendant(struct kernfs_node *pos) { - struct sysfs_dirent *last; + struct kernfs_node *last; while (true) { struct rb_node *rbn; @@ -742,7 +742,7 @@ static struct sysfs_dirent *sysfs_leftmost_descendant(struct sysfs_dirent *pos) if (!rbn) break; - pos = to_sysfs_dirent(rbn); + pos = rb_to_kn(rbn); } return last; @@ -751,14 +751,14 @@ static struct sysfs_dirent *sysfs_leftmost_descendant(struct sysfs_dirent *pos) /** * sysfs_next_descendant_post - find the next descendant for post-order walk * @pos: the current position (%NULL to initiate traversal) - * @root: sysfs_dirent whose descendants to walk + * @root: kernfs_node whose descendants to walk * * Find the next descendant to visit for post-order traversal of @root's * descendants. @root is included in the iteration and the last node to be * visited. */ -static struct sysfs_dirent *sysfs_next_descendant_post(struct sysfs_dirent *pos, - struct sysfs_dirent *root) +static struct kernfs_node *sysfs_next_descendant_post(struct kernfs_node *pos, + struct kernfs_node *root) { struct rb_node *rbn; @@ -775,62 +775,62 @@ static struct sysfs_dirent *sysfs_next_descendant_post(struct sysfs_dirent *pos, /* if there's an unvisited sibling, visit its leftmost descendant */ rbn = rb_next(&pos->s_rb); if (rbn) - return sysfs_leftmost_descendant(to_sysfs_dirent(rbn)); + return sysfs_leftmost_descendant(rb_to_kn(rbn)); /* no sibling left, visit parent */ return pos->s_parent; } static void __kernfs_remove(struct sysfs_addrm_cxt *acxt, - struct sysfs_dirent *sd) + struct kernfs_node *kn) { - struct sysfs_dirent *pos, *next; + struct kernfs_node *pos, *next; - if (!sd) + if (!kn) return; - pr_debug("sysfs %s: removing\n", sd->s_name); + pr_debug("sysfs %s: removing\n", kn->s_name); next = NULL; do { pos = next; - next = sysfs_next_descendant_post(pos, sd); + next = sysfs_next_descendant_post(pos, kn); if (pos) sysfs_remove_one(acxt, pos); } while (next); } /** - * kernfs_remove - remove a sysfs_dirent recursively - * @sd: the sysfs_dirent to remove + * kernfs_remove - remove a kernfs_node recursively + * @kn: the kernfs_node to remove * - * Remove @sd along with all its subdirectories and files. + * Remove @kn along with all its subdirectories and files. */ -void kernfs_remove(struct sysfs_dirent *sd) +void kernfs_remove(struct kernfs_node *kn) { struct sysfs_addrm_cxt acxt; sysfs_addrm_start(&acxt); - __kernfs_remove(&acxt, sd); + __kernfs_remove(&acxt, kn); sysfs_addrm_finish(&acxt); } /** - * kernfs_remove_by_name_ns - find a sysfs_dirent by name and remove it - * @dir_sd: parent of the target - * @name: name of the sysfs_dirent to remove - * @ns: namespace tag of the sysfs_dirent to remove + * kernfs_remove_by_name_ns - find a kernfs_node by name and remove it + * @parent: parent of the target + * @name: name of the kernfs_node to remove + * @ns: namespace tag of the kernfs_node to remove * - * Look for the sysfs_dirent with @name and @ns under @dir_sd and remove - * it. Returns 0 on success, -ENOENT if such entry doesn't exist. + * Look for the kernfs_node with @name and @ns under @parent and remove it. + * Returns 0 on success, -ENOENT if such entry doesn't exist. */ -int kernfs_remove_by_name_ns(struct sysfs_dirent *dir_sd, const char *name, +int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, const void *ns) { struct sysfs_addrm_cxt acxt; - struct sysfs_dirent *sd; + struct kernfs_node *kn; - if (!dir_sd) { + if (!parent) { WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n", name); return -ENOENT; @@ -838,13 +838,13 @@ int kernfs_remove_by_name_ns(struct sysfs_dirent *dir_sd, const char *name, sysfs_addrm_start(&acxt); - sd = kernfs_find_ns(dir_sd, name, ns); - if (sd) - __kernfs_remove(&acxt, sd); + kn = kernfs_find_ns(parent, name, ns); + if (kn) + __kernfs_remove(&acxt, kn); sysfs_addrm_finish(&acxt); - if (sd) + if (kn) return 0; else return -ENOENT; @@ -852,12 +852,12 @@ int kernfs_remove_by_name_ns(struct sysfs_dirent *dir_sd, const char *name, /** * kernfs_rename_ns - move and rename a kernfs_node - * @sd: target node + * @kn: target node * @new_parent: new parent to put @sd under * @new_name: new name * @new_ns: new namespace tag */ -int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent, +int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, const char *new_name, const void *new_ns) { int error; @@ -865,35 +865,35 @@ int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent, mutex_lock(&sysfs_mutex); error = 0; - if ((sd->s_parent == new_parent) && (sd->s_ns == new_ns) && - (strcmp(sd->s_name, new_name) == 0)) + if ((kn->s_parent == new_parent) && (kn->s_ns == new_ns) && + (strcmp(kn->s_name, new_name) == 0)) goto out; /* nothing to rename */ error = -EEXIST; if (kernfs_find_ns(new_parent, new_name, new_ns)) goto out; - /* rename sysfs_dirent */ - if (strcmp(sd->s_name, new_name) != 0) { + /* rename kernfs_node */ + if (strcmp(kn->s_name, new_name) != 0) { error = -ENOMEM; new_name = kstrdup(new_name, GFP_KERNEL); if (!new_name) goto out; - kfree(sd->s_name); - sd->s_name = new_name; + kfree(kn->s_name); + kn->s_name = new_name; } /* * Move to the appropriate place in the appropriate directories rbtree. */ - sysfs_unlink_sibling(sd); + sysfs_unlink_sibling(kn); kernfs_get(new_parent); - kernfs_put(sd->s_parent); - sd->s_ns = new_ns; - sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); - sd->s_parent = new_parent; - sysfs_link_sibling(sd); + kernfs_put(kn->s_parent); + kn->s_ns = new_ns; + kn->s_hash = sysfs_name_hash(kn->s_name, kn->s_ns); + kn->s_parent = new_parent; + sysfs_link_sibling(kn); error = 0; out: @@ -902,9 +902,9 @@ int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent, } /* Relationship between s_mode and the DT_xxx types */ -static inline unsigned char dt_type(struct sysfs_dirent *sd) +static inline unsigned char dt_type(struct kernfs_node *kn) { - return (sd->s_mode >> 12) & 15; + return (kn->s_mode >> 12) & 15; } static int sysfs_dir_release(struct inode *inode, struct file *filp) @@ -913,21 +913,21 @@ static int sysfs_dir_release(struct inode *inode, struct file *filp) return 0; } -static struct sysfs_dirent *sysfs_dir_pos(const void *ns, - struct sysfs_dirent *parent_sd, loff_t hash, struct sysfs_dirent *pos) +static struct kernfs_node *sysfs_dir_pos(const void *ns, + struct kernfs_node *parent, loff_t hash, struct kernfs_node *pos) { if (pos) { int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && - pos->s_parent == parent_sd && + pos->s_parent == parent && hash == pos->s_hash; kernfs_put(pos); if (!valid) pos = NULL; } if (!pos && (hash > 1) && (hash < INT_MAX)) { - struct rb_node *node = parent_sd->s_dir.children.rb_node; + struct rb_node *node = parent->s_dir.children.rb_node; while (node) { - pos = to_sysfs_dirent(node); + pos = rb_to_kn(node); if (hash < pos->s_hash) node = node->rb_left; @@ -943,22 +943,22 @@ static struct sysfs_dirent *sysfs_dir_pos(const void *ns, if (!node) pos = NULL; else - pos = to_sysfs_dirent(node); + pos = rb_to_kn(node); } return pos; } -static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, - struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) +static struct kernfs_node *sysfs_dir_next_pos(const void *ns, + struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos) { - pos = sysfs_dir_pos(ns, parent_sd, ino, pos); + pos = sysfs_dir_pos(ns, parent, ino, pos); if (pos) do { struct rb_node *node = rb_next(&pos->s_rb); if (!node) pos = NULL; else - pos = to_sysfs_dirent(node); + pos = rb_to_kn(node); } while (pos && pos->s_ns != ns); return pos; } @@ -966,20 +966,20 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, static int sysfs_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = file->f_path.dentry; - struct sysfs_dirent *parent_sd = dentry->d_fsdata; - struct sysfs_dirent *pos = file->private_data; + struct kernfs_node *parent = dentry->d_fsdata; + struct kernfs_node *pos = file->private_data; const void *ns = NULL; if (!dir_emit_dots(file, ctx)) return 0; mutex_lock(&sysfs_mutex); - if (kernfs_ns_enabled(parent_sd)) + if (kernfs_ns_enabled(parent)) ns = sysfs_info(dentry->d_sb)->ns; - for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); + for (pos = sysfs_dir_pos(ns, parent, ctx->pos, pos); pos; - pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { + pos = sysfs_dir_next_pos(ns, parent, ctx->pos, pos)) { const char *name = pos->s_name; unsigned int type = dt_type(pos); int len = strlen(name); diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index fa053151fa96..1bf07ded826a 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -19,9 +19,9 @@ /* * There's one sysfs_open_file for each open file and one sysfs_open_dirent - * for each sysfs_dirent with one or more open files. + * for each kernfs_node with one or more open files. * - * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open is + * kernfs_node->s_attr.open points to sysfs_open_dirent. s_attr.open is * protected by sysfs_open_dirent_lock. * * filp->private_data points to seq_file whose ->private points to @@ -44,14 +44,14 @@ static struct sysfs_open_file *sysfs_of(struct file *file) } /* - * Determine the kernfs_ops for the given sysfs_dirent. This function must + * Determine the kernfs_ops for the given kernfs_node. This function must * be called while holding an active reference. */ -static const struct kernfs_ops *kernfs_ops(struct sysfs_dirent *sd) +static const struct kernfs_ops *kernfs_ops(struct kernfs_node *kn) { - if (sd->s_flags & SYSFS_FLAG_LOCKDEP) - lockdep_assert_held(sd); - return sd->s_attr.ops; + if (kn->s_flags & SYSFS_FLAG_LOCKDEP) + lockdep_assert_held(kn); + return kn->s_attr.ops; } static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) @@ -64,10 +64,10 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) * the ops aren't called concurrently for the same open file. */ mutex_lock(&of->mutex); - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return ERR_PTR(-ENODEV); - ops = kernfs_ops(of->sd); + ops = kernfs_ops(of->kn); if (ops->seq_start) { return ops->seq_start(sf, ppos); } else { @@ -82,7 +82,7 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos) { struct sysfs_open_file *of = sf->private; - const struct kernfs_ops *ops = kernfs_ops(of->sd); + const struct kernfs_ops *ops = kernfs_ops(of->kn); if (ops->seq_next) { return ops->seq_next(sf, v, ppos); @@ -99,12 +99,12 @@ static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos) static void kernfs_seq_stop(struct seq_file *sf, void *v) { struct sysfs_open_file *of = sf->private; - const struct kernfs_ops *ops = kernfs_ops(of->sd); + const struct kernfs_ops *ops = kernfs_ops(of->kn); if (ops->seq_stop) ops->seq_stop(sf, v); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); mutex_unlock(&of->mutex); } @@ -112,9 +112,9 @@ static int kernfs_seq_show(struct seq_file *sf, void *v) { struct sysfs_open_file *of = sf->private; - of->event = atomic_read(&of->sd->s_attr.open->event); + of->event = atomic_read(&of->kn->s_attr.open->event); - return of->sd->s_attr.ops->seq_show(sf, v); + return of->kn->s_attr.ops->seq_show(sf, v); } static const struct seq_operations kernfs_seq_ops = { @@ -147,19 +147,19 @@ static ssize_t kernfs_file_direct_read(struct sysfs_open_file *of, * the ops aren't called concurrently for the same open file. */ mutex_lock(&of->mutex); - if (!sysfs_get_active(of->sd)) { + if (!sysfs_get_active(of->kn)) { len = -ENODEV; mutex_unlock(&of->mutex); goto out_free; } - ops = kernfs_ops(of->sd); + ops = kernfs_ops(of->kn); if (ops->read) len = ops->read(of, buf, len, *ppos); else len = -EINVAL; - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); mutex_unlock(&of->mutex); if (len < 0) @@ -189,7 +189,7 @@ static ssize_t kernfs_file_read(struct file *file, char __user *user_buf, { struct sysfs_open_file *of = sysfs_of(file); - if (of->sd->s_flags & SYSFS_FLAG_HAS_SEQ_SHOW) + if (of->kn->s_flags & SYSFS_FLAG_HAS_SEQ_SHOW) return seq_read(file, user_buf, count, ppos); else return kernfs_file_direct_read(of, user_buf, count, ppos); @@ -234,19 +234,19 @@ static ssize_t kernfs_file_write(struct file *file, const char __user *user_buf, * the ops aren't called concurrently for the same open file. */ mutex_lock(&of->mutex); - if (!sysfs_get_active(of->sd)) { + if (!sysfs_get_active(of->kn)) { mutex_unlock(&of->mutex); len = -ENODEV; goto out_free; } - ops = kernfs_ops(of->sd); + ops = kernfs_ops(of->kn); if (ops->write) len = ops->write(of, buf, len, *ppos); else len = -EINVAL; - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); mutex_unlock(&of->mutex); if (len > 0) @@ -264,13 +264,13 @@ static void kernfs_vma_open(struct vm_area_struct *vma) if (!of->vm_ops) return; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return; if (of->vm_ops->open) of->vm_ops->open(vma); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); } static int kernfs_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -282,14 +282,14 @@ static int kernfs_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) if (!of->vm_ops) return VM_FAULT_SIGBUS; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return VM_FAULT_SIGBUS; ret = VM_FAULT_SIGBUS; if (of->vm_ops->fault) ret = of->vm_ops->fault(vma, vmf); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); return ret; } @@ -303,7 +303,7 @@ static int kernfs_vma_page_mkwrite(struct vm_area_struct *vma, if (!of->vm_ops) return VM_FAULT_SIGBUS; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return VM_FAULT_SIGBUS; ret = 0; @@ -312,7 +312,7 @@ static int kernfs_vma_page_mkwrite(struct vm_area_struct *vma, else file_update_time(file); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); return ret; } @@ -326,14 +326,14 @@ static int kernfs_vma_access(struct vm_area_struct *vma, unsigned long addr, if (!of->vm_ops) return -EINVAL; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return -EINVAL; ret = -EINVAL; if (of->vm_ops->access) ret = of->vm_ops->access(vma, addr, buf, len, write); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); return ret; } @@ -348,14 +348,14 @@ static int kernfs_vma_set_policy(struct vm_area_struct *vma, if (!of->vm_ops) return 0; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return -EINVAL; ret = 0; if (of->vm_ops->set_policy) ret = of->vm_ops->set_policy(vma, new); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); return ret; } @@ -369,14 +369,14 @@ static struct mempolicy *kernfs_vma_get_policy(struct vm_area_struct *vma, if (!of->vm_ops) return vma->vm_policy; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return vma->vm_policy; pol = vma->vm_policy; if (of->vm_ops->get_policy) pol = of->vm_ops->get_policy(vma, addr); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); return pol; } @@ -391,14 +391,14 @@ static int kernfs_vma_migrate(struct vm_area_struct *vma, if (!of->vm_ops) return 0; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) return 0; ret = 0; if (of->vm_ops->migrate) ret = of->vm_ops->migrate(vma, from, to, flags); - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); return ret; } #endif @@ -428,16 +428,16 @@ static int kernfs_file_mmap(struct file *file, struct vm_area_struct *vma) * without grabbing @of->mutex by testing HAS_MMAP flag. See the * comment in kernfs_file_open() for more details. */ - if (!(of->sd->s_flags & SYSFS_FLAG_HAS_MMAP)) + if (!(of->kn->s_flags & SYSFS_FLAG_HAS_MMAP)) return -ENODEV; mutex_lock(&of->mutex); rc = -ENODEV; - if (!sysfs_get_active(of->sd)) + if (!sysfs_get_active(of->kn)) goto out_unlock; - ops = kernfs_ops(of->sd); + ops = kernfs_ops(of->kn); rc = ops->mmap(of, vma); /* @@ -465,7 +465,7 @@ static int kernfs_file_mmap(struct file *file, struct vm_area_struct *vma) of->vm_ops = vma->vm_ops; vma->vm_ops = &kernfs_vm_ops; out_put: - sysfs_put_active(of->sd); + sysfs_put_active(of->kn); out_unlock: mutex_unlock(&of->mutex); @@ -474,10 +474,10 @@ out_unlock: /** * sysfs_get_open_dirent - get or create sysfs_open_dirent - * @sd: target sysfs_dirent + * @kn: target kernfs_node * @of: sysfs_open_file for this instance of open * - * If @sd->s_attr.open exists, increment its reference count; + * If @kn->s_attr.open exists, increment its reference count; * otherwise, create one. @of is chained to the files list. * * LOCKING: @@ -486,7 +486,7 @@ out_unlock: * RETURNS: * 0 on success, -errno on failure. */ -static int sysfs_get_open_dirent(struct sysfs_dirent *sd, +static int sysfs_get_open_dirent(struct kernfs_node *kn, struct sysfs_open_file *of) { struct sysfs_open_dirent *od, *new_od = NULL; @@ -495,12 +495,12 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd, mutex_lock(&sysfs_open_file_mutex); spin_lock_irq(&sysfs_open_dirent_lock); - if (!sd->s_attr.open && new_od) { - sd->s_attr.open = new_od; + if (!kn->s_attr.open && new_od) { + kn->s_attr.open = new_od; new_od = NULL; } - od = sd->s_attr.open; + od = kn->s_attr.open; if (od) { atomic_inc(&od->refcnt); list_add_tail(&of->list, &od->files); @@ -528,19 +528,19 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd, /** * sysfs_put_open_dirent - put sysfs_open_dirent - * @sd: target sysfs_dirent + * @kn: target kernfs_nodet * @of: associated sysfs_open_file * - * Put @sd->s_attr.open and unlink @of from the files list. If + * Put @kn->s_attr.open and unlink @of from the files list. If * reference count reaches zero, disassociate and free it. * * LOCKING: * None. */ -static void sysfs_put_open_dirent(struct sysfs_dirent *sd, +static void sysfs_put_open_dirent(struct kernfs_node *kn, struct sysfs_open_file *of) { - struct sysfs_open_dirent *od = sd->s_attr.open; + struct sysfs_open_dirent *od = kn->s_attr.open; unsigned long flags; mutex_lock(&sysfs_open_file_mutex); @@ -550,7 +550,7 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd, list_del(&of->list); if (atomic_dec_and_test(&od->refcnt)) - sd->s_attr.open = NULL; + kn->s_attr.open = NULL; else od = NULL; @@ -562,16 +562,16 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd, static int kernfs_file_open(struct inode *inode, struct file *file) { - struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct kernfs_node *kn = file->f_path.dentry->d_fsdata; const struct kernfs_ops *ops; struct sysfs_open_file *of; bool has_read, has_write, has_mmap; int error = -EACCES; - if (!sysfs_get_active(attr_sd)) + if (!sysfs_get_active(kn)) return -ENODEV; - ops = kernfs_ops(attr_sd); + ops = kernfs_ops(kn); has_read = ops->seq_show || ops->read || ops->mmap; has_write = ops->write || ops->mmap; @@ -612,7 +612,7 @@ static int kernfs_file_open(struct inode *inode, struct file *file) else mutex_init(&of->mutex); - of->sd = attr_sd; + of->kn = kn; of->file = file; /* @@ -634,12 +634,12 @@ static int kernfs_file_open(struct inode *inode, struct file *file) file->f_mode |= FMODE_PWRITE; /* make sure we have open dirent struct */ - error = sysfs_get_open_dirent(attr_sd, of); + error = sysfs_get_open_dirent(kn, of); if (error) goto err_close; /* open succeeded, put active references */ - sysfs_put_active(attr_sd); + sysfs_put_active(kn); return 0; err_close: @@ -647,32 +647,32 @@ err_close: err_free: kfree(of); err_out: - sysfs_put_active(attr_sd); + sysfs_put_active(kn); return error; } static int kernfs_file_release(struct inode *inode, struct file *filp) { - struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata; + struct kernfs_node *kn = filp->f_path.dentry->d_fsdata; struct sysfs_open_file *of = sysfs_of(filp); - sysfs_put_open_dirent(sd, of); + sysfs_put_open_dirent(kn, of); seq_release(inode, filp); kfree(of); return 0; } -void sysfs_unmap_bin_file(struct sysfs_dirent *sd) +void sysfs_unmap_bin_file(struct kernfs_node *kn) { struct sysfs_open_dirent *od; struct sysfs_open_file *of; - if (!(sd->s_flags & SYSFS_FLAG_HAS_MMAP)) + if (!(kn->s_flags & SYSFS_FLAG_HAS_MMAP)) return; spin_lock_irq(&sysfs_open_dirent_lock); - od = sd->s_attr.open; + od = kn->s_attr.open; if (od) atomic_inc(&od->refcnt); spin_unlock_irq(&sysfs_open_dirent_lock); @@ -686,7 +686,7 @@ void sysfs_unmap_bin_file(struct sysfs_dirent *sd) } mutex_unlock(&sysfs_open_file_mutex); - sysfs_put_open_dirent(sd, NULL); + sysfs_put_open_dirent(kn, NULL); } /* Sysfs attribute files are pollable. The idea is that you read @@ -705,16 +705,16 @@ void sysfs_unmap_bin_file(struct sysfs_dirent *sd) static unsigned int kernfs_file_poll(struct file *filp, poll_table *wait) { struct sysfs_open_file *of = sysfs_of(filp); - struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; - struct sysfs_open_dirent *od = attr_sd->s_attr.open; + struct kernfs_node *kn = filp->f_path.dentry->d_fsdata; + struct sysfs_open_dirent *od = kn->s_attr.open; /* need parent for the kobj, grab both */ - if (!sysfs_get_active(attr_sd)) + if (!sysfs_get_active(kn)) goto trigger; poll_wait(filp, &od->poll, wait); - sysfs_put_active(attr_sd); + sysfs_put_active(kn); if (of->event != atomic_read(&od->event)) goto trigger; @@ -727,19 +727,19 @@ static unsigned int kernfs_file_poll(struct file *filp, poll_table *wait) /** * kernfs_notify - notify a kernfs file - * @sd: file to notify + * @kn: file to notify * - * Notify @sd such that poll(2) on @sd wakes up. + * Notify @kn such that poll(2) on @kn wakes up. */ -void kernfs_notify(struct sysfs_dirent *sd) +void kernfs_notify(struct kernfs_node *kn) { struct sysfs_open_dirent *od; unsigned long flags; spin_lock_irqsave(&sysfs_open_dirent_lock, flags); - if (!WARN_ON(sysfs_type(sd) != SYSFS_KOBJ_ATTR)) { - od = sd->s_attr.open; + if (!WARN_ON(sysfs_type(kn) != SYSFS_KOBJ_ATTR)) { + od = kn->s_attr.open; if (od) { atomic_inc(&od->event); wake_up_interruptible(&od->poll); @@ -773,51 +773,51 @@ const struct file_operations kernfs_file_operations = { * * Returns the created node on success, ERR_PTR() value on error. */ -struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent, - const char *name, - umode_t mode, loff_t size, - const struct kernfs_ops *ops, - void *priv, const void *ns, - struct lock_class_key *key) +struct kernfs_node *kernfs_create_file_ns_key(struct kernfs_node *parent, + const char *name, + umode_t mode, loff_t size, + const struct kernfs_ops *ops, + void *priv, const void *ns, + struct lock_class_key *key) { struct sysfs_addrm_cxt acxt; - struct sysfs_dirent *sd; + struct kernfs_node *kn; int rc; - sd = sysfs_new_dirent(kernfs_root(parent), name, + kn = sysfs_new_dirent(kernfs_root(parent), name, (mode & S_IALLUGO) | S_IFREG, SYSFS_KOBJ_ATTR); - if (!sd) + if (!kn) return ERR_PTR(-ENOMEM); - sd->s_attr.ops = ops; - sd->s_attr.size = size; - sd->s_ns = ns; - sd->priv = priv; + kn->s_attr.ops = ops; + kn->s_attr.size = size; + kn->s_ns = ns; + kn->priv = priv; #ifdef CONFIG_DEBUG_LOCK_ALLOC if (key) { - lockdep_init_map(&sd->dep_map, "s_active", key, 0); - sd->s_flags |= SYSFS_FLAG_LOCKDEP; + lockdep_init_map(&kn->dep_map, "s_active", key, 0); + kn->s_flags |= SYSFS_FLAG_LOCKDEP; } #endif /* - * sd->s_attr.ops is accesible only while holding active ref. We + * kn->s_attr.ops is accesible only while holding active ref. We * need to know whether some ops are implemented outside active * ref. Cache their existence in flags. */ if (ops->seq_show) - sd->s_flags |= SYSFS_FLAG_HAS_SEQ_SHOW; + kn->s_flags |= SYSFS_FLAG_HAS_SEQ_SHOW; if (ops->mmap) - sd->s_flags |= SYSFS_FLAG_HAS_MMAP; + kn->s_flags |= SYSFS_FLAG_HAS_MMAP; sysfs_addrm_start(&acxt); - rc = sysfs_add_one(&acxt, sd, parent); + rc = sysfs_add_one(&acxt, kn, parent); sysfs_addrm_finish(&acxt); if (rc) { - kernfs_put(sd); + kernfs_put(kn); return ERR_PTR(rc); } - return sd; + return kn; } diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 18ad431e8c2a..9e74eed63539 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -46,36 +46,36 @@ void __init sysfs_inode_init(void) panic("failed to init sysfs_backing_dev_info"); } -static struct sysfs_inode_attrs *sysfs_inode_attrs(struct sysfs_dirent *sd) +static struct sysfs_inode_attrs *sysfs_inode_attrs(struct kernfs_node *kn) { struct iattr *iattrs; - if (sd->s_iattr) - return sd->s_iattr; + if (kn->s_iattr) + return kn->s_iattr; - sd->s_iattr = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL); - if (!sd->s_iattr) + kn->s_iattr = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL); + if (!kn->s_iattr) return NULL; - iattrs = &sd->s_iattr->ia_iattr; + iattrs = &kn->s_iattr->ia_iattr; /* assign default attributes */ - iattrs->ia_mode = sd->s_mode; + iattrs->ia_mode = kn->s_mode; iattrs->ia_uid = GLOBAL_ROOT_UID; iattrs->ia_gid = GLOBAL_ROOT_GID; iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; - simple_xattrs_init(&sd->s_iattr->xattrs); + simple_xattrs_init(&kn->s_iattr->xattrs); - return sd->s_iattr; + return kn->s_iattr; } -static int __kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr) +static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) { struct sysfs_inode_attrs *attrs; struct iattr *iattrs; unsigned int ia_valid = iattr->ia_valid; - attrs = sysfs_inode_attrs(sd); + attrs = sysfs_inode_attrs(kn); if (!attrs) return -ENOMEM; @@ -93,24 +93,24 @@ static int __kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr) iattrs->ia_ctime = iattr->ia_ctime; if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; - iattrs->ia_mode = sd->s_mode = mode; + iattrs->ia_mode = kn->s_mode = mode; } return 0; } /** * kernfs_setattr - set iattr on a node - * @sd: target node + * @kn: target node * @iattr: iattr to set * * Returns 0 on success, -errno on failure. */ -int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr) +int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) { int ret; mutex_lock(&sysfs_mutex); - ret = __kernfs_setattr(sd, iattr); + ret = __kernfs_setattr(kn, iattr); mutex_unlock(&sysfs_mutex); return ret; } @@ -118,10 +118,10 @@ int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr) int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; - struct sysfs_dirent *sd = dentry->d_fsdata; + struct kernfs_node *kn = dentry->d_fsdata; int error; - if (!sd) + if (!kn) return -EINVAL; mutex_lock(&sysfs_mutex); @@ -129,7 +129,7 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) if (error) goto out; - error = __kernfs_setattr(sd, iattr); + error = __kernfs_setattr(kn, iattr); if (error) goto out; @@ -141,14 +141,14 @@ out: return error; } -static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, +static int sysfs_sd_setsecdata(struct kernfs_node *kn, void **secdata, u32 *secdata_len) { struct sysfs_inode_attrs *attrs; void *old_secdata; size_t old_secdata_len; - attrs = sysfs_inode_attrs(sd); + attrs = sysfs_inode_attrs(kn); if (!attrs) return -ENOMEM; @@ -166,13 +166,13 @@ static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - struct sysfs_dirent *sd = dentry->d_fsdata; + struct kernfs_node *kn = dentry->d_fsdata; struct sysfs_inode_attrs *attrs; void *secdata; int error; u32 secdata_len = 0; - attrs = sysfs_inode_attrs(sd); + attrs = sysfs_inode_attrs(kn); if (!attrs) return -ENOMEM; @@ -188,7 +188,7 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, return error; mutex_lock(&sysfs_mutex); - error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len); + error = sysfs_sd_setsecdata(kn, &secdata, &secdata_len); mutex_unlock(&sysfs_mutex); if (secdata) @@ -204,10 +204,10 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, int sysfs_removexattr(struct dentry *dentry, const char *name) { - struct sysfs_dirent *sd = dentry->d_fsdata; + struct kernfs_node *kn = dentry->d_fsdata; struct sysfs_inode_attrs *attrs; - attrs = sysfs_inode_attrs(sd); + attrs = sysfs_inode_attrs(kn); if (!attrs) return -ENOMEM; @@ -217,10 +217,10 @@ int sysfs_removexattr(struct dentry *dentry, const char *name) ssize_t sysfs_getxattr(struct dentry *dentry, const char *name, void *buf, size_t size) { - struct sysfs_dirent *sd = dentry->d_fsdata; + struct kernfs_node *kn = dentry->d_fsdata; struct sysfs_inode_attrs *attrs; - attrs = sysfs_inode_attrs(sd); + attrs = sysfs_inode_attrs(kn); if (!attrs) return -ENOMEM; @@ -229,10 +229,10 @@ ssize_t sysfs_getxattr(struct dentry *dentry, const char *name, void *buf, ssize_t sysfs_listxattr(struct dentry *dentry, char *buf, size_t size) { - struct sysfs_dirent *sd = dentry->d_fsdata; + struct kernfs_node *kn = dentry->d_fsdata; struct sysfs_inode_attrs *attrs; - attrs = sysfs_inode_attrs(sd); + attrs = sysfs_inode_attrs(kn); if (!attrs) return -ENOMEM; @@ -254,57 +254,58 @@ static inline void set_inode_attr(struct inode *inode, struct iattr *iattr) inode->i_ctime = iattr->ia_ctime; } -static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) +static void sysfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) { - struct sysfs_inode_attrs *attrs = sd->s_iattr; + struct sysfs_inode_attrs *attrs = kn->s_iattr; - inode->i_mode = sd->s_mode; + inode->i_mode = kn->s_mode; if (attrs) { - /* sysfs_dirent has non-default attributes - * get them from persistent copy in sysfs_dirent + /* + * kernfs_node has non-default attributes get them from + * persistent copy in kernfs_node. */ set_inode_attr(inode, &attrs->ia_iattr); security_inode_notifysecctx(inode, attrs->ia_secdata, attrs->ia_secdata_len); } - if (sysfs_type(sd) == SYSFS_DIR) - set_nlink(inode, sd->s_dir.subdirs + 2); + if (sysfs_type(kn) == SYSFS_DIR) + set_nlink(inode, kn->s_dir.subdirs + 2); } int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { - struct sysfs_dirent *sd = dentry->d_fsdata; + struct kernfs_node *kn = dentry->d_fsdata; struct inode *inode = dentry->d_inode; mutex_lock(&sysfs_mutex); - sysfs_refresh_inode(sd, inode); + sysfs_refresh_inode(kn, inode); mutex_unlock(&sysfs_mutex); generic_fillattr(inode, stat); return 0; } -static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) +static void sysfs_init_inode(struct kernfs_node *kn, struct inode *inode) { - kernfs_get(sd); - inode->i_private = sd; + kernfs_get(kn); + inode->i_private = kn; inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_op = &sysfs_inode_operations; - set_default_inode_attr(inode, sd->s_mode); - sysfs_refresh_inode(sd, inode); + set_default_inode_attr(inode, kn->s_mode); + sysfs_refresh_inode(kn, inode); /* initialize inode according to type */ - switch (sysfs_type(sd)) { + switch (sysfs_type(kn)) { case SYSFS_DIR: inode->i_op = &sysfs_dir_inode_operations; inode->i_fop = &sysfs_dir_operations; break; case SYSFS_KOBJ_ATTR: - inode->i_size = sd->s_attr.size; + inode->i_size = kn->s_attr.size; inode->i_fop = &kernfs_file_operations; break; case SYSFS_KOBJ_LINK: @@ -318,13 +319,13 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) } /** - * sysfs_get_inode - get inode for sysfs_dirent + * sysfs_get_inode - get inode for kernfs_node * @sb: super block - * @sd: sysfs_dirent to allocate inode for + * @kn: kernfs_node to allocate inode for * - * Get inode for @sd. If such inode doesn't exist, a new inode - * is allocated and basics are initialized. New inode is - * returned locked. + * Get inode for @kn. If such inode doesn't exist, a new inode is + * allocated and basics are initialized. New inode is returned + * locked. * * LOCKING: * Kernel thread context (may sleep). @@ -332,44 +333,44 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) * RETURNS: * Pointer to allocated inode on success, NULL on failure. */ -struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd) +struct inode *sysfs_get_inode(struct super_block *sb, struct kernfs_node *kn) { struct inode *inode; - inode = iget_locked(sb, sd->s_ino); + inode = iget_locked(sb, kn->s_ino); if (inode && (inode->i_state & I_NEW)) - sysfs_init_inode(sd, inode); + sysfs_init_inode(kn, inode); return inode; } /* - * The sysfs_dirent serves as both an inode and a directory entry for sysfs. - * To prevent the sysfs inode numbers from being freed prematurely we take a - * reference to sysfs_dirent from the sysfs inode. A + * The kernfs_node serves as both an inode and a directory entry for sysfs. + * To prevent the sysfs inode numbers from being freed prematurely we take + * a reference to kernfs_node from the sysfs inode. A * super_operations.evict_inode() implementation is needed to drop that * reference upon inode destruction. */ void sysfs_evict_inode(struct inode *inode) { - struct sysfs_dirent *sd = inode->i_private; + struct kernfs_node *kn = inode->i_private; truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); - kernfs_put(sd); + kernfs_put(kn); } int sysfs_permission(struct inode *inode, int mask) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; if (mask & MAY_NOT_BLOCK) return -ECHILD; - sd = inode->i_private; + kn = inode->i_private; mutex_lock(&sysfs_mutex); - sysfs_refresh_inode(sd, inode); + sysfs_refresh_inode(kn, inode); mutex_unlock(&sysfs_mutex); return generic_permission(inode, mask); diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 910e485b7333..b7ea76c6fb33 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -31,24 +31,24 @@ struct sysfs_inode_attrs { /* SYSFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ /** - * kernfs_root - find out the kernfs_root a sysfs_dirent belongs to - * @sd: sysfs_dirent of interest + * kernfs_root - find out the kernfs_root a kernfs_node belongs to + * @kn: kernfs_node of interest * - * Return the kernfs_root @sd belongs to. + * Return the kernfs_root @kn belongs to. */ -static inline struct kernfs_root *kernfs_root(struct sysfs_dirent *sd) +static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) { /* if parent exists, it's always a dir; otherwise, @sd is a dir */ - if (sd->s_parent) - sd = sd->s_parent; - return sd->s_dir.root; + if (kn->s_parent) + kn = kn->s_parent; + return kn->s_dir.root; } /* * Context structure to be used while adding/removing nodes. */ struct sysfs_addrm_cxt { - struct sysfs_dirent *removed; + struct kernfs_node *removed; }; /* @@ -62,10 +62,10 @@ struct sysfs_super_info { struct kernfs_root *root; /* - * Each sb is associated with one namespace tag, currently the network - * namespace of the task which mounted this sysfs instance. If multiple - * tags become necessary, make the following an array and compare - * sysfs_dirent tag against every entry. + * Each sb is associated with one namespace tag, currently the + * network namespace of the task which mounted this sysfs instance. + * If multiple tags become necessary, make the following an array + * and compare kernfs_node tag against every entry. */ const void *ns; }; @@ -76,7 +76,7 @@ extern struct kmem_cache *sysfs_dir_cachep; /* * inode.c */ -struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); +struct inode *sysfs_get_inode(struct super_block *sb, struct kernfs_node *kn); void sysfs_evict_inode(struct inode *inode); int sysfs_permission(struct inode *inode, int mask); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); @@ -98,21 +98,21 @@ extern const struct dentry_operations sysfs_dentry_ops; extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; -struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); -void sysfs_put_active(struct sysfs_dirent *sd); +struct kernfs_node *sysfs_get_active(struct kernfs_node *kn); +void sysfs_put_active(struct kernfs_node *kn); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt); -int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, - struct sysfs_dirent *parent_sd); +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct kernfs_node *kn, + struct kernfs_node *parent); void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); -struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root, - const char *name, umode_t mode, int type); +struct kernfs_node *sysfs_new_dirent(struct kernfs_root *root, + const char *name, umode_t mode, int type); /* * file.c */ extern const struct file_operations kernfs_file_operations; -void sysfs_unmap_bin_file(struct sysfs_dirent *sd); +void sysfs_unmap_bin_file(struct kernfs_node *kn); /* * symlink.c diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index 84c83e24bf25..9dbbf37b1af9 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -39,7 +39,7 @@ static int sysfs_fill_super(struct super_block *sb) /* get root inode, initialize and unlock it */ mutex_lock(&sysfs_mutex); - inode = sysfs_get_inode(sb, info->root->sd); + inode = sysfs_get_inode(sb, info->root->kn); mutex_unlock(&sysfs_mutex); if (!inode) { pr_debug("sysfs: could not get root inode\n"); @@ -52,8 +52,8 @@ static int sysfs_fill_super(struct super_block *sb) pr_debug("%s: could not get root dentry!\n", __func__); return -ENOMEM; } - kernfs_get(info->root->sd); - root->d_fsdata = info->root->sd; + kernfs_get(info->root->kn); + root->d_fsdata = info->root->kn; sb->s_root = root; sb->s_d_op = &sysfs_dentry_ops; return 0; @@ -145,7 +145,7 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, void kernfs_kill_sb(struct super_block *sb) { struct sysfs_super_info *info = sysfs_info(sb); - struct sysfs_dirent *root_sd = sb->s_root->d_fsdata; + struct kernfs_node *root_kn = sb->s_root->d_fsdata; /* * Remove the superblock from fs_supers/s_instances @@ -153,13 +153,13 @@ void kernfs_kill_sb(struct super_block *sb) */ kill_anon_super(sb); kfree(info); - kernfs_put(root_sd); + kernfs_put(root_kn); } void __init kernfs_init(void) { sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache", - sizeof(struct sysfs_dirent), + sizeof(struct kernfs_node), 0, SLAB_PANIC, NULL); sysfs_inode_init(); } diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index adf28755b0ee..29dcf5e8debd 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -22,50 +22,50 @@ * * Returns the created node on success, ERR_PTR() value on error. */ -struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, - const char *name, - struct sysfs_dirent *target) +struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, + const char *name, + struct kernfs_node *target) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; struct sysfs_addrm_cxt acxt; int error; - sd = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, + kn = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); - if (!sd) + if (!kn) return ERR_PTR(-ENOMEM); if (kernfs_ns_enabled(parent)) - sd->s_ns = target->s_ns; - sd->s_symlink.target_sd = target; + kn->s_ns = target->s_ns; + kn->s_symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ sysfs_addrm_start(&acxt); - error = sysfs_add_one(&acxt, sd, parent); + error = sysfs_add_one(&acxt, kn, parent); sysfs_addrm_finish(&acxt); if (!error) - return sd; + return kn; - kernfs_put(sd); + kernfs_put(kn); return ERR_PTR(error); } -static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, - struct sysfs_dirent *target_sd, char *path) +static int sysfs_get_target_path(struct kernfs_node *parent, + struct kernfs_node *target, char *path) { - struct sysfs_dirent *base, *sd; + struct kernfs_node *base, *kn; char *s = path; int len = 0; /* go up to the root, stop at the base */ - base = parent_sd; + base = parent; while (base->s_parent) { - sd = target_sd->s_parent; - while (sd->s_parent && base != sd) - sd = sd->s_parent; + kn = target->s_parent; + while (kn->s_parent && base != kn) + kn = kn->s_parent; - if (base == sd) + if (base == kn) break; strcpy(s, "../"); @@ -74,10 +74,10 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, } /* determine end of target string for reverse fillup */ - sd = target_sd; - while (sd->s_parent && sd != base) { - len += strlen(sd->s_name) + 1; - sd = sd->s_parent; + kn = target; + while (kn->s_parent && kn != base) { + len += strlen(kn->s_name) + 1; + kn = kn->s_parent; } /* check limits */ @@ -88,16 +88,16 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, return -ENAMETOOLONG; /* reverse fillup of target string from target to base */ - sd = target_sd; - while (sd->s_parent && sd != base) { - int slen = strlen(sd->s_name); + kn = target; + while (kn->s_parent && kn != base) { + int slen = strlen(kn->s_name); len -= slen; - strncpy(s + len, sd->s_name, slen); + strncpy(s + len, kn->s_name, slen); if (len) s[--len] = '/'; - sd = sd->s_parent; + kn = kn->s_parent; } return 0; @@ -105,13 +105,13 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, static int sysfs_getlink(struct dentry *dentry, char *path) { - struct sysfs_dirent *sd = dentry->d_fsdata; - struct sysfs_dirent *parent_sd = sd->s_parent; - struct sysfs_dirent *target_sd = sd->s_symlink.target_sd; + struct kernfs_node *kn = dentry->d_fsdata; + struct kernfs_node *parent = kn->s_parent; + struct kernfs_node *target = kn->s_symlink.target_kn; int error; mutex_lock(&sysfs_mutex); - error = sysfs_get_target_path(parent_sd, target_sd, path); + error = sysfs_get_target_path(parent, target, path); mutex_unlock(&sysfs_mutex); return error; diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 2fea501889e7..f1efe3df0de6 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -21,23 +21,23 @@ DEFINE_SPINLOCK(sysfs_symlink_target_lock); /** * sysfs_pathname - return full path to sysfs dirent - * @sd: sysfs_dirent whose path we want + * @kn: kernfs_node whose path we want * @path: caller allocated buffer of size PATH_MAX * * Gives the name "/" to the sysfs_root entry; any path returned * is relative to wherever sysfs is mounted. */ -static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) +static char *sysfs_pathname(struct kernfs_node *kn, char *path) { - if (sd->s_parent) { - sysfs_pathname(sd->s_parent, path); + if (kn->s_parent) { + sysfs_pathname(kn->s_parent, path); strlcat(path, "/", PATH_MAX); } - strlcat(path, sd->s_name, PATH_MAX); + strlcat(path, kn->s_name, PATH_MAX); return path; } -void sysfs_warn_dup(struct sysfs_dirent *parent, const char *name) +void sysfs_warn_dup(struct kernfs_node *parent, const char *name) { char *path; @@ -61,26 +61,26 @@ void sysfs_warn_dup(struct sysfs_dirent *parent, const char *name) */ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) { - struct sysfs_dirent *parent_sd, *sd; + struct kernfs_node *parent, *kn; BUG_ON(!kobj); if (kobj->parent) - parent_sd = kobj->parent->sd; + parent = kobj->parent->sd; else - parent_sd = sysfs_root_sd; + parent = sysfs_root_kn; - if (!parent_sd) + if (!parent) return -ENOENT; - sd = kernfs_create_dir_ns(parent_sd, kobject_name(kobj), kobj, ns); - if (IS_ERR(sd)) { - if (PTR_ERR(sd) == -EEXIST) - sysfs_warn_dup(parent_sd, kobject_name(kobj)); - return PTR_ERR(sd); + kn = kernfs_create_dir_ns(parent, kobject_name(kobj), kobj, ns); + if (IS_ERR(kn)) { + if (PTR_ERR(kn) == -EEXIST) + sysfs_warn_dup(parent, kobject_name(kobj)); + return PTR_ERR(kn); } - kobj->sd = sd; + kobj->sd = kn; return 0; } @@ -94,47 +94,47 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) */ void sysfs_remove_dir(struct kobject *kobj) { - struct sysfs_dirent *sd = kobj->sd; + struct kernfs_node *kn = kobj->sd; /* * In general, kboject owner is responsible for ensuring removal * doesn't race with other operations and sysfs doesn't provide any * protection; however, when @kobj is used as a symlink target, the * symlinking entity usually doesn't own @kobj and thus has no - * control over removal. @kobj->sd may be removed anytime and - * symlink code may end up dereferencing an already freed sd. + * control over removal. @kobj->sd may be removed anytime + * and symlink code may end up dereferencing an already freed node. * - * sysfs_symlink_target_lock synchronizes @kobj->sd disassociation - * against symlink operations so that symlink code can safely - * dereference @kobj->sd. + * sysfs_symlink_target_lock synchronizes @kobj->sd + * disassociation against symlink operations so that symlink code + * can safely dereference @kobj->sd. */ spin_lock(&sysfs_symlink_target_lock); kobj->sd = NULL; spin_unlock(&sysfs_symlink_target_lock); - if (sd) { - WARN_ON_ONCE(sysfs_type(sd) != SYSFS_DIR); - kernfs_remove(sd); + if (kn) { + WARN_ON_ONCE(sysfs_type(kn) != SYSFS_DIR); + kernfs_remove(kn); } } int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, const void *new_ns) { - struct sysfs_dirent *parent_sd = kobj->sd->s_parent; + struct kernfs_node *parent = kobj->sd->s_parent; - return kernfs_rename_ns(kobj->sd, parent_sd, new_name, new_ns); + return kernfs_rename_ns(kobj->sd, parent, new_name, new_ns); } int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj, const void *new_ns) { - struct sysfs_dirent *sd = kobj->sd; - struct sysfs_dirent *new_parent_sd; + struct kernfs_node *kn = kobj->sd; + struct kernfs_node *new_parent; - BUG_ON(!sd->s_parent); - new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? - new_parent_kobj->sd : sysfs_root_sd; + BUG_ON(!kn->s_parent); + new_parent = new_parent_kobj && new_parent_kobj->sd ? + new_parent_kobj->sd : sysfs_root_kn; - return kernfs_rename_ns(sd, new_parent_sd, sd->s_name, new_ns); + return kernfs_rename_ns(kn, new_parent, kn->s_name, new_ns); } diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index a67d1c682fed..be1cc39035bd 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -22,15 +22,15 @@ #include "../kernfs/kernfs-internal.h" /* - * Determine ktype->sysfs_ops for the given sysfs_dirent. This function + * Determine ktype->sysfs_ops for the given kernfs_node. This function * must be called while holding an active reference. */ -static const struct sysfs_ops *sysfs_file_ops(struct sysfs_dirent *sd) +static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn) { - struct kobject *kobj = sd->s_parent->priv; + struct kobject *kobj = kn->s_parent->priv; - if (sd->s_flags & SYSFS_FLAG_LOCKDEP) - lockdep_assert_held(sd); + if (kn->s_flags & SYSFS_FLAG_LOCKDEP) + lockdep_assert_held(kn); return kobj->ktype ? kobj->ktype->sysfs_ops : NULL; } @@ -42,8 +42,8 @@ static const struct sysfs_ops *sysfs_file_ops(struct sysfs_dirent *sd) static int sysfs_kf_seq_show(struct seq_file *sf, void *v) { struct sysfs_open_file *of = sf->private; - struct kobject *kobj = of->sd->s_parent->priv; - const struct sysfs_ops *ops = sysfs_file_ops(of->sd); + struct kobject *kobj = of->kn->s_parent->priv; + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); ssize_t count; char *buf; @@ -59,7 +59,7 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v) * if @ops->show() isn't implemented. */ if (ops->show) { - count = ops->show(kobj, of->sd->priv, buf); + count = ops->show(kobj, of->kn->priv, buf); if (count < 0) return count; } @@ -81,8 +81,8 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v) static ssize_t sysfs_kf_bin_read(struct sysfs_open_file *of, char *buf, size_t count, loff_t pos) { - struct bin_attribute *battr = of->sd->priv; - struct kobject *kobj = of->sd->s_parent->priv; + struct bin_attribute *battr = of->kn->priv; + struct kobject *kobj = of->kn->s_parent->priv; loff_t size = file_inode(of->file)->i_size; if (!count) @@ -105,21 +105,21 @@ static ssize_t sysfs_kf_bin_read(struct sysfs_open_file *of, char *buf, static ssize_t sysfs_kf_write(struct sysfs_open_file *of, char *buf, size_t count, loff_t pos) { - const struct sysfs_ops *ops = sysfs_file_ops(of->sd); - struct kobject *kobj = of->sd->s_parent->priv; + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); + struct kobject *kobj = of->kn->s_parent->priv; if (!count) return 0; - return ops->store(kobj, of->sd->priv, buf, count); + return ops->store(kobj, of->kn->priv, buf, count); } /* kernfs write callback for bin sysfs files */ static ssize_t sysfs_kf_bin_write(struct sysfs_open_file *of, char *buf, size_t count, loff_t pos) { - struct bin_attribute *battr = of->sd->priv; - struct kobject *kobj = of->sd->s_parent->priv; + struct bin_attribute *battr = of->kn->priv; + struct kobject *kobj = of->kn->s_parent->priv; loff_t size = file_inode(of->file)->i_size; if (size) { @@ -139,30 +139,30 @@ static ssize_t sysfs_kf_bin_write(struct sysfs_open_file *of, char *buf, static int sysfs_kf_bin_mmap(struct sysfs_open_file *of, struct vm_area_struct *vma) { - struct bin_attribute *battr = of->sd->priv; - struct kobject *kobj = of->sd->s_parent->priv; + struct bin_attribute *battr = of->kn->priv; + struct kobject *kobj = of->kn->s_parent->priv; return battr->mmap(of->file, kobj, battr, vma); } -void sysfs_notify(struct kobject *k, const char *dir, const char *attr) +void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr) { - struct sysfs_dirent *sd = k->sd, *tmp; + struct kernfs_node *kn = kobj->sd, *tmp; - if (sd && dir) - sd = kernfs_find_and_get(sd, dir); + if (kn && dir) + kn = kernfs_find_and_get(kn, dir); else - kernfs_get(sd); + kernfs_get(kn); - if (sd && attr) { - tmp = kernfs_find_and_get(sd, attr); - kernfs_put(sd); - sd = tmp; + if (kn && attr) { + tmp = kernfs_find_and_get(kn, attr); + kernfs_put(kn); + kn = tmp; } - if (sd) { - kernfs_notify(sd); - kernfs_put(sd); + if (kn) { + kernfs_notify(kn); + kernfs_put(kn); } } EXPORT_SYMBOL_GPL(sysfs_notify); @@ -202,17 +202,17 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = { .mmap = sysfs_kf_bin_mmap, }; -int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, +int sysfs_add_file_mode_ns(struct kernfs_node *parent, const struct attribute *attr, bool is_bin, umode_t mode, const void *ns) { struct lock_class_key *key = NULL; const struct kernfs_ops *ops; - struct sysfs_dirent *sd; + struct kernfs_node *kn; loff_t size; if (!is_bin) { - struct kobject *kobj = dir_sd->priv; + struct kobject *kobj = parent->priv; const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops; /* every kobject with an attribute needs a ktype assigned */ @@ -252,20 +252,20 @@ int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, if (!attr->ignore_lockdep) key = attr->key ?: (struct lock_class_key *)&attr->skey; #endif - sd = kernfs_create_file_ns_key(dir_sd, attr->name, mode, size, + kn = kernfs_create_file_ns_key(parent, attr->name, mode, size, ops, (void *)attr, ns, key); - if (IS_ERR(sd)) { - if (PTR_ERR(sd) == -EEXIST) - sysfs_warn_dup(dir_sd, attr->name); - return PTR_ERR(sd); + if (IS_ERR(kn)) { + if (PTR_ERR(kn) == -EEXIST) + sysfs_warn_dup(parent, attr->name); + return PTR_ERR(kn); } return 0; } -int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, +int sysfs_add_file(struct kernfs_node *parent, const struct attribute *attr, bool is_bin) { - return sysfs_add_file_mode_ns(dir_sd, attr, is_bin, attr->mode, NULL); + return sysfs_add_file_mode_ns(parent, attr, is_bin, attr->mode, NULL); } /** @@ -307,21 +307,21 @@ EXPORT_SYMBOL_GPL(sysfs_create_files); int sysfs_add_file_to_group(struct kobject *kobj, const struct attribute *attr, const char *group) { - struct sysfs_dirent *dir_sd; + struct kernfs_node *parent; int error; if (group) { - dir_sd = kernfs_find_and_get(kobj->sd, group); + parent = kernfs_find_and_get(kobj->sd, group); } else { - dir_sd = kobj->sd; - kernfs_get(dir_sd); + parent = kobj->sd; + kernfs_get(parent); } - if (!dir_sd) + if (!parent) return -ENOENT; - error = sysfs_add_file(dir_sd, attr, false); - kernfs_put(dir_sd); + error = sysfs_add_file(parent, attr, false); + kernfs_put(parent); return error; } @@ -337,20 +337,20 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, umode_t mode) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; struct iattr newattrs; int rc; - sd = kernfs_find_and_get(kobj->sd, attr->name); - if (!sd) + kn = kernfs_find_and_get(kobj->sd, attr->name); + if (!kn) return -ENOENT; - newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO); + newattrs.ia_mode = (mode & S_IALLUGO) | (kn->s_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE; - rc = kernfs_setattr(sd, &newattrs); + rc = kernfs_setattr(kn, &newattrs); - kernfs_put(sd); + kernfs_put(kn); return rc; } EXPORT_SYMBOL_GPL(sysfs_chmod_file); @@ -366,9 +366,9 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, const void *ns) { - struct sysfs_dirent *dir_sd = kobj->sd; + struct kernfs_node *parent = kobj->sd; - kernfs_remove_by_name_ns(dir_sd, attr->name, ns); + kernfs_remove_by_name_ns(parent, attr->name, ns); } EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); @@ -389,18 +389,18 @@ EXPORT_SYMBOL_GPL(sysfs_remove_files); void sysfs_remove_file_from_group(struct kobject *kobj, const struct attribute *attr, const char *group) { - struct sysfs_dirent *dir_sd; + struct kernfs_node *parent; if (group) { - dir_sd = kernfs_find_and_get(kobj->sd, group); + parent = kernfs_find_and_get(kobj->sd, group); } else { - dir_sd = kobj->sd; - kernfs_get(dir_sd); + parent = kobj->sd; + kernfs_get(parent); } - if (dir_sd) { - kernfs_remove_by_name(dir_sd, attr->name); - kernfs_put(dir_sd); + if (parent) { + kernfs_remove_by_name(parent, attr->name); + kernfs_put(parent); } } EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 7177532b8f7b..4d00d3996477 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -18,7 +18,7 @@ #include "sysfs.h" -static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, +static void remove_files(struct kernfs_node *parent, struct kobject *kobj, const struct attribute_group *grp) { struct attribute *const *attr; @@ -26,13 +26,13 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, if (grp->attrs) for (attr = grp->attrs; *attr; attr++) - kernfs_remove_by_name(dir_sd, (*attr)->name); + kernfs_remove_by_name(parent, (*attr)->name); if (grp->bin_attrs) for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) sysfs_remove_bin_file(kobj, *bin_attr); } -static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, +static int create_files(struct kernfs_node *parent, struct kobject *kobj, const struct attribute_group *grp, int update) { struct attribute *const *attr; @@ -49,20 +49,20 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, * re-adding (if required) the file. */ if (update) - kernfs_remove_by_name(dir_sd, (*attr)->name); + kernfs_remove_by_name(parent, (*attr)->name); if (grp->is_visible) { mode = grp->is_visible(kobj, *attr, i); if (!mode) continue; } - error = sysfs_add_file_mode_ns(dir_sd, *attr, false, + error = sysfs_add_file_mode_ns(parent, *attr, false, (*attr)->mode | mode, NULL); if (unlikely(error)) break; } if (error) { - remove_files(dir_sd, kobj, grp); + remove_files(parent, kobj, grp); goto exit; } } @@ -76,7 +76,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, break; } if (error) - remove_files(dir_sd, kobj, grp); + remove_files(parent, kobj, grp); } exit: return error; @@ -86,7 +86,7 @@ exit: static int internal_create_group(struct kobject *kobj, int update, const struct attribute_group *grp) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; int error; BUG_ON(!kobj || (!update && !kobj->sd)); @@ -100,21 +100,21 @@ static int internal_create_group(struct kobject *kobj, int update, return -EINVAL; } if (grp->name) { - sd = kernfs_create_dir(kobj->sd, grp->name, kobj); - if (IS_ERR(sd)) { - if (PTR_ERR(sd) == -EEXIST) + kn = kernfs_create_dir(kobj->sd, grp->name, kobj); + if (IS_ERR(kn)) { + if (PTR_ERR(kn) == -EEXIST) sysfs_warn_dup(kobj->sd, grp->name); - return PTR_ERR(sd); + return PTR_ERR(kn); } } else - sd = kobj->sd; - kernfs_get(sd); - error = create_files(sd, kobj, grp, update); + kn = kobj->sd; + kernfs_get(kn); + error = create_files(kn, kobj, grp, update); if (error) { if (grp->name) - kernfs_remove(sd); + kernfs_remove(kn); } - kernfs_put(sd); + kernfs_put(kn); return error; } @@ -204,27 +204,27 @@ EXPORT_SYMBOL_GPL(sysfs_update_group); void sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp) { - struct sysfs_dirent *dir_sd = kobj->sd; - struct sysfs_dirent *sd; + struct kernfs_node *parent = kobj->sd; + struct kernfs_node *kn; if (grp->name) { - sd = kernfs_find_and_get(dir_sd, grp->name); - if (!sd) { - WARN(!sd, KERN_WARNING + kn = kernfs_find_and_get(parent, grp->name); + if (!kn) { + WARN(!kn, KERN_WARNING "sysfs group %p not found for kobject '%s'\n", grp, kobject_name(kobj)); return; } } else { - sd = dir_sd; - kernfs_get(sd); + kn = parent; + kernfs_get(kn); } - remove_files(sd, kobj, grp); + remove_files(kn, kobj, grp); if (grp->name) - kernfs_remove(sd); + kernfs_remove(kn); - kernfs_put(sd); + kernfs_put(kn); } EXPORT_SYMBOL_GPL(sysfs_remove_group); @@ -260,22 +260,22 @@ EXPORT_SYMBOL_GPL(sysfs_remove_groups); int sysfs_merge_group(struct kobject *kobj, const struct attribute_group *grp) { - struct sysfs_dirent *dir_sd; + struct kernfs_node *parent; int error = 0; struct attribute *const *attr; int i; - dir_sd = kernfs_find_and_get(kobj->sd, grp->name); - if (!dir_sd) + parent = kernfs_find_and_get(kobj->sd, grp->name); + if (!parent) return -ENOENT; for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr)) - error = sysfs_add_file(dir_sd, *attr, false); + error = sysfs_add_file(parent, *attr, false); if (error) { while (--i >= 0) - kernfs_remove_by_name(dir_sd, (*--attr)->name); + kernfs_remove_by_name(parent, (*--attr)->name); } - kernfs_put(dir_sd); + kernfs_put(parent); return error; } @@ -289,14 +289,14 @@ EXPORT_SYMBOL_GPL(sysfs_merge_group); void sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp) { - struct sysfs_dirent *dir_sd; + struct kernfs_node *parent; struct attribute *const *attr; - dir_sd = kernfs_find_and_get(kobj->sd, grp->name); - if (dir_sd) { + parent = kernfs_find_and_get(kobj->sd, grp->name); + if (parent) { for (attr = grp->attrs; *attr; ++attr) - kernfs_remove_by_name(dir_sd, (*attr)->name); - kernfs_put(dir_sd); + kernfs_remove_by_name(parent, (*attr)->name); + kernfs_put(parent); } } EXPORT_SYMBOL_GPL(sysfs_unmerge_group); @@ -311,15 +311,15 @@ EXPORT_SYMBOL_GPL(sysfs_unmerge_group); int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, struct kobject *target, const char *link_name) { - struct sysfs_dirent *dir_sd; + struct kernfs_node *parent; int error = 0; - dir_sd = kernfs_find_and_get(kobj->sd, group_name); - if (!dir_sd) + parent = kernfs_find_and_get(kobj->sd, group_name); + if (!parent) return -ENOENT; - error = sysfs_create_link_sd(dir_sd, target, link_name); - kernfs_put(dir_sd); + error = sysfs_create_link_sd(parent, target, link_name); + kernfs_put(parent); return error; } @@ -334,12 +334,12 @@ EXPORT_SYMBOL_GPL(sysfs_add_link_to_group); void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, const char *link_name) { - struct sysfs_dirent *dir_sd; + struct kernfs_node *parent; - dir_sd = kernfs_find_and_get(kobj->sd, group_name); - if (dir_sd) { - kernfs_remove_by_name(dir_sd, link_name); - kernfs_put(dir_sd); + parent = kernfs_find_and_get(kobj->sd, group_name); + if (parent) { + kernfs_remove_by_name(parent, link_name); + kernfs_put(parent); } } EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 8d075272cace..701a56f341c6 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -20,7 +20,7 @@ #include "sysfs.h" static struct kernfs_root *sysfs_root; -struct sysfs_dirent *sysfs_root_sd; +struct kernfs_node *sysfs_root_kn; static struct dentry *sysfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) @@ -66,7 +66,7 @@ int __init sysfs_init(void) if (IS_ERR(sysfs_root)) return PTR_ERR(sysfs_root); - sysfs_root_sd = sysfs_root->sd; + sysfs_root_kn = sysfs_root->kn; err = register_filesystem(&sysfs_fs_type); if (err) { diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 1b8c9ed8511a..4ed3d49ad279 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -18,66 +18,66 @@ #include "sysfs.h" -static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, - struct kobject *target, +static int sysfs_do_create_link_sd(struct kernfs_node *parent, + struct kobject *target_kobj, const char *name, int warn) { - struct sysfs_dirent *sd, *target_sd = NULL; + struct kernfs_node *kn, *target = NULL; - BUG_ON(!name || !parent_sd); + BUG_ON(!name || !parent); /* - * We don't own @target and it may be removed at any time. + * We don't own @target_kobj and it may be removed at any time. * Synchronize using sysfs_symlink_target_lock. See * sysfs_remove_dir() for details. */ spin_lock(&sysfs_symlink_target_lock); - if (target->sd) { - target_sd = target->sd; - kernfs_get(target_sd); + if (target_kobj->sd) { + target = target_kobj->sd; + kernfs_get(target); } spin_unlock(&sysfs_symlink_target_lock); - if (!target_sd) + if (!target) return -ENOENT; - sd = kernfs_create_link(parent_sd, name, target_sd); - kernfs_put(target_sd); + kn = kernfs_create_link(parent, name, target); + kernfs_put(target); - if (!IS_ERR(sd)) + if (!IS_ERR(kn)) return 0; - if (warn && PTR_ERR(sd) == -EEXIST) - sysfs_warn_dup(parent_sd, name); - return PTR_ERR(sd); + if (warn && PTR_ERR(kn) == -EEXIST) + sysfs_warn_dup(parent, name); + return PTR_ERR(kn); } /** * sysfs_create_link_sd - create symlink to a given object. - * @sd: directory we're creating the link in. + * @kn: directory we're creating the link in. * @target: object we're pointing to. * @name: name of the symlink. */ -int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target, +int sysfs_create_link_sd(struct kernfs_node *kn, struct kobject *target, const char *name) { - return sysfs_do_create_link_sd(sd, target, name, 1); + return sysfs_do_create_link_sd(kn, target, name, 1); } static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, const char *name, int warn) { - struct sysfs_dirent *parent_sd = NULL; + struct kernfs_node *parent = NULL; if (!kobj) - parent_sd = sysfs_root_sd; + parent = sysfs_root_kn; else - parent_sd = kobj->sd; + parent = kobj->sd; - if (!parent_sd) + if (!parent) return -EFAULT; - return sysfs_do_create_link_sd(parent_sd, target, name, warn); + return sysfs_do_create_link_sd(parent, target, name, warn); } /** @@ -141,14 +141,14 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, */ void sysfs_remove_link(struct kobject *kobj, const char *name) { - struct sysfs_dirent *parent_sd = NULL; + struct kernfs_node *parent = NULL; if (!kobj) - parent_sd = sysfs_root_sd; + parent = sysfs_root_kn; else - parent_sd = kobj->sd; + parent = kobj->sd; - kernfs_remove_by_name(parent_sd, name); + kernfs_remove_by_name(parent, name); } EXPORT_SYMBOL_GPL(sysfs_remove_link); @@ -165,33 +165,33 @@ EXPORT_SYMBOL_GPL(sysfs_remove_link); int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ, const char *old, const char *new, const void *new_ns) { - struct sysfs_dirent *parent_sd, *sd = NULL; + struct kernfs_node *parent, *kn = NULL; const void *old_ns = NULL; int result; if (!kobj) - parent_sd = sysfs_root_sd; + parent = sysfs_root_kn; else - parent_sd = kobj->sd; + parent = kobj->sd; if (targ->sd) old_ns = targ->sd->s_ns; result = -ENOENT; - sd = kernfs_find_and_get_ns(parent_sd, old, old_ns); - if (!sd) + kn = kernfs_find_and_get_ns(parent, old, old_ns); + if (!kn) goto out; result = -EINVAL; - if (sysfs_type(sd) != SYSFS_KOBJ_LINK) + if (sysfs_type(kn) != SYSFS_KOBJ_LINK) goto out; - if (sd->s_symlink.target_sd->priv != targ) + if (kn->s_symlink.target_kn->priv != targ) goto out; - result = kernfs_rename_ns(sd, parent_sd, new, new_ns); + result = kernfs_rename_ns(kn, parent, new, new_ns); out: - kernfs_put(sd); + kernfs_put(kn); return result; } EXPORT_SYMBOL_GPL(sysfs_rename_link_ns); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index c8e395b49330..0e2f1cccb812 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -16,28 +16,28 @@ /* * mount.c */ -extern struct sysfs_dirent *sysfs_root_sd; +extern struct kernfs_node *sysfs_root_kn; /* * dir.c */ extern spinlock_t sysfs_symlink_target_lock; -void sysfs_warn_dup(struct sysfs_dirent *parent, const char *name); +void sysfs_warn_dup(struct kernfs_node *parent, const char *name); /* * file.c */ -int sysfs_add_file(struct sysfs_dirent *dir_sd, +int sysfs_add_file(struct kernfs_node *parent, const struct attribute *attr, bool is_bin); -int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, +int sysfs_add_file_mode_ns(struct kernfs_node *parent, const struct attribute *attr, bool is_bin, umode_t amode, const void *ns); /* * symlink.c */ -int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target, +int sysfs_create_link_sd(struct kernfs_node *kn, struct kobject *target, const char *name); #endif /* __SYSFS_INTERNAL_H */ diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index d65541308419..195d1c6a8b0c 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -46,61 +46,61 @@ enum kernfs_node_flag { SYSFS_FLAG_LOCKDEP = 0x0100, }; -/* type-specific structures for sysfs_dirent->s_* union members */ -struct sysfs_elem_dir { +/* type-specific structures for kernfs_node union members */ +struct kernfs_elem_dir { unsigned long subdirs; - /* children rbtree starts here and goes through sd->s_rb */ + /* children rbtree starts here and goes through kn->s_rb */ struct rb_root children; /* * The kernfs hierarchy this directory belongs to. This fits - * better directly in sysfs_dirent but is here to save space. + * better directly in kernfs_node but is here to save space. */ struct kernfs_root *root; }; -struct sysfs_elem_symlink { - struct sysfs_dirent *target_sd; +struct kernfs_elem_symlink { + struct kernfs_node *target_kn; }; -struct sysfs_elem_attr { +struct kernfs_elem_attr { const struct kernfs_ops *ops; struct sysfs_open_dirent *open; loff_t size; }; /* - * sysfs_dirent - the building block of sysfs hierarchy. Each and every - * sysfs node is represented by single sysfs_dirent. Most fields are + * kernfs_node - the building block of kernfs hierarchy. Each and every + * kernfs node is represented by single kernfs_node. Most fields are * private to kernfs and shouldn't be accessed directly by kernfs users. * - * As long as s_count reference is held, the sysfs_dirent itself is - * accessible. Dereferencing s_elem or any other outer entity - * requires s_active reference. + * As long as s_count reference is held, the kernfs_node itself is + * accessible. Dereferencing elem or any other outer entity requires + * active reference. */ -struct sysfs_dirent { +struct kernfs_node { atomic_t s_count; atomic_t s_active; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif /* the following two fields are published */ - struct sysfs_dirent *s_parent; + struct kernfs_node *s_parent; const char *s_name; struct rb_node s_rb; union { struct completion *completion; - struct sysfs_dirent *removed_list; + struct kernfs_node *removed_list; } u; const void *s_ns; /* namespace tag */ unsigned int s_hash; /* ns + name hash */ union { - struct sysfs_elem_dir s_dir; - struct sysfs_elem_symlink s_symlink; - struct sysfs_elem_attr s_attr; + struct kernfs_elem_dir s_dir; + struct kernfs_elem_symlink s_symlink; + struct kernfs_elem_attr s_attr; }; void *priv; @@ -113,7 +113,7 @@ struct sysfs_dirent { struct kernfs_root { /* published fields */ - struct sysfs_dirent *sd; + struct kernfs_node *kn; /* private fields, do not use outside kernfs proper */ struct ida ino_ida; @@ -121,7 +121,7 @@ struct kernfs_root { struct sysfs_open_file { /* published fields */ - struct sysfs_dirent *sd; + struct kernfs_node *kn; struct file *file; /* private fields, do not use outside kernfs proper */ @@ -170,64 +170,64 @@ struct kernfs_ops { #ifdef CONFIG_SYSFS -static inline enum kernfs_node_type sysfs_type(struct sysfs_dirent *sd) +static inline enum kernfs_node_type sysfs_type(struct kernfs_node *kn) { - return sd->s_flags & SYSFS_TYPE_MASK; + return kn->s_flags & SYSFS_TYPE_MASK; } /** * kernfs_enable_ns - enable namespace under a directory - * @sd: directory of interest, should be empty + * @kn: directory of interest, should be empty * - * This is to be called right after @sd is created to enable namespace - * under it. All children of @sd must have non-NULL namespace tags and + * This is to be called right after @kn is created to enable namespace + * under it. All children of @kn must have non-NULL namespace tags and * only the ones which match the super_block's tag will be visible. */ -static inline void kernfs_enable_ns(struct sysfs_dirent *sd) +static inline void kernfs_enable_ns(struct kernfs_node *kn) { - WARN_ON_ONCE(sysfs_type(sd) != SYSFS_DIR); - WARN_ON_ONCE(!RB_EMPTY_ROOT(&sd->s_dir.children)); - sd->s_flags |= SYSFS_FLAG_NS; + WARN_ON_ONCE(sysfs_type(kn) != SYSFS_DIR); + WARN_ON_ONCE(!RB_EMPTY_ROOT(&kn->s_dir.children)); + kn->s_flags |= SYSFS_FLAG_NS; } /** * kernfs_ns_enabled - test whether namespace is enabled - * @sd: the node to test + * @kn: the node to test * * Test whether namespace filtering is enabled for the children of @ns. */ -static inline bool kernfs_ns_enabled(struct sysfs_dirent *sd) +static inline bool kernfs_ns_enabled(struct kernfs_node *kn) { - return sd->s_flags & SYSFS_FLAG_NS; + return kn->s_flags & SYSFS_FLAG_NS; } -struct sysfs_dirent *kernfs_find_and_get_ns(struct sysfs_dirent *parent, - const char *name, const void *ns); -void kernfs_get(struct sysfs_dirent *sd); -void kernfs_put(struct sysfs_dirent *sd); +struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, + const char *name, const void *ns); +void kernfs_get(struct kernfs_node *kn); +void kernfs_put(struct kernfs_node *kn); struct kernfs_root *kernfs_create_root(void *priv); void kernfs_destroy_root(struct kernfs_root *root); -struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent, - const char *name, void *priv, - const void *ns); -struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent, - const char *name, - umode_t mode, loff_t size, - const struct kernfs_ops *ops, - void *priv, const void *ns, - struct lock_class_key *key); -struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, - const char *name, - struct sysfs_dirent *target); -void kernfs_remove(struct sysfs_dirent *sd); -int kernfs_remove_by_name_ns(struct sysfs_dirent *parent, const char *name, +struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, + const char *name, void *priv, + const void *ns); +struct kernfs_node *kernfs_create_file_ns_key(struct kernfs_node *parent, + const char *name, + umode_t mode, loff_t size, + const struct kernfs_ops *ops, + void *priv, const void *ns, + struct lock_class_key *key); +struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, + const char *name, + struct kernfs_node *target); +void kernfs_remove(struct kernfs_node *kn); +int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, const void *ns); -int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent, +int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, const char *new_name, const void *new_ns); -int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr); -void kernfs_notify(struct sysfs_dirent *sd); +int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr); +void kernfs_notify(struct kernfs_node *kn); const void *kernfs_super_ns(struct super_block *sb); struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags, @@ -238,60 +238,60 @@ void kernfs_init(void); #else /* CONFIG_SYSFS */ -static inline enum kernfs_node_type sysfs_type(struct sysfs_dirent *sd) +static inline enum kernfs_node_type sysfs_type(struct kernfs_node *kn) { return 0; } /* whatever */ -static inline void kernfs_enable_ns(struct sysfs_dirent *sd) { } +static inline void kernfs_enable_ns(struct kernfs_node *kn) { } -static inline bool kernfs_ns_enabled(struct sysfs_dirent *sd) +static inline bool kernfs_ns_enabled(struct kernfs_node *kn) { return false; } -static inline struct sysfs_dirent * -kernfs_find_and_get_ns(struct sysfs_dirent *parent, const char *name, +static inline struct kernfs_node * +kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, const void *ns) { return NULL; } -static inline void kernfs_get(struct sysfs_dirent *sd) { } -static inline void kernfs_put(struct sysfs_dirent *sd) { } +static inline void kernfs_get(struct kernfs_node *kn) { } +static inline void kernfs_put(struct kernfs_node *kn) { } static inline struct kernfs_root *kernfs_create_root(void *priv) { return ERR_PTR(-ENOSYS); } static inline void kernfs_destroy_root(struct kernfs_root *root) { } -static inline struct sysfs_dirent * -kernfs_create_dir_ns(struct sysfs_dirent *parent, const char *name, void *priv, +static inline struct kernfs_node * +kernfs_create_dir_ns(struct kernfs_node *parent, const char *name, void *priv, const void *ns) { return ERR_PTR(-ENOSYS); } -static inline struct sysfs_dirent * -kernfs_create_file_ns_key(struct sysfs_dirent *parent, const char *name, +static inline struct kernfs_node * +kernfs_create_file_ns_key(struct kernfs_node *parent, const char *name, umode_t mode, loff_t size, const struct kernfs_ops *ops, void *priv, const void *ns, struct lock_class_key *key) { return ERR_PTR(-ENOSYS); } -static inline struct sysfs_dirent * -kernfs_create_link(struct sysfs_dirent *parent, const char *name, - struct sysfs_dirent *target) +static inline struct kernfs_node * +kernfs_create_link(struct kernfs_node *parent, const char *name, + struct kernfs_node *target) { return ERR_PTR(-ENOSYS); } -static inline void kernfs_remove(struct sysfs_dirent *sd) { } +static inline void kernfs_remove(struct kernfs_node *kn) { } -static inline int kernfs_remove_by_name_ns(struct sysfs_dirent *parent, +static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn, const char *name, const void *ns) { return -ENOSYS; } -static inline int kernfs_rename_ns(struct sysfs_dirent *sd, - struct sysfs_dirent *new_parent, +static inline int kernfs_rename_ns(struct kernfs_node *kn, + struct kernfs_node *new_parent, const char *new_name, const void *new_ns) { return -ENOSYS; } -static inline int kernfs_setattr(struct sysfs_dirent *sd, +static inline int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) { return -ENOSYS; } -static inline void kernfs_notify(struct sysfs_dirent *sd) { } +static inline void kernfs_notify(struct kernfs_node *kn) { } static inline const void *kernfs_super_ns(struct super_block *sb) { return NULL; } @@ -307,20 +307,20 @@ static inline void kernfs_init(void) { } #endif /* CONFIG_SYSFS */ -static inline struct sysfs_dirent * -kernfs_find_and_get(struct sysfs_dirent *sd, const char *name) +static inline struct kernfs_node * +kernfs_find_and_get(struct kernfs_node *kn, const char *name) { - return kernfs_find_and_get_ns(sd, name, NULL); + return kernfs_find_and_get_ns(kn, name, NULL); } -static inline struct sysfs_dirent * -kernfs_create_dir(struct sysfs_dirent *parent, const char *name, void *priv) +static inline struct kernfs_node * +kernfs_create_dir(struct kernfs_node *parent, const char *name, void *priv) { return kernfs_create_dir_ns(parent, name, priv, NULL); } -static inline struct sysfs_dirent * -kernfs_create_file_ns(struct sysfs_dirent *parent, const char *name, +static inline struct kernfs_node * +kernfs_create_file_ns(struct kernfs_node *parent, const char *name, umode_t mode, loff_t size, const struct kernfs_ops *ops, void *priv, const void *ns) { @@ -333,14 +333,14 @@ kernfs_create_file_ns(struct sysfs_dirent *parent, const char *name, ns, key); } -static inline struct sysfs_dirent * -kernfs_create_file(struct sysfs_dirent *parent, const char *name, umode_t mode, +static inline struct kernfs_node * +kernfs_create_file(struct kernfs_node *parent, const char *name, umode_t mode, loff_t size, const struct kernfs_ops *ops, void *priv) { return kernfs_create_file_ns(parent, name, mode, size, ops, priv, NULL); } -static inline int kernfs_remove_by_name(struct sysfs_dirent *parent, +static inline int kernfs_remove_by_name(struct kernfs_node *parent, const char *name) { return kernfs_remove_by_name_ns(parent, name, NULL); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index e7ba650086ce..926afb6f6b5f 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -64,7 +64,7 @@ struct kobject { struct kobject *parent; struct kset *kset; struct kobj_type *ktype; - struct sysfs_dirent *sd; + struct kernfs_node *sd; struct kref kref; #ifdef CONFIG_DEBUG_KOBJECT_RELEASE struct delayed_work release; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index cd8f90bf51a7..30b2ebee6439 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -438,26 +438,26 @@ static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL); } -static inline void sysfs_notify_dirent(struct sysfs_dirent *sd) +static inline void sysfs_notify_dirent(struct kernfs_node *kn) { - kernfs_notify(sd); + kernfs_notify(kn); } -static inline struct sysfs_dirent * -sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name) +static inline struct kernfs_node *sysfs_get_dirent(struct kernfs_node *parent, + const unsigned char *name) { - return kernfs_find_and_get(parent_sd, name); + return kernfs_find_and_get(parent, name); } -static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd) +static inline struct kernfs_node *sysfs_get(struct kernfs_node *kn) { - kernfs_get(sd); - return sd; + kernfs_get(kn); + return kn; } -static inline void sysfs_put(struct sysfs_dirent *sd) +static inline void sysfs_put(struct kernfs_node *kn) { - kernfs_put(sd); + kernfs_put(kn); } #endif /* _SYSFS_H_ */ diff --git a/lib/kobject.c b/lib/kobject.c index 94b321f4ac67..064451f2a6c3 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -556,7 +556,7 @@ out: */ void kobject_del(struct kobject *kobj) { - struct sysfs_dirent *sd; + struct kernfs_node *sd; if (!kobj) return; -- cgit v1.2.3 From 6d5b988e7dc56bb97c39bdcbc006fadcd6ca371b Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 5 Nov 2013 17:33:17 -0700 Subject: clk: tegra: implement a reset driver The Tegra CAR module implements both a clock and reset controller. So far, the driver exposes the clock feature via the common clock API and the reset feature using a custom API. This patch adds an implementation of the common reset framework API (include/linux/reset*.h). The legacy reset implementation will be removed once all drivers have been converted. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Acked-By: Peter De Schrijver --- drivers/clk/tegra/clk-tegra114.c | 3 ++- drivers/clk/tegra/clk-tegra124.c | 2 +- drivers/clk/tegra/clk-tegra20.c | 3 ++- drivers/clk/tegra/clk-tegra30.c | 3 ++- drivers/clk/tegra/clk.c | 50 +++++++++++++++++++++++++++++++++++++++- drivers/clk/tegra/clk.h | 2 +- 6 files changed, 57 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 29b912582e3d..90d9d25f2228 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1460,7 +1460,8 @@ static void __init tegra114_clock_init(struct device_node *np) return; } - clks = tegra_clk_init(TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_PERIPH_BANKS); + clks = tegra_clk_init(clk_base, TEGRA114_CLK_CLK_MAX, + TEGRA114_CLK_PERIPH_BANKS); if (!clks) return; diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 0ef4485e9b0a..aff86b5bc745 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1398,7 +1398,7 @@ static void __init tegra124_clock_init(struct device_node *np) return; } - clks = tegra_clk_init(TEGRA124_CLK_CLK_MAX, 6); + clks = tegra_clk_init(clk_base, TEGRA124_CLK_CLK_MAX, 6); if (!clks) return; diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index b3b7204acfe7..5a6a60d9443a 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1109,7 +1109,8 @@ static void __init tegra20_clock_init(struct device_node *np) BUG(); } - clks = tegra_clk_init(TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_PERIPH_BANKS); + clks = tegra_clk_init(clk_base, TEGRA20_CLK_CLK_MAX, + TEGRA20_CLK_PERIPH_BANKS); if (!clks) return; diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index dcb6843b3a89..2e47383418c8 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1427,7 +1427,8 @@ static void __init tegra30_clock_init(struct device_node *np) BUG(); } - clks = tegra_clk_init(TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_PERIPH_BANKS); + clks = tegra_clk_init(clk_base, TEGRA30_CLK_CLK_MAX, + TEGRA30_CLK_PERIPH_BANKS); if (!clks) return; diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index a12a5f5107ec..c0a7d7723510 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "clk.h" @@ -121,6 +123,35 @@ static struct tegra_clk_periph_regs periph_regs[] = { }, }; +static void __iomem *clk_base; + +static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + /* + * If peripheral is on the APB bus then we must read the APB bus to + * flush the write operation in apb bus. This will avoid peripheral + * access after disabling clock. Since the reset driver has no + * knowledge of which reset IDs represent which devices, simply do + * this all the time. + */ + tegra_read_chipid(); + + writel_relaxed(BIT(id % 32), + clk_base + periph_regs[id / 32].rst_set_reg); + + return 0; +} + +static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + writel_relaxed(BIT(id % 32), + clk_base + periph_regs[id / 32].rst_clr_reg); + + return 0; +} + struct tegra_clk_periph_regs *get_reg_bank(int clkid) { int reg_bank = clkid / 32; @@ -133,8 +164,10 @@ struct tegra_clk_periph_regs *get_reg_bank(int clkid) } } -struct clk ** __init tegra_clk_init(int num, int banks) +struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks) { + clk_base = regs; + if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) return NULL; @@ -203,6 +236,17 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, } } +static struct reset_control_ops rst_ops = { + .assert = tegra_clk_rst_assert, + .deassert = tegra_clk_rst_deassert, +}; + +static struct reset_controller_dev rst_ctlr = { + .ops = &rst_ops, + .owner = THIS_MODULE, + .of_reset_n_cells = 1, +}; + void __init tegra_add_of_provider(struct device_node *np) { int i; @@ -220,6 +264,10 @@ void __init tegra_add_of_provider(struct device_node *np) clk_data.clks = clks; clk_data.clk_num = clk_num; of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + rst_ctlr.of_node = np; + rst_ctlr.nr_resets = clk_num * 32; + reset_controller_register(&rst_ctlr); } void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 40fb011233c0..07c62f997371 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -597,7 +597,7 @@ void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, struct clk *clks[], int clk_max); struct tegra_clk_periph_regs *get_reg_bank(int clkid); -struct clk **tegra_clk_init(int num, int periph_banks); +struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); -- cgit v1.2.3 From 3127a6b2a2342ecd7d7579ccbf39b50908b9df02 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 15:56:58 -0700 Subject: pci: tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. The old Tegra-specific API used a struct clock to represent the module to reset. Some of the clocks retrieved during probe() were only used for reset purposes, and indeed aren't even true clocks. So, there's no need to get() them any more. Signed-off-by: Stephen Warren Acked-by: Bjorn Helgaas Reviewed-by: Thierry Reding Acked-by: Thierry Reding --- drivers/pci/host/pci-tegra.c | 50 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 0afbbbc55c81..6681c3182c85 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -25,7 +25,6 @@ */ #include -#include #include #include #include @@ -39,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -259,10 +259,13 @@ struct tegra_pcie { struct clk *pex_clk; struct clk *afi_clk; - struct clk *pcie_xclk; struct clk *pll_e; struct clk *cml_clk; + struct reset_control *pex_rst; + struct reset_control *afi_rst; + struct reset_control *pcie_xrst; + struct tegra_msi msi; struct list_head ports; @@ -858,7 +861,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) pads_writel(pcie, value, PADS_CTL); /* take the PCIe interface module out of reset */ - tegra_periph_reset_deassert(pcie->pcie_xclk); + reset_control_deassert(pcie->pcie_xrst); /* finally enable PCIe */ value = afi_readl(pcie, AFI_CONFIGURATION); @@ -891,9 +894,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie) /* TODO: disable and unprepare clocks? */ - tegra_periph_reset_assert(pcie->pcie_xclk); - tegra_periph_reset_assert(pcie->afi_clk); - tegra_periph_reset_assert(pcie->pex_clk); + reset_control_assert(pcie->pcie_xrst); + reset_control_assert(pcie->afi_rst); + reset_control_assert(pcie->pex_rst); tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); @@ -921,9 +924,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) const struct tegra_pcie_soc_data *soc = pcie->soc_data; int err; - tegra_periph_reset_assert(pcie->pcie_xclk); - tegra_periph_reset_assert(pcie->afi_clk); - tegra_periph_reset_assert(pcie->pex_clk); + reset_control_assert(pcie->pcie_xrst); + reset_control_assert(pcie->afi_rst); + reset_control_assert(pcie->pex_rst); tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); @@ -958,7 +961,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) return err; } - tegra_periph_reset_deassert(pcie->afi_clk); + reset_control_deassert(pcie->afi_rst); err = clk_prepare_enable(pcie->afi_clk); if (err < 0) { @@ -996,10 +999,6 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) if (IS_ERR(pcie->afi_clk)) return PTR_ERR(pcie->afi_clk); - pcie->pcie_xclk = devm_clk_get(pcie->dev, "pcie_xclk"); - if (IS_ERR(pcie->pcie_xclk)) - return PTR_ERR(pcie->pcie_xclk); - pcie->pll_e = devm_clk_get(pcie->dev, "pll_e"); if (IS_ERR(pcie->pll_e)) return PTR_ERR(pcie->pll_e); @@ -1013,6 +1012,23 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) return 0; } +static int tegra_pcie_resets_get(struct tegra_pcie *pcie) +{ + pcie->pex_rst = devm_reset_control_get(pcie->dev, "pex"); + if (IS_ERR(pcie->pex_rst)) + return PTR_ERR(pcie->pex_rst); + + pcie->afi_rst = devm_reset_control_get(pcie->dev, "afi"); + if (IS_ERR(pcie->afi_rst)) + return PTR_ERR(pcie->afi_rst); + + pcie->pcie_xrst = devm_reset_control_get(pcie->dev, "pcie_x"); + if (IS_ERR(pcie->pcie_xrst)) + return PTR_ERR(pcie->pcie_xrst); + + return 0; +} + static int tegra_pcie_get_resources(struct tegra_pcie *pcie) { struct platform_device *pdev = to_platform_device(pcie->dev); @@ -1025,6 +1041,12 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) return err; } + err = tegra_pcie_resets_get(pcie); + if (err) { + dev_err(&pdev->dev, "failed to get resets: %d\n", err); + return err; + } + err = tegra_pcie_power_on(pcie); if (err) { dev_err(&pdev->dev, "failed to power up: %d\n", err); -- cgit v1.2.3 From ca48080a039f667c9a1e2d6236ea18dde2d36e7e Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:20:54 -0700 Subject: drm/tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-By: Terje Bergstrom --- drivers/gpu/drm/tegra/Kconfig | 1 + drivers/gpu/drm/tegra/dc.c | 10 ++++++++-- drivers/gpu/drm/tegra/drm.h | 3 +++ drivers/gpu/drm/tegra/gr3d.c | 16 ++++++++++++++++ drivers/gpu/drm/tegra/hdmi.c | 15 +++++++++++---- 5 files changed, 39 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 8961ba6a34b8..8db9b3bce001 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -2,6 +2,7 @@ config DRM_TEGRA bool "NVIDIA Tegra DRM" depends on ARCH_TEGRA || ARCH_MULTIPLATFORM depends on DRM + depends on RESET_CONTROLLER select TEGRA_HOST1X select DRM_KMS_HELPER select DRM_KMS_FB_HELPER diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index ae1cb31ead7e..cd7f1e499616 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -8,8 +8,8 @@ */ #include -#include #include +#include #include "dc.h" #include "drm.h" @@ -712,7 +712,7 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc) unsigned long value; /* hardware initialization */ - tegra_periph_reset_deassert(dc->clk); + reset_control_deassert(dc->rst); usleep_range(10000, 20000); if (dc->pipe) @@ -1187,6 +1187,12 @@ static int tegra_dc_probe(struct platform_device *pdev) return PTR_ERR(dc->clk); } + dc->rst = devm_reset_control_get(&pdev->dev, "dc"); + if (IS_ERR(dc->rst)) { + dev_err(&pdev->dev, "failed to get reset\n"); + return PTR_ERR(dc->rst); + } + err = clk_prepare_enable(dc->clk); if (err < 0) return err; diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index fdfe259ed7f8..f717c18b28c2 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -19,6 +19,8 @@ #include #include +struct reset_control; + struct tegra_fb { struct drm_framebuffer base; struct tegra_bo **planes; @@ -93,6 +95,7 @@ struct tegra_dc { int pipe; struct clk *clk; + struct reset_control *rst; void __iomem *regs; int irq; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 4cec8f526af7..f629e38b00e4 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "drm.h" @@ -22,6 +23,8 @@ struct gr3d { struct host1x_channel *channel; struct clk *clk_secondary; struct clk *clk; + struct reset_control *rst_secondary; + struct reset_control *rst; DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS); }; @@ -255,12 +258,25 @@ static int gr3d_probe(struct platform_device *pdev) return PTR_ERR(gr3d->clk); } + gr3d->rst = devm_reset_control_get(&pdev->dev, "3d"); + if (IS_ERR(gr3d->rst)) { + dev_err(&pdev->dev, "cannot get reset\n"); + return PTR_ERR(gr3d->rst); + } + if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) { gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2"); if (IS_ERR(gr3d->clk)) { dev_err(&pdev->dev, "cannot get secondary clock\n"); return PTR_ERR(gr3d->clk); } + + gr3d->rst_secondary = devm_reset_control_get(&pdev->dev, + "3d2"); + if (IS_ERR(gr3d->rst_secondary)) { + dev_err(&pdev->dev, "cannot get secondary reset\n"); + return PTR_ERR(gr3d->rst_secondary); + } } err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk); diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 0cd9bc2056e8..7f6253ea5cb5 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -8,10 +8,10 @@ */ #include -#include #include #include #include +#include #include "hdmi.h" #include "drm.h" @@ -49,6 +49,7 @@ struct tegra_hdmi { struct clk *clk_parent; struct clk *clk; + struct reset_control *rst; const struct tegra_hdmi_config *config; @@ -731,9 +732,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output) return err; } - tegra_periph_reset_assert(hdmi->clk); + reset_control_assert(hdmi->rst); usleep_range(1000, 2000); - tegra_periph_reset_deassert(hdmi->clk); + reset_control_deassert(hdmi->rst); tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS); @@ -912,7 +913,7 @@ static int tegra_output_hdmi_disable(struct tegra_output *output) { struct tegra_hdmi *hdmi = to_hdmi(output); - tegra_periph_reset_assert(hdmi->clk); + reset_control_assert(hdmi->rst); clk_disable(hdmi->clk); regulator_disable(hdmi->pll); @@ -1338,6 +1339,12 @@ static int tegra_hdmi_probe(struct platform_device *pdev) return PTR_ERR(hdmi->clk); } + hdmi->rst = devm_reset_control_get(&pdev->dev, "hdmi"); + if (IS_ERR(hdmi->rst)) { + dev_err(&pdev->dev, "failed to get reset\n"); + return PTR_ERR(hdmi->rst); + } + err = clk_prepare(hdmi->clk); if (err < 0) return err; -- cgit v1.2.3 From 80b28791ff0416a472e5a555a4b6f5f39df2fc24 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 15:45:46 -0700 Subject: ARM: tegra: pass reset to tegra_powergate_sequence_power_up() Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Bjorn Helgaas Acked-By: Terje Bergstrom Reviewed-by: Thierry Reding Acked-by: Thierry Reding --- arch/arm/mach-tegra/powergate.c | 8 +++++--- drivers/gpu/drm/tegra/gr3d.c | 6 ++++-- drivers/pci/host/pci-tegra.c | 3 ++- include/linux/tegra-powergate.h | 7 +++++-- 4 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 85d28e756bb7..f6f5b54ff95e 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -144,11 +145,12 @@ int tegra_powergate_remove_clamping(int id) } /* Must be called with clk disabled, and returns with clk enabled */ -int tegra_powergate_sequence_power_up(int id, struct clk *clk) +int tegra_powergate_sequence_power_up(int id, struct clk *clk, + struct reset_control *rst) { int ret; - tegra_periph_reset_assert(clk); + reset_control_assert(rst); ret = tegra_powergate_power_on(id); if (ret) @@ -165,7 +167,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk) goto err_clamp; udelay(10); - tegra_periph_reset_deassert(clk); + reset_control_deassert(rst); return 0; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index f629e38b00e4..0cbb24b1ae04 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -279,7 +279,8 @@ static int gr3d_probe(struct platform_device *pdev) } } - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk); + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk, + gr3d->rst); if (err < 0) { dev_err(&pdev->dev, "failed to power up 3D unit\n"); return err; @@ -287,7 +288,8 @@ static int gr3d_probe(struct platform_device *pdev) if (gr3d->clk_secondary) { err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D1, - gr3d->clk_secondary); + gr3d->clk_secondary, + gr3d->rst_secondary); if (err < 0) { dev_err(&pdev->dev, "failed to power up secondary 3D unit\n"); diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 6681c3182c85..0175041ab728 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -955,7 +955,8 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) } err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, - pcie->pex_clk); + pcie->pex_clk, + pcie->pex_rst); if (err) { dev_err(pcie->dev, "powerup sequence failed: %d\n", err); return err; diff --git a/include/linux/tegra-powergate.h b/include/linux/tegra-powergate.h index fd4498329c7c..afe442d2629a 100644 --- a/include/linux/tegra-powergate.h +++ b/include/linux/tegra-powergate.h @@ -19,6 +19,7 @@ #define _MACH_TEGRA_POWERGATE_H_ struct clk; +struct reset_control; #define TEGRA_POWERGATE_CPU 0 #define TEGRA_POWERGATE_3D 1 @@ -52,7 +53,8 @@ int tegra_powergate_power_off(int id); int tegra_powergate_remove_clamping(int id); /* Must be called with clk disabled, and returns with clk enabled */ -int tegra_powergate_sequence_power_up(int id, struct clk *clk); +int tegra_powergate_sequence_power_up(int id, struct clk *clk, + struct reset_control *rst); #else static inline int tegra_powergate_is_powered(int id) { @@ -74,7 +76,8 @@ static inline int tegra_powergate_remove_clamping(int id) return -ENOSYS; } -static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk) +static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk, + struct reset_control *rst); { return -ENOSYS; } -- cgit v1.2.3 From 9aa433d2a77220fc261cb8248bb93bdd8e3944ef Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:35:34 -0700 Subject: dma: tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Acked-by: Dan Williams Acked-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 73654e33f13b..afa5844c9346 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -32,8 +32,8 @@ #include #include #include +#include #include -#include #include "dmaengine.h" @@ -208,6 +208,7 @@ struct tegra_dma { struct dma_device dma_dev; struct device *dev; struct clk *dma_clk; + struct reset_control *rst; spinlock_t global_lock; void __iomem *base_addr; const struct tegra_dma_chip_data *chip_data; @@ -1282,6 +1283,12 @@ static int tegra_dma_probe(struct platform_device *pdev) return PTR_ERR(tdma->dma_clk); } + tdma->rst = devm_reset_control_get(&pdev->dev, "dma"); + if (IS_ERR(tdma->rst)) { + dev_err(&pdev->dev, "Error: Missing reset\n"); + return PTR_ERR(tdma->rst); + } + spin_lock_init(&tdma->global_lock); pm_runtime_enable(&pdev->dev); @@ -1302,9 +1309,9 @@ static int tegra_dma_probe(struct platform_device *pdev) } /* Reset DMA controller */ - tegra_periph_reset_assert(tdma->dma_clk); + reset_control_assert(tdma->rst); udelay(2); - tegra_periph_reset_deassert(tdma->dma_clk); + reset_control_deassert(tdma->rst); /* Enable global DMA registers */ tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); -- cgit v1.2.3 From 996556c92a706058cf5ce6b3ef8dacc4032a3e0d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 11 Nov 2013 13:09:35 -0700 Subject: dma: tegra: register as an OF DMA controller Call of_dma_controller_register() so that DMA clients can look up the Tegra DMA controller using standard APIs. This requires the of_xlate() function to save off the DMA slave ID, and for tegra_dma_slave_config() not to over-write this information; once DMA client drivers are converted to dma_request_slave_channel() and DT-based lookups, they won't set this field of struct dma_slave_config anymore. Signed-off-by: Stephen Warren Acked-by: Arnd Bergmann Reviewed-by: Thierry Reding --- drivers/dma/tegra20-apb-dma.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index afa5844c9346..d11bb3620f27 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1,7 +1,7 @@ /* * DMA driver for Nvidia's Tegra20 APB DMA controller. * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -199,6 +200,7 @@ struct tegra_dma_channel { void *callback_param; /* Channel-slave specific configuration */ + unsigned int slave_id; struct dma_slave_config dma_sconfig; struct tegra_dma_channel_regs channel_reg; }; @@ -340,6 +342,8 @@ static int tegra_dma_slave_config(struct dma_chan *dc, } memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig)); + if (!tdc->slave_id) + tdc->slave_id = sconfig->slave_id; tdc->config_init = true; return 0; } @@ -942,7 +946,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW; - csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; + csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; if (flags & DMA_PREP_INTERRUPT) csr |= TEGRA_APBDMA_CSR_IE_EOC; @@ -1086,7 +1090,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( csr |= TEGRA_APBDMA_CSR_FLOW; if (flags & DMA_PREP_INTERRUPT) csr |= TEGRA_APBDMA_CSR_IE_EOC; - csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; + csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; @@ -1206,6 +1210,25 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) kfree(sg_req); } clk_disable_unprepare(tdma->dma_clk); + + tdc->slave_id = 0; +} + +static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct tegra_dma *tdma = ofdma->of_dma_data; + struct dma_chan *chan; + struct tegra_dma_channel *tdc; + + chan = dma_get_any_slave_channel(&tdma->dma_dev); + if (!chan) + return NULL; + + tdc = to_tegra_dma_chan(chan); + tdc->slave_id = dma_spec->args[0]; + + return chan; } /* Tegra20 specific DMA controller information */ @@ -1383,10 +1406,20 @@ static int tegra_dma_probe(struct platform_device *pdev) goto err_irq; } + ret = of_dma_controller_register(pdev->dev.of_node, + tegra_dma_of_xlate, tdma); + if (ret < 0) { + dev_err(&pdev->dev, + "Tegra20 APB DMA OF registration failed %d\n", ret); + goto err_unregister_dma_dev; + } + dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n", cdata->nr_channels); return 0; +err_unregister_dma_dev: + dma_async_device_unregister(&tdma->dma_dev); err_irq: while (--i >= 0) { struct tegra_dma_channel *tdc = &tdma->channels[i]; -- cgit v1.2.3 From dda9d6a8262cb1fa63eb815dc0de2a984389c71b Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:42:05 -0700 Subject: i2c: tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Wolfram Sang Reviewed-by: Thierry Reding --- drivers/i2c/busses/i2c-tegra.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index e661edee4d0c..9704537aee3c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include @@ -160,6 +160,7 @@ struct tegra_i2c_dev { struct i2c_adapter adapter; struct clk *div_clk; struct clk *fast_clk; + struct reset_control *rst; void __iomem *base; int cont_id; int irq; @@ -415,9 +416,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) return err; } - tegra_periph_reset_assert(i2c_dev->div_clk); + reset_control_assert(i2c_dev->rst); udelay(2); - tegra_periph_reset_deassert(i2c_dev->div_clk); + reset_control_deassert(i2c_dev->rst); if (i2c_dev->is_dvc) tegra_dvc_init(i2c_dev); @@ -743,6 +744,12 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->cont_id = pdev->id; i2c_dev->dev = &pdev->dev; + i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c"); + if (IS_ERR(i2c_dev->rst)) { + dev_err(&pdev->dev, "missing controller reset"); + return PTR_ERR(i2c_dev->rst); + } + ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency", &i2c_dev->bus_clk_rate); if (ret) -- cgit v1.2.3 From c0df5bf5369ec5d12d781491c95e3207ec5ee2b7 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:46:24 -0700 Subject: staging: nvec: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Marc Dietrich Acked-by: Greg Kroah-Hartman Reviewed-by: Thierry Reding --- drivers/staging/nvec/nvec.c | 11 ++++++++--- drivers/staging/nvec/nvec.h | 5 ++++- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 49ea76b3435d..986870593b0c 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "nvec.h" @@ -734,9 +733,9 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) clk_prepare_enable(nvec->i2c_clk); - tegra_periph_reset_assert(nvec->i2c_clk); + reset_control_assert(nvec->rst); udelay(2); - tegra_periph_reset_deassert(nvec->i2c_clk); + reset_control_deassert(nvec->rst); val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN | (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); @@ -837,6 +836,12 @@ static int tegra_nvec_probe(struct platform_device *pdev) return -ENODEV; } + nvec->rst = devm_reset_control_get(&pdev->dev, "i2c"); + if (IS_ERR(nvec->rst)) { + dev_err(nvec->dev, "failed to get controller reset\n"); + return PTR_ERR(nvec->rst); + } + nvec->base = base; nvec->irq = res->start; nvec->i2c_clk = i2c_clk; diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h index e880518935fb..e271375053fa 100644 --- a/drivers/staging/nvec/nvec.h +++ b/drivers/staging/nvec/nvec.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -109,7 +110,8 @@ struct nvec_msg { * @irq: The IRQ of the I2C device * @i2c_addr: The address of the I2C slave * @base: The base of the memory mapped region of the I2C device - * @clk: The clock of the I2C device + * @i2c_clk: The clock of the I2C device + * @rst: The reset of the I2C device * @notifier_list: Notifiers to be called on received messages, see * nvec_register_notifier() * @rx_data: Received messages that have to be processed @@ -139,6 +141,7 @@ struct nvec_chip { int i2c_addr; void __iomem *base; struct clk *i2c_clk; + struct reset_control *rst; struct atomic_notifier_head notifier_list; struct list_head rx_data, tx_data; struct notifier_block nvec_status_notifier; -- cgit v1.2.3 From ff2251e3de37b002e2e91e4917119f5776e210e3 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:31:24 -0700 Subject: spi: tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Mark Brown Reviewed-by: Thierry Reding --- drivers/spi/Kconfig | 3 +++ drivers/spi/spi-tegra114.c | 18 +++++++++++++----- drivers/spi/spi-tegra20-sflash.c | 18 +++++++++++++----- drivers/spi/spi-tegra20-slink.c | 18 +++++++++++++----- 4 files changed, 42 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index eb1f1ef5fa2e..9fc66e83c1a7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -448,6 +448,7 @@ config SPI_MXS config SPI_TEGRA114 tristate "NVIDIA Tegra114 SPI Controller" depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST + depends on RESET_CONTROLLER help SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller is different than the older SoCs SPI controller and also register interface @@ -456,6 +457,7 @@ config SPI_TEGRA114 config SPI_TEGRA20_SFLASH tristate "Nvidia Tegra20 Serial flash Controller" depends on ARCH_TEGRA || COMPILE_TEST + depends on RESET_CONTROLLER help SPI driver for Nvidia Tegra20 Serial flash Controller interface. The main usecase of this controller is to use spi flash as boot @@ -464,6 +466,7 @@ config SPI_TEGRA20_SFLASH config SPI_TEGRA20_SLINK tristate "Nvidia Tegra20/Tegra30 SLINK Controller" depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST + depends on RESET_CONTROLLER help SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface. diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index aaecfb3ebf58..f62e6e5e90e3 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #include #define SPI_COMMAND1 0x000 @@ -174,6 +174,7 @@ struct tegra_spi_data { spinlock_t lock; struct clk *clk; + struct reset_control *rst; void __iomem *base; phys_addr_t phys; unsigned irq; @@ -918,9 +919,9 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); - tegra_periph_reset_assert(tspi->clk); + reset_control_assert(tspi->rst); udelay(2); - tegra_periph_reset_deassert(tspi->clk); + reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); goto exit; } @@ -990,9 +991,9 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); - tegra_periph_reset_assert(tspi->clk); + reset_control_assert(tspi->rst); udelay(2); - tegra_periph_reset_deassert(tspi->clk); + reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); return IRQ_HANDLED; @@ -1127,6 +1128,13 @@ static int tegra_spi_probe(struct platform_device *pdev) goto exit_free_irq; } + tspi->rst = devm_reset_control_get(&pdev->dev, "spi"); + if (IS_ERR(tspi->rst)) { + dev_err(&pdev->dev, "can not get reset\n"); + ret = PTR_ERR(tspi->rst); + goto exit_free_irq; + } + tspi->max_buf_size = SPI_FIFO_DEPTH << 2; tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN; diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 4dc8e8129459..e6f382b33818 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -32,8 +32,8 @@ #include #include #include +#include #include -#include #define SPI_COMMAND 0x000 #define SPI_GO BIT(30) @@ -118,6 +118,7 @@ struct tegra_sflash_data { spinlock_t lock; struct clk *clk; + struct reset_control *rst; void __iomem *base; unsigned irq; u32 spi_max_frequency; @@ -389,9 +390,9 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_sflash_data *tsd) dev_err(tsd->dev, "CpuXfer 0x%08x:0x%08x\n", tsd->command_reg, tsd->dma_control_reg); - tegra_periph_reset_assert(tsd->clk); + reset_control_assert(tsd->rst); udelay(2); - tegra_periph_reset_deassert(tsd->clk); + reset_control_deassert(tsd->rst); complete(&tsd->xfer_completion); goto exit; } @@ -505,6 +506,13 @@ static int tegra_sflash_probe(struct platform_device *pdev) goto exit_free_irq; } + tsd->rst = devm_reset_control_get(&pdev->dev, "spi"); + if (IS_ERR(tsd->rst)) { + dev_err(&pdev->dev, "can not get reset\n"); + ret = PTR_ERR(tsd->rst); + goto exit_free_irq; + } + init_completion(&tsd->xfer_completion); pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { @@ -520,9 +528,9 @@ static int tegra_sflash_probe(struct platform_device *pdev) } /* Reset controller */ - tegra_periph_reset_assert(tsd->clk); + reset_control_assert(tsd->rst); udelay(2); - tegra_periph_reset_deassert(tsd->clk); + reset_control_deassert(tsd->rst); tsd->def_command_reg = SPI_M_S | SPI_CS_SW; tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index e66715ba37ed..1305b8f933ba 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -33,8 +33,8 @@ #include #include #include +#include #include -#include #define SLINK_COMMAND 0x000 #define SLINK_BIT_LENGTH(x) (((x) & 0x1f) << 0) @@ -167,6 +167,7 @@ struct tegra_slink_data { spinlock_t lock; struct clk *clk; + struct reset_control *rst; void __iomem *base; phys_addr_t phys; unsigned irq; @@ -884,9 +885,9 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi) dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg, tspi->command2_reg, tspi->dma_control_reg); - tegra_periph_reset_assert(tspi->clk); + reset_control_assert(tspi->rst); udelay(2); - tegra_periph_reset_deassert(tspi->clk); + reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); goto exit; } @@ -957,9 +958,9 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_slink_data *tspi) dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg, tspi->command2_reg, tspi->dma_control_reg); - tegra_periph_reset_assert(tspi->clk); + reset_control_assert(tspi->rst); udelay(2); - tegra_periph_reset_deassert(tspi->clk); + reset_control_assert(tspi->rst); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); return IRQ_HANDLED; @@ -1118,6 +1119,13 @@ static int tegra_slink_probe(struct platform_device *pdev) goto exit_free_irq; } + tspi->rst = devm_reset_control_get(&pdev->dev, "spi"); + if (IS_ERR(tspi->rst)) { + dev_err(&pdev->dev, "can not get reset\n"); + ret = PTR_ERR(tspi->rst); + goto exit_free_irq; + } + tspi->max_buf_size = SLINK_FIFO_DEPTH << 2; tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN; -- cgit v1.2.3 From a915d150f68d8fd8ad72de6d9d4d7be26813b214 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 11 Nov 2013 13:13:47 -0700 Subject: spi: tegra: convert to standard DMA DT bindings By using dma_request_slave_channel_or_err(), the DMA slave ID can be looked up from standard DT properties, and squirrelled away during channel allocation. Hence, there's no need to use a custom DT property to store the slave ID. Signed-off-by: Stephen Warren Acked-by: Mark Brown --- drivers/spi/spi-tegra114.c | 48 +++++++++++++++-------------------------- drivers/spi/spi-tegra20-slink.c | 48 +++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index f62e6e5e90e3..c8604981a058 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -178,7 +178,6 @@ struct tegra_spi_data { void __iomem *base; phys_addr_t phys; unsigned irq; - int dma_req_sel; u32 spi_max_frequency; u32 cur_speed; @@ -601,15 +600,15 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, dma_addr_t dma_phys; int ret; struct dma_slave_config dma_sconfig; - dma_cap_mask_t mask; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_chan = dma_request_channel(mask, NULL, NULL); - if (!dma_chan) { - dev_err(tspi->dev, - "Dma channel is not available, will try later\n"); - return -EPROBE_DEFER; + dma_chan = dma_request_slave_channel_reason(tspi->dev, + dma_to_memory ? "rx" : "tx"); + if (IS_ERR(dma_chan)) { + ret = PTR_ERR(dma_chan); + if (ret != -EPROBE_DEFER) + dev_err(tspi->dev, + "Dma channel is not available: %d\n", ret); + return ret; } dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size, @@ -620,7 +619,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, return -ENOMEM; } - dma_sconfig.slave_id = tspi->dma_req_sel; if (dma_to_memory) { dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -1055,11 +1053,6 @@ static void tegra_spi_parse_dt(struct platform_device *pdev, struct tegra_spi_data *tspi) { struct device_node *np = pdev->dev.of_node; - u32 of_dma[2]; - - if (of_property_read_u32_array(np, "nvidia,dma-request-selector", - of_dma, 2) >= 0) - tspi->dma_req_sel = of_dma[1]; if (of_property_read_u32(np, "spi-max-frequency", &tspi->spi_max_frequency)) @@ -1138,22 +1131,15 @@ static int tegra_spi_probe(struct platform_device *pdev) tspi->max_buf_size = SPI_FIFO_DEPTH << 2; tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN; - if (tspi->dma_req_sel) { - ret = tegra_spi_init_dma_param(tspi, true); - if (ret < 0) { - dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret); - goto exit_free_irq; - } - - ret = tegra_spi_init_dma_param(tspi, false); - if (ret < 0) { - dev_err(&pdev->dev, "TxDma Init failed, err %d\n", ret); - goto exit_rx_dma_free; - } - tspi->max_buf_size = tspi->dma_buf_size; - init_completion(&tspi->tx_dma_complete); - init_completion(&tspi->rx_dma_complete); - } + ret = tegra_spi_init_dma_param(tspi, true); + if (ret < 0) + goto exit_free_irq; + ret = tegra_spi_init_dma_param(tspi, false); + if (ret < 0) + goto exit_rx_dma_free; + tspi->max_buf_size = tspi->dma_buf_size; + init_completion(&tspi->tx_dma_complete); + init_completion(&tspi->rx_dma_complete); init_completion(&tspi->xfer_completion); diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 1305b8f933ba..dd6f26c05947 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -171,7 +171,6 @@ struct tegra_slink_data { void __iomem *base; phys_addr_t phys; unsigned irq; - int dma_req_sel; u32 spi_max_frequency; u32 cur_speed; @@ -630,15 +629,15 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi, dma_addr_t dma_phys; int ret; struct dma_slave_config dma_sconfig; - dma_cap_mask_t mask; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_chan = dma_request_channel(mask, NULL, NULL); - if (!dma_chan) { - dev_err(tspi->dev, - "Dma channel is not available, will try later\n"); - return -EPROBE_DEFER; + dma_chan = dma_request_slave_channel(tspi->dev, + dma_to_memory ? "rx" : "tx"); + if (IS_ERR(dma_chan)) { + ret = PTR_ERR(dma_chan); + if (ret != -EPROBE_DEFER) + dev_err(tspi->dev, + "Dma channel is not available: %d\n", ret); + return ret; } dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size, @@ -649,7 +648,6 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi, return -ENOMEM; } - dma_sconfig.slave_id = tspi->dma_req_sel; if (dma_to_memory) { dma_sconfig.src_addr = tspi->phys + SLINK_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -1021,11 +1019,6 @@ static irqreturn_t tegra_slink_isr(int irq, void *context_data) static void tegra_slink_parse_dt(struct tegra_slink_data *tspi) { struct device_node *np = tspi->dev->of_node; - u32 of_dma[2]; - - if (of_property_read_u32_array(np, "nvidia,dma-request-selector", - of_dma, 2) >= 0) - tspi->dma_req_sel = of_dma[1]; if (of_property_read_u32(np, "spi-max-frequency", &tspi->spi_max_frequency)) @@ -1129,22 +1122,15 @@ static int tegra_slink_probe(struct platform_device *pdev) tspi->max_buf_size = SLINK_FIFO_DEPTH << 2; tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN; - if (tspi->dma_req_sel) { - ret = tegra_slink_init_dma_param(tspi, true); - if (ret < 0) { - dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret); - goto exit_free_irq; - } - - ret = tegra_slink_init_dma_param(tspi, false); - if (ret < 0) { - dev_err(&pdev->dev, "TxDma Init failed, err %d\n", ret); - goto exit_rx_dma_free; - } - tspi->max_buf_size = tspi->dma_buf_size; - init_completion(&tspi->tx_dma_complete); - init_completion(&tspi->rx_dma_complete); - } + ret = tegra_slink_init_dma_param(tspi, true); + if (ret < 0) + goto exit_free_irq; + ret = tegra_slink_init_dma_param(tspi, false); + if (ret < 0) + goto exit_rx_dma_free; + tspi->max_buf_size = tspi->dma_buf_size; + init_completion(&tspi->tx_dma_complete); + init_completion(&tspi->rx_dma_complete); init_completion(&tspi->xfer_completion); -- cgit v1.2.3 From d3d654ef230d8b8370e1b2820589521282c868d8 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:50:44 -0700 Subject: serial: tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Greg Kroah-Hartman Reviewed-by: Thierry Reding --- drivers/tty/serial/serial-tegra.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index dfe79ccc4fb3..4455481a3517 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +45,6 @@ #include #include -#include - #define TEGRA_UART_TYPE "TEGRA_UART" #define TX_EMPTY_STATUS (UART_LSR_TEMT | UART_LSR_THRE) #define BYTES_TO_ALIGN(x) ((unsigned long)(x) & 0x3) @@ -103,6 +102,7 @@ struct tegra_uart_port { const struct tegra_uart_chip_data *cdata; struct clk *uart_clk; + struct reset_control *rst; unsigned int current_baud; /* Register shadow */ @@ -832,9 +832,9 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) clk_prepare_enable(tup->uart_clk); /* Reset the UART controller to clear all previous status.*/ - tegra_periph_reset_assert(tup->uart_clk); + reset_control_assert(tup->rst); udelay(10); - tegra_periph_reset_deassert(tup->uart_clk); + reset_control_deassert(tup->rst); tup->rx_in_progress = 0; tup->tx_in_progress = 0; @@ -1320,6 +1320,12 @@ static int tegra_uart_probe(struct platform_device *pdev) return PTR_ERR(tup->uart_clk); } + tup->rst = devm_reset_control_get(&pdev->dev, "serial"); + if (IS_ERR(tup->rst)) { + dev_err(&pdev->dev, "Couldn't get the reset\n"); + return PTR_ERR(tup->rst); + } + u->iotype = UPIO_MEM32; u->irq = platform_get_irq(pdev, 0); u->regshift = 2; -- cgit v1.2.3 From c2b329f56196cce5ebde42f0b6ffc3c12db4c826 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 11 Nov 2013 14:16:38 -0700 Subject: serial: tegra: convert to standard DMA DT bindings By using dma_request_slave_channel_or_err(), the DMA slave ID can be looked up from standard DT properties, and squirrelled away during channel allocation. Hence, there's no need to use a custom DT property to store the slave ID. Acked-by: Greg Kroah-Hartman Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding --- drivers/tty/serial/serial-tegra.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 4455481a3517..d5c2a287b7e7 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -120,7 +120,6 @@ struct tegra_uart_port { bool rx_timeout; int rx_in_progress; int symb_bit; - int dma_req_sel; struct dma_chan *rx_dma_chan; struct dma_chan *tx_dma_chan; @@ -910,15 +909,14 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup, dma_addr_t dma_phys; int ret; struct dma_slave_config dma_sconfig; - dma_cap_mask_t mask; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_chan = dma_request_channel(mask, NULL, NULL); - if (!dma_chan) { + dma_chan = dma_request_slave_channel_reason(tup->uport.dev, + dma_to_memory ? "rx" : "tx"); + if (IS_ERR(dma_chan)) { + ret = PTR_ERR(dma_chan); dev_err(tup->uport.dev, - "Dma channel is not available, will try later\n"); - return -EPROBE_DEFER; + "DMA channel alloc failed: %d\n", ret); + return ret; } if (dma_to_memory) { @@ -938,7 +936,6 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup, dma_buf = tup->uport.state->xmit.buf; } - dma_sconfig.slave_id = tup->dma_req_sel; if (dma_to_memory) { dma_sconfig.src_addr = tup->uport.mapbase; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; @@ -1222,17 +1219,8 @@ static int tegra_uart_parse_dt(struct platform_device *pdev, struct tegra_uart_port *tup) { struct device_node *np = pdev->dev.of_node; - u32 of_dma[2]; int port; - if (of_property_read_u32_array(np, "nvidia,dma-request-selector", - of_dma, 2) >= 0) { - tup->dma_req_sel = of_dma[1]; - } else { - dev_err(&pdev->dev, "missing dma requestor in device tree\n"); - return -EINVAL; - } - port = of_alias_get_id(np, "serial"); if (port < 0) { dev_err(&pdev->dev, "failed to get alias id, errno %d\n", port); -- cgit v1.2.3 From fe6b0dfaba689ad5481037bdfbf31531b3e4c074 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:48:16 -0700 Subject: Input: tegra-kbc - use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Dmitry Torokhov Reviewed-by: Thierry Reding --- drivers/input/keyboard/tegra-kbc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 8508879f6faf..9757a58bc897 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #define KBC_MAX_KPENT 8 @@ -116,6 +116,7 @@ struct tegra_kbc { u32 wakeup_key; struct timer_list timer; struct clk *clk; + struct reset_control *rst; const struct tegra_kbc_hw_support *hw_support; int max_keys; int num_rows_and_columns; @@ -373,9 +374,9 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) clk_prepare_enable(kbc->clk); /* Reset the KBC controller to clear all previous status.*/ - tegra_periph_reset_assert(kbc->clk); + reset_control_assert(kbc->rst); udelay(100); - tegra_periph_reset_deassert(kbc->clk); + reset_control_assert(kbc->rst); udelay(100); tegra_kbc_config_pins(kbc); @@ -663,6 +664,12 @@ static int tegra_kbc_probe(struct platform_device *pdev) return PTR_ERR(kbc->clk); } + kbc->rst = devm_reset_control_get(&pdev->dev, "kbc"); + if (IS_ERR(kbc->rst)) { + dev_err(&pdev->dev, "failed to get keyboard reset\n"); + return PTR_ERR(kbc->rst); + } + /* * The time delay between two consecutive reads of the FIFO is * the sum of the repeat time and the time taken for scanning -- cgit v1.2.3 From 75606f5d32fabef51c1337eac274492c0470d774 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:53:58 -0700 Subject: USB: EHCI: tegra: use reset framework Tegra's clock driver now provides an implementation of the common reset API (include/linux/reset.h). Use this instead of the old Tegra- specific API; that will soon be removed. Signed-off-by: Stephen Warren Acked-by: Alan Stern Acked-by: Greg Kroah-Hartman Reviewed-by: Thierry Reding --- drivers/usb/host/ehci-tegra.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index b9fd0396011e..6f7e23dd1417 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +62,7 @@ static int (*orig_hub_control)(struct usb_hcd *hcd, struct tegra_ehci_hcd { struct tegra_usb_phy *phy; struct clk *clk; + struct reset_control *rst; int port_resuming; bool needs_double_reset; enum tegra_usb_phy_port_speed port_speed; @@ -385,13 +386,20 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto cleanup_hcd_create; } + tegra->rst = devm_reset_control_get(&pdev->dev, "usb"); + if (IS_ERR(tegra->rst)) { + dev_err(&pdev->dev, "Can't get ehci reset\n"); + err = PTR_ERR(tegra->rst); + goto cleanup_hcd_create; + } + err = clk_prepare_enable(tegra->clk); if (err) goto cleanup_hcd_create; - tegra_periph_reset_assert(tegra->clk); + reset_control_assert(tegra->rst); udelay(1); - tegra_periph_reset_deassert(tegra->clk); + reset_control_deassert(tegra->rst); u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); if (IS_ERR(u_phy)) { -- cgit v1.2.3 From 2ae77527bb1a510070d039aaa22d1ae9a5807b6f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Nov 2013 16:58:16 -0700 Subject: clk: tegra: remove legacy reset APIs Now that no code uses the custom Tegra module reset API, we can remove its implementation. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Acked-By: Peter De Schrijver --- drivers/clk/tegra/clk-periph-gate.c | 22 -------------------- drivers/clk/tegra/clk-periph.c | 40 ------------------------------------- drivers/clk/tegra/clk.h | 1 - include/linux/clk/tegra.h | 7 ------- 4 files changed, 70 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index f38f33e3c65d..507015314827 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -36,8 +36,6 @@ static DEFINE_SPINLOCK(periph_ref_lock); #define read_rst(gate) \ readl_relaxed(gate->clk_base + (gate->regs->rst_reg)) -#define write_rst_set(val, gate) \ - writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg)) #define write_rst_clr(val, gate) \ writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg)) @@ -123,26 +121,6 @@ static void clk_periph_disable(struct clk_hw *hw) spin_unlock_irqrestore(&periph_ref_lock, flags); } -void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert) -{ - if (gate->flags & TEGRA_PERIPH_NO_RESET) - return; - - if (assert) { - /* - * If peripheral is in the APB bus then read the APB bus to - * flush the write operation in apb bus. This will avoid the - * peripheral access after disabling clock - */ - if (gate->flags & TEGRA_PERIPH_ON_APB) - tegra_read_chipid(); - - write_rst_set(periph_clk_to_bit(gate), gate); - } else { - write_rst_clr(periph_clk_to_bit(gate), gate); - } -} - const struct clk_ops tegra_clk_periph_gate_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index d62b396863c1..c534043c0481 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -111,46 +111,6 @@ static void clk_periph_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); } -void tegra_periph_reset_deassert(struct clk *c) -{ - struct clk_hw *hw = __clk_get_hw(c); - struct tegra_clk_periph *periph = to_clk_periph(hw); - struct tegra_clk_periph_gate *gate; - - if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) { - gate = to_clk_periph_gate(hw); - if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) { - WARN_ON(1); - return; - } - } else { - gate = &periph->gate; - } - - tegra_periph_reset(gate, 0); -} -EXPORT_SYMBOL(tegra_periph_reset_deassert); - -void tegra_periph_reset_assert(struct clk *c) -{ - struct clk_hw *hw = __clk_get_hw(c); - struct tegra_clk_periph *periph = to_clk_periph(hw); - struct tegra_clk_periph_gate *gate; - - if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) { - gate = to_clk_periph_gate(hw); - if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) { - WARN_ON(1); - return; - } - } else { - gate = &periph->gate; - } - - tegra_periph_reset(gate, 1); -} -EXPORT_SYMBOL(tegra_periph_reset_assert); - const struct clk_ops tegra_clk_periph_ops = { .get_parent = clk_periph_get_parent, .set_parent = clk_periph_set_parent, diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 07c62f997371..16ec8d6bb87f 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -393,7 +393,6 @@ struct tegra_clk_periph_gate { #define TEGRA_PERIPH_NO_DIV BIT(4) #define TEGRA_PERIPH_NO_GATE BIT(5) -void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); extern const struct clk_ops tegra_clk_periph_gate_ops; struct clk *tegra_clk_register_periph_gate(const char *name, const char *parent_name, u8 gate_flags, void __iomem *clk_base, diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index 23a0ceee831f..3ca9fca827a2 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h @@ -120,13 +120,6 @@ static inline void tegra_cpu_clock_resume(void) } #endif -#ifdef CONFIG_ARCH_TEGRA -void tegra_periph_reset_deassert(struct clk *c); -void tegra_periph_reset_assert(struct clk *c); -#else -static inline void tegra_periph_reset_deassert(struct clk *c) {} -static inline void tegra_periph_reset_assert(struct clk *c) {} -#endif void tegra_clocks_apply_init_table(void); #endif /* __LINUX_CLK_TEGRA_H_ */ -- cgit v1.2.3 From a85f06badc3cff4069f2f5112cea63cd39d99920 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 7 Nov 2013 10:58:21 -0700 Subject: clk: tegra: remove bogus PCIE_XCLK The "pcie_xclk" clock is not actually a clock at all, but rather a reset domain. Now that the custom Tegra module reset API has been removed, we can remove the definition of any "clocks" that existed solely to support it. Signed-off-by: Stephen Warren Reviewed-by: Thierry Reding Acked-By: Peter De Schrijver --- drivers/clk/tegra/clk-tegra20.c | 6 ------ drivers/clk/tegra/clk-tegra30.c | 7 ------- include/dt-bindings/clock/tegra20-car.h | 2 +- include/dt-bindings/clock/tegra30-car.h | 2 +- 4 files changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 5a6a60d9443a..dbace152b2fa 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -468,7 +468,6 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "isp", .dev_id = "tegra_camera", .dt_id = TEGRA20_CLK_ISP }, { .con_id = "pex", .dt_id = TEGRA20_CLK_PEX }, { .con_id = "afi", .dt_id = TEGRA20_CLK_AFI }, - { .con_id = "pcie_xclk", .dt_id = TEGRA20_CLK_PCIE_XCLK }, { .con_id = "cdev1", .dt_id = TEGRA20_CLK_CDEV1 }, { .con_id = "cdev2", .dt_id = TEGRA20_CLK_CDEV2 }, { .con_id = "clk_32k", .dt_id = TEGRA20_CLK_CLK_32K }, @@ -834,11 +833,6 @@ static void __init tegra20_periph_clk_init(void) periph_clk_enb_refcnt); clks[TEGRA20_CLK_PEX] = clk; - /* pcie_xclk */ - clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base, - 0, 74, periph_clk_enb_refcnt); - clks[TEGRA20_CLK_PCIE_XCLK] = clk; - /* cdev1 */ clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT, 26000000); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 2e47383418c8..8b10c38b6e3c 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -649,7 +649,6 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "isp", .dev_id = "tegra_camera", .dt_id = TEGRA30_CLK_ISP }, { .con_id = "pcie", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIE }, { .con_id = "afi", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_AFI }, - { .con_id = "pciex", .dev_id = "tegra-pcie", .dt_id = TEGRA30_CLK_PCIEX }, { .con_id = "fuse", .dt_id = TEGRA30_CLK_FUSE }, { .con_id = "fuse_burn", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE_BURN }, { .con_id = "apbif", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_APBIF }, @@ -1150,11 +1149,6 @@ static void __init tegra30_periph_clk_init(void) periph_clk_enb_refcnt); clks[TEGRA30_CLK_AFI] = clk; - /* pciex */ - clk = tegra_clk_register_periph_gate("pciex", "pll_e", 0, clk_base, 0, - 74, periph_clk_enb_refcnt); - clks[TEGRA30_CLK_PCIEX] = clk; - /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, ARRAY_SIZE(mux_pllmcp_clkm), @@ -1395,7 +1389,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { TEGRA_CLK_DUPLICATE(TEGRA30_CLK_BSEA, "nvavp", "bsea"), TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML1, "tegra_sata_cml", NULL), TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML0, "tegra_pcie", "cml"), - TEGRA_CLK_DUPLICATE(TEGRA30_CLK_PCIEX, "tegra_pcie", "pciex"), TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VCP, "nvavp", "vcp"), TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL), /* MUST be the last entry */ }; diff --git a/include/dt-bindings/clock/tegra20-car.h b/include/dt-bindings/clock/tegra20-car.h index a1ae9a8fdd6c..9406207cfac8 100644 --- a/include/dt-bindings/clock/tegra20-car.h +++ b/include/dt-bindings/clock/tegra20-car.h @@ -92,7 +92,7 @@ #define TEGRA20_CLK_OWR 71 #define TEGRA20_CLK_AFI 72 #define TEGRA20_CLK_CSITE 73 -#define TEGRA20_CLK_PCIE_XCLK 74 +/* 74 */ #define TEGRA20_CLK_AVPUCQ 75 #define TEGRA20_CLK_LA 76 /* 77 */ diff --git a/include/dt-bindings/clock/tegra30-car.h b/include/dt-bindings/clock/tegra30-car.h index 22445820a929..889e49ba0aa3 100644 --- a/include/dt-bindings/clock/tegra30-car.h +++ b/include/dt-bindings/clock/tegra30-car.h @@ -92,7 +92,7 @@ #define TEGRA30_CLK_OWR 71 #define TEGRA30_CLK_AFI 72 #define TEGRA30_CLK_CSITE 73 -#define TEGRA30_CLK_PCIEX 74 +/* 74 */ #define TEGRA30_CLK_AVPUCQ 75 #define TEGRA30_CLK_LA 76 /* 77 */ -- cgit v1.2.3 From 63832aabec12a28a41a221773ab3819d30ba0a67 Mon Sep 17 00:00:00 2001 From: Shivaram Upadhyayula Date: Tue, 10 Dec 2013 16:06:40 +0530 Subject: qla2xxx: Fix schedule_delayed_work() for target timeout calculations This patch fixes two cases in qla_target.c code where the schedule_delayed_work() value was being incorrectly calculated from sess->expires - jiffies. Signed-off-by: Shivaram U Cc: #3.6+ Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_target.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 596480022b0a..3bb0a1d1622a 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -471,7 +471,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, schedule_delayed_work(&tgt->sess_del_work, 0); else schedule_delayed_work(&tgt->sess_del_work, - jiffies - sess->expires); + sess->expires - jiffies); } /* ha->hardware_lock supposed to be held on entry */ @@ -550,13 +550,14 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) struct scsi_qla_host *vha = tgt->vha; struct qla_hw_data *ha = vha->hw; struct qla_tgt_sess *sess; - unsigned long flags; + unsigned long flags, elapsed; spin_lock_irqsave(&ha->hardware_lock, flags); while (!list_empty(&tgt->del_sess_list)) { sess = list_entry(tgt->del_sess_list.next, typeof(*sess), del_list_entry); - if (time_after_eq(jiffies, sess->expires)) { + elapsed = jiffies; + if (time_after_eq(elapsed, sess->expires)) { qlt_undelete_sess(sess); ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, @@ -566,7 +567,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) ha->tgt.tgt_ops->put_sess(sess); } else { schedule_delayed_work(&tgt->sess_del_work, - jiffies - sess->expires); + sess->expires - elapsed); break; } } -- cgit v1.2.3 From c767db5147f0f257accbb26639a2b916d5ffb1e6 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 11 Dec 2013 15:51:20 -0800 Subject: net: eth: davinci_cpdma: 64-bit phys/dma_addr_t cleanup Silences the below warnings when building with ARM_LPAE enabled, which gives longer dma_addr_t by default: drivers/net/ethernet/ti/davinci_cpdma.c: In function 'cpdma_desc_pool_create': drivers/net/ethernet/ti/davinci_cpdma.c:182:3: warning: passing argument 3 of 'dma_alloc_attrs' from incompatible pointer type [enabled by default] drivers/net/ethernet/ti/davinci_cpdma.c: In function 'desc_phys': drivers/net/ethernet/ti/davinci_cpdma.c:222:25: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/net/ethernet/ti/davinci_cpdma.c:223:8: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Olof Johansson Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_cpdma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 90a79462c869..b041a877fe23 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -81,7 +81,7 @@ struct cpdma_desc { }; struct cpdma_desc_pool { - u32 phys; + phys_addr_t phys; u32 hw_addr; void __iomem *iomap; /* ioremap map */ void *cpumap; /* dma_alloc map */ @@ -219,8 +219,7 @@ static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, { if (!desc) return 0; - return pool->hw_addr + (__force dma_addr_t)desc - - (__force dma_addr_t)pool->iomap; + return pool->hw_addr + (__force long)desc - (__force long)pool->iomap; } static inline struct cpdma_desc __iomem * -- cgit v1.2.3 From df7841604394c57289072d15fcd90a2585b701a6 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 11 Dec 2013 15:51:21 -0800 Subject: net: eth: davinci_cpdma: Mark a local variable static Only used locally. Found by sparse. Signed-off-by: Olof Johansson Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_cpdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index b041a877fe23..364d0c7952c0 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -971,7 +971,7 @@ struct cpdma_control_info { #define ACCESS_RW (ACCESS_RO | ACCESS_WO) }; -struct cpdma_control_info controls[] = { +static struct cpdma_control_info controls[] = { [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, -- cgit v1.2.3 From 1a3b50566f259eb79039b720dbfdbb97a7a1b9c5 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 11 Dec 2013 15:58:07 -0800 Subject: net: eth: cpsw: 64-bit phys_addr_t and sparse cleanup Minor fix for printk format of a phys_addr_t, and the switch of two local functions to static since they're not used outside of the file. Signed-off-by: Olof Johansson Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index c8a54f96cf5d..915eca910569 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -582,7 +582,7 @@ static void cpsw_intr_disable(struct cpsw_priv *priv) return; } -void cpsw_tx_handler(void *token, int len, int status) +static void cpsw_tx_handler(void *token, int len, int status) { struct sk_buff *skb = token; struct net_device *ndev = skb->dev; @@ -599,7 +599,7 @@ void cpsw_tx_handler(void *token, int len, int status) dev_kfree_skb_any(skb); } -void cpsw_rx_handler(void *token, int len, int status) +static void cpsw_rx_handler(void *token, int len, int status) { struct sk_buff *skb = token; struct sk_buff *new_skb; @@ -2142,8 +2142,8 @@ static int cpsw_probe(struct platform_device *pdev) data->cpts_clock_mult, data->cpts_clock_shift)) dev_err(priv->dev, "error registering cpts device\n"); - cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n", - ss_res->start, ndev->irq); + cpsw_notice(priv, probe, "initialized device (regs %pa, irq %d)\n", + &ss_res->start, ndev->irq); if (priv->data.dual_emac) { ret = cpsw_probe_dual_emac(pdev, priv); -- cgit v1.2.3 From b9f10a10cd56414659724bfb9f8b65499f07d538 Mon Sep 17 00:00:00 2001 From: Qiao Zhou Date: Thu, 5 Dec 2013 09:36:21 +0800 Subject: ARM: mmp: build sram driver alone sram driver can be used by many chips besides CPU_MMP2, and so build it alone. Also need to select MMP_SRAM for MMP_TDMA driver. Reported-by: Dan Williams Signed-off-by: Qiao Zhou Signed-off-by: Haojian Zhuang Signed-off-by: Olof Johansson --- arch/arm/mach-mmp/Kconfig | 3 +++ arch/arm/mach-mmp/Makefile | 3 ++- drivers/dma/Kconfig | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index ebdda8346a26..ebdba87b9671 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -136,4 +136,7 @@ config USB_EHCI_MV_U2O help Enables support for OTG controller which can be switched to host mode. +config MMP_SRAM + bool + endif diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index 9b702a1dc7b0..98f0f6388e44 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile @@ -7,7 +7,8 @@ obj-y += common.o devices.o time.o # SoC support obj-$(CONFIG_CPU_PXA168) += pxa168.o obj-$(CONFIG_CPU_PXA910) += pxa910.o -obj-$(CONFIG_CPU_MMP2) += mmp2.o sram.o +obj-$(CONFIG_CPU_MMP2) += mmp2.o +obj-$(CONFIG_MMP_SRAM) += sram.o ifeq ($(CONFIG_COMMON_CLK), ) obj-y += clock.o diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 446687cc2334..af3676333da4 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -289,9 +289,11 @@ config MMP_TDMA bool "MMP Two-Channel DMA support" depends on ARCH_MMP select DMA_ENGINE + select MMP_SRAM help Support the MMP Two-Channel DMA engine. This engine used for MMP Audio DMA and pxa910 SQU. + It needs sram driver under mach-mmp. Say Y here if you enabled MMP ADMA, otherwise say N. -- cgit v1.2.3 From 9ae9ab522094406915c27dc729d3ecef7b44af72 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2013 09:52:58 +0000 Subject: drm/i915: Prevent double unref following alloc failure during execbuffer Whilst looking up the objects required for an execbuffer, an untimely allocation failure in creating the vma results in the object being unreferenced from two lists. The ownership during the lookup is meant to be moved from the list of objects being looked to the vma, and this double unreference upon error results in a use-after-free. Fixes regression from commit 27173f1f95db5e74ceb35fe9a2f2f348ea11bac9 Author: Ben Widawsky Date: Wed Aug 14 11:38:36 2013 +0200 drm/i915: Convert execbuf code to use vmas Based on the fix by Ben Widawsky. Signed-off-by: Chris Wilson Cc: Ben Widawsky Cc: stable@vger.kernel.org [danvet: Bikeshed the crucial comment above the ownership transfer as discussed on irc.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b7e787fb4649..a3ba9a8cd687 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -93,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb, { struct drm_i915_gem_object *obj; struct list_head objects; - int i, ret = 0; + int i, ret; INIT_LIST_HEAD(&objects); spin_lock(&file->table_lock); @@ -106,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb, DRM_DEBUG("Invalid object handle %d at index %d\n", exec[i].handle, i); ret = -ENOENT; - goto out; + goto err; } if (!list_empty(&obj->obj_exec_link)) { @@ -114,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb, DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n", obj, exec[i].handle, i); ret = -EINVAL; - goto out; + goto err; } drm_gem_object_reference(&obj->base); @@ -123,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb, spin_unlock(&file->table_lock); i = 0; - list_for_each_entry(obj, &objects, obj_exec_link) { + while (!list_empty(&objects)) { struct i915_vma *vma; + obj = list_first_entry(&objects, + struct drm_i915_gem_object, + obj_exec_link); + /* * NOTE: We can leak any vmas created here when something fails * later on. But that's no issue since vma_unbind can deal with @@ -138,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb, if (IS_ERR(vma)) { DRM_DEBUG("Failed to lookup VMA\n"); ret = PTR_ERR(vma); - goto out; + goto err; } + /* Transfer ownership from the objects list to the vmas list. */ list_add_tail(&vma->exec_list, &eb->vmas); + list_del_init(&obj->obj_exec_link); vma->exec_entry = &exec[i]; if (eb->and < 0) { @@ -155,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb, ++i; } + return 0; + -out: +err: while (!list_empty(&objects)) { obj = list_first_entry(&objects, struct drm_i915_gem_object, obj_exec_link); list_del_init(&obj->obj_exec_link); - if (ret) - drm_gem_object_unreference(&obj->base); + drm_gem_object_unreference(&obj->base); } + /* + * Objects already transfered to the vmas list will be unreferenced by + * eb_destroy. + */ + return ret; } -- cgit v1.2.3 From 4db080f9e93411c3c41ec402244da28e2bbde835 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2013 11:37:09 +0000 Subject: drm/i915: Fix erroneous dereference of batch_obj inside reset_status As the rings may be processed and their requests deallocated in a different order to the natural retirement during a reset, /* Whilst this request exists, batch_obj will be on the * active_list, and so will hold the active reference. Only when this * request is retired will the the batch_obj be moved onto the * inactive_list and lose its active reference. Hence we do not need * to explicitly hold another reference here. */ is violated, and the batch_obj may be dereferenced after it had been freed on another ring. This can be simply avoided by processing the status update prior to deallocating any requests. Fixes regression (a possible OOPS following a GPU hang) from commit aa60c664e6df502578454621c3a9b1f087ff8d25 Author: Mika Kuoppala Date: Wed Jun 12 15:13:20 2013 +0300 drm/i915: find guilty batch buffer on ring resets Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: stable@vger.kernel.org Reviewed-by: Mika Kuoppala [danvet: Add the code comment Chris supplied.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 621c7c67a643..76d3d1ab73c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2343,15 +2343,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request) kfree(request); } -static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, - struct intel_ring_buffer *ring) +static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) { - u32 completed_seqno; - u32 acthd; + u32 completed_seqno = ring->get_seqno(ring, false); + u32 acthd = intel_ring_get_active_head(ring); + struct drm_i915_gem_request *request; + + list_for_each_entry(request, &ring->request_list, list) { + if (i915_seqno_passed(completed_seqno, request->seqno)) + continue; - acthd = intel_ring_get_active_head(ring); - completed_seqno = ring->get_seqno(ring, false); + i915_set_reset_status(ring, request, acthd); + } +} +static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) +{ while (!list_empty(&ring->request_list)) { struct drm_i915_gem_request *request; @@ -2359,9 +2368,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, struct drm_i915_gem_request, list); - if (request->seqno > completed_seqno) - i915_set_reset_status(ring, request, acthd); - i915_gem_free_request(request); } @@ -2403,8 +2409,16 @@ void i915_gem_reset(struct drm_device *dev) struct intel_ring_buffer *ring; int i; + /* + * Before we free the objects from the requests, we need to inspect + * them for finding the guilty party. As the requests only borrow + * their reference to the objects, the inspection must be done first. + */ + for_each_ring(ring, dev_priv, i) + i915_gem_reset_ring_status(dev_priv, ring); + for_each_ring(ring, dev_priv, i) - i915_gem_reset_ring_lists(dev_priv, ring); + i915_gem_reset_ring_cleanup(dev_priv, ring); i915_gem_cleanup_ringbuffer(dev); -- cgit v1.2.3 From 714bb654e97535c4bed4a8da0628cbc842dc8e31 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 12 Dec 2013 12:53:52 +0800 Subject: spi/fsl-espi: Add Power Management support for eSPI controller Add PM support for eSPI controller using callback function suspend and resume in .driver.pm of platform_driver. Signed-off-by: Hou Zhiqiang Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 8106006cdc39..428dc7a6b62e 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -727,6 +727,66 @@ static int of_fsl_espi_remove(struct platform_device *dev) return mpc8xxx_spi_remove(&dev->dev); } +#ifdef CONFIG_PM_SLEEP +static int of_fsl_espi_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct mpc8xxx_spi *mpc8xxx_spi; + struct fsl_espi_reg *reg_base; + u32 regval; + int ret; + + mpc8xxx_spi = spi_master_get_devdata(master); + reg_base = mpc8xxx_spi->reg_base; + + ret = spi_master_suspend(master); + if (ret) { + dev_warn(dev, "cannot suspend master\n"); + return ret; + } + + regval = mpc8xxx_spi_read_reg(®_base->mode); + regval &= ~SPMODE_ENABLE; + mpc8xxx_spi_write_reg(®_base->mode, regval); + + return 0; +} + +static int of_fsl_espi_resume(struct device *dev) +{ + struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); + struct spi_master *master = dev_get_drvdata(dev); + struct mpc8xxx_spi *mpc8xxx_spi; + struct fsl_espi_reg *reg_base; + u32 regval; + int i; + + mpc8xxx_spi = spi_master_get_devdata(master); + reg_base = mpc8xxx_spi->reg_base; + + /* SPI controller initializations */ + mpc8xxx_spi_write_reg(®_base->mode, 0); + mpc8xxx_spi_write_reg(®_base->mask, 0); + mpc8xxx_spi_write_reg(®_base->command, 0); + mpc8xxx_spi_write_reg(®_base->event, 0xffffffff); + + /* Init eSPI CS mode register */ + for (i = 0; i < pdata->max_chipselect; i++) + mpc8xxx_spi_write_reg(®_base->csmode[i], CSMODE_INIT_VAL); + + /* Enable SPI interface */ + regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; + + mpc8xxx_spi_write_reg(®_base->mode, regval); + + return spi_master_resume(master); +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops espi_pm = { + SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume) +}; + static const struct of_device_id of_fsl_espi_match[] = { { .compatible = "fsl,mpc8536-espi" }, {} @@ -738,6 +798,7 @@ static struct platform_driver fsl_espi_driver = { .name = "fsl_espi", .owner = THIS_MODULE, .of_match_table = of_fsl_espi_match, + .pm = &espi_pm, }, .probe = of_fsl_espi_probe, .remove = of_fsl_espi_remove, -- cgit v1.2.3 From 272012d0f748de2e4d2428f5cb7003280032ce08 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 4 Dec 2013 21:05:46 +0900 Subject: irqchip: renesas-irqc: Use lazy disable Set the ->irq_enable() and ->irq_disable() methods to NULL to enable lazy disable of interrupts. This by itself provides some level of optimization, but is mainly enabled as ground work for future Suspend-to-RAM wake up support. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- drivers/irqchip/irq-renesas-irqc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 2f404ba61c6c..8fdd7d68cd00 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c @@ -212,8 +212,6 @@ static int irqc_probe(struct platform_device *pdev) irq_chip->name = name; irq_chip->irq_mask = irqc_irq_disable; irq_chip->irq_unmask = irqc_irq_enable; - irq_chip->irq_enable = irqc_irq_enable; - irq_chip->irq_disable = irqc_irq_disable; irq_chip->irq_set_type = irqc_irq_set_type; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; -- cgit v1.2.3 From 6a7e3b3007b5396a9e812ca0ceddc7915f8768dd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 4 Dec 2013 21:05:56 +0900 Subject: irqchip: renesas-irqc: Enable mask on suspend Now when lazy interrupt disable has been enabled in the driver then extend the code to set IRQCHIP_MASK_ON_SUSPEND which tells the core that only IRQs marked as wakeups need to stay enabled during Suspend-to-RAM. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- drivers/irqchip/irq-renesas-irqc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 8fdd7d68cd00..082d95cb5528 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c @@ -213,7 +213,7 @@ static int irqc_probe(struct platform_device *pdev) irq_chip->irq_mask = irqc_irq_disable; irq_chip->irq_unmask = irqc_irq_enable; irq_chip->irq_set_type = irqc_irq_set_type; - irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; + irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->number_of_irqs, -- cgit v1.2.3 From 078c6ac1bd83654df62ea5914f98093e1f764320 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 7 Dec 2013 18:13:15 +0100 Subject: pwm: jz4740: Pass device to clk_get() In preparation to switching the jz4740 clk driver to the common clk framework make sure to pass the device to clk_get(). Signed-off-by: Lars-Peter Clausen Signed-off-by: Thierry Reding --- drivers/pwm/pwm-jz4740.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 0a2ede3c3932..a44d890c3818 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -171,7 +171,7 @@ static int jz4740_pwm_probe(struct platform_device *pdev) if (!jz4740) return -ENOMEM; - jz4740->clk = clk_get(NULL, "ext"); + jz4740->clk = clk_get(&pdev->dev, "ext"); if (IS_ERR(jz4740->clk)) return PTR_ERR(jz4740->clk); -- cgit v1.2.3 From 0dc1135fdf5e2b2a3dbacd59c66f3e9236894425 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 7 Dec 2013 18:13:16 +0100 Subject: pwm: jz4740: Use devm_clk_get() Using the managed version of clk_get() makes the code a bit shorter and the error paths less complicated. Signed-off-by: Lars-Peter Clausen Signed-off-by: Thierry Reding --- drivers/pwm/pwm-jz4740.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index a44d890c3818..9c46209e1d02 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -165,13 +165,12 @@ static const struct pwm_ops jz4740_pwm_ops = { static int jz4740_pwm_probe(struct platform_device *pdev) { struct jz4740_pwm_chip *jz4740; - int ret; jz4740 = devm_kzalloc(&pdev->dev, sizeof(*jz4740), GFP_KERNEL); if (!jz4740) return -ENOMEM; - jz4740->clk = clk_get(&pdev->dev, "ext"); + jz4740->clk = devm_clk_get(&pdev->dev, "ext"); if (IS_ERR(jz4740->clk)) return PTR_ERR(jz4740->clk); @@ -180,29 +179,16 @@ static int jz4740_pwm_probe(struct platform_device *pdev) jz4740->chip.npwm = NUM_PWM; jz4740->chip.base = -1; - ret = pwmchip_add(&jz4740->chip); - if (ret < 0) { - clk_put(jz4740->clk); - return ret; - } - platform_set_drvdata(pdev, jz4740); - return 0; + return pwmchip_add(&jz4740->chip); } static int jz4740_pwm_remove(struct platform_device *pdev) { struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev); - int ret; - - ret = pwmchip_remove(&jz4740->chip); - if (ret < 0) - return ret; - clk_put(jz4740->clk); - - return 0; + return pwmchip_remove(&jz4740->chip); } static struct platform_driver jz4740_pwm_driver = { -- cgit v1.2.3 From b664607480ace4c13c946dee6a1c0e72a2d0d48e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 11 Dec 2013 18:50:08 -0200 Subject: drm/i915: remove i915_disable_vga_mem declaration It was supposed to have been killed on the same commit that killed the function, e1264ebe9ff48e1b3e1dd11805eec9f5b143ab7c, but I guess the intel_drv.h reorganization accidentally brought it back. Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4a4effba134b..a829ab5516f4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -703,7 +703,6 @@ void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, int dotclock); bool intel_crtc_active(struct drm_crtc *crtc); -void i915_disable_vga_mem(struct drm_device *dev); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); void intel_display_set_init_power(struct drm_device *dev, bool enable); -- cgit v1.2.3 From d5e8fdc8c10bdff9b8af9cc8b25607ae71e26d3b Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 11 Dec 2013 18:50:09 -0200 Subject: drm/i915: extract hsw_power_well_post_{enable, disable} I want to add more code to the post_enable function. Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 75 ++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2590a5c90725..d8fb00a2b565 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5681,12 +5681,53 @@ bool intel_display_power_enabled(struct drm_device *dev, return is_enabled; } +static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + unsigned long irqflags; + + if (IS_BROADWELL(dev)) { + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), + dev_priv->de_irq_mask[PIPE_B]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), + ~dev_priv->de_irq_mask[PIPE_B] | + GEN8_PIPE_VBLANK); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), + dev_priv->de_irq_mask[PIPE_C]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), + ~dev_priv->de_irq_mask[PIPE_C] | + GEN8_PIPE_VBLANK); + POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + } +} + +static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + enum pipe p; + unsigned long irqflags; + + /* + * After this, the registers on the pipes that are part of the power + * well will become zero, so we have to adjust our counters according to + * that. + * + * FIXME: Should we do this in general in drm_vblank_post_modeset? + */ + spin_lock_irqsave(&dev->vbl_lock, irqflags); + for_each_pipe(p) + if (p != PIPE_A) + dev->vblank[p].last = 0; + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); +} + static void hsw_set_power_well(struct drm_device *dev, struct i915_power_well *power_well, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; bool is_enabled, enable_requested; - unsigned long irqflags; uint32_t tmp; WARN_ON(dev_priv->pc8.enabled); @@ -5707,42 +5748,14 @@ static void hsw_set_power_well(struct drm_device *dev, DRM_ERROR("Timeout enabling power well\n"); } - if (IS_BROADWELL(dev)) { - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), - dev_priv->de_irq_mask[PIPE_B]); - I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), - ~dev_priv->de_irq_mask[PIPE_B] | - GEN8_PIPE_VBLANK); - I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), - dev_priv->de_irq_mask[PIPE_C]); - I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), - ~dev_priv->de_irq_mask[PIPE_C] | - GEN8_PIPE_VBLANK); - POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - } + hsw_power_well_post_enable(dev_priv); } else { if (enable_requested) { - enum pipe p; - I915_WRITE(HSW_PWR_WELL_DRIVER, 0); POSTING_READ(HSW_PWR_WELL_DRIVER); DRM_DEBUG_KMS("Requesting to disable the power well\n"); - /* - * After this, the registers on the pipes that are part - * of the power well will become zero, so we have to - * adjust our counters according to that. - * - * FIXME: Should we do this in general in - * drm_vblank_post_modeset? - */ - spin_lock_irqsave(&dev->vbl_lock, irqflags); - for_each_pipe(p) - if (p != PIPE_A) - dev->vblank[p].last = 0; - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + hsw_power_well_post_disable(dev_priv); } } } -- cgit v1.2.3 From f9dcb0dfee98406c9c64e1aad10af427d644b78f Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 11 Dec 2013 18:50:10 -0200 Subject: drm/i915: touch VGA MSR after we enable the power well Fixes regression introduced by: commit bf51d5e2cda5d36d98e4b46ac7fca9461e512c41 Author: Paulo Zanoni Date: Wed Jul 3 17:12:13 2013 -0300 drm/i915: switch disable_power_well default value to 1 The bug I'm seeing can be reproduced with: - Have vgacon configured/enabled - Make sure the power well gets disabled, then enabled. You can check this by seeing the messages print by hsw_set_power_well - Stop your display manager - echo 0 > /sys/class/vtconsole/vtcon1/bind I can easily reproduce this by blacklising snd_hda_intel and booting with eDP+HDMI. If you do this and then look at dmesg, you'll see we're printing infinite "Unclaimed register" messages. This is happening because we're stuck on an infinite loop inside console_unlock(), which is calling many functions from vgacon.c. And the code that's triggering the error messages is from vgacon_set_cursor_size(). After we re-enable the power well, every time we read/write the VGA address 0x3d5 we get an "unclaimed register" interrupt (ERR_INT) and print error messages. If we write anything to the VGA MSR register (it doesn't really matter which value you write to bit 0), any reads/writes to 0x3d5 _don't_ trigger the "unclaimed register" errors anymore (even if MSR bit 0 is zero). So what happens with the current code is that when we unbind i915 and bind vgacon, we call console_unlock(). Function console_unlock() is responsible for printing any messages that were supposed to be print when the console was locked, so it calls the TTY layer, which calls the console layer, which calls vgacon to print the messages. At this point, vgacon eventually calls vgacon_set_cursor_size(), which touches 0x3d5, which triggers unclaimed register interrupts. The problem is that when we get these interrupts, we print the error messages, so we add more work to console_unlock(), which will try to print it again, and then call vgacon again, trigger a new interrupt, which will put more stuff to the buffer, and then we'll be stuck at console_unlock() forever. If you patch intel_uncore.c to not print anything when we detect unclaimed registers, we won't get into the console_unlock() infinite loop and the driver unbind will work just fine. We will still be getting interrupts every time vgacon touches those registers, but we will survive. This is a valid experiment, but IMHO it's not the real fix: if we don't print any error messages we will still keep getting the interrupts, and if we disable ERR_INT we won't get the interrupt anymore, but we will also stop getting all the other error interrupts. I talked about this problem with the HW engineer and his recommendation is "So don't do any VGA I/O or memory access while the power well is disabled, and make to re-program MSR after enabling the power well and before using VGA I/O or memory accesses.". Notice that this is just a partial fix to fd.o #67813. This fixes the case where the power well is already enabled when we unbind, not when it's disabled when we unbind. V2: - Rebase (first version was sent in September). V3: - Complete rewrite of the same fix: smaller implementation, improved commit message. Testcase: igt/drv_module_reload Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813 Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d8fb00a2b565..3cd521f3823b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -30,6 +30,7 @@ #include "intel_drv.h" #include "../../../platform/x86/intel_ips.h" #include +#include #include #include @@ -5686,6 +5687,20 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; unsigned long irqflags; + /* + * After we re-enable the power well, if we touch VGA register 0x3d5 + * we'll get unclaimed register interrupts. This stops after we write + * anything to the VGA MSR register. The vgacon module uses this + * register all the time, so if we unbind our driver and, as a + * consequence, bind vgacon, we'll get stuck in an infinite loop at + * console_unlock(). So make here we touch the VGA MSR register, making + * sure vgacon can keep working normally without triggering interrupts + * and error messages. + */ + vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); + outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); + vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); + if (IS_BROADWELL(dev)) { spin_lock_irqsave(&dev_priv->irq_lock, irqflags); I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), -- cgit v1.2.3 From 94d88d63c64a2d9420b77f5efa3f9bf2103fb9a8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 02:18:33 +0100 Subject: pwm: renesas-tpu: Enable driver compilation with COMPILE_TEST This helps increasing build testing coverage. Cc: Thierry Reding Cc: linux-pwm@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index eece329d7872..5de6fcf7f0d4 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -139,7 +139,7 @@ config PWM_PXA config PWM_RENESAS_TPU tristate "Renesas TPU PWM support" - depends on ARCH_SHMOBILE + depends on ARCH_SHMOBILE || COMPILE_TEST help This driver exposes the Timer Pulse Unit (TPU) PWM controller found in Renesas chips through the PWM API. -- cgit v1.2.3 From e2afca6988c335d2ec7b66f2fadcd63286570bf8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 13:40:31 +0100 Subject: serial: sh-sci: Fix warnings due to improper casts and printk formats Use the %zu and %pad printk specifiers to print size_t and dma_addr_t variables, and cast pointers to uintptr_t instead of unsigned int where applicable. This fixes warnings on platforms where pointers and/or dma_addr_t have a different size than int. Cc: linux-serial@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/tty/serial/sh-sci.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 7d8103cd3e2e..6e5ce628b4eb 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -557,7 +557,7 @@ static inline int sci_rxd_in(struct uart_port *port) return 1; /* Cast for ARM damage */ - return !!__raw_readb((void __iomem *)s->cfg->port_reg); + return !!__raw_readb((void __iomem *)(uintptr_t)s->cfg->port_reg); } /* ********************************************************************** * @@ -1309,7 +1309,7 @@ static int sci_dma_rx_push(struct sci_port *s, size_t count) } if (room < count) - dev_warn(port->dev, "Rx overrun: dropping %u bytes\n", + dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n", count - room); if (!room) return room; @@ -1442,7 +1442,7 @@ static void work_fn_rx(struct work_struct *work) int count; chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); - dev_dbg(port->dev, "Read %u bytes with cookie %d\n", + dev_dbg(port->dev, "Read %zu bytes with cookie %d\n", sh_desc->partial, sh_desc->cookie); spin_lock_irqsave(&port->lock, flags); @@ -1691,16 +1691,17 @@ static void sci_request_dma(struct uart_port *port) s->chan_tx = chan; sg_init_table(&s->sg_tx, 1); /* UART circular tx buffer is an aligned page. */ - BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK); + BUG_ON((uintptr_t)port->state->xmit.buf & ~PAGE_MASK); sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf), - UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK); + UART_XMIT_SIZE, + (uintptr_t)port->state->xmit.buf & ~PAGE_MASK); nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE); if (!nent) sci_tx_dma_release(s, false); else - dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__, - sg_dma_len(&s->sg_tx), - port->state->xmit.buf, sg_dma_address(&s->sg_tx)); + dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__, + sg_dma_len(&s->sg_tx), port->state->xmit.buf, + &sg_dma_address(&s->sg_tx)); s->sg_len_tx = nent; @@ -1740,7 +1741,7 @@ static void sci_request_dma(struct uart_port *port) sg_init_table(sg, 1); sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, - (int)buf[i] & ~PAGE_MASK); + (uintptr_t)buf[i] & ~PAGE_MASK); sg_dma_address(sg) = dma[i]; } -- cgit v1.2.3 From 61e7380403efbaf5f796e8cf979827c602bf6c50 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 7 Dec 2013 14:08:22 +0400 Subject: gpio: 74x164: Remove non-DT support Commit 20bc4d5d565159eb2b942bf4b7fae86fba94e32c (gpio: 74x164: Add support for the daisy-chaining) introduce check for DT for the driver, so driver cannot be used without DT. There are no in-tree users of this driver, so remove non-DT support completely. Signed-off-by: Alexander Shiyan Acked-by: Mark Brown Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 6 +++--- drivers/gpio/gpio-74x164.c | 14 +------------- include/linux/spi/74x164.h | 9 --------- 3 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 include/linux/spi/74x164.h (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ae3682d25a3c..4127f68412eb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -714,10 +714,10 @@ config GPIO_MC33880 config GPIO_74X164 tristate "74x164 serial-in/parallel-out 8-bits shift register" - depends on SPI_MASTER + depends on SPI_MASTER && OF help - Platform driver for 74x164 compatible serial-in/parallel-out - 8-outputs shift registers. This driver can be used to provide access + Driver for 74x164 compatible serial-in/parallel-out 8-outputs + shift registers. This driver can be used to provide access to more gpio outputs. comment "AC97 GPIO expanders:" diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ddb831232407..4d4e15ca67e0 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -108,14 +107,8 @@ static int gen_74x164_direction_output(struct gpio_chip *gc, static int gen_74x164_probe(struct spi_device *spi) { struct gen_74x164_chip *chip; - struct gen_74x164_chip_platform_data *pdata; int ret; - if (!spi->dev.of_node) { - dev_err(&spi->dev, "No device tree data available.\n"); - return -EINVAL; - } - /* * bits_per_word cannot be configured in platform data */ @@ -129,12 +122,6 @@ static int gen_74x164_probe(struct spi_device *spi) if (!chip) return -ENOMEM; - pdata = dev_get_platdata(&spi->dev); - if (pdata && pdata->base) - chip->gpio_chip.base = pdata->base; - else - chip->gpio_chip.base = -1; - mutex_init(&chip->lock); spi_set_drvdata(spi, chip); @@ -145,6 +132,7 @@ static int gen_74x164_probe(struct spi_device *spi) chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; + chip->gpio_chip.base = -1; if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) { dev_err(&spi->dev, "Missing registers-number property in the DT.\n"); diff --git a/include/linux/spi/74x164.h b/include/linux/spi/74x164.h deleted file mode 100644 index 0aa6acc73317..000000000000 --- a/include/linux/spi/74x164.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef LINUX_SPI_74X164_H -#define LINUX_SPI_74X164_H - -struct gen_74x164_chip_platform_data { - /* number assigned to the first GPIO */ - unsigned base; -}; - -#endif -- cgit v1.2.3 From bcc0562c776e4b09c7b9f24cddb8724fbe7a3fa5 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 7 Dec 2013 14:08:23 +0400 Subject: gpio: 74x164: Driver cleanup - Removed excess "spi" field from private data. - Removed excess check for spi_get_drvdata() in remove(). - Removed unneeded message in remove(). - Simplify error path in probe(). - Fixed warnings by scripts/checkfile.pl. Signed-off-by: Alexander Shiyan Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74x164.c | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 4d4e15ca67e0..e4ae29824c32 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -20,7 +20,6 @@ #define GEN_74X164_NUMBER_GPIOS 8 struct gen_74x164_chip { - struct spi_device *spi; u8 *buffer; struct gpio_chip gpio_chip; struct mutex lock; @@ -34,6 +33,7 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) static int __gen_74x164_write_config(struct gen_74x164_chip *chip) { + struct spi_device *spi = to_spi_device(chip->gpio_chip.dev); struct spi_message message; struct spi_transfer *msg_buf; int i, ret = 0; @@ -54,12 +54,12 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip) * byte of the buffer will end up in the last register. */ for (i = chip->registers - 1; i >= 0; i--) { - msg_buf[i].tx_buf = chip->buffer +i; + msg_buf[i].tx_buf = chip->buffer + i; msg_buf[i].len = sizeof(u8); spi_message_add_tail(msg_buf + i, &message); } - ret = spi_sync(chip->spi, &message); + ret = spi_sync(spi, &message); kfree(msg_buf); @@ -122,35 +122,32 @@ static int gen_74x164_probe(struct spi_device *spi) if (!chip) return -ENOMEM; - mutex_init(&chip->lock); - spi_set_drvdata(spi, chip); - chip->spi = spi; - chip->gpio_chip.label = spi->modalias; chip->gpio_chip.direction_output = gen_74x164_direction_output; chip->gpio_chip.get = gen_74x164_get_value; chip->gpio_chip.set = gen_74x164_set_value; chip->gpio_chip.base = -1; - if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) { - dev_err(&spi->dev, "Missing registers-number property in the DT.\n"); - ret = -EINVAL; - goto exit_destroy; + if (of_property_read_u32(spi->dev.of_node, "registers-number", + &chip->registers)) { + dev_err(&spi->dev, + "Missing registers-number property in the DT.\n"); + return -EINVAL; } chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL); - if (!chip->buffer) { - ret = -ENOMEM; - goto exit_destroy; - } + if (!chip->buffer) + return -ENOMEM; chip->gpio_chip.can_sleep = true; chip->gpio_chip.dev = &spi->dev; chip->gpio_chip.owner = THIS_MODULE; + mutex_init(&chip->lock); + ret = __gen_74x164_write_config(chip); if (ret) { dev_err(&spi->dev, "Failed writing: %d\n", ret); @@ -158,31 +155,23 @@ static int gen_74x164_probe(struct spi_device *spi) } ret = gpiochip_add(&chip->gpio_chip); - if (ret) - goto exit_destroy; - - return ret; + if (!ret) + return 0; exit_destroy: mutex_destroy(&chip->lock); + return ret; } static int gen_74x164_remove(struct spi_device *spi) { - struct gen_74x164_chip *chip; + struct gen_74x164_chip *chip = spi_get_drvdata(spi); int ret; - chip = spi_get_drvdata(spi); - if (chip == NULL) - return -ENODEV; - ret = gpiochip_remove(&chip->gpio_chip); if (!ret) mutex_destroy(&chip->lock); - else - dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", - ret); return ret; } -- cgit v1.2.3 From 3b31d0eca5fd8d7d485c7cb7319a5cd6a3207726 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 12 Dec 2013 11:18:41 +0200 Subject: gpio: driver for Xtensa GPIO32 GPIO32 is a standard optional extension to the Xtensa architecture core that provides preconfigured output and input ports for intra SoC signaling. The GPIO32 option is implemented as 32bit Tensilica Instruction Extension (TIE) output state called EXPSTATE, and 32bit input wire called IMPWIRE. This driver treats input and output states as two distinct devices. v3: * Use BUG() in xtensa_impwire_set_value() to indicate that it should never be called (Linus Walleij) v2: * Address the comments of Linus Walleij: - Add a few comments - Expand commit log message - Use the BIT() macro for bit offsets - Rewrite CPENABLE handling as static inlines - Use device_initcall() * Depend on !SMP for reason explained in the comments (Marc Gauthier) * Use XCHAL_CP_ID_XTIOP to enable/disable GPIO32 only Signed-off-by: Baruch Siach Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-xtensa.c | 163 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 drivers/gpio/gpio-xtensa.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4127f68412eb..02e8d5350f8b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -288,6 +288,14 @@ config GPIO_XILINX help Say yes here to support the Xilinx FPGA GPIO device +config GPIO_XTENSA + bool "Xtensa GPIO32 support" + depends on XTENSA + depends on !SMP + help + Say yes here to support the Xtensa internal GPIO32 IMPWIRE (input) + and EXPSTATE (output) ports + config GPIO_VR41XX tristate "NEC VR4100 series General-purpose I/O Uint support" depends on CPU_VR41XX diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ee95154cb1d2..699e7cd96584 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -96,3 +96,4 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o +obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o diff --git a/drivers/gpio/gpio-xtensa.c b/drivers/gpio/gpio-xtensa.c new file mode 100644 index 000000000000..1d136eceda62 --- /dev/null +++ b/drivers/gpio/gpio-xtensa.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013 TangoTec Ltd. + * Author: Baruch Siach + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for the Xtensa LX4 GPIO32 Option + * + * Documentation: Xtensa LX4 Microprocessor Data Book, Section 2.22 + * + * GPIO32 is a standard optional extension to the Xtensa architecture core that + * provides preconfigured output and input ports for intra SoC signaling. The + * GPIO32 option is implemented as 32bit Tensilica Instruction Extension (TIE) + * output state called EXPSTATE, and 32bit input wire called IMPWIRE. This + * driver treats input and output states as two distinct devices. + * + * Access to GPIO32 specific instructions is controlled by the CPENABLE + * (Coprocessor Enable Bits) register. By default Xtensa Linux startup code + * disables access to all coprocessors. This driver sets the CPENABLE bit + * corresponding to GPIO32 before any GPIO32 specific instruction, and restores + * CPENABLE state after that. + * + * This driver is currently incompatible with SMP. The GPIO32 extension is not + * guaranteed to be available in all cores. Moreover, each core controls a + * different set of IO wires. A theoretical SMP aware version of this driver + * would need to have a per core workqueue to do the actual GPIO manipulation. + */ + +#include +#include +#include +#include +#include + +#include /* CPENABLE read/write macros */ + +#ifndef XCHAL_CP_ID_XTIOP +#error GPIO32 option is not enabled for your xtensa core variant +#endif + +static inline unsigned long enable_cp(unsigned long *cpenable) +{ + unsigned long flags; + + local_irq_save(flags); + RSR_CPENABLE(*cpenable); + WSR_CPENABLE(*cpenable | BIT(XCHAL_CP_ID_XTIOP)); + + return flags; +} + +static inline void disable_cp(unsigned long flags, unsigned long cpenable) +{ + WSR_CPENABLE(cpenable); + local_irq_restore(flags); +} + +static int xtensa_impwire_get_direction(struct gpio_chip *gc, unsigned offset) +{ + return 1; /* input only */ +} + +static int xtensa_impwire_get_value(struct gpio_chip *gc, unsigned offset) +{ + unsigned long flags, saved_cpenable; + u32 impwire; + + flags = enable_cp(&saved_cpenable); + __asm__ __volatile__("read_impwire %0" : "=a" (impwire)); + disable_cp(flags, saved_cpenable); + + return !!(impwire & BIT(offset)); +} + +static void xtensa_impwire_set_value(struct gpio_chip *gc, unsigned offset, + int value) +{ + BUG(); /* output only; should never be called */ +} + +static int xtensa_expstate_get_direction(struct gpio_chip *gc, unsigned offset) +{ + return 0; /* output only */ +} + +static int xtensa_expstate_get_value(struct gpio_chip *gc, unsigned offset) +{ + unsigned long flags, saved_cpenable; + u32 expstate; + + flags = enable_cp(&saved_cpenable); + __asm__ __volatile__("rur.expstate %0" : "=a" (expstate)); + disable_cp(flags, saved_cpenable); + + return !!(expstate & BIT(offset)); +} + +static void xtensa_expstate_set_value(struct gpio_chip *gc, unsigned offset, + int value) +{ + unsigned long flags, saved_cpenable; + u32 mask = BIT(offset); + u32 val = value ? BIT(offset) : 0; + + flags = enable_cp(&saved_cpenable); + __asm__ __volatile__("wrmsk_expstate %0, %1" + :: "a" (val), "a" (mask)); + disable_cp(flags, saved_cpenable); +} + +static struct gpio_chip impwire_chip = { + .label = "impwire", + .base = -1, + .ngpio = 32, + .get_direction = xtensa_impwire_get_direction, + .get = xtensa_impwire_get_value, + .set = xtensa_impwire_set_value, +}; + +static struct gpio_chip expstate_chip = { + .label = "expstate", + .base = -1, + .ngpio = 32, + .get_direction = xtensa_expstate_get_direction, + .get = xtensa_expstate_get_value, + .set = xtensa_expstate_set_value, +}; + +static int xtensa_gpio_probe(struct platform_device *pdev) +{ + int ret; + + ret = gpiochip_add(&impwire_chip); + if (ret) + return ret; + return gpiochip_add(&expstate_chip); +} + +static struct platform_driver xtensa_gpio_driver = { + .driver = { + .name = "xtensa-gpio", + .owner = THIS_MODULE, + }, + .probe = xtensa_gpio_probe, +}; + +static int __init xtensa_gpio_init(void) +{ + struct platform_device *pdev; + + pdev = platform_device_register_simple("xtensa-gpio", 0, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return platform_driver_register(&xtensa_gpio_driver); +} +device_initcall(xtensa_gpio_init); + +MODULE_AUTHOR("Baruch Siach "); +MODULE_DESCRIPTION("Xtensa LX4 GPIO32 driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8333f0fe133be420ce3fcddfd568c3a559ab274e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Dec 2013 18:15:51 -0500 Subject: drm/radeon: Fix sideport problems on certain RS690 boards Some RS690 boards with 64MB of sideport memory show up as having 128MB sideport + 256MB of UMA. In this case, just skip the sideport memory and use UMA. This fixes rendering corruption and should improve performance. bug: https://bugs.freedesktop.org/show_bug.cgi?id=35457 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/rs690.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 1c560629575a..e7dab069cccf 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -162,6 +162,16 @@ static void rs690_mc_init(struct radeon_device *rdev) base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + /* Some boards seem to be configured for 128MB of sideport memory, + * but really only have 64MB. Just skip the sideport and use + * UMA memory. + */ + if (rdev->mc.igp_sideport_enabled && + (rdev->mc.real_vram_size == (384 * 1024 * 1024))) { + base += 128 * 1024 * 1024; + rdev->mc.real_vram_size -= 128 * 1024 * 1024; + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + } /* Use K8 direct mapping for fast fb access. */ rdev->fastfb_working = false; -- cgit v1.2.3 From 47e9766df0298739aab87c9874a21feb71560953 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 10 Dec 2013 17:02:43 +0200 Subject: drm/i915: Fix timeout with missed interrupts in __wait_seqno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 094f9a54e355 ("drm/i915: Fix __wait_seqno to use true infinite timeouts") added support for __wait_seqno to detect missing interrupts and go around them by polling. As there is also timeout detection in __wait_seqno, the polling and timeout detection were done with the same timer. When there has been missed interrupts and polling is needed, the timer is set to trigger in (now + 1) jiffies in future, instead of the caller specified timeout. Now when io_schedule() returns, we calculate the jiffies left to timeout using the timer expiration value. As the current jiffies is now bound to be always equal or greater than the expiration value, the timeout_jiffies will become zero or negative and we return -ETIME to caller even tho the timeout was never reached. Fix this by decoupling timeout calculation from timer expiration. v2: Commit message with some sense in it (Chris Wilson) v3: add parenthesis on timeout_expire calculation v4: don't read jiffies without timeout (Chris Wilson) Signed-off-by: Mika Kuoppala Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index df83fec174e9..279387a2fef5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1017,7 +1017,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, drm_i915_private_t *dev_priv = ring->dev->dev_private; struct timespec before, now; DEFINE_WAIT(wait); - long timeout_jiffies; + unsigned long timeout_expire; int ret; WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n"); @@ -1025,7 +1025,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, if (i915_seqno_passed(ring->get_seqno(ring, true), seqno)) return 0; - timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1; + timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0; if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) { gen6_rps_boost(dev_priv); @@ -1044,7 +1044,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, getrawmonotonic(&before); for (;;) { struct timer_list timer; - unsigned long expire; prepare_to_wait(&ring->irq_queue, &wait, interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); @@ -1070,23 +1069,22 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, break; } - if (timeout_jiffies <= 0) { + if (timeout && time_after_eq(jiffies, timeout_expire)) { ret = -ETIME; break; } timer.function = NULL; if (timeout || missed_irq(dev_priv, ring)) { + unsigned long expire; + setup_timer_on_stack(&timer, fake_irq, (unsigned long)current); - expire = jiffies + (missed_irq(dev_priv, ring) ? 1: timeout_jiffies); + expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire; mod_timer(&timer, expire); } io_schedule(); - if (timeout) - timeout_jiffies = expire - jiffies; - if (timer.function) { del_singleshot_timer_sync(&timer); destroy_timer_on_stack(&timer); -- cgit v1.2.3 From 566b734a190766f25f21c8c44633c14a122e61fa Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 25 Nov 2013 15:27:08 -0200 Subject: drm/i915: split intel_ddi_pll_mode_set in 2 pieces The first piece, intel_ddi_pll_select, finds a PLL and assigns it to the CRTC, but doesn't write any register. It can also fail in case it doesn't find a PLL. The second piece, intel_ddi_pll_enable, uses the information stored by intel_ddi_pll_select to actually enable the PLL by writing to its register. This function can't fail. We also have some refcount sanity checks here. The idea is that one day we'll remove all the functions that touch registers from haswell_crtc_mode_set to haswell_crtc_enable, so we'll call intel_ddi_pll_select at haswell_crtc_mode_set and then call intel_ddi_pll_enable at haswell_crtc_enable. Since I'm already touching this code, let's take care of this particular split today. v2: - Clock on the debug message is in KHz - Add missing POSTING_READ Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau [danvet: Bikeshed comments.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 108 +++++++++++++++++++++++++++++------ drivers/gpu/drm/i915/intel_display.c | 3 +- drivers/gpu/drm/i915/intel_drv.h | 3 +- 3 files changed, 94 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 8b0e96ff76c9..cec06a5453cc 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -696,21 +696,23 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */, *n2_out = best.n2; *p_out = best.p; *r2_out = best.r2; - - DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n", - clock, *p_out, *n2_out, *r2_out); } -bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) +/* + * Tries to find a PLL for the CRTC. If it finds, it increases the refcount and + * stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to + * steal the selected PLL. You need to call intel_ddi_pll_enable to actually + * enable the PLL. + */ +bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_crtc *crtc = &intel_crtc->base; struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); struct drm_encoder *encoder = &intel_encoder->base; struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_ddi_plls *plls = &dev_priv->ddi_plls; int type = intel_encoder->type; enum pipe pipe = intel_crtc->pipe; - uint32_t reg, val; int clock = intel_crtc->config.port_clock; intel_ddi_put_crtc_pll(crtc); @@ -734,10 +736,8 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) return false; } - /* We don't need to turn any PLL on because we'll use LCPLL. */ - return true; - } else if (type == INTEL_OUTPUT_HDMI) { + uint32_t reg, val; unsigned p, n2, r2; intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); @@ -767,6 +767,9 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) return false; } + DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n", + clock, p, n2, r2); + if (reg == WRPLL_CTL1) { plls->wrpll1_refcount++; intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; @@ -780,29 +783,98 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) DRM_DEBUG_KMS("Using SPLL on pipe %c\n", pipe_name(pipe)); plls->spll_refcount++; - reg = SPLL_CTL; intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL; } else { DRM_ERROR("SPLL already in use\n"); return false; } - WARN(I915_READ(reg) & SPLL_PLL_ENABLE, - "SPLL already enabled\n"); - - val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; - } else { WARN(1, "Invalid DDI encoder type %d\n", type); return false; } - I915_WRITE(reg, val); - udelay(20); - return true; } +/* + * To be called after intel_ddi_pll_select(). That one selects the PLL to be + * used, this one actually enables the PLL. + */ +void intel_ddi_pll_enable(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ddi_plls *plls = &dev_priv->ddi_plls; + int clock = crtc->config.port_clock; + uint32_t reg, cur_val, new_val; + int refcount; + const char *pll_name; + uint32_t enable_bit = (1 << 31); + unsigned int p, n2, r2; + + BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE); + BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE); + + switch (crtc->ddi_pll_sel) { + case PORT_CLK_SEL_LCPLL_2700: + case PORT_CLK_SEL_LCPLL_1350: + case PORT_CLK_SEL_LCPLL_810: + /* + * LCPLL should always be enabled at this point of the mode set + * sequence, so nothing to do. + */ + return; + + case PORT_CLK_SEL_SPLL: + pll_name = "SPLL"; + reg = SPLL_CTL; + refcount = plls->spll_refcount; + new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | + SPLL_PLL_SSC; + break; + + case PORT_CLK_SEL_WRPLL1: + case PORT_CLK_SEL_WRPLL2: + if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) { + pll_name = "WRPLL1"; + reg = WRPLL_CTL1; + refcount = plls->wrpll1_refcount; + } else { + pll_name = "WRPLL2"; + reg = WRPLL_CTL2; + refcount = plls->wrpll2_refcount; + } + + intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); + + new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | + WRPLL_DIVIDER_REFERENCE(r2) | + WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p); + + break; + + case PORT_CLK_SEL_NONE: + WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n"); + return; + default: + WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel); + return; + } + + cur_val = I915_READ(reg); + + WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount); + if (refcount == 1) { + WARN(cur_val & enable_bit, "%s already enabled\n", pll_name); + I915_WRITE(reg, new_val); + POSTING_READ(reg); + udelay(20); + } else { + WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name); + } +} + void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c01aff8a36bb..a40651ef525c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6902,8 +6902,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, int plane = intel_crtc->plane; int ret; - if (!intel_ddi_pll_mode_set(crtc)) + if (!intel_ddi_pll_select(intel_crtc)) return -EINVAL; + intel_ddi_pll_enable(intel_crtc); if (intel_crtc->config.has_dp_encoder) intel_dp_set_m_n(intel_crtc); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a829ab5516f4..e903432c7c37 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -613,7 +613,8 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc); void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc); void intel_ddi_setup_hw_pll_state(struct drm_device *dev); -bool intel_ddi_pll_mode_set(struct drm_crtc *crtc); +bool intel_ddi_pll_select(struct intel_crtc *crtc); +void intel_ddi_pll_enable(struct intel_crtc *crtc); void intel_ddi_put_crtc_pll(struct drm_crtc *crtc); void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); -- cgit v1.2.3 From c2eb9e7f02118764969c49879c458c9462ccabdc Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 7 Dec 2013 14:08:52 +0100 Subject: pinctrl: at91: correct a few typos Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index a7549c4c83b4..6446dc804aa7 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -118,7 +118,7 @@ struct at91_pin_group { }; /** - * struct at91_pinctrl_mux_ops - describes an At91 mux ops group + * struct at91_pinctrl_mux_ops - describes an AT91 mux ops group * on new IP with support for periph C and D the way to mux in * periph A and B has changed * So provide the right call back @@ -1396,7 +1396,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) chained_irq_enter(chip, desc); for (;;) { /* Reading ISR acks pending (edge triggered) GPIO interrupts. - * When there none are pending, we're finished unless we need + * When there are none pending, we're finished unless we need * to process multiple banks (like ID_PIOCDE on sam9263). */ isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR); @@ -1505,7 +1505,7 @@ static int at91_gpio_of_irq_setup(struct device_node *node, prev = gpio_chips[at91_gpio->pioc_idx - 1]; /* The top level handler handles one bank of GPIOs, except - * on some SoC it can handles up to three... + * on some SoC it can handle up to three... * We only set up the handler for the first of the list. */ if (prev && prev->next == at91_gpio) -- cgit v1.2.3 From 1292e6936658af72c2e585ee8df0b478b4a8c28a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 7 Dec 2013 14:08:53 +0100 Subject: pinctrl: at91: initialize config parameter to 0 When passing a not initialized config parameter, at91_pinconf_get() would return a bogus value. Fix that by initializing it to zero before using it. Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 6446dc804aa7..b0b78f3468ae 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -722,7 +722,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin; int div; - dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config); + *config = 0; + dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id); pio = pin_to_controller(info, pin_to_bank(pin_id)); pin = pin_id % MAX_NB_GPIO_PER_BANK; -- cgit v1.2.3 From 42a430f51c7500be41ca4cbd5b3de930853bd5ee Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:29:56 +0200 Subject: drm/i915: Gen2 FBC1 CFB pitch wants 32B units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On gen2 the compressed frame buffer pitch is specified in 32B units rather than the 64B units used on gen3+. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3cd521f3823b..599d445f7ce9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -104,8 +104,11 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) if (fb->pitches[0] < cfb_pitch) cfb_pitch = fb->pitches[0]; - /* FBC_CTL wants 64B units */ - cfb_pitch = (cfb_pitch / 64) - 1; + /* FBC_CTL wants 32B or 64B units */ + if (IS_GEN2(dev)) + cfb_pitch = (cfb_pitch / 32) - 1; + else + cfb_pitch = (cfb_pitch / 64) - 1; plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB; /* Clear old tags */ -- cgit v1.2.3 From 159f98750e413f5d6e63d1131417c5310ea175fb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:29:57 +0200 Subject: drm/i915: FBC_CONTROL2 is gen4 only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gen2 and gen3 don't have the FBC_CONTROL2 register, so don't touch it. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 599d445f7ce9..d7cb6bf5712d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -98,7 +98,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int cfb_pitch; int plane, i; - u32 fbc_ctl, fbc_ctl2; + u32 fbc_ctl; cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE; if (fb->pitches[0] < cfb_pitch) @@ -115,11 +115,15 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) I915_WRITE(FBC_TAG + (i * 4), 0); - /* Set it up... */ - fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; - fbc_ctl2 |= plane; - I915_WRITE(FBC_CONTROL2, fbc_ctl2); - I915_WRITE(FBC_FENCE_OFF, crtc->y); + if (IS_GEN4(dev)) { + u32 fbc_ctl2; + + /* Set it up... */ + fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; + fbc_ctl2 |= plane; + I915_WRITE(FBC_CONTROL2, fbc_ctl2); + I915_WRITE(FBC_FENCE_OFF, crtc->y); + } /* enable it... */ fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; -- cgit v1.2.3 From fd70d52acc7abef6402e21e3e11950773af3d769 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2013 17:30:02 +0200 Subject: drm/i915: Enable FBC for all mobile gen2 and gen3 platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All mobile gen2 and gen3 chipsets should have FBC1, and the code should now handle them all. So just set has_fbc=true for all such chipsets. Note that fbc is still disabled by default for now. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2137a33d5bb2..c2c9a93861ae 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -172,6 +172,7 @@ static const struct intel_device_info intel_i85x_info = { .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, + .has_fbc = 1, .ring_mask = RENDER_RING, }; @@ -191,6 +192,7 @@ static const struct intel_device_info intel_i915gm_info = { .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, + .has_fbc = 1, .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i945g_info = { @@ -203,6 +205,7 @@ static const struct intel_device_info intel_i945gm_info = { .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, + .has_fbc = 1, .ring_mask = RENDER_RING, }; -- cgit v1.2.3 From 7d6203af30b45bb1506e20935a270286c3e2393f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 7 Dec 2013 14:00:19 +0800 Subject: ahci: imx: fix the error handling in imx_ahci_probe() Release alloced resources instead of direct return from imx_ahci_probe() in the error handling case. Fixes: 4a23d1793f8e ('ahci: imx: Add i.MX53 support') Signed-off-by: Wei Yongjun Signed-off-by: Tejun Heo Acked-by: Marek Vasut --- drivers/ata/ahci_imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 2daa28891b7f..dd4d6f74d7bd 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -331,7 +331,8 @@ static int imx_ahci_probe(struct platform_device *pdev) if (IS_ERR(imxpriv->gpr)) { dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); - return PTR_ERR(imxpriv->gpr); + ret = PTR_ERR(imxpriv->gpr); + goto err_out; } /* -- cgit v1.2.3 From 1522f9c79cd29c8f55120777ddc8ba63b9216509 Mon Sep 17 00:00:00 2001 From: Martin Andersson Date: Sat, 7 Dec 2013 23:22:10 +0100 Subject: drm/radeon/dpm: Fix hwmon crash Commit ec39f64bba3421c2060fcbd1aeb6eec81fe0a42d (drm/radeon/dpm: Convert to use devm_hwmon_register_with_groups) converted one usage of dev_get_drvdata, but there were two more. bug: https://bugs.freedesktop.org/show_bug.cgi?id=72457 Signed-off-by: Martin Andersson Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_pm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index dc75bb603ea5..984097b907ef 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -552,8 +552,7 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); int hyst = to_sensor_dev_attr(attr)->index; int temp; @@ -580,8 +579,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct attribute *attr, int index) { struct device *dev = container_of(kobj, struct device, kobj); - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); /* Skip limit attributes if DPM is not enabled */ if (rdev->pm.pm_method != PM_METHOD_DPM && -- cgit v1.2.3 From 7819678faec569f90c243d877c6f948dfb03f3a9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 9 Dec 2013 17:38:51 -0500 Subject: drm/radeon/cik: plug in missing blit callback I implemented support for this, but forget to hook up the callback so the driver can actually use it. On asics with a dedicated DMA engine, we use the DMA engine for buffer migration so this is just for testing purposes. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_asic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e354ce94cdd1..c0425bb6223a 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2021,7 +2021,7 @@ static struct radeon_asic ci_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = NULL, + .blit = &cik_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -2122,7 +2122,7 @@ static struct radeon_asic kv_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = NULL, + .blit = &cik_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, -- cgit v1.2.3 From 1b3abef830db98c11d7f916a483abaf2501f3323 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 10 Dec 2013 17:57:37 +0100 Subject: drm/radeon: fix typo in cik_copy_dma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we end up with a rather strange looking result. Signed-off-by: Christian König Tested-by: Tom Stellard Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik_sdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 0300727a4f70..d08b83c6267b 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -458,7 +458,7 @@ int cik_copy_dma(struct radeon_device *rdev, radeon_ring_write(ring, 0); /* src/dst endian swap */ radeon_ring_write(ring, src_offset & 0xffffffff); radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff); - radeon_ring_write(ring, dst_offset & 0xfffffffc); + radeon_ring_write(ring, dst_offset & 0xffffffff); radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff); src_offset += cur_size_in_bytes; dst_offset += cur_size_in_bytes; -- cgit v1.2.3 From 227ae10f17a5f2fd1307b7e582b603ef7bbb7e97 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Dec 2013 11:43:58 -0500 Subject: drm/radeon: add missing display tiling setup for oland Fixes improperly set up display params for 2D tiling on oland. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 80a20120e625..b1970596a782 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1196,7 +1196,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, } else if ((rdev->family == CHIP_TAHITI) || (rdev->family == CHIP_PITCAIRN)) fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16); - else if (rdev->family == CHIP_VERDE) + else if ((rdev->family == CHIP_VERDE) || + (rdev->family == CHIP_OLAND) || + (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */ fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16); switch (radeon_crtc->crtc_id) { -- cgit v1.2.3 From 59aebe2b32466f7ed5b79f18646be6dddc926a6d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 12 Dec 2013 09:05:06 -0500 Subject: Revert "drm/radeon: Implement radeon_pci_shutdown" This causes a race condition between drm_dev_unregister() and pci_driver.shutdown at shutdown or driver unload time. We need to revisit how to properly support kexec within the drm. This reverts commit 846ae41ae99d314bf2a02784152208a6ddf7eddc. --- drivers/gpu/drm/radeon/radeon_drv.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 9f5ff28864f6..1958b36ad0e5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -508,15 +508,6 @@ static const struct file_operations radeon_driver_kms_fops = { #endif }; - -static void -radeon_pci_shutdown(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - - radeon_driver_unload_kms(dev); -} - static struct drm_driver kms_driver = { .driver_features = DRIVER_USE_AGP | @@ -586,7 +577,6 @@ static struct pci_driver radeon_kms_pci_driver = { .probe = radeon_pci_probe, .remove = radeon_pci_remove, .driver.pm = &radeon_pm_ops, - .shutdown = radeon_pci_shutdown, }; static int __init radeon_init(void) -- cgit v1.2.3 From be943c7d27b14dbd700770d2fd6c704be95a0ec9 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 14 Oct 2013 17:52:38 +0200 Subject: crypto: atmel-aes - add support for Device Tree Add support for Device Tree and use of the DMA DT API to get the needed channels. Documentation is added for these DT nodes. Initial code by: Nicolas Royer and Eukrea. Signed-off-by: Nicolas Ferre Acked-by: Herbert Xu --- .../devicetree/bindings/crypto/atmel-crypto.txt | 23 ++++ drivers/crypto/atmel-aes.c | 143 ++++++++++++++------- 2 files changed, 117 insertions(+), 49 deletions(-) create mode 100644 Documentation/devicetree/bindings/crypto/atmel-crypto.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt new file mode 100644 index 000000000000..d273f0ba549e --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt @@ -0,0 +1,23 @@ +* Atmel HW cryptographic accelerators + +These are the HW cryptographic accelerators found on some Atmel products. + +* Advanced Encryption Standard (AES) + +Required properties: +- compatible : Should be "atmel,at91sam9g46-aes". +- reg: Should contain AES registers location and length. +- interrupts: Should contain the IRQ line for the AES. +- dmas: List of two DMA specifiers as described in + atmel-dma.txt and dma.txt files. +- dma-names: Contains one identifier string for each DMA specifier + in the dmas property. + +Example: +aes@f8038000 { + compatible = "atmel,at91sam9g46-aes"; + reg = <0xf8038000 0x100>; + interrupts = <43 4 0>; + dmas = <&dma1 2 18>, + <&dma1 2 19>; + dma-names = "tx", "rx"; diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index c1efd910d97b..d7c9e317423c 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include "atmel-aes-regs.h" #define CFB8_BLOCK_SIZE 1 @@ -747,59 +749,50 @@ static int atmel_aes_dma_init(struct atmel_aes_dev *dd, struct crypto_platform_data *pdata) { int err = -ENOMEM; - dma_cap_mask_t mask_in, mask_out; + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Try to grab 2 DMA channels */ + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask, + atmel_aes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); + if (!dd->dma_lch_in.chan) + goto err_dma_in; + + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + AES_IDATAR(0); + dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size; + dd->dma_lch_in.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size; + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.device_fc = false; + + dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask, + atmel_aes_filter, &pdata->dma_slave->txdata, dd->dev, "rx"); + if (!dd->dma_lch_out.chan) + goto err_dma_out; + + dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; + dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + + AES_ODATAR(0); + dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size; + dd->dma_lch_out.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.device_fc = false; - if (pdata && pdata->dma_slave->txdata.dma_dev && - pdata->dma_slave->rxdata.dma_dev) { - - /* Try to grab 2 DMA channels */ - dma_cap_zero(mask_in); - dma_cap_set(DMA_SLAVE, mask_in); - - dd->dma_lch_in.chan = dma_request_channel(mask_in, - atmel_aes_filter, &pdata->dma_slave->rxdata); - - if (!dd->dma_lch_in.chan) - goto err_dma_in; - - dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; - dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + - AES_IDATAR(0); - dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size; - dd->dma_lch_in.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size; - dd->dma_lch_in.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.device_fc = false; - - dma_cap_zero(mask_out); - dma_cap_set(DMA_SLAVE, mask_out); - dd->dma_lch_out.chan = dma_request_channel(mask_out, - atmel_aes_filter, &pdata->dma_slave->txdata); - - if (!dd->dma_lch_out.chan) - goto err_dma_out; - - dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; - dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + - AES_ODATAR(0); - dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size; - dd->dma_lch_out.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size; - dd->dma_lch_out.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.device_fc = false; - - return 0; - } else { - return -ENODEV; - } + return 0; err_dma_out: dma_release_channel(dd->dma_lch_in.chan); err_dma_in: + dev_warn(dd->dev, "no DMA channel available\n"); return err; } @@ -1261,6 +1254,47 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) } } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_aes_dt_ids[] = { + { .compatible = "atmel,at91sam9g46-aes" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids); + +static struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct crypto_platform_data *pdata; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + + return pdata; +} +#else +static inline struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static int atmel_aes_probe(struct platform_device *pdev) { struct atmel_aes_dev *aes_dd; @@ -1272,6 +1306,14 @@ static int atmel_aes_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (!pdata) { + pdata = atmel_aes_of_init(pdev); + if (IS_ERR(pdata)) { + err = PTR_ERR(pdata); + goto aes_dd_err; + } + } + + if (!pdata->dma_slave) { err = -ENXIO; goto aes_dd_err; } @@ -1358,7 +1400,9 @@ static int atmel_aes_probe(struct platform_device *pdev) if (err) goto err_algs; - dev_info(dev, "Atmel AES\n"); + dev_info(dev, "Atmel AES - Using %s, %s for DMA transfers\n", + dma_chan_name(aes_dd->dma_lch_in.chan), + dma_chan_name(aes_dd->dma_lch_out.chan)); return 0; @@ -1424,6 +1468,7 @@ static struct platform_driver atmel_aes_driver = { .driver = { .name = "atmel_aes", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_aes_dt_ids), }, }; -- cgit v1.2.3 From 84c8976b643af63150072e6c3e5f156dd6f9c910 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 15 Oct 2013 12:14:58 +0200 Subject: crypto: atmel-tdes - add support for Device Tree Add support for Device Tree and use of the DMA DT API to get the channels if needed. Documentation is added for these DT nodes. Initial code by: Nicolas Royer and Eukrea. Signed-off-by: Nicolas Ferre Acked-by: Herbert Xu --- .../devicetree/bindings/crypto/atmel-crypto.txt | 23 ++++ drivers/crypto/atmel-tdes.c | 143 ++++++++++++++------- 2 files changed, 117 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt index d273f0ba549e..9a24fd900614 100644 --- a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt +++ b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt @@ -21,3 +21,26 @@ aes@f8038000 { dmas = <&dma1 2 18>, <&dma1 2 19>; dma-names = "tx", "rx"; + +* Triple Data Encryption Standard (Triple DES) + +Required properties: +- compatible : Should be "atmel,at91sam9g46-tdes". +- reg: Should contain TDES registers location and length. +- interrupts: Should contain the IRQ line for the TDES. + +Optional properties: +- dmas: List of two DMA specifiers as described in + atmel-dma.txt and dma.txt files. +- dma-names: Contains one identifier string for each DMA specifier + in the dmas property. + +Example: +tdes@f803c000 { + compatible = "atmel,at91sam9g46-tdes"; + reg = <0xf803c000 0x100>; + interrupts = <44 4 0>; + dmas = <&dma1 2 20>, + <&dma1 2 21>; + dma-names = "tx", "rx"; +}; diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 4a99564a08e6..6cde5b530c69 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -716,59 +717,50 @@ static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd, struct crypto_platform_data *pdata) { int err = -ENOMEM; - dma_cap_mask_t mask_in, mask_out; + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Try to grab 2 DMA channels */ + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask, + atmel_tdes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); + if (!dd->dma_lch_in.chan) + goto err_dma_in; + + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + TDES_IDATA1R; + dd->dma_lch_in.dma_conf.src_maxburst = 1; + dd->dma_lch_in.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.dst_maxburst = 1; + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.device_fc = false; + + dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask, + atmel_tdes_filter, &pdata->dma_slave->txdata, dd->dev, "rx"); + if (!dd->dma_lch_out.chan) + goto err_dma_out; + + dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; + dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + + TDES_ODATA1R; + dd->dma_lch_out.dma_conf.src_maxburst = 1; + dd->dma_lch_out.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.dst_maxburst = 1; + dd->dma_lch_out.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.device_fc = false; - if (pdata && pdata->dma_slave->txdata.dma_dev && - pdata->dma_slave->rxdata.dma_dev) { - - /* Try to grab 2 DMA channels */ - dma_cap_zero(mask_in); - dma_cap_set(DMA_SLAVE, mask_in); - - dd->dma_lch_in.chan = dma_request_channel(mask_in, - atmel_tdes_filter, &pdata->dma_slave->rxdata); - - if (!dd->dma_lch_in.chan) - goto err_dma_in; - - dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; - dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + - TDES_IDATA1R; - dd->dma_lch_in.dma_conf.src_maxburst = 1; - dd->dma_lch_in.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.dst_maxburst = 1; - dd->dma_lch_in.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.device_fc = false; - - dma_cap_zero(mask_out); - dma_cap_set(DMA_SLAVE, mask_out); - dd->dma_lch_out.chan = dma_request_channel(mask_out, - atmel_tdes_filter, &pdata->dma_slave->txdata); - - if (!dd->dma_lch_out.chan) - goto err_dma_out; - - dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM; - dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + - TDES_ODATA1R; - dd->dma_lch_out.dma_conf.src_maxburst = 1; - dd->dma_lch_out.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.dst_maxburst = 1; - dd->dma_lch_out.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_out.dma_conf.device_fc = false; - - return 0; - } else { - return -ENODEV; - } + return 0; err_dma_out: dma_release_channel(dd->dma_lch_in.chan); err_dma_in: + dev_warn(dd->dev, "no DMA channel available\n"); return err; } @@ -1317,6 +1309,47 @@ static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd) } } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_tdes_dt_ids[] = { + { .compatible = "atmel,at91sam9g46-tdes" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, atmel_tdes_dt_ids); + +static struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct crypto_platform_data *pdata; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + + return pdata; +} +#else /* CONFIG_OF */ +static inline struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *pdev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static int atmel_tdes_probe(struct platform_device *pdev) { struct atmel_tdes_dev *tdes_dd; @@ -1399,13 +1432,24 @@ static int atmel_tdes_probe(struct platform_device *pdev) if (tdes_dd->caps.has_dma) { pdata = pdev->dev.platform_data; if (!pdata) { - dev_err(&pdev->dev, "platform data not available\n"); + pdata = atmel_tdes_of_init(pdev); + if (IS_ERR(pdata)) { + dev_err(&pdev->dev, "platform data not available\n"); + err = PTR_ERR(pdata); + goto err_pdata; + } + } + if (!pdata->dma_slave) { err = -ENXIO; goto err_pdata; } err = atmel_tdes_dma_init(tdes_dd, pdata); if (err) goto err_tdes_dma; + + dev_info(dev, "using %s, %s for DMA transfers\n", + dma_chan_name(tdes_dd->dma_lch_in.chan), + dma_chan_name(tdes_dd->dma_lch_out.chan)); } spin_lock(&atmel_tdes.lock); @@ -1487,6 +1531,7 @@ static struct platform_driver atmel_tdes_driver = { .driver = { .name = "atmel_tdes", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_tdes_dt_ids), }, }; -- cgit v1.2.3 From abfe7ae407c44de51f0fec8d87d448c7c27e1285 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 15 Oct 2013 15:36:34 +0200 Subject: crypto: atmel-sha - add support for Device Tree Add support for Device Tree and use of the DMA DT API to get the channels if needed. Documentation is added for these DT nodes. Initial code by: Nicolas Royer and Eukrea. Signed-off-by: Nicolas Ferre Acked-by: Herbert Xu --- .../devicetree/bindings/crypto/atmel-crypto.txt | 22 +++++ drivers/crypto/atmel-sha.c | 99 ++++++++++++++++------ 2 files changed, 97 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt index 9a24fd900614..f2aab3dc2b52 100644 --- a/Documentation/devicetree/bindings/crypto/atmel-crypto.txt +++ b/Documentation/devicetree/bindings/crypto/atmel-crypto.txt @@ -44,3 +44,25 @@ tdes@f803c000 { <&dma1 2 21>; dma-names = "tx", "rx"; }; + +* Secure Hash Algorithm (SHA) + +Required properties: +- compatible : Should be "atmel,at91sam9g46-sha". +- reg: Should contain SHA registers location and length. +- interrupts: Should contain the IRQ line for the SHA. + +Optional properties: +- dmas: One DMA specifiers as described in + atmel-dma.txt and dma.txt files. +- dma-names: Contains one identifier string for each DMA specifier + in the dmas property. Only one "tx" string needed. + +Example: +sha@f8034000 { + compatible = "atmel,at91sam9g46-sha"; + reg = <0xf8034000 0x100>; + interrupts = <42 4 0>; + dmas = <&dma1 2 17>; + dma-names = "tx"; +}; diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index eaed8bf183bc..ecfdf727cc36 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -1263,32 +1264,29 @@ static int atmel_sha_dma_init(struct atmel_sha_dev *dd, int err = -ENOMEM; dma_cap_mask_t mask_in; - if (pdata && pdata->dma_slave->rxdata.dma_dev) { - /* Try to grab DMA channel */ - dma_cap_zero(mask_in); - dma_cap_set(DMA_SLAVE, mask_in); + /* Try to grab DMA channel */ + dma_cap_zero(mask_in); + dma_cap_set(DMA_SLAVE, mask_in); - dd->dma_lch_in.chan = dma_request_channel(mask_in, - atmel_sha_filter, &pdata->dma_slave->rxdata); - - if (!dd->dma_lch_in.chan) - return err; - - dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; - dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + - SHA_REG_DIN(0); - dd->dma_lch_in.dma_conf.src_maxburst = 1; - dd->dma_lch_in.dma_conf.src_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.dst_maxburst = 1; - dd->dma_lch_in.dma_conf.dst_addr_width = - DMA_SLAVE_BUSWIDTH_4_BYTES; - dd->dma_lch_in.dma_conf.device_fc = false; - - return 0; + dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask_in, + atmel_sha_filter, &pdata->dma_slave->rxdata, dd->dev, "tx"); + if (!dd->dma_lch_in.chan) { + dev_warn(dd->dev, "no DMA channel available\n"); + return err; } - return -ENODEV; + dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV; + dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + + SHA_REG_DIN(0); + dd->dma_lch_in.dma_conf.src_maxburst = 1; + dd->dma_lch_in.dma_conf.src_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.dst_maxburst = 1; + dd->dma_lch_in.dma_conf.dst_addr_width = + DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_in.dma_conf.device_fc = false; + + return 0; } static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd) @@ -1326,6 +1324,48 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) } } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_sha_dt_ids[] = { + { .compatible = "atmel,at91sam9g46-sha" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_sha_dt_ids); + +static struct crypto_platform_data *atmel_sha_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct crypto_platform_data *pdata; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + + return pdata; +} +#else /* CONFIG_OF */ +static inline struct crypto_platform_data *atmel_sha_of_init(struct platform_device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static int atmel_sha_probe(struct platform_device *pdev) { struct atmel_sha_dev *sha_dd; @@ -1402,13 +1442,23 @@ static int atmel_sha_probe(struct platform_device *pdev) if (sha_dd->caps.has_dma) { pdata = pdev->dev.platform_data; if (!pdata) { - dev_err(&pdev->dev, "platform data not available\n"); + pdata = atmel_sha_of_init(pdev); + if (IS_ERR(pdata)) { + dev_err(&pdev->dev, "platform data not available\n"); + err = PTR_ERR(pdata); + goto err_pdata; + } + } + if (!pdata->dma_slave) { err = -ENXIO; goto err_pdata; } err = atmel_sha_dma_init(sha_dd, pdata); if (err) goto err_sha_dma; + + dev_info(dev, "using %s for DMA transfers\n", + dma_chan_name(sha_dd->dma_lch_in.chan)); } spin_lock(&atmel_sha.lock); @@ -1483,6 +1533,7 @@ static struct platform_driver atmel_sha_driver = { .driver = { .name = "atmel_sha", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_sha_dt_ids), }, }; -- cgit v1.2.3 From 1ca5b7d95315c42cf0b78d33cd316e404a9f137c Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 15 Oct 2013 16:37:44 +0200 Subject: crypto: atmel-sha - add sha information to the log Depending on peripheral capabilities, print SHA information at the end of the probe function. Signed-off-by: Nicolas Ferre Acked-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index ecfdf727cc36..0618be06b9fb 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1469,7 +1469,9 @@ static int atmel_sha_probe(struct platform_device *pdev) if (err) goto err_algs; - dev_info(dev, "Atmel SHA1/SHA256\n"); + dev_info(dev, "Atmel SHA1/SHA256%s%s\n", + sha_dd->caps.has_sha224 ? "/SHA224" : "", + sha_dd->caps.has_sha_384_512 ? "/SHA384/SHA512" : ""); return 0; -- cgit v1.2.3 From 83301480111c9ac3fbd03ec5b0c90c21c5aa39f7 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 12 Dec 2013 17:00:45 +0100 Subject: ARM: at91: remove AT91_PROGRAMMABLE_CLOCKS configuration option This AT91 specific Kconfig option removed the code that dealt with programmable clocks. Each AT91 SoC embeds programmable clocks and there is little gain to remove this code in case that such a clock is not used. If this option is not selected, it causes certain drivers to fail to build. We simply remove this option instead of adding code just to build a workaround. Signed-off-by: Nicolas Ferre Signed-off-by: Kevin Hilman --- arch/arm/configs/at91_dt_defconfig | 1 - arch/arm/configs/at91rm9200_defconfig | 1 - arch/arm/configs/at91sam9260_9g20_defconfig | 1 - arch/arm/configs/at91sam9261_9g10_defconfig | 1 - arch/arm/configs/at91sam9g45_defconfig | 1 - arch/arm/configs/at91sam9rl_defconfig | 1 - arch/arm/configs/sama5_defconfig | 1 - arch/arm/mach-at91/Kconfig | 6 ------ arch/arm/mach-at91/clock.c | 6 ------ arch/arm/mach-at91/pm.c | 3 --- drivers/clk/at91/Makefile | 3 +-- drivers/clk/at91/pmc.c | 2 -- drivers/clk/at91/pmc.h | 2 -- sound/soc/atmel/Kconfig | 2 +- 14 files changed, 2 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index 690e89273230..0b4e9b5210d8 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -22,7 +22,6 @@ CONFIG_SOC_AT91SAM9X5=y CONFIG_SOC_AT91SAM9N12=y CONFIG_MACH_AT91RM9200_DT=y CONFIG_MACH_AT91SAM9_DT=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_TIMER_HZ=128 CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig index 75502c4d222c..bf057719dab0 100644 --- a/arch/arm/configs/at91rm9200_defconfig +++ b/arch/arm/configs/at91rm9200_defconfig @@ -31,7 +31,6 @@ CONFIG_MACH_YL9200=y CONFIG_MACH_CPUAT91=y CONFIG_MACH_ECO920=y CONFIG_MTD_AT91_DATAFLASH_CARD=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_TIMER_HZ=100 # CONFIG_ARM_THUMB is not set CONFIG_PCCARD=y diff --git a/arch/arm/configs/at91sam9260_9g20_defconfig b/arch/arm/configs/at91sam9260_9g20_defconfig index 69b6928d3d9d..955dc480f3ee 100644 --- a/arch/arm/configs/at91sam9260_9g20_defconfig +++ b/arch/arm/configs/at91sam9260_9g20_defconfig @@ -28,7 +28,6 @@ CONFIG_MACH_PCONTROL_G20=y CONFIG_MACH_GSIA18S=y CONFIG_MACH_SNAPPER_9260=y CONFIG_MACH_AT91SAM9_DT=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_SLOW_CLOCK=y # CONFIG_ARM_THUMB is not set CONFIG_AEABI=y diff --git a/arch/arm/configs/at91sam9261_9g10_defconfig b/arch/arm/configs/at91sam9261_9g10_defconfig index 9d35cd81c611..f80e993b04ce 100644 --- a/arch/arm/configs/at91sam9261_9g10_defconfig +++ b/arch/arm/configs/at91sam9261_9g10_defconfig @@ -18,7 +18,6 @@ CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9261=y CONFIG_MACH_AT91SAM9261EK=y CONFIG_MACH_AT91SAM9G10EK=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y # CONFIG_ARM_THUMB is not set CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig index 08166cd4e7d6..e181a50fd65a 100644 --- a/arch/arm/configs/at91sam9g45_defconfig +++ b/arch/arm/configs/at91sam9g45_defconfig @@ -18,7 +18,6 @@ CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9G45=y CONFIG_MACH_AT91SAM9M10G45EK=y CONFIG_MACH_AT91SAM9_DT=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_SLOW_CLOCK=y CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig index 7cf87856d63c..7b6f131cecd6 100644 --- a/arch/arm/configs/at91sam9rl_defconfig +++ b/arch/arm/configs/at91sam9rl_defconfig @@ -13,7 +13,6 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9RL=y CONFIG_MACH_AT91SAM9RLEK=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y # CONFIG_ARM_THUMB is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index f6e78f83c3c3..dc3881e07630 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -20,7 +20,6 @@ CONFIG_ARCH_AT91=y CONFIG_SOC_SAM_V7=y CONFIG_SOC_SAMA5D3=y CONFIG_MACH_SAMA5_DT=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set CONFIG_UACCESS_WITH_MEMCPY=y diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index aac7814db4f9..f1bf952da747 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -214,12 +214,6 @@ config MACH_SAMA5_DT comment "AT91 Feature Selections" -config AT91_PROGRAMMABLE_CLOCKS - bool "Programmable Clocks" - help - Select this if you need to program one or more of the PCK0..PCK3 - programmable clock outputs. - config AT91_SLOW_CLOCK bool "Suspend-to-RAM disables main oscillator" depends on SUSPEND diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 72b257944733..034529d801b2 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -330,8 +330,6 @@ EXPORT_SYMBOL(clk_get_rate); /*------------------------------------------------------------------------*/ -#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS - /* * For now, only the programmable clocks support reparenting (MCK could * do this too, with care) or rate changing (the PLLs could do this too, @@ -459,8 +457,6 @@ static void __init init_programmable_clock(struct clk *clk) clk->rate_hz = parent->rate_hz / pmc_prescaler_divider(pckr); } -#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ - /*------------------------------------------------------------------------*/ #ifdef CONFIG_DEBUG_FS @@ -577,12 +573,10 @@ int __init clk_register(struct clk *clk) clk->parent = &mck; clk->mode = pmc_sys_mode; } -#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS else if (clk_is_programmable(clk)) { clk->mode = pmc_sys_mode; init_programmable_clock(clk); } -#endif at91_clk_add(clk); diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index d43b79f56e94..590b52dea9f7 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -155,9 +155,6 @@ static int at91_pm_verify_clocks(void) } } - if (!IS_ENABLED(CONFIG_AT91_PROGRAMMABLE_CLOCKS)) - return 1; - /* PCK0..PCK3 must be disabled, or configured to use clk32k */ for (i = 0; i < 4; i++) { u32 css; diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 0e92b716f934..46c1d3d0d66b 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -4,9 +4,8 @@ obj-y += pmc.o obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o -obj-y += clk-system.o clk-peripheral.o +obj-y += clk-system.o clk-peripheral.o clk-programmable.o -obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 7b9db603b936..11fceff8d9f1 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -279,7 +279,6 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .data = of_at91sam9x5_clk_periph_setup, }, /* Programmable clocks */ -#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS) { .compatible = "atmel,at91rm9200-clk-programmable", .data = of_at91rm9200_clk_prog_setup, @@ -292,7 +291,6 @@ static const struct of_device_id pmc_clk_ids[] __initdata = { .compatible = "atmel,at91sam9x5-clk-programmable", .data = of_at91sam9x5_clk_prog_setup, }, -#endif /* UTMI clock */ #if defined(CONFIG_HAVE_AT91_UTMI) { diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index ba8d14233f80..441350983ccb 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -85,14 +85,12 @@ extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np, extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc); -#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS) extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc); extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc); extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc); -#endif #if defined(CONFIG_HAVE_AT91_UTMI) extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e48d38a1b95c..e634eb78ed03 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -25,7 +25,7 @@ config SND_ATMEL_SOC_SSC config SND_AT91_SOC_SAM9G20_WM8731 tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" - depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC && AT91_PROGRAMMABLE_CLOCKS + depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC select SND_SOC_WM8731 -- cgit v1.2.3 From c420619d5177ac8f4a624a2ec6d0ed00b8b64ddb Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 9 Dec 2013 11:38:29 +0100 Subject: pinctrl: pinconf: remove checks on ops->pin_config_get ops->pin_config_get() is only used in one specific path that will only be taken for generic pinconf drivers (ops->is_generic == true) when dumping the pinconf by using debugfs. By removing the check in pinconf_check_ops(), let's stop pressuring people to write a pin_config_get() function that will never be used and so will probably never be tested. Removing the check in pinconf_pins_show() allows driver to not implement pin_config_get() but still get a dump of the pinconf in debugfs by implementing pin_config_dbg_show(). Finally, not implementing pin_config_get() now results in returning -ENOTSUPP instead of -EINVAL. While this doesn't have any real impact for now, this feels more right. Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index b8fcc38c0d11..4187fe58794d 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -28,12 +28,6 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev) { const struct pinconf_ops *ops = pctldev->desc->confops; - /* We must be able to read out pin status */ - if (!ops->pin_config_get && !ops->pin_config_group_get) { - dev_err(pctldev->dev, - "pinconf must be able to read out pin status\n"); - return -EINVAL; - } /* We have to be able to config the pins in SOME way */ if (!ops->pin_config_set && !ops->pin_config_group_set) { dev_err(pctldev->dev, @@ -67,9 +61,9 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, const struct pinconf_ops *ops = pctldev->desc->confops; if (!ops || !ops->pin_config_get) { - dev_err(pctldev->dev, "cannot get pin configuration, missing " + dev_dbg(pctldev->dev, "cannot get pin configuration, missing " "pin_config_get() function in driver\n"); - return -EINVAL; + return -ENOTSUPP; } return ops->pin_config_get(pctldev, pin, config); @@ -93,10 +87,10 @@ int pin_config_group_get(const char *dev_name, const char *pin_group, ops = pctldev->desc->confops; if (!ops || !ops->pin_config_group_get) { - dev_err(pctldev->dev, "cannot get configuration for pin " + dev_dbg(pctldev->dev, "cannot get configuration for pin " "group, missing group config get function in " "driver\n"); - ret = -EINVAL; + ret = -ENOTSUPP; goto unlock; } @@ -305,9 +299,6 @@ static int pinconf_pins_show(struct seq_file *s, void *what) const struct pinconf_ops *ops = pctldev->desc->confops; unsigned i, pin; - if (!ops || !ops->pin_config_get) - return 0; - seq_puts(s, "Pin config settings per pin\n"); seq_puts(s, "Format: pin (name): configs\n"); @@ -356,9 +347,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) unsigned ngroups = pctlops->get_groups_count(pctldev); unsigned selector = 0; - if (!ops || !ops->pin_config_group_get) - return 0; - seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Format: group (name): configs\n"); -- cgit v1.2.3 From 2a3cf6a3599e901528d3e0025a1bd0722a8d3575 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 11 Dec 2013 11:32:28 +0900 Subject: gpiolib: return -ENOENT if no GPIO mapping exists Some devices drivers make use of optional GPIO parameters. For such drivers, it is important to discriminate between the case where no GPIO mapping has been defined for the function they are requesting, and the case where a mapping exists but an error occured while resolving it or when acquiring the GPIO. This patch changes the family of gpiod_get() functions such that they will return -ENOENT if and only if no GPIO mapping is defined for the requested function. Other error codes are used when an actual error occured during the GPIO resolution. Signed-off-by: Alexandre Courbot Reviewed-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- Documentation/gpio/consumer.txt | 6 +++++- drivers/gpio/gpiolib.c | 34 +++++++++++++++++----------------- 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt index 07c74a3765a0..e42f77d8d4ca 100644 --- a/Documentation/gpio/consumer.txt +++ b/Documentation/gpio/consumer.txt @@ -38,7 +38,11 @@ device that displays digits), an additional index argument can be specified: const char *con_id, unsigned int idx) Both functions return either a valid GPIO descriptor, or an error code checkable -with IS_ERR(). They will never return a NULL pointer. +with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned +if and only if no GPIO has been assigned to the device/function/index triplet, +other error codes are used for cases where a GPIO has been assigned but an error +occured while trying to acquire it. This is useful to discriminate between mere +errors and an absence of GPIO for optional GPIO parameters. Device-managed variants of these functions are also defined: diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 12e47dfabd8d..c0b06a9adad9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2367,7 +2367,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) { - struct gpio_desc *desc = ERR_PTR(-ENODEV); + struct gpio_desc *desc = ERR_PTR(-ENOENT); struct gpiod_lookup_table *table; struct gpiod_lookup *p; @@ -2389,19 +2389,22 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, chip = find_chip_by_name(p->chip_label); if (!chip) { - dev_warn(dev, "cannot find GPIO chip %s\n", - p->chip_label); - continue; + dev_err(dev, "cannot find GPIO chip %s\n", + p->chip_label); + return ERR_PTR(-ENODEV); } if (chip->ngpio <= p->chip_hwnum) { - dev_warn(dev, "GPIO chip %s has %d GPIOs\n", - chip->label, chip->ngpio); - continue; + dev_err(dev, + "requested GPIO %d is out of range [0..%d] for chip %s\n", + idx, chip->ngpio, chip->label); + return ERR_PTR(-EINVAL); } desc = gpiochip_offset_to_desc(chip, p->chip_hwnum); *flags = p->flags; + + return desc; } return desc; @@ -2413,7 +2416,8 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, * @con_id: function within the GPIO consumer * * Return the GPIO descriptor corresponding to the function con_id of device - * dev, or an IS_ERR() condition if an error occured. + * dev, -ENOENT if no GPIO has been assigned to the requested function, or + * another IS_ERR() code if an error occured while trying to acquire the GPIO. */ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id) { @@ -2430,7 +2434,9 @@ EXPORT_SYMBOL_GPL(gpiod_get); * This variant of gpiod_get() allows to access GPIOs other than the first * defined one for functions that define several GPIOs. * - * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error. + * Return a valid GPIO descriptor, -ENOENT if no GPIO has been assigned to the + * requested function and/or index, or another IS_ERR() code if an error + * occured while trying to acquire the GPIO. */ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, const char *con_id, @@ -2455,15 +2461,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, * Either we are not using DT or ACPI, or their lookup did not return * a result. In that case, use platform lookup as a fallback. */ - if (!desc || IS_ERR(desc)) { - struct gpio_desc *pdesc; - + if (!desc || desc == ERR_PTR(-ENOENT)) { dev_dbg(dev, "using lookup tables for GPIO lookup"); - pdesc = gpiod_find(dev, con_id, idx, &flags); - - /* If used as fallback, do not replace the previous error */ - if (!IS_ERR(pdesc) || !desc) - desc = pdesc; + desc = gpiod_find(dev, con_id, idx, &flags); } if (IS_ERR(desc)) { -- cgit v1.2.3 From 6acf54f1cf0a6747bac9fea26f34cfc5a9029523 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 11 Dec 2013 13:27:10 -0500 Subject: macvtap: Add support of packet capture on macvtap device. Macvtap device currently doesn not allow a user to capture traffic on due to the fact that it steals the packets from the network stack before the skb->dev is set correctly on the receive side, and that use uses macvlan transmit path directly on the send side. As a result, we never get a change to give traffic to the taps while the correct device is set in the skb. This patch makes macvtap device behave almost exaclty like macvlan. On the send side, we switch to using dev_queue_xmit(). On the receive side, to deliver packets to macvtap, we now use netif_rx and dev_forward_skb just like macvlan. The only differnce now is that macvtap has its own rx_handler which is attached to the macvtap netdev. It is here that we now steal the packet and provide it to the socket. As a result, we can now capture traffic on the macvtap device: tcpdump -i macvtap0 It also gives us the abilit to add tc actions to the macvtap device and actually utilize different bandwidth management queues on output. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 59 ++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 4a34bcb6549f..85ecfccf9c60 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -70,6 +70,11 @@ static const struct proto_ops macvtap_socket_ops; #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) +static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev) +{ + return rcu_dereference(dev->rx_handler_data); +} + /* * RCU usage: * The macvtap_queue and the macvlan_dev are loosely coupled, the @@ -271,24 +276,27 @@ static void macvtap_del_queues(struct net_device *dev) sock_put(&qlist[j]->sk); } -/* - * Forward happens for data that gets sent from one macvlan - * endpoint to another one in bridge mode. We just take - * the skb and put it into the receive queue. - */ -static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) +static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb) { - struct macvlan_dev *vlan = netdev_priv(dev); - struct macvtap_queue *q = macvtap_get_queue(dev, skb); + struct sk_buff *skb = *pskb; + struct net_device *dev = skb->dev; + struct macvlan_dev *vlan; + struct macvtap_queue *q; netdev_features_t features = TAP_FEATURES; + vlan = macvtap_get_vlan_rcu(dev); + if (!vlan) + return RX_HANDLER_PASS; + + q = macvtap_get_queue(dev, skb); if (!q) - goto drop; + return RX_HANDLER_PASS; if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len) goto drop; - skb->dev = dev; + skb_push(skb, ETH_HLEN); + /* Apply the forward feature mask so that we perform segmentation * according to users wishes. This only works if VNET_HDR is * enabled. @@ -320,22 +328,13 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) wake_up: wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); - return NET_RX_SUCCESS; + return RX_HANDLER_CONSUMED; drop: + /* Count errors/drops only here, thus don't care about args. */ + macvlan_count_rx(vlan, 0, 0, 0); kfree_skb(skb); - return NET_RX_DROP; -} - -/* - * Receive is for data from the external interface (lowerdev), - * in case of macvtap, we can treat that the same way as - * forward, which macvlan cannot. - */ -static int macvtap_receive(struct sk_buff *skb) -{ - skb_push(skb, ETH_HLEN); - return macvtap_forward(skb->dev, skb); + return RX_HANDLER_CONSUMED; } static int macvtap_get_minor(struct macvlan_dev *vlan) @@ -385,6 +384,8 @@ static int macvtap_newlink(struct net *src_net, struct nlattr *data[]) { struct macvlan_dev *vlan = netdev_priv(dev); + int err; + INIT_LIST_HEAD(&vlan->queue_list); /* Since macvlan supports all offloads by default, make @@ -392,16 +393,21 @@ static int macvtap_newlink(struct net *src_net, */ vlan->tap_features = TUN_OFFLOADS; + err = netdev_rx_handler_register(dev, macvtap_handle_frame, vlan); + if (err) + return err; + /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ return macvlan_common_newlink(src_net, dev, tb, data, - macvtap_receive, macvtap_forward); + netif_rx, dev_forward_skb); } static void macvtap_dellink(struct net_device *dev, struct list_head *head) { + netdev_rx_handler_unregister(dev); macvtap_del_queues(dev); macvlan_dellink(dev, head); } @@ -725,9 +731,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; } if (vlan) { - local_bh_disable(); - macvlan_start_xmit(skb, vlan->dev); - local_bh_enable(); + skb->dev = vlan->dev; + dev_queue_xmit(skb); } else { kfree_skb(skb); } -- cgit v1.2.3 From 2f6a1b6607fd6b0eb9501843a40e0c7555f37b4a Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 11 Dec 2013 13:27:11 -0500 Subject: macvlan: Remove custom recieve and forward handlers Since now macvlan and macvtap use the same receive and forward handlers, we can remove them completely and use netif_rx and dev_forward_skb() directly. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 17 +++++------------ drivers/net/macvtap.c | 3 +-- include/linux/if_macvlan.h | 7 +------ 3 files changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index cfb91570cddd..24ea994b6274 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -120,7 +120,7 @@ static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev = vlan->dev; if (local) - return vlan->forward(dev, skb); + return dev_forward_skb(dev, skb); skb->dev = dev; if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast)) @@ -128,7 +128,7 @@ static int macvlan_broadcast_one(struct sk_buff *skb, else skb->pkt_type = PACKET_MULTICAST; - return vlan->receive(skb); + return netif_rx(skb); } static u32 macvlan_hash_mix(const struct macvlan_dev *vlan) @@ -251,7 +251,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) skb->dev = dev; skb->pkt_type = PACKET_HOST; - ret = vlan->receive(skb); + ret = netif_rx(skb); out: macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0); @@ -803,10 +803,7 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) } int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - int (*receive)(struct sk_buff *skb), - int (*forward)(struct net_device *dev, - struct sk_buff *skb)) + struct nlattr *tb[], struct nlattr *data[]) { struct macvlan_dev *vlan = netdev_priv(dev); struct macvlan_port *port; @@ -848,8 +845,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, vlan->lowerdev = lowerdev; vlan->dev = dev; vlan->port = port; - vlan->receive = receive; - vlan->forward = forward; vlan->set_features = MACVLAN_FEATURES; vlan->mode = MACVLAN_MODE_VEPA; @@ -894,9 +889,7 @@ EXPORT_SYMBOL_GPL(macvlan_common_newlink); static int macvlan_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { - return macvlan_common_newlink(src_net, dev, tb, data, - netif_rx, - dev_forward_skb); + return macvlan_common_newlink(src_net, dev, tb, data); } void macvlan_dellink(struct net_device *dev, struct list_head *head) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 85ecfccf9c60..64409af0da31 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -400,8 +400,7 @@ static int macvtap_newlink(struct net *src_net, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - return macvlan_common_newlink(src_net, dev, tb, data, - netif_rx, dev_forward_skb); + return macvlan_common_newlink(src_net, dev, tb, data); } static void macvtap_dellink(struct net_device *dev, diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 84ba5ac39e03..ea22721ba269 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -69,8 +69,6 @@ struct macvlan_dev { netdev_features_t set_features; enum macvlan_mode mode; u16 flags; - int (*receive)(struct sk_buff *skb); - int (*forward)(struct net_device *dev, struct sk_buff *skb); /* This array tracks active taps. */ struct macvtap_queue __rcu *taps[MAX_MACVTAP_QUEUES]; /* This list tracks all taps (both enabled and disabled) */ @@ -103,10 +101,7 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, extern void macvlan_common_setup(struct net_device *dev); extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - int (*receive)(struct sk_buff *skb), - int (*forward)(struct net_device *dev, - struct sk_buff *skb)); + struct nlattr *tb[], struct nlattr *data[]); extern void macvlan_count_rx(const struct macvlan_dev *vlan, unsigned int len, bool success, -- cgit v1.2.3 From 4cc629b7a20945ce35628179180329b6bc9e552b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 10 Dec 2013 15:19:03 -0800 Subject: gpio: msm: Fix irq mask/unmask by writing bits instead of numbers We should be writing bits here but instead we're writing the numbers that correspond to the bits we want to write. Fix it by wrapping the numbers in the BIT() macro. This fixes gpios acting as interrupts. Cc: stable@vger.kernel.org Signed-off-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpio-msm-v2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c index 7b37300973db..2baf0ddf7e02 100644 --- a/drivers/gpio/gpio-msm-v2.c +++ b/drivers/gpio/gpio-msm-v2.c @@ -252,7 +252,7 @@ static void msm_gpio_irq_mask(struct irq_data *d) spin_lock_irqsave(&tlmm_lock, irq_flags); writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); - clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); + clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio)); __clear_bit(gpio, msm_gpio.enabled_irqs); spin_unlock_irqrestore(&tlmm_lock, irq_flags); } @@ -264,7 +264,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d) spin_lock_irqsave(&tlmm_lock, irq_flags); __set_bit(gpio, msm_gpio.enabled_irqs); - set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); + set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio)); writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio)); spin_unlock_irqrestore(&tlmm_lock, irq_flags); } -- cgit v1.2.3 From 335802d1c297a2851d7140d84af6ec05c1d3cf3f Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 12 Dec 2013 00:39:37 -0800 Subject: net: eth: 8390: remove section warning in etherh.c Commit c45f812f0280 ('8390 : Replace ei_debug with msg_enable/NETIF_MSG_* feature') ended up moving the printout of version[] from something that will be compiled out due to defines, to something that is now evaluated at runtime. That means that what always used to be an access to an __initdata string from non-__init code started showing up as a section mismatch when it didn't before. All other 8390 versions skip __initdata on the version string, and starting to annotate the whole chain of callers with __init seems like more churn than it's worth on this driver, so remove it from etherh.c as well. Fixes: c45f812f0280 ('8390 : Replace ei_debug with msg_enable/NETIF_MSG_* feature') Signed-off-by: Olof Johansson Signed-off-by: David S. Miller --- drivers/net/ethernet/8390/etherh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c index b15e482a7c63..b36ee9e0d220 100644 --- a/drivers/net/ethernet/8390/etherh.c +++ b/drivers/net/ethernet/8390/etherh.c @@ -59,7 +59,7 @@ #define DRV_NAME "etherh" #define DRV_VERSION "1.11" -static char version[] __initdata = +static char version[] = "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n"; #include "lib8390.c" -- cgit v1.2.3 From fcffa97f8e182306cf76f101ccb3b397399da772 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 10 Dec 2013 15:19:04 -0800 Subject: gpio: msm: Add module device table and mark table const This allows the module to be loaded automatically. Signed-off-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpio-msm-v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c index 7b37300973db..81c1d55abf72 100644 --- a/drivers/gpio/gpio-msm-v2.c +++ b/drivers/gpio/gpio-msm-v2.c @@ -430,10 +430,11 @@ static int msm_gpio_probe(struct platform_device *pdev) return 0; } -static struct of_device_id msm_gpio_of_match[] = { +static const struct of_device_id msm_gpio_of_match[] = { { .compatible = "qcom,msm-gpio", }, { }, }; +MODULE_DEVICE_TABLE(of, msm_gpio_of_match); static int msm_gpio_remove(struct platform_device *dev) { -- cgit v1.2.3 From 943befc314ae5848e3be50d1fcdbdf6456e8d6d4 Mon Sep 17 00:00:00 2001 From: WingMan Kwok Date: Thu, 12 Dec 2013 12:25:29 -0500 Subject: usb: dwc3: add Keystone specific glue layer Add Keystone platform specific glue layer to support USB3 Host mode. [ balbi@ti.com : fix order of clk_disable() and platform_device_unregister() ] Cc: Greg Kroah-Hartman Acked-by: Santosh Shilimkar Signed-off-by: WingMan Kwok Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 7 ++ drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-keystone.c | 202 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 drivers/usb/dwc3/dwc3-keystone.c (limited to 'drivers') diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 70fc43027a5c..e2c730fc9a90 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -70,6 +70,13 @@ config USB_DWC3_PCI One such PCIe-based platform is Synopsys' PCIe HAPS model of this IP. +config USB_DWC3_KEYSTONE + tristate "Texas Instruments Keystone2 Platforms" + default USB_DWC3 + help + Support of USB2/3 functionality in TI Keystone2 platforms. + Say 'Y' or 'M' here if you have one such device + comment "Debugging features" config USB_DWC3_DEBUG diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index dd1760145c46..10ac3e72482e 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -32,3 +32,4 @@ endif obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o +obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c new file mode 100644 index 000000000000..1fad1618df6e --- /dev/null +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -0,0 +1,202 @@ +/** + * dwc3-keystone.c - Keystone Specific Glue layer + * + * Copyright (C) 2010-2013 Texas Instruments Incorporated - http://www.ti.com + * + * Author: WingMan Kwok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* USBSS register offsets */ +#define USBSS_REVISION 0x0000 +#define USBSS_SYSCONFIG 0x0010 +#define USBSS_IRQ_EOI 0x0018 +#define USBSS_IRQSTATUS_RAW_0 0x0020 +#define USBSS_IRQSTATUS_0 0x0024 +#define USBSS_IRQENABLE_SET_0 0x0028 +#define USBSS_IRQENABLE_CLR_0 0x002c + +/* IRQ register bits */ +#define USBSS_IRQ_EOI_LINE(n) BIT(n) +#define USBSS_IRQ_EVENT_ST BIT(0) +#define USBSS_IRQ_COREIRQ_EN BIT(0) +#define USBSS_IRQ_COREIRQ_CLR BIT(0) + +static u64 kdwc3_dma_mask; + +struct dwc3_keystone { + struct device *dev; + struct clk *clk; + void __iomem *usbss; +}; + +static inline u32 kdwc3_readl(void __iomem *base, u32 offset) +{ + return readl(base + offset); +} + +static inline void kdwc3_writel(void __iomem *base, u32 offset, u32 value) +{ + writel(value, base + offset); +} + +static void kdwc3_enable_irqs(struct dwc3_keystone *kdwc) +{ + u32 val; + + val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0); + val |= USBSS_IRQ_COREIRQ_EN; + kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val); +} + +static void kdwc3_disable_irqs(struct dwc3_keystone *kdwc) +{ + u32 val; + + val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0); + val &= ~USBSS_IRQ_COREIRQ_EN; + kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val); +} + +static irqreturn_t dwc3_keystone_interrupt(int irq, void *_kdwc) +{ + struct dwc3_keystone *kdwc = _kdwc; + + kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_CLR_0, USBSS_IRQ_COREIRQ_CLR); + kdwc3_writel(kdwc->usbss, USBSS_IRQSTATUS_0, USBSS_IRQ_EVENT_ST); + kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, USBSS_IRQ_COREIRQ_EN); + kdwc3_writel(kdwc->usbss, USBSS_IRQ_EOI, USBSS_IRQ_EOI_LINE(0)); + + return IRQ_HANDLED; +} + +static int kdwc3_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = pdev->dev.of_node; + struct dwc3_keystone *kdwc; + struct resource *res; + int error, irq; + + kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL); + if (!kdwc) + return -ENOMEM; + + platform_set_drvdata(pdev, kdwc); + + kdwc->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "missing usbss resource\n"); + return -EINVAL; + } + + kdwc->usbss = devm_ioremap_resource(dev, res); + if (IS_ERR(kdwc->usbss)) + return PTR_ERR(kdwc->usbss); + + kdwc3_dma_mask = dma_get_mask(dev); + dev->dma_mask = &kdwc3_dma_mask; + + kdwc->clk = devm_clk_get(kdwc->dev, "usb"); + + error = clk_prepare_enable(kdwc->clk); + if (error < 0) { + dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n", + error); + return error; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "missing irq\n"); + goto err_irq; + } + + error = devm_request_irq(dev, irq, dwc3_keystone_interrupt, IRQF_SHARED, + dev_name(dev), kdwc); + if (error) { + dev_err(dev, "failed to request IRQ #%d --> %d\n", + irq, error); + goto err_irq; + } + + kdwc3_enable_irqs(kdwc); + + error = of_platform_populate(node, NULL, NULL, dev); + if (error) { + dev_err(&pdev->dev, "failed to create dwc3 core\n"); + goto err_core; + } + + return 0; + +err_core: + kdwc3_disable_irqs(kdwc); +err_irq: + clk_disable_unprepare(kdwc->clk); + + return error; +} + +static int kdwc3_remove_core(struct device *dev, void *c) +{ + struct platform_device *pdev = to_platform_device(dev); + + platform_device_unregister(pdev); + + return 0; +} + +static int kdwc3_remove(struct platform_device *pdev) +{ + struct dwc3_keystone *kdwc = platform_get_drvdata(pdev); + + kdwc3_disable_irqs(kdwc); + device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core); + clk_disable_unprepare(kdwc->clk); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id kdwc3_of_match[] = { + { .compatible = "ti,keystone-dwc3", }, + {}, +}; +MODULE_DEVICE_TABLE(of, kdwc3_of_match); + +static struct platform_driver kdwc3_driver = { + .probe = kdwc3_probe, + .remove = kdwc3_remove, + .driver = { + .name = "keystone-dwc3", + .owner = THIS_MODULE, + .of_match_table = kdwc3_of_match, + }, +}; + +module_platform_driver(kdwc3_driver); + +MODULE_ALIAS("platform:keystone-dwc3"); +MODULE_AUTHOR("WingMan Kwok "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("DesignWare USB3 KEYSTONE Glue Layer"); -- cgit v1.2.3 From 25acdd08fd715cf612428c2b3c39ce2a41926238 Mon Sep 17 00:00:00 2001 From: WingMan Kwok Date: Thu, 12 Dec 2013 12:25:30 -0500 Subject: usb: phy: add Keystone usb phy driver Add Keystone platform USB PHY driver support. Current main purpose of this driver is to enable the PHY reference clock gate on the Keystone SoC. Otherwise it is a nop PHY. [ balbi@ti.com : add COMPILE_TEST as a possible dependency make sure drvdata is initialized before adding PHY ] Cc: Greg Kroah-Hartman Acked-by: Santosh Shilimkar Signed-off-by: WingMan Kwok Signed-off-by: Felipe Balbi --- drivers/usb/phy/Kconfig | 9 +++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-keystone.c | 142 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 drivers/usb/phy/phy-keystone.c (limited to 'drivers') diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 4f22762f3d6f..54bebba39e91 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -48,6 +48,15 @@ config ISP1301_OMAP This driver can also be built as a module. If so, the module will be called isp1301_omap. +config KEYSTONE_USB_PHY + tristate "Keystone USB PHY Driver" + depends on ARCH_KEYSTONE || COMPILE_TEST + select NOP_USB_XCEIV + help + Enable this to support Keystone USB phy. This driver provides + interface to interact with USB 2.0 and USB 3.0 PHY that is part + of the Keystone SOC. + config MV_U3D_PHY bool "Marvell USB 3.0 PHY controller Driver" depends on CPU_MMP3 diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 9b3be9e0aeb4..be58adae3496 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o obj-$(CONFIG_USB_RCAR_GEN2_PHY) += phy-rcar-gen2-usb.o obj-$(CONFIG_USB_ULPI) += phy-ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o +obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c new file mode 100644 index 000000000000..a04fb940d62c --- /dev/null +++ b/drivers/usb/phy/phy-keystone.c @@ -0,0 +1,142 @@ +/* + * phy-keystone - USB PHY, talking to dwc3 controller in Keystone. + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com + * 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. + * + * Author: WingMan Kwok + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include +#include + +#include "phy-generic.h" + +/* USB PHY control register offsets */ +#define USB_PHY_CTL_UTMI 0x0000 +#define USB_PHY_CTL_PIPE 0x0004 +#define USB_PHY_CTL_PARAM_1 0x0008 +#define USB_PHY_CTL_PARAM_2 0x000c +#define USB_PHY_CTL_CLOCK 0x0010 +#define USB_PHY_CTL_PLL 0x0014 + +#define PHY_REF_SSP_EN BIT(29) + +struct keystone_usbphy { + struct usb_phy_gen_xceiv usb_phy_gen; + void __iomem *phy_ctrl; +}; + +static inline u32 keystone_usbphy_readl(void __iomem *base, u32 offset) +{ + return readl(base + offset); +} + +static inline void keystone_usbphy_writel(void __iomem *base, + u32 offset, u32 value) +{ + writel(value, base + offset); +} + +static int keystone_usbphy_init(struct usb_phy *phy) +{ + struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev); + u32 val; + + val = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK); + keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK, + val | PHY_REF_SSP_EN); + return 0; +} + +static void keystone_usbphy_shutdown(struct usb_phy *phy) +{ + struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev); + u32 val; + + val = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK); + keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK, + val &= ~PHY_REF_SSP_EN); +} + +static int keystone_usbphy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct keystone_usbphy *k_phy; + struct resource *res; + int ret; + + k_phy = devm_kzalloc(dev, sizeof(*k_phy), GFP_KERNEL); + if (!k_phy) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "missing usb phy resource\n"); + return -EINVAL; + } + + k_phy->phy_ctrl = devm_ioremap_resource(dev, res); + if (IS_ERR(k_phy->phy_ctrl)) + return PTR_ERR(k_phy->phy_ctrl); + + ret = usb_phy_gen_create_phy(dev, &k_phy->usb_phy_gen, + USB_PHY_TYPE_USB2, 0, false); + if (ret) + return ret; + + k_phy->usb_phy_gen.phy.init = keystone_usbphy_init; + k_phy->usb_phy_gen.phy.shutdown = keystone_usbphy_shutdown; + + platform_set_drvdata(pdev, k_phy); + + ret = usb_add_phy_dev(&k_phy->usb_phy_gen.phy); + if (ret) + return ret; + + return 0; +} + +static int keystone_usbphy_remove(struct platform_device *pdev) +{ + struct keystone_usbphy *k_phy = platform_get_drvdata(pdev); + + usb_remove_phy(&k_phy->usb_phy_gen.phy); + + return 0; +} + +static const struct of_device_id keystone_usbphy_ids[] = { + { .compatible = "ti,keystone-usbphy" }, + { } +}; +MODULE_DEVICE_TABLE(of, keystone_usbphy_ids); + +static struct platform_driver keystone_usbphy_driver = { + .probe = keystone_usbphy_probe, + .remove = keystone_usbphy_remove, + .driver = { + .name = "keystone-usbphy", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(keystone_usbphy_ids), + }, +}; + +module_platform_driver(keystone_usbphy_driver); + +MODULE_ALIAS("platform:keystone-usbphy"); +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("Keystone USB phy driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 1b2e21b082a1c67cd7861bd86c4a46a3f0f348ea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 10 Dec 2013 19:09:02 -0800 Subject: usb: renesas_usbhs: fifo: request DMAEngine once DMAEngine uses IRQ if dma_request_channel() was called, and it is using devm_request_irq() today, OTOH, dma_request_channel() will be called when each USB connection happened on this driver. This means same IRQ will be requested many times whenever each USB connected, and this IRQ isn't freed when USB disconnected. Request DMAEngine once. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 45b94019aec8..d49f9c326035 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -1124,19 +1124,8 @@ void usbhs_fifo_init(struct usbhs_priv *priv) mod->irq_brdysts = 0; cfifo->pipe = NULL; - cfifo->tx_chan = NULL; - cfifo->rx_chan = NULL; - d0fifo->pipe = NULL; - d0fifo->tx_chan = NULL; - d0fifo->rx_chan = NULL; - d1fifo->pipe = NULL; - d1fifo->tx_chan = NULL; - d1fifo->rx_chan = NULL; - - usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv)); - usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv)); } void usbhs_fifo_quit(struct usbhs_priv *priv) @@ -1147,9 +1136,6 @@ void usbhs_fifo_quit(struct usbhs_priv *priv) mod->irq_ready = NULL; mod->irq_bempsts = 0; mod->irq_brdysts = 0; - - usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv)); - usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv)); } int usbhs_fifo_probe(struct usbhs_priv *priv) @@ -1171,6 +1157,7 @@ int usbhs_fifo_probe(struct usbhs_priv *priv) fifo->ctr = D0FIFOCTR; fifo->tx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id); fifo->rx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id); + usbhsf_dma_init(priv, fifo); /* D1FIFO */ fifo = usbhsf_get_d1fifo(priv); @@ -1180,10 +1167,13 @@ int usbhs_fifo_probe(struct usbhs_priv *priv) fifo->ctr = D1FIFOCTR; fifo->tx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id); fifo->rx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id); + usbhsf_dma_init(priv, fifo); return 0; } void usbhs_fifo_remove(struct usbhs_priv *priv) { + usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv)); + usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv)); } -- cgit v1.2.3 From 31e322272d9d7da0724ae6e3180478575aa48909 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Wed, 11 Dec 2013 14:45:14 +0800 Subject: usb: phy: initialize the notifier when add a new phy We need to initialize the notifer before use it. So lets initialize it when add a new phy device to reduce the code redundancy. Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 2 -- drivers/usb/phy/phy-generic.c | 1 - drivers/usb/phy/phy-gpio-vbus-usb.c | 2 -- drivers/usb/phy/phy-mxs-usb.c | 2 -- drivers/usb/phy/phy.c | 4 ++++ 5 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 087402350b6d..11ab2c45e462 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -1415,8 +1415,6 @@ static int ab8500_usb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ab); - ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); - /* all: Disable phy when called from set_host and set_peripheral */ INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index fce3a9e9bb5d..cd19bbc6e3cd 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -210,7 +210,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, nop->phy.otg->set_host = nop_set_host; nop->phy.otg->set_peripheral = nop_set_peripheral; - ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); return 0; } EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c index 02799a5efcd4..69462e09d014 100644 --- a/drivers/usb/phy/phy-gpio-vbus-usb.c +++ b/drivers/usb/phy/phy-gpio-vbus-usb.c @@ -314,8 +314,6 @@ static int gpio_vbus_probe(struct platform_device *pdev) goto err_irq; } - ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier); - INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work); gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw"); diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 797c45b9ddab..fa44c0f3e861 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -167,8 +167,6 @@ static int mxs_phy_probe(struct platform_device *pdev) mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect; mxs_phy->phy.type = USB_PHY_TYPE_USB2; - ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier); - mxs_phy->clk = clk; platform_set_drvdata(pdev, &mxs_phy->phy); diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 1b74523e1fee..e6f61e4361df 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -329,6 +329,8 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) return -EINVAL; } + ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); + spin_lock_irqsave(&phy_lock, flags); list_for_each_entry(phy, &phy_list, head) { @@ -367,6 +369,8 @@ int usb_add_phy_dev(struct usb_phy *x) return -EINVAL; } + ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); + spin_lock_irqsave(&phy_lock, flags); list_for_each_entry(phy_bind, &phy_bind_list, list) if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev)))) -- cgit v1.2.3 From 295538ff7e5389d5aee5845c548f114b793d60c9 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 6 Dec 2013 13:03:44 +0100 Subject: usb: gadget: s3c-hsotg: fix maxpacket size in s3c_hsotg_irq_enumdone This patch set maximum possible maxpacket value for each speed. Previous values didn't allow to use maxpacket sizes greater than 64 in full speed and 512 in high speed, although hardware is able to handle up to 1023 in fs and 1024 in hs. Tested-by: Matt Porter Signed-off-by: Robert Baldyga Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 9875d9c0823f..2fa7a9c593e3 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2080,13 +2080,13 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) case DSTS_EnumSpd_FS48: hsotg->gadget.speed = USB_SPEED_FULL; ep0_mps = EP0_MPS_LIMIT; - ep_mps = 64; + ep_mps = 1023; break; case DSTS_EnumSpd_HS: hsotg->gadget.speed = USB_SPEED_HIGH; ep0_mps = EP0_MPS_LIMIT; - ep_mps = 512; + ep_mps = 1024; break; case DSTS_EnumSpd_LS: -- cgit v1.2.3 From b963a81a4803fb387d6551ea0fb66876e0c8ff12 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 6 Dec 2013 13:03:45 +0100 Subject: usb: gadget: s3c-hsotg: add flush TX FIFO when kill all requests This patch adds flushing TX FIFO in kill_all_requests() function in dedicated-fifo mode. It's because when requests are killed (when endpoint is disabled or in case of device reset/disconnection) in FIFO can stay some unsent data. In the worst case FIFO can stay full, and then if endpoint will be back enabled, sending new data will be impossible. Signed-off-by: Robert Baldyga Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 2fa7a9c593e3..6c80bfcefa87 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2150,6 +2150,9 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, s3c_hsotg_complete_request(hsotg, ep, req, result); } + if(hsotg->dedicated_fifos) + if ((readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4 < 3072) + s3c_hsotg_txfifo_flush(hsotg, ep->index); } #define call_gadget(_hs, _entry) \ -- cgit v1.2.3 From 1933861db4f7c9beecca5cc7460c6c814554cc34 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:21 +0100 Subject: usb: gadget: configfs: allow setting function instance's name USB function's configfs config group is created in a generic way in usb/gadget/configfs.c:function_make(), which in turn delegates actual allocation and setup of the USB function instance to a particular implementation, e.g. in f_acm.c. The said implementation does its job in a parameter-less function e.g. acm_alloc_instance(), which results in creating an unnamed config group, whose name is set later in function_make(). function_make() creates the name by parsing a string of the form: . which comes from userspace as a parameter to mkdir invocation. Up to now only has been used, while has been ignored. This patch adds a set_inst_name() operation to struct usb_function_instance which allows passing the from function_make() so that it is not ignored. It is entirely up to the implementor of set_inst_name() what to do with the . In a typical case, the struct usb_function_instance is embedded in a larger struct which is retrieved in set_inst_name() with container_of(), and the larger struct contains a field to store the . Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/configfs.c | 7 +++++++ include/linux/usb/composite.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 25885112fa35..d6c8ab4a5327 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -564,6 +564,13 @@ static struct config_group *function_make( usb_put_function_instance(fi); return ERR_PTR(ret); } + if (fi->set_inst_name) { + ret = fi->set_inst_name(fi, instance_name); + if (ret) { + usb_put_function_instance(fi); + return ERR_PTR(ret); + } + } gi = container_of(group, struct gadget_info, functions_group); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 5e61589fc166..dba63f53906c 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -468,6 +468,8 @@ struct usb_function_instance { struct config_group group; struct list_head cfs_list; struct usb_function_driver *fd; + int (*set_inst_name)(struct usb_function_instance *inst, + const char *name); void (*free_func_inst)(struct usb_function_instance *inst); }; -- cgit v1.2.3 From 1ec8f00f34a78f8d43504ffba3f31eddf4433408 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:22 +0100 Subject: usb: gadget: g_ffs: remove a reduntant gfs_ether_setup variable Since d6a0143985489e470a118605352f4b18df0ce142 usb: gadget: move the global the_dev variable to their users "the_dev" variable can be used as a "setup done" flag; non-NULL meaning "setup done", NULL meaning "setup not done". Moreover, gether_cleanup() can be safely called with a NULL argument. Corrected a comment to be consistent with the code. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/g_ffs.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 2344efe4f4ce..e9540824e713 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -182,7 +182,6 @@ static __refdata struct usb_composite_driver gfs_driver = { static DEFINE_MUTEX(gfs_lock); static unsigned int missing_funcs; -static bool gfs_ether_setup; static bool gfs_registered; static bool gfs_single_func; static struct gfs_ffs_obj *ffs_tab; @@ -364,7 +363,6 @@ static int gfs_bind(struct usb_composite_dev *cdev) ret = PTR_ERR(the_dev); goto error_quick; } - gfs_ether_setup = true; ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) @@ -401,8 +399,8 @@ error_unbind: functionfs_unbind(ffs_tab[i].ffs_data); error: gether_cleanup(the_dev); + the_dev = NULL; error_quick: - gfs_ether_setup = false; return ret; } @@ -415,18 +413,17 @@ static int gfs_unbind(struct usb_composite_dev *cdev) ENTER(); + gether_cleanup(the_dev); + the_dev = NULL; + /* * We may have been called in an error recovery from * composite_bind() after gfs_unbind() failure so we need to - * check if gfs_ffs_data is not NULL since gfs_bind() handles + * check if instance's ffs_data is not NULL since gfs_bind() handles * all error recovery itself. I'd rather we werent called * from composite on orror recovery, but what you're gonna * do...? */ - if (gfs_ether_setup) - gether_cleanup(the_dev); - gfs_ether_setup = false; - for (i = func_num; i--; ) if (ffs_tab[i].ffs_data) functionfs_unbind(ffs_tab[i].ffs_data); -- cgit v1.2.3 From f212ad4e39759ab24434858630ac627b59e879db Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:23 +0100 Subject: usb: gadget: g_ffs: convert to new interface of f_ecm There is a new funtion interface and g_ffs is the last gadget to use the old. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/g_ffs.c | 93 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5f1d4443aa0c..b135856852ec 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -895,6 +895,7 @@ config USB_FUNCTIONFS_ETH bool "Include configuration with CDC ECM (Ethernet)" depends on USB_FUNCTIONFS && NET select USB_U_ETHER + select USB_F_ECM help Include a configuration with CDC ECM function (Ethernet) and the Function Filesystem. diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index e9540824e713..cda4c5d34260 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -28,8 +28,7 @@ # define USB_ETH_RNDIS y # endif -#define USBF_ECM_INCLUDED -# include "f_ecm.c" +# include "u_ecm.h" #define USB_FSUBSET_INCLUDED # include "f_subset.c" # ifdef USB_ETH_RNDIS @@ -39,11 +38,15 @@ # endif # include "u_ether.h" +USB_ETHERNET_MODULE_PARAMETERS(); + static u8 gfs_host_mac[ETH_ALEN]; static struct eth_dev *the_dev; # ifdef CONFIG_USB_FUNCTIONFS_ETH static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], struct eth_dev *dev); +static struct usb_function_instance *fi_ecm; +static struct usb_function *f_ecm; # endif #else # define the_dev NULL @@ -76,10 +79,6 @@ struct gfs_ffs_obj { USB_GADGET_COMPOSITE_OPTIONS(); -#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS -USB_ETHERNET_MODULE_PARAMETERS(); -#endif - static struct usb_device_descriptor gfs_dev_desc = { .bLength = sizeof gfs_dev_desc, .bDescriptorType = USB_DT_DEVICE, @@ -355,14 +354,50 @@ static int gfs_bind(struct usb_composite_dev *cdev) if (missing_funcs) return -ENODEV; -#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS +#if defined CONFIG_USB_FUNCTIONFS_ETH + if (can_support_ecm(cdev->gadget)) { + struct f_ecm_opts *ecm_opts; + + fi_ecm = usb_get_function_instance("ecm"); + if (IS_ERR(fi_ecm)) + return PTR_ERR(fi_ecm); + ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); + + gether_set_qmult(ecm_opts->net, qmult); + + if (!gether_set_host_addr(ecm_opts->net, host_addr)) + pr_info("using host ethernet address: %s", host_addr); + if (!gether_set_dev_addr(ecm_opts->net, dev_addr)) + pr_info("using self ethernet address: %s", dev_addr); + + the_dev = netdev_priv(ecm_opts->net); + } else { + the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, + gfs_host_mac, qmult); + } + +#elif defined CONFIG_USB_FUNCTIONFS_RNDIS + the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac, qmult); #endif - if (IS_ERR(the_dev)) { - ret = PTR_ERR(the_dev); - goto error_quick; + if (IS_ERR(the_dev)) + return PTR_ERR(the_dev); + +#if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH + if (can_support_ecm(cdev->gadget)) { + struct f_ecm_opts *ecm_opts; + + ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); + + gether_set_gadget(ecm_opts->net, cdev->gadget); + ret = gether_register_netdev(ecm_opts->net); + if (ret) + goto error; + ecm_opts->bound = true; + gether_get_host_addr_u8(ecm_opts->net, gfs_host_mac); } +#endif ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) @@ -398,9 +433,16 @@ error_unbind: for (i = 0; i < func_num; i++) functionfs_unbind(ffs_tab[i].ffs_data); error: +#if defined CONFIG_USB_FUNCTIONFS_ETH + if (can_support_ecm(cdev->gadget)) + usb_put_function_instance(fi_ecm); + else + gether_cleanup(the_dev); + the_dev = NULL; +#elif defined CONFIG_USB_FUNCTIONFS_RNDIS gether_cleanup(the_dev); the_dev = NULL; -error_quick: +#endif return ret; } @@ -413,8 +455,19 @@ static int gfs_unbind(struct usb_composite_dev *cdev) ENTER(); + +#if defined CONFIG_USB_FUNCTIONFS_ETH + if (can_support_ecm(cdev->gadget)) { + usb_put_function(f_ecm); + usb_put_function_instance(fi_ecm); + } else { + gether_cleanup(the_dev); + } + the_dev = NULL; +#elif defined CONFIG_USB_FUNCTIONFS_RNDIS gether_cleanup(the_dev); the_dev = NULL; +#endif /* * We may have been called in an error recovery from @@ -483,9 +536,21 @@ static int gfs_do_config(struct usb_configuration *c) static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], struct eth_dev *dev) { - return can_support_ecm(c->cdev->gadget) - ? ecm_bind_config(c, ethaddr, dev) - : geth_bind_config(c, ethaddr, dev); + int status = 0; + + if (can_support_ecm(c->cdev->gadget)) { + f_ecm = usb_get_function(fi_ecm); + if (IS_ERR(f_ecm)) + return PTR_ERR(f_ecm); + + status = usb_add_function(c, f_ecm); + if (status < 0) + usb_put_function(f_ecm); + + } else { + status = geth_bind_config(c, ethaddr, dev); + } + return status; } #endif -- cgit v1.2.3 From f1a2ca2e4be7327e9f71257c88c0b4f511cb6677 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:24 +0100 Subject: usb: gadget: f_ecm: remove compatibility layer There are no old function interface users left, so the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmim Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_ecm.c | 73 +------------------------------------------- drivers/usb/gadget/u_ether.h | 2 -- 2 files changed, 1 insertion(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 8d9e6f7e8f1a..798760fa7e70 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -691,7 +691,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) int status; struct usb_ep *ep; -#ifndef USBF_ECM_INCLUDED struct f_ecm_opts *ecm_opts; if (!can_support_ecm(cdev->gadget)) @@ -715,7 +714,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) return status; ecm_opts->bound = true; } -#endif + us = usb_gstrings_attach(cdev, ecm_strings, ARRAY_SIZE(ecm_string_defs)); if (IS_ERR(us)) @@ -834,74 +833,6 @@ fail: return status; } -#ifdef USBF_ECM_INCLUDED - -static void -ecm_old_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_ecm *ecm = func_to_ecm(f); - - DBG(c->cdev, "ecm unbind\n"); - - usb_free_all_descriptors(f); - - kfree(ecm->notify_req->buf); - usb_ep_free_request(ecm->notify, ecm->notify_req); - kfree(ecm); -} - -/** - * ecm_bind_config - add CDC Ethernet network link to a configuration - * @c: the configuration to support the network link - * @ethaddr: a buffer in which the ethernet address of the host side - * side of the link was recorded - * @dev: eth_dev structure - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - * Caller must have called @gether_setup(). Caller is also responsible - * for calling @gether_cleanup() before module unload. - */ -int -ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - struct eth_dev *dev) -{ - struct f_ecm *ecm; - int status; - - if (!can_support_ecm(c->cdev->gadget) || !ethaddr) - return -EINVAL; - - /* allocate and initialize one new instance */ - ecm = kzalloc(sizeof *ecm, GFP_KERNEL); - if (!ecm) - return -ENOMEM; - - /* export host's Ethernet address in CDC format */ - snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr); - ecm_string_defs[1].s = ecm->ethaddr; - - ecm->port.ioport = dev; - ecm->port.cdc_filter = DEFAULT_FILTER; - - ecm->port.func.name = "cdc_ethernet"; - /* descriptors are per-instance copies */ - ecm->port.func.bind = ecm_bind; - ecm->port.func.unbind = ecm_old_unbind; - ecm->port.func.set_alt = ecm_set_alt; - ecm->port.func.get_alt = ecm_get_alt; - ecm->port.func.setup = ecm_setup; - ecm->port.func.disable = ecm_disable; - - status = usb_add_function(c, &ecm->port.func); - if (status) - kfree(ecm); - return status; -} - -#else - static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item) { return container_of(to_config_group(item), struct f_ecm_opts, @@ -1040,5 +971,3 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi) DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); - -#endif diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index a32b41e27450..c06059568d6c 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -270,8 +270,6 @@ static inline bool can_support_ecm(struct usb_gadget *gadget) /* each configuration may bind one instance of an ethernet link */ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], struct eth_dev *dev); -int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - struct eth_dev *dev); #ifdef USB_ETH_RNDIS -- cgit v1.2.3 From 85aec59fabaa89f96cafe77fa02ee566e0499636 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:25 +0100 Subject: usb: gadget: g_ffs: convert to new interface of f_subset There is a new function interface of f_subset and g_ffs is the last to use the old one. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/g_ffs.c | 69 +++++++++++++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b135856852ec..d8a1d5cb1e75 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -896,6 +896,7 @@ config USB_FUNCTIONFS_ETH depends on USB_FUNCTIONFS && NET select USB_U_ETHER select USB_F_ECM + select USB_F_SUBSET help Include a configuration with CDC ECM function (Ethernet) and the Function Filesystem. diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index cda4c5d34260..99ae8ec23c9c 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -21,6 +21,8 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS +#include + # if defined USB_ETH_RNDIS # undef USB_ETH_RNDIS # endif @@ -29,8 +31,7 @@ # endif # include "u_ecm.h" -#define USB_FSUBSET_INCLUDED -# include "f_subset.c" +# include "u_gether.h" # ifdef USB_ETH_RNDIS # define USB_FRNDIS_INCLUDED # include "f_rndis.c" @@ -47,6 +48,8 @@ static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], struct eth_dev *dev); static struct usb_function_instance *fi_ecm; static struct usb_function *f_ecm; +static struct usb_function_instance *fi_geth; +static struct usb_function *f_geth; # endif #else # define the_dev NULL @@ -348,6 +351,9 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data) */ static int gfs_bind(struct usb_composite_dev *cdev) { +#if defined CONFIG_USB_FUNCTIONFS_ETH + struct net_device *net; +#endif int ret, i; ENTER(); @@ -362,19 +368,25 @@ static int gfs_bind(struct usb_composite_dev *cdev) if (IS_ERR(fi_ecm)) return PTR_ERR(fi_ecm); ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); - - gether_set_qmult(ecm_opts->net, qmult); - - if (!gether_set_host_addr(ecm_opts->net, host_addr)) - pr_info("using host ethernet address: %s", host_addr); - if (!gether_set_dev_addr(ecm_opts->net, dev_addr)) - pr_info("using self ethernet address: %s", dev_addr); - - the_dev = netdev_priv(ecm_opts->net); + net = ecm_opts->net; } else { - the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, - gfs_host_mac, qmult); + struct f_gether_opts *geth_opts; + + fi_geth = usb_get_function_instance("geth"); + if (IS_ERR(fi_geth)) + return PTR_ERR(fi_geth); + geth_opts = container_of(fi_geth, struct f_gether_opts, + func_inst); + net = geth_opts->net; } + gether_set_qmult(net, qmult); + + if (!gether_set_host_addr(net, host_addr)) + pr_info("using host ethernet address: %s", host_addr); + if (!gether_set_dev_addr(net, dev_addr)) + pr_info("using self ethernet address: %s", dev_addr); + + the_dev = netdev_priv(net); #elif defined CONFIG_USB_FUNCTIONFS_RNDIS @@ -385,18 +397,24 @@ static int gfs_bind(struct usb_composite_dev *cdev) return PTR_ERR(the_dev); #if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH + gether_set_gadget(net, cdev->gadget); + ret = gether_register_netdev(net); + if (ret) + goto error; + if (can_support_ecm(cdev->gadget)) { struct f_ecm_opts *ecm_opts; ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); - - gether_set_gadget(ecm_opts->net, cdev->gadget); - ret = gether_register_netdev(ecm_opts->net); - if (ret) - goto error; ecm_opts->bound = true; - gether_get_host_addr_u8(ecm_opts->net, gfs_host_mac); + } else { + struct f_gether_opts *geth_opts; + + geth_opts = container_of(fi_geth, struct f_gether_opts, + func_inst); + geth_opts->bound = true; } + gether_get_host_addr_u8(net, gfs_host_mac); #endif ret = usb_string_ids_tab(cdev, gfs_strings); @@ -437,7 +455,7 @@ error: if (can_support_ecm(cdev->gadget)) usb_put_function_instance(fi_ecm); else - gether_cleanup(the_dev); + usb_put_function_instance(fi_geth); the_dev = NULL; #elif defined CONFIG_USB_FUNCTIONFS_RNDIS gether_cleanup(the_dev); @@ -461,7 +479,8 @@ static int gfs_unbind(struct usb_composite_dev *cdev) usb_put_function(f_ecm); usb_put_function_instance(fi_ecm); } else { - gether_cleanup(the_dev); + usb_put_function(f_geth); + usb_put_function_instance(fi_geth); } the_dev = NULL; #elif defined CONFIG_USB_FUNCTIONFS_RNDIS @@ -548,7 +567,13 @@ static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], usb_put_function(f_ecm); } else { - status = geth_bind_config(c, ethaddr, dev); + f_geth = usb_get_function(fi_geth); + if (IS_ERR(f_geth)) + return PTR_ERR(f_geth); + + status = usb_add_function(c, f_geth); + if (status < 0) + usb_put_function(f_geth); } return status; } -- cgit v1.2.3 From 05de3fe3d1c124e4de53b111806c5740acd8d732 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:26 +0100 Subject: usb: gadget: f_subset: remove compatibility layer There are no old function interface users left, so the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_subset.c | 60 +------------------------------------------ drivers/usb/gadget/u_ether.h | 3 --- 2 files changed, 1 insertion(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 7c8674fa7e80..f1a59190ac9a 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -301,7 +301,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) int status; struct usb_ep *ep; -#ifndef USB_FSUBSET_INCLUDED struct f_gether_opts *gether_opts; gether_opts = container_of(f->fi, struct f_gether_opts, func_inst); @@ -322,7 +321,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) return status; gether_opts->bound = true; } -#endif + us = usb_gstrings_attach(cdev, geth_strings, ARRAY_SIZE(geth_string_defs)); if (IS_ERR(us)) @@ -393,61 +392,6 @@ fail: return status; } -#ifdef USB_FSUBSET_INCLUDED - -static void -geth_old_unbind(struct usb_configuration *c, struct usb_function *f) -{ - geth_string_defs[0].id = 0; - usb_free_all_descriptors(f); - kfree(func_to_geth(f)); -} - -/** - * geth_bind_config - add CDC Subset network link to a configuration - * @c: the configuration to support the network link - * @ethaddr: a buffer in which the ethernet address of the host side - * side of the link was recorded - * @dev: eth_dev structure - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - * Caller must have called @gether_setup(). Caller is also responsible - * for calling @gether_cleanup() before module unload. - */ -int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - struct eth_dev *dev) -{ - struct f_gether *geth; - int status; - - /* allocate and initialize one new instance */ - geth = kzalloc(sizeof *geth, GFP_KERNEL); - if (!geth) - return -ENOMEM; - - /* export host's Ethernet address in CDC format */ - snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr); - geth_string_defs[1].s = geth->ethaddr; - - geth->port.ioport = dev; - geth->port.cdc_filter = DEFAULT_FILTER; - - geth->port.func.name = "cdc_subset"; - geth->port.func.bind = geth_bind; - geth->port.func.unbind = geth_old_unbind; - geth->port.func.set_alt = geth_set_alt; - geth->port.func.disable = geth_disable; - - status = usb_add_function(c, &geth->port.func); - if (status) - kfree(geth); - return status; -} - -#else - static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item) { return container_of(to_config_group(item), struct f_gether_opts, @@ -573,5 +517,3 @@ static struct usb_function *geth_alloc(struct usb_function_instance *fi) DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); - -#endif diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index c06059568d6c..72b6facde40d 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -268,9 +268,6 @@ static inline bool can_support_ecm(struct usb_gadget *gadget) } /* each configuration may bind one instance of an ethernet link */ -int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - struct eth_dev *dev); - #ifdef USB_ETH_RNDIS int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], -- cgit v1.2.3 From 6e257b14218d0d963058a96736da6c6e2abb08f3 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:27 +0100 Subject: usb: gadget: g_ffs: convert to new interface of f_rndis There is a new interface of f_rndis and g_ffs is the last to use the old one. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/g_ffs.c | 105 ++++++++++++++++++++++++++++----------------- 2 files changed, 66 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index d8a1d5cb1e75..8cea14f3d590 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -906,6 +906,7 @@ config USB_FUNCTIONFS_RNDIS depends on USB_FUNCTIONFS && NET select USB_U_ETHER select USB_U_RNDIS + select USB_F_RNDIS help Include a configuration with RNDIS function (Ethernet) and the Filesystem. diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 99ae8ec23c9c..7099a112c734 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -33,29 +33,25 @@ # include "u_ecm.h" # include "u_gether.h" # ifdef USB_ETH_RNDIS -# define USB_FRNDIS_INCLUDED -# include "f_rndis.c" +# include "u_rndis.h" # include "rndis.h" # endif # include "u_ether.h" USB_ETHERNET_MODULE_PARAMETERS(); -static u8 gfs_host_mac[ETH_ALEN]; -static struct eth_dev *the_dev; # ifdef CONFIG_USB_FUNCTIONFS_ETH -static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - struct eth_dev *dev); +static int eth_bind_config(struct usb_configuration *c); static struct usb_function_instance *fi_ecm; static struct usb_function *f_ecm; static struct usb_function_instance *fi_geth; static struct usb_function *f_geth; # endif -#else -# define the_dev NULL -# define gether_cleanup(dev) do { } while (0) -# define gfs_host_mac NULL -struct eth_dev; +# ifdef CONFIG_USB_FUNCTIONFS_RNDIS +static int bind_rndis_config(struct usb_configuration *c); +static struct usb_function_instance *fi_rndis; +static struct usb_function *f_rndis; +# endif #endif #include "f_fs.c" @@ -148,12 +144,11 @@ static struct usb_gadget_strings *gfs_dev_strings[] = { struct gfs_configuration { struct usb_configuration c; - int (*eth)(struct usb_configuration *c, u8 *ethaddr, - struct eth_dev *dev); + int (*eth)(struct usb_configuration *c); } gfs_configurations[] = { #ifdef CONFIG_USB_FUNCTIONFS_RNDIS { - .eth = rndis_bind_config, + .eth = bind_rndis_config, }, #endif @@ -351,7 +346,7 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data) */ static int gfs_bind(struct usb_composite_dev *cdev) { -#if defined CONFIG_USB_FUNCTIONFS_ETH +#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS struct net_device *net; #endif int ret, i; @@ -379,28 +374,38 @@ static int gfs_bind(struct usb_composite_dev *cdev) func_inst); net = geth_opts->net; } - gether_set_qmult(net, qmult); +#endif + +#ifdef CONFIG_USB_FUNCTIONFS_RNDIS + { + struct f_rndis_opts *rndis_opts; + + fi_rndis = usb_get_function_instance("rndis"); + if (IS_ERR(fi_rndis)) { + ret = PTR_ERR(fi_rndis); + goto error; + } + rndis_opts = container_of(fi_rndis, struct f_rndis_opts, + func_inst); +#ifndef CONFIG_USB_FUNCTIONFS_ETH + net = rndis_opts->net; +#endif + } +#endif +#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS + gether_set_qmult(net, qmult); if (!gether_set_host_addr(net, host_addr)) pr_info("using host ethernet address: %s", host_addr); if (!gether_set_dev_addr(net, dev_addr)) pr_info("using self ethernet address: %s", dev_addr); - - the_dev = netdev_priv(net); - -#elif defined CONFIG_USB_FUNCTIONFS_RNDIS - - the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac, - qmult); #endif - if (IS_ERR(the_dev)) - return PTR_ERR(the_dev); #if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH gether_set_gadget(net, cdev->gadget); ret = gether_register_netdev(net); if (ret) - goto error; + goto error_rndis; if (can_support_ecm(cdev->gadget)) { struct f_ecm_opts *ecm_opts; @@ -414,12 +419,13 @@ static int gfs_bind(struct usb_composite_dev *cdev) func_inst); geth_opts->bound = true; } - gether_get_host_addr_u8(net, gfs_host_mac); + + rndis_borrow_net(fi_rndis, net); #endif ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) - goto error; + goto error_rndis; gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; for (i = func_num; i--; ) { @@ -427,7 +433,7 @@ static int gfs_bind(struct usb_composite_dev *cdev) if (unlikely(ret < 0)) { while (++i < func_num) functionfs_unbind(ffs_tab[i].ffs_data); - goto error; + goto error_rndis; } } @@ -450,16 +456,16 @@ static int gfs_bind(struct usb_composite_dev *cdev) error_unbind: for (i = 0; i < func_num; i++) functionfs_unbind(ffs_tab[i].ffs_data); +error_rndis: +#ifdef CONFIG_USB_FUNCTIONFS_RNDIS + usb_put_function_instance(fi_rndis); error: +#endif #if defined CONFIG_USB_FUNCTIONFS_ETH if (can_support_ecm(cdev->gadget)) usb_put_function_instance(fi_ecm); else usb_put_function_instance(fi_geth); - the_dev = NULL; -#elif defined CONFIG_USB_FUNCTIONFS_RNDIS - gether_cleanup(the_dev); - the_dev = NULL; #endif return ret; } @@ -474,6 +480,11 @@ static int gfs_unbind(struct usb_composite_dev *cdev) ENTER(); +#ifdef CONFIG_USB_FUNCTIONFS_RNDIS + usb_put_function(f_rndis); + usb_put_function_instance(fi_rndis); +#endif + #if defined CONFIG_USB_FUNCTIONFS_ETH if (can_support_ecm(cdev->gadget)) { usb_put_function(f_ecm); @@ -482,10 +493,6 @@ static int gfs_unbind(struct usb_composite_dev *cdev) usb_put_function(f_geth); usb_put_function_instance(fi_geth); } - the_dev = NULL; -#elif defined CONFIG_USB_FUNCTIONFS_RNDIS - gether_cleanup(the_dev); - the_dev = NULL; #endif /* @@ -523,7 +530,7 @@ static int gfs_do_config(struct usb_configuration *c) } if (gc->eth) { - ret = gc->eth(c, gfs_host_mac, the_dev); + ret = gc->eth(c); if (unlikely(ret < 0)) return ret; } @@ -552,8 +559,7 @@ static int gfs_do_config(struct usb_configuration *c) #ifdef CONFIG_USB_FUNCTIONFS_ETH -static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - struct eth_dev *dev) +static int eth_bind_config(struct usb_configuration *c) { int status = 0; @@ -579,3 +585,22 @@ static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], } #endif + +#ifdef CONFIG_USB_FUNCTIONFS_RNDIS + +static int bind_rndis_config(struct usb_configuration *c) +{ + int status = 0; + + f_rndis = usb_get_function(fi_rndis); + if (IS_ERR(f_rndis)) + return PTR_ERR(f_rndis); + + status = usb_add_function(c, f_rndis); + if (status < 0) + usb_put_function(f_rndis); + + return status; +} + +#endif -- cgit v1.2.3 From 31f89db1b81ea1c54ca7d186a0c0ebab0d4988f0 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:28 +0100 Subject: usb: gadget: f_rndis: remove compatibility layer There are no old function interface users left, so the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_rndis.c | 72 +------------------------------------------- drivers/usb/gadget/u_ether.h | 36 ---------------------- 2 files changed, 1 insertion(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 717ed7f95639..9d7c99526dda 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -675,7 +675,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) int status; struct usb_ep *ep; -#ifndef USB_FRNDIS_INCLUDED struct f_rndis_opts *rndis_opts; if (!can_support_rndis(c)) @@ -697,7 +696,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) return status; rndis_opts->bound = true; } -#endif + us = usb_gstrings_attach(cdev, rndis_strings, ARRAY_SIZE(rndis_string_defs)); if (IS_ERR(us)) @@ -782,13 +781,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) rndis->port.open = rndis_open; rndis->port.close = rndis_close; -#ifdef USB_FRNDIS_INCLUDED - status = rndis_register(rndis_response_available, rndis); - if (status < 0) - goto fail; - rndis->config = status; -#endif - rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); rndis_set_host_mac(rndis->config, rndis->ethaddr); @@ -830,66 +822,6 @@ fail: return status; } -#ifdef USB_FRNDIS_INCLUDED - -static void -rndis_old_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_rndis *rndis = func_to_rndis(f); - - rndis_deregister(rndis->config); - - usb_free_all_descriptors(f); - - kfree(rndis->notify_req->buf); - usb_ep_free_request(rndis->notify, rndis->notify_req); - - kfree(rndis); -} - -int -rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - u32 vendorID, const char *manufacturer, struct eth_dev *dev) -{ - struct f_rndis *rndis; - int status; - - /* allocate and initialize one new instance */ - status = -ENOMEM; - rndis = kzalloc(sizeof *rndis, GFP_KERNEL); - if (!rndis) - goto fail; - - memcpy(rndis->ethaddr, ethaddr, ETH_ALEN); - rndis->vendorID = vendorID; - rndis->manufacturer = manufacturer; - - rndis->port.ioport = dev; - /* RNDIS activates when the host changes this filter */ - rndis->port.cdc_filter = 0; - - /* RNDIS has special (and complex) framing */ - rndis->port.header_len = sizeof(struct rndis_packet_msg_type); - rndis->port.wrap = rndis_add_header; - rndis->port.unwrap = rndis_rm_hdr; - - rndis->port.func.name = "rndis"; - /* descriptors are per-instance copies */ - rndis->port.func.bind = rndis_bind; - rndis->port.func.unbind = rndis_old_unbind; - rndis->port.func.set_alt = rndis_set_alt; - rndis->port.func.setup = rndis_setup; - rndis->port.func.disable = rndis_disable; - - status = usb_add_function(c, &rndis->port.func); - if (status) - kfree(rndis); -fail: - return status; -} - -#else - void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net) { struct f_rndis_opts *opts; @@ -1050,5 +982,3 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); - -#endif diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index 72b6facde40d..0f0290acea7e 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -267,40 +267,4 @@ static inline bool can_support_ecm(struct usb_gadget *gadget) return true; } -/* each configuration may bind one instance of an ethernet link */ -#ifdef USB_ETH_RNDIS - -int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - u32 vendorID, const char *manufacturer, struct eth_dev *dev); - -#else - -static inline int -rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - u32 vendorID, const char *manufacturer, struct eth_dev *dev) -{ - return 0; -} - -#endif - -/** - * rndis_bind_config - add RNDIS network link to a configuration - * @c: the configuration to support the network link - * @ethaddr: a buffer in which the ethernet address of the host side - * side of the link was recorded - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - * Caller must have called @gether_setup(). Caller is also responsible - * for calling @gether_cleanup() before module unload. - */ -static inline int rndis_bind_config(struct usb_configuration *c, - u8 ethaddr[ETH_ALEN], struct eth_dev *dev) -{ - return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev); -} - - #endif /* __U_ETHER_H */ -- cgit v1.2.3 From 9c2b85f4f99cb5c5f4b8e29ef15e344f93ec5be1 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:29 +0100 Subject: usb: gadget: rndis: merge u_rndis.ko with usb_f_rndis.ko The rndis function's users use only the new interface, so the two modules can be merged. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 7 ------- drivers/usb/gadget/Makefile | 4 +--- drivers/usb/gadget/f_rndis.c | 22 +++++++++++++++++++++- drivers/usb/gadget/rndis.c | 7 ++----- drivers/usb/gadget/u_rndis.h | 2 ++ 5 files changed, 26 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 8cea14f3d590..aa3610ea9d9f 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -512,9 +512,6 @@ config USB_U_SERIAL config USB_U_ETHER tristate -config USB_U_RNDIS - tristate - config USB_F_SERIAL tristate @@ -642,7 +639,6 @@ config USB_CONFIGFS_RNDIS depends on USB_CONFIGFS depends on NET select USB_U_ETHER - select USB_U_RNDIS select USB_F_RNDIS help Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, @@ -772,7 +768,6 @@ config USB_ETH depends on NET select USB_LIBCOMPOSITE select USB_U_ETHER - select USB_U_RNDIS select USB_F_ECM select USB_F_SUBSET select CRC32 @@ -905,7 +900,6 @@ config USB_FUNCTIONFS_RNDIS bool "Include configuration with RNDIS (Ethernet)" depends on USB_FUNCTIONFS && NET select USB_U_ETHER - select USB_U_RNDIS select USB_F_RNDIS help Include a configuration with RNDIS function (Ethernet) and the Filesystem. @@ -1080,7 +1074,6 @@ config USB_G_MULTI config USB_G_MULTI_RNDIS bool "RNDIS + CDC Serial + Storage configuration" depends on USB_G_MULTI - select USB_U_RNDIS select USB_F_RNDIS default y help diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 40bd0f80b5ad..0c40277931f4 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -47,8 +47,6 @@ obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o usb_f_obex-y := f_obex.o obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o obj-$(CONFIG_USB_U_ETHER) += u_ether.o -u_rndis-y := rndis.o -obj-$(CONFIG_USB_U_RNDIS) += u_rndis.o usb_f_ncm-y := f_ncm.o obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o usb_f_ecm-y := f_ecm.o @@ -59,7 +57,7 @@ usb_f_eem-y := f_eem.o obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o usb_f_ecm_subset-y := f_subset.o obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o -usb_f_rndis-y := f_rndis.o +usb_f_rndis-y := f_rndis.o rndis.o obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o usb_f_mass_storage-y := f_mass_storage.o storage_common.o obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 9d7c99526dda..c11761ce5113 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -979,6 +979,26 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) return &rndis->port.func; } -DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc); +DECLARE_USB_FUNCTION(rndis, rndis_alloc_inst, rndis_alloc); + +static int __init rndis_mod_init(void) +{ + int ret; + + ret = rndis_init(); + if (ret) + return ret; + + return usb_function_register(&rndisusb_func); +} +module_init(rndis_mod_init); + +static void __exit rndis_mod_exit(void) +{ + usb_function_unregister(&rndisusb_func); + rndis_exit(); +} +module_exit(rndis_mod_exit); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index a3ad732bc812..1ffbdb4659f2 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1142,7 +1142,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; #endif /* CONFIG_USB_GADGET_DEBUG_FILES */ -static int rndis_init(void) +int rndis_init(void) { u8 i; @@ -1174,9 +1174,8 @@ static int rndis_init(void) return 0; } -module_init(rndis_init); -static void rndis_exit(void) +void rndis_exit(void) { #ifdef CONFIG_USB_GADGET_DEBUG_FILES u8 i; @@ -1188,6 +1187,4 @@ static void rndis_exit(void) } #endif } -module_exit(rndis_exit); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/u_rndis.h index c62ba82e9600..7291b15c9dce 100644 --- a/drivers/usb/gadget/u_rndis.h +++ b/drivers/usb/gadget/u_rndis.h @@ -36,6 +36,8 @@ struct f_rndis_opts { int refcnt; }; +int rndis_init(void); +void rndis_exit(void); void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net); #endif /* U_RNDIS_H */ -- cgit v1.2.3 From e6f3862fa1ecea6579dd1727869655e88be7a5ef Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:30 +0100 Subject: usb: gadget: FunctionFS: Remove VLAIS usage from gadget code The use of variable length arrays in structs (VLAIS) in the Linux Kernel code precludes the use of compilers which don't implement VLAIS (for instance the Clang compiler). This alternate patch calculates offsets into the kmalloc-ed memory buffer using macros. The previous patch required multiple kmalloc and kfree calls. This version uses "group" vs "struct" since it really is not a struct and is essentially a group of VLA in a common allocated block. This version also fixes the issues pointed out by Andrzej Pietrasiewicz and Michal Nazarewicz. Signed-off-by: Mark Charlebois Signed-off-by: Behan Webster [elimination of miexed declaration and code, checkpatch cleanup] [fixes after Michal's review] Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 116 ++++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 34940439bb18..91b94b1dcfe3 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -30,6 +30,31 @@ #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ +/* Variable Length Array Macros **********************************************/ +#define vla_group(groupname) size_t groupname##__next = 0 +#define vla_group_size(groupname) groupname##__next + +#define vla_item(groupname, type, name, n) \ + size_t groupname##_##name##__offset = ({ \ + size_t align_mask = __alignof__(type) - 1; \ + size_t offset = (groupname##__next + align_mask) & ~align_mask;\ + size_t size = (n) * sizeof(type); \ + groupname##__next = offset + size; \ + offset; \ + }) + +#define vla_item_with_sz(groupname, type, name, n) \ + size_t groupname##_##name##__sz = (n) * sizeof(type); \ + size_t groupname##_##name##__offset = ({ \ + size_t align_mask = __alignof__(type) - 1; \ + size_t offset = (groupname##__next + align_mask) & ~align_mask;\ + size_t size = groupname##_##name##__sz; \ + groupname##__next = offset + size; \ + offset; \ + }) + +#define vla_ptr(ptr, groupname, name) \ + ((void *) ((char *)ptr + groupname##_##name##__offset)) /* Debugging ****************************************************************/ @@ -1902,30 +1927,34 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, /* Allocate everything in one chunk so there's less maintenance. */ { - struct { - struct usb_gadget_strings *stringtabs[lang_count + 1]; - struct usb_gadget_strings stringtab[lang_count]; - struct usb_string strings[lang_count*(needed_count+1)]; - } *d; unsigned i = 0; + vla_group(d); + vla_item(d, struct usb_gadget_strings *, stringtabs, + lang_count + 1); + vla_item(d, struct usb_gadget_strings, stringtab, lang_count); + vla_item(d, struct usb_string, strings, + lang_count*(needed_count+1)); - d = kmalloc(sizeof *d, GFP_KERNEL); - if (unlikely(!d)) { + char *vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL); + + if (unlikely(!vlabuf)) { kfree(_data); return -ENOMEM; } - stringtabs = d->stringtabs; - t = d->stringtab; + /* Initialize the VLA pointers */ + stringtabs = vla_ptr(vlabuf, d, stringtabs); + t = vla_ptr(vlabuf, d, stringtab); i = lang_count; do { *stringtabs++ = t++; } while (--i); *stringtabs = NULL; - stringtabs = d->stringtabs; - t = d->stringtab; - s = d->strings; + /* stringtabs = vlabuf = d_stringtabs for later kfree */ + stringtabs = vla_ptr(vlabuf, d, stringtabs); + t = vla_ptr(vlabuf, d, stringtab); + s = vla_ptr(vlabuf, d, strings); strings = s; } @@ -2201,16 +2230,16 @@ static int ffs_func_bind(struct usb_configuration *c, int ret; /* Make it a single chunk, less management later on */ - struct { - struct ffs_ep eps[ffs->eps_count]; - struct usb_descriptor_header - *fs_descs[full ? ffs->fs_descs_count + 1 : 0]; - struct usb_descriptor_header - *hs_descs[high ? ffs->hs_descs_count + 1 : 0]; - short inums[ffs->interfaces_count]; - char raw_descs[high ? ffs->raw_descs_length - : ffs->raw_fs_descs_length]; - } *data; + vla_group(d); + vla_item_with_sz(d, struct ffs_ep, eps, ffs->eps_count); + vla_item_with_sz(d, struct usb_descriptor_header *, fs_descs, + full ? ffs->fs_descs_count + 1 : 0); + vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs, + high ? ffs->hs_descs_count + 1 : 0); + vla_item_with_sz(d, short, inums, ffs->interfaces_count); + vla_item_with_sz(d, char, raw_descs, + high ? ffs->raw_descs_length : ffs->raw_fs_descs_length); + char *vlabuf; ENTER(); @@ -2218,21 +2247,28 @@ static int ffs_func_bind(struct usb_configuration *c, if (unlikely(!(full | high))) return -ENOTSUPP; - /* Allocate */ - data = kmalloc(sizeof *data, GFP_KERNEL); - if (unlikely(!data)) + /* Allocate a single chunk, less management later on */ + vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL); + if (unlikely(!vlabuf)) return -ENOMEM; /* Zero */ - memset(data->eps, 0, sizeof data->eps); - memcpy(data->raw_descs, ffs->raw_descs + 16, sizeof data->raw_descs); - memset(data->inums, 0xff, sizeof data->inums); - for (ret = ffs->eps_count; ret; --ret) - data->eps[ret].num = -1; + memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz); + memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs + 16, + d_raw_descs__sz); + memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz); + for (ret = ffs->eps_count; ret; --ret) { + struct ffs_ep *ptr; + + ptr = vla_ptr(vlabuf, d, eps); + ptr[ret].num = -1; + } - /* Save pointers */ - func->eps = data->eps; - func->interfaces_nums = data->inums; + /* Save pointers + * d_eps == vlabuf, func->eps used to kfree vlabuf later + */ + func->eps = vla_ptr(vlabuf, d, eps); + func->interfaces_nums = vla_ptr(vlabuf, d, inums); /* * Go through all the endpoint descriptors and allocate @@ -2240,10 +2276,10 @@ static int ffs_func_bind(struct usb_configuration *c, * numbers without worrying that it may be described later on. */ if (likely(full)) { - func->function.fs_descriptors = data->fs_descs; + func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs); ret = ffs_do_descs(ffs->fs_descs_count, - data->raw_descs, - sizeof data->raw_descs, + vla_ptr(vlabuf, d, raw_descs), + d_raw_descs__sz, __ffs_func_bind_do_descs, func); if (unlikely(ret < 0)) goto error; @@ -2252,10 +2288,10 @@ static int ffs_func_bind(struct usb_configuration *c, } if (likely(high)) { - func->function.hs_descriptors = data->hs_descs; + func->function.hs_descriptors = vla_ptr(vlabuf, d, hs_descs); ret = ffs_do_descs(ffs->hs_descs_count, - data->raw_descs + ret, - (sizeof data->raw_descs) - ret, + vla_ptr(vlabuf, d, raw_descs) + ret, + d_raw_descs__sz - ret, __ffs_func_bind_do_descs, func); if (unlikely(ret < 0)) goto error; @@ -2268,7 +2304,7 @@ static int ffs_func_bind(struct usb_configuration *c, */ ret = ffs_do_descs(ffs->fs_descs_count + (high ? ffs->hs_descs_count : 0), - data->raw_descs, sizeof data->raw_descs, + vla_ptr(vlabuf, d, raw_descs), d_raw_descs__sz, __ffs_func_bind_do_nums, func); if (unlikely(ret < 0)) goto error; -- cgit v1.2.3 From e72c39c0692d17da4c7f08e20d6c57f7409415f7 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:31 +0100 Subject: usb: gadget: FunctionFS: create utility file A header file to be used by f_fs.c and g_ffs.c will be required when f_fs.c is converted into a module. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 1 + drivers/usb/gadget/g_ffs.c | 19 ++++++------------- drivers/usb/gadget/u_fs.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/gadget/u_fs.h (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 91b94b1dcfe3..c0b4cf808638 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -27,6 +27,7 @@ #include #include +#include "u_fs.h" #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 7099a112c734..1aaa103e01c6 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -69,13 +69,6 @@ MODULE_LICENSE("GPL"); #define GFS_MAX_DEVS 10 -struct gfs_ffs_obj { - const char *name; - bool mounted; - bool desc_ready; - struct ffs_data *ffs_data; -}; - USB_GADGET_COMPOSITE_OPTIONS(); static struct usb_device_descriptor gfs_dev_desc = { @@ -181,7 +174,7 @@ static DEFINE_MUTEX(gfs_lock); static unsigned int missing_funcs; static bool gfs_registered; static bool gfs_single_func; -static struct gfs_ffs_obj *ffs_tab; +static struct ffs_dev *ffs_tab; static int __init gfs_init(void) { @@ -224,7 +217,7 @@ static void __exit gfs_exit(void) } module_exit(gfs_exit); -static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name) +static struct ffs_dev *gfs_find_dev(const char *dev_name) { int i; @@ -242,7 +235,7 @@ static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name) static int functionfs_ready_callback(struct ffs_data *ffs) { - struct gfs_ffs_obj *ffs_obj; + struct ffs_dev *ffs_obj; int ret; ENTER(); @@ -283,7 +276,7 @@ done: static void functionfs_closed_callback(struct ffs_data *ffs) { - struct gfs_ffs_obj *ffs_obj; + struct ffs_dev *ffs_obj; ENTER(); mutex_lock(&gfs_lock); @@ -305,7 +298,7 @@ done: static void *functionfs_acquire_dev_callback(const char *dev_name) { - struct gfs_ffs_obj *ffs_dev; + struct ffs_dev *ffs_dev; ENTER(); mutex_lock(&gfs_lock); @@ -329,7 +322,7 @@ done: static void functionfs_release_dev_callback(struct ffs_data *ffs_data) { - struct gfs_ffs_obj *ffs_dev; + struct ffs_dev *ffs_dev; ENTER(); mutex_lock(&gfs_lock); diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h new file mode 100644 index 000000000000..5d9229a01560 --- /dev/null +++ b/drivers/usb/gadget/u_fs.h @@ -0,0 +1,28 @@ +/* + * u_fs.h + * + * Utility definitions for the FunctionFS + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef U_FFS_H +#define U_FFS_H + +#include + +struct ffs_dev { + const char *name; + bool mounted; + bool desc_ready; + struct ffs_data *ffs_data; +}; + +#endif /* U_FFS_H */ -- cgit v1.2.3 From 4b187fceec3c731815ff8e6a7317fd5ba50d1d5d Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:32 +0100 Subject: usb: gadget: FunctionFS: add devices management code This will be required in order to use the new function interface (usb_get_function_instance/usb_put_function_instance) Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyunmgin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 238 +++++++++++++++++++++++++++++++++++++++-- drivers/usb/gadget/g_ffs.c | 175 ++++++++++-------------------- drivers/usb/gadget/u_fs.h | 24 +++++ include/linux/usb/functionfs.h | 14 --- 4 files changed, 314 insertions(+), 137 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index c0b4cf808638..d17930d9a843 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -90,7 +90,7 @@ enum ffs_state { /* * We've got descriptors and strings. We are or have called - * functionfs_ready_callback(). functionfs_bind() may have + * ffs_ready(). functionfs_bind() may have * been called but we don't know. * * This is the only state in which operations on epfiles may @@ -103,7 +103,7 @@ enum ffs_state { * we encounter an unrecoverable error. The only * unrecoverable error is situation when after reading strings * from user space we fail to initialise epfiles or - * functionfs_ready_callback() returns with error (<0). + * ffs_ready() returns with error (<0). * * In this state no open(2), read(2) or write(2) (both on ep0 * as well as epfile) may succeed (at this point epfiles are @@ -361,6 +361,15 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data, const struct file_operations *fops, struct dentry **dentry_p); +/* Devices management *******************************************************/ + +DEFINE_MUTEX(ffs_lock); + +static struct ffs_dev *ffs_find_dev(const char *name); +static void *ffs_acquire_dev(const char *dev_name); +static void ffs_release_dev(struct ffs_data *ffs_data); +static int ffs_ready(struct ffs_data *ffs); +static void ffs_closed(struct ffs_data *ffs); /* Misc helper functions ****************************************************/ @@ -486,7 +495,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, ffs->state = FFS_ACTIVE; mutex_unlock(&ffs->mutex); - ret = functionfs_ready_callback(ffs); + ret = ffs_ready(ffs); if (unlikely(ret < 0)) { ffs->state = FFS_CLOSING; return ret; @@ -1218,7 +1227,7 @@ ffs_fs_mount(struct file_system_type *t, int flags, return ERR_PTR(-ENOMEM); } - ffs_dev = functionfs_acquire_dev_callback(dev_name); + ffs_dev = ffs_acquire_dev(dev_name); if (IS_ERR(ffs_dev)) { ffs_data_put(ffs); return ERR_CAST(ffs_dev); @@ -1228,7 +1237,7 @@ ffs_fs_mount(struct file_system_type *t, int flags, rv = mount_nodev(t, flags, &data, ffs_sb_fill); if (IS_ERR(rv) && data.ffs_data) { - functionfs_release_dev_callback(data.ffs_data); + ffs_release_dev(data.ffs_data); ffs_data_put(data.ffs_data); } return rv; @@ -1241,7 +1250,7 @@ ffs_fs_kill_sb(struct super_block *sb) kill_litter_super(sb); if (sb->s_fs_info) { - functionfs_release_dev_callback(sb->s_fs_info); + ffs_release_dev(sb->s_fs_info); ffs_data_put(sb->s_fs_info); } } @@ -1354,7 +1363,7 @@ static void ffs_data_clear(struct ffs_data *ffs) ENTER(); if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags)) - functionfs_closed_callback(ffs); + ffs_closed(ffs); BUG_ON(ffs->gadget); @@ -2466,6 +2475,221 @@ static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf) } +/* Devices management *******************************************************/ + +static LIST_HEAD(ffs_devices); + +static struct ffs_dev *_ffs_find_dev(const char *name) +{ + struct ffs_dev *dev; + + list_for_each_entry(dev, &ffs_devices, entry) { + if (!dev->name || !name) + continue; + if (strcmp(dev->name, name) == 0) + return dev; + } + + return NULL; +} + +/* + * ffs_lock must be taken by the caller of this function + */ +static struct ffs_dev *ffs_get_single_dev(void) +{ + struct ffs_dev *dev; + + if (list_is_singular(&ffs_devices)) { + dev = list_first_entry(&ffs_devices, struct ffs_dev, entry); + if (dev->single) + return dev; + } + + return NULL; +} + +/* + * ffs_lock must be taken by the caller of this function + */ +static struct ffs_dev *ffs_find_dev(const char *name) +{ + struct ffs_dev *dev; + + dev = ffs_get_single_dev(); + if (dev) + return dev; + + return _ffs_find_dev(name); +} + +/* + * ffs_lock must be taken by the caller of this function + */ +struct ffs_dev *ffs_alloc_dev(void) +{ + struct ffs_dev *dev; + int ret; + + if (ffs_get_single_dev()) + return ERR_PTR(-EBUSY); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + + if (list_empty(&ffs_devices)) { + ret = functionfs_init(); + if (ret) { + kfree(dev); + return ERR_PTR(ret); + } + } + + list_add(&dev->entry, &ffs_devices); + + return dev; +} + +/* + * ffs_lock must be taken by the caller of this function + * The caller is responsible for "name" being available whenever f_fs needs it + */ +static int _ffs_name_dev(struct ffs_dev *dev, const char *name) +{ + struct ffs_dev *existing; + + existing = _ffs_find_dev(name); + if (existing) + return -EBUSY; + + dev->name = name; + + return 0; +} + +/* + * The caller is responsible for "name" being available whenever f_fs needs it + */ +int ffs_name_dev(struct ffs_dev *dev, const char *name) +{ + int ret; + + ffs_dev_lock(); + ret = _ffs_name_dev(dev, name); + ffs_dev_unlock(); + + return ret; +} + +int ffs_single_dev(struct ffs_dev *dev) +{ + int ret; + + ret = 0; + ffs_dev_lock(); + + if (!list_is_singular(&ffs_devices)) + ret = -EBUSY; + else + dev->single = true; + + ffs_dev_unlock(); + return ret; +} + +/* + * ffs_lock must be taken by the caller of this function + */ +void ffs_free_dev(struct ffs_dev *dev) +{ + list_del(&dev->entry); + kfree(dev); + if (list_empty(&ffs_devices)) + functionfs_cleanup(); +} + +static void *ffs_acquire_dev(const char *dev_name) +{ + struct ffs_dev *ffs_dev; + + ENTER(); + ffs_dev_lock(); + + ffs_dev = ffs_find_dev(dev_name); + if (!ffs_dev) + ffs_dev = ERR_PTR(-ENODEV); + else if (ffs_dev->mounted) + ffs_dev = ERR_PTR(-EBUSY); + else + ffs_dev->mounted = true; + + ffs_dev_unlock(); + return ffs_dev; +} + +static void ffs_release_dev(struct ffs_data *ffs_data) +{ + struct ffs_dev *ffs_dev; + + ENTER(); + ffs_dev_lock(); + + ffs_dev = ffs_data->private_data; + if (ffs_dev) + ffs_dev->mounted = false; + + ffs_dev_unlock(); +} + +static int ffs_ready(struct ffs_data *ffs) +{ + struct ffs_dev *ffs_obj; + int ret = 0; + + ENTER(); + ffs_dev_lock(); + + ffs_obj = ffs->private_data; + if (!ffs_obj) { + ret = -EINVAL; + goto done; + } + if (WARN_ON(ffs_obj->desc_ready)) { + ret = -EBUSY; + goto done; + } + + ffs_obj->desc_ready = true; + ffs_obj->ffs_data = ffs; + + if (ffs_obj->ffs_ready_callback) + ret = ffs_obj->ffs_ready_callback(ffs); + +done: + ffs_dev_unlock(); + return ret; +} + +static void ffs_closed(struct ffs_data *ffs) +{ + struct ffs_dev *ffs_obj; + + ENTER(); + ffs_dev_lock(); + + ffs_obj = ffs->private_data; + if (!ffs_obj) + goto done; + + ffs_obj->desc_ready = false; + + if (ffs_obj->ffs_closed_callback) + ffs_obj->ffs_closed_callback(ffs); +done: + ffs_dev_unlock(); +} + /* Misc helper functions ****************************************************/ static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock) diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 1aaa103e01c6..074df0d56255 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -157,6 +157,8 @@ struct gfs_configuration { #endif }; +static int functionfs_ready_callback(struct ffs_data *ffs); +static void functionfs_closed_callback(struct ffs_data *ffs); static int gfs_bind(struct usb_composite_dev *cdev); static int gfs_unbind(struct usb_composite_dev *cdev); static int gfs_do_config(struct usb_configuration *c); @@ -170,172 +172,113 @@ static __refdata struct usb_composite_driver gfs_driver = { .unbind = gfs_unbind, }; -static DEFINE_MUTEX(gfs_lock); static unsigned int missing_funcs; static bool gfs_registered; static bool gfs_single_func; -static struct ffs_dev *ffs_tab; +static struct ffs_dev **ffs_tab; static int __init gfs_init(void) { int i; + int ret = 0; ENTER(); - if (!func_num) { + if (func_num < 2) { gfs_single_func = true; func_num = 1; } - ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL); + ffs_tab = kcalloc(func_num, sizeof(*ffs_tab), GFP_KERNEL); if (!ffs_tab) return -ENOMEM; - if (!gfs_single_func) - for (i = 0; i < func_num; i++) - ffs_tab[i].name = func_names[i]; + for (i = 0; i < func_num; i++) { + ffs_dev_lock(); + ffs_tab[i] = ffs_alloc_dev(); + ffs_dev_unlock(); + if (IS_ERR(ffs_tab[i])) { + ret = PTR_ERR(ffs_tab[i]); + --i; + goto no_dev; + } + if (gfs_single_func) + ret = ffs_single_dev(ffs_tab[i]); + else + ret = ffs_name_dev(ffs_tab[i], func_names[i]); + if (ret) + goto no_dev; + ffs_tab[i]->ffs_ready_callback = functionfs_ready_callback; + ffs_tab[i]->ffs_closed_callback = functionfs_closed_callback; + } missing_funcs = func_num; - return functionfs_init(); + return 0; +no_dev: + ffs_dev_lock(); + while (i >= 0) + ffs_free_dev(ffs_tab[i--]); + ffs_dev_unlock(); + kfree(ffs_tab); + return ret; } module_init(gfs_init); static void __exit gfs_exit(void) { + int i; + ENTER(); - mutex_lock(&gfs_lock); + ffs_dev_lock(); if (gfs_registered) usb_composite_unregister(&gfs_driver); gfs_registered = false; - functionfs_cleanup(); - - mutex_unlock(&gfs_lock); + for (i = 0; i < func_num; i++) + ffs_free_dev(ffs_tab[i]); + ffs_dev_unlock(); kfree(ffs_tab); } module_exit(gfs_exit); -static struct ffs_dev *gfs_find_dev(const char *dev_name) -{ - int i; - - ENTER(); - - if (gfs_single_func) - return &ffs_tab[0]; - - for (i = 0; i < func_num; i++) - if (strcmp(ffs_tab[i].name, dev_name) == 0) - return &ffs_tab[i]; - - return NULL; -} - +/* + * The caller of this function takes ffs_lock + */ static int functionfs_ready_callback(struct ffs_data *ffs) { - struct ffs_dev *ffs_obj; - int ret; - - ENTER(); - mutex_lock(&gfs_lock); + int ret = 0; - ffs_obj = ffs->private_data; - if (!ffs_obj) { - ret = -EINVAL; - goto done; - } - - if (WARN_ON(ffs_obj->desc_ready)) { - ret = -EBUSY; - goto done; - } - ffs_obj->desc_ready = true; - ffs_obj->ffs_data = ffs; + if (--missing_funcs) + return 0; - if (--missing_funcs) { - ret = 0; - goto done; - } + if (gfs_registered) + return -EBUSY; - if (gfs_registered) { - ret = -EBUSY; - goto done; - } gfs_registered = true; ret = usb_composite_probe(&gfs_driver); if (unlikely(ret < 0)) gfs_registered = false; - -done: - mutex_unlock(&gfs_lock); + return ret; } +/* + * The caller of this function takes ffs_lock + */ static void functionfs_closed_callback(struct ffs_data *ffs) { - struct ffs_dev *ffs_obj; - - ENTER(); - mutex_lock(&gfs_lock); - - ffs_obj = ffs->private_data; - if (!ffs_obj) - goto done; - - ffs_obj->desc_ready = false; missing_funcs++; if (gfs_registered) usb_composite_unregister(&gfs_driver); gfs_registered = false; - -done: - mutex_unlock(&gfs_lock); -} - -static void *functionfs_acquire_dev_callback(const char *dev_name) -{ - struct ffs_dev *ffs_dev; - - ENTER(); - mutex_lock(&gfs_lock); - - ffs_dev = gfs_find_dev(dev_name); - if (!ffs_dev) { - ffs_dev = ERR_PTR(-ENODEV); - goto done; - } - - if (ffs_dev->mounted) { - ffs_dev = ERR_PTR(-EBUSY); - goto done; - } - ffs_dev->mounted = true; - -done: - mutex_unlock(&gfs_lock); - return ffs_dev; -} - -static void functionfs_release_dev_callback(struct ffs_data *ffs_data) -{ - struct ffs_dev *ffs_dev; - - ENTER(); - mutex_lock(&gfs_lock); - - ffs_dev = ffs_data->private_data; - if (ffs_dev) - ffs_dev->mounted = false; - - mutex_unlock(&gfs_lock); } /* - * It is assumed that gfs_bind is called from a context where gfs_lock is held + * It is assumed that gfs_bind is called from a context where ffs_lock is held */ static int gfs_bind(struct usb_composite_dev *cdev) { @@ -422,10 +365,10 @@ static int gfs_bind(struct usb_composite_dev *cdev) gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; for (i = func_num; i--; ) { - ret = functionfs_bind(ffs_tab[i].ffs_data, cdev); + ret = functionfs_bind(ffs_tab[i]->ffs_data, cdev); if (unlikely(ret < 0)) { while (++i < func_num) - functionfs_unbind(ffs_tab[i].ffs_data); + functionfs_unbind(ffs_tab[i]->ffs_data); goto error_rndis; } } @@ -448,7 +391,7 @@ static int gfs_bind(struct usb_composite_dev *cdev) error_unbind: for (i = 0; i < func_num; i++) - functionfs_unbind(ffs_tab[i].ffs_data); + functionfs_unbind(ffs_tab[i]->ffs_data); error_rndis: #ifdef CONFIG_USB_FUNCTIONFS_RNDIS usb_put_function_instance(fi_rndis); @@ -464,7 +407,7 @@ error: } /* - * It is assumed that gfs_unbind is called from a context where gfs_lock is held + * It is assumed that gfs_unbind is called from a context where ffs_lock is held */ static int gfs_unbind(struct usb_composite_dev *cdev) { @@ -497,15 +440,15 @@ static int gfs_unbind(struct usb_composite_dev *cdev) * do...? */ for (i = func_num; i--; ) - if (ffs_tab[i].ffs_data) - functionfs_unbind(ffs_tab[i].ffs_data); + if (ffs_tab[i]->ffs_data) + functionfs_unbind(ffs_tab[i]->ffs_data); return 0; } /* * It is assumed that gfs_do_config is called from a context where - * gfs_lock is held + * ffs_lock is held */ static int gfs_do_config(struct usb_configuration *c) { @@ -529,7 +472,7 @@ static int gfs_do_config(struct usb_configuration *c) } for (i = 0; i < func_num; i++) { - ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data); + ret = functionfs_bind_config(c->cdev, c, ffs_tab[i]->ffs_data); if (unlikely(ret < 0)) return ret; } diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h index 5d9229a01560..2d00f9d296a3 100644 --- a/drivers/usb/gadget/u_fs.h +++ b/drivers/usb/gadget/u_fs.h @@ -17,12 +17,36 @@ #define U_FFS_H #include +#include +#include struct ffs_dev { const char *name; bool mounted; bool desc_ready; + bool single; struct ffs_data *ffs_data; + struct list_head entry; + + int (*ffs_ready_callback)(struct ffs_data *ffs); + void (*ffs_closed_callback)(struct ffs_data *ffs); }; +extern struct mutex ffs_lock; + +static inline void ffs_dev_lock(void) +{ + mutex_lock(&ffs_lock); +} + +static inline void ffs_dev_unlock(void) +{ + mutex_unlock(&ffs_lock); +} + +struct ffs_dev *ffs_alloc_dev(void); +int ffs_name_dev(struct ffs_dev *dev, const char *name); +int ffs_single_dev(struct ffs_dev *dev); +void ffs_free_dev(struct ffs_dev *dev); + #endif /* U_FFS_H */ diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h index 65d0a88dbc67..9c1e92620dfb 100644 --- a/include/linux/usb/functionfs.h +++ b/include/linux/usb/functionfs.h @@ -8,10 +8,6 @@ struct ffs_data; struct usb_composite_dev; struct usb_configuration; - -static int functionfs_init(void) __attribute__((warn_unused_result)); -static void functionfs_cleanup(void); - static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) __attribute__((warn_unused_result, nonnull)); static void functionfs_unbind(struct ffs_data *ffs) @@ -23,14 +19,4 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, __attribute__((warn_unused_result, nonnull)); -static int functionfs_ready_callback(struct ffs_data *ffs) - __attribute__((warn_unused_result, nonnull)); -static void functionfs_closed_callback(struct ffs_data *ffs) - __attribute__((nonnull)); -static void *functionfs_acquire_dev_callback(const char *dev_name) - __attribute__((warn_unused_result, nonnull)); -static void functionfs_release_dev_callback(struct ffs_data *ffs_data) - __attribute__((nonnull)); - - #endif -- cgit v1.2.3 From 5920cda627688c3229fd63157ff031f3f174175e Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:33 +0100 Subject: usb: gadget: FunctionFS: convert to new function interface with backward compatibility This is required in order to integrate configfs support. f_fs needs to be a separately compiled module and so it needs to use the new interface. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 3 + drivers/usb/gadget/Makefile | 2 + drivers/usb/gadget/f_fs.c | 422 +++++++++++++++++++++-------------------- drivers/usb/gadget/g_ffs.c | 1 + drivers/usb/gadget/u_fs.h | 214 +++++++++++++++++++++ include/linux/usb/functionfs.h | 2 + 6 files changed, 435 insertions(+), 209 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index aa3610ea9d9f..1761a3b8b31a 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -539,6 +539,9 @@ config USB_F_RNDIS config USB_F_MASS_STORAGE tristate +config USB_F_FS + tristate + choice tristate "USB Gadget Drivers" default USB_ETH diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 0c40277931f4..6cccdfed140c 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -61,6 +61,8 @@ usb_f_rndis-y := f_rndis.o rndis.o obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o usb_f_mass_storage-y := f_mass_storage.o storage_common.o obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o +usb_f_fs-y := f_fs.o +obj-$(CONFIG_USB_F_FS) += usb_f_fs.o # # USB gadget drivers diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index d17930d9a843..8d318eaaaf20 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -57,210 +58,6 @@ #define vla_ptr(ptr, groupname, name) \ ((void *) ((char *)ptr + groupname##_##name##__offset)) -/* Debugging ****************************************************************/ - -#ifdef VERBOSE_DEBUG -#ifndef pr_vdebug -# define pr_vdebug pr_debug -#endif /* pr_vdebug */ -# define ffs_dump_mem(prefix, ptr, len) \ - print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) -#else -#ifndef pr_vdebug -# define pr_vdebug(...) do { } while (0) -#endif /* pr_vdebug */ -# define ffs_dump_mem(prefix, ptr, len) do { } while (0) -#endif /* VERBOSE_DEBUG */ - -#define ENTER() pr_vdebug("%s()\n", __func__) - - -/* The data structure and setup file ****************************************/ - -enum ffs_state { - /* - * Waiting for descriptors and strings. - * - * In this state no open(2), read(2) or write(2) on epfiles - * may succeed (which should not be the problem as there - * should be no such files opened in the first place). - */ - FFS_READ_DESCRIPTORS, - FFS_READ_STRINGS, - - /* - * We've got descriptors and strings. We are or have called - * ffs_ready(). functionfs_bind() may have - * been called but we don't know. - * - * This is the only state in which operations on epfiles may - * succeed. - */ - FFS_ACTIVE, - - /* - * All endpoints have been closed. This state is also set if - * we encounter an unrecoverable error. The only - * unrecoverable error is situation when after reading strings - * from user space we fail to initialise epfiles or - * ffs_ready() returns with error (<0). - * - * In this state no open(2), read(2) or write(2) (both on ep0 - * as well as epfile) may succeed (at this point epfiles are - * unlinked and all closed so this is not a problem; ep0 is - * also closed but ep0 file exists and so open(2) on ep0 must - * fail). - */ - FFS_CLOSING -}; - - -enum ffs_setup_state { - /* There is no setup request pending. */ - FFS_NO_SETUP, - /* - * User has read events and there was a setup request event - * there. The next read/write on ep0 will handle the - * request. - */ - FFS_SETUP_PENDING, - /* - * There was event pending but before user space handled it - * some other event was introduced which canceled existing - * setup. If this state is set read/write on ep0 return - * -EIDRM. This state is only set when adding event. - */ - FFS_SETUP_CANCELED -}; - - - -struct ffs_epfile; -struct ffs_function; - -struct ffs_data { - struct usb_gadget *gadget; - - /* - * Protect access read/write operations, only one read/write - * at a time. As a consequence protects ep0req and company. - * While setup request is being processed (queued) this is - * held. - */ - struct mutex mutex; - - /* - * Protect access to endpoint related structures (basically - * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for - * endpoint zero. - */ - spinlock_t eps_lock; - - /* - * XXX REVISIT do we need our own request? Since we are not - * handling setup requests immediately user space may be so - * slow that another setup will be sent to the gadget but this - * time not to us but another function and then there could be - * a race. Is that the case? Or maybe we can use cdev->req - * after all, maybe we just need some spinlock for that? - */ - struct usb_request *ep0req; /* P: mutex */ - struct completion ep0req_completion; /* P: mutex */ - int ep0req_status; /* P: mutex */ - - /* reference counter */ - atomic_t ref; - /* how many files are opened (EP0 and others) */ - atomic_t opened; - - /* EP0 state */ - enum ffs_state state; - - /* - * Possible transitions: - * + FFS_NO_SETUP -> FFS_SETUP_PENDING -- P: ev.waitq.lock - * happens only in ep0 read which is P: mutex - * + FFS_SETUP_PENDING -> FFS_NO_SETUP -- P: ev.waitq.lock - * happens only in ep0 i/o which is P: mutex - * + FFS_SETUP_PENDING -> FFS_SETUP_CANCELED -- P: ev.waitq.lock - * + FFS_SETUP_CANCELED -> FFS_NO_SETUP -- cmpxchg - */ - enum ffs_setup_state setup_state; - -#define FFS_SETUP_STATE(ffs) \ - ((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state, \ - FFS_SETUP_CANCELED, FFS_NO_SETUP)) - - /* Events & such. */ - struct { - u8 types[4]; - unsigned short count; - /* XXX REVISIT need to update it in some places, or do we? */ - unsigned short can_stall; - struct usb_ctrlrequest setup; - - wait_queue_head_t waitq; - } ev; /* the whole structure, P: ev.waitq.lock */ - - /* Flags */ - unsigned long flags; -#define FFS_FL_CALL_CLOSED_CALLBACK 0 -#define FFS_FL_BOUND 1 - - /* Active function */ - struct ffs_function *func; - - /* - * Device name, write once when file system is mounted. - * Intended for user to read if she wants. - */ - const char *dev_name; - /* Private data for our user (ie. gadget). Managed by user. */ - void *private_data; - - /* filled by __ffs_data_got_descs() */ - /* - * Real descriptors are 16 bytes after raw_descs (so you need - * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the - * first full speed descriptor). raw_descs_length and - * raw_fs_descs_length do not have those 16 bytes added. - */ - const void *raw_descs; - unsigned raw_descs_length; - unsigned raw_fs_descs_length; - unsigned fs_descs_count; - unsigned hs_descs_count; - - unsigned short strings_count; - unsigned short interfaces_count; - unsigned short eps_count; - unsigned short _pad1; - - /* filled by __ffs_data_got_strings() */ - /* ids in stringtabs are set in functionfs_bind() */ - const void *raw_strings; - struct usb_gadget_strings **stringtabs; - - /* - * File system's super block, write once when file system is - * mounted. - */ - struct super_block *sb; - - /* File permissions, written once when fs is mounted */ - struct ffs_file_perms { - umode_t mode; - kuid_t uid; - kgid_t gid; - } file_perms; - - /* - * The endpoint files, filled by ffs_epfiles_create(), - * destroyed by ffs_epfiles_destroy(). - */ - struct ffs_epfile *epfiles; -}; - /* Reference counter handling */ static void ffs_data_get(struct ffs_data *ffs); static void ffs_data_put(struct ffs_data *ffs); @@ -300,15 +97,19 @@ static struct ffs_function *ffs_func_from_usb(struct usb_function *f) return container_of(f, struct ffs_function, function); } +#ifdef USB_FFS_INCLUDED static void ffs_func_free(struct ffs_function *func); +#endif static void ffs_func_eps_disable(struct ffs_function *func); static int __must_check ffs_func_eps_enable(struct ffs_function *func); static int ffs_func_bind(struct usb_configuration *, struct usb_function *); -static void ffs_func_unbind(struct usb_configuration *, +#ifdef USB_FFS_INCLUDED +static void old_ffs_func_unbind(struct usb_configuration *, struct usb_function *); +#endif static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned); static void ffs_func_disable(struct usb_function *); static int ffs_func_setup(struct usb_function *, @@ -364,6 +165,9 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data, /* Devices management *******************************************************/ DEFINE_MUTEX(ffs_lock); +#ifndef USB_FFS_INCLUDED +EXPORT_SYMBOL(ffs_lock); +#endif static struct ffs_dev *ffs_find_dev(const char *name); static void *ffs_acquire_dev(const char *dev_name); @@ -1499,6 +1303,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) kfree(epfiles); } +#ifdef USB_FFS_INCLUDED + static int functionfs_bind_config(struct usb_composite_dev *cdev, struct usb_configuration *c, struct ffs_data *ffs) @@ -1516,7 +1322,7 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, func->function.strings = ffs->stringtabs; func->function.bind = ffs_func_bind; - func->function.unbind = ffs_func_unbind; + func->function.unbind = old_ffs_func_unbind; func->function.set_alt = ffs_func_set_alt; func->function.disable = ffs_func_disable; func->function.setup = ffs_func_setup; @@ -1565,6 +1371,8 @@ static void ffs_func_free(struct ffs_function *func) kfree(func); } +#endif + static void ffs_func_eps_disable(struct ffs_function *func) { struct ffs_ep *ep = func->eps; @@ -2227,8 +2035,59 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep, return 0; } -static int ffs_func_bind(struct usb_configuration *c, - struct usb_function *f) +#ifndef USB_FFS_INCLUDED +static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, + struct usb_configuration *c) +{ + struct ffs_function *func = ffs_func_from_usb(f); + struct f_fs_opts *ffs_opts = + container_of(f->fi, struct f_fs_opts, func_inst); + int ret; + + ENTER(); + + /* + * Legacy gadget triggers binding in functionfs_ready_callback, + * which already uses locking; taking the same lock here would + * cause a deadlock. + * + * Configfs-enabled gadgets however do need ffs_dev_lock. + */ + if (!ffs_opts->no_configfs) + ffs_dev_lock(); + ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV; + func->ffs = ffs_opts->dev->ffs_data; + if (!ffs_opts->no_configfs) + ffs_dev_unlock(); + if (ret) + return ERR_PTR(ret); + + func->conf = c; + func->gadget = c->cdev->gadget; + + ffs_data_get(func->ffs); + + /* + * in drivers/usb/gadget/configfs.c:configfs_composite_bind() + * configurations are bound in sequence with list_for_each_entry, + * in each configuration its functions are bound in sequence + * with list_for_each_entry, so we assume no race condition + * with regard to ffs_opts->bound access + */ + if (!ffs_opts->refcnt) { + ret = functionfs_bind(func->ffs, c->cdev); + if (ret) + return ERR_PTR(ret); + } + ffs_opts->refcnt++; + func->function.strings = func->ffs->stringtabs; + + return ffs_opts; +} +#endif + +static int _ffs_func_bind(struct usb_configuration *c, + struct usb_function *f) { struct ffs_function *func = ffs_func_from_usb(f); struct ffs_data *ffs = func->ffs; @@ -2328,10 +2187,25 @@ error: return ret; } +static int ffs_func_bind(struct usb_configuration *c, + struct usb_function *f) +{ +#ifndef USB_FFS_INCLUDED + struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c); + + if (IS_ERR(ffs_opts)) + return PTR_ERR(ffs_opts); +#endif + + return _ffs_func_bind(c, f); +} + /* Other USB function hooks *************************************************/ -static void ffs_func_unbind(struct usb_configuration *c, +#ifdef USB_FFS_INCLUDED + +static void old_ffs_func_unbind(struct usb_configuration *c, struct usb_function *f) { struct ffs_function *func = ffs_func_from_usb(f); @@ -2349,6 +2223,8 @@ static void ffs_func_unbind(struct usb_configuration *c, ffs_func_free(func); } +#endif + static int ffs_func_set_alt(struct usb_function *f, unsigned interface, unsigned alt) { @@ -2523,6 +2399,116 @@ static struct ffs_dev *ffs_find_dev(const char *name) return _ffs_find_dev(name); } +/* Function registration interface ******************************************/ + +#ifndef USB_FFS_INCLUDED + +static void ffs_free_inst(struct usb_function_instance *f) +{ + struct f_fs_opts *opts; + + opts = to_f_fs_opts(f); + ffs_dev_lock(); + ffs_free_dev(opts->dev); + ffs_dev_unlock(); + kfree(opts); +} + +static struct usb_function_instance *ffs_alloc_inst(void) +{ + struct f_fs_opts *opts; + struct ffs_dev *dev; + + opts = kzalloc(sizeof(*opts), GFP_KERNEL); + if (!opts) + return ERR_PTR(-ENOMEM); + + opts->func_inst.free_func_inst = ffs_free_inst; + ffs_dev_lock(); + dev = ffs_alloc_dev(); + ffs_dev_unlock(); + if (IS_ERR(dev)) { + kfree(opts); + return ERR_CAST(dev); + } + opts->dev = dev; + + return &opts->func_inst; +} + +static void ffs_free(struct usb_function *f) +{ + kfree(ffs_func_from_usb(f)); +} + +static void ffs_func_unbind(struct usb_configuration *c, + struct usb_function *f) +{ + struct ffs_function *func = ffs_func_from_usb(f); + struct ffs_data *ffs = func->ffs; + struct f_fs_opts *opts = + container_of(f->fi, struct f_fs_opts, func_inst); + struct ffs_ep *ep = func->eps; + unsigned count = ffs->eps_count; + unsigned long flags; + + ENTER(); + if (ffs->func == func) { + ffs_func_eps_disable(func); + ffs->func = NULL; + } + + if (!--opts->refcnt) + functionfs_unbind(ffs); + + /* cleanup after autoconfig */ + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + if (ep->ep && ep->req) + usb_ep_free_request(ep->ep, ep->req); + ep->req = NULL; + ++ep; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + kfree(func->eps); + func->eps = NULL; + /* + * eps, descriptors and interfaces_nums are allocated in the + * same chunk so only one free is required. + */ + func->function.fs_descriptors = NULL; + func->function.hs_descriptors = NULL; + func->interfaces_nums = NULL; + + ffs_event_add(ffs, FUNCTIONFS_UNBIND); +} + +static struct usb_function *ffs_alloc(struct usb_function_instance *fi) +{ + struct ffs_function *func; + + ENTER(); + + func = kzalloc(sizeof(*func), GFP_KERNEL); + if (unlikely(!func)) + return ERR_PTR(-ENOMEM); + + func->function.name = "Function FS Gadget"; + + func->function.bind = ffs_func_bind; + func->function.unbind = ffs_func_unbind; + func->function.set_alt = ffs_func_set_alt; + func->function.disable = ffs_func_disable; + func->function.setup = ffs_func_setup; + func->function.suspend = ffs_func_suspend; + func->function.resume = ffs_func_resume; + func->function.free_func = ffs_free; + + return &func->function; +} + +#endif + /* * ffs_lock must be taken by the caller of this function */ @@ -2581,6 +2567,9 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name) return ret; } +#ifndef USB_FFS_INCLUDED +EXPORT_SYMBOL(ffs_name_dev); +#endif int ffs_single_dev(struct ffs_dev *dev) { @@ -2597,6 +2586,9 @@ int ffs_single_dev(struct ffs_dev *dev) ffs_dev_unlock(); return ret; } +#ifndef USB_FFS_INCLUDED +EXPORT_SYMBOL(ffs_single_dev); +#endif /* * ffs_lock must be taken by the caller of this function @@ -2621,6 +2613,9 @@ static void *ffs_acquire_dev(const char *dev_name) ffs_dev = ERR_PTR(-ENODEV); else if (ffs_dev->mounted) ffs_dev = ERR_PTR(-EBUSY); + else if (ffs_dev->ffs_acquire_dev_callback && + ffs_dev->ffs_acquire_dev_callback(ffs_dev)) + ffs_dev = ERR_PTR(-ENODEV); else ffs_dev->mounted = true; @@ -2638,6 +2633,9 @@ static void ffs_release_dev(struct ffs_data *ffs_data) ffs_dev = ffs_data->private_data; if (ffs_dev) ffs_dev->mounted = false; + + if (ffs_dev->ffs_release_dev_callback) + ffs_dev->ffs_release_dev_callback(ffs_dev); ffs_dev_unlock(); } @@ -2720,3 +2718,9 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len) return data; } + +#ifndef USB_FFS_INCLUDED +DECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Michal Nazarewicz"); +#endif diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 074df0d56255..ffde36f2c672 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -54,6 +54,7 @@ static struct usb_function *f_rndis; # endif #endif +#define USB_FFS_INCLUDED #include "f_fs.c" #define DRIVER_NAME "g_ffs" diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h index 2d00f9d296a3..d60a9ddc0332 100644 --- a/drivers/usb/gadget/u_fs.h +++ b/drivers/usb/gadget/u_fs.h @@ -20,6 +20,22 @@ #include #include +#ifdef VERBOSE_DEBUG +#ifndef pr_vdebug +# define pr_vdebug pr_debug +#endif /* pr_vdebug */ +# define ffs_dump_mem(prefix, ptr, len) \ + print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) +#else +#ifndef pr_vdebug +# define pr_vdebug(...) do { } while (0) +#endif /* pr_vdebug */ +# define ffs_dump_mem(prefix, ptr, len) do { } while (0) +#endif /* VERBOSE_DEBUG */ + +#define ENTER() pr_vdebug("%s()\n", __func__) + + struct ffs_dev { const char *name; bool mounted; @@ -30,6 +46,8 @@ struct ffs_dev { int (*ffs_ready_callback)(struct ffs_data *ffs); void (*ffs_closed_callback)(struct ffs_data *ffs); + void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev); + void (*ffs_release_dev_callback)(struct ffs_dev *dev); }; extern struct mutex ffs_lock; @@ -49,4 +67,200 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name); int ffs_single_dev(struct ffs_dev *dev); void ffs_free_dev(struct ffs_dev *dev); +struct ffs_epfile; +struct ffs_function; + +enum ffs_state { + /* + * Waiting for descriptors and strings. + * + * In this state no open(2), read(2) or write(2) on epfiles + * may succeed (which should not be the problem as there + * should be no such files opened in the first place). + */ + FFS_READ_DESCRIPTORS, + FFS_READ_STRINGS, + + /* + * We've got descriptors and strings. We are or have called + * functionfs_ready_callback(). functionfs_bind() may have + * been called but we don't know. + * + * This is the only state in which operations on epfiles may + * succeed. + */ + FFS_ACTIVE, + + /* + * All endpoints have been closed. This state is also set if + * we encounter an unrecoverable error. The only + * unrecoverable error is situation when after reading strings + * from user space we fail to initialise epfiles or + * functionfs_ready_callback() returns with error (<0). + * + * In this state no open(2), read(2) or write(2) (both on ep0 + * as well as epfile) may succeed (at this point epfiles are + * unlinked and all closed so this is not a problem; ep0 is + * also closed but ep0 file exists and so open(2) on ep0 must + * fail). + */ + FFS_CLOSING +}; + +enum ffs_setup_state { + /* There is no setup request pending. */ + FFS_NO_SETUP, + /* + * User has read events and there was a setup request event + * there. The next read/write on ep0 will handle the + * request. + */ + FFS_SETUP_PENDING, + /* + * There was event pending but before user space handled it + * some other event was introduced which canceled existing + * setup. If this state is set read/write on ep0 return + * -EIDRM. This state is only set when adding event. + */ + FFS_SETUP_CANCELED +}; + +struct ffs_data { + struct usb_gadget *gadget; + + /* + * Protect access read/write operations, only one read/write + * at a time. As a consequence protects ep0req and company. + * While setup request is being processed (queued) this is + * held. + */ + struct mutex mutex; + + /* + * Protect access to endpoint related structures (basically + * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for + * endpoint zero. + */ + spinlock_t eps_lock; + + /* + * XXX REVISIT do we need our own request? Since we are not + * handling setup requests immediately user space may be so + * slow that another setup will be sent to the gadget but this + * time not to us but another function and then there could be + * a race. Is that the case? Or maybe we can use cdev->req + * after all, maybe we just need some spinlock for that? + */ + struct usb_request *ep0req; /* P: mutex */ + struct completion ep0req_completion; /* P: mutex */ + int ep0req_status; /* P: mutex */ + + /* reference counter */ + atomic_t ref; + /* how many files are opened (EP0 and others) */ + atomic_t opened; + + /* EP0 state */ + enum ffs_state state; + + /* + * Possible transitions: + * + FFS_NO_SETUP -> FFS_SETUP_PENDING -- P: ev.waitq.lock + * happens only in ep0 read which is P: mutex + * + FFS_SETUP_PENDING -> FFS_NO_SETUP -- P: ev.waitq.lock + * happens only in ep0 i/o which is P: mutex + * + FFS_SETUP_PENDING -> FFS_SETUP_CANCELED -- P: ev.waitq.lock + * + FFS_SETUP_CANCELED -> FFS_NO_SETUP -- cmpxchg + */ + enum ffs_setup_state setup_state; + +#define FFS_SETUP_STATE(ffs) \ + ((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state, \ + FFS_SETUP_CANCELED, FFS_NO_SETUP)) + + /* Events & such. */ + struct { + u8 types[4]; + unsigned short count; + /* XXX REVISIT need to update it in some places, or do we? */ + unsigned short can_stall; + struct usb_ctrlrequest setup; + + wait_queue_head_t waitq; + } ev; /* the whole structure, P: ev.waitq.lock */ + + /* Flags */ + unsigned long flags; +#define FFS_FL_CALL_CLOSED_CALLBACK 0 +#define FFS_FL_BOUND 1 + + /* Active function */ + struct ffs_function *func; + + /* + * Device name, write once when file system is mounted. + * Intended for user to read if she wants. + */ + const char *dev_name; + /* Private data for our user (ie. gadget). Managed by user. */ + void *private_data; + + /* filled by __ffs_data_got_descs() */ + /* + * Real descriptors are 16 bytes after raw_descs (so you need + * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the + * first full speed descriptor). raw_descs_length and + * raw_fs_descs_length do not have those 16 bytes added. + */ + const void *raw_descs; + unsigned raw_descs_length; + unsigned raw_fs_descs_length; + unsigned fs_descs_count; + unsigned hs_descs_count; + + unsigned short strings_count; + unsigned short interfaces_count; + unsigned short eps_count; + unsigned short _pad1; + + /* filled by __ffs_data_got_strings() */ + /* ids in stringtabs are set in functionfs_bind() */ + const void *raw_strings; + struct usb_gadget_strings **stringtabs; + + /* + * File system's super block, write once when file system is + * mounted. + */ + struct super_block *sb; + + /* File permissions, written once when fs is mounted */ + struct ffs_file_perms { + umode_t mode; + kuid_t uid; + kgid_t gid; + } file_perms; + + /* + * The endpoint files, filled by ffs_epfiles_create(), + * destroyed by ffs_epfiles_destroy(). + */ + struct ffs_epfile *epfiles; +}; + + +#ifndef USB_FFS_INCLUDED +struct f_fs_opts { + struct usb_function_instance func_inst; + struct ffs_dev *dev; + unsigned refcnt; + bool no_configfs; +}; + +static inline struct f_fs_opts *to_f_fs_opts(struct usb_function_instance *fi) +{ + return container_of(fi, struct f_fs_opts, func_inst); +} +#endif + #endif /* U_FFS_H */ diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h index 9c1e92620dfb..3448efbe56aa 100644 --- a/include/linux/usb/functionfs.h +++ b/include/linux/usb/functionfs.h @@ -3,6 +3,7 @@ #include +#ifdef USB_FFS_INCLUDED struct ffs_data; struct usb_composite_dev; @@ -20,3 +21,4 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, #endif +#endif -- cgit v1.2.3 From 6f823cd5305c78ad1282fab8634b369eac4620b1 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:34 +0100 Subject: usb: gadget: g_ffs: convert to new interface of f_fs Prepare for configfs integration. Use the new interface so that f_fs can be made a module. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/g_ffs.c | 151 ++++++++++++++++++++++++++++----------------- 2 files changed, 96 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1761a3b8b31a..97eb540ddef2 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -874,6 +874,7 @@ config USB_GADGETFS config USB_FUNCTIONFS tristate "Function Filesystem" select USB_LIBCOMPOSITE + select USB_F_FS select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) help The Function Filesystem (FunctionFS) lets one create USB diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index ffde36f2c672..fe12e6a27448 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -13,13 +13,7 @@ #define pr_fmt(fmt) "g_ffs: " fmt #include -/* - * kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ + #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS #include @@ -54,8 +48,7 @@ static struct usb_function *f_rndis; # endif #endif -#define USB_FFS_INCLUDED -#include "f_fs.c" +#include "u_fs.h" #define DRIVER_NAME "g_ffs" #define DRIVER_DESC "USB Function Filesystem" @@ -139,6 +132,7 @@ static struct usb_gadget_strings *gfs_dev_strings[] = { struct gfs_configuration { struct usb_configuration c; int (*eth)(struct usb_configuration *c); + int num; } gfs_configurations[] = { #ifdef CONFIG_USB_FUNCTIONFS_RNDIS { @@ -158,12 +152,15 @@ struct gfs_configuration { #endif }; +static void *functionfs_acquire_dev(struct ffs_dev *dev); +static void functionfs_release_dev(struct ffs_dev *dev); static int functionfs_ready_callback(struct ffs_data *ffs); static void functionfs_closed_callback(struct ffs_data *ffs); static int gfs_bind(struct usb_composite_dev *cdev); static int gfs_unbind(struct usb_composite_dev *cdev); static int gfs_do_config(struct usb_configuration *c); + static __refdata struct usb_composite_driver gfs_driver = { .name = DRIVER_NAME, .dev = &gfs_dev_desc, @@ -176,10 +173,26 @@ static __refdata struct usb_composite_driver gfs_driver = { static unsigned int missing_funcs; static bool gfs_registered; static bool gfs_single_func; -static struct ffs_dev **ffs_tab; +static struct usb_function_instance **fi_ffs; +static struct usb_function **f_ffs[] = { +#ifdef CONFIG_USB_FUNCTIONFS_RNDIS + NULL, +#endif + +#ifdef CONFIG_USB_FUNCTIONFS_ETH + NULL, +#endif + +#ifdef CONFIG_USB_FUNCTIONFS_GENERIC + NULL, +#endif +}; + +#define N_CONF ARRAY_SIZE(f_ffs) static int __init gfs_init(void) { + struct f_fs_opts *opts; int i; int ret = 0; @@ -190,38 +203,53 @@ static int __init gfs_init(void) func_num = 1; } - ffs_tab = kcalloc(func_num, sizeof(*ffs_tab), GFP_KERNEL); - if (!ffs_tab) - return -ENOMEM; + /* + * Allocate in one chunk for easier maintenance + */ + f_ffs[0] = kcalloc(func_num * N_CONF, sizeof(*f_ffs), GFP_KERNEL); + if (!f_ffs[0]) { + ret = -ENOMEM; + goto no_func; + } + for (i = 1; i < N_CONF; ++i) + f_ffs[i] = f_ffs[0] + i * func_num; + + fi_ffs = kcalloc(func_num, sizeof(*fi_ffs), GFP_KERNEL); + if (!fi_ffs) { + ret = -ENOMEM; + goto no_func; + } for (i = 0; i < func_num; i++) { - ffs_dev_lock(); - ffs_tab[i] = ffs_alloc_dev(); - ffs_dev_unlock(); - if (IS_ERR(ffs_tab[i])) { - ret = PTR_ERR(ffs_tab[i]); + fi_ffs[i] = usb_get_function_instance("ffs"); + if (IS_ERR(fi_ffs[i])) { + ret = PTR_ERR(fi_ffs[i]); --i; goto no_dev; } + opts = to_f_fs_opts(fi_ffs[i]); if (gfs_single_func) - ret = ffs_single_dev(ffs_tab[i]); + ret = ffs_single_dev(opts->dev); else - ret = ffs_name_dev(ffs_tab[i], func_names[i]); + ret = ffs_name_dev(opts->dev, func_names[i]); if (ret) goto no_dev; - ffs_tab[i]->ffs_ready_callback = functionfs_ready_callback; - ffs_tab[i]->ffs_closed_callback = functionfs_closed_callback; + opts->dev->ffs_ready_callback = functionfs_ready_callback; + opts->dev->ffs_closed_callback = functionfs_closed_callback; + opts->dev->ffs_acquire_dev_callback = functionfs_acquire_dev; + opts->dev->ffs_release_dev_callback = functionfs_release_dev; + opts->no_configfs = true; } missing_funcs = func_num; return 0; no_dev: - ffs_dev_lock(); while (i >= 0) - ffs_free_dev(ffs_tab[i--]); - ffs_dev_unlock(); - kfree(ffs_tab); + usb_put_function_instance(fi_ffs[i--]); + kfree(fi_ffs); +no_func: + kfree(f_ffs[0]); return ret; } module_init(gfs_init); @@ -231,19 +259,33 @@ static void __exit gfs_exit(void) int i; ENTER(); - ffs_dev_lock(); if (gfs_registered) usb_composite_unregister(&gfs_driver); gfs_registered = false; + kfree(f_ffs[0]); + for (i = 0; i < func_num; i++) - ffs_free_dev(ffs_tab[i]); - ffs_dev_unlock(); - kfree(ffs_tab); + usb_put_function_instance(fi_ffs[i]); + + kfree(fi_ffs); } module_exit(gfs_exit); +static void *functionfs_acquire_dev(struct ffs_dev *dev) +{ + if (!try_module_get(THIS_MODULE)) + return ERR_PTR(-ENODEV); + + return 0; +} + +static void functionfs_release_dev(struct ffs_dev *dev) +{ + module_put(THIS_MODULE); +} + /* * The caller of this function takes ffs_lock */ @@ -360,20 +402,12 @@ static int gfs_bind(struct usb_composite_dev *cdev) rndis_borrow_net(fi_rndis, net); #endif + /* TODO: gstrings_attach? */ ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) goto error_rndis; gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; - for (i = func_num; i--; ) { - ret = functionfs_bind(ffs_tab[i]->ffs_data, cdev); - if (unlikely(ret < 0)) { - while (++i < func_num) - functionfs_unbind(ffs_tab[i]->ffs_data); - goto error_rndis; - } - } - for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { struct gfs_configuration *c = gfs_configurations + i; int sid = USB_GADGET_FIRST_AVAIL_IDX + i; @@ -383,6 +417,8 @@ static int gfs_bind(struct usb_composite_dev *cdev) c->c.bConfigurationValue = 1 + i; c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; + c->num = i; + ret = usb_add_config(cdev, &c->c, gfs_do_config); if (unlikely(ret < 0)) goto error_unbind; @@ -390,9 +426,8 @@ static int gfs_bind(struct usb_composite_dev *cdev) usb_composite_overwrite_options(cdev, &coverwrite); return 0; +/* TODO */ error_unbind: - for (i = 0; i < func_num; i++) - functionfs_unbind(ffs_tab[i]->ffs_data); error_rndis: #ifdef CONFIG_USB_FUNCTIONFS_RNDIS usb_put_function_instance(fi_rndis); @@ -431,18 +466,8 @@ static int gfs_unbind(struct usb_composite_dev *cdev) usb_put_function_instance(fi_geth); } #endif - - /* - * We may have been called in an error recovery from - * composite_bind() after gfs_unbind() failure so we need to - * check if instance's ffs_data is not NULL since gfs_bind() handles - * all error recovery itself. I'd rather we werent called - * from composite on orror recovery, but what you're gonna - * do...? - */ - for (i = func_num; i--; ) - if (ffs_tab[i]->ffs_data) - functionfs_unbind(ffs_tab[i]->ffs_data); + for (i = 0; i < N_CONF * func_num; ++i) + usb_put_function(*(f_ffs[0] + i)); return 0; } @@ -473,9 +498,16 @@ static int gfs_do_config(struct usb_configuration *c) } for (i = 0; i < func_num; i++) { - ret = functionfs_bind_config(c->cdev, c, ffs_tab[i]->ffs_data); - if (unlikely(ret < 0)) - return ret; + f_ffs[gc->num][i] = usb_get_function(fi_ffs[i]); + if (IS_ERR(f_ffs[gc->num][i])) { + ret = PTR_ERR(f_ffs[gc->num][i]); + goto error; + } + ret = usb_add_function(c, f_ffs[gc->num][i]); + if (ret < 0) { + usb_put_function(f_ffs[gc->num][i]); + goto error; + } } /* @@ -492,6 +524,13 @@ static int gfs_do_config(struct usb_configuration *c) c->interface[c->next_interface_id] = NULL; return 0; +error: + while (--i >= 0) { + if (!IS_ERR(f_ffs[gc->num][i])) + usb_remove_function(c, f_ffs[gc->num][i]); + usb_put_function(f_ffs[gc->num][i]); + } + return ret; } #ifdef CONFIG_USB_FUNCTIONFS_ETH -- cgit v1.2.3 From 3d8d72a4c3c844c3c770c153bf570dc843143ac0 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:35 +0100 Subject: usb: gadget: FunctionFS: Remove compatibility layer There are no old function interface users left, so the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 114 ----------------------------------------- drivers/usb/gadget/u_fs.h | 2 - include/linux/usb/functionfs.h | 18 ------- 3 files changed, 134 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 8d318eaaaf20..9c8c74c25f1e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -97,19 +97,12 @@ static struct ffs_function *ffs_func_from_usb(struct usb_function *f) return container_of(f, struct ffs_function, function); } -#ifdef USB_FFS_INCLUDED -static void ffs_func_free(struct ffs_function *func); -#endif static void ffs_func_eps_disable(struct ffs_function *func); static int __must_check ffs_func_eps_enable(struct ffs_function *func); static int ffs_func_bind(struct usb_configuration *, struct usb_function *); -#ifdef USB_FFS_INCLUDED -static void old_ffs_func_unbind(struct usb_configuration *, - struct usb_function *); -#endif static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned); static void ffs_func_disable(struct usb_function *); static int ffs_func_setup(struct usb_function *, @@ -165,9 +158,7 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data, /* Devices management *******************************************************/ DEFINE_MUTEX(ffs_lock); -#ifndef USB_FFS_INCLUDED EXPORT_SYMBOL(ffs_lock); -#endif static struct ffs_dev *ffs_find_dev(const char *name); static void *ffs_acquire_dev(const char *dev_name); @@ -1303,75 +1294,6 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) kfree(epfiles); } -#ifdef USB_FFS_INCLUDED - -static int functionfs_bind_config(struct usb_composite_dev *cdev, - struct usb_configuration *c, - struct ffs_data *ffs) -{ - struct ffs_function *func; - int ret; - - ENTER(); - - func = kzalloc(sizeof *func, GFP_KERNEL); - if (unlikely(!func)) - return -ENOMEM; - - func->function.name = "Function FS Gadget"; - func->function.strings = ffs->stringtabs; - - func->function.bind = ffs_func_bind; - func->function.unbind = old_ffs_func_unbind; - func->function.set_alt = ffs_func_set_alt; - func->function.disable = ffs_func_disable; - func->function.setup = ffs_func_setup; - func->function.suspend = ffs_func_suspend; - func->function.resume = ffs_func_resume; - - func->conf = c; - func->gadget = cdev->gadget; - func->ffs = ffs; - ffs_data_get(ffs); - - ret = usb_add_function(c, &func->function); - if (unlikely(ret)) - ffs_func_free(func); - - return ret; -} - -static void ffs_func_free(struct ffs_function *func) -{ - struct ffs_ep *ep = func->eps; - unsigned count = func->ffs->eps_count; - unsigned long flags; - - ENTER(); - - /* cleanup after autoconfig */ - spin_lock_irqsave(&func->ffs->eps_lock, flags); - do { - if (ep->ep && ep->req) - usb_ep_free_request(ep->ep, ep->req); - ep->req = NULL; - ++ep; - } while (--count); - spin_unlock_irqrestore(&func->ffs->eps_lock, flags); - - ffs_data_put(func->ffs); - - kfree(func->eps); - /* - * eps and interfaces_nums are allocated in the same chunk so - * only one free is required. Descriptors are also allocated - * in the same chunk. - */ - - kfree(func); -} - -#endif static void ffs_func_eps_disable(struct ffs_function *func) { @@ -2035,7 +1957,6 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep, return 0; } -#ifndef USB_FFS_INCLUDED static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, struct usb_configuration *c) { @@ -2084,7 +2005,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, return ffs_opts; } -#endif static int _ffs_func_bind(struct usb_configuration *c, struct usb_function *f) @@ -2190,12 +2110,10 @@ error: static int ffs_func_bind(struct usb_configuration *c, struct usb_function *f) { -#ifndef USB_FFS_INCLUDED struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c); if (IS_ERR(ffs_opts)) return PTR_ERR(ffs_opts); -#endif return _ffs_func_bind(c, f); } @@ -2203,28 +2121,6 @@ static int ffs_func_bind(struct usb_configuration *c, /* Other USB function hooks *************************************************/ -#ifdef USB_FFS_INCLUDED - -static void old_ffs_func_unbind(struct usb_configuration *c, - struct usb_function *f) -{ - struct ffs_function *func = ffs_func_from_usb(f); - struct ffs_data *ffs = func->ffs; - - ENTER(); - - if (ffs->func == func) { - ffs_func_eps_disable(func); - ffs->func = NULL; - } - - ffs_event_add(ffs, FUNCTIONFS_UNBIND); - - ffs_func_free(func); -} - -#endif - static int ffs_func_set_alt(struct usb_function *f, unsigned interface, unsigned alt) { @@ -2401,8 +2297,6 @@ static struct ffs_dev *ffs_find_dev(const char *name) /* Function registration interface ******************************************/ -#ifndef USB_FFS_INCLUDED - static void ffs_free_inst(struct usb_function_instance *f) { struct f_fs_opts *opts; @@ -2507,8 +2401,6 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi) return &func->function; } -#endif - /* * ffs_lock must be taken by the caller of this function */ @@ -2567,9 +2459,7 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name) return ret; } -#ifndef USB_FFS_INCLUDED EXPORT_SYMBOL(ffs_name_dev); -#endif int ffs_single_dev(struct ffs_dev *dev) { @@ -2586,9 +2476,7 @@ int ffs_single_dev(struct ffs_dev *dev) ffs_dev_unlock(); return ret; } -#ifndef USB_FFS_INCLUDED EXPORT_SYMBOL(ffs_single_dev); -#endif /* * ffs_lock must be taken by the caller of this function @@ -2719,8 +2607,6 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len) return data; } -#ifndef USB_FFS_INCLUDED DECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Nazarewicz"); -#endif diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h index d60a9ddc0332..09313750f913 100644 --- a/drivers/usb/gadget/u_fs.h +++ b/drivers/usb/gadget/u_fs.h @@ -249,7 +249,6 @@ struct ffs_data { }; -#ifndef USB_FFS_INCLUDED struct f_fs_opts { struct usb_function_instance func_inst; struct ffs_dev *dev; @@ -261,6 +260,5 @@ static inline struct f_fs_opts *to_f_fs_opts(struct usb_function_instance *fi) { return container_of(fi, struct f_fs_opts, func_inst); } -#endif #endif /* U_FFS_H */ diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h index 3448efbe56aa..71190663f1ee 100644 --- a/include/linux/usb/functionfs.h +++ b/include/linux/usb/functionfs.h @@ -3,22 +3,4 @@ #include -#ifdef USB_FFS_INCLUDED - -struct ffs_data; -struct usb_composite_dev; -struct usb_configuration; - -static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) - __attribute__((warn_unused_result, nonnull)); -static void functionfs_unbind(struct ffs_data *ffs) - __attribute__((nonnull)); - -static int functionfs_bind_config(struct usb_composite_dev *cdev, - struct usb_configuration *c, - struct ffs_data *ffs) - __attribute__((warn_unused_result, nonnull)); - - -#endif #endif -- cgit v1.2.3 From b658499f0f0f4ebf21d09c7da62a46f66ffa67cb Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 3 Dec 2013 15:15:36 +0100 Subject: usb: gadget: FunctionFS: add configfs support Add support for using FunctionFS in configfs-based USB gadgets. [ balbi@ti.com : removed redefinition of VERBOSE_DEBUG and few trailing whitespaces ] Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- Documentation/ABI/testing/configfs-usb-gadget-ffs | 9 +++ drivers/usb/gadget/Kconfig | 12 ++++ drivers/usb/gadget/f_fs.c | 80 ++++++++++++++++++++++- drivers/usb/gadget/u_fs.h | 3 + 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-ffs (limited to 'drivers') diff --git a/Documentation/ABI/testing/configfs-usb-gadget-ffs b/Documentation/ABI/testing/configfs-usb-gadget-ffs new file mode 100644 index 000000000000..14343e237e83 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-ffs @@ -0,0 +1,9 @@ +What: /config/usb-gadget/gadget/functions/ffs.name +Date: Nov 2013 +KenelVersion: 3.13 +Description: The purpose of this directory is to create and remove it. + + A corresponding USB function instance is created/removed. + There are no attributes here. + + All parameters are set through FunctionFS. diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 97eb540ddef2..0ae2e6559397 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -701,6 +701,18 @@ config USB_CONFIGFS_F_LB_SS test software, like the "usbtest" driver, to put your hardware and its driver through a basic set of functional tests. +config USB_CONFIGFS_F_FS + boolean "Function filesystem (FunctionFS)" + depends on USB_CONFIGFS + select USB_F_FS + help + The Function Filesystem (FunctionFS) lets one create USB + composite functions in user space in the same way GadgetFS + lets one create USB gadgets in user space. This allows creation + of composite gadgets such that some of the functions are + implemented in kernel space (for instance Ethernet, serial or + mass storage) and other are implemented in user space. + config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" select USB_LIBCOMPOSITE diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 9c8c74c25f1e..12a64e1c31ef 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -29,6 +29,7 @@ #include #include "u_fs.h" +#include "configfs.h" #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ @@ -161,6 +162,7 @@ DEFINE_MUTEX(ffs_lock); EXPORT_SYMBOL(ffs_lock); static struct ffs_dev *ffs_find_dev(const char *name); +static int _ffs_name_dev(struct ffs_dev *dev, const char *name); static void *ffs_acquire_dev(const char *dev_name); static void ffs_release_dev(struct ffs_data *ffs_data); static int ffs_ready(struct ffs_data *ffs); @@ -2261,7 +2263,7 @@ static struct ffs_dev *_ffs_find_dev(const char *name) if (strcmp(dev->name, name) == 0) return dev; } - + return NULL; } @@ -2295,6 +2297,31 @@ static struct ffs_dev *ffs_find_dev(const char *name) return _ffs_find_dev(name); } +/* Configfs support *********************************************************/ + +static inline struct f_fs_opts *to_ffs_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_fs_opts, + func_inst.group); +} + +static void ffs_attr_release(struct config_item *item) +{ + struct f_fs_opts *opts = to_ffs_opts(item); + + usb_put_function_instance(&opts->func_inst); +} + +static struct configfs_item_operations ffs_item_ops = { + .release = ffs_attr_release, +}; + +static struct config_item_type ffs_func_type = { + .ct_item_ops = &ffs_item_ops, + .ct_owner = THIS_MODULE, +}; + + /* Function registration interface ******************************************/ static void ffs_free_inst(struct usb_function_instance *f) @@ -2308,6 +2335,44 @@ static void ffs_free_inst(struct usb_function_instance *f) kfree(opts); } +#define MAX_INST_NAME_LEN 40 + +static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) +{ + struct f_fs_opts *opts; + char *ptr; + const char *tmp; + int name_len, ret; + + name_len = strlen(name) + 1; + if (name_len > MAX_INST_NAME_LEN) + return -ENAMETOOLONG; + + ptr = kstrndup(name, name_len, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + opts = to_f_fs_opts(fi); + tmp = NULL; + + ffs_dev_lock(); + + tmp = opts->dev->name_allocated ? opts->dev->name : NULL; + ret = _ffs_name_dev(opts->dev, ptr); + if (ret) { + kfree(ptr); + ffs_dev_unlock(); + return ret; + } + opts->dev->name_allocated = true; + + ffs_dev_unlock(); + + kfree(tmp); + + return 0; +} + static struct usb_function_instance *ffs_alloc_inst(void) { struct f_fs_opts *opts; @@ -2317,6 +2382,7 @@ static struct usb_function_instance *ffs_alloc_inst(void) if (!opts) return ERR_PTR(-ENOMEM); + opts->func_inst.set_inst_name = ffs_set_inst_name; opts->func_inst.free_func_inst = ffs_free_inst; ffs_dev_lock(); dev = ffs_alloc_dev(); @@ -2326,7 +2392,10 @@ static struct usb_function_instance *ffs_alloc_inst(void) return ERR_CAST(dev); } opts->dev = dev; + dev->opts = opts; + config_group_init_type_name(&opts->func_inst.group, "", + &ffs_func_type); return &opts->func_inst; } @@ -2484,6 +2553,8 @@ EXPORT_SYMBOL(ffs_single_dev); void ffs_free_dev(struct ffs_dev *dev) { list_del(&dev->entry); + if (dev->name_allocated) + kfree(dev->name); kfree(dev); if (list_empty(&ffs_devices)) functionfs_cleanup(); @@ -2572,6 +2643,13 @@ static void ffs_closed(struct ffs_data *ffs) if (ffs_obj->ffs_closed_callback) ffs_obj->ffs_closed_callback(ffs); + + if (!ffs_obj->opts || ffs_obj->opts->no_configfs + || !ffs_obj->opts->func_inst.group.cg_item.ci_parent) + goto done; + + unregister_gadget_item(ffs_obj->opts-> + func_inst.group.cg_item.ci_parent->ci_parent); done: ffs_dev_unlock(); } diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h index 09313750f913..bc2d3718219b 100644 --- a/drivers/usb/gadget/u_fs.h +++ b/drivers/usb/gadget/u_fs.h @@ -35,13 +35,16 @@ #define ENTER() pr_vdebug("%s()\n", __func__) +struct f_fs_opts; struct ffs_dev { const char *name; + bool name_allocated; bool mounted; bool desc_ready; bool single; struct ffs_data *ffs_data; + struct f_fs_opts *opts; struct list_head entry; int (*ffs_ready_callback)(struct ffs_data *ffs); -- cgit v1.2.3 From f8800d47bcdf5ae0582ac674657fd939a9105be0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 12 Dec 2013 12:15:43 -0600 Subject: usb: gadget: f_fs: fix sparse warning use NULL when returning NULL pointers, not 0. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 12a64e1c31ef..306a2b52125c 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1137,7 +1137,7 @@ static struct ffs_data *ffs_data_new(void) { struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); if (unlikely(!ffs)) - return 0; + return NULL; ENTER(); -- cgit v1.2.3 From 8808b64daac68a2c85366c767a3ef850824ede74 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Fri, 29 Nov 2013 22:04:09 +0400 Subject: gpio: rcar: Fix level interrupt handling According to the manual, if a port is set for level detection using the corresponding bit in the edge/level select register and an external level interrupt signal is asserted, the corresponding bit in INTDT does not use the FF to hold the input. Thus, writing 1 to the corresponding bits in INTCLR cannot clear the corresponding bits in the INTDT register. Instead, when an external input signal is stopped, the corresponding bit in INTDT is cleared automatically. Since the INTDT bit cannot be cleared for the level interrupts until the interrupt signal is stopped, we end up with the infinite loop when using deferred (threaded) IRQ handling. Since a deferred interrupt is disabled by the low-level handler and re-enabled only when the deferred handler is completed, Fix the issue by dropping disabled interrupts from the pending mask as suggested by Laurent Pinchart Changes in V2: * Drop disabled interrupts from pending mask altogether instead of dropping level interrupts one by one once they get handled. Signed-off-by: Valentine Barshak Acked-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index fe088a30567a..8b7e719a68c3 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -169,7 +169,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) u32 pending; unsigned int offset, irqs_handled = 0; - while ((pending = gpio_rcar_read(p, INTDT))) { + while ((pending = gpio_rcar_read(p, INTDT) & + gpio_rcar_read(p, INTMSK))) { offset = __ffs(pending); gpio_rcar_write(p, INTCLR, BIT(offset)); generic_handle_irq(irq_find_mapping(p->irq_domain, offset)); -- cgit v1.2.3 From 36708b89e00951b004b4dd6c14181301e2e98354 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 9 Dec 2013 15:19:53 -0800 Subject: bonding: Use RCU_INIT_POINTER() for better overhead and for sparse Although rcu_assign_pointer() can be used to assign a constant NULL pointer, doing so gets you an unnecessary memory barrier and in some circumstances, sparse warnings. This commit therefore changes the rcu_assign_pointer() of NULL in __bond_release_one() to RCU_INIT_POINTER(). Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett --- drivers/net/bonding/bond_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4dd5ee2a34cc..a0b97c4c655d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1763,7 +1763,7 @@ static int __bond_release_one(struct net_device *bond_dev, } if (all) { - rcu_assign_pointer(bond->curr_active_slave, NULL); + RCU_INIT_POINTER(bond->curr_active_slave, NULL); } else if (oldcurrent == slave) { /* * Note that we hold RTNL over this sequence, so there -- cgit v1.2.3 From a00580c2809f44fd1d284bf2638395a261d28cc9 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 10 Dec 2013 12:00:27 +0200 Subject: gpio / ACPI: return -ENOENT when no mapping exists Doing this allows drivers to distinguish between a real error case (if there was an error when we tried to resolve the GPIO) and when the optional GPIO line was not available. Signed-off-by: Mika Westerberg Acked-by: Alexandre Courbot Acked-by: Rafael J. Wysocki Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index ae0ffdce8bd5..137d20c70afe 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -307,6 +307,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, if (lookup.desc && info) *info = lookup.info; - return lookup.desc ? lookup.desc : ERR_PTR(-ENODEV); + return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index); -- cgit v1.2.3 From 8d72a7fc8dd74d41ec5f37b70797679e910007e0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 04:26:21 +0100 Subject: sh-pfc: Turn unsigned indices into unsigned int Some indices take positive values only, make them unsigned. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/core.c | 8 ++++---- drivers/pinctrl/sh-pfc/gpio.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index d77ece5217f0..06e648bf3a1b 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -29,7 +29,7 @@ static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev) { struct resource *res; - int k; + unsigned int k; if (pdev->num_resources == 0) return -EINVAL; @@ -147,7 +147,7 @@ static void sh_pfc_config_reg_helper(struct sh_pfc *pfc, unsigned long *maskp, unsigned long *posp) { - int k; + unsigned int k; *mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg); @@ -196,7 +196,7 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id, { const struct pinmux_cfg_reg *config_reg; unsigned long r_width, f_width, curr_width, ncomb; - int k, m, n, pos, bit_pos; + unsigned int k, m, n, pos, bit_pos; k = 0; while (1) { @@ -238,7 +238,7 @@ static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos, u16 *enum_idp) { const u16 *data = pfc->info->gpio_data; - int k; + unsigned int k; if (pos) { *enum_idp = data[pos + 1]; diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 04bf52b64fb3..3d30e6ecdf4a 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -204,7 +204,7 @@ static void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value) static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) { struct sh_pfc *pfc = gpio_to_pfc(gc); - int i, k; + unsigned int i, k; for (i = 0; i < pfc->info->gpio_irq_size; i++) { unsigned short *gpios = pfc->info->gpio_irq[i].gpios; -- cgit v1.2.3 From 316b2550015dc8d26fb1395826533e9ef3434da9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 04:26:22 +0100 Subject: sh-pfc: Terminate gpios array by -1 0 is a valid GPIO value, use -1 to terminate the gpios array in IRQ lists. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/gpio.c | 4 ++-- drivers/pinctrl/sh-pfc/sh_pfc.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 3d30e6ecdf4a..c24be810f56c 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -207,9 +207,9 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) unsigned int i, k; for (i = 0; i < pfc->info->gpio_irq_size; i++) { - unsigned short *gpios = pfc->info->gpio_irq[i].gpios; + short *gpios = pfc->info->gpio_irq[i].gpios; - for (k = 0; gpios[k]; k++) { + for (k = 0; gpios[k] >= 0; k++) { if (gpios[k] == offset) return pfc->info->gpio_irq[i].irq; } diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 8a494e557b43..e17ccab54f2d 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -94,11 +94,11 @@ struct pinmux_data_reg { struct pinmux_irq { int irq; - unsigned short *gpios; + short *gpios; }; #define PINMUX_IRQ(irq_nr, ids...) \ - { .irq = irq_nr, .gpios = (unsigned short []) { ids, 0 } } \ + { .irq = irq_nr, .gpios = (short []) { ids, -1 } } struct pinmux_range { u16 begin; -- cgit v1.2.3 From c48ca30341011fabb0c8bb88b58fce5b7ae9ebd9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 04:26:23 +0100 Subject: sh-pfc: sh73a0: Add missing IRQ15 The external IRQ15 input multiplexed on GPIO 0 is missing. Add it. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/pfc-sh73a0.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index b81b56eae0c9..a6bd1e772345 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3651,6 +3651,7 @@ static const struct pinmux_data_reg pinmux_data_regs[] = { }; static const struct pinmux_irq pinmux_irqs[] = { + PINMUX_IRQ(irq_pin(15), 0), PINMUX_IRQ(irq_pin(19), 9), PINMUX_IRQ(irq_pin(1), 10), PINMUX_IRQ(irq_pin(0), 11), -- cgit v1.2.3 From de55c71feb312baa7cf18d3eb966e3bf932d455a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 04:26:24 +0100 Subject: sh-pfc: sh73a0: Sort IRQ entries by IRQ number This makes catching duplicate entries easier. Merge the two IRQ9 entries found after sorting. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/pfc-sh73a0.c | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index a6bd1e772345..a8d472210e32 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3651,39 +3651,38 @@ static const struct pinmux_data_reg pinmux_data_regs[] = { }; static const struct pinmux_irq pinmux_irqs[] = { - PINMUX_IRQ(irq_pin(15), 0), - PINMUX_IRQ(irq_pin(19), 9), - PINMUX_IRQ(irq_pin(1), 10), PINMUX_IRQ(irq_pin(0), 11), + PINMUX_IRQ(irq_pin(1), 10), + PINMUX_IRQ(irq_pin(2), 149), + PINMUX_IRQ(irq_pin(3), 224), + PINMUX_IRQ(irq_pin(4), 159), + PINMUX_IRQ(irq_pin(5), 227), + PINMUX_IRQ(irq_pin(6), 147), + PINMUX_IRQ(irq_pin(7), 150), + PINMUX_IRQ(irq_pin(8), 223), + PINMUX_IRQ(irq_pin(9), 56, 308), + PINMUX_IRQ(irq_pin(10), 54), + PINMUX_IRQ(irq_pin(11), 238), + PINMUX_IRQ(irq_pin(12), 156), + PINMUX_IRQ(irq_pin(13), 239), + PINMUX_IRQ(irq_pin(14), 251), + PINMUX_IRQ(irq_pin(15), 0), + PINMUX_IRQ(irq_pin(16), 249), + PINMUX_IRQ(irq_pin(17), 234), PINMUX_IRQ(irq_pin(18), 13), + PINMUX_IRQ(irq_pin(19), 9), PINMUX_IRQ(irq_pin(20), 14), PINMUX_IRQ(irq_pin(21), 15), - PINMUX_IRQ(irq_pin(31), 26), - PINMUX_IRQ(irq_pin(30), 27), - PINMUX_IRQ(irq_pin(29), 28), PINMUX_IRQ(irq_pin(22), 40), PINMUX_IRQ(irq_pin(23), 53), - PINMUX_IRQ(irq_pin(10), 54), - PINMUX_IRQ(irq_pin(9), 56), + PINMUX_IRQ(irq_pin(24), 118), + PINMUX_IRQ(irq_pin(25), 164), PINMUX_IRQ(irq_pin(26), 115), PINMUX_IRQ(irq_pin(27), 116), PINMUX_IRQ(irq_pin(28), 117), - PINMUX_IRQ(irq_pin(24), 118), - PINMUX_IRQ(irq_pin(6), 147), - PINMUX_IRQ(irq_pin(2), 149), - PINMUX_IRQ(irq_pin(7), 150), - PINMUX_IRQ(irq_pin(12), 156), - PINMUX_IRQ(irq_pin(4), 159), - PINMUX_IRQ(irq_pin(25), 164), - PINMUX_IRQ(irq_pin(8), 223), - PINMUX_IRQ(irq_pin(3), 224), - PINMUX_IRQ(irq_pin(5), 227), - PINMUX_IRQ(irq_pin(17), 234), - PINMUX_IRQ(irq_pin(11), 238), - PINMUX_IRQ(irq_pin(13), 239), - PINMUX_IRQ(irq_pin(16), 249), - PINMUX_IRQ(irq_pin(14), 251), - PINMUX_IRQ(irq_pin(9), 308), + PINMUX_IRQ(irq_pin(29), 28), + PINMUX_IRQ(irq_pin(30), 27), + PINMUX_IRQ(irq_pin(31), 26), }; /* ----------------------------------------------------------------------------- -- cgit v1.2.3 From 5b46ac3a7723636082ec6234289517ca5b9c65af Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 04:26:25 +0100 Subject: sh-pfc: Rename sh_pfc window field to windows There's more than one window, name the field windows. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/core.c | 19 ++++++++++--------- drivers/pinctrl/sh-pfc/core.h | 2 +- drivers/pinctrl/sh-pfc/gpio.c | 4 ++-- drivers/pinctrl/sh-pfc/pfc-r8a73a4.c | 4 ++-- drivers/pinctrl/sh-pfc/pfc-r8a7740.c | 2 +- drivers/pinctrl/sh-pfc/pfc-sh7372.c | 2 +- drivers/pinctrl/sh-pfc/pfc-sh73a0.c | 8 ++++---- 7 files changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 06e648bf3a1b..7831f078a5ef 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -34,20 +34,21 @@ static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev) if (pdev->num_resources == 0) return -EINVAL; - pfc->window = devm_kzalloc(pfc->dev, pdev->num_resources * - sizeof(*pfc->window), GFP_NOWAIT); - if (!pfc->window) + pfc->windows = devm_kzalloc(pfc->dev, pdev->num_resources * + sizeof(*pfc->windows), GFP_NOWAIT); + if (!pfc->windows) return -ENOMEM; pfc->num_windows = pdev->num_resources; for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) { WARN_ON(resource_type(res) != IORESOURCE_MEM); - pfc->window[k].phys = res->start; - pfc->window[k].size = resource_size(res); - pfc->window[k].virt = devm_ioremap_nocache(pfc->dev, res->start, - resource_size(res)); - if (!pfc->window[k].virt) + pfc->windows[k].phys = res->start; + pfc->windows[k].size = resource_size(res); + pfc->windows[k].virt = + devm_ioremap_nocache(pfc->dev, res->start, + resource_size(res)); + if (!pfc->windows[k].virt) return -ENOMEM; } @@ -62,7 +63,7 @@ static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, /* scan through physical windows and convert address */ for (i = 0; i < pfc->num_windows; i++) { - window = pfc->window + i; + window = pfc->windows + i; if (address < window->phys) continue; diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index 11ea87268658..a83b7472e674 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -37,7 +37,7 @@ struct sh_pfc { spinlock_t lock; unsigned int num_windows; - struct sh_pfc_window *window; + struct sh_pfc_window *windows; struct sh_pfc_pin_range *ranges; unsigned int nr_ranges; diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index c24be810f56c..6a21349fb116 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -347,7 +347,7 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc) * GPIOs. */ for (i = 0; i < pfc->num_windows; ++i) { - struct sh_pfc_window *window = &pfc->window[i]; + struct sh_pfc_window *window = &pfc->windows[i]; if (pfc->info->data_regs[0].reg >= window->phys && pfc->info->data_regs[0].reg < window->phys + window->size) @@ -358,7 +358,7 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc) return 0; /* Register the real GPIOs chip. */ - chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->window[i]); + chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]); if (IS_ERR(chip)) return PTR_ERR(chip); diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c index d76cc343a82a..32dd478f28e3 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c @@ -2680,7 +2680,7 @@ static unsigned int r8a73a4_pinmux_get_bias(struct sh_pfc *pfc, { void __iomem *addr; - addr = pfc->window->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; + addr = pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; switch (ioread8(addr) & PORTCR_PULMD_MASK) { case PORTCR_PULMD_UP: @@ -2699,7 +2699,7 @@ static void r8a73a4_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, void __iomem *addr; u32 value; - addr = pfc->window->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; + addr = pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; value = ioread8(addr) & ~PORTCR_PULMD_MASK; switch (bias) { diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c index 7ac006583558..a189b962a1eb 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c @@ -3710,7 +3710,7 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin) &r8a7740_portcr_offsets[i]; if (i <= group->end_pin) - return pfc->window->virt + group->offset + pin; + return pfc->windows->virt + group->offset + pin; } return NULL; diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c index 4fea6ceb2dbf..bcdd5c3cdcf0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c @@ -2574,7 +2574,7 @@ static void __iomem *sh7372_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin) &sh7372_portcr_offsets[i]; if (i <= group->end_pin) - return pfc->window->virt + group->offset + pin; + return pfc->windows->virt + group->offset + pin; } return NULL; diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index a8d472210e32..dc7c7fb33805 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3692,7 +3692,7 @@ static const struct pinmux_irq pinmux_irqs[] = { static void sh73a0_vccq_mc0_endisable(struct regulator_dev *reg, bool enable) { struct sh_pfc *pfc = reg->reg_data; - void __iomem *addr = pfc->window[1].virt + 4; + void __iomem *addr = pfc->windows[1].virt + 4; unsigned long flags; u32 value; @@ -3725,7 +3725,7 @@ static int sh73a0_vccq_mc0_disable(struct regulator_dev *reg) static int sh73a0_vccq_mc0_is_enabled(struct regulator_dev *reg) { struct sh_pfc *pfc = reg->reg_data; - void __iomem *addr = pfc->window[1].virt + 4; + void __iomem *addr = pfc->windows[1].virt + 4; unsigned long flags; u32 value; @@ -3784,7 +3784,7 @@ static const unsigned int sh73a0_portcr_offsets[] = { static unsigned int sh73a0_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) { - void __iomem *addr = pfc->window->virt + void __iomem *addr = pfc->windows->virt + sh73a0_portcr_offsets[pin >> 5] + pin; u32 value = ioread8(addr) & PORTnCR_PULMD_MASK; @@ -3802,7 +3802,7 @@ static unsigned int sh73a0_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) static void sh73a0_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, unsigned int bias) { - void __iomem *addr = pfc->window->virt + void __iomem *addr = pfc->windows->virt + sh73a0_portcr_offsets[pin >> 5] + pin; u32 value = ioread8(addr) & ~PORTnCR_PULMD_MASK; -- cgit v1.2.3 From 70c8f01a357ac74d223a632659787396fef1e649 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Dec 2013 04:26:26 +0100 Subject: sh-pfc: Support GPIO to IRQ mapping specified IRQ resources On non-DT platforms IRQ controllers associated with the GPIOs have a fixed IRQ base value known at compile time. The sh-pfc driver translates GPIO number to IRQ numbers using a hardcoded table. This mechanism breaks on DT platforms, as the IRQ base values are dynamic in that case. Fix this by specifying IRQs associated with GPIOs in IRQ resources, populated automatically from the device tree. When IRQ resources are specified the driver requires one IRQ resource per GPIO able to generate an interrupt, and uses the translation table to compute the IRQ resource offset instead of the IRQ number. Cc: devicetree@vger.kernel.org Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- .../bindings/pinctrl/renesas,pfc-pinctrl.txt | 14 +++++ drivers/pinctrl/sh-pfc/core.c | 69 +++++++++++++++++----- drivers/pinctrl/sh-pfc/core.h | 2 + drivers/pinctrl/sh-pfc/gpio.c | 14 ++++- 4 files changed, 82 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt index d5dac7b843a9..35d2e1f186f0 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt @@ -26,6 +26,11 @@ Optional properties: - #gpio-range-cells: Mandatory when the PFC doesn't handle GPIO, forbidden otherwise. Should be 3. + - interrupts-extended: Specify the interrupts associated with external + IRQ pins. This property is mandatory when the PFC handles GPIOs and + forbidden otherwise. When specified, it must contain one interrupt per + external IRQ, sorted by external IRQ number. + The PFC node also acts as a container for pin configuration nodes. Please refer to pinctrl-bindings.txt in this directory for the definition of the term "pin configuration node" and for the common pinctrl bindings used by client devices. @@ -103,6 +108,15 @@ Example 1: SH73A0 (SH-Mobile AG5) pin controller node <0xe605801c 0x1c>; gpio-controller; #gpio-cells = <2>; + interrupts-extended = + <&irqpin0 0 0>, <&irqpin0 1 0>, <&irqpin0 2 0>, <&irqpin0 3 0>, + <&irqpin0 4 0>, <&irqpin0 5 0>, <&irqpin0 6 0>, <&irqpin0 7 0>, + <&irqpin1 0 0>, <&irqpin1 1 0>, <&irqpin1 2 0>, <&irqpin1 3 0>, + <&irqpin1 4 0>, <&irqpin1 5 0>, <&irqpin1 6 0>, <&irqpin1 7 0>, + <&irqpin2 0 0>, <&irqpin2 1 0>, <&irqpin2 2 0>, <&irqpin2 3 0>, + <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>, + <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>, + <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>; }; Example 2: A GPIO LED node that references a GPIO diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 7831f078a5ef..b9b464d0578c 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -26,30 +26,67 @@ #include "core.h" -static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev) +static int sh_pfc_map_resources(struct sh_pfc *pfc, + struct platform_device *pdev) { + unsigned int num_windows = 0; + unsigned int num_irqs = 0; + struct sh_pfc_window *windows; + unsigned int *irqs = NULL; struct resource *res; - unsigned int k; + unsigned int i; + + /* Count the MEM and IRQ resources. */ + for (i = 0; i < pdev->num_resources; ++i) { + switch (resource_type(&pdev->resource[i])) { + case IORESOURCE_MEM: + num_windows++; + break; + + case IORESOURCE_IRQ: + num_irqs++; + break; + } + } - if (pdev->num_resources == 0) + if (num_windows == 0) return -EINVAL; - pfc->windows = devm_kzalloc(pfc->dev, pdev->num_resources * - sizeof(*pfc->windows), GFP_NOWAIT); - if (!pfc->windows) + /* Allocate memory windows and IRQs arrays. */ + windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows), + GFP_KERNEL); + if (windows == NULL) return -ENOMEM; - pfc->num_windows = pdev->num_resources; + pfc->num_windows = num_windows; + pfc->windows = windows; - for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) { - WARN_ON(resource_type(res) != IORESOURCE_MEM); - pfc->windows[k].phys = res->start; - pfc->windows[k].size = resource_size(res); - pfc->windows[k].virt = - devm_ioremap_nocache(pfc->dev, res->start, - resource_size(res)); - if (!pfc->windows[k].virt) + if (num_irqs) { + irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs), + GFP_KERNEL); + if (irqs == NULL) return -ENOMEM; + + pfc->num_irqs = num_irqs; + pfc->irqs = irqs; + } + + /* Fill them. */ + for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) { + switch (resource_type(res)) { + case IORESOURCE_MEM: + windows->phys = res->start; + windows->size = resource_size(res); + windows->virt = devm_ioremap_resource(pfc->dev, res); + if (IS_ERR(windows->virt)) + return -ENOMEM; + windows++; + break; + + case IORESOURCE_IRQ: + *irqs++ = res->start; + break; + } } return 0; @@ -482,7 +519,7 @@ static int sh_pfc_probe(struct platform_device *pdev) pfc->info = info; pfc->dev = &pdev->dev; - ret = sh_pfc_ioremap(pfc, pdev); + ret = sh_pfc_map_resources(pfc, pdev); if (unlikely(ret < 0)) return ret; diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index a83b7472e674..b7b0e6ccf305 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -38,6 +38,8 @@ struct sh_pfc { unsigned int num_windows; struct sh_pfc_window *windows; + unsigned int num_irqs; + unsigned int *irqs; struct sh_pfc_pin_range *ranges; unsigned int nr_ranges; diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 6a21349fb116..63480815e1af 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -211,11 +211,17 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) for (k = 0; gpios[k] >= 0; k++) { if (gpios[k] == offset) - return pfc->info->gpio_irq[i].irq; + goto found; } } return -ENOSYS; + +found: + if (pfc->num_irqs) + return pfc->irqs[i]; + else + return pfc->info->gpio_irq[i].irq; } static int gpio_pin_setup(struct sh_pfc_chip *chip) @@ -357,6 +363,12 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc) if (i == pfc->num_windows) return 0; + /* If we have IRQ resources make sure their number is correct. */ + if (pfc->num_irqs && pfc->num_irqs != pfc->info->gpio_irq_size) { + dev_err(pfc->dev, "invalid number of IRQ resources\n"); + return -EINVAL; + } + /* Register the real GPIOs chip. */ chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]); if (IS_ERR(chip)) -- cgit v1.2.3 From 1a16bee6bce39ca31724cf928dce19bd48d78df5 Mon Sep 17 00:00:00 2001 From: Ashwini Ghuge Date: Tue, 10 Dec 2013 12:40:56 +0530 Subject: pinctrl: tegra: add pinmux controller driver for Tegra124 This adds a driver for the Tegra124 pinmux, and required parameterization data for Tegra124. The driver uses the common Tegra pincontrol driver utility functions to implement the majority of the driver. This driver is not compatible with the earlier NVIDIA's SoCs, hence add new compatibile as "nvidia,tegra124-pinmux". Originally written by Ashwini Gguhe. Thierry: - Cleanups in patches. ldewangan: - Fix some entries for groups. - Fix MUX enums and group sequence. Signed-off-by: Ashwini Ghuge Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Tested-by: Stephen Warren CC: Thierry Reding Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 4 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-tegra124.c | 3137 ++++++++++++++++++++++++++++++++++++ 3 files changed, 3142 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-tegra124.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 30fcb897eb99..ad58e7efe1d5 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -280,6 +280,10 @@ config PINCTRL_TEGRA114 bool select PINCTRL_TEGRA +config PINCTRL_TEGRA124 + bool + select PINCTRL_TEGRA + config PINCTRL_TZ1090 bool "Toumaz Xenif TZ1090 pin control driver" depends on SOC_TZ1090 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 5d91e4b448d4..0f5c2215c0df 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o +obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o diff --git a/drivers/pinctrl/pinctrl-tegra124.c b/drivers/pinctrl/pinctrl-tegra124.c new file mode 100644 index 000000000000..c20e0e1dda83 --- /dev/null +++ b/drivers/pinctrl/pinctrl-tegra124.c @@ -0,0 +1,3137 @@ +/* + * Pinctrl data for the NVIDIA Tegra124 pinmux + * + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_PB0 _GPIO(8) +#define TEGRA_PIN_PB1 _GPIO(9) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_PC7 _GPIO(23) +#define TEGRA_PIN_PG0 _GPIO(48) +#define TEGRA_PIN_PG1 _GPIO(49) +#define TEGRA_PIN_PG2 _GPIO(50) +#define TEGRA_PIN_PG3 _GPIO(51) +#define TEGRA_PIN_PG4 _GPIO(52) +#define TEGRA_PIN_PG5 _GPIO(53) +#define TEGRA_PIN_PG6 _GPIO(54) +#define TEGRA_PIN_PG7 _GPIO(55) +#define TEGRA_PIN_PH0 _GPIO(56) +#define TEGRA_PIN_PH1 _GPIO(57) +#define TEGRA_PIN_PH2 _GPIO(58) +#define TEGRA_PIN_PH3 _GPIO(59) +#define TEGRA_PIN_PH4 _GPIO(60) +#define TEGRA_PIN_PH5 _GPIO(61) +#define TEGRA_PIN_PH6 _GPIO(62) +#define TEGRA_PIN_PH7 _GPIO(63) +#define TEGRA_PIN_PI0 _GPIO(64) +#define TEGRA_PIN_PI1 _GPIO(65) +#define TEGRA_PIN_PI2 _GPIO(66) +#define TEGRA_PIN_PI3 _GPIO(67) +#define TEGRA_PIN_PI4 _GPIO(68) +#define TEGRA_PIN_PI5 _GPIO(69) +#define TEGRA_PIN_PI6 _GPIO(70) +#define TEGRA_PIN_PI7 _GPIO(71) +#define TEGRA_PIN_PJ0 _GPIO(72) +#define TEGRA_PIN_PJ2 _GPIO(74) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_PJ7 _GPIO(79) +#define TEGRA_PIN_PK0 _GPIO(80) +#define TEGRA_PIN_PK1 _GPIO(81) +#define TEGRA_PIN_PK2 _GPIO(82) +#define TEGRA_PIN_PK3 _GPIO(83) +#define TEGRA_PIN_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_PK7 _GPIO(87) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) +#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_KB_ROW16_PT0 _GPIO(152) +#define TEGRA_PIN_KB_ROW17_PT1 _GPIO(153) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) +#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) +#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) +#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) +#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) +#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) +#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) +#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) +#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) +#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) +#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) +#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) +#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) +#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) +#define TEGRA_PIN_DP_HPD_PFF0 _GPIO(248) +#define TEGRA_PIN_USB_VBUS_EN2_PFF1 _GPIO(249) +#define TEGRA_PIN_PFF2 _GPIO(250) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PFF2 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_GMI_CLK_LB _PIN(3) +#define TEGRA_PIN_RESET_OUT_N _PIN(4) +#define TEGRA_PIN_OWR _PIN(5) +#define TEGRA_PIN_CLK_32K_IN _PIN(6) +#define TEGRA_PIN_JTAG_RTCK _PIN(7) + +static const struct pinctrl_pin_desc tegra124_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"), + PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"), + PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"), + PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"), + PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"), + PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"), + PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"), + PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"), + PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"), + PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"), + PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"), + PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"), + PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"), + PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"), + PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"), + PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"), + PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), + PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"), + PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"), + PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"), + PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"), + PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"), + PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"), + PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"), + PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"), + PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"), + PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"), + PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"), + PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), + PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), + PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), + PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), + PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW10 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW10 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW10 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW10 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW10 PS7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW10 PT0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW10 PT1"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), + PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"), + PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned pb0_pins[] = { + TEGRA_PIN_PB0, +}; + +static const unsigned pb1_pins[] = { + TEGRA_PIN_PB1, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned pc7_pins[] = { + TEGRA_PIN_PC7, +}; + +static const unsigned pg0_pins[] = { + TEGRA_PIN_PG0, +}; + +static const unsigned pg1_pins[] = { + TEGRA_PIN_PG1, +}; + +static const unsigned pg2_pins[] = { + TEGRA_PIN_PG2, +}; + +static const unsigned pg3_pins[] = { + TEGRA_PIN_PG3, +}; + +static const unsigned pg4_pins[] = { + TEGRA_PIN_PG4, +}; + +static const unsigned pg5_pins[] = { + TEGRA_PIN_PG5, +}; + +static const unsigned pg6_pins[] = { + TEGRA_PIN_PG6, +}; + +static const unsigned pg7_pins[] = { + TEGRA_PIN_PG7, +}; + +static const unsigned ph0_pins[] = { + TEGRA_PIN_PH0, +}; + +static const unsigned ph1_pins[] = { + TEGRA_PIN_PH1, +}; + +static const unsigned ph2_pins[] = { + TEGRA_PIN_PH2, +}; + +static const unsigned ph3_pins[] = { + TEGRA_PIN_PH3, +}; + +static const unsigned ph4_pins[] = { + TEGRA_PIN_PH4, +}; + +static const unsigned ph5_pins[] = { + TEGRA_PIN_PH5, +}; + +static const unsigned ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned ph7_pins[] = { + TEGRA_PIN_PH7, +}; + +static const unsigned pi0_pins[] = { + TEGRA_PIN_PI0, +}; + +static const unsigned pi1_pins[] = { + TEGRA_PIN_PI1, +}; + +static const unsigned pi2_pins[] = { + TEGRA_PIN_PI2, +}; + +static const unsigned pi3_pins[] = { + TEGRA_PIN_PI3, +}; + +static const unsigned pi4_pins[] = { + TEGRA_PIN_PI4, +}; + +static const unsigned pi5_pins[] = { + TEGRA_PIN_PI5, +}; + +static const unsigned pi6_pins[] = { + TEGRA_PIN_PI6, +}; + +static const unsigned pi7_pins[] = { + TEGRA_PIN_PI7, +}; + +static const unsigned pj0_pins[] = { + TEGRA_PIN_PJ0, +}; + +static const unsigned pj2_pins[] = { + TEGRA_PIN_PJ2, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned pj7_pins[] = { + TEGRA_PIN_PJ7, +}; + +static const unsigned pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned usb_vbus_en0_pn4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, +}; + +static const unsigned usb_vbus_en1_pn5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned kb_row11_ps3_pins[] = { + TEGRA_PIN_KB_ROW11_PS3, +}; + +static const unsigned kb_row12_ps4_pins[] = { + TEGRA_PIN_KB_ROW12_PS4, +}; + +static const unsigned kb_row13_ps5_pins[] = { + TEGRA_PIN_KB_ROW13_PS5, +}; + +static const unsigned kb_row14_ps6_pins[] = { + TEGRA_PIN_KB_ROW14_PS6, +}; + +static const unsigned kb_row15_ps7_pins[] = { + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned kb_row16_pt0_pins[] = { + TEGRA_PIN_KB_ROW16_PT0, +}; + +static const unsigned kb_row17_pt1_pins[] = { + TEGRA_PIN_KB_ROW17_PT1, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned sdmmc3_cd_n_pv2_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned sdmmc1_wp_n_pv3_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned gpio_w2_aud_pw2_pins[] = { + TEGRA_PIN_GPIO_W2_AUD_PW2, +}; + +static const unsigned gpio_w3_aud_pw3_pins[] = { + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned dap_mclk1_pw4_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned dvfs_pwm_px0_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, +}; + +static const unsigned gpio_x1_aud_px1_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PX1, +}; + +static const unsigned dvfs_clk_px2_pins[] = { + TEGRA_PIN_DVFS_CLK_PX2, +}; + +static const unsigned gpio_x3_aud_px3_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PX3, +}; + +static const unsigned gpio_x4_aud_px4_pins[] = { + TEGRA_PIN_GPIO_X4_AUD_PX4, +}; + +static const unsigned gpio_x5_aud_px5_pins[] = { + TEGRA_PIN_GPIO_X5_AUD_PX5, +}; + +static const unsigned gpio_x6_aud_px6_pins[] = { + TEGRA_PIN_GPIO_X6_AUD_PX6, +}; + +static const unsigned gpio_x7_aud_px7_pins[] = { + TEGRA_PIN_GPIO_X7_AUD_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned pex_l0_rst_n_pdd1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, +}; + +static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, +}; + +static const unsigned pex_wake_n_pdd3_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PDD3, +}; + +static const unsigned pex_l1_rst_n_pdd5_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PDD5, +}; + +static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned dap_mclk1_req_pee2_pins[] = { + TEGRA_PIN_DAP_MCLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, +}; + +static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; +static const unsigned dp_hpd_pff0_pins[] = { + TEGRA_PIN_DP_HPD_PFF0, +}; + +static const unsigned usb_vbus_en2_pff1_pins[] = { + TEGRA_PIN_USB_VBUS_EN2_PFF1, +}; + +static const unsigned pff2_pins[] = { + TEGRA_PIN_PFF2, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned reset_out_n_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned gmi_clk_lb_pins[] = { + TEGRA_PIN_GMI_CLK_LB, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_CLK_32K_IN, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_KB_ROW16_PT0, + TEGRA_PIN_KB_ROW17_PT1, + TEGRA_PIN_SDMMC3_CD_N_PV2, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_PH0, + TEGRA_PIN_PH1, + TEGRA_PIN_PH2, + TEGRA_PIN_PH3, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_PG0, + TEGRA_PIN_PG1, + TEGRA_PIN_PG2, + TEGRA_PIN_PG3, + TEGRA_PIN_PG4, + TEGRA_PIN_PG5, + TEGRA_PIN_PG6, + TEGRA_PIN_PG7, + TEGRA_PIN_PI0, + TEGRA_PIN_PI1, + TEGRA_PIN_PI3, + TEGRA_PIN_PI4, + TEGRA_PIN_PI7, + TEGRA_PIN_PK0, + TEGRA_PIN_PK2, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_PC7, + TEGRA_PIN_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_PB0, + TEGRA_PIN_PB1, + TEGRA_PIN_PJ0, + TEGRA_PIN_PJ7, + TEGRA_PIN_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, + TEGRA_PIN_DAP_MCLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, + TEGRA_PIN_GPIO_X1_AUD_PX1, + TEGRA_PIN_DVFS_CLK_PX2, + TEGRA_PIN_GPIO_X3_AUD_PX3, + TEGRA_PIN_GPIO_X4_AUD_PX4, + TEGRA_PIN_GPIO_X5_AUD_PX5, + TEGRA_PIN_GPIO_X6_AUD_PX6, + TEGRA_PIN_GPIO_X7_AUD_PX7, + TEGRA_PIN_GPIO_W2_AUD_PW2, + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, + TEGRA_PIN_SDMMC4_CMD_PT7, + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, + TEGRA_PIN_OWR, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_gpv_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, + TEGRA_PIN_PEX_WAKE_N_PDD3, + TEGRA_PIN_PEX_L1_RST_N_PDD5, + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, + TEGRA_PIN_USB_VBUS_EN2_PFF1, + TEGRA_PIN_PFF2, +}; + +static const unsigned drive_cec_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned drive_dev3_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned drive_at6_pins[] = { + TEGRA_PIN_PK1, + TEGRA_PIN_PK3, + TEGRA_PIN_PK4, + TEGRA_PIN_PI2, + TEGRA_PIN_PI5, + TEGRA_PIN_PI6, + TEGRA_PIN_PH4, + TEGRA_PIN_PH5, + TEGRA_PIN_PH6, + TEGRA_PIN_PH7, +}; + +static const unsigned drive_dap5_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_DP_HPD_PFF0, +}; + +static const unsigned drive_usb_vbus_en_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned drive_ao3_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned drive_ao0_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned drive_hv0_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned drive_sdio4_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned drive_ao4_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK12, + TEGRA_MUX_CPU, + TEGRA_MUX_DAP, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYA_ALT, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_OWR, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWRON, + TEGRA_MUX_RESET_OUT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SOC, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_ULPI, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT3, + TEGRA_MUX_VIMCLK2, + TEGRA_MUX_VIMCLK2_ALT, + TEGRA_MUX_SATA, + TEGRA_MUX_CCLA, + TEGRA_MUX_PE0, + TEGRA_MUX_PE, + TEGRA_MUX_PE1, + TEGRA_MUX_DP, + TEGRA_MUX_RTCK, + TEGRA_MUX_SYS, + TEGRA_MUX_CLK, + TEGRA_MUX_TMDS, +}; + +static const char * const blink_groups[] = { + "clk_32k_out_pa0", +}; + +static const char * const cec_groups[] = { + "hdmi_cec_pee3", +}; + +static const char * const cldvfs_groups[] = { + "ph2", + "ph3", + "kb_row7_pr7", + "kb_row8_ps0", + "dvfs_pwm_px0", + "dvfs_clk_px2", +}; + +static const char * const clk12_groups[] = { + "sdmmc1_wp_n_pv3", + "sdmmc1_clk_pz0", +}; + +static const char * const cpu_groups[] = { + "cpu_pwr_req", +}; + +static const char * const dap_groups[] = { + "dap_mclk1_pee2", + "clk2_req_pcc5", +}; + +static const char * const dap1_groups[] = { + "dap_mclk1_pee2", +}; + +static const char * const dap2_groups[] = { + "dap_mclk1_pw4", + "gpio_x4_aud_px4", +}; + +static const char * const dev3_groups[] = { + "clk3_req_pee1", +}; + +static const char * const displaya_groups[] = { + "dap3_fs_pp0", + "dap3_din_pp1", + "dap3_dout_pp2", + "ph1", + "pi4", + "pbb3", + "pbb4", + "pbb5", + "kb_row3_pr3", + "kb_row4_pr4", + "kb_row5_pr5", + "kb_row6_pr6", + "kb_col3_pq3", + "sdmmc3_dat2_pb5", +}; + +static const char * const displaya_alt_groups[] = { + "kb_row6_pr6", +}; + +static const char * const displayb_groups[] = { + "dap3_fs_pp0", + "dap3_din_pp1", + "dap3_sclk_pp3", + + "pu3", + "pu4", + "pu5", + + "pbb3", + "pbb4", + "pbb6", + + "kb_row3_pr3", + "kb_row4_pr4", + "kb_row5_pr5", + "kb_row6_pr6", + + "sdmmc3_dat3_pb4", +}; + +static const char * const dtv_groups[] = { + "uart3_cts_n_pa1", + "uart3_rts_n_pc0", + "dap4_fs_pp4", + "dap4_dout_pp6", + "pi7", + "ph0", + "ph6", + "ph7", +}; + +static const char * const extperiph1_groups[] = { + "dap_mclk1_pw4", +}; + +static const char * const extperiph2_groups[] = { + "clk2_out_pw5", +}; + +static const char * const extperiph3_groups[] = { + "clk3_out_pee0", +}; + +static const char * const gmi_groups[] = { + "uart2_cts_n_pj5", + "uart2_rts_n_pj6", + "uart3_txd_pw6", + "uart3_rxd_pw7", + "uart3_cts_n_pa1", + "uart3_rts_n_pc0", + + "pu0", + "pu1", + "pu2", + "pu3", + "pu4", + "pu5", + "pu6", + + "dap4_fs_pp4", + "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_sclk_pp7", + + "pc7", + + "pg0", + "pg1", + "pg2", + "pg3", + "pg4", + "pg5", + "pg6", + "pg7", + + "ph0", + "ph1", + "ph2", + "ph3", + "ph4", + "ph5", + "ph6", + "ph7", + + "pi0", + "pi1", + "pi2", + "pi3", + "pi4", + "pi5", + "pi6", + "pi7", + + "pj0", + "pj2", + + "pk0", + "pk1", + "pk2", + "pk3", + "pk4", + + "pj7", + "pb0", + "pb1", + "pk7", + + "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6", + + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7", + "sdmmc4_clk_pcc4", + "sdmmc4_cmd_pt7", + "gmi_clk_lb", + + "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3", + + "dap2_fs_pa2", + "dap2_din_pa4", + "dap2_dout_pa5", + "dap2_sclk_pa3", + + "dvfs_pwm_px0", + "dvfs_clk_px2", + "gpio_x1_aud_px1", + "gpio_x3_aud_px3", + "gpio_x4_aud_px4", + "gpio_x5_aud_px5", + "gpio_x6_aud_px6", +}; + +static const char * const gmi_alt_groups[] = { + "pc7", + "pk4", + "pj7", +}; + +static const char * const hda_groups[] = { + "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3", + "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5", +}; + +static const char * const hsi_groups[] = { + "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0", +}; + +static const char * const i2c1_groups[] = { + "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5", + "gpio_w2_aud_pw2", + "gpio_w3_aud_pw3", +}; + +static const char * const i2c2_groups[] = { + "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6", +}; + +static const char * const i2c3_groups[] = { + "spdif_in_pk6", + "spdif_out_pk5", + "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2", +}; + +static const char * const i2c4_groups[] = { + "ddc_scl_pv4", + "ddc_sda_pv5", +}; + +static const char * const i2cpwr_groups[] = { + "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7", +}; + +static const char * const i2s0_groups[] = { + "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3", +}; + +static const char * const i2s1_groups[] = { + "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5", +}; + +static const char * const i2s2_groups[] = { + "dap3_fs_pp0", + "dap3_din_pp1", + "dap3_dout_pp2", + "dap3_sclk_pp3", +}; + +static const char * const i2s3_groups[] = { + "dap4_fs_pp4", + "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_sclk_pp7", +}; + +static const char * const i2s4_groups[] = { + "pcc1", + "pbb6", + "pbb7", + "pcc2", +}; + +static const char * const irda_groups[] = { + "uart2_rxd_pc3", + "uart2_txd_pc2", + "kb_row11_ps3", + "kb_row12_ps4", +}; + +static const char * const kbc_groups[] = { + "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row3_pr3", + "kb_row4_pr4", + "kb_row5_pr5", + "kb_row6_pr6", + "kb_row7_pr7", + "kb_row8_ps0", + "kb_row9_ps1", + "kb_row10_ps2", + "kb_row11_ps3", + "kb_row12_ps4", + "kb_row13_ps5", + "kb_row14_ps6", + "kb_row15_ps7", + "kb_row16_pt0", + "kb_row17_pt1", + + "kb_col0_pq0", + "kb_col1_pq1", + "kb_col2_pq2", + "kb_col3_pq3", + "kb_col4_pq4", + "kb_col5_pq5", + "kb_col6_pq6", + "kb_col7_pq7", +}; + +static const char * const owr_groups[] = { + "pu0", + "kb_col4_pq4", + "owr", + "sdmmc3_cd_n_pv2", +}; + +static const char * const pmi_groups[] = { + "pwr_int_n", +}; + +static const char * const pwm0_groups[] = { + "sdmmc1_dat2_py5", + "uart3_rts_n_pc0", + "pu3", + "ph0", + "sdmmc3_dat3_pb4", +}; + +static const char * const pwm1_groups[] = { + "sdmmc1_dat1_py6", + "pu4", + "ph1", + "sdmmc3_dat2_pb5", +}; + +static const char * const pwm2_groups[] = { + "pu5", + "ph2", + "kb_col3_pq3", + "sdmmc3_dat1_pb6", +}; + +static const char * const pwm3_groups[] = { + "pu6", + "ph3", + "sdmmc3_cmd_pa7", +}; + +static const char * const pwron_groups[] = { + "core_pwr_req", +}; + +static const char * const reset_out_n_groups[] = { + "reset_out_n", +}; + +static const char * const rsvd1_groups[] = { + "pv0", + "pv1", + + "hdmi_int_pn7", + "pu1", + "pu2", + "pc7", + "pi7", + "pk0", + "pj0", + "pj2", + "pk2", + "pi3", + "pi6", + + "pg0", + "pg1", + "pg2", + "pg3", + "pg4", + "pg5", + "pg6", + "pg7", + + "pi0", + "pi1", + + "gpio_x7_aud_px7", + + "reset_out_n", +}; + +static const char * const rsvd2_groups[] = { + "pv0", + "pv1", + + "sdmmc1_dat0_py7", + "clk2_out_pw5", + "clk2_req_pcc5", + "hdmi_int_pn7", + "ddc_scl_pv4", + "ddc_sda_pv5", + + "uart3_txd_pw6", + "uart3_rxd_pw7", + + "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5", + + "clk2_out_pee0", + "clk2_req_pee1", + "pc7", + "pi5", + "pj0", + "pj2", + + "pk4", + "pk2", + "pi3", + "pi6", + "pg0", + "pg1", + "pg5", + "pg6", + "pg7", + + "ph4", + "ph5", + "pj7", + "pb0", + "pb1", + "pk7", + "pi0", + "pi1", + + "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6", + "sdmmc4_clk_pcc4", + "sdmmc4_cmd_pt7", + "sdmmc4_dat7_paa7", + "pcc1", + "pbb6", + "pbb7", + "pcc2", + "jtag_rtck", + + "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7", + + "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row7_pr7", + "kb_row8_ps0", + "kb_row9_ps1", + "kb_row10_ps2", + "kb_row11_ps3", + "kb_row12_ps4", + "kb_row13_ps5", + "kb_row14_ps6", + + "kb_col0_pq0", + "kb_col1_pq1", + "kb_col2_pq2", + "kb_col5_pq5", + "kb_col6_pq6", + "kb_col7_pq7", + + "core_pwr_req", + "cpu_pwr_req", + "pwr_int_n", + "clk_32k_in", + "owr", + + "spdif_in_pk6", + "spdif_out_pk5", + "gpio_x1_aud_px1", + + "sdmmc3_clk_pa6", + "sdmmc3_dat0_pb7", + + "pex_l0_rst_n_pdd1", + "pex_l0_clkreq_n_pdd2", + "pex_wake_n_pdd3", + "pex_l1_rst_n_pdd5", + "pex_l1_clkreq_n_pdd6", + "hdmi_cec_pee3", + + "gpio_w2_aud_pw2", + "usb_vbus_en0_pn4", + "usb_vbus_en1_pn5", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5", + "gmi_clk_lb", + "reset_out_n", + "kb_row16_pt0", + "kb_row17_pt1", + "dp_hpd_pff0", + "usb_vbus_en2_pff1", + "pff2", +}; + +static const char * const rsvd3_groups[] = { + "dap3_sclk_pp3", + "pv0", + "pv1", + "sdmmc1_clk_pz0", + "clk2_out_pw5", + "clk2_req_pcc5", + "hdmi_int_pn7", + + "ddc_scl_pv4", + "ddc_sda_pv5", + + "pu6", + + "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5", + + "dap4_din_pp5", + "dap4_sclk_pp7", + + "clk3_out_pee0", + "clk3_req_pee1", + + "sdmmc4_dat5_paa5", + "gpio_pcc1", + "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2", + "pbb5", + "pbb7", + "jtag_rtck", + "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7", + + "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row4_pr4", + "kb_row5_pr5", + "kb_row9_ps1", + "kb_row10_ps2", + "kb_row11_ps3", + "kb_row12_ps4", + "kb_row15_ps7", + + "clk_32k_out_pa0", + "core_pwr_req", + "cpu_pwr_req", + "pwr_int_n", + "clk_32k_in", + "owr", + + "dap_mclk1_pw4", + "spdif_in_pk6", + "spdif_out_pk5", + "sdmmc3_clk_pa6", + "sdmmc3_dat0_pb7", + + "pex_l0_rst_n_pdd1", + "pex_l0_clkreq_n_pdd2", + "pex_wake_n_pdd3", + "pex_l1_rst_n_pdd5", + "pex_l1_clkreq_n_pdd6", + "hdmi_cec_pee3", + + "sdmmc3_cd_n_pv2", + "usb_vbus_en0_pn4", + "usb_vbus_en1_pn5", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5", + "reset_out_n", + "kb_row16_pt0", + "kb_row17_pt1", + "dp_hpd_pff0", + "usb_vbus_en2_pff1", + "pff2", +}; + +static const char * const rsvd4_groups[] = { + "dap3_dout_pp2", + "pv0", + "pv1", + "sdmmc1_clk_pz0", + + "clk2_out_pw5", + "clk2_req_pcc5", + "hdmi_int_pn7", + "ddc_scl_pv4", + "ddc_sda_pv5", + + "uart2_rts_n_pj6", + "uart2_cts_n_pj5", + "uart3_txd_pw6", + "uart3_rxd_pw7", + + "pu0", + "pu1", + "pu2", + + "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5", + + "dap4_fs_pp4", + "dap4_dout_pp6", + "dap4_din_pp5", + "dap4_sclk_pp7", + + "clk3_out_pee0", + "clk3_req_pee1", + + "pi5", + "pk1", + "pk2", + "pg0", + "pg1", + "pg2", + "pg3", + "ph4", + "ph5", + "pb0", + "pb1", + "pk7", + "pi0", + "pi1", + "pi2", + + "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6", + + "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7", + + "jtag_rtck", + "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7", + + "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row13_ps5", + "kb_row14_ps6", + "kb_row15_ps7", + + "kb_col0_pq0", + "kb_col1_pq1", + "kb_col2_pq2", + "kb_col5_pq5", + + "clk_32k_out_pa0", + "core_pwr_req", + "cpu_pwr_req", + "pwr_int_n", + "clk_32k_in", + "owr", + + "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_sclk_pn3", + "dap_mclk1_req_pee2", + "dap_mclk1_pw5", + + "dap2_fs_pa2", + "dap2_din_pa4", + "dap2_dout_pa5", + "dap2_sclk_pa3", + + "dvfs_pwm_px0", + "dvfs_clk_px2", + "gpio_x1_aud_px1", + "gpio_x3_aud_px3", + + "gpio_x5_aud_px5", + "gpio_x7_aud_px7", + + "pex_l0_rst_n_pdd1", + "pex_l0_clkreq_n_pdd2", + "pex_wake_n_pdd3", + "pex_l1_rst_n_pdd5", + "pex_l1_clkreq_n_pdd6", + "hdmi_cec_pee3", + + "sdmmc3_cd_n_pv2", + "usb_vbus_en0_pn4", + "usb_vbus_en1_pn5", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5", + "gmi_clk_lb", + + "dp_hpd_pff0", + "usb_vbus_en2_pff1", + "pff2", +}; + +static const char * const sdmmc1_groups[] = { + "sdmmc1_clk_pz0", + "sdmmc1_cmd_pz1", + "sdmmc1_dat3_py4", + "sdmmc1_dat2_py5", + "sdmmc1_dat1_py6", + "sdmmc1_dat0_py7", + "clk2_out_pw5", + "clk2_req_pcc", + "uart3_cts_n_pa1", + "sdmmc1_wp_n_pv3", +}; + +static const char * const sdmmc2_groups[] = { + "pi5", + "pk1", + "pk3", + "pk4", + "pi6", + "ph4", + "ph5", + "ph6", + "ph7", + "pi2", + "cam_mclk_pcc0", + "pcc1", + "pbb0", + "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2", + "pbb3", + "pbb4", + "pbb5", + "pbb6", + "pbb7", + "pcc2", + "gmi_clk_lb", +}; + +static const char * const sdmmc3_groups[] = { + "pk0", + "pcc2", + + "kb_col4_pq4", + "kb_col5_pq5", + + "sdmmc3_clk_pa6", + "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + + "sdmmc3_cd_n_pv2", + "sdmmc3_clk_lb_in_pee5", + "sdmmc3_clk_lb_out_pee4", +}; + +static const char * const sdmmc4_groups[] = { + "sdmmc4_clk_pcc4", + "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7", +}; + +static const char * const soc_groups[] = { + "pk0", + "pj2", + "kb_row15_ps7", + "clk_32k_out_pa0", +}; + +static const char * const spdif_groups[] = { + "sdmmc1_cmd_pz1", + "sdmmc1_dat3_py4", + "uart2_rxd_pc3", + "uart2_txd_pc2", + "spdif_in_pk6", + "spdif_out_pk5", +}; + +static const char * const spi1_groups[] = { + "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3", + "gpio_x3_aud_px3", + "gpio_x4_aud_px4", + "gpio_x5_aud_px5", + "gpio_x6_aud_px6", + "gpio_x7_aud_px7", + "gpio_w3_aud_pw3", +}; + +static const char * const spi2_groups[] = { + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0", + + "kb_row13_ps5", + "kb_row14_ps6", + "kb_row15_ps7", + "kb_col0_pq0", + "kb_col1_pq1", + "kb_col2_pq2", + "kb_col6_pq6", + "kb_col7_pq7", + "gpio_x4_aud_px4", + "gpio_x5_aud_px5", + "gpio_x6_aud_px6", + "gpio_x7_aud_px7", + "gpio_w2_aud_pw2", + "gpio_w3_aud_pw3", +}; + +static const char * const spi3_groups[] = { + "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc3_clk_pa6", + "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", +}; + +static const char * const spi4_groups[] = { + "sdmmc1_cmd_pz1", + "sdmmc1_dat3_py4", + "sdmmc1_dat2_py5", + "sdmmc1_dat1_py6", + "sdmmc1_dat0_py7", + + "uart2_rxd_pc3", + "uart2_txd_pc2", + "uart2_rts_n_pj6", + "uart2_cts_n_pj5", + "uart3_txd_pw6", + "uart3_rxd_pw7", + + "pi3", + "pg4", + "pg5", + "pg6", + "pg7", + "ph3", + "pi4", + "sdmmc1_wp_n_pv3", +}; + +static const char * const spi5_groups[] = { + "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3", + "dap3_fs_pp0", + "dap3_din_pp1", + "dap3_dout_pp2", + "dap3_sclk_pp3", +}; + +static const char * const spi6_groups[] = { + "dvfs_pwm_px0", + "gpio_x1_aud_px1", + "gpio_x3_aud_px3", + "dvfs_clk_px2", + "gpio_x6_aud_px6", + "gpio_w2_aud_pw2", + "gpio_w3_aud_pw3", +}; + +static const char * const trace_groups[] = { + "pi2", + "pi4", + "pi7", + "ph0", + "ph6", + "ph7", + "pg2", + "pg3", + "pk1", + "pk3", +}; + +static const char * const uarta_groups[] = { + "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0", + + "sdmmc1_cmd_pz1", + "sdmmc1_dat3_py4", + "sdmmc1_dat2_py5", + "sdmmc1_dat1_py6", + "sdmmc1_dat0_py7", + + + "uart2_rxd_pc3", + "uart2_txd_pc2", + "uart2_rts_n_pj6", + "uart2_cts_n_pj5", + + "pu0", + "pu1", + "pu2", + "pu3", + "pu4", + "pu5", + "pu6", + + "kb_row7_pr7", + "kb_row8_ps0", + "kb_row9_ps1", + "kb_row10_ps2", + "kb_col3_pq3", + "kb_col4_pq4", + + "sdmmc3_cmd_pa7", + "sdmmc3_dat1_pb6", + "sdmmc1_wp_n_pv3", + +}; + +static const char * const uartb_groups[] = { + "uart2_rts_n_pj6", + "uart2_cts_n_pj5", +}; + +static const char * const uartc_groups[] = { + "uart3_txd_pw6", + "uart3_rxd_pw7", + "uart3_cts_n_pa1", + "uart3_rts_n_pc0", + "kb_row16_pt0", + "kn_row17_pt1", +}; + +static const char * const uartd_groups[] = { + "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3", + "pj7", + "pb0", + "pb1", + "pk7", + "kb_col6_pq6", + "kb_col7_pq7", +}; + +static const char * const ulpi_groups[] = { + "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0", + "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3", +}; + +static const char * const usb_groups[] = { + "pj0", + "usb_vbus_en0_pn4", + "usb_vbus_en1_pn5", + "usb_vbus_en2_pff1", +}; + +static const char * const vgp1_groups[] = { + "cam_i2c_scl_pbb1", +}; + +static const char * const vgp2_groups[] = { + "cam_i2c_sda_pbb2", +}; + +static const char * const vgp3_groups[] = { + "pbb3", +}; + +static const char * const vgp4_groups[] = { + "pbb4", +}; + +static const char * const vgp5_groups[] = { + "pbb5", +}; + +static const char * const vgp6_groups[] = { + "pbb0", +}; + +static const char * const vi_groups[] = { + "cam_mclk_pcc0", +}; + +static const char * const vi_alt1_groups[] = { + "cam_mclk_pcc0", +}; + +static const char * const vi_alt3_groups[] = { + "cam_mclk_pcc0", +}; + +static const char * const vimclk2_groups[] = { + "pbb0", +}; + +static const char * const vimclk2_alt_groups[] = { + "pbb0", +}; + +static const char * const sata_groups[] = { + "dap_mclk1_req_pee2", + "dap1_dout_pn2", + "pff2", +}; + +static const char * const ccla_groups[] = { + "pk3", +}; + +static const char * const rtck_groups[] = { + "jtag_rtck", +}; + +static const char * const sys_groups[] = { + "kb_row3_pr3", +}; + +static const char * const pe0_groups[] = { + "pex_l0_rst_n_pdd1", + "pex_l0_clkreq_n_pdd2", +}; + +static const char * const pe_groups[] = { + "pex_wake_n_pdd3", +}; + +static const char * const pe1_groups[] = { + "pex_l1_rst_n_pdd5", + "pex_l1_clkreq_n_pdd6", +}; + +static const char * const dp_groups[] = { + "dp_hpd_pff0", +}; + +static const char * const clk_groups[] = { + "clk_32k_in", +}; + +static const char * const tmds_groups[] = { + "pg4", + "ph1", + "ph2", +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct tegra_function tegra124_functions[] = { + FUNCTION(blink), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk12), + FUNCTION(cpu), + FUNCTION(dap), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displaya_alt), + FUNCTION(displayb), + FUNCTION(dtv), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(owr), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwron), + FUNCTION(reset_out_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(soc), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(ulpi), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt3), + FUNCTION(vimclk2), + FUNCTION(vimclk2_alt), + FUNCTION(sata), + FUNCTION(ccla), + FUNCTION(pe0), + FUNCTION(pe), + FUNCTION(pe1), + FUNCTION(dp), + FUNCTION(rtck), + FUNCTION(sys), + FUNCTION(clk), + FUNCTION(tmds), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A) +#define PINGROUP_REG_N(r) -1 + +#define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior, rcv_sel) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_ ## f0, \ + TEGRA_MUX_ ## f1, \ + TEGRA_MUX_ ## f2, \ + TEGRA_MUX_ ## f3, \ + }, \ + .func_safe = TEGRA_MUX_ ## f_safe, \ + .mux_reg = PINGROUP_REG_Y(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG_Y(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG_Y(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_reg = PINGROUP_REG_Y(r), \ + .einput_bank = 1, \ + .einput_bit = 5, \ + .odrain_reg = PINGROUP_REG_##od(r), \ + .odrain_bank = 1, \ + .odrain_bit = 6, \ + .lock_reg = PINGROUP_REG_Y(r), \ + .lock_bank = 1, \ + .lock_bit = 7, \ + .ioreset_reg = PINGROUP_REG_##ior(r), \ + .ioreset_bank = 1, \ + .ioreset_bit = 8, \ + .rcv_sel_reg = PINGROUP_REG_##rcv_sel(r), \ + .rcv_sel_bank = 1, \ + .rcv_sel_bit = 9, \ + .drv_reg = -1, \ + .drvtype_reg = -1, \ + } + +#define DRV_PINGROUP_DVRTYPE_Y(r) ((r) - DRV_PINGROUP_REG_A) +#define DRV_PINGROUP_DVRTYPE_N(r) -1 + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, \ + drvdn_b, drvdn_w, drvup_b, drvup_w, \ + slwr_b, slwr_w, slwf_b, slwf_w, \ + drvtype) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_reg = -1, \ + .odrain_reg = -1, \ + .lock_reg = -1, \ + .ioreset_reg = -1, \ + .rcv_sel_reg = -1, \ + .drv_reg = DRV_PINGROUP_DVRTYPE_Y(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_reg = DRV_PINGROUP_DVRTYPE_##drvtype(r), \ + .drvtype_bank = 0, \ + .drvtype_bit = 6, \ + } + +static const struct tegra_pingroup tegra124_groups[] = { + /* pg_name, f0, f1, f2, f3, safe, r, od, ior, rcv_sel */ + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, SPI3, 0x3000, N, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, SPI3, 0x3004, N, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, SPI3, 0x3008, N, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, SPI3, 0x300c, N, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, SPI2, 0x3010, N, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, SPI2, 0x3014, N, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, SPI2, 0x3018, N, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, SPI2, 0x301c, N, N, N), + PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, SPI1, 0x3020, N, N, N), + PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, SPI1, 0x3024, N, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, SPI1, 0x3028, N, N, N), + PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, SPI1, 0x302c, N, N, N), + PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, I2S2, 0x3030, N, N, N), + PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, I2S2, 0x3034, N, N, N), + PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, RSVD4, I2S2, 0x3038, N, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, SPI5, RSVD3, DISPLAYB, I2S2, 0x303c, N, N, N), + PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, RSVD1, 0x3040, N, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, RSVD1, 0x3044, N, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, RSVD3, 0x3048, N, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, SDMMC1, 0x304c, N, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, SDMMC1, 0x3050, N, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, SDMMC1, 0x3054, N, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, SDMMC1, 0x3058, N, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, SDMMC1, 0x305c, N, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, EXTPERIPH2, 0x3068, N, N, N), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, DAP, 0x306c, N, N, N), + PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, RSVD1, 0x3110, N, N, Y), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, I2C4, 0x3114, N, N, Y), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, I2C4, 0x3118, N, N, Y), + PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, IRDA, 0x3164, N, N, N), + PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, IRDA, 0x3168, N, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, UARTA, 0x316c, N, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, UARTA, 0x3170, N, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, SPI4, UARTC, 0x3174, N, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, SPI4, UARTC, 0x3178, N, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, GMI, UARTC, 0x317c, N, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, GMI, UARTC, 0x3180, N, N, N), + PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, RSVD4, 0x3184, N, N, N), + PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, RSVD4, 0x3188, N, N, N), + PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, RSVD4, 0x318c, N, N, N), + PINGROUP(pu3, PWM0, UARTA, GMI, DISPLAYB, PWM0, 0x3190, N, N, N), + PINGROUP(pu4, PWM1, UARTA, GMI, DISPLAYB, PWM1, 0x3194, N, N, N), + PINGROUP(pu5, PWM2, UARTA, GMI, DISPLAYB, PWM2, 0x3198, N, N, N), + PINGROUP(pu6, PWM3, UARTA, RSVD3, GMI, RSVD3, 0x319c, N, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, I2C1, 0x31a0, Y, N, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, I2C1, 0x31a4, Y, N, N), + PINGROUP(dap4_fs_pp4, I2S3, GMI, DTV, RSVD4, I2S3, 0x31a8, N, N, N), + PINGROUP(dap4_din_pp5, I2S3, GMI, RSVD3, RSVD4, I2S3, 0x31ac, N, N, N), + PINGROUP(dap4_dout_pp6, I2S3, GMI, DTV, RSVD4, I2S3, 0x31b0, N, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, GMI, RSVD3, RSVD4, I2S3, 0x31b4, N, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, RSVD3, 0x31b8, N, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, RSVD4, 0x31bc, N, N, N), + PINGROUP(pc7, RSVD1, RSVD2, GMI, GMI_ALT, RSVD1, 0x31c0, N, N, N), + PINGROUP(pi5, SDMMC2, RSVD2, GMI, RSVD4, GMI, 0x31c4, N, N, N), + PINGROUP(pi7, RSVD1, TRACE, GMI, DTV, RSVD1, 0x31c8, N, N, N), + PINGROUP(pk0, RSVD1, SDMMC3, GMI, SOC, RSVD1, 0x31cc, N, N, N), + PINGROUP(pk1, SDMMC2, TRACE, GMI, RSVD4, GMI, 0x31d0, N, N, N), + PINGROUP(pj0, RSVD1, RSVD2, GMI, USB, RSVD1, 0x31d4, N, N, N), + PINGROUP(pj2, RSVD1, RSVD2, GMI, SOC, RSVD1, 0x31d8, N, N, N), + PINGROUP(pk3, SDMMC2, TRACE, GMI, CCLA, GMI, 0x31dc, N, N, N), + PINGROUP(pk4, SDMMC2, RSVD2, GMI, GMI_ALT, GMI, 0x31e0, N, N, N), + PINGROUP(pk2, RSVD1, RSVD2, GMI, RSVD4, RSVD4, 0x31e4, N, N, N), + PINGROUP(pi3, RSVD1, RSVD2, GMI, SPI4, RSVD1, 0x31e8, N, N, N), + PINGROUP(pi6, RSVD1, RSVD2, GMI, SDMMC2, RSVD1, 0x31ec, N, N, N), + PINGROUP(pg0, RSVD1, RSVD2, GMI, RSVD4, RSVD4, 0x31f0, N, N, N), + PINGROUP(pg1, RSVD1, RSVD2, GMI, RSVD4, RSVD4, 0x31f4, N, N, N), + PINGROUP(pg2, RSVD1, TRACE, GMI, RSVD4, RSVD4, 0x31f8, N, N, N), + PINGROUP(pg3, RSVD1, TRACE, GMI, RSVD4, RSVD4, 0x31fc, N, N, N), + PINGROUP(pg4, RSVD1, TMDS, GMI, SPI4, RSVD1, 0x3200, N, N, N), + PINGROUP(pg5, RSVD1, RSVD2, GMI, SPI4, RSVD1, 0x3204, N, N, N), + PINGROUP(pg6, RSVD1, RSVD2, GMI, SPI4, RSVD1, 0x3208, N, N, N), + PINGROUP(pg7, RSVD1, RSVD2, GMI, SPI4, RSVD1, 0x320c, N, N, N), + PINGROUP(ph0, PWM0, TRACE, GMI, DTV, GMI, 0x3210, N, N, N), + PINGROUP(ph1, PWM1, TMDS, GMI, DISPLAYA, GMI, 0x3214, N, N, N), + PINGROUP(ph2, PWM2, TMDS, GMI, CLDVFS, GMI, 0x3218, N, N, N), + PINGROUP(ph3, PWM3, SPI4, GMI, CLDVFS, GMI, 0x321c, N, N, N), + PINGROUP(ph4, SDMMC2, RSVD2, GMI, RSVD4, GMI, 0x3220, N, N, N), + PINGROUP(ph5, SDMMC2, RSVD2, GMI, RSVD4, GMI, 0x3224, N, N, N), + PINGROUP(ph6, SDMMC2, TRACE, GMI, DTV, GMI, 0x3228, N, N, N), + PINGROUP(ph7, SDMMC2, TRACE, GMI, DTV, GMI, 0x322c, N, N, N), + PINGROUP(pj7, UARTD, RSVD2, GMI, GMI_ALT, RSVD2, 0x3230, N, N, N), + PINGROUP(pb0, UARTD, RSVD2, GMI, RSVD4, RSVD2, 0x3234, N, N, N), + PINGROUP(pb1, UARTD, RSVD2, GMI, RSVD4, RSVD2, 0x3238, N, N, N), + PINGROUP(pk7, UARTD, RSVD2, GMI, RSVD4, RSVD2, 0x323c, N, N, N), + PINGROUP(pi0, RSVD1, RSVD2, GMI, RSVD4, RSVD4, 0x3240, N, N, N), + PINGROUP(pi1, RSVD1, RSVD2, GMI, RSVD4, RSVD1, 0x3244, N, N, N), + PINGROUP(pi2, SDMMC2, TRACE, GMI, RSVD4, GMI, 0x3248, N, N, N), + PINGROUP(pi4, SPI4, TRACE, GMI, DISPLAYA, GMI, 0x324c, N, N, N), + PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, RSVD2, 0x3250, Y, N, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, RSVD2, 0x3254, Y, N, N), + PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, RSVD2, 0x3258, N, Y, N), + PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, RSVD2, 0x325c, N, Y, N), + PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, SDMMC4, 0x3260, N, Y, N), + PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, SDMMC4, 0x3264, N, Y, N), + PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, SDMMC4, 0x3268, N, Y, N), + PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, SDMMC4, 0x326c, N, Y, N), + PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, SDMMC4, 0x3270, N, Y, N), + PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, RSVD3, RSVD4, SDMMC4, 0x3274, N, Y, N), + PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, SDMMC4, 0x3278, N, Y, N), + PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD1, GMI, RSVD4, SDMMC4, 0x327c, N, Y, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC2, VI, 0x3284, N, N, N), + PINGROUP(pcc1, I2S4, RSVD1, RSVD3, SDMMC2, I2S4, 0x3288, N, N, N), + PINGROUP(pbb0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT, VGP6, 0x328c, N, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC2, VGP1, 0x3290, Y, N, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC2, VGP2, 0x3294, Y, N, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC2, VGP3, 0x3298, N, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC2, VGP4, 0x329c, N, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, RSVD3, SDMMC2, VGP5, 0x32a0, N, N, N), + PINGROUP(pbb6, I2S4, RSVD2, DISPLAYB, SDMMC2, I2S4, 0x32a4, N, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC2, I2S4, 0x32a8, N, N, N), + PINGROUP(pcc2, I2S4, RSVD2, SDMMC3, SDMMC2, I2S4, 0x32ac, N, N, N), + PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, RTCK, 0x32b0, N, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, RSVD2, 0x32b4, Y, N, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, RSVD2, 0x32b8, Y, N, N), + PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, RSVD4, 0x32bc, N, N, N), + PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, RSVD4, 0x32c0, N, N, N), + PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, RSVD4, 0x32c4, N, N, N), + PINGROUP(kb_row3_pr3, KBC, DISPLAYA, SYS, DISPLAYB, KBC, 0x32c8, N, N, N), + PINGROUP(kb_row4_pr4, KBC, DISPLAYA, RSVD3, DISPLAYB, RSVD3, 0x32cc, N, N, N), + PINGROUP(kb_row5_pr5, KBC, DISPLAYA, RSVD3, DISPLAYB, RSVD3, 0x32d0, N, N, N), + PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, KBC, 0x32d4, N, N, N), + PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, RSVD2, 0x32d8, N, N, N), + PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, RSVD2, 0x32dc, N, N, N), + PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, KBC, 0x32e0, N, N, N), + PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, KBC, 0x32e4, N, N, N), + PINGROUP(kb_row11_ps3, KBC, RSVD2, RSVD3, IRDA, RSVD3, 0x32e8, N, N, N), + PINGROUP(kb_row12_ps4, KBC, RSVD2, RSVD3, IRDA, RSVD3, 0x32ec, N, N, N), + PINGROUP(kb_row13_ps5, KBC, RSVD2, SPI2, RSVD4, RSVD4, 0x32f0, N, N, N), + PINGROUP(kb_row14_ps6, KBC, RSVD2, SPI2, RSVD4, RSVD4, 0x32f4, N, N, N), + PINGROUP(kb_row15_ps7, KBC, SOC, RSVD3, RSVD4, KBC, 0x32f8, N, N, N), + PINGROUP(kb_col0_pq0, KBC, RSVD2, SPI2, RSVD4, RSVD4, 0x32fc, N, N, N), + PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, RSVD4, RSVD4, 0x3300, N, N, N), + PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, RSVD4, 0x3304, N, N, N), + PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, KBC, 0x3308, N, N, N), + PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, KBC, 0x330c, N, N, N), + PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC3, RSVD4, RSVD4, 0x3310, N, N, N), + PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, UARTD, RSVD2, 0x3314, N, N, N), + PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, UARTD, RSVD2, 0x3318, N, N, N), + PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, RSVD3, 0x331c, N, N, N), + PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, RSVD2, 0x3324, N, N, N), + PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, RSVD2, 0x3328, N, N, N), + PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, RSVD2, 0x332c, N, N, N), + PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, RSVD2, 0x3330, N, N, N), + PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, RSVD2, 0x3334, N, N, Y), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, RSVD4, 0x3338, N, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, RSVD4, 0x333c, N, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SATA, I2S0, 0x3340, N, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, I2S0, 0x3344, N, N, N), + PINGROUP(dap_mclk1_req_pee2, DAP, DAP1, SATA, RSVD4, DAP, 0x3348, N, N, N), + PINGROUP(dap_mclk1_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, RSVD3, 0x334c, N, N, N), + PINGROUP(spdif_in_pk6, SPDIF, RSVD2, RSVD3, I2C3, RSVD3, 0x3350, N, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, I2C3, RSVD3, 0x3354, N, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, GMI, RSVD4, I2S1, 0x3358, N, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, GMI, RSVD4, I2S1, 0x335c, N, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, GMI, RSVD4, I2S1, 0x3360, N, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, GMI, RSVD4, I2S1, 0x3364, N, N, N), + PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, GMI, RSVD4, SPI6, 0x3368, N, N, N), + PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, GMI, RSVD4, SPI6, 0x336c, N, N, N), + PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, GMI, RSVD4, SPI6, 0x3370, N, N, N), + PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, GMI, RSVD4, SPI6, 0x3374, N, N, N), + PINGROUP(gpio_x4_aud_px4, GMI, SPI1, SPI2, DAP2, SPI1, 0x3378, N, N, N), + PINGROUP(gpio_x5_aud_px5, GMI, SPI1, SPI2, RSVD4, SPI1, 0x337c, N, N, N), + PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, GMI, SPI1, 0x3380, N, N, N), + PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, SPI1, 0x3384, N, N, N), + PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, SDMMC3, 0x3390, N, N, N), + PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, SDMMC3, 0x3394, N, N, N), + PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, SDMMC3, 0x3398, N, N, N), + PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, SDMMC3, 0x339c, N, N, N), + PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, SDMMC3, 0x33a0, N, N, N), + PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, SDMMC3, 0x33a4, N, N, N), + PINGROUP(pex_l0_rst_n_pdd1, PE0, RSVD2, RSVD3, RSVD4, PE0, 0x33bc, N, N, N), + PINGROUP(pex_l0_clkreq_n_pdd2, PE0, RSVD2, RSVD3, RSVD4, PE0, 0x33c0, N, N, N), + PINGROUP(pex_wake_n_pdd3, PE, RSVD2, RSVD3, RSVD4, PE, 0x33c4, N, N, N), + PINGROUP(pex_l1_rst_n_pdd5, PE1, RSVD2, RSVD3, RSVD4, PE1, 0x33cc, N, N, N), + PINGROUP(pex_l1_clkreq_n_pdd6, PE1, RSVD2, RSVD3, RSVD4, PE1, 0x33d0, N, N, N), + PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, CEC, 0x33e0, Y, N, N), + PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, SDMMC1, 0x33e4, N, N, N), + PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, SDMMC3, 0x33e8, N, N, N), + PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, RSVD2, 0x33ec, N, N, N), + PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, SPI1, 0x33f0, N, N, N), + PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, USB, 0x33f4, Y, N, N), + PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, USB, 0x33f8, Y, N, N), + PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, SDMMC3, 0x33fc, N, N, N), + PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, SDMMC3, 0x3400, N, N, N), + PINGROUP(gmi_clk_lb, SDMMC2, RSVD2, GMI, RSVD4, SDMMC2, 0x3404, N, N, N), + PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, RSVD1, 0x3408, N, N, N), + PINGROUP(kb_row16_pt0, KBC, RSVD2, RSVD3, UARTC, KBC, 0x340c, N, N, N), + PINGROUP(kb_row17_pt1, KBC, RSVD2, RSVD3, UARTC, KBC, 0x3410, N, N, N), + PINGROUP(usb_vbus_en2_pff1, USB, RSVD2, RSVD3, RSVD4, USB, 0x3414, Y, N, N), + PINGROUP(pff2, SATA, RSVD2, RSVD3, RSVD4, RSVD2, 0x3418, Y, N, N), + PINGROUP(dp_hpd_pff0, DP, RSVD2, RSVD3, RSVD4, DP, 0x3430, N, N, N), + + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at1, 0x870, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at2, 0x874, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at3, 0x878, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gma, 0x900, 2, 3, 4, 14, 5, 20, 5, 28, 2, 30, 2, Y), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao3, 0x9a8, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(ao0, 0x9b0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(hv0, 0x9b4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(sdio4, 0x9c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), +}; + +static const struct tegra_pinctrl_soc_data tegra124_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra124_pins, + .npins = ARRAY_SIZE(tegra124_pins), + .functions = tegra124_functions, + .nfunctions = ARRAY_SIZE(tegra124_functions), + .groups = tegra124_groups, + .ngroups = ARRAY_SIZE(tegra124_groups), +}; + +static int tegra124_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra124_pinctrl); +} + +static struct of_device_id tegra124_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra124-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match); + +static struct platform_driver tegra124_pinctrl_driver = { + .driver = { + .name = "tegra124-pinctrl", + .owner = THIS_MODULE, + .of_match_table = tegra124_pinctrl_of_match, + }, + .probe = tegra124_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra124_pinctrl_driver); + +MODULE_AUTHOR("Ashwini Ghuge "); +MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 993495ae992c91e98ade8fbe977c57bfd81910c1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 12 Dec 2013 17:27:40 +0200 Subject: drm/i915: Rework the FBC interval/stall stuff a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't touch DPFC_RECOMP_CTL on FBC2, use RMW to update the FBC_CONTROL on FBC1 to make it easier for people to experiment with different numbers. Also fix the interval mask for FBC1. v2: Rebased Reviewed-by: Imre Deak Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 +-- drivers/gpu/drm/i915/intel_pm.c | 34 ++++++++++++++-------------------- 2 files changed, 15 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 709b20e0e3f0..ae2c80c1981b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -372,7 +372,7 @@ struct dpll; struct drm_i915_display_funcs { bool (*fbc_enabled)(struct drm_device *dev); - void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval); + void (*enable_fbc)(struct drm_crtc *crtc); void (*disable_fbc)(struct drm_device *dev); int (*get_display_clock_speed)(struct drm_device *dev); int (*get_fifo_size)(struct drm_device *dev, int plane); @@ -695,7 +695,6 @@ struct i915_fbc { struct delayed_work work; struct drm_crtc *crtc; struct drm_framebuffer *fb; - int interval; } *fbc_work; enum no_fbc_reason { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d7cb6bf5712d..c68abf718825 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -88,7 +88,7 @@ static void i8xx_disable_fbc(struct drm_device *dev) DRM_DEBUG_KMS("disabled FBC\n"); } -static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +static void i8xx_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -126,11 +126,12 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) } /* enable it... */ - fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; + fbc_ctl = I915_READ(FBC_CONTROL); + fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT; + fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC; if (IS_I945GM(dev)) fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; - fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; fbc_ctl |= obj->fence_reg; I915_WRITE(FBC_CONTROL, fbc_ctl); @@ -145,7 +146,7 @@ static bool i8xx_fbc_enabled(struct drm_device *dev) return I915_READ(FBC_CONTROL) & FBC_CTL_EN; } -static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +static void g4x_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -154,16 +155,12 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; - unsigned long stall_watermark = 200; u32 dpfc_ctl; dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); - I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | - (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | - (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); I915_WRITE(DPFC_FENCE_YOFF, crtc->y); /* enable it... */ @@ -219,7 +216,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA); } -static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +static void ironlake_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -228,7 +225,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; - unsigned long stall_watermark = 200; u32 dpfc_ctl; dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); @@ -241,9 +237,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) dpfc_ctl |= obj->fence_reg; I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); - I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | - (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | - (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); /* enable it... */ @@ -281,7 +274,7 @@ static bool ironlake_fbc_enabled(struct drm_device *dev) return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; } -static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +static void gen7_enable_fbc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -338,8 +331,7 @@ static void intel_fbc_work_fn(struct work_struct *__work) * the prior work. */ if (work->crtc->fb == work->fb) { - dev_priv->display.enable_fbc(work->crtc, - work->interval); + dev_priv->display.enable_fbc(work->crtc); dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane; dev_priv->fbc.fb_id = work->crtc->fb->base.id; @@ -376,7 +368,7 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) dev_priv->fbc.fbc_work = NULL; } -static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +static void intel_enable_fbc(struct drm_crtc *crtc) { struct intel_fbc_work *work; struct drm_device *dev = crtc->dev; @@ -390,13 +382,12 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) { DRM_ERROR("Failed to allocate FBC work structure\n"); - dev_priv->display.enable_fbc(crtc, interval); + dev_priv->display.enable_fbc(crtc); return; } work->crtc = crtc; work->fb = crtc->fb; - work->interval = interval; INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); dev_priv->fbc.fbc_work = work; @@ -611,7 +602,7 @@ void intel_update_fbc(struct drm_device *dev) intel_disable_fbc(dev); } - intel_enable_fbc(crtc, 500); + intel_enable_fbc(crtc); dev_priv->fbc.no_fbc_reason = FBC_OK; return; @@ -6073,6 +6064,9 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.fbc_enabled = i8xx_fbc_enabled; dev_priv->display.enable_fbc = i8xx_enable_fbc; dev_priv->display.disable_fbc = i8xx_disable_fbc; + + /* This value was pulled out of someone's hat */ + I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT); } } -- cgit v1.2.3 From 168c3f2151a7de906b060a335d19b0ba483a6718 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Thu, 12 Dec 2013 17:54:42 +0200 Subject: drm/i915: dont call irq_put when irq test is on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If test is running, irq_get was not called so we should gain balance by not doing irq_put "So the rule is: if you access unlocked values, you use ACCESS_ONCE(). You don't say "but it can't matter". Because you simply don't know." -- Linus v2: use local variable so it can't change during test (Chris) v3: update commit msg and use ACCESS_ONCE (Ville) Signed-off-by: Mika Kuoppala Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 279387a2fef5..e34b48e862e7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1015,6 +1015,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, struct drm_i915_file_private *file_priv) { drm_i915_private_t *dev_priv = ring->dev->dev_private; + const bool irq_test_in_progress = + ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring); struct timespec before, now; DEFINE_WAIT(wait); unsigned long timeout_expire; @@ -1035,8 +1037,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, msecs_to_jiffies(100)); } - if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) && - WARN_ON(!ring->irq_get(ring))) + if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) return -ENODEV; /* Record current time in case interrupted by signal, or wedged */ @@ -1093,7 +1094,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, getrawmonotonic(&now); trace_i915_gem_request_wait_end(ring, seqno); - ring->irq_put(ring); + if (!irq_test_in_progress) + ring->irq_put(ring); finish_wait(&ring->irq_queue, &wait); -- cgit v1.2.3 From 74cd60a4d7b4f686146efd7ed211974691f0c2c1 Mon Sep 17 00:00:00 2001 From: Jon Cooper Date: Mon, 16 Sep 2013 14:18:51 +0100 Subject: sfc: Add MC BISTs to ethtool offline self test on EF10 To run BISTs the MC goes down in to a special mode where it will only respond to MCDI from the testing PF, and TX, RX and event queues are torn down. Other PFs get a message as it goes down to tell them it's going down. When the other PFs get this message, they check the soft status register to tell when the MC has rebooted after BIST mode and they can start recovery. [bwh: Convert the test result to 1 or -1 as for earlier NICs] Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 84 ++++++++++++++++++++++++++++++++++- drivers/net/ethernet/sfc/efx.c | 29 ++++++++++++ drivers/net/ethernet/sfc/enum.h | 1 + drivers/net/ethernet/sfc/ethtool.c | 2 + drivers/net/ethernet/sfc/mcdi.c | 34 ++++++++++++++ drivers/net/ethernet/sfc/net_driver.h | 1 + drivers/net/ethernet/sfc/selftest.c | 2 +- drivers/net/ethernet/sfc/selftest.h | 1 + 8 files changed, 152 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 676c3c057bfb..5d46d155b642 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -14,6 +14,7 @@ #include "mcdi_pcol.h" #include "nic.h" #include "workarounds.h" +#include "selftest.h" #include #include #include @@ -3195,6 +3196,87 @@ static int efx_ef10_mac_reconfigure(struct efx_nic *efx) return efx_mcdi_set_mac(efx); } +static int efx_ef10_start_bist(struct efx_nic *efx, u32 bist_type) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN); + + MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_type); + return efx_mcdi_rpc(efx, MC_CMD_START_BIST, inbuf, sizeof(inbuf), + NULL, 0, NULL); +} + +/* MC BISTs follow a different poll mechanism to phy BISTs. + * The BIST is done in the poll handler on the MC, and the MCDI command + * will block until the BIST is done. + */ +static int efx_ef10_poll_bist(struct efx_nic *efx) +{ + int rc; + MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_LEN); + size_t outlen; + u32 result; + + rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0, + outbuf, sizeof(outbuf), &outlen); + if (rc != 0) + return rc; + + if (outlen < MC_CMD_POLL_BIST_OUT_LEN) + return -EIO; + + result = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT); + switch (result) { + case MC_CMD_POLL_BIST_PASSED: + netif_dbg(efx, hw, efx->net_dev, "BIST passed.\n"); + return 0; + case MC_CMD_POLL_BIST_TIMEOUT: + netif_err(efx, hw, efx->net_dev, "BIST timed out\n"); + return -EIO; + case MC_CMD_POLL_BIST_FAILED: + netif_err(efx, hw, efx->net_dev, "BIST failed.\n"); + return -EIO; + default: + netif_err(efx, hw, efx->net_dev, + "BIST returned unknown result %u", result); + return -EIO; + } +} + +static int efx_ef10_run_bist(struct efx_nic *efx, u32 bist_type) +{ + int rc; + + netif_dbg(efx, drv, efx->net_dev, "starting BIST type %u\n", bist_type); + + rc = efx_ef10_start_bist(efx, bist_type); + if (rc != 0) + return rc; + + return efx_ef10_poll_bist(efx); +} + +static int +efx_ef10_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) +{ + int rc, rc2; + + efx_reset_down(efx, RESET_TYPE_WORLD); + + rc = efx_mcdi_rpc(efx, MC_CMD_ENABLE_OFFLINE_BIST, + NULL, 0, NULL, 0, NULL); + if (rc != 0) + goto out; + + tests->memory = efx_ef10_run_bist(efx, MC_CMD_MC_MEM_BIST) ? -1 : 1; + tests->registers = efx_ef10_run_bist(efx, MC_CMD_REG_BIST) ? -1 : 1; + + rc = efx_mcdi_reset(efx, RESET_TYPE_WORLD); + +out: + rc2 = efx_reset_up(efx, RESET_TYPE_WORLD, rc == 0); + return rc ? rc : rc2; +} + #ifdef CONFIG_SFC_MTD struct efx_ef10_nvram_type_info { @@ -3345,7 +3427,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .get_wol = efx_ef10_get_wol, .set_wol = efx_ef10_set_wol, .resume_wol = efx_port_dummy_op_void, - /* TODO: test_chip */ + .test_chip = efx_ef10_test_chip, .test_nvram = efx_mcdi_nvram_test_all, .mcdi_request = efx_ef10_mcdi_request, .mcdi_poll_response = efx_ef10_mcdi_poll_response, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index a35c63d43ae5..869418164364 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -83,6 +83,7 @@ const char *const efx_reset_type_names[] = { [RESET_TYPE_DMA_ERROR] = "DMA_ERROR", [RESET_TYPE_TX_SKIP] = "TX_SKIP", [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", + [RESET_TYPE_MC_BIST] = "MC_BIST", }; /* Reset workqueue. If any NIC has a hardware failure then a reset will be @@ -91,6 +92,12 @@ const char *const efx_reset_type_names[] = { */ static struct workqueue_struct *reset_workqueue; +/* How often and how many times to poll for a reset while waiting for a + * BIST that another function started to complete. + */ +#define BIST_WAIT_DELAY_MS 100 +#define BIST_WAIT_DELAY_COUNT 100 + /************************************************************************** * * Configurable values @@ -2389,6 +2396,24 @@ int efx_try_recovery(struct efx_nic *efx) return 0; } +static void efx_wait_for_bist_end(struct efx_nic *efx) +{ + int i; + + for (i = 0; i < BIST_WAIT_DELAY_COUNT; ++i) { + if (efx_mcdi_poll_reboot(efx)) + goto out; + msleep(BIST_WAIT_DELAY_MS); + } + + netif_err(efx, drv, efx->net_dev, "Warning: No MC reboot after BIST mode\n"); +out: + /* Either way unset the BIST flag. If we found no reboot we probably + * won't recover, but we should try. + */ + efx->mc_bist_for_other_fn = false; +} + /* The worker thread exists so that code that cannot sleep can * schedule a reset for later. */ @@ -2401,6 +2426,9 @@ static void efx_reset_work(struct work_struct *data) pending = ACCESS_ONCE(efx->reset_pending); method = fls(pending) - 1; + if (method == RESET_TYPE_MC_BIST) + efx_wait_for_bist_end(efx); + if ((method == RESET_TYPE_RECOVER_OR_DISABLE || method == RESET_TYPE_RECOVER_OR_ALL) && efx_try_recovery(efx)) @@ -2439,6 +2467,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) case RESET_TYPE_WORLD: case RESET_TYPE_DISABLE: case RESET_TYPE_RECOVER_OR_DISABLE: + case RESET_TYPE_MC_BIST: method = type; netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", RESET_TYPE(method)); diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h index 7fdfee019092..75ef7ef6450b 100644 --- a/drivers/net/ethernet/sfc/enum.h +++ b/drivers/net/ethernet/sfc/enum.h @@ -165,6 +165,7 @@ enum reset_type { RESET_TYPE_DMA_ERROR, RESET_TYPE_TX_SKIP, RESET_TYPE_MC_FAILURE, + RESET_TYPE_MC_BIST, RESET_TYPE_MAX, }; diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 1f529fa2edb1..fb8993806167 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -318,6 +318,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, "eventq.int", NULL); } + efx_fill_test(n++, strings, data, &tests->memory, + "core", 0, "memory", NULL); efx_fill_test(n++, strings, data, &tests->registers, "core", 0, "registers", NULL); diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 25f91c0ca6a6..da14e2428944 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -543,6 +543,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, if (rc) return rc; + if (efx->mc_bist_for_other_fn) + return -ENETDOWN; + efx_mcdi_acquire_sync(mcdi); efx_mcdi_send_request(efx, cmd, inbuf, inlen); return 0; @@ -581,6 +584,9 @@ efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, if (rc) return rc; + if (efx->mc_bist_for_other_fn) + return -ENETDOWN; + async = kmalloc(sizeof(*async) + ALIGN(max(inlen, outlen), 4), GFP_ATOMIC); if (!async) @@ -834,6 +840,30 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc) spin_unlock(&mcdi->iface_lock); } +/* The MC is going down in to BIST mode. set the BIST flag to block + * new MCDI, cancel any outstanding MCDI and and schedule a BIST-type reset + * (which doesn't actually execute a reset, it waits for the controlling + * function to reset it). + */ +static void efx_mcdi_ev_bist(struct efx_nic *efx) +{ + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + + spin_lock(&mcdi->iface_lock); + efx->mc_bist_for_other_fn = true; + if (efx_mcdi_complete_sync(mcdi)) { + if (mcdi->mode == MCDI_MODE_EVENTS) { + mcdi->resprc = -EIO; + mcdi->resp_hdr_len = 0; + mcdi->resp_data_len = 0; + ++mcdi->credits; + } + } + mcdi->new_epoch = true; + efx_schedule_reset(efx, RESET_TYPE_MC_BIST); + spin_unlock(&mcdi->iface_lock); +} + /* Called from falcon_process_eventq for MCDI events */ void efx_mcdi_process_event(struct efx_channel *channel, efx_qword_t *event) @@ -875,6 +905,10 @@ void efx_mcdi_process_event(struct efx_channel *channel, netif_info(efx, hw, efx->net_dev, "MC Reboot\n"); efx_mcdi_ev_death(efx, -EIO); break; + case MCDI_EVENT_CODE_MC_BIST: + netif_info(efx, hw, efx->net_dev, "MC entered BIST mode\n"); + efx_mcdi_ev_bist(efx); + break; case MCDI_EVENT_CODE_MAC_STATS_DMA: /* MAC stats are gather lazily. We can ignore this. */ break; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 542a0d252ae0..d98b3f031ab5 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -852,6 +852,7 @@ struct efx_nic { struct work_struct mac_work; bool port_enabled; + bool mc_bist_for_other_fn; bool port_initialized; struct net_device *net_dev; diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 144bbff5a4ae..26641817a9c7 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -722,7 +722,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, return rc_reset; } - if ((tests->registers < 0) && !rc_test) + if ((tests->memory < 0 || tests->registers < 0) && !rc_test) rc_test = -EIO; } diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h index a2f4a06ffa4e..009dbe88f3be 100644 --- a/drivers/net/ethernet/sfc/selftest.h +++ b/drivers/net/ethernet/sfc/selftest.h @@ -38,6 +38,7 @@ struct efx_self_tests { int eventq_dma[EFX_MAX_CHANNELS]; int eventq_int[EFX_MAX_CHANNELS]; /* offline tests */ + int memory; int registers; int phy_ext[EFX_MAX_PHY_TESTS]; struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; -- cgit v1.2.3 From 92a04168390a2cb67cb60891e5870626d58c2abb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 24 Sep 2013 23:21:57 +0100 Subject: sfc: Tighten the check for RX merged completion events The addition of RX event merging support means we don't reliably detect dropped RX events now. Currently we will only detect them if the previous event for the RX queue had the CONT bit set. Only accept RX completion events as merged if the GET_CAPABILITIES_OUT_RX_BATCHING bit is set in datapath_caps (which it won't be for the low-latency datapath) and the CONT bit is not set on the event. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 5d46d155b642..2f77359607d2 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1766,6 +1766,8 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel, ((1 << ESF_DZ_RX_DSC_PTR_LBITS_WIDTH) - 1)); if (n_descs != rx_queue->scatter_n + 1) { + struct efx_ef10_nic_data *nic_data = efx->nic_data; + /* detect rx abort */ if (unlikely(n_descs == rx_queue->scatter_n)) { WARN_ON(rx_bytes != 0); @@ -1773,10 +1775,13 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel, return 0; } - if (unlikely(rx_queue->scatter_n != 0)) { - /* Scattered packet completions cannot be - * merged, so something has gone wrong. - */ + /* Check that RX completion merging is valid, i.e. + * the current firmware supports it and this is a + * non-scattered packet. + */ + if (!(nic_data->datapath_caps & + (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN)) || + rx_queue->scatter_n != 0 || rx_cont) { efx_ef10_handle_rx_bad_lbits( rx_queue, next_ptr_lbits, (rx_queue->removed_count + -- cgit v1.2.3 From cce28794bc99c15f0d4c98936a473ac6e21be0ad Mon Sep 17 00:00:00 2001 From: Jon Cooper Date: Wed, 2 Oct 2013 11:04:14 +0100 Subject: sfc: Make initial fill of RX descriptors synchronous Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/efx.c | 6 ++++-- drivers/net/ethernet/sfc/efx.h | 2 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ethernet/sfc/rx.c | 9 +++++---- 5 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 2f77359607d2..e9c546bdbdfe 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1907,7 +1907,7 @@ static void efx_ef10_handle_driver_generated_event(struct efx_channel *channel, * events, so efx_process_channel() won't refill the * queue. Refill it here */ - efx_fast_push_rx_descriptors(&channel->rx_queue); + efx_fast_push_rx_descriptors(&channel->rx_queue, true); break; default: netif_err(efx, hw, efx->net_dev, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 869418164364..5e2454d07137 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -253,7 +253,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget) efx_channel_get_rx_queue(channel); efx_rx_flush_packet(channel); - efx_fast_push_rx_descriptors(rx_queue); + efx_fast_push_rx_descriptors(rx_queue, true); } return spent; @@ -646,7 +646,9 @@ static void efx_start_datapath(struct efx_nic *efx) efx_for_each_channel_rx_queue(rx_queue, channel) { efx_init_rx_queue(rx_queue); atomic_inc(&efx->active_queues); - efx_nic_generate_fill_event(rx_queue); + efx_stop_eventq(channel); + efx_fast_push_rx_descriptors(rx_queue, false); + efx_start_eventq(channel); } WARN_ON(channel->rx_pkt_n_frags); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index b8235ee5d7d7..a653786fbbe7 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -37,7 +37,7 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); void efx_remove_rx_queue(struct efx_rx_queue *rx_queue); void efx_init_rx_queue(struct efx_rx_queue *rx_queue); void efx_fini_rx_queue(struct efx_rx_queue *rx_queue); -void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue); +void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, bool atomic); void efx_rx_slow_fill(unsigned long context); void __efx_rx_packet(struct efx_channel *channel); void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index c0907d884d75..984e85ee76f6 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -1147,7 +1147,7 @@ static void efx_farch_handle_generated_event(struct efx_channel *channel, /* The queue must be empty, so we won't receive any rx * events, so efx_process_channel() won't refill the * queue. Refill it here */ - efx_fast_push_rx_descriptors(rx_queue); + efx_fast_push_rx_descriptors(rx_queue, true); } else if (rx_queue && magic == EFX_CHANNEL_MAGIC_RX_DRAIN(rx_queue)) { efx_farch_handle_drain_event(channel); } else if (code == _EFX_CHANNEL_MAGIC_TX_DRAIN) { diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 42488df1f4ec..8671bc199a9d 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -149,7 +149,7 @@ static struct page *efx_reuse_page(struct efx_rx_queue *rx_queue) * 0 on success. If a single page can be used for multiple buffers, * then the page will either be inserted fully, or not at all. */ -static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue) +static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue, bool atomic) { struct efx_nic *efx = rx_queue->efx; struct efx_rx_buffer *rx_buf; @@ -163,7 +163,8 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue) do { page = efx_reuse_page(rx_queue); if (page == NULL) { - page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC, + page = alloc_pages(__GFP_COLD | __GFP_COMP | + (atomic ? GFP_ATOMIC : GFP_KERNEL), efx->rx_buffer_order); if (unlikely(page == NULL)) return -ENOMEM; @@ -321,7 +322,7 @@ static void efx_discard_rx_packet(struct efx_channel *channel, * this means this function must run from the NAPI handler, or be called * when NAPI is disabled. */ -void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue) +void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, bool atomic) { struct efx_nic *efx = rx_queue->efx; unsigned int fill_level, batch_size; @@ -354,7 +355,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue) do { - rc = efx_init_rx_buffers(rx_queue); + rc = efx_init_rx_buffers(rx_queue, atomic); if (unlikely(rc)) { /* Ensure that we don't leave the rx queue empty */ if (rx_queue->added_count == rx_queue->removed_count) -- cgit v1.2.3 From f8f3b5ae3ea45ef6b00b471fed0fc90552a3c4af Mon Sep 17 00:00:00 2001 From: Jon Cooper Date: Mon, 30 Sep 2013 17:36:50 +0100 Subject: sfc: Correct RX dropped count for drops while interface is down We don't directly control RX ingress on Siena or any later controllers, and so we cannot prevent packets from entering the RX datapath while the RX queues are not set up. This results in the hardware incrementing RX_NODESC_DROP_CNT, but it's not an error and we should not include it in error stats. When bringing an interface up or down, pull (or wait for) stats and count the number of packets that were dropped while the interface was down. Subtract this from the reported RX dropped count. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 2 ++ drivers/net/ethernet/sfc/efx.c | 11 ++++++++ drivers/net/ethernet/sfc/falcon.c | 10 +++++++ drivers/net/ethernet/sfc/mcdi.h | 1 + drivers/net/ethernet/sfc/mcdi_port.c | 49 +++++++++++++++++++++++++++-------- drivers/net/ethernet/sfc/net_driver.h | 5 ++++ drivers/net/ethernet/sfc/nic.c | 12 +++++++++ drivers/net/ethernet/sfc/nic.h | 1 + drivers/net/ethernet/sfc/siena.c | 3 +++ 9 files changed, 83 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index e9c546bdbdfe..c1b85edcb204 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -902,6 +902,7 @@ static int efx_ef10_try_update_nic_stats(struct efx_nic *efx) return -EAGAIN; /* Update derived statistics */ + efx_nic_fix_nodesc_drop_stat(efx, &stats[EF10_STAT_rx_nodesc_drops]); stats[EF10_STAT_rx_good_bytes] = stats[EF10_STAT_rx_bytes] - stats[EF10_STAT_rx_bytes_minus_good_bytes]; @@ -3423,6 +3424,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .describe_stats = efx_ef10_describe_stats, .update_stats = efx_ef10_update_stats, .start_stats = efx_mcdi_mac_start_stats, + .pull_stats = efx_mcdi_mac_pull_stats, .stop_stats = efx_mcdi_mac_stop_stats, .set_id_led = efx_mcdi_set_id_led, .push_irq_moderation = efx_ef10_push_irq_moderation, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 5e2454d07137..c734fba8c99c 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1684,6 +1684,10 @@ static void efx_start_all(struct efx_nic *efx) } efx->type->start_stats(efx); + efx->type->pull_stats(efx); + spin_lock_bh(&efx->stats_lock); + efx->type->update_stats(efx, NULL, NULL); + spin_unlock_bh(&efx->stats_lock); } /* Flush all delayed work. Should only be called when no more delayed work @@ -1711,6 +1715,13 @@ static void efx_stop_all(struct efx_nic *efx) if (!efx->port_enabled) return; + /* update stats before we go down so we can accurately count + * rx_nodesc_drops + */ + efx->type->pull_stats(efx); + spin_lock_bh(&efx->stats_lock); + efx->type->update_stats(efx, NULL, NULL); + spin_unlock_bh(&efx->stats_lock); efx->type->stop_stats(efx); efx_stop_port(efx); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index ff5d322b9b49..4a9e05c82e2a 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2593,6 +2593,14 @@ void falcon_start_nic_stats(struct efx_nic *efx) spin_unlock_bh(&efx->stats_lock); } +/* We don't acutally pull stats on falcon. Wait 10ms so that + * they arrive when we call this just after start_stats + */ +void falcon_pull_nic_stats(struct efx_nic *efx) +{ + msleep(10); +} + void falcon_stop_nic_stats(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; @@ -2672,6 +2680,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .describe_stats = falcon_describe_nic_stats, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, + .pull_stats = falcon_pull_nic_stats, .stop_stats = falcon_stop_nic_stats, .set_id_led = falcon_set_id_led, .push_irq_moderation = falcon_push_irq_moderation, @@ -2765,6 +2774,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .describe_stats = falcon_describe_nic_stats, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, + .pull_stats = falcon_pull_nic_stats, .stop_stats = falcon_stop_nic_stats, .set_id_led = falcon_set_id_led, .push_irq_moderation = falcon_push_irq_moderation, diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 15816cacb548..d861628b7ee6 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -301,6 +301,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx); #define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1)) void efx_mcdi_mac_start_stats(struct efx_nic *efx); void efx_mcdi_mac_stop_stats(struct efx_nic *efx); +void efx_mcdi_mac_pull_stats(struct efx_nic *efx); bool efx_mcdi_mac_check_fault(struct efx_nic *efx); enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason); int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method); diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index 7b6be61d549f..7288aefc2877 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c @@ -927,12 +927,23 @@ bool efx_mcdi_mac_check_fault(struct efx_nic *efx) return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0; } -static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, - u32 dma_len, int enable, int clear) +enum efx_stats_action { + EFX_STATS_ENABLE, + EFX_STATS_DISABLE, + EFX_STATS_PULL, +}; + +static int efx_mcdi_mac_stats(struct efx_nic *efx, + enum efx_stats_action action, int clear) { MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN); int rc; - int period = enable ? 1000 : 0; + int change = action == EFX_STATS_PULL ? 0 : 1; + int enable = action == EFX_STATS_ENABLE ? 1 : 0; + int period = action == EFX_STATS_ENABLE ? 1000 : 0; + dma_addr_t dma_addr = efx->stats_buffer.dma_addr; + u32 dma_len = action != EFX_STATS_DISABLE ? + MC_CMD_MAC_NSTATS * sizeof(u64) : 0; BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); @@ -940,8 +951,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD, MAC_STATS_IN_DMA, !!enable, MAC_STATS_IN_CLEAR, clear, - MAC_STATS_IN_PERIODIC_CHANGE, 1, - MAC_STATS_IN_PERIODIC_ENABLE, !!enable, + MAC_STATS_IN_PERIODIC_CHANGE, change, + MAC_STATS_IN_PERIODIC_ENABLE, enable, MAC_STATS_IN_PERIODIC_CLEAR, 0, MAC_STATS_IN_PERIODIC_NOEVENT, 1, MAC_STATS_IN_PERIOD_MS, period); @@ -955,8 +966,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, return 0; fail: - netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n", - __func__, enable ? "enable" : "disable", rc); + netif_err(efx, hw, efx->net_dev, "%s: action %d failed rc=%d\n", + __func__, action, rc); return rc; } @@ -966,13 +977,29 @@ void efx_mcdi_mac_start_stats(struct efx_nic *efx) dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID; - efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, - MC_CMD_MAC_NSTATS * sizeof(u64), 1, 0); + efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0); } void efx_mcdi_mac_stop_stats(struct efx_nic *efx) { - efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0); + efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0); +} + +#define EFX_MAC_STATS_WAIT_US 100 +#define EFX_MAC_STATS_WAIT_ATTEMPTS 10 + +void efx_mcdi_mac_pull_stats(struct efx_nic *efx) +{ + __le64 *dma_stats = efx->stats_buffer.addr; + int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS; + + dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID; + efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0); + + while (dma_stats[MC_CMD_MAC_GENERATION_END] == + EFX_MC_STATS_GENERATION_INVALID && + attempts-- != 0) + udelay(EFX_MAC_STATS_WAIT_US); } int efx_mcdi_port_probe(struct efx_nic *efx) @@ -1003,7 +1030,7 @@ int efx_mcdi_port_probe(struct efx_nic *efx) efx->stats_buffer.addr, (u64)virt_to_phys(efx->stats_buffer.addr)); - efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1); + efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1); return 0; } diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index d98b3f031ab5..f47bac78b92c 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -857,6 +857,9 @@ struct efx_nic { struct net_device *net_dev; struct efx_buffer stats_buffer; + u64 rx_nodesc_drops_total; + u64 rx_nodesc_drops_while_down; + bool rx_nodesc_drops_prev_state; unsigned int phy_type; const struct efx_phy_operations *phy_op; @@ -960,6 +963,7 @@ struct efx_mtd_partition { * @update_stats: Update statistics not provided by event handling. * Either argument may be %NULL. * @start_stats: Start the regular fetching of statistics + * @pull_stats: Pull stats from the NIC and wait until they arrive. * @stop_stats: Stop the regular fetching of statistics * @set_id_led: Set state of identifying LED or revert to automatic function * @push_irq_moderation: Apply interrupt moderation value @@ -1078,6 +1082,7 @@ struct efx_nic_type { size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, struct rtnl_link_stats64 *core_stats); void (*start_stats)(struct efx_nic *efx); + void (*pull_stats)(struct efx_nic *efx); void (*stop_stats)(struct efx_nic *efx); void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode); void (*push_irq_moderation)(struct efx_channel *channel); diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 9c90bf56090f..79226b19e3c4 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -519,3 +519,15 @@ void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count, } } } + +void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *rx_nodesc_drops) +{ + /* if down, or this is the first update after coming up */ + if (!(efx->net_dev->flags & IFF_UP) || !efx->rx_nodesc_drops_prev_state) + efx->rx_nodesc_drops_while_down += + *rx_nodesc_drops - efx->rx_nodesc_drops_total; + efx->rx_nodesc_drops_total = *rx_nodesc_drops; + efx->rx_nodesc_drops_prev_state = !!(efx->net_dev->flags & IFF_UP); + *rx_nodesc_drops -= efx->rx_nodesc_drops_while_down; +} + diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index fe71e81ee8bf..7ac9c000696f 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -775,6 +775,7 @@ size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count, const unsigned long *mask, u64 *stats, const void *dma_buf, bool accumulate); +void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *stat); #define EFX_MAX_FLUSH_TIME 5000 diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index d034bcd124ef..f2a7ad4c76aa 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -458,6 +458,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) return -EAGAIN; /* Update derived statistics */ + efx_nic_fix_nodesc_drop_stat(efx, + &stats[SIENA_STAT_rx_nodesc_drop_cnt]); efx_update_diff_stat(&stats[SIENA_STAT_tx_good_bytes], stats[SIENA_STAT_tx_bytes] - stats[SIENA_STAT_tx_bad_bytes]); @@ -878,6 +880,7 @@ const struct efx_nic_type siena_a0_nic_type = { .describe_stats = siena_describe_nic_stats, .update_stats = siena_update_nic_stats, .start_stats = efx_mcdi_mac_start_stats, + .pull_stats = efx_mcdi_mac_pull_stats, .stop_stats = efx_mcdi_mac_stop_stats, .set_id_led = efx_mcdi_set_id_led, .push_irq_moderation = siena_push_irq_moderation, -- cgit v1.2.3 From 2b216cef086a5b564a4415d7f1b6095ea1c2089c Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 30 Sep 2013 10:52:49 +0100 Subject: sfc: Report units in sensor warnings Add units to the "Sensor reports condition X for raw value Y" messages. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi_mon.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c index d72ad4fc3617..99c80f8c0a0e 100644 --- a/drivers/net/ethernet/sfc/mcdi_mon.c +++ b/drivers/net/ethernet/sfc/mcdi_mon.c @@ -24,6 +24,15 @@ enum efx_hwmon_type { EFX_HWMON_IN, /* voltage */ EFX_HWMON_CURR, /* current */ EFX_HWMON_POWER, /* power */ + EFX_HWMON_TYPES_COUNT +}; + +static const char *const efx_hwmon_unit[EFX_HWMON_TYPES_COUNT] = { + [EFX_HWMON_TEMP] = " degC", + [EFX_HWMON_COOL] = " rpm", /* though nonsense for a heatsink */ + [EFX_HWMON_IN] = " mV", + [EFX_HWMON_CURR] = " mA", + [EFX_HWMON_POWER] = " W", }; static const struct { @@ -91,7 +100,8 @@ static const char *const sensor_status_names[] = { void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) { unsigned int type, state, value; - const char *name = NULL, *state_txt; + enum efx_hwmon_type hwmon_type = EFX_HWMON_UNKNOWN; + const char *name = NULL, *state_txt, *unit; type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR); state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE); @@ -99,16 +109,22 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) /* Deal gracefully with the board having more drivers than we * know about, but do not expect new sensor states. */ - if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) + if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) { name = efx_mcdi_sensor_type[type].label; + hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; + } if (!name) name = "No sensor name available"; EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names)); state_txt = sensor_status_names[state]; + EFX_BUG_ON_PARANOID(hwmon_type >= EFX_HWMON_TYPES_COUNT); + unit = efx_hwmon_unit[hwmon_type]; + if (!unit) + unit = ""; netif_err(efx, hw, efx->net_dev, - "Sensor %d (%s) reports condition '%s' for raw value %d\n", - type, name, state_txt, value); + "Sensor %d (%s) reports condition '%s' for value %d%s\n", + type, name, state_txt, value, unit); } #ifdef CONFIG_SFC_MCDI_MON -- cgit v1.2.3 From 0cf7a455d4fed61549098fa8cce37462185c1bf8 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 3 Oct 2013 19:06:18 +0100 Subject: sfc: Revise sensor names to be more understandable and consistent Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi_mon.c | 49 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c index 99c80f8c0a0e..2891b409d263 100644 --- a/drivers/net/ethernet/sfc/mcdi_mon.c +++ b/drivers/net/ethernet/sfc/mcdi_mon.c @@ -42,13 +42,13 @@ static const struct { } efx_mcdi_sensor_type[] = { #define SENSOR(name, label, hwmon_type, port) \ [MC_CMD_SENSOR_##name] = { label, EFX_HWMON_ ## hwmon_type, port } - SENSOR(CONTROLLER_TEMP, "Controller ext. temp.", TEMP, -1), + SENSOR(CONTROLLER_TEMP, "Controller board temp.", TEMP, -1), SENSOR(PHY_COMMON_TEMP, "PHY temp.", TEMP, -1), - SENSOR(CONTROLLER_COOLING, "Controller cooling", COOL, -1), + SENSOR(CONTROLLER_COOLING, "Controller heat sink", COOL, -1), SENSOR(PHY0_TEMP, "PHY temp.", TEMP, 0), - SENSOR(PHY0_COOLING, "PHY cooling", COOL, 0), + SENSOR(PHY0_COOLING, "PHY heat sink", COOL, 0), SENSOR(PHY1_TEMP, "PHY temp.", TEMP, 1), - SENSOR(PHY1_COOLING, "PHY cooling", COOL, 1), + SENSOR(PHY1_COOLING, "PHY heat sink", COOL, 1), SENSOR(IN_1V0, "1.0V supply", IN, -1), SENSOR(IN_1V2, "1.2V supply", IN, -1), SENSOR(IN_1V8, "1.8V supply", IN, -1), @@ -56,34 +56,37 @@ static const struct { SENSOR(IN_3V3, "3.3V supply", IN, -1), SENSOR(IN_12V0, "12.0V supply", IN, -1), SENSOR(IN_1V2A, "1.2V analogue supply", IN, -1), - SENSOR(IN_VREF, "ref. voltage", IN, -1), - SENSOR(OUT_VAOE, "AOE power supply", IN, -1), - SENSOR(AOE_TEMP, "AOE temp.", TEMP, -1), - SENSOR(PSU_AOE_TEMP, "AOE PSU temp.", TEMP, -1), - SENSOR(PSU_TEMP, "Controller PSU temp.", TEMP, -1), - SENSOR(FAN_0, NULL, COOL, -1), - SENSOR(FAN_1, NULL, COOL, -1), - SENSOR(FAN_2, NULL, COOL, -1), - SENSOR(FAN_3, NULL, COOL, -1), - SENSOR(FAN_4, NULL, COOL, -1), + SENSOR(IN_VREF, "Ref. voltage", IN, -1), + SENSOR(OUT_VAOE, "AOE FPGA supply", IN, -1), + SENSOR(AOE_TEMP, "AOE FPGA temp.", TEMP, -1), + SENSOR(PSU_AOE_TEMP, "AOE regulator temp.", TEMP, -1), + SENSOR(PSU_TEMP, "Controller regulator temp.", + TEMP, -1), + SENSOR(FAN_0, "Fan 0", COOL, -1), + SENSOR(FAN_1, "Fan 1", COOL, -1), + SENSOR(FAN_2, "Fan 2", COOL, -1), + SENSOR(FAN_3, "Fan 3", COOL, -1), + SENSOR(FAN_4, "Fan 4", COOL, -1), SENSOR(IN_VAOE, "AOE input supply", IN, -1), SENSOR(OUT_IAOE, "AOE output current", CURR, -1), SENSOR(IN_IAOE, "AOE input current", CURR, -1), SENSOR(NIC_POWER, "Board power use", POWER, -1), SENSOR(IN_0V9, "0.9V supply", IN, -1), - SENSOR(IN_I0V9, "0.9V input current", CURR, -1), - SENSOR(IN_I1V2, "1.2V input current", CURR, -1), - SENSOR(IN_0V9_ADC, "0.9V supply (at ADC)", IN, -1), - SENSOR(CONTROLLER_2_TEMP, "Controller ext. temp. 2", TEMP, -1), - SENSOR(VREG_INTERNAL_TEMP, "Voltage regulator temp.", TEMP, -1), + SENSOR(IN_I0V9, "0.9V supply current", CURR, -1), + SENSOR(IN_I1V2, "1.2V supply current", CURR, -1), + SENSOR(IN_0V9_ADC, "0.9V supply (ext. ADC)", IN, -1), + SENSOR(CONTROLLER_2_TEMP, "Controller board temp. 2", TEMP, -1), + SENSOR(VREG_INTERNAL_TEMP, "Regulator die temp.", TEMP, -1), SENSOR(VREG_0V9_TEMP, "0.9V regulator temp.", TEMP, -1), SENSOR(VREG_1V2_TEMP, "1.2V regulator temp.", TEMP, -1), - SENSOR(CONTROLLER_VPTAT, "Controller int. temp. raw", IN, -1), - SENSOR(CONTROLLER_INTERNAL_TEMP, "Controller int. temp.", TEMP, -1), + SENSOR(CONTROLLER_VPTAT, + "Controller PTAT voltage (int. ADC)", IN, -1), + SENSOR(CONTROLLER_INTERNAL_TEMP, + "Controller die temp. (int. ADC)", TEMP, -1), SENSOR(CONTROLLER_VPTAT_EXTADC, - "Controller int. temp. raw (at ADC)", IN, -1), + "Controller PTAT voltage (ext. ADC)", IN, -1), SENSOR(CONTROLLER_INTERNAL_TEMP_EXTADC, - "Controller int. temp. (via ADC)", TEMP, -1), + "Controller die temp. (ext. ADC)", TEMP, -1), SENSOR(AMBIENT_TEMP, "Ambient temp.", TEMP, -1), SENSOR(AIRFLOW, "Air flow raw", IN, -1), #undef SENSOR -- cgit v1.2.3 From 8d13a377b8c2bc20a349b98443bb7e7c5970e991 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Dec 2013 20:17:28 +0000 Subject: sfc: Add new sensor names Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi_mon.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c index 2891b409d263..bc27d5b580f5 100644 --- a/drivers/net/ethernet/sfc/mcdi_mon.c +++ b/drivers/net/ethernet/sfc/mcdi_mon.c @@ -89,6 +89,9 @@ static const struct { "Controller die temp. (ext. ADC)", TEMP, -1), SENSOR(AMBIENT_TEMP, "Ambient temp.", TEMP, -1), SENSOR(AIRFLOW, "Air flow raw", IN, -1), + SENSOR(VDD08D_VSS08D_CSR, "0.9V die (int. ADC)", IN, -1), + SENSOR(VDD08D_VSS08D_CSR_EXTADC, "0.9V die (ext. ADC)", IN, -1), + SENSOR(HOTPOINT_TEMP, "Controller board temp. (hotpoint)", TEMP, -1), #undef SENSOR }; -- cgit v1.2.3 From 1e0b8120b2aef503f480b0e0182d7a7304acfb3d Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Fri, 31 May 2013 18:36:12 +0100 Subject: sfc: Log all unexpected MCDI errors Split each of efx_mcdi_rpc, efx_mcdi_rpc_finish, and efx_mcdi_rpc_async into a normal and a _quiet version; made the former log MCDI errors with netif_err (and include the raw MCDI error code), and the latter never log them at all. Changed various callers; any where some errors are expected (but others are not) call the _quiet version and then if necessary log the MCDI error themselves. Said logging is done by new efx_mcdi_display_error. Callers of efx_mcdi_rpc*_quiet functions which may want to log the error need to ensure that their outbuf is big enough to hold an MCDI error; to this end, they now use MCDI_DECLARE_BUF_OUT_OR_ERR, which always allocates at least 8 bytes. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 39 ++-- drivers/net/ethernet/sfc/mcdi.c | 369 +++++++++++++++++++---------------- drivers/net/ethernet/sfc/mcdi.h | 18 ++ drivers/net/ethernet/sfc/mcdi_port.c | 44 +---- drivers/net/ethernet/sfc/ptp.c | 24 ++- 5 files changed, 265 insertions(+), 229 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index c1b85edcb204..69a0cf7f4f47 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -278,11 +278,17 @@ fail1: static int efx_ef10_free_vis(struct efx_nic *efx) { - int rc = efx_mcdi_rpc(efx, MC_CMD_FREE_VIS, NULL, 0, NULL, 0, NULL); + MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, 0); + size_t outlen; + int rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FREE_VIS, NULL, 0, + outbuf, sizeof(outbuf), &outlen); /* -EALREADY means nothing to free, so ignore */ if (rc == -EALREADY) rc = 0; + if (rc) + efx_mcdi_display_error(efx, MC_CMD_FREE_VIS, 0, outbuf, outlen, + rc); return rc; } @@ -1244,7 +1250,6 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue) fail: WARN_ON(true); - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); } static void efx_ef10_tx_fini(struct efx_tx_queue *tx_queue) @@ -1258,7 +1263,7 @@ static void efx_ef10_tx_fini(struct efx_tx_queue *tx_queue) MCDI_SET_DWORD(inbuf, FINI_TXQ_IN_INSTANCE, tx_queue->queue); - rc = efx_mcdi_rpc(efx, MC_CMD_FINI_TXQ, inbuf, sizeof(inbuf), + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FINI_TXQ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc && rc != -EALREADY) @@ -1267,7 +1272,8 @@ static void efx_ef10_tx_fini(struct efx_tx_queue *tx_queue) return; fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); + efx_mcdi_display_error(efx, MC_CMD_FINI_TXQ, MC_CMD_FINI_TXQ_IN_LEN, + outbuf, outlen, rc); } static void efx_ef10_tx_remove(struct efx_tx_queue *tx_queue) @@ -1482,14 +1488,9 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue) rc = efx_mcdi_rpc(efx, MC_CMD_INIT_RXQ, inbuf, inlen, outbuf, sizeof(outbuf), &outlen); - if (rc) - goto fail; + WARN_ON(rc); return; - -fail: - WARN_ON(true); - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); } static void efx_ef10_rx_fini(struct efx_rx_queue *rx_queue) @@ -1503,7 +1504,7 @@ static void efx_ef10_rx_fini(struct efx_rx_queue *rx_queue) MCDI_SET_DWORD(inbuf, FINI_RXQ_IN_INSTANCE, efx_rx_queue_index(rx_queue)); - rc = efx_mcdi_rpc(efx, MC_CMD_FINI_RXQ, inbuf, sizeof(inbuf), + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FINI_RXQ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc && rc != -EALREADY) @@ -1512,7 +1513,8 @@ static void efx_ef10_rx_fini(struct efx_rx_queue *rx_queue) return; fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); + efx_mcdi_display_error(efx, MC_CMD_FINI_RXQ, MC_CMD_FINI_RXQ_IN_LEN, + outbuf, outlen, rc); } static void efx_ef10_rx_remove(struct efx_rx_queue *rx_queue) @@ -1649,15 +1651,7 @@ static int efx_ef10_ev_init(struct efx_channel *channel) rc = efx_mcdi_rpc(efx, MC_CMD_INIT_EVQ, inbuf, inlen, outbuf, sizeof(outbuf), &outlen); - if (rc) - goto fail; - /* IRQ return is ignored */ - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1671,7 +1665,7 @@ static void efx_ef10_ev_fini(struct efx_channel *channel) MCDI_SET_DWORD(inbuf, FINI_EVQ_IN_INSTANCE, channel->channel); - rc = efx_mcdi_rpc(efx, MC_CMD_FINI_EVQ, inbuf, sizeof(inbuf), + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FINI_EVQ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc && rc != -EALREADY) @@ -1680,7 +1674,8 @@ static void efx_ef10_ev_fini(struct efx_channel *channel) return; fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); + efx_mcdi_display_error(efx, MC_CMD_FINI_EVQ, MC_CMD_FINI_EVQ_IN_LEN, + outbuf, outlen, rc); } static void efx_ef10_ev_remove(struct efx_channel *channel) diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index da14e2428944..aee67be3d8c5 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -42,6 +42,7 @@ struct efx_mcdi_async_param { unsigned int cmd; size_t inlen; size_t outlen; + bool quiet; efx_mcdi_async_completer *complete; unsigned long cookie; /* followed by request/response buffer */ @@ -402,8 +403,9 @@ static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout) { struct efx_nic *efx = mcdi->efx; struct efx_mcdi_async_param *async; - size_t hdr_len, data_len; + size_t hdr_len, data_len, err_len; efx_dword_t *outbuf; + MCDI_DECLARE_BUF_OUT_OR_ERR(errbuf, 0); int rc; if (cmpxchg(&mcdi->state, @@ -444,6 +446,13 @@ static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout) outbuf = (efx_dword_t *)(async + 1); efx->type->mcdi_read_response(efx, outbuf, hdr_len, min(async->outlen, data_len)); + if (!timeout && rc && !async->quiet) { + err_len = min(sizeof(errbuf), data_len); + efx->type->mcdi_read_response(efx, errbuf, hdr_len, + sizeof(errbuf)); + efx_mcdi_display_error(efx, async->cmd, async->inlen, errbuf, + err_len, rc); + } async->complete(efx, async->cookie, rc, outbuf, data_len); kfree(async); @@ -519,18 +528,129 @@ efx_mcdi_check_supported(struct efx_nic *efx, unsigned int cmd, size_t inlen) return 0; } +static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, + efx_dword_t *outbuf, size_t outlen, + size_t *outlen_actual, bool quiet) +{ + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + MCDI_DECLARE_BUF_OUT_OR_ERR(errbuf, 0); + int rc; + + if (mcdi->mode == MCDI_MODE_POLL) + rc = efx_mcdi_poll(efx); + else + rc = efx_mcdi_await_completion(efx); + + if (rc != 0) { + netif_err(efx, hw, efx->net_dev, + "MC command 0x%x inlen %d mode %d timed out\n", + cmd, (int)inlen, mcdi->mode); + + if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) { + netif_err(efx, hw, efx->net_dev, + "MCDI request was completed without an event\n"); + rc = 0; + } + + /* Close the race with efx_mcdi_ev_cpl() executing just too late + * and completing a request we've just cancelled, by ensuring + * that the seqno check therein fails. + */ + spin_lock_bh(&mcdi->iface_lock); + ++mcdi->seqno; + ++mcdi->credits; + spin_unlock_bh(&mcdi->iface_lock); + } + + if (rc != 0) { + if (outlen_actual) + *outlen_actual = 0; + } else { + size_t hdr_len, data_len, err_len; + + /* At the very least we need a memory barrier here to ensure + * we pick up changes from efx_mcdi_ev_cpl(). Protect against + * a spurious efx_mcdi_ev_cpl() running concurrently by + * acquiring the iface_lock. */ + spin_lock_bh(&mcdi->iface_lock); + rc = mcdi->resprc; + hdr_len = mcdi->resp_hdr_len; + data_len = mcdi->resp_data_len; + err_len = min(sizeof(errbuf), data_len); + spin_unlock_bh(&mcdi->iface_lock); + + BUG_ON(rc > 0); + + efx->type->mcdi_read_response(efx, outbuf, hdr_len, + min(outlen, data_len)); + if (outlen_actual) + *outlen_actual = data_len; + + efx->type->mcdi_read_response(efx, errbuf, hdr_len, err_len); + + if (cmd == MC_CMD_REBOOT && rc == -EIO) { + /* Don't reset if MC_CMD_REBOOT returns EIO */ + } else if (rc == -EIO || rc == -EINTR) { + netif_err(efx, hw, efx->net_dev, "MC fatal error %d\n", + -rc); + efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE); + } else if (rc && !quiet) { + efx_mcdi_display_error(efx, cmd, inlen, errbuf, err_len, + rc); + } + + if (rc == -EIO || rc == -EINTR) { + msleep(MCDI_STATUS_SLEEP_MS); + efx_mcdi_poll_reboot(efx); + mcdi->new_epoch = true; + } + } + + efx_mcdi_release(mcdi); + return rc; +} + +static int _efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, + const efx_dword_t *inbuf, size_t inlen, + efx_dword_t *outbuf, size_t outlen, + size_t *outlen_actual, bool quiet) +{ + int rc; + + rc = efx_mcdi_rpc_start(efx, cmd, inbuf, inlen); + if (rc) { + if (outlen_actual) + *outlen_actual = 0; + return rc; + } + return _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen, + outlen_actual, quiet); +} + int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const efx_dword_t *inbuf, size_t inlen, efx_dword_t *outbuf, size_t outlen, size_t *outlen_actual) { - int rc; + return _efx_mcdi_rpc(efx, cmd, inbuf, inlen, outbuf, outlen, + outlen_actual, false); +} - rc = efx_mcdi_rpc_start(efx, cmd, inbuf, inlen); - if (rc) - return rc; - return efx_mcdi_rpc_finish(efx, cmd, inlen, - outbuf, outlen, outlen_actual); +/* Normally, on receiving an error code in the MCDI response, + * efx_mcdi_rpc will log an error message containing (among other + * things) the raw error code, by means of efx_mcdi_display_error. + * This _quiet version suppresses that; if the caller wishes to log + * the error conditionally on the return code, it should call this + * function and is then responsible for calling efx_mcdi_display_error + * as needed. + */ +int efx_mcdi_rpc_quiet(struct efx_nic *efx, unsigned cmd, + const efx_dword_t *inbuf, size_t inlen, + efx_dword_t *outbuf, size_t outlen, + size_t *outlen_actual) +{ + return _efx_mcdi_rpc(efx, cmd, inbuf, inlen, outbuf, outlen, + outlen_actual, true); } int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, @@ -551,30 +671,11 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, return 0; } -/** - * efx_mcdi_rpc_async - Schedule an MCDI command to run asynchronously - * @efx: NIC through which to issue the command - * @cmd: Command type number - * @inbuf: Command parameters - * @inlen: Length of command parameters, in bytes - * @outlen: Length to allocate for response buffer, in bytes - * @complete: Function to be called on completion or cancellation. - * @cookie: Arbitrary value to be passed to @complete. - * - * This function does not sleep and therefore may be called in atomic - * context. It will fail if event queues are disabled or if MCDI - * event completions have been disabled due to an error. - * - * If it succeeds, the @complete function will be called exactly once - * in atomic context, when one of the following occurs: - * (a) the completion event is received (in NAPI context) - * (b) event queues are disabled (in the process that disables them) - * (c) the request times-out (in timer context) - */ -int -efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, - const efx_dword_t *inbuf, size_t inlen, size_t outlen, - efx_mcdi_async_completer *complete, unsigned long cookie) +static int _efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, + const efx_dword_t *inbuf, size_t inlen, + size_t outlen, + efx_mcdi_async_completer *complete, + unsigned long cookie, bool quiet) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); struct efx_mcdi_async_param *async; @@ -595,6 +696,7 @@ efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, async->cmd = cmd; async->inlen = inlen; async->outlen = outlen; + async->quiet = quiet; async->complete = complete; async->cookie = cookie; memcpy(async + 1, inbuf, inlen); @@ -623,79 +725,73 @@ efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, return rc; } +/** + * efx_mcdi_rpc_async - Schedule an MCDI command to run asynchronously + * @efx: NIC through which to issue the command + * @cmd: Command type number + * @inbuf: Command parameters + * @inlen: Length of command parameters, in bytes + * @outlen: Length to allocate for response buffer, in bytes + * @complete: Function to be called on completion or cancellation. + * @cookie: Arbitrary value to be passed to @complete. + * + * This function does not sleep and therefore may be called in atomic + * context. It will fail if event queues are disabled or if MCDI + * event completions have been disabled due to an error. + * + * If it succeeds, the @complete function will be called exactly once + * in atomic context, when one of the following occurs: + * (a) the completion event is received (in NAPI context) + * (b) event queues are disabled (in the process that disables them) + * (c) the request times-out (in timer context) + */ +int +efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, + const efx_dword_t *inbuf, size_t inlen, size_t outlen, + efx_mcdi_async_completer *complete, unsigned long cookie) +{ + return _efx_mcdi_rpc_async(efx, cmd, inbuf, inlen, outlen, complete, + cookie, false); +} + +int efx_mcdi_rpc_async_quiet(struct efx_nic *efx, unsigned int cmd, + const efx_dword_t *inbuf, size_t inlen, + size_t outlen, efx_mcdi_async_completer *complete, + unsigned long cookie) +{ + return _efx_mcdi_rpc_async(efx, cmd, inbuf, inlen, outlen, complete, + cookie, true); +} + int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, efx_dword_t *outbuf, size_t outlen, size_t *outlen_actual) { - struct efx_mcdi_iface *mcdi = efx_mcdi(efx); - int rc; - - if (mcdi->mode == MCDI_MODE_POLL) - rc = efx_mcdi_poll(efx); - else - rc = efx_mcdi_await_completion(efx); - - if (rc != 0) { - netif_err(efx, hw, efx->net_dev, - "MC command 0x%x inlen %d mode %d timed out\n", - cmd, (int)inlen, mcdi->mode); - - if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) { - netif_err(efx, hw, efx->net_dev, - "MCDI request was completed without an event\n"); - rc = 0; - } - - /* Close the race with efx_mcdi_ev_cpl() executing just too late - * and completing a request we've just cancelled, by ensuring - * that the seqno check therein fails. - */ - spin_lock_bh(&mcdi->iface_lock); - ++mcdi->seqno; - ++mcdi->credits; - spin_unlock_bh(&mcdi->iface_lock); - } - - if (rc == 0) { - size_t hdr_len, data_len; - - /* At the very least we need a memory barrier here to ensure - * we pick up changes from efx_mcdi_ev_cpl(). Protect against - * a spurious efx_mcdi_ev_cpl() running concurrently by - * acquiring the iface_lock. */ - spin_lock_bh(&mcdi->iface_lock); - rc = mcdi->resprc; - hdr_len = mcdi->resp_hdr_len; - data_len = mcdi->resp_data_len; - spin_unlock_bh(&mcdi->iface_lock); - - BUG_ON(rc > 0); + return _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen, + outlen_actual, false); +} - if (rc == 0) { - efx->type->mcdi_read_response(efx, outbuf, hdr_len, - min(outlen, data_len)); - if (outlen_actual != NULL) - *outlen_actual = data_len; - } else if (cmd == MC_CMD_REBOOT && rc == -EIO) - ; /* Don't reset if MC_CMD_REBOOT returns EIO */ - else if (rc == -EIO || rc == -EINTR) { - netif_err(efx, hw, efx->net_dev, "MC fatal error %d\n", - -rc); - efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE); - } else - netif_dbg(efx, hw, efx->net_dev, - "MC command 0x%x inlen %d failed rc=%d\n", - cmd, (int)inlen, -rc); +int efx_mcdi_rpc_finish_quiet(struct efx_nic *efx, unsigned cmd, size_t inlen, + efx_dword_t *outbuf, size_t outlen, + size_t *outlen_actual) +{ + return _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen, + outlen_actual, true); +} - if (rc == -EIO || rc == -EINTR) { - msleep(MCDI_STATUS_SLEEP_MS); - efx_mcdi_poll_reboot(efx); - mcdi->new_epoch = true; - } - } +void efx_mcdi_display_error(struct efx_nic *efx, unsigned cmd, + size_t inlen, efx_dword_t *outbuf, + size_t outlen, int rc) +{ + int code = 0, err_arg = 0; - efx_mcdi_release(mcdi); - return rc; + if (outlen >= MC_CMD_ERR_CODE_OFST + 4) + code = MCDI_DWORD(outbuf, ERR_CODE); + if (outlen >= MC_CMD_ERR_ARG_OFST + 4) + err_arg = MCDI_DWORD(outbuf, ERR_ARG); + netif_err(efx, hw, efx->net_dev, + "MC command 0x%x inlen %d failed rc=%d (raw=%d) arg=%d\n", + cmd, (int)inlen, rc, code, err_arg); } /* Switch to polled MCDI completions. This can be called in various @@ -1131,13 +1227,6 @@ int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq) rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1254,7 +1343,7 @@ fail1: static int efx_mcdi_read_assertion(struct efx_nic *efx) { MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN); - MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN); + MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN); unsigned int flags, index; const char *reason; size_t outlen; @@ -1269,13 +1358,17 @@ static int efx_mcdi_read_assertion(struct efx_nic *efx) retry = 2; do { MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1); - rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS, - inbuf, MC_CMD_GET_ASSERTS_IN_LEN, - outbuf, sizeof(outbuf), &outlen); + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_GET_ASSERTS, + inbuf, MC_CMD_GET_ASSERTS_IN_LEN, + outbuf, sizeof(outbuf), &outlen); } while ((rc == -EINTR || rc == -EIO) && retry-- > 0); - if (rc) + if (rc) { + efx_mcdi_display_error(efx, MC_CMD_GET_ASSERTS, + MC_CMD_GET_ASSERTS_IN_LEN, outbuf, + outlen, rc); return rc; + } if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN) return -EIO; @@ -1353,18 +1446,11 @@ void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", - __func__, rc); } static int efx_mcdi_reset_port(struct efx_nic *efx) { - int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL); - if (rc) - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", - __func__, rc); - return rc; + return efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL); } static int efx_mcdi_reset_mc(struct efx_nic *efx) @@ -1381,7 +1467,6 @@ static int efx_mcdi_reset_mc(struct efx_nic *efx) return 0; if (rc == 0) rc = -EIO; - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1483,13 +1568,6 @@ int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id) rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1530,13 +1608,6 @@ int efx_mcdi_wol_filter_reset(struct efx_nic *efx) int rc; rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1566,13 +1637,6 @@ static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type) rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1592,14 +1656,10 @@ static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) - goto fail; + return rc; memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length); return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); - return rc; } static int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type, @@ -1619,13 +1679,6 @@ static int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type, rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf, ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1643,13 +1696,6 @@ static int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type, rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -1664,13 +1710,6 @@ static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type) rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index d861628b7ee6..171f5f58f84a 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -116,12 +116,19 @@ void efx_mcdi_fini(struct efx_nic *efx); int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const efx_dword_t *inbuf, size_t inlen, efx_dword_t *outbuf, size_t outlen, size_t *outlen_actual); +int efx_mcdi_rpc_quiet(struct efx_nic *efx, unsigned cmd, + const efx_dword_t *inbuf, size_t inlen, + efx_dword_t *outbuf, size_t outlen, + size_t *outlen_actual); int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, const efx_dword_t *inbuf, size_t inlen); int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, efx_dword_t *outbuf, size_t outlen, size_t *outlen_actual); +int efx_mcdi_rpc_finish_quiet(struct efx_nic *efx, unsigned cmd, + size_t inlen, efx_dword_t *outbuf, + size_t outlen, size_t *outlen_actual); typedef void efx_mcdi_async_completer(struct efx_nic *efx, unsigned long cookie, int rc, @@ -131,6 +138,15 @@ int efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd, const efx_dword_t *inbuf, size_t inlen, size_t outlen, efx_mcdi_async_completer *complete, unsigned long cookie); +int efx_mcdi_rpc_async_quiet(struct efx_nic *efx, unsigned int cmd, + const efx_dword_t *inbuf, size_t inlen, + size_t outlen, + efx_mcdi_async_completer *complete, + unsigned long cookie); + +void efx_mcdi_display_error(struct efx_nic *efx, unsigned cmd, + size_t inlen, efx_dword_t *outbuf, + size_t outlen, int rc); int efx_mcdi_poll_reboot(struct efx_nic *efx); void efx_mcdi_mode_poll(struct efx_nic *efx); @@ -147,6 +163,8 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); */ #define MCDI_DECLARE_BUF(_name, _len) \ efx_dword_t _name[DIV_ROUND_UP(_len, 4)] +#define MCDI_DECLARE_BUF_OUT_OR_ERR(_name, _len) \ + MCDI_DECLARE_BUF(_name, max_t(size_t, _len, 8)) #define _MCDI_PTR(_buf, _offset) \ ((u8 *)(_buf) + (_offset)) #define MCDI_PTR(_buf, _field) \ diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index 7288aefc2877..91d23252f8fa 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c @@ -90,13 +90,6 @@ static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities, rc = efx_mcdi_rpc(efx, MC_CMD_SET_LINK, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; } @@ -143,17 +136,13 @@ static int efx_mcdi_mdio_read(struct net_device *net_dev, rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) - goto fail; + return rc; if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) != MC_CMD_MDIO_STATUS_GOOD) return -EIO; return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE); - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); - return rc; } static int efx_mcdi_mdio_write(struct net_device *net_dev, @@ -174,17 +163,13 @@ static int efx_mcdi_mdio_write(struct net_device *net_dev, rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) - goto fail; + return rc; if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) != MC_CMD_MDIO_STATUS_GOOD) return -EIO; return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); - return rc; } static u32 mcdi_to_ethtool_cap(u32 media, u32 cap) @@ -487,17 +472,14 @@ static bool efx_mcdi_phy_poll(struct efx_nic *efx) rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), NULL); - if (rc) { - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", - __func__, rc); + if (rc) efx->link_state.up = false; - } else { + else efx_mcdi_phy_decode_link( efx, &efx->link_state, MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED), MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS), MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL)); - } return !efx_link_state_equal(&efx->link_state, &old_state); } @@ -531,11 +513,8 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), NULL); - if (rc) { - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", - __func__, rc); + if (rc) return; - } ecmd->lp_advertising = mcdi_to_ethtool_cap(phy_cfg->media, MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP)); @@ -918,11 +897,8 @@ bool efx_mcdi_mac_check_fault(struct efx_nic *efx) rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), &outlength); - if (rc) { - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", - __func__, rc); + if (rc) return true; - } return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0; } @@ -960,14 +936,6 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), NULL, 0, NULL); - if (rc) - goto fail; - - return 0; - -fail: - netif_err(efx, hw, efx->net_dev, "%s: action %d failed rc=%d\n", - __func__, action, rc); return rc; } diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 34b25864b121..24bd2e3040f8 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -313,6 +313,8 @@ static int efx_phc_enable(struct ptp_clock_info *ptp, static int efx_ptp_enable(struct efx_nic *efx) { MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ENABLE_LEN); + MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, 0); + int rc; MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ENABLE); MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); @@ -320,8 +322,14 @@ static int efx_ptp_enable(struct efx_nic *efx) efx->ptp_data->channel->channel); MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode); - return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), - NULL, 0, NULL); + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), NULL); + rc = (rc == -EALREADY) ? 0 : rc; + if (rc) + efx_mcdi_display_error(efx, MC_CMD_PTP, + MC_CMD_PTP_IN_ENABLE_LEN, + outbuf, sizeof(outbuf), rc); + return rc; } /* Disable MCDI PTP support. @@ -332,11 +340,19 @@ static int efx_ptp_enable(struct efx_nic *efx) static int efx_ptp_disable(struct efx_nic *efx) { MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_DISABLE_LEN); + MCDI_DECLARE_BUF_OUT_OR_ERR(outbuf, 0); + int rc; MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_DISABLE); MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); - return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), - NULL, 0, NULL); + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), NULL); + rc = (rc == -EALREADY) ? 0 : rc; + if (rc) + efx_mcdi_display_error(efx, MC_CMD_PTP, + MC_CMD_PTP_IN_DISABLE_LEN, + outbuf, sizeof(outbuf), rc); + return rc; } static void efx_ptp_deliver_rx_queue(struct sk_buff_head *q) -- cgit v1.2.3 From ea136ae71f392341475116a371b92cc78183c2b2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 8 Oct 2013 16:36:58 +0100 Subject: sfc: Map MCDI error MC_CMD_ERR_ENOTSUP to Linux EOPNOTSUPP Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index aee67be3d8c5..d317dfdee845 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -192,6 +192,8 @@ static int efx_mcdi_errno(unsigned int mcdi_err) TRANSLATE_ERROR(EALREADY); TRANSLATE_ERROR(ENOSPC); #undef TRANSLATE_ERROR + case MC_CMD_ERR_ENOTSUP: + return -EOPNOTSUPP; case MC_CMD_ERR_ALLOC_FAIL: return -ENOBUFS; case MC_CMD_ERR_MAC_EXIST: -- cgit v1.2.3 From d615c03937f2b26d3b346d4bdcd9ef342df2ce18 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 8 Oct 2013 17:33:20 +0100 Subject: sfc: Fold efx_flush_all() into efx_stop_port() and update comments efx_flush_all() is a really misleading name - it has nothing to do with e.g. flushing DMA queues. Since it's called immediately after efx_stop_port() and is highly dependent on what that does, combine the two functions. Update comments to explain what this is doing a little better. Also update an related and erroneous comment in efx_start_port(). Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index c734fba8c99c..893cd78c3a6c 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1060,18 +1060,23 @@ static void efx_start_port(struct efx_nic *efx) mutex_lock(&efx->mac_lock); efx->port_enabled = true; - /* efx_mac_work() might have been scheduled after efx_stop_port(), - * and then cancelled by efx_flush_all() */ + /* Ensure MAC ingress/egress is enabled */ efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); } -/* Prevent efx_mac_work() and efx_monitor() from working */ +/* Cancel work for MAC reconfiguration, periodic hardware monitoring + * and the async self-test, wait for them to finish and prevent them + * being scheduled again. This doesn't cover online resets, which + * should only be cancelled when removing the device. + */ static void efx_stop_port(struct efx_nic *efx) { netif_dbg(efx, ifdown, efx->net_dev, "stop port\n"); + EFX_ASSERT_RESET_SERIALISED(efx); + mutex_lock(&efx->mac_lock); efx->port_enabled = false; mutex_unlock(&efx->mac_lock); @@ -1079,6 +1084,10 @@ static void efx_stop_port(struct efx_nic *efx) /* Serialise against efx_set_multicast_list() */ netif_addr_lock_bh(efx->net_dev); netif_addr_unlock_bh(efx->net_dev); + + cancel_delayed_work_sync(&efx->monitor_work); + efx_selftest_async_cancel(efx); + cancel_work_sync(&efx->mac_work); } static void efx_fini_port(struct efx_nic *efx) @@ -1690,18 +1699,6 @@ static void efx_start_all(struct efx_nic *efx) spin_unlock_bh(&efx->stats_lock); } -/* Flush all delayed work. Should only be called when no more delayed work - * will be scheduled. This doesn't flush pending online resets (efx_reset), - * since we're holding the rtnl_lock at this point. */ -static void efx_flush_all(struct efx_nic *efx) -{ - /* Make sure the hardware monitor and event self-test are stopped */ - cancel_delayed_work_sync(&efx->monitor_work); - efx_selftest_async_cancel(efx); - /* Stop scheduled port reconfigurations */ - cancel_work_sync(&efx->mac_work); -} - /* Quiesce the hardware and software data path, and regular activity * for the port without bringing the link down. Safe to call multiple * times with the NIC in almost any state, but interrupts should be @@ -1725,9 +1722,6 @@ static void efx_stop_all(struct efx_nic *efx) efx->type->stop_stats(efx); efx_stop_port(efx); - /* Flush efx_mac_work(), refill_workqueue, monitor_work */ - efx_flush_all(efx); - /* Stop the kernel transmit interface. This is only valid if * the device is stopped or detached; otherwise the watchdog * may fire immediately. -- cgit v1.2.3 From a84f3bf909c7ef5dbadd3401c95376d8ea44b2fe Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 9 Oct 2013 14:14:41 +0100 Subject: sfc: Expose NVRAM_PARTITION_TYPE_LICENSE on EF10 Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 69a0cf7f4f47..45af374b1df9 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -3296,6 +3296,7 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = { { NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT1, 0, 1, "sfc_exp_rom_cfg" }, { NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT2, 0, 2, "sfc_exp_rom_cfg" }, { NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT3, 0, 3, "sfc_exp_rom_cfg" }, + { NVRAM_PARTITION_TYPE_LICENSE, 0, 0, "sfc_license" }, { NVRAM_PARTITION_TYPE_PHY_MIN, 0xff, 0, "sfc_phy_fw" }, }; -- cgit v1.2.3 From 065e64c4b211a4ad18d8c39ce987edef645bdaf0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 9 Oct 2013 14:17:27 +0100 Subject: sfc: Return EBUSY for filter insertion on EF10, matching Falcon/Siena The MC firmware will return error MC_CMD_ERR_ENOSPC if filter insertion fails due to lack of resources. The net driver's filter implementation for Falcon-architecture returns EBUSY. They should behave consistently, so for EF10 change ENOSPC to EBUSY. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 45af374b1df9..ca922b958a2e 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2259,6 +2259,8 @@ static int efx_ef10_filter_push(struct efx_nic *efx, outbuf, sizeof(outbuf), NULL); if (rc == 0) *handle = MCDI_QWORD(outbuf, FILTER_OP_OUT_HANDLE); + if (rc == -ENOSPC) + rc = -EBUSY; /* to match efx_farch_filter_insert() */ return rc; } -- cgit v1.2.3 From 62a1c703568b696c2775a9618840865751cd07d8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 15 Oct 2013 17:54:56 +0100 Subject: sfc: Split PTP multicast filter insertion/removal out of efx_ptp_{start,stop}() Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 56 +++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 24bd2e3040f8..7ae66d900256 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -755,13 +755,27 @@ static inline void efx_ptp_process_rx(struct efx_nic *efx, struct sk_buff *skb) local_bh_enable(); } -static int efx_ptp_start(struct efx_nic *efx) +static void efx_ptp_remove_multicast_filters(struct efx_nic *efx) +{ + struct efx_ptp_data *ptp = efx->ptp_data; + + if (ptp->rxfilter_installed) { + efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, + ptp->rxfilter_general); + efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, + ptp->rxfilter_event); + ptp->rxfilter_installed = false; + } +} + +static int efx_ptp_insert_multicast_filters(struct efx_nic *efx) { struct efx_ptp_data *ptp = efx->ptp_data; struct efx_filter_spec rxfilter; int rc; - ptp->reset_required = false; + if (ptp->rxfilter_installed) + return 0; /* Must filter on both event and general ports to ensure * that there is no packet re-ordering. @@ -794,23 +808,37 @@ static int efx_ptp_start(struct efx_nic *efx) goto fail; ptp->rxfilter_general = rc; + ptp->rxfilter_installed = true; + return 0; + +fail: + efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, + ptp->rxfilter_event); + return rc; +} + +static int efx_ptp_start(struct efx_nic *efx) +{ + struct efx_ptp_data *ptp = efx->ptp_data; + int rc; + + ptp->reset_required = false; + + rc = efx_ptp_insert_multicast_filters(efx); + if (rc) + return rc; + rc = efx_ptp_enable(efx); if (rc != 0) - goto fail2; + goto fail; ptp->evt_frag_idx = 0; ptp->current_adjfreq = 0; - ptp->rxfilter_installed = true; return 0; -fail2: - efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, - ptp->rxfilter_general); fail: - efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, - ptp->rxfilter_event); - + efx_ptp_remove_multicast_filters(efx); return rc; } @@ -826,13 +854,7 @@ static int efx_ptp_stop(struct efx_nic *efx) rc = efx_ptp_disable(efx); - if (ptp->rxfilter_installed) { - efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, - ptp->rxfilter_general); - efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, - ptp->rxfilter_event); - ptp->rxfilter_installed = false; - } + efx_ptp_remove_multicast_filters(efx); /* Make sure RX packets are really delivered */ efx_ptp_deliver_rx_queue(&efx->ptp_data->rxq); -- cgit v1.2.3 From ac36baf817c39fc9b53eff190f5901610c5dc5b7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 15 Oct 2013 17:54:56 +0100 Subject: sfc: Remove dependency of PTP on having a dedicated channel We need a dedicated channel on Siena to ensure we can match up the separate RX and timestamp events for each PTP packet. We won't do this for EF10 as timestamps are delivered inline. Pass a channel index of 0 to MC_CMD_PTP_OP_ENABLE when there is no dedicated channel. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/nic.h | 4 ++- drivers/net/ethernet/sfc/ptp.c | 59 +++++++++++++++++++++++++--------------- drivers/net/ethernet/sfc/siena.c | 2 +- 3 files changed, 41 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 7ac9c000696f..25178536f053 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -554,7 +554,9 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, bool spoofchk); struct ethtool_ts_info; -void efx_ptp_probe(struct efx_nic *efx); +int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel); +void efx_ptp_defer_probe_with_channel(struct efx_nic *efx); +void efx_ptp_remove(struct efx_nic *efx); int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 7ae66d900256..aa4876edaac6 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -214,7 +214,8 @@ struct efx_ptp_timeset { /** * struct efx_ptp_data - Precision Time Protocol (PTP) state - * @channel: The PTP channel + * @efx: The NIC context + * @channel: The PTP channel (Siena only) * @rxq: Receive queue (awaiting timestamps) * @txq: Transmit queue * @evt_list: List of MC receive events awaiting packets @@ -265,6 +266,7 @@ struct efx_ptp_timeset { * @timeset: Last set of synchronisation statistics. */ struct efx_ptp_data { + struct efx_nic *efx; struct efx_channel *channel; struct sk_buff_head rxq; struct sk_buff_head txq; @@ -319,7 +321,8 @@ static int efx_ptp_enable(struct efx_nic *efx) MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ENABLE); MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_QUEUE, - efx->ptp_data->channel->channel); + efx->ptp_data->channel ? + efx->ptp_data->channel->channel : 0); MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode); rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), @@ -774,7 +777,7 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx) struct efx_filter_spec rxfilter; int rc; - if (ptp->rxfilter_installed) + if (!ptp->channel || ptp->rxfilter_installed) return 0; /* Must filter on both event and general ports to ensure @@ -882,7 +885,7 @@ static void efx_ptp_pps_worker(struct work_struct *work) { struct efx_ptp_data *ptp = container_of(work, struct efx_ptp_data, pps_work); - struct efx_nic *efx = ptp->channel->efx; + struct efx_nic *efx = ptp->efx; struct ptp_clock_event ptp_evt; if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS)) @@ -899,7 +902,7 @@ static void efx_ptp_worker(struct work_struct *work) { struct efx_ptp_data *ptp_data = container_of(work, struct efx_ptp_data, work); - struct efx_nic *efx = ptp_data->channel->efx; + struct efx_nic *efx = ptp_data->efx; struct sk_buff *skb; struct sk_buff_head tempq; @@ -923,31 +926,25 @@ static void efx_ptp_worker(struct work_struct *work) efx_ptp_process_rx(efx, skb); } -/* Initialise PTP channel and state. - * - * Setting core_index to zero causes the queue to be initialised and doesn't - * overlap with 'rxq0' because ptp.c doesn't use skb_record_rx_queue. - */ -static int efx_ptp_probe_channel(struct efx_channel *channel) +/* Initialise PTP state. */ +int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) { - struct efx_nic *efx = channel->efx; struct efx_ptp_data *ptp; int rc = 0; unsigned int pos; - channel->irq_moderation = 0; - channel->rx_queue.core_index = 0; - ptp = kzalloc(sizeof(struct efx_ptp_data), GFP_KERNEL); efx->ptp_data = ptp; if (!efx->ptp_data) return -ENOMEM; + ptp->efx = efx; + ptp->channel = channel; + rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); if (rc != 0) goto fail1; - ptp->channel = channel; skb_queue_head_init(&ptp->rxq); skb_queue_head_init(&ptp->txq); ptp->workwq = create_singlethread_workqueue("sfc_ptp"); @@ -1014,14 +1011,27 @@ fail1: return rc; } -static void efx_ptp_remove_channel(struct efx_channel *channel) +/* Initialise PTP channel. + * + * Setting core_index to zero causes the queue to be initialised and doesn't + * overlap with 'rxq0' because ptp.c doesn't use skb_record_rx_queue. + */ +static int efx_ptp_probe_channel(struct efx_channel *channel) { struct efx_nic *efx = channel->efx; + channel->irq_moderation = 0; + channel->rx_queue.core_index = 0; + + return efx_ptp_probe(efx, channel); +} + +void efx_ptp_remove(struct efx_nic *efx) +{ if (!efx->ptp_data) return; - (void)efx_ptp_disable(channel->efx); + (void)efx_ptp_disable(efx); cancel_work_sync(&efx->ptp_data->work); cancel_work_sync(&efx->ptp_data->pps_work); @@ -1038,6 +1048,11 @@ static void efx_ptp_remove_channel(struct efx_channel *channel) kfree(efx->ptp_data); } +static void efx_ptp_remove_channel(struct efx_channel *channel) +{ + efx_ptp_remove(channel->efx); +} + static void efx_ptp_get_channel_name(struct efx_channel *channel, char *buf, size_t len) { @@ -1449,7 +1464,7 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) struct efx_ptp_data *ptp_data = container_of(ptp, struct efx_ptp_data, phc_clock_info); - struct efx_nic *efx = ptp_data->channel->efx; + struct efx_nic *efx = ptp_data->efx; MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN); s64 adjustment_ns; int rc; @@ -1482,7 +1497,7 @@ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) struct efx_ptp_data *ptp_data = container_of(ptp, struct efx_ptp_data, phc_clock_info); - struct efx_nic *efx = ptp_data->channel->efx; + struct efx_nic *efx = ptp_data->efx; struct timespec delta_ts = ns_to_timespec(delta); MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN); @@ -1500,7 +1515,7 @@ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) struct efx_ptp_data *ptp_data = container_of(ptp, struct efx_ptp_data, phc_clock_info); - struct efx_nic *efx = ptp_data->channel->efx; + struct efx_nic *efx = ptp_data->efx; MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_READ_NIC_TIME_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_READ_NIC_TIME_LEN); int rc; @@ -1566,7 +1581,7 @@ static const struct efx_channel_type efx_ptp_channel_type = { .keep_eventq = false, }; -void efx_ptp_probe(struct efx_nic *efx) +void efx_ptp_defer_probe_with_channel(struct efx_nic *efx) { /* Check whether PTP is implemented on this NIC. The DISABLE * operation will succeed if and only if it is implemented. diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index f2a7ad4c76aa..53b4ce67be0e 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -259,7 +259,7 @@ static int siena_probe_nic(struct efx_nic *efx) goto fail5; efx_sriov_probe(efx); - efx_ptp_probe(efx); + efx_ptp_defer_probe_with_channel(efx); return 0; -- cgit v1.2.3 From 8349f7f610263a2b469feb0eb07583ad0742e7ba Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Oct 2013 18:32:34 +0100 Subject: sfc: Store flags from MC_CMD_DRV_ATTACH for later use Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 18 ++++++++++++++++-- drivers/net/ethernet/sfc/mcdi.h | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index d317dfdee845..d608838f6729 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1132,13 +1132,27 @@ static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, goto fail; } + if (driver_operating) { + if (outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN) { + efx->mcdi->fn_flags = + MCDI_DWORD(outbuf, + DRV_ATTACH_EXT_OUT_FUNC_FLAGS); + } else { + /* Synthesise flags for Siena */ + efx->mcdi->fn_flags = + 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | + 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED | + (efx_port_num(efx) == 0) << + MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY; + } + } + /* We currently assume we have control of the external link * and are completely trusted by firmware. Abort probing * if that's not true for this function. */ if (driver_operating && - outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN && - (MCDI_DWORD(outbuf, DRV_ATTACH_EXT_OUT_FUNC_FLAGS) & + (efx->mcdi->fn_flags & (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | 1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) != (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL | diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 171f5f58f84a..52931aebf3c3 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -94,12 +94,14 @@ struct efx_mcdi_mtd_partition { * struct efx_mcdi_data - extra state for NICs that implement MCDI * @iface: Interface/protocol state * @hwmon: Hardware monitor state + * @fn_flags: Flags for this function, as returned by %MC_CMD_DRV_ATTACH. */ struct efx_mcdi_data { struct efx_mcdi_iface iface; #ifdef CONFIG_SFC_MCDI_MON struct efx_mcdi_mon hwmon; #endif + u32 fn_flags; }; #ifdef CONFIG_SFC_MCDI_MON -- cgit v1.2.3 From c1dbdea98d9b32090d5d3e575d60464eb68616d1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Oct 2013 18:32:39 +0100 Subject: sfc: Do not use MAC address as clock name We'll be sharing clocks between multiple functions with their own MAC addresses. The name field is now documented as 'A short "friendly name" to identify the clock ...' and '... not meant to be a unique id.' So use the name 'sfc'. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index aa4876edaac6..5b434597ac63 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -965,9 +965,8 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) ptp->evt_overflow = false; ptp->phc_clock_info.owner = THIS_MODULE; - snprintf(ptp->phc_clock_info.name, - sizeof(ptp->phc_clock_info.name), - "%pm", efx->net_dev->perm_addr); + strlcpy(ptp->phc_clock_info.name, "sfc", + sizeof(ptp->phc_clock_info.name)); ptp->phc_clock_info.max_adj = MAX_PPB; ptp->phc_clock_info.n_alarm = 0; ptp->phc_clock_info.n_ext_ts = 0; -- cgit v1.2.3 From 5d0dab01175bff0e7f14f76c769a4c7dee864139 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Oct 2013 18:32:41 +0100 Subject: sfc: Initialise efx_ptp_data::phc_clock_info from a static template Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 5b434597ac63..96008202cbc3 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -926,6 +926,21 @@ static void efx_ptp_worker(struct work_struct *work) efx_ptp_process_rx(efx, skb); } +static const struct ptp_clock_info efx_phc_clock_info = { + .owner = THIS_MODULE, + .name = "sfc", + .max_adj = MAX_PPB, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .pps = 1, + .adjfreq = efx_phc_adjfreq, + .adjtime = efx_phc_adjtime, + .gettime = efx_phc_gettime, + .settime = efx_phc_settime, + .enable = efx_phc_enable, +}; + /* Initialise PTP state. */ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) { @@ -964,20 +979,7 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); ptp->evt_overflow = false; - ptp->phc_clock_info.owner = THIS_MODULE; - strlcpy(ptp->phc_clock_info.name, "sfc", - sizeof(ptp->phc_clock_info.name)); - ptp->phc_clock_info.max_adj = MAX_PPB; - ptp->phc_clock_info.n_alarm = 0; - ptp->phc_clock_info.n_ext_ts = 0; - ptp->phc_clock_info.n_per_out = 0; - ptp->phc_clock_info.pps = 1; - ptp->phc_clock_info.adjfreq = efx_phc_adjfreq; - ptp->phc_clock_info.adjtime = efx_phc_adjtime; - ptp->phc_clock_info.gettime = efx_phc_gettime; - ptp->phc_clock_info.settime = efx_phc_settime; - ptp->phc_clock_info.enable = efx_phc_enable; - + ptp->phc_clock_info = efx_phc_clock_info; ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, &efx->pci_dev->dev); if (IS_ERR(ptp->phc_clock)) { -- cgit v1.2.3 From bc0f3c1392ddfb6342fb22438faf23d09760e4c8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 6 Dec 2013 18:52:34 +0000 Subject: sfc: Remove kernel-doc for efx_ptp_data fields not present in this version Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 96008202cbc3..be7ed4e1c96c 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -248,21 +248,6 @@ struct efx_ptp_timeset { * @nic_ts_enabled: Flag indicating if NIC generated TS events are handled * @txbuf: Buffer for use when transmitting (PTP) packets to MC (avoids * allocations in main data path). - * @debug_ptp_dir: PTP debugfs directory - * @missed_rx_sync: Number of packets received without syncrhonisation. - * @good_syncs: Number of successful synchronisations. - * @no_time_syncs: Number of synchronisations with no good times. - * @bad_sync_durations: Number of synchronisations with bad durations. - * @bad_syncs: Number of failed synchronisations. - * @last_sync_time: Number of nanoseconds for last synchronisation. - * @sync_timeouts: Number of synchronisation timeouts - * @fast_syncs: Number of synchronisations requiring short delay - * @min_sync_delta: Minimum time between event and synchronisation - * @max_sync_delta: Maximum time between event and synchronisation - * @average_sync_delta: Average time between event and synchronisation. - * Modified moving average. - * @last_sync_delta: Last time between event and synchronisation - * @mc_stats: Context value for MC statistics * @timeset: Last set of synchronisation statistics. */ struct efx_ptp_data { -- cgit v1.2.3 From 94cd60d09eba9e8de0522d416d867fb16858fccd Mon Sep 17 00:00:00 2001 From: Laurence Evans Date: Thu, 21 Nov 2013 10:38:24 +0000 Subject: sfc: PTP - tidy up unused/useless variables Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index be7ed4e1c96c..82d8e27e8a58 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -237,9 +237,6 @@ struct efx_ptp_timeset { * @evt_code: Last event code * @start: Address at which MC indicates ready for synchronisation * @host_time_pps: Host time at last PPS - * @last_sync_ns: Last number of nanoseconds between readings when synchronising - * @base_sync_ns: Number of nanoseconds for last synchronisation. - * @base_sync_valid: Whether base_sync_time is valid. * @current_adjfreq: Current ppb adjustment. * @phc_clock: Pointer to registered phc device * @phc_clock_info: Registration structure for phc device @@ -274,9 +271,6 @@ struct efx_ptp_data { int evt_code; struct efx_buffer start; struct pps_event_time host_time_pps; - unsigned last_sync_ns; - unsigned base_sync_ns; - bool base_sync_valid; s64 current_adjfreq; struct ptp_clock *phc_clock; struct ptp_clock_info phc_clock_info; @@ -482,18 +476,10 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), if (ngood == 0) { netif_warn(efx, drv, efx->net_dev, - "PTP no suitable synchronisations %dns\n", - ptp->base_sync_ns); + "PTP no suitable synchronisations\n"); return -EAGAIN; } - /* Average minimum this synchronisation */ - ptp->last_sync_ns = DIV_ROUND_UP(total, ngood); - if (!ptp->base_sync_valid || (ptp->last_sync_ns < ptp->base_sync_ns)) { - ptp->base_sync_valid = true; - ptp->base_sync_ns = ptp->last_sync_ns; - } - /* Calculate delay from actual PPS to last_time */ delta.tv_nsec = ptp->timeset[last_good].nanoseconds + -- cgit v1.2.3 From dfd8d581fbdce9f3b4777a7c59d28ca35ed194be Mon Sep 17 00:00:00 2001 From: Laurence Evans Date: Thu, 21 Nov 2013 10:38:24 +0000 Subject: sfc: Tidy up PTP synchronization code Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 44 +++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 82d8e27e8a58..361d7cedd897 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -435,7 +435,6 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), MCDI_VAR_ARRAY_LEN(response_length, PTP_OUT_SYNCHRONIZE_TIMESET); unsigned i; - unsigned total; unsigned ngood = 0; unsigned last_good = 0; struct efx_ptp_data *ptp = efx->ptp_data; @@ -446,33 +445,38 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), if (number_readings == 0) return -EAGAIN; - /* Read the set of results and increment stats for any results that - * appera to be erroneous. + /* Read the set of results and find the last good host-MC + * synchronization result. The MC times when it finishes reading the + * host time so the corrected window time should be fairly constant + * for a given platform. */ for (i = 0; i < number_readings; i++) { + s32 window, corrected; + efx_ptp_read_timeset( MCDI_ARRAY_STRUCT_PTR(synch_buf, PTP_OUT_SYNCHRONIZE_TIMESET, i), &ptp->timeset[i]); - } - /* Find the last good host-MC synchronization result. The MC times - * when it finishes reading the host time so the corrected window time - * should be fairly constant for a given platform. - */ - total = 0; - for (i = 0; i < number_readings; i++) - if (ptp->timeset[i].window > ptp->timeset[i].waitns) { - unsigned win; - - win = ptp->timeset[i].window - ptp->timeset[i].waitns; - if (win >= MIN_SYNCHRONISATION_NS && - win < MAX_SYNCHRONISATION_NS) { - total += ptp->timeset[i].window; - ngood++; - last_good = i; - } + window = ptp->timeset[i].window; + corrected = window - ptp->timeset[i].waitns; + + /* We expect the uncorrected synchronization window to be at + * least as large as the interval between host start and end + * times. If it is smaller than this then this is mostly likely + * to be a consequence of the host's time being adjusted. + * Check that the corrected sync window is in a reasonable + * range. If it is out of range it is likely to be because an + * interrupt or other delay occurred between reading the system + * time and writing it to MC memory. + */ + if (window >= SYNCHRONISATION_GRANULARITY_NS && + corrected < MAX_SYNCHRONISATION_NS && + corrected >= MIN_SYNCHRONISATION_NS) { + ngood++; + last_good = i; } + } if (ngood == 0) { netif_warn(efx, drv, efx->net_dev, -- cgit v1.2.3 From a6f73460b592404cca4ceafa69a835a61cdc20d8 Mon Sep 17 00:00:00 2001 From: Laurence Evans Date: Wed, 4 Dec 2013 23:47:56 +0000 Subject: sfc: Add support for SFC9100 timestamp format The clock minor tick on the SFC9100 family is 2^-27 s, not 1 ns. There are also various pipeline delays which we need to correct for when interpreting timestamps. We query the firmware for the clock format and corrections at run-time. [bwh: Combined and rebased several changes] Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 256 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 231 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 361d7cedd897..cf2ae11b13f1 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -62,7 +62,7 @@ #define SYNCHRONISATION_GRANULARITY_NS 200 /* Minimum permitted length of a (corrected) synchronisation time */ -#define MIN_SYNCHRONISATION_NS 120 +#define DEFAULT_MIN_SYNCHRONISATION_NS 120 /* Maximum permitted length of a (corrected) synchronisation time */ #define MAX_SYNCHRONISATION_NS 1000 @@ -195,20 +195,20 @@ struct efx_ptp_event_rx { /** * struct efx_ptp_timeset - Synchronisation between host and MC * @host_start: Host time immediately before hardware timestamp taken - * @seconds: Hardware timestamp, seconds - * @nanoseconds: Hardware timestamp, nanoseconds + * @major: Hardware timestamp, major + * @minor: Hardware timestamp, minor * @host_end: Host time immediately after hardware timestamp taken - * @waitns: Number of nanoseconds between hardware timestamp being read and + * @wait: Number of NIC clock ticks between hardware timestamp being read and * host end time being seen * @window: Difference of host_end and host_start * @valid: Whether this timeset is valid */ struct efx_ptp_timeset { u32 host_start; - u32 seconds; - u32 nanoseconds; + u32 major; + u32 minor; u32 host_end; - u32 waitns; + u32 wait; u32 window; /* Derived: end - start, allowing for wrap */ }; @@ -232,6 +232,14 @@ struct efx_ptp_timeset { * @config: Current timestamp configuration * @enabled: PTP operation enabled * @mode: Mode in which PTP operating (PTP version) + * @time_format: Time format supported by this NIC + * @ns_to_nic_time: Function to convert from scalar nanoseconds to NIC time + * @nic_to_kernel_time: Function to convert from NIC to kernel time + * @min_synchronisation_ns: Minimum acceptable corrected sync window + * @ts_corrections.tx: Required driver correction of transmit timestamps + * @ts_corrections.rx: Required driver correction of receive timestamps + * @ts_corrections.pps_out: PPS output error (information only) + * @ts_corrections.pps_in: Required driver correction of PPS input timestamps * @evt_frags: Partly assembled PTP events * @evt_frag_idx: Current fragment number * @evt_code: Last event code @@ -266,6 +274,17 @@ struct efx_ptp_data { struct hwtstamp_config config; bool enabled; unsigned int mode; + unsigned int time_format; + void (*ns_to_nic_time)(s64 ns, u32 *nic_major, u32 *nic_minor); + ktime_t (*nic_to_kernel_time)(u32 nic_major, u32 nic_minor, + s32 correction); + unsigned int min_synchronisation_ns; + struct { + s32 tx; + s32 rx; + s32 pps_out; + s32 pps_in; + } ts_corrections; efx_qword_t evt_frags[MAX_EVENT_FRAGS]; int evt_frag_idx; int evt_code; @@ -290,6 +309,167 @@ static int efx_phc_settime(struct ptp_clock_info *ptp, static int efx_phc_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *request, int on); +/* For Siena platforms NIC time is s and ns */ +static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor) +{ + struct timespec ts = ns_to_timespec(ns); + *nic_major = ts.tv_sec; + *nic_minor = ts.tv_nsec; +} + +static ktime_t efx_ptp_s_ns_to_ktime(u32 nic_major, u32 nic_minor, + s32 correction) +{ + ktime_t kt = ktime_set(nic_major, nic_minor); + if (correction >= 0) + kt = ktime_add_ns(kt, (u64)correction); + else + kt = ktime_sub_ns(kt, (u64)-correction); + return kt; +} + +/* To convert from s27 format to ns we multiply then divide by a power of 2. + * For the conversion from ns to s27, the operation is also converted to a + * multiply and shift. + */ +#define S27_TO_NS_SHIFT (27) +#define NS_TO_S27_MULT (((1ULL << 63) + NSEC_PER_SEC / 2) / NSEC_PER_SEC) +#define NS_TO_S27_SHIFT (63 - S27_TO_NS_SHIFT) +#define S27_MINOR_MAX (1 << S27_TO_NS_SHIFT) + +/* For Huntington platforms NIC time is in seconds and fractions of a second + * where the minor register only uses 27 bits in units of 2^-27s. + */ +static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor) +{ + struct timespec ts = ns_to_timespec(ns); + u32 maj = ts.tv_sec; + u32 min = (u32)(((u64)ts.tv_nsec * NS_TO_S27_MULT + + (1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT); + + /* The conversion can result in the minor value exceeding the maximum. + * In this case, round up to the next second. + */ + if (min >= S27_MINOR_MAX) { + min -= S27_MINOR_MAX; + maj++; + } + + *nic_major = maj; + *nic_minor = min; +} + +static ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor, + s32 correction) +{ + u32 ns; + + /* Apply the correction and deal with carry */ + nic_minor += correction; + if ((s32)nic_minor < 0) { + nic_minor += S27_MINOR_MAX; + nic_major--; + } else if (nic_minor >= S27_MINOR_MAX) { + nic_minor -= S27_MINOR_MAX; + nic_major++; + } + + ns = (u32)(((u64)nic_minor * NSEC_PER_SEC + + (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); + + return ktime_set(nic_major, ns); +} + +/* Get PTP attributes and set up time conversions */ +static int efx_ptp_get_attributes(struct efx_nic *efx) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_GET_ATTRIBUTES_LEN); + MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_GET_ATTRIBUTES_LEN); + struct efx_ptp_data *ptp = efx->ptp_data; + int rc; + u32 fmt; + size_t out_len; + + /* Get the PTP attributes. If the NIC doesn't support the operation we + * use the default format for compatibility with older NICs i.e. + * seconds and nanoseconds. + */ + MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_GET_ATTRIBUTES); + MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); + rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), &out_len); + if (rc == 0) + fmt = MCDI_DWORD(outbuf, PTP_OUT_GET_ATTRIBUTES_TIME_FORMAT); + else if (rc == -EINVAL) + fmt = MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS; + else + return rc; + + if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_27FRACTION) { + ptp->ns_to_nic_time = efx_ptp_ns_to_s27; + ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime; + } else if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS) { + ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; + ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime; + } else { + return -ERANGE; + } + + ptp->time_format = fmt; + + /* MC_CMD_PTP_OP_GET_ATTRIBUTES is an extended version of an older + * operation MC_CMD_PTP_OP_GET_TIME_FORMAT that also returns a value + * to use for the minimum acceptable corrected synchronization window. + * If we have the extra information store it. For older firmware that + * does not implement the extended command use the default value. + */ + if (rc == 0 && out_len >= MC_CMD_PTP_OUT_GET_ATTRIBUTES_LEN) + ptp->min_synchronisation_ns = + MCDI_DWORD(outbuf, + PTP_OUT_GET_ATTRIBUTES_SYNC_WINDOW_MIN); + else + ptp->min_synchronisation_ns = DEFAULT_MIN_SYNCHRONISATION_NS; + + return 0; +} + +/* Get PTP timestamp corrections */ +static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_GET_TIMESTAMP_CORRECTIONS_LEN); + MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN); + int rc; + + /* Get the timestamp corrections from the NIC. If this operation is + * not supported (older NICs) then no correction is required. + */ + MCDI_SET_DWORD(inbuf, PTP_IN_OP, + MC_CMD_PTP_OP_GET_TIMESTAMP_CORRECTIONS); + MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); + + rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), NULL); + if (rc == 0) { + efx->ptp_data->ts_corrections.tx = MCDI_DWORD(outbuf, + PTP_OUT_GET_TIMESTAMP_CORRECTIONS_TRANSMIT); + efx->ptp_data->ts_corrections.rx = MCDI_DWORD(outbuf, + PTP_OUT_GET_TIMESTAMP_CORRECTIONS_RECEIVE); + efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf, + PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_OUT); + efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf, + PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_IN); + } else if (rc == -EINVAL) { + efx->ptp_data->ts_corrections.tx = 0; + efx->ptp_data->ts_corrections.rx = 0; + efx->ptp_data->ts_corrections.pps_out = 0; + efx->ptp_data->ts_corrections.pps_in = 0; + } else { + return rc; + } + + return 0; +} + /* Enable MCDI PTP support. */ static int efx_ptp_enable(struct efx_nic *efx) { @@ -402,11 +582,10 @@ static void efx_ptp_read_timeset(MCDI_DECLARE_STRUCT_PTR(data), unsigned start_ns, end_ns; timeset->host_start = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTSTART); - timeset->seconds = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_SECONDS); - timeset->nanoseconds = MCDI_DWORD(data, - PTP_OUT_SYNCHRONIZE_NANOSECONDS); + timeset->major = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MAJOR); + timeset->minor = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MINOR); timeset->host_end = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTEND), - timeset->waitns = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); + timeset->wait = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); /* Ignore seconds */ start_ns = timeset->host_start & MC_NANOSECOND_MASK; @@ -441,6 +620,7 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), u32 last_sec; u32 start_sec; struct timespec delta; + ktime_t mc_time; if (number_readings == 0) return -EAGAIN; @@ -452,14 +632,17 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), */ for (i = 0; i < number_readings; i++) { s32 window, corrected; + struct timespec wait; efx_ptp_read_timeset( MCDI_ARRAY_STRUCT_PTR(synch_buf, PTP_OUT_SYNCHRONIZE_TIMESET, i), &ptp->timeset[i]); + wait = ktime_to_timespec( + ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0)); window = ptp->timeset[i].window; - corrected = window - ptp->timeset[i].waitns; + corrected = window - wait.tv_nsec; /* We expect the uncorrected synchronization window to be at * least as large as the interval between host start and end @@ -472,7 +655,7 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), */ if (window >= SYNCHRONISATION_GRANULARITY_NS && corrected < MAX_SYNCHRONISATION_NS && - corrected >= MIN_SYNCHRONISATION_NS) { + corrected >= ptp->min_synchronisation_ns) { ngood++; last_good = i; } @@ -484,9 +667,15 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), return -EAGAIN; } + /* Convert the NIC time into kernel time. No correction is required- + * this time is the output of a firmware process. + */ + mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, + ptp->timeset[last_good].minor, 0); + /* Calculate delay from actual PPS to last_time */ - delta.tv_nsec = - ptp->timeset[last_good].nanoseconds + + delta = ktime_to_timespec(mc_time); + delta.tv_nsec += last_time->ts_real.tv_nsec - (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); @@ -596,9 +785,10 @@ static int efx_ptp_xmit_skb(struct efx_nic *efx, struct sk_buff *skb) goto fail; memset(×tamps, 0, sizeof(timestamps)); - timestamps.hwtstamp = ktime_set( - MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_SECONDS), - MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_NANOSECONDS)); + timestamps.hwtstamp = ptp_data->nic_to_kernel_time( + MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MAJOR), + MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MINOR), + ptp_data->ts_corrections.tx); skb_tstamp_tx(skb, ×tamps); @@ -954,6 +1144,16 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); ptp->evt_overflow = false; + /* Get the NIC PTP attributes and set up time conversions */ + rc = efx_ptp_get_attributes(efx); + if (rc < 0) + goto fail3; + + /* Get the timestamp corrections */ + rc = efx_ptp_get_timestamp_corrections(efx); + if (rc < 0) + goto fail3; + ptp->phc_clock_info = efx_phc_clock_info; ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, &efx->pci_dev->dev); @@ -1358,9 +1558,10 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) MCDI_EVENT_SRC) << 8) | (EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_SRC) << 16)); - evt->hwtimestamp = ktime_set( + evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time( EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA), - EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA)); + EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA), + ptp->ts_corrections.rx); evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); list_add_tail(&evt->link, &ptp->evt_list); @@ -1470,18 +1671,20 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) { + u32 nic_major, nic_minor; struct efx_ptp_data *ptp_data = container_of(ptp, struct efx_ptp_data, phc_clock_info); struct efx_nic *efx = ptp_data->efx; - struct timespec delta_ts = ns_to_timespec(delta); MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN); + efx->ptp_data->ns_to_nic_time(delta, &nic_major, &nic_minor); + MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST); MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); - MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec); - MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec); + MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_MAJOR, nic_major); + MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_MINOR, nic_minor); return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), NULL, 0, NULL); } @@ -1495,6 +1698,7 @@ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_READ_NIC_TIME_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_READ_NIC_TIME_LEN); int rc; + ktime_t kt; MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_READ_NIC_TIME); MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); @@ -1504,8 +1708,10 @@ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) if (rc != 0) return rc; - ts->tv_sec = MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_SECONDS); - ts->tv_nsec = MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_NANOSECONDS); + kt = ptp_data->nic_to_kernel_time( + MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_MAJOR), + MCDI_DWORD(outbuf, PTP_OUT_READ_NIC_TIME_MINOR), 0); + *ts = ktime_to_timespec(kt); return 0; } -- cgit v1.2.3 From 9ec0659595c8020f1efa55aa00870e8773f8ee89 Mon Sep 17 00:00:00 2001 From: Daniel Pieczko Date: Thu, 21 Nov 2013 17:11:25 +0000 Subject: sfc: split setup of hardware timestamping into NIC-type operation I added efx_ptp_get_mode() to avoid moving the definition for efx_ptp_data, since the current PTP mode is needed for siena.c:siena_set_ptp_hwtstamp. [bwh: Also move the rx_filters mask, and add kernel-doc] Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/net_driver.h | 9 +++++ drivers/net/ethernet/sfc/nic.h | 3 ++ drivers/net/ethernet/sfc/ptp.c | 69 +++++------------------------------ drivers/net/ethernet/sfc/siena.c | 69 ++++++++++++++++++++++++++++------- 4 files changed, 78 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index f47bac78b92c..01ffbe849683 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -91,6 +91,7 @@ /* Forward declare Precision Time Protocol (PTP) support structure. */ struct efx_ptp_data; +struct hwtstamp_config; struct efx_self_tests; @@ -1042,6 +1043,10 @@ struct efx_mtd_partition { * @mtd_sync: Wait for write-back to complete on MTD partition. This * also notifies the driver that a writer has finished using this * partition. + * @ptp_write_host_time: Send host time to MC as part of sync protocol + * @ptp_set_ts_config: Set hardware timestamp configuration. The flags + * and tx_type will already have been validated but this operation + * must validate and update rx_filter. * @revision: Hardware architecture revision * @txd_ptr_tbl_base: TX descriptor ring base address * @rxd_ptr_tbl_base: RX descriptor ring base address @@ -1060,6 +1065,7 @@ struct efx_mtd_partition { * @offload_features: net_device feature flags for protocol offload * features implemented in hardware * @mcdi_max_ver: Maximum MCDI version supported + * @hwtstamp_filters: Mask of hardware timestamp filter types supported */ struct efx_nic_type { unsigned int (*mem_map_size)(struct efx_nic *efx); @@ -1161,6 +1167,8 @@ struct efx_nic_type { int (*mtd_sync)(struct mtd_info *mtd); #endif void (*ptp_write_host_time)(struct efx_nic *efx, u32 host_time); + int (*ptp_set_ts_config)(struct efx_nic *efx, + struct hwtstamp_config *init); int revision; unsigned int txd_ptr_tbl_base; @@ -1179,6 +1187,7 @@ struct efx_nic_type { netdev_features_t offload_features; int mcdi_max_ver; unsigned int max_rx_ip_filters; + u32 hwtstamp_filters; }; /************************************************************************** diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 25178536f053..999ef285662d 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -561,6 +561,9 @@ int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); +int efx_ptp_get_mode(struct efx_nic *efx); +int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, + unsigned int new_mode); int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); void efx_ptp_start_datapath(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index cf2ae11b13f1..1d1a6f7325da 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1361,8 +1361,13 @@ int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb) return NETDEV_TX_OK; } -static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, - unsigned int new_mode) +int efx_ptp_get_mode(struct efx_nic *efx) +{ + return efx->ptp_data->mode; +} + +int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, + unsigned int new_mode) { if ((enable_wanted != efx->ptp_data->enabled) || (enable_wanted && (efx->ptp_data->mode != new_mode))) { @@ -1406,8 +1411,6 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) { - bool enable_wanted = false; - unsigned int new_mode; int rc; if (init->flags) @@ -1417,57 +1420,11 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) (init->tx_type != HWTSTAMP_TX_ON)) return -ERANGE; - new_mode = efx->ptp_data->mode; - /* Determine whether any PTP HW operations are required */ - switch (init->rx_filter) { - case HWTSTAMP_FILTER_NONE: - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - init->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; - new_mode = MC_CMD_PTP_MODE_V1; - enable_wanted = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - /* Although these three are accepted only IPV4 packets will be - * timestamped - */ - init->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; - new_mode = MC_CMD_PTP_MODE_V2_ENHANCED; - enable_wanted = true; - break; - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - /* Non-IP + IPv6 timestamping not supported */ - return -ERANGE; - break; - default: - return -ERANGE; - } - - if (init->tx_type != HWTSTAMP_TX_OFF) - enable_wanted = true; - - /* Old versions of the firmware do not support the improved - * UUID filtering option (SF bug 33070). If the firmware does - * not accept the enhanced mode, fall back to the standard PTP - * v2 UUID filtering. - */ - rc = efx_ptp_change_mode(efx, enable_wanted, new_mode); - if ((rc != 0) && (new_mode == MC_CMD_PTP_MODE_V2_ENHANCED)) - rc = efx_ptp_change_mode(efx, enable_wanted, MC_CMD_PTP_MODE_V2); - if (rc != 0) + rc = efx->type->ptp_set_ts_config(efx, init); + if (rc) return rc; efx->ptp_data->config = *init; - return 0; } @@ -1483,13 +1440,7 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) SOF_TIMESTAMPING_RAW_HARDWARE); ts_info->phc_index = ptp_clock_index(ptp->phc_clock); ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; - ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE | - 1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT | - 1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC | - 1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ | - 1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT | - 1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC | - 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); + ts_info->rx_filters = ptp->efx->type->hwtstamp_filters; } int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr) diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 53b4ce67be0e..f65db356fe09 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -116,6 +116,54 @@ out: return rc ? rc : rc2; } +/************************************************************************** + * + * PTP + * + ************************************************************************** + */ + +static void siena_ptp_write_host_time(struct efx_nic *efx, u32 host_time) +{ + _efx_writed(efx, cpu_to_le32(host_time), + FR_CZ_MC_TREG_SMEM + MC_SMEM_P0_PTP_TIME_OFST); +} + +static int siena_ptp_set_ts_config(struct efx_nic *efx, + struct hwtstamp_config *init) +{ + int rc; + + switch (init->rx_filter) { + case HWTSTAMP_FILTER_NONE: + /* if TX timestamping is still requested then leave PTP on */ + return efx_ptp_change_mode(efx, + init->tx_type != HWTSTAMP_TX_OFF, + efx_ptp_get_mode(efx)); + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + init->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; + return efx_ptp_change_mode(efx, true, MC_CMD_PTP_MODE_V1); + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + init->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; + rc = efx_ptp_change_mode(efx, true, + MC_CMD_PTP_MODE_V2_ENHANCED); + /* bug 33070 - old versions of the firmware do not support the + * improved UUID filtering option. Similarly old versions of the + * application do not expect it to be enabled. If the firmware + * does not accept the enhanced mode, fall back to the standard + * PTP v2 UUID filtering. */ + if (rc != 0) + rc = efx_ptp_change_mode(efx, true, MC_CMD_PTP_MODE_V2); + return rc; + default: + return -ERANGE; + } +} + /************************************************************************** * * Device reset @@ -837,19 +885,6 @@ fail: #endif /* CONFIG_SFC_MTD */ -/************************************************************************** - * - * PTP - * - ************************************************************************** - */ - -static void siena_ptp_write_host_time(struct efx_nic *efx, u32 host_time) -{ - _efx_writed(efx, cpu_to_le32(host_time), - FR_CZ_MC_TREG_SMEM + MC_SMEM_P0_PTP_TIME_OFST); -} - /************************************************************************** * * Revision-dependent attributes used by efx.c and nic.c @@ -942,6 +977,7 @@ const struct efx_nic_type siena_a0_nic_type = { .mtd_sync = efx_mcdi_mtd_sync, #endif .ptp_write_host_time = siena_ptp_write_host_time, + .ptp_set_ts_config = siena_ptp_set_ts_config, .revision = EFX_REV_SIENA_A0, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, @@ -960,4 +996,11 @@ const struct efx_nic_type siena_a0_nic_type = { NETIF_F_RXHASH | NETIF_F_NTUPLE), .mcdi_max_ver = 1, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, + .hwtstamp_filters = (1 << HWTSTAMP_FILTER_NONE | + 1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT | + 1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC | + 1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ | + 1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT | + 1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC | + 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ), }; -- cgit v1.2.3 From 2ccd0b192534b1dc6af45ffb81faa44b7ae416bf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 28 Nov 2013 18:58:11 +0000 Subject: sfc: Copy RX prefix into skb head area in efx_rx_mk_skb() We can potentially pull the entire packet contents into the head area and then free the page it was in. In order to read an inline timestamp safely, we need to copy the prefix into the head area as well. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/net_driver.h | 9 --------- drivers/net/ethernet/sfc/rx.c | 10 +++++++--- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 01ffbe849683..1a3e4972c68f 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -521,15 +521,6 @@ enum nic_state { STATE_RECOVERY = 3, /* device recovering from PCI error */ }; -/* - * Alignment of the skb->head which wraps a page-allocated RX buffer - * - * The skb allocated to wrap an rx_buffer can have this alignment. Since - * the data is memcpy'd from the rx_buf, it does not need to be equal to - * NET_IP_ALIGN. - */ -#define EFX_PAGE_SKB_ALIGN 2 - /* Forward declaration */ struct efx_nic; diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 8671bc199a9d..d12abc543975 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -476,14 +476,18 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel, struct sk_buff *skb; /* Allocate an SKB to store the headers */ - skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN); + skb = netdev_alloc_skb(efx->net_dev, + efx->rx_ip_align + efx->rx_prefix_size + + hdr_len); if (unlikely(skb == NULL)) return NULL; EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len); - skb_reserve(skb, EFX_PAGE_SKB_ALIGN); - memcpy(__skb_put(skb, hdr_len), eh, hdr_len); + memcpy(skb->data + efx->rx_ip_align, eh - efx->rx_prefix_size, + efx->rx_prefix_size + hdr_len); + skb_reserve(skb, efx->rx_ip_align + efx->rx_prefix_size); + __skb_put(skb, hdr_len); /* Append the remaining page(s) onto the frag list */ if (rx_buf->len > hdr_len) { -- cgit v1.2.3 From bd9a265db26cdbfe74a303111381d90e66f56877 Mon Sep 17 00:00:00 2001 From: Jon Cooper Date: Mon, 18 Nov 2013 12:54:41 +0000 Subject: sfc: Add RX packet timestamping for EF10 The EF10 firmware can optionally insert RX timestamps in the packet prefix. These only include the clock minor value. We must also enable periodic time sync events on each event queue which provide the high bits of the clock value. [bwh: Combined and rebased several changes. Added the above description and some sanity checks for inline vs separate timestamps. Changed efx_rx_skb_attach_timestamp() to read the packet prefix from the skb head area.] Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 123 ++++++++++++++++++++++++++++++- drivers/net/ethernet/sfc/efx.c | 2 + drivers/net/ethernet/sfc/mcdi.c | 3 + drivers/net/ethernet/sfc/net_driver.h | 22 ++++++ drivers/net/ethernet/sfc/nic.h | 9 +++ drivers/net/ethernet/sfc/ptp.c | 131 ++++++++++++++++++++++++++++++---- drivers/net/ethernet/sfc/rx.c | 2 + 7 files changed, 277 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index ca922b958a2e..a3d891764030 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1469,8 +1469,9 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue) MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_LABEL, efx_rx_queue_index(rx_queue)); MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_INSTANCE, efx_rx_queue_index(rx_queue)); - MCDI_POPULATE_DWORD_1(inbuf, INIT_RXQ_IN_FLAGS, - INIT_RXQ_IN_FLAG_PREFIX, 1); + MCDI_POPULATE_DWORD_2(inbuf, INIT_RXQ_IN_FLAGS, + INIT_RXQ_IN_FLAG_PREFIX, 1, + INIT_RXQ_IN_FLAG_TIMESTAMP, 1); MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_OWNER_ID, 0); MCDI_SET_DWORD(inbuf, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); @@ -3406,6 +3407,119 @@ static void efx_ef10_ptp_write_host_time(struct efx_nic *efx, u32 host_time) _efx_writed(efx, cpu_to_le32(host_time), ER_DZ_MC_DB_LWRD); } +static int efx_ef10_rx_enable_timestamping(struct efx_channel *channel, + bool temp) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE_LEN); + int rc; + + if (channel->sync_events_state == SYNC_EVENTS_REQUESTED || + channel->sync_events_state == SYNC_EVENTS_VALID || + (temp && channel->sync_events_state == SYNC_EVENTS_DISABLED)) + return 0; + channel->sync_events_state = SYNC_EVENTS_REQUESTED; + + MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_SUBSCRIBE); + MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); + MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_SUBSCRIBE_QUEUE, + channel->channel); + + rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP, + inbuf, sizeof(inbuf), NULL, 0, NULL); + + if (rc != 0) + channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT : + SYNC_EVENTS_DISABLED; + + return rc; +} + +static int efx_ef10_rx_disable_timestamping(struct efx_channel *channel, + bool temp) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_LEN); + int rc; + + if (channel->sync_events_state == SYNC_EVENTS_DISABLED || + (temp && channel->sync_events_state == SYNC_EVENTS_QUIESCENT)) + return 0; + if (channel->sync_events_state == SYNC_EVENTS_QUIESCENT) { + channel->sync_events_state = SYNC_EVENTS_DISABLED; + return 0; + } + channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT : + SYNC_EVENTS_DISABLED; + + MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_UNSUBSCRIBE); + MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); + MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_CONTROL, + MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_SINGLE); + MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_QUEUE, + channel->channel); + + rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP, + inbuf, sizeof(inbuf), NULL, 0, NULL); + + return rc; +} + +static int efx_ef10_ptp_set_ts_sync_events(struct efx_nic *efx, bool en, + bool temp) +{ + int (*set)(struct efx_channel *channel, bool temp); + struct efx_channel *channel; + + set = en ? + efx_ef10_rx_enable_timestamping : + efx_ef10_rx_disable_timestamping; + + efx_for_each_channel(channel, efx) { + int rc = set(channel, temp); + if (en && rc != 0) { + efx_ef10_ptp_set_ts_sync_events(efx, false, temp); + return rc; + } + } + + return 0; +} + +static int efx_ef10_ptp_set_ts_config(struct efx_nic *efx, + struct hwtstamp_config *init) +{ + int rc; + + switch (init->rx_filter) { + case HWTSTAMP_FILTER_NONE: + efx_ef10_ptp_set_ts_sync_events(efx, false, false); + /* if TX timestamping is still requested then leave PTP on */ + return efx_ptp_change_mode(efx, + init->tx_type != HWTSTAMP_TX_OFF, 0); + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + init->rx_filter = HWTSTAMP_FILTER_ALL; + rc = efx_ptp_change_mode(efx, true, 0); + if (!rc) + rc = efx_ef10_ptp_set_ts_sync_events(efx, true, false); + if (rc) + efx_ptp_change_mode(efx, false, 0); + return rc; + default: + return -ERANGE; + } +} + const struct efx_nic_type efx_hunt_a0_nic_type = { .mem_map_size = efx_ef10_mem_map_size, .probe = efx_ef10_probe, @@ -3484,11 +3598,14 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .mtd_sync = efx_mcdi_mtd_sync, #endif .ptp_write_host_time = efx_ef10_ptp_write_host_time, + .ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events, + .ptp_set_ts_config = efx_ef10_ptp_set_ts_config, .revision = EFX_REV_HUNT_A0, .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), .rx_prefix_size = ES_DZ_RX_PREFIX_SIZE, .rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST, + .rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST, .can_rx_scatter = true, .always_rx_scatter = true, .max_interrupt_mode = EFX_INT_MODE_MSIX, @@ -3497,4 +3614,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { NETIF_F_RXHASH | NETIF_F_NTUPLE), .mcdi_max_ver = 2, .max_rx_ip_filters = HUNT_FILTER_TBL_ROWS, + .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | + 1 << HWTSTAMP_FILTER_ALL, }; diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 893cd78c3a6c..b9929d9ed69d 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2586,6 +2586,8 @@ static int efx_init_struct(struct efx_nic *efx, NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; efx->rx_packet_hash_offset = efx->type->rx_hash_offset - efx->type->rx_prefix_size; + efx->rx_packet_ts_offset = + efx->type->rx_ts_offset - efx->type->rx_prefix_size; spin_lock_init(&efx->stats_lock); mutex_init(&efx->mac_lock); efx->phy_op = &efx_dummy_phy_operations; diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index d608838f6729..540f57915d6f 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1018,6 +1018,9 @@ void efx_mcdi_process_event(struct efx_channel *channel, case MCDI_EVENT_CODE_PTP_PPS: efx_ptp_event(efx, event); break; + case MCDI_EVENT_CODE_PTP_TIME: + efx_time_sync_event(channel, event); + break; case MCDI_EVENT_CODE_TX_FLUSH: case MCDI_EVENT_CODE_RX_FLUSH: /* Two flush events will be sent: one to the same event diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 1a3e4972c68f..0d0e8eb88332 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -369,6 +369,13 @@ enum efx_rx_alloc_method { RX_ALLOC_METHOD_PAGE = 2, }; +enum efx_sync_events_state { + SYNC_EVENTS_DISABLED = 0, + SYNC_EVENTS_QUIESCENT, + SYNC_EVENTS_REQUESTED, + SYNC_EVENTS_VALID, +}; + /** * struct efx_channel - An Efx channel * @@ -408,6 +415,9 @@ enum efx_rx_alloc_method { * by __efx_rx_packet(), if @rx_pkt_n_frags != 0 * @rx_queue: RX queue for this channel * @tx_queue: TX queues for this channel + * @sync_events_state: Current state of sync events on this channel + * @sync_timestamp_major: Major part of the last ptp sync event + * @sync_timestamp_minor: Minor part of the last ptp sync event */ struct efx_channel { struct efx_nic *efx; @@ -446,6 +456,10 @@ struct efx_channel { struct efx_rx_queue rx_queue; struct efx_tx_queue tx_queue[EFX_TXQ_TYPES]; + + enum efx_sync_events_state sync_events_state; + u32 sync_timestamp_major; + u32 sync_timestamp_minor; }; /** @@ -686,6 +700,8 @@ struct vfdi_status; * (valid only if @rx_prefix_size != 0; always negative) * @rx_packet_len_offset: Offset of RX packet length from start of packet data * (valid only for NICs that set %EFX_RX_PKT_PREFIX_LEN; always negative) + * @rx_packet_ts_offset: Offset of timestamp from start of packet data + * (valid only if channel->sync_timestamps_enabled; always negative) * @rx_hash_key: Toeplitz hash key for RSS * @rx_indir_table: Indirection table for RSS * @rx_scatter: Scatter mode enabled for receives @@ -820,6 +836,7 @@ struct efx_nic { unsigned int rx_prefix_size; int rx_packet_hash_offset; int rx_packet_len_offset; + int rx_packet_ts_offset; u8 rx_hash_key[40]; u32 rx_indir_table[128]; bool rx_scatter; @@ -1035,6 +1052,8 @@ struct efx_mtd_partition { * also notifies the driver that a writer has finished using this * partition. * @ptp_write_host_time: Send host time to MC as part of sync protocol + * @ptp_set_ts_sync_events: Enable or disable sync events for inline RX + * timestamping, possibly only temporarily for the purposes of a reset. * @ptp_set_ts_config: Set hardware timestamp configuration. The flags * and tx_type will already have been validated but this operation * must validate and update rx_filter. @@ -1047,6 +1066,7 @@ struct efx_mtd_partition { * @max_dma_mask: Maximum possible DMA mask * @rx_prefix_size: Size of RX prefix before packet data * @rx_hash_offset: Offset of RX flow hash within prefix + * @rx_ts_offset: Offset of timestamp within prefix * @rx_buffer_padding: Size of padding at end of RX packet * @can_rx_scatter: NIC is able to scatter packets to multiple buffers * @always_rx_scatter: NIC will always scatter packets to multiple buffers @@ -1158,6 +1178,7 @@ struct efx_nic_type { int (*mtd_sync)(struct mtd_info *mtd); #endif void (*ptp_write_host_time)(struct efx_nic *efx, u32 host_time); + int (*ptp_set_ts_sync_events)(struct efx_nic *efx, bool en, bool temp); int (*ptp_set_ts_config)(struct efx_nic *efx, struct hwtstamp_config *init); @@ -1170,6 +1191,7 @@ struct efx_nic_type { u64 max_dma_mask; unsigned int rx_prefix_size; unsigned int rx_hash_offset; + unsigned int rx_ts_offset; unsigned int rx_buffer_padding; bool can_rx_scatter; bool always_rx_scatter; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 999ef285662d..5d9e2dc121f7 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -566,6 +566,15 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, unsigned int new_mode); int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); +void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev); +void __efx_rx_skb_attach_timestamp(struct efx_channel *channel, + struct sk_buff *skb); +static inline void efx_rx_skb_attach_timestamp(struct efx_channel *channel, + struct sk_buff *skb) +{ + if (channel->sync_events_state == SYNC_EVENTS_VALID) + __efx_rx_skb_attach_timestamp(channel, skb); +} void efx_ptp_start_datapath(struct efx_nic *efx); void efx_ptp_stop_datapath(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 1d1a6f7325da..843e98dfb1b2 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -216,6 +216,8 @@ struct efx_ptp_timeset { * struct efx_ptp_data - Precision Time Protocol (PTP) state * @efx: The NIC context * @channel: The PTP channel (Siena only) + * @rx_ts_inline: Flag for whether RX timestamps are inline (else they are + * separate events) * @rxq: Receive queue (awaiting timestamps) * @txq: Transmit queue * @evt_list: List of MC receive events awaiting packets @@ -258,6 +260,7 @@ struct efx_ptp_timeset { struct efx_ptp_data { struct efx_nic *efx; struct efx_channel *channel; + bool rx_ts_inline; struct sk_buff_head rxq; struct sk_buff_head txq; struct list_head evt_list; @@ -317,8 +320,8 @@ static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor) *nic_minor = ts.tv_nsec; } -static ktime_t efx_ptp_s_ns_to_ktime(u32 nic_major, u32 nic_minor, - s32 correction) +static ktime_t efx_ptp_s_ns_to_ktime_correction(u32 nic_major, u32 nic_minor, + s32 correction) { ktime_t kt = ktime_set(nic_major, nic_minor); if (correction >= 0) @@ -359,11 +362,16 @@ static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor) *nic_minor = min; } -static ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor, - s32 correction) +static inline ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor) { - u32 ns; + u32 ns = (u32)(((u64)nic_minor * NSEC_PER_SEC + + (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); + return ktime_set(nic_major, ns); +} +static ktime_t efx_ptp_s27_to_ktime_correction(u32 nic_major, u32 nic_minor, + s32 correction) +{ /* Apply the correction and deal with carry */ nic_minor += correction; if ((s32)nic_minor < 0) { @@ -374,10 +382,7 @@ static ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor, nic_major++; } - ns = (u32)(((u64)nic_minor * NSEC_PER_SEC + - (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); - - return ktime_set(nic_major, ns); + return efx_ptp_s27_to_ktime(nic_major, nic_minor); } /* Get PTP attributes and set up time conversions */ @@ -407,10 +412,10 @@ static int efx_ptp_get_attributes(struct efx_nic *efx) if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_27FRACTION) { ptp->ns_to_nic_time = efx_ptp_ns_to_s27; - ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime; + ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime_correction; } else if (fmt == MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS) { ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; - ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime; + ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime_correction; } else { return -ERANGE; } @@ -806,6 +811,9 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx) struct list_head *cursor; struct list_head *next; + if (ptp->rx_ts_inline) + return; + /* Drop time-expired events */ spin_lock_bh(&ptp->evt_lock); if (!list_empty(&ptp->evt_list)) { @@ -839,6 +847,8 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, struct efx_ptp_match *match; enum ptp_packet_state rc = PTP_PACKET_STATE_UNMATCHED; + WARN_ON_ONCE(ptp->rx_ts_inline); + spin_lock_bh(&ptp->evt_lock); evts_waiting = !list_empty(&ptp->evt_list); spin_unlock_bh(&ptp->evt_lock); @@ -1061,8 +1071,6 @@ static void efx_ptp_pps_worker(struct work_struct *work) ptp_clock_event(ptp->phc_clock, &ptp_evt); } -/* Process any pending transmissions and timestamp any received packets. - */ static void efx_ptp_worker(struct work_struct *work) { struct efx_ptp_data *ptp_data = @@ -1120,6 +1128,7 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) ptp->efx = efx; ptp->channel = channel; + ptp->rx_ts_inline = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); if (rc != 0) @@ -1491,6 +1500,9 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) { struct efx_ptp_event_rx *evt = NULL; + if (WARN_ON_ONCE(ptp->rx_ts_inline)) + return; + if (ptp->evt_frag_idx != 3) { ptp_event_failure(efx, 3); return; @@ -1587,6 +1599,93 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) } } +void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev) +{ + channel->sync_timestamp_major = MCDI_EVENT_FIELD(*ev, PTP_TIME_MAJOR); + channel->sync_timestamp_minor = + MCDI_EVENT_FIELD(*ev, PTP_TIME_MINOR_26_19) << 19; + /* if sync events have been disabled then we want to silently ignore + * this event, so throw away result. + */ + (void) cmpxchg(&channel->sync_events_state, SYNC_EVENTS_REQUESTED, + SYNC_EVENTS_VALID); +} + +/* make some assumptions about the time representation rather than abstract it, + * since we currently only support one type of inline timestamping and only on + * EF10. + */ +#define MINOR_TICKS_PER_SECOND 0x8000000 +/* Fuzz factor for sync events to be out of order with RX events */ +#define FUZZ (MINOR_TICKS_PER_SECOND / 10) +#define EXPECTED_SYNC_EVENTS_PER_SECOND 4 + +static inline u32 efx_rx_buf_timestamp_minor(struct efx_nic *efx, const u8 *eh) +{ +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_ts_offset)); +#else + const u8 *data = eh + efx->rx_packet_ts_offset; + return (u32)data[0] | + (u32)data[1] << 8 | + (u32)data[2] << 16 | + (u32)data[3] << 24; +#endif +} + +void __efx_rx_skb_attach_timestamp(struct efx_channel *channel, + struct sk_buff *skb) +{ + struct efx_nic *efx = channel->efx; + u32 pkt_timestamp_major, pkt_timestamp_minor; + u32 diff, carry; + struct skb_shared_hwtstamps *timestamps; + + pkt_timestamp_minor = (efx_rx_buf_timestamp_minor(efx, + skb_mac_header(skb)) + + (u32) efx->ptp_data->ts_corrections.rx) & + (MINOR_TICKS_PER_SECOND - 1); + + /* get the difference between the packet and sync timestamps, + * modulo one second + */ + diff = (pkt_timestamp_minor - channel->sync_timestamp_minor) & + (MINOR_TICKS_PER_SECOND - 1); + /* do we roll over a second boundary and need to carry the one? */ + carry = channel->sync_timestamp_minor + diff > MINOR_TICKS_PER_SECOND ? + 1 : 0; + + if (diff <= MINOR_TICKS_PER_SECOND / EXPECTED_SYNC_EVENTS_PER_SECOND + + FUZZ) { + /* packet is ahead of the sync event by a quarter of a second or + * less (allowing for fuzz) + */ + pkt_timestamp_major = channel->sync_timestamp_major + carry; + } else if (diff >= MINOR_TICKS_PER_SECOND - FUZZ) { + /* packet is behind the sync event but within the fuzz factor. + * This means the RX packet and sync event crossed as they were + * placed on the event queue, which can sometimes happen. + */ + pkt_timestamp_major = channel->sync_timestamp_major - 1 + carry; + } else { + /* it's outside tolerance in both directions. this might be + * indicative of us missing sync events for some reason, so + * we'll call it an error rather than risk giving a bogus + * timestamp. + */ + netif_vdbg(efx, drv, efx->net_dev, + "packet timestamp %x too far from sync event %x:%x\n", + pkt_timestamp_minor, channel->sync_timestamp_major, + channel->sync_timestamp_minor); + return; + } + + /* attach the timestamps to the skb */ + timestamps = skb_hwtstamps(skb); + timestamps->hwtstamp = + efx_ptp_s27_to_ktime(pkt_timestamp_major, pkt_timestamp_minor); +} + static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) { struct efx_ptp_data *ptp_data = container_of(ptp, @@ -1728,9 +1827,15 @@ void efx_ptp_start_datapath(struct efx_nic *efx) { if (efx_ptp_restart(efx)) netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); + /* re-enable timestamping if it was previously enabled */ + if (efx->type->ptp_set_ts_sync_events) + efx->type->ptp_set_ts_sync_events(efx, true, true); } void efx_ptp_stop_datapath(struct efx_nic *efx) { + /* temporarily disable timestamping */ + if (efx->type->ptp_set_ts_sync_events) + efx->type->ptp_set_ts_sync_events(efx, false, true); efx_ptp_stop(efx); } diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index d12abc543975..1fde9b8ac456 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -624,6 +624,8 @@ static void efx_rx_deliver(struct efx_channel *channel, u8 *eh, if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) skb->ip_summed = CHECKSUM_UNNECESSARY; + efx_rx_skb_attach_timestamp(channel, skb); + if (channel->type->receive_skb) if (channel->type->receive_skb(channel, skb)) return; -- cgit v1.2.3 From ef215e64760ef6bd756c2999e7c8cee95b98e30a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Dec 2013 20:13:22 +0000 Subject: sfc: Store VPD serial number at probe time Original version by Stuart Hodgson. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 38 ++++++++++++++++++++++++++++------- drivers/net/ethernet/sfc/net_driver.h | 3 +++ 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index b9929d9ed69d..5745a9fd034e 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2628,6 +2628,8 @@ static void efx_fini_struct(struct efx_nic *efx) for (i = 0; i < EFX_MAX_CHANNELS; i++) kfree(efx->channel[i]); + kfree(efx->vpd_sn); + if (efx->workqueue) { destroy_workqueue(efx->workqueue); efx->workqueue = NULL; @@ -2699,12 +2701,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev) * always appear within the first 512 bytes. */ #define SFC_VPD_LEN 512 -static void efx_print_product_vpd(struct efx_nic *efx) +static void efx_probe_vpd_strings(struct efx_nic *efx) { struct pci_dev *dev = efx->pci_dev; char vpd_data[SFC_VPD_LEN]; ssize_t vpd_size; - int i, j; + int ro_start, ro_size, i, j; /* Get the vpd data from the device */ vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data); @@ -2714,14 +2716,15 @@ static void efx_print_product_vpd(struct efx_nic *efx) } /* Get the Read only section */ - i = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA); - if (i < 0) { + ro_start = pci_vpd_find_tag(vpd_data, 0, vpd_size, PCI_VPD_LRDT_RO_DATA); + if (ro_start < 0) { netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n"); return; } - j = pci_vpd_lrdt_size(&vpd_data[i]); - i += PCI_VPD_LRDT_TAG_SIZE; + ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]); + j = ro_size; + i = ro_start + PCI_VPD_LRDT_TAG_SIZE; if (i + j > vpd_size) j = vpd_size - i; @@ -2741,6 +2744,27 @@ static void efx_print_product_vpd(struct efx_nic *efx) netif_info(efx, drv, efx->net_dev, "Part Number : %.*s\n", j, &vpd_data[i]); + + i = ro_start + PCI_VPD_LRDT_TAG_SIZE; + j = ro_size; + i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN"); + if (i < 0) { + netif_err(efx, drv, efx->net_dev, "Serial number not found\n"); + return; + } + + j = pci_vpd_info_field_size(&vpd_data[i]); + i += PCI_VPD_INFO_FLD_HDR_SIZE; + if (i + j > vpd_size) { + netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n"); + return; + } + + efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL); + if (!efx->vpd_sn) + return; + + snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]); } @@ -2837,7 +2861,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev, netif_info(efx, probe, efx->net_dev, "Solarflare NIC detected\n"); - efx_print_product_vpd(efx); + efx_probe_vpd_strings(efx); /* Set up basic I/O (BAR mappings etc) */ rc = efx_init_io(efx); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 0d0e8eb88332..be8a616a1649 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -771,6 +771,7 @@ struct vfdi_status; * @local_lock: Mutex protecting %local_addr_list and %local_page_list. * @peer_work: Work item to broadcast peer addresses to VMs. * @ptp_data: PTP state data + * @vpd_sn: Serial number read from VPD * @monitor_work: Hardware monitor workitem * @biu_lock: BIU (bus interface unit) lock * @last_irq_cpu: Last CPU to handle a possible test interrupt. This @@ -920,6 +921,8 @@ struct efx_nic { struct efx_ptp_data *ptp_data; + char *vpd_sn; + /* The following fields may be written more often */ struct delayed_work monitor_work ____cacheline_aligned_in_smp; -- cgit v1.2.3 From 0bcf4a645fc027d05d15e79ce48b5893cff28082 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 18 Oct 2013 19:21:45 +0100 Subject: sfc: Associate primary and secondary functions of controller The primary function of an EF10 controller will share its clock device with other functions in the same domain (which we call secondary functions). To this end, we need to associate functions on the same controller. We do not control probe order, so allow primary and secondary functions to appear in any order. Maintain global lists of all primary functions and of unassociated secondary functions, and a list of secondary functions on each primary function. Use the VPD serial number to tell whether functions are part of the same controller. VPD will not be readable by virtual functions, so this may need to be revisited later. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 77 +++++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/falcon.c | 2 + drivers/net/ethernet/sfc/mcdi.c | 4 ++ drivers/net/ethernet/sfc/net_driver.h | 10 +++++ 4 files changed, 93 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 5745a9fd034e..d6a927021523 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1117,6 +1117,77 @@ static void efx_remove_port(struct efx_nic *efx) * **************************************************************************/ +static LIST_HEAD(efx_primary_list); +static LIST_HEAD(efx_unassociated_list); + +static bool efx_same_controller(struct efx_nic *left, struct efx_nic *right) +{ + return left->type == right->type && + left->vpd_sn && right->vpd_sn && + !strcmp(left->vpd_sn, right->vpd_sn); +} + +static void efx_associate(struct efx_nic *efx) +{ + struct efx_nic *other, *next; + + if (efx->primary == efx) { + /* Adding primary function; look for secondaries */ + + netif_dbg(efx, probe, efx->net_dev, "adding to primary list\n"); + list_add_tail(&efx->node, &efx_primary_list); + + list_for_each_entry_safe(other, next, &efx_unassociated_list, + node) { + if (efx_same_controller(efx, other)) { + list_del(&other->node); + netif_dbg(other, probe, other->net_dev, + "moving to secondary list of %s %s\n", + pci_name(efx->pci_dev), + efx->net_dev->name); + list_add_tail(&other->node, + &efx->secondary_list); + other->primary = efx; + } + } + } else { + /* Adding secondary function; look for primary */ + + list_for_each_entry(other, &efx_primary_list, node) { + if (efx_same_controller(efx, other)) { + netif_dbg(efx, probe, efx->net_dev, + "adding to secondary list of %s %s\n", + pci_name(other->pci_dev), + other->net_dev->name); + list_add_tail(&efx->node, + &other->secondary_list); + efx->primary = other; + return; + } + } + + netif_dbg(efx, probe, efx->net_dev, + "adding to unassociated list\n"); + list_add_tail(&efx->node, &efx_unassociated_list); + } +} + +static void efx_dissociate(struct efx_nic *efx) +{ + struct efx_nic *other, *next; + + list_del(&efx->node); + efx->primary = NULL; + + list_for_each_entry_safe(other, next, &efx->secondary_list, node) { + list_del(&other->node); + netif_dbg(other, probe, other->net_dev, + "moving to unassociated list\n"); + list_add_tail(&other->node, &efx_unassociated_list); + other->primary = NULL; + } +} + /* This configures the PCI device to enable I/O and DMA. */ static int efx_init_io(struct efx_nic *efx) { @@ -2214,6 +2285,8 @@ static int efx_register_netdev(struct efx_nic *efx) efx_init_tx_queue_core_txq(tx_queue); } + efx_associate(efx); + rtnl_unlock(); rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); @@ -2227,6 +2300,7 @@ static int efx_register_netdev(struct efx_nic *efx) fail_registered: rtnl_lock(); + efx_dissociate(efx); unregister_netdevice(net_dev); fail_locked: efx->state = STATE_UNINIT; @@ -2568,6 +2642,8 @@ static int efx_init_struct(struct efx_nic *efx, int i; /* Initialise common structures */ + INIT_LIST_HEAD(&efx->node); + INIT_LIST_HEAD(&efx->secondary_list); spin_lock_init(&efx->biu_lock); #ifdef CONFIG_SFC_MTD INIT_LIST_HEAD(&efx->mtd_list); @@ -2674,6 +2750,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) /* Mark the NIC as fini, then stop the interface */ rtnl_lock(); + efx_dissociate(efx); dev_close(efx->net_dev); efx_disable_interrupts(efx); rtnl_unlock(); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 4a9e05c82e2a..76699f4e6e04 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2247,6 +2247,8 @@ static int falcon_probe_nic(struct efx_nic *efx) struct falcon_board *board; int rc; + efx->primary = efx; /* only one usable function per controller */ + /* Allocate storage for hardware specific data */ nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); if (!nic_data) diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 540f57915d6f..0d5d7b5325e8 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -102,6 +102,10 @@ int efx_mcdi_init(struct efx_nic *efx) netif_err(efx, probe, efx->net_dev, "Host already registered with MCPU\n"); + if (efx->mcdi->fn_flags & + (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY)) + efx->primary = efx; + return 0; } diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index be8a616a1649..653b8782c956 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -657,6 +657,13 @@ struct vfdi_status; * struct efx_nic - an Efx NIC * @name: Device name (net device name or bus id before net device registered) * @pci_dev: The PCI device + * @node: List node for maintaning primary/secondary function lists + * @primary: &struct efx_nic instance for the primary function of this + * controller. May be the same structure, and may be %NULL if no + * primary function is bound. Serialised by rtnl_lock. + * @secondary_list: List of &struct efx_nic instances for the secondary PCI + * functions of the controller, if this is for the primary function. + * Serialised by rtnl_lock. * @type: Controller type attributes * @legacy_irq: IRQ number * @workqueue: Workqueue for port reconfigures and the HW monitor. @@ -786,6 +793,9 @@ struct efx_nic { /* The following fields should be written very rarely */ char name[IFNAMSIZ]; + struct list_head node; + struct efx_nic *primary; + struct list_head secondary_list; struct pci_dev *pci_dev; unsigned int port_num; const struct efx_nic_type *type; -- cgit v1.2.3 From 9aecda95d0a2865ed7139d19fe4ae9d819e738be Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Dec 2013 21:28:42 +0000 Subject: sfc: Enable PTP clock and timestamping for all functions on EF10 The SFC9100 family has only one clock per controller, shared by all functions. Therefore only create a clock device under the primary function, and make all other functions refer to the primary's clock device. Since PTP functionality is limited to port 0 and PF 0 on the earlier SFN[56]322F boards, and we also set the primary flag for that function, we can make the creation of a clock device conditional only on this flag. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 5 ++++- drivers/net/ethernet/sfc/ptp.c | 42 +++++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index a3d891764030..dfff8e7a55e2 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -264,6 +264,8 @@ static int efx_ef10_probe(struct efx_nic *efx) if (rc) goto fail3; + efx_ptp_probe(efx, NULL); + return 0; fail3: @@ -472,9 +474,10 @@ static void efx_ef10_remove(struct efx_nic *efx) struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; + efx_ptp_remove(efx); + efx_mcdi_mon_remove(efx); - /* This needs to be after efx_ptp_remove_channel() with no filters */ efx_ef10_rx_free_indir_table(efx); if (nic_data->wc_membase) diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 843e98dfb1b2..fe3c6d04fce8 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -248,7 +248,7 @@ struct efx_ptp_timeset { * @start: Address at which MC indicates ready for synchronisation * @host_time_pps: Host time at last PPS * @current_adjfreq: Current ppb adjustment. - * @phc_clock: Pointer to registered phc device + * @phc_clock: Pointer to registered phc device (if primary function) * @phc_clock_info: Registration structure for phc device * @pps_work: pps work task for handling pps events * @pps_workwq: pps work queue @@ -1163,19 +1163,22 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) if (rc < 0) goto fail3; - ptp->phc_clock_info = efx_phc_clock_info; - ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, - &efx->pci_dev->dev); - if (IS_ERR(ptp->phc_clock)) { - rc = PTR_ERR(ptp->phc_clock); - goto fail3; - } + if (efx->mcdi->fn_flags & + (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY)) { + ptp->phc_clock_info = efx_phc_clock_info; + ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, + &efx->pci_dev->dev); + if (IS_ERR(ptp->phc_clock)) { + rc = PTR_ERR(ptp->phc_clock); + goto fail3; + } - INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); - ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); - if (!ptp->pps_workwq) { - rc = -ENOMEM; - goto fail4; + INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); + ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); + if (!ptp->pps_workwq) { + rc = -ENOMEM; + goto fail4; + } } ptp->nic_ts_enabled = false; @@ -1224,10 +1227,12 @@ void efx_ptp_remove(struct efx_nic *efx) skb_queue_purge(&efx->ptp_data->rxq); skb_queue_purge(&efx->ptp_data->txq); - ptp_clock_unregister(efx->ptp_data->phc_clock); + if (efx->ptp_data->phc_clock) { + destroy_workqueue(efx->ptp_data->pps_workwq); + ptp_clock_unregister(efx->ptp_data->phc_clock); + } destroy_workqueue(efx->ptp_data->workwq); - destroy_workqueue(efx->ptp_data->pps_workwq); efx_nic_free_buffer(efx, &efx->ptp_data->start); kfree(efx->ptp_data); @@ -1440,6 +1445,9 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) { struct efx_ptp_data *ptp = efx->ptp_data; + struct efx_nic *primary = efx->primary; + + ASSERT_RTNL(); if (!ptp) return; @@ -1447,7 +1455,9 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE); - ts_info->phc_index = ptp_clock_index(ptp->phc_clock); + if (primary && primary->ptp_data && primary->ptp_data->phc_clock) + ts_info->phc_index = + ptp_clock_index(primary->ptp_data->phc_clock); ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; ts_info->rx_filters = ptp->efx->type->hwtstamp_filters; } -- cgit v1.2.3 From a45a3a5cdc8dca283e4373045aae8af485f07a07 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 28 Nov 2013 18:58:11 +0000 Subject: sfc: Don't clear timestamps in efx_ptp_rx() A freshly allocated skb starts with timestamps clear. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index fe3c6d04fce8..06c6420f40d7 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1323,14 +1323,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) /* Does this packet require timestamping? */ if (ntohs(*(__be16 *)&skb->data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { - struct skb_shared_hwtstamps *timestamps; - match->state = PTP_PACKET_STATE_UNMATCHED; - /* Clear all timestamps held: filled in later */ - timestamps = skb_hwtstamps(skb); - memset(timestamps, 0, sizeof(*timestamps)); - /* We expect the sequence number to be in the same position in * the packet for PTP V1 and V2 */ -- cgit v1.2.3 From bbbe7149bf0bd14432373de39315505e7a133acc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 28 Nov 2013 18:58:12 +0000 Subject: sfc: Remove unnecessary condition for processing the TX timestamp queue Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ptp.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 06c6420f40d7..084e2d44790f 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -890,13 +890,10 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, /* Process any queued receive events and corresponding packets * * q is returned with all the packets that are ready for delivery. - * true is returned if at least one of those packets requires - * synchronisation. */ -static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) +static void efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) { struct efx_ptp_data *ptp = efx->ptp_data; - bool rc = false; struct sk_buff *skb; while ((skb = skb_dequeue(&ptp->rxq))) { @@ -907,7 +904,6 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) __skb_queue_tail(q, skb); } else if (efx_ptp_match_rx(efx, skb) == PTP_PACKET_STATE_MATCHED) { - rc = true; __skb_queue_tail(q, skb); } else if (time_after(jiffies, match->expiry)) { match->state = PTP_PACKET_STATE_TIMED_OUT; @@ -921,8 +917,6 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) break; } } - - return rc; } /* Complete processing of a received packet */ @@ -1088,12 +1082,10 @@ static void efx_ptp_worker(struct work_struct *work) efx_ptp_drop_time_expired_events(efx); __skb_queue_head_init(&tempq); - if (efx_ptp_process_events(efx, &tempq) || - !skb_queue_empty(&ptp_data->txq)) { + efx_ptp_process_events(efx, &tempq); - while ((skb = skb_dequeue(&ptp_data->txq))) - efx_ptp_xmit_skb(efx, skb); - } + while ((skb = skb_dequeue(&ptp_data->txq))) + efx_ptp_xmit_skb(efx, skb); while ((skb = __skb_dequeue(&tempq))) efx_ptp_process_rx(efx, skb); -- cgit v1.2.3 From 48ce5634a79265cd83e5bdb268728165c0ea85a0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Nov 2013 16:42:44 +0000 Subject: sfc: Add more information to many warnings using WARN() and netdev_WARN() In case of certain hardware and firmware errors it can be useful to have more context than just the file and line number. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index dfff8e7a55e2..9ec6072896c2 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1252,7 +1252,8 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue) return; fail: - WARN_ON(true); + netdev_WARN(efx->net_dev, "failed to initialise TXQ %d\n", + tx_queue->queue); } static void efx_ef10_tx_fini(struct efx_tx_queue *tx_queue) @@ -1492,9 +1493,9 @@ static void efx_ef10_rx_init(struct efx_rx_queue *rx_queue) rc = efx_mcdi_rpc(efx, MC_CMD_INIT_RXQ, inbuf, inlen, outbuf, sizeof(outbuf), &outlen); - WARN_ON(rc); - - return; + if (rc) + netdev_WARN(efx->net_dev, "failed to initialise RXQ %d\n", + efx_rx_queue_index(rx_queue)); } static void efx_ef10_rx_fini(struct efx_rx_queue *rx_queue) @@ -1718,8 +1719,6 @@ static void efx_ef10_handle_rx_abort(struct efx_rx_queue *rx_queue) { unsigned int rx_desc_ptr; - WARN_ON(rx_queue->scatter_n == 0); - netif_dbg(rx_queue->efx, hw, rx_queue->efx->net_dev, "scattered RX aborted (dropping %u buffers)\n", rx_queue->scatter_n); @@ -1755,7 +1754,10 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel, rx_l4_class = EFX_QWORD_FIELD(*event, ESF_DZ_RX_L4_CLASS); rx_cont = EFX_QWORD_FIELD(*event, ESF_DZ_RX_CONT); - WARN_ON(EFX_QWORD_FIELD(*event, ESF_DZ_RX_DROP_EVENT)); + if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_DROP_EVENT)) + netdev_WARN(efx->net_dev, "saw RX_DROP_EVENT: event=" + EFX_QWORD_FMT "\n", + EFX_QWORD_VAL(*event)); rx_queue = efx_channel_get_rx_queue(channel); @@ -1770,7 +1772,12 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel, /* detect rx abort */ if (unlikely(n_descs == rx_queue->scatter_n)) { - WARN_ON(rx_bytes != 0); + if (rx_queue->scatter_n == 0 || rx_bytes != 0) + netdev_WARN(efx->net_dev, + "invalid RX abort: scatter_n=%u event=" + EFX_QWORD_FMT "\n", + rx_queue->scatter_n, + EFX_QWORD_VAL(*event)); efx_ef10_handle_rx_abort(rx_queue); return 0; } @@ -3035,8 +3042,11 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx) table->entry[filter_idx].handle); rc = efx_mcdi_rpc(efx, MC_CMD_FILTER_OP, inbuf, sizeof(inbuf), NULL, 0, NULL); - - WARN_ON(rc != 0); + if (rc) + netdev_WARN(efx->net_dev, + "filter_idx=%#x handle=%#llx\n", + filter_idx, + table->entry[filter_idx].handle); kfree(spec); } -- cgit v1.2.3 From d43050c0c7d930cdeb10fb9201d9e2d005cef02a Mon Sep 17 00:00:00 2001 From: Andrew Rybchenko Date: Thu, 14 Nov 2013 09:00:27 +0400 Subject: sfc: Change efx_nic_type::rx_push_indir_table to push hash key as well The EF10 implementation already does this, and it makes more logical sense to group the RSS hash key and indirection table together. Rename the operation to rx_push_rss_config. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 10 ++++---- drivers/net/ethernet/sfc/ethtool.c | 2 +- drivers/net/ethernet/sfc/falcon.c | 26 ++++++++++++++++---- drivers/net/ethernet/sfc/farch.c | 5 +--- drivers/net/ethernet/sfc/net_driver.h | 4 ++-- drivers/net/ethernet/sfc/nic.h | 4 ---- drivers/net/ethernet/sfc/siena.c | 45 +++++++++++++++++++++-------------- 7 files changed, 57 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 9ec6072896c2..137c46b4b405 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -77,7 +77,7 @@ struct efx_ef10_filter_table { /* An arbitrary search limit for the software hash table */ #define EFX_EF10_FILTER_SEARCH_LIMIT 200 -static void efx_ef10_rx_push_indir_table(struct efx_nic *efx); +static void efx_ef10_rx_push_rss_config(struct efx_nic *efx); static void efx_ef10_rx_free_indir_table(struct efx_nic *efx); static void efx_ef10_filter_table_remove(struct efx_nic *efx); @@ -679,7 +679,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) nic_data->must_restore_piobufs = false; } - efx_ef10_rx_push_indir_table(efx); + efx_ef10_rx_push_rss_config(efx); return 0; } @@ -1420,12 +1420,12 @@ static void efx_ef10_rx_free_indir_table(struct efx_nic *efx) nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID; } -static void efx_ef10_rx_push_indir_table(struct efx_nic *efx) +static void efx_ef10_rx_push_rss_config(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; - netif_dbg(efx, drv, efx->net_dev, "pushing RX indirection table\n"); + netif_dbg(efx, drv, efx->net_dev, "pushing RSS config\n"); if (nic_data->rx_rss_context == EFX_EF10_RSS_CONTEXT_INVALID) { rc = efx_ef10_alloc_rss_context(efx, &nic_data->rx_rss_context); @@ -3574,7 +3574,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .tx_init = efx_ef10_tx_init, .tx_remove = efx_ef10_tx_remove, .tx_write = efx_ef10_tx_write, - .rx_push_indir_table = efx_ef10_rx_push_indir_table, + .rx_push_rss_config = efx_ef10_rx_push_rss_config, .rx_probe = efx_ef10_rx_probe, .rx_init = efx_ef10_rx_init, .rx_remove = efx_ef10_rx_remove, diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index fb8993806167..bb2af8045281 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -1034,7 +1034,7 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); memcpy(efx->rx_indir_table, indir, sizeof(efx->rx_indir_table)); - efx_nic_push_rx_indir_table(efx); + efx->type->rx_push_rss_config(efx); return 0; } diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 76699f4e6e04..5c6d63cfc394 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -467,6 +467,24 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) efx_schedule_channel_irq(efx_get_channel(efx, 1)); return IRQ_HANDLED; } +/************************************************************************** + * + * RSS + * + ************************************************************************** + */ + +static void falcon_b0_rx_push_rss_config(struct efx_nic *efx) +{ + efx_oword_t temp; + + /* Set hash key for IPv4 */ + memcpy(&temp, efx->rx_hash_key, sizeof(temp)); + efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY); + + efx_farch_rx_push_indir_table(efx); +} + /************************************************************************** * * EEPROM/flash @@ -2484,9 +2502,7 @@ static int falcon_init_nic(struct efx_nic *efx) falcon_init_rx_cfg(efx); if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) { - /* Set hash key for IPv4 */ - memcpy(&temp, efx->rx_hash_key, sizeof(temp)); - efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY); + falcon_b0_rx_push_rss_config(efx); /* Set destination of both TX and RX Flush events */ EFX_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0); @@ -2703,7 +2719,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .tx_init = efx_farch_tx_init, .tx_remove = efx_farch_tx_remove, .tx_write = efx_farch_tx_write, - .rx_push_indir_table = efx_farch_rx_push_indir_table, + .rx_push_rss_config = efx_port_dummy_op_void, .rx_probe = efx_farch_rx_probe, .rx_init = efx_farch_rx_init, .rx_remove = efx_farch_rx_remove, @@ -2798,7 +2814,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .tx_init = efx_farch_tx_init, .tx_remove = efx_farch_tx_remove, .tx_write = efx_farch_tx_write, - .rx_push_indir_table = efx_farch_rx_push_indir_table, + .rx_push_rss_config = falcon_b0_rx_push_rss_config, .rx_probe = efx_farch_rx_probe, .rx_init = efx_farch_rx_init, .rx_remove = efx_farch_rx_remove, diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 984e85ee76f6..4c64ad7c9200 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -1618,8 +1618,7 @@ void efx_farch_rx_push_indir_table(struct efx_nic *efx) size_t i = 0; efx_dword_t dword; - if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) - return; + BUG_ON(efx_nic_rev(efx) < EFX_REV_FALCON_B0); BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) != FR_BZ_RX_INDIRECTION_TBL_ROWS); @@ -1745,8 +1744,6 @@ void efx_farch_init_common(struct efx_nic *efx) EFX_INVERT_OWORD(temp); efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER); - efx_farch_rx_push_indir_table(efx); - /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q. */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 653b8782c956..1b3c4e5207c5 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1024,7 +1024,7 @@ struct efx_mtd_partition { * @tx_init: Initialise TX queue on the NIC * @tx_remove: Free resources for TX queue * @tx_write: Write TX descriptors and doorbell - * @rx_push_indir_table: Write RSS indirection table to the NIC + * @rx_push_rss_config: Write RSS hash key and indirection table to the NIC * @rx_probe: Allocate resources for RX queue * @rx_init: Initialise RX queue on the NIC * @rx_remove: Free resources for RX queue @@ -1141,7 +1141,7 @@ struct efx_nic_type { void (*tx_init)(struct efx_tx_queue *tx_queue); void (*tx_remove)(struct efx_tx_queue *tx_queue); void (*tx_write)(struct efx_tx_queue *tx_queue); - void (*rx_push_indir_table)(struct efx_nic *efx); + void (*rx_push_rss_config)(struct efx_nic *efx); int (*rx_probe)(struct efx_rx_queue *rx_queue); void (*rx_init)(struct efx_rx_queue *rx_queue); void (*rx_remove)(struct efx_rx_queue *rx_queue); diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 5d9e2dc121f7..c665ff6c8012 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -762,10 +762,6 @@ int falcon_reset_xaui(struct efx_nic *efx); void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw); void efx_farch_init_common(struct efx_nic *efx); void efx_ef10_handle_drain_event(struct efx_nic *efx); -static inline void efx_nic_push_rx_indir_table(struct efx_nic *efx) -{ - efx->type->rx_push_indir_table(efx); -} void efx_farch_rx_push_indir_table(struct efx_nic *efx); int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer, diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index f65db356fe09..23f3a6f7737a 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -321,6 +321,31 @@ fail1: return rc; } +static void siena_rx_push_rss_config(struct efx_nic *efx) +{ + efx_oword_t temp; + + /* Set hash key for IPv4 */ + memcpy(&temp, efx->rx_hash_key, sizeof(temp)); + efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY); + + /* Enable IPv6 RSS */ + BUILD_BUG_ON(sizeof(efx->rx_hash_key) < + 2 * sizeof(temp) + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8 || + FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN != 0); + memcpy(&temp, efx->rx_hash_key, sizeof(temp)); + efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1); + memcpy(&temp, efx->rx_hash_key + sizeof(temp), sizeof(temp)); + efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2); + EFX_POPULATE_OWORD_2(temp, FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1, + FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, 1); + memcpy(&temp, efx->rx_hash_key + 2 * sizeof(temp), + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8); + efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3); + + efx_farch_rx_push_indir_table(efx); +} + /* This call performs hardware-specific global initialisation, such as * defining the descriptor cache sizes and number of RSS channels. * It does not set up any buffers, descriptor rings or event queues. @@ -361,23 +386,7 @@ static int siena_init_nic(struct efx_nic *efx) EFX_RX_USR_BUF_SIZE >> 5); efx_writeo(efx, &temp, FR_AZ_RX_CFG); - /* Set hash key for IPv4 */ - memcpy(&temp, efx->rx_hash_key, sizeof(temp)); - efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY); - - /* Enable IPv6 RSS */ - BUILD_BUG_ON(sizeof(efx->rx_hash_key) < - 2 * sizeof(temp) + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8 || - FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN != 0); - memcpy(&temp, efx->rx_hash_key, sizeof(temp)); - efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1); - memcpy(&temp, efx->rx_hash_key + sizeof(temp), sizeof(temp)); - efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2); - EFX_POPULATE_OWORD_2(temp, FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1, - FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, 1); - memcpy(&temp, efx->rx_hash_key + 2 * sizeof(temp), - FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8); - efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3); + siena_rx_push_rss_config(efx); /* Enable event logging */ rc = efx_mcdi_log_ctrl(efx, true, false, 0); @@ -940,7 +949,7 @@ const struct efx_nic_type siena_a0_nic_type = { .tx_init = efx_farch_tx_init, .tx_remove = efx_farch_tx_remove, .tx_write = efx_farch_tx_write, - .rx_push_indir_table = efx_farch_rx_push_indir_table, + .rx_push_rss_config = siena_rx_push_rss_config, .rx_probe = efx_farch_rx_probe, .rx_init = efx_farch_rx_init, .rx_remove = efx_farch_rx_remove, -- cgit v1.2.3 From 7665d1abea22cb44d4f0bac99e77275eba39bbf1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 21 Nov 2013 19:02:18 +0000 Subject: sfc: Change priority and flags for automatic MAC filters MAC filters inserted automatically by the driver, based on the device address list (EF10) or no-match filters (Siena), should be overridable at MANUAL or REQUIRED priority. Currently they themselves have REQUIRED priority and this requires some odd special-casing. We also can't reliably tell whether such a MAC filter has or has not been overridden. We just remember that it is wanted by the stack (RX_STACK flag). Add another priority level, AUTO, between HINT and MANUAL, and use this for the automatic filters while they have not been overridden. Remove the RX_STACK flag. Add an RX_OVER_AUTO flag which is set only when an AUTO filter has been overridden (or was requested to be inserted while a higher-priority filter existed). Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 73 ++++++++++++++++++++++----------------- drivers/net/ethernet/sfc/efx.h | 3 ++ drivers/net/ethernet/sfc/farch.c | 28 +++++++-------- drivers/net/ethernet/sfc/filter.h | 17 +++++---- 4 files changed, 67 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 137c46b4b405..e5eeac9063d2 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2341,10 +2341,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx, EFX_EF10_FILTER_FLAG_BUSY) break; if (spec->priority < saved_spec->priority && - !(saved_spec->priority == - EFX_FILTER_PRI_REQUIRED && - saved_spec->flags & - EFX_FILTER_FLAG_RX_STACK)) { + spec->priority != EFX_FILTER_PRI_AUTO) { rc = -EPERM; goto out_unlock; } @@ -2398,9 +2395,11 @@ found: */ saved_spec = efx_ef10_filter_entry_spec(table, ins_index); if (saved_spec) { - if (spec->flags & EFX_FILTER_FLAG_RX_STACK) { + if (spec->priority == EFX_FILTER_PRI_AUTO && + saved_spec->priority >= EFX_FILTER_PRI_AUTO) { /* Just make sure it won't be removed */ - saved_spec->flags |= EFX_FILTER_FLAG_RX_STACK; + if (saved_spec->priority > EFX_FILTER_PRI_AUTO) + saved_spec->flags |= EFX_FILTER_FLAG_RX_OVER_AUTO; table->entry[ins_index].spec &= ~EFX_EF10_FILTER_FLAG_STACK_OLD; rc = ins_index; @@ -2442,8 +2441,11 @@ found: if (rc == 0) { if (replacing) { /* Update the fields that may differ */ + if (saved_spec->priority == EFX_FILTER_PRI_AUTO) + saved_spec->flags |= + EFX_FILTER_FLAG_RX_OVER_AUTO; saved_spec->priority = spec->priority; - saved_spec->flags &= EFX_FILTER_FLAG_RX_STACK; + saved_spec->flags &= EFX_FILTER_FLAG_RX_OVER_AUTO; saved_spec->flags |= spec->flags; saved_spec->rss_context = spec->rss_context; saved_spec->dmaq_id = spec->dmaq_id; @@ -2542,26 +2544,41 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, spin_unlock_bh(&efx->filter_lock); schedule(); } + spec = efx_ef10_filter_entry_spec(table, filter_idx); - if (!spec || spec->priority > priority || + if (!spec || (!stack_requested && efx_ef10_filter_rx_match_pri(table, spec->match_flags) != filter_id / HUNT_FILTER_TBL_ROWS)) { rc = -ENOENT; goto out_unlock; } + + if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO && + priority == EFX_FILTER_PRI_AUTO) { + /* Just remove flags */ + spec->flags &= ~EFX_FILTER_FLAG_RX_OVER_AUTO; + table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_STACK_OLD; + rc = 0; + goto out_unlock; + } + + if (spec->priority > priority) { + rc = -ENOENT; + goto out_unlock; + } + table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY; spin_unlock_bh(&efx->filter_lock); - if (spec->flags & EFX_FILTER_FLAG_RX_STACK && !stack_requested) { + if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) { /* Reset steering of a stack-owned filter */ struct efx_filter_spec new_spec = *spec; - new_spec.priority = EFX_FILTER_PRI_REQUIRED; + new_spec.priority = EFX_FILTER_PRI_AUTO; new_spec.flags = (EFX_FILTER_FLAG_RX | - EFX_FILTER_FLAG_RX_RSS | - EFX_FILTER_FLAG_RX_STACK); + EFX_FILTER_FLAG_RX_RSS); new_spec.dmaq_id = 0; new_spec.rss_context = EFX_FILTER_RSS_CONTEXT_DEFAULT; rc = efx_ef10_filter_push(efx, &new_spec, @@ -2589,6 +2606,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, efx_ef10_filter_set_entry(table, filter_idx, NULL, 0); } } + table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_BUSY; wake_up_all(&table->waitq); out_unlock: @@ -2731,8 +2749,6 @@ static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx, rc = -EBUSY; goto fail_unlock; } - EFX_WARN_ON_PARANOID(saved_spec->flags & - EFX_FILTER_FLAG_RX_STACK); if (spec->priority < saved_spec->priority) { rc = -EPERM; goto fail_unlock; @@ -3118,9 +3134,8 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) /* Insert/renew unicast filters */ if (table->stack_uc_count >= 0) { for (i = 0; i < table->stack_uc_count; i++) { - efx_filter_init_rx(&spec, EFX_FILTER_PRI_REQUIRED, - EFX_FILTER_FLAG_RX_RSS | - EFX_FILTER_FLAG_RX_STACK, + efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, + EFX_FILTER_FLAG_RX_RSS, 0); efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, table->stack_uc_list[i].addr); @@ -3129,7 +3144,7 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) /* Fall back to unicast-promisc */ while (i--) efx_ef10_filter_remove_safe( - efx, EFX_FILTER_PRI_REQUIRED, + efx, EFX_FILTER_PRI_AUTO, table->stack_uc_list[i].id); table->stack_uc_count = -1; break; @@ -3138,9 +3153,8 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) } } if (table->stack_uc_count < 0) { - efx_filter_init_rx(&spec, EFX_FILTER_PRI_REQUIRED, - EFX_FILTER_FLAG_RX_RSS | - EFX_FILTER_FLAG_RX_STACK, + efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, + EFX_FILTER_FLAG_RX_RSS, 0); efx_filter_set_uc_def(&spec); rc = efx_ef10_filter_insert(efx, &spec, true); @@ -3155,9 +3169,8 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) /* Insert/renew multicast filters */ if (table->stack_mc_count >= 0) { for (i = 0; i < table->stack_mc_count; i++) { - efx_filter_init_rx(&spec, EFX_FILTER_PRI_REQUIRED, - EFX_FILTER_FLAG_RX_RSS | - EFX_FILTER_FLAG_RX_STACK, + efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, + EFX_FILTER_FLAG_RX_RSS, 0); efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, table->stack_mc_list[i].addr); @@ -3166,7 +3179,7 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) /* Fall back to multicast-promisc */ while (i--) efx_ef10_filter_remove_safe( - efx, EFX_FILTER_PRI_REQUIRED, + efx, EFX_FILTER_PRI_AUTO, table->stack_mc_list[i].id); table->stack_mc_count = -1; break; @@ -3175,9 +3188,8 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) } } if (table->stack_mc_count < 0) { - efx_filter_init_rx(&spec, EFX_FILTER_PRI_REQUIRED, - EFX_FILTER_FLAG_RX_RSS | - EFX_FILTER_FLAG_RX_STACK, + efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, + EFX_FILTER_FLAG_RX_RSS, 0); efx_filter_set_mc_def(&spec); rc = efx_ef10_filter_insert(efx, &spec, true); @@ -3197,9 +3209,8 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) { if (ACCESS_ONCE(table->entry[i].spec) & EFX_EF10_FILTER_FLAG_STACK_OLD) { - if (efx_ef10_filter_remove_internal(efx, - EFX_FILTER_PRI_REQUIRED, - i, true) < 0) + if (efx_ef10_filter_remove_internal( + efx, EFX_FILTER_PRI_AUTO, i, true) < 0) remove_failed = true; } } diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index a653786fbbe7..3a67030c73ea 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -138,6 +138,9 @@ efx_filter_get_filter_safe(struct efx_nic *efx, * efx_farch_filter_clear_rx - remove RX filters by priority * @efx: NIC from which to remove the filters * @priority: Maximum priority to remove + * + * Remove all RX filters whose priority is less than or equal to the + * given @priority and is not %EFX_FILTER_PRI_AUTO. */ static inline void efx_filter_clear_rx(struct efx_nic *efx, enum efx_filter_priority priority) diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 4c64ad7c9200..fbd923ddf546 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -2190,8 +2190,8 @@ efx_farch_filter_init_rx_for_stack(struct efx_nic *efx, /* If there's only one channel then disable RSS for non VF * traffic, thereby allowing VFs to use RSS when the PF can't. */ - spec->priority = EFX_FILTER_PRI_REQUIRED; - spec->flags = (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_STACK | + spec->priority = EFX_FILTER_PRI_AUTO; + spec->flags = (EFX_FILTER_FLAG_RX | (efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) | (efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0)); spec->dmaq_id = 0; @@ -2456,20 +2456,13 @@ s32 efx_farch_filter_insert(struct efx_nic *efx, rc = -EEXIST; goto out; } - if (spec.priority < saved_spec->priority && - !(saved_spec->priority == EFX_FILTER_PRI_REQUIRED && - saved_spec->flags & EFX_FILTER_FLAG_RX_STACK)) { + if (spec.priority < saved_spec->priority) { rc = -EPERM; goto out; } - if (spec.flags & EFX_FILTER_FLAG_RX_STACK) { - /* Just make sure it won't be removed */ - saved_spec->flags |= EFX_FILTER_FLAG_RX_STACK; - rc = 0; - goto out; - } - /* Retain the RX_STACK flag */ - spec.flags |= saved_spec->flags & EFX_FILTER_FLAG_RX_STACK; + if (saved_spec->priority == EFX_FILTER_PRI_AUTO || + saved_spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) + spec.flags |= EFX_FILTER_FLAG_RX_OVER_AUTO; } /* Insert the filter */ @@ -2553,7 +2546,7 @@ static int efx_farch_filter_remove(struct efx_nic *efx, spec->priority > priority) return -ENOENT; - if (spec->flags & EFX_FILTER_FLAG_RX_STACK) { + if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) { efx_farch_filter_init_rx_for_stack(efx, spec); efx_farch_filter_push_rx_config(efx); } else { @@ -2637,8 +2630,11 @@ efx_farch_filter_table_clear(struct efx_nic *efx, unsigned int filter_idx; spin_lock_bh(&efx->filter_lock); - for (filter_idx = 0; filter_idx < table->size; ++filter_idx) - efx_farch_filter_remove(efx, table, filter_idx, priority); + for (filter_idx = 0; filter_idx < table->size; ++filter_idx) { + if (table->spec[filter_idx].priority != EFX_FILTER_PRI_AUTO) + efx_farch_filter_remove(efx, table, + filter_idx, priority); + } spin_unlock_bh(&efx->filter_lock); } diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h index 63c77a557178..3ef298d3c47e 100644 --- a/drivers/net/ethernet/sfc/filter.h +++ b/drivers/net/ethernet/sfc/filter.h @@ -59,12 +59,16 @@ enum efx_filter_match_flags { /** * enum efx_filter_priority - priority of a hardware filter specification * @EFX_FILTER_PRI_HINT: Performance hint + * @EFX_FILTER_PRI_AUTO: Automatic filter based on device address list + * or hardware requirements. This may only be used by the filter + * implementation for each NIC type. * @EFX_FILTER_PRI_MANUAL: Manually configured filter * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level * networking and SR-IOV) */ enum efx_filter_priority { EFX_FILTER_PRI_HINT = 0, + EFX_FILTER_PRI_AUTO, EFX_FILTER_PRI_MANUAL, EFX_FILTER_PRI_REQUIRED, }; @@ -78,19 +82,18 @@ enum efx_filter_priority { * according to the indirection table. * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving * queue. - * @EFX_FILTER_FLAG_RX_STACK: Indicates a filter inserted for the - * network stack. The filter must have a priority of - * %EFX_FILTER_PRI_REQUIRED. It can be steered by a replacement - * request with priority %EFX_FILTER_PRI_MANUAL, and a removal - * request with priority %EFX_FILTER_PRI_MANUAL will reset the - * steering (but not remove the filter). + * @EFX_FILTER_FLAG_RX_OVER_AUTO: Indicates a filter that is + * overriding an automatic filter (priority + * %EFX_FILTER_PRI_AUTO). This may only be set by the filter + * implementation for each type. A removal request will restore + * the automatic filter in its place. * @EFX_FILTER_FLAG_RX: Filter is for RX * @EFX_FILTER_FLAG_TX: Filter is for TX */ enum efx_filter_flags { EFX_FILTER_FLAG_RX_RSS = 0x01, EFX_FILTER_FLAG_RX_SCATTER = 0x02, - EFX_FILTER_FLAG_RX_STACK = 0x04, + EFX_FILTER_FLAG_RX_OVER_AUTO = 0x04, EFX_FILTER_FLAG_RX = 0x08, EFX_FILTER_FLAG_TX = 0x10, }; -- cgit v1.2.3 From b59e6ef87c337541c1c57742116d780813c9601c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 21 Nov 2013 19:02:22 +0000 Subject: sfc: Don't refer to 'stack' in filter implementation Change all the 'stack' naming to 'auto' (or other meaningful term); the device address list is based on more than just what the network stack wants, and the no-match filters aren't really what the stack wants at all. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 104 +++++++++++++++++++-------------------- drivers/net/ethernet/sfc/farch.c | 8 +-- 2 files changed, 56 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index e5eeac9063d2..2adc8e45461b 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -53,25 +53,25 @@ struct efx_ef10_filter_table { struct { unsigned long spec; /* pointer to spec plus flag bits */ -/* BUSY flag indicates that an update is in progress. STACK_OLD is - * used to mark and sweep stack-owned MAC filters. +/* BUSY flag indicates that an update is in progress. AUTO_OLD is + * used to mark and sweep MAC filters for the device address lists. */ #define EFX_EF10_FILTER_FLAG_BUSY 1UL -#define EFX_EF10_FILTER_FLAG_STACK_OLD 2UL +#define EFX_EF10_FILTER_FLAG_AUTO_OLD 2UL #define EFX_EF10_FILTER_FLAGS 3UL u64 handle; /* firmware handle */ } *entry; wait_queue_head_t waitq; /* Shadow of net_device address lists, guarded by mac_lock */ -#define EFX_EF10_FILTER_STACK_UC_MAX 32 -#define EFX_EF10_FILTER_STACK_MC_MAX 256 +#define EFX_EF10_FILTER_DEV_UC_MAX 32 +#define EFX_EF10_FILTER_DEV_MC_MAX 256 struct { u8 addr[ETH_ALEN]; u16 id; - } stack_uc_list[EFX_EF10_FILTER_STACK_UC_MAX], - stack_mc_list[EFX_EF10_FILTER_STACK_MC_MAX]; - int stack_uc_count; /* negative for PROMISC */ - int stack_mc_count; /* negative for PROMISC/ALLMULTI */ + } dev_uc_list[EFX_EF10_FILTER_DEV_UC_MAX], + dev_mc_list[EFX_EF10_FILTER_DEV_MC_MAX]; + int dev_uc_count; /* negative for PROMISC */ + int dev_mc_count; /* negative for PROMISC/ALLMULTI */ }; /* An arbitrary search limit for the software hash table */ @@ -2401,7 +2401,7 @@ found: if (saved_spec->priority > EFX_FILTER_PRI_AUTO) saved_spec->flags |= EFX_FILTER_FLAG_RX_OVER_AUTO; table->entry[ins_index].spec &= - ~EFX_EF10_FILTER_FLAG_STACK_OLD; + ~EFX_EF10_FILTER_FLAG_AUTO_OLD; rc = ins_index; goto out_unlock; } @@ -2514,13 +2514,13 @@ static void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx) } /* Remove a filter. - * If !stack_requested, remove by ID - * If stack_requested, remove by index + * If !by_index, remove by ID + * If by_index, remove by index * Filter ID may come from userland and must be range-checked. */ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, enum efx_filter_priority priority, - u32 filter_id, bool stack_requested) + u32 filter_id, bool by_index) { unsigned int filter_idx = filter_id % HUNT_FILTER_TBL_ROWS; struct efx_ef10_filter_table *table = efx->filter_state; @@ -2547,7 +2547,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, spec = efx_ef10_filter_entry_spec(table, filter_idx); if (!spec || - (!stack_requested && + (!by_index && efx_ef10_filter_rx_match_pri(table, spec->match_flags) != filter_id / HUNT_FILTER_TBL_ROWS)) { rc = -ENOENT; @@ -2558,7 +2558,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, priority == EFX_FILTER_PRI_AUTO) { /* Just remove flags */ spec->flags &= ~EFX_FILTER_FLAG_RX_OVER_AUTO; - table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_STACK_OLD; + table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_AUTO_OLD; rc = 0; goto out_unlock; } @@ -2572,7 +2572,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, spin_unlock_bh(&efx->filter_lock); if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) { - /* Reset steering of a stack-owned filter */ + /* Reset to an automatic filter */ struct efx_filter_spec new_spec = *spec; @@ -3086,15 +3086,15 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) /* Mark old filters that may need to be removed */ spin_lock_bh(&efx->filter_lock); - n = table->stack_uc_count < 0 ? 1 : table->stack_uc_count; + n = table->dev_uc_count < 0 ? 1 : table->dev_uc_count; for (i = 0; i < n; i++) { - filter_idx = table->stack_uc_list[i].id % HUNT_FILTER_TBL_ROWS; - table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_STACK_OLD; + filter_idx = table->dev_uc_list[i].id % HUNT_FILTER_TBL_ROWS; + table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_AUTO_OLD; } - n = table->stack_mc_count < 0 ? 1 : table->stack_mc_count; + n = table->dev_mc_count < 0 ? 1 : table->dev_mc_count; for (i = 0; i < n; i++) { - filter_idx = table->stack_mc_list[i].id % HUNT_FILTER_TBL_ROWS; - table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_STACK_OLD; + filter_idx = table->dev_mc_list[i].id % HUNT_FILTER_TBL_ROWS; + table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_AUTO_OLD; } spin_unlock_bh(&efx->filter_lock); @@ -3103,28 +3103,28 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) */ netif_addr_lock_bh(net_dev); if (net_dev->flags & IFF_PROMISC || - netdev_uc_count(net_dev) >= EFX_EF10_FILTER_STACK_UC_MAX) { - table->stack_uc_count = -1; + netdev_uc_count(net_dev) >= EFX_EF10_FILTER_DEV_UC_MAX) { + table->dev_uc_count = -1; } else { - table->stack_uc_count = 1 + netdev_uc_count(net_dev); - memcpy(table->stack_uc_list[0].addr, net_dev->dev_addr, + table->dev_uc_count = 1 + netdev_uc_count(net_dev); + memcpy(table->dev_uc_list[0].addr, net_dev->dev_addr, ETH_ALEN); i = 1; netdev_for_each_uc_addr(uc, net_dev) { - memcpy(table->stack_uc_list[i].addr, + memcpy(table->dev_uc_list[i].addr, uc->addr, ETH_ALEN); i++; } } if (net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI) || - netdev_mc_count(net_dev) >= EFX_EF10_FILTER_STACK_MC_MAX) { - table->stack_mc_count = -1; + netdev_mc_count(net_dev) >= EFX_EF10_FILTER_DEV_MC_MAX) { + table->dev_mc_count = -1; } else { - table->stack_mc_count = 1 + netdev_mc_count(net_dev); - eth_broadcast_addr(table->stack_mc_list[0].addr); + table->dev_mc_count = 1 + netdev_mc_count(net_dev); + eth_broadcast_addr(table->dev_mc_list[0].addr); i = 1; netdev_for_each_mc_addr(mc, net_dev) { - memcpy(table->stack_mc_list[i].addr, + memcpy(table->dev_mc_list[i].addr, mc->addr, ETH_ALEN); i++; } @@ -3132,27 +3132,27 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) netif_addr_unlock_bh(net_dev); /* Insert/renew unicast filters */ - if (table->stack_uc_count >= 0) { - for (i = 0; i < table->stack_uc_count; i++) { + if (table->dev_uc_count >= 0) { + for (i = 0; i < table->dev_uc_count; i++) { efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, EFX_FILTER_FLAG_RX_RSS, 0); efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, - table->stack_uc_list[i].addr); + table->dev_uc_list[i].addr); rc = efx_ef10_filter_insert(efx, &spec, true); if (rc < 0) { /* Fall back to unicast-promisc */ while (i--) efx_ef10_filter_remove_safe( efx, EFX_FILTER_PRI_AUTO, - table->stack_uc_list[i].id); - table->stack_uc_count = -1; + table->dev_uc_list[i].id); + table->dev_uc_count = -1; break; } - table->stack_uc_list[i].id = rc; + table->dev_uc_list[i].id = rc; } } - if (table->stack_uc_count < 0) { + if (table->dev_uc_count < 0) { efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, EFX_FILTER_FLAG_RX_RSS, 0); @@ -3160,34 +3160,34 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) rc = efx_ef10_filter_insert(efx, &spec, true); if (rc < 0) { WARN_ON(1); - table->stack_uc_count = 0; + table->dev_uc_count = 0; } else { - table->stack_uc_list[0].id = rc; + table->dev_uc_list[0].id = rc; } } /* Insert/renew multicast filters */ - if (table->stack_mc_count >= 0) { - for (i = 0; i < table->stack_mc_count; i++) { + if (table->dev_mc_count >= 0) { + for (i = 0; i < table->dev_mc_count; i++) { efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, EFX_FILTER_FLAG_RX_RSS, 0); efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, - table->stack_mc_list[i].addr); + table->dev_mc_list[i].addr); rc = efx_ef10_filter_insert(efx, &spec, true); if (rc < 0) { /* Fall back to multicast-promisc */ while (i--) efx_ef10_filter_remove_safe( efx, EFX_FILTER_PRI_AUTO, - table->stack_mc_list[i].id); - table->stack_mc_count = -1; + table->dev_mc_list[i].id); + table->dev_mc_count = -1; break; } - table->stack_mc_list[i].id = rc; + table->dev_mc_list[i].id = rc; } } - if (table->stack_mc_count < 0) { + if (table->dev_mc_count < 0) { efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, EFX_FILTER_FLAG_RX_RSS, 0); @@ -3195,20 +3195,20 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) rc = efx_ef10_filter_insert(efx, &spec, true); if (rc < 0) { WARN_ON(1); - table->stack_mc_count = 0; + table->dev_mc_count = 0; } else { - table->stack_mc_list[0].id = rc; + table->dev_mc_list[0].id = rc; } } /* Remove filters that weren't renewed. Since nothing else - * changes the STACK_OLD flag or removes these filters, we + * changes the AUTO_OLD flag or removes these filters, we * don't need to hold the filter_lock while scanning for * these filters. */ for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) { if (ACCESS_ONCE(table->entry[i].spec) & - EFX_EF10_FILTER_FLAG_STACK_OLD) { + EFX_EF10_FILTER_FLAG_AUTO_OLD) { if (efx_ef10_filter_remove_internal( efx, EFX_FILTER_PRI_AUTO, i, true) < 0) remove_failed = true; diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index fbd923ddf546..378d6b968c4c 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -2184,8 +2184,8 @@ efx_farch_filter_to_gen_spec(struct efx_filter_spec *gen_spec, } static void -efx_farch_filter_init_rx_for_stack(struct efx_nic *efx, - struct efx_farch_filter_spec *spec) +efx_farch_filter_init_rx_auto(struct efx_nic *efx, + struct efx_farch_filter_spec *spec) { /* If there's only one channel then disable RSS for non VF * traffic, thereby allowing VFs to use RSS when the PF can't. @@ -2547,7 +2547,7 @@ static int efx_farch_filter_remove(struct efx_nic *efx, return -ENOENT; if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) { - efx_farch_filter_init_rx_for_stack(efx, spec); + efx_farch_filter_init_rx_auto(efx, spec); efx_farch_filter_push_rx_config(efx); } else { efx_farch_filter_table_clear_entry(efx, table, filter_idx); @@ -2815,7 +2815,7 @@ int efx_farch_filter_table_probe(struct efx_nic *efx) for (i = 0; i < EFX_FARCH_FILTER_SIZE_RX_DEF; i++) { spec = &table->spec[i]; spec->type = EFX_FARCH_FILTER_UC_DEF + i; - efx_farch_filter_init_rx_for_stack(efx, spec); + efx_farch_filter_init_rx_auto(efx, spec); __set_bit(i, table->used_bitmap); } } -- cgit v1.2.3 From f72848021d603846be8aed662bd23372c7d6688e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 21 Nov 2013 19:11:47 +0000 Subject: sfc: Allow filter removal only with exactly matching priority Currently a higher priority client can remove a lower priority client's filter with equal match-expression. This might happen if (a) the higher priority client has a double-free bug, or (b) another client with sufficient priority replaced and then removed an equal filter, allowing the low priority client to insert an equal filter. In neither case does it actually make sense to carry out the removal; we should say the filter doesn't exist, as the filter currently present is not the one that the high-priority client is referring to. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/farch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 2adc8e45461b..155602c500d5 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2563,7 +2563,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, goto out_unlock; } - if (spec->priority > priority) { + if (spec->priority != priority) { rc = -ENOENT; goto out_unlock; } diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 378d6b968c4c..eed0741c2497 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -2543,7 +2543,7 @@ static int efx_farch_filter_remove(struct efx_nic *efx, struct efx_farch_filter_spec *spec = &table->spec[filter_idx]; if (!test_bit(filter_idx, table->used_bitmap) || - spec->priority > priority) + spec->priority != priority) return -ENOENT; if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) { -- cgit v1.2.3 From fbd791202b8c5a06c8c9312bf191d69c0bb5136c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 21 Nov 2013 19:15:03 +0000 Subject: sfc: Implement efx_nic_type::filter_clear_rx operation for EF10 The operation can now fail, so change its return type to int. Remove the inline wrapper while we're changing the signature. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 30 +++++++++++++++++++++++------- drivers/net/ethernet/sfc/efx.c | 2 +- drivers/net/ethernet/sfc/efx.h | 14 -------------- drivers/net/ethernet/sfc/farch.c | 3 ++- drivers/net/ethernet/sfc/net_driver.h | 7 ++++--- drivers/net/ethernet/sfc/nic.h | 4 ++-- 6 files changed, 32 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 155602c500d5..b6a0c2133b8a 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2519,7 +2519,7 @@ static void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx) * Filter ID may come from userland and must be range-checked. */ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, - enum efx_filter_priority priority, + unsigned int priority_mask, u32 filter_id, bool by_index) { unsigned int filter_idx = filter_id % HUNT_FILTER_TBL_ROWS; @@ -2555,7 +2555,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, } if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO && - priority == EFX_FILTER_PRI_AUTO) { + priority_mask == (1U << EFX_FILTER_PRI_AUTO)) { /* Just remove flags */ spec->flags &= ~EFX_FILTER_FLAG_RX_OVER_AUTO; table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_AUTO_OLD; @@ -2563,7 +2563,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx, goto out_unlock; } - if (spec->priority != priority) { + if (!(priority_mask & (1U << spec->priority))) { rc = -ENOENT; goto out_unlock; } @@ -2619,7 +2619,8 @@ static int efx_ef10_filter_remove_safe(struct efx_nic *efx, enum efx_filter_priority priority, u32 filter_id) { - return efx_ef10_filter_remove_internal(efx, priority, filter_id, false); + return efx_ef10_filter_remove_internal(efx, 1U << priority, + filter_id, false); } static int efx_ef10_filter_get_safe(struct efx_nic *efx, @@ -2645,10 +2646,24 @@ static int efx_ef10_filter_get_safe(struct efx_nic *efx, return rc; } -static void efx_ef10_filter_clear_rx(struct efx_nic *efx, +static int efx_ef10_filter_clear_rx(struct efx_nic *efx, enum efx_filter_priority priority) { - /* TODO */ + unsigned int priority_mask; + unsigned int i; + int rc; + + priority_mask = (((1U << (priority + 1)) - 1) & + ~(1U << EFX_FILTER_PRI_AUTO)); + + for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) { + rc = efx_ef10_filter_remove_internal(efx, priority_mask, + i, true); + if (rc && rc != -ENOENT) + return rc; + } + + return 0; } static u32 efx_ef10_filter_count_rx_used(struct efx_nic *efx, @@ -3210,7 +3225,8 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) if (ACCESS_ONCE(table->entry[i].spec) & EFX_EF10_FILTER_FLAG_AUTO_OLD) { if (efx_ef10_filter_remove_internal( - efx, EFX_FILTER_PRI_AUTO, i, true) < 0) + efx, 1U << EFX_FILTER_PRI_AUTO, + i, true) < 0) remove_failed = true; } } diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index d6a927021523..ff0d9c624560 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2151,7 +2151,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data) /* If disabling RX n-tuple filtering, clear existing filters */ if (net_dev->features & ~data & NETIF_F_NTUPLE) - efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); + return efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); return 0; } diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 3a67030c73ea..601224736b9b 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -134,20 +134,6 @@ efx_filter_get_filter_safe(struct efx_nic *efx, return efx->type->filter_get_safe(efx, priority, filter_id, spec); } -/** - * efx_farch_filter_clear_rx - remove RX filters by priority - * @efx: NIC from which to remove the filters - * @priority: Maximum priority to remove - * - * Remove all RX filters whose priority is less than or equal to the - * given @priority and is not %EFX_FILTER_PRI_AUTO. - */ -static inline void efx_filter_clear_rx(struct efx_nic *efx, - enum efx_filter_priority priority) -{ - return efx->type->filter_clear_rx(efx, priority); -} - static inline u32 efx_filter_count_rx_used(struct efx_nic *efx, enum efx_filter_priority priority) { diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index eed0741c2497..f72489a105ca 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -2638,7 +2638,7 @@ efx_farch_filter_table_clear(struct efx_nic *efx, spin_unlock_bh(&efx->filter_lock); } -void efx_farch_filter_clear_rx(struct efx_nic *efx, +int efx_farch_filter_clear_rx(struct efx_nic *efx, enum efx_filter_priority priority) { efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_IP, @@ -2647,6 +2647,7 @@ void efx_farch_filter_clear_rx(struct efx_nic *efx, priority); efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_DEF, priority); + return 0; } u32 efx_farch_filter_count_rx_used(struct efx_nic *efx, diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 1b3c4e5207c5..a0de5c50a0e7 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1044,7 +1044,8 @@ struct efx_mtd_partition { * @filter_insert: add or replace a filter * @filter_remove_safe: remove a filter by ID, carefully * @filter_get_safe: retrieve a filter by ID, carefully - * @filter_clear_rx: remove RX filters by priority + * @filter_clear_rx: Remove all RX filters whose priority is less than or + * equal to the given priority and is not %EFX_FILTER_PRI_AUTO * @filter_count_rx_used: Get the number of filters in use at a given priority * @filter_get_rx_id_limit: Get maximum value of a filter id, plus 1 * @filter_get_rx_ids: Get list of RX filters at a given priority @@ -1166,8 +1167,8 @@ struct efx_nic_type { int (*filter_get_safe)(struct efx_nic *efx, enum efx_filter_priority priority, u32 filter_id, struct efx_filter_spec *); - void (*filter_clear_rx)(struct efx_nic *efx, - enum efx_filter_priority priority); + int (*filter_clear_rx)(struct efx_nic *efx, + enum efx_filter_priority priority); u32 (*filter_count_rx_used)(struct efx_nic *efx, enum efx_filter_priority priority); u32 (*filter_get_rx_id_limit)(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index c665ff6c8012..e25aaf6bda87 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -693,8 +693,8 @@ int efx_farch_filter_remove_safe(struct efx_nic *efx, int efx_farch_filter_get_safe(struct efx_nic *efx, enum efx_filter_priority priority, u32 filter_id, struct efx_filter_spec *); -void efx_farch_filter_clear_rx(struct efx_nic *efx, - enum efx_filter_priority priority); +int efx_farch_filter_clear_rx(struct efx_nic *efx, + enum efx_filter_priority priority); u32 efx_farch_filter_count_rx_used(struct efx_nic *efx, enum efx_filter_priority priority); u32 efx_farch_filter_get_rx_id_limit(struct efx_nic *efx); -- cgit v1.2.3 From ff2de51bfb26e8d6f2ee6d45d5a5eedf51c19d2f Mon Sep 17 00:00:00 2001 From: Andrew Rybchenko Date: Sat, 23 Nov 2013 08:42:07 +0400 Subject: sfc: remove unused 'refcnt' from efx_rx_page_state Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/net_driver.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index a0de5c50a0e7..bc1ff36c03e6 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -288,12 +288,9 @@ struct efx_rx_buffer { * Used to facilitate sharing dma mappings between recycled rx buffers * and those passed up to the kernel. * - * @refcnt: Number of struct efx_rx_buffer's referencing this page. - * When refcnt falls to zero, the page is unmapped for dma * @dma_addr: The dma address of this page. */ struct efx_rx_page_state { - unsigned refcnt; dma_addr_t dma_addr; unsigned int __pad[0] ____cacheline_aligned; -- cgit v1.2.3 From 8c5270acf3f74a2bff04461ce7fbbcf0ae54b2ae Mon Sep 17 00:00:00 2001 From: Andrew Rybchenko Date: Thu, 28 Nov 2013 08:28:13 +0400 Subject: sfc: remove unused 'enum efx_rx_alloc_method' Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/net_driver.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index bc1ff36c03e6..af2b8c59a903 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -360,12 +360,6 @@ struct efx_rx_queue { unsigned int slow_fill_count; }; -enum efx_rx_alloc_method { - RX_ALLOC_METHOD_AUTO = 0, - RX_ALLOC_METHOD_SKB = 1, - RX_ALLOC_METHOD_PAGE = 2, -}; - enum efx_sync_events_state { SYNC_EVENTS_DISABLED = 0, SYNC_EVENTS_QUIESCENT, -- cgit v1.2.3 From 79ac47ae74c1e905c204c2eeb090c8098d570ef2 Mon Sep 17 00:00:00 2001 From: Shradha Shah Date: Thu, 28 Nov 2013 18:48:49 +0000 Subject: sfc: Changed the statistic name emerg_{fetch,wait} to hlb_{fetch,wait} The original names are unnecessarily alarming. Head-of-line blocking is not an emergency. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 8 ++++---- drivers/net/ethernet/sfc/nic.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index b6a0c2133b8a..d352bdc4e53e 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -774,8 +774,8 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = { EF10_DMA_STAT(rx_dp_q_disabled_packets, RXDP_Q_DISABLED_PKTS), EF10_DMA_STAT(rx_dp_di_dropped_packets, RXDP_DI_DROPPED_PKTS), EF10_DMA_STAT(rx_dp_streaming_packets, RXDP_STREAMING_PKTS), - EF10_DMA_STAT(rx_dp_emerg_fetch, RXDP_EMERGENCY_FETCH_CONDITIONS), - EF10_DMA_STAT(rx_dp_emerg_wait, RXDP_EMERGENCY_WAIT_CONDITIONS), + EF10_DMA_STAT(rx_dp_hlb_fetch, RXDP_EMERGENCY_FETCH_CONDITIONS), + EF10_DMA_STAT(rx_dp_hlb_wait, RXDP_EMERGENCY_WAIT_CONDITIONS), }; #define HUNT_COMMON_STAT_MASK ((1ULL << EF10_STAT_tx_bytes) | \ @@ -844,8 +844,8 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = { (1ULL << EF10_STAT_rx_dp_q_disabled_packets) | \ (1ULL << EF10_STAT_rx_dp_di_dropped_packets) | \ (1ULL << EF10_STAT_rx_dp_streaming_packets) | \ - (1ULL << EF10_STAT_rx_dp_emerg_fetch) | \ - (1ULL << EF10_STAT_rx_dp_emerg_wait)) + (1ULL << EF10_STAT_rx_dp_hlb_fetch) | \ + (1ULL << EF10_STAT_rx_dp_hlb_wait)) static u64 efx_ef10_raw_stat_mask(struct efx_nic *efx) { diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index e25aaf6bda87..170ac6ee3ab2 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -412,8 +412,8 @@ enum { EF10_STAT_rx_dp_q_disabled_packets, EF10_STAT_rx_dp_di_dropped_packets, EF10_STAT_rx_dp_streaming_packets, - EF10_STAT_rx_dp_emerg_fetch, - EF10_STAT_rx_dp_emerg_wait, + EF10_STAT_rx_dp_hlb_fetch, + EF10_STAT_rx_dp_hlb_wait, EF10_STAT_COUNT }; -- cgit v1.2.3 From 99691c4ac112666fe8aef30cffef1cc9f6f94f79 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 11 Dec 2013 02:36:08 +0000 Subject: sfc: Add PTP counters to ethtool stats These were implemented by Andrew Jackson and Laurence Evans but not previously included in-tree. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ethtool.c | 8 ++- drivers/net/ethernet/sfc/nic.h | 2 + drivers/net/ethernet/sfc/ptp.c | 126 ++++++++++++++++++++++++++++++++++--- 3 files changed, 127 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index bb2af8045281..f181522688b2 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -359,7 +359,8 @@ static int efx_ethtool_get_sset_count(struct net_device *net_dev, switch (string_set) { case ETH_SS_STATS: return efx->type->describe_stats(efx, NULL) + - EFX_ETHTOOL_SW_STAT_COUNT; + EFX_ETHTOOL_SW_STAT_COUNT + + efx_ptp_describe_stats(efx, NULL); case ETH_SS_TEST: return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL); default: @@ -380,6 +381,8 @@ static void efx_ethtool_get_strings(struct net_device *net_dev, for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) strlcpy(strings + i * ETH_GSTRING_LEN, efx_sw_stat_desc[i].name, ETH_GSTRING_LEN); + strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN; + efx_ptp_describe_stats(efx, strings); break; case ETH_SS_TEST: efx_ethtool_fill_self_tests(efx, NULL, strings, NULL); @@ -429,8 +432,11 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, break; } } + data += EFX_ETHTOOL_SW_STAT_COUNT; spin_unlock_bh(&efx->stats_lock); + + efx_ptp_update_stats(efx, data); } static void efx_ethtool_self_test(struct net_device *net_dev, diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 170ac6ee3ab2..a001fae1a8d7 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -566,6 +566,8 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, unsigned int new_mode); int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); +size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings); +size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats); void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev); void __efx_rx_skb_attach_timestamp(struct efx_channel *channel, struct sk_buff *skb); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 084e2d44790f..7aa070813960 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -255,6 +255,15 @@ struct efx_ptp_timeset { * @nic_ts_enabled: Flag indicating if NIC generated TS events are handled * @txbuf: Buffer for use when transmitting (PTP) packets to MC (avoids * allocations in main data path). + * @good_syncs: Number of successful synchronisations. + * @fast_syncs: Number of synchronisations requiring short delay + * @bad_syncs: Number of failed synchronisations. + * @sync_timeouts: Number of synchronisation timeouts + * @no_time_syncs: Number of synchronisations with no good times. + * @invalid_sync_windows: Number of sync windows with bad durations. + * @undersize_sync_windows: Number of corrected sync windows that are too small + * @oversize_sync_windows: Number of corrected sync windows that are too large + * @rx_no_timestamp: Number of packets received without a timestamp. * @timeset: Last set of synchronisation statistics. */ struct efx_ptp_data { @@ -300,6 +309,16 @@ struct efx_ptp_data { struct workqueue_struct *pps_workwq; bool nic_ts_enabled; MCDI_DECLARE_BUF(txbuf, MC_CMD_PTP_IN_TRANSMIT_LENMAX); + + unsigned int good_syncs; + unsigned int fast_syncs; + unsigned int bad_syncs; + unsigned int sync_timeouts; + unsigned int no_time_syncs; + unsigned int invalid_sync_windows; + unsigned int undersize_sync_windows; + unsigned int oversize_sync_windows; + unsigned int rx_no_timestamp; struct efx_ptp_timeset timeset[MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM]; }; @@ -312,6 +331,78 @@ static int efx_phc_settime(struct ptp_clock_info *ptp, static int efx_phc_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *request, int on); +#define PTP_SW_STAT(ext_name, field_name) \ + { #ext_name, 0, offsetof(struct efx_ptp_data, field_name) } +#define PTP_MC_STAT(ext_name, mcdi_name) \ + { #ext_name, 32, MC_CMD_PTP_OUT_STATUS_STATS_ ## mcdi_name ## _OFST } +static const struct efx_hw_stat_desc efx_ptp_stat_desc[] = { + PTP_SW_STAT(ptp_good_syncs, good_syncs), + PTP_SW_STAT(ptp_fast_syncs, fast_syncs), + PTP_SW_STAT(ptp_bad_syncs, bad_syncs), + PTP_SW_STAT(ptp_sync_timeouts, sync_timeouts), + PTP_SW_STAT(ptp_no_time_syncs, no_time_syncs), + PTP_SW_STAT(ptp_invalid_sync_windows, invalid_sync_windows), + PTP_SW_STAT(ptp_undersize_sync_windows, undersize_sync_windows), + PTP_SW_STAT(ptp_oversize_sync_windows, oversize_sync_windows), + PTP_SW_STAT(ptp_rx_no_timestamp, rx_no_timestamp), + PTP_MC_STAT(ptp_tx_timestamp_packets, TX), + PTP_MC_STAT(ptp_rx_timestamp_packets, RX), + PTP_MC_STAT(ptp_timestamp_packets, TS), + PTP_MC_STAT(ptp_filter_matches, FM), + PTP_MC_STAT(ptp_non_filter_matches, NFM), +}; +#define PTP_STAT_COUNT ARRAY_SIZE(efx_ptp_stat_desc) +static const unsigned long efx_ptp_stat_mask[] = { + [0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL, +}; + +size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings) +{ + if (!efx->ptp_data) + return 0; + + return efx_nic_describe_stats(efx_ptp_stat_desc, PTP_STAT_COUNT, + efx_ptp_stat_mask, strings); +} + +size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_STATUS_LEN); + MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_STATUS_LEN); + size_t i; + int rc; + + if (!efx->ptp_data) + return 0; + + /* Copy software statistics */ + for (i = 0; i < PTP_STAT_COUNT; i++) { + if (efx_ptp_stat_desc[i].dma_width) + continue; + stats[i] = *(unsigned int *)((char *)efx->ptp_data + + efx_ptp_stat_desc[i].offset); + } + + /* Fetch MC statistics. We *must* fill in all statistics or + * risk leaking kernel memory to userland, so if the MCDI + * request fails we pretend we got zeroes. + */ + MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_STATUS); + MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); + rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), NULL); + if (rc) { + netif_err(efx, hw, efx->net_dev, + "MC_CMD_PTP_OP_STATUS failed (%d)\n", rc); + memset(outbuf, 0, sizeof(outbuf)); + } + efx_nic_update_stats(efx_ptp_stat_desc, PTP_STAT_COUNT, + efx_ptp_stat_mask, + stats, _MCDI_PTR(outbuf, 0), false); + + return PTP_STAT_COUNT; +} + /* For Siena platforms NIC time is s and ns */ static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor) { @@ -633,7 +724,8 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), /* Read the set of results and find the last good host-MC * synchronization result. The MC times when it finishes reading the * host time so the corrected window time should be fairly constant - * for a given platform. + * for a given platform. Increment stats for any results that appear + * to be erroneous. */ for (i = 0; i < number_readings; i++) { s32 window, corrected; @@ -658,9 +750,13 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), * interrupt or other delay occurred between reading the system * time and writing it to MC memory. */ - if (window >= SYNCHRONISATION_GRANULARITY_NS && - corrected < MAX_SYNCHRONISATION_NS && - corrected >= ptp->min_synchronisation_ns) { + if (window < SYNCHRONISATION_GRANULARITY_NS) { + ++ptp->invalid_sync_windows; + } else if (corrected >= MAX_SYNCHRONISATION_NS) { + ++ptp->undersize_sync_windows; + } else if (corrected < ptp->min_synchronisation_ns) { + ++ptp->oversize_sync_windows; + } else { ngood++; last_good = i; } @@ -741,6 +837,11 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings) loops++; } + if (loops <= 1) + ++ptp->fast_syncs; + if (!time_before(jiffies, timeout)) + ++ptp->sync_timeouts; + if (ACCESS_ONCE(*start)) efx_ptp_send_times(efx, &last_time); @@ -749,9 +850,20 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings) MC_CMD_PTP_IN_SYNCHRONIZE_LEN, synch_buf, sizeof(synch_buf), &response_length); - if (rc == 0) + if (rc == 0) { rc = efx_ptp_process_times(efx, synch_buf, response_length, &last_time); + if (rc == 0) + ++ptp->good_syncs; + else + ++ptp->no_time_syncs; + } + + /* Increment the bad syncs counter if the synchronize fails, whatever + * the reason. + */ + if (rc != 0) + ++ptp->bad_syncs; return rc; } @@ -907,9 +1019,7 @@ static void efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q) __skb_queue_tail(q, skb); } else if (time_after(jiffies, match->expiry)) { match->state = PTP_PACKET_STATE_TIMED_OUT; - if (net_ratelimit()) - netif_warn(efx, rx_err, efx->net_dev, - "PTP packet - no timestamp seen\n"); + ++ptp->rx_no_timestamp; __skb_queue_tail(q, skb); } else { /* Replace unprocessed entry and stop */ -- cgit v1.2.3 From 0f58411d4fd704d8958879fb08751eae3573271b Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 5 Dec 2013 09:42:49 -0500 Subject: drm: don't double-free on driver load error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All instances of drm_dev_register are followed by drm_dev_free on failure. Don't free dev->control/render/primary on failure, as they will be freed by drm_dev_free since commit 8f6599da8e (drm: delay minor destruction to drm_dev_free()). Instead unplug them. Signed-off-by: Ilia Mirkin Reported-and-tested-by: Bruno Prémont Reviewed-by: David Herrmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_stub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index f53d5246979c..66dd3a001cf1 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -566,11 +566,11 @@ err_unload: if (dev->driver->unload) dev->driver->unload(dev); err_primary_node: - drm_put_minor(dev->primary); + drm_unplug_minor(dev->primary); err_render_node: - drm_put_minor(dev->render); + drm_unplug_minor(dev->render); err_control_node: - drm_put_minor(dev->control); + drm_unplug_minor(dev->control); err_agp: if (dev->driver->bus->agp_destroy) dev->driver->bus->agp_destroy(dev); -- cgit v1.2.3 From 10cdfe9f327ab8d120cf6957e58c6203e3a53847 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 Nov 2013 13:14:19 +0100 Subject: clk: shmobile: Add R-Car Gen2 clocks support The R-Car Gen2 SoCs (R8A7790 and R8A7791) have several clocks that are too custom to be supported in a generic driver. Those clocks can be divided in two categories: - Fixed rate clocks with multiplier and divisor set according to boot mode configuration - Custom divider clocks with SoC-specific divider values This driver supports both. Signed-off-by: Laurent Pinchart Acked-by: Kumar Gala Signed-off-by: Mike Turquette --- .../clock/renesas,rcar-gen2-cpg-clocks.txt | 32 +++ drivers/clk/Makefile | 1 + drivers/clk/shmobile/Makefile | 5 + drivers/clk/shmobile/clk-rcar-gen2.c | 298 +++++++++++++++++++++ include/linux/clk/shmobile.h | 19 ++ 5 files changed, 355 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt create mode 100644 drivers/clk/shmobile/Makefile create mode 100644 drivers/clk/shmobile/clk-rcar-gen2.c create mode 100644 include/linux/clk/shmobile.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt new file mode 100644 index 000000000000..7b41c2fe54db --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt @@ -0,0 +1,32 @@ +* Renesas R-Car Gen2 Clock Pulse Generator (CPG) + +The CPG generates core clocks for the R-Car Gen2 SoCs. It includes three PLLs +and several fixed ratio dividers. + +Required Properties: + + - compatible: Must be one of + - "renesas,r8a7790-cpg-clocks" for the r8a7790 CPG + - "renesas,r8a7791-cpg-clocks" for the r8a7791 CPG + - "renesas,rcar-gen2-cpg-clocks" for the generic R-Car Gen2 CPG + + - reg: Base address and length of the memory resource used by the CPG + + - clocks: Reference to the parent clock + - #clock-cells: Must be 1 + - clock-output-names: The names of the clocks. Supported clocks are "main", + "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1" and "z" + + +Example +------- + + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,r8a7790-cpg-clocks", + "renesas,rcar-gen2-cpg-clocks"; + reg = <0 0xe6150000 0 0x1000>; + clocks = <&extal_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0, "pll1", "pll3", + "lb", "qspi", "sdh", "sd0", "sd1", "z"; + }; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7a10bc9a23e7..8dd1339be98b 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile new file mode 100644 index 000000000000..d0a9034a7946 --- /dev/null +++ b/drivers/clk/shmobile/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o +obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o + +# for emply built-in.o +obj-n := dummy diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c new file mode 100644 index 000000000000..a59ec217a124 --- /dev/null +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -0,0 +1,298 @@ +/* + * rcar_gen2 Core CPG Clocks + * + * Copyright (C) 2013 Ideas On Board SPRL + * + * Contact: Laurent Pinchart + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rcar_gen2_cpg { + struct clk_onecell_data data; + spinlock_t lock; + void __iomem *reg; +}; + +#define CPG_SDCKCR 0x00000074 +#define CPG_PLL0CR 0x000000d8 +#define CPG_FRQCRC 0x000000e0 +#define CPG_FRQCRC_ZFC_MASK (0x1f << 8) +#define CPG_FRQCRC_ZFC_SHIFT 8 + +/* ----------------------------------------------------------------------------- + * Z Clock + * + * Traits of this clock: + * prepare - clk_prepare only ensures that parents are prepared + * enable - clk_enable only ensures that parents are enabled + * rate - rate is adjustable. clk->rate = parent->rate * mult / 32 + * parent - fixed parent. No clk_set_parent support + */ + +struct cpg_z_clk { + struct clk_hw hw; + void __iomem *reg; +}; + +#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) + +static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cpg_z_clk *zclk = to_z_clk(hw); + unsigned int mult; + unsigned int val; + + val = (clk_readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) + >> CPG_FRQCRC_ZFC_SHIFT; + mult = 32 - val; + + return div_u64((u64)parent_rate * mult, 32); +} + +static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long prate = *parent_rate; + unsigned int mult; + + if (!prate) + prate = 1; + + mult = div_u64((u64)rate * 32, prate); + mult = clamp(mult, 1U, 32U); + + return *parent_rate / 32 * mult; +} + +static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cpg_z_clk *zclk = to_z_clk(hw); + unsigned int mult; + u32 val; + + mult = div_u64((u64)rate * 32, parent_rate); + mult = clamp(mult, 1U, 32U); + + val = clk_readl(zclk->reg); + val &= ~CPG_FRQCRC_ZFC_MASK; + val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT; + clk_writel(val, zclk->reg); + + return 0; +} + +static const struct clk_ops cpg_z_clk_ops = { + .recalc_rate = cpg_z_clk_recalc_rate, + .round_rate = cpg_z_clk_round_rate, + .set_rate = cpg_z_clk_set_rate, +}; + +static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg) +{ + static const char *parent_name = "pll0"; + struct clk_init_data init; + struct cpg_z_clk *zclk; + struct clk *clk; + + zclk = kzalloc(sizeof(*zclk), GFP_KERNEL); + if (!zclk) + return ERR_PTR(-ENOMEM); + + init.name = "z"; + init.ops = &cpg_z_clk_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + zclk->reg = cpg->reg + CPG_FRQCRC; + zclk->hw.init = &init; + + clk = clk_register(NULL, &zclk->hw); + if (IS_ERR(clk)) + kfree(zclk); + + return clk; +} + +/* ----------------------------------------------------------------------------- + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL3 + * 14 13 19 (MHz) *1 *1 + *--------------------------------------------------- + * 0 0 0 15 x 1 x172/2 x208/2 x106 + * 0 0 1 15 x 1 x172/2 x208/2 x88 + * 0 1 0 20 x 1 x130/2 x156/2 x80 + * 0 1 1 20 x 1 x130/2 x156/2 x66 + * 1 0 0 26 / 2 x200/2 x240/2 x122 + * 1 0 1 26 / 2 x200/2 x240/2 x102 + * 1 1 0 30 / 2 x172/2 x208/2 x106 + * 1 1 1 30 / 2 x172/2 x208/2 x88 + * + * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2) + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ + (((md) & BIT(13)) >> 12) | \ + (((md) & BIT(19)) >> 19)) +struct cpg_pll_config { + unsigned int extal_div; + unsigned int pll1_mult; + unsigned int pll3_mult; +}; + +static const struct cpg_pll_config cpg_pll_configs[8] __initconst = { + { 1, 208, 106 }, { 1, 208, 88 }, { 1, 156, 80 }, { 1, 156, 66 }, + { 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208, 88 }, +}; + +/* SDHI divisors */ +static const struct clk_div_table cpg_sdh_div_table[] = { + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, + { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, + { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, +}; + +static const struct clk_div_table cpg_sd01_div_table[] = { + { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, + { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, +}; + +/* ----------------------------------------------------------------------------- + * Initialization + */ + +static u32 cpg_mode __initdata; + +static struct clk * __init +rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, + const struct cpg_pll_config *config, + const char *name) +{ + const struct clk_div_table *table = NULL; + const char *parent_name = "main"; + unsigned int shift; + unsigned int mult = 1; + unsigned int div = 1; + + if (!strcmp(name, "main")) { + parent_name = of_clk_get_parent_name(np, 0); + div = config->extal_div; + } else if (!strcmp(name, "pll0")) { + /* PLL0 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + u32 value = clk_readl(cpg->reg + CPG_PLL0CR); + mult = ((value >> 24) & ((1 << 7) - 1)) + 1; + } else if (!strcmp(name, "pll1")) { + mult = config->pll1_mult / 2; + } else if (!strcmp(name, "pll3")) { + mult = config->pll3_mult; + } else if (!strcmp(name, "lb")) { + div = cpg_mode & BIT(18) ? 36 : 24; + } else if (!strcmp(name, "qspi")) { + div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) + ? 16 : 20; + } else if (!strcmp(name, "sdh")) { + table = cpg_sdh_div_table; + shift = 8; + } else if (!strcmp(name, "sd0")) { + table = cpg_sd01_div_table; + shift = 4; + } else if (!strcmp(name, "sd1")) { + table = cpg_sd01_div_table; + shift = 0; + } else if (!strcmp(name, "z")) { + return cpg_z_clk_register(cpg); + } else { + return ERR_PTR(-EINVAL); + } + + if (!table) + return clk_register_fixed_factor(NULL, name, parent_name, 0, + mult, div); + else + return clk_register_divider_table(NULL, name, parent_name, 0, + cpg->reg + CPG_SDCKCR, shift, + 4, 0, table, &cpg->lock); +} + +static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) +{ + const struct cpg_pll_config *config; + struct rcar_gen2_cpg *cpg; + struct clk **clks; + unsigned int i; + int num_clks; + + num_clks = of_property_count_strings(np, "clock-output-names"); + if (num_clks < 0) { + pr_err("%s: failed to count clocks\n", __func__); + return; + } + + cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); + clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); + if (cpg == NULL || clks == NULL) { + /* We're leaking memory on purpose, there's no point in cleaning + * up as the system won't boot anyway. + */ + pr_err("%s: failed to allocate cpg\n", __func__); + return; + } + + spin_lock_init(&cpg->lock); + + cpg->data.clks = clks; + cpg->data.clk_num = num_clks; + + cpg->reg = of_iomap(np, 0); + if (WARN_ON(cpg->reg == NULL)) + return; + + config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + for (i = 0; i < num_clks; ++i) { + const char *name; + struct clk *clk; + + of_property_read_string_index(np, "clock-output-names", i, + &name); + + clk = rcar_gen2_cpg_register_clock(np, cpg, config, name); + if (IS_ERR(clk)) + pr_err("%s: failed to register %s %s clock (%ld)\n", + __func__, np->name, name, PTR_ERR(clk)); + else + cpg->data.clks[i] = clk; + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); +} +CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks", + rcar_gen2_cpg_clocks_init); + +void __init rcar_gen2_clocks_init(u32 mode) +{ + cpg_mode = mode; + + of_clk_init(NULL); +} diff --git a/include/linux/clk/shmobile.h b/include/linux/clk/shmobile.h new file mode 100644 index 000000000000..f9bf080a1123 --- /dev/null +++ b/include/linux/clk/shmobile.h @@ -0,0 +1,19 @@ +/* + * Copyright 2013 Ideas On Board SPRL + * + * Contact: Laurent Pinchart + * + * 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 __LINUX_CLK_SHMOBILE_H_ +#define __LINUX_CLK_SHMOBILE_H_ + +#include + +void rcar_gen2_clocks_init(u32 mode); + +#endif -- cgit v1.2.3 From abe844aa5bb50444ac3e02aed89b431823d6ad56 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 17 Oct 2013 23:54:07 +0200 Subject: clk: shmobile: Add DIV6 clock support DIV6 clocks are divider gate clocks controlled through a single register. The divider is expressed on 6 bits, hence the name, and can take values from 1/1 to 1/64. Those clocks are found on Renesas ARM SoCs. Signed-off-by: Laurent Pinchart Signed-off-by: Mike Turquette --- .../bindings/clock/renesas,cpg-div6-clocks.txt | 28 ++++ drivers/clk/shmobile/Makefile | 1 + drivers/clk/shmobile/clk-div6.c | 185 +++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt create mode 100644 drivers/clk/shmobile/clk-div6.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt new file mode 100644 index 000000000000..952e373178d2 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt @@ -0,0 +1,28 @@ +* Renesas CPG DIV6 Clock + +The CPG DIV6 clocks are variable factor clocks provided by the Clock Pulse +Generator (CPG). They clock input is divided by a configurable factor from 1 +to 64. + +Required Properties: + + - compatible: Must be one of the following + - "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks + - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2) DIV6 clocks + - "renesas,cpg-div6-clock" for generic DIV6 clocks + - reg: Base address and length of the memory resource used by the DIV6 clock + - clocks: Reference to the parent clock + - #clock-cells: Must be 0 + - clock-output-names: The name of the clock as a free-form string + + +Example +------- + + sd2_clk: sd2_clk@e6150078 { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150078 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd2"; + }; diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index d0a9034a7946..2e4a1197aa0a 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o +obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o # for emply built-in.o obj-n := dummy diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c new file mode 100644 index 000000000000..aac4756ec52e --- /dev/null +++ b/drivers/clk/shmobile/clk-div6.c @@ -0,0 +1,185 @@ +/* + * r8a7790 Common Clock Framework support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * + * Contact: Laurent Pinchart + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CPG_DIV6_CKSTP BIT(8) +#define CPG_DIV6_DIV(d) ((d) & 0x3f) +#define CPG_DIV6_DIV_MASK 0x3f + +/** + * struct div6_clock - MSTP gating clock + * @hw: handle between common and hardware-specific interfaces + * @reg: IO-remapped register + * @div: divisor value (1-64) + */ +struct div6_clock { + struct clk_hw hw; + void __iomem *reg; + unsigned int div; +}; + +#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) + +static int cpg_div6_clock_enable(struct clk_hw *hw) +{ + struct div6_clock *clock = to_div6_clock(hw); + + clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg); + + return 0; +} + +static void cpg_div6_clock_disable(struct clk_hw *hw) +{ + struct div6_clock *clock = to_div6_clock(hw); + + /* DIV6 clocks require the divisor field to be non-zero when stopping + * the clock. + */ + clk_writel(CPG_DIV6_CKSTP | CPG_DIV6_DIV(CPG_DIV6_DIV_MASK), + clock->reg); +} + +static int cpg_div6_clock_is_enabled(struct clk_hw *hw) +{ + struct div6_clock *clock = to_div6_clock(hw); + + return !(clk_readl(clock->reg) & CPG_DIV6_CKSTP); +} + +static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct div6_clock *clock = to_div6_clock(hw); + unsigned int div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; + + return parent_rate / div; +} + +static unsigned int cpg_div6_clock_calc_div(unsigned long rate, + unsigned long parent_rate) +{ + unsigned int div; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + return clamp_t(unsigned int, div, 1, 64); +} + +static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate); + + return *parent_rate / div; +} + +static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct div6_clock *clock = to_div6_clock(hw); + unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate); + + clock->div = div; + + /* Only program the new divisor if the clock isn't stopped. */ + if (!(clk_readl(clock->reg) & CPG_DIV6_CKSTP)) + clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg); + + return 0; +} + +static const struct clk_ops cpg_div6_clock_ops = { + .enable = cpg_div6_clock_enable, + .disable = cpg_div6_clock_disable, + .is_enabled = cpg_div6_clock_is_enabled, + .recalc_rate = cpg_div6_clock_recalc_rate, + .round_rate = cpg_div6_clock_round_rate, + .set_rate = cpg_div6_clock_set_rate, +}; + +static void __init cpg_div6_clock_init(struct device_node *np) +{ + struct clk_init_data init; + struct div6_clock *clock; + const char *parent_name; + const char *name; + struct clk *clk; + int ret; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) { + pr_err("%s: failed to allocate %s DIV6 clock\n", + __func__, np->name); + return; + } + + /* Remap the clock register and read the divisor. Disabling the + * clock overwrites the divisor, so we need to cache its value for the + * enable operation. + */ + clock->reg = of_iomap(np, 0); + if (clock->reg == NULL) { + pr_err("%s: failed to map %s DIV6 clock register\n", + __func__, np->name); + goto error; + } + + clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; + + /* Parse the DT properties. */ + ret = of_property_read_string(np, "clock-output-names", &name); + if (ret < 0) { + pr_err("%s: failed to get %s DIV6 clock output name\n", + __func__, np->name); + goto error; + } + + parent_name = of_clk_get_parent_name(np, 0); + if (parent_name == NULL) { + pr_err("%s: failed to get %s DIV6 clock parent name\n", + __func__, np->name); + goto error; + } + + /* Register the clock. */ + init.name = name; + init.ops = &cpg_div6_clock_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register %s DIV6 clock (%ld)\n", + __func__, np->name, PTR_ERR(clk)); + goto error; + } + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + + return; + +error: + if (clock->reg) + iounmap(clock->reg); + kfree(clock); +} +CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); -- cgit v1.2.3 From f94859c215b6d977794108a1a9a101239e393c09 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 17 Oct 2013 23:54:07 +0200 Subject: clk: shmobile: Add MSTP clock support MSTP clocks are gate clocks controlled through a register that handles up to 32 clocks. The register is often sparsely populated. Those clocks are found on Renesas ARM SoCs. Signed-off-by: Laurent Pinchart Signed-off-by: Mike Turquette --- .../bindings/clock/renesas,cpg-mstp-clocks.txt | 51 +++++ drivers/clk/shmobile/Makefile | 1 + drivers/clk/shmobile/clk-mstp.c | 229 +++++++++++++++++++++ 3 files changed, 281 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt create mode 100644 drivers/clk/shmobile/clk-mstp.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt new file mode 100644 index 000000000000..a6a352c2771e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt @@ -0,0 +1,51 @@ +* Renesas CPG Module Stop (MSTP) Clocks + +The CPG can gate SoC device clocks. The gates are organized in groups of up to +32 gates. + +This device tree binding describes a single 32 gate clocks group per node. +Clocks are referenced by user nodes by the MSTP node phandle and the clock +index in the group, from 0 to 31. + +Required Properties: + + - compatible: Must be one of the following + - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks + - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2) MSTP gate clocks + - "renesas,cpg-mstp-clock" for generic MSTP gate clocks + - reg: Base address and length of the I/O mapped registers used by the MSTP + clocks. The first register is the clock control register and is mandatory. + The second register is the clock status register and is optional when not + implemented in hardware. + - clocks: Reference to the parent clocks, one per output clock. The parents + must appear in the same order as the output clocks. + - #clock-cells: Must be 1 + - clock-output-names: The name of the clocks as free-form strings + - renesas,indices: Indices of the gate clocks into the group (0 to 31) + +The clocks, clock-output-names and renesas,indices properties contain one +entry per gate clock. The MSTP groups are sparsely populated. Unimplemented +gate clocks must not be declared. + + +Example +------- + + #include + + mstp3_clks: mstp3_clks@e615013c { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; + clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>, + <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, + <&mmc0_clk>; + #clock-cells = <1>; + clock-output-names = + "tpu0", "mmcif1", "sdhi3", "sdhi2", + "sdhi1", "sdhi0", "mmcif0"; + renesas,clock-indices = < + R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 + R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 + R8A7790_CLK_MMCIF0 + >; + }; diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index 2e4a1197aa0a..706adc6ae70c 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o +obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o # for emply built-in.o obj-n := dummy diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c new file mode 100644 index 000000000000..e576b60de20e --- /dev/null +++ b/drivers/clk/shmobile/clk-mstp.c @@ -0,0 +1,229 @@ +/* + * R-Car MSTP clocks + * + * Copyright (C) 2013 Ideas On Board SPRL + * + * Contact: Laurent Pinchart + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include + +/* + * MSTP clocks. We can't use standard gate clocks as we need to poll on the + * status register when enabling the clock. + */ + +#define MSTP_MAX_CLOCKS 32 + +/** + * struct mstp_clock_group - MSTP gating clocks group + * + * @data: clocks in this group + * @smstpcr: module stop control register + * @mstpsr: module stop status register (optional) + * @lock: protects writes to SMSTPCR + */ +struct mstp_clock_group { + struct clk_onecell_data data; + void __iomem *smstpcr; + void __iomem *mstpsr; + spinlock_t lock; +}; + +/** + * struct mstp_clock - MSTP gating clock + * @hw: handle between common and hardware-specific interfaces + * @bit_index: control bit index + * @group: MSTP clocks group + */ +struct mstp_clock { + struct clk_hw hw; + u32 bit_index; + struct mstp_clock_group *group; +}; + +#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw) + +static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) +{ + struct mstp_clock *clock = to_mstp_clock(hw); + struct mstp_clock_group *group = clock->group; + u32 bitmask = BIT(clock->bit_index); + unsigned long flags; + unsigned int i; + u32 value; + + spin_lock_irqsave(&group->lock, flags); + + value = clk_readl(group->smstpcr); + if (enable) + value &= ~bitmask; + else + value |= bitmask; + clk_writel(value, group->smstpcr); + + spin_unlock_irqrestore(&group->lock, flags); + + if (!enable || !group->mstpsr) + return 0; + + for (i = 1000; i > 0; --i) { + if (!(clk_readl(group->mstpsr) & bitmask)) + break; + cpu_relax(); + } + + if (!i) { + pr_err("%s: failed to enable %p[%d]\n", __func__, + group->smstpcr, clock->bit_index); + return -ETIMEDOUT; + } + + return 0; +} + +static int cpg_mstp_clock_enable(struct clk_hw *hw) +{ + return cpg_mstp_clock_endisable(hw, true); +} + +static void cpg_mstp_clock_disable(struct clk_hw *hw) +{ + cpg_mstp_clock_endisable(hw, false); +} + +static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) +{ + struct mstp_clock *clock = to_mstp_clock(hw); + struct mstp_clock_group *group = clock->group; + u32 value; + + if (group->mstpsr) + value = clk_readl(group->mstpsr); + else + value = clk_readl(group->smstpcr); + + return !!(value & BIT(clock->bit_index)); +} + +static const struct clk_ops cpg_mstp_clock_ops = { + .enable = cpg_mstp_clock_enable, + .disable = cpg_mstp_clock_disable, + .is_enabled = cpg_mstp_clock_is_enabled, +}; + +static struct clk * __init +cpg_mstp_clock_register(const char *name, const char *parent_name, + unsigned int index, struct mstp_clock_group *group) +{ + struct clk_init_data init; + struct mstp_clock *clock; + struct clk *clk; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) { + pr_err("%s: failed to allocate MSTP clock.\n", __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = name; + init.ops = &cpg_mstp_clock_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->bit_index = index; + clock->group = group; + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + + if (IS_ERR(clk)) + kfree(clock); + + return clk; +} + +static void __init cpg_mstp_clocks_init(struct device_node *np) +{ + struct mstp_clock_group *group; + struct clk **clks; + unsigned int i; + + group = kzalloc(sizeof(*group), GFP_KERNEL); + clks = kzalloc(MSTP_MAX_CLOCKS * sizeof(*clks), GFP_KERNEL); + if (group == NULL || clks == NULL) { + kfree(group); + kfree(clks); + pr_err("%s: failed to allocate group\n", __func__); + return; + } + + spin_lock_init(&group->lock); + group->data.clks = clks; + + group->smstpcr = of_iomap(np, 0); + group->mstpsr = of_iomap(np, 1); + + if (group->smstpcr == NULL) { + pr_err("%s: failed to remap SMSTPCR\n", __func__); + kfree(group); + kfree(clks); + return; + } + + for (i = 0; i < MSTP_MAX_CLOCKS; ++i) { + const char *parent_name; + const char *name; + u32 clkidx; + int ret; + + /* Skip clocks with no name. */ + ret = of_property_read_string_index(np, "clock-output-names", + i, &name); + if (ret < 0 || strlen(name) == 0) + continue; + + parent_name = of_clk_get_parent_name(np, i); + ret = of_property_read_u32_index(np, "renesas,clock-indices", i, + &clkidx); + if (parent_name == NULL || ret < 0) + break; + + if (clkidx >= MSTP_MAX_CLOCKS) { + pr_err("%s: invalid clock %s %s index %u)\n", + __func__, np->name, name, clkidx); + continue; + } + + clks[clkidx] = cpg_mstp_clock_register(name, parent_name, i, + group); + if (!IS_ERR(clks[clkidx])) { + group->data.clk_num = max(group->data.clk_num, clkidx); + /* + * Register a clkdev to let board code retrieve the + * clock by name and register aliases for non-DT + * devices. + * + * FIXME: Remove this when all devices that require a + * clock will be instantiated from DT. + */ + clk_register_clkdev(clks[clkidx], name, NULL); + } else { + pr_err("%s: failed to register %s %s clock (%ld)\n", + __func__, np->name, name, PTR_ERR(clks[clkidx])); + } + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &group->data); +} +CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); -- cgit v1.2.3 From f984841bc0c4d596c4e95d1798f318291c4f78f5 Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Mon, 9 Dec 2013 11:15:56 -0800 Subject: dma: mv_xor: remove mv_desc_get_dest_addr() The following commit: 54f8d501e842 dmaengine: remove DMA unmap from drivers removed the last caller to mv_desc_get_dest_addr(), creating the warning: drivers/dma/mv_xor.c:57:12: warning: mv_desc_get_dest_addr defined but not used [-Wunused-function] Remove it. Signed-off-by: Jason Cooper Acked-by: Vinod Koul Signed-off-by: Dan Williams --- drivers/dma/mv_xor.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 7807f0ef4e20..23bcc9158cbc 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -54,12 +54,6 @@ static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags) hw_desc->desc_command = (1 << 31); } -static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc) -{ - struct mv_xor_desc *hw_desc = desc->hw_desc; - return hw_desc->phy_dest_addr; -} - static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc, u32 byte_count) { -- cgit v1.2.3 From d7fb0300fe663a5e338e3adeb7f811a2f9727e6c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 9 Dec 2013 11:15:57 -0800 Subject: dmaengine: at_hdmac: remove unused function commit 54f8d501e8428 ('dmaengine: remove DMA unmap from drivers') refactored some code which resulted in an unused function in the at_hdmac driver: drivers/dma/at_hdmac_regs.h:350:23: warning: 'chan2parent' defined but not used [-Wunused-function] Fixes: 54f8d501e8428 ('dmaengine: remove DMA unmap from drivers') Signed-off-by: Olof Johansson Cc: Bartlomiej Zolnierkiewicz Acked-by: Nicolas Ferre Acked-by: Bartlomiej Zolnierkiewicz Acked-by: Vinod Koul Signed-off-by: Dan Williams --- drivers/dma/at_hdmac_regs.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index f31d647acdfa..2787aba60c6b 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -347,10 +347,6 @@ static struct device *chan2dev(struct dma_chan *chan) { return &chan->dev->device; } -static struct device *chan2parent(struct dma_chan *chan) -{ - return chan->dev->device.parent; -} #if defined(VERBOSE_DEBUG) static void vdbg_dump_regs(struct at_dma_chan *atchan) -- cgit v1.2.3 From 6aa2731ce2c7bd1305b553b5fc14ae4856d36569 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Dec 2013 11:15:59 -0800 Subject: dma: fix build warnings in ppc4xx drivers/dma/ppc4xx/adma.c:1507:6: warning: unused variable 'i' [-Wunused-variable] - due to unmap reworks drivers/dma/ppc4xx/adma.c:3900:2: warning: format '%s' expects a matching 'char *' argument [-Wformat] - due to memset removal drivers/dma/ppc4xx/adma.c:538:13: warning: 'ppc440spe_desc_init_memset' defined but not used [-Wunused-function] - due to memset removal Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Dan Williams --- drivers/dma/ppc4xx/adma.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 8da48c6b2a38..8bba298535b0 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -532,29 +532,6 @@ static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc, hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2; } -/** - * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation - */ -static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc, - int value, unsigned long flags) -{ - struct dma_cdb *hw_desc = desc->hw_desc; - - memset(desc->hw_desc, 0, sizeof(struct dma_cdb)); - desc->hw_next = NULL; - desc->src_cnt = 1; - desc->dst_cnt = 1; - - if (flags & DMA_PREP_INTERRUPT) - set_bit(PPC440SPE_DESC_INT, &desc->flags); - else - clear_bit(PPC440SPE_DESC_INT, &desc->flags); - - hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value); - hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value); - hw_desc->opc = DMA_CDB_OPC_DFILL128; -} - /** * ppc440spe_desc_set_src_addr - set source address into the descriptor */ @@ -1504,8 +1481,6 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions( struct ppc440spe_adma_chan *chan, dma_cookie_t cookie) { - int i; - BUG_ON(desc->async_tx.cookie < 0); if (desc->async_tx.cookie > 0) { cookie = desc->async_tx.cookie; @@ -3898,7 +3873,7 @@ static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev) ppc440spe_adma_prep_dma_interrupt; } pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: " - "( %s%s%s%s%s%s%s)\n", + "( %s%s%s%s%s%s)\n", dev_name(adev->dev), dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "", dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "", -- cgit v1.2.3 From bbc76560d488c437dbddff72242b0a07e42a0fd0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Dec 2013 11:16:00 -0800 Subject: dma: fix fsldma build warnings drivers/dma/fsldma.c: In function 'fsldma_cleanup_descriptor': drivers/dma/fsldma.c:860:6: warning: unused variable 'len' [-Wunused-variable] drivers/dma/fsldma.c:859:13: warning: unused variable 'dst' [-Wunused-variable] drivers/dma/fsldma.c:858:13: warning: unused variable 'src' [-Wunused-variable] drivers/dma/fsldma.c:857:17: warning: unused variable 'dev' [-Wunused-variable] - due to unmap changes drivers/dma/fsldma.c: In function 'fsl_dma_tx_submit': drivers/dma/fsldma.c:428:2: warning: 'cookie' may be used uninitialized in this function [-Wuninitialized] - long standing warning Cc: Bartlomiej Zolnierkiewicz Cc: Li Yang Cc: Zhang Wei Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 7086a16a55f2..f157c6f76b32 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -86,11 +86,6 @@ static void set_desc_cnt(struct fsldma_chan *chan, hw->count = CPU_TO_DMA(chan, count, 32); } -static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc) -{ - return DMA_TO_CPU(chan, desc->hw.count, 32); -} - static void set_desc_src(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, dma_addr_t src) { @@ -101,16 +96,6 @@ static void set_desc_src(struct fsldma_chan *chan, hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64); } -static dma_addr_t get_desc_src(struct fsldma_chan *chan, - struct fsl_desc_sw *desc) -{ - u64 snoop_bits; - - snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) - ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0; - return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits; -} - static void set_desc_dst(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, dma_addr_t dst) { @@ -121,16 +106,6 @@ static void set_desc_dst(struct fsldma_chan *chan, hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64); } -static dma_addr_t get_desc_dst(struct fsldma_chan *chan, - struct fsl_desc_sw *desc) -{ - u64 snoop_bits; - - snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) - ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0; - return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits; -} - static void set_desc_next(struct fsldma_chan *chan, struct fsl_dma_ld_hw *hw, dma_addr_t next) { @@ -408,7 +383,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx) struct fsl_desc_sw *desc = tx_to_fsl_desc(tx); struct fsl_desc_sw *child; unsigned long flags; - dma_cookie_t cookie; + dma_cookie_t cookie = -EINVAL; spin_lock_irqsave(&chan->desc_lock, flags); @@ -854,10 +829,6 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan, struct fsl_desc_sw *desc) { struct dma_async_tx_descriptor *txd = &desc->async_tx; - struct device *dev = chan->common.device->dev; - dma_addr_t src = get_desc_src(chan, desc); - dma_addr_t dst = get_desc_dst(chan, desc); - u32 len = get_desc_cnt(chan, desc); /* Run the link descriptor callback function */ if (txd->callback) { -- cgit v1.2.3 From 745c00daf9a75bacb53d0fe8635a132673ab0b46 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Dec 2013 11:16:01 -0800 Subject: dmatest: fix build warning on mips drivers/dma/dmatest.c:543:11: warning: passing argument 1 of 'virt_to_phys' makes pointer from integer without a cast [enabled by default] mips expects virt_to_phys() to take a pointer. Fix up the types accordingly. Signed-off-by: Dan Williams --- drivers/dma/dmatest.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 20f9a3aaf926..9dfcaf5c1288 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -539,9 +539,9 @@ static int dmatest_func(void *data) um->len = params->buf_size; for (i = 0; i < src_cnt; i++) { - unsigned long buf = (unsigned long) thread->srcs[i]; + void *buf = thread->srcs[i]; struct page *pg = virt_to_page(buf); - unsigned pg_off = buf & ~PAGE_MASK; + unsigned pg_off = (unsigned long) buf & ~PAGE_MASK; um->addr[i] = dma_map_page(dev->dev, pg, pg_off, um->len, DMA_TO_DEVICE); @@ -559,9 +559,9 @@ static int dmatest_func(void *data) /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ dsts = &um->addr[src_cnt]; for (i = 0; i < dst_cnt; i++) { - unsigned long buf = (unsigned long) thread->dsts[i]; + void *buf = thread->dsts[i]; struct page *pg = virt_to_page(buf); - unsigned pg_off = buf & ~PAGE_MASK; + unsigned pg_off = (unsigned long) buf & ~PAGE_MASK; dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len, DMA_BIDIRECTIONAL); -- cgit v1.2.3 From 8e5ee258d98a6643227d958361aec2a62559b804 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Dec 2013 11:16:03 -0800 Subject: dma: fix build warnings in txx9 The unmap rework missed this: drivers/dma/txx9dmac.c:409:25: warning: unused variable 'ds' [-Wunused-variable] Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Dan Williams --- drivers/dma/txx9dmac.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index bae6c29f5502..17686caf64d5 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -406,7 +406,6 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc, dma_async_tx_callback callback; void *param; struct dma_async_tx_descriptor *txd = &desc->txd; - struct txx9dmac_slave *ds = dc->chan.private; dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n", txd->cookie, desc); -- cgit v1.2.3 From 3cc377b9ae4bd3133bf8ba388d2b2b66b2b973c1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Dec 2013 10:33:16 -0800 Subject: dmaengine: fix enable for high order unmap pools The higher order mempools support raid operations, and we want to disable them when raid support is not enabled. Making them conditional on ASYNC_TX_DMA is not sufficient as other users (specifically dmatest) will also issue raid operations. Make raid drivers explicitly request that the core carry the higher order pools. Reported-by: Ezequiel Garcia Tested-by: Ezequiel Garcia Signed-off-by: Dan Williams --- drivers/dma/Kconfig | 6 ++++++ drivers/dma/dmaengine.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 446687cc2334..132a4fd375b2 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -62,6 +62,7 @@ config INTEL_IOATDMA tristate "Intel I/OAT DMA support" depends on PCI && X86 select DMA_ENGINE + select DMA_ENGINE_RAID select DCA help Enable support for the Intel(R) I/OAT DMA engine present @@ -112,6 +113,7 @@ config MV_XOR bool "Marvell XOR engine support" depends on PLAT_ORION select DMA_ENGINE + select DMA_ENGINE_RAID select ASYNC_TX_ENABLE_CHANNEL_SWITCH ---help--- Enable support for the Marvell XOR engine. @@ -187,6 +189,7 @@ config AMCC_PPC440SPE_ADMA tristate "AMCC PPC440SPe ADMA support" depends on 440SPe || 440SP select DMA_ENGINE + select DMA_ENGINE_RAID select ARCH_HAS_ASYNC_TX_FIND_CHANNEL select ASYNC_TX_ENABLE_CHANNEL_SWITCH help @@ -377,4 +380,7 @@ config DMATEST Simple DMA test client. Say N unless you're debugging a DMA Device driver. +config DMA_ENGINE_RAID + bool + endif diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index ea806bdc12ef..b601024f518c 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -912,7 +912,7 @@ struct dmaengine_unmap_pool { #define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) } static struct dmaengine_unmap_pool unmap_pool[] = { __UNMAP_POOL(2), - #if IS_ENABLED(CONFIG_ASYNC_TX_DMA) + #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID) __UNMAP_POOL(16), __UNMAP_POOL(128), __UNMAP_POOL(256), -- cgit v1.2.3 From d16695a75019ac4baad7a117dc86d1d292e09115 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 10 Dec 2013 09:32:36 -0300 Subject: dma: mv_xor: Use dmaengine_unmap_data for the self-tests The driver-specific unmap code was removed in: commit 54f8d501e842879143e867e70996574a54d1e130 Author: Bartlomiej Zolnierkiewicz Date: Fri Oct 18 19:35:32 2013 +0200 dmaengine: remove DMA unmap from drivers which had the side-effect of not unmapping the self-test mappings. Fix this by using dmaengine_unmap_data in the self-test routines. In addition, since dmaengine_unmap() assumes that all mappings were created with dma_map_page, this commit changes the single mapping to a page mapping to avoid an incorrect unmapping of the memcpy self-test. The allocation could be changed to be alloc_page(), but sticking to kmalloc results in a less intrusive patch. The size of the test buffer is increased, since dma_map_page() seem to fail when the source and destination pages are the same page. Signed-off-by: Ezequiel Garcia Signed-off-by: Dan Williams --- drivers/dma/mv_xor.c | 71 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 23bcc9158cbc..79620887d637 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -781,7 +781,6 @@ static void mv_xor_issue_pending(struct dma_chan *chan) /* * Perform a transaction to verify the HW works. */ -#define MV_XOR_TEST_SIZE 2000 static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) { @@ -791,20 +790,21 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) struct dma_chan *dma_chan; dma_cookie_t cookie; struct dma_async_tx_descriptor *tx; + struct dmaengine_unmap_data *unmap; int err = 0; - src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL); + src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL); if (!src) return -ENOMEM; - dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL); + dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL); if (!dest) { kfree(src); return -ENOMEM; } /* Fill in src buffer */ - for (i = 0; i < MV_XOR_TEST_SIZE; i++) + for (i = 0; i < PAGE_SIZE; i++) ((u8 *) src)[i] = (u8)i; dma_chan = &mv_chan->dmachan; @@ -813,14 +813,26 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) goto out; } - dest_dma = dma_map_single(dma_chan->device->dev, dest, - MV_XOR_TEST_SIZE, DMA_FROM_DEVICE); + unmap = dmaengine_get_unmap_data(dma_chan->device->dev, 2, GFP_KERNEL); + if (!unmap) { + err = -ENOMEM; + goto free_resources; + } + + src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0, + PAGE_SIZE, DMA_TO_DEVICE); + unmap->to_cnt = 1; + unmap->addr[0] = src_dma; - src_dma = dma_map_single(dma_chan->device->dev, src, - MV_XOR_TEST_SIZE, DMA_TO_DEVICE); + dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0, + PAGE_SIZE, DMA_FROM_DEVICE); + unmap->from_cnt = 1; + unmap->addr[1] = dest_dma; + + unmap->len = PAGE_SIZE; tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma, - MV_XOR_TEST_SIZE, 0); + PAGE_SIZE, 0); cookie = mv_xor_tx_submit(tx); mv_xor_issue_pending(dma_chan); async_tx_ack(tx); @@ -835,8 +847,8 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) } dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma, - MV_XOR_TEST_SIZE, DMA_FROM_DEVICE); - if (memcmp(src, dest, MV_XOR_TEST_SIZE)) { + PAGE_SIZE, DMA_FROM_DEVICE); + if (memcmp(src, dest, PAGE_SIZE)) { dev_err(dma_chan->device->dev, "Self-test copy failed compare, disabling\n"); err = -ENODEV; @@ -844,6 +856,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) } free_resources: + dmaengine_unmap_put(unmap); mv_xor_free_chan_resources(dma_chan); out: kfree(src); @@ -861,13 +874,15 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST]; dma_addr_t dest_dma; struct dma_async_tx_descriptor *tx; + struct dmaengine_unmap_data *unmap; struct dma_chan *dma_chan; dma_cookie_t cookie; u8 cmp_byte = 0; u32 cmp_word; int err = 0; + int src_count = MV_XOR_NUM_SRC_TEST; - for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { + for (src_idx = 0; src_idx < src_count; src_idx++) { xor_srcs[src_idx] = alloc_page(GFP_KERNEL); if (!xor_srcs[src_idx]) { while (src_idx--) @@ -884,13 +899,13 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) } /* Fill in src buffers */ - for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { + for (src_idx = 0; src_idx < src_count; src_idx++) { u8 *ptr = page_address(xor_srcs[src_idx]); for (i = 0; i < PAGE_SIZE; i++) ptr[i] = (1 << src_idx); } - for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) + for (src_idx = 0; src_idx < src_count; src_idx++) cmp_byte ^= (u8) (1 << src_idx); cmp_word = (cmp_byte << 24) | (cmp_byte << 16) | @@ -904,16 +919,29 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) goto out; } + unmap = dmaengine_get_unmap_data(dma_chan->device->dev, src_count + 1, + GFP_KERNEL); + if (!unmap) { + err = -ENOMEM; + goto free_resources; + } + /* test xor */ - dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE, - DMA_FROM_DEVICE); + for (i = 0; i < src_count; i++) { + unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i], + 0, PAGE_SIZE, DMA_TO_DEVICE); + dma_srcs[i] = unmap->addr[i]; + unmap->to_cnt++; + } - for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++) - dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i], - 0, PAGE_SIZE, DMA_TO_DEVICE); + unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE, + DMA_FROM_DEVICE); + dest_dma = unmap->addr[src_count]; + unmap->from_cnt = 1; + unmap->len = PAGE_SIZE; tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs, - MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0); + src_count, PAGE_SIZE, 0); cookie = mv_xor_tx_submit(tx); mv_xor_issue_pending(dma_chan); @@ -942,9 +970,10 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) } free_resources: + dmaengine_unmap_put(unmap); mv_xor_free_chan_resources(dma_chan); out: - src_idx = MV_XOR_NUM_SRC_TEST; + src_idx = src_count; while (src_idx--) __free_page(xor_srcs[src_idx]); __free_page(dest); -- cgit v1.2.3 From 0be8253fa2b4385e6246387db1d6067366e987ba Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Dec 2013 23:59:08 +0000 Subject: dmaengine: mv_xor: fix oops when channels fail to initialise When a channel fails to initialise, we error out and clean up any previously unregistered channels by walking the entire xordev->channels array. Unfortunately, there are paths which end up storing an error pointer in this array, which we then try and dereference in the cleanup code, which causes an oops. Fix this by avoiding writing invalid pointers to this array in the first place. Tested-by: Aaro Koskinen Signed-off-by: Russell King Signed-off-by: Dan Williams --- drivers/dma/mv_xor.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 79620887d637..53fb0c8365b0 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -1199,6 +1199,7 @@ static int mv_xor_probe(struct platform_device *pdev) int i = 0; for_each_child_of_node(pdev->dev.of_node, np) { + struct mv_xor_chan *chan; dma_cap_mask_t cap_mask; int irq; @@ -1216,21 +1217,21 @@ static int mv_xor_probe(struct platform_device *pdev) goto err_channel_add; } - xordev->channels[i] = - mv_xor_channel_add(xordev, pdev, i, - cap_mask, irq); - if (IS_ERR(xordev->channels[i])) { - ret = PTR_ERR(xordev->channels[i]); - xordev->channels[i] = NULL; + chan = mv_xor_channel_add(xordev, pdev, i, + cap_mask, irq); + if (IS_ERR(chan)) { + ret = PTR_ERR(chan); irq_dispose_mapping(irq); goto err_channel_add; } + xordev->channels[i] = chan; i++; } } else if (pdata && pdata->channels) { for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) { struct mv_xor_channel_data *cd; + struct mv_xor_chan *chan; int irq; cd = &pdata->channels[i]; @@ -1245,13 +1246,14 @@ static int mv_xor_probe(struct platform_device *pdev) goto err_channel_add; } - xordev->channels[i] = - mv_xor_channel_add(xordev, pdev, i, - cd->cap_mask, irq); - if (IS_ERR(xordev->channels[i])) { - ret = PTR_ERR(xordev->channels[i]); + chan = mv_xor_channel_add(xordev, pdev, i, + cd->cap_mask, irq); + if (IS_ERR(chan)) { + ret = PTR_ERR(chan); goto err_channel_add; } + + xordev->channels[i] = chan; } } -- cgit v1.2.3 From 8194ee27764b1a86fa7a6b0d411f0a225a6abd5f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 13 Dec 2013 00:57:03 -0800 Subject: dmaengine: fix sleep in atomic BUG: sleeping function called from invalid context at mm/mempool.c:203 in_atomic(): 1, irqs_disabled(): 0, pid: 43502, name: linbug no locks held by linbug/43502. CPU: 7 PID: 43502 Comm: linbug Not tainted 3.13.0-rc1+ #15 Hardware name: 0000000000000010 ffff88005ebd1878 ffffffff8172d512 ffff8801752bc1c0 ffff8801752bc1c0 ffff88005ebd1898 ffffffff8109d1f6 ffff88005f9a3c58 ffff880177f0f080 ffff88005ebd1918 ffffffff81161f43 ffff88005ebd18f8 Call Trace: [] dump_stack+0x4e/0x68 [] __might_sleep+0xe6/0x120 [] mempool_alloc+0x93/0x170 [] ? mark_held_locks+0x74/0x140 [] ? follow_page_mask+0x556/0x600 [] dmaengine_get_unmap_data+0x2e/0x60 [] dma_async_memcpy_pg_to_pg+0x41/0x1c0 [] dma_async_memcpy_buf_to_pg+0x50/0x60 [] dma_memcpy_to_iovec+0xfc/0x190 [] dma_skb_copy_datagram_iovec+0x6f/0x2b0 Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index b601024f518c..ef63b9058f3c 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1054,7 +1054,7 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg, dma_cookie_t cookie; unsigned long flags; - unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOIO); + unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOWAIT); if (!unmap) return -ENOMEM; -- cgit v1.2.3 From 4d9b8a8e4657010e3254d2e52e9542c4cedf448d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 7 Dec 2013 14:08:54 +0100 Subject: pinctrl: at91: implement at91_pinconf_dbg_show This allows to get the pin configuration by using debugfs. On my system: # cat /sys/kernel/debug/pinctrl/pinctrl.3/pinconf-pins Signed-off-by: Alexandre Belloni Acked-by: Nicolas Ferre Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index b0b78f3468ae..bcfc8a2eebca 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -784,10 +784,35 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, return 0; } +#define DBG_SHOW_FLAG(flag) do { \ + if (config & flag) { \ + if (num_conf) \ + seq_puts(s, "|"); \ + seq_puts(s, #flag); \ + num_conf++; \ + } \ +} while (0) + static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned pin_id) { + unsigned long config; + int ret, val, num_conf = 0; + + ret = at91_pinconf_get(pctldev, pin_id, &config); + + DBG_SHOW_FLAG(MULTI_DRIVE); + DBG_SHOW_FLAG(PULL_UP); + DBG_SHOW_FLAG(PULL_DOWN); + DBG_SHOW_FLAG(DIS_SCHMIT); + DBG_SHOW_FLAG(DEGLITCH); + DBG_SHOW_FLAG(DEBOUNCE); + if (config & DEBOUNCE) { + val = config >> DEBOUNCE_VAL_SHIFT; + seq_printf(s, "(%d)", val); + } + return; } static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, -- cgit v1.2.3 From 97058870e616631a80721e08d5797d7da4b23b0a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 3 Dec 2013 11:30:09 +0200 Subject: drm/i915: Clear out old GT FIFO errors in intel_uncore_early_sanitize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BIOS or someone else might have done something bad and there might be old GT FIFO erros reported in GTFIFODBG. Clear those out in intel_uncore_early_sanitize() to make sure we don't mistake them for our problems. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 8102af9a178d..32527a74dc46 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -332,6 +332,11 @@ void intel_uncore_early_sanitize(struct drm_device *dev) DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size); } + /* clear out old GT FIFO errors */ + if (IS_GEN6(dev) || IS_GEN7(dev)) + __raw_i915_write32(dev_priv, GTFIFODBG, + __raw_i915_read32(dev_priv, GTFIFODBG)); + intel_uncore_forcewake_reset(dev); } -- cgit v1.2.3 From b5728cf766f61e8a08121315a6b6883a0a2c21b9 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Dec 2013 12:14:36 +0100 Subject: pinctrl: pinconf: remove warning: unused variable 'ops' Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 4187fe58794d..8bfa0643e5dc 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -296,7 +296,6 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev, static int pinconf_pins_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; - const struct pinconf_ops *ops = pctldev->desc->confops; unsigned i, pin; seq_puts(s, "Pin config settings per pin\n"); @@ -343,7 +342,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - const struct pinconf_ops *ops = pctldev->desc->confops; unsigned ngroups = pctlops->get_groups_count(pctldev); unsigned selector = 0; -- cgit v1.2.3 From 954bb3da814e794f546f55449c508299a127fef8 Mon Sep 17 00:00:00 2001 From: Emanuel Krenz Date: Fri, 13 Dec 2013 14:51:53 +0100 Subject: HID: add support for SiS multitouch panel in the touch monitor LG 23ET83V [jkosina@suse.cz: refresh to apply after SIS quirk merging] Signed-off-by: Emanuel Krenz Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 4 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 36cb475b1934..48296c02ed01 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1824,6 +1824,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 92b2ddc83516..c1077ba1bde0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -760,6 +760,7 @@ #define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 #define USB_DEVICE_ID_SIS817_TOUCH 0x0817 #define USB_DEVICE_ID_SIS_TS 0x1013 +#define USB_DEVICE_ID_SIS1030_TOUCH 0x1030 #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 9ce8e8b757db..1f0ba5c8e644 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1306,6 +1306,9 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, + USB_DEVICE_ID_SIS1030_TOUCH) }, /* Stantum panels */ { .driver_data = MT_CLS_CONFIDENCE, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index b3c7684e8706..175ec0afb70c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -87,6 +87,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -- cgit v1.2.3 From 350d71b94fc9ed4ba9a349786f928aa5e594adc1 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Mon, 9 Sep 2013 14:01:20 +0200 Subject: irqchip: add DesignWare APB ICTL interrupt controller This adds an irqchip driver and corresponding devicetree binding for the secondary interrupt controllers based on Synopsys DesignWare IP dw_apb_ictl. Signed-off-by: Sebastian Hesselbarth Reviewed-by: Mark Rutland Reviewed-by: Jisheng Zhang Reviewed-by: Thomas Gleixner --- .../interrupt-controller/snps,dw-apb-ictl.txt | 32 +++++ drivers/irqchip/Kconfig | 4 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-dw-apb-ictl.c | 150 +++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt create mode 100644 drivers/irqchip/irq-dw-apb-ictl.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt b/Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt new file mode 100644 index 000000000000..492911744ca3 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/snps,dw-apb-ictl.txt @@ -0,0 +1,32 @@ +Synopsys DesignWare APB interrupt controller (dw_apb_ictl) + +Synopsys DesignWare provides interrupt controller IP for APB known as +dw_apb_ictl. The IP is used as secondary interrupt controller in some SoCs with +APB bus, e.g. Marvell Armada 1500. + +Required properties: +- compatible: shall be "snps,dw-apb-ictl" +- reg: physical base address of the controller and length of memory mapped + region starting with ENABLE_LOW register +- interrupt-controller: identifies the node as an interrupt controller +- #interrupt-cells: number of cells to encode an interrupt-specifier, shall be 1 +- interrupts: interrupt reference to primary interrupt controller +- interrupt-parent: (optional) reference specific primary interrupt controller + +The interrupt sources map to the corresponding bits in the interrupt +registers, i.e. +- 0 maps to bit 0 of low interrupts, +- 1 maps to bit 1 of low interrupts, +- 32 maps to bit 0 of high interrupts, +- 33 maps to bit 1 of high interrupts, +- (optional) fast interrupts start at 64. + +Example: + aic: interrupt-controller@3000 { + compatible = "snps,dw-apb-ictl"; + reg = <0x3000 0xc00>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + }; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 3792a1aa52b8..940638ddc982 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -30,6 +30,10 @@ config ARM_VIC_NR The maximum number of VICs available in the system, for power management. +config DW_APB_ICTL + bool + select IRQ_DOMAIN + config IMGPDC_IRQ bool select GENERIC_IRQ_CHIP diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index c60b9010b152..6427323af4c3 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_MMP) += irq-mmp.o obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o obj-$(CONFIG_ARCH_MXS) += irq-mxs.o obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o +obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o obj-$(CONFIG_METAG) += irq-metag-ext.o obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o diff --git a/drivers/irqchip/irq-dw-apb-ictl.c b/drivers/irqchip/irq-dw-apb-ictl.c new file mode 100644 index 000000000000..31e231e1f566 --- /dev/null +++ b/drivers/irqchip/irq-dw-apb-ictl.c @@ -0,0 +1,150 @@ +/* + * Synopsys DW APB ICTL irqchip driver. + * + * Sebastian Hesselbarth + * + * based on GPL'ed 2.6 kernel sources + * (c) Marvell International Ltd. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + +#include "irqchip.h" + +#define APB_INT_ENABLE_L 0x00 +#define APB_INT_ENABLE_H 0x04 +#define APB_INT_MASK_L 0x08 +#define APB_INT_MASK_H 0x0c +#define APB_INT_FINALSTATUS_L 0x30 +#define APB_INT_FINALSTATUS_H 0x34 + +static void dw_apb_ictl_handler(unsigned int irq, struct irq_desc *desc) +{ + struct irq_chip *chip = irq_get_chip(irq); + struct irq_chip_generic *gc = irq_get_handler_data(irq); + struct irq_domain *d = gc->private; + u32 stat; + int n; + + chained_irq_enter(chip, desc); + + for (n = 0; n < gc->num_ct; n++) { + stat = readl_relaxed(gc->reg_base + + APB_INT_FINALSTATUS_L + 4 * n); + while (stat) { + u32 hwirq = ffs(stat) - 1; + generic_handle_irq(irq_find_mapping(d, + gc->irq_base + hwirq + 32 * n)); + stat &= ~(1 << hwirq); + } + } + + chained_irq_exit(chip, desc); +} + +static int __init dw_apb_ictl_init(struct device_node *np, + struct device_node *parent) +{ + unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; + struct resource r; + struct irq_domain *domain; + struct irq_chip_generic *gc; + void __iomem *iobase; + int ret, nrirqs, irq; + u32 reg; + + /* Map the parent interrupt for the chained handler */ + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) { + pr_err("%s: unable to parse irq\n", np->full_name); + return -EINVAL; + } + + ret = of_address_to_resource(np, 0, &r); + if (ret) { + pr_err("%s: unable to get resource\n", np->full_name); + return ret; + } + + if (!request_mem_region(r.start, resource_size(&r), np->full_name)) { + pr_err("%s: unable to request mem region\n", np->full_name); + return -ENOMEM; + } + + iobase = ioremap(r.start, resource_size(&r)); + if (!iobase) { + pr_err("%s: unable to map resource\n", np->full_name); + ret = -ENOMEM; + goto err_release; + } + + /* + * DW IP can be configured to allow 2-64 irqs. We can determine + * the number of irqs supported by writing into enable register + * and look for bits not set, as corresponding flip-flops will + * have been removed by sythesis tool. + */ + + /* mask and enable all interrupts */ + writel(~0, iobase + APB_INT_MASK_L); + writel(~0, iobase + APB_INT_MASK_H); + writel(~0, iobase + APB_INT_ENABLE_L); + writel(~0, iobase + APB_INT_ENABLE_H); + + reg = readl(iobase + APB_INT_ENABLE_H); + if (reg) + nrirqs = 32 + fls(reg); + else + nrirqs = fls(readl(iobase + APB_INT_ENABLE_L)); + + domain = irq_domain_add_linear(np, nrirqs, + &irq_generic_chip_ops, NULL); + if (!domain) { + pr_err("%s: unable to add irq domain\n", np->full_name); + ret = -ENOMEM; + goto err_unmap; + } + + ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1, + np->name, handle_level_irq, clr, 0, + IRQ_GC_INIT_MASK_CACHE); + if (ret) { + pr_err("%s: unable to alloc irq domain gc\n", np->full_name); + goto err_unmap; + } + + gc = irq_get_domain_generic_chip(domain, 0); + gc->private = domain; + gc->reg_base = iobase; + + gc->chip_types[0].regs.mask = APB_INT_MASK_L; + gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; + gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; + + if (nrirqs > 32) { + gc->chip_types[1].regs.mask = APB_INT_MASK_H; + gc->chip_types[1].chip.irq_mask = irq_gc_mask_set_bit; + gc->chip_types[1].chip.irq_unmask = irq_gc_mask_clr_bit; + } + + irq_set_handler_data(irq, gc); + irq_set_chained_handler(irq, dw_apb_ictl_handler); + + return 0; + +err_unmap: + iounmap(iobase); +err_release: + release_mem_region(r.start, resource_size(&r)); + return ret; +} +IRQCHIP_DECLARE(dw_apb_ictl, + "snps,dw-apb-ictl", dw_apb_ictl_init); -- cgit v1.2.3 From 6f825b73e249a2b46f0349d1f86adfbb3ea703e0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Nov 2013 20:07:17 +0100 Subject: PCI/portdrv: Remove superfluous name cast device_driver.name is "const char *" Signed-off-by: Geert Uytterhoeven Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/portdrv_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 0b6e76604068..ce9d9ae17bfd 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -554,7 +554,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new) if (pcie_ports_disabled) return -ENODEV; - new->driver.name = (char *)new->name; + new->driver.name = new->name; new->driver.bus = &pcie_port_bus_type; new->driver.probe = pcie_port_probe_service; new->driver.remove = pcie_port_remove_service; -- cgit v1.2.3 From ac8344c4c0bf74c7efaf962cf2a6404331678ce4 Mon Sep 17 00:00:00 2001 From: DuanZhenzhong Date: Wed, 4 Dec 2013 13:09:16 +0800 Subject: PCI: Drop "irq" param from *_restore_msi_irqs() Change x86_msi.restore_msi_irqs(struct pci_dev *dev, int irq) to x86_msi.restore_msi_irqs(struct pci_dev *dev). restore_msi_irqs() restores multiple MSI-X IRQs, so param 'int irq' is unneeded. This makes code more consistent between vm and bare metal. Dom0 MSI-X restore code can also be optimized as XEN only has a hypercall to restore all MSI-X vectors at one time. Tested-by: Sucheta Chakraborty Signed-off-by: Zhenzhong Duan Signed-off-by: Bjorn Helgaas Acked-by: Konrad Rzeszutek Wilk --- arch/x86/include/asm/pci.h | 2 +- arch/x86/include/asm/x86_init.h | 2 +- arch/x86/kernel/x86_init.c | 4 ++-- arch/x86/pci/xen.c | 2 +- drivers/pci/msi.c | 19 ++++++++++++++----- include/linux/msi.h | 4 ++-- 6 files changed, 21 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 947b5c417e83..0de52c5bf9a2 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -104,7 +104,7 @@ extern void pci_iommu_alloc(void); struct msi_desc; int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); void native_teardown_msi_irq(unsigned int irq); -void native_restore_msi_irqs(struct pci_dev *dev, int irq); +void native_restore_msi_irqs(struct pci_dev *dev); int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, unsigned int irq_base, unsigned int irq_offset); #else diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 0f1be11e43d2..e45e4da96bf1 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -181,7 +181,7 @@ struct x86_msi_ops { u8 hpet_id); void (*teardown_msi_irq)(unsigned int irq); void (*teardown_msi_irqs)(struct pci_dev *dev); - void (*restore_msi_irqs)(struct pci_dev *dev, int irq); + void (*restore_msi_irqs)(struct pci_dev *dev); int (*setup_hpet_msi)(unsigned int irq, unsigned int id); u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag); u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag); diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 021783b1f46a..e48b674639cc 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -136,9 +136,9 @@ void arch_teardown_msi_irq(unsigned int irq) x86_msi.teardown_msi_irq(irq); } -void arch_restore_msi_irqs(struct pci_dev *dev, int irq) +void arch_restore_msi_irqs(struct pci_dev *dev) { - x86_msi.restore_msi_irqs(dev, irq); + x86_msi.restore_msi_irqs(dev); } u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) { diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 5eee4959785d..103e702ec5a7 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -337,7 +337,7 @@ out: return ret; } -static void xen_initdom_restore_msi_irqs(struct pci_dev *dev, int irq) +static void xen_initdom_restore_msi_irqs(struct pci_dev *dev) { int ret = 0; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 3fcd67a16677..51bf0400a889 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -116,7 +116,7 @@ void __weak arch_teardown_msi_irqs(struct pci_dev *dev) return default_teardown_msi_irqs(dev); } -void default_restore_msi_irqs(struct pci_dev *dev, int irq) +static void default_restore_msi_irq(struct pci_dev *dev, int irq) { struct msi_desc *entry; @@ -134,9 +134,9 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq) write_msi_msg(irq, &entry->msg); } -void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq) +void __weak arch_restore_msi_irqs(struct pci_dev *dev) { - return default_restore_msi_irqs(dev, irq); + return default_restore_msi_irqs(dev); } static void msi_set_enable(struct pci_dev *dev, int enable) @@ -262,6 +262,15 @@ void unmask_msi_irq(struct irq_data *data) msi_set_mask_bit(data, 0); } +void default_restore_msi_irqs(struct pci_dev *dev) +{ + struct msi_desc *entry; + + list_for_each_entry(entry, &dev->msi_list, list) { + default_restore_msi_irq(dev, entry->irq); + } +} + void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) { BUG_ON(entry->dev->current_state != PCI_D0); @@ -430,7 +439,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev) pci_intx_for_msi(dev, 0); msi_set_enable(dev, 0); - arch_restore_msi_irqs(dev, dev->irq); + arch_restore_msi_irqs(dev); pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); msi_mask_irq(entry, msi_capable_mask(control), entry->masked); @@ -455,8 +464,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev) control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL; pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); + arch_restore_msi_irqs(dev); list_for_each_entry(entry, &dev->msi_list, list) { - arch_restore_msi_irqs(dev, entry->irq); msix_mask_irq(entry, entry->masked); } diff --git a/include/linux/msi.h b/include/linux/msi.h index 009b02481436..92a2f991262a 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -60,10 +60,10 @@ void arch_teardown_msi_irq(unsigned int irq); int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); void arch_teardown_msi_irqs(struct pci_dev *dev); int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); -void arch_restore_msi_irqs(struct pci_dev *dev, int irq); +void arch_restore_msi_irqs(struct pci_dev *dev); void default_teardown_msi_irqs(struct pci_dev *dev); -void default_restore_msi_irqs(struct pci_dev *dev, int irq); +void default_restore_msi_irqs(struct pci_dev *dev); u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag); u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag); -- cgit v1.2.3 From d2f54d9b3ee32bc006a7ff25d716b32feba4b522 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 27 Nov 2013 15:31:07 -0700 Subject: PCI: Prevent bus conflicts while checking for bridge apertures pci_bridge_check_ranges() determines whether the bridge supports an I/O aperture and a prefetchable memory aperture. Previously, if the I/O aperture was unsupported, disabled, or configured at [io 0x0000-0x0fff], we wrote 0xf0 to PCI_IO_BASE and PCI_IO_LIMIT, which, if the bridge supports it, enables the I/O aperture at [io 0xf000-0xffff]. The enabled aperture may conflict with other devices in the system. Similarly, we wrote 0xfff0 to PCI_PREF_MEMORY_BASE and PCI_PREF_MEMORY_LIMIT, which enables the prefetchable memory aperture at [mem 0xfff00000-0xffffffff], and that may also conflict with other devices. All we need to know is whether the base and limit registers are writable, so we can use values that leave the apertures disabled, e.g., PCI_IO_BASE = 0xf0, PCI_IO_LIMIT = 0xe0, PCI_PREF_MEMORY_BASE = 0xfff0, PCI_PREF_MEMORY_LIMIT = 0xffe0. Writing non-zero values to both the base and limit registers means we detect whether either or both are writable, as we did before. Reported-by: Jason Gunthorpe Based-on-patch-by: Jason Gunthorpe Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 219a4106480a..80350299a6ea 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -665,21 +665,23 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) pci_read_config_word(bridge, PCI_IO_BASE, &io); if (!io) { - pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); + pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0); pci_read_config_word(bridge, PCI_IO_BASE, &io); pci_write_config_word(bridge, PCI_IO_BASE, 0x0); } if (io) b_res[0].flags |= IORESOURCE_IO; + /* DECchip 21050 pass 2 errata: the bridge may miss an address disconnect boundary by one PCI data phase. Workaround: do not use prefetching on this device. */ if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001) return; + pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); if (!pmem) { pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, - 0xfff0fff0); + 0xffe0fff0); pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); } -- cgit v1.2.3 From 5b764b834ea925b7fc87df4a87a0fde95acbecb9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 27 Nov 2013 17:24:50 -0700 Subject: PCI: Stop clearing bridge Secondary Status when setting up I/O aperture pci_setup_bridge_io() accessed PCI_IO_BASE and PCI_IO_LIMIT using dword (32-bit) reads and writes, which also access the Secondary Status register. Since the Secondary Status register is in the upper 16 bits of the dword, and we preserved those upper 16 bits, this had the effect of clearing any of the write-1-to-clear bits that happened to be set in the Secondary Status register. That's not what we want, so use word (16-bit) accesses to update only PCI_IO_BASE and PCI_IO_LIMIT. Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 80350299a6ea..2e344a5581ae 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -538,7 +538,8 @@ static void pci_setup_bridge_io(struct pci_bus *bus) struct pci_bus_region region; unsigned long io_mask; u8 io_base_lo, io_limit_lo; - u32 l, io_upper16; + u16 l; + u32 io_upper16; io_mask = PCI_IO_RANGE_MASK; if (bridge->io_window_1k) @@ -548,11 +549,10 @@ static void pci_setup_bridge_io(struct pci_bus *bus) res = bus->resource[0]; pcibios_resource_to_bus(bridge, ®ion, res); if (res->flags & IORESOURCE_IO) { - pci_read_config_dword(bridge, PCI_IO_BASE, &l); - l &= 0xffff0000; + pci_read_config_word(bridge, PCI_IO_BASE, &l); io_base_lo = (region.start >> 8) & io_mask; io_limit_lo = (region.end >> 8) & io_mask; - l |= ((u32) io_limit_lo << 8) | io_base_lo; + l = ((u16) io_limit_lo << 8) | io_base_lo; /* Set up upper 16 bits of I/O base/limit. */ io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); dev_info(&bridge->dev, " bridge window %pR\n", res); @@ -564,7 +564,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus) /* Temporarily disable the I/O range before updating PCI_IO_BASE. */ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); /* Update lower 16 bits of I/O base/limit. */ - pci_write_config_dword(bridge, PCI_IO_BASE, l); + pci_write_config_word(bridge, PCI_IO_BASE, l); /* Update upper 16 bits of I/O base/limit. */ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); } -- cgit v1.2.3 From c1d15f5c8bc1170dafe16e988e55437245966dfe Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 11 Dec 2013 16:58:42 +0000 Subject: xen/balloon: Seperate the auto-translate logic properly (v2) The auto-xlat logic vs the non-xlat means that we don't need to for auto-xlat guests (like PVH, HVM or ARM): - use P2M - use scratch page. However the code in increase_reservation does modify the p2m for auto_translate guests, but not in decrease_reservation. Fix that by avoiding any p2m modifications in both increase_reservation and decrease_reservation for auto_translated guests. And also avoid allocating or using scratch pages for auto_translated guests. Lastly, since !auto-xlat is really another way of saying 'xen_pv' remove the redundant 'xen_pv_domain' check. Signed-off-by: Stefano Stabellini [v2: Updated the description] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/balloon.c | 63 +++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 55ea73f7c70b..4c02e2b94103 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -350,17 +350,19 @@ static enum bp_state increase_reservation(unsigned long nr_pages) pfn = page_to_pfn(page); - set_phys_to_machine(pfn, frame_list[i]); - #ifdef CONFIG_XEN_HAVE_PVMMU - /* Link back into the page tables if not highmem. */ - if (xen_pv_domain() && !PageHighMem(page)) { - int ret; - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - mfn_pte(frame_list[i], PAGE_KERNEL), - 0); - BUG_ON(ret); + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + set_phys_to_machine(pfn, frame_list[i]); + + /* Link back into the page tables if not highmem. */ + if (!PageHighMem(page)) { + int ret; + ret = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + mfn_pte(frame_list[i], PAGE_KERNEL), + 0); + BUG_ON(ret); + } } #endif @@ -378,7 +380,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) enum bp_state state = BP_DONE; unsigned long pfn, i; struct page *page; - struct page *scratch_page; int ret; struct xen_memory_reservation reservation = { .address_bits = 0, @@ -411,27 +412,29 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) scrub_page(page); +#ifdef CONFIG_XEN_HAVE_PVMMU /* * Ballooned out frames are effectively replaced with * a scratch frame. Ensure direct mappings and the * p2m are consistent. */ - scratch_page = get_balloon_scratch_page(); -#ifdef CONFIG_XEN_HAVE_PVMMU - if (xen_pv_domain() && !PageHighMem(page)) { - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - pfn_pte(page_to_pfn(scratch_page), - PAGE_KERNEL_RO), 0); - BUG_ON(ret); - } -#endif if (!xen_feature(XENFEAT_auto_translated_physmap)) { unsigned long p; + struct page *scratch_page = get_balloon_scratch_page(); + + if (!PageHighMem(page)) { + ret = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + pfn_pte(page_to_pfn(scratch_page), + PAGE_KERNEL_RO), 0); + BUG_ON(ret); + } p = page_to_pfn(scratch_page); __set_phys_to_machine(pfn, pfn_to_mfn(p)); + + put_balloon_scratch_page(); } - put_balloon_scratch_page(); +#endif balloon_append(pfn_to_page(pfn)); } @@ -627,15 +630,17 @@ static int __init balloon_init(void) if (!xen_domain()) return -ENODEV; - for_each_online_cpu(cpu) - { - per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL); - if (per_cpu(balloon_scratch_page, cpu) == NULL) { - pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu); - return -ENOMEM; + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + for_each_online_cpu(cpu) + { + per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL); + if (per_cpu(balloon_scratch_page, cpu) == NULL) { + pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu); + return -ENOMEM; + } } + register_cpu_notifier(&balloon_cpu_notifier); } - register_cpu_notifier(&balloon_cpu_notifier); pr_info("Initialising balloon driver\n"); -- cgit v1.2.3 From a6f089e95b1e08cdea9633d50ad20aa5d44ba64d Mon Sep 17 00:00:00 2001 From: Lior Amsalem Date: Mon, 25 Nov 2013 17:26:44 +0100 Subject: irqchip: armada-370-xp: fix IPI race condition In the Armada 370/XP driver, when we receive an IRQ 0, we read the list of doorbells that caused the interrupt from register ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS. This gives the list of IPIs that were generated. However, instead of acknowledging only the IPIs that were generated, we acknowledge *all* the IPIs, by writing ~IPI_DOORBELL_MASK in the ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS register. This creates a race condition: if a new IPI that isn't part of the ones read into the temporary "ipimask" variable is fired before we acknowledge all IPIs, then we will simply loose it. This is causing scheduling hangs on SMP intensive workloads. It is important to mention that this ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS register has the following behavior: "A CPU write of 0 clears the bits in this field. A CPU write of 1 has no effect". This is what allows us to simply write ~ipimask to acknoledge the handled IPIs. Notice that the same problem is present in the MSI implementation, but it will be fixed as a separate patch, so that this IPI fix can be pushed to older stable versions as appropriate (all the way to 3.8), while the MSI code only appeared in 3.13. Signed-off-by: Lior Amsalem Signed-off-by: Thomas Petazzoni Cc: stable@vger.kernel.org # v3.8+ Fixes: 344e873e5657e8dc0 'arm: mvebu: Add IPI support via doorbells' Cc: Thomas Gleixner Signed-off-by: Jason Cooper --- drivers/irqchip/irq-armada-370-xp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 433cc8568dec..f5e49a2d8e5a 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -407,7 +407,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) & IPI_DOORBELL_MASK; - writel(~IPI_DOORBELL_MASK, per_cpu_int_base + + writel(~ipimask, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); /* Handle all pending doorbells */ -- cgit v1.2.3 From c7f7bd4a136e4b02dd2a66bf95aec545bd93e8db Mon Sep 17 00:00:00 2001 From: Lior Amsalem Date: Mon, 25 Nov 2013 17:26:45 +0100 Subject: irqchip: armada-370-xp: fix MSI race condition In the Armada 370/XP driver, when we receive an IRQ 1, we read the list of doorbells that caused the interrupt from register ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS. This gives the list of MSIs that were generated. However, instead of acknowledging only the MSIs that were generated, we acknowledge *all* the MSIs, by writing ~MSI_DOORBELL_MASK in the ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS register. This creates a race condition: if a new MSI that isn't part of the ones read into the temporary "msimask" variable is fired before we acknowledge all MSIs, then we will simply loose it. It is important to mention that this ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS register has the following behavior: "A CPU write of 0 clears the bits in this field. A CPU write of 1 has no effect". This is what allows us to simply write ~msimask to acknoledge the handled MSIs. Notice that the same problem is present in the IPI implementation, but it is fixed as a separate patch, so that this IPI fix can be pushed to older stable versions as appropriate (all the way to 3.8), while the MSI code only appeared in 3.13. Signed-off-by: Lior Amsalem Signed-off-by: Thomas Petazzoni Cc: Thomas Gleixner Signed-off-by: Jason Cooper --- drivers/irqchip/irq-armada-370-xp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index f5e49a2d8e5a..3fac063b4a78 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -381,7 +381,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) & PCI_MSI_DOORBELL_MASK; - writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base + + writel(~msimask, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); for (msinr = PCI_MSI_DOORBELL_START; -- cgit v1.2.3 From 047ef2fa4e687b6c0d4e7d47b8a184147151482c Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Mon, 23 Sep 2013 10:20:34 -0700 Subject: rename ARCH_BCM to ARCH_BCM_MOBILE (clocksource) Currently ARCH_BCM has been used for Broadcom Mobile V7 based SoCs. In order to allow other Broadcom SoCs to also use mach-bcm directory and files, this patch renames the original ARCH_BCM to ARCH_BCM_MOBILE, and uses ARCH_BCM to define any Broadcom chip residing in mach-bcm directory. Signed-off-by: Christian Daudt Acked-by: Olof Johansson Acked-by: Daniel Lezcano --- drivers/clocksource/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 33621efb9148..1f42e8f0d7c2 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o -obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o +obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o -- cgit v1.2.3 From a3564d2b5236b73bceb271f482965d38cd9d8d8e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2013 13:26:20 +0200 Subject: drm/i915/bdw: Don't use forcewake needlessly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all registers need forcewake even if they're not shadowed. Add the missing check to gen8_writeX() to avoid needless forcewake usage when writing eg. display registers. v2: Use straight up <0x40000 check instead of NEEDS_FORCE_WAKE() Reviewed-by: Ben Widawsky Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 32527a74dc46..2c8143c37de3 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -634,7 +634,7 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg) #define __gen8_write(x) \ static void \ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \ + bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \ REG_WRITE_HEADER; \ if (__needs_put) { \ dev_priv->uncore.funcs.force_wake_get(dev_priv, \ -- cgit v1.2.3 From 63801f211c6eeb6def635ceee39d165e00fd6e09 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 12 Dec 2013 17:26:03 -0800 Subject: drm/i915/bdw: Force all Data Cache Data Port access to be Non-Coherent I stumbled on to some unimplemented errata. To be honest, I am not really sure of the impact, just that the docs say to do. No w/a name for this one. v2: v1 was a stale thing which should have never seen the light of day. (Haihao) Cc: Kenneth Graunke Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e8cc27cd9494..3259e83eb2c6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4167,6 +4167,10 @@ #define GEN7_L3SQCREG4 0xb034 #define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27) +/* GEN8 chicken */ +#define HDC_CHICKEN0 0x7300 +#define HDC_FORCE_NON_COHERENT (1<<4) + /* WaCatErrorRejectionIssue */ #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030 #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c68abf718825..791fbe386b7c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5269,6 +5269,14 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_READ(CHICKEN_PIPESL_1(i) | DPRS_MASK_VBLANK_SRD)); } + + /* Use Force Non-Coherent whenever executing a 3D context. This is a + * workaround for for a possible hang in the unlikely event a TLB + * invalidation occurs during a PSD flush. + */ + I915_WRITE(HDC_CHICKEN0, + I915_READ(HDC_CHICKEN0) | + _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT)); } static void haswell_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3 From ab57fff1302c485d74992d34df24ccb5efda244e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 12 Dec 2013 15:28:04 -0800 Subject: drm/i915/bdw: Implement ff workarounds WaVSRefCountFullforceMissDisable and WaDSRefCountFullforceMissDisable VS is a carry-over from HSW, and DS is likely not used by anyone yet. Cc: Kenneth Graunke Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau [danvet: Line of 106 chars is too long. Really.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3259e83eb2c6..f1eece4a63d5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1003,6 +1003,7 @@ #define GEN7_FF_THREAD_MODE 0x20a0 #define GEN7_FF_SCHED_MASK 0x0077070 +#define GEN8_FF_DS_REF_CNT_FFME (1 << 19) #define GEN7_FF_TS_SCHED_HS1 (0x5<<16) #define GEN7_FF_TS_SCHED_HS0 (0x3<<16) #define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 791fbe386b7c..b35f65ed6c5e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5256,14 +5256,14 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE)); - /* WaSwitchSolVfFArbitrationPriority */ + /* WaSwitchSolVfFArbitrationPriority:bdw */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); - /* WaPsrDPAMaskVBlankInSRD */ + /* WaPsrDPAMaskVBlankInSRD:bdw */ I915_WRITE(CHICKEN_PAR1_1, I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD); - /* WaPsrDPRSUnmaskVBlankInSRD */ + /* WaPsrDPRSUnmaskVBlankInSRD:bdw */ for_each_pipe(i) { I915_WRITE(CHICKEN_PIPESL_1(i), I915_READ(CHICKEN_PIPESL_1(i) | @@ -5277,6 +5277,12 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_WRITE(HDC_CHICKEN0, I915_READ(HDC_CHICKEN0) | _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT)); + + /* WaVSRefCountFullforceMissDisable:bdw */ + /* WaDSRefCountFullforceMissDisable:bdw */ + I915_WRITE(GEN7_FF_THREAD_MODE, + I915_READ(GEN7_FF_THREAD_MODE) & + ~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME)); } static void haswell_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3 From 96b4026878d9dac71bd4c3d6e05c7fbb16a3e0aa Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 6 Dec 2013 20:29:01 -0200 Subject: drm/i915: change CRTC assertion on LCPLL disable Currently, PC8 is enabled at modeset_global_resources, which is called after intel_modeset_update_state. Due to this, there's a small race condition on the case where we start enabling PC8, then do a modeset while PC8 is still being enabled. The racing condition triggers a WARN because intel_modeset_update_state will mark the CRTC as enabled, then the thread that's still enabling PC8 might look at the data structure and think that PC8 is being enabled while a pipe is enabled. Despite the WARN, this is not really a bug since we'll wait for the PC8-enabling thread to finish when we call modeset_global_resources. The spec says the CRTC cannot be enabled when we disable LCPLL, so we had a check for crtc->base.enabled. If we change to crtc->active we will still prevent disabling LCPLL while the CRTC is enabled, and we will also prevent the WARN above. This is a replacement for the previous patch named "drm/i915: get/put PC8 when we get/put a CRTC" Testcase: igt/pm_pc8/modeset-lpsp-stress-no-wait Signed-off-by: Paulo Zanoni (cherry picked from commit 798183c54799fbe1e5a5bfabb3a8c0505ffd2149 from -next due to Dave's report.) Reported-by: Dave Jones Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8b8bde7dce53..4049a65a9f8c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6303,7 +6303,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) uint32_t val; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) - WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n", + WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); -- cgit v1.2.3 From 04df008afe0c569fd09400a35b7d3db29067114c Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Fri, 13 Dec 2013 19:39:54 +0100 Subject: EISA: Call put_device() if device_register() fails We need to give up the last reference to edev->dev, so we need to call put_device(). Signed-off-by: Levente Kurusa Signed-off-by: Bjorn Helgaas --- drivers/eisa/eisa-bus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 272a3ec35957..8842cde69177 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -232,8 +232,10 @@ static int __init eisa_init_device(struct eisa_root_device *root, static int __init eisa_register_device(struct eisa_device *edev) { int rc = device_register(&edev->dev); - if (rc) + if (rc) { + put_device(&edev->dev); return rc; + } rc = device_create_file(&edev->dev, &dev_attr_signature); if (rc) -- cgit v1.2.3 From 4e6a1ee72b74ce013f0b31063915a58ba7db2f88 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Dec 2013 12:42:48 +0100 Subject: xhci: Add quirks module option It makes easier for debugging some hardware specific issues. Note that this option won't override the value to be set. That is, you can turn quirks on by this option but cannot turn them off if set by the driver. Signed-off-by: Takashi Iwai Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d68ec1aa473d..6bc966cfb60e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -40,6 +40,10 @@ static int link_quirk; module_param(link_quirk, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); +static unsigned int quirks; +module_param(quirks, uint, S_IRUGO); +MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); + /* TODO: copied from ehci-hcd.c - can this be refactored? */ /* * xhci_handshake - spin reading hc until handshake completes or fails @@ -4770,6 +4774,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci->hcc_params = readl(&xhci->cap_regs->hcc_params); xhci_print_registers(xhci); + xhci->quirks = quirks; + get_quirks(dev, xhci); /* In xhci controllers which follow xhci 1.0 spec gives a spurious -- cgit v1.2.3 From be3d26b0588ca5f4db6b50d13e92afb0ac57d6ab Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 13 Dec 2013 17:46:38 -0200 Subject: drm/i915: get a PC8 reference when enabling the power well In the current code, at haswell_modeset_global_resources, first we decide if we want to enable/disable the power well, then we decide if we want to enable/disable PC8. On the case where we're enabling PC8 this works fine, but on the case where we disable PC8 due to a non-eDP monitor being enabled, we first enable the power well and then disable PC8. Although wrong, this doesn't seem to be causing any problems now, and we don't even see anything in dmesg. But the patches for runtime D3 turn this problem into a real bug, so we need to fix it. This fixes the "modeset-non-lpsp" subtest from the "pm_pc8" test from intel-gpu-tools. v2: - Rebase (i915_disable_power_well). v3: - More reabase. v4: - Rebase on top of -fixes instead of -nightly. This is commit d62292c8f778772d1b6ec125d461c8c16fdc0417 in -next, but we need it in -fixes to address Dave's report. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Reported-by: Dave Jones Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3657ab43c8fd..26c29c173221 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5688,6 +5688,8 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) unsigned long irqflags; uint32_t tmp; + WARN_ON(dev_priv->pc8.enabled); + tmp = I915_READ(HSW_PWR_WELL_DRIVER); is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED; enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST; @@ -5747,16 +5749,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) static void __intel_power_well_get(struct drm_device *dev, struct i915_power_well *power_well) { - if (!power_well->count++) + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!power_well->count++) { + hsw_disable_package_c8(dev_priv); __intel_set_power_well(dev, true); + } } static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { + struct drm_i915_private *dev_priv = dev->dev_private; + WARN_ON(!power_well->count); - if (!--power_well->count && i915_disable_power_well) + if (!--power_well->count && i915_disable_power_well) { __intel_set_power_well(dev, false); + hsw_enable_package_c8(dev_priv); + } } void intel_display_power_get(struct drm_device *dev, -- cgit v1.2.3 From fab4c256a58bcd6877bca5b6afc97afa3b6664ac Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 13 Dec 2013 14:39:56 -0700 Subject: PCI/AER: Add a TLP header print helper ... and call it instead of duplicating the large printk format statement. No functionality change. Signed-off-by: Borislav Petkov Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aerdrv_errprint.c | 44 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 2c7c9f5f592c..32efc5e0d2eb 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -124,6 +124,21 @@ static const char *aer_agent_string[] = { "Transmitter ID" }; +static void __print_tlp_header(struct pci_dev *dev, + struct aer_header_log_regs *t) +{ + unsigned char *tlp = (unsigned char *)&t; + + dev_err(&dev->dev, " TLP Header:" + " %02x%02x%02x%02x %02x%02x%02x%02x" + " %02x%02x%02x%02x %02x%02x%02x%02x\n", + *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, + *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), + *(tlp + 11), *(tlp + 10), *(tlp + 9), + *(tlp + 8), *(tlp + 15), *(tlp + 14), + *(tlp + 13), *(tlp + 12)); +} + static void __aer_print_error(struct pci_dev *dev, struct aer_err_info *info) { @@ -178,17 +193,8 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) __aer_print_error(dev, info); - if (info->tlp_header_valid) { - unsigned char *tlp = (unsigned char *) &info->tlp; - dev_err(&dev->dev, " TLP Header:" - " %02x%02x%02x%02x %02x%02x%02x%02x" - " %02x%02x%02x%02x %02x%02x%02x%02x\n", - *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, - *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), - *(tlp + 11), *(tlp + 10), *(tlp + 9), - *(tlp + 8), *(tlp + 15), *(tlp + 14), - *(tlp + 13), *(tlp + 12)); - } + if (info->tlp_header_valid) + __print_tlp_header(dev, &info->tlp); } if (info->id && info->error_dev_num > 1 && info->id == id) @@ -250,18 +256,10 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity, if (aer_severity != AER_CORRECTABLE) dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", aer->uncor_severity); - if (tlp_header_valid) { - const unsigned char *tlp; - tlp = (const unsigned char *)&aer->header_log; - dev_err(&dev->dev, "aer_tlp_header:" - " %02x%02x%02x%02x %02x%02x%02x%02x" - " %02x%02x%02x%02x %02x%02x%02x%02x\n", - *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, - *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), - *(tlp + 11), *(tlp + 10), *(tlp + 9), - *(tlp + 8), *(tlp + 15), *(tlp + 14), - *(tlp + 13), *(tlp + 12)); - } + + if (tlp_header_valid) + __print_tlp_header(dev, &aer->header_log); + trace_aer_event(dev_name(&dev->dev), (status & ~mask), aer_severity); } -- cgit v1.2.3 From 1c38108a086f1cca3700765607059a6d865910c2 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 13 Dec 2013 14:40:03 -0700 Subject: PCI/AER: Clean up error printing code a bit Save one indentation level in aer_print_error() for the generic case where we have info->status of an error, disregard 80 cols rule a bit for the sake of better readability, fix alignment. No functionality change. Signed-off-by: Borislav Petkov Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aerdrv_errprint.c | 51 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 32efc5e0d2eb..34ff7026440c 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -168,39 +168,39 @@ static void __aer_print_error(struct pci_dev *dev, void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) { + int layer, agent; int id = ((dev->bus->number << 8) | dev->devfn); - if (info->status == 0) { + if (!info->status) { dev_err(&dev->dev, "PCIe Bus Error: severity=%s, type=Unaccessible, " "id=%04x(Unregistered Agent ID)\n", aer_error_severity_string[info->severity], id); - } else { - int layer, agent; + goto out; + } - layer = AER_GET_LAYER_ERROR(info->severity, info->status); - agent = AER_GET_AGENT(info->severity, info->status); + layer = AER_GET_LAYER_ERROR(info->severity, info->status); + agent = AER_GET_AGENT(info->severity, info->status); - dev_err(&dev->dev, - "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", - aer_error_severity_string[info->severity], - aer_error_layer[layer], id, aer_agent_string[agent]); + dev_err(&dev->dev, + "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", + aer_error_severity_string[info->severity], + aer_error_layer[layer], id, aer_agent_string[agent]); - dev_err(&dev->dev, - " device [%04x:%04x] error status/mask=%08x/%08x\n", - dev->vendor, dev->device, - info->status, info->mask); + dev_err(&dev->dev, + " device [%04x:%04x] error status/mask=%08x/%08x\n", + dev->vendor, dev->device, + info->status, info->mask); - __aer_print_error(dev, info); + __aer_print_error(dev, info); - if (info->tlp_header_valid) - __print_tlp_header(dev, &info->tlp); - } + if (info->tlp_header_valid) + __print_tlp_header(dev, &info->tlp); +out: if (info->id && info->error_dev_num > 1 && info->id == id) - dev_err(&dev->dev, - " Error of this Agent(%04x) is reported first\n", - id); + dev_err(&dev->dev, " Error of this Agent(%04x) is reported first\n", id); + trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask), info->severity); } @@ -234,6 +234,7 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity, const char **status_strs; aer_severity = cper_severity_to_aer(cper_severity); + if (aer_severity == AER_CORRECTABLE) { status = aer->cor_status; mask = aer->cor_mask; @@ -246,16 +247,18 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity, status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string); tlp_header_valid = status & AER_LOG_TLP_MASKS; } + layer = AER_GET_LAYER_ERROR(aer_severity, status); agent = AER_GET_AGENT(aer_severity, status); - dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", - status, mask); + + dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask); cper_print_bits("", status, status_strs, status_strs_size); dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", - aer_error_layer[layer], aer_agent_string[agent]); + aer_error_layer[layer], aer_agent_string[agent]); + if (aer_severity != AER_CORRECTABLE) dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", - aer->uncor_severity); + aer->uncor_severity); if (tlp_header_valid) __print_tlp_header(dev, &aer->header_log); -- cgit v1.2.3 From 8e7f8d0b30d4e3e30007b10eb2916d970b5f8c93 Mon Sep 17 00:00:00 2001 From: Betty Dall Date: Fri, 13 Dec 2013 08:23:16 -0700 Subject: PCI/AER: Ignore non-PCIe AER error sources in aer_hest_parse() aer_set_firmware_first() searches the HEST for an error source descriptor matching the specified PCI device. It uses the apei_hest_parse() iterator to call aer_hest_parse() for every descriptor in the HEST. Previously, aer_hest_parse() incorrectly assumed every descriptor was for a PCIe error source. This patch adds a check to avoid that error. [bhelgaas: factor check into helper, use in aer_hest_parse_aff(), changelog] Signed-off-by: Betty Dall Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aerdrv_acpi.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index cf611ab2193a..a23995749f1d 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -50,12 +50,24 @@ struct aer_hest_parse_info { int firmware_first; }; +static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr) +{ + if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT || + hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT || + hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE) + return 1; + return 0; +} + static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) { struct aer_hest_parse_info *info = data; struct acpi_hest_aer_common *p; int ff; + if (!hest_source_is_pcie_aer(hest_hdr)) + return 0; + p = (struct acpi_hest_aer_common *)(hest_hdr + 1); ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); if (p->flags & ACPI_HEST_GLOBAL) { @@ -104,15 +116,12 @@ static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data) if (aer_firmware_first) return 0; - switch (hest_hdr->type) { - case ACPI_HEST_TYPE_AER_ROOT_PORT: - case ACPI_HEST_TYPE_AER_ENDPOINT: - case ACPI_HEST_TYPE_AER_BRIDGE: - p = (struct acpi_hest_aer_common *)(hest_hdr + 1); - aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); - default: + if (!hest_source_is_pcie_aer(hest_hdr)) return 0; - } + + p = (struct acpi_hest_aer_common *)(hest_hdr + 1); + aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); + return 0; } /** -- cgit v1.2.3 From 3620437a73b0ba68bac9c4e8d0fc9b809efca521 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 13 Dec 2013 15:42:53 -0700 Subject: PCI/AER: Consolidate HEST error source parsers aer_hest_parse() and aer_hest_parse_aff() are almost identical. We use aer_hest_parse() to check the ACPI_HEST_FIRMWARE_FIRST flag for a specific device, and we use aer_hest_parse_aff() to check to see if any device sets the flag. This drops aer_hest_parse_aff() and enhances aer_hest_parse() so it collects the union of the PCIe ACPI_HEST_FIRMWARE_FIRST flag settings when no specific device is supplied. No functional change. Signed-off-by: Bjorn Helgaas Reviewed-by: Betty Dall --- drivers/pci/pcie/aer/aerdrv_acpi.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index a23995749f1d..4d6991794fa2 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -70,6 +70,17 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) p = (struct acpi_hest_aer_common *)(hest_hdr + 1); ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); + + /* + * If no specific device is supplied, determine whether + * FIRMWARE_FIRST is set for *any* PCIe device. + */ + if (!info->pci_dev) { + info->firmware_first |= ff; + return 0; + } + + /* Otherwise, check the specific device */ if (p->flags & ACPI_HEST_GLOBAL) { if (hest_match_type(hest_hdr, info->pci_dev)) info->firmware_first = ff; @@ -109,30 +120,20 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev) static bool aer_firmware_first; -static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data) -{ - struct acpi_hest_aer_common *p; - - if (aer_firmware_first) - return 0; - - if (!hest_source_is_pcie_aer(hest_hdr)) - return 0; - - p = (struct acpi_hest_aer_common *)(hest_hdr + 1); - aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); - return 0; -} - /** * aer_acpi_firmware_first - Check if APEI should control AER. */ bool aer_acpi_firmware_first(void) { static bool parsed = false; + struct aer_hest_parse_info info = { + .pci_dev = NULL, /* Check all PCIe devices */ + .firmware_first = 0, + }; if (!parsed) { - apei_hest_parse(aer_hest_parse_aff, NULL); + apei_hest_parse(aer_hest_parse, &info); + aer_firmware_first = info.firmware_first; parsed = true; } return aer_firmware_first; -- cgit v1.2.3 From caec70381b469d6ed1bd3d0441a19aa6de0bbff3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Nov 2013 18:11:45 +0100 Subject: serial: sh-sci: Don't enable/disable port from within break timer The break timer accesses hardware registers and thus requires the port to be enabled. It currently ensures this by enabling the port at the beginning of the timer handler, and disabling it at the end. However, the enable/disable operations call the runtime PM sync functions, which are not allowed in atomic context. The current situation is thus broken. This change relies on non-atomic code to enable/disable the port. The break timer will only be started from the IRQ handler, which already runs with the port enabled. We just need to ensure that the port won't be disabled with the timer running, and that's easily done by just cancelling the timer in the port disable function. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/tty/serial/sh-sci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 6e5ce628b4eb..1ebac3e9e53a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -431,6 +431,14 @@ static void sci_port_disable(struct sci_port *sci_port) if (!sci_port->port.dev) return; + /* Cancel the break timer to ensure that the timer handler will not try + * to access the hardware with clocks and power disabled. Reset the + * break flag to make the break debouncing state machine ready for the + * next break. + */ + del_timer_sync(&sci_port->break_timer); + sci_port->break_flag = 0; + clk_disable(sci_port->fclk); clk_disable(sci_port->iclk); @@ -733,8 +741,6 @@ static void sci_break_timer(unsigned long data) { struct sci_port *port = (struct sci_port *)data; - sci_port_enable(port); - if (sci_rxd_in(&port->port) == 0) { port->break_flag = 1; sci_schedule_break_timer(port); @@ -744,8 +750,6 @@ static void sci_break_timer(unsigned long data) sci_schedule_break_timer(port); } else port->break_flag = 0; - - sci_port_disable(port); } static int sci_handle_errors(struct uart_port *port) -- cgit v1.2.3 From b016b646e8676858f39ea9be760494b04b9ee0af Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Nov 2013 18:11:46 +0100 Subject: serial: sh-sci: Convert to clk_prepare/unprepare Turn clk_enable() and clk_disable() calls into clk_prepare_enable() and clk_disable_unprepare() to get ready for the migration to the common clock framework. Signed-off-by: Laurent Pinchart Acked-by: Magnus Damm Acked-by: Greg Kroah-Hartman Signed-off-by: Simon Horman --- drivers/tty/serial/sh-sci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 1ebac3e9e53a..1a3fc7a2e4db 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -421,9 +421,9 @@ static void sci_port_enable(struct sci_port *sci_port) pm_runtime_get_sync(sci_port->port.dev); - clk_enable(sci_port->iclk); + clk_prepare_enable(sci_port->iclk); sci_port->port.uartclk = clk_get_rate(sci_port->iclk); - clk_enable(sci_port->fclk); + clk_prepare_enable(sci_port->fclk); } static void sci_port_disable(struct sci_port *sci_port) @@ -439,8 +439,8 @@ static void sci_port_disable(struct sci_port *sci_port) del_timer_sync(&sci_port->break_timer); sci_port->break_flag = 0; - clk_disable(sci_port->fclk); - clk_disable(sci_port->iclk); + clk_disable_unprepare(sci_port->fclk); + clk_disable_unprepare(sci_port->iclk); pm_runtime_put_sync(sci_port->port.dev); } -- cgit v1.2.3 From 92ca6a8ce97e07206d474da5477d8da4e41bad6c Mon Sep 17 00:00:00 2001 From: Takashi Yoshii Date: Tue, 8 Oct 2013 14:32:17 +0900 Subject: clk: emev2: Add support for emev2 SMU clocks with DT Device tree clock binding document for EMMA Mobile EV2 SMU, And Common clock framework based implementation of it. Following nodes are defined to describe clock tree. - renesas,emev2-smu - renesas,emev2-smu-clkdiv - renesas,emev2-smu-gclk These bindings are designed manually based on 19UH0037EJ1000_SMU : System Management Unit User's Manual So far, reparent is not implemented, and is fixed to index #0. Clock tree description is not included, and should be provided by device-tree. Signed-off-by: Takashi Yoshii Acked-by: Magnus Damm Signed-off-by: Simon Horman --- .../devicetree/bindings/clock/emev2-clock.txt | 98 +++++++++++++++++++ drivers/clk/shmobile/Makefile | 2 +- drivers/clk/shmobile/clk-emev2.c | 104 +++++++++++++++++++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/clock/emev2-clock.txt create mode 100644 drivers/clk/shmobile/clk-emev2.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/emev2-clock.txt b/Documentation/devicetree/bindings/clock/emev2-clock.txt new file mode 100644 index 000000000000..60bbb1a8c69a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/emev2-clock.txt @@ -0,0 +1,98 @@ +Device tree Clock bindings for Renesas EMMA Mobile EV2 + +This binding uses the common clock binding. + +* SMU +System Management Unit described in user's manual R19UH0037EJ1000_SMU. +This is not a clock provider, but clocks under SMU depend on it. + +Required properties: +- compatible: Should be "renesas,emev2-smu" +- reg: Address and Size of SMU registers + +* SMU_CLKDIV +Function block with an input mux and a divider, which corresponds to +"Serial clock generator" in fig."Clock System Overview" of the manual, +and "xxx frequency division setting register" (XXXCLKDIV) registers. +This makes internal (neither input nor output) clock that is provided +to input of xxxGCLK block. + +Required properties: +- compatible: Should be "renesas,emev2-smu-clkdiv" +- reg: Byte offset from SMU base and Bit position in the register +- clocks: Parent clocks. Input clocks as described in clock-bindings.txt +- #clock-cells: Should be <0> + +* SMU_GCLK +Clock gating node shown as "Clock stop processing block" in the +fig."Clock System Overview" of the manual. +Registers are "xxx clock gate control register" (XXXGCLKCTRL). + +Required properties: +- compatible: Should be "renesas,emev2-smu-gclk" +- reg: Byte offset from SMU base and Bit position in the register +- clocks: Input clock as described in clock-bindings.txt +- #clock-cells: Should be <0> + +Example of provider: + +usia_u0_sclkdiv: usia_u0_sclkdiv { + compatible = "renesas,emev2-smu-clkdiv"; + reg = <0x610 0>; + clocks = <&pll3_fo>, <&pll4_fo>, <&pll1_fo>, <&osc1_fo>; + #clock-cells = <0>; +}; + +usia_u0_sclk: usia_u0_sclk { + compatible = "renesas,emev2-smu-gclk"; + reg = <0x4a0 1>; + clocks = <&usia_u0_sclkdiv>; + #clock-cells = <0>; +}; + +Example of consumer: + +uart@e1020000 { + compatible = "renesas,em-uart"; + reg = <0xe1020000 0x38>; + interrupts = <0 8 0>; + clocks = <&usia_u0_sclk>; + clock-names = "sclk"; +}; + +Example of clock-tree description: + + This describes a clock path in the clock tree + c32ki -> pll3_fo -> usia_u0_sclkdiv -> usia_u0_sclk + +smu@e0110000 { + compatible = "renesas,emev2-smu"; + reg = <0xe0110000 0x10000>; + #address-cells = <2>; + #size-cells = <0>; + + c32ki: c32ki { + compatible = "fixed-clock"; + clock-frequency = <32768>; + #clock-cells = <0>; + }; + pll3_fo: pll3_fo { + compatible = "fixed-factor-clock"; + clocks = <&c32ki>; + clock-div = <1>; + clock-mult = <7000>; + #clock-cells = <0>; + }; + usia_u0_sclkdiv: usia_u0_sclkdiv { + compatible = "renesas,emev2-smu-clkdiv"; + reg = <0x610 0>; + clocks = <&pll3_fo>; + #clock-cells = <0>; + }; + usia_u0_sclk: usia_u0_sclk { + compatible = "renesas,emev2-smu-gclk"; + reg = <0x4a0 1>; + clocks = <&usia_u0_sclkdiv>; + #clock-cells = <0>; + }; +}; diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index 706adc6ae70c..9ecef140dba7 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile @@ -1,7 +1,7 @@ +obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o - # for emply built-in.o obj-n := dummy diff --git a/drivers/clk/shmobile/clk-emev2.c b/drivers/clk/shmobile/clk-emev2.c new file mode 100644 index 000000000000..6c7c929c7765 --- /dev/null +++ b/drivers/clk/shmobile/clk-emev2.c @@ -0,0 +1,104 @@ +/* + * EMMA Mobile EV2 common clock framework support + * + * Copyright (C) 2013 Takashi Yoshii + * Copyright (C) 2012 Magnus Damm + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +/* EMEV2 SMU registers */ +#define USIAU0_RSTCTRL 0x094 +#define USIBU1_RSTCTRL 0x0ac +#define USIBU2_RSTCTRL 0x0b0 +#define USIBU3_RSTCTRL 0x0b4 +#define STI_RSTCTRL 0x124 +#define STI_CLKSEL 0x688 + +static DEFINE_SPINLOCK(lock); + +/* not pretty, but hey */ +void __iomem *smu_base; + +static void __init emev2_smu_write(unsigned long value, int offs) +{ + BUG_ON(!smu_base || (offs >= PAGE_SIZE)); + writel_relaxed(value, smu_base + offs); +} + +static const struct of_device_id smu_id[] __initconst = { + { .compatible = "renesas,emev2-smu", }, + {}, +}; + +static void __init emev2_smu_init(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, smu_id); + BUG_ON(!np); + smu_base = of_iomap(np, 0); + BUG_ON(!smu_base); + of_node_put(np); + + /* setup STI timer to run on 32.768 kHz and deassert reset */ + emev2_smu_write(0, STI_CLKSEL); + emev2_smu_write(1, STI_RSTCTRL); + + /* deassert reset for UART0->UART3 */ + emev2_smu_write(2, USIAU0_RSTCTRL); + emev2_smu_write(2, USIBU1_RSTCTRL); + emev2_smu_write(2, USIBU2_RSTCTRL); + emev2_smu_write(2, USIBU3_RSTCTRL); +} + +static void __init emev2_smu_clkdiv_init(struct device_node *np) +{ + u32 reg[2]; + struct clk *clk; + const char *parent_name = of_clk_get_parent_name(np, 0); + if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2))) + return; + if (!smu_base) + emev2_smu_init(); + clk = clk_register_divider(NULL, np->name, parent_name, 0, + smu_base + reg[0], reg[1], 8, 0, &lock); + of_clk_add_provider(np, of_clk_src_simple_get, clk); + clk_register_clkdev(clk, np->name, NULL); + pr_debug("## %s %s %p\n", __func__, np->name, clk); +} +CLK_OF_DECLARE(emev2_smu_clkdiv, "renesas,emev2-smu-clkdiv", + emev2_smu_clkdiv_init); + +static void __init emev2_smu_gclk_init(struct device_node *np) +{ + u32 reg[2]; + struct clk *clk; + const char *parent_name = of_clk_get_parent_name(np, 0); + if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2))) + return; + if (!smu_base) + emev2_smu_init(); + clk = clk_register_gate(NULL, np->name, parent_name, 0, + smu_base + reg[0], reg[1], 0, &lock); + of_clk_add_provider(np, of_clk_src_simple_get, clk); + clk_register_clkdev(clk, np->name, NULL); + pr_debug("## %s %s %p\n", __func__, np->name, clk); +} +CLK_OF_DECLARE(emev2_smu_gclk, "renesas,emev2-smu-gclk", emev2_smu_gclk_init); -- cgit v1.2.3 From eecdaa6e20284efbe9e76eebd44eac2b22f7b5d7 Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:09:55 -0800 Subject: bonding: add miimon netlink support Add IFLA_BOND_MIIMON to allow get/set of bonding parameter miimon via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 32 ++++++++++++++++++----- drivers/net/bonding/bond_options.c | 42 ++++++++++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 53 +++++++------------------------------- drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 80 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 40e7b1cb4aea..28a88beb749b 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -1,6 +1,7 @@ /* * drivers/net/bond/bond_netlink.c - Netlink interface for bonding * Copyright (c) 2013 Jiri Pirko + * Copyright (c) 2013 Scott Feldman * * 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 @@ -23,6 +24,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_MODE] = { .type = NLA_U8 }, [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 }, + [IFLA_BOND_MIIMON] = { .type = NLA_U32 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -42,14 +44,17 @@ static int bond_changelink(struct net_device *bond_dev, struct bonding *bond = netdev_priv(bond_dev); int err; - if (data && data[IFLA_BOND_MODE]) { + if (!data) + return 0; + + if (data[IFLA_BOND_MODE]) { int mode = nla_get_u8(data[IFLA_BOND_MODE]); err = bond_option_mode_set(bond, mode); if (err) return err; } - if (data && data[IFLA_BOND_ACTIVE_SLAVE]) { + if (data[IFLA_BOND_ACTIVE_SLAVE]) { int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]); struct net_device *slave_dev; @@ -65,6 +70,13 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_MIIMON]) { + int miimon = nla_get_u32(data[IFLA_BOND_MIIMON]); + + err = bond_option_miimon_set(bond, miimon); + if (err) + return err; + } return 0; } @@ -83,7 +95,9 @@ static int bond_newlink(struct net *src_net, struct net_device *bond_dev, static size_t bond_get_size(const struct net_device *bond_dev) { return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */ - nla_total_size(sizeof(u32)); /* IFLA_BOND_ACTIVE_SLAVE */ + nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */ + nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */ + 0; } static int bond_fill_info(struct sk_buff *skb, @@ -92,10 +106,16 @@ static int bond_fill_info(struct sk_buff *skb, struct bonding *bond = netdev_priv(bond_dev); struct net_device *slave_dev = bond_option_active_slave_get(bond); - if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode) || - (slave_dev && - nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))) + if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode)) goto nla_put_failure; + + if (slave_dev && + nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex)) + goto nla_put_failure; + + if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index ea6f640782b7..8ae42d36f11f 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1,6 +1,7 @@ /* * drivers/net/bond/bond_options.c - bonding options * Copyright (c) 2013 Jiri Pirko + * Copyright (c) 2013 Scott Feldman * * 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 @@ -145,3 +146,44 @@ int bond_option_active_slave_set(struct bonding *bond, unblock_netpoll_tx(); return ret; } + +int bond_option_miimon_set(struct bonding *bond, int miimon) +{ + if (miimon < 0) { + pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n", + bond->dev->name, miimon, 0, INT_MAX); + return -EINVAL; + } + pr_info("%s: Setting MII monitoring interval to %d.\n", + bond->dev->name, miimon); + bond->params.miimon = miimon; + if (bond->params.updelay) + pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n", + bond->dev->name, + bond->params.updelay * bond->params.miimon); + if (bond->params.downdelay) + pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n", + bond->dev->name, + bond->params.downdelay * bond->params.miimon); + if (miimon && bond->params.arp_interval) { + pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n", + bond->dev->name); + bond->params.arp_interval = 0; + if (bond->params.arp_validate) + bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; + } + if (bond->dev->flags & IFF_UP) { + /* If the interface is up, we may need to fire off + * the MII timer. If the interface is down, the + * timer will get fired off when the open function + * is called. + */ + if (!miimon) { + cancel_delayed_work_sync(&bond->mii_work); + } else { + cancel_delayed_work_sync(&bond->arp_work); + queue_delayed_work(bond->wq, &bond->mii_work, 0); + } + } + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index e46467683e82..d6d6fc7812d5 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -970,55 +970,22 @@ static ssize_t bonding_store_miimon(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - int new_value, ret = count; + int new_value, ret; struct bonding *bond = to_bond(d); - if (!rtnl_trylock()) - return restart_syscall(); if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no miimon value specified.\n", bond->dev->name); - ret = -EINVAL; - goto out; - } - if (new_value < 0) { - pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n", - bond->dev->name, new_value, 0, INT_MAX); - ret = -EINVAL; - goto out; - } - pr_info("%s: Setting MII monitoring interval to %d.\n", - bond->dev->name, new_value); - bond->params.miimon = new_value; - if (bond->params.updelay) - pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n", - bond->dev->name, - bond->params.updelay * bond->params.miimon); - if (bond->params.downdelay) - pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n", - bond->dev->name, - bond->params.downdelay * bond->params.miimon); - if (new_value && bond->params.arp_interval) { - pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n", - bond->dev->name); - bond->params.arp_interval = 0; - if (bond->params.arp_validate) - bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; - } - if (bond->dev->flags & IFF_UP) { - /* If the interface is up, we may need to fire off - * the MII timer. If the interface is down, the - * timer will get fired off when the open function - * is called. - */ - if (!new_value) { - cancel_delayed_work_sync(&bond->mii_work); - } else { - cancel_delayed_work_sync(&bond->arp_work); - queue_delayed_work(bond->wq, &bond->mii_work, 0); - } + return -EINVAL; } -out: + + if (!rtnl_trylock()) + return restart_syscall(); + + ret = bond_option_miimon_set(bond, new_value); + if (!ret) + ret = count; + rtnl_unlock(); return ret; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index a74c92c83ead..b146479d5859 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -439,6 +439,7 @@ int bond_netlink_init(void); void bond_netlink_fini(void); int bond_option_mode_set(struct bonding *bond, int mode); int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); +int bond_option_miimon_set(struct bonding *bond, int miimon); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 6db460121f84..739b2db3f035 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -331,6 +331,7 @@ enum { IFLA_BOND_UNSPEC, IFLA_BOND_MODE, IFLA_BOND_ACTIVE_SLAVE, + IFLA_BOND_MIIMON, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From 25852e29dfc58d249ad0db235996b36c33db6d61 Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:02 -0800 Subject: bonding: add updelay netlink support Add IFLA_BOND_UPDELAY to allow get/set of bonding parameter updelay via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 13 ++++++++++++ drivers/net/bonding/bond_options.c | 29 ++++++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 42 +++++++++----------------------------- drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 54 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 28a88beb749b..086cf4f5f0a6 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -25,6 +25,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_MODE] = { .type = NLA_U8 }, [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 }, [IFLA_BOND_MIIMON] = { .type = NLA_U32 }, + [IFLA_BOND_UPDELAY] = { .type = NLA_U32 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -77,6 +78,13 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_UPDELAY]) { + int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]); + + err = bond_option_updelay_set(bond, updelay); + if (err) + return err; + } return 0; } @@ -97,6 +105,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) return nla_total_size(sizeof(u8)) + /* IFLA_BOND_MODE */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */ + nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */ 0; } @@ -116,6 +125,10 @@ static int bond_fill_info(struct sk_buff *skb, if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon)) goto nla_put_failure; + if (nla_put_u32(skb, IFLA_BOND_UPDELAY, + bond->params.updelay * bond->params.miimon)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 8ae42d36f11f..ae94b847ffcc 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -187,3 +187,32 @@ int bond_option_miimon_set(struct bonding *bond, int miimon) } return 0; } + +int bond_option_updelay_set(struct bonding *bond, int updelay) +{ + if (!(bond->params.miimon)) { + pr_err("%s: Unable to set up delay as MII monitoring is disabled\n", + bond->dev->name); + return -EPERM; + } + + if (updelay < 0) { + pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n", + bond->dev->name, updelay, 0, INT_MAX); + return -EINVAL; + } else { + if ((updelay % bond->params.miimon) != 0) { + pr_warn("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n", + bond->dev->name, updelay, + bond->params.miimon, + (updelay / bond->params.miimon) * + bond->params.miimon); + } + bond->params.updelay = updelay / bond->params.miimon; + pr_info("%s: Setting up delay to %d.\n", + bond->dev->name, + bond->params.updelay * bond->params.miimon); + } + + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index d6d6fc7812d5..4dcbec4e07c0 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -747,44 +747,22 @@ static ssize_t bonding_store_updelay(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - int new_value, ret = count; + int new_value, ret; struct bonding *bond = to_bond(d); - if (!rtnl_trylock()) - return restart_syscall(); - if (!(bond->params.miimon)) { - pr_err("%s: Unable to set up delay as MII monitoring is disabled\n", - bond->dev->name); - ret = -EPERM; - goto out; - } - if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no up delay value specified.\n", - bond->dev->name); - ret = -EINVAL; - goto out; - } - if (new_value < 0) { - pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n", - bond->dev->name, new_value, 0, INT_MAX); - ret = -EINVAL; - goto out; - } else { - if ((new_value % bond->params.miimon) != 0) { - pr_warning("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n", - bond->dev->name, new_value, - bond->params.miimon, - (new_value / bond->params.miimon) * - bond->params.miimon); - } - bond->params.updelay = new_value / bond->params.miimon; - pr_info("%s: Setting up delay to %d.\n", - bond->dev->name, - bond->params.updelay * bond->params.miimon); + bond->dev->name); + return -EINVAL; } -out: + if (!rtnl_trylock()) + return restart_syscall(); + + ret = bond_option_updelay_set(bond, new_value); + if (!ret) + ret = count; + rtnl_unlock(); return ret; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index b146479d5859..8a91f7187e51 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -440,6 +440,7 @@ void bond_netlink_fini(void); int bond_option_mode_set(struct bonding *bond, int mode); int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); int bond_option_miimon_set(struct bonding *bond, int miimon); +int bond_option_updelay_set(struct bonding *bond, int updelay); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 739b2db3f035..7588c8120e7f 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -332,6 +332,7 @@ enum { IFLA_BOND_MODE, IFLA_BOND_ACTIVE_SLAVE, IFLA_BOND_MIIMON, + IFLA_BOND_UPDELAY, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From c7461f9bf5a11bf88fdbd05b26c6d55b77dcd46d Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:09 -0800 Subject: bonding: add downdelay netlink support Add IFLA_BOND_DOWNDELAY to allow get/set of bonding parameter downdelay via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 13 +++++++++++++ drivers/net/bonding/bond_options.c | 29 ++++++++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 39 ++++++++------------------------------ drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 52 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 086cf4f5f0a6..a0a2e8c32fe5 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -26,6 +26,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 }, [IFLA_BOND_MIIMON] = { .type = NLA_U32 }, [IFLA_BOND_UPDELAY] = { .type = NLA_U32 }, + [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -85,6 +86,13 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_DOWNDELAY]) { + int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]); + + err = bond_option_downdelay_set(bond, downdelay); + if (err) + return err; + } return 0; } @@ -106,6 +114,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) nla_total_size(sizeof(u32)) + /* IFLA_BOND_ACTIVE_SLAVE */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */ + nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */ 0; } @@ -129,6 +138,10 @@ static int bond_fill_info(struct sk_buff *skb, bond->params.updelay * bond->params.miimon)) goto nla_put_failure; + if (nla_put_u32(skb, IFLA_BOND_DOWNDELAY, + bond->params.downdelay * bond->params.miimon)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index ae94b847ffcc..2914d649ee34 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -216,3 +216,32 @@ int bond_option_updelay_set(struct bonding *bond, int updelay) return 0; } + +int bond_option_downdelay_set(struct bonding *bond, int downdelay) +{ + if (!(bond->params.miimon)) { + pr_err("%s: Unable to set down delay as MII monitoring is disabled\n", + bond->dev->name); + return -EPERM; + } + + if (downdelay < 0) { + pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n", + bond->dev->name, downdelay, 0, INT_MAX); + return -EINVAL; + } else { + if ((downdelay % bond->params.miimon) != 0) { + pr_warn("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n", + bond->dev->name, downdelay, + bond->params.miimon, + (downdelay / bond->params.miimon) * + bond->params.miimon); + } + bond->params.downdelay = downdelay / bond->params.miimon; + pr_info("%s: Setting down delay to %d.\n", + bond->dev->name, + bond->params.downdelay * bond->params.miimon); + } + + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 4dcbec4e07c0..bec20bc08d31 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -689,44 +689,21 @@ static ssize_t bonding_store_downdelay(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - int new_value, ret = count; + int new_value, ret; struct bonding *bond = to_bond(d); - if (!rtnl_trylock()) - return restart_syscall(); - if (!(bond->params.miimon)) { - pr_err("%s: Unable to set down delay as MII monitoring is disabled\n", - bond->dev->name); - ret = -EPERM; - goto out; - } - if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no down delay value specified.\n", bond->dev->name); - ret = -EINVAL; - goto out; + return -EINVAL; } - if (new_value < 0) { - pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n", - bond->dev->name, new_value, 0, INT_MAX); - ret = -EINVAL; - goto out; - } else { - if ((new_value % bond->params.miimon) != 0) { - pr_warning("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n", - bond->dev->name, new_value, - bond->params.miimon, - (new_value / bond->params.miimon) * - bond->params.miimon); - } - bond->params.downdelay = new_value / bond->params.miimon; - pr_info("%s: Setting down delay to %d.\n", - bond->dev->name, - bond->params.downdelay * bond->params.miimon); - } + if (!rtnl_trylock()) + return restart_syscall(); + + ret = bond_option_downdelay_set(bond, new_value); + if (!ret) + ret = count; -out: rtnl_unlock(); return ret; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 8a91f7187e51..f5749b18d168 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -441,6 +441,7 @@ int bond_option_mode_set(struct bonding *bond, int mode); int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev); int bond_option_miimon_set(struct bonding *bond, int miimon); int bond_option_updelay_set(struct bonding *bond, int updelay); +int bond_option_downdelay_set(struct bonding *bond, int downdelay); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 7588c8120e7f..f95506777710 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -333,6 +333,7 @@ enum { IFLA_BOND_ACTIVE_SLAVE, IFLA_BOND_MIIMON, IFLA_BOND_UPDELAY, + IFLA_BOND_DOWNDELAY, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From 9f53e14e86c46a2300f17309f6308ad0dfbb53ff Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:16 -0800 Subject: bonding: add use_carrier netlink support Add IFLA_BOND_USE_CARRIER to allow get/set of bonding parameter use_carrier via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 12 ++++++++++++ drivers/net/bonding/bond_options.c | 14 ++++++++++++++ drivers/net/bonding/bond_sysfs.c | 24 +++++++++++------------- drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index a0a2e8c32fe5..7edf6399cea2 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -27,6 +27,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_MIIMON] = { .type = NLA_U32 }, [IFLA_BOND_UPDELAY] = { .type = NLA_U32 }, [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 }, + [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -93,6 +94,13 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_USE_CARRIER]) { + int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]); + + err = bond_option_use_carrier_set(bond, use_carrier); + if (err) + return err; + } return 0; } @@ -115,6 +123,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) nla_total_size(sizeof(u32)) + /* IFLA_BOND_MIIMON */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */ + nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */ 0; } @@ -142,6 +151,9 @@ static int bond_fill_info(struct sk_buff *skb, bond->params.downdelay * bond->params.miimon)) goto nla_put_failure; + if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 2914d649ee34..6fc7bbf0b85f 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -245,3 +245,17 @@ int bond_option_downdelay_set(struct bonding *bond, int downdelay) return 0; } + +int bond_option_use_carrier_set(struct bonding *bond, int use_carrier) +{ + if ((use_carrier == 0) || (use_carrier == 1)) { + bond->params.use_carrier = use_carrier; + pr_info("%s: Setting use_carrier to %d.\n", + bond->dev->name, use_carrier); + } else { + pr_info("%s: Ignoring invalid use_carrier value %d.\n", + bond->dev->name, use_carrier); + } + + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index bec20bc08d31..114760af9a6d 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1097,25 +1097,23 @@ static ssize_t bonding_store_carrier(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - int new_value, ret = count; + int new_value, ret; struct bonding *bond = to_bond(d); - if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no use_carrier value specified.\n", bond->dev->name); - ret = -EINVAL; - goto out; - } - if ((new_value == 0) || (new_value == 1)) { - bond->params.use_carrier = new_value; - pr_info("%s: Setting use_carrier to %d.\n", - bond->dev->name, new_value); - } else { - pr_info("%s: Ignoring invalid use_carrier value %d.\n", - bond->dev->name, new_value); + return -EINVAL; } -out: + + if (!rtnl_trylock()) + return restart_syscall(); + + ret = bond_option_use_carrier_set(bond, new_value); + if (!ret) + ret = count; + + rtnl_unlock(); return ret; } static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index f5749b18d168..df159da8db30 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -442,6 +442,7 @@ int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_ int bond_option_miimon_set(struct bonding *bond, int miimon); int bond_option_updelay_set(struct bonding *bond, int updelay); int bond_option_downdelay_set(struct bonding *bond, int downdelay); +int bond_option_use_carrier_set(struct bonding *bond, int use_carrier); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index f95506777710..77c41bda36a4 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -334,6 +334,7 @@ enum { IFLA_BOND_MIIMON, IFLA_BOND_UPDELAY, IFLA_BOND_DOWNDELAY, + IFLA_BOND_USE_CARRIER, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From 06151dbcf3f76edbe900138cde9e862f429918c9 Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:24 -0800 Subject: bonding: add arp_interval netlink support Add IFLA_BOND_ARP_INTERVAL to allow get/set of bonding parameter arp_interval via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 21 ++++++++++++- drivers/net/bonding/bond_options.c | 47 +++++++++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 61 +++++++------------------------------- drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 80 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 7edf6399cea2..58e71235b75f 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -28,6 +28,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_UPDELAY] = { .type = NLA_U32 }, [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 }, [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 }, + [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -45,6 +46,7 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[], struct nlattr *data[]) { struct bonding *bond = netdev_priv(bond_dev); + int miimon = 0; int err; if (!data) @@ -74,7 +76,7 @@ static int bond_changelink(struct net_device *bond_dev, return err; } if (data[IFLA_BOND_MIIMON]) { - int miimon = nla_get_u32(data[IFLA_BOND_MIIMON]); + miimon = nla_get_u32(data[IFLA_BOND_MIIMON]); err = bond_option_miimon_set(bond, miimon); if (err) @@ -101,6 +103,19 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_ARP_INTERVAL]) { + int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]); + + if (arp_interval && miimon) { + pr_err("%s: ARP monitoring cannot be used with MII monitoring.\n", + bond->dev->name); + return -EINVAL; + } + + err = bond_option_arp_interval_set(bond, arp_interval); + if (err) + return err; + } return 0; } @@ -124,6 +139,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) nla_total_size(sizeof(u32)) + /* IFLA_BOND_UPDELAY */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */ nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */ + nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */ 0; } @@ -154,6 +170,9 @@ static int bond_fill_info(struct sk_buff *skb, if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier)) goto nla_put_failure; + if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 6fc7bbf0b85f..a84e729d02ef 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -259,3 +259,50 @@ int bond_option_use_carrier_set(struct bonding *bond, int use_carrier) return 0; } + +int bond_option_arp_interval_set(struct bonding *bond, int arp_interval) +{ + if (arp_interval < 0) { + pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n", + bond->dev->name, arp_interval, INT_MAX); + return -EINVAL; + } + if (BOND_NO_USES_ARP(bond->params.mode)) { + pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n", + bond->dev->name, bond->dev->name); + return -EINVAL; + } + pr_info("%s: Setting ARP monitoring interval to %d.\n", + bond->dev->name, arp_interval); + bond->params.arp_interval = arp_interval; + if (arp_interval) { + if (bond->params.miimon) { + pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n", + bond->dev->name, bond->dev->name); + bond->params.miimon = 0; + } + if (!bond->params.arp_targets[0]) + pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n", + bond->dev->name); + } + if (bond->dev->flags & IFF_UP) { + /* If the interface is up, we may need to fire off + * the ARP timer. If the interface is down, the + * timer will get fired off when the open function + * is called. + */ + if (!arp_interval) { + if (bond->params.arp_validate) + bond->recv_probe = NULL; + cancel_delayed_work_sync(&bond->arp_work); + } else { + /* arp_validate can be set only in active-backup mode */ + if (bond->params.arp_validate) + bond->recv_probe = bond_arp_rcv; + cancel_delayed_work_sync(&bond->mii_work); + queue_delayed_work(bond->wq, &bond->arp_work, 0); + } + } + + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 114760af9a6d..12128bfa88ce 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -506,60 +506,21 @@ static ssize_t bonding_store_arp_interval(struct device *d, const char *buf, size_t count) { struct bonding *bond = to_bond(d); - int new_value, ret = count; + int new_value, ret; - if (!rtnl_trylock()) - return restart_syscall(); if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no arp_interval value specified.\n", - bond->dev->name); - ret = -EINVAL; - goto out; - } - if (new_value < 0) { - pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n", - bond->dev->name, new_value, INT_MAX); - ret = -EINVAL; - goto out; - } - if (BOND_NO_USES_ARP(bond->params.mode)) { - pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n", - bond->dev->name, bond->dev->name); - ret = -EINVAL; - goto out; - } - pr_info("%s: Setting ARP monitoring interval to %d.\n", - bond->dev->name, new_value); - bond->params.arp_interval = new_value; - if (new_value) { - if (bond->params.miimon) { - pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n", - bond->dev->name, bond->dev->name); - bond->params.miimon = 0; - } - if (!bond->params.arp_targets[0]) - pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n", - bond->dev->name); - } - if (bond->dev->flags & IFF_UP) { - /* If the interface is up, we may need to fire off - * the ARP timer. If the interface is down, the - * timer will get fired off when the open function - * is called. - */ - if (!new_value) { - if (bond->params.arp_validate) - bond->recv_probe = NULL; - cancel_delayed_work_sync(&bond->arp_work); - } else { - /* arp_validate can be set only in active-backup mode */ - if (bond->params.arp_validate) - bond->recv_probe = bond_arp_rcv; - cancel_delayed_work_sync(&bond->mii_work); - queue_delayed_work(bond->wq, &bond->arp_work, 0); - } + bond->dev->name); + return -EINVAL; } -out: + + if (!rtnl_trylock()) + return restart_syscall(); + + ret = bond_option_arp_interval_set(bond, new_value); + if (!ret) + ret = count; + rtnl_unlock(); return ret; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index df159da8db30..44df2738577d 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -443,6 +443,7 @@ int bond_option_miimon_set(struct bonding *bond, int miimon); int bond_option_updelay_set(struct bonding *bond, int updelay); int bond_option_downdelay_set(struct bonding *bond, int downdelay); int bond_option_use_carrier_set(struct bonding *bond, int use_carrier); +int bond_option_arp_interval_set(struct bonding *bond, int arp_interval); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 77c41bda36a4..c73d878afd58 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -335,6 +335,7 @@ enum { IFLA_BOND_UPDELAY, IFLA_BOND_DOWNDELAY, IFLA_BOND_USE_CARRIER, + IFLA_BOND_ARP_INTERVAL, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From 7f28fa10e21376a10d3b9faad5836869465cc376 Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:31 -0800 Subject: bonding: add arp_ip_target netlink support Add IFLA_BOND_ARP_IP_TARGET to allow get/set of bonding parameter arp_ip_target via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 36 ++++++++++ drivers/net/bonding/bond_options.c | 130 +++++++++++++++++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 84 +++++------------------- drivers/net/bonding/bonding.h | 4 ++ include/uapi/linux/if_link.h | 1 + 5 files changed, 187 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 58e71235b75f..6d30e5db9e3c 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -29,6 +29,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 }, [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 }, [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 }, + [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -116,6 +117,20 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_ARP_IP_TARGET]) { + __be32 targets[BOND_MAX_ARP_TARGETS] = { 0, }; + struct nlattr *attr; + int i = 0, rem; + + nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) { + __be32 target = nla_get_u32(attr); + targets[i++] = target; + } + + err = bond_option_arp_ip_targets_set(bond, targets, i); + if (err) + return err; + } return 0; } @@ -140,6 +155,8 @@ static size_t bond_get_size(const struct net_device *bond_dev) nla_total_size(sizeof(u32)) + /* IFLA_BOND_DOWNDELAY */ nla_total_size(sizeof(u8)) + /* IFLA_BOND_USE_CARRIER */ nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */ + /* IFLA_BOND_ARP_IP_TARGET */ + nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS + 0; } @@ -148,6 +165,8 @@ static int bond_fill_info(struct sk_buff *skb, { struct bonding *bond = netdev_priv(bond_dev); struct net_device *slave_dev = bond_option_active_slave_get(bond); + struct nlattr *targets; + int i, targets_added; if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode)) goto nla_put_failure; @@ -173,6 +192,23 @@ static int bond_fill_info(struct sk_buff *skb, if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval)) goto nla_put_failure; + targets = nla_nest_start(skb, IFLA_BOND_ARP_IP_TARGET); + if (!targets) + goto nla_put_failure; + + targets_added = 0; + for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { + if (bond->params.arp_targets[i]) { + nla_put_u32(skb, i, bond->params.arp_targets[i]); + targets_added = 1; + } + } + + if (targets_added) + nla_nest_end(skb, targets); + else + nla_nest_cancel(skb, targets); + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index a84e729d02ef..f8c2e4f17066 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -306,3 +306,133 @@ int bond_option_arp_interval_set(struct bonding *bond, int arp_interval) return 0; } + +static void _bond_options_arp_ip_target_set(struct bonding *bond, int slot, + __be32 target, + unsigned long last_rx) +{ + __be32 *targets = bond->params.arp_targets; + struct list_head *iter; + struct slave *slave; + + if (slot >= 0 && slot < BOND_MAX_ARP_TARGETS) { + bond_for_each_slave(bond, slave, iter) + slave->target_last_arp_rx[slot] = last_rx; + targets[slot] = target; + } +} + +static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target) +{ + __be32 *targets = bond->params.arp_targets; + int ind; + + if (IS_IP_TARGET_UNUSABLE_ADDRESS(target)) { + pr_err("%s: invalid ARP target %pI4 specified for addition\n", + bond->dev->name, &target); + return -EINVAL; + } + + if (bond_get_targets_ip(targets, target) != -1) { /* dup */ + pr_err("%s: ARP target %pI4 is already present\n", + bond->dev->name, &target); + return -EINVAL; + } + + ind = bond_get_targets_ip(targets, 0); /* first free slot */ + if (ind == -1) { + pr_err("%s: ARP target table is full!\n", + bond->dev->name); + return -EINVAL; + } + + pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, &target); + + _bond_options_arp_ip_target_set(bond, ind, target, jiffies); + + return 0; +} + +int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target) +{ + int ret; + + /* not to race with bond_arp_rcv */ + write_lock_bh(&bond->lock); + ret = _bond_option_arp_ip_target_add(bond, target); + write_unlock_bh(&bond->lock); + + return ret; +} + +int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target) +{ + __be32 *targets = bond->params.arp_targets; + struct list_head *iter; + struct slave *slave; + unsigned long *targets_rx; + int ind, i; + + if (IS_IP_TARGET_UNUSABLE_ADDRESS(target)) { + pr_err("%s: invalid ARP target %pI4 specified for removal\n", + bond->dev->name, &target); + return -EINVAL; + } + + ind = bond_get_targets_ip(targets, target); + if (ind == -1) { + pr_err("%s: unable to remove nonexistent ARP target %pI4.\n", + bond->dev->name, &target); + return -EINVAL; + } + + if (ind == 0 && !targets[1] && bond->params.arp_interval) + pr_warn("%s: removing last arp target with arp_interval on\n", + bond->dev->name); + + pr_info("%s: removing ARP target %pI4.\n", bond->dev->name, + &target); + + /* not to race with bond_arp_rcv */ + write_lock_bh(&bond->lock); + + bond_for_each_slave(bond, slave, iter) { + targets_rx = slave->target_last_arp_rx; + for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) + targets_rx[i] = targets_rx[i+1]; + targets_rx[i] = 0; + } + for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) + targets[i] = targets[i+1]; + targets[i] = 0; + + write_unlock_bh(&bond->lock); + + return 0; +} + +int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets, + int count) +{ + int i, ret = 0; + + /* not to race with bond_arp_rcv */ + write_lock_bh(&bond->lock); + + /* clear table */ + for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) + _bond_options_arp_ip_target_set(bond, i, 0, 0); + + if (count == 0 && bond->params.arp_interval) + pr_warn("%s: removing last arp target with arp_interval on\n", + bond->dev->name); + + for (i = 0; i < count; i++) { + ret = _bond_option_arp_ip_target_add(bond, targets[i]); + if (ret) + break; + } + + write_unlock_bh(&bond->lock); + return ret; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 12128bfa88ce..a443bbd0fe86 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -552,81 +552,29 @@ static ssize_t bonding_store_arp_targets(struct device *d, const char *buf, size_t count) { struct bonding *bond = to_bond(d); - struct list_head *iter; - struct slave *slave; - __be32 newtarget, *targets; - unsigned long *targets_rx; - int ind, i, j, ret = -EINVAL; + __be32 target; + int ret = -EPERM; - if (!rtnl_trylock()) - return restart_syscall(); - - targets = bond->params.arp_targets; - if (!in4_pton(buf + 1, -1, (u8 *)&newtarget, -1, NULL) || - IS_IP_TARGET_UNUSABLE_ADDRESS(newtarget)) { - pr_err("%s: invalid ARP target %pI4 specified for addition\n", - bond->dev->name, &newtarget); - goto out; + if (!in4_pton(buf + 1, -1, (u8 *)&target, -1, NULL)) { + pr_err("%s: invalid ARP target %pI4 specified\n", + bond->dev->name, &target); + return -EPERM; } - /* look for adds */ - if (buf[0] == '+') { - if (bond_get_targets_ip(targets, newtarget) != -1) { /* dup */ - pr_err("%s: ARP target %pI4 is already present\n", - bond->dev->name, &newtarget); - goto out; - } - - ind = bond_get_targets_ip(targets, 0); /* first free slot */ - if (ind == -1) { - pr_err("%s: ARP target table is full!\n", - bond->dev->name); - goto out; - } - - pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, - &newtarget); - /* not to race with bond_arp_rcv */ - write_lock_bh(&bond->lock); - bond_for_each_slave(bond, slave, iter) - slave->target_last_arp_rx[ind] = jiffies; - targets[ind] = newtarget; - write_unlock_bh(&bond->lock); - } else if (buf[0] == '-') { - ind = bond_get_targets_ip(targets, newtarget); - if (ind == -1) { - pr_err("%s: unable to remove nonexistent ARP target %pI4.\n", - bond->dev->name, &newtarget); - goto out; - } - if (ind == 0 && !targets[1] && bond->params.arp_interval) - pr_warn("%s: removing last arp target with arp_interval on\n", - bond->dev->name); - - pr_info("%s: removing ARP target %pI4.\n", bond->dev->name, - &newtarget); + if (!rtnl_trylock()) + return restart_syscall(); - write_lock_bh(&bond->lock); - bond_for_each_slave(bond, slave, iter) { - targets_rx = slave->target_last_arp_rx; - j = ind; - for (; (j < BOND_MAX_ARP_TARGETS-1) && targets[j+1]; j++) - targets_rx[j] = targets_rx[j+1]; - targets_rx[j] = 0; - } - for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) - targets[i] = targets[i+1]; - targets[i] = 0; - write_unlock_bh(&bond->lock); - } else { + if (buf[0] == '+') + ret = bond_option_arp_ip_target_add(bond, target); + else if (buf[0] == '-') + ret = bond_option_arp_ip_target_rem(bond, target); + else pr_err("no command found in arp_ip_targets file for bond %s. Use + or -.\n", bond->dev->name); - ret = -EPERM; - goto out; - } - ret = count; -out: + if (!ret) + ret = count; + rtnl_unlock(); return ret; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 44df2738577d..dcdc8095c169 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -444,6 +444,10 @@ int bond_option_updelay_set(struct bonding *bond, int updelay); int bond_option_downdelay_set(struct bonding *bond, int downdelay); int bond_option_use_carrier_set(struct bonding *bond, int use_carrier); int bond_option_arp_interval_set(struct bonding *bond, int arp_interval); +int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets, + int count); +int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target); +int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index c73d878afd58..5b0c44469279 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -336,6 +336,7 @@ enum { IFLA_BOND_DOWNDELAY, IFLA_BOND_USE_CARRIER, IFLA_BOND_ARP_INTERVAL, + IFLA_BOND_ARP_IP_TARGET, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From 29c4948293bfc426e52a921f4259eb3676961e81 Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:38 -0800 Subject: bonding: add arp_validate netlink support Add IFLA_BOND_ARP_VALIDATE to allow get/set of bonding parameter arp_validate via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 18 ++++++++++++++++++ drivers/net/bonding/bond_options.c | 22 ++++++++++++++++++++++ drivers/net/bonding/bond_sysfs.c | 30 ++++++++---------------------- drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 50 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 6d30e5db9e3c..8588cb91caa9 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -30,6 +30,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 }, [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 }, [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED }, + [IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -131,6 +132,19 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_ARP_VALIDATE]) { + int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]); + + if (arp_validate && miimon) { + pr_err("%s: ARP validating cannot be used with MII monitoring.\n", + bond->dev->name); + return -EINVAL; + } + + err = bond_option_arp_validate_set(bond, arp_validate); + if (err) + return err; + } return 0; } @@ -157,6 +171,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_INTERVAL */ /* IFLA_BOND_ARP_IP_TARGET */ nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS + + nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_VALIDATE */ 0; } @@ -209,6 +224,9 @@ static int bond_fill_info(struct sk_buff *skb, else nla_nest_cancel(skb, targets); + if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index f8c2e4f17066..698079e94e74 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -436,3 +436,25 @@ int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets, write_unlock_bh(&bond->lock); return ret; } + +int bond_option_arp_validate_set(struct bonding *bond, int arp_validate) +{ + if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) { + pr_err("%s: arp_validate only supported in active-backup mode.\n", + bond->dev->name); + return -EINVAL; + } + pr_info("%s: setting arp_validate to %s (%d).\n", + bond->dev->name, arp_validate_tbl[arp_validate].modename, + arp_validate); + + if (bond->dev->flags & IFF_UP) { + if (!arp_validate) + bond->recv_probe = NULL; + else if (bond->params.arp_interval) + bond->recv_probe = bond_arp_rcv; + } + bond->params.arp_validate = arp_validate; + + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index a443bbd0fe86..bda00a01393a 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -358,35 +358,21 @@ static ssize_t bonding_store_arp_validate(struct device *d, const char *buf, size_t count) { struct bonding *bond = to_bond(d); - int new_value, ret = count; + int new_value, ret; - if (!rtnl_trylock()) - return restart_syscall(); new_value = bond_parse_parm(buf, arp_validate_tbl); if (new_value < 0) { pr_err("%s: Ignoring invalid arp_validate value %s\n", bond->dev->name, buf); - ret = -EINVAL; - goto out; - } - if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) { - pr_err("%s: arp_validate only supported in active-backup mode.\n", - bond->dev->name); - ret = -EINVAL; - goto out; + return -EINVAL; } - pr_info("%s: setting arp_validate to %s (%d).\n", - bond->dev->name, arp_validate_tbl[new_value].modename, - new_value); + if (!rtnl_trylock()) + return restart_syscall(); + + ret = bond_option_arp_validate_set(bond, new_value); + if (!ret) + ret = count; - if (bond->dev->flags & IFF_UP) { - if (!new_value) - bond->recv_probe = NULL; - else if (bond->params.arp_interval) - bond->recv_probe = bond_arp_rcv; - } - bond->params.arp_validate = new_value; -out: rtnl_unlock(); return ret; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index dcdc8095c169..cef10adac6e6 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -448,6 +448,7 @@ int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets, int count); int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target); int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target); +int bond_option_arp_validate_set(struct bonding *bond, int arp_validate); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 5b0c44469279..3ba16fa9ad6c 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -337,6 +337,7 @@ enum { IFLA_BOND_USE_CARRIER, IFLA_BOND_ARP_INTERVAL, IFLA_BOND_ARP_IP_TARGET, + IFLA_BOND_ARP_VALIDATE, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From d5c842544342fc3f13774ffc5581d4dd3975059b Mon Sep 17 00:00:00 2001 From: "sfeldma@cumulusnetworks.com" Date: Thu, 12 Dec 2013 14:10:45 -0800 Subject: bonding: add arp_all_targets netlink support Add IFLA_BOND_ARP_ALL_TARGETS to allow get/set of bonding parameter arp_all_targets via netlink. Signed-off-by: Scott Feldman Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_netlink.c | 14 ++++++++++++++ drivers/net/bonding/bond_options.c | 11 +++++++++++ drivers/net/bonding/bond_sysfs.c | 16 ++++++++++------ drivers/net/bonding/bonding.h | 1 + include/uapi/linux/if_link.h | 1 + 5 files changed, 37 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 8588cb91caa9..d7d84db9eed7 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -31,6 +31,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 }, [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED }, [IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 }, + [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NLA_U32 }, }; static int bond_validate(struct nlattr *tb[], struct nlattr *data[]) @@ -145,6 +146,14 @@ static int bond_changelink(struct net_device *bond_dev, if (err) return err; } + if (data[IFLA_BOND_ARP_ALL_TARGETS]) { + int arp_all_targets = + nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]); + + err = bond_option_arp_all_targets_set(bond, arp_all_targets); + if (err) + return err; + } return 0; } @@ -172,6 +181,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) /* IFLA_BOND_ARP_IP_TARGET */ nla_total_size(sizeof(u32)) * BOND_MAX_ARP_TARGETS + nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_VALIDATE */ + nla_total_size(sizeof(u32)) + /* IFLA_BOND_ARP_ALL_TARGETS */ 0; } @@ -227,6 +237,10 @@ static int bond_fill_info(struct sk_buff *skb, if (nla_put_u32(skb, IFLA_BOND_ARP_VALIDATE, bond->params.arp_validate)) goto nla_put_failure; + if (nla_put_u32(skb, IFLA_BOND_ARP_ALL_TARGETS, + bond->params.arp_all_targets)) + goto nla_put_failure; + return 0; nla_put_failure: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 698079e94e74..dfef673d53d1 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -458,3 +458,14 @@ int bond_option_arp_validate_set(struct bonding *bond, int arp_validate) return 0; } + +int bond_option_arp_all_targets_set(struct bonding *bond, int arp_all_targets) +{ + pr_info("%s: setting arp_all_targets to %s (%d).\n", + bond->dev->name, arp_all_targets_tbl[arp_all_targets].modename, + arp_all_targets); + + bond->params.arp_all_targets = arp_all_targets; + + return 0; +} diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index bda00a01393a..dad9bea95122 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -399,7 +399,7 @@ static ssize_t bonding_store_arp_all_targets(struct device *d, const char *buf, size_t count) { struct bonding *bond = to_bond(d); - int new_value; + int new_value, ret; new_value = bond_parse_parm(buf, arp_all_targets_tbl); if (new_value < 0) { @@ -407,13 +407,17 @@ static ssize_t bonding_store_arp_all_targets(struct device *d, bond->dev->name, buf); return -EINVAL; } - pr_info("%s: setting arp_all_targets to %s (%d).\n", - bond->dev->name, arp_all_targets_tbl[new_value].modename, - new_value); - bond->params.arp_all_targets = new_value; + if (!rtnl_trylock()) + return restart_syscall(); - return count; + ret = bond_option_arp_all_targets_set(bond, new_value); + if (!ret) + ret = count; + + rtnl_unlock(); + + return ret; } static DEVICE_ATTR(arp_all_targets, S_IRUGO | S_IWUSR, diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index cef10adac6e6..8283cbdec50a 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -449,6 +449,7 @@ int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets, int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target); int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target); int bond_option_arp_validate_set(struct bonding *bond, int arp_validate); +int bond_option_arp_all_targets_set(struct bonding *bond, int arp_all_targets); struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); struct net_device *bond_option_active_slave_get(struct bonding *bond); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 3ba16fa9ad6c..a897b7e22541 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -338,6 +338,7 @@ enum { IFLA_BOND_ARP_INTERVAL, IFLA_BOND_ARP_IP_TARGET, IFLA_BOND_ARP_VALIDATE, + IFLA_BOND_ARP_ALL_TARGETS, __IFLA_BOND_MAX, }; -- cgit v1.2.3 From b2e7aceb00b2621431e220748f7158b131b89e7b Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:19:32 +0800 Subject: bonding: remove the no effect lock for bond_select_active_slave() The bond slave list was no longer protected by bond lock and only protected by RTNL or RCU, so anywhere that use bond lock to protect slave list is meaningless. remove the release and acquire bond lock for bond_select_active_slave(). The curr_active_slave could only be changed in 3 place: 1. enslave slave. 2. release slave. 3. change_active_slave. all above place were holding bond lock, RTNL and curr_slave_lock together, it is tedious and meaningless, obviously bond lock is no need here, but RTNL or curr_slave_lock is needed, so if you want to access active slave, you have to choose one lock, RTNL or curr_slave_lock, if RTNL is exist, no need to add curr_slave_lock, otherwise curr_slave_lock is better, because of the performance. there are several place calling bond_select_active_slave() and bond_change_active_slave(), the next step I will clean these place and remove the no effect lock. there are some document changed together when update the function. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 12 +++--------- drivers/net/bonding/bond_main.c | 15 +++------------ 2 files changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 2250b063ab89..7b806e330364 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -469,7 +469,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[]) /* slave being removed should not be active at this point * - * Caller must hold bond lock for read + * Caller must hold rtnl. */ static void rlb_clear_slave(struct bonding *bond, struct slave *slave) { @@ -1679,14 +1679,11 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char * If new_slave is NULL, caller must hold curr_slave_lock or * bond->lock for write. * - * If new_slave is not NULL, caller must hold RTNL, bond->lock for - * read and curr_slave_lock for write. Processing here may sleep, so - * no other locks may be held. + * If new_slave is not NULL, caller must hold RTNL, curr_slave_lock + * for write. Processing here may sleep, so no other locks may be held. */ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave) __releases(&bond->curr_slave_lock) - __releases(&bond->lock) - __acquires(&bond->lock) __acquires(&bond->curr_slave_lock) { struct slave *swap_slave; @@ -1722,7 +1719,6 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave tlb_clear_slave(bond, new_slave, 1); write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); ASSERT_RTNL(); @@ -1748,11 +1744,9 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave /* swap mac address */ alb_swap_mac_addr(swap_slave, new_slave); alb_fasten_mac_swap(bond, swap_slave, new_slave); - read_lock(&bond->lock); } else { /* set the new_slave to the bond mac address */ alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr); - read_lock(&bond->lock); alb_send_learning_packets(new_slave, bond->dev->dev_addr); } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 398e299ee1bd..04ae426fcc81 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -697,14 +697,12 @@ static void bond_set_dev_addr(struct net_device *bond_dev, * * Perform special MAC address swapping for fail_over_mac settings * - * Called with RTNL, bond->lock for read, curr_slave_lock for write_bh. + * Called with RTNL, curr_slave_lock for write_bh. */ static void bond_do_fail_over_mac(struct bonding *bond, struct slave *new_active, struct slave *old_active) __releases(&bond->curr_slave_lock) - __releases(&bond->lock) - __acquires(&bond->lock) __acquires(&bond->curr_slave_lock) { u8 tmp_mac[ETH_ALEN]; @@ -715,9 +713,7 @@ static void bond_do_fail_over_mac(struct bonding *bond, case BOND_FOM_ACTIVE: if (new_active) { write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); bond_set_dev_addr(bond->dev, new_active->dev); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); } break; @@ -731,7 +727,6 @@ static void bond_do_fail_over_mac(struct bonding *bond, return; write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); if (old_active) { memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN); @@ -761,7 +756,6 @@ static void bond_do_fail_over_mac(struct bonding *bond, pr_err("%s: Error %d setting MAC of slave %s\n", bond->dev->name, -rv, new_active->dev->name); out: - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); break; default: @@ -846,8 +840,7 @@ static bool bond_should_notify_peers(struct bonding *bond) * because it is apparently the best available slave we have, even though its * updelay hasn't timed out yet. * - * If new_active is not NULL, caller must hold bond->lock for read and - * curr_slave_lock for write_bh. + * If new_active is not NULL, caller must hold curr_slave_lock for write_bh. */ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) { @@ -916,14 +909,12 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev); if (should_notify_peers) call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); } } @@ -949,7 +940,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) * - The primary_slave has got its link back. * - A slave has got its link back and there's no old curr_active_slave. * - * Caller must hold bond->lock for read and curr_slave_lock for write_bh. + * Caller must hold curr_slave_lock for write_bh. */ void bond_select_active_slave(struct bonding *bond) { -- cgit v1.2.3 From 4cb4f97b7e361745281e843499ba58691112d2f8 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:19:39 +0800 Subject: bonding: rebuild the lock use for bond_mii_monitor() The bond_mii_monitor() still use bond lock to protect bond slave list, it is no effect, I have 2 way to fix the problem, move the RTNL to the top of the function, or add RCU to protect the bond slave list, according to the Jay Vosburgh's opinion, 10 times one second is a truely big performance loss if use RTNL to protect the whole monitor, so I would take the advice and use RCU to protect the bond slave list. The bond_has_slave() will not protect by anything, there will no things happen if the slave list is be changed, unless the bond was free, but it will not happened before the monitor, the bond will closed before be freed. The peers notify for the bond will calling curr_active_slave, so derefence the slave to make sure we will accessing the same slave if the curr_active_slave changed, as the rcu dereference need in read-side critical sector and bond_change_active_slave() will call it with no RCU hold, so add peer notify in rcu_read_lock which will be nested in monitor. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 04ae426fcc81..b34634a96710 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -815,7 +815,11 @@ static struct slave *bond_find_best_slave(struct bonding *bond) static bool bond_should_notify_peers(struct bonding *bond) { - struct slave *slave = bond->curr_active_slave; + struct slave *slave; + + rcu_read_lock(); + slave = rcu_dereference(bond->curr_active_slave); + rcu_read_unlock(); pr_debug("bond_should_notify_peers: bond %s slave %s\n", bond->dev->name, slave ? slave->dev->name : "NULL"); @@ -1919,7 +1923,7 @@ static int bond_miimon_inspect(struct bonding *bond) ignore_updelay = !bond->curr_active_slave ? true : false; - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { slave->new_link = BOND_LINK_NOCHANGE; link_state = bond_check_dev_link(bond, slave->dev, 0); @@ -2117,41 +2121,35 @@ void bond_mii_monitor(struct work_struct *work) bool should_notify_peers = false; unsigned long delay; - read_lock(&bond->lock); - delay = msecs_to_jiffies(bond->params.miimon); if (!bond_has_slaves(bond)) goto re_arm; + rcu_read_lock(); + should_notify_peers = bond_should_notify_peers(bond); if (bond_miimon_inspect(bond)) { - read_unlock(&bond->lock); + rcu_read_unlock(); /* Race avoidance with bond_close cancel of workqueue */ if (!rtnl_trylock()) { - read_lock(&bond->lock); delay = 1; should_notify_peers = false; goto re_arm; } - read_lock(&bond->lock); - bond_miimon_commit(bond); - read_unlock(&bond->lock); rtnl_unlock(); /* might sleep, hold no other locks */ - read_lock(&bond->lock); - } + } else + rcu_read_unlock(); re_arm: if (bond->params.miimon) queue_delayed_work(bond->wq, &bond->mii_work, delay); - read_unlock(&bond->lock); - if (should_notify_peers) { if (!rtnl_trylock()) return; -- cgit v1.2.3 From 733ab63935beab905b03a329cdc544e8c171b6b9 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:19:45 +0800 Subject: bonding: rebuild the lock use for bond_alb_monitor() The bond_alb_monitor use bond lock to protect the bond slave list, it is no effect here, we need to use RTNL or RCU to replace bond lock, the bond_alb_monitor will called 10 times one second, RTNL may loss performance here, so I replace bond lock with RCU to protect the bond slave list, also the RTNL is preserved, the logic of the monitor did not changed. Suggested-by: Nikolay Aleksandrov Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 7b806e330364..759ddeebe390 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -815,7 +815,7 @@ static void rlb_rebalance(struct bonding *bond) for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->used_next) { client_info = &(bond_info->rx_hashtbl[hash_index]); - assigned_slave = rlb_next_rx_slave(bond); + assigned_slave = __rlb_next_rx_slave(bond); if (assigned_slave && (client_info->slave != assigned_slave)) { client_info->slave = assigned_slave; client_info->ntt = 1; @@ -1494,14 +1494,14 @@ void bond_alb_monitor(struct work_struct *work) struct list_head *iter; struct slave *slave; - read_lock(&bond->lock); - if (!bond_has_slaves(bond)) { bond_info->tx_rebalance_counter = 0; bond_info->lp_counter = 0; goto re_arm; } + rcu_read_lock(); + bond_info->tx_rebalance_counter++; bond_info->lp_counter++; @@ -1514,7 +1514,7 @@ void bond_alb_monitor(struct work_struct *work) */ read_lock(&bond->curr_slave_lock); - bond_for_each_slave(bond, slave, iter) + bond_for_each_slave_rcu(bond, slave, iter) alb_send_learning_packets(slave, slave->dev->dev_addr); read_unlock(&bond->curr_slave_lock); @@ -1527,7 +1527,7 @@ void bond_alb_monitor(struct work_struct *work) read_lock(&bond->curr_slave_lock); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { tlb_clear_slave(bond, slave, 1); if (slave == bond->curr_active_slave) { SLAVE_TLB_INFO(slave).load = @@ -1551,11 +1551,9 @@ void bond_alb_monitor(struct work_struct *work) * dev_set_promiscuity requires rtnl and * nothing else. Avoid race with bond_close. */ - read_unlock(&bond->lock); - if (!rtnl_trylock()) { - read_lock(&bond->lock); + rcu_read_unlock(); + if (!rtnl_trylock()) goto re_arm; - } bond_info->rlb_promisc_timeout_counter = 0; @@ -1567,7 +1565,7 @@ void bond_alb_monitor(struct work_struct *work) bond_info->primary_is_promisc = 0; rtnl_unlock(); - read_lock(&bond->lock); + rcu_read_lock(); } if (bond_info->rlb_rebalance) { @@ -1589,11 +1587,9 @@ void bond_alb_monitor(struct work_struct *work) } } } - + rcu_read_unlock(); re_arm: queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks); - - read_unlock(&bond->lock); } /* assumption: called before the slave is attached to the bond -- cgit v1.2.3 From 2e52f4fe3655c7a2311070c6713f7feabc75486c Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:19:50 +0800 Subject: bonding: rebuild the lock use for bond_loadbalance_arp_mon() The bond_loadbalance_arp_mon() use the bond lock to protect the bond slave list, it is no effect, so I could use RTNL or RCU to replace it, considering the performance impact, the RCU is more better here, so the bond lock replace with the RCU. The bond_select_active_slave() need RTNL and curr_slave_lock together, but there is no RTNL lock here, so add a rtnl_rtylock. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b34634a96710..1781ea620d76 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2411,12 +2411,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work) struct list_head *iter; int do_failover = 0; - read_lock(&bond->lock); - if (!bond_has_slaves(bond)) goto re_arm; - oldcurrent = bond->curr_active_slave; + rcu_read_lock(); + + oldcurrent = ACCESS_ONCE(bond->curr_active_slave); /* see if any of the previous devices are up now (i.e. they have * xmt and rcv traffic). the curr_active_slave does not come into * the picture unless it is null. also, slave->jiffies is not needed @@ -2425,7 +2425,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * TODO: what about up/down delay in arp mode? it wasn't here before * so it can wait */ - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { unsigned long trans_start = dev_trans_start(slave->dev); if (slave->link != BOND_LINK_UP) { @@ -2487,7 +2487,14 @@ void bond_loadbalance_arp_mon(struct work_struct *work) bond_arp_send_all(bond, slave); } + rcu_read_unlock(); + if (do_failover) { + /* the bond_select_active_slave must hold RTNL + * and curr_slave_lock for write. + */ + if (!rtnl_trylock()) + goto re_arm; block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); @@ -2495,14 +2502,13 @@ void bond_loadbalance_arp_mon(struct work_struct *work) write_unlock_bh(&bond->curr_slave_lock); unblock_netpoll_tx(); + rtnl_unlock(); } re_arm: if (bond->params.arp_interval) queue_delayed_work(bond->wq, &bond->arp_work, msecs_to_jiffies(bond->params.arp_interval)); - - read_unlock(&bond->lock); } /* -- cgit v1.2.3 From e001bfad913bf119fb67c1e8dd2d4ec1f5d392fa Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:19:55 +0800 Subject: bonding: create bond_first_slave_rcu() The bond_first_slave_rcu() will be used to instead of bond_first_slave() in rcu_read_lock(). According to the Jay Vosburgh's suggestion, the struct netdev_adjacent should hide from users who wanted to use it directly. so I package a new function to get the first slave of the bond. Suggested-by: Nikolay Aleksandrov Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bonding.h | 4 ++++ include/linux/netdevice.h | 1 + net/core/dev.c | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 8283cbdec50a..8f0d6d0c383b 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -101,6 +101,10 @@ netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \ NULL) +/* Caller must have rcu_read_lock */ +#define bond_first_slave_rcu(bond) \ + netdev_lower_get_first_private_rcu(bond->dev) + #define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond)) #define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond)) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5260d2eae2e6..2c74d20dad34 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2907,6 +2907,7 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, priv = netdev_lower_get_next_private_rcu(dev, &(iter))) void *netdev_adjacent_get_private(struct list_head *adj_list); +void *netdev_lower_get_first_private_rcu(struct net_device *dev); struct net_device *netdev_master_upper_dev_get(struct net_device *dev); struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev); diff --git a/net/core/dev.c b/net/core/dev.c index c95d664b2b42..9d4369ece679 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4543,6 +4543,27 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, } EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); +/** + * netdev_lower_get_first_private_rcu - Get the first ->private from the + * lower neighbour list, RCU + * variant + * @dev: device + * + * Gets the first netdev_adjacent->private from the dev's lower neighbour + * list. The caller must hold RCU read lock. + */ +void *netdev_lower_get_first_private_rcu(struct net_device *dev) +{ + struct netdev_adjacent *lower; + + lower = list_first_or_null_rcu(&dev->adj_list.lower, + struct netdev_adjacent, list); + if (lower) + return lower->private; + return NULL; +} +EXPORT_SYMBOL(netdev_lower_get_first_private_rcu); + /** * netdev_master_upper_dev_get_rcu - Get master upper device * @dev: device -- cgit v1.2.3 From eb9fa4b0199f62df3d174d32b4bd534df8ba4533 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:20:02 +0800 Subject: bonding: rebuild the lock use for bond_activebackup_arp_mon() The bond_activebackup_arp_mon() use the bond lock for read to protect the slave list, it is no effect, and the RTNL is only called for bond_ab_arp_commit() and peer notify, for the performance better, use RCU to replace with the bond lock, to the bond slave list need to called in RCU, add a new bond_first_slave_rcu() to get the first slave in RCU protection. In bond_ab_arp_probe(), the bond->current_arp_slave may changd if bond release slave, just like: bond_ab_arp_probe() bond_release() cpu 0 cpu 1 ... if (bond->current_arp_slave...) ... ... bond->current_arp_slave = NULl bond->current_arp_slave->dev->name ... So the current_arp_slave need to dereference in the section. Suggested-by: Nikolay Aleksandrov Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 45 ++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1781ea620d76..bad1bf949546 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2517,7 +2517,7 @@ re_arm: * place for the slave. Returns 0 if no changes are found, >0 if changes * to link states must be committed. * - * Called with bond->lock held for read. + * Called with rcu_read_lock hold. */ static int bond_ab_arp_inspect(struct bonding *bond) { @@ -2526,7 +2526,7 @@ static int bond_ab_arp_inspect(struct bonding *bond) struct slave *slave; int commit = 0; - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { slave->new_link = BOND_LINK_NOCHANGE; last_rx = slave_last_rx(bond, slave); @@ -2588,7 +2588,7 @@ static int bond_ab_arp_inspect(struct bonding *bond) * Called to commit link state changes noted by inspection step of * active-backup mode ARP monitor. * - * Called with RTNL and bond->lock for read. + * Called with RTNL hold. */ static void bond_ab_arp_commit(struct bonding *bond) { @@ -2663,19 +2663,20 @@ do_failover: /* * Send ARP probes for active-backup mode ARP monitor. * - * Called with bond->lock held for read. + * Called with rcu_read_lock hold. */ static void bond_ab_arp_probe(struct bonding *bond) { - struct slave *slave, *before = NULL, *new_slave = NULL; + struct slave *slave, *before = NULL, *new_slave = NULL, + *curr_arp_slave = rcu_dereference(bond->current_arp_slave); struct list_head *iter; bool found = false; read_lock(&bond->curr_slave_lock); - if (bond->current_arp_slave && bond->curr_active_slave) + if (curr_arp_slave && bond->curr_active_slave) pr_info("PROBE: c_arp %s && cas %s BAD\n", - bond->current_arp_slave->dev->name, + curr_arp_slave->dev->name, bond->curr_active_slave->dev->name); if (bond->curr_active_slave) { @@ -2691,15 +2692,15 @@ static void bond_ab_arp_probe(struct bonding *bond) * for becoming the curr_active_slave */ - if (!bond->current_arp_slave) { - bond->current_arp_slave = bond_first_slave(bond); - if (!bond->current_arp_slave) + if (!curr_arp_slave) { + curr_arp_slave = bond_first_slave_rcu(bond); + if (!curr_arp_slave) return; } - bond_set_slave_inactive_flags(bond->current_arp_slave); + bond_set_slave_inactive_flags(curr_arp_slave); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { if (!found && !before && IS_UP(slave->dev)) before = slave; @@ -2722,7 +2723,7 @@ static void bond_ab_arp_probe(struct bonding *bond) pr_info("%s: backup interface %s is now down.\n", bond->dev->name, slave->dev->name); } - if (slave == bond->current_arp_slave) + if (slave == curr_arp_slave) found = true; } @@ -2736,8 +2737,7 @@ static void bond_ab_arp_probe(struct bonding *bond) bond_set_slave_active_flags(new_slave); bond_arp_send_all(bond, new_slave); new_slave->jiffies = jiffies; - bond->current_arp_slave = new_slave; - + rcu_assign_pointer(bond->current_arp_slave, new_slave); } void bond_activebackup_arp_mon(struct work_struct *work) @@ -2747,43 +2747,38 @@ void bond_activebackup_arp_mon(struct work_struct *work) bool should_notify_peers = false; int delta_in_ticks; - read_lock(&bond->lock); - delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); if (!bond_has_slaves(bond)) goto re_arm; + rcu_read_lock(); + should_notify_peers = bond_should_notify_peers(bond); if (bond_ab_arp_inspect(bond)) { - read_unlock(&bond->lock); + rcu_read_unlock(); /* Race avoidance with bond_close flush of workqueue */ if (!rtnl_trylock()) { - read_lock(&bond->lock); delta_in_ticks = 1; should_notify_peers = false; goto re_arm; } - read_lock(&bond->lock); - bond_ab_arp_commit(bond); - read_unlock(&bond->lock); rtnl_unlock(); - read_lock(&bond->lock); + rcu_read_lock(); } bond_ab_arp_probe(bond); + rcu_read_unlock(); re_arm: if (bond->params.arp_interval) queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); - read_unlock(&bond->lock); - if (should_notify_peers) { if (!rtnl_trylock()) return; -- cgit v1.2.3 From c8517035445834350b8d498723b68f4e81286110 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:20:07 +0800 Subject: bonding: remove unwanted lock for bond enslave and release The bond_change_active_slave() and bond_select_active_slave() do't need bond lock anymore, so remove the unwanted bond lock for these two functions. The bond_select_active_slave() will release and acquire curr_slave_lock, so the curr_slave_lock need to protect the function. In bond enslave and bond release, the bond slave list is also protected by RTNL, so bond lock is no need to exist, remove the lock and clean the functions. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bad1bf949546..1b1dd01fbf72 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1589,11 +1589,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_carrier(bond); if (USES_PRIMARY(bond->params.mode)) { - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); } pr_info("%s: enslaving %s as a%s interface with a%s link.\n", @@ -1613,19 +1611,13 @@ err_detach: bond_hw_addr_flush(bond_dev, slave_dev); vlan_vids_del_by_dev(slave_dev, bond_dev); - write_lock_bh(&bond->lock); if (bond->primary_slave == new_slave) bond->primary_slave = NULL; if (bond->curr_active_slave == new_slave) { - bond_change_active_slave(bond, NULL); - write_unlock_bh(&bond->lock); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); + bond_change_active_slave(bond, NULL); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); - } else { - write_unlock_bh(&bond->lock); } slave_disable_netpoll(new_slave); @@ -1690,20 +1682,16 @@ static int __bond_release_one(struct net_device *bond_dev, } block_netpoll_tx(); - write_lock_bh(&bond->lock); slave = bond_get_slave_by_dev(bond, slave_dev); if (!slave) { /* not a slave of this bond */ pr_info("%s: %s not enslaved\n", bond_dev->name, slave_dev->name); - write_unlock_bh(&bond->lock); unblock_netpoll_tx(); return -EINVAL; } - write_unlock_bh(&bond->lock); - /* release the slave from its bond */ bond->slave_cnt--; @@ -1721,6 +1709,7 @@ static int __bond_release_one(struct net_device *bond_dev, */ bond_3ad_unbind_slave(slave); } + write_unlock_bh(&bond->lock); pr_info("%s: releasing %s interface %s\n", bond_dev->name, @@ -1743,8 +1732,11 @@ static int __bond_release_one(struct net_device *bond_dev, if (bond->primary_slave == slave) bond->primary_slave = NULL; - if (oldcurrent == slave) + if (oldcurrent == slave) { + write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, NULL); + write_unlock_bh(&bond->curr_slave_lock); + } if (bond_is_lb(bond)) { /* Must be called only after the slave has been @@ -1752,9 +1744,7 @@ static int __bond_release_one(struct net_device *bond_dev, * has been cleared (if our_slave == old_current), * but before a new active slave is selected. */ - write_unlock_bh(&bond->lock); bond_alb_deinit_slave(bond, slave); - write_lock_bh(&bond->lock); } if (all) { @@ -1765,15 +1755,11 @@ static int __bond_release_one(struct net_device *bond_dev, * is no concern that another slave add/remove event * will interfere. */ - write_unlock_bh(&bond->lock); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); - write_lock_bh(&bond->lock); } if (!bond_has_slaves(bond)) { @@ -1788,7 +1774,6 @@ static int __bond_release_one(struct net_device *bond_dev, } } - write_unlock_bh(&bond->lock); unblock_netpoll_tx(); synchronize_rcu(); -- cgit v1.2.3 From be79bd048abe9fb6aee049ea903d1e70b44d6480 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:20:12 +0800 Subject: bonding: add RCU for bond_3ad_state_machine_handler() The bond_3ad_state_machine_handler() use the bond lock to protect the bond slave list and slave port together, but it is not enough, the bond slave list was link and unlink in RTNL, not bond lock, so I add RCU to protect the slave list from leaving. The bond lock is still used here, because when the slave has been removed from the list by the time the state machine runs, it appears to be possible for both function to manupulate the same aggregator->lag_ports by finding the aggregator via two different ports that are both members of that aggregator (i.e., port A of the agg is being unbound, and port B of the agg is runing its state machine). If I remove the bond lock, there are nothing to mutex changes to aggregator->lag_ports between bond_3ad_state_machine_handler and bond_3ad_unbind_slave, So the bond lock is the simplest way to protect aggregator->lag_ports. There was a lot of function need RCU protect, I have two choice to make the function in RCU-safe, (1) create new similar functions and make the bond slave list in RCU. (2) modify the existed functions and make them in read-side critical section, because the RCU read-side critical sections may be nested. I choose (2) because it is no need to create more similar functions. The nots in the function is still too old, clean up the nots. Suggested-by: Nikolay Aleksandrov Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 54 +++++++++++++++++++++++++---------------- drivers/net/bonding/bond_main.c | 7 ++---- 2 files changed, 35 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 187b1b7772ef..58c2249a3324 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -147,11 +147,12 @@ static inline struct aggregator *__get_first_agg(struct port *port) struct bonding *bond = __get_bond_by_port(port); struct slave *first_slave; - // If there's no bond for this port, or bond has no slaves + /* If there's no bond for this port, or bond has no slaves */ if (bond == NULL) return NULL; - first_slave = bond_first_slave(bond); - + rcu_read_lock(); + first_slave = bond_first_slave_rcu(bond); + rcu_read_unlock(); return first_slave ? &(SLAVE_AD_INFO(first_slave).aggregator) : NULL; } @@ -702,9 +703,13 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator) struct list_head *iter; struct slave *slave; - bond_for_each_slave(bond, slave, iter) - if (SLAVE_AD_INFO(slave).aggregator.is_active) + rcu_read_lock(); + bond_for_each_slave_rcu(bond, slave, iter) + if (SLAVE_AD_INFO(slave).aggregator.is_active) { + rcu_read_unlock(); return &(SLAVE_AD_INFO(slave).aggregator); + } + rcu_read_unlock(); return NULL; } @@ -1471,7 +1476,8 @@ static void ad_agg_selection_logic(struct aggregator *agg) active = __get_active_agg(agg); best = (active && agg_device_up(active)) ? active : NULL; - bond_for_each_slave(bond, slave, iter) { + rcu_read_lock(); + bond_for_each_slave_rcu(bond, slave, iter) { agg = &(SLAVE_AD_INFO(slave).aggregator); agg->is_active = 0; @@ -1505,7 +1511,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) active->is_active = 1; } - // if there is new best aggregator, activate it + /* if there is new best aggregator, activate it */ if (best) { pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", best->aggregator_identifier, best->num_of_ports, @@ -1516,7 +1522,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) best->lag_ports, best->slave, best->slave ? best->slave->dev->name : "NULL"); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { agg = &(SLAVE_AD_INFO(slave).aggregator); pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", @@ -1526,10 +1532,11 @@ static void ad_agg_selection_logic(struct aggregator *agg) agg->is_individual, agg->is_active); } - // check if any partner replys + /* check if any partner replys */ if (best->is_individual) { pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", - best->slave ? best->slave->bond->dev->name : "NULL"); + best->slave ? + best->slave->bond->dev->name : "NULL"); } best->is_active = 1; @@ -1541,7 +1548,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) best->partner_oper_aggregator_key, best->is_individual, best->is_active); - // disable the ports that were related to the former active_aggregator + /* disable the ports that were related to the former active_aggregator */ if (active) { for (port = active->lag_ports; port; port = port->next_port_in_aggregator) { @@ -1565,6 +1572,8 @@ static void ad_agg_selection_logic(struct aggregator *agg) } } + rcu_read_unlock(); + bond_3ad_set_carrier(bond); } @@ -2069,17 +2078,18 @@ void bond_3ad_state_machine_handler(struct work_struct *work) struct port *port; read_lock(&bond->lock); + rcu_read_lock(); - //check if there are any slaves + /* check if there are any slaves */ if (!bond_has_slaves(bond)) goto re_arm; - // check if agg_select_timer timer after initialize is timed out + /* check if agg_select_timer timer after initialize is timed out */ if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) { - slave = bond_first_slave(bond); + slave = bond_first_slave_rcu(bond); port = slave ? &(SLAVE_AD_INFO(slave).port) : NULL; - // select the active aggregator for the bond + /* select the active aggregator for the bond */ if (port) { if (!port->slave) { pr_warning("%s: Warning: bond's first port is uninitialized\n", @@ -2093,8 +2103,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work) bond_3ad_set_carrier(bond); } - // for each port run the state machines - bond_for_each_slave(bond, slave, iter) { + /* for each port run the state machines */ + bond_for_each_slave_rcu(bond, slave, iter) { port = &(SLAVE_AD_INFO(slave).port); if (!port->slave) { pr_warning("%s: Warning: Found an uninitialized port\n", @@ -2114,7 +2124,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) ad_mux_machine(port); ad_tx_machine(port); - // turn off the BEGIN bit, since we already handled it + /* turn off the BEGIN bit, since we already handled it */ if (port->sm_vars & AD_PORT_BEGIN) port->sm_vars &= ~AD_PORT_BEGIN; @@ -2122,9 +2132,9 @@ void bond_3ad_state_machine_handler(struct work_struct *work) } re_arm: - queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); - + rcu_read_unlock(); read_unlock(&bond->lock); + queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); } /** @@ -2303,7 +2313,9 @@ int bond_3ad_set_carrier(struct bonding *bond) struct aggregator *active; struct slave *first_slave; - first_slave = bond_first_slave(bond); + rcu_read_lock(); + first_slave = bond_first_slave_rcu(bond); + rcu_read_unlock(); if (!first_slave) return 0; active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator)); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1b1dd01fbf72..720a826eb071 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1703,12 +1703,9 @@ static int __bond_release_one(struct net_device *bond_dev, write_lock_bh(&bond->lock); /* Inform AD package of unbinding of slave. */ - if (bond->params.mode == BOND_MODE_8023AD) { - /* must be called before the slave is - * detached from the list - */ + if (bond->params.mode == BOND_MODE_8023AD) bond_3ad_unbind_slave(slave); - } + write_unlock_bh(&bond->lock); pr_info("%s: releasing %s interface %s\n", -- cgit v1.2.3 From 4e789fc1a62d4c25726ee053044399d71471fe2f Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:20:17 +0800 Subject: bonding: remove unwanted lock for bond_option_active_slave_set() The bond_option_active_slave_set() is always called in RTNL, the RTNL could protect bond slave list, so remove the unwanted bond lock. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_options.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index dfef673d53d1..600779e5904f 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -107,7 +107,6 @@ int bond_option_active_slave_set(struct bonding *bond, } block_netpoll_tx(); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); /* check to see if we are clearing active */ @@ -142,7 +141,6 @@ int bond_option_active_slave_set(struct bonding *bond, } write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); unblock_netpoll_tx(); return ret; } -- cgit v1.2.3 From 75ad932c182d0b3d2cab24a2e2252bb7acd42d45 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:20:22 +0800 Subject: bonding: remove unwanted lock for bond_store_primaryxxx() The bond_select_active_slave() will not release and acquire bond lock, so it is no need to read the bond lock for them, and the bond_store_primaryxxx() is already in RTNL, so remove the unwanted lock. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_sysfs.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index dad9bea95122..6368d299d5a6 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -878,7 +878,6 @@ static ssize_t bonding_store_primary(struct device *d, if (!rtnl_trylock()) return restart_syscall(); block_netpoll_tx(); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); if (!USES_PRIMARY(bond->params.mode)) { @@ -918,7 +917,6 @@ static ssize_t bonding_store_primary(struct device *d, bond->dev->name, ifname, bond->dev->name); out: write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); unblock_netpoll_tx(); rtnl_unlock(); @@ -966,11 +964,9 @@ static ssize_t bonding_store_primary_reselect(struct device *d, new_value); block_netpoll_tx(); - read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); unblock_netpoll_tx(); out: rtnl_unlock(); -- cgit v1.2.3 From f23691095b3c2c05b3ee4ab03cb8e90cfe245ea8 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Fri, 13 Dec 2013 10:20:26 +0800 Subject: bonding: rebuild the bond_resend_igmp_join_requests_delayed() The bond_resend_igmp_join_requests_delayed() and bond_resend_igmp_join_requests() should be integrated, because the bond_resend_igmp_join_requests_delayed() did nothing except bond_resend_igmp_join_requests(). The bond igmp_retrans could only be changed in bond_change_active_slave and here, bond_change_active_slave will be called in RTNL and curr_slave_lock, the bond_resend_igmp_join_requests already hold RTNL, so no need to free RTNL and hold curr_slave_lock again, it may be a small optimization, so move the igmp_retrans in RTNL and remove the curr_slave_lock. Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 720a826eb071..c0456cc86610 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -591,33 +591,22 @@ static int bond_set_allmulti(struct bonding *bond, int inc) * device and retransmit an IGMP JOIN request to the current active * slave. */ -static void bond_resend_igmp_join_requests(struct bonding *bond) +static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) { + struct bonding *bond = container_of(work, struct bonding, + mcast_work.work); + if (!rtnl_trylock()) { queue_delayed_work(bond->wq, &bond->mcast_work, 1); return; } call_netdevice_notifiers(NETDEV_RESEND_IGMP, bond->dev); - rtnl_unlock(); - /* We use curr_slave_lock to protect against concurrent access to - * igmp_retrans from multiple running instances of this function and - * bond_change_active_slave - */ - write_lock_bh(&bond->curr_slave_lock); if (bond->igmp_retrans > 1) { bond->igmp_retrans--; queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5); } - write_unlock_bh(&bond->curr_slave_lock); -} - -static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) -{ - struct bonding *bond = container_of(work, struct bonding, - mcast_work.work); - - bond_resend_igmp_join_requests(bond); + rtnl_unlock(); } /* Flush bond's hardware addresses from slave -- cgit v1.2.3 From 16a3d6ef9f9db6b0e54e6bb756a6b6165166cf44 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 13 Dec 2013 15:22:30 -0200 Subject: drm/i915: cancel the hangcheck before runtime suspend The hangcheck function requires the hardware to be working, and if we're suspending we're going to put the HW in D3 state. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c2c9a93861ae..df634a42cc0c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -917,6 +917,7 @@ static int i915_runtime_suspend(struct device *device) DRM_DEBUG_KMS("Suspending device\n"); + del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); dev_priv->pm.suspended = true; intel_opregion_notify_adapter(dev, PCI_D3cold); -- cgit v1.2.3 From 48018a57a8f5900e7e53ffaa0adeb784095accfb Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 13 Dec 2013 15:22:31 -0200 Subject: drm/i915: release the GTT mmaps when going into D3 So we'll get a fault when someone tries to access the mmap, then we'll wake up from D3. v2: - Rebase v3: - Use gtt active/inactive Testcase: igt/pm_pc8/gem-mmap-gtt Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi [danvet: Add comment + WARN as discussed with Paulo on irc.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index df634a42cc0c..aea909b2f22e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -917,6 +917,8 @@ static int i915_runtime_suspend(struct device *device) DRM_DEBUG_KMS("Suspending device\n"); + i915_gem_release_all_mmaps(dev_priv); + del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); dev_priv->pm.suspended = true; intel_opregion_notify_adapter(dev, PCI_D3cold); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ae2c80c1981b..9e4b5ca6ee72 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2015,6 +2015,7 @@ void i915_gem_object_unpin(struct drm_i915_gem_object *obj); int __must_check i915_vma_unbind(struct i915_vma *vma); int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); +void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); void i915_gem_release_mmap(struct drm_i915_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e34b48e862e7..c5a99c46ca9c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1465,6 +1465,22 @@ out: return ret; } +void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv) +{ + struct i915_vma *vma; + + /* + * Only the global gtt is relevant for gtt memory mappings, so restrict + * list traversal to objects bound into the global address space. Note + * that the active list should be empty, but better safe than sorry. + */ + WARN_ON(!list_empty(&dev_priv->gtt.base.active_list)); + list_for_each_entry(vma, &dev_priv->gtt.base.active_list, mm_list) + i915_gem_release_mmap(vma->obj); + list_for_each_entry(vma, &dev_priv->gtt.base.inactive_list, mm_list) + i915_gem_release_mmap(vma->obj); +} + /** * i915_gem_release_mmap - remove physical page mappings * @obj: obj in question -- cgit v1.2.3 From df4547d82589714f1b0cecd93569130a452cbf46 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 13 Dec 2013 15:22:32 -0200 Subject: drm/i915: add runtime PM support on Haswell Now that all the infrastructure is in place and all the tests from pm_pc8 pass, we can finally enable the feature. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9e4b5ca6ee72..67f2ca1e50e0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1848,7 +1848,7 @@ struct drm_i915_file_private { #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */ -#define HAS_RUNTIME_PM(dev) false +#define HAS_RUNTIME_PM(dev) (IS_HASWELL(dev)) #define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 -- cgit v1.2.3 From c30707be128e952ca2ba77417cb5509e254a4aac Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 19:38:38 -0800 Subject: gpu: ion: Add ION Memory Manager Signed-off-by: Rebecca Schultz Zavin [jstultz: Squished in Colin Cross' move to staging change, also disables ION from the build, as it won't compile till the end of the patchset] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Kconfig | 2 + drivers/staging/android/Makefile | 3 + drivers/staging/android/ion/Kconfig | 12 + drivers/staging/android/ion/Makefile | 2 + drivers/staging/android/ion/ion.c | 1187 +++++++++++++++++++++++ drivers/staging/android/ion/ion.h | 344 +++++++ drivers/staging/android/ion/ion_carveout_heap.c | 162 ++++ drivers/staging/android/ion/ion_heap.c | 72 ++ drivers/staging/android/ion/ion_priv.h | 185 ++++ drivers/staging/android/ion/ion_system_heap.c | 198 ++++ drivers/staging/android/ion/ion_system_mapper.c | 114 +++ drivers/staging/android/ion/tegra/Makefile | 1 + drivers/staging/android/ion/tegra/tegra_ion.c | 96 ++ 13 files changed, 2378 insertions(+) create mode 100644 drivers/staging/android/ion/Kconfig create mode 100644 drivers/staging/android/ion/Makefile create mode 100644 drivers/staging/android/ion/ion.c create mode 100644 drivers/staging/android/ion/ion.h create mode 100644 drivers/staging/android/ion/ion_carveout_heap.c create mode 100644 drivers/staging/android/ion/ion_heap.c create mode 100644 drivers/staging/android/ion/ion_priv.h create mode 100644 drivers/staging/android/ion/ion_system_heap.c create mode 100644 drivers/staging/android/ion/ion_system_mapper.c create mode 100644 drivers/staging/android/ion/tegra/Makefile create mode 100644 drivers/staging/android/ion/tegra/tegra_ion.c (limited to 'drivers') diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 1e9ab6dfc90d..b91c758883bf 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -100,6 +100,8 @@ config SW_SYNC_USER *WARNING* improper use of this can result in deadlocking kernel drivers from userspace. +source "drivers/staging/android/ion/Kconfig" + endif # if ANDROID endmenu diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index c136299e05af..29c5ff05abe4 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -1,5 +1,8 @@ ccflags-y += -I$(src) # needed for trace events +# ION doesn't build just yet, so disable it from the build +#obj-y += ion/ + obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOGGER) += logger.o diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig new file mode 100644 index 000000000000..5b48b4e85e73 --- /dev/null +++ b/drivers/staging/android/ion/Kconfig @@ -0,0 +1,12 @@ +menuconfig ION + tristate "Ion Memory Manager" + select GENERIC_ALLOCATOR + help + Chose this option to enable the ION Memory Manager. + +config ION_TEGRA + tristate "Ion for Tegra" + depends on ARCH_TEGRA && ION + help + Choose this option if you wish to use ion on an nVidia Tegra. + diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile new file mode 100644 index 000000000000..73fe3fa10706 --- /dev/null +++ b/drivers/staging/android/ion/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o +obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c new file mode 100644 index 000000000000..d93fb33d05ed --- /dev/null +++ b/drivers/staging/android/ion/ion.c @@ -0,0 +1,1187 @@ +/* + * drivers/staging/android/ion/ion.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ion.h" +#include "ion_priv.h" +#define DEBUG + +/** + * struct ion_device - the metadata of the ion device node + * @dev: the actual misc device + * @buffers: an rb tree of all the existing buffers + * @lock: lock protecting the buffers & heaps trees + * @heaps: list of all the heaps in the system + * @user_clients: list of all the clients created from userspace + */ +struct ion_device { + struct miscdevice dev; + struct rb_root buffers; + struct mutex lock; + struct rb_root heaps; + long (*custom_ioctl) (struct ion_client *client, unsigned int cmd, + unsigned long arg); + struct rb_root user_clients; + struct rb_root kernel_clients; + struct dentry *debug_root; +}; + +/** + * struct ion_client - a process/hw block local address space + * @ref: for reference counting the client + * @node: node in the tree of all clients + * @dev: backpointer to ion device + * @handles: an rb tree of all the handles in this client + * @lock: lock protecting the tree of handles + * @heap_mask: mask of all supported heaps + * @name: used for debugging + * @task: used for debugging + * + * A client represents a list of buffers this client may access. + * The mutex stored here is used to protect both handles tree + * as well as the handles themselves, and should be held while modifying either. + */ +struct ion_client { + struct kref ref; + struct rb_node node; + struct ion_device *dev; + struct rb_root handles; + struct mutex lock; + unsigned int heap_mask; + const char *name; + struct task_struct *task; + pid_t pid; + struct dentry *debug_root; +}; + +/** + * ion_handle - a client local reference to a buffer + * @ref: reference count + * @client: back pointer to the client the buffer resides in + * @buffer: pointer to the buffer + * @node: node in the client's handle rbtree + * @kmap_cnt: count of times this client has mapped to kernel + * @dmap_cnt: count of times this client has mapped for dma + * @usermap_cnt: count of times this client has mapped for userspace + * + * Modifications to node, map_cnt or mapping should be protected by the + * lock in the client. Other fields are never changed after initialization. + */ +struct ion_handle { + struct kref ref; + struct ion_client *client; + struct ion_buffer *buffer; + struct rb_node node; + unsigned int kmap_cnt; + unsigned int dmap_cnt; + unsigned int usermap_cnt; +}; + +/* this function should only be called while dev->lock is held */ +static void ion_buffer_add(struct ion_device *dev, + struct ion_buffer *buffer) +{ + struct rb_node **p = &dev->buffers.rb_node; + struct rb_node *parent = NULL; + struct ion_buffer *entry; + + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_buffer, node); + + if (buffer < entry) { + p = &(*p)->rb_left; + } else if (buffer > entry) { + p = &(*p)->rb_right; + } else { + pr_err("%s: buffer already found.", __func__); + BUG(); + } + } + + rb_link_node(&buffer->node, parent, p); + rb_insert_color(&buffer->node, &dev->buffers); +} + +/* this function should only be called while dev->lock is held */ +static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, + struct ion_device *dev, + unsigned long len, + unsigned long align, + unsigned long flags) +{ + struct ion_buffer *buffer; + int ret; + + buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + + buffer->heap = heap; + kref_init(&buffer->ref); + + ret = heap->ops->allocate(heap, buffer, len, align, flags); + if (ret) { + kfree(buffer); + return ERR_PTR(ret); + } + buffer->dev = dev; + buffer->size = len; + mutex_init(&buffer->lock); + ion_buffer_add(dev, buffer); + return buffer; +} + +static void ion_buffer_destroy(struct kref *kref) +{ + struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); + struct ion_device *dev = buffer->dev; + + buffer->heap->ops->free(buffer); + mutex_lock(&dev->lock); + rb_erase(&buffer->node, &dev->buffers); + mutex_unlock(&dev->lock); + kfree(buffer); +} + +static void ion_buffer_get(struct ion_buffer *buffer) +{ + kref_get(&buffer->ref); +} + +static int ion_buffer_put(struct ion_buffer *buffer) +{ + return kref_put(&buffer->ref, ion_buffer_destroy); +} + +static struct ion_handle *ion_handle_create(struct ion_client *client, + struct ion_buffer *buffer) +{ + struct ion_handle *handle; + + handle = kzalloc(sizeof(struct ion_handle), GFP_KERNEL); + if (!handle) + return ERR_PTR(-ENOMEM); + kref_init(&handle->ref); + RB_CLEAR_NODE(&handle->node); + handle->client = client; + ion_buffer_get(buffer); + handle->buffer = buffer; + + return handle; +} + +static void ion_handle_destroy(struct kref *kref) +{ + struct ion_handle *handle = container_of(kref, struct ion_handle, ref); + /* XXX Can a handle be destroyed while it's map count is non-zero?: + if (handle->map_cnt) unmap + */ + ion_buffer_put(handle->buffer); + mutex_lock(&handle->client->lock); + if (!RB_EMPTY_NODE(&handle->node)) + rb_erase(&handle->node, &handle->client->handles); + mutex_unlock(&handle->client->lock); + kfree(handle); +} + +struct ion_buffer *ion_handle_buffer(struct ion_handle *handle) +{ + return handle->buffer; +} + +static void ion_handle_get(struct ion_handle *handle) +{ + kref_get(&handle->ref); +} + +static int ion_handle_put(struct ion_handle *handle) +{ + return kref_put(&handle->ref, ion_handle_destroy); +} + +static struct ion_handle *ion_handle_lookup(struct ion_client *client, + struct ion_buffer *buffer) +{ + struct rb_node *n; + + for (n = rb_first(&client->handles); n; n = rb_next(n)) { + struct ion_handle *handle = rb_entry(n, struct ion_handle, + node); + if (handle->buffer == buffer) + return handle; + } + return NULL; +} + +static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) +{ + struct rb_node *n = client->handles.rb_node; + + while (n) { + struct ion_handle *handle_node = rb_entry(n, struct ion_handle, + node); + if (handle < handle_node) + n = n->rb_left; + else if (handle > handle_node) + n = n->rb_right; + else + return true; + } + return false; +} + +static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) +{ + struct rb_node **p = &client->handles.rb_node; + struct rb_node *parent = NULL; + struct ion_handle *entry; + + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_handle, node); + + if (handle < entry) + p = &(*p)->rb_left; + else if (handle > entry) + p = &(*p)->rb_right; + else + WARN(1, "%s: buffer already found.", __func__); + } + + rb_link_node(&handle->node, parent, p); + rb_insert_color(&handle->node, &client->handles); +} + +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + size_t align, unsigned int flags) +{ + struct rb_node *n; + struct ion_handle *handle; + struct ion_device *dev = client->dev; + struct ion_buffer *buffer = NULL; + + /* + * traverse the list of heaps available in this system in priority + * order. If the heap type is supported by the client, and matches the + * request of the caller allocate from it. Repeat until allocate has + * succeeded or all heaps have been tried + */ + mutex_lock(&dev->lock); + for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) { + struct ion_heap *heap = rb_entry(n, struct ion_heap, node); + /* if the client doesn't support this heap type */ + if (!((1 << heap->type) & client->heap_mask)) + continue; + /* if the caller didn't specify this heap type */ + if (!((1 << heap->id) & flags)) + continue; + buffer = ion_buffer_create(heap, dev, len, align, flags); + if (!IS_ERR_OR_NULL(buffer)) + break; + } + mutex_unlock(&dev->lock); + + if (IS_ERR_OR_NULL(buffer)) + return ERR_PTR(PTR_ERR(buffer)); + + handle = ion_handle_create(client, buffer); + + if (IS_ERR_OR_NULL(handle)) + goto end; + + /* + * ion_buffer_create will create a buffer with a ref_cnt of 1, + * and ion_handle_create will take a second reference, drop one here + */ + ion_buffer_put(buffer); + + mutex_lock(&client->lock); + ion_handle_add(client, handle); + mutex_unlock(&client->lock); + return handle; + +end: + ion_buffer_put(buffer); + return handle; +} + +void ion_free(struct ion_client *client, struct ion_handle *handle) +{ + bool valid_handle; + + BUG_ON(client != handle->client); + + mutex_lock(&client->lock); + valid_handle = ion_handle_validate(client, handle); + mutex_unlock(&client->lock); + + if (!valid_handle) { + WARN("%s: invalid handle passed to free.\n", __func__); + return; + } + ion_handle_put(handle); +} + +static void ion_client_get(struct ion_client *client); +static int ion_client_put(struct ion_client *client); + +static bool _ion_map(int *buffer_cnt, int *handle_cnt) +{ + bool map; + + BUG_ON(*handle_cnt != 0 && *buffer_cnt == 0); + + if (*buffer_cnt) + map = false; + else + map = true; + if (*handle_cnt == 0) + (*buffer_cnt)++; + (*handle_cnt)++; + return map; +} + +static bool _ion_unmap(int *buffer_cnt, int *handle_cnt) +{ + BUG_ON(*handle_cnt == 0); + (*handle_cnt)--; + if (*handle_cnt != 0) + return false; + BUG_ON(*buffer_cnt == 0); + (*buffer_cnt)--; + if (*buffer_cnt == 0) + return true; + return false; +} + +int ion_phys(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len) +{ + struct ion_buffer *buffer; + int ret; + + mutex_lock(&client->lock); + if (!ion_handle_validate(client, handle)) { + mutex_unlock(&client->lock); + return -EINVAL; + } + + buffer = handle->buffer; + + if (!buffer->heap->ops->phys) { + pr_err("%s: ion_phys is not implemented by this heap.\n", + __func__); + mutex_unlock(&client->lock); + return -ENODEV; + } + mutex_unlock(&client->lock); + ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); + return ret; +} + +void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) +{ + struct ion_buffer *buffer; + void *vaddr; + + mutex_lock(&client->lock); + if (!ion_handle_validate(client, handle)) { + pr_err("%s: invalid handle passed to map_kernel.\n", + __func__); + mutex_unlock(&client->lock); + return ERR_PTR(-EINVAL); + } + + buffer = handle->buffer; + mutex_lock(&buffer->lock); + + if (!handle->buffer->heap->ops->map_kernel) { + pr_err("%s: map_kernel is not implemented by this heap.\n", + __func__); + mutex_unlock(&buffer->lock); + mutex_unlock(&client->lock); + return ERR_PTR(-ENODEV); + } + + if (_ion_map(&buffer->kmap_cnt, &handle->kmap_cnt)) { + vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); + if (IS_ERR_OR_NULL(vaddr)) + _ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt); + buffer->vaddr = vaddr; + } else { + vaddr = buffer->vaddr; + } + mutex_unlock(&buffer->lock); + mutex_unlock(&client->lock); + return vaddr; +} + +struct scatterlist *ion_map_dma(struct ion_client *client, + struct ion_handle *handle) +{ + struct ion_buffer *buffer; + struct scatterlist *sglist; + + mutex_lock(&client->lock); + if (!ion_handle_validate(client, handle)) { + pr_err("%s: invalid handle passed to map_dma.\n", + __func__); + mutex_unlock(&client->lock); + return ERR_PTR(-EINVAL); + } + buffer = handle->buffer; + mutex_lock(&buffer->lock); + + if (!handle->buffer->heap->ops->map_dma) { + pr_err("%s: map_kernel is not implemented by this heap.\n", + __func__); + mutex_unlock(&buffer->lock); + mutex_unlock(&client->lock); + return ERR_PTR(-ENODEV); + } + if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) { + sglist = buffer->heap->ops->map_dma(buffer->heap, buffer); + if (IS_ERR_OR_NULL(sglist)) + _ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt); + buffer->sglist = sglist; + } else { + sglist = buffer->sglist; + } + mutex_unlock(&buffer->lock); + mutex_unlock(&client->lock); + return sglist; +} + +void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) +{ + struct ion_buffer *buffer; + + mutex_lock(&client->lock); + buffer = handle->buffer; + mutex_lock(&buffer->lock); + if (_ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt)) { + buffer->heap->ops->unmap_kernel(buffer->heap, buffer); + buffer->vaddr = NULL; + } + mutex_unlock(&buffer->lock); + mutex_unlock(&client->lock); +} + +void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) +{ + struct ion_buffer *buffer; + + mutex_lock(&client->lock); + buffer = handle->buffer; + mutex_lock(&buffer->lock); + if (_ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt)) { + buffer->heap->ops->unmap_dma(buffer->heap, buffer); + buffer->sglist = NULL; + } + mutex_unlock(&buffer->lock); + mutex_unlock(&client->lock); +} + + +struct ion_buffer *ion_share(struct ion_client *client, + struct ion_handle *handle) +{ + bool valid_handle; + + mutex_lock(&client->lock); + valid_handle = ion_handle_validate(client, handle); + mutex_unlock(&client->lock); + if (!valid_handle) { + WARN("%s: invalid handle passed to share.\n", __func__); + return ERR_PTR(-EINVAL); + } + + /* do not take an extra reference here, the burden is on the caller + * to make sure the buffer doesn't go away while it's passing it + * to another client -- ion_free should not be called on this handle + * until the buffer has been imported into the other client + */ + return handle->buffer; +} + +struct ion_handle *ion_import(struct ion_client *client, + struct ion_buffer *buffer) +{ + struct ion_handle *handle = NULL; + + mutex_lock(&client->lock); + /* if a handle exists for this buffer just take a reference to it */ + handle = ion_handle_lookup(client, buffer); + if (!IS_ERR_OR_NULL(handle)) { + ion_handle_get(handle); + goto end; + } + handle = ion_handle_create(client, buffer); + if (IS_ERR_OR_NULL(handle)) + goto end; + ion_handle_add(client, handle); +end: + mutex_unlock(&client->lock); + return handle; +} + +static const struct file_operations ion_share_fops; + +struct ion_handle *ion_import_fd(struct ion_client *client, int fd) +{ + struct file *file = fget(fd); + struct ion_handle *handle; + + if (!file) { + pr_err("%s: imported fd not found in file table.\n", __func__); + return ERR_PTR(-EINVAL); + } + if (file->f_op != &ion_share_fops) { + pr_err("%s: imported file is not a shared ion file.\n", + __func__); + handle = ERR_PTR(-EINVAL); + goto end; + } + handle = ion_import(client, file->private_data); +end: + fput(file); + return handle; +} + +static int ion_debug_client_show(struct seq_file *s, void *unused) +{ + struct ion_client *client = s->private; + struct rb_node *n; + size_t sizes[ION_NUM_HEAPS] = {0}; + const char *names[ION_NUM_HEAPS] = {0}; + int i; + + mutex_lock(&client->lock); + for (n = rb_first(&client->handles); n; n = rb_next(n)) { + struct ion_handle *handle = rb_entry(n, struct ion_handle, + node); + enum ion_heap_type type = handle->buffer->heap->type; + + if (!names[type]) + names[type] = handle->buffer->heap->name; + sizes[type] += handle->buffer->size; + } + mutex_unlock(&client->lock); + + seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes"); + for (i = 0; i < ION_NUM_HEAPS; i++) { + if (!names[i]) + continue; + seq_printf(s, "%16.16s: %16u %d\n", names[i], sizes[i], + atomic_read(&client->ref.refcount)); + } + return 0; +} + +static int ion_debug_client_open(struct inode *inode, struct file *file) +{ + return single_open(file, ion_debug_client_show, inode->i_private); +} + +static const struct file_operations debug_client_fops = { + .open = ion_debug_client_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct ion_client *ion_client_lookup(struct ion_device *dev, + struct task_struct *task) +{ + struct rb_node *n = dev->user_clients.rb_node; + struct ion_client *client; + + mutex_lock(&dev->lock); + while (n) { + client = rb_entry(n, struct ion_client, node); + if (task == client->task) { + ion_client_get(client); + mutex_unlock(&dev->lock); + return client; + } else if (task < client->task) { + n = n->rb_left; + } else if (task > client->task) { + n = n->rb_right; + } + } + mutex_unlock(&dev->lock); + return NULL; +} + +struct ion_client *ion_client_create(struct ion_device *dev, + unsigned int heap_mask, + const char *name) +{ + struct ion_client *client; + struct task_struct *task; + struct rb_node **p; + struct rb_node *parent = NULL; + struct ion_client *entry; + char debug_name[64]; + pid_t pid; + + get_task_struct(current->group_leader); + task_lock(current->group_leader); + pid = task_pid_nr(current->group_leader); + /* don't bother to store task struct for kernel threads, + they can't be killed anyway */ + if (current->group_leader->flags & PF_KTHREAD) { + put_task_struct(current->group_leader); + task = NULL; + } else { + task = current->group_leader; + } + task_unlock(current->group_leader); + + /* if this isn't a kernel thread, see if a client already + exists */ + if (task) { + client = ion_client_lookup(dev, task); + if (!IS_ERR_OR_NULL(client)) { + put_task_struct(current->group_leader); + return client; + } + } + + client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); + if (!client) { + put_task_struct(current->group_leader); + return ERR_PTR(-ENOMEM); + } + + client->dev = dev; + client->handles = RB_ROOT; + mutex_init(&client->lock); + client->name = name; + client->heap_mask = heap_mask; + client->task = task; + client->pid = pid; + kref_init(&client->ref); + + mutex_lock(&dev->lock); + if (task) { + p = &dev->user_clients.rb_node; + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_client, node); + + if (task < entry->task) + p = &(*p)->rb_left; + else if (task > entry->task) + p = &(*p)->rb_right; + } + rb_link_node(&client->node, parent, p); + rb_insert_color(&client->node, &dev->user_clients); + } else { + p = &dev->kernel_clients.rb_node; + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_client, node); + + if (client < entry) + p = &(*p)->rb_left; + else if (client > entry) + p = &(*p)->rb_right; + } + rb_link_node(&client->node, parent, p); + rb_insert_color(&client->node, &dev->kernel_clients); + } + + snprintf(debug_name, 64, "%u", client->pid); + client->debug_root = debugfs_create_file(debug_name, 0664, + dev->debug_root, client, + &debug_client_fops); + mutex_unlock(&dev->lock); + + return client; +} + +static void _ion_client_destroy(struct kref *kref) +{ + struct ion_client *client = container_of(kref, struct ion_client, ref); + struct ion_device *dev = client->dev; + struct rb_node *n; + + pr_debug("%s: %d\n", __func__, __LINE__); + while ((n = rb_first(&client->handles))) { + struct ion_handle *handle = rb_entry(n, struct ion_handle, + node); + ion_handle_destroy(&handle->ref); + } + mutex_lock(&dev->lock); + if (client->task) { + rb_erase(&client->node, &dev->user_clients); + put_task_struct(client->task); + } else { + rb_erase(&client->node, &dev->kernel_clients); + } + debugfs_remove_recursive(client->debug_root); + mutex_unlock(&dev->lock); + + kfree(client); +} + +static void ion_client_get(struct ion_client *client) +{ + kref_get(&client->ref); +} + +static int ion_client_put(struct ion_client *client) +{ + return kref_put(&client->ref, _ion_client_destroy); +} + +void ion_client_destroy(struct ion_client *client) +{ + ion_client_put(client); +} + +static int ion_share_release(struct inode *inode, struct file* file) +{ + struct ion_buffer *buffer = file->private_data; + + pr_debug("%s: %d\n", __func__, __LINE__); + /* drop the reference to the buffer -- this prevents the + buffer from going away because the client holding it exited + while it was being passed */ + ion_buffer_put(buffer); + return 0; +} + +static void ion_vma_open(struct vm_area_struct *vma) +{ + + struct ion_buffer *buffer = vma->vm_file->private_data; + struct ion_handle *handle = vma->vm_private_data; + struct ion_client *client; + + pr_debug("%s: %d\n", __func__, __LINE__); + /* check that the client still exists and take a reference so + it can't go away until this vma is closed */ + client = ion_client_lookup(buffer->dev, current->group_leader); + if (IS_ERR_OR_NULL(client)) { + vma->vm_private_data = NULL; + return; + } + pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", + __func__, __LINE__, + atomic_read(&client->ref.refcount), + atomic_read(&handle->ref.refcount), + atomic_read(&buffer->ref.refcount)); +} + +static void ion_vma_close(struct vm_area_struct *vma) +{ + struct ion_handle *handle = vma->vm_private_data; + struct ion_buffer *buffer = vma->vm_file->private_data; + struct ion_client *client; + + pr_debug("%s: %d\n", __func__, __LINE__); + /* this indicates the client is gone, nothing to do here */ + if (!handle) + return; + client = handle->client; + pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", + __func__, __LINE__, + atomic_read(&client->ref.refcount), + atomic_read(&handle->ref.refcount), + atomic_read(&buffer->ref.refcount)); + ion_handle_put(handle); + ion_client_put(client); + pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", + __func__, __LINE__, + atomic_read(&client->ref.refcount), + atomic_read(&handle->ref.refcount), + atomic_read(&buffer->ref.refcount)); +} + +static struct vm_operations_struct ion_vm_ops = { + .open = ion_vma_open, + .close = ion_vma_close, +}; + +static int ion_share_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct ion_buffer *buffer = file->private_data; + unsigned long size = vma->vm_end - vma->vm_start; + struct ion_client *client; + struct ion_handle *handle; + int ret; + + pr_debug("%s: %d\n", __func__, __LINE__); + /* make sure the client still exists, it's possible for the client to + have gone away but the map/share fd still to be around, take + a reference to it so it can't go away while this mapping exists */ + client = ion_client_lookup(buffer->dev, current->group_leader); + if (IS_ERR_OR_NULL(client)) { + pr_err("%s: trying to mmap an ion handle in a process with no " + "ion client\n", __func__); + return -EINVAL; + } + + if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) > + buffer->size)) { + pr_err("%s: trying to map larger area than handle has available" + "\n", __func__); + ret = -EINVAL; + goto err; + } + + /* find the handle and take a reference to it */ + handle = ion_import(client, buffer); + if (IS_ERR_OR_NULL(handle)) { + ret = -EINVAL; + goto err; + } + + if (!handle->buffer->heap->ops->map_user) { + pr_err("%s: this heap does not define a method for mapping " + "to userspace\n", __func__); + ret = -EINVAL; + goto err1; + } + + mutex_lock(&buffer->lock); + /* now map it to userspace */ + ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); + mutex_unlock(&buffer->lock); + if (ret) { + pr_err("%s: failure mapping buffer to userspace\n", + __func__); + goto err1; + } + + vma->vm_ops = &ion_vm_ops; + /* move the handle into the vm_private_data so we can access it from + vma_open/close */ + vma->vm_private_data = handle; + pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", + __func__, __LINE__, + atomic_read(&client->ref.refcount), + atomic_read(&handle->ref.refcount), + atomic_read(&buffer->ref.refcount)); + return 0; + +err1: + /* drop the reference to the handle */ + ion_handle_put(handle); +err: + /* drop the reference to the client */ + ion_client_put(client); + return ret; +} + +static const struct file_operations ion_share_fops = { + .owner = THIS_MODULE, + .release = ion_share_release, + .mmap = ion_share_mmap, +}; + +static int ion_ioctl_share(struct file *parent, struct ion_client *client, + struct ion_handle *handle) +{ + int fd = get_unused_fd(); + struct file *file; + + if (fd < 0) + return -ENFILE; + + file = anon_inode_getfile("ion_share_fd", &ion_share_fops, + handle->buffer, O_RDWR); + if (IS_ERR_OR_NULL(file)) + goto err; + ion_buffer_get(handle->buffer); + fd_install(fd, file); + + return fd; + +err: + put_unused_fd(fd); + return -ENFILE; +} + +static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct ion_client *client = filp->private_data; + + switch (cmd) { + case ION_IOC_ALLOC: + { + struct ion_allocation_data data; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) + return -EFAULT; + data.handle = ion_alloc(client, data.len, data.align, + data.flags); + if (copy_to_user((void __user *)arg, &data, sizeof(data))) + return -EFAULT; + break; + } + case ION_IOC_FREE: + { + struct ion_handle_data data; + bool valid; + + if (copy_from_user(&data, (void __user *)arg, + sizeof(struct ion_handle_data))) + return -EFAULT; + mutex_lock(&client->lock); + valid = ion_handle_validate(client, data.handle); + mutex_unlock(&client->lock); + if (!valid) + return -EINVAL; + ion_free(client, data.handle); + break; + } + case ION_IOC_MAP: + case ION_IOC_SHARE: + { + struct ion_fd_data data; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) + return -EFAULT; + mutex_lock(&client->lock); + if (!ion_handle_validate(client, data.handle)) { + pr_err("%s: invalid handle passed to share ioctl.\n", + __func__); + mutex_unlock(&client->lock); + return -EINVAL; + } + data.fd = ion_ioctl_share(filp, client, data.handle); + mutex_unlock(&client->lock); + if (copy_to_user((void __user *)arg, &data, sizeof(data))) + return -EFAULT; + break; + } + case ION_IOC_IMPORT: + { + struct ion_fd_data data; + if (copy_from_user(&data, (void __user *)arg, + sizeof(struct ion_fd_data))) + return -EFAULT; + + data.handle = ion_import_fd(client, data.fd); + if (IS_ERR(data.handle)) + data.handle = NULL; + if (copy_to_user((void __user *)arg, &data, + sizeof(struct ion_fd_data))) + return -EFAULT; + break; + } + case ION_IOC_CUSTOM: + { + struct ion_device *dev = client->dev; + struct ion_custom_data data; + + if (!dev->custom_ioctl) + return -ENOTTY; + if (copy_from_user(&data, (void __user *)arg, + sizeof(struct ion_custom_data))) + return -EFAULT; + return dev->custom_ioctl(client, data.cmd, data.arg); + } + default: + return -ENOTTY; + } + return 0; +} + +static int ion_release(struct inode *inode, struct file *file) +{ + struct ion_client *client = file->private_data; + + pr_debug("%s: %d\n", __func__, __LINE__); + ion_client_put(client); + return 0; +} + +static int ion_open(struct inode *inode, struct file *file) +{ + struct miscdevice *miscdev = file->private_data; + struct ion_device *dev = container_of(miscdev, struct ion_device, dev); + struct ion_client *client; + + pr_debug("%s: %d\n", __func__, __LINE__); + client = ion_client_create(dev, -1, "user"); + if (IS_ERR_OR_NULL(client)) + return PTR_ERR(client); + file->private_data = client; + + return 0; +} + +static const struct file_operations ion_fops = { + .owner = THIS_MODULE, + .open = ion_open, + .release = ion_release, + .unlocked_ioctl = ion_ioctl, +}; + +static size_t ion_debug_heap_total(struct ion_client *client, + enum ion_heap_type type) +{ + size_t size = 0; + struct rb_node *n; + + mutex_lock(&client->lock); + for (n = rb_first(&client->handles); n; n = rb_next(n)) { + struct ion_handle *handle = rb_entry(n, + struct ion_handle, + node); + if (handle->buffer->heap->type == type) + size += handle->buffer->size; + } + mutex_unlock(&client->lock); + return size; +} + +static int ion_debug_heap_show(struct seq_file *s, void *unused) +{ + struct ion_heap *heap = s->private; + struct ion_device *dev = heap->dev; + struct rb_node *n; + + seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size"); + for (n = rb_first(&dev->user_clients); n; n = rb_next(n)) { + struct ion_client *client = rb_entry(n, struct ion_client, + node); + char task_comm[TASK_COMM_LEN]; + size_t size = ion_debug_heap_total(client, heap->type); + if (!size) + continue; + + get_task_comm(task_comm, client->task); + seq_printf(s, "%16.s %16u %16u\n", task_comm, client->pid, + size); + } + + for (n = rb_first(&dev->kernel_clients); n; n = rb_next(n)) { + struct ion_client *client = rb_entry(n, struct ion_client, + node); + size_t size = ion_debug_heap_total(client, heap->type); + if (!size) + continue; + seq_printf(s, "%16.s %16u %16u\n", client->name, client->pid, + size); + } + return 0; +} + +static int ion_debug_heap_open(struct inode *inode, struct file *file) +{ + return single_open(file, ion_debug_heap_show, inode->i_private); +} + +static const struct file_operations debug_heap_fops = { + .open = ion_debug_heap_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) +{ + struct rb_node **p = &dev->heaps.rb_node; + struct rb_node *parent = NULL; + struct ion_heap *entry; + + heap->dev = dev; + mutex_lock(&dev->lock); + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_heap, node); + + if (heap->id < entry->id) { + p = &(*p)->rb_left; + } else if (heap->id > entry->id ) { + p = &(*p)->rb_right; + } else { + pr_err("%s: can not insert multiple heaps with " + "id %d\n", __func__, heap->id); + goto end; + } + } + + rb_link_node(&heap->node, parent, p); + rb_insert_color(&heap->node, &dev->heaps); + debugfs_create_file(heap->name, 0664, dev->debug_root, heap, + &debug_heap_fops); +end: + mutex_unlock(&dev->lock); +} + +struct ion_device *ion_device_create(long (*custom_ioctl) + (struct ion_client *client, + unsigned int cmd, + unsigned long arg)) +{ + struct ion_device *idev; + int ret; + + idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL); + if (!idev) + return ERR_PTR(-ENOMEM); + + idev->dev.minor = MISC_DYNAMIC_MINOR; + idev->dev.name = "ion"; + idev->dev.fops = &ion_fops; + idev->dev.parent = NULL; + ret = misc_register(&idev->dev); + if (ret) { + pr_err("ion: failed to register misc device.\n"); + return ERR_PTR(ret); + } + + idev->debug_root = debugfs_create_dir("ion", NULL); + if (IS_ERR_OR_NULL(idev->debug_root)) + pr_err("ion: failed to create debug files.\n"); + + idev->custom_ioctl = custom_ioctl; + idev->buffers = RB_ROOT; + mutex_init(&idev->lock); + idev->heaps = RB_ROOT; + idev->user_clients = RB_ROOT; + idev->kernel_clients = RB_ROOT; + return idev; +} + +void ion_device_destroy(struct ion_device *dev) +{ + misc_deregister(&dev->dev); + /* XXX need to free the heaps and clients ? */ + kfree(dev); +} diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h new file mode 100644 index 000000000000..60b25439af50 --- /dev/null +++ b/drivers/staging/android/ion/ion.h @@ -0,0 +1,344 @@ +/* + * drivers/staging/android/ion/ion.h + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#ifndef _LINUX_ION_H +#define _LINUX_ION_H + +#include + +struct ion_handle; +/** + * enum ion_heap_types - list of all possible types of heaps + * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc + * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc + * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved + * carveout heap, allocations are physically + * contiguous + * @ION_HEAP_END: helper for iterating over heaps + */ +enum ion_heap_type { + ION_HEAP_TYPE_SYSTEM, + ION_HEAP_TYPE_SYSTEM_CONTIG, + ION_HEAP_TYPE_CARVEOUT, + ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always + are at the end of this enum */ + ION_NUM_HEAPS, +}; + +#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) +#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) +#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) + +#ifdef __KERNEL__ +struct ion_device; +struct ion_heap; +struct ion_mapper; +struct ion_client; +struct ion_buffer; + +/* This should be removed some day when phys_addr_t's are fully + plumbed in the kernel, and all instances of ion_phys_addr_t should + be converted to phys_addr_t. For the time being many kernel interfaces + do not accept phys_addr_t's that would have to */ +#define ion_phys_addr_t unsigned long + +/** + * struct ion_platform_heap - defines a heap in the given platform + * @type: type of the heap from ion_heap_type enum + * @id: unique identifier for heap. When allocating (lower numbers + * will be allocated from first) + * @name: used for debug purposes + * @base: base address of heap in physical memory if applicable + * @size: size of the heap in bytes if applicable + * + * Provided by the board file. + */ +struct ion_platform_heap { + enum ion_heap_type type; + unsigned int id; + const char *name; + ion_phys_addr_t base; + size_t size; +}; + +/** + * struct ion_platform_data - array of platform heaps passed from board file + * @nr: number of structures in the array + * @heaps: array of platform_heap structions + * + * Provided by the board file in the form of platform data to a platform device. + */ +struct ion_platform_data { + int nr; + struct ion_platform_heap heaps[]; +}; + +/** + * ion_client_create() - allocate a client and returns it + * @dev: the global ion device + * @heap_mask: mask of heaps this client can allocate from + * @name: used for debugging + */ +struct ion_client *ion_client_create(struct ion_device *dev, + unsigned int heap_mask, const char *name); + +/** + * ion_client_destroy() - free's a client and all it's handles + * @client: the client + * + * Free the provided client and all it's resources including + * any handles it is holding. + */ +void ion_client_destroy(struct ion_client *client); + +/** + * ion_alloc - allocate ion memory + * @client: the client + * @len: size of the allocation + * @align: requested allocation alignment, lots of hardware blocks have + * alignment requirements of some kind + * @flags: mask of heaps to allocate from, if multiple bits are set + * heaps will be tried in order from lowest to highest order bit + * + * Allocate memory in one of the heaps provided in heap mask and return + * an opaque handle to it. + */ +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + size_t align, unsigned int flags); + +/** + * ion_free - free a handle + * @client: the client + * @handle: the handle to free + * + * Free the provided handle. + */ +void ion_free(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_phys - returns the physical address and len of a handle + * @client: the client + * @handle: the handle + * @addr: a pointer to put the address in + * @len: a pointer to put the length in + * + * This function queries the heap for a particular handle to get the + * handle's physical address. It't output is only correct if + * a heap returns physically contiguous memory -- in other cases + * this api should not be implemented -- ion_map_dma should be used + * instead. Returns -EINVAL if the handle is invalid. This has + * no implications on the reference counting of the handle -- + * the returned value may not be valid if the caller is not + * holding a reference. + */ +int ion_phys(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len); + +/** + * ion_map_kernel - create mapping for the given handle + * @client: the client + * @handle: handle to map + * + * Map the given handle into the kernel and return a kernel address that + * can be used to access this address. + */ +void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_unmap_kernel() - destroy a kernel mapping for a handle + * @client: the client + * @handle: handle to unmap + */ +void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_map_dma - create a dma mapping for a given handle + * @client: the client + * @handle: handle to map + * + * Return an sglist describing the given handle + */ +struct scatterlist *ion_map_dma(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_unmap_dma() - destroy a dma mapping for a handle + * @client: the client + * @handle: handle to unmap + */ +void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_share() - given a handle, obtain a buffer to pass to other clients + * @client: the client + * @handle: the handle to share + * + * Given a handle, return a buffer, which exists in a global name + * space, and can be passed to other clients. Should be passed into ion_import + * to obtain a new handle for this buffer. + * + * NOTE: This function does do not an extra reference. The burden is on the + * caller to make sure the buffer doesn't go away while it's being passed to + * another client. That is, ion_free should not be called on this handle until + * the buffer has been imported into the other client. + */ +struct ion_buffer *ion_share(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_import() - given an buffer in another client, import it + * @client: this blocks client + * @buffer: the buffer to import (as obtained from ion_share) + * + * Given a buffer, add it to the client and return the handle to use to refer + * to it further. This is called to share a handle from one kernel client to + * another. + */ +struct ion_handle *ion_import(struct ion_client *client, + struct ion_buffer *buffer); + +/** + * ion_import_fd() - given an fd obtained via ION_IOC_SHARE ioctl, import it + * @client: this blocks client + * @fd: the fd + * + * A helper function for drivers that will be recieving ion buffers shared + * with them from userspace. These buffers are represented by a file + * descriptor obtained as the return from the ION_IOC_SHARE ioctl. + * This function coverts that fd into the underlying buffer, and returns + * the handle to use to refer to it further. + */ +struct ion_handle *ion_import_fd(struct ion_client *client, int fd); +#endif /* __KERNEL__ */ + +/** + * DOC: Ion Userspace API + * + * create a client by opening /dev/ion + * most operations handled via following ioctls + * + */ + +/** + * struct ion_allocation_data - metadata passed from userspace for allocations + * @len: size of the allocation + * @align: required alignment of the allocation + * @flags: flags passed to heap + * @handle: pointer that will be populated with a cookie to use to refer + * to this allocation + * + * Provided by userspace as an argument to the ioctl + */ +struct ion_allocation_data { + size_t len; + size_t align; + unsigned int flags; + struct ion_handle *handle; +}; + +/** + * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair + * @handle: a handle + * @fd: a file descriptor representing that handle + * + * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with + * the handle returned from ion alloc, and the kernel returns the file + * descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace + * provides the file descriptor and the kernel returns the handle. + */ +struct ion_fd_data { + struct ion_handle *handle; + int fd; +}; + +/** + * struct ion_handle_data - a handle passed to/from the kernel + * @handle: a handle + */ +struct ion_handle_data { + struct ion_handle *handle; +}; + +/** + * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl + * @cmd: the custom ioctl function to call + * @arg: additional data to pass to the custom ioctl, typically a user + * pointer to a predefined structure + * + * This works just like the regular cmd and arg fields of an ioctl. + */ +struct ion_custom_data { + unsigned int cmd; + unsigned long arg; +}; + +#define ION_IOC_MAGIC 'I' + +/** + * DOC: ION_IOC_ALLOC - allocate memory + * + * Takes an ion_allocation_data struct and returns it with the handle field + * populated with the opaque handle for the allocation. + */ +#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ + struct ion_allocation_data) + +/** + * DOC: ION_IOC_FREE - free memory + * + * Takes an ion_handle_data struct and frees the handle. + */ +#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) + +/** + * DOC: ION_IOC_MAP - get a file descriptor to mmap + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be used as an argument to mmap. + */ +#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data) + +/** + * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be passed to another process. The corresponding opaque handle can + * be retrieved via ION_IOC_IMPORT. + */ +#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) + +/** + * DOC: ION_IOC_IMPORT - imports a shared file descriptor + * + * Takes an ion_fd_data struct with the fd field populated with a valid file + * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle + * filed set to the corresponding opaque handle. + */ +#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, int) + +/** + * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl + * + * Takes the argument of the architecture specific ioctl to call and + * passes appropriate userdata for that ioctl + */ +#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) + +#endif /* _LINUX_ION_H */ diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c new file mode 100644 index 000000000000..6d02cd306602 --- /dev/null +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -0,0 +1,162 @@ +/* + * drivers/staging/android/ion/ion_carveout_heap.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" + +#include + +struct ion_carveout_heap { + struct ion_heap heap; + struct gen_pool *pool; + ion_phys_addr_t base; +}; + +ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, + unsigned long size, + unsigned long align) +{ + struct ion_carveout_heap *carveout_heap = + container_of(heap, struct ion_carveout_heap, heap); + unsigned long offset = gen_pool_alloc(carveout_heap->pool, size); + + if (!offset) + return ION_CARVEOUT_ALLOCATE_FAIL; + + return offset; +} + +void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, + unsigned long size) +{ + struct ion_carveout_heap *carveout_heap = + container_of(heap, struct ion_carveout_heap, heap); + + if (addr == ION_CARVEOUT_ALLOCATE_FAIL) + return; + gen_pool_free(carveout_heap->pool, addr, size); +} + +static int ion_carveout_heap_phys(struct ion_heap *heap, + struct ion_buffer *buffer, + ion_phys_addr_t *addr, size_t *len) +{ + *addr = buffer->priv_phys; + *len = buffer->size; + return 0; +} + +static int ion_carveout_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) +{ + buffer->priv_phys = ion_carveout_allocate(heap, size, align); + return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; +} + +static void ion_carveout_heap_free(struct ion_buffer *buffer) +{ + struct ion_heap *heap = buffer->heap; + + ion_carveout_free(heap, buffer->priv_phys, buffer->size); + buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; +} + +struct scatterlist *ion_carveout_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return ERR_PTR(-EINVAL); +} + +void ion_carveout_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return; +} + +void *ion_carveout_heap_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return __arch_ioremap(buffer->priv_phys, buffer->size, + MT_MEMORY_NONCACHED); +} + +void ion_carveout_heap_unmap_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + __arch_iounmap(buffer->vaddr); + buffer->vaddr = NULL; + return; +} + +int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + return remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff, + buffer->size, + pgprot_noncached(vma->vm_page_prot)); +} + +static struct ion_heap_ops carveout_heap_ops = { + .allocate = ion_carveout_heap_allocate, + .free = ion_carveout_heap_free, + .phys = ion_carveout_heap_phys, + .map_user = ion_carveout_heap_map_user, + .map_kernel = ion_carveout_heap_map_kernel, + .unmap_kernel = ion_carveout_heap_unmap_kernel, +}; + +struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) +{ + struct ion_carveout_heap *carveout_heap; + + carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL); + if (!carveout_heap) + return ERR_PTR(-ENOMEM); + + carveout_heap->pool = gen_pool_create(12, -1); + if (!carveout_heap->pool) { + kfree(carveout_heap); + return ERR_PTR(-ENOMEM); + } + carveout_heap->base = heap_data->base; + gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size, + -1); + carveout_heap->heap.ops = &carveout_heap_ops; + carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT; + + return &carveout_heap->heap; +} + +void ion_carveout_heap_destroy(struct ion_heap *heap) +{ + struct ion_carveout_heap *carveout_heap = + container_of(heap, struct ion_carveout_heap, heap); + + gen_pool_destroy(carveout_heap->pool); + kfree(carveout_heap); + carveout_heap = NULL; +} diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c new file mode 100644 index 000000000000..4f7caa87bca9 --- /dev/null +++ b/drivers/staging/android/ion/ion_heap.c @@ -0,0 +1,72 @@ +/* + * drivers/staging/android/ion/ion_heap.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include "ion.h" +#include "ion_priv.h" + +struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) +{ + struct ion_heap *heap = NULL; + + switch (heap_data->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: + heap = ion_system_contig_heap_create(heap_data); + break; + case ION_HEAP_TYPE_SYSTEM: + heap = ion_system_heap_create(heap_data); + break; + case ION_HEAP_TYPE_CARVEOUT: + heap = ion_carveout_heap_create(heap_data); + break; + default: + pr_err("%s: Invalid heap type %d\n", __func__, + heap_data->type); + return ERR_PTR(-EINVAL); + } + + if (IS_ERR_OR_NULL(heap)) { + pr_err("%s: error creating heap %s type %d base %lu size %u\n", + __func__, heap_data->name, heap_data->type, + heap_data->base, heap_data->size); + return ERR_PTR(-EINVAL); + } + + heap->name = heap_data->name; + heap->id = heap_data->id; + return heap; +} + +void ion_heap_destroy(struct ion_heap *heap) +{ + if (!heap) + return; + + switch (heap->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: + ion_system_contig_heap_destroy(heap); + break; + case ION_HEAP_TYPE_SYSTEM: + ion_system_heap_destroy(heap); + break; + case ION_HEAP_TYPE_CARVEOUT: + ion_carveout_heap_destroy(heap); + break; + default: + pr_err("%s: Invalid heap type %d\n", __func__, + heap->type); + } +} diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h new file mode 100644 index 000000000000..cbd9f03b5870 --- /dev/null +++ b/drivers/staging/android/ion/ion_priv.h @@ -0,0 +1,185 @@ +/* + * drivers/staging/android/ion/ion_priv.h + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#ifndef _ION_PRIV_H +#define _ION_PRIV_H + +#include +#include +#include +#include + +#include "ion.h" + +struct ion_mapping; + +struct ion_dma_mapping { + struct kref ref; + struct scatterlist *sglist; +}; + +struct ion_kernel_mapping { + struct kref ref; + void *vaddr; +}; + +struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); + +/** + * struct ion_buffer - metadata for a particular buffer + * @ref: refernce count + * @node: node in the ion_device buffers tree + * @dev: back pointer to the ion_device + * @heap: back pointer to the heap the buffer came from + * @flags: buffer specific flags + * @size: size of the buffer + * @priv_virt: private data to the buffer representable as + * a void * + * @priv_phys: private data to the buffer representable as + * an ion_phys_addr_t (and someday a phys_addr_t) + * @lock: protects the buffers cnt fields + * @kmap_cnt: number of times the buffer is mapped to the kernel + * @vaddr: the kenrel mapping if kmap_cnt is not zero + * @dmap_cnt: number of times the buffer is mapped for dma + * @sglist: the scatterlist for the buffer is dmap_cnt is not zero +*/ +struct ion_buffer { + struct kref ref; + struct rb_node node; + struct ion_device *dev; + struct ion_heap *heap; + unsigned long flags; + size_t size; + union { + void *priv_virt; + ion_phys_addr_t priv_phys; + }; + struct mutex lock; + int kmap_cnt; + void *vaddr; + int dmap_cnt; + struct scatterlist *sglist; +}; + +/** + * struct ion_heap_ops - ops to operate on a given heap + * @allocate: allocate memory + * @free: free memory + * @phys get physical address of a buffer (only define on + * physically contiguous heaps) + * @map_dma map the memory for dma to a scatterlist + * @unmap_dma unmap the memory for dma + * @map_kernel map memory to the kernel + * @unmap_kernel unmap memory to the kernel + * @map_user map memory to userspace + */ +struct ion_heap_ops { + int (*allocate) (struct ion_heap *heap, + struct ion_buffer *buffer, unsigned long len, + unsigned long align, unsigned long flags); + void (*free) (struct ion_buffer *buffer); + int (*phys) (struct ion_heap *heap, struct ion_buffer *buffer, + ion_phys_addr_t *addr, size_t *len); + struct scatterlist *(*map_dma) (struct ion_heap *heap, + struct ion_buffer *buffer); + void (*unmap_dma) (struct ion_heap *heap, struct ion_buffer *buffer); + void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); + void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); + int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer, + struct vm_area_struct *vma); +}; + +/** + * struct ion_heap - represents a heap in the system + * @node: rb node to put the heap on the device's tree of heaps + * @dev: back pointer to the ion_device + * @type: type of heap + * @ops: ops struct as above + * @id: id of heap, also indicates priority of this heap when + * allocating. These are specified by platform data and + * MUST be unique + * @name: used for debugging + * + * Represents a pool of memory from which buffers can be made. In some + * systems the only heap is regular system memory allocated via vmalloc. + * On others, some blocks might require large physically contiguous buffers + * that are allocated from a specially reserved heap. + */ +struct ion_heap { + struct rb_node node; + struct ion_device *dev; + enum ion_heap_type type; + struct ion_heap_ops *ops; + int id; + const char *name; +}; + +/** + * ion_device_create - allocates and returns an ion device + * @custom_ioctl: arch specific ioctl function if applicable + * + * returns a valid device or -PTR_ERR + */ +struct ion_device *ion_device_create(long (*custom_ioctl) + (struct ion_client *client, + unsigned int cmd, + unsigned long arg)); + +/** + * ion_device_destroy - free and device and it's resource + * @dev: the device + */ +void ion_device_destroy(struct ion_device *dev); + +/** + * ion_device_add_heap - adds a heap to the ion device + * @dev: the device + * @heap: the heap to add + */ +void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); + +/** + * functions for creating and destroying the built in ion heaps. + * architectures can add their own custom architecture specific + * heaps as appropriate. + */ + +struct ion_heap *ion_heap_create(struct ion_platform_heap *); +void ion_heap_destroy(struct ion_heap *); + +struct ion_heap *ion_system_heap_create(struct ion_platform_heap *); +void ion_system_heap_destroy(struct ion_heap *); + +struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *); +void ion_system_contig_heap_destroy(struct ion_heap *); + +struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *); +void ion_carveout_heap_destroy(struct ion_heap *); +/** + * kernel api to allocate/free from carveout -- used when carveout is + * used to back an architecture specific custom heap + */ +ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size, + unsigned long align); +void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, + unsigned long size); +/** + * The carveout heap returns physical addresses, since 0 may be a valid + * physical address, this is used to indicate allocation failed + */ +#define ION_CARVEOUT_ALLOCATE_FAIL -1 + +#endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c new file mode 100644 index 000000000000..3daa1eeb8bd8 --- /dev/null +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -0,0 +1,198 @@ +/* + * drivers/staging/android/ion/ion_system_heap.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" + +static int ion_system_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) +{ + buffer->priv_virt = vmalloc_user(size); + if (!buffer->priv_virt) + return -ENOMEM; + return 0; +} + +void ion_system_heap_free(struct ion_buffer *buffer) +{ + vfree(buffer->priv_virt); +} + +struct scatterlist *ion_system_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct scatterlist *sglist; + struct page *page; + int i; + int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; + void *vaddr = buffer->priv_virt; + + sglist = vmalloc(npages * sizeof(struct scatterlist)); + if (!sglist) + return ERR_PTR(-ENOMEM); + memset(sglist, 0, npages * sizeof(struct scatterlist)); + sg_init_table(sglist, npages); + for (i = 0; i < npages; i++) { + page = vmalloc_to_page(vaddr); + if (!page) + goto end; + sg_set_page(&sglist[i], page, PAGE_SIZE, 0); + vaddr += PAGE_SIZE; + } + /* XXX do cache maintenance for dma? */ + return sglist; +end: + vfree(sglist); + return NULL; +} + +void ion_system_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + /* XXX undo cache maintenance for dma? */ + if (buffer->sglist) + vfree(buffer->sglist); +} + +void *ion_system_heap_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return buffer->priv_virt; +} + +void ion_system_heap_unmap_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ +} + +int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff); +} + +static struct ion_heap_ops vmalloc_ops = { + .allocate = ion_system_heap_allocate, + .free = ion_system_heap_free, + .map_dma = ion_system_heap_map_dma, + .unmap_dma = ion_system_heap_unmap_dma, + .map_kernel = ion_system_heap_map_kernel, + .unmap_kernel = ion_system_heap_unmap_kernel, + .map_user = ion_system_heap_map_user, +}; + +struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) +{ + struct ion_heap *heap; + + heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL); + if (!heap) + return ERR_PTR(-ENOMEM); + heap->ops = &vmalloc_ops; + heap->type = ION_HEAP_TYPE_SYSTEM; + return heap; +} + +void ion_system_heap_destroy(struct ion_heap *heap) +{ + kfree(heap); +} + +static int ion_system_contig_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long len, + unsigned long align, + unsigned long flags) +{ + buffer->priv_virt = kzalloc(len, GFP_KERNEL); + if (!buffer->priv_virt) + return -ENOMEM; + return 0; +} + +void ion_system_contig_heap_free(struct ion_buffer *buffer) +{ + kfree(buffer->priv_virt); +} + +static int ion_system_contig_heap_phys(struct ion_heap *heap, + struct ion_buffer *buffer, + ion_phys_addr_t *addr, size_t *len) +{ + *addr = virt_to_phys(buffer->priv_virt); + *len = buffer->size; + return 0; +} + +struct scatterlist *ion_system_contig_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct scatterlist *sglist; + + sglist = vmalloc(sizeof(struct scatterlist)); + if (!sglist) + return ERR_PTR(-ENOMEM); + sg_init_table(sglist, 1); + sg_set_page(sglist, virt_to_page(buffer->priv_virt), buffer->size, 0); + return sglist; +} + +int ion_system_contig_heap_map_user(struct ion_heap *heap, + struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt)); + return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + +} + +static struct ion_heap_ops kmalloc_ops = { + .allocate = ion_system_contig_heap_allocate, + .free = ion_system_contig_heap_free, + .phys = ion_system_contig_heap_phys, + .map_dma = ion_system_contig_heap_map_dma, + .unmap_dma = ion_system_heap_unmap_dma, + .map_kernel = ion_system_heap_map_kernel, + .unmap_kernel = ion_system_heap_unmap_kernel, + .map_user = ion_system_contig_heap_map_user, +}; + +struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused) +{ + struct ion_heap *heap; + + heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL); + if (!heap) + return ERR_PTR(-ENOMEM); + heap->ops = &kmalloc_ops; + heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; + return heap; +} + +void ion_system_contig_heap_destroy(struct ion_heap *heap) +{ + kfree(heap); +} + diff --git a/drivers/staging/android/ion/ion_system_mapper.c b/drivers/staging/android/ion/ion_system_mapper.c new file mode 100644 index 000000000000..285430d2f79a --- /dev/null +++ b/drivers/staging/android/ion/ion_system_mapper.c @@ -0,0 +1,114 @@ +/* + * drivers/staging/android/ion/ion_system_mapper.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" +/* + * This mapper is valid for any heap that allocates memory that already has + * a kernel mapping, this includes vmalloc'd memory, kmalloc'd memory, + * pages obtained via io_remap, etc. + */ +static void *ion_kernel_mapper_map(struct ion_mapper *mapper, + struct ion_buffer *buffer, + struct ion_mapping **mapping) +{ + if (!((1 << buffer->heap->type) & mapper->heap_mask)) { + pr_err("%s: attempting to map an unsupported heap\n", __func__); + return ERR_PTR(-EINVAL); + } + /* XXX REVISIT ME!!! */ + *((unsigned long *)mapping) = (unsigned long)buffer->priv; + return buffer->priv; +} + +static void ion_kernel_mapper_unmap(struct ion_mapper *mapper, + struct ion_buffer *buffer, + struct ion_mapping *mapping) +{ + if (!((1 << buffer->heap->type) & mapper->heap_mask)) + pr_err("%s: attempting to unmap an unsupported heap\n", + __func__); +} + +static void *ion_kernel_mapper_map_kernel(struct ion_mapper *mapper, + struct ion_buffer *buffer, + struct ion_mapping *mapping) +{ + if (!((1 << buffer->heap->type) & mapper->heap_mask)) { + pr_err("%s: attempting to unmap an unsupported heap\n", + __func__); + return ERR_PTR(-EINVAL); + } + return buffer->priv; +} + +static int ion_kernel_mapper_map_user(struct ion_mapper *mapper, + struct ion_buffer *buffer, + struct vm_area_struct *vma, + struct ion_mapping *mapping) +{ + int ret; + + switch (buffer->heap->type) { + case ION_HEAP_KMALLOC: + { + unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv)); + ret = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + break; + } + case ION_HEAP_VMALLOC: + ret = remap_vmalloc_range(vma, buffer->priv, vma->vm_pgoff); + break; + default: + pr_err("%s: attempting to map unsupported heap to userspace\n", + __func__); + return -EINVAL; + } + + return ret; +} + +static struct ion_mapper_ops ops = { + .map = ion_kernel_mapper_map, + .map_kernel = ion_kernel_mapper_map_kernel, + .map_user = ion_kernel_mapper_map_user, + .unmap = ion_kernel_mapper_unmap, +}; + +struct ion_mapper *ion_system_mapper_create(void) +{ + struct ion_mapper *mapper; + mapper = kzalloc(sizeof(struct ion_mapper), GFP_KERNEL); + if (!mapper) + return ERR_PTR(-ENOMEM); + mapper->type = ION_SYSTEM_MAPPER; + mapper->ops = &ops; + mapper->heap_mask = (1 << ION_HEAP_VMALLOC) | (1 << ION_HEAP_KMALLOC); + return mapper; +} + +void ion_system_mapper_destroy(struct ion_mapper *mapper) +{ + kfree(mapper); +} + diff --git a/drivers/staging/android/ion/tegra/Makefile b/drivers/staging/android/ion/tegra/Makefile new file mode 100644 index 000000000000..11cd003fb08f --- /dev/null +++ b/drivers/staging/android/ion/tegra/Makefile @@ -0,0 +1 @@ +obj-y += tegra_ion.o diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c new file mode 100644 index 000000000000..0849600bcc00 --- /dev/null +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -0,0 +1,96 @@ +/* + * drivers/gpu/tegra/tegra_ion.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include "../ion.h" +#include "../ion_priv.h" + +struct ion_device *idev; +struct ion_mapper *tegra_user_mapper; +int num_heaps; +struct ion_heap **heaps; + +int tegra_ion_probe(struct platform_device *pdev) +{ + struct ion_platform_data *pdata = pdev->dev.platform_data; + int err; + int i; + + num_heaps = pdata->nr; + + heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL); + + idev = ion_device_create(NULL); + if (IS_ERR_OR_NULL(idev)) { + kfree(heaps); + return PTR_ERR(idev); + } + + /* create the heaps as specified in the board file */ + for (i = 0; i < num_heaps; i++) { + struct ion_platform_heap *heap_data = &pdata->heaps[i]; + + heaps[i] = ion_heap_create(heap_data); + if (IS_ERR_OR_NULL(heaps[i])) { + err = PTR_ERR(heaps[i]); + goto err; + } + ion_device_add_heap(idev, heaps[i]); + } + platform_set_drvdata(pdev, idev); + return 0; +err: + for (i = 0; i < num_heaps; i++) { + if (heaps[i]) + ion_heap_destroy(heaps[i]); + } + kfree(heaps); + return err; +} + +int tegra_ion_remove(struct platform_device *pdev) +{ + struct ion_device *idev = platform_get_drvdata(pdev); + int i; + + ion_device_destroy(idev); + for (i = 0; i < num_heaps; i++) + ion_heap_destroy(heaps[i]); + kfree(heaps); + return 0; +} + +static struct platform_driver ion_driver = { + .probe = tegra_ion_probe, + .remove = tegra_ion_remove, + .driver = { .name = "ion-tegra" } +}; + +static int __init ion_init(void) +{ + return platform_driver_register(&ion_driver); +} + +static void __exit ion_exit(void) +{ + platform_driver_unregister(&ion_driver); +} + +module_init(ion_init); +module_exit(ion_exit); + -- cgit v1.2.3 From 0f3cbb59ec47f313e138913c89a1dd0048561355 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:23:36 -0800 Subject: gpu: ion: ion_carveout_heap: fix for 3.4 __arch_ioremap is no longer available, use __arm_ioremap instead. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 6d02cd306602..e8c4e36d5328 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -99,14 +99,14 @@ void ion_carveout_heap_unmap_dma(struct ion_heap *heap, void *ion_carveout_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { - return __arch_ioremap(buffer->priv_phys, buffer->size, + return __arm_ioremap(buffer->priv_phys, buffer->size, MT_MEMORY_NONCACHED); } void ion_carveout_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { - __arch_iounmap(buffer->vaddr); + __arm_iounmap(buffer->vaddr); buffer->vaddr = NULL; return; } -- cgit v1.2.3 From 4d5ca3299fb7b27ceb6c33a62bc10ce4d408dc0b Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:37 -0800 Subject: ion: Switch map/unmap dma api to sg_tables Switch these api's from scatterlists to sg_tables Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 16 +++---- drivers/staging/android/ion/ion.h | 6 +-- drivers/staging/android/ion/ion_priv.h | 18 ++------ drivers/staging/android/ion/ion_system_heap.c | 66 ++++++++++++++++----------- 4 files changed, 53 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d93fb33d05ed..bca8d9e925e4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -445,11 +445,11 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) return vaddr; } -struct scatterlist *ion_map_dma(struct ion_client *client, +struct sg_table *ion_map_dma(struct ion_client *client, struct ion_handle *handle) { struct ion_buffer *buffer; - struct scatterlist *sglist; + struct sg_table *table; mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { @@ -469,16 +469,16 @@ struct scatterlist *ion_map_dma(struct ion_client *client, return ERR_PTR(-ENODEV); } if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) { - sglist = buffer->heap->ops->map_dma(buffer->heap, buffer); - if (IS_ERR_OR_NULL(sglist)) + table = buffer->heap->ops->map_dma(buffer->heap, buffer); + if (IS_ERR_OR_NULL(table)) _ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt); - buffer->sglist = sglist; + buffer->sg_table = table; } else { - sglist = buffer->sglist; + table = buffer->sg_table; } mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); - return sglist; + return table; } void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) @@ -505,7 +505,7 @@ void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) mutex_lock(&buffer->lock); if (_ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt)) { buffer->heap->ops->unmap_dma(buffer->heap, buffer); - buffer->sglist = NULL; + buffer->sg_table = NULL; } mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 60b25439af50..87f6a45bcd1f 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -169,10 +169,10 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); * @client: the client * @handle: handle to map * - * Return an sglist describing the given handle + * Return an sg_table describing the given handle */ -struct scatterlist *ion_map_dma(struct ion_client *client, - struct ion_handle *handle); +struct sg_table *ion_map_dma(struct ion_client *client, + struct ion_handle *handle); /** * ion_unmap_dma() - destroy a dma mapping for a handle diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index cbd9f03b5870..7a77f6f626c8 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -24,18 +24,6 @@ #include "ion.h" -struct ion_mapping; - -struct ion_dma_mapping { - struct kref ref; - struct scatterlist *sglist; -}; - -struct ion_kernel_mapping { - struct kref ref; - void *vaddr; -}; - struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); /** @@ -54,7 +42,7 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @kmap_cnt: number of times the buffer is mapped to the kernel * @vaddr: the kenrel mapping if kmap_cnt is not zero * @dmap_cnt: number of times the buffer is mapped for dma - * @sglist: the scatterlist for the buffer is dmap_cnt is not zero + * @sg_table: the sg table for the buffer if dmap_cnt is not zero */ struct ion_buffer { struct kref ref; @@ -71,7 +59,7 @@ struct ion_buffer { int kmap_cnt; void *vaddr; int dmap_cnt; - struct scatterlist *sglist; + struct sg_table *sg_table; }; /** @@ -93,7 +81,7 @@ struct ion_heap_ops { void (*free) (struct ion_buffer *buffer); int (*phys) (struct ion_heap *heap, struct ion_buffer *buffer, ion_phys_addr_t *addr, size_t *len); - struct scatterlist *(*map_dma) (struct ion_heap *heap, + struct sg_table *(*map_dma) (struct ion_heap *heap, struct ion_buffer *buffer); void (*unmap_dma) (struct ion_heap *heap, struct ion_buffer *buffer); void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 3daa1eeb8bd8..d7e0fa0c1ef6 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -38,40 +38,46 @@ void ion_system_heap_free(struct ion_buffer *buffer) vfree(buffer->priv_virt); } -struct scatterlist *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { - struct scatterlist *sglist; - struct page *page; + struct sg_table *table; + struct scatterlist *sg; int i; int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; void *vaddr = buffer->priv_virt; + int ret; - sglist = vmalloc(npages * sizeof(struct scatterlist)); - if (!sglist) + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) return ERR_PTR(-ENOMEM); - memset(sglist, 0, npages * sizeof(struct scatterlist)); - sg_init_table(sglist, npages); - for (i = 0; i < npages; i++) { + ret = sg_alloc_table(table, npages, GFP_KERNEL); + if (ret) + goto err0; + for_each_sg(table->sgl, sg, table->nents, i) { + struct page *page; page = vmalloc_to_page(vaddr); - if (!page) - goto end; - sg_set_page(&sglist[i], page, PAGE_SIZE, 0); + if (!page) { + ret = -ENOMEM; + goto err1; + } + sg_set_page(sg, page, PAGE_SIZE, 0); vaddr += PAGE_SIZE; } - /* XXX do cache maintenance for dma? */ - return sglist; -end: - vfree(sglist); - return NULL; + return table; +err1: + sg_free_table(table); +err0: + kfree(table); + return ERR_PTR(ret); } void ion_system_heap_unmap_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - /* XXX undo cache maintenance for dma? */ - if (buffer->sglist) - vfree(buffer->sglist); + if (buffer->sg_table) + sg_free_table(buffer->sg_table); + kfree(buffer->sg_table); } void *ion_system_heap_map_kernel(struct ion_heap *heap, @@ -144,17 +150,23 @@ static int ion_system_contig_heap_phys(struct ion_heap *heap, return 0; } -struct scatterlist *ion_system_contig_heap_map_dma(struct ion_heap *heap, +struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - struct scatterlist *sglist; + struct sg_table *table; + int ret; - sglist = vmalloc(sizeof(struct scatterlist)); - if (!sglist) + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) return ERR_PTR(-ENOMEM); - sg_init_table(sglist, 1); - sg_set_page(sglist, virt_to_page(buffer->priv_virt), buffer->size, 0); - return sglist; + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) { + kfree(table); + return ERR_PTR(ret); + } + sg_set_page(table->sgl, virt_to_page(buffer->priv_virt), buffer->size, + 0); + return table; } int ion_system_contig_heap_map_user(struct ion_heap *heap, -- cgit v1.2.3 From 2991b7a044c82252e7b6456321515ebdbdf3acac Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:38 -0800 Subject: ion: Add reserve function to ion Rather than requiring each platform call memblock_remove or reserve from the board file, add this to ion Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 17 +++++++++++++++++ drivers/staging/android/ion/ion.h | 11 +++++++++++ 2 files changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bca8d9e925e4..004c0d4f7353 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1185,3 +1186,19 @@ void ion_device_destroy(struct ion_device *dev) /* XXX need to free the heaps and clients ? */ kfree(dev); } + +void __init ion_reserve(struct ion_platform_data *data) +{ + int i, ret; + + for (i = 0; i < data->nr; i++) { + if (data->heaps[i].size == 0) + continue; + ret = memblock_reserve(data->heaps[i].base, + data->heaps[i].size); + if (ret) + pr_err("memblock reserve of %x@%lx failed\n", + data->heaps[i].size, + data->heaps[i].base); + } +} diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 87f6a45bcd1f..4e012b86a839 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -86,6 +86,17 @@ struct ion_platform_data { struct ion_platform_heap heaps[]; }; +/** + * ion_reserve() - reserve memory for ion heaps if applicable + * @data: platform data specifying starting physical address and + * size + * + * Calls memblock reserve to set aside memory for heaps that are + * located at specific memory addresses or of specfic sizes not + * managed by the kernel + */ +void ion_reserve(struct ion_platform_data *data); + /** * ion_client_create() - allocate a client and returns it * @dev: the global ion device -- cgit v1.2.3 From 54ac078421ae89b8ac28357bb615262174aec255 Mon Sep 17 00:00:00 2001 From: KyongHo Cho Date: Fri, 13 Dec 2013 14:23:39 -0800 Subject: gpu: ion: several bugfixes and enhancements of ION 1. Verifying if the size of memory allocation in ion_alloc() is aligned by PAGE_SIZE at least. If it is not, this change makes the size to be aligned by PAGE_SIZE. 2. Unmaps all mappings to the kernel and DMA address spaces when destroying ion_buffer in ion_buffer_destroy(). This prevents leaks in those virtual address spaces. 3. Makes the return value of ion_alloc() to be explicit Linux error code when it fails to allocate a buffer. 4. Makes ion_alloc() implementation simpler. Removes 'goto' statement and relavant call to ion_buffer_put(). 5. Checks if the task is valid before calling put_task_struct() due to failure on creating a ion client in ion_client_create(). 6. Returns error when buffer allocation requested by userspace is failed. Signed-off-by: KyongHo Cho [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 52 +++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 004c0d4f7353..3c9ca318e024 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -166,6 +166,12 @@ static void ion_buffer_destroy(struct kref *kref) struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); struct ion_device *dev = buffer->dev; + if (WARN_ON(buffer->kmap_cnt > 0)) + buffer->heap->ops->unmap_kernel(buffer->heap, buffer); + + if (WARN_ON(buffer->dmap_cnt > 0)) + buffer->heap->ops->unmap_dma(buffer->heap, buffer); + buffer->heap->ops->free(buffer); mutex_lock(&dev->lock); rb_erase(&buffer->node, &dev->buffers); @@ -296,6 +302,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, * request of the caller allocate from it. Repeat until allocate has * succeeded or all heaps have been tried */ + if (WARN_ON(!len)) + return ERR_PTR(-EINVAL); + + len = PAGE_ALIGN(len); + mutex_lock(&dev->lock); for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) { struct ion_heap *heap = rb_entry(n, struct ion_heap, node); @@ -311,27 +322,26 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } mutex_unlock(&dev->lock); - if (IS_ERR_OR_NULL(buffer)) + if (buffer == NULL) + return ERR_PTR(-ENODEV); + + if (IS_ERR(buffer)) return ERR_PTR(PTR_ERR(buffer)); handle = ion_handle_create(client, buffer); - if (IS_ERR_OR_NULL(handle)) - goto end; - /* * ion_buffer_create will create a buffer with a ref_cnt of 1, * and ion_handle_create will take a second reference, drop one here */ ion_buffer_put(buffer); - mutex_lock(&client->lock); - ion_handle_add(client, handle); - mutex_unlock(&client->lock); - return handle; + if (!IS_ERR(handle)) { + mutex_lock(&client->lock); + ion_handle_add(client, handle); + mutex_unlock(&client->lock); + } -end: - ion_buffer_put(buffer); return handle; } @@ -680,7 +690,8 @@ struct ion_client *ion_client_create(struct ion_device *dev, client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); if (!client) { - put_task_struct(current->group_leader); + if (task) + put_task_struct(current->group_leader); return ERR_PTR(-ENOMEM); } @@ -798,6 +809,15 @@ static void ion_vma_open(struct vm_area_struct *vma) vma->vm_private_data = NULL; return; } + + if (!ion_handle_validate(client, handle)) { + ion_client_put(client); + vma->vm_private_data = NULL; + return; + } + + ion_handle_get(handle); + pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", __func__, __LINE__, atomic_read(&client->ref.refcount), @@ -919,7 +939,7 @@ static int ion_ioctl_share(struct file *parent, struct ion_client *client, struct file *file; if (fd < 0) - return -ENFILE; + return fd; file = anon_inode_getfile("ion_share_fd", &ion_share_fops, handle->buffer, O_RDWR); @@ -948,8 +968,14 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; data.handle = ion_alloc(client, data.len, data.align, data.flags); - if (copy_to_user((void __user *)arg, &data, sizeof(data))) + + if (IS_ERR(data.handle)) + return PTR_ERR(data.handle); + + if (copy_to_user((void __user *)arg, &data, sizeof(data))) { + ion_free(client, data.handle); return -EFAULT; + } break; } case ION_IOC_FREE: -- cgit v1.2.3 From b892bf75b2034e0e4af23da9a276160b8ad26c15 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:40 -0800 Subject: ion: Switch ion to use dma-buf Ion now uses dma-buf file descriptors to share buffers with userspace. Ion becomes a dma-buf exporter and any driver that can import dma-bufs can now import ion file descriptors. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 1 + drivers/staging/android/ion/ion.c | 648 +++++++++++++----------------------- drivers/staging/android/ion/ion.h | 58 +--- 3 files changed, 236 insertions(+), 471 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 5b48b4e85e73..b5bfdb47fd09 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,6 +1,7 @@ menuconfig ION tristate "Ion Memory Manager" select GENERIC_ALLOCATOR + select DMA_SHARED_BUFFER help Chose this option to enable the ION Memory Manager. diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3c9ca318e024..75bf8f2c8f03 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "ion.h" #include "ion_priv.h" @@ -50,14 +51,12 @@ struct ion_device { struct rb_root heaps; long (*custom_ioctl) (struct ion_client *client, unsigned int cmd, unsigned long arg); - struct rb_root user_clients; - struct rb_root kernel_clients; + struct rb_root clients; struct dentry *debug_root; }; /** * struct ion_client - a process/hw block local address space - * @ref: for reference counting the client * @node: node in the tree of all clients * @dev: backpointer to ion device * @handles: an rb tree of all the handles in this client @@ -71,7 +70,6 @@ struct ion_device { * as well as the handles themselves, and should be held while modifying either. */ struct ion_client { - struct kref ref; struct rb_node node; struct ion_device *dev; struct rb_root handles; @@ -91,7 +89,6 @@ struct ion_client { * @node: node in the client's handle rbtree * @kmap_cnt: count of times this client has mapped to kernel * @dmap_cnt: count of times this client has mapped for dma - * @usermap_cnt: count of times this client has mapped for userspace * * Modifications to node, map_cnt or mapping should be protected by the * lock in the client. Other fields are never changed after initialization. @@ -102,8 +99,6 @@ struct ion_handle { struct ion_buffer *buffer; struct rb_node node; unsigned int kmap_cnt; - unsigned int dmap_cnt; - unsigned int usermap_cnt; }; /* this function should only be called while dev->lock is held */ @@ -206,17 +201,26 @@ static struct ion_handle *ion_handle_create(struct ion_client *client, return handle; } +static void ion_handle_kmap_put(struct ion_handle *); + static void ion_handle_destroy(struct kref *kref) { struct ion_handle *handle = container_of(kref, struct ion_handle, ref); - /* XXX Can a handle be destroyed while it's map count is non-zero?: - if (handle->map_cnt) unmap - */ - ion_buffer_put(handle->buffer); - mutex_lock(&handle->client->lock); + struct ion_client *client = handle->client; + struct ion_buffer *buffer = handle->buffer; + + mutex_lock(&client->lock); + + mutex_lock(&buffer->lock); + while (buffer->kmap_cnt) + ion_handle_kmap_put(handle); + mutex_unlock(&buffer->lock); + if (!RB_EMPTY_NODE(&handle->node)) - rb_erase(&handle->node, &handle->client->handles); - mutex_unlock(&handle->client->lock); + rb_erase(&handle->node, &client->handles); + mutex_unlock(&client->lock); + + ion_buffer_put(buffer); kfree(handle); } @@ -362,38 +366,6 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) ion_handle_put(handle); } -static void ion_client_get(struct ion_client *client); -static int ion_client_put(struct ion_client *client); - -static bool _ion_map(int *buffer_cnt, int *handle_cnt) -{ - bool map; - - BUG_ON(*handle_cnt != 0 && *buffer_cnt == 0); - - if (*buffer_cnt) - map = false; - else - map = true; - if (*handle_cnt == 0) - (*buffer_cnt)++; - (*handle_cnt)++; - return map; -} - -static bool _ion_unmap(int *buffer_cnt, int *handle_cnt) -{ - BUG_ON(*handle_cnt == 0); - (*handle_cnt)--; - if (*handle_cnt != 0) - return false; - BUG_ON(*buffer_cnt == 0); - (*buffer_cnt)--; - if (*buffer_cnt == 0) - return true; - return false; -} - int ion_phys(struct ion_client *client, struct ion_handle *handle, ion_phys_addr_t *addr, size_t *len) { @@ -419,175 +391,85 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, return ret; } -void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) +static void *ion_handle_kmap_get(struct ion_handle *handle) { - struct ion_buffer *buffer; + struct ion_buffer *buffer = handle->buffer; void *vaddr; - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_kernel.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); + if (handle->kmap_cnt) { + handle->kmap_cnt++; + return buffer->vaddr; + } else if (buffer->kmap_cnt) { + handle->kmap_cnt++; + buffer->kmap_cnt++; + return buffer->vaddr; } - buffer = handle->buffer; - mutex_lock(&buffer->lock); - - if (!handle->buffer->heap->ops->map_kernel) { - pr_err("%s: map_kernel is not implemented by this heap.\n", - __func__); - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); - return ERR_PTR(-ENODEV); + vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); + buffer->vaddr = vaddr; + if (IS_ERR_OR_NULL(vaddr)) { + buffer->vaddr = NULL; + return vaddr; } + handle->kmap_cnt++; + buffer->kmap_cnt++; + return vaddr; +} - if (_ion_map(&buffer->kmap_cnt, &handle->kmap_cnt)) { - vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - if (IS_ERR_OR_NULL(vaddr)) - _ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt); - buffer->vaddr = vaddr; - } else { - vaddr = buffer->vaddr; +static void ion_handle_kmap_put(struct ion_handle *handle) +{ + struct ion_buffer *buffer = handle->buffer; + + handle->kmap_cnt--; + if (!handle->kmap_cnt) + buffer->kmap_cnt--; + if (!buffer->kmap_cnt) { + buffer->heap->ops->unmap_kernel(buffer->heap, buffer); + buffer->vaddr = NULL; } - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); - return vaddr; } -struct sg_table *ion_map_dma(struct ion_client *client, - struct ion_handle *handle) +void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) { struct ion_buffer *buffer; - struct sg_table *table; + void *vaddr; mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_dma.\n", + pr_err("%s: invalid handle passed to map_kernel.\n", __func__); mutex_unlock(&client->lock); return ERR_PTR(-EINVAL); } + buffer = handle->buffer; - mutex_lock(&buffer->lock); - if (!handle->buffer->heap->ops->map_dma) { + if (!handle->buffer->heap->ops->map_kernel) { pr_err("%s: map_kernel is not implemented by this heap.\n", __func__); - mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return ERR_PTR(-ENODEV); } - if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) { - table = buffer->heap->ops->map_dma(buffer->heap, buffer); - if (IS_ERR_OR_NULL(table)) - _ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt); - buffer->sg_table = table; - } else { - table = buffer->sg_table; - } - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); - return table; -} - -void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) -{ - struct ion_buffer *buffer; - mutex_lock(&client->lock); - buffer = handle->buffer; mutex_lock(&buffer->lock); - if (_ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt)) { - buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->vaddr = NULL; - } + vaddr = ion_handle_kmap_get(handle); mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); + return vaddr; } -void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) +void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) { struct ion_buffer *buffer; mutex_lock(&client->lock); buffer = handle->buffer; mutex_lock(&buffer->lock); - if (_ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt)) { - buffer->heap->ops->unmap_dma(buffer->heap, buffer); - buffer->sg_table = NULL; - } + ion_handle_kmap_put(handle); mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); } - -struct ion_buffer *ion_share(struct ion_client *client, - struct ion_handle *handle) -{ - bool valid_handle; - - mutex_lock(&client->lock); - valid_handle = ion_handle_validate(client, handle); - mutex_unlock(&client->lock); - if (!valid_handle) { - WARN("%s: invalid handle passed to share.\n", __func__); - return ERR_PTR(-EINVAL); - } - - /* do not take an extra reference here, the burden is on the caller - * to make sure the buffer doesn't go away while it's passing it - * to another client -- ion_free should not be called on this handle - * until the buffer has been imported into the other client - */ - return handle->buffer; -} - -struct ion_handle *ion_import(struct ion_client *client, - struct ion_buffer *buffer) -{ - struct ion_handle *handle = NULL; - - mutex_lock(&client->lock); - /* if a handle exists for this buffer just take a reference to it */ - handle = ion_handle_lookup(client, buffer); - if (!IS_ERR_OR_NULL(handle)) { - ion_handle_get(handle); - goto end; - } - handle = ion_handle_create(client, buffer); - if (IS_ERR_OR_NULL(handle)) - goto end; - ion_handle_add(client, handle); -end: - mutex_unlock(&client->lock); - return handle; -} - -static const struct file_operations ion_share_fops; - -struct ion_handle *ion_import_fd(struct ion_client *client, int fd) -{ - struct file *file = fget(fd); - struct ion_handle *handle; - - if (!file) { - pr_err("%s: imported fd not found in file table.\n", __func__); - return ERR_PTR(-EINVAL); - } - if (file->f_op != &ion_share_fops) { - pr_err("%s: imported file is not a shared ion file.\n", - __func__); - handle = ERR_PTR(-EINVAL); - goto end; - } - handle = ion_import(client, file->private_data); -end: - fput(file); - return handle; -} - static int ion_debug_client_show(struct seq_file *s, void *unused) { struct ion_client *client = s->private; @@ -612,8 +494,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) for (i = 0; i < ION_NUM_HEAPS; i++) { if (!names[i]) continue; - seq_printf(s, "%16.16s: %16u %d\n", names[i], sizes[i], - atomic_read(&client->ref.refcount)); + seq_printf(s, "%16.16s: %16u\n", names[i], sizes[i]); } return 0; } @@ -630,29 +511,6 @@ static const struct file_operations debug_client_fops = { .release = single_release, }; -static struct ion_client *ion_client_lookup(struct ion_device *dev, - struct task_struct *task) -{ - struct rb_node *n = dev->user_clients.rb_node; - struct ion_client *client; - - mutex_lock(&dev->lock); - while (n) { - client = rb_entry(n, struct ion_client, node); - if (task == client->task) { - ion_client_get(client); - mutex_unlock(&dev->lock); - return client; - } else if (task < client->task) { - n = n->rb_left; - } else if (task > client->task) { - n = n->rb_right; - } - } - mutex_unlock(&dev->lock); - return NULL; -} - struct ion_client *ion_client_create(struct ion_device *dev, unsigned int heap_mask, const char *name) @@ -678,16 +536,6 @@ struct ion_client *ion_client_create(struct ion_device *dev, } task_unlock(current->group_leader); - /* if this isn't a kernel thread, see if a client already - exists */ - if (task) { - client = ion_client_lookup(dev, task); - if (!IS_ERR_OR_NULL(client)) { - put_task_struct(current->group_leader); - return client; - } - } - client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); if (!client) { if (task) @@ -702,36 +550,20 @@ struct ion_client *ion_client_create(struct ion_device *dev, client->heap_mask = heap_mask; client->task = task; client->pid = pid; - kref_init(&client->ref); mutex_lock(&dev->lock); - if (task) { - p = &dev->user_clients.rb_node; - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_client, node); - - if (task < entry->task) - p = &(*p)->rb_left; - else if (task > entry->task) - p = &(*p)->rb_right; - } - rb_link_node(&client->node, parent, p); - rb_insert_color(&client->node, &dev->user_clients); - } else { - p = &dev->kernel_clients.rb_node; - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_client, node); - - if (client < entry) - p = &(*p)->rb_left; - else if (client > entry) - p = &(*p)->rb_right; - } - rb_link_node(&client->node, parent, p); - rb_insert_color(&client->node, &dev->kernel_clients); + p = &dev->clients.rb_node; + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_client, node); + + if (client < entry) + p = &(*p)->rb_left; + else if (client > entry) + p = &(*p)->rb_right; } + rb_link_node(&client->node, parent, p); + rb_insert_color(&client->node, &dev->clients); snprintf(debug_name, 64, "%u", client->pid); client->debug_root = debugfs_create_file(debug_name, 0664, @@ -742,9 +574,8 @@ struct ion_client *ion_client_create(struct ion_device *dev, return client; } -static void _ion_client_destroy(struct kref *kref) +void ion_client_destroy(struct ion_client *client) { - struct ion_client *client = container_of(kref, struct ion_client, ref); struct ion_device *dev = client->dev; struct rb_node *n; @@ -755,204 +586,192 @@ static void _ion_client_destroy(struct kref *kref) ion_handle_destroy(&handle->ref); } mutex_lock(&dev->lock); - if (client->task) { - rb_erase(&client->node, &dev->user_clients); + if (client->task) put_task_struct(client->task); - } else { - rb_erase(&client->node, &dev->kernel_clients); - } + rb_erase(&client->node, &dev->clients); debugfs_remove_recursive(client->debug_root); mutex_unlock(&dev->lock); kfree(client); } -static void ion_client_get(struct ion_client *client) -{ - kref_get(&client->ref); -} - -static int ion_client_put(struct ion_client *client) -{ - return kref_put(&client->ref, _ion_client_destroy); -} - -void ion_client_destroy(struct ion_client *client) -{ - ion_client_put(client); -} - -static int ion_share_release(struct inode *inode, struct file* file) -{ - struct ion_buffer *buffer = file->private_data; - - pr_debug("%s: %d\n", __func__, __LINE__); - /* drop the reference to the buffer -- this prevents the - buffer from going away because the client holding it exited - while it was being passed */ - ion_buffer_put(buffer); - return 0; -} - -static void ion_vma_open(struct vm_area_struct *vma) +static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) { + struct dma_buf *dmabuf = attachment->dmabuf; + struct ion_buffer *buffer = dmabuf->priv; + struct sg_table *table; - struct ion_buffer *buffer = vma->vm_file->private_data; - struct ion_handle *handle = vma->vm_private_data; - struct ion_client *client; + mutex_lock(&buffer->lock); - pr_debug("%s: %d\n", __func__, __LINE__); - /* check that the client still exists and take a reference so - it can't go away until this vma is closed */ - client = ion_client_lookup(buffer->dev, current->group_leader); - if (IS_ERR_OR_NULL(client)) { - vma->vm_private_data = NULL; - return; + if (!buffer->heap->ops->map_dma) { + pr_err("%s: map_dma is not implemented by this heap.\n", + __func__); + mutex_unlock(&buffer->lock); + return ERR_PTR(-ENODEV); } - - if (!ion_handle_validate(client, handle)) { - ion_client_put(client); - vma->vm_private_data = NULL; - return; + /* if an sg list already exists for this buffer just return it */ + if (buffer->dmap_cnt) { + table = buffer->sg_table; + goto end; } - ion_handle_get(handle); - - pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", - __func__, __LINE__, - atomic_read(&client->ref.refcount), - atomic_read(&handle->ref.refcount), - atomic_read(&buffer->ref.refcount)); + /* otherwise call into the heap to create one */ + table = buffer->heap->ops->map_dma(buffer->heap, buffer); + if (IS_ERR_OR_NULL(table)) + goto err; + buffer->sg_table = table; +end: + buffer->dmap_cnt++; +err: + mutex_unlock(&buffer->lock); + return table; } -static void ion_vma_close(struct vm_area_struct *vma) +static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) { - struct ion_handle *handle = vma->vm_private_data; - struct ion_buffer *buffer = vma->vm_file->private_data; - struct ion_client *client; + struct dma_buf *dmabuf = attachment->dmabuf; + struct ion_buffer *buffer = dmabuf->priv; - pr_debug("%s: %d\n", __func__, __LINE__); - /* this indicates the client is gone, nothing to do here */ - if (!handle) - return; - client = handle->client; - pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", - __func__, __LINE__, - atomic_read(&client->ref.refcount), - atomic_read(&handle->ref.refcount), - atomic_read(&buffer->ref.refcount)); - ion_handle_put(handle); - ion_client_put(client); - pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", - __func__, __LINE__, - atomic_read(&client->ref.refcount), - atomic_read(&handle->ref.refcount), - atomic_read(&buffer->ref.refcount)); + mutex_lock(&buffer->lock); + buffer->dmap_cnt--; + if (!buffer->dmap_cnt) { + buffer->heap->ops->unmap_dma(buffer->heap, buffer); + buffer->sg_table = NULL; + } + mutex_unlock(&buffer->lock); } -static struct vm_operations_struct ion_vm_ops = { - .open = ion_vma_open, - .close = ion_vma_close, -}; - -static int ion_share_mmap(struct file *file, struct vm_area_struct *vma) +static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { - struct ion_buffer *buffer = file->private_data; - unsigned long size = vma->vm_end - vma->vm_start; - struct ion_client *client; - struct ion_handle *handle; + struct ion_buffer *buffer = dmabuf->priv; int ret; - pr_debug("%s: %d\n", __func__, __LINE__); - /* make sure the client still exists, it's possible for the client to - have gone away but the map/share fd still to be around, take - a reference to it so it can't go away while this mapping exists */ - client = ion_client_lookup(buffer->dev, current->group_leader); - if (IS_ERR_OR_NULL(client)) { - pr_err("%s: trying to mmap an ion handle in a process with no " - "ion client\n", __func__); - return -EINVAL; - } - - if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) > - buffer->size)) { - pr_err("%s: trying to map larger area than handle has available" - "\n", __func__); - ret = -EINVAL; - goto err; - } - - /* find the handle and take a reference to it */ - handle = ion_import(client, buffer); - if (IS_ERR_OR_NULL(handle)) { - ret = -EINVAL; - goto err; - } - - if (!handle->buffer->heap->ops->map_user) { + if (!buffer->heap->ops->map_user) { pr_err("%s: this heap does not define a method for mapping " "to userspace\n", __func__); - ret = -EINVAL; - goto err1; + return -EINVAL; } mutex_lock(&buffer->lock); /* now map it to userspace */ ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); mutex_unlock(&buffer->lock); - if (ret) { + + if (ret) pr_err("%s: failure mapping buffer to userspace\n", __func__); - goto err1; - } - vma->vm_ops = &ion_vm_ops; - /* move the handle into the vm_private_data so we can access it from - vma_open/close */ - vma->vm_private_data = handle; - pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", - __func__, __LINE__, - atomic_read(&client->ref.refcount), - atomic_read(&handle->ref.refcount), - atomic_read(&buffer->ref.refcount)); - return 0; - -err1: - /* drop the reference to the handle */ - ion_handle_put(handle); -err: - /* drop the reference to the client */ - ion_client_put(client); return ret; } -static const struct file_operations ion_share_fops = { - .owner = THIS_MODULE, - .release = ion_share_release, - .mmap = ion_share_mmap, -}; +static void ion_dma_buf_release(struct dma_buf *dmabuf) +{ + struct ion_buffer *buffer = dmabuf->priv; + ion_buffer_put(buffer); +} -static int ion_ioctl_share(struct file *parent, struct ion_client *client, - struct ion_handle *handle) +static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) { - int fd = get_unused_fd(); - struct file *file; + return NULL; +} - if (fd < 0) - return fd; +static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, + void *ptr) +{ + return; +} + +static void *ion_dma_buf_kmap_atomic(struct dma_buf *dmabuf, + unsigned long offset) +{ + return NULL; +} + +static void ion_dma_buf_kunmap_atomic(struct dma_buf *dmabuf, + unsigned long offset, void *ptr) +{ + return; +} - file = anon_inode_getfile("ion_share_fd", &ion_share_fops, - handle->buffer, O_RDWR); - if (IS_ERR_OR_NULL(file)) - goto err; - ion_buffer_get(handle->buffer); - fd_install(fd, file); +struct dma_buf_ops dma_buf_ops = { + .map_dma_buf = ion_map_dma_buf, + .unmap_dma_buf = ion_unmap_dma_buf, + .mmap = ion_mmap, + .release = ion_dma_buf_release, + .kmap_atomic = ion_dma_buf_kmap_atomic, + .kunmap_atomic = ion_dma_buf_kunmap_atomic, + .kmap = ion_dma_buf_kmap, + .kunmap = ion_dma_buf_kunmap, +}; + +int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) +{ + struct ion_buffer *buffer; + struct dma_buf *dmabuf; + bool valid_handle; + int fd; + + mutex_lock(&client->lock); + valid_handle = ion_handle_validate(client, handle); + mutex_unlock(&client->lock); + if (!valid_handle) { + WARN("%s: invalid handle passed to share.\n", __func__); + return -EINVAL; + } + + buffer = handle->buffer; + ion_buffer_get(buffer); + dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR); + if (IS_ERR(dmabuf)) { + ion_buffer_put(buffer); + return PTR_ERR(dmabuf); + } + fd = dma_buf_fd(dmabuf, O_CLOEXEC); + if (fd < 0) { + dma_buf_put(dmabuf); + ion_buffer_put(buffer); + } return fd; +} -err: - put_unused_fd(fd); - return -ENFILE; +struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) +{ + struct dma_buf *dmabuf; + struct ion_buffer *buffer; + struct ion_handle *handle; + + dmabuf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dmabuf)) + return ERR_PTR(PTR_ERR(dmabuf)); + /* if this memory came from ion */ + + if (dmabuf->ops != &dma_buf_ops) { + pr_err("%s: can not import dmabuf from another exporter\n", + __func__); + dma_buf_put(dmabuf); + return ERR_PTR(-EINVAL); + } + buffer = dmabuf->priv; + + mutex_lock(&client->lock); + /* if a handle exists for this buffer just take a reference to it */ + handle = ion_handle_lookup(client, buffer); + if (!IS_ERR_OR_NULL(handle)) { + ion_handle_get(handle); + goto end; + } + handle = ion_handle_create(client, buffer); + if (IS_ERR_OR_NULL(handle)) + goto end; + ion_handle_add(client, handle); +end: + mutex_unlock(&client->lock); + dma_buf_put(dmabuf); + return handle; } static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -994,22 +813,13 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ion_free(client, data.handle); break; } - case ION_IOC_MAP: case ION_IOC_SHARE: { struct ion_fd_data data; if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - mutex_lock(&client->lock); - if (!ion_handle_validate(client, data.handle)) { - pr_err("%s: invalid handle passed to share ioctl.\n", - __func__); - mutex_unlock(&client->lock); - return -EINVAL; - } - data.fd = ion_ioctl_share(filp, client, data.handle); - mutex_unlock(&client->lock); + data.fd = ion_share_dma_buf(client, data.handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; break; @@ -1020,8 +830,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(struct ion_fd_data))) return -EFAULT; - - data.handle = ion_import_fd(client, data.fd); + data.handle = ion_import_dma_buf(client, data.fd); if (IS_ERR(data.handle)) data.handle = NULL; if (copy_to_user((void __user *)arg, &data, @@ -1052,7 +861,7 @@ static int ion_release(struct inode *inode, struct file *file) struct ion_client *client = file->private_data; pr_debug("%s: %d\n", __func__, __LINE__); - ion_client_put(client); + ion_client_destroy(client); return 0; } @@ -1103,27 +912,23 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) struct rb_node *n; seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size"); - for (n = rb_first(&dev->user_clients); n; n = rb_next(n)) { - struct ion_client *client = rb_entry(n, struct ion_client, - node); - char task_comm[TASK_COMM_LEN]; - size_t size = ion_debug_heap_total(client, heap->type); - if (!size) - continue; - get_task_comm(task_comm, client->task); - seq_printf(s, "%16.s %16u %16u\n", task_comm, client->pid, - size); - } - - for (n = rb_first(&dev->kernel_clients); n; n = rb_next(n)) { + for (n = rb_first(&dev->clients); n; n = rb_next(n)) { struct ion_client *client = rb_entry(n, struct ion_client, node); size_t size = ion_debug_heap_total(client, heap->type); if (!size) continue; - seq_printf(s, "%16.s %16u %16u\n", client->name, client->pid, - size); + if (client->task) { + char task_comm[TASK_COMM_LEN]; + + get_task_comm(task_comm, client->task); + seq_printf(s, "%16.s %16u %16u\n", task_comm, + client->pid, size); + } else { + seq_printf(s, "%16.s %16u %16u\n", client->name, + client->pid, size); + } } return 0; } @@ -1201,8 +1006,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) idev->buffers = RB_ROOT; mutex_init(&idev->lock); idev->heaps = RB_ROOT; - idev->user_clients = RB_ROOT; - idev->kernel_clients = RB_ROOT; + idev->clients = RB_ROOT; return idev; } diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 4e012b86a839..84ca2a98ae83 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -176,63 +176,23 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle); void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); /** - * ion_map_dma - create a dma mapping for a given handle + * ion_share_dma_buf() - given an ion client, create a dma-buf fd * @client: the client - * @handle: handle to map - * - * Return an sg_table describing the given handle - */ -struct sg_table *ion_map_dma(struct ion_client *client, - struct ion_handle *handle); - -/** - * ion_unmap_dma() - destroy a dma mapping for a handle - * @client: the client - * @handle: handle to unmap + * @handle: the handle */ -void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle); +int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle); /** - * ion_share() - given a handle, obtain a buffer to pass to other clients + * ion_import_dma_buf() - given an dma-buf fd from the ion exporter get handle * @client: the client - * @handle: the handle to share + * @fd: the dma-buf fd * - * Given a handle, return a buffer, which exists in a global name - * space, and can be passed to other clients. Should be passed into ion_import - * to obtain a new handle for this buffer. - * - * NOTE: This function does do not an extra reference. The burden is on the - * caller to make sure the buffer doesn't go away while it's being passed to - * another client. That is, ion_free should not be called on this handle until - * the buffer has been imported into the other client. - */ -struct ion_buffer *ion_share(struct ion_client *client, - struct ion_handle *handle); - -/** - * ion_import() - given an buffer in another client, import it - * @client: this blocks client - * @buffer: the buffer to import (as obtained from ion_share) - * - * Given a buffer, add it to the client and return the handle to use to refer - * to it further. This is called to share a handle from one kernel client to - * another. + * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf, + * import that fd and return a handle representing it. If a dma-buf from + * another exporter is passed in this function will return ERR_PTR(-EINVAL) */ -struct ion_handle *ion_import(struct ion_client *client, - struct ion_buffer *buffer); +struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); -/** - * ion_import_fd() - given an fd obtained via ION_IOC_SHARE ioctl, import it - * @client: this blocks client - * @fd: the fd - * - * A helper function for drivers that will be recieving ion buffers shared - * with them from userspace. These buffers are represented by a file - * descriptor obtained as the return from the ION_IOC_SHARE ioctl. - * This function coverts that fd into the underlying buffer, and returns - * the handle to use to refer to it further. - */ -struct ion_handle *ion_import_fd(struct ion_client *client, int fd); #endif /* __KERNEL__ */ /** -- cgit v1.2.3 From b15934b62d959ddc75f7a85fa2a721bea28756b6 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:41 -0800 Subject: gpu: ion: Use alloc_pages instead of vmalloc from the system heap With this change the ion_system_heap will only use kernel address space when the memory is mapped into the kernel (rare case). Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 94 +++++++++++++++++---------- 1 file changed, 61 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index d7e0fa0c1ef6..3383a881b720 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -26,75 +26,103 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long size, unsigned long align, unsigned long flags) -{ - buffer->priv_virt = vmalloc_user(size); - if (!buffer->priv_virt) - return -ENOMEM; - return 0; -} - -void ion_system_heap_free(struct ion_buffer *buffer) -{ - vfree(buffer->priv_virt); -} - -struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) { struct sg_table *table; struct scatterlist *sg; - int i; - int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - void *vaddr = buffer->priv_virt; - int ret; + int i, j; + int npages = PAGE_ALIGN(size) / PAGE_SIZE; - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) - return ERR_PTR(-ENOMEM); - ret = sg_alloc_table(table, npages, GFP_KERNEL); - if (ret) + return -ENOMEM; + i = sg_alloc_table(table, npages, GFP_KERNEL); + if (i) goto err0; for_each_sg(table->sgl, sg, table->nents, i) { struct page *page; - page = vmalloc_to_page(vaddr); - if (!page) { - ret = -ENOMEM; + page = alloc_page(GFP_KERNEL); + if (!page) goto err1; - } sg_set_page(sg, page, PAGE_SIZE, 0); - vaddr += PAGE_SIZE; } - return table; + buffer->priv_virt = table; + return 0; err1: + for_each_sg(table->sgl, sg, i, j) + __free_page(sg_page(sg)); sg_free_table(table); err0: kfree(table); - return ERR_PTR(ret); + return -ENOMEM; } -void ion_system_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +void ion_system_heap_free(struct ion_buffer *buffer) { + int i; + struct scatterlist *sg; + struct sg_table *table = buffer->priv_virt; + + for_each_sg(table->sgl, sg, table->nents, i) + __free_page(sg_page(sg)); if (buffer->sg_table) sg_free_table(buffer->sg_table); kfree(buffer->sg_table); } +struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return buffer->priv_virt; +} + +void ion_system_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return; +} + void *ion_system_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { - return buffer->priv_virt; + struct scatterlist *sg; + int i; + void *vaddr; + struct sg_table *table = buffer->priv_virt; + struct page **pages = kmalloc(sizeof(struct page *) * table->nents, + GFP_KERNEL); + + for_each_sg(table->sgl, sg, table->nents, i) + pages[i] = sg_page(sg); + vaddr = vmap(pages, table->nents, VM_MAP, PAGE_KERNEL); + kfree(pages); + + return vaddr; } void ion_system_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { + vunmap(buffer->vaddr); } int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, struct vm_area_struct *vma) { - return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff); + struct sg_table *table = buffer->priv_virt; + unsigned long addr = vma->vm_start; + unsigned long offset = vma->vm_pgoff; + struct scatterlist *sg; + int i; + + for_each_sg(table->sgl, sg, table->nents, i) { + if (offset) { + offset--; + continue; + } + vm_insert_page(vma, addr, sg_page(sg)); + addr += PAGE_SIZE; + } + return 0; } static struct ion_heap_ops vmalloc_ops = { -- cgit v1.2.3 From 0f34faf89f7e0755c9dad0f96087a76f0df48d26 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:42 -0800 Subject: gpu: ion: support begin/end and kmap/kunmap dma_buf ops These ops were added in the 3.4 kernel. This patch adds support for them to ion. Previous ion_map/unmap_kernel api is also retained in addition to this new api. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 88 +++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 75bf8f2c8f03..8937618f93da 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -391,6 +391,22 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, return ret; } +static void *ion_buffer_kmap_get(struct ion_buffer *buffer) +{ + void *vaddr; + + if (buffer->kmap_cnt) { + buffer->kmap_cnt++; + return buffer->vaddr; + } + vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); + if (IS_ERR_OR_NULL(vaddr)) + return vaddr; + buffer->vaddr = vaddr; + buffer->kmap_cnt++; + return vaddr; +} + static void *ion_handle_kmap_get(struct ion_handle *handle) { struct ion_buffer *buffer = handle->buffer; @@ -399,34 +415,30 @@ static void *ion_handle_kmap_get(struct ion_handle *handle) if (handle->kmap_cnt) { handle->kmap_cnt++; return buffer->vaddr; - } else if (buffer->kmap_cnt) { - handle->kmap_cnt++; - buffer->kmap_cnt++; - return buffer->vaddr; } - - vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - buffer->vaddr = vaddr; - if (IS_ERR_OR_NULL(vaddr)) { - buffer->vaddr = NULL; + vaddr = ion_buffer_kmap_get(buffer); + if (IS_ERR_OR_NULL(vaddr)) return vaddr; - } handle->kmap_cnt++; - buffer->kmap_cnt++; return vaddr; } +static void ion_buffer_kmap_put(struct ion_buffer *buffer) +{ + buffer->kmap_cnt--; + if (!buffer->kmap_cnt) { + buffer->heap->ops->unmap_kernel(buffer->heap, buffer); + buffer->vaddr = NULL; + } +} + static void ion_handle_kmap_put(struct ion_handle *handle) { struct ion_buffer *buffer = handle->buffer; handle->kmap_cnt--; if (!handle->kmap_cnt) - buffer->kmap_cnt--; - if (!buffer->kmap_cnt) { - buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->vaddr = NULL; - } + ion_buffer_kmap_put(buffer); } void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) @@ -675,7 +687,8 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) { - return NULL; + struct ion_buffer *buffer = dmabuf->priv; + return buffer->vaddr + offset; } static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, @@ -684,26 +697,49 @@ static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, return; } -static void *ion_dma_buf_kmap_atomic(struct dma_buf *dmabuf, - unsigned long offset) +static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, + size_t len, + enum dma_data_direction direction) { - return NULL; + struct ion_buffer *buffer = dmabuf->priv; + void *vaddr; + + if (!buffer->heap->ops->map_kernel) { + pr_err("%s: map kernel is not implemented by this heap.\n", + __func__); + return -ENODEV; + } + + mutex_lock(&buffer->lock); + vaddr = ion_buffer_kmap_get(buffer); + mutex_unlock(&buffer->lock); + if (IS_ERR(vaddr)) + return PTR_ERR(vaddr); + if (!vaddr) + return -ENOMEM; + return 0; } -static void ion_dma_buf_kunmap_atomic(struct dma_buf *dmabuf, - unsigned long offset, void *ptr) +static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, + size_t len, + enum dma_data_direction direction) { - return; -} + struct ion_buffer *buffer = dmabuf->priv; + mutex_lock(&buffer->lock); + ion_buffer_kmap_put(buffer); + mutex_unlock(&buffer->lock); +} struct dma_buf_ops dma_buf_ops = { .map_dma_buf = ion_map_dma_buf, .unmap_dma_buf = ion_unmap_dma_buf, .mmap = ion_mmap, .release = ion_dma_buf_release, - .kmap_atomic = ion_dma_buf_kmap_atomic, - .kunmap_atomic = ion_dma_buf_kunmap_atomic, + .begin_cpu_access = ion_dma_buf_begin_cpu_access, + .end_cpu_access = ion_dma_buf_end_cpu_access, + .kmap_atomic = ion_dma_buf_kmap, + .kunmap_atomic = ion_dma_buf_kunmap, .kmap = ion_dma_buf_kmap, .kunmap = ion_dma_buf_kunmap, }; -- cgit v1.2.3 From 29ae6bc7123f2d2d6796ac81c013bbfdd0a0a8d5 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:43 -0800 Subject: gpu: ion: Allocate the sg_table at creation time rather than dynamically Rather than calling map_dma on the allocations dynamically, this patch switches to creating the sg_table at the time the buffer is created. This is necessary because in future updates the sg_table will be used for cache maintenance. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 79 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 8937618f93da..b95202b0a51a 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -135,6 +135,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, unsigned long flags) { struct ion_buffer *buffer; + struct sg_table *table; int ret; buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL); @@ -149,6 +150,15 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, kfree(buffer); return ERR_PTR(ret); } + + table = buffer->heap->ops->map_dma(buffer->heap, buffer); + if (IS_ERR_OR_NULL(table)) { + heap->ops->free(buffer); + kfree(buffer); + return ERR_PTR(PTR_ERR(table)); + } + buffer->sg_table = table; + buffer->dev = dev; buffer->size = len; mutex_init(&buffer->lock); @@ -164,9 +174,7 @@ static void ion_buffer_destroy(struct kref *kref) if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - if (WARN_ON(buffer->dmap_cnt > 0)) - buffer->heap->ops->unmap_dma(buffer->heap, buffer); - + buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); mutex_lock(&dev->lock); rb_erase(&buffer->node, &dev->buffers); @@ -346,6 +354,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, mutex_unlock(&client->lock); } + return handle; } @@ -607,53 +616,42 @@ void ion_client_destroy(struct ion_client *client) kfree(client); } -static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, - enum dma_data_direction direction) +struct sg_table *ion_map_dma(struct ion_client *client, + struct ion_handle *handle) { - struct dma_buf *dmabuf = attachment->dmabuf; - struct ion_buffer *buffer = dmabuf->priv; + struct ion_buffer *buffer; struct sg_table *table; - mutex_lock(&buffer->lock); - - if (!buffer->heap->ops->map_dma) { - pr_err("%s: map_dma is not implemented by this heap.\n", + mutex_lock(&client->lock); + if (!ion_handle_validate(client, handle)) { + pr_err("%s: invalid handle passed to map_dma.\n", __func__); - mutex_unlock(&buffer->lock); - return ERR_PTR(-ENODEV); - } - /* if an sg list already exists for this buffer just return it */ - if (buffer->dmap_cnt) { - table = buffer->sg_table; - goto end; + mutex_unlock(&client->lock); + return ERR_PTR(-EINVAL); } - - /* otherwise call into the heap to create one */ - table = buffer->heap->ops->map_dma(buffer->heap, buffer); - if (IS_ERR_OR_NULL(table)) - goto err; - buffer->sg_table = table; -end: - buffer->dmap_cnt++; -err: - mutex_unlock(&buffer->lock); + buffer = handle->buffer; + table = buffer->sg_table; + mutex_unlock(&client->lock); return table; } -static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *table, - enum dma_data_direction direction) +void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) +{ +} + +static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) { struct dma_buf *dmabuf = attachment->dmabuf; struct ion_buffer *buffer = dmabuf->priv; - mutex_lock(&buffer->lock); - buffer->dmap_cnt--; - if (!buffer->dmap_cnt) { - buffer->heap->ops->unmap_dma(buffer->heap, buffer); - buffer->sg_table = NULL; - } - mutex_unlock(&buffer->lock); + return buffer->sg_table; +} + +static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ } static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) @@ -987,6 +985,11 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) struct rb_node *parent = NULL; struct ion_heap *entry; + if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || + !heap->ops->unmap_dma) + pr_err("%s: can not add heap with invalid ops struct.\n", + __func__); + heap->dev = dev; mutex_lock(&dev->lock); while (*p) { -- cgit v1.2.3 From ce1f147a2ed5ed468ad3a2f8418dddfd205d1fd9 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:44 -0800 Subject: gpu: ion: Get an sg_table from an ion handle This patch adds an interface to return and sg_table given a valid ion handle. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 8 ++------ drivers/staging/android/ion/ion.h | 13 ++++++++++++- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index b95202b0a51a..7ff9983c8eb9 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -616,8 +616,8 @@ void ion_client_destroy(struct ion_client *client) kfree(client); } -struct sg_table *ion_map_dma(struct ion_client *client, - struct ion_handle *handle) +struct sg_table *ion_sg_table(struct ion_client *client, + struct ion_handle *handle) { struct ion_buffer *buffer; struct sg_table *table; @@ -635,10 +635,6 @@ struct sg_table *ion_map_dma(struct ion_client *client, return table; } -void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) -{ -} - static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, enum dma_data_direction direction) { diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 84ca2a98ae83..28810c8295bd 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -149,7 +149,7 @@ void ion_free(struct ion_client *client, struct ion_handle *handle); * This function queries the heap for a particular handle to get the * handle's physical address. It't output is only correct if * a heap returns physically contiguous memory -- in other cases - * this api should not be implemented -- ion_map_dma should be used + * this api should not be implemented -- ion_sg_table should be used * instead. Returns -EINVAL if the handle is invalid. This has * no implications on the reference counting of the handle -- * the returned value may not be valid if the caller is not @@ -158,6 +158,17 @@ void ion_free(struct ion_client *client, struct ion_handle *handle); int ion_phys(struct ion_client *client, struct ion_handle *handle, ion_phys_addr_t *addr, size_t *len); +/** + * ion_map_dma - return an sg_table describing a handle + * @client: the client + * @handle: the handle + * + * This function returns the sg_table describing + * a particular ion handle. + */ +struct sg_table *ion_sg_table(struct ion_client *client, + struct ion_handle *handle); + /** * ion_map_kernel - create mapping for the given handle * @client: the client -- cgit v1.2.3 From 056be396881d6cc69e5946a3b4bfbd0f58d8c45a Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Fri, 13 Dec 2013 14:23:45 -0800 Subject: gpu: ion: fill in buffer->{dev,size} before mapping new buffers At least one map_dma() implementation (EXYNOS_CONTIG) assumes the fields are filled in Signed-off-by: Greg Hackmann [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7ff9983c8eb9..552a86a94f61 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -151,6 +151,9 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, return ERR_PTR(ret); } + buffer->dev = dev; + buffer->size = len; + table = buffer->heap->ops->map_dma(buffer->heap, buffer); if (IS_ERR_OR_NULL(table)) { heap->ops->free(buffer); @@ -159,8 +162,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, } buffer->sg_table = table; - buffer->dev = dev; - buffer->size = len; mutex_init(&buffer->lock); ion_buffer_add(dev, buffer); return buffer; -- cgit v1.2.3 From a46b6b2d4d49d3fdb6a2ef47455dc170fbce48b7 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:46 -0800 Subject: gpu: ion: Set the dma_address of the sg list at alloc time This patch sets the dma_address field of the sglist representing an allocation at allocation time. This technically breaks the dma api which states that these addresses should be set when a particular device takes ownership of a buffer via the dma_map apis. In the case of our systems the only dma address space is physical addresses. Additionally, we can not afford the overhead of calling dma_map_sg from this location as it implies a cache invalidate that is not necessary if the memory was previously mapped cached. Instead, the expectation is that memory being returned from the heaps is ready for dma in that if any cached mappings of that memory exist they have been invalidated. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 552a86a94f61..ddfe49a8eaa6 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -136,7 +136,8 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, { struct ion_buffer *buffer; struct sg_table *table; - int ret; + struct scatterlist *sg; + int i, ret; buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL); if (!buffer) @@ -163,6 +164,16 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->sg_table = table; mutex_init(&buffer->lock); + /* this will set up dma addresses for the sglist -- it is not + technically correct as per the dma api -- a specific + device isn't really taking ownership here. However, in practice on + our systems the only dma_address space is physical addresses. + Additionally, we can't afford the overhead of invalidating every + allocation via dma_map_sg. The implicit contract here is that + memory comming from the heaps is ready for dma, ie if it has a + cached mapping that mapping has been invalidated */ + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) + sg_dma_address(sg) = sg_phys(sg); ion_buffer_add(dev, buffer); return buffer; } -- cgit v1.2.3 From 0de9577b5e708b903a58a9d5e91d6474daa29c2d Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:47 -0800 Subject: gpu: ion: ion_system_heap: Change allocations to GFP_HIGHUSER Previously the ion_system_heap was using GFP_KERNEL, forcing all allocations to be in lowmem. This quickly causes us to run out of lowmem. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 3383a881b720..35b3726e4a34 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -40,7 +40,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, goto err0; for_each_sg(table->sgl, sg, table->nents, i) { struct page *page; - page = alloc_page(GFP_KERNEL); + page = alloc_page(GFP_HIGHUSER | __GFP_ZERO); if (!page) goto err1; sg_set_page(sg, page, PAGE_SIZE, 0); -- cgit v1.2.3 From 2900cd767180e9674947101fea96e318dc9b23eb Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 13 Dec 2013 14:23:48 -0800 Subject: gpu: ion: Loop on the handle count when destroying When destroying a handle, all kernel mappings to that handle should be destroyed. Other handles may still have references and valid mappings to the buffer underneath which should not be destroyed. Loop on the handle reference count, not the buffer reference count to get rid of all kernel mappings for the handle. Signed-off-by: Laura Abbott [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ddfe49a8eaa6..dc7174d96b55 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -232,7 +232,7 @@ static void ion_handle_destroy(struct kref *kref) mutex_lock(&client->lock); mutex_lock(&buffer->lock); - while (buffer->kmap_cnt) + while (handle->kmap_cnt) ion_handle_kmap_put(handle); mutex_unlock(&buffer->lock); -- cgit v1.2.3 From 7b903e44c40fdd8300582b0791ef20b70d81178c Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 13 Dec 2013 14:23:49 -0800 Subject: gpu: ion: Map only the vma size given When mapping carveout buffers into userspace, only map the size of the vma given, not the full size of the buffer since clients may map less than the buffer size. Signed-off-by: Laura Abbott [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index e8c4e36d5328..16f4fc7da414 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -116,7 +116,7 @@ int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, { return remap_pfn_range(vma, vma->vm_start, __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff, - buffer->size, + vma->vm_end - vma->vm_start, pgprot_noncached(vma->vm_page_prot)); } -- cgit v1.2.3 From 56a7c1851341a2fa9bd115746c1310411a6537a1 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:50 -0800 Subject: gpu: ion: Add cache maintenance to ion. This patch adds cache maintenance operations to ion. As per mailing list discussions regarding dma_buf, cache operations are done implicitly. At buffer allocaiton time the user can select whether he'd like mappings (both kernel and user) to be cached. When cached mappings are selected, no mappings will be created for a buffer at mmap time. Instead pages will be faulted in one at a time so we can track which pages require flushing before dma. When the buffers are mapped for dma (via the dma_buf apis) any pages which were touched will be synced for device. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 162 ++++++++++++++++++++++-- drivers/staging/android/ion/ion.h | 19 ++- drivers/staging/android/ion/ion_carveout_heap.c | 26 +++- drivers/staging/android/ion/ion_priv.h | 2 + drivers/staging/android/ion/ion_system_heap.c | 20 ++- 5 files changed, 210 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index dc7174d96b55..bc9e922bfbf8 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -34,7 +34,6 @@ #include "ion.h" #include "ion_priv.h" -#define DEBUG /** * struct ion_device - the metadata of the ion device node @@ -127,6 +126,8 @@ static void ion_buffer_add(struct ion_device *dev, rb_insert_color(&buffer->node, &dev->buffers); } +static int ion_buffer_alloc_dirty(struct ion_buffer *buffer); + /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -154,15 +155,38 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->dev = dev; buffer->size = len; + buffer->flags = flags; - table = buffer->heap->ops->map_dma(buffer->heap, buffer); + table = heap->ops->map_dma(heap, buffer); if (IS_ERR_OR_NULL(table)) { heap->ops->free(buffer); kfree(buffer); return ERR_PTR(PTR_ERR(table)); } buffer->sg_table = table; + if (buffer->flags & ION_FLAG_CACHED) + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, + i) { + if (sg_dma_len(sg) == PAGE_SIZE) + continue; + pr_err("%s: cached mappings must have pagewise " + "sg_lists\n", __func__); + heap->ops->unmap_dma(heap, buffer); + kfree(buffer); + return ERR_PTR(-EINVAL); + } + ret = ion_buffer_alloc_dirty(buffer); + if (ret) { + heap->ops->unmap_dma(heap, buffer); + heap->ops->free(buffer); + kfree(buffer); + return ERR_PTR(ret); + } + + buffer->dev = dev; + buffer->size = len; + INIT_LIST_HEAD(&buffer->vmas); mutex_init(&buffer->lock); /* this will set up dma addresses for the sglist -- it is not technically correct as per the dma api -- a specific @@ -313,13 +337,16 @@ static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) } struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int flags) + size_t align, unsigned int heap_mask, + unsigned int flags) { struct rb_node *n; struct ion_handle *handle; struct ion_device *dev = client->dev; struct ion_buffer *buffer = NULL; + pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len, + align, heap_mask, flags); /* * traverse the list of heaps available in this system in priority * order. If the heap type is supported by the client, and matches the @@ -338,7 +365,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, if (!((1 << heap->type) & client->heap_mask)) continue; /* if the caller didn't specify this heap type */ - if (!((1 << heap->id) & flags)) + if (!((1 << heap->id) & heap_mask)) continue; buffer = ion_buffer_create(heap, dev, len, align, flags); if (!IS_ERR_OR_NULL(buffer)) @@ -647,12 +674,18 @@ struct sg_table *ion_sg_table(struct ion_client *client, return table; } +static void ion_buffer_sync_for_device(struct ion_buffer *buffer, + struct device *dev, + enum dma_data_direction direction); + static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, enum dma_data_direction direction) { struct dma_buf *dmabuf = attachment->dmabuf; struct ion_buffer *buffer = dmabuf->priv; + if (buffer->flags & ION_FLAG_CACHED) + ion_buffer_sync_for_device(buffer, attachment->dev, direction); return buffer->sg_table; } @@ -662,10 +695,112 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, { } +static int ion_buffer_alloc_dirty(struct ion_buffer *buffer) +{ + unsigned long pages = buffer->sg_table->nents; + unsigned long length = (pages + BITS_PER_LONG - 1)/BITS_PER_LONG; + + buffer->dirty = kzalloc(length * sizeof(unsigned long), GFP_KERNEL); + if (!buffer->dirty) + return -ENOMEM; + return 0; +} + +struct ion_vma_list { + struct list_head list; + struct vm_area_struct *vma; +}; + +static void ion_buffer_sync_for_device(struct ion_buffer *buffer, + struct device *dev, + enum dma_data_direction dir) +{ + struct scatterlist *sg; + int i; + struct ion_vma_list *vma_list; + + pr_debug("%s: syncing for device %s\n", __func__, + dev ? dev_name(dev) : "null"); + mutex_lock(&buffer->lock); + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { + if (!test_bit(i, buffer->dirty)) + continue; + dma_sync_sg_for_device(dev, sg, 1, dir); + clear_bit(i, buffer->dirty); + } + list_for_each_entry(vma_list, &buffer->vmas, list) { + struct vm_area_struct *vma = vma_list->vma; + + zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, + NULL); + } + mutex_unlock(&buffer->lock); +} + +int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct ion_buffer *buffer = vma->vm_private_data; + struct scatterlist *sg; + int i; + + mutex_lock(&buffer->lock); + set_bit(vmf->pgoff, buffer->dirty); + + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { + if (i != vmf->pgoff) + continue; + dma_sync_sg_for_cpu(NULL, sg, 1, DMA_BIDIRECTIONAL); + vm_insert_page(vma, (unsigned long)vmf->virtual_address, + sg_page(sg)); + break; + } + mutex_unlock(&buffer->lock); + return VM_FAULT_NOPAGE; +} + +static void ion_vm_open(struct vm_area_struct *vma) +{ + struct ion_buffer *buffer = vma->vm_private_data; + struct ion_vma_list *vma_list; + + vma_list = kmalloc(sizeof(struct ion_vma_list), GFP_KERNEL); + if (!vma_list) + return; + vma_list->vma = vma; + mutex_lock(&buffer->lock); + list_add(&vma_list->list, &buffer->vmas); + mutex_unlock(&buffer->lock); + pr_debug("%s: adding %p\n", __func__, vma); +} + +static void ion_vm_close(struct vm_area_struct *vma) +{ + struct ion_buffer *buffer = vma->vm_private_data; + struct ion_vma_list *vma_list, *tmp; + + pr_debug("%s\n", __func__); + mutex_lock(&buffer->lock); + list_for_each_entry_safe(vma_list, tmp, &buffer->vmas, list) { + if (vma_list->vma != vma) + continue; + list_del(&vma_list->list); + kfree(vma_list); + pr_debug("%s: deleting %p\n", __func__, vma); + break; + } + mutex_unlock(&buffer->lock); +} + +struct vm_operations_struct ion_vma_ops = { + .open = ion_vm_open, + .close = ion_vm_close, + .fault = ion_vm_fault, +}; + static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { struct ion_buffer *buffer = dmabuf->priv; - int ret; + int ret = 0; if (!buffer->heap->ops->map_user) { pr_err("%s: this heap does not define a method for mapping " @@ -673,10 +808,17 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) return -EINVAL; } - mutex_lock(&buffer->lock); - /* now map it to userspace */ - ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); - mutex_unlock(&buffer->lock); + if (buffer->flags & ION_FLAG_CACHED) { + vma->vm_private_data = buffer; + vma->vm_ops = &ion_vma_ops; + ion_vm_open(vma); + } else { + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + mutex_lock(&buffer->lock); + /* now map it to userspace */ + ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); + mutex_unlock(&buffer->lock); + } if (ret) pr_err("%s: failure mapping buffer to userspace\n", @@ -828,7 +970,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; data.handle = ion_alloc(client, data.len, data.align, - data.flags); + data.heap_mask, data.flags); if (IS_ERR(data.handle)) return PTR_ERR(data.handle); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 28810c8295bd..88b9a2f5f87e 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -42,6 +42,15 @@ enum ion_heap_type { #define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) +/** + * heap flags - the lower 16 bits are used by core ion, the upper 16 + * bits are reserved for use by the heaps themselves. + */ +#define ION_FLAG_CACHED 1 /* mappings of this buffer should be + cached, ion will do cache + maintenance when the buffer is + mapped for dma */ + #ifdef __KERNEL__ struct ion_device; struct ion_heap; @@ -121,14 +130,18 @@ void ion_client_destroy(struct ion_client *client); * @len: size of the allocation * @align: requested allocation alignment, lots of hardware blocks have * alignment requirements of some kind - * @flags: mask of heaps to allocate from, if multiple bits are set + * @heap_mask: mask of heaps to allocate from, if multiple bits are set * heaps will be tried in order from lowest to highest order bit + * @flags: heap flags, the low 16 bits are consumed by ion, the high 16 + * bits are passed on to the respective heap and can be heap + * custom * * Allocate memory in one of the heaps provided in heap mask and return * an opaque handle to it. */ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int flags); + size_t align, unsigned int heap_mask, + unsigned int flags); /** * ion_free - free a handle @@ -218,6 +231,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); * struct ion_allocation_data - metadata passed from userspace for allocations * @len: size of the allocation * @align: required alignment of the allocation + * @heap_mask: mask of heaps to allocate from * @flags: flags passed to heap * @handle: pointer that will be populated with a cookie to use to refer * to this allocation @@ -227,6 +241,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); struct ion_allocation_data { size_t len; size_t align; + unsigned int heap_mask; unsigned int flags; struct ion_handle *handle; }; diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 16f4fc7da414..daa348e3a65a 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -84,23 +84,41 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; } -struct scatterlist *ion_carveout_heap_map_dma(struct ion_heap *heap, +struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - return ERR_PTR(-EINVAL); + struct sg_table *table; + int ret; + + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) { + kfree(table); + return ERR_PTR(ret); + } + sg_set_page(table->sgl, phys_to_page(buffer->priv_phys), buffer->size, + 0); + return table; } void ion_carveout_heap_unmap_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - return; + sg_free_table(buffer->sg_table); } void *ion_carveout_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { + int mtype = MT_MEMORY_NONCACHED; + + if (buffer->flags & ION_FLAG_CACHED) + mtype = MT_MEMORY; + return __arm_ioremap(buffer->priv_phys, buffer->size, - MT_MEMORY_NONCACHED); + mtype); } void ion_carveout_heap_unmap_kernel(struct ion_heap *heap, diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 7a77f6f626c8..406d1f43bf10 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -60,6 +60,8 @@ struct ion_buffer { void *vaddr; int dmap_cnt; struct sg_table *sg_table; + unsigned long *dirty; + struct list_head vmas; }; /** diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 35b3726e4a34..dceed5b791cf 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -87,13 +87,20 @@ void *ion_system_heap_map_kernel(struct ion_heap *heap, struct scatterlist *sg; int i; void *vaddr; + pgprot_t pgprot; struct sg_table *table = buffer->priv_virt; struct page **pages = kmalloc(sizeof(struct page *) * table->nents, GFP_KERNEL); for_each_sg(table->sgl, sg, table->nents, i) pages[i] = sg_page(sg); - vaddr = vmap(pages, table->nents, VM_MAP, PAGE_KERNEL); + + if (buffer->flags & ION_FLAG_CACHED) + pgprot = PAGE_KERNEL; + else + pgprot = pgprot_writecombine(PAGE_KERNEL); + + vaddr = vmap(pages, table->nents, VM_MAP, pgprot); kfree(pages); return vaddr; @@ -179,7 +186,7 @@ static int ion_system_contig_heap_phys(struct ion_heap *heap, } struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) + struct ion_buffer *buffer) { struct sg_table *table; int ret; @@ -197,6 +204,13 @@ struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, return table; } +void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + sg_free_table(buffer->sg_table); + kfree(buffer->sg_table); +} + int ion_system_contig_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, struct vm_area_struct *vma) @@ -213,7 +227,7 @@ static struct ion_heap_ops kmalloc_ops = { .free = ion_system_contig_heap_free, .phys = ion_system_contig_heap_phys, .map_dma = ion_system_contig_heap_map_dma, - .unmap_dma = ion_system_heap_unmap_dma, + .unmap_dma = ion_system_contig_heap_unmap_dma, .map_kernel = ion_system_heap_map_kernel, .unmap_kernel = ion_system_heap_unmap_kernel, .map_user = ion_system_contig_heap_map_user, -- cgit v1.2.3 From bd5d6bdae118c49d194869ef757fd650dcabd33e Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:51 -0800 Subject: gpu: ion: Modify the system heap to try to allocate large/huge pages On some systems there is a performance benefit to reducing tlb pressure by minimizing the number of chunks in an allocation. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 116 ++++++++++++++++++++------ 1 file changed, 90 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index dceed5b791cf..98711ce03753 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -14,7 +14,10 @@ * */ +#include +#include #include +#include #include #include #include @@ -22,6 +25,35 @@ #include "ion.h" #include "ion_priv.h" +struct page_info { + struct page *page; + unsigned long order; + struct list_head list; +}; + +static struct page_info *alloc_largest_available(unsigned long size) +{ + static unsigned int orders[] = {8, 4, 0}; + struct page *page; + struct page_info *info; + int i; + + for (i = 0; i < ARRAY_SIZE(orders); i++) { + if (size < (1 << orders[i]) * PAGE_SIZE) + continue; + page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP | + __GFP_NOWARN | __GFP_NORETRY, orders[i]); + if (!page) + continue; + split_page(page, orders[i]); + info = kmap(page); + info->page = page; + info->order = orders[i]; + return info; + } + return NULL; +} + static int ion_system_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long size, unsigned long align, @@ -29,30 +61,54 @@ static int ion_system_heap_allocate(struct ion_heap *heap, { struct sg_table *table; struct scatterlist *sg; - int i, j; - int npages = PAGE_ALIGN(size) / PAGE_SIZE; + int ret; + struct list_head pages; + struct page_info *info, *tmp_info; + int i; + long size_remaining = PAGE_ALIGN(size); + + INIT_LIST_HEAD(&pages); + while (size_remaining > 0) { + info = alloc_largest_available(size_remaining); + if (!info) + goto err; + list_add_tail(&info->list, &pages); + size_remaining -= (1 << info->order) * PAGE_SIZE; + } table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) - return -ENOMEM; - i = sg_alloc_table(table, npages, GFP_KERNEL); - if (i) - goto err0; - for_each_sg(table->sgl, sg, table->nents, i) { - struct page *page; - page = alloc_page(GFP_HIGHUSER | __GFP_ZERO); - if (!page) - goto err1; - sg_set_page(sg, page, PAGE_SIZE, 0); + goto err; + + ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE, GFP_KERNEL); + if (ret) + goto err1; + + sg = table->sgl; + list_for_each_entry_safe(info, tmp_info, &pages, list) { + struct page *page = info->page; + for (i = 0; i < (1 << info->order); i++) { + sg_set_page(sg, page + i, PAGE_SIZE, 0); + sg = sg_next(sg); + } + list_del(&info->list); + memset(info, 0, sizeof(struct page_info)); + kunmap(page); } + + dma_sync_sg_for_device(NULL, table->sgl, table->nents, + DMA_BIDIRECTIONAL); + buffer->priv_virt = table; return 0; err1: - for_each_sg(table->sgl, sg, i, j) - __free_page(sg_page(sg)); - sg_free_table(table); -err0: kfree(table); +err: + list_for_each_entry(info, &pages, list) { + for (i = 0; i < (1 << info->order); i++) + __free_page(info->page + i); + kunmap(info->page); + } return -ENOMEM; } @@ -63,7 +119,7 @@ void ion_system_heap_free(struct ion_buffer *buffer) struct sg_table *table = buffer->priv_virt; for_each_sg(table->sgl, sg, table->nents, i) - __free_page(sg_page(sg)); + __free_pages(sg_page(sg), get_order(sg_dma_len(sg))); if (buffer->sg_table) sg_free_table(buffer->sg_table); kfree(buffer->sg_table); @@ -85,22 +141,29 @@ void *ion_system_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { struct scatterlist *sg; - int i; + int i, j; void *vaddr; pgprot_t pgprot; struct sg_table *table = buffer->priv_virt; - struct page **pages = kmalloc(sizeof(struct page *) * table->nents, - GFP_KERNEL); - - for_each_sg(table->sgl, sg, table->nents, i) - pages[i] = sg_page(sg); + int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; + struct page **pages = kzalloc(sizeof(struct page *) * npages, + GFP_KERNEL); + struct page **tmp = pages; if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; else pgprot = pgprot_writecombine(PAGE_KERNEL); - vaddr = vmap(pages, table->nents, VM_MAP, pgprot); + for_each_sg(table->sgl, sg, table->nents, i) { + int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; + struct page *page = sg_page(sg); + BUG_ON(i >= npages); + for (j = 0; j < npages_this_entry; j++) { + *(tmp++) = page++; + } + } + vaddr = vmap(pages, npages, VM_MAP, pgprot); kfree(pages); return vaddr; @@ -126,8 +189,9 @@ int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, offset--; continue; } - vm_insert_page(vma, addr, sg_page(sg)); - addr += PAGE_SIZE; + remap_pfn_range(vma, addr, page_to_pfn(sg_page(sg)), + sg_dma_len(sg), vma->vm_page_prot); + addr += sg_dma_len(sg); } return 0; } -- cgit v1.2.3 From 0b9ec1cfd4aafbadfb5e053cd201d7c3944dec80 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:52 -0800 Subject: gpu: ion: Add explicit sync ioctl This is deprecated in favor of using the dma_buf api which will automatically sync a buffer to memory when it is mapped to a device. However, that functionality is not ready, so this patch adds the ability to sync a buffer explicitly. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 38 ++++++++++++++++++++++++++++++++++++-- drivers/staging/android/ion/ion.h | 12 +++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bc9e922bfbf8..d4e4c686d098 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -684,8 +684,7 @@ static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, struct dma_buf *dmabuf = attachment->dmabuf; struct ion_buffer *buffer = dmabuf->priv; - if (buffer->flags & ION_FLAG_CACHED) - ion_buffer_sync_for_device(buffer, attachment->dev, direction); + ion_buffer_sync_for_device(buffer, attachment->dev, direction); return buffer->sg_table; } @@ -721,6 +720,10 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, pr_debug("%s: syncing for device %s\n", __func__, dev ? dev_name(dev) : "null"); + + if (!(buffer->flags & ION_FLAG_CACHED)) + return; + mutex_lock(&buffer->lock); for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { if (!test_bit(i, buffer->dirty)) @@ -958,6 +961,28 @@ end: return handle; } +static int ion_sync_for_device(struct ion_client *client, int fd) +{ + struct dma_buf *dmabuf; + struct ion_buffer *buffer; + + dmabuf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dmabuf)) + return PTR_ERR(dmabuf); + + /* if this memory came from ion */ + if (dmabuf->ops != &dma_buf_ops) { + pr_err("%s: can not sync dmabuf from another exporter\n", + __func__); + dma_buf_put(dmabuf); + return -EINVAL; + } + buffer = dmabuf->priv; + ion_buffer_sync_for_device(buffer, NULL, DMA_BIDIRECTIONAL); + dma_buf_put(dmabuf); + return 0; +} + static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_client *client = filp->private_data; @@ -1022,6 +1047,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; break; } + case ION_IOC_SYNC: + { + struct ion_fd_data data; + if (copy_from_user(&data, (void __user *)arg, + sizeof(struct ion_fd_data))) + return -EFAULT; + ion_sync_for_device(client, data.fd); + break; + } case ION_IOC_CUSTOM: { struct ion_device *dev = client->dev; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 88b9a2f5f87e..83baa3830fc6 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -328,7 +328,17 @@ struct ion_custom_data { * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle * filed set to the corresponding opaque handle. */ -#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, int) +#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data) + +/** + * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory + * + * Deprecated in favor of using the dma_buf api's correctly (syncing + * will happend automatically when the buffer is mapped to a device). + * If necessary should be used after touching a cached buffer from the cpu, + * this will make the buffer in memory coherent. + */ +#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data) /** * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl -- cgit v1.2.3 From fe65ec5bd1e0f44d601a9990aa253e85561c224d Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 13 Dec 2013 14:23:53 -0800 Subject: gpu: ion: do not ask for compound pages in system heap Signed-off-by: Dima Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 98711ce03753..3f607df63809 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -41,7 +41,7 @@ static struct page_info *alloc_largest_available(unsigned long size) for (i = 0; i < ARRAY_SIZE(orders); i++) { if (size < (1 << orders[i]) * PAGE_SIZE) continue; - page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP | + page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY, orders[i]); if (!page) continue; -- cgit v1.2.3 From a9bb075da5cdd67fddee27ea20e47ed3d04d6bb4 Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Fri, 13 Dec 2013 14:23:54 -0800 Subject: gpu: ion: Add missing argument to WARN call The condition argument to the WARN call in ion_free and ion_share_dma_buf are missing. Add the argument to allow correct printing of warning message. Signed-off-by: Olav Haugan [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d4e4c686d098..5872dd3e24e4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -408,7 +408,7 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&client->lock); if (!valid_handle) { - WARN("%s: invalid handle passed to free.\n", __func__); + WARN(1, "%s: invalid handle passed to free.\n", __func__); return; } ion_handle_put(handle); @@ -906,7 +906,7 @@ int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) valid_handle = ion_handle_validate(client, handle); mutex_unlock(&client->lock); if (!valid_handle) { - WARN("%s: invalid handle passed to share.\n", __func__); + WARN(1, "%s: invalid handle passed to share.\n", __func__); return -EINVAL; } -- cgit v1.2.3 From ee4c8aa9f94be03a69500af4b3c3a3efa5903ce0 Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Fri, 13 Dec 2013 14:23:55 -0800 Subject: gpu: ion: Add EXPORT_SYMBOL to functions Several functions in the ion interface is missing EXPORT_SYMBOL. This is needed to allow clients to use these functions from kernel modules. Add EXPORT_SYMBOL to functions that are supposed to be exposed. Signed-off-by: Olav Haugan [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 5872dd3e24e4..f536ce542782 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -396,6 +396,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, return handle; } +EXPORT_SYMBOL(ion_alloc); void ion_free(struct ion_client *client, struct ion_handle *handle) { @@ -413,6 +414,7 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) } ion_handle_put(handle); } +EXPORT_SYMBOL(ion_free); int ion_phys(struct ion_client *client, struct ion_handle *handle, ion_phys_addr_t *addr, size_t *len) @@ -438,6 +440,7 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); return ret; } +EXPORT_SYMBOL(ion_phys); static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { @@ -517,6 +520,7 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&client->lock); return vaddr; } +EXPORT_SYMBOL(ion_map_kernel); void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) { @@ -529,6 +533,7 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); } +EXPORT_SYMBOL(ion_unmap_kernel); static int ion_debug_client_show(struct seq_file *s, void *unused) { @@ -654,6 +659,7 @@ void ion_client_destroy(struct ion_client *client) kfree(client); } +EXPORT_SYMBOL(ion_client_destroy); struct sg_table *ion_sg_table(struct ion_client *client, struct ion_handle *handle) @@ -673,6 +679,7 @@ struct sg_table *ion_sg_table(struct ion_client *client, mutex_unlock(&client->lock); return table; } +EXPORT_SYMBOL(ion_sg_table); static void ion_buffer_sync_for_device(struct ion_buffer *buffer, struct device *dev, @@ -924,6 +931,7 @@ int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) } return fd; } +EXPORT_SYMBOL(ion_share_dma_buf); struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) { @@ -960,6 +968,7 @@ end: dma_buf_put(dmabuf); return handle; } +EXPORT_SYMBOL(ion_import_dma_buf); static int ion_sync_for_device(struct ion_client *client, int fd) { -- cgit v1.2.3 From a1c6b996ec1d9c78ab58f189719e1674fea3d2fb Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Fri, 13 Dec 2013 14:23:56 -0800 Subject: gpu: ion: IOCTL return success when error occurs ION_IOC_MAP, ION_IOC_SHARE, and ION_IOC_IMPORT may return success when an error occurs. Add correct error handling to ION_IOC_MAP, ION_IOC_SHARE, and ION_IOC_IMPORT. Signed-off-by: Olav Haugan [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index f536ce542782..a054edd41959 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1040,20 +1040,27 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) data.fd = ion_share_dma_buf(client, data.handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; + if (data.fd < 0) + return data.fd; break; } case ION_IOC_IMPORT: { struct ion_fd_data data; + int ret = 0; if (copy_from_user(&data, (void __user *)arg, sizeof(struct ion_fd_data))) return -EFAULT; data.handle = ion_import_dma_buf(client, data.fd); - if (IS_ERR(data.handle)) + if (IS_ERR(data.handle)) { + ret = PTR_ERR(data.handle); data.handle = NULL; + } if (copy_to_user((void __user *)arg, &data, sizeof(struct ion_fd_data))) return -EFAULT; + if (ret < 0) + return ret; break; } case ION_IOC_SYNC: -- cgit v1.2.3 From 55808b8d4dbd907834ac11e4959ef7d7040c3982 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 13 Dec 2013 14:23:57 -0800 Subject: gpu: ion: Don't call ion_buffer_put on error path If dma_buf_fd fails, the dma_buf needs to be cleaned up by calling dma_buf_put. dma_buf_put will call ion_dma_buf_release which in turn calls ion_buffer_put to clean up the buffer reference. Calling ion_buffer_put after dma_buf_put drops the reference count by one more which is incorrect. Fix this by getting rid of the extra ion_buffer_put call. Signed-off-by: Laura Abbott [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a054edd41959..4d91d20a4a81 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -925,10 +925,9 @@ int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) return PTR_ERR(dmabuf); } fd = dma_buf_fd(dmabuf, O_CLOEXEC); - if (fd < 0) { + if (fd < 0) dma_buf_put(dmabuf); - ion_buffer_put(buffer); - } + return fd; } EXPORT_SYMBOL(ion_share_dma_buf); -- cgit v1.2.3 From b82302438bbb496c76d5c4d64d82263253b0ac2b Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:58 -0800 Subject: gpu: ion: Only map as much of the vma as the user requested Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 3f607df63809..7397bc41fb45 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -192,6 +192,8 @@ int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, remap_pfn_range(vma, addr, page_to_pfn(sg_page(sg)), sg_dma_len(sg), vma->vm_page_prot); addr += sg_dma_len(sg); + if (addr >= vma->vm_end) + return 0; } return 0; } -- cgit v1.2.3 From 708f0cac89d00c366d562265e0b0244cda6f903d Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:23:59 -0800 Subject: gpu: ion: Switch to using kmalloc rather than kmap during allocation Previously, metadata was stored in the allocated pages themselves during allocation. However the system can only have a limited number of kmapped pages. A very large allocation might exceed this limit. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 7397bc41fb45..2fb9a6497089 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -46,7 +46,7 @@ static struct page_info *alloc_largest_available(unsigned long size) if (!page) continue; split_page(page, orders[i]); - info = kmap(page); + info = kmalloc(sizeof(struct page_info *), GFP_KERNEL); info->page = page; info->order = orders[i]; return info; @@ -93,7 +93,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, } list_del(&info->list); memset(info, 0, sizeof(struct page_info)); - kunmap(page); + kfree(info); } dma_sync_sg_for_device(NULL, table->sgl, table->nents, @@ -107,7 +107,7 @@ err: list_for_each_entry(info, &pages, list) { for (i = 0; i < (1 << info->order); i++) __free_page(info->page + i); - kunmap(info->page); + kfree(info); } return -ENOMEM; } -- cgit v1.2.3 From 12edf53db310345693fb7227c50e70a9b1fce434 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Fri, 13 Dec 2013 14:24:00 -0800 Subject: gpu: ion: fix page offset in dma_buf_kmap() Signed-off-by: Greg Hackmann [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 4d91d20a4a81..84229bd9bfbc 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -846,7 +846,7 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) { struct ion_buffer *buffer = dmabuf->priv; - return buffer->vaddr + offset; + return buffer->vaddr + offset * PAGE_SIZE; } static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, -- cgit v1.2.3 From 0e9c03a58ed599594780a69c988bd11e6459a752 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:01 -0800 Subject: gpu: ion: Fix race between ion_import and ion_free If preemted during ion_free after the refcount is updated but before the handle can be removed from the rb_tree, import might find that handle in the tree and try to reuse it when execution returns to free, the handle will be cleaned up leaving the caller of import with a corrupt handle. This patch modifies the locking to protect agains this race. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 84229bd9bfbc..f7dc82163c71 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -253,8 +253,6 @@ static void ion_handle_destroy(struct kref *kref) struct ion_client *client = handle->client; struct ion_buffer *buffer = handle->buffer; - mutex_lock(&client->lock); - mutex_lock(&buffer->lock); while (handle->kmap_cnt) ion_handle_kmap_put(handle); @@ -262,7 +260,6 @@ static void ion_handle_destroy(struct kref *kref) if (!RB_EMPTY_NODE(&handle->node)) rb_erase(&handle->node, &client->handles); - mutex_unlock(&client->lock); ion_buffer_put(buffer); kfree(handle); @@ -406,13 +403,13 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) mutex_lock(&client->lock); valid_handle = ion_handle_validate(client, handle); - mutex_unlock(&client->lock); if (!valid_handle) { WARN(1, "%s: invalid handle passed to free.\n", __func__); return; } ion_handle_put(handle); + mutex_unlock(&client->lock); } EXPORT_SYMBOL(ion_free); -- cgit v1.2.3 From 37bdbf00c618203467a17d01a4dfae324a818022 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:02 -0800 Subject: gpu: ion: Fix bug in ion_free Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index f7dc82163c71..e52522c11c5f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -406,6 +406,7 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) if (!valid_handle) { WARN(1, "%s: invalid handle passed to free.\n", __func__); + mutex_unlock(&client->lock); return; } ion_handle_put(handle); -- cgit v1.2.3 From 5ad7bc3addbc3886df05ebced942964307c243c8 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:03 -0800 Subject: gpu: ion: Add debug information for orphaned handles It is possible for a buffer to exist only as a dma_buf file descriptor without it being held in any handles. When this occurs it is impossible to track where the buffer is in the system (without traversing every process in the system and inspecting its file table). When buffers are orphaned like this, copy the task comm and pid of the last client to hold them into the buffer so we have a debugging hint as to where this buffer came from. In practice this will probalby be the process that allocated the buffer. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 58 ++++++++++++++++++++++++++++++++++ drivers/staging/android/ion/ion_priv.h | 14 ++++++++ 2 files changed, 72 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e52522c11c5f..6ba2c39f793b 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -228,6 +228,37 @@ static int ion_buffer_put(struct ion_buffer *buffer) return kref_put(&buffer->ref, ion_buffer_destroy); } +static void ion_buffer_add_to_handle(struct ion_buffer *buffer) +{ + mutex_lock(&buffer->dev->lock); + buffer->handle_count++; + mutex_unlock(&buffer->dev->lock); +} + +static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) +{ + /* + * when a buffer is removed from a handle, if it is not in + * any other handles, copy the taskcomm and the pid of the + * process it's being removed from into the buffer. At this + * point there will be no way to track what processes this buffer is + * being used by, it only exists as a dma_buf file descriptor. + * The taskcomm and pid can provide a debug hint as to where this fd + * is in the system + */ + mutex_lock(&buffer->dev->lock); + buffer->handle_count--; + BUG_ON(buffer->handle_count < 0); + if (!buffer->handle_count) { + struct task_struct *task; + + task = current->group_leader; + get_task_comm(buffer->task_comm, task); + buffer->pid = task_pid_nr(task); + } + mutex_unlock(&buffer->dev->lock); +} + static struct ion_handle *ion_handle_create(struct ion_client *client, struct ion_buffer *buffer) { @@ -240,6 +271,7 @@ static struct ion_handle *ion_handle_create(struct ion_client *client, RB_CLEAR_NODE(&handle->node); handle->client = client; ion_buffer_get(buffer); + ion_buffer_add_to_handle(buffer); handle->buffer = buffer; return handle; @@ -261,7 +293,9 @@ static void ion_handle_destroy(struct kref *kref) if (!RB_EMPTY_NODE(&handle->node)) rb_erase(&handle->node, &client->handles); + ion_buffer_remove_from_handle(buffer); ion_buffer_put(buffer); + kfree(handle); } @@ -1141,8 +1175,11 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) struct ion_heap *heap = s->private; struct ion_device *dev = heap->dev; struct rb_node *n; + size_t total_size = 0; + size_t total_orphaned_size = 0; seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size"); + seq_printf(s, "----------------------------------------------------\n"); for (n = rb_first(&dev->clients); n; n = rb_next(n)) { struct ion_client *client = rb_entry(n, struct ion_client, @@ -1161,6 +1198,27 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) client->pid, size); } } + seq_printf(s, "----------------------------------------------------\n"); + seq_printf(s, "orphaned allocations (info is from last known client):" + "\n"); + mutex_lock(&dev->lock); + for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { + struct ion_buffer *buffer = rb_entry(n, struct ion_buffer, + node); + if (buffer->heap->type == heap->type) + total_size += buffer->size; + if (!buffer->handle_count) { + seq_printf(s, "%16.s %16u %16u\n", buffer->task_comm, + buffer->pid, buffer->size); + total_orphaned_size += buffer->size; + } + } + mutex_unlock(&dev->lock); + seq_printf(s, "----------------------------------------------------\n"); + seq_printf(s, "%16.s %16u\n", "total orphaned", + total_orphaned_size); + seq_printf(s, "%16.s %16u\n", "total ", total_size); + return 0; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 406d1f43bf10..dabe1e87bedc 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "ion.h" @@ -43,6 +44,15 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @vaddr: the kenrel mapping if kmap_cnt is not zero * @dmap_cnt: number of times the buffer is mapped for dma * @sg_table: the sg table for the buffer if dmap_cnt is not zero + * @dirty: bitmask representing which pages of this buffer have + * been dirtied by the cpu and need cache maintenance + * before dma + * @vmas: list of vma's mapping this buffer + * @handle_count: count of handles referencing this buffer + * @task_comm: taskcomm of last client to reference this buffer in a + * handle, used for debugging + * @pid: pid of last client to reference this buffer in a + * handle, used for debugging */ struct ion_buffer { struct kref ref; @@ -62,6 +72,10 @@ struct ion_buffer { struct sg_table *sg_table; unsigned long *dirty; struct list_head vmas; + /* used to track orphaned buffers */ + int handle_count; + char task_comm[TASK_COMM_LEN]; + pid_t pid; }; /** -- cgit v1.2.3 From d3c0bced267a6726a2abc44c3457495bd7b427ca Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:04 -0800 Subject: gpu: ion: Fix memory leak of dirty bits Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 6ba2c39f793b..3aeb41c258d0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -164,24 +164,20 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, return ERR_PTR(PTR_ERR(table)); } buffer->sg_table = table; - if (buffer->flags & ION_FLAG_CACHED) + if (buffer->flags & ION_FLAG_CACHED) { for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { if (sg_dma_len(sg) == PAGE_SIZE) continue; pr_err("%s: cached mappings must have pagewise " "sg_lists\n", __func__); - heap->ops->unmap_dma(heap, buffer); - kfree(buffer); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto err; } - ret = ion_buffer_alloc_dirty(buffer); - if (ret) { - heap->ops->unmap_dma(heap, buffer); - heap->ops->free(buffer); - kfree(buffer); - return ERR_PTR(ret); + ret = ion_buffer_alloc_dirty(buffer); + if (ret) + goto err; } buffer->dev = dev; @@ -200,6 +196,12 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, sg_dma_address(sg) = sg_phys(sg); ion_buffer_add(dev, buffer); return buffer; + +err: + heap->ops->unmap_dma(heap, buffer); + heap->ops->free(buffer); + kfree(buffer); + return ERR_PTR(ret); } static void ion_buffer_destroy(struct kref *kref) @@ -209,12 +211,13 @@ static void ion_buffer_destroy(struct kref *kref) if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); mutex_lock(&dev->lock); rb_erase(&buffer->node, &dev->buffers); mutex_unlock(&dev->lock); + if (buffer->flags & ION_FLAG_CACHED) + kfree(buffer->dirty); kfree(buffer); } -- cgit v1.2.3 From 856661d514e8afc452bcda6f4c05a957694fea78 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:05 -0800 Subject: gpu: ion: Add support for cached mappings that don't fault We have found that faulting in the mappings for cached allocations has a significant performance impact and is only a benefit if only a small part of the buffer is touched by the cpu (an uncommon case for software rendering). This patch introduces a ION_FLAG_CACHED_NEEDS_SYNC which determines whether a mapping should be created by faulting or at mmap time. If this flag is set, userspace must manage the caches explictly using the SYNC ioctl. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 28 ++++++++++++++++++---------- drivers/staging/android/ion/ion.h | 3 +++ 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3aeb41c258d0..d1c7b84345e7 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -164,7 +164,8 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, return ERR_PTR(PTR_ERR(table)); } buffer->sg_table = table; - if (buffer->flags & ION_FLAG_CACHED) { + if (buffer->flags & ION_FLAG_CACHED && + !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)) { for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { if (sg_dma_len(sg) == PAGE_SIZE) @@ -763,7 +764,8 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, pr_debug("%s: syncing for device %s\n", __func__, dev ? dev_name(dev) : "null"); - if (!(buffer->flags & ION_FLAG_CACHED)) + if (!(buffer->flags & ION_FLAG_CACHED) || + (buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)) return; mutex_lock(&buffer->lock); @@ -853,18 +855,22 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) return -EINVAL; } - if (buffer->flags & ION_FLAG_CACHED) { + if (buffer->flags & ION_FLAG_CACHED && + !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)) { vma->vm_private_data = buffer; vma->vm_ops = &ion_vma_ops; ion_vm_open(vma); - } else { - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - mutex_lock(&buffer->lock); - /* now map it to userspace */ - ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); - mutex_unlock(&buffer->lock); + return 0; } + if (!(buffer->flags & ION_FLAG_CACHED)) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + mutex_lock(&buffer->lock); + /* now map it to userspace */ + ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); + mutex_unlock(&buffer->lock); + if (ret) pr_err("%s: failure mapping buffer to userspace\n", __func__); @@ -1021,7 +1027,9 @@ static int ion_sync_for_device(struct ion_client *client, int fd) return -EINVAL; } buffer = dmabuf->priv; - ion_buffer_sync_for_device(buffer, NULL, DMA_BIDIRECTIONAL); + + dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, + buffer->sg_table->nents, DMA_BIDIRECTIONAL); dma_buf_put(dmabuf); return 0; } diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 83baa3830fc6..072d64d72d60 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -50,6 +50,9 @@ enum ion_heap_type { cached, ion will do cache maintenance when the buffer is mapped for dma */ +#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* mappings of this buffer will created + at mmap time, if this is set + caches must be managed manually */ #ifdef __KERNEL__ struct ion_device; -- cgit v1.2.3 From 13ba7805f9bf710016ffde5e24437fd6e5a798dc Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:06 -0800 Subject: gpu: ion: optimize system heap for non fault buffers If a buffer's user mappings are not going to be faulted in it need not be allocated page wise. We can optimize this common case by allocating an sglist of larger chunks rather than creating an entry for each page in the allocation. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 21 ++++++++------ drivers/staging/android/ion/ion_priv.h | 9 ++++++ drivers/staging/android/ion/ion_system_heap.c | 40 ++++++++++++++++++++------- 3 files changed, 51 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d1c7b84345e7..6c589cb035d4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -100,6 +100,12 @@ struct ion_handle { unsigned int kmap_cnt; }; +bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) +{ + return ((buffer->flags & ION_FLAG_CACHED) && + !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); +} + /* this function should only be called while dev->lock is held */ static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) @@ -145,6 +151,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, return ERR_PTR(-ENOMEM); buffer->heap = heap; + buffer->flags = flags; kref_init(&buffer->ref); ret = heap->ops->allocate(heap, buffer, len, align, flags); @@ -155,7 +162,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->dev = dev; buffer->size = len; - buffer->flags = flags; table = heap->ops->map_dma(heap, buffer); if (IS_ERR_OR_NULL(table)) { @@ -164,14 +170,13 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, return ERR_PTR(PTR_ERR(table)); } buffer->sg_table = table; - if (buffer->flags & ION_FLAG_CACHED && - !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)) { + if (ion_buffer_fault_user_mappings(buffer)) { for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { if (sg_dma_len(sg) == PAGE_SIZE) continue; - pr_err("%s: cached mappings must have pagewise " - "sg_lists\n", __func__); + pr_err("%s: cached mappings that will be faulted in " + "must have pagewise sg_lists\n", __func__); ret = -EINVAL; goto err; } @@ -764,8 +769,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, pr_debug("%s: syncing for device %s\n", __func__, dev ? dev_name(dev) : "null"); - if (!(buffer->flags & ION_FLAG_CACHED) || - (buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)) + if (!ion_buffer_fault_user_mappings(buffer)) return; mutex_lock(&buffer->lock); @@ -855,8 +859,7 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) return -EINVAL; } - if (buffer->flags & ION_FLAG_CACHED && - !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)) { + if (ion_buffer_fault_user_mappings(buffer)) { vma->vm_private_data = buffer; vma->vm_ops = &ion_vma_ops; ion_vm_open(vma); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index dabe1e87bedc..1027ef4c9d16 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -131,6 +131,15 @@ struct ion_heap { const char *name; }; +/** + * ion_buffer_fault_user_mappings - fault in user mappings of this buffer + * @buffer: buffer + * + * indicates whether userspace mappings of this buffer will be faulted + * in, this can affect how buffers are allocated from the heap. + */ +bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer); + /** * ion_device_create - allocates and returns an ion device * @custom_ioctl: arch specific ioctl function if applicable diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 2fb9a6497089..ef8afc7e4e72 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -31,7 +31,8 @@ struct page_info { struct list_head list; }; -static struct page_info *alloc_largest_available(unsigned long size) +static struct page_info *alloc_largest_available(unsigned long size, + bool split_pages) { static unsigned int orders[] = {8, 4, 0}; struct page *page; @@ -45,7 +46,8 @@ static struct page_info *alloc_largest_available(unsigned long size) __GFP_NOWARN | __GFP_NORETRY, orders[i]); if (!page) continue; - split_page(page, orders[i]); + if (split_pages) + split_page(page, orders[i]); info = kmalloc(sizeof(struct page_info *), GFP_KERNEL); info->page = page; info->order = orders[i]; @@ -64,35 +66,49 @@ static int ion_system_heap_allocate(struct ion_heap *heap, int ret; struct list_head pages; struct page_info *info, *tmp_info; - int i; + int i = 0; long size_remaining = PAGE_ALIGN(size); + bool split_pages = ion_buffer_fault_user_mappings(buffer); + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { - info = alloc_largest_available(size_remaining); + info = alloc_largest_available(size_remaining, split_pages); if (!info) goto err; list_add_tail(&info->list, &pages); size_remaining -= (1 << info->order) * PAGE_SIZE; + i++; } table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) goto err; - ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE, GFP_KERNEL); + if (split_pages) + ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE, + GFP_KERNEL); + else + ret = sg_alloc_table(table, i, GFP_KERNEL); + if (ret) goto err1; sg = table->sgl; list_for_each_entry_safe(info, tmp_info, &pages, list) { struct page *page = info->page; - for (i = 0; i < (1 << info->order); i++) { - sg_set_page(sg, page + i, PAGE_SIZE, 0); + + if (split_pages) { + for (i = 0; i < (1 << info->order); i++) { + sg_set_page(sg, page + i, PAGE_SIZE, 0); + sg = sg_next(sg); + } + } else { + sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE, + 0); sg = sg_next(sg); } list_del(&info->list); - memset(info, 0, sizeof(struct page_info)); kfree(info); } @@ -105,8 +121,12 @@ err1: kfree(table); err: list_for_each_entry(info, &pages, list) { - for (i = 0; i < (1 << info->order); i++) - __free_page(info->page + i); + if (split_pages) + for (i = 0; i < (1 << info->order); i++) + __free_page(info->page + i); + else + __free_pages(info->page, info->order); + kfree(info); } return -ENOMEM; -- cgit v1.2.3 From ba96a2eed5d357c4107f04d8c9f32a58c9ed01da Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:07 -0800 Subject: gpu: ion: Stop trying to allocate from an order on first failure With this patch the system heap will only try to allocate from each order as long as allocations succeed. If it failes to obtain a higher order allocation, it doesn't retry that order. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index ef8afc7e4e72..30a225a92c40 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -32,7 +32,8 @@ struct page_info { }; static struct page_info *alloc_largest_available(unsigned long size, - bool split_pages) + bool split_pages, + unsigned int max_order) { static unsigned int orders[] = {8, 4, 0}; struct page *page; @@ -42,6 +43,8 @@ static struct page_info *alloc_largest_available(unsigned long size, for (i = 0; i < ARRAY_SIZE(orders); i++) { if (size < (1 << orders[i]) * PAGE_SIZE) continue; + if (max_order < orders[i]) + continue; page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY, orders[i]); if (!page) @@ -71,13 +74,17 @@ static int ion_system_heap_allocate(struct ion_heap *heap, bool split_pages = ion_buffer_fault_user_mappings(buffer); + unsigned int max_order = orders[0]; + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { - info = alloc_largest_available(size_remaining, split_pages); + info = alloc_largest_available(size_remaining, split_pages, + max_order); if (!info) goto err; list_add_tail(&info->list, &pages); size_remaining -= (1 << info->order) * PAGE_SIZE; + max_order = info->order; i++; } -- cgit v1.2.3 From b0599c014028eb19d0e0b2cd82390555a8eef22d Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:08 -0800 Subject: gpu: ion: ion_system_heap: Fix bug preventing compilation Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 30a225a92c40..25b02556076a 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -31,11 +31,12 @@ struct page_info { struct list_head list; }; +static unsigned int orders[] = {8, 4, 0}; + static struct page_info *alloc_largest_available(unsigned long size, bool split_pages, unsigned int max_order) { - static unsigned int orders[] = {8, 4, 0}; struct page *page; struct page_info *info; int i; -- cgit v1.2.3 From 98d5d5f8bad43770803a08e5a969cc9d8200b681 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:09 -0800 Subject: gpu: ion: use vmalloc to allocate page array to map kernel When ion_map_kernel is execute the system must allocate an array large enough to hold a pointer to each page in the buffer. If the buffer is very large and the system memory has become very fragmented, there may not be sufficient high order allocations available from kmalloc. Use vmalloc instead. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 25b02556076a..fcfbb661f2df 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -174,10 +174,12 @@ void *ion_system_heap_map_kernel(struct ion_heap *heap, pgprot_t pgprot; struct sg_table *table = buffer->priv_virt; int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - struct page **pages = kzalloc(sizeof(struct page *) * npages, - GFP_KERNEL); + struct page **pages = vmalloc(sizeof(struct page *) * npages); struct page **tmp = pages; + if (!pages) + return 0; + if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; else @@ -192,7 +194,7 @@ void *ion_system_heap_map_kernel(struct ion_heap *heap, } } vaddr = vmap(pages, npages, VM_MAP, pgprot); - kfree(pages); + vfree(pages); return vaddr; } -- cgit v1.2.3 From 0214c7f20bf4d5d2e204afaf43789f2f4782d9ae Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:10 -0800 Subject: gpu: ion: Add ion_page_pool. This patch adds a new utility heaps can use to manage memory. In the past we have found it can be very expensive to manage the caches when allocating memory, but it is imposible to know whether a previous user of a given memory allocation had a cached mapping. This patch adds the ability to store a pool of pages that were previously used uncached so that cache maintenance only need be done when growing this pool. The pool also contains a shrinker so memory from the pool can be recovered in low memory conditions. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Makefile | 3 +- drivers/staging/android/ion/ion_page_pool.c | 163 ++++++++++++++++++++++++++++ drivers/staging/android/ion/ion_priv.h | 44 ++++++++ 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/android/ion/ion_page_pool.c (limited to 'drivers') diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 73fe3fa10706..d1ddebb74a3f 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o +obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ + ion_carveout_heap.o obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c new file mode 100644 index 000000000000..78f39f7a719c --- /dev/null +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -0,0 +1,163 @@ +/* + * drivers/staging/android/ion/ion_mem_pool.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include +#include +#include "ion_priv.h" + +struct ion_page_pool_item { + struct page *page; + struct list_head list; +}; + +static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) +{ + struct page *page = alloc_pages(pool->gfp_mask, pool->order); + + if (!page) + return NULL; + /* this is only being used to flush the page for dma, + this api is not really suitable for calling from a driver + but no better way to flush a page for dma exist at this time */ + __dma_page_cpu_to_dev(page, 0, PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); + return page; +} + +static void ion_page_pool_free_pages(struct ion_page_pool *pool, + struct page *page) +{ + __free_pages(page, pool->order); +} + +static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) +{ + struct ion_page_pool_item *item; + + item = kmalloc(sizeof(struct ion_page_pool_item), GFP_KERNEL); + if (!item) + return -ENOMEM; + item->page = page; + list_add_tail(&item->list, &pool->items); + pool->count++; + return 0; +} + +static struct page *ion_page_pool_remove(struct ion_page_pool *pool) +{ + struct ion_page_pool_item *item; + struct page *page; + + BUG_ON(!pool->count); + BUG_ON(list_empty(&pool->items)); + + item = list_first_entry(&pool->items, struct ion_page_pool_item, list); + list_del(&item->list); + page = item->page; + kfree(item); + pool->count--; + return page; +} + +void *ion_page_pool_alloc(struct ion_page_pool *pool) +{ + struct page *page = NULL; + + BUG_ON(!pool); + + mutex_lock(&pool->mutex); + if (pool->count) + page = ion_page_pool_remove(pool); + else + page = ion_page_pool_alloc_pages(pool); + mutex_unlock(&pool->mutex); + + return page; +} + +void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) +{ + int ret; + + mutex_lock(&pool->mutex); + ret = ion_page_pool_add(pool, page); + if (ret) + ion_page_pool_free_pages(pool, page); + mutex_unlock(&pool->mutex); +} + +static int ion_page_pool_shrink(struct shrinker *shrinker, + struct shrink_control *sc) +{ + struct ion_page_pool *pool = container_of(shrinker, + struct ion_page_pool, + shrinker); + int nr_freed = 0; + int i; + + if (sc->nr_to_scan == 0) + return pool->count * (1 << pool->order); + + mutex_lock(&pool->mutex); + for (i = 0; i < sc->nr_to_scan && pool->count; i++) { + struct ion_page_pool_item *item; + struct page *page; + + item = list_first_entry(&pool->items, struct ion_page_pool_item, list); + page = item->page; + if (PageHighMem(page) && !(sc->gfp_mask & __GFP_HIGHMEM)) { + list_move_tail(&item->list, &pool->items); + continue; + } + BUG_ON(page != ion_page_pool_remove(pool)); + ion_page_pool_free_pages(pool, page); + nr_freed += (1 << pool->order); + } + pr_info("%s: shrunk page_pool of order %d by %d pages\n", __func__, + pool->order, nr_freed); + mutex_unlock(&pool->mutex); + + return pool->count * (1 << pool->order); +} + +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) +{ + struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool), + GFP_KERNEL); + if (!pool) + return NULL; + pool->count = 0; + INIT_LIST_HEAD(&pool->items); + pool->shrinker.shrink = ion_page_pool_shrink; + pool->shrinker.seeks = DEFAULT_SEEKS * 16; + pool->shrinker.batch = 0; + register_shrinker(&pool->shrinker); + pool->gfp_mask = gfp_mask; + pool->order = order; + mutex_init(&pool->mutex); + + return pool; +} + +void ion_page_pool_destroy(struct ion_page_pool *pool) +{ + unregister_shrinker(&pool->shrinker); + kfree(pool); +} + diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 1027ef4c9d16..0707733b7304 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "ion.h" @@ -195,4 +197,46 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, */ #define ION_CARVEOUT_ALLOCATE_FAIL -1 +/** + * functions for creating and destroying a heap pool -- allows you + * to keep a pool of pre allocated memory to use from your heap. Keeping + * a pool of memory that is ready for dma, ie any cached mapping have been + * invalidated from the cache, provides a significant peformance benefit on + * many systems */ + +/** + * struct ion_page_pool - pagepool struct + * @count: number of items in the pool + * @items: list of items + * @shrinker: a shrinker for the items + * @mutex: lock protecting this struct and especially the count + * item list + * @alloc: function to be used to allocate pageory when the pool + * is empty + * @free: function to be used to free pageory back to the system + * when the shrinker fires + * @gfp_mask: gfp_mask to use from alloc + * @order: order of pages in the pool + * + * Allows you to keep a pool of pre allocated pages to use from your heap. + * Keeping a pool of pages that is ready for dma, ie any cached mapping have + * been invalidated from the cache, provides a significant peformance benefit + * on many systems + */ +struct ion_page_pool { + int count; + struct list_head items; + struct shrinker shrinker; + struct mutex mutex; + void *(*alloc)(struct ion_page_pool *pool); + void (*free)(struct ion_page_pool *pool, struct page *page); + gfp_t gfp_mask; + unsigned int order; +}; + +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); +void ion_page_pool_destroy(struct ion_page_pool *); +void *ion_page_pool_alloc(struct ion_page_pool *); +void ion_page_pool_free(struct ion_page_pool *, struct page *); + #endif /* _ION_PRIV_H */ -- cgit v1.2.3 From 45b17a809fda352086b63518e32d272cc3442ed5 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:11 -0800 Subject: gpu: ion: Use the ion_page_pool from the system heap With this change the system heap will use pagepools to avoid having to invalidate memory when it is allocated, a significant performance improvement on some systems. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 18 ++- drivers/staging/android/ion/ion_priv.h | 11 ++ drivers/staging/android/ion/ion_system_heap.c | 191 +++++++++++++++++++++----- 3 files changed, 180 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 6c589cb035d4..0070c9bb7909 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -106,6 +106,11 @@ bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); } +bool ion_buffer_cached(struct ion_buffer *buffer) +{ + return !!(buffer->flags & ION_FLAG_CACHED); +} + /* this function should only be called while dev->lock is held */ static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) @@ -1219,11 +1224,12 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { struct ion_buffer *buffer = rb_entry(n, struct ion_buffer, node); - if (buffer->heap->type == heap->type) - total_size += buffer->size; + if (buffer->heap->type != heap->type) + continue; + total_size += buffer->size; if (!buffer->handle_count) { - seq_printf(s, "%16.s %16u %16u\n", buffer->task_comm, - buffer->pid, buffer->size); + seq_printf(s, "%16.s %16u %16u %d %d\n", buffer->task_comm, + buffer->pid, buffer->size, buffer->kmap_cnt, buffer->ref); total_orphaned_size += buffer->size; } } @@ -1232,6 +1238,10 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "%16.s %16u\n", "total orphaned", total_orphaned_size); seq_printf(s, "%16.s %16u\n", "total ", total_size); + seq_printf(s, "----------------------------------------------------\n"); + + if (heap->debug_show) + heap->debug_show(heap, s, unused); return 0; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 0707733b7304..9f326345b281 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -118,6 +118,8 @@ struct ion_heap_ops { * allocating. These are specified by platform data and * MUST be unique * @name: used for debugging + * @debug_show: called when heap debug file is read to add any + * heap specific debug info to output * * Represents a pool of memory from which buffers can be made. In some * systems the only heap is regular system memory allocated via vmalloc. @@ -131,8 +133,17 @@ struct ion_heap { struct ion_heap_ops *ops; int id; const char *name; + int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); }; +/** + * ion_buffer_cached - this ion buffer is cached + * @buffer: buffer + * + * indicates whether this ion buffer is cached + */ +bool ion_buffer_cached(struct ion_buffer *buffer); + /** * ion_buffer_fault_user_mappings - fault in user mappings of this buffer * @buffer: buffer diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index fcfbb661f2df..35fbfffa1ee2 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -20,39 +20,112 @@ #include #include #include +#include #include #include #include "ion.h" #include "ion_priv.h" +static const unsigned int orders[] = {8, 4, 0}; +static const int num_orders = ARRAY_SIZE(orders); +static int order_to_index(unsigned int order) +{ + int i; + for (i = 0; i < num_orders; i++) + if (order == orders[i]) + return i; + BUG(); + return -1; +} + +static unsigned int order_to_size(int order) +{ + return PAGE_SIZE << order; +} + +struct ion_system_heap { + struct ion_heap heap; + struct ion_page_pool **pools; +}; + struct page_info { struct page *page; - unsigned long order; + unsigned int order; struct list_head list; }; -static unsigned int orders[] = {8, 4, 0}; +static struct page *alloc_buffer_page(struct ion_system_heap *heap, + struct ion_buffer *buffer, + unsigned long order) +{ + bool cached = ion_buffer_cached(buffer); + bool split_pages = ion_buffer_fault_user_mappings(buffer); + struct ion_page_pool *pool = heap->pools[order_to_index(order)]; + struct page *page; -static struct page_info *alloc_largest_available(unsigned long size, - bool split_pages, + if (!cached) + page = ion_page_pool_alloc(pool); + else + page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | + __GFP_NOWARN | __GFP_NORETRY, order); + if (!page) + return 0; + if (split_pages) + split_page(page, order); + return page; +} + +static void free_buffer_page(struct ion_system_heap *heap, + struct ion_buffer *buffer, struct page *page, + unsigned int order) +{ + bool cached = ion_buffer_cached(buffer); + bool split_pages = ion_buffer_fault_user_mappings(buffer); + int i; + + if (!cached) { + struct ion_page_pool *pool = heap->pools[order_to_index(order)]; + /* zero the pages before returning them to the pool for + security. This uses vmap as we want to set the pgprot so + the writes to occur to noncached mappings, as the pool's + purpose is to keep the pages out of the cache */ + for (i = 0; i < order / PAGE_SIZE; i++) { + struct page *sub_page = page + i; + void *addr = vmap(&sub_page, 1, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); + memset(addr, 0, PAGE_SIZE); + vunmap(addr); + } + ion_page_pool_free(pool, page); + } else if (split_pages) { + for (i = 0; i < (1 << order); i++) + __free_page(page + i); + } else { + __free_pages(page, order); + } +} + + +static struct page_info *alloc_largest_available(struct ion_system_heap *heap, + struct ion_buffer *buffer, + unsigned long size, unsigned int max_order) { struct page *page; struct page_info *info; int i; - for (i = 0; i < ARRAY_SIZE(orders); i++) { - if (size < (1 << orders[i]) * PAGE_SIZE) + for (i = 0; i < num_orders; i++) { + if (size < order_to_size(orders[i])) continue; if (max_order < orders[i]) continue; - page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY, orders[i]); + + page = alloc_buffer_page(heap, buffer, orders[i]); if (!page) continue; - if (split_pages) - split_page(page, orders[i]); - info = kmalloc(sizeof(struct page_info *), GFP_KERNEL); + + info = kmalloc(sizeof(struct page_info), GFP_KERNEL); info->page = page; info->order = orders[i]; return info; @@ -65,6 +138,9 @@ static int ion_system_heap_allocate(struct ion_heap *heap, unsigned long size, unsigned long align, unsigned long flags) { + struct ion_system_heap *sys_heap = container_of(heap, + struct ion_system_heap, + heap); struct sg_table *table; struct scatterlist *sg; int ret; @@ -72,15 +148,12 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct page_info *info, *tmp_info; int i = 0; long size_remaining = PAGE_ALIGN(size); - bool split_pages = ion_buffer_fault_user_mappings(buffer); - - unsigned int max_order = orders[0]; + bool split_pages = ion_buffer_fault_user_mappings(buffer); INIT_LIST_HEAD(&pages); while (size_remaining > 0) { - info = alloc_largest_available(size_remaining, split_pages, - max_order); + info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); if (!info) goto err; list_add_tail(&info->list, &pages); @@ -105,7 +178,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, sg = table->sgl; list_for_each_entry_safe(info, tmp_info, &pages, list) { struct page *page = info->page; - if (split_pages) { for (i = 0; i < (1 << info->order); i++) { sg_set_page(sg, page + i, PAGE_SIZE, 0); @@ -129,12 +201,7 @@ err1: kfree(table); err: list_for_each_entry(info, &pages, list) { - if (split_pages) - for (i = 0; i < (1 << info->order); i++) - __free_page(info->page + i); - else - __free_pages(info->page, info->order); - + free_buffer_page(sys_heap, buffer, info->page, info->order); kfree(info); } return -ENOMEM; @@ -142,15 +209,19 @@ err: void ion_system_heap_free(struct ion_buffer *buffer) { - int i; - struct scatterlist *sg; + struct ion_heap *heap = buffer->heap; + struct ion_system_heap *sys_heap = container_of(heap, + struct ion_system_heap, + heap); struct sg_table *table = buffer->priv_virt; + struct scatterlist *sg; + LIST_HEAD(pages); + int i; for_each_sg(table->sgl, sg, table->nents, i) - __free_pages(sg_page(sg), get_order(sg_dma_len(sg))); - if (buffer->sg_table) - sg_free_table(buffer->sg_table); - kfree(buffer->sg_table); + free_buffer_page(sys_heap, buffer, sg_page(sg), get_order(sg_dma_len(sg))); + sg_free_table(table); + kfree(table); } struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, @@ -228,7 +299,7 @@ int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } -static struct ion_heap_ops vmalloc_ops = { +static struct ion_heap_ops system_heap_ops = { .allocate = ion_system_heap_allocate, .free = ion_system_heap_free, .map_dma = ion_system_heap_map_dma, @@ -238,21 +309,69 @@ static struct ion_heap_ops vmalloc_ops = { .map_user = ion_system_heap_map_user, }; +static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, + void *unused) +{ + + struct ion_system_heap *sys_heap = container_of(heap, + struct ion_system_heap, + heap); + int i; + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool = sys_heap->pools[i]; + seq_printf(s, "%d order %u pages in pool = %lu total\n", + pool->count, pool->order, + (1 << pool->order) * PAGE_SIZE * pool->count); + } + return 0; +} + struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) { - struct ion_heap *heap; + struct ion_system_heap *heap; + int i; - heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL); + heap = kzalloc(sizeof(struct ion_system_heap), GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); - heap->ops = &vmalloc_ops; - heap->type = ION_HEAP_TYPE_SYSTEM; - return heap; + heap->heap.ops = &system_heap_ops; + heap->heap.type = ION_HEAP_TYPE_SYSTEM; + heap->pools = kzalloc(sizeof(struct ion_page_pool *) * num_orders, + GFP_KERNEL); + if (!heap->pools) + goto err_alloc_pools; + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool; + pool = ion_page_pool_create(GFP_HIGHUSER | __GFP_ZERO | + __GFP_NOWARN | __GFP_NORETRY, + orders[i]); + if (!pool) + goto err_create_pool; + heap->pools[i] = pool; + } + heap->heap.debug_show = ion_system_heap_debug_show; + return &heap->heap; +err_create_pool: + for (i = 0; i < num_orders; i++) + if (heap->pools[i]) + ion_page_pool_destroy(heap->pools[i]); + kfree(heap->pools); +err_alloc_pools: + kfree(heap); + return ERR_PTR(-ENOMEM); } void ion_system_heap_destroy(struct ion_heap *heap) { - kfree(heap); + struct ion_system_heap *sys_heap = container_of(heap, + struct ion_system_heap, + heap); + int i; + + for (i = 0; i < num_orders; i++) + ion_page_pool_destroy(sys_heap->pools[i]); + kfree(sys_heap->pools); + kfree(sys_heap); } static int ion_system_contig_heap_allocate(struct ion_heap *heap, -- cgit v1.2.3 From ee4a4986d1a5998ada72c805c040daf759b687be Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:12 -0800 Subject: gpu: ion: Modify gfp flags in ion_system_heap When allocations larger than order 4 are made, use _GFP_NORETRY and __GFP_NO_KSWAPD so kswapd doesn't get kicked off to reclaim these larger chunks. For smaller allocaitons, these are unnecessary, as the system should be able to reclaim these. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 35fbfffa1ee2..b99fa0e7c7e8 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -26,6 +26,11 @@ #include "ion.h" #include "ion_priv.h" +static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | + __GFP_NOWARN | __GFP_NORETRY | + __GFP_NO_KSWAPD); +static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | + __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; static const int num_orders = ARRAY_SIZE(orders); static int order_to_index(unsigned int order) @@ -63,11 +68,15 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, struct ion_page_pool *pool = heap->pools[order_to_index(order)]; struct page *page; - if (!cached) + if (!cached) { page = ion_page_pool_alloc(pool); - else - page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY, order); + } else { + gfp_t gfp_flags = low_order_gfp_flags; + + if (order > 4) + gfp_flags = high_order_gfp_flags; + page = alloc_pages(gfp_flags, order); + } if (!page) return 0; if (split_pages) @@ -342,9 +351,11 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) goto err_alloc_pools; for (i = 0; i < num_orders; i++) { struct ion_page_pool *pool; - pool = ion_page_pool_create(GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY, - orders[i]); + gfp_t gfp_flags = low_order_gfp_flags; + + if (orders[i] > 4) + gfp_flags = high_order_gfp_flags; + pool = ion_page_pool_create(gfp_flags, orders[i]); if (!pool) goto err_create_pool; heap->pools[i] = pool; -- cgit v1.2.3 From 0fb9b815fe2010e9f8ff4b18bfd2a0ed9cf4eb8d Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:13 -0800 Subject: gpu: ion: Fix several issues with page pool Split out low and high mem pages so they are correctly reported when the shrinker is called. Fix potential deadlock caused by holding the page pool lock while allocationg and also needing that lock from the shrink function Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 77 ++++++++++++++++++--------- drivers/staging/android/ion/ion_priv.h | 12 +++-- drivers/staging/android/ion/ion_system_heap.c | 9 ++-- 3 files changed, 65 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 78f39f7a719c..ea45380d748c 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -54,24 +54,36 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) if (!item) return -ENOMEM; item->page = page; - list_add_tail(&item->list, &pool->items); - pool->count++; + if (PageHighMem(page)) { + list_add_tail(&item->list, &pool->high_items); + pool->high_count++; + } else { + list_add_tail(&item->list, &pool->low_items); + pool->low_count++; + } return 0; } -static struct page *ion_page_pool_remove(struct ion_page_pool *pool) +static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high) { struct ion_page_pool_item *item; struct page *page; - BUG_ON(!pool->count); - BUG_ON(list_empty(&pool->items)); + if (high) { + BUG_ON(!pool->high_count); + item = list_first_entry(&pool->high_items, + struct ion_page_pool_item, list); + pool->high_count--; + } else { + BUG_ON(!pool->low_count); + item = list_first_entry(&pool->low_items, + struct ion_page_pool_item, list); + pool->low_count--; + } - item = list_first_entry(&pool->items, struct ion_page_pool_item, list); list_del(&item->list); page = item->page; kfree(item); - pool->count--; return page; } @@ -82,12 +94,15 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool) BUG_ON(!pool); mutex_lock(&pool->mutex); - if (pool->count) - page = ion_page_pool_remove(pool); - else - page = ion_page_pool_alloc_pages(pool); + if (pool->high_count) + page = ion_page_pool_remove(pool, true); + else if (pool->low_count) + page = ion_page_pool_remove(pool, false); mutex_unlock(&pool->mutex); + if (!page) + page = ion_page_pool_alloc_pages(pool); + return page; } @@ -97,9 +112,9 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) mutex_lock(&pool->mutex); ret = ion_page_pool_add(pool, page); + mutex_unlock(&pool->mutex); if (ret) ion_page_pool_free_pages(pool, page); - mutex_unlock(&pool->mutex); } static int ion_page_pool_shrink(struct shrinker *shrinker, @@ -110,30 +125,38 @@ static int ion_page_pool_shrink(struct shrinker *shrinker, shrinker); int nr_freed = 0; int i; + bool high; + + if (sc->gfp_mask & __GFP_HIGHMEM) + high = true; if (sc->nr_to_scan == 0) - return pool->count * (1 << pool->order); + return high ? (pool->high_count + pool->low_count) * + (1 << pool->order) : + pool->low_count * (1 << pool->order); - mutex_lock(&pool->mutex); - for (i = 0; i < sc->nr_to_scan && pool->count; i++) { - struct ion_page_pool_item *item; + for (i = 0; i < sc->nr_to_scan; i++) { struct page *page; - item = list_first_entry(&pool->items, struct ion_page_pool_item, list); - page = item->page; - if (PageHighMem(page) && !(sc->gfp_mask & __GFP_HIGHMEM)) { - list_move_tail(&item->list, &pool->items); - continue; + mutex_lock(&pool->mutex); + if (high && pool->high_count) { + page = ion_page_pool_remove(pool, true); + } else if (pool->low_count) { + page = ion_page_pool_remove(pool, false); + } else { + mutex_unlock(&pool->mutex); + break; } - BUG_ON(page != ion_page_pool_remove(pool)); + mutex_unlock(&pool->mutex); ion_page_pool_free_pages(pool, page); nr_freed += (1 << pool->order); } pr_info("%s: shrunk page_pool of order %d by %d pages\n", __func__, pool->order, nr_freed); - mutex_unlock(&pool->mutex); - return pool->count * (1 << pool->order); + return high ? (pool->high_count + pool->low_count) * + (1 << pool->order) : + pool->low_count * (1 << pool->order); } struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) @@ -142,8 +165,10 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) GFP_KERNEL); if (!pool) return NULL; - pool->count = 0; - INIT_LIST_HEAD(&pool->items); + pool->high_count = 0; + pool->low_count = 0; + INIT_LIST_HEAD(&pool->low_items); + INIT_LIST_HEAD(&pool->high_items); pool->shrinker.shrink = ion_page_pool_shrink; pool->shrinker.seeks = DEFAULT_SEEKS * 16; pool->shrinker.batch = 0; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 9f326345b281..beb15957589c 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -217,8 +217,10 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, /** * struct ion_page_pool - pagepool struct - * @count: number of items in the pool - * @items: list of items + * @high_count: number of highmem items in the pool + * @low_count: number of lowmem items in the pool + * @high_items: list of highmem items + * @low_items: list of lowmem items * @shrinker: a shrinker for the items * @mutex: lock protecting this struct and especially the count * item list @@ -235,8 +237,10 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, * on many systems */ struct ion_page_pool { - int count; - struct list_head items; + int high_count; + int low_count; + struct list_head high_items; + struct list_head low_items; struct shrinker shrinker; struct mutex mutex; void *(*alloc)(struct ion_page_pool *pool); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index b99fa0e7c7e8..2204206ef5ff 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -328,9 +328,12 @@ static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, int i; for (i = 0; i < num_orders; i++) { struct ion_page_pool *pool = sys_heap->pools[i]; - seq_printf(s, "%d order %u pages in pool = %lu total\n", - pool->count, pool->order, - (1 << pool->order) * PAGE_SIZE * pool->count); + seq_printf(s, "%d order %u highmem pages in pool = %lu total\n", + pool->high_count, pool->order, + (1 << pool->order) * PAGE_SIZE * pool->high_count); + seq_printf(s, "%d order %u lowmem pages in pool = %lu total\n", + pool->low_count, pool->order, + (1 << pool->order) * PAGE_SIZE * pool->low_count); } return 0; } -- cgit v1.2.3 From efee5a0c62d827c0eca7044c2d14dd3324b325aa Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:14 -0800 Subject: gpu: ion: Fix lockdep issue in ion_page_pool Currently the mutex is held while kmalloc is called, under a low memory condition this might trigger the shrinker which also takes this mutex. Refactor so the mutex is not held during allocation. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index ea45380d748c..20790eb18c7d 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -53,6 +53,8 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) item = kmalloc(sizeof(struct ion_page_pool_item), GFP_KERNEL); if (!item) return -ENOMEM; + + mutex_lock(&pool->mutex); item->page = page; if (PageHighMem(page)) { list_add_tail(&item->list, &pool->high_items); @@ -61,6 +63,7 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) list_add_tail(&item->list, &pool->low_items); pool->low_count++; } + mutex_unlock(&pool->mutex); return 0; } @@ -110,9 +113,7 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) { int ret; - mutex_lock(&pool->mutex); ret = ion_page_pool_add(pool, page); - mutex_unlock(&pool->mutex); if (ret) ion_page_pool_free_pages(pool, page); } -- cgit v1.2.3 From 797a95c48c48d5b83bf1a7893602161d2e2a4654 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:15 -0800 Subject: gpu: ion: Switch to using a single shrink function The single shrink function will free lower order pages first. This enables compaction to work properly. [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 150 ++++++++++++++++++++++------ drivers/staging/android/ion/ion_priv.h | 3 +- 2 files changed, 123 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 20790eb18c7d..e59da3a5ed9f 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -14,13 +14,21 @@ * */ +#include #include #include +#include #include +#include #include #include #include "ion_priv.h" +/* #define DEBUG_PAGE_POOL_SHRINKER */ + +static struct plist_head pools = PLIST_HEAD_INIT(pools); +static struct shrinker shrinker; + struct ion_page_pool_item { struct page *page; struct list_head list; @@ -118,46 +126,110 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) ion_page_pool_free_pages(pool, page); } +#ifdef DEBUG_PAGE_POOL_SHRINKER +static int debug_drop_pools_set(void *data, u64 val) +{ + struct shrink_control sc; + int objs; + + sc.gfp_mask = -1; + sc.nr_to_scan = 0; + + if (!val) + return 0; + + objs = shrinker.shrink(&shrinker, &sc); + sc.nr_to_scan = objs; + + shrinker.shrink(&shrinker, &sc); + return 0; +} + +static int debug_drop_pools_get(void *data, u64 *val) +{ + struct shrink_control sc; + int objs; + + sc.gfp_mask = -1; + sc.nr_to_scan = 0; + + objs = shrinker.shrink(&shrinker, &sc); + *val = objs; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_drop_pools_fops, debug_drop_pools_get, + debug_drop_pools_set, "%llu\n"); + +static int debug_grow_pools_set(void *data, u64 val) +{ + struct ion_page_pool *pool; + struct page *page; + + plist_for_each_entry(pool, &pools, list) { + if (val != pool->list.prio) + continue; + page = ion_page_pool_alloc_pages(pool); + if (page) + ion_page_pool_add(pool, page); + } + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_grow_pools_fops, debug_drop_pools_get, + debug_grow_pools_set, "%llu\n"); +#endif + +static int ion_page_pool_total(bool high) +{ + struct ion_page_pool *pool; + int total = 0; + + plist_for_each_entry(pool, &pools, list) { + total += high ? (pool->high_count + pool->low_count) * + (1 << pool->order) : + pool->low_count * (1 << pool->order); + } + return total; +} + static int ion_page_pool_shrink(struct shrinker *shrinker, struct shrink_control *sc) { - struct ion_page_pool *pool = container_of(shrinker, - struct ion_page_pool, - shrinker); + struct ion_page_pool *pool; int nr_freed = 0; int i; bool high; + int nr_to_scan = sc->nr_to_scan; if (sc->gfp_mask & __GFP_HIGHMEM) high = true; - if (sc->nr_to_scan == 0) - return high ? (pool->high_count + pool->low_count) * - (1 << pool->order) : - pool->low_count * (1 << pool->order); + if (nr_to_scan == 0) + return ion_page_pool_total(high); - for (i = 0; i < sc->nr_to_scan; i++) { - struct page *page; + plist_for_each_entry(pool, &pools, list) { + for (i = 0; i < nr_to_scan; i++) { + struct page *page; - mutex_lock(&pool->mutex); - if (high && pool->high_count) { - page = ion_page_pool_remove(pool, true); - } else if (pool->low_count) { - page = ion_page_pool_remove(pool, false); - } else { + mutex_lock(&pool->mutex); + if (high && pool->high_count) { + page = ion_page_pool_remove(pool, true); + } else if (pool->low_count) { + page = ion_page_pool_remove(pool, false); + } else { + mutex_unlock(&pool->mutex); + break; + } mutex_unlock(&pool->mutex); - break; + ion_page_pool_free_pages(pool, page); + nr_freed += (1 << pool->order); } - mutex_unlock(&pool->mutex); - ion_page_pool_free_pages(pool, page); - nr_freed += (1 << pool->order); + nr_to_scan -= i; } - pr_info("%s: shrunk page_pool of order %d by %d pages\n", __func__, - pool->order, nr_freed); - return high ? (pool->high_count + pool->low_count) * - (1 << pool->order) : - pool->low_count * (1 << pool->order); + return ion_page_pool_total(high); } struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) @@ -170,20 +242,40 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) pool->low_count = 0; INIT_LIST_HEAD(&pool->low_items); INIT_LIST_HEAD(&pool->high_items); - pool->shrinker.shrink = ion_page_pool_shrink; - pool->shrinker.seeks = DEFAULT_SEEKS * 16; - pool->shrinker.batch = 0; - register_shrinker(&pool->shrinker); pool->gfp_mask = gfp_mask; pool->order = order; mutex_init(&pool->mutex); + plist_node_init(&pool->list, order); + plist_add(&pool->list, &pools); return pool; } void ion_page_pool_destroy(struct ion_page_pool *pool) { - unregister_shrinker(&pool->shrinker); + plist_del(&pool->list, &pools); kfree(pool); } +static int __init ion_page_pool_init(void) +{ + shrinker.shrink = ion_page_pool_shrink; + shrinker.seeks = DEFAULT_SEEKS; + shrinker.batch = 0; + register_shrinker(&shrinker); +#ifdef DEBUG_PAGE_POOL_SHRINKER + debugfs_create_file("ion_pools_shrink", 0644, NULL, NULL, + &debug_drop_pools_fops); + debugfs_create_file("ion_pools_grow", 0644, NULL, NULL, + &debug_grow_pools_fops); +#endif + return 0; +} + +static void __exit ion_page_pool_exit(void) +{ + unregister_shrinker(&shrinker); +} + +module_init(ion_page_pool_init); +module_exit(ion_page_pool_exit); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index beb15957589c..77e2ac0652c5 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -230,6 +230,7 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, * when the shrinker fires * @gfp_mask: gfp_mask to use from alloc * @order: order of pages in the pool + * @list: plist node for list of pools * * Allows you to keep a pool of pre allocated pages to use from your heap. * Keeping a pool of pages that is ready for dma, ie any cached mapping have @@ -241,12 +242,12 @@ struct ion_page_pool { int low_count; struct list_head high_items; struct list_head low_items; - struct shrinker shrinker; struct mutex mutex; void *(*alloc)(struct ion_page_pool *pool); void (*free)(struct ion_page_pool *pool, struct page *page); gfp_t gfp_mask; unsigned int order; + struct plist_node list; }; struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); -- cgit v1.2.3 From 8d7ab9a9e15b1d8965fb99b8486cae039a2de40e Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:16 -0800 Subject: gpu: ion: Refactor locking Removes contention for lock between allocate and free by reducing the length of time the lock is held for. Split out a seperate lock to protect the list of heaps and replace it with a rwsem since the list will most likely only be updated during initialization. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 45 ++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 0070c9bb7909..ef8f132bc2dd 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -38,15 +38,17 @@ /** * struct ion_device - the metadata of the ion device node * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @lock: lock protecting the buffers & heaps trees + * @buffers: an rb tree of all the existing buffers + * @buffer_lock: lock protecting the tree of buffers + * @lock: rwsem protecting the tree of heaps and clients * @heaps: list of all the heaps in the system * @user_clients: list of all the clients created from userspace */ struct ion_device { struct miscdevice dev; struct rb_root buffers; - struct mutex lock; + struct mutex buffer_lock; + struct rw_semaphore lock; struct rb_root heaps; long (*custom_ioctl) (struct ion_client *client, unsigned int cmd, unsigned long arg); @@ -205,7 +207,9 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, cached mapping that mapping has been invalidated */ for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) sg_dma_address(sg) = sg_phys(sg); + mutex_lock(&dev->buffer_lock); ion_buffer_add(dev, buffer); + mutex_unlock(&dev->buffer_lock); return buffer; err: @@ -224,9 +228,9 @@ static void ion_buffer_destroy(struct kref *kref) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); - mutex_lock(&dev->lock); + mutex_lock(&dev->buffer_lock); rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->buffer_lock); if (buffer->flags & ION_FLAG_CACHED) kfree(buffer->dirty); kfree(buffer); @@ -244,9 +248,9 @@ static int ion_buffer_put(struct ion_buffer *buffer) static void ion_buffer_add_to_handle(struct ion_buffer *buffer) { - mutex_lock(&buffer->dev->lock); + mutex_lock(&buffer->lock); buffer->handle_count++; - mutex_unlock(&buffer->dev->lock); + mutex_unlock(&buffer->lock); } static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) @@ -260,7 +264,7 @@ static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) * The taskcomm and pid can provide a debug hint as to where this fd * is in the system */ - mutex_lock(&buffer->dev->lock); + mutex_lock(&buffer->lock); buffer->handle_count--; BUG_ON(buffer->handle_count < 0); if (!buffer->handle_count) { @@ -270,7 +274,7 @@ static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) get_task_comm(buffer->task_comm, task); buffer->pid = task_pid_nr(task); } - mutex_unlock(&buffer->dev->lock); + mutex_unlock(&buffer->lock); } static struct ion_handle *ion_handle_create(struct ion_client *client, @@ -403,7 +407,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, len = PAGE_ALIGN(len); - mutex_lock(&dev->lock); + down_read(&dev->lock); for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) { struct ion_heap *heap = rb_entry(n, struct ion_heap, node); /* if the client doesn't support this heap type */ @@ -416,7 +420,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, if (!IS_ERR_OR_NULL(buffer)) break; } - mutex_unlock(&dev->lock); + up_read(&dev->lock); if (buffer == NULL) return ERR_PTR(-ENODEV); @@ -662,7 +666,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, client->task = task; client->pid = pid; - mutex_lock(&dev->lock); + down_write(&dev->lock); p = &dev->clients.rb_node; while (*p) { parent = *p; @@ -680,7 +684,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, client->debug_root = debugfs_create_file(debug_name, 0664, dev->debug_root, client, &debug_client_fops); - mutex_unlock(&dev->lock); + up_write(&dev->lock); return client; } @@ -696,12 +700,12 @@ void ion_client_destroy(struct ion_client *client) node); ion_handle_destroy(&handle->ref); } - mutex_lock(&dev->lock); + down_write(&dev->lock); if (client->task) put_task_struct(client->task); rb_erase(&client->node, &dev->clients); debugfs_remove_recursive(client->debug_root); - mutex_unlock(&dev->lock); + up_write(&dev->lock); kfree(client); } @@ -1220,7 +1224,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "----------------------------------------------------\n"); seq_printf(s, "orphaned allocations (info is from last known client):" "\n"); - mutex_lock(&dev->lock); + mutex_lock(&dev->buffer_lock); for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { struct ion_buffer *buffer = rb_entry(n, struct ion_buffer, node); @@ -1233,7 +1237,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) total_orphaned_size += buffer->size; } } - mutex_unlock(&dev->lock); + mutex_unlock(&dev->buffer_lock); seq_printf(s, "----------------------------------------------------\n"); seq_printf(s, "%16.s %16u\n", "total orphaned", total_orphaned_size); @@ -1270,7 +1274,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) __func__); heap->dev = dev; - mutex_lock(&dev->lock); + down_write(&dev->lock); while (*p) { parent = *p; entry = rb_entry(parent, struct ion_heap, node); @@ -1291,7 +1295,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) debugfs_create_file(heap->name, 0664, dev->debug_root, heap, &debug_heap_fops); end: - mutex_unlock(&dev->lock); + up_write(&dev->lock); } struct ion_device *ion_device_create(long (*custom_ioctl) @@ -1322,7 +1326,8 @@ struct ion_device *ion_device_create(long (*custom_ioctl) idev->custom_ioctl = custom_ioctl; idev->buffers = RB_ROOT; - mutex_init(&idev->lock); + mutex_init(&idev->buffer_lock); + init_rwsem(&idev->lock); idev->heaps = RB_ROOT; idev->clients = RB_ROOT; return idev; -- cgit v1.2.3 From 31b9432b4b588777b30ad1f7d8eecf7770a45edc Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:17 -0800 Subject: gpu: ion: Clear GFP_WAIT flag on high order allocations This will prevent the kernel from kicking off compaction when higher order allocations are made. Instead we will get these high order allocations only if they are readily available. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 2204206ef5ff..ad4933e1b421 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -28,7 +28,7 @@ static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY | - __GFP_NO_KSWAPD); + __GFP_NO_KSWAPD) & ~__GFP_WAIT; static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; -- cgit v1.2.3 From 8fae831288210dae626e212aaab459154b65ed79 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:18 -0800 Subject: gpu: ion: Don't flush allocatoins that come from the page pools Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index ad4933e1b421..02726a9702b1 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -76,9 +76,14 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (order > 4) gfp_flags = high_order_gfp_flags; page = alloc_pages(gfp_flags, order); + if (!page) + return 0; + __dma_page_cpu_to_dev(page, 0, PAGE_SIZE << order, + DMA_BIDIRECTIONAL); } if (!page) return 0; + if (split_pages) split_page(page, order); return page; @@ -201,9 +206,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, kfree(info); } - dma_sync_sg_for_device(NULL, table->sgl, table->nents, - DMA_BIDIRECTIONAL); - buffer->priv_virt = table; return 0; err1: -- cgit v1.2.3 From b308a7c5cfef6e0d15b8872982645313f415b229 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:19 -0800 Subject: gpu: ion: Fix bug in ion_system_heap map_user When the requested mmap length was not an integer number of chunks or the buffer, or if an offset was provided, a bug would cause extra or incorrect pages of the buffer to be mapped. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 02726a9702b1..df084695221b 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -292,18 +292,27 @@ int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, { struct sg_table *table = buffer->priv_virt; unsigned long addr = vma->vm_start; - unsigned long offset = vma->vm_pgoff; + unsigned long offset = vma->vm_pgoff * PAGE_SIZE; struct scatterlist *sg; int i; for_each_sg(table->sgl, sg, table->nents, i) { - if (offset) { - offset--; + struct page *page = sg_page(sg); + unsigned long remainder = vma->vm_end - addr; + unsigned long len = sg_dma_len(sg); + + if (offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); continue; + } else if (offset) { + page += offset / PAGE_SIZE; + len = sg_dma_len(sg) - offset; + offset = 0; } - remap_pfn_range(vma, addr, page_to_pfn(sg_page(sg)), - sg_dma_len(sg), vma->vm_page_prot); - addr += sg_dma_len(sg); + len = min(len, remainder); + remap_pfn_range(vma, addr, page_to_pfn(page), len, + vma->vm_page_prot); + addr += len; if (addr >= vma->vm_end) return 0; } -- cgit v1.2.3 From 4f597eac2cecf49eab3d0be02d17887f04d95c39 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:20 -0800 Subject: gpu: ion: Fix bug in zeroing pages in system heap Pages are zeroed for security purposes when returned to the ion heap. There was a bug in this code preventing this from happening. Bug: 7573871 Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index df084695221b..9327a320a960 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -103,7 +103,7 @@ static void free_buffer_page(struct ion_system_heap *heap, security. This uses vmap as we want to set the pgprot so the writes to occur to noncached mappings, as the pool's purpose is to keep the pages out of the cache */ - for (i = 0; i < order / PAGE_SIZE; i++) { + for (i = 0; i < (1 << order); i++) { struct page *sub_page = page + i; void *addr = vmap(&sub_page, 1, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); -- cgit v1.2.3 From caaf3f12970057b32176eb333a1bfc3c6f67cbdd Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 13 Dec 2013 14:24:21 -0800 Subject: gpu: ion: fix carveout ops when using carveout heap ion_buffer_create function failed because map_dma and unmap_dma operations aren't set by carveout heap. Signed-off-by: Benjamin Gaignard [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index daa348e3a65a..fd641688127c 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -142,6 +142,8 @@ static struct ion_heap_ops carveout_heap_ops = { .allocate = ion_carveout_heap_allocate, .free = ion_carveout_heap_free, .phys = ion_carveout_heap_phys, + .map_dma = ion_carveout_heap_map_dma, + .unmap_dma = ion_carveout_heap_unmap_dma, .map_user = ion_carveout_heap_map_user, .map_kernel = ion_carveout_heap_map_kernel, .unmap_kernel = ion_carveout_heap_unmap_kernel, -- cgit v1.2.3 From 092c354b8a2e590b028957e68ad38c69b21cadd8 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 13 Dec 2013 14:24:22 -0800 Subject: gpu: ion: fix compilation warning use atomic_read to get the refcount value to avoid compilation warning Signed-off-by: Benjamin Gaignard [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ef8f132bc2dd..e0eb2de73695 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1233,7 +1233,8 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) total_size += buffer->size; if (!buffer->handle_count) { seq_printf(s, "%16.s %16u %16u %d %d\n", buffer->task_comm, - buffer->pid, buffer->size, buffer->kmap_cnt, buffer->ref); + buffer->pid, buffer->size, buffer->kmap_cnt, + atomic_read(&buffer->ref.refcount)); total_orphaned_size += buffer->size; } } -- cgit v1.2.3 From fa9bba557dd3cd3d9188541cf309f5c71486d8a6 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:23 -0800 Subject: gpu: ion: Modify reserve function for carveouts with no start address This patch allows you to specify a heap that requires carveout memory but that doesn't specify a start address. Memblock_alloc will be called to find a location for these heaps. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e0eb2de73695..3167c1d46169 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1343,16 +1343,35 @@ void ion_device_destroy(struct ion_device *dev) void __init ion_reserve(struct ion_platform_data *data) { - int i, ret; + int i; for (i = 0; i < data->nr; i++) { if (data->heaps[i].size == 0) continue; - ret = memblock_reserve(data->heaps[i].base, - data->heaps[i].size); - if (ret) - pr_err("memblock reserve of %x@%lx failed\n", - data->heaps[i].size, - data->heaps[i].base); + + if (data->heaps[i].base == 0) { + phys_addr_t paddr; + paddr = memblock_alloc_base(data->heaps[i].size, + data->heaps[i].align, + MEMBLOCK_ALLOC_ANYWHERE); + if (!paddr) { + pr_err("%s: error allocating memblock for " + "heap %d\n", + __func__, i); + continue; + } + data->heaps[i].base = paddr; + } else { + int ret = memblock_reserve(data->heaps[i].base, + data->heaps[i].size); + if (ret) + pr_err("memblock reserve of %x@%lx failed\n", + data->heaps[i].size, + data->heaps[i].base); + } + pr_info("%s: %s reserved base %lx size %d\n", __func__, + data->heaps[i].name, + data->heaps[i].base, + data->heaps[i].size); } } -- cgit v1.2.3 From df0f6c7634f0856c3eb3d26ddc909d414199f6a7 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:24 -0800 Subject: gpu: ion: Fix bug where MAP ioctl was no longer supported Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3167c1d46169..3f22f88a3906 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1086,6 +1086,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } case ION_IOC_SHARE: + case ION_IOC_MAP: { struct ion_fd_data data; -- cgit v1.2.3 From cd69488c7be3abb0767b49f313b12b8591abe5dc Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:25 -0800 Subject: gpu: ion: Switch heap rbtree to a prio list Switches the rbtree tree of heaps for a plist. This significantly simplifies the code and the list is small and is modified only at first boot so the rbtree is unnecessary. This also switches the traversal of the heap list to traverse from highest to lowest id's. This allows allocations to pass a heap mask that falls back on the system heap -- typically id 0, which is the common case. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 35 ++++++++-------------------------- drivers/staging/android/ion/ion_priv.h | 4 ++-- 2 files changed, 10 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3f22f88a3906..8cc0489e69d1 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -49,7 +49,7 @@ struct ion_device { struct rb_root buffers; struct mutex buffer_lock; struct rw_semaphore lock; - struct rb_root heaps; + struct plist_head heaps; long (*custom_ioctl) (struct ion_client *client, unsigned int cmd, unsigned long arg); struct rb_root clients; @@ -389,10 +389,10 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, size_t align, unsigned int heap_mask, unsigned int flags) { - struct rb_node *n; struct ion_handle *handle; struct ion_device *dev = client->dev; struct ion_buffer *buffer = NULL; + struct ion_heap *heap; pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len, align, heap_mask, flags); @@ -408,8 +408,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, len = PAGE_ALIGN(len); down_read(&dev->lock); - for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) { - struct ion_heap *heap = rb_entry(n, struct ion_heap, node); + plist_for_each_entry(heap, &dev->heaps, node) { /* if the client doesn't support this heap type */ if (!((1 << heap->type) & client->heap_mask)) continue; @@ -1266,10 +1265,6 @@ static const struct file_operations debug_heap_fops = { void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { - struct rb_node **p = &dev->heaps.rb_node; - struct rb_node *parent = NULL; - struct ion_heap *entry; - if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || !heap->ops->unmap_dma) pr_err("%s: can not add heap with invalid ops struct.\n", @@ -1277,26 +1272,12 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) heap->dev = dev; down_write(&dev->lock); - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_heap, node); - - if (heap->id < entry->id) { - p = &(*p)->rb_left; - } else if (heap->id > entry->id ) { - p = &(*p)->rb_right; - } else { - pr_err("%s: can not insert multiple heaps with " - "id %d\n", __func__, heap->id); - goto end; - } - } - - rb_link_node(&heap->node, parent, p); - rb_insert_color(&heap->node, &dev->heaps); + /* use negative heap->id to reverse the priority -- when traversing + the list later attempt higher id numbers first */ + plist_node_init(&heap->node, -heap->id); + plist_add(&heap->node, &dev->heaps); debugfs_create_file(heap->name, 0664, dev->debug_root, heap, &debug_heap_fops); -end: up_write(&dev->lock); } @@ -1330,7 +1311,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); - idev->heaps = RB_ROOT; + plist_head_init(&idev->heaps); idev->clients = RB_ROOT; return idev; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 77e2ac0652c5..57dbf6a39fac 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -127,11 +127,11 @@ struct ion_heap_ops { * that are allocated from a specially reserved heap. */ struct ion_heap { - struct rb_node node; + struct plist_node node; struct ion_device *dev; enum ion_heap_type type; struct ion_heap_ops *ops; - int id; + unsigned int id; const char *name; int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); }; -- cgit v1.2.3 From 8898227ed555b477e2989a2a9b984fa37e7a9b42 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:26 -0800 Subject: gpu: ion: Refactor common mapping functions out of system heap The system heap contained several general purpose functions to map buffers to the kernel and userspace. This patch refactors those into ion_heap.c so they can be used by other heaps. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 75 ++++++++++++++++++++++++ drivers/staging/android/ion/ion_priv.h | 10 ++++ drivers/staging/android/ion/ion_system_heap.c | 84 ++------------------------- 3 files changed, 91 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 4f7caa87bca9..441e9ef0b69c 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -15,9 +15,84 @@ */ #include +#include +#include +#include #include "ion.h" #include "ion_priv.h" +void *ion_heap_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct scatterlist *sg; + int i, j; + void *vaddr; + pgprot_t pgprot; + struct sg_table *table = buffer->sg_table; + int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; + struct page **pages = vmalloc(sizeof(struct page *) * npages); + struct page **tmp = pages; + + if (!pages) + return 0; + + if (buffer->flags & ION_FLAG_CACHED) + pgprot = PAGE_KERNEL; + else + pgprot = pgprot_writecombine(PAGE_KERNEL); + + for_each_sg(table->sgl, sg, table->nents, i) { + int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; + struct page *page = sg_page(sg); + BUG_ON(i >= npages); + for (j = 0; j < npages_this_entry; j++) { + *(tmp++) = page++; + } + } + vaddr = vmap(pages, npages, VM_MAP, pgprot); + vfree(pages); + + return vaddr; +} + +void ion_heap_unmap_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + vunmap(buffer->vaddr); +} + +int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + struct sg_table *table = buffer->sg_table; + unsigned long addr = vma->vm_start; + unsigned long offset = vma->vm_pgoff * PAGE_SIZE; + struct scatterlist *sg; + int i; + + for_each_sg(table->sgl, sg, table->nents, i) { + struct page *page = sg_page(sg); + unsigned long remainder = vma->vm_end - addr; + unsigned long len = sg_dma_len(sg); + + if (offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + continue; + } else if (offset) { + page += offset / PAGE_SIZE; + len = sg_dma_len(sg) - offset; + offset = 0; + } + len = min(len, remainder); + remap_pfn_range(vma, addr, page_to_pfn(page), len, + vma->vm_page_prot); + addr += len; + if (addr >= vma->vm_end) + return 0; + } + return 0; +} + struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) { struct ion_heap *heap = NULL; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 57dbf6a39fac..6b3616e31d14 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -177,6 +177,16 @@ void ion_device_destroy(struct ion_device *dev); */ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); +/** + * some helpers for common operations on buffers using the sg_table + * and vaddr fields + */ +void *ion_heap_map_kernel(struct ion_heap *, struct ion_buffer *); +void ion_heap_unmap_kernel(struct ion_heap *, struct ion_buffer *); +int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, + struct vm_area_struct *); + + /** * functions for creating and destroying the built in ion heaps. * architectures can add their own custom architecture specific diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 9327a320a960..89247cf965d7 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -224,7 +224,7 @@ void ion_system_heap_free(struct ion_buffer *buffer) struct ion_system_heap *sys_heap = container_of(heap, struct ion_system_heap, heap); - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct scatterlist *sg; LIST_HEAD(pages); int i; @@ -247,86 +247,14 @@ void ion_system_heap_unmap_dma(struct ion_heap *heap, return; } -void *ion_system_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct scatterlist *sg; - int i, j; - void *vaddr; - pgprot_t pgprot; - struct sg_table *table = buffer->priv_virt; - int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - struct page **pages = vmalloc(sizeof(struct page *) * npages); - struct page **tmp = pages; - - if (!pages) - return 0; - - if (buffer->flags & ION_FLAG_CACHED) - pgprot = PAGE_KERNEL; - else - pgprot = pgprot_writecombine(PAGE_KERNEL); - - for_each_sg(table->sgl, sg, table->nents, i) { - int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; - struct page *page = sg_page(sg); - BUG_ON(i >= npages); - for (j = 0; j < npages_this_entry; j++) { - *(tmp++) = page++; - } - } - vaddr = vmap(pages, npages, VM_MAP, pgprot); - vfree(pages); - - return vaddr; -} - -void ion_system_heap_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - vunmap(buffer->vaddr); -} - -int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - struct sg_table *table = buffer->priv_virt; - unsigned long addr = vma->vm_start; - unsigned long offset = vma->vm_pgoff * PAGE_SIZE; - struct scatterlist *sg; - int i; - - for_each_sg(table->sgl, sg, table->nents, i) { - struct page *page = sg_page(sg); - unsigned long remainder = vma->vm_end - addr; - unsigned long len = sg_dma_len(sg); - - if (offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - continue; - } else if (offset) { - page += offset / PAGE_SIZE; - len = sg_dma_len(sg) - offset; - offset = 0; - } - len = min(len, remainder); - remap_pfn_range(vma, addr, page_to_pfn(page), len, - vma->vm_page_prot); - addr += len; - if (addr >= vma->vm_end) - return 0; - } - return 0; -} - static struct ion_heap_ops system_heap_ops = { .allocate = ion_system_heap_allocate, .free = ion_system_heap_free, .map_dma = ion_system_heap_map_dma, .unmap_dma = ion_system_heap_unmap_dma, - .map_kernel = ion_system_heap_map_kernel, - .unmap_kernel = ion_system_heap_unmap_kernel, - .map_user = ion_system_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, + .map_user = ion_heap_map_user, }; static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, @@ -468,8 +396,8 @@ static struct ion_heap_ops kmalloc_ops = { .phys = ion_system_contig_heap_phys, .map_dma = ion_system_contig_heap_map_dma, .unmap_dma = ion_system_contig_heap_unmap_dma, - .map_kernel = ion_system_heap_map_kernel, - .unmap_kernel = ion_system_heap_unmap_kernel, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_system_contig_heap_map_user, }; -- cgit v1.2.3 From e3c2eb7cd9f291bf17ee056e388d0089cf378345 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:27 -0800 Subject: gpu: ion: Add chunk heap This patch adds support for a chunk heap that allows for buffers that are made up of a list of fixed size chunks taken from a carveout. Chunk sizes are configured when the heaps are created by passing the chunk size in the priv field of the heap platform data. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Makefile | 2 +- drivers/staging/android/ion/ion.h | 5 + drivers/staging/android/ion/ion_chunk_heap.c | 174 +++++++++++++++++++++++++++ drivers/staging/android/ion/ion_heap.c | 6 + drivers/staging/android/ion/ion_priv.h | 4 +- 5 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 drivers/staging/android/ion/ion_chunk_heap.c (limited to 'drivers') diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index d1ddebb74a3f..306fff970de4 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ - ion_carveout_heap.o + ion_carveout_heap.o ion_chunk_heap.o obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 072d64d72d60..e5f679f1b989 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -33,6 +33,7 @@ enum ion_heap_type { ION_HEAP_TYPE_SYSTEM, ION_HEAP_TYPE_SYSTEM_CONTIG, ION_HEAP_TYPE_CARVEOUT, + ION_HEAP_TYPE_CHUNK, ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always are at the end of this enum */ ION_NUM_HEAPS, @@ -75,6 +76,8 @@ struct ion_buffer; * @name: used for debug purposes * @base: base address of heap in physical memory if applicable * @size: size of the heap in bytes if applicable + * @align: required alignment in physical memory if applicable + * @priv: private info passed from the board file * * Provided by the board file. */ @@ -84,6 +87,8 @@ struct ion_platform_heap { const char *name; ion_phys_addr_t base; size_t size; + ion_phys_addr_t align; + void *priv; }; /** diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c new file mode 100644 index 000000000000..1d4740987267 --- /dev/null +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -0,0 +1,174 @@ +/* + * drivers/staging/android/ion/ion_chunk_heap.c + * + * Copyright (C) 2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" + +#include + +struct ion_chunk_heap { + struct ion_heap heap; + struct gen_pool *pool; + ion_phys_addr_t base; + unsigned long chunk_size; + unsigned long size; + unsigned long allocated; +}; + +static int ion_chunk_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) +{ + struct ion_chunk_heap *chunk_heap = + container_of(heap, struct ion_chunk_heap, heap); + struct sg_table *table; + struct scatterlist *sg; + int ret, i; + unsigned long num_chunks; + + if (ion_buffer_fault_user_mappings(buffer)) + return -ENOMEM; + + num_chunks = ALIGN(size, chunk_heap->chunk_size) / + chunk_heap->chunk_size; + buffer->size = num_chunks * chunk_heap->chunk_size; + + if (buffer->size > chunk_heap->size - chunk_heap->allocated) + return -ENOMEM; + + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + ret = sg_alloc_table(table, num_chunks, GFP_KERNEL); + if (ret) { + kfree(table); + return ret; + } + + sg = table->sgl; + for (i = 0; i < num_chunks; i++) { + unsigned long paddr = gen_pool_alloc(chunk_heap->pool, + chunk_heap->chunk_size); + if (!paddr) + goto err; + sg_set_page(sg, phys_to_page(paddr), chunk_heap->chunk_size, 0); + sg = sg_next(sg); + } + + buffer->priv_virt = table; + chunk_heap->allocated += buffer->size; + return 0; +err: + sg = table->sgl; + for (i -= 1; i >= 0; i--) { + gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), + sg_dma_len(sg)); + sg = sg_next(sg); + } + sg_free_table(table); + kfree(table); + return -ENOMEM; +} + +static void ion_chunk_heap_free(struct ion_buffer *buffer) +{ + struct ion_heap *heap = buffer->heap; + struct ion_chunk_heap *chunk_heap = + container_of(heap, struct ion_chunk_heap, heap); + struct sg_table *table = buffer->priv_virt; + struct scatterlist *sg; + int i; + + for_each_sg(table->sgl, sg, table->nents, i) { + __dma_page_cpu_to_dev(sg_page(sg), 0, sg_dma_len(sg), + DMA_BIDIRECTIONAL); + gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), + sg_dma_len(sg)); + } + chunk_heap->allocated -= buffer->size; + sg_free_table(table); + kfree(table); +} + +struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return buffer->priv_virt; +} + +void ion_chunk_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return; +} + +static struct ion_heap_ops chunk_heap_ops = { + .allocate = ion_chunk_heap_allocate, + .free = ion_chunk_heap_free, + .map_dma = ion_chunk_heap_map_dma, + .unmap_dma = ion_chunk_heap_unmap_dma, + .map_user = ion_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, +}; + +struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) +{ + struct ion_chunk_heap *chunk_heap; + + chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL); + if (!chunk_heap) + return ERR_PTR(-ENOMEM); + + chunk_heap->chunk_size = (unsigned long)heap_data->priv; + chunk_heap->pool = gen_pool_create(get_order(chunk_heap->chunk_size) + + PAGE_SHIFT, -1); + if (!chunk_heap->pool) { + kfree(chunk_heap); + return ERR_PTR(-ENOMEM); + } + chunk_heap->base = heap_data->base; + chunk_heap->size = heap_data->size; + chunk_heap->allocated = 0; + __dma_page_cpu_to_dev(phys_to_page(heap_data->base), 0, heap_data->size, + DMA_BIDIRECTIONAL); + gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); + chunk_heap->heap.ops = &chunk_heap_ops; + chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; + pr_info("%s: base %lu size %ld align %ld\n", __func__, chunk_heap->base, + heap_data->size, heap_data->align); + + return &chunk_heap->heap; +} + +void ion_chunk_heap_destroy(struct ion_heap *heap) +{ + struct ion_chunk_heap *chunk_heap = + container_of(heap, struct ion_chunk_heap, heap); + + gen_pool_destroy(chunk_heap->pool); + kfree(chunk_heap); + chunk_heap = NULL; +} diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 441e9ef0b69c..a9bf52e4d6f1 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -107,6 +107,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) case ION_HEAP_TYPE_CARVEOUT: heap = ion_carveout_heap_create(heap_data); break; + case ION_HEAP_TYPE_CHUNK: + heap = ion_chunk_heap_create(heap_data); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type); @@ -140,6 +143,9 @@ void ion_heap_destroy(struct ion_heap *heap) case ION_HEAP_TYPE_CARVEOUT: ion_carveout_heap_destroy(heap); break; + case ION_HEAP_TYPE_CHUNK: + ion_chunk_heap_destroy(heap); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap->type); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 6b3616e31d14..eef4de81e817 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -195,7 +195,6 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct ion_heap *ion_heap_create(struct ion_platform_heap *); void ion_heap_destroy(struct ion_heap *); - struct ion_heap *ion_system_heap_create(struct ion_platform_heap *); void ion_system_heap_destroy(struct ion_heap *); @@ -204,6 +203,9 @@ void ion_system_contig_heap_destroy(struct ion_heap *); struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *); void ion_carveout_heap_destroy(struct ion_heap *); + +struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *); +void ion_chunk_heap_destroy(struct ion_heap *); /** * kernel api to allocate/free from carveout -- used when carveout is * used to back an architecture specific custom heap -- cgit v1.2.3 From 38eeeb51245c88d2be9bd098bcc32b15f6014bfa Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:28 -0800 Subject: gpu: ion: Clarify variable names and comments around heap ids v types There is some confusion between when to use the heap type and when the id. This patch clarifies this by using clearer variable names and describing the intention in the comments. Also fixes the client debug code to print heaps by id instead of type. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 37 ++++++++++++++-------------- drivers/staging/android/ion/ion.h | 51 +++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 8cc0489e69d1..c775e4f2c5a5 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,4 +1,5 @@ /* + * drivers/staging/android/ion/ion.c * * Copyright (C) 2011 Google, Inc. @@ -62,7 +63,7 @@ struct ion_device { * @dev: backpointer to ion device * @handles: an rb tree of all the handles in this client * @lock: lock protecting the tree of handles - * @heap_mask: mask of all supported heaps + * @heap_type_mask: mask of all supported heap types * @name: used for debugging * @task: used for debugging * @@ -75,7 +76,7 @@ struct ion_client { struct ion_device *dev; struct rb_root handles; struct mutex lock; - unsigned int heap_mask; + unsigned int heap_type_mask; const char *name; struct task_struct *task; pid_t pid; @@ -386,7 +387,7 @@ static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) } struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int heap_mask, + size_t align, unsigned int heap_id_mask, unsigned int flags) { struct ion_handle *handle; @@ -394,8 +395,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, struct ion_buffer *buffer = NULL; struct ion_heap *heap; - pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len, - align, heap_mask, flags); + pr_debug("%s: len %d align %d heap_id_mask %u flags %x\n", __func__, + len, align, heap_id_mask, flags); /* * traverse the list of heaps available in this system in priority * order. If the heap type is supported by the client, and matches the @@ -410,10 +411,10 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, down_read(&dev->lock); plist_for_each_entry(heap, &dev->heaps, node) { /* if the client doesn't support this heap type */ - if (!((1 << heap->type) & client->heap_mask)) + if (!((1 << heap->type) & client->heap_type_mask)) continue; - /* if the caller didn't specify this heap type */ - if (!((1 << heap->id) & heap_mask)) + /* if the caller didn't specify this heap id */ + if (!((1 << heap->id) & heap_id_mask)) continue; buffer = ion_buffer_create(heap, dev, len, align, flags); if (!IS_ERR_OR_NULL(buffer)) @@ -588,24 +589,24 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) { struct ion_client *client = s->private; struct rb_node *n; - size_t sizes[ION_NUM_HEAPS] = {0}; - const char *names[ION_NUM_HEAPS] = {0}; + size_t sizes[ION_NUM_HEAP_IDS] = {0}; + const char *names[ION_NUM_HEAP_IDS] = {0}; int i; mutex_lock(&client->lock); for (n = rb_first(&client->handles); n; n = rb_next(n)) { struct ion_handle *handle = rb_entry(n, struct ion_handle, node); - enum ion_heap_type type = handle->buffer->heap->type; + unsigned int id = handle->buffer->heap->id; - if (!names[type]) - names[type] = handle->buffer->heap->name; - sizes[type] += handle->buffer->size; + if (!names[id]) + names[id] = handle->buffer->heap->name; + sizes[id] += handle->buffer->size; } mutex_unlock(&client->lock); seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes"); - for (i = 0; i < ION_NUM_HEAPS; i++) { + for (i = 0; i < ION_NUM_HEAP_IDS; i++) { if (!names[i]) continue; seq_printf(s, "%16.16s: %16u\n", names[i], sizes[i]); @@ -626,7 +627,7 @@ static const struct file_operations debug_client_fops = { }; struct ion_client *ion_client_create(struct ion_device *dev, - unsigned int heap_mask, + unsigned int heap_type_mask, const char *name) { struct ion_client *client; @@ -661,7 +662,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, client->handles = RB_ROOT; mutex_init(&client->lock); client->name = name; - client->heap_mask = heap_mask; + client->heap_type_mask = heap_type_mask; client->task = task; client->pid = pid; @@ -1057,7 +1058,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; data.handle = ion_alloc(client, data.len, data.align, - data.heap_mask, data.flags); + data.heap_id_mask, data.flags); if (IS_ERR(data.handle)) return PTR_ERR(data.handle); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index e5f679f1b989..a315858f96a4 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -43,6 +43,8 @@ enum ion_heap_type { #define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) +#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8 + /** * heap flags - the lower 16 bits are used by core ion, the upper 16 * bits are reserved for use by the heaps themselves. @@ -71,8 +73,9 @@ struct ion_buffer; /** * struct ion_platform_heap - defines a heap in the given platform * @type: type of the heap from ion_heap_type enum - * @id: unique identifier for heap. When allocating (lower numbers - * will be allocated from first) + * @id: unique identifier for heap. When allocating higher numbers + * will be allocated from first. At allocation these are passed + * as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS. * @name: used for debug purposes * @base: base address of heap in physical memory if applicable * @size: size of the heap in bytes if applicable @@ -116,12 +119,13 @@ void ion_reserve(struct ion_platform_data *data); /** * ion_client_create() - allocate a client and returns it - * @dev: the global ion device - * @heap_mask: mask of heaps this client can allocate from - * @name: used for debugging + * @dev: the global ion device + * @heap_type_mask: mask of heaps this client can allocate from + * @name: used for debugging */ struct ion_client *ion_client_create(struct ion_device *dev, - unsigned int heap_mask, const char *name); + unsigned int heap_type_mask, + const char *name); /** * ion_client_destroy() - free's a client and all it's handles @@ -134,21 +138,22 @@ void ion_client_destroy(struct ion_client *client); /** * ion_alloc - allocate ion memory - * @client: the client - * @len: size of the allocation - * @align: requested allocation alignment, lots of hardware blocks have - * alignment requirements of some kind - * @heap_mask: mask of heaps to allocate from, if multiple bits are set - * heaps will be tried in order from lowest to highest order bit - * @flags: heap flags, the low 16 bits are consumed by ion, the high 16 - * bits are passed on to the respective heap and can be heap - * custom + * @client: the client + * @len: size of the allocation + * @align: requested allocation alignment, lots of hardware blocks + * have alignment requirements of some kind + * @heap_id_mask: mask of heaps to allocate from, if multiple bits are set + * heaps will be tried in order from highest to lowest + * id + * @flags: heap flags, the low 16 bits are consumed by ion, the + * high 16 bits are passed on to the respective heap and + * can be heap custom * * Allocate memory in one of the heaps provided in heap mask and return * an opaque handle to it. */ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int heap_mask, + size_t align, unsigned int heap_id_mask, unsigned int flags); /** @@ -237,19 +242,19 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); /** * struct ion_allocation_data - metadata passed from userspace for allocations - * @len: size of the allocation - * @align: required alignment of the allocation - * @heap_mask: mask of heaps to allocate from - * @flags: flags passed to heap - * @handle: pointer that will be populated with a cookie to use to refer - * to this allocation + * @len: size of the allocation + * @align: required alignment of the allocation + * @heap_id_mask: mask of heap ids to allocate from + * @flags: flags passed to heap + * @handle: pointer that will be populated with a cookie to use to + * refer to this allocation * * Provided by userspace as an argument to the ioctl */ struct ion_allocation_data { size_t len; size_t align; - unsigned int heap_mask; + unsigned int heap_id_mask; unsigned int flags; struct ion_handle *handle; }; -- cgit v1.2.3 From 9122fe867de6d0c4021c208b18612166931b5487 Mon Sep 17 00:00:00 2001 From: Johan Mossberg Date: Fri, 13 Dec 2013 14:24:29 -0800 Subject: gpu: ion: Export ion_client_create Will enable modules to allocate memory with ion. Signed-off-by: Johan Mossberg [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index c775e4f2c5a5..7c25d9fc6b38 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -688,6 +688,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, return client; } +EXPORT_SYMBOL(ion_client_create); void ion_client_destroy(struct ion_client *client) { -- cgit v1.2.3 From 2bb9f5034ec75ea40068e4a462cde882ce9f5a1e Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:30 -0800 Subject: gpu: ion: Remove heapmask from client The heapmask in the client generally wasn't being used. This patch removes it. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 17 +++++------------ drivers/staging/android/ion/ion.h | 1 - 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7c25d9fc6b38..054e672f1794 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -63,7 +63,6 @@ struct ion_device { * @dev: backpointer to ion device * @handles: an rb tree of all the handles in this client * @lock: lock protecting the tree of handles - * @heap_type_mask: mask of all supported heap types * @name: used for debugging * @task: used for debugging * @@ -76,7 +75,6 @@ struct ion_client { struct ion_device *dev; struct rb_root handles; struct mutex lock; - unsigned int heap_type_mask; const char *name; struct task_struct *task; pid_t pid; @@ -410,9 +408,6 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, down_read(&dev->lock); plist_for_each_entry(heap, &dev->heaps, node) { - /* if the client doesn't support this heap type */ - if (!((1 << heap->type) & client->heap_type_mask)) - continue; /* if the caller didn't specify this heap id */ if (!((1 << heap->id) & heap_id_mask)) continue; @@ -627,7 +622,6 @@ static const struct file_operations debug_client_fops = { }; struct ion_client *ion_client_create(struct ion_device *dev, - unsigned int heap_type_mask, const char *name) { struct ion_client *client; @@ -662,7 +656,6 @@ struct ion_client *ion_client_create(struct ion_device *dev, client->handles = RB_ROOT; mutex_init(&client->lock); client->name = name; - client->heap_type_mask = heap_type_mask; client->task = task; client->pid = pid; @@ -1162,7 +1155,7 @@ static int ion_open(struct inode *inode, struct file *file) struct ion_client *client; pr_debug("%s: %d\n", __func__, __LINE__); - client = ion_client_create(dev, -1, "user"); + client = ion_client_create(dev, "user"); if (IS_ERR_OR_NULL(client)) return PTR_ERR(client); file->private_data = client; @@ -1178,7 +1171,7 @@ static const struct file_operations ion_fops = { }; static size_t ion_debug_heap_total(struct ion_client *client, - enum ion_heap_type type) + unsigned int id) { size_t size = 0; struct rb_node *n; @@ -1188,7 +1181,7 @@ static size_t ion_debug_heap_total(struct ion_client *client, struct ion_handle *handle = rb_entry(n, struct ion_handle, node); - if (handle->buffer->heap->type == type) + if (handle->buffer->heap->id == id) size += handle->buffer->size; } mutex_unlock(&client->lock); @@ -1209,7 +1202,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) for (n = rb_first(&dev->clients); n; n = rb_next(n)) { struct ion_client *client = rb_entry(n, struct ion_client, node); - size_t size = ion_debug_heap_total(client, heap->type); + size_t size = ion_debug_heap_total(client, heap->id); if (!size) continue; if (client->task) { @@ -1230,7 +1223,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { struct ion_buffer *buffer = rb_entry(n, struct ion_buffer, node); - if (buffer->heap->type != heap->type) + if (buffer->heap->id != heap->id) continue; total_size += buffer->size; if (!buffer->handle_count) { diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index a315858f96a4..0f67014f2403 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -124,7 +124,6 @@ void ion_reserve(struct ion_platform_data *data); * @name: used for debugging */ struct ion_client *ion_client_create(struct ion_device *dev, - unsigned int heap_type_mask, const char *name); /** -- cgit v1.2.3 From 77cbe828a10026f8ff208eaa67d75675a3ffbdfc Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:31 -0800 Subject: gpu: ion: Modify zeroing code so it only allocates address space once vmap/vunmap spend a significant amount of time allocating the address space to map into. Rather than allocating address space for each page, instead allocate once for the entire allocation and then just map and unmap each page into that address space. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 28 ++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 89247cf965d7..e54307fbc30d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -91,7 +91,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, static void free_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, struct page *page, - unsigned int order) + unsigned int order, struct vm_struct *vm_struct) { bool cached = ion_buffer_cached(buffer); bool split_pages = ion_buffer_fault_user_mappings(buffer); @@ -105,10 +105,13 @@ static void free_buffer_page(struct ion_system_heap *heap, purpose is to keep the pages out of the cache */ for (i = 0; i < (1 << order); i++) { struct page *sub_page = page + i; - void *addr = vmap(&sub_page, 1, VM_MAP, - pgprot_writecombine(PAGE_KERNEL)); - memset(addr, 0, PAGE_SIZE); - vunmap(addr); + struct page **pages = &sub_page; + map_vm_area(vm_struct, + pgprot_writecombine(PAGE_KERNEL), + &pages); + memset(vm_struct->addr, 0, PAGE_SIZE); + unmap_kernel_range((unsigned long)vm_struct->addr, + PAGE_SIZE); } ion_page_pool_free(pool, page); } else if (split_pages) { @@ -164,6 +167,8 @@ static int ion_system_heap_allocate(struct ion_heap *heap, long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; bool split_pages = ion_buffer_fault_user_mappings(buffer); + struct vm_struct *vm_struct; + pte_t *ptes; INIT_LIST_HEAD(&pages); while (size_remaining > 0) { @@ -211,10 +216,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap, err1: kfree(table); err: + vm_struct = get_vm_area(PAGE_SIZE, &ptes); list_for_each_entry(info, &pages, list) { - free_buffer_page(sys_heap, buffer, info->page, info->order); + free_buffer_page(sys_heap, buffer, info->page, info->order, + vm_struct); kfree(info); } + free_vm_area(vm_struct); return -ENOMEM; } @@ -227,10 +235,16 @@ void ion_system_heap_free(struct ion_buffer *buffer) struct sg_table *table = buffer->sg_table; struct scatterlist *sg; LIST_HEAD(pages); + struct vm_struct *vm_struct; + pte_t *ptes; int i; + vm_struct = get_vm_area(PAGE_SIZE, &ptes); + for_each_sg(table->sgl, sg, table->nents, i) - free_buffer_page(sys_heap, buffer, sg_page(sg), get_order(sg_dma_len(sg))); + free_buffer_page(sys_heap, buffer, sg_page(sg), + get_order(sg_dma_len(sg)), vm_struct); + free_vm_area(vm_struct); sg_free_table(table); kfree(table); } -- cgit v1.2.3 From 0b6b2cde0928707a618ce8c07970219f21d066e5 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:32 -0800 Subject: gpu: ion: Refactor the code to zero buffers Refactor the code in the system heap used to map and zero the buffers into a seperate utility so it can be called from other heaps. Use it from the chunk heap. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 2 ++ drivers/staging/android/ion/ion_heap.c | 37 +++++++++++++++++++++++++++ drivers/staging/android/ion/ion_priv.h | 1 + drivers/staging/android/ion/ion_system_heap.c | 34 ++++++------------------ 4 files changed, 48 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 1d4740987267..558290989fe6 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -101,6 +101,8 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) struct scatterlist *sg; int i; + ion_heap_buffer_zero(buffer); + for_each_sg(table->sgl, sg, table->nents, i) { __dma_page_cpu_to_dev(sg_page(sg), 0, sg_dma_len(sg), DMA_BIDIRECTIONAL); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index a9bf52e4d6f1..11066a2abb4b 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -93,6 +93,43 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } +int ion_heap_buffer_zero(struct ion_buffer *buffer) +{ + struct sg_table *table = buffer->sg_table; + pgprot_t pgprot; + struct scatterlist *sg; + struct vm_struct *vm_struct; + int i, j, ret = 0; + + if (buffer->flags & ION_FLAG_CACHED) + pgprot = PAGE_KERNEL; + else + pgprot = pgprot_writecombine(PAGE_KERNEL); + + vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC); + if (!vm_struct) + return -ENOMEM; + + for_each_sg(table->sgl, sg, table->nents, i) { + struct page *page = sg_page(sg); + unsigned long len = sg_dma_len(sg); + + for (j = 0; j < len / PAGE_SIZE; j++) { + struct page *sub_page = page + j; + struct page **pages = &sub_page; + ret = map_vm_area(vm_struct, pgprot, &pages); + if (ret) + goto end; + memset(vm_struct->addr, 0, PAGE_SIZE); + unmap_kernel_range((unsigned long)vm_struct->addr, + PAGE_SIZE); + } + } +end: + free_vm_area(vm_struct); + return ret; +} + struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) { struct ion_heap *heap = NULL; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index eef4de81e817..cfb4264fe499 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -185,6 +185,7 @@ void *ion_heap_map_kernel(struct ion_heap *, struct ion_buffer *); void ion_heap_unmap_kernel(struct ion_heap *, struct ion_buffer *); int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); +int ion_heap_buffer_zero(struct ion_buffer *buffer); /** diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index e54307fbc30d..3ca704e3ee14 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -91,7 +91,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, static void free_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, struct page *page, - unsigned int order, struct vm_struct *vm_struct) + unsigned int order) { bool cached = ion_buffer_cached(buffer); bool split_pages = ion_buffer_fault_user_mappings(buffer); @@ -99,20 +99,6 @@ static void free_buffer_page(struct ion_system_heap *heap, if (!cached) { struct ion_page_pool *pool = heap->pools[order_to_index(order)]; - /* zero the pages before returning them to the pool for - security. This uses vmap as we want to set the pgprot so - the writes to occur to noncached mappings, as the pool's - purpose is to keep the pages out of the cache */ - for (i = 0; i < (1 << order); i++) { - struct page *sub_page = page + i; - struct page **pages = &sub_page; - map_vm_area(vm_struct, - pgprot_writecombine(PAGE_KERNEL), - &pages); - memset(vm_struct->addr, 0, PAGE_SIZE); - unmap_kernel_range((unsigned long)vm_struct->addr, - PAGE_SIZE); - } ion_page_pool_free(pool, page); } else if (split_pages) { for (i = 0; i < (1 << order); i++) @@ -167,8 +153,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; bool split_pages = ion_buffer_fault_user_mappings(buffer); - struct vm_struct *vm_struct; - pte_t *ptes; INIT_LIST_HEAD(&pages); while (size_remaining > 0) { @@ -216,13 +200,10 @@ static int ion_system_heap_allocate(struct ion_heap *heap, err1: kfree(table); err: - vm_struct = get_vm_area(PAGE_SIZE, &ptes); list_for_each_entry(info, &pages, list) { - free_buffer_page(sys_heap, buffer, info->page, info->order, - vm_struct); + free_buffer_page(sys_heap, buffer, info->page, info->order); kfree(info); } - free_vm_area(vm_struct); return -ENOMEM; } @@ -233,18 +214,19 @@ void ion_system_heap_free(struct ion_buffer *buffer) struct ion_system_heap, heap); struct sg_table *table = buffer->sg_table; + bool cached = ion_buffer_cached(buffer); struct scatterlist *sg; LIST_HEAD(pages); - struct vm_struct *vm_struct; - pte_t *ptes; int i; - vm_struct = get_vm_area(PAGE_SIZE, &ptes); + /* uncached pages come from the page pools, zero them before returning + for security purposes (other allocations are zerod at alloc time */ + if (!cached) + ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) free_buffer_page(sys_heap, buffer, sg_page(sg), - get_order(sg_dma_len(sg)), vm_struct); - free_vm_area(vm_struct); + get_order(sg_dma_len(sg))); sg_free_table(table); kfree(table); } -- cgit v1.2.3 From 88d4bda8807d846cc31e13ee58a28c7c0d3afbd0 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:33 -0800 Subject: gpu: ion: Only flush buffers in the chunk heap if they were used cached Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 558290989fe6..60cd91ca2071 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -104,8 +104,9 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) { - __dma_page_cpu_to_dev(sg_page(sg), 0, sg_dma_len(sg), - DMA_BIDIRECTIONAL); + if (ion_buffer_cached(buffer)) + __dma_page_cpu_to_dev(sg_page(sg), 0, sg_dma_len(sg), + DMA_BIDIRECTIONAL); gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), sg_dma_len(sg)); } -- cgit v1.2.3 From 22ba43220b594983c18394442e58ed4988893de6 Mon Sep 17 00:00:00 2001 From: Johan Mossberg Date: Fri, 13 Dec 2013 14:24:34 -0800 Subject: gpu: ion: Add support for sharing buffers with dma buf kernel handles Currently ion can only share buffers with dma buf fd's. Fd's can not be used inside the kernel as they are process specific so support for sharing buffers with dma buf kernel handles is needed to support kernel only use cases. An example use case could be a GPU driver using ion that wants to share its output buffers with a 3d party display controller driver supporting dma buf. Signed-off-by: Johan Mossberg [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 26 ++++++++++++++++++++------ drivers/staging/android/ion/ion.h | 12 ++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 054e672f1794..ba65bef05b6c 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -949,19 +949,19 @@ struct dma_buf_ops dma_buf_ops = { .kunmap = ion_dma_buf_kunmap, }; -int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) +struct dma_buf *ion_share_dma_buf(struct ion_client *client, + struct ion_handle *handle) { struct ion_buffer *buffer; struct dma_buf *dmabuf; bool valid_handle; - int fd; mutex_lock(&client->lock); valid_handle = ion_handle_validate(client, handle); mutex_unlock(&client->lock); if (!valid_handle) { WARN(1, "%s: invalid handle passed to share.\n", __func__); - return -EINVAL; + return ERR_PTR(-EINVAL); } buffer = handle->buffer; @@ -969,15 +969,29 @@ int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR); if (IS_ERR(dmabuf)) { ion_buffer_put(buffer); - return PTR_ERR(dmabuf); + return dmabuf; } + + return dmabuf; +} +EXPORT_SYMBOL(ion_share_dma_buf); + +int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) +{ + struct dma_buf *dmabuf; + int fd; + + dmabuf = ion_share_dma_buf(client, handle); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + fd = dma_buf_fd(dmabuf, O_CLOEXEC); if (fd < 0) dma_buf_put(dmabuf); return fd; } -EXPORT_SYMBOL(ion_share_dma_buf); +EXPORT_SYMBOL(ion_share_dma_buf_fd); struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) { @@ -1086,7 +1100,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - data.fd = ion_share_dma_buf(client, data.handle); + data.fd = ion_share_dma_buf_fd(client, data.handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; if (data.fd < 0) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 0f67014f2403..976123b189ae 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -212,11 +212,19 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle); void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); /** - * ion_share_dma_buf() - given an ion client, create a dma-buf fd + * ion_share_dma_buf() - share buffer as dma-buf * @client: the client * @handle: the handle */ -int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle); +struct dma_buf *ion_share_dma_buf(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_share_dma_buf_fd() - given an ion client, create a dma-buf fd + * @client: the client + * @handle: the handle + */ +int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); /** * ion_import_dma_buf() - given an dma-buf fd from the ion exporter get handle -- cgit v1.2.3 From fe2faea7003516dd615812f663b6a9b141b842ce Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:35 -0800 Subject: gpu: ion: Make ion_free asynchronous Add the ability for a heap to free buffers asynchrounously. Freed buffers are placed on a free list and freed from a low priority background thread. If allocations from a particular heap fail, the free list is drained. This patch also enable asynchronous frees from the chunk heap. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 112 +++++++++++++++++++++++--- drivers/staging/android/ion/ion.h | 2 +- drivers/staging/android/ion/ion_chunk_heap.c | 3 +- drivers/staging/android/ion/ion_priv.h | 20 ++++- drivers/staging/android/ion/ion_system_heap.c | 1 + 5 files changed, 126 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ba65bef05b6c..b965f1559536 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -26,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -140,6 +143,7 @@ static void ion_buffer_add(struct ion_device *dev, static int ion_buffer_alloc_dirty(struct ion_buffer *buffer); +static bool ion_heap_drain_freelist(struct ion_heap *heap); /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -161,9 +165,16 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, kref_init(&buffer->ref); ret = heap->ops->allocate(heap, buffer, len, align, flags); + if (ret) { - kfree(buffer); - return ERR_PTR(ret); + if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE)) + goto err2; + + ion_heap_drain_freelist(heap); + ret = heap->ops->allocate(heap, buffer, len, align, + flags); + if (ret) + goto err2; } buffer->dev = dev; @@ -214,27 +225,42 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, err: heap->ops->unmap_dma(heap, buffer); heap->ops->free(buffer); +err2: kfree(buffer); return ERR_PTR(ret); } -static void ion_buffer_destroy(struct kref *kref) +static void _ion_buffer_destroy(struct ion_buffer *buffer) { - struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); - struct ion_device *dev = buffer->dev; - if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); - mutex_lock(&dev->buffer_lock); - rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->buffer_lock); if (buffer->flags & ION_FLAG_CACHED) kfree(buffer->dirty); kfree(buffer); } +static void ion_buffer_destroy(struct kref *kref) +{ + struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); + struct ion_heap *heap = buffer->heap; + struct ion_device *dev = buffer->dev; + + mutex_lock(&dev->buffer_lock); + rb_erase(&buffer->node, &dev->buffers); + mutex_unlock(&dev->buffer_lock); + + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) { + rt_mutex_lock(&heap->lock); + list_add(&buffer->list, &heap->free_list); + rt_mutex_unlock(&heap->lock); + wake_up(&heap->waitqueue); + return; + } + _ion_buffer_destroy(buffer); +} + static void ion_buffer_get(struct ion_buffer *buffer) { kref_get(&buffer->ref); @@ -1272,13 +1298,81 @@ static const struct file_operations debug_heap_fops = { .release = single_release, }; +static size_t ion_heap_free_list_is_empty(struct ion_heap *heap) +{ + bool is_empty; + + rt_mutex_lock(&heap->lock); + is_empty = list_empty(&heap->free_list); + rt_mutex_unlock(&heap->lock); + + return is_empty; +} + +static int ion_heap_deferred_free(void *data) +{ + struct ion_heap *heap = data; + + while (true) { + struct ion_buffer *buffer; + + wait_event_freezable(heap->waitqueue, + !ion_heap_free_list_is_empty(heap)); + + rt_mutex_lock(&heap->lock); + if (list_empty(&heap->free_list)) { + rt_mutex_unlock(&heap->lock); + continue; + } + buffer = list_first_entry(&heap->free_list, struct ion_buffer, + list); + list_del(&buffer->list); + rt_mutex_unlock(&heap->lock); + _ion_buffer_destroy(buffer); + } + + return 0; +} + +static bool ion_heap_drain_freelist(struct ion_heap *heap) +{ + struct ion_buffer *buffer, *tmp; + + if (ion_heap_free_list_is_empty(heap)) + return false; + rt_mutex_lock(&heap->lock); + list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) { + _ion_buffer_destroy(buffer); + list_del(&buffer->list); + } + BUG_ON(!list_empty(&heap->free_list)); + rt_mutex_unlock(&heap->lock); + + + return true; +} + void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { + struct sched_param param = { .sched_priority = 0 }; + if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || !heap->ops->unmap_dma) pr_err("%s: can not add heap with invalid ops struct.\n", __func__); + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) { + INIT_LIST_HEAD(&heap->free_list); + rt_mutex_init(&heap->lock); + init_waitqueue_head(&heap->waitqueue); + heap->task = kthread_run(ion_heap_deferred_free, heap, + "%s", heap->name); + sched_setscheduler(heap->task, SCHED_IDLE, ¶m); + if (IS_ERR(heap->task)) + pr_err("%s: creating thread for deferred free failed\n", + __func__); + } + heap->dev = dev; down_write(&dev->lock); /* use negative heap->id to reverse the priority -- when traversing diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 976123b189ae..679031ceee91 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -46,7 +46,7 @@ enum ion_heap_type { #define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8 /** - * heap flags - the lower 16 bits are used by core ion, the upper 16 + * allocation flags - the lower 16 bits are used by core ion, the upper 16 * bits are reserved for use by the heaps themselves. */ #define ION_FLAG_CACHED 1 /* mappings of this buffer should be diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 60cd91ca2071..ac7cf132985b 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -160,7 +160,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; - pr_info("%s: base %lu size %ld align %ld\n", __func__, chunk_heap->base, + chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; + pr_info("%s: base %lu size %u align %ld\n", __func__, chunk_heap->base, heap_data->size, heap_data->align); return &chunk_heap->heap; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index cfb4264fe499..ab1a8d956ada 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -58,7 +58,10 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); */ struct ion_buffer { struct kref ref; - struct rb_node node; + union { + struct rb_node node; + struct list_head list; + }; struct ion_device *dev; struct ion_heap *heap; unsigned long flags; @@ -108,16 +111,26 @@ struct ion_heap_ops { struct vm_area_struct *vma); }; +/** + * heap flags - flags between the heaps and core ion code + */ +#define ION_HEAP_FLAG_DEFER_FREE (1 << 0) + /** * struct ion_heap - represents a heap in the system * @node: rb node to put the heap on the device's tree of heaps * @dev: back pointer to the ion_device * @type: type of heap * @ops: ops struct as above + * @flags: flags * @id: id of heap, also indicates priority of this heap when * allocating. These are specified by platform data and * MUST be unique * @name: used for debugging + * @free_list: free list head if deferred free is used + * @lock: protects the free list + * @waitqueue: queue to wait on from deferred free thread + * @task: task struct of deferred free thread * @debug_show: called when heap debug file is read to add any * heap specific debug info to output * @@ -131,8 +144,13 @@ struct ion_heap { struct ion_device *dev; enum ion_heap_type type; struct ion_heap_ops *ops; + unsigned long flags; unsigned int id; const char *name; + struct list_head free_list; + struct rt_mutex lock; + wait_queue_head_t waitqueue; + struct task_struct *task; int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); }; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 3ca704e3ee14..6665797f5370 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -283,6 +283,7 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) return ERR_PTR(-ENOMEM); heap->heap.ops = &system_heap_ops; heap->heap.type = ION_HEAP_TYPE_SYSTEM; + heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; heap->pools = kzalloc(sizeof(struct ion_page_pool *) * num_orders, GFP_KERNEL); if (!heap->pools) -- cgit v1.2.3 From e09539a04285b616ebcc50f2f6b75ad7fbb0aec5 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 13 Dec 2013 14:24:36 -0800 Subject: gpu: ion: fix kfree/list_del order With CONFIG_SLUB_DEBUG_ON it would panic during ion_alloc() ion_buffer_create() io_heap_drain_freelist() Signed-off-by: JP Abgrall [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index b965f1559536..b2dcee5ceae5 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1342,8 +1342,8 @@ static bool ion_heap_drain_freelist(struct ion_heap *heap) return false; rt_mutex_lock(&heap->lock); list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) { - _ion_buffer_destroy(buffer); list_del(&buffer->list); + _ion_buffer_destroy(buffer); } BUG_ON(!list_empty(&heap->free_list)); rt_mutex_unlock(&heap->lock); -- cgit v1.2.3 From 57b5cd067fc713433e75688348832e2e2f82b843 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:37 -0800 Subject: gpu: ion: ion_chunk_heap: Zero chunk heap memory at creation time Allocations from the ion heap need to be zeroed to protect userspace from seeing memory belonging to other processes. First allocations from this heap were not zero'd allowing users to see memory from other processes on a warm reset. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 34 ++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index ac7cf132985b..4c2f22322ea1 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -140,6 +140,10 @@ static struct ion_heap_ops chunk_heap_ops = { struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) { struct ion_chunk_heap *chunk_heap; + struct vm_struct *vm_struct; + pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); + int i, ret; + chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL); if (!chunk_heap) @@ -149,12 +153,30 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->pool = gen_pool_create(get_order(chunk_heap->chunk_size) + PAGE_SHIFT, -1); if (!chunk_heap->pool) { - kfree(chunk_heap); - return ERR_PTR(-ENOMEM); + ret = -ENOMEM; + goto error_gen_pool_create; } chunk_heap->base = heap_data->base; chunk_heap->size = heap_data->size; chunk_heap->allocated = 0; + + vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC); + if (!vm_struct) { + ret = -ENOMEM; + goto error; + } + for (i = 0; i < chunk_heap->size; i += PAGE_SIZE) { + struct page *page = phys_to_page(chunk_heap->base + i); + struct page **pages = &page; + + ret = map_vm_area(vm_struct, pgprot, &pages); + if (ret) + goto error_map_vm_area; + memset(vm_struct->addr, 0, PAGE_SIZE); + unmap_kernel_range((unsigned long)vm_struct->addr, PAGE_SIZE); + } + free_vm_area(vm_struct); + __dma_page_cpu_to_dev(phys_to_page(heap_data->base), 0, heap_data->size, DMA_BIDIRECTIONAL); gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); @@ -165,6 +187,14 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) heap_data->size, heap_data->align); return &chunk_heap->heap; + +error_map_vm_area: + free_vm_area(vm_struct); +error: + gen_pool_destroy(chunk_heap->pool); +error_gen_pool_create: + kfree(chunk_heap); + return ERR_PTR(ret); } void ion_chunk_heap_destroy(struct ion_heap *heap) -- cgit v1.2.3 From da4aab37836b8e45e31c7d557c6d6a2c623d8eea Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:38 -0800 Subject: gpu: ion: Fix bug in ion shrinker The high variable was sometimes used uninitialized Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index e59da3a5ed9f..df6e29c1854e 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -203,8 +203,7 @@ static int ion_page_pool_shrink(struct shrinker *shrinker, bool high; int nr_to_scan = sc->nr_to_scan; - if (sc->gfp_mask & __GFP_HIGHMEM) - high = true; + high = sc->gfp_mask & __GFP_HIGHMEM; if (nr_to_scan == 0) return ion_page_pool_total(high); -- cgit v1.2.3 From ea313b5f88ed7119f79ad3f6b85e9620971b9875 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:39 -0800 Subject: gpu: ion: Also shrink memory cached in the deferred free list When the system is low on memory, we want to shrink any cached system memory ion is holding. Previously we were shrinking memory in the page pools, but not in the deferred free list. This patch makes it possible to shrink both. It also moves the shrinker code into the heaps so they can correctly manage any caches they might contain. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 115 +++++++++-------------- drivers/staging/android/ion/ion_heap.c | 107 ++++++++++++++++++++++ drivers/staging/android/ion/ion_page_pool.c | 126 +++++--------------------- drivers/staging/android/ion/ion_priv.h | 57 +++++++++++- drivers/staging/android/ion/ion_system_heap.c | 49 ++++++++++ 5 files changed, 278 insertions(+), 176 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index b2dcee5ceae5..ddf8fde9ae93 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include #include #include @@ -143,7 +141,6 @@ static void ion_buffer_add(struct ion_device *dev, static int ion_buffer_alloc_dirty(struct ion_buffer *buffer); -static bool ion_heap_drain_freelist(struct ion_heap *heap); /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -170,7 +167,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE)) goto err2; - ion_heap_drain_freelist(heap); + ion_heap_freelist_drain(heap, 0); ret = heap->ops->allocate(heap, buffer, len, align, flags); if (ret) @@ -230,7 +227,7 @@ err2: return ERR_PTR(ret); } -static void _ion_buffer_destroy(struct ion_buffer *buffer) +void ion_buffer_destroy(struct ion_buffer *buffer) { if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); @@ -241,7 +238,7 @@ static void _ion_buffer_destroy(struct ion_buffer *buffer) kfree(buffer); } -static void ion_buffer_destroy(struct kref *kref) +static void _ion_buffer_destroy(struct kref *kref) { struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref); struct ion_heap *heap = buffer->heap; @@ -251,14 +248,10 @@ static void ion_buffer_destroy(struct kref *kref) rb_erase(&buffer->node, &dev->buffers); mutex_unlock(&dev->buffer_lock); - if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) { - rt_mutex_lock(&heap->lock); - list_add(&buffer->list, &heap->free_list); - rt_mutex_unlock(&heap->lock); - wake_up(&heap->waitqueue); - return; - } - _ion_buffer_destroy(buffer); + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) + ion_heap_freelist_add(heap, buffer); + else + ion_buffer_destroy(buffer); } static void ion_buffer_get(struct ion_buffer *buffer) @@ -268,7 +261,7 @@ static void ion_buffer_get(struct ion_buffer *buffer) static int ion_buffer_put(struct ion_buffer *buffer) { - return kref_put(&buffer->ref, ion_buffer_destroy); + return kref_put(&buffer->ref, _ion_buffer_destroy); } static void ion_buffer_add_to_handle(struct ion_buffer *buffer) @@ -1298,80 +1291,53 @@ static const struct file_operations debug_heap_fops = { .release = single_release, }; -static size_t ion_heap_free_list_is_empty(struct ion_heap *heap) +#ifdef DEBUG_HEAP_SHRINKER +static int debug_shrink_set(void *data, u64 val) { - bool is_empty; + struct ion_heap *heap = data; + struct shrink_control sc; + int objs; - rt_mutex_lock(&heap->lock); - is_empty = list_empty(&heap->free_list); - rt_mutex_unlock(&heap->lock); + sc.gfp_mask = -1; + sc.nr_to_scan = 0; - return is_empty; -} - -static int ion_heap_deferred_free(void *data) -{ - struct ion_heap *heap = data; + if (!val) + return 0; - while (true) { - struct ion_buffer *buffer; + objs = heap->shrinker.shrink(&heap->shrinker, &sc); + sc.nr_to_scan = objs; - wait_event_freezable(heap->waitqueue, - !ion_heap_free_list_is_empty(heap)); - - rt_mutex_lock(&heap->lock); - if (list_empty(&heap->free_list)) { - rt_mutex_unlock(&heap->lock); - continue; - } - buffer = list_first_entry(&heap->free_list, struct ion_buffer, - list); - list_del(&buffer->list); - rt_mutex_unlock(&heap->lock); - _ion_buffer_destroy(buffer); - } - - return 0; + heap->shrinker.shrink(&heap->shrinker, &sc); + return 0; } -static bool ion_heap_drain_freelist(struct ion_heap *heap) +static int debug_shrink_get(void *data, u64 *val) { - struct ion_buffer *buffer, *tmp; - - if (ion_heap_free_list_is_empty(heap)) - return false; - rt_mutex_lock(&heap->lock); - list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) { - list_del(&buffer->list); - _ion_buffer_destroy(buffer); - } - BUG_ON(!list_empty(&heap->free_list)); - rt_mutex_unlock(&heap->lock); + struct ion_heap *heap = data; + struct shrink_control sc; + int objs; + sc.gfp_mask = -1; + sc.nr_to_scan = 0; - return true; + objs = heap->shrinker.shrink(&heap->shrinker, &sc); + *val = objs; + return 0; } +DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, + debug_shrink_set, "%llu\n"); +#endif + void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { - struct sched_param param = { .sched_priority = 0 }; - if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || !heap->ops->unmap_dma) pr_err("%s: can not add heap with invalid ops struct.\n", __func__); - if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) { - INIT_LIST_HEAD(&heap->free_list); - rt_mutex_init(&heap->lock); - init_waitqueue_head(&heap->waitqueue); - heap->task = kthread_run(ion_heap_deferred_free, heap, - "%s", heap->name); - sched_setscheduler(heap->task, SCHED_IDLE, ¶m); - if (IS_ERR(heap->task)) - pr_err("%s: creating thread for deferred free failed\n", - __func__); - } + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) + ion_heap_init_deferred_free(heap); heap->dev = dev; down_write(&dev->lock); @@ -1381,6 +1347,15 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) plist_add(&heap->node, &dev->heaps); debugfs_create_file(heap->name, 0664, dev->debug_root, heap, &debug_heap_fops); +#ifdef DEBUG_HEAP_SHRINKER + if (heap->shrinker.shrink) { + char debug_name[64]; + + snprintf(debug_name, 64, "%s_shrink", heap->name); + debugfs_create_file(debug_name, 0644, dev->debug_root, heap, + &debug_shrink_fops); + } +#endif up_write(&dev->lock); } diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 11066a2abb4b..f541bff26435 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -15,7 +15,11 @@ */ #include +#include +#include #include +#include +#include #include #include #include "ion.h" @@ -130,6 +134,109 @@ end: return ret; } +void ion_heap_free_page(struct ion_buffer *buffer, struct page *page, + unsigned int order) +{ + int i; + + if (!ion_buffer_fault_user_mappings(buffer)) { + __free_pages(page, order); + return; + } + for (i = 0; i < (1 << order); i++) + __free_page(page + i); +} + +void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) +{ + rt_mutex_lock(&heap->lock); + list_add(&buffer->list, &heap->free_list); + heap->free_list_size += buffer->size; + rt_mutex_unlock(&heap->lock); + wake_up(&heap->waitqueue); +} + +size_t ion_heap_freelist_size(struct ion_heap *heap) +{ + size_t size; + + rt_mutex_lock(&heap->lock); + size = heap->free_list_size; + rt_mutex_unlock(&heap->lock); + + return size; +} + +size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) +{ + struct ion_buffer *buffer, *tmp; + size_t total_drained = 0; + + if (ion_heap_freelist_size(heap) == 0) + return 0; + + rt_mutex_lock(&heap->lock); + if (size == 0) + size = heap->free_list_size; + + list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) { + if (total_drained >= size) + break; + list_del(&buffer->list); + ion_buffer_destroy(buffer); + heap->free_list_size -= buffer->size; + total_drained += buffer->size; + } + rt_mutex_unlock(&heap->lock); + + return total_drained; +} + +int ion_heap_deferred_free(void *data) +{ + struct ion_heap *heap = data; + + while (true) { + struct ion_buffer *buffer; + + wait_event_freezable(heap->waitqueue, + ion_heap_freelist_size(heap) > 0); + + rt_mutex_lock(&heap->lock); + if (list_empty(&heap->free_list)) { + rt_mutex_unlock(&heap->lock); + continue; + } + buffer = list_first_entry(&heap->free_list, struct ion_buffer, + list); + list_del(&buffer->list); + heap->free_list_size -= buffer->size; + rt_mutex_unlock(&heap->lock); + ion_buffer_destroy(buffer); + } + + return 0; +} + +int ion_heap_init_deferred_free(struct ion_heap *heap) +{ + struct sched_param param = { .sched_priority = 0 }; + + INIT_LIST_HEAD(&heap->free_list); + heap->free_list_size = 0; + rt_mutex_init(&heap->lock); + init_waitqueue_head(&heap->waitqueue); + heap->task = kthread_run(ion_heap_deferred_free, heap, + "%s", heap->name); + sched_setscheduler(heap->task, SCHED_IDLE, ¶m); + if (IS_ERR(heap->task)) { + pr_err("%s: creating thread for deferred free failed\n", + __func__); + return PTR_RET(heap->task); + } + return 0; +} + struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) { struct ion_heap *heap = NULL; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index df6e29c1854e..d624dee170ba 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -21,14 +21,8 @@ #include #include #include -#include #include "ion_priv.h" -/* #define DEBUG_PAGE_POOL_SHRINKER */ - -static struct plist_head pools = PLIST_HEAD_INIT(pools); -static struct shrinker shrinker; - struct ion_page_pool_item { struct page *page; struct list_head list; @@ -126,109 +120,46 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) ion_page_pool_free_pages(pool, page); } -#ifdef DEBUG_PAGE_POOL_SHRINKER -static int debug_drop_pools_set(void *data, u64 val) -{ - struct shrink_control sc; - int objs; - - sc.gfp_mask = -1; - sc.nr_to_scan = 0; - - if (!val) - return 0; - - objs = shrinker.shrink(&shrinker, &sc); - sc.nr_to_scan = objs; - - shrinker.shrink(&shrinker, &sc); - return 0; -} - -static int debug_drop_pools_get(void *data, u64 *val) +static int ion_page_pool_total(struct ion_page_pool *pool, bool high) { - struct shrink_control sc; - int objs; - - sc.gfp_mask = -1; - sc.nr_to_scan = 0; - - objs = shrinker.shrink(&shrinker, &sc); - *val = objs; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_drop_pools_fops, debug_drop_pools_get, - debug_drop_pools_set, "%llu\n"); - -static int debug_grow_pools_set(void *data, u64 val) -{ - struct ion_page_pool *pool; - struct page *page; - - plist_for_each_entry(pool, &pools, list) { - if (val != pool->list.prio) - continue; - page = ion_page_pool_alloc_pages(pool); - if (page) - ion_page_pool_add(pool, page); - } - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_grow_pools_fops, debug_drop_pools_get, - debug_grow_pools_set, "%llu\n"); -#endif - -static int ion_page_pool_total(bool high) -{ - struct ion_page_pool *pool; int total = 0; - plist_for_each_entry(pool, &pools, list) { - total += high ? (pool->high_count + pool->low_count) * - (1 << pool->order) : + total += high ? (pool->high_count + pool->low_count) * + (1 << pool->order) : pool->low_count * (1 << pool->order); - } return total; } -static int ion_page_pool_shrink(struct shrinker *shrinker, - struct shrink_control *sc) +int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, + int nr_to_scan) { - struct ion_page_pool *pool; int nr_freed = 0; int i; bool high; - int nr_to_scan = sc->nr_to_scan; - high = sc->gfp_mask & __GFP_HIGHMEM; + high = gfp_mask & __GFP_HIGHMEM; if (nr_to_scan == 0) - return ion_page_pool_total(high); - - plist_for_each_entry(pool, &pools, list) { - for (i = 0; i < nr_to_scan; i++) { - struct page *page; - - mutex_lock(&pool->mutex); - if (high && pool->high_count) { - page = ion_page_pool_remove(pool, true); - } else if (pool->low_count) { - page = ion_page_pool_remove(pool, false); - } else { - mutex_unlock(&pool->mutex); - break; - } + return ion_page_pool_total(pool, high); + + for (i = 0; i < nr_to_scan; i++) { + struct page *page; + + mutex_lock(&pool->mutex); + if (high && pool->high_count) { + page = ion_page_pool_remove(pool, true); + } else if (pool->low_count) { + page = ion_page_pool_remove(pool, false); + } else { mutex_unlock(&pool->mutex); - ion_page_pool_free_pages(pool, page); - nr_freed += (1 << pool->order); + break; } - nr_to_scan -= i; + mutex_unlock(&pool->mutex); + ion_page_pool_free_pages(pool, page); + nr_freed += (1 << pool->order); } - return ion_page_pool_total(high); + return nr_freed; } struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) @@ -245,35 +176,22 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) pool->order = order; mutex_init(&pool->mutex); plist_node_init(&pool->list, order); - plist_add(&pool->list, &pools); return pool; } void ion_page_pool_destroy(struct ion_page_pool *pool) { - plist_del(&pool->list, &pools); kfree(pool); } static int __init ion_page_pool_init(void) { - shrinker.shrink = ion_page_pool_shrink; - shrinker.seeks = DEFAULT_SEEKS; - shrinker.batch = 0; - register_shrinker(&shrinker); -#ifdef DEBUG_PAGE_POOL_SHRINKER - debugfs_create_file("ion_pools_shrink", 0644, NULL, NULL, - &debug_drop_pools_fops); - debugfs_create_file("ion_pools_grow", 0644, NULL, NULL, - &debug_grow_pools_fops); -#endif return 0; } static void __exit ion_page_pool_exit(void) { - unregister_shrinker(&shrinker); } module_init(ion_page_pool_init); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index ab1a8d956ada..bdc1e344d731 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -82,6 +82,7 @@ struct ion_buffer { char task_comm[TASK_COMM_LEN]; pid_t pid; }; +void ion_buffer_destroy(struct ion_buffer *buffer); /** * struct ion_heap_ops - ops to operate on a given heap @@ -127,7 +128,12 @@ struct ion_heap_ops { * allocating. These are specified by platform data and * MUST be unique * @name: used for debugging + * @shrinker: a shrinker for the heap, if the heap caches system + * memory, it must define a shrinker to return it on low + * memory conditions, this includes system memory cached + * in the deferred free lists for heaps that support it * @free_list: free list head if deferred free is used + * @free_list_size size of the deferred free list in bytes * @lock: protects the free list * @waitqueue: queue to wait on from deferred free thread * @task: task struct of deferred free thread @@ -147,7 +153,9 @@ struct ion_heap { unsigned long flags; unsigned int id; const char *name; + struct shrinker shrinker; struct list_head free_list; + size_t free_list_size; struct rt_mutex lock; wait_queue_head_t waitqueue; struct task_struct *task; @@ -205,6 +213,43 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); int ion_heap_buffer_zero(struct ion_buffer *buffer); +/** + * ion_heap_init_deferred_free -- initialize deferred free functionality + * @heap: the heap + * + * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will + * be called to setup deferred frees. Calls to free the buffer will + * return immediately and the actual free will occur some time later + */ +int ion_heap_init_deferred_free(struct ion_heap *heap); + +/** + * ion_heap_freelist_add - add a buffer to the deferred free list + * @heap: the heap + * @buffer: the buffer + * + * Adds an item to the deferred freelist. + */ +void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); + +/** + * ion_heap_freelist_drain - drain the deferred free list + * @heap: the heap + * @size: ammount of memory to drain in bytes + * + * Drains the indicated amount of memory from the deferred freelist immediately. + * Returns the total amount freed. The total freed may be higher depending + * on the size of the items in the list, or lower if there is insufficient + * total memory on the freelist. + */ +size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); + +/** + * ion_heap_freelist_size - returns the size of the freelist in bytes + * @heap: the heap + */ +size_t ion_heap_freelist_size(struct ion_heap *heap); + /** * functions for creating and destroying the built in ion heaps. @@ -274,8 +319,6 @@ struct ion_page_pool { struct list_head high_items; struct list_head low_items; struct mutex mutex; - void *(*alloc)(struct ion_page_pool *pool); - void (*free)(struct ion_page_pool *pool, struct page *page); gfp_t gfp_mask; unsigned int order; struct plist_node list; @@ -286,4 +329,14 @@ void ion_page_pool_destroy(struct ion_page_pool *); void *ion_page_pool_alloc(struct ion_page_pool *); void ion_page_pool_free(struct ion_page_pool *, struct page *); +/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool + * @pool: the pool + * @gfp_mask: the memory type to reclaim + * @nr_to_scan: number of items to shrink in pages + * + * returns the number of items freed in pages + */ +int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, + int nr_to_scan); + #endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 6665797f5370..fedbc0d5fa7d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -253,6 +253,50 @@ static struct ion_heap_ops system_heap_ops = { .map_user = ion_heap_map_user, }; +static int ion_system_heap_shrink(struct shrinker *shrinker, + struct shrink_control *sc) { + + struct ion_heap *heap = container_of(shrinker, struct ion_heap, + shrinker); + struct ion_system_heap *sys_heap = container_of(heap, + struct ion_system_heap, + heap); + int nr_total = 0; + int nr_freed = 0; + int i; + + if (sc->nr_to_scan == 0) + goto end; + + /* shrink the free list first, no point in zeroing the memory if + we're just going to reclaim it */ + nr_freed += ion_heap_freelist_drain(heap, sc->nr_to_scan * PAGE_SIZE) / + PAGE_SIZE; + + if (nr_freed >= sc->nr_to_scan) + goto end; + + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool = sys_heap->pools[i]; + + nr_freed += ion_page_pool_shrink(pool, sc->gfp_mask, + sc->nr_to_scan); + if (nr_freed >= sc->nr_to_scan) + break; + } + +end: + /* total number of items is whatever the page pools are holding + plus whatever's in the freelist */ + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool = sys_heap->pools[i]; + nr_total += ion_page_pool_shrink(pool, sc->gfp_mask, 0); + } + nr_total += ion_heap_freelist_size(heap) / PAGE_SIZE; + return nr_total; + +} + static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, void *unused) { @@ -299,6 +343,11 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) goto err_create_pool; heap->pools[i] = pool; } + + heap->heap.shrinker.shrink = ion_system_heap_shrink; + heap->heap.shrinker.seeks = DEFAULT_SEEKS; + heap->heap.shrinker.batch = 0; + register_shrinker(&heap->heap.shrinker); heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; err_create_pool: -- cgit v1.2.3 From def5c4926b3f691dfbcef39a94f206c0f0f3a92f Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Fri, 13 Dec 2013 14:24:40 -0800 Subject: gpu: ion: __dma_page_cpu_to_dev -> arm_dma_ops.sync_single_for_device hack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Arve Hjønnevåg [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 10 ++++++---- drivers/staging/android/ion/ion_page_pool.c | 6 ++++-- drivers/staging/android/ion/ion_system_heap.c | 5 +++-- 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 4c2f22322ea1..410c08e4028f 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -105,8 +105,9 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) for_each_sg(table->sgl, sg, table->nents, i) { if (ion_buffer_cached(buffer)) - __dma_page_cpu_to_dev(sg_page(sg), 0, sg_dma_len(sg), - DMA_BIDIRECTIONAL); + arm_dma_ops.sync_single_for_device(NULL, + pfn_to_dma(NULL, page_to_pfn(sg_page(sg))), + sg_dma_len(sg), DMA_BIDIRECTIONAL); gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), sg_dma_len(sg)); } @@ -177,8 +178,9 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) } free_vm_area(vm_struct); - __dma_page_cpu_to_dev(phys_to_page(heap_data->base), 0, heap_data->size, - DMA_BIDIRECTIONAL); + arm_dma_ops.sync_single_for_device(NULL, + pfn_to_dma(NULL, page_to_pfn(phys_to_page(heap_data->base))), + heap_data->size, DMA_BIDIRECTIONAL); gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index d624dee170ba..855f30c3967a 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -37,8 +37,10 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) /* this is only being used to flush the page for dma, this api is not really suitable for calling from a driver but no better way to flush a page for dma exist at this time */ - __dma_page_cpu_to_dev(page, 0, PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); + arm_dma_ops.sync_single_for_device(NULL, + pfn_to_dma(NULL, page_to_pfn(page)), + PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); return page; } diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index fedbc0d5fa7d..d4f0a564c459 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -78,8 +78,9 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, page = alloc_pages(gfp_flags, order); if (!page) return 0; - __dma_page_cpu_to_dev(page, 0, PAGE_SIZE << order, - DMA_BIDIRECTIONAL); + arm_dma_ops.sync_single_for_device(NULL, + pfn_to_dma(NULL, page_to_pfn(page)), + PAGE_SIZE << order, DMA_BIDIRECTIONAL); } if (!page) return 0; -- cgit v1.2.3 From 1584f40ff0b8f2d1b42a4353f3a27b0c1f8545a5 Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Fri, 13 Dec 2013 14:24:41 -0800 Subject: gpu: ion: Remove __GFP_NO_KSWAPD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It no longer exists. Signed-off-by: Arve Hjønnevåg [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index d4f0a564c459..344f7538400a 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -27,8 +27,8 @@ #include "ion_priv.h" static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY | - __GFP_NO_KSWAPD) & ~__GFP_WAIT; + __GFP_NOWARN | __GFP_NORETRY) & + ~__GFP_WAIT; static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; -- cgit v1.2.3 From d1cf3e98d9777877df7aefe402ed99b68620e354 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Dec 2013 14:24:42 -0800 Subject: ion: Add Kconfig dependency to ARM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ion code has some very specific arm-isms which keeps it from building on other architectures. These should probably be resolved, but in the mean time, add a dependency on CONFIG_ARM to avoid build failures. v2: Fix earlier flub, sending out an early untested version of the patch. Cc: Arve Hjønnevåg Cc: Rebecca Schultz Zavin Cc: Android Kernel Team [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index b5bfdb47fd09..c62f2cbb9e89 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,6 @@ menuconfig ION tristate "Ion Memory Manager" + depends on ARM select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER help -- cgit v1.2.3 From 19007b1420ba6f780621aa2e710c44881e8be983 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 13 Dec 2013 14:24:43 -0800 Subject: gpu: ion: fix ion_platform_data definition fix ion_platform_heap to make is use an usual way in board configuration file. Signed-off-by: Benjamin Gaignard [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 679031ceee91..226bfd56be56 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -103,7 +103,7 @@ struct ion_platform_heap { */ struct ion_platform_data { int nr; - struct ion_platform_heap heaps[]; + struct ion_platform_heap *heaps; }; /** -- cgit v1.2.3 From 349c9e13855109df99c5205a4e8d53d9fa169490 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 13 Dec 2013 14:24:44 -0800 Subject: gpu: ion: add CMA heap New heap type ION_HEAP_TYPE_DMA where allocation is done with dma_alloc_coherent API. device coherent_dma_mask must be set to DMA_BIT_MASK(32). ion_platform_heap private field is used to retrieve the device linked to CMA, if NULL the default CMA area is used. ion_cma_get_sgtable is a copy of dma_common_get_sgtable function which should be in kernel 3.5 Signed-off-by: Benjamin Gaignard [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Makefile | 2 +- drivers/staging/android/ion/ion.h | 7 +- drivers/staging/android/ion/ion_cma_heap.c | 233 +++++++++++++++++++++++++++++ drivers/staging/android/ion/ion_heap.c | 6 + drivers/staging/android/ion/ion_priv.h | 3 + 5 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 drivers/staging/android/ion/ion_cma_heap.c (limited to 'drivers') diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 306fff970de4..ce0f1ef1c233 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ - ion_carveout_heap.o ion_chunk_heap.o + ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 226bfd56be56..3942b3ecb992 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -27,13 +27,17 @@ struct ion_handle; * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved * carveout heap, allocations are physically * contiguous - * @ION_HEAP_END: helper for iterating over heaps + * @ION_HEAP_TYPE_DMA: memory allocated via DMA API + * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask + * is used to identify the heaps, so only 32 + * total heap types are supported */ enum ion_heap_type { ION_HEAP_TYPE_SYSTEM, ION_HEAP_TYPE_SYSTEM_CONTIG, ION_HEAP_TYPE_CARVEOUT, ION_HEAP_TYPE_CHUNK, + ION_HEAP_TYPE_DMA, ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always are at the end of this enum */ ION_NUM_HEAPS, @@ -42,6 +46,7 @@ enum ion_heap_type { #define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) #define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) +#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) #define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8 diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c new file mode 100644 index 000000000000..74e3c77f1873 --- /dev/null +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -0,0 +1,233 @@ +/* + * drivers/staging/android/ion/ion_cma_heap.c + * + * Copyright (C) Linaro 2012 + * Author: for ST-Ericsson. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include +#include +#include + +#include "ion.h" +#include "ion_priv.h" + +#define ION_CMA_ALLOCATE_FAILED -1 + +struct ion_cma_heap { + struct ion_heap heap; + struct device *dev; +}; + +#define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap) + +struct ion_cma_buffer_info { + void *cpu_addr; + dma_addr_t handle; + struct sg_table *table; +}; + +/* + * Create scatter-list for the already allocated DMA buffer. + * This function could be replaced by dma_common_get_sgtable + * as soon as it will avalaible. + */ +int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t handle, size_t size) +{ + struct page *page = virt_to_page(cpu_addr); + int ret; + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (unlikely(ret)) + return ret; + + sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); + return 0; +} + +/* + * Create scatter-list for each page of the already allocated DMA buffer. + */ +int ion_cma_get_sgtable_per_page(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t handle, size_t size) +{ + struct page *page = virt_to_page(cpu_addr); + int ret, i; + struct scatterlist *sg; + + ret = sg_alloc_table(sgt, PAGE_ALIGN(size) / PAGE_SIZE, GFP_KERNEL); + if (unlikely(ret)) + return ret; + + sg = sgt->sgl; + for (i = 0; i < (PAGE_ALIGN(size) / PAGE_SIZE); i++) { + page = virt_to_page(cpu_addr + (i * PAGE_SIZE)); + sg_set_page(sg, page, PAGE_SIZE, 0); + sg = sg_next(sg); + } + return 0; +} + +/* ION CMA heap operations functions */ +static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, + unsigned long len, unsigned long align, + unsigned long flags) +{ + struct ion_cma_heap *cma_heap = to_cma_heap(heap); + struct device *dev = cma_heap->dev; + struct ion_cma_buffer_info *info; + + dev_dbg(dev, "Request buffer allocation len %ld\n", len); + + info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); + if (!info) { + dev_err(dev, "Can't allocate buffer info\n"); + return ION_CMA_ALLOCATE_FAILED; + } + + info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), 0); + + if (!info->cpu_addr) { + dev_err(dev, "Fail to allocate buffer\n"); + goto err; + } + + info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!info->table) { + dev_err(dev, "Fail to allocate sg table\n"); + goto free_mem; + } + + if (ion_buffer_fault_user_mappings(buffer)) { + if (ion_cma_get_sgtable_per_page + (dev, info->table, info->cpu_addr, info->handle, len)) + goto free_table; + } else { + if (ion_cma_get_sgtable + (dev, info->table, info->cpu_addr, info->handle, len)) + goto free_table; + } + /* keep this for memory release */ + buffer->priv_virt = info; + dev_dbg(dev, "Allocate buffer %p\n", buffer); + return 0; + +free_table: + kfree(info->table); +free_mem: + dma_free_coherent(dev, len, info->cpu_addr, info->handle); +err: + kfree(info); + return ION_CMA_ALLOCATE_FAILED; +} + +static void ion_cma_free(struct ion_buffer *buffer) +{ + struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); + struct device *dev = cma_heap->dev; + struct ion_cma_buffer_info *info = buffer->priv_virt; + + dev_dbg(dev, "Release buffer %p\n", buffer); + /* release memory */ + dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle); + /* release sg table */ + sg_free_table(info->table); + kfree(info->table); + kfree(info); +} + +/* return physical address in addr */ +static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, + ion_phys_addr_t *addr, size_t *len) +{ + struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); + struct device *dev = cma_heap->dev; + struct ion_cma_buffer_info *info = buffer->priv_virt; + + dev_dbg(dev, "Return buffer %p physical address 0x%x\n", buffer, + info->handle); + + *addr = info->handle; + *len = buffer->size; + + return 0; +} + +struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct ion_cma_buffer_info *info = buffer->priv_virt; + + return info->table; +} + +void ion_cma_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + return; +} + +static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); + struct device *dev = cma_heap->dev; + struct ion_cma_buffer_info *info = buffer->priv_virt; + + return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle, + buffer->size); +} + +void *ion_cma_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) +{ + struct ion_cma_buffer_info *info = buffer->priv_virt; + /* kernel memory mapping has been done at allocation time */ + return info->cpu_addr; +} + +static struct ion_heap_ops ion_cma_ops = { + .allocate = ion_cma_allocate, + .free = ion_cma_free, + .map_dma = ion_cma_heap_map_dma, + .unmap_dma = ion_cma_heap_unmap_dma, + .phys = ion_cma_phys, + .map_user = ion_cma_mmap, + .map_kernel = ion_cma_map_kernel, +}; + +struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) +{ + struct ion_cma_heap *cma_heap; + + cma_heap = kzalloc(sizeof(struct ion_cma_heap), GFP_KERNEL); + + if (!cma_heap) + return ERR_PTR(-ENOMEM); + + cma_heap->heap.ops = &ion_cma_ops; + /* get device from private heaps data, later it will be + * used to make the link with reserved CMA memory */ + cma_heap->dev = data->priv; + cma_heap->heap.type = ION_HEAP_TYPE_DMA; + return &cma_heap->heap; +} + +void ion_cma_heap_destroy(struct ion_heap *heap) +{ + struct ion_cma_heap *cma_heap = to_cma_heap(heap); + + kfree(cma_heap); +} diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index f541bff26435..3fc1dcc8153b 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -254,6 +254,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) case ION_HEAP_TYPE_CHUNK: heap = ion_chunk_heap_create(heap_data); break; + case ION_HEAP_TYPE_DMA: + heap = ion_cma_heap_create(heap_data); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type); @@ -290,6 +293,9 @@ void ion_heap_destroy(struct ion_heap *heap) case ION_HEAP_TYPE_CHUNK: ion_chunk_heap_destroy(heap); break; + case ION_HEAP_TYPE_DMA: + ion_cma_heap_destroy(heap); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap->type); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index bdc1e344d731..f5a09b6a4182 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -270,6 +270,9 @@ void ion_carveout_heap_destroy(struct ion_heap *); struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *); void ion_chunk_heap_destroy(struct ion_heap *); +struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *); +void ion_cma_heap_destroy(struct ion_heap *); + /** * kernel api to allocate/free from carveout -- used when carveout is * used to back an architecture specific custom heap -- cgit v1.2.3 From c13bd1c4eb714c08214e897fcbe51b13e0e0f279 Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Fri, 13 Dec 2013 14:24:45 -0800 Subject: gpu: ion: Fix performance issue in faulting code Previously the code to fault ion buffers in one page at a time had a performance problem caused by the requirement to traverse the sg list looking for the right page to load in (a result of the fact that the items in the list may not be of uniform size). To fix the problem, for buffers that will be faulted in, also keep a flat array of all the pages in the buffer to use from the fault handler. To recover some of the additional memory footprint this creates per buffer, dirty bits used to indicate which pages have been faulted in to the cpu are now stored in the low bit of each page struct pointer in the page array. Signed-off-by: Rebecca Schultz Zavin [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 105 +++++++++++++++----------- drivers/staging/android/ion/ion_cma_heap.c | 35 +-------- drivers/staging/android/ion/ion_heap.c | 18 ++++- drivers/staging/android/ion/ion_priv.h | 20 ++++- drivers/staging/android/ion/ion_system_heap.c | 25 +----- 5 files changed, 99 insertions(+), 104 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ddf8fde9ae93..38d65c2b296a 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -104,13 +105,33 @@ struct ion_handle { bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) { - return ((buffer->flags & ION_FLAG_CACHED) && - !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); + return ((buffer->flags & ION_FLAG_CACHED) && + !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); } bool ion_buffer_cached(struct ion_buffer *buffer) { - return !!(buffer->flags & ION_FLAG_CACHED); + return !!(buffer->flags & ION_FLAG_CACHED); +} + +static inline struct page *ion_buffer_page(struct page *page) +{ + return (struct page *)((unsigned long)page & ~(1UL)); +} + +static inline bool ion_buffer_page_is_dirty(struct page *page) +{ + return !!((unsigned long)page & 1UL); +} + +static inline void ion_buffer_page_dirty(struct page **page) +{ + *page = (struct page *)((unsigned long)(*page) | 1UL); +} + +static inline void ion_buffer_page_clean(struct page **page) +{ + *page = (struct page *)((unsigned long)(*page) & ~(1UL)); } /* this function should only be called while dev->lock is held */ @@ -139,8 +160,6 @@ static void ion_buffer_add(struct ion_device *dev, rb_insert_color(&buffer->node, &dev->buffers); } -static int ion_buffer_alloc_dirty(struct ion_buffer *buffer); - /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -185,17 +204,23 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, } buffer->sg_table = table; if (ion_buffer_fault_user_mappings(buffer)) { - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, - i) { - if (sg_dma_len(sg) == PAGE_SIZE) - continue; - pr_err("%s: cached mappings that will be faulted in " - "must have pagewise sg_lists\n", __func__); - ret = -EINVAL; - goto err; + int num_pages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; + struct scatterlist *sg; + int i, j, k = 0; + + buffer->pages = vmalloc(sizeof(struct page *) * num_pages); + if (!buffer->pages) { + ret = -ENOMEM; + goto err1; + } + + for_each_sg(table->sgl, sg, table->nents, i) { + struct page *page = sg_page(sg); + + for (j = 0; j < sg_dma_len(sg) / PAGE_SIZE; j++) + buffer->pages[k++] = page++; } - ret = ion_buffer_alloc_dirty(buffer); if (ret) goto err; } @@ -222,6 +247,9 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, err: heap->ops->unmap_dma(heap, buffer); heap->ops->free(buffer); +err1: + if (buffer->pages) + vfree(buffer->pages); err2: kfree(buffer); return ERR_PTR(ret); @@ -233,8 +261,8 @@ void ion_buffer_destroy(struct ion_buffer *buffer) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); - if (buffer->flags & ION_FLAG_CACHED) - kfree(buffer->dirty); + if (buffer->pages) + vfree(buffer->pages); kfree(buffer); } @@ -764,17 +792,6 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, { } -static int ion_buffer_alloc_dirty(struct ion_buffer *buffer) -{ - unsigned long pages = buffer->sg_table->nents; - unsigned long length = (pages + BITS_PER_LONG - 1)/BITS_PER_LONG; - - buffer->dirty = kzalloc(length * sizeof(unsigned long), GFP_KERNEL); - if (!buffer->dirty) - return -ENOMEM; - return 0; -} - struct ion_vma_list { struct list_head list; struct vm_area_struct *vma; @@ -784,9 +801,9 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, struct device *dev, enum dma_data_direction dir) { - struct scatterlist *sg; - int i; struct ion_vma_list *vma_list; + int pages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; + int i; pr_debug("%s: syncing for device %s\n", __func__, dev ? dev_name(dev) : "null"); @@ -795,11 +812,12 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, return; mutex_lock(&buffer->lock); - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { - if (!test_bit(i, buffer->dirty)) - continue; - dma_sync_sg_for_device(dev, sg, 1, dir); - clear_bit(i, buffer->dirty); + for (i = 0; i < pages; i++) { + struct page *page = buffer->pages[i]; + + if (ion_buffer_page_is_dirty(page)) + __dma_page_cpu_to_dev(page, 0, PAGE_SIZE, dir); + ion_buffer_page_clean(buffer->pages + i); } list_for_each_entry(vma_list, &buffer->vmas, list) { struct vm_area_struct *vma = vma_list->vma; @@ -813,21 +831,18 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct ion_buffer *buffer = vma->vm_private_data; - struct scatterlist *sg; - int i; + int ret; mutex_lock(&buffer->lock); - set_bit(vmf->pgoff, buffer->dirty); + ion_buffer_page_dirty(buffer->pages + vmf->pgoff); - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { - if (i != vmf->pgoff) - continue; - dma_sync_sg_for_cpu(NULL, sg, 1, DMA_BIDIRECTIONAL); - vm_insert_page(vma, (unsigned long)vmf->virtual_address, - sg_page(sg)); - break; - } + BUG_ON(!buffer->pages || !buffer->pages[vmf->pgoff]); + ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, + ion_buffer_page(buffer->pages[vmf->pgoff])); mutex_unlock(&buffer->lock); + if (ret) + return VM_FAULT_ERROR; + return VM_FAULT_NOPAGE; } diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 74e3c77f1873..86b6cf5da824 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -58,29 +58,6 @@ int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, return 0; } -/* - * Create scatter-list for each page of the already allocated DMA buffer. - */ -int ion_cma_get_sgtable_per_page(struct device *dev, struct sg_table *sgt, - void *cpu_addr, dma_addr_t handle, size_t size) -{ - struct page *page = virt_to_page(cpu_addr); - int ret, i; - struct scatterlist *sg; - - ret = sg_alloc_table(sgt, PAGE_ALIGN(size) / PAGE_SIZE, GFP_KERNEL); - if (unlikely(ret)) - return ret; - - sg = sgt->sgl; - for (i = 0; i < (PAGE_ALIGN(size) / PAGE_SIZE); i++) { - page = virt_to_page(cpu_addr + (i * PAGE_SIZE)); - sg_set_page(sg, page, PAGE_SIZE, 0); - sg = sg_next(sg); - } - return 0; -} - /* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, @@ -111,15 +88,9 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, goto free_mem; } - if (ion_buffer_fault_user_mappings(buffer)) { - if (ion_cma_get_sgtable_per_page - (dev, info->table, info->cpu_addr, info->handle, len)) - goto free_table; - } else { - if (ion_cma_get_sgtable - (dev, info->table, info->cpu_addr, info->handle, len)) - goto free_table; - } + if (ion_cma_get_sgtable + (dev, info->table, info->cpu_addr, info->handle, len)) + goto free_table; /* keep this for memory release */ buffer->priv_virt = info; dev_dbg(dev, "Allocate buffer %p\n", buffer); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 3fc1dcc8153b..cc2a42547605 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -134,8 +134,22 @@ end: return ret; } -void ion_heap_free_page(struct ion_buffer *buffer, struct page *page, - unsigned int order) +struct page *ion_heap_alloc_pages(struct ion_buffer *buffer, gfp_t gfp_flags, + unsigned int order) +{ + struct page *page = alloc_pages(gfp_flags, order); + + if (!page) + return page; + + if (ion_buffer_fault_user_mappings(buffer)) + split_page(page, order); + + return page; +} + +void ion_heap_free_pages(struct ion_buffer *buffer, struct page *page, + unsigned int order) { int i; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index f5a09b6a4182..965471afa47e 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -46,9 +46,8 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @vaddr: the kenrel mapping if kmap_cnt is not zero * @dmap_cnt: number of times the buffer is mapped for dma * @sg_table: the sg table for the buffer if dmap_cnt is not zero - * @dirty: bitmask representing which pages of this buffer have - * been dirtied by the cpu and need cache maintenance - * before dma + * @pages: flat array of pages in the buffer -- used by fault + * handler and only valid for buffers that are faulted in * @vmas: list of vma's mapping this buffer * @handle_count: count of handles referencing this buffer * @task_comm: taskcomm of last client to reference this buffer in a @@ -75,7 +74,7 @@ struct ion_buffer { void *vaddr; int dmap_cnt; struct sg_table *sg_table; - unsigned long *dirty; + struct page **pages; struct list_head vmas; /* used to track orphaned buffers */ int handle_count; @@ -213,6 +212,19 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); int ion_heap_buffer_zero(struct ion_buffer *buffer); +/** + * ion_heap_alloc_pages - allocate pages from alloc_pages + * @buffer: the buffer to allocate for, used to extract the flags + * @gfp_flags: the gfp_t for the allocation + * @order: the order of the allocatoin + * + * This funciton allocations from alloc pages and also does any other + * necessary operations based on the buffer->flags. For buffers which + * will be faulted in the pages are split using split_page + */ +struct page *ion_heap_alloc_pages(struct ion_buffer *buffer, gfp_t gfp_flags, + unsigned int order); + /** * ion_heap_init_deferred_free -- initialize deferred free functionality * @heap: the heap diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 344f7538400a..b9b10365f450 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -64,7 +64,6 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, unsigned long order) { bool cached = ion_buffer_cached(buffer); - bool split_pages = ion_buffer_fault_user_mappings(buffer); struct ion_page_pool *pool = heap->pools[order_to_index(order)]; struct page *page; @@ -75,7 +74,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (order > 4) gfp_flags = high_order_gfp_flags; - page = alloc_pages(gfp_flags, order); + page = ion_heap_alloc_pages(buffer, gfp_flags, order); if (!page) return 0; arm_dma_ops.sync_single_for_device(NULL, @@ -85,8 +84,6 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (!page) return 0; - if (split_pages) - split_page(page, order); return page; } @@ -153,7 +150,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, int i = 0; long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; - bool split_pages = ion_buffer_fault_user_mappings(buffer); INIT_LIST_HEAD(&pages); while (size_remaining > 0) { @@ -170,28 +166,15 @@ static int ion_system_heap_allocate(struct ion_heap *heap, if (!table) goto err; - if (split_pages) - ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE, - GFP_KERNEL); - else - ret = sg_alloc_table(table, i, GFP_KERNEL); - + ret = sg_alloc_table(table, i, GFP_KERNEL); if (ret) goto err1; sg = table->sgl; list_for_each_entry_safe(info, tmp_info, &pages, list) { struct page *page = info->page; - if (split_pages) { - for (i = 0; i < (1 << info->order); i++) { - sg_set_page(sg, page + i, PAGE_SIZE, 0); - sg = sg_next(sg); - } - } else { - sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE, - 0); - sg = sg_next(sg); - } + sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE, 0); + sg = sg_next(sg); list_del(&info->list); kfree(info); } -- cgit v1.2.3 From ea89faff84e35c7a5b386f158b5aec0c6327441c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:46 -0800 Subject: ion: chunk_heap: fix leak in allocated counter buffer->size is controlled by the outer ion layer, don't modify it inside the heap. Instead, compute the rounded up allocated size on demand. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 410c08e4028f..85fefe778845 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -47,15 +47,15 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, struct scatterlist *sg; int ret, i; unsigned long num_chunks; + unsigned long allocated_size; if (ion_buffer_fault_user_mappings(buffer)) return -ENOMEM; - num_chunks = ALIGN(size, chunk_heap->chunk_size) / - chunk_heap->chunk_size; - buffer->size = num_chunks * chunk_heap->chunk_size; + allocated_size = ALIGN(size, chunk_heap->chunk_size); + num_chunks = allocated_size / chunk_heap->chunk_size; - if (buffer->size > chunk_heap->size - chunk_heap->allocated) + if (allocated_size > chunk_heap->size - chunk_heap->allocated) return -ENOMEM; table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); @@ -78,7 +78,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, } buffer->priv_virt = table; - chunk_heap->allocated += buffer->size; + chunk_heap->allocated += allocated_size; return 0; err: sg = table->sgl; @@ -100,6 +100,9 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) struct sg_table *table = buffer->priv_virt; struct scatterlist *sg; int i; + unsigned long allocated_size; + + allocated_size = ALIGN(buffer->size, chunk_heap->chunk_size); ion_heap_buffer_zero(buffer); @@ -111,7 +114,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), sg_dma_len(sg)); } - chunk_heap->allocated -= buffer->size; + chunk_heap->allocated -= allocated_size; sg_free_table(table); kfree(table); } -- cgit v1.2.3 From 2540c73a5bf068b8c1c092fc3ce63c62ba949371 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:47 -0800 Subject: ion: add free list size to heap debug files Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 38d65c2b296a..93b84a9b45f4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1286,6 +1286,9 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "%16.s %16u\n", "total orphaned", total_orphaned_size); seq_printf(s, "%16.s %16u\n", "total ", total_size); + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) + seq_printf(s, "%16.s %16u\n", "deferred free", + heap->free_list_size); seq_printf(s, "----------------------------------------------------\n"); if (heap->debug_show) -- cgit v1.2.3 From dfc4a9b1769095d8125a56e5515f6728c9f137c0 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:48 -0800 Subject: ion: convert map_kernel to return ERR_PTR ion is going to stop accepting NULL as an error value, use ERR_PTR. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 7 ++++++- drivers/staging/android/ion/ion_heap.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index fd641688127c..36df34c1ed53 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -112,13 +112,18 @@ void ion_carveout_heap_unmap_dma(struct ion_heap *heap, void *ion_carveout_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) { + void *ret; int mtype = MT_MEMORY_NONCACHED; if (buffer->flags & ION_FLAG_CACHED) mtype = MT_MEMORY; - return __arm_ioremap(buffer->priv_phys, buffer->size, + ret = __arm_ioremap(buffer->priv_phys, buffer->size, mtype); + if (ret == NULL) + return ERR_PTR(-ENOMEM); + + return ret; } void ion_carveout_heap_unmap_kernel(struct ion_heap *heap, diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index cc2a42547605..a584ec036862 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -56,6 +56,9 @@ void *ion_heap_map_kernel(struct ion_heap *heap, vaddr = vmap(pages, npages, VM_MAP, pgprot); vfree(pages); + if (vaddr == NULL) + return ERR_PTR(-ENOMEM); + return vaddr; } -- cgit v1.2.3 From 9e907654d3c0ff58fb27b51d94128a9749c7e85c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:49 -0800 Subject: ion: remove IS_ERR_OR_NULL IS_ERR_OR_NULL is often part of a bad pattern that can accidentally return 0 on error: if (IS_ERR_OR_NULL(ptr)) return PTR_ERR(ptr); It also usually means that the errors of a function are not well defined. Replace all uses in ion.c by ensure that the return type of any function in ion is an ERR_PTR. Specify that the expected return value from map_kernel or map_dma heap ops is ERR_PTR, and warn if a heap returns NULL. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 28 +++++++++++++++------------- drivers/staging/android/ion/ion_priv.h | 3 +++ 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 93b84a9b45f4..54a00fe9a2e1 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -197,7 +197,9 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->size = len; table = heap->ops->map_dma(heap, buffer); - if (IS_ERR_OR_NULL(table)) { + if (WARN_ONCE(table == NULL, "heap->ops->map_dma should return ERR_PTR on error")) + table = ERR_PTR(-EINVAL); + if (IS_ERR(table)) { heap->ops->free(buffer); kfree(buffer); return ERR_PTR(PTR_ERR(table)); @@ -389,7 +391,7 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, if (handle->buffer == buffer) return handle; } - return NULL; + return ERR_PTR(-EINVAL); } static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) @@ -459,7 +461,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, if (!((1 << heap->id) & heap_id_mask)) continue; buffer = ion_buffer_create(heap, dev, len, align, flags); - if (!IS_ERR_OR_NULL(buffer)) + if (!IS_ERR(buffer)) break; } up_read(&dev->lock); @@ -543,7 +545,9 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) return buffer->vaddr; } vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - if (IS_ERR_OR_NULL(vaddr)) + if (WARN_ONCE(vaddr == NULL, "heap->ops->map_kernel should return ERR_PTR on error")) + return ERR_PTR(-EINVAL); + if (IS_ERR(vaddr)) return vaddr; buffer->vaddr = vaddr; buffer->kmap_cnt++; @@ -560,7 +564,7 @@ static void *ion_handle_kmap_get(struct ion_handle *handle) return buffer->vaddr; } vaddr = ion_buffer_kmap_get(buffer); - if (IS_ERR_OR_NULL(vaddr)) + if (IS_ERR(vaddr)) return vaddr; handle->kmap_cnt++; return vaddr; @@ -954,8 +958,6 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, mutex_unlock(&buffer->lock); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); - if (!vaddr) - return -ENOMEM; return 0; } @@ -1034,7 +1036,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) struct ion_handle *handle; dmabuf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(dmabuf)) + if (IS_ERR(dmabuf)) return ERR_PTR(PTR_ERR(dmabuf)); /* if this memory came from ion */ @@ -1049,12 +1051,12 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) mutex_lock(&client->lock); /* if a handle exists for this buffer just take a reference to it */ handle = ion_handle_lookup(client, buffer); - if (!IS_ERR_OR_NULL(handle)) { + if (!IS_ERR(handle)) { ion_handle_get(handle); goto end; } handle = ion_handle_create(client, buffer); - if (IS_ERR_OR_NULL(handle)) + if (IS_ERR(handle)) goto end; ion_handle_add(client, handle); end: @@ -1070,7 +1072,7 @@ static int ion_sync_for_device(struct ion_client *client, int fd) struct ion_buffer *buffer; dmabuf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(dmabuf)) + if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); /* if this memory came from ion */ @@ -1204,7 +1206,7 @@ static int ion_open(struct inode *inode, struct file *file) pr_debug("%s: %d\n", __func__, __LINE__); client = ion_client_create(dev, "user"); - if (IS_ERR_OR_NULL(client)) + if (IS_ERR(client)) return PTR_ERR(client); file->private_data = client; @@ -1400,7 +1402,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) } idev->debug_root = debugfs_create_dir("ion", NULL); - if (IS_ERR_OR_NULL(idev->debug_root)) + if (!idev->debug_root) pr_err("ion: failed to create debug files.\n"); idev->custom_ioctl = custom_ioctl; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 965471afa47e..f2635631e9be 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -94,6 +94,9 @@ void ion_buffer_destroy(struct ion_buffer *buffer); * @map_kernel map memory to the kernel * @unmap_kernel unmap memory to the kernel * @map_user map memory to userspace + * + * allocate, phys, and map_user return 0 on success, -errno on error. + * map_dma and map_kernel return pointer on success, ERR_PTR on error. */ struct ion_heap_ops { int (*allocate) (struct ion_heap *heap, -- cgit v1.2.3 From 47b404580bd92ec8dd3e691020bd515f6af262af Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:50 -0800 Subject: ion: replace userspace handle cookies with idr Userspace handles should not leak kernel virtual addresses to userspace. They have to be validated by looking them up in an rbtree anyways, so replace them with an idr and validate them by using idr_find to convert the id number to the struct ion_handle pointer. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 107 +++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 54a00fe9a2e1..ece1a4c327ac 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "ion.h" #include "ion_priv.h" @@ -64,6 +65,7 @@ struct ion_device { * @node: node in the tree of all clients * @dev: backpointer to ion device * @handles: an rb tree of all the handles in this client + * @idr: an idr space for allocating handle ids * @lock: lock protecting the tree of handles * @name: used for debugging * @task: used for debugging @@ -76,6 +78,7 @@ struct ion_client { struct rb_node node; struct ion_device *dev; struct rb_root handles; + struct idr idr; struct mutex lock; const char *name; struct task_struct *task; @@ -90,7 +93,7 @@ struct ion_client { * @buffer: pointer to the buffer * @node: node in the client's handle rbtree * @kmap_cnt: count of times this client has mapped to kernel - * @dmap_cnt: count of times this client has mapped for dma + * @id: client-unique id allocated by client->idr * * Modifications to node, map_cnt or mapping should be protected by the * lock in the client. Other fields are never changed after initialization. @@ -101,6 +104,7 @@ struct ion_handle { struct ion_buffer *buffer; struct rb_node node; unsigned int kmap_cnt; + int id; }; bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) @@ -356,6 +360,7 @@ static void ion_handle_destroy(struct kref *kref) ion_handle_kmap_put(handle); mutex_unlock(&buffer->lock); + idr_remove(&client->idr, handle->id); if (!RB_EMPTY_NODE(&handle->node)) rb_erase(&handle->node, &client->handles); @@ -387,36 +392,42 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, for (n = rb_first(&client->handles); n; n = rb_next(n)) { struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); + node); if (handle->buffer == buffer) return handle; } return ERR_PTR(-EINVAL); } -static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) +static struct ion_handle *ion_uhandle_get(struct ion_client *client, int id) { - struct rb_node *n = client->handles.rb_node; + return idr_find(&client->idr, id); +} - while (n) { - struct ion_handle *handle_node = rb_entry(n, struct ion_handle, - node); - if (handle < handle_node) - n = n->rb_left; - else if (handle > handle_node) - n = n->rb_right; - else - return true; - } - return false; +static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) +{ + return (ion_uhandle_get(client, handle->id) == handle); } -static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) +static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) { + int rc; struct rb_node **p = &client->handles.rb_node; struct rb_node *parent = NULL; struct ion_handle *entry; + do { + int id; + rc = idr_pre_get(&client->idr, GFP_KERNEL); + if (!rc) + return -ENOMEM; + rc = idr_get_new(&client->idr, handle, &id); + handle->id = id; + } while (rc == -EAGAIN); + + if (rc < 0) + return rc; + while (*p) { parent = *p; entry = rb_entry(parent, struct ion_handle, node); @@ -431,6 +442,8 @@ static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) rb_link_node(&handle->node, parent, p); rb_insert_color(&handle->node, &client->handles); + + return 0; } struct ion_handle *ion_alloc(struct ion_client *client, size_t len, @@ -441,6 +454,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, struct ion_device *dev = client->dev; struct ion_buffer *buffer = NULL; struct ion_heap *heap; + int ret; pr_debug("%s: len %d align %d heap_id_mask %u flags %x\n", __func__, len, align, heap_id_mask, flags); @@ -480,12 +494,16 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, */ ion_buffer_put(buffer); - if (!IS_ERR(handle)) { - mutex_lock(&client->lock); - ion_handle_add(client, handle); - mutex_unlock(&client->lock); - } + if (IS_ERR(handle)) + return handle; + mutex_lock(&client->lock); + ret = ion_handle_add(client, handle); + if (ret) { + ion_handle_put(handle); + handle = ERR_PTR(ret); + } + mutex_unlock(&client->lock); return handle; } @@ -705,6 +723,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, client->dev = dev; client->handles = RB_ROOT; + idr_init(&client->idr); mutex_init(&client->lock); client->name = name; client->task = task; @@ -745,6 +764,10 @@ void ion_client_destroy(struct ion_client *client) node); ion_handle_destroy(&handle->ref); } + + idr_remove_all(&client->idr); + idr_destroy(&client->idr); + down_write(&dev->lock); if (client->task) put_task_struct(client->task); @@ -1034,6 +1057,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) struct dma_buf *dmabuf; struct ion_buffer *buffer; struct ion_handle *handle; + int ret; dmabuf = dma_buf_get(fd); if (IS_ERR(dmabuf)) @@ -1058,7 +1082,11 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) handle = ion_handle_create(client, buffer); if (IS_ERR(handle)) goto end; - ion_handle_add(client, handle); + ret = ion_handle_add(client, handle); + if (ret) { + ion_handle_put(handle); + handle = ERR_PTR(ret); + } end: mutex_unlock(&client->lock); dma_buf_put(dmabuf); @@ -1098,17 +1126,20 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case ION_IOC_ALLOC: { struct ion_allocation_data data; + struct ion_handle *handle; if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - data.handle = ion_alloc(client, data.len, data.align, + handle = ion_alloc(client, data.len, data.align, data.heap_id_mask, data.flags); - if (IS_ERR(data.handle)) - return PTR_ERR(data.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + data.handle = (struct ion_handle *)handle->id; if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - ion_free(client, data.handle); + ion_free(client, handle); return -EFAULT; } break; @@ -1116,27 +1147,29 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case ION_IOC_FREE: { struct ion_handle_data data; - bool valid; + struct ion_handle *handle; if (copy_from_user(&data, (void __user *)arg, sizeof(struct ion_handle_data))) return -EFAULT; mutex_lock(&client->lock); - valid = ion_handle_validate(client, data.handle); + handle = ion_uhandle_get(client, (int)data.handle); mutex_unlock(&client->lock); - if (!valid) + if (!handle) return -EINVAL; - ion_free(client, data.handle); + ion_free(client, handle); break; } case ION_IOC_SHARE: case ION_IOC_MAP: { struct ion_fd_data data; + struct ion_handle *handle; if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - data.fd = ion_share_dma_buf_fd(client, data.handle); + handle = ion_uhandle_get(client, (int)data.handle); + data.fd = ion_share_dma_buf_fd(client, handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; if (data.fd < 0) @@ -1146,15 +1179,17 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case ION_IOC_IMPORT: { struct ion_fd_data data; + struct ion_handle *handle; int ret = 0; if (copy_from_user(&data, (void __user *)arg, sizeof(struct ion_fd_data))) return -EFAULT; - data.handle = ion_import_dma_buf(client, data.fd); - if (IS_ERR(data.handle)) { - ret = PTR_ERR(data.handle); - data.handle = NULL; - } + handle = ion_import_dma_buf(client, data.fd); + if (IS_ERR(handle)) + ret = PTR_ERR(handle); + else + data.handle = (struct ion_handle *)handle->id; + if (copy_to_user((void __user *)arg, &data, sizeof(struct ion_fd_data))) return -EFAULT; -- cgit v1.2.3 From e1cf36823407751d1ad1168bc718cf5a0ac5dbf4 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:51 -0800 Subject: ion: index client->handles rbtree by buffer The only remaining users of the client->handles rbtree are iterating through it like a list. Keep the rbtree, but change its index to be the buffer address instead of the handle address, which makes ion_handle_lookup a fast rbtree search. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ece1a4c327ac..ef0b2d704a7b 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -388,13 +388,16 @@ static int ion_handle_put(struct ion_handle *handle) static struct ion_handle *ion_handle_lookup(struct ion_client *client, struct ion_buffer *buffer) { - struct rb_node *n; - - for (n = rb_first(&client->handles); n; n = rb_next(n)) { - struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); - if (handle->buffer == buffer) - return handle; + struct rb_node *n = client->handles.rb_node; + + while (n) { + struct ion_handle *entry = rb_entry(n, struct ion_handle, node); + if (buffer < entry->buffer) + n = n->rb_left; + else if (buffer > entry->buffer) + n = n->rb_right; + else + return entry; } return ERR_PTR(-EINVAL); } @@ -432,9 +435,9 @@ static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) parent = *p; entry = rb_entry(parent, struct ion_handle, node); - if (handle < entry) + if (handle->buffer < entry->buffer) p = &(*p)->rb_left; - else if (handle > entry) + else if (handle->buffer > entry->buffer) p = &(*p)->rb_right; else WARN(1, "%s: buffer already found.", __func__); -- cgit v1.2.3 From b4f8d242c6fb5e631ba861c1a6024ae14b02f5a8 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:52 -0800 Subject: ion: don't use id 0 for handle cookie ion userspace clients think that the cookie is a pointer, so they use NULL to check if the handle has been initialized. Set the first id number to 1. Signed-off-by: Colin Cross [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ef0b2d704a7b..273ec3a51fff 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -424,7 +424,7 @@ static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) rc = idr_pre_get(&client->idr, GFP_KERNEL); if (!rc) return -ENOMEM; - rc = idr_get_new(&client->idr, handle, &id); + rc = idr_get_new_above(&client->idr, handle, 1, &id); handle->id = id; } while (rc == -EAGAIN); -- cgit v1.2.3 From 22b7f24d6131ac4cbbf03f7a81000942e74fcd49 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 13 Dec 2013 14:24:53 -0800 Subject: ion: add new ion_user_handle_t type for the user-space token Declare new ion_user_handle_t type to contain the token returned to user-space. This allows a 2-step migration of the user-space code to a new kernel header first, then will allow us to change the definition of the ion_user_handle_type_t to int without breaking the API. Signed-off-by: Rom Lemarchand (cherry picked from commit ebb8269bbb05b06ecedca3e21b3e65f23d48eadd) [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 4 ++-- drivers/staging/android/ion/ion.h | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 273ec3a51fff..e2a303398dd0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1139,7 +1139,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(handle)) return PTR_ERR(handle); - data.handle = (struct ion_handle *)handle->id; + data.handle = (ion_user_handle_t)handle->id; if (copy_to_user((void __user *)arg, &data, sizeof(data))) { ion_free(client, handle); @@ -1191,7 +1191,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(handle)) ret = PTR_ERR(handle); else - data.handle = (struct ion_handle *)handle->id; + data.handle = (ion_user_handle_t)handle->id; if (copy_to_user((void __user *)arg, &data, sizeof(struct ion_fd_data))) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 3942b3ecb992..244f085b5895 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -20,6 +20,8 @@ #include struct ion_handle; +typedef struct ion_handle *ion_user_handle_t; + /** * enum ion_heap_types - list of all possible types of heaps * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc @@ -268,7 +270,7 @@ struct ion_allocation_data { size_t align; unsigned int heap_id_mask; unsigned int flags; - struct ion_handle *handle; + ion_user_handle_t handle; }; /** @@ -282,7 +284,7 @@ struct ion_allocation_data { * provides the file descriptor and the kernel returns the handle. */ struct ion_fd_data { - struct ion_handle *handle; + ion_user_handle_t handle; int fd; }; @@ -291,7 +293,7 @@ struct ion_fd_data { * @handle: a handle */ struct ion_handle_data { - struct ion_handle *handle; + ion_user_handle_t handle; }; /** -- cgit v1.2.3 From b88fa7319ef3c77478d732fab2f6750c305c1873 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 13 Dec 2013 14:24:54 -0800 Subject: ion: change ion_user_handle_t definition to int Turn ion_user_handle_t to int. This change reflects the underlying type returned by the ion driver. Signed-off-by: Rom Lemarchand [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 8 ++++---- drivers/staging/android/ion/ion.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e2a303398dd0..1c40b74bc9a3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1139,7 +1139,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(handle)) return PTR_ERR(handle); - data.handle = (ion_user_handle_t)handle->id; + data.handle = handle->id; if (copy_to_user((void __user *)arg, &data, sizeof(data))) { ion_free(client, handle); @@ -1156,7 +1156,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) sizeof(struct ion_handle_data))) return -EFAULT; mutex_lock(&client->lock); - handle = ion_uhandle_get(client, (int)data.handle); + handle = ion_uhandle_get(client, data.handle); mutex_unlock(&client->lock); if (!handle) return -EINVAL; @@ -1171,7 +1171,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - handle = ion_uhandle_get(client, (int)data.handle); + handle = ion_uhandle_get(client, data.handle); data.fd = ion_share_dma_buf_fd(client, handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; @@ -1191,7 +1191,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(handle)) ret = PTR_ERR(handle); else - data.handle = (ion_user_handle_t)handle->id; + data.handle = handle->id; if (copy_to_user((void __user *)arg, &data, sizeof(struct ion_fd_data))) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 244f085b5895..d9798909f809 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -19,8 +19,7 @@ #include -struct ion_handle; -typedef struct ion_handle *ion_user_handle_t; +typedef int ion_user_handle_t; /** * enum ion_heap_types - list of all possible types of heaps @@ -65,6 +64,7 @@ enum ion_heap_type { caches must be managed manually */ #ifdef __KERNEL__ +struct ion_handle; struct ion_device; struct ion_heap; struct ion_mapper; -- cgit v1.2.3 From 827c849e37b71cb6396d56096ad497748bbbe98f Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 13 Dec 2013 14:24:55 -0800 Subject: ion: add compat_ioctl Add a compat_ioctl to the ion driver Signed-off-by: Rom Lemarchand [jstultz: modified patch to apply to staging directory] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Makefile | 3 + drivers/staging/android/ion/compat_ion.c | 172 +++++++++++++++++++++++++++++++ drivers/staging/android/ion/compat_ion.h | 30 ++++++ drivers/staging/android/ion/ion.c | 2 + 4 files changed, 207 insertions(+) create mode 100644 drivers/staging/android/ion/compat_ion.c create mode 100644 drivers/staging/android/ion/compat_ion.h (limited to 'drivers') diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index ce0f1ef1c233..9c956659124b 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,3 +1,6 @@ obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o +ifdef CONFIG_COMPAT +obj-$(CONFIG_ION) += compat_ion.o +endif obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c new file mode 100644 index 000000000000..83842a67fe24 --- /dev/null +++ b/drivers/staging/android/ion/compat_ion.c @@ -0,0 +1,172 @@ +/* + * drivers/staging/android/ion/compat_ion.c + * + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#include +#include +#include + +#include "ion.h" +#include "compat_ion.h" + +/* See drivers/staging/android/ion/ion.h for the definition of these structs */ +struct compat_ion_allocation_data { + compat_size_t len; + compat_size_t align; + compat_uint_t heap_id_mask; + compat_uint_t flags; + compat_int_t handle; +}; + +struct compat_ion_custom_data { + compat_uint_t cmd; + compat_ulong_t arg; +}; + +static int compat_get_ion_allocation_data( + struct compat_ion_allocation_data __user *data32, + struct ion_allocation_data __user *data) +{ + compat_size_t s; + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(s, &data32->len); + err |= put_user(s, &data->len); + err |= get_user(s, &data32->align); + err |= put_user(s, &data->align); + err |= get_user(u, &data32->heap_id_mask); + err |= put_user(u, &data->heap_id_mask); + err |= get_user(u, &data32->flags); + err |= put_user(u, &data->flags); + err |= get_user(i, &data32->handle); + err |= put_user(i, &data->handle); + + return err; +} + +static int compat_put_ion_allocation_data( + struct compat_ion_allocation_data __user *data32, + struct ion_allocation_data __user *data) +{ + compat_size_t s; + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(s, &data->len); + err |= put_user(s, &data32->len); + err |= get_user(s, &data->align); + err |= put_user(s, &data32->align); + err |= get_user(u, &data->heap_id_mask); + err |= put_user(u, &data32->heap_id_mask); + err |= get_user(u, &data->flags); + err |= put_user(u, &data32->flags); + err |= get_user(i, &data->handle); + err |= put_user(i, &data32->handle); + + return err; +} + +static int compat_get_ion_custom_data( + struct compat_ion_custom_data __user *data32, + struct ion_custom_data __user *data) +{ + compat_uint_t cmd; + compat_ulong_t arg; + int err; + + err = get_user(cmd, &data32->cmd); + err |= put_user(cmd, &data->cmd); + err |= get_user(arg, &data32->arg); + err |= put_user(arg, &data->arg); + + return err; +}; + +long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + case ION_IOC_ALLOC: + { + struct compat_ion_allocation_data __user *data32; + struct ion_allocation_data __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_ion_allocation_data(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, cmd, + (unsigned long)data); + err = compat_put_ion_allocation_data(data32, data); + return ret ? ret : err; + } + case ION_IOC_FREE: + { + struct compat_ion_allocation_data __user *data32; + struct ion_allocation_data __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_ion_allocation_data(data32, data); + if (err) + return err; + + return filp->f_op->unlocked_ioctl(filp, cmd, + (unsigned long)data); + } + case ION_IOC_CUSTOM: { + struct compat_ion_custom_data __user *data32; + struct ion_custom_data __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_ion_custom_data(data32, data); + if (err) + return err; + + return filp->f_op->unlocked_ioctl(filp, cmd, + (unsigned long)data); + } + case ION_IOC_SHARE: + case ION_IOC_MAP: + case ION_IOC_IMPORT: + case ION_IOC_SYNC: + return filp->f_op->unlocked_ioctl(filp, cmd, + (unsigned long)compat_ptr(arg)); + default: + return -ENOIOCTLCMD; + } +} diff --git a/drivers/staging/android/ion/compat_ion.h b/drivers/staging/android/ion/compat_ion.h new file mode 100644 index 000000000000..c2ad5893dfda --- /dev/null +++ b/drivers/staging/android/ion/compat_ion.h @@ -0,0 +1,30 @@ +/* + + * drivers/staging/android/ion/compat_ion.h + * + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#ifndef _LINUX_COMPAT_ION_H +#define _LINUX_COMPAT_ION_H + +#if IS_ENABLED(CONFIG_COMPAT) + +long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); + +#else + +#define compat_ion_ioctl NULL + +#endif /* CONFIG_COMPAT */ +#endif /* _LINUX_COMPAT_ION_H */ diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 1c40b74bc9a3..d97117f3abb6 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -38,6 +38,7 @@ #include "ion.h" #include "ion_priv.h" +#include "compat_ion.h" /** * struct ion_device - the metadata of the ion device node @@ -1256,6 +1257,7 @@ static const struct file_operations ion_fops = { .open = ion_open, .release = ion_release, .unlocked_ioctl = ion_ioctl, + .compat_ioctl = compat_ion_ioctl, }; static size_t ion_debug_heap_total(struct ion_client *client, -- cgit v1.2.3 From 9e57e108d2c140909fa81e7a7c1498e23bb32b41 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:56 -0800 Subject: gpu: ion: delete ion_system_mapper.c The mapper abstraction layer was removed before the initial ion commit, but a stray ion_system_mapper.c file was left in. Delete it. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_mapper.c | 114 ------------------------ 1 file changed, 114 deletions(-) delete mode 100644 drivers/staging/android/ion/ion_system_mapper.c (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_mapper.c b/drivers/staging/android/ion/ion_system_mapper.c deleted file mode 100644 index 285430d2f79a..000000000000 --- a/drivers/staging/android/ion/ion_system_mapper.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * drivers/staging/android/ion/ion_system_mapper.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * 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. - * - */ - -#include -#include -#include -#include -#include -#include "ion.h" -#include "ion_priv.h" -/* - * This mapper is valid for any heap that allocates memory that already has - * a kernel mapping, this includes vmalloc'd memory, kmalloc'd memory, - * pages obtained via io_remap, etc. - */ -static void *ion_kernel_mapper_map(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct ion_mapping **mapping) -{ - if (!((1 << buffer->heap->type) & mapper->heap_mask)) { - pr_err("%s: attempting to map an unsupported heap\n", __func__); - return ERR_PTR(-EINVAL); - } - /* XXX REVISIT ME!!! */ - *((unsigned long *)mapping) = (unsigned long)buffer->priv; - return buffer->priv; -} - -static void ion_kernel_mapper_unmap(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct ion_mapping *mapping) -{ - if (!((1 << buffer->heap->type) & mapper->heap_mask)) - pr_err("%s: attempting to unmap an unsupported heap\n", - __func__); -} - -static void *ion_kernel_mapper_map_kernel(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct ion_mapping *mapping) -{ - if (!((1 << buffer->heap->type) & mapper->heap_mask)) { - pr_err("%s: attempting to unmap an unsupported heap\n", - __func__); - return ERR_PTR(-EINVAL); - } - return buffer->priv; -} - -static int ion_kernel_mapper_map_user(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct vm_area_struct *vma, - struct ion_mapping *mapping) -{ - int ret; - - switch (buffer->heap->type) { - case ION_HEAP_KMALLOC: - { - unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv)); - ret = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - break; - } - case ION_HEAP_VMALLOC: - ret = remap_vmalloc_range(vma, buffer->priv, vma->vm_pgoff); - break; - default: - pr_err("%s: attempting to map unsupported heap to userspace\n", - __func__); - return -EINVAL; - } - - return ret; -} - -static struct ion_mapper_ops ops = { - .map = ion_kernel_mapper_map, - .map_kernel = ion_kernel_mapper_map_kernel, - .map_user = ion_kernel_mapper_map_user, - .unmap = ion_kernel_mapper_unmap, -}; - -struct ion_mapper *ion_system_mapper_create(void) -{ - struct ion_mapper *mapper; - mapper = kzalloc(sizeof(struct ion_mapper), GFP_KERNEL); - if (!mapper) - return ERR_PTR(-ENOMEM); - mapper->type = ION_SYSTEM_MAPPER; - mapper->ops = &ops; - mapper->heap_mask = (1 << ION_HEAP_VMALLOC) | (1 << ION_HEAP_KMALLOC); - return mapper; -} - -void ion_system_mapper_destroy(struct ion_mapper *mapper) -{ - kfree(mapper); -} - -- cgit v1.2.3 From c3a2fe03148f13b119c7bf0427a0526bdb288a92 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:57 -0800 Subject: ion: move userspace api into uapi/ion.h Split the userspace api out of drivers/staging/android/ion/ion.h into drivers/staging/android/uapi/ion.h Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/compat_ion.c | 2 +- drivers/staging/android/ion/ion.h | 176 +-------------------------- drivers/staging/android/uapi/ion.h | 196 +++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+), 176 deletions(-) create mode 100644 drivers/staging/android/uapi/ion.h (limited to 'drivers') diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index 83842a67fe24..d4a33c7a419c 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -21,7 +21,7 @@ #include "ion.h" #include "compat_ion.h" -/* See drivers/staging/android/ion/ion.h for the definition of these structs */ +/* See drivers/staging/android/uapi/ion.h for the definition of these structs */ struct compat_ion_allocation_data { compat_size_t len; compat_size_t align; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index d9798909f809..962e1c58d362 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -19,51 +19,8 @@ #include -typedef int ion_user_handle_t; +#include "../uapi/ion.h" -/** - * enum ion_heap_types - list of all possible types of heaps - * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc - * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc - * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved - * carveout heap, allocations are physically - * contiguous - * @ION_HEAP_TYPE_DMA: memory allocated via DMA API - * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask - * is used to identify the heaps, so only 32 - * total heap types are supported - */ -enum ion_heap_type { - ION_HEAP_TYPE_SYSTEM, - ION_HEAP_TYPE_SYSTEM_CONTIG, - ION_HEAP_TYPE_CARVEOUT, - ION_HEAP_TYPE_CHUNK, - ION_HEAP_TYPE_DMA, - ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always - are at the end of this enum */ - ION_NUM_HEAPS, -}; - -#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) -#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) -#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) -#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) - -#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8 - -/** - * allocation flags - the lower 16 bits are used by core ion, the upper 16 - * bits are reserved for use by the heaps themselves. - */ -#define ION_FLAG_CACHED 1 /* mappings of this buffer should be - cached, ion will do cache - maintenance when the buffer is - mapped for dma */ -#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* mappings of this buffer will created - at mmap time, if this is set - caches must be managed manually */ - -#ifdef __KERNEL__ struct ion_handle; struct ion_device; struct ion_heap; @@ -244,135 +201,4 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); */ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); -#endif /* __KERNEL__ */ - -/** - * DOC: Ion Userspace API - * - * create a client by opening /dev/ion - * most operations handled via following ioctls - * - */ - -/** - * struct ion_allocation_data - metadata passed from userspace for allocations - * @len: size of the allocation - * @align: required alignment of the allocation - * @heap_id_mask: mask of heap ids to allocate from - * @flags: flags passed to heap - * @handle: pointer that will be populated with a cookie to use to - * refer to this allocation - * - * Provided by userspace as an argument to the ioctl - */ -struct ion_allocation_data { - size_t len; - size_t align; - unsigned int heap_id_mask; - unsigned int flags; - ion_user_handle_t handle; -}; - -/** - * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair - * @handle: a handle - * @fd: a file descriptor representing that handle - * - * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with - * the handle returned from ion alloc, and the kernel returns the file - * descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace - * provides the file descriptor and the kernel returns the handle. - */ -struct ion_fd_data { - ion_user_handle_t handle; - int fd; -}; - -/** - * struct ion_handle_data - a handle passed to/from the kernel - * @handle: a handle - */ -struct ion_handle_data { - ion_user_handle_t handle; -}; - -/** - * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl - * @cmd: the custom ioctl function to call - * @arg: additional data to pass to the custom ioctl, typically a user - * pointer to a predefined structure - * - * This works just like the regular cmd and arg fields of an ioctl. - */ -struct ion_custom_data { - unsigned int cmd; - unsigned long arg; -}; - -#define ION_IOC_MAGIC 'I' - -/** - * DOC: ION_IOC_ALLOC - allocate memory - * - * Takes an ion_allocation_data struct and returns it with the handle field - * populated with the opaque handle for the allocation. - */ -#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ - struct ion_allocation_data) - -/** - * DOC: ION_IOC_FREE - free memory - * - * Takes an ion_handle_data struct and frees the handle. - */ -#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) - -/** - * DOC: ION_IOC_MAP - get a file descriptor to mmap - * - * Takes an ion_fd_data struct with the handle field populated with a valid - * opaque handle. Returns the struct with the fd field set to a file - * descriptor open in the current address space. This file descriptor - * can then be used as an argument to mmap. - */ -#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data) - -/** - * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation - * - * Takes an ion_fd_data struct with the handle field populated with a valid - * opaque handle. Returns the struct with the fd field set to a file - * descriptor open in the current address space. This file descriptor - * can then be passed to another process. The corresponding opaque handle can - * be retrieved via ION_IOC_IMPORT. - */ -#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) - -/** - * DOC: ION_IOC_IMPORT - imports a shared file descriptor - * - * Takes an ion_fd_data struct with the fd field populated with a valid file - * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle - * filed set to the corresponding opaque handle. - */ -#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data) - -/** - * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory - * - * Deprecated in favor of using the dma_buf api's correctly (syncing - * will happend automatically when the buffer is mapped to a device). - * If necessary should be used after touching a cached buffer from the cpu, - * this will make the buffer in memory coherent. - */ -#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data) - -/** - * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl - * - * Takes the argument of the architecture specific ioctl to call and - * passes appropriate userdata for that ioctl - */ -#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) - #endif /* _LINUX_ION_H */ diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h new file mode 100644 index 000000000000..f09e7c154d69 --- /dev/null +++ b/drivers/staging/android/uapi/ion.h @@ -0,0 +1,196 @@ +/* + * drivers/staging/android/uapi/ion.h + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#ifndef _UAPI_LINUX_ION_H +#define _UAPI_LINUX_ION_H + +#include +#include + +typedef int ion_user_handle_t; + +/** + * enum ion_heap_types - list of all possible types of heaps + * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc + * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc + * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved + * carveout heap, allocations are physically + * contiguous + * @ION_HEAP_TYPE_DMA: memory allocated via DMA API + * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask + * is used to identify the heaps, so only 32 + * total heap types are supported + */ +enum ion_heap_type { + ION_HEAP_TYPE_SYSTEM, + ION_HEAP_TYPE_SYSTEM_CONTIG, + ION_HEAP_TYPE_CARVEOUT, + ION_HEAP_TYPE_CHUNK, + ION_HEAP_TYPE_DMA, + ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always + are at the end of this enum */ + ION_NUM_HEAPS = 16, +}; + +#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) +#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) +#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) +#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) + +#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8 + +/** + * allocation flags - the lower 16 bits are used by core ion, the upper 16 + * bits are reserved for use by the heaps themselves. + */ +#define ION_FLAG_CACHED 1 /* mappings of this buffer should be + cached, ion will do cache + maintenance when the buffer is + mapped for dma */ +#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* mappings of this buffer will created + at mmap time, if this is set + caches must be managed manually */ + +/** + * DOC: Ion Userspace API + * + * create a client by opening /dev/ion + * most operations handled via following ioctls + * + */ + +/** + * struct ion_allocation_data - metadata passed from userspace for allocations + * @len: size of the allocation + * @align: required alignment of the allocation + * @heap_id_mask: mask of heap ids to allocate from + * @flags: flags passed to heap + * @handle: pointer that will be populated with a cookie to use to + * refer to this allocation + * + * Provided by userspace as an argument to the ioctl + */ +struct ion_allocation_data { + size_t len; + size_t align; + unsigned int heap_id_mask; + unsigned int flags; + ion_user_handle_t handle; +}; + +/** + * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair + * @handle: a handle + * @fd: a file descriptor representing that handle + * + * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with + * the handle returned from ion alloc, and the kernel returns the file + * descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace + * provides the file descriptor and the kernel returns the handle. + */ +struct ion_fd_data { + ion_user_handle_t handle; + int fd; +}; + +/** + * struct ion_handle_data - a handle passed to/from the kernel + * @handle: a handle + */ +struct ion_handle_data { + ion_user_handle_t handle; +}; + +/** + * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl + * @cmd: the custom ioctl function to call + * @arg: additional data to pass to the custom ioctl, typically a user + * pointer to a predefined structure + * + * This works just like the regular cmd and arg fields of an ioctl. + */ +struct ion_custom_data { + unsigned int cmd; + unsigned long arg; +}; + +#define ION_IOC_MAGIC 'I' + +/** + * DOC: ION_IOC_ALLOC - allocate memory + * + * Takes an ion_allocation_data struct and returns it with the handle field + * populated with the opaque handle for the allocation. + */ +#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ + struct ion_allocation_data) + +/** + * DOC: ION_IOC_FREE - free memory + * + * Takes an ion_handle_data struct and frees the handle. + */ +#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) + +/** + * DOC: ION_IOC_MAP - get a file descriptor to mmap + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be used as an argument to mmap. + */ +#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data) + +/** + * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be passed to another process. The corresponding opaque handle can + * be retrieved via ION_IOC_IMPORT. + */ +#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) + +/** + * DOC: ION_IOC_IMPORT - imports a shared file descriptor + * + * Takes an ion_fd_data struct with the fd field populated with a valid file + * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle + * filed set to the corresponding opaque handle. + */ +#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data) + +/** + * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory + * + * Deprecated in favor of using the dma_buf api's correctly (syncing + * will happend automatically when the buffer is mapped to a device). + * If necessary should be used after touching a cached buffer from the cpu, + * this will make the buffer in memory coherent. + */ +#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data) + +/** + * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl + * + * Takes the argument of the architecture specific ioctl to call and + * passes appropriate userdata for that ioctl + */ +#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) + +#endif /* _UAPI_LINUX_ION_H */ -- cgit v1.2.3 From 687258f7c89107154ed8d7967e0ad47e0f6f679f Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Dec 2013 14:24:58 -0800 Subject: ion: Fix compat support to use proper compat ioctl numbers The compat support added to ion didn't provide compat ioctl numbers (who's value depends on the compat structure size). So 32bit applications would get an error when trying to make ioctl calls. This patch adds the needed COMPAT_ macros and uses them in the compat_ion_ioctl, translating them to their non-compat cmd when calling the normal ioctl call. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/compat_ion.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index d4a33c7a419c..079a5bbd2951 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -35,6 +35,12 @@ struct compat_ion_custom_data { compat_ulong_t arg; }; +#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ + struct compat_ion_allocation_data) +#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) +#define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \ + struct compat_ion_custom_data) + static int compat_get_ion_allocation_data( struct compat_ion_allocation_data __user *data32, struct ion_allocation_data __user *data) @@ -105,7 +111,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; switch (cmd) { - case ION_IOC_ALLOC: + case COMPAT_ION_IOC_ALLOC: { struct compat_ion_allocation_data __user *data32; struct ion_allocation_data __user *data; @@ -119,13 +125,12 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = compat_get_ion_allocation_data(data32, data); if (err) return err; - - ret = filp->f_op->unlocked_ioctl(filp, cmd, + ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC, (unsigned long)data); err = compat_put_ion_allocation_data(data32, data); return ret ? ret : err; } - case ION_IOC_FREE: + case COMPAT_ION_IOC_FREE: { struct compat_ion_allocation_data __user *data32; struct ion_allocation_data __user *data; @@ -140,10 +145,10 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) return err; - return filp->f_op->unlocked_ioctl(filp, cmd, + return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE, (unsigned long)data); } - case ION_IOC_CUSTOM: { + case COMPAT_ION_IOC_CUSTOM: { struct compat_ion_custom_data __user *data32; struct ion_custom_data __user *data; int err; @@ -157,7 +162,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) return err; - return filp->f_op->unlocked_ioctl(filp, cmd, + return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM, (unsigned long)data); } case ION_IOC_SHARE: -- cgit v1.2.3 From 83271f6262c91a49df325c52bec8f00f4de294ca Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:24:59 -0800 Subject: ion: hold reference to handle after ion_uhandle_get commit 1262ab1846cf76f7549c66ef709120dbfbe6d49f (ion: replace userspace handle cookies with idr) broke the locking in ion. The ION_IOC_FREE and ION_IOC_MAP ioctls were relying on ion_handle_validate to detect the case where a call raced with another ION_IOC_FREE which may have freed the struct ion_handle. Rename ion_uhandle_get to ion_handle_get_by_id, and have it take the client lock and return with an extra reference to the handle. Make each caller put its reference once it is done with the handle. Also modify users of ion_handle_validate to continue to hold the client lock after calling ion_handle_validate until they are done with the handle, and warn if ion_handle_validate is called without the client lock held. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 56 ++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d97117f3abb6..cf9fc7813004 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -383,7 +383,14 @@ static void ion_handle_get(struct ion_handle *handle) static int ion_handle_put(struct ion_handle *handle) { - return kref_put(&handle->ref, ion_handle_destroy); + struct ion_client *client = handle->client; + int ret; + + mutex_lock(&client->lock); + ret = kref_put(&handle->ref, ion_handle_destroy); + mutex_unlock(&client->lock); + + return ret; } static struct ion_handle *ion_handle_lookup(struct ion_client *client, @@ -403,14 +410,24 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, return ERR_PTR(-EINVAL); } -static struct ion_handle *ion_uhandle_get(struct ion_client *client, int id) +static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, + int id) { - return idr_find(&client->idr, id); + struct ion_handle *handle; + + mutex_lock(&client->lock); + handle = idr_find(&client->idr, id); + if (handle) + ion_handle_get(handle); + mutex_unlock(&client->lock); + + return handle ? handle : ERR_PTR(-EINVAL); } static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) { - return (ion_uhandle_get(client, handle->id) == handle); + WARN_ON(!mutex_is_locked(&client->lock)); + return (idr_find(&client->idr, handle->id) == handle); } static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) @@ -503,11 +520,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, mutex_lock(&client->lock); ret = ion_handle_add(client, handle); + mutex_unlock(&client->lock); if (ret) { ion_handle_put(handle); handle = ERR_PTR(ret); } - mutex_unlock(&client->lock); return handle; } @@ -527,8 +544,8 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&client->lock); return; } - ion_handle_put(handle); mutex_unlock(&client->lock); + ion_handle_put(handle); } EXPORT_SYMBOL(ion_free); @@ -1021,14 +1038,15 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client, mutex_lock(&client->lock); valid_handle = ion_handle_validate(client, handle); - mutex_unlock(&client->lock); if (!valid_handle) { WARN(1, "%s: invalid handle passed to share.\n", __func__); + mutex_unlock(&client->lock); return ERR_PTR(-EINVAL); } - buffer = handle->buffer; ion_buffer_get(buffer); + mutex_unlock(&client->lock); + dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR); if (IS_ERR(dmabuf)) { ion_buffer_put(buffer); @@ -1081,18 +1099,24 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) handle = ion_handle_lookup(client, buffer); if (!IS_ERR(handle)) { ion_handle_get(handle); + mutex_unlock(&client->lock); goto end; } + mutex_unlock(&client->lock); + handle = ion_handle_create(client, buffer); if (IS_ERR(handle)) goto end; + + mutex_lock(&client->lock); ret = ion_handle_add(client, handle); + mutex_unlock(&client->lock); if (ret) { ion_handle_put(handle); handle = ERR_PTR(ret); } + end: - mutex_unlock(&client->lock); dma_buf_put(dmabuf); return handle; } @@ -1156,12 +1180,11 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(struct ion_handle_data))) return -EFAULT; - mutex_lock(&client->lock); - handle = ion_uhandle_get(client, data.handle); - mutex_unlock(&client->lock); - if (!handle) - return -EINVAL; + handle = ion_handle_get_by_id(client, data.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); ion_free(client, handle); + ion_handle_put(handle); break; } case ION_IOC_SHARE: @@ -1172,8 +1195,11 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - handle = ion_uhandle_get(client, data.handle); + handle = ion_handle_get_by_id(client, data.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); data.fd = ion_share_dma_buf_fd(client, handle); + ion_handle_put(handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; if (data.fd < 0) -- cgit v1.2.3 From a14baf71b91845a7f68438d48f462cb754699ae2 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:00 -0800 Subject: ion: fix crash when alloc len is -1 If userspace passes a length between -4095 and -1 to allocate it will pass the len != 0 check, but when len is page aligned it will be 0. Check len after page aligning. Drop the warning as well, userspace shouldn't be able to trigger a warning in the kernel. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index cf9fc7813004..2e7be70dd9c0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -485,11 +485,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, * request of the caller allocate from it. Repeat until allocate has * succeeded or all heaps have been tried */ - if (WARN_ON(!len)) - return ERR_PTR(-EINVAL); - len = PAGE_ALIGN(len); + if (!len) + return ERR_PTR(-EINVAL); + down_read(&dev->lock); plist_for_each_entry(heap, &dev->heaps, node) { /* if the caller didn't specify this heap id */ -- cgit v1.2.3 From e946b209c2ed15b1f7917def8fe6602747c3f771 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:01 -0800 Subject: ion: fix dma APIs __dma_page_cpu_to_dev is a private ARM api that is not available on 3.10 and was never available on other architectures. We can get the same behavior by calling dma_sync_sg_for_device with a scatterlist containing a single page. It's still not quite a kosher use of the dma apis, we still conflate physical addresses with bus addresses, but it should at least compile on all platforms, and work on any platform that doesn't have a physical to bus address translation. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 20 +++++++++++++++++++- drivers/staging/android/ion/ion_chunk_heap.c | 15 +++++++-------- drivers/staging/android/ion/ion_page_pool.c | 9 ++------- drivers/staging/android/ion/ion_priv.h | 12 ++++++++++++ drivers/staging/android/ion/ion_system_heap.c | 5 ++--- 5 files changed, 42 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 2e7be70dd9c0..4bdbdece3f30 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -840,6 +840,22 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, { } +void ion_pages_sync_for_device(struct device *dev, struct page *page, + size_t size, enum dma_data_direction dir) +{ + struct scatterlist sg; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + /* + * This is not correct - sg_dma_address needs a dma_addr_t that is valid + * for the the targeted device, but this works on the currently targeted + * hardware. + */ + sg_dma_address(&sg) = page_to_phys(page); + dma_sync_sg_for_device(dev, &sg, 1, dir); +} + struct ion_vma_list { struct list_head list; struct vm_area_struct *vma; @@ -864,7 +880,9 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, struct page *page = buffer->pages[i]; if (ion_buffer_page_is_dirty(page)) - __dma_page_cpu_to_dev(page, 0, PAGE_SIZE, dir); + ion_pages_sync_for_device(dev, ion_buffer_page(page), + PAGE_SIZE, dir); + ion_buffer_page_clean(buffer->pages + i); } list_for_each_entry(vma_list, &buffer->vmas, list) { diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 85fefe778845..2fddc041ac13 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -106,11 +106,11 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) ion_heap_buffer_zero(buffer); + if (ion_buffer_cached(buffer)) + dma_sync_sg_for_device(NULL, table->sgl, table->nents, + DMA_BIDIRECTIONAL); + for_each_sg(table->sgl, sg, table->nents, i) { - if (ion_buffer_cached(buffer)) - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(sg_page(sg))), - sg_dma_len(sg), DMA_BIDIRECTIONAL); gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), sg_dma_len(sg)); } @@ -148,7 +148,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); int i, ret; - chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL); if (!chunk_heap) return ERR_PTR(-ENOMEM); @@ -181,9 +180,9 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) } free_vm_area(vm_struct); - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(phys_to_page(heap_data->base))), - heap_data->size, DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(NULL, pfn_to_page(PFN_DOWN(heap_data->base)), + heap_data->size, DMA_BIDIRECTIONAL); + gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 855f30c3967a..979d2e4a6b12 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -34,13 +34,8 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) if (!page) return NULL; - /* this is only being used to flush the page for dma, - this api is not really suitable for calling from a driver - but no better way to flush a page for dma exist at this time */ - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(page)), - PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); return page; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index f2635631e9be..d1fa7719b240 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -17,6 +17,7 @@ #ifndef _ION_PRIV_H #define _ION_PRIV_H +#include #include #include #include @@ -357,4 +358,15 @@ void ion_page_pool_free(struct ion_page_pool *, struct page *); int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan); +/** + * ion_pages_sync_for_device - cache flush pages for use with the specified + * device + * @dev: the device the pages will be used with + * @page: the first page to be flushed + * @size: size in bytes of region to be flushed + * @dir: direction of dma transfer + */ +void ion_pages_sync_for_device(struct device *dev, struct page *page, + size_t size, enum dma_data_direction dir); + #endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index b9b10365f450..792cade3e404 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -77,9 +77,8 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, page = ion_heap_alloc_pages(buffer, gfp_flags, order); if (!page) return 0; - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(page)), - PAGE_SIZE << order, DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, + DMA_BIDIRECTIONAL); } if (!page) return 0; -- cgit v1.2.3 From 06e0dcaeb4fd72a010a1f5ad0c03abd8e0a58ef9 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:02 -0800 Subject: ion: convert sg_dma_len(sg) to sg->length ion is always dealing with the allocation and not the mapping, so it should always be using sg->length and not sg->dma_length. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- drivers/staging/android/ion/ion_chunk_heap.c | 4 ++-- drivers/staging/android/ion/ion_heap.c | 12 ++++++------ drivers/staging/android/ion/ion_system_heap.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 4bdbdece3f30..8d568caa0f33 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -224,7 +224,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); - for (j = 0; j < sg_dma_len(sg) / PAGE_SIZE; j++) + for (j = 0; j < sg->length / PAGE_SIZE; j++) buffer->pages[k++] = page++; } diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 2fddc041ac13..62f7439e02b1 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -84,7 +84,7 @@ err: sg = table->sgl; for (i -= 1; i >= 0; i--) { gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), - sg_dma_len(sg)); + sg->length); sg = sg_next(sg); } sg_free_table(table); @@ -112,7 +112,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) for_each_sg(table->sgl, sg, table->nents, i) { gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), - sg_dma_len(sg)); + sg->length); } chunk_heap->allocated -= allocated_size; sg_free_table(table); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index a584ec036862..a5a7c572ad2a 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -46,7 +46,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, pgprot = pgprot_writecombine(PAGE_KERNEL); for_each_sg(table->sgl, sg, table->nents, i) { - int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; + int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; struct page *page = sg_page(sg); BUG_ON(i >= npages); for (j = 0; j < npages_this_entry; j++) { @@ -80,14 +80,14 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); unsigned long remainder = vma->vm_end - addr; - unsigned long len = sg_dma_len(sg); + unsigned long len = sg->length; - if (offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); + if (offset >= sg->length) { + offset -= sg->length; continue; } else if (offset) { page += offset / PAGE_SIZE; - len = sg_dma_len(sg) - offset; + len = sg->length - offset; offset = 0; } len = min(len, remainder); @@ -119,7 +119,7 @@ int ion_heap_buffer_zero(struct ion_buffer *buffer) for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); - unsigned long len = sg_dma_len(sg); + unsigned long len = sg->length; for (j = 0; j < len / PAGE_SIZE; j++) { struct page *sub_page = page + j; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 792cade3e404..967eedc3af84 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -209,7 +209,7 @@ void ion_system_heap_free(struct ion_buffer *buffer) for_each_sg(table->sgl, sg, table->nents, i) free_buffer_page(sys_heap, buffer, sg_page(sg), - get_order(sg_dma_len(sg))); + get_order(sg->length)); sg_free_table(table); kfree(table); } -- cgit v1.2.3 From c13d1df947f1c312143eda77a754149d0043e4d3 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:03 -0800 Subject: ion: check invalid values in ion_system_heap ion_system_heap can only satisfy page alignment, and ion_system_contig_heap can only satisify alignment to the allocation size. Neither can support faulting user mappings because they use slab pages. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 967eedc3af84..62a07ec7d5bf 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -150,6 +150,12 @@ static int ion_system_heap_allocate(struct ion_heap *heap, long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; + if (align > PAGE_SIZE) + return -EINVAL; + + if (ion_buffer_fault_user_mappings(buffer)) + return -EINVAL; + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); @@ -362,6 +368,14 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, unsigned long align, unsigned long flags) { + int order = get_order(len); + + if (align > (PAGE_SIZE << order)) + return -EINVAL; + + if (ion_buffer_fault_user_mappings(buffer)) + return -EINVAL; + buffer->priv_virt = kzalloc(len, GFP_KERNEL); if (!buffer->priv_virt) return -ENOMEM; -- cgit v1.2.3 From ceff95d49cc3e28c06c2352e8d94f56046271aeb Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:04 -0800 Subject: ion: add test device for unit tests to interact with dma_bufs Add a /dev/ion-test device that will be created if CONFIG_ION_TEST is set. The device accepts a dma_buf fd and allows reading and writing to the backing memory using DMA-like apis or kernel mapping apis. Can be used to test the dma_buf mapping ops, including the ion implementations, from userspace. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 7 + drivers/staging/android/ion/Makefile | 1 + drivers/staging/android/ion/ion_test.c | 281 ++++++++++++++++++++++++++++++++ drivers/staging/android/uapi/ion_test.h | 71 ++++++++ 4 files changed, 360 insertions(+) create mode 100644 drivers/staging/android/ion/ion_test.c create mode 100644 drivers/staging/android/uapi/ion_test.h (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index c62f2cbb9e89..6a5d8cfe7935 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -6,6 +6,13 @@ menuconfig ION help Chose this option to enable the ION Memory Manager. +config ION_TEST + tristate "Ion Test Device" + depends on ION + help + Choose this option to create a device that can be used to test the + kernel and device side ION functions. + config ION_TEGRA tristate "Ion for Tegra" depends on ARCH_TEGRA && ION diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 9c956659124b..75039b98eebb 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o +obj-$(CONFIG_ION_TEST) += ion_test.o ifdef CONFIG_COMPAT obj-$(CONFIG_ION) += compat_ion.o endif diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c new file mode 100644 index 000000000000..3e20349baf7c --- /dev/null +++ b/drivers/staging/android/ion/ion_test.c @@ -0,0 +1,281 @@ +/* + * + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#define pr_fmt(fmt) "ion-test: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ion.h" +#include "../uapi/ion_test.h" + +#define u64_to_uptr(x) ((void __user *)(unsigned long)(x)) + +struct ion_test_device { + struct miscdevice misc; +}; + +struct ion_test_data { + struct dma_buf *dma_buf; + struct device *dev; +}; + +static int ion_handle_test_dma(struct device *dev, struct dma_buf *dma_buf, + void __user *ptr, size_t offset, size_t size, bool write) +{ + int ret = 0; + struct dma_buf_attachment *attach; + struct sg_table *table; + pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); + enum dma_data_direction dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + struct sg_page_iter sg_iter; + unsigned long offset_page; + + attach = dma_buf_attach(dma_buf, dev); + if (IS_ERR(attach)) + return PTR_ERR(attach); + + table = dma_buf_map_attachment(attach, dir); + if (IS_ERR(table)) + return PTR_ERR(table); + + offset_page = offset >> PAGE_SHIFT; + offset %= PAGE_SIZE; + + for_each_sg_page(table->sgl, &sg_iter, table->nents, offset_page) { + struct page *page = sg_page_iter_page(&sg_iter); + void *vaddr = vmap(&page, 1, VM_MAP, pgprot); + size_t to_copy = PAGE_SIZE - offset; + + to_copy = min(to_copy, size); + if (!vaddr) { + ret = -ENOMEM; + goto err; + } + + if (write) + ret = copy_from_user(vaddr + offset, ptr, to_copy); + else + ret = copy_to_user(ptr, vaddr + offset, to_copy); + + vunmap(vaddr); + if (ret) { + ret = -EFAULT; + goto err; + } + size -= to_copy; + if (!size) + break; + ptr += to_copy; + offset = 0; + } + +err: + dma_buf_unmap_attachment(attach, table, dir); + dma_buf_detach(dma_buf, attach); + return ret; +} + +static int ion_handle_test_kernel(struct dma_buf *dma_buf, void __user *ptr, + size_t offset, size_t size, bool write) +{ + int ret; + unsigned long page_offset = offset >> PAGE_SHIFT; + size_t copy_offset = offset % PAGE_SIZE; + size_t copy_size = size; + enum dma_data_direction dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + if (offset > dma_buf->size || size > dma_buf->size - offset) + return -EINVAL; + + ret = dma_buf_begin_cpu_access(dma_buf, offset, size, dir); + if (ret) + return ret; + + while (copy_size > 0) { + size_t to_copy; + void *vaddr = dma_buf_kmap(dma_buf, page_offset); + + if (!vaddr) + goto err; + + to_copy = min_t(size_t, PAGE_SIZE - copy_offset, copy_size); + + if (write) + ret = copy_from_user(vaddr + copy_offset, ptr, to_copy); + else + ret = copy_to_user(ptr, vaddr + copy_offset, to_copy); + + dma_buf_kunmap(dma_buf, page_offset, vaddr); + if (ret) { + ret = -EFAULT; + goto err; + } + + copy_size -= to_copy; + ptr += to_copy; + page_offset++; + copy_offset = 0; + } +err: + dma_buf_end_cpu_access(dma_buf, offset, size, dir); + return ret; +} + +static long ion_test_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct ion_test_data *test_data = filp->private_data; + int ret = 0; + + union { + struct ion_test_rw_data test_rw; + } data; + + if (_IOC_SIZE(cmd) > sizeof(data)) + return -EINVAL; + + if (_IOC_DIR(cmd) & _IOC_WRITE) + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + + switch (cmd) { + case ION_IOC_TEST_SET_FD: + { + struct dma_buf *dma_buf = NULL; + int fd = arg; + + if (fd >= 0) { + dma_buf = dma_buf_get((int)arg); + if (IS_ERR(dma_buf)) + return PTR_ERR(dma_buf); + } + if (test_data->dma_buf) + dma_buf_put(test_data->dma_buf); + test_data->dma_buf = dma_buf; + break; + } + case ION_IOC_TEST_DMA_MAPPING: + { + ret = ion_handle_test_dma(test_data->dev, test_data->dma_buf, + u64_to_uptr(data.test_rw.ptr), + data.test_rw.offset, data.test_rw.size, + data.test_rw.write); + break; + } + case ION_IOC_TEST_KERNEL_MAPPING: + { + ret = ion_handle_test_kernel(test_data->dma_buf, + u64_to_uptr(data.test_rw.ptr), + data.test_rw.offset, data.test_rw.size, + data.test_rw.write); + break; + } + default: + return -ENOTTY; + } + + if (_IOC_DIR(cmd) & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, sizeof(data))) + return -EFAULT; + } + return ret; +} + +static int ion_test_open(struct inode *inode, struct file *file) +{ + struct ion_test_data *data; + struct miscdevice *miscdev = file->private_data; + + data = kzalloc(sizeof(struct ion_test_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->dev = miscdev->parent; + + file->private_data = data; + + return 0; +} + +static int ion_test_release(struct inode *inode, struct file *file) +{ + struct ion_test_data *data = file->private_data; + + kfree(data); + + return 0; +} + +static const struct file_operations ion_test_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = ion_test_ioctl, + .open = ion_test_open, + .release = ion_test_release, +}; + +static int __init ion_test_probe(struct platform_device *pdev) +{ + int ret; + struct ion_test_device *testdev; + + testdev = devm_kzalloc(&pdev->dev, sizeof(struct ion_test_device), + GFP_KERNEL); + if (!testdev) + return -ENOMEM; + + testdev->misc.minor = MISC_DYNAMIC_MINOR; + testdev->misc.name = "ion-test"; + testdev->misc.fops = &ion_test_fops; + testdev->misc.parent = &pdev->dev; + ret = misc_register(&testdev->misc); + if (ret) { + pr_err("failed to register misc device.\n"); + return ret; + } + + platform_set_drvdata(pdev, testdev); + + return 0; +} + +static struct platform_driver ion_test_platform_driver = { + .driver = { + .name = "ion-test", + }, +}; + +static int __init ion_test_init(void) +{ + platform_device_register_simple("ion-test", -1, NULL, 0); + return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); +} + +static void __exit ion_test_exit(void) +{ + platform_driver_unregister(&ion_test_platform_driver); +} + +module_init(ion_test_init); +module_exit(ion_test_exit); diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h new file mode 100644 index 000000000000..352379a02690 --- /dev/null +++ b/drivers/staging/android/uapi/ion_test.h @@ -0,0 +1,71 @@ +/* + * drivers/staging/android/uapi/ion.h + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * 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. + * + */ + +#ifndef _UAPI_LINUX_ION_TEST_H +#define _UAPI_LINUX_ION_TEST_H + +#include +#include + +typedef int ion_user_handle_t; + +/** + * struct ion_test_rw_data - metadata passed to the kernel to read handle + * @ptr: a pointer to an area at least as large as size + * @offset: offset into the ion buffer to start reading + * @size: size to read or write + * @write: 1 to write, 0 to read + */ +struct ion_test_rw_data { + __u64 ptr; + __u64 offset; + __u64 size; + int write; +}; + +#define ION_IOC_MAGIC 'I' + +/** + * DOC: ION_IOC_TEST_SET_DMA_BUF - attach a dma buf to the test driver + * + * Attaches a dma buf fd to the test driver. Passing a second fd or -1 will + * release the first fd. + */ +#define ION_IOC_TEST_SET_FD \ + _IO(ION_IOC_MAGIC, 0xf0) + +/** + * DOC: ION_IOC_TEST_DMA_MAPPING - read or write memory from a handle as DMA + * + * Reads or writes the memory from a handle using an uncached mapping. Can be + * used by unit tests to emulate a DMA engine as close as possible. Only + * expected to be used for debugging and testing, may not always be available. + */ +#define ION_IOC_TEST_DMA_MAPPING \ + _IOW(ION_IOC_MAGIC, 0xf1, struct ion_test_rw_data) + +/** + * DOC: ION_IOC_TEST_KERNEL_MAPPING - read or write memory from a handle + * + * Reads or writes the memory from a handle using a kernel mapping. Can be + * used by unit tests to test heap map_kernel functions. Only expected to be + * used for debugging and testing, may not always be available. + */ +#define ION_IOC_TEST_KERNEL_MAPPING \ + _IOW(ION_IOC_MAGIC, 0xf2, struct ion_test_rw_data) + + +#endif /* _UAPI_LINUX_ION_H */ -- cgit v1.2.3 From b26661d1f6a1f94c11a12fef85cd2e942888310e Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:05 -0800 Subject: ion: update idr to avoid deprecated apis Use idr_alloc instead if idr_pre_get/idr_get_new_above, and remove idr_remove_all. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 8d568caa0f33..199ab9ae0dca 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -432,22 +432,16 @@ static bool ion_handle_validate(struct ion_client *client, struct ion_handle *ha static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) { - int rc; + int id; struct rb_node **p = &client->handles.rb_node; struct rb_node *parent = NULL; struct ion_handle *entry; - do { - int id; - rc = idr_pre_get(&client->idr, GFP_KERNEL); - if (!rc) - return -ENOMEM; - rc = idr_get_new_above(&client->idr, handle, 1, &id); - handle->id = id; - } while (rc == -EAGAIN); + id = idr_alloc(&client->idr, handle, 1, 0, GFP_KERNEL); + if (id < 0) + return id; - if (rc < 0) - return rc; + handle->id = id; while (*p) { parent = *p; @@ -786,7 +780,6 @@ void ion_client_destroy(struct ion_client *client) ion_handle_destroy(&handle->ref); } - idr_remove_all(&client->idr); idr_destroy(&client->idr); down_write(&dev->lock); -- cgit v1.2.3 From 8be3759a5e4ed91ffbe24d98b33a71f651cb3f9b Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 14:25:06 -0800 Subject: ion: don't use __arm_ioremap to map pages ion_heap_map_kernel already implements mapping a scatterlist of pages into the kernel, and all heaps are required to have struct pages associated with them, so delete the functions that use __arm_ioremap and use ion_heap_map_kernel instead. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 42 ++----------------------- drivers/staging/android/ion/ion_chunk_heap.c | 2 -- 2 files changed, 3 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 36df34c1ed53..051363a442dc 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -25,8 +25,6 @@ #include "ion.h" #include "ion_priv.h" -#include - struct ion_carveout_heap { struct ion_heap heap; struct gen_pool *pool; @@ -109,49 +107,15 @@ void ion_carveout_heap_unmap_dma(struct ion_heap *heap, sg_free_table(buffer->sg_table); } -void *ion_carveout_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - void *ret; - int mtype = MT_MEMORY_NONCACHED; - - if (buffer->flags & ION_FLAG_CACHED) - mtype = MT_MEMORY; - - ret = __arm_ioremap(buffer->priv_phys, buffer->size, - mtype); - if (ret == NULL) - return ERR_PTR(-ENOMEM); - - return ret; -} - -void ion_carveout_heap_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - __arm_iounmap(buffer->vaddr); - buffer->vaddr = NULL; - return; -} - -int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - return remap_pfn_range(vma, vma->vm_start, - __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - pgprot_noncached(vma->vm_page_prot)); -} - static struct ion_heap_ops carveout_heap_ops = { .allocate = ion_carveout_heap_allocate, .free = ion_carveout_heap_free, .phys = ion_carveout_heap_phys, .map_dma = ion_carveout_heap_map_dma, .unmap_dma = ion_carveout_heap_unmap_dma, - .map_user = ion_carveout_heap_map_user, - .map_kernel = ion_carveout_heap_map_kernel, - .unmap_kernel = ion_carveout_heap_unmap_kernel, + .map_user = ion_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, }; struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 62f7439e02b1..d3363d6088db 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -25,8 +25,6 @@ #include "ion.h" #include "ion_priv.h" -#include - struct ion_chunk_heap { struct ion_heap heap; struct gen_pool *pool; -- cgit v1.2.3 From 1d804535c37cb669334781afdbc2987284621623 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:13 -0800 Subject: ion: don't use phys_to_page or __phys_to_pfn phys_to_page and __phys_to_pfn don't exist on all platforms. Use a combination of pfn_to_page, PFN_DOWN, page_to_pfn, and virt_to_page to get the same results. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 4 ++-- drivers/staging/android/ion/ion_chunk_heap.c | 5 +++-- drivers/staging/android/ion/ion_system_heap.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 051363a442dc..1d53e9120b90 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -96,8 +96,8 @@ struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, kfree(table); return ERR_PTR(ret); } - sg_set_page(table->sgl, phys_to_page(buffer->priv_phys), buffer->size, - 0); + sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->priv_phys)), + buffer->size, 0); return table; } diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index d3363d6088db..fb1a7b9bf752 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -71,7 +71,8 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, chunk_heap->chunk_size); if (!paddr) goto err; - sg_set_page(sg, phys_to_page(paddr), chunk_heap->chunk_size, 0); + sg_set_page(sg, pfn_to_page(PFN_DOWN(paddr)), + chunk_heap->chunk_size, 0); sg = sg_next(sg); } @@ -167,7 +168,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) goto error; } for (i = 0; i < chunk_heap->size; i += PAGE_SIZE) { - struct page *page = phys_to_page(chunk_heap->base + i); + struct page *page = pfn_to_page(PFN_DOWN(chunk_heap->base + i)); struct page **pages = &page; ret = map_vm_area(vm_struct, pgprot, &pages); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 62a07ec7d5bf..3b2f420b945d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -426,7 +426,7 @@ int ion_system_contig_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, struct vm_area_struct *vma) { - unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt)); + unsigned long pfn = page_to_pfn(virt_to_page(buffer->priv_virt)); return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); -- cgit v1.2.3 From e61fc915fa8c6991f0ed14ce70a0a3c139012684 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:14 -0800 Subject: ion: fix printk warnings Use %z for size_t and %pa for dma_addr_t to avoid warnings in printks. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 23 ++++++++++++----------- drivers/staging/android/ion/ion_chunk_heap.c | 2 +- drivers/staging/android/ion/ion_cma_heap.c | 4 ++-- drivers/staging/android/ion/ion_heap.c | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 199ab9ae0dca..57698e6e4ae6 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -471,7 +471,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, struct ion_heap *heap; int ret; - pr_debug("%s: len %d align %d heap_id_mask %u flags %x\n", __func__, + pr_debug("%s: len %zu align %zu heap_id_mask %u flags %x\n", __func__, len, align, heap_id_mask, flags); /* * traverse the list of heaps available in this system in priority @@ -688,7 +688,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) for (i = 0; i < ION_NUM_HEAP_IDS; i++) { if (!names[i]) continue; - seq_printf(s, "%16.16s: %16u\n", names[i], sizes[i]); + seq_printf(s, "%16.16s: %16zu\n", names[i], sizes[i]); } return 0; } @@ -1336,10 +1336,10 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) char task_comm[TASK_COMM_LEN]; get_task_comm(task_comm, client->task); - seq_printf(s, "%16.s %16u %16u\n", task_comm, + seq_printf(s, "%16.s %16u %16zu\n", task_comm, client->pid, size); } else { - seq_printf(s, "%16.s %16u %16u\n", client->name, + seq_printf(s, "%16.s %16u %16zu\n", client->name, client->pid, size); } } @@ -1354,19 +1354,20 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) continue; total_size += buffer->size; if (!buffer->handle_count) { - seq_printf(s, "%16.s %16u %16u %d %d\n", buffer->task_comm, - buffer->pid, buffer->size, buffer->kmap_cnt, + seq_printf(s, "%16.s %16u %16zu %d %d\n", + buffer->task_comm, buffer->pid, + buffer->size, buffer->kmap_cnt, atomic_read(&buffer->ref.refcount)); total_orphaned_size += buffer->size; } } mutex_unlock(&dev->buffer_lock); seq_printf(s, "----------------------------------------------------\n"); - seq_printf(s, "%16.s %16u\n", "total orphaned", + seq_printf(s, "%16.s %16zu\n", "total orphaned", total_orphaned_size); - seq_printf(s, "%16.s %16u\n", "total ", total_size); + seq_printf(s, "%16.s %16zu\n", "total ", total_size); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) - seq_printf(s, "%16.s %16u\n", "deferred free", + seq_printf(s, "%16.s %16zu\n", "deferred free", heap->free_list_size); seq_printf(s, "----------------------------------------------------\n"); @@ -1522,11 +1523,11 @@ void __init ion_reserve(struct ion_platform_data *data) int ret = memblock_reserve(data->heaps[i].base, data->heaps[i].size); if (ret) - pr_err("memblock reserve of %x@%lx failed\n", + pr_err("memblock reserve of %zx@%lx failed\n", data->heaps[i].size, data->heaps[i].base); } - pr_info("%s: %s reserved base %lx size %d\n", __func__, + pr_info("%s: %s reserved base %lx size %zu\n", __func__, data->heaps[i].name, data->heaps[i].base, data->heaps[i].size); diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index fb1a7b9bf752..4eacf52c031c 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -186,7 +186,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - pr_info("%s: base %lu size %u align %ld\n", __func__, chunk_heap->base, + pr_info("%s: base %lu size %zu align %ld\n", __func__, chunk_heap->base, heap_data->size, heap_data->align); return &chunk_heap->heap; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 86b6cf5da824..1e308a092fe6 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -128,8 +128,8 @@ static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info = buffer->priv_virt; - dev_dbg(dev, "Return buffer %p physical address 0x%x\n", buffer, - info->handle); + dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer, + &info->handle); *addr = info->handle; *len = buffer->size; diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index a5a7c572ad2a..deaab7cd8116 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -281,7 +281,7 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) } if (IS_ERR_OR_NULL(heap)) { - pr_err("%s: error creating heap %s type %d base %lu size %u\n", + pr_err("%s: error creating heap %s type %d base %lu size %zu\n", __func__, heap_data->name, heap_data->type, heap_data->base, heap_data->size); return ERR_PTR(-EINVAL); -- cgit v1.2.3 From a82130f470893c4a5be3e3cfcdc72c427a41b630 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:15 -0800 Subject: gpu: ion: remove unnecessary function from system heap ion_system_contig_heap buffers have an sglist, just call ion_heap_map_user to map it. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 3b2f420b945d..9250ee51171d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -422,17 +422,6 @@ void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, kfree(buffer->sg_table); } -int ion_system_contig_heap_map_user(struct ion_heap *heap, - struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - unsigned long pfn = page_to_pfn(virt_to_page(buffer->priv_virt)); - return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - -} - static struct ion_heap_ops kmalloc_ops = { .allocate = ion_system_contig_heap_allocate, .free = ion_system_contig_heap_free, @@ -441,7 +430,7 @@ static struct ion_heap_ops kmalloc_ops = { .unmap_dma = ion_system_contig_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, - .map_user = ion_system_contig_heap_map_user, + .map_user = ion_heap_map_user, }; struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused) -- cgit v1.2.3 From db866e3ded294aac1059d45d6497cf1bdbebaa04 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:16 -0800 Subject: ion: clean up ioctls Convert the ion ioctls to use _IOW instead of _IOWR where appropriate, and factor out the copy_from_user and copy_to_user based on the _IOC_DIR bits. For the existing incorrect ioctls, add a function to wrap _IOC_DIR to return the corrected value. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 110 ++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 57698e6e4ae6..fc77aa638a9e 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1157,41 +1157,65 @@ static int ion_sync_for_device(struct ion_client *client, int fd) return 0; } +/* fix up the cases where the ioctl direction bits are incorrect */ +static unsigned int ion_ioctl_dir(unsigned int cmd) +{ + switch (cmd) { + case ION_IOC_SYNC: + case ION_IOC_FREE: + case ION_IOC_CUSTOM: + return _IOC_WRITE; + default: + return _IOC_DIR(cmd); + } +} + static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_client *client = filp->private_data; + struct ion_device *dev = client->dev; + struct ion_handle *cleanup_handle = NULL; + int ret = 0; + unsigned int dir; + + union { + struct ion_fd_data fd; + struct ion_allocation_data allocation; + struct ion_handle_data handle; + struct ion_custom_data custom; + } data; + + dir = ion_ioctl_dir(cmd); + + if (_IOC_SIZE(cmd) > sizeof(data)) + return -EINVAL; + + if (dir & _IOC_WRITE) + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; switch (cmd) { case ION_IOC_ALLOC: { - struct ion_allocation_data data; struct ion_handle *handle; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; - handle = ion_alloc(client, data.len, data.align, - data.heap_id_mask, data.flags); - + handle = ion_alloc(client, data.allocation.len, + data.allocation.align, + data.allocation.heap_id_mask, + data.allocation.flags); if (IS_ERR(handle)) return PTR_ERR(handle); - data.handle = handle->id; + data.allocation.handle = handle->id; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - ion_free(client, handle); - return -EFAULT; - } + cleanup_handle = handle; break; } case ION_IOC_FREE: { - struct ion_handle_data data; struct ion_handle *handle; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_handle_data))) - return -EFAULT; - handle = ion_handle_get_by_id(client, data.handle); + handle = ion_handle_get_by_id(client, data.handle.handle); if (IS_ERR(handle)) return PTR_ERR(handle); ion_free(client, handle); @@ -1201,68 +1225,52 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case ION_IOC_SHARE: case ION_IOC_MAP: { - struct ion_fd_data data; struct ion_handle *handle; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; - handle = ion_handle_get_by_id(client, data.handle); + handle = ion_handle_get_by_id(client, data.handle.handle); if (IS_ERR(handle)) return PTR_ERR(handle); - data.fd = ion_share_dma_buf_fd(client, handle); + data.fd.fd = ion_share_dma_buf_fd(client, handle); ion_handle_put(handle); - if (copy_to_user((void __user *)arg, &data, sizeof(data))) - return -EFAULT; - if (data.fd < 0) - return data.fd; + if (data.fd.fd < 0) + ret = data.fd.fd; break; } case ION_IOC_IMPORT: { - struct ion_fd_data data; struct ion_handle *handle; - int ret = 0; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_fd_data))) - return -EFAULT; - handle = ion_import_dma_buf(client, data.fd); + handle = ion_import_dma_buf(client, data.fd.fd); if (IS_ERR(handle)) ret = PTR_ERR(handle); else - data.handle = handle->id; - - if (copy_to_user((void __user *)arg, &data, - sizeof(struct ion_fd_data))) - return -EFAULT; - if (ret < 0) - return ret; + data.handle.handle = handle->id; break; } case ION_IOC_SYNC: { - struct ion_fd_data data; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_fd_data))) - return -EFAULT; - ion_sync_for_device(client, data.fd); + ret = ion_sync_for_device(client, data.fd.fd); break; } case ION_IOC_CUSTOM: { - struct ion_device *dev = client->dev; - struct ion_custom_data data; - if (!dev->custom_ioctl) return -ENOTTY; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_custom_data))) - return -EFAULT; - return dev->custom_ioctl(client, data.cmd, data.arg); + ret = dev->custom_ioctl(client, data.custom.cmd, + data.custom.arg); + break; } default: return -ENOTTY; } - return 0; + + if (dir & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { + if (cleanup_handle) + ion_free(client, cleanup_handle); + return -EFAULT; + } + } + return ret; } static int ion_release(struct inode *inode, struct file *file) -- cgit v1.2.3 From f020b4430bf29a25229fd9975662baefb02facda Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Fri, 13 Dec 2013 19:26:17 -0800 Subject: gpu: ion: fix use-after-free in ion_heap_freelist_drain The `buffer' variable is being used after being freed. Fix this. Signed-off-by: Mitchel Humpherys Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index deaab7cd8116..0a5cea0c01e3 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -200,9 +200,9 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) if (total_drained >= size) break; list_del(&buffer->list); - ion_buffer_destroy(buffer); heap->free_list_size -= buffer->size; total_drained += buffer->size; + ion_buffer_destroy(buffer); } rt_mutex_unlock(&heap->lock); -- cgit v1.2.3 From ea725ec8b1d2a5f6a46dd45174fcd6a5f8c9dd5b Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Dec 2013 19:26:18 -0800 Subject: ion: Fix two small issues in system_heap allocation In testing ion system heap allocations, I ran across two issues: 1) Not k*z*allocing the sg table. This can cause trouble if we end up trying call sg_alloc_table() with too many entries, then sg_alloc_table() internally fails and tries to free what it thinks is internal table structure, which causes bad pointer traversals. 2) The second list_for_each_entry probably should be _safe, since I was seeing strange lock warnings and oopses on occasion. This seems to resolve it, but could use some extra checking. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 9250ee51171d..bec9d4585e62 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -166,8 +166,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, max_order = info->order; i++; } - - table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) goto err; @@ -189,7 +188,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, err1: kfree(table); err: - list_for_each_entry(info, &pages, list) { + list_for_each_entry_safe(info, tmp_info, &pages, list) { free_buffer_page(sys_heap, buffer, info->page, info->order); kfree(info); } -- cgit v1.2.3 From 797e88be2f3e928fe5d8498f42a65a6e77b09c29 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:19 -0800 Subject: ion: drop dependency on ARM Ion will compile and run on other platforms now, remove the dependency on ARM. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 6a5d8cfe7935..3215bd8fb458 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,6 +1,5 @@ menuconfig ION tristate "Ion Memory Manager" - depends on ARM select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER help -- cgit v1.2.3 From f0f06763820e5b5f6e13afa814e68e8f4d955c45 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:20 -0800 Subject: ion: add alignment check to carveout heap Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 1d53e9120b90..b0b08c30f6f0 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -70,6 +70,9 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, unsigned long size, unsigned long align, unsigned long flags) { + if (align > PAGE_SIZE) + return -EINVAL; + buffer->priv_phys = ion_carveout_allocate(heap, size, align); return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; } -- cgit v1.2.3 From 8b312bb9a795c9c07661aee7b694cbfd3217e25c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:21 -0800 Subject: ion: optimize ion_heap_buffer_zero ion_heap_buffer_zero can spend a long time in unmap_kernel_range if it has to broadcast a tlb flush to every cpu for every page. Modify it to batch pages into a larger region to clear using a single mapping. This may cause the mapping size to change if the buffer size is not a multiple of the mapping size, so switch to allocating the address space for each chunk. This allows us to use vm_map_ram to handle the allocation and mapping together. The number of pages to zero using a single mapping is set to 32 to hit the fastpath in vm_map_ram. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 36 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 0a5cea0c01e3..ce3156163704 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -100,40 +100,48 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } +static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) +{ + void *addr = vm_map_ram(pages, num, -1, pgprot); + if (!addr) + return -ENOMEM; + memset(addr, 0, PAGE_SIZE * num); + vm_unmap_ram(addr, num); + + return 0; +} + int ion_heap_buffer_zero(struct ion_buffer *buffer) { struct sg_table *table = buffer->sg_table; pgprot_t pgprot; struct scatterlist *sg; - struct vm_struct *vm_struct; int i, j, ret = 0; + struct page *pages[32]; + int k = 0; if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; else pgprot = pgprot_writecombine(PAGE_KERNEL); - vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC); - if (!vm_struct) - return -ENOMEM; - for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); unsigned long len = sg->length; for (j = 0; j < len / PAGE_SIZE; j++) { - struct page *sub_page = page + j; - struct page **pages = &sub_page; - ret = map_vm_area(vm_struct, pgprot, &pages); - if (ret) - goto end; - memset(vm_struct->addr, 0, PAGE_SIZE); - unmap_kernel_range((unsigned long)vm_struct->addr, - PAGE_SIZE); + pages[k++] = page + j; + if (k == ARRAY_SIZE(pages)) { + ret = ion_heap_clear_pages(pages, k, pgprot); + if (ret) + goto end; + k = 0; + } } + if (k) + ret = ion_heap_clear_pages(pages, k, pgprot); } end: - free_vm_area(vm_struct); return ret; } -- cgit v1.2.3 From ce3d10933a3e2e1d2cb3b9ae91b6b945f189bb90 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:22 -0800 Subject: ion: free low memory from page pools first When the shrinkers are called with GFP_HIGH free low memory first, it is more important to have free than high memory. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 979d2e4a6b12..0ad026359cf8 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -143,10 +143,10 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, struct page *page; mutex_lock(&pool->mutex); - if (high && pool->high_count) { - page = ion_page_pool_remove(pool, true); - } else if (pool->low_count) { + if (pool->low_count) { page = ion_page_pool_remove(pool, false); + } else if (high && pool->high_count) { + page = ion_page_pool_remove(pool, true); } else { mutex_unlock(&pool->mutex); break; -- cgit v1.2.3 From e460bc5e43f0750c8bdb6967058ed4f18e92812c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:23 -0800 Subject: ion: check return value from remap_pfn_range Check the return value of remap_pfn_range and return an error if it fails. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index ce3156163704..ecc14fd9f6ac 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -76,6 +76,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long offset = vma->vm_pgoff * PAGE_SIZE; struct scatterlist *sg; int i; + int ret; for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); @@ -91,8 +92,10 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, offset = 0; } len = min(len, remainder); - remap_pfn_range(vma, addr, page_to_pfn(page), len, + ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, vma->vm_page_prot); + if (ret) + return ret; addr += len; if (addr >= vma->vm_end) return 0; -- cgit v1.2.3 From 462be0c616c297776556b24daa1511bcc0e0cd2c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:24 -0800 Subject: ion: use vm_insert_pfn for faulted pages Most ion userspace mappings are created with remap_pfn_range. Use vm_insert_pfn instead of vm_insert_page to make faulted cached mappings look more like uncached mappings. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index fc77aa638a9e..45127f5cd2f0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -890,14 +890,15 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct ion_buffer *buffer = vma->vm_private_data; + unsigned long pfn; int ret; mutex_lock(&buffer->lock); ion_buffer_page_dirty(buffer->pages + vmf->pgoff); - BUG_ON(!buffer->pages || !buffer->pages[vmf->pgoff]); - ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, - ion_buffer_page(buffer->pages[vmf->pgoff])); + + pfn = page_to_pfn(ion_buffer_page(buffer->pages[vmf->pgoff])); + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); mutex_unlock(&buffer->lock); if (ret) return VM_FAULT_ERROR; @@ -956,6 +957,8 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) } if (ion_buffer_fault_user_mappings(buffer)) { + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | + VM_DONTDUMP; vma->vm_private_data = buffer; vma->vm_ops = &ion_vma_ops; ion_vm_open(vma); -- cgit v1.2.3 From a3056906bfb98d10618122bc2ba7d142a61fcaf1 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:25 -0800 Subject: ion: remove ion_heap_alloc_pages Now that ion_vm_fault doesn't need a struct page with a nonzero refcount, there is no need allocate heap memory for cached pages using split_page. Remove the ion_heap_alloc_pages and ion_heap_free_pages helpers in favor of direct calls to alloc_pages and __free_pages, and remove the special handling in the system heap. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 27 --------------------------- drivers/staging/android/ion/ion_priv.h | 13 ------------- drivers/staging/android/ion/ion_system_heap.c | 7 +------ 3 files changed, 1 insertion(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index ecc14fd9f6ac..8054611e874a 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -148,33 +148,6 @@ end: return ret; } -struct page *ion_heap_alloc_pages(struct ion_buffer *buffer, gfp_t gfp_flags, - unsigned int order) -{ - struct page *page = alloc_pages(gfp_flags, order); - - if (!page) - return page; - - if (ion_buffer_fault_user_mappings(buffer)) - split_page(page, order); - - return page; -} - -void ion_heap_free_pages(struct ion_buffer *buffer, struct page *page, - unsigned int order) -{ - int i; - - if (!ion_buffer_fault_user_mappings(buffer)) { - __free_pages(page, order); - return; - } - for (i = 0; i < (1 << order); i++) - __free_page(page + i); -} - void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) { rt_mutex_lock(&heap->lock); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index d1fa7719b240..c9b507da7708 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -216,19 +216,6 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); int ion_heap_buffer_zero(struct ion_buffer *buffer); -/** - * ion_heap_alloc_pages - allocate pages from alloc_pages - * @buffer: the buffer to allocate for, used to extract the flags - * @gfp_flags: the gfp_t for the allocation - * @order: the order of the allocatoin - * - * This funciton allocations from alloc pages and also does any other - * necessary operations based on the buffer->flags. For buffers which - * will be faulted in the pages are split using split_page - */ -struct page *ion_heap_alloc_pages(struct ion_buffer *buffer, gfp_t gfp_flags, - unsigned int order); - /** * ion_heap_init_deferred_free -- initialize deferred free functionality * @heap: the heap diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index bec9d4585e62..a4bcf0923be7 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -74,7 +74,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (order > 4) gfp_flags = high_order_gfp_flags; - page = ion_heap_alloc_pages(buffer, gfp_flags, order); + page = alloc_pages(gfp_flags, order); if (!page) return 0; ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, @@ -91,15 +91,10 @@ static void free_buffer_page(struct ion_system_heap *heap, unsigned int order) { bool cached = ion_buffer_cached(buffer); - bool split_pages = ion_buffer_fault_user_mappings(buffer); - int i; if (!cached) { struct ion_page_pool *pool = heap->pools[order_to_index(order)]; ion_page_pool_free(pool, page); - } else if (split_pages) { - for (i = 0; i < (1 << order); i++) - __free_page(page + i); } else { __free_pages(page, order); } -- cgit v1.2.3 From a053b6ace160a7751fc53326bb354266e3e914f0 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:26 -0800 Subject: ion: allow cached mappings of chunk and system heap buffers Now that ion_vm_fault uses vm_insert_pfn instead of vm_insert_page cached buffers can be supported in any heap. Remove the checks in the chunk and system heaps. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 3 --- drivers/staging/android/ion/ion_system_heap.c | 3 --- 2 files changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 4eacf52c031c..34d1d18d4fc4 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -47,9 +47,6 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, unsigned long num_chunks; unsigned long allocated_size; - if (ion_buffer_fault_user_mappings(buffer)) - return -ENOMEM; - allocated_size = ALIGN(size, chunk_heap->chunk_size); num_chunks = allocated_size / chunk_heap->chunk_size; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index a4bcf0923be7..53afa33a4f6d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -148,9 +148,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, if (align > PAGE_SIZE) return -EINVAL; - if (ion_buffer_fault_user_mappings(buffer)) - return -EINVAL; - INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); -- cgit v1.2.3 From 5c6a470557e51bb4e868c22450811726c32f5787 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:27 -0800 Subject: ion: use alloc_pages in system contig heap There is no reason to use kzalloc, just call alloc_pages directly. Change the GFP from GFP_KERNEL to include __GFP_HIGH, to allow it to return contiguous pages from highmem. virt_to_* functions aren't valid on highmem pages, so store the struct page * in an sg_table in buffer->priv_virt like most other heaps, and replace virt_to_* with page_to_*. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 71 ++++++++++++++++++--------- 1 file changed, 48 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 53afa33a4f6d..841511df0f1c 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -360,29 +360,69 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, unsigned long flags) { int order = get_order(len); + struct page *page; + struct sg_table *table; + unsigned long i; + int ret; if (align > (PAGE_SIZE << order)) return -EINVAL; - if (ion_buffer_fault_user_mappings(buffer)) - return -EINVAL; - - buffer->priv_virt = kzalloc(len, GFP_KERNEL); - if (!buffer->priv_virt) + page = alloc_pages(low_order_gfp_flags, order); + if (!page) return -ENOMEM; + + split_page(page, order); + + len = PAGE_ALIGN(len); + for (i = len >> PAGE_SHIFT; i < (1 << order); i++) + __free_page(page + i); + + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) { + ret = -ENOMEM; + goto out; + } + + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) + goto out; + + sg_set_page(table->sgl, page, len, 0); + + buffer->priv_virt = table; + + ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL); + return 0; + +out: + for (i = 0; i < len >> PAGE_SHIFT; i++) + __free_page(page + i); + kfree(table); + return ret; } void ion_system_contig_heap_free(struct ion_buffer *buffer) { - kfree(buffer->priv_virt); + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; + unsigned long i; + + for (i = 0; i < pages; i++) + __free_page(page + i); + sg_free_table(table); + kfree(table); } static int ion_system_contig_heap_phys(struct ion_heap *heap, struct ion_buffer *buffer, ion_phys_addr_t *addr, size_t *len) { - *addr = virt_to_phys(buffer->priv_virt); + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + *addr = page_to_phys(page); *len = buffer->size; return 0; } @@ -390,27 +430,12 @@ static int ion_system_contig_heap_phys(struct ion_heap *heap, struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - struct sg_table *table; - int ret; - - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); - ret = sg_alloc_table(table, 1, GFP_KERNEL); - if (ret) { - kfree(table); - return ERR_PTR(ret); - } - sg_set_page(table->sgl, virt_to_page(buffer->priv_virt), buffer->size, - 0); - return table; + return buffer->priv_virt; } void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - sg_free_table(buffer->sg_table); - kfree(buffer->sg_table); } static struct ion_heap_ops kmalloc_ops = { -- cgit v1.2.3 From f63958d80c07c04db48812d97ff7450517d80ffa Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:28 -0800 Subject: ion: fix sparse warnings Fix sparse warnings in ion. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 8 +++---- drivers/staging/android/ion/ion_carveout_heap.c | 8 +++---- drivers/staging/android/ion/ion_chunk_heap.c | 8 +++---- drivers/staging/android/ion/ion_cma_heap.c | 15 +++++++------ drivers/staging/android/ion/ion_heap.c | 4 ++-- drivers/staging/android/ion/ion_page_pool.c | 2 +- drivers/staging/android/ion/ion_system_heap.c | 30 ++++++++++++------------- 7 files changed, 37 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 45127f5cd2f0..559e4ee6f7e5 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -669,7 +669,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) struct ion_client *client = s->private; struct rb_node *n; size_t sizes[ION_NUM_HEAP_IDS] = {0}; - const char *names[ION_NUM_HEAP_IDS] = {0}; + const char *names[ION_NUM_HEAP_IDS] = {NULL}; int i; mutex_lock(&client->lock); @@ -887,7 +887,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, mutex_unlock(&buffer->lock); } -int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +static int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct ion_buffer *buffer = vma->vm_private_data; unsigned long pfn; @@ -939,7 +939,7 @@ static void ion_vm_close(struct vm_area_struct *vma) mutex_unlock(&buffer->lock); } -struct vm_operations_struct ion_vma_ops = { +static struct vm_operations_struct ion_vma_ops = { .open = ion_vm_open, .close = ion_vm_close, .fault = ion_vm_fault, @@ -1030,7 +1030,7 @@ static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, mutex_unlock(&buffer->lock); } -struct dma_buf_ops dma_buf_ops = { +static struct dma_buf_ops dma_buf_ops = { .map_dma_buf = ion_map_dma_buf, .unmap_dma_buf = ion_unmap_dma_buf, .mmap = ion_mmap, diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index b0b08c30f6f0..9bf20a371f1a 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -85,8 +85,8 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; } -struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { struct sg_table *table; int ret; @@ -104,8 +104,8 @@ struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, return table; } -void ion_carveout_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { sg_free_table(buffer->sg_table); } diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 34d1d18d4fc4..46e8a3bf7a2f 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -115,14 +115,14 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) kfree(table); } -struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return buffer->priv_virt; } -void ion_chunk_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_chunk_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return; } diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 1e308a092fe6..3dcf9b47d5d5 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -44,8 +44,8 @@ struct ion_cma_buffer_info { * This function could be replaced by dma_common_get_sgtable * as soon as it will avalaible. */ -int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, - void *cpu_addr, dma_addr_t handle, size_t size) +static int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t handle, size_t size) { struct page *page = virt_to_page(cpu_addr); int ret; @@ -137,16 +137,16 @@ static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } -struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { struct ion_cma_buffer_info *info = buffer->priv_virt; return info->table; } -void ion_cma_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_cma_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return; } @@ -162,7 +162,8 @@ static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, buffer->size); } -void *ion_cma_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) +static void *ion_cma_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) { struct ion_cma_buffer_info *info = buffer->priv_virt; /* kernel memory mapping has been done at allocation time */ diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 8054611e874a..c3a213b6dcda 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -38,7 +38,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, struct page **tmp = pages; if (!pages) - return 0; + return NULL; if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; @@ -193,7 +193,7 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) return total_drained; } -int ion_heap_deferred_free(void *data) +static int ion_heap_deferred_free(void *data) { struct ion_heap *heap = data; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 0ad026359cf8..a1c51a839d66 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -134,7 +134,7 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int i; bool high; - high = gfp_mask & __GFP_HIGHMEM; + high = !!(gfp_mask & __GFP_HIGHMEM); if (nr_to_scan == 0) return ion_page_pool_total(pool, high); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 841511df0f1c..301d019a3270 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -26,11 +26,9 @@ #include "ion.h" #include "ion_priv.h" -static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY) & - ~__GFP_WAIT; -static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN); +static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | + __GFP_NORETRY) & ~__GFP_WAIT; +static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; static const int num_orders = ARRAY_SIZE(orders); static int order_to_index(unsigned int order) @@ -76,12 +74,12 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, gfp_flags = high_order_gfp_flags; page = alloc_pages(gfp_flags, order); if (!page) - return 0; + return NULL; ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, DMA_BIDIRECTIONAL); } if (!page) - return 0; + return NULL; return page; } @@ -187,7 +185,7 @@ err: return -ENOMEM; } -void ion_system_heap_free(struct ion_buffer *buffer) +static void ion_system_heap_free(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; struct ion_system_heap *sys_heap = container_of(heap, @@ -211,14 +209,14 @@ void ion_system_heap_free(struct ion_buffer *buffer) kfree(table); } -struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return buffer->priv_virt; } -void ion_system_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_system_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return; } @@ -403,7 +401,7 @@ out: return ret; } -void ion_system_contig_heap_free(struct ion_buffer *buffer) +static void ion_system_contig_heap_free(struct ion_buffer *buffer) { struct sg_table *table = buffer->priv_virt; struct page *page = sg_page(table->sgl); @@ -427,14 +425,14 @@ static int ion_system_contig_heap_phys(struct ion_heap *heap, return 0; } -struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, +static struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { return buffer->priv_virt; } -void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { } -- cgit v1.2.3 From ed5bf01aac7a524a1ca05f96947aeba8363cb669 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:29 -0800 Subject: ion: carveout heap: zero buffers on free, fix memory leak The carveout heap wasn't zeroing its buffers after use. Create the sg_table during allocate instead of map_dma, to allow using the sg_table during free, and call ion_heap_buffer_zero during free. Also fixes a missing kfree when destroying the table. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 69 +++++++++++++++++-------- 1 file changed, 48 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 9bf20a371f1a..66dec4ca5bea 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -14,7 +14,7 @@ * */ #include - +#include #include #include #include @@ -60,7 +60,11 @@ static int ion_carveout_heap_phys(struct ion_heap *heap, struct ion_buffer *buffer, ion_phys_addr_t *addr, size_t *len) { - *addr = buffer->priv_phys; + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + + *addr = paddr; *len = buffer->size; return 0; } @@ -70,44 +74,66 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, unsigned long size, unsigned long align, unsigned long flags) { + struct sg_table *table; + ion_phys_addr_t paddr; + int ret; + if (align > PAGE_SIZE) return -EINVAL; - buffer->priv_phys = ion_carveout_allocate(heap, size, align); - return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) + goto err_free; + + paddr = ion_carveout_allocate(heap, size, align); + if (paddr == ION_CARVEOUT_ALLOCATE_FAIL) { + ret = -ENOMEM; + goto err_free_table; + } + + sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0); + buffer->priv_virt = table; + + return 0; + +err_free_table: + sg_free_table(table); +err_free: + kfree(table); + return ret; } static void ion_carveout_heap_free(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + + ion_heap_buffer_zero(buffer); - ion_carveout_free(heap, buffer->priv_phys, buffer->size); - buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; + if (ion_buffer_cached(buffer)) + dma_sync_sg_for_device(NULL, table->sgl, table->nents, + DMA_BIDIRECTIONAL); + + ion_carveout_free(heap, paddr, buffer->size); + sg_free_table(table); + kfree(table); } static struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - struct sg_table *table; - int ret; - - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); - ret = sg_alloc_table(table, 1, GFP_KERNEL); - if (ret) { - kfree(table); - return ERR_PTR(ret); - } - sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->priv_phys)), - buffer->size, 0); - return table; + return buffer->priv_virt; } static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - sg_free_table(buffer->sg_table); + return; } static struct ion_heap_ops carveout_heap_ops = { @@ -139,6 +165,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) -1); carveout_heap->heap.ops = &carveout_heap_ops; carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT; + carveout_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; return &carveout_heap->heap; } -- cgit v1.2.3 From df6cf5c8af54e3e89643511272f6f5f5cfb71a7d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:30 -0800 Subject: ion: add helper to zero contiguous region of pages Add ion_heap_pages_zero for ion heaps to use to zero pages during initialization or allocation, when a struct ion_buffer may not be available. Use it from the chunk heap and carveout heaps. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 13 ++++++ drivers/staging/android/ion/ion_chunk_heap.c | 39 ++++++------------ drivers/staging/android/ion/ion_heap.c | 53 +++++++++++++++---------- drivers/staging/android/ion/ion_priv.h | 1 + 4 files changed, 58 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 66dec4ca5bea..3cb05b9b0e93 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -150,6 +150,19 @@ static struct ion_heap_ops carveout_heap_ops = { struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) { struct ion_carveout_heap *carveout_heap; + int ret; + + struct page *page; + size_t size; + + page = pfn_to_page(PFN_DOWN(heap_data->base)); + size = heap_data->size; + + ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL); + + ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); + if (ret) + return ERR_PTR(ret); carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL); if (!carveout_heap) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 46e8a3bf7a2f..f21530f4f7ae 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -140,9 +140,18 @@ static struct ion_heap_ops chunk_heap_ops = { struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) { struct ion_chunk_heap *chunk_heap; - struct vm_struct *vm_struct; - pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); - int i, ret; + int ret; + struct page *page; + size_t size; + + page = pfn_to_page(PFN_DOWN(heap_data->base)); + size = heap_data->size; + + ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL); + + ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); + if (ret) + return ERR_PTR(ret); chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL); if (!chunk_heap) @@ -159,26 +168,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->size = heap_data->size; chunk_heap->allocated = 0; - vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC); - if (!vm_struct) { - ret = -ENOMEM; - goto error; - } - for (i = 0; i < chunk_heap->size; i += PAGE_SIZE) { - struct page *page = pfn_to_page(PFN_DOWN(chunk_heap->base + i)); - struct page **pages = &page; - - ret = map_vm_area(vm_struct, pgprot, &pages); - if (ret) - goto error_map_vm_area; - memset(vm_struct->addr, 0, PAGE_SIZE); - unmap_kernel_range((unsigned long)vm_struct->addr, PAGE_SIZE); - } - free_vm_area(vm_struct); - - ion_pages_sync_for_device(NULL, pfn_to_page(PFN_DOWN(heap_data->base)), - heap_data->size, DMA_BIDIRECTIONAL); - gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; @@ -188,10 +177,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) return &chunk_heap->heap; -error_map_vm_area: - free_vm_area(vm_struct); -error: - gen_pool_destroy(chunk_heap->pool); error_gen_pool_create: kfree(chunk_heap); return ERR_PTR(ret); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index c3a213b6dcda..2d1d5555fc3d 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -114,38 +114,49 @@ static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) return 0; } +static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, + pgprot_t pgprot) +{ + int p = 0; + int ret = 0; + struct sg_page_iter piter; + struct page *pages[32]; + + for_each_sg_page(sgl, &piter, nents, 0) { + pages[p++] = sg_page_iter_page(&piter); + if (p == ARRAY_SIZE(pages)) { + ret = ion_heap_clear_pages(pages, p, pgprot); + if (ret) + return ret; + p = 0; + } + } + if (p) + ret = ion_heap_clear_pages(pages, p, pgprot); + + return ret; +} + int ion_heap_buffer_zero(struct ion_buffer *buffer) { struct sg_table *table = buffer->sg_table; pgprot_t pgprot; - struct scatterlist *sg; - int i, j, ret = 0; - struct page *pages[32]; - int k = 0; if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; else pgprot = pgprot_writecombine(PAGE_KERNEL); - for_each_sg(table->sgl, sg, table->nents, i) { - struct page *page = sg_page(sg); - unsigned long len = sg->length; + return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); +} - for (j = 0; j < len / PAGE_SIZE; j++) { - pages[k++] = page + j; - if (k == ARRAY_SIZE(pages)) { - ret = ion_heap_clear_pages(pages, k, pgprot); - if (ret) - goto end; - k = 0; - } - } - if (k) - ret = ion_heap_clear_pages(pages, k, pgprot); - } -end: - return ret; +int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) +{ + struct scatterlist sg; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + return ion_heap_sglist_zero(&sg, 1, pgprot); } void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index c9b507da7708..fa96175f7731 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -215,6 +215,7 @@ void ion_heap_unmap_kernel(struct ion_heap *, struct ion_buffer *); int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); int ion_heap_buffer_zero(struct ion_buffer *buffer); +int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); /** * ion_heap_init_deferred_free -- initialize deferred free functionality -- cgit v1.2.3 From dd608dd29a417da78f6aa1715efb9786787c550e Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:31 -0800 Subject: ion: add alignment check to chunk heap Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index f21530f4f7ae..a0720891fe4e 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -47,6 +47,9 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, unsigned long num_chunks; unsigned long allocated_size; + if (align > chunk_heap->chunk_size) + return -EINVAL; + allocated_size = ALIGN(size, chunk_heap->chunk_size); num_chunks = allocated_size / chunk_heap->chunk_size; -- cgit v1.2.3 From 661f82f6c219dc515ee5123213d8f57481694fe4 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 13 Dec 2013 19:26:32 -0800 Subject: ion: fix bugs in cma heap Implement ion_cma_unmap_kernel, ion will call it unconditionally. Use correct gfp flags when calling dma_alloc_coherent so it doesn't try to use atomic DMA memory. Check for invalid alignment when allocating. Reject cached allocations - the cpu address returned by dma_alloc_coherent is always going to be an uncached mapping, so map_kernel will not see data written by a cached userspace mapping. Signed-off-by: Colin Cross Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_cma_heap.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 3dcf9b47d5d5..f0f98897e4b9 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -69,13 +69,20 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, dev_dbg(dev, "Request buffer allocation len %ld\n", len); + if (buffer->flags & ION_FLAG_CACHED) + return -EINVAL; + + if (align > PAGE_SIZE) + return -EINVAL; + info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) { dev_err(dev, "Can't allocate buffer info\n"); return ION_CMA_ALLOCATE_FAILED; } - info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), 0); + info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), + GFP_HIGHUSER | __GFP_ZERO); if (!info->cpu_addr) { dev_err(dev, "Fail to allocate buffer\n"); @@ -170,6 +177,11 @@ static void *ion_cma_map_kernel(struct ion_heap *heap, return info->cpu_addr; } +static void ion_cma_unmap_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ +} + static struct ion_heap_ops ion_cma_ops = { .allocate = ion_cma_allocate, .free = ion_cma_free, @@ -178,6 +190,7 @@ static struct ion_heap_ops ion_cma_ops = { .phys = ion_cma_phys, .map_user = ion_cma_mmap, .map_kernel = ion_cma_map_kernel, + .unmap_kernel = ion_cma_unmap_kernel, }; struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) -- cgit v1.2.3 From e1d855b02f5ac4c3a6cbeaa253958b2708826b9f Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Dec 2013 19:26:33 -0800 Subject: ion: Cleanup whitespace issues and other checkpatch problems Just some simple cleanups to address whitespace issues and other issues found w/ checkpatch. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/compat_ion.c | 4 +- drivers/staging/android/ion/ion.c | 53 ++++++++++++++------------- drivers/staging/android/ion/ion.h | 2 +- drivers/staging/android/ion/ion_chunk_heap.c | 1 - drivers/staging/android/ion/ion_heap.c | 5 +-- drivers/staging/android/ion/ion_page_pool.c | 2 +- drivers/staging/android/ion/ion_priv.h | 2 +- drivers/staging/android/ion/ion_system_heap.c | 3 +- 8 files changed, 37 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index 079a5bbd2951..af6cd370b30f 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -91,8 +91,8 @@ static int compat_get_ion_custom_data( struct compat_ion_custom_data __user *data32, struct ion_custom_data __user *data) { - compat_uint_t cmd; - compat_ulong_t arg; + compat_uint_t cmd; + compat_ulong_t arg; int err; err = get_user(cmd, &data32->cmd); diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 559e4ee6f7e5..574066ff73f8 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -110,8 +110,8 @@ struct ion_handle { bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) { - return ((buffer->flags & ION_FLAG_CACHED) && - !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); + return (buffer->flags & ION_FLAG_CACHED) && + !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC); } bool ion_buffer_cached(struct ion_buffer *buffer) @@ -202,7 +202,8 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->size = len; table = heap->ops->map_dma(heap, buffer); - if (WARN_ONCE(table == NULL, "heap->ops->map_dma should return ERR_PTR on error")) + if (WARN_ONCE(table == NULL, + "heap->ops->map_dma should return ERR_PTR on error")) table = ERR_PTR(-EINVAL); if (IS_ERR(table)) { heap->ops->free(buffer); @@ -424,7 +425,8 @@ static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, return handle ? handle : ERR_PTR(-EINVAL); } -static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) +static bool ion_handle_validate(struct ion_client *client, + struct ion_handle *handle) { WARN_ON(!mutex_is_locked(&client->lock)); return (idr_find(&client->idr, handle->id) == handle); @@ -578,7 +580,8 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) return buffer->vaddr; } vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - if (WARN_ONCE(vaddr == NULL, "heap->ops->map_kernel should return ERR_PTR on error")) + if (WARN_ONCE(vaddr == NULL, + "heap->ops->map_kernel should return ERR_PTR on error")) return ERR_PTR(-EINVAL); if (IS_ERR(vaddr)) return vaddr; @@ -1403,39 +1406,39 @@ static const struct file_operations debug_heap_fops = { #ifdef DEBUG_HEAP_SHRINKER static int debug_shrink_set(void *data, u64 val) { - struct ion_heap *heap = data; - struct shrink_control sc; - int objs; + struct ion_heap *heap = data; + struct shrink_control sc; + int objs; - sc.gfp_mask = -1; - sc.nr_to_scan = 0; + sc.gfp_mask = -1; + sc.nr_to_scan = 0; - if (!val) - return 0; + if (!val) + return 0; - objs = heap->shrinker.shrink(&heap->shrinker, &sc); - sc.nr_to_scan = objs; + objs = heap->shrinker.shrink(&heap->shrinker, &sc); + sc.nr_to_scan = objs; - heap->shrinker.shrink(&heap->shrinker, &sc); - return 0; + heap->shrinker.shrink(&heap->shrinker, &sc); + return 0; } static int debug_shrink_get(void *data, u64 *val) { - struct ion_heap *heap = data; - struct shrink_control sc; - int objs; + struct ion_heap *heap = data; + struct shrink_control sc; + int objs; - sc.gfp_mask = -1; - sc.nr_to_scan = 0; + sc.gfp_mask = -1; + sc.nr_to_scan = 0; - objs = heap->shrinker.shrink(&heap->shrinker, &sc); - *val = objs; - return 0; + objs = heap->shrinker.shrink(&heap->shrinker, &sc); + *val = objs; + return 0; } DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, - debug_shrink_set, "%llu\n"); + debug_shrink_set, "%llu\n"); #endif void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 962e1c58d362..dcd2a0cdb192 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -38,7 +38,7 @@ struct ion_buffer; * struct ion_platform_heap - defines a heap in the given platform * @type: type of the heap from ion_heap_type enum * @id: unique identifier for heap. When allocating higher numbers - * will be allocated from first. At allocation these are passed + * will be allocated from first. At allocation these are passed * as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS. * @name: used for debug purposes * @base: base address of heap in physical memory if applicable diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index a0720891fe4e..d40f5f831808 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. * */ -//#include #include #include #include diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 2d1d5555fc3d..9cf562224386 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -49,9 +49,8 @@ void *ion_heap_map_kernel(struct ion_heap *heap, int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; struct page *page = sg_page(sg); BUG_ON(i >= npages); - for (j = 0; j < npages_this_entry; j++) { + for (j = 0; j < npages_this_entry; j++) *(tmp++) = page++; - } } vaddr = vmap(pages, npages, VM_MAP, pgprot); vfree(pages); @@ -159,7 +158,7 @@ int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) return ion_heap_sglist_zero(&sg, 1, pgprot); } -void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) +void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer) { rt_mutex_lock(&heap->lock); list_add(&buffer->list, &heap->free_list); diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index a1c51a839d66..fa693c23681a 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -108,7 +108,7 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool) return page; } -void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) +void ion_page_pool_free(struct ion_page_pool *pool, struct page *page) { int ret; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index fa96175f7731..fc8a4c3cee5d 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -230,7 +230,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap); /** * ion_heap_freelist_add - add a buffer to the deferred free list * @heap: the heap - * @buffer: the buffer + * @buffer: the buffer * * Adds an item to the deferred freelist. */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 301d019a3270..b5acd6c178e6 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -148,7 +148,8 @@ static int ion_system_heap_allocate(struct ion_heap *heap, INIT_LIST_HEAD(&pages); while (size_remaining > 0) { - info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); + info = alloc_largest_available(sys_heap, buffer, size_remaining, + max_order); if (!info) goto err; list_add_tail(&info->list, &pages); -- cgit v1.2.3 From 024789ae3b5517de151032623d1534aae804236b Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Dec 2013 19:26:34 -0800 Subject: ion: Improve ION config description Mostly just to quiet checkpatch warnings, be more verbose in describing the ION config option. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 3215bd8fb458..a342d96ee4f0 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -2,8 +2,12 @@ menuconfig ION tristate "Ion Memory Manager" select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER - help - Chose this option to enable the ION Memory Manager. + ---help--- + Chose this option to enable the ION Memory Manager, + used by Android to efficiently allocate buffers + from userspace that can be shared between drivers. + If you're not using Android its probably safe to + say N here. config ION_TEST tristate "Ion Test Device" -- cgit v1.2.3 From b1aced6f2dfd8c11a36643b020aa8d7040eb0557 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Dec 2013 19:26:35 -0800 Subject: ion: Update system heap shrinker to use the new count/scan interface Update the ION system heap shrinker to use the new count/scan interfaces that landed in 3.12 Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 40 +++++++++++++++++++-------- 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index b5acd6c178e6..144b22727505 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -232,15 +232,37 @@ static struct ion_heap_ops system_heap_ops = { .map_user = ion_heap_map_user, }; -static int ion_system_heap_shrink(struct shrinker *shrinker, - struct shrink_control *sc) { - +static unsigned long ion_system_heap_shrink_count(struct shrinker *shrinker, + struct shrink_control *sc) +{ struct ion_heap *heap = container_of(shrinker, struct ion_heap, shrinker); struct ion_system_heap *sys_heap = container_of(heap, struct ion_system_heap, heap); int nr_total = 0; + int i; + + /* total number of items is whatever the page pools are holding + plus whatever's in the freelist */ + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool = sys_heap->pools[i]; + nr_total += ion_page_pool_shrink(pool, sc->gfp_mask, 0); + } + nr_total += ion_heap_freelist_size(heap) / PAGE_SIZE; + return nr_total; + +} + +static unsigned long ion_system_heap_shrink_scan(struct shrinker *shrinker, + struct shrink_control *sc) +{ + + struct ion_heap *heap = container_of(shrinker, struct ion_heap, + shrinker); + struct ion_system_heap *sys_heap = container_of(heap, + struct ion_system_heap, + heap); int nr_freed = 0; int i; @@ -265,14 +287,7 @@ static int ion_system_heap_shrink(struct shrinker *shrinker, } end: - /* total number of items is whatever the page pools are holding - plus whatever's in the freelist */ - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - nr_total += ion_page_pool_shrink(pool, sc->gfp_mask, 0); - } - nr_total += ion_heap_freelist_size(heap) / PAGE_SIZE; - return nr_total; + return nr_freed; } @@ -323,7 +338,8 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) heap->pools[i] = pool; } - heap->heap.shrinker.shrink = ion_system_heap_shrink; + heap->heap.shrinker.scan_objects = ion_system_heap_shrink_scan; + heap->heap.shrinker.count_objects = ion_system_heap_shrink_count; heap->heap.shrinker.seeks = DEFAULT_SEEKS; heap->heap.shrinker.batch = 0; register_shrinker(&heap->heap.shrinker); -- cgit v1.2.3 From cd84d34074f56595fbae7a70f8a85b7d089249d1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 9 May 2013 11:26:16 -0600 Subject: PCI: pciehp: Drop pciehp_readw()/pciehp_writew() wrappers The pciehp_readw() and pciehp_writew() wrappers only look up the pci_dev and call the PCIe Capability accessors, so we can make things a little more straightforward by just using the PCIe Capability accessors directly. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 95 ++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 3eea3fdd4b0b..53bb5501d199 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -41,28 +41,9 @@ #include "../pci.h" #include "pciehp.h" -static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) +static inline struct pci_dev *ctrl_dev(struct controller *ctrl) { - struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_read_word(dev, reg, value); -} - -static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) -{ - struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_read_dword(dev, reg, value); -} - -static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) -{ - struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_write_word(dev, reg, value); -} - -static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) -{ - struct pci_dev *dev = ctrl->pcie->port; - return pcie_capability_write_dword(dev, reg, value); + return ctrl->pcie->port; } /* Power Control Command */ @@ -129,20 +110,24 @@ static inline void pciehp_free_irq(struct controller *ctrl) static int pcie_poll_cmd(struct controller *ctrl) { + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; int err, timeout = 1000; - err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + err = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { - pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_CC); return 1; } while (timeout > 0) { msleep(10); timeout -= 10; - err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + err = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, + &slot_status); if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { - pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_CC); return 1; } } @@ -171,13 +156,14 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll) */ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) { + struct pci_dev *pdev = ctrl_dev(ctrl); int retval = 0; u16 slot_status; u16 slot_ctrl; mutex_lock(&ctrl->ctrl_lock); - retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", __func__); @@ -207,7 +193,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) } } - retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); goto out; @@ -217,7 +203,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) slot_ctrl |= (cmd & mask); ctrl->cmd_busy = 1; smp_mb(); - retval = pciehp_writew(ctrl, PCI_EXP_SLTCTL, slot_ctrl); + retval = pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); if (retval) ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); @@ -243,10 +229,11 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) static bool check_link_active(struct controller *ctrl) { + struct pci_dev *pdev = ctrl_dev(ctrl); bool ret = false; u16 lnk_status; - if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status)) + if (pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status)) return ret; ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); @@ -311,6 +298,7 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) int pciehp_check_link_status(struct controller *ctrl) { + struct pci_dev *pdev = ctrl_dev(ctrl); u16 lnk_status; int retval = 0; bool found = false; @@ -330,7 +318,7 @@ int pciehp_check_link_status(struct controller *ctrl) found = pci_bus_check_dev(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); - retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); + retval = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); if (retval) { ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); return retval; @@ -354,10 +342,11 @@ int pciehp_check_link_status(struct controller *ctrl) static int __pciehp_link_set(struct controller *ctrl, bool enable) { + struct pci_dev *pdev = ctrl_dev(ctrl); u16 lnk_ctrl; int retval = 0; - retval = pciehp_readw(ctrl, PCI_EXP_LNKCTL, &lnk_ctrl); + retval = pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl); if (retval) { ctrl_err(ctrl, "Cannot read LNKCTRL register\n"); return retval; @@ -368,7 +357,7 @@ static int __pciehp_link_set(struct controller *ctrl, bool enable) else lnk_ctrl |= PCI_EXP_LNKCTL_LD; - retval = pciehp_writew(ctrl, PCI_EXP_LNKCTL, lnk_ctrl); + retval = pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl); if (retval) { ctrl_err(ctrl, "Cannot write LNKCTRL register\n"); return retval; @@ -391,11 +380,12 @@ static int pciehp_link_disable(struct controller *ctrl) int pciehp_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; u8 atten_led_state; int retval = 0; - retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); return retval; @@ -430,11 +420,12 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status) int pciehp_get_power_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; u8 pwr_state; int retval = 0; - retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); return retval; @@ -462,10 +453,11 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) int pciehp_get_latch_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; int retval; - retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", __func__); @@ -478,10 +470,11 @@ int pciehp_get_latch_status(struct slot *slot, u8 *status) int pciehp_get_adapter_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; int retval; - retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", __func__); @@ -494,10 +487,11 @@ int pciehp_get_adapter_status(struct slot *slot, u8 *status) int pciehp_query_power_fault(struct slot *slot) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; int retval; - retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "Cannot check for power fault\n"); return retval; @@ -572,13 +566,14 @@ void pciehp_green_led_blink(struct slot *slot) int pciehp_power_on_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_cmd; u16 cmd_mask; u16 slot_status; int retval = 0; /* Clear sticky power-fault bit from previous power failures */ - retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); + retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", __func__); @@ -586,7 +581,7 @@ int pciehp_power_on_slot(struct slot * slot) } slot_status &= PCI_EXP_SLTSTA_PFD; if (slot_status) { - retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status); + retval = pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS register\n", @@ -643,6 +638,7 @@ int pciehp_power_off_slot(struct slot * slot) static irqreturn_t pcie_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; + struct pci_dev *pdev = ctrl_dev(ctrl); struct slot *slot = ctrl->slot; u16 detected, intr_loc; @@ -653,7 +649,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) */ intr_loc = 0; do { - if (pciehp_readw(ctrl, PCI_EXP_SLTSTA, &detected)) { + if (pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, + &detected)) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n", __func__); return IRQ_NONE; @@ -666,7 +663,9 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) intr_loc |= detected; if (!intr_loc) return IRQ_NONE; - if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, intr_loc)) { + if (detected && + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + intr_loc)) { ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", __func__); return IRQ_NONE; @@ -758,6 +757,7 @@ static void pcie_disable_notification(struct controller *ctrl) int pciehp_reset_slot(struct slot *slot, int probe) { struct controller *ctrl = slot->ctrl; + struct pci_dev *pdev = ctrl_dev(ctrl); if (probe) return 0; @@ -771,7 +771,8 @@ int pciehp_reset_slot(struct slot *slot, int probe) pci_reset_bridge_secondary_bus(ctrl->pcie->port); if (HP_SUPR_RM(ctrl)) { - pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDC); + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDC); pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE); if (pciehp_poll_mode) int_poll_timeout(ctrl->poll_timer.data); @@ -875,9 +876,9 @@ static inline void dbg_ctrl(struct controller *ctrl) EMI(ctrl) ? "yes" : "no"); ctrl_info(ctrl, " Command Completed : %3s\n", NO_CMD_CMPL(ctrl) ? "no" : "yes"); - pciehp_readw(ctrl, PCI_EXP_SLTSTA, ®16); + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, ®16); ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16); - pciehp_readw(ctrl, PCI_EXP_SLTCTL, ®16); + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, ®16); ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16); } @@ -893,7 +894,7 @@ struct controller *pcie_init(struct pcie_device *dev) goto abort; } ctrl->pcie = dev; - if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) { + if (pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap)) { ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); goto abort_ctrl; } @@ -913,7 +914,7 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->no_cmd_complete = 1; /* Check if Data Link Layer Link Active Reporting is implemented */ - if (pciehp_readl(ctrl, PCI_EXP_LNKCAP, &link_cap)) { + if (pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap)) { ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); goto abort_ctrl; } @@ -923,7 +924,7 @@ struct controller *pcie_init(struct pcie_device *dev) } /* Clear all remaining event bits in Slot Status register */ - if (pciehp_writew(ctrl, PCI_EXP_SLTSTA, 0x1f)) + if (pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, 0x1f)) goto abort_ctrl; /* Disable software notification */ -- cgit v1.2.3 From d934145139664daa1ae918d3f0a7f3f47225ff33 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 14 Dec 2013 19:38:08 +0530 Subject: drivers: ata: Mark the function ahci_init_interrupts() as static in ahci.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the function ahci_init_interrupts() as static in ahci.c because it is not used outside this file. Thus, it also eliminates the following warning in ahci.c: drivers/ata/ahci.c:1099:5: warning: no previous prototype for ‘ahci_init_interrupts’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Signed-off-by: Tejun Heo Reviewed-by: Josh Triplett --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ef8642e12a76..ea5b5a33a8b8 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1145,7 +1145,7 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) {} #endif -int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv) +static int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv) { int rc; unsigned int maxvec; -- cgit v1.2.3 From 73993396d8591580f03fe0ee9c6cc5ea8fa09928 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 14 Dec 2013 19:40:21 +0530 Subject: drivers: ata: Mark the function as static in libahci.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the function ahci_port_intr() and ahci_hw_port_interrupt() as static in libahci.c because they are not used outside this file. Thus, it also eliminates the following warnings in libahci.c: drivers/ata/libahci.c:1767:6: warning: no previous prototype for ‘ahci_port_intr’ [-Wmissing-prototypes] drivers/ata/libahci.c:1800:6: warning: no previous prototype for ‘ahci_hw_port_interrupt’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Signed-off-by: Tejun Heo Reviewed-by: Josh Triplett --- drivers/ata/libahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index c482f8cadd7a..36605abe5a67 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1764,7 +1764,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap, } } -void ahci_port_intr(struct ata_port *ap) +static void ahci_port_intr(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); u32 status; @@ -1797,7 +1797,7 @@ irqreturn_t ahci_thread_fn(int irq, void *dev_instance) } EXPORT_SYMBOL_GPL(ahci_thread_fn); -void ahci_hw_port_interrupt(struct ata_port *ap) +static void ahci_hw_port_interrupt(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); struct ahci_port_priv *pp = ap->private_data; -- cgit v1.2.3 From 3a5aec246f294004564cbe960724fa0ace59a4c5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 16 Oct 2013 00:40:03 -0700 Subject: clk: Fix debugfs reparenting NULL pointer dereference Adding clocks from a kernel module can cause a NULL pointer dereference if the parent of a clock is added after the clock is added. This happens because __clk_init() iterates over the list of orphans and reparents the orphans to the clock being registered before creating the debugfs entry for the clock. Create the debugfs entry first before reparenting the orphans. Unable to handle kernel NULL pointer dereference at virtual address 00000028 pgd = ef3e4000 [00000028] *pgd=bf810831 Internal error: Oops: 17 [#1] PREEMPT SMP ARM Modules linked in: mmcc_8960(+) CPU: 0 PID: 52 Comm: modprobe Not tainted 3.12.0-rc2-00023-g1021a28-dirty #659 task: ef319200 ti: ef3a6000 task.ti: ef3a6000 PC is at lock_rename+0x24/0xc4 LR is at debugfs_rename+0x34/0x208 pc : [] lr : [] psr: 00000013 sp : ef3a7b88 ip : ef3a7ba8 fp : ef3a7ba4 r10: ef3d51cc r9 : ef3bc680 r8 : ef3d5210 r7 : ef3bc640 r6 : eee287e0 r5 : eee287e0 r4 : 00000000 r3 : ef3bc640 r2 : 00000000 r1 : eee287e0 r0 : 00000000 Flags: nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5787d Table: af3e406a DAC: 00000015 Process modprobe (pid: 52, stack limit = 0xef3a6240) Stack: (0xef3a7b88 to 0xef3a8000) 7b80: ef3bc640 ee4047e0 00000000 eee287e0 ef3a7bec ef3a7ba8 7ba0: c047dfe4 c0317220 ef3bc680 ef3d51cc ef3a7bdc ef3a7bc0 c06e29d0 c0268784 7bc0: c08946e8 ef3d5210 00000000 ef3bc700 ef3d5290 ef3d5210 ef3bc680 ef3d51cc 7be0: ef3a7c0c ef3a7bf0 c05b9e9c c047dfbc 00000000 00000000 ef3d5210 ef3d5290 7c00: ef3a7c24 ef3a7c10 c05baebc c05b9e30 00000001 00000001 ef3a7c64 ef3a7c28 7c20: c05bb124 c05bae9c bf000cd8 ef3bc7c0 000000d0 c0ff129c bf001774 00000002 7c40: ef3bc740 ef3d5290 ef0f9a10 bf001774 bf00042c 00000061 ef3a7c8c ef3a7c68 7c60: c05bb480 c05baed8 bf001774 ef3d5290 ef0f9a10 bf001774 ef38bc10 ef0f9a00 7c80: ef3a7cac ef3a7c90 c05bb5a8 c05bb3a0 bf001774 00000062 ef0f9a10 ef38bc18 7ca0: ef3a7cec ef3a7cb0 bf00010c c05bb56c 00000000 ef38ba00 00000000 ef3d60d0 7cc0: ef3a7cdc c0fefc24 ef0f9a10 c0a091c0 bf000d24 00000000 bf0029f0 bf006000 7ce0: ef3a7cfc ef3a7cf0 c05156c0 bf000040 ef3a7d2c ef3a7d00 c0513f5c c05156a8 7d00: ef3a7d2c ef0f9a10 ef0f9a10 bf000d24 ef0f9a44 c09ca588 00000000 bf006000 7d20: ef3a7d4c ef3a7d30 c05142b8 c0513ecc ef0fd25c 00000000 bf000d24 c0514214 7d40: ef3a7d74 ef3a7d50 c0512030 c0514220 ef0050a8 ef0fd250 ef0050f8 bf000d24 7d60: ef37c100 c09ed150 ef3a7d84 ef3a7d78 c05139c8 c0511fd8 ef3a7 7d80: c051344c c05139a8 bf000864 c09ca588 ef3a7db4 bf000d24 bf002 7da0: c09ca588 00000000 ef3a7dcc ef3a7db8 c05149dc c0513360 ef3a7 7dc0: ef3a7ddc ef3a7dd0 c0515914 c0514960 ef3a7dec ef3a7de0 bf006 7de0: ef3a7e74 ef3a7df0 c0208800 bf00600c ef3a7e1c ef3a7e00 c04c5 7e00: ffffffff c09d46c4 00000000 bf0029a8 ef3a7e34 ef3a7e20 c024c 7e20: ffffffff c09d46c4 ef3a7e5c ef3a7e38 c024e2fc c024ce40 00000 7e40: ef3a7f48 bf0029b4 bf0029a8 271aeb1c ef3a7f48 bf0029a8 00000001 ef383c00 7e60: bf0029f0 00000001 ef3a7f3c ef3a7e78 c028fac4 c0208718 bf0029b4 00007fff 7e80: c028cd58 000000d2 f0065000 00000000 ef3a7ebc 00000000 00000000 bf0029b4 7ea0: 00000000 bf0029ac bf0029b4 ef3a6000 ef3a7efc c08bf128 00000000 00000000 7ec0: 00000000 00000000 00000000 00000000 6e72656b 00006c65 00000000 00000000 7ee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7f00: 00000000 00000000 00000000 271aeb1c ef3a7f2c 00016376 b6f38008 001d3774 7f20: 00000080 c020f968 ef3a6000 00000000 ef3a7fa4 ef3a7f40 c02904dc c028e178 7f40: c020f898 010ccfa8 f0065000 00016376 f0073f60 f0073d7d f007a1e8 00002b24 7f60: 000039e4 00000000 00000000 00000000 0000002f 00000030 00000019 00000016 7f80: 00000012 00000000 00000000 010de1b2 b6f38008 010ccfa8 00000000 ef3a7fa8 7fa0: c020f6c0 c0290434 010de1b2 b6f38008 b6f38008 00016376 001d3774 00000000 7fc0: 010de1b2 b6f38008 010ccfa8 00000080 010de1b2 bedb6f90 010de1c9 0001d8dc 7fe0: 0000000c bedb674c 0001ce30 000094c4 60000010 b6f38008 00000008 0000001d [] (lock_rename+0x24/0xc4) from [] (debugfs_rename+0x34/0x208) [] (debugfs_rename+0x34/0x208) from [] (clk_debug_reparent+0x78/0xc0) [] (__clk_reparent+0x2c/0x3c) from [] (__clk_init+0x258/0x4c8) [] (__clk_init+0x258/0x4c8) from [] (_clk_register+0xec/0x1cc) [] (_clk_register+0xec/0x1cc) from [] (devm_clk_register+0x48/0x7c) [] (devm_clk_register+0x48/0x7c) from [] (msm_mmcc_8960_probe+0xd8/0x190 [mmcc_8960]) [] (msm_mmcc_8960_probe+0xd8/0x190 [mmcc_8960]) from [] (platform_drv_probe+0x24/0x28) [] (platform_drv_probe+0x24/0x28) from [] (driver_probe_device+0x9c/0x354) [] (driver_probe_device+0x9c/0x354) from [] (__driver_attach+0xa4/0xa8) [] (__driver_attach+0xa4/0xa8) from [] (bus_for_each_dev+0x64/0x98) [] (bus_for_each_dev+0x64/0x98) from [] (driver_attach+0x2c/0x30) [] (driver_attach+0x2c/0x30) from [] (bus_add_driver+0xf8/0x2a8) [] (bus_add_driver+0xf8/0x2a8) from [] (driver_register+0x88/0x104) [] (driver_register+0x88/0x104) from [] (__platform_driver_register+0x58/0x6c) [] (__platform_driver_register+0x58/0x6c) from [] (msm_mmcc_8960_driver_init+0x18/0x24 [mmcc_8960]) [] (msm_mmcc_8960_driver_init+0x18/0x24 [mmcc_8960]) from [] (do_one_initcall+0xf4/0x1b8) [] (do_one_initcall+0xf4/0x1b8) from [] (load_module+0x1958/0x22bc) [] (load_module+0x1958/0x22bc) from [] (SyS_init_module+0xb4/0x120) [] (SyS_init_module+0xb4/0x120) from [] (ret_fast_syscall+0x0/0x48) Code: e1500001 e1a04000 e1a05001 0a000021 (e5903028) Signed-off-by: Stephen Boyd Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 77fcd069c64a..83127363ad4c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1744,6 +1744,7 @@ int __clk_init(struct device *dev, struct clk *clk) else clk->rate = 0; + clk_debug_register(clk); /* * walk the list of orphan clocks and reparent any that are children of * this clock @@ -1774,8 +1775,6 @@ int __clk_init(struct device *dev, struct clk *clk) if (clk->ops->init) clk->ops->init(clk->hw); - clk_debug_register(clk); - out: clk_prepare_unlock(); -- cgit v1.2.3 From 1459c837036a44e2dcf14a9452ed330201fb23b5 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 21 Sep 2013 16:40:39 -0700 Subject: clk: si570: Add a driver for SI570 oscillators Add a driver for SILabs 570, 571, 598, 599 programmable oscillators. The devices generate low-jitter clock signals and are reprogrammable via an I2C interface. Reviewed-by: Guenter Roeck Signed-off-by: Soren Brinkmann Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/silabs,si570.txt | 39 ++ drivers/clk/Kconfig | 10 + drivers/clk/Makefile | 1 + drivers/clk/clk-si570.c | 531 +++++++++++++++++++++ 4 files changed, 581 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/silabs,si570.txt create mode 100644 drivers/clk/clk-si570.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/silabs,si570.txt b/Documentation/devicetree/bindings/clock/silabs,si570.txt new file mode 100644 index 000000000000..c09f21e1d98f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/silabs,si570.txt @@ -0,0 +1,39 @@ +Binding for Silicon Labs 570, 571, 598 and 599 programmable +I2C clock generators. + +Reference +This binding uses the common clock binding[1]. Details about the devices can be +found in the data sheets[2][3]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Si570/571 Data Sheet + http://www.silabs.com/Support%20Documents/TechnicalDocs/si570.pdf +[3] Si598/599 Data Sheet + http://www.silabs.com/Support%20Documents/TechnicalDocs/si598-99.pdf + +Required properties: + - compatible: Shall be one of "silabs,si570", "silabs,si571", + "silabs,si598", "silabs,si599" + - reg: I2C device address. + - #clock-cells: From common clock bindings: Shall be 0. + - factory-fout: Factory set default frequency. This frequency is part specific. + The correct frequency for the part used has to be provided in + order to generate the correct output frequencies. For more + details, please refer to the data sheet. + - temperature-stability: Temperature stability of the device in PPM. Should be + one of: 7, 20, 50 or 100. + +Optional properties: + - clock-output-names: From common clock bindings. Recommended to be "si570". + - clock-frequency: Output frequency to generate. This defines the output + frequency set during boot. It can be reprogrammed during + runtime through the common clock framework. + +Example: + si570: clock-generator@5d { + #clock-cells = <0>; + compatible = "silabs,si570"; + temperature-stability = <50>; + reg = <0x5d>; + factory-fout = <156250000>; + }; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 5c51115081b3..3089f05ba661 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -64,6 +64,16 @@ config COMMON_CLK_SI5351 This driver supports Silicon Labs 5351A/B/C programmable clock generators. +config COMMON_CLK_SI570 + tristate "Clock driver for SiLabs 570 and compatible devices" + depends on I2C + depends on OF + select REGMAP_I2C + help + ---help--- + This driver supports Silicon Labs 570/571/598/599 programmable + clock generators. + config COMMON_CLK_S2MPS11 tristate "Clock driver for S2MPS11 MFD" depends on MFD_SEC_CORE diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 2460afd59405..6705d9a82cbc 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o +obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c new file mode 100644 index 000000000000..5d0ac9f8e1ee --- /dev/null +++ b/drivers/clk/clk-si570.c @@ -0,0 +1,531 @@ +/* + * Driver for Silicon Labs Si570/Si571 Programmable XO/VCXO + * + * Copyright (C) 2010, 2011 Ericsson AB. + * Copyright (C) 2011 Guenter Roeck. + * Copyright (C) 2011 - 2013 Xilinx Inc. + * + * Author: Guenter Roeck + * Sören Brinkmann + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * 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. + */ + +#include +#include +#include +#include +#include +#include + +/* Si570 registers */ +#define SI570_REG_HS_N1 7 +#define SI570_REG_N1_RFREQ0 8 +#define SI570_REG_RFREQ1 9 +#define SI570_REG_RFREQ2 10 +#define SI570_REG_RFREQ3 11 +#define SI570_REG_RFREQ4 12 +#define SI570_REG_CONTROL 135 +#define SI570_REG_FREEZE_DCO 137 +#define SI570_DIV_OFFSET_7PPM 6 + +#define HS_DIV_SHIFT 5 +#define HS_DIV_MASK 0xe0 +#define HS_DIV_OFFSET 4 +#define N1_6_2_MASK 0x1f +#define N1_1_0_MASK 0xc0 +#define RFREQ_37_32_MASK 0x3f + +#define SI570_MIN_FREQ 10000000L +#define SI570_MAX_FREQ 1417500000L +#define SI598_MAX_FREQ 525000000L + +#define FDCO_MIN 4850000000LL +#define FDCO_MAX 5670000000LL + +#define SI570_CNTRL_RECALL (1 << 0) +#define SI570_CNTRL_FREEZE_M (1 << 5) +#define SI570_CNTRL_NEWFREQ (1 << 6) + +#define SI570_FREEZE_DCO (1 << 4) + +/** + * struct clk_si570: + * @hw: Clock hw struct + * @regmap: Device's regmap + * @div_offset: Rgister offset for dividers + * @max_freq: Maximum frequency for this device + * @fxtal: Factory xtal frequency + * @n1: Clock divider N1 + * @hs_div: Clock divider HSDIV + * @rfreq: Clock multiplier RFREQ + * @frequency: Current output frequency + * @i2c_client: I2C client pointer + */ +struct clk_si570 { + struct clk_hw hw; + struct regmap *regmap; + unsigned int div_offset; + u64 max_freq; + u64 fxtal; + unsigned int n1; + unsigned int hs_div; + u64 rfreq; + u64 frequency; + struct i2c_client *i2c_client; +}; +#define to_clk_si570(_hw) container_of(_hw, struct clk_si570, hw) + +enum clk_si570_variant { + si57x, + si59x +}; + +/** + * si570_get_divs() - Read clock dividers from HW + * @data: Pointer to struct clk_si570 + * @rfreq: Fractional multiplier (output) + * @n1: Divider N1 (output) + * @hs_div: Divider HSDIV (output) + * Returns 0 on success, negative errno otherwise. + * + * Retrieve clock dividers and multipliers from the HW. + */ +static int si570_get_divs(struct clk_si570 *data, u64 *rfreq, + unsigned int *n1, unsigned int *hs_div) +{ + int err; + u8 reg[6]; + u64 tmp; + + err = regmap_bulk_read(data->regmap, SI570_REG_HS_N1 + data->div_offset, + reg, ARRAY_SIZE(reg)); + if (err) + return err; + + *hs_div = ((reg[0] & HS_DIV_MASK) >> HS_DIV_SHIFT) + HS_DIV_OFFSET; + *n1 = ((reg[0] & N1_6_2_MASK) << 2) + ((reg[1] & N1_1_0_MASK) >> 6) + 1; + /* Handle invalid cases */ + if (*n1 > 1) + *n1 &= ~1; + + tmp = reg[1] & RFREQ_37_32_MASK; + tmp = (tmp << 8) + reg[2]; + tmp = (tmp << 8) + reg[3]; + tmp = (tmp << 8) + reg[4]; + tmp = (tmp << 8) + reg[5]; + *rfreq = tmp; + + return 0; +} + +/** + * si570_get_defaults() - Get default values + * @data: Driver data structure + * @fout: Factory frequency output + * Returns 0 on success, negative errno otherwise. + */ +static int si570_get_defaults(struct clk_si570 *data, u64 fout) +{ + int err; + u64 fdco; + + regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_RECALL); + + err = si570_get_divs(data, &data->rfreq, &data->n1, &data->hs_div); + if (err) + return err; + + /* + * Accept optional precision loss to avoid arithmetic overflows. + * Acceptable per Silicon Labs Application Note AN334. + */ + fdco = fout * data->n1 * data->hs_div; + if (fdco >= (1LL << 36)) + data->fxtal = div64_u64(fdco << 24, data->rfreq >> 4); + else + data->fxtal = div64_u64(fdco << 28, data->rfreq); + + data->frequency = fout; + + return 0; +} + +/** + * si570_update_rfreq() - Update clock multiplier + * @data: Driver data structure + * Passes on regmap_bulk_write() return value. + */ +static int si570_update_rfreq(struct clk_si570 *data) +{ + u8 reg[5]; + + reg[0] = ((data->n1 - 1) << 6) | + ((data->rfreq >> 32) & RFREQ_37_32_MASK); + reg[1] = (data->rfreq >> 24) & 0xff; + reg[2] = (data->rfreq >> 16) & 0xff; + reg[3] = (data->rfreq >> 8) & 0xff; + reg[4] = data->rfreq & 0xff; + + return regmap_bulk_write(data->regmap, SI570_REG_N1_RFREQ0 + + data->div_offset, reg, ARRAY_SIZE(reg)); +} + +/** + * si570_calc_divs() - Caluclate clock dividers + * @frequency: Target frequency + * @data: Driver data structure + * @out_rfreq: RFREG fractional multiplier (output) + * @out_n1: Clock divider N1 (output) + * @out_hs_div: Clock divider HSDIV (output) + * Returns 0 on success, negative errno otherwise. + * + * Calculate the clock dividers (@out_hs_div, @out_n1) and clock multiplier + * (@out_rfreq) for a given target @frequency. + */ +static int si570_calc_divs(unsigned long frequency, struct clk_si570 *data, + u64 *out_rfreq, unsigned int *out_n1, unsigned int *out_hs_div) +{ + int i; + unsigned int n1, hs_div; + u64 fdco, best_fdco = ULLONG_MAX; + static const uint8_t si570_hs_div_values[] = { 11, 9, 7, 6, 5, 4 }; + + for (i = 0; i < ARRAY_SIZE(si570_hs_div_values); i++) { + hs_div = si570_hs_div_values[i]; + /* Calculate lowest possible value for n1 */ + n1 = div_u64(div_u64(FDCO_MIN, hs_div), frequency); + if (!n1 || (n1 & 1)) + n1++; + while (n1 <= 128) { + fdco = (u64)frequency * (u64)hs_div * (u64)n1; + if (fdco > FDCO_MAX) + break; + if (fdco >= FDCO_MIN && fdco < best_fdco) { + *out_n1 = n1; + *out_hs_div = hs_div; + *out_rfreq = div64_u64(fdco << 28, data->fxtal); + best_fdco = fdco; + } + n1 += (n1 == 1 ? 1 : 2); + } + } + + if (best_fdco == ULLONG_MAX) + return -EINVAL; + + return 0; +} + +static unsigned long si570_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + int err; + u64 rfreq, rate; + unsigned int n1, hs_div; + struct clk_si570 *data = to_clk_si570(hw); + + err = si570_get_divs(data, &rfreq, &n1, &hs_div); + if (err) { + dev_err(&data->i2c_client->dev, "unable to recalc rate\n"); + return data->frequency; + } + + rfreq = div_u64(rfreq, hs_div * n1); + rate = (data->fxtal * rfreq) >> 28; + + return rate; +} + +static long si570_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + int err; + u64 rfreq; + unsigned int n1, hs_div; + struct clk_si570 *data = to_clk_si570(hw); + + if (!rate) + return 0; + + if (div64_u64(abs(rate - data->frequency) * 10000LL, + data->frequency) < 35) { + rfreq = div64_u64((data->rfreq * rate) + + div64_u64(data->frequency, 2), data->frequency); + n1 = data->n1; + hs_div = data->hs_div; + + } else { + err = si570_calc_divs(rate, data, &rfreq, &n1, &hs_div); + if (err) { + dev_err(&data->i2c_client->dev, + "unable to round rate\n"); + return 0; + } + } + + return rate; +} + +/** + * si570_set_frequency() - Adjust output frequency + * @data: Driver data structure + * @frequency: Target frequency + * Returns 0 on success. + * + * Update output frequency for big frequency changes (> 3,500 ppm). + */ +static int si570_set_frequency(struct clk_si570 *data, unsigned long frequency) +{ + int err; + + err = si570_calc_divs(frequency, data, &data->rfreq, &data->n1, + &data->hs_div); + if (err) + return err; + + /* + * The DCO reg should be accessed with a read-modify-write operation + * per AN334 + */ + regmap_write(data->regmap, SI570_REG_FREEZE_DCO, SI570_FREEZE_DCO); + regmap_write(data->regmap, SI570_REG_HS_N1 + data->div_offset, + ((data->hs_div - HS_DIV_OFFSET) << HS_DIV_SHIFT) | + (((data->n1 - 1) >> 2) & N1_6_2_MASK)); + si570_update_rfreq(data); + regmap_write(data->regmap, SI570_REG_FREEZE_DCO, 0); + regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_NEWFREQ); + + /* Applying a new frequency can take up to 10ms */ + usleep_range(10000, 12000); + + return 0; +} + +/** + * si570_set_frequency_small() - Adjust output frequency + * @data: Driver data structure + * @frequency: Target frequency + * Returns 0 on success. + * + * Update output frequency for small frequency changes (< 3,500 ppm). + */ +static int si570_set_frequency_small(struct clk_si570 *data, + unsigned long frequency) +{ + /* + * This is a re-implementation of DIV_ROUND_CLOSEST + * using the div64_u64 function lieu of letting the compiler + * insert EABI calls + */ + data->rfreq = div64_u64((data->rfreq * frequency) + + div_u64(data->frequency, 2), data->frequency); + regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_FREEZE_M); + si570_update_rfreq(data); + regmap_write(data->regmap, SI570_REG_CONTROL, 0); + + /* Applying a new frequency (small change) can take up to 100us */ + usleep_range(100, 200); + + return 0; +} + +static int si570_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_si570 *data = to_clk_si570(hw); + struct i2c_client *client = data->i2c_client; + int err; + + if (rate < SI570_MIN_FREQ || rate > data->max_freq) { + dev_err(&client->dev, + "requested frequency %lu Hz is out of range\n", rate); + return -EINVAL; + } + + if (div64_u64(abs(rate - data->frequency) * 10000LL, + data->frequency) < 35) + err = si570_set_frequency_small(data, rate); + else + err = si570_set_frequency(data, rate); + + if (err) + return err; + + data->frequency = rate; + + return 0; +} + +static const struct clk_ops si570_clk_ops = { + .recalc_rate = si570_recalc_rate, + .round_rate = si570_round_rate, + .set_rate = si570_set_rate, +}; + +static bool si570_regmap_is_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case SI570_REG_CONTROL: + return true; + default: + return false; + } +} + +static bool si570_regmap_is_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case SI570_REG_HS_N1 ... (SI570_REG_RFREQ4 + SI570_DIV_OFFSET_7PPM): + case SI570_REG_CONTROL: + case SI570_REG_FREEZE_DCO: + return true; + default: + return false; + } +} + +static struct regmap_config si570_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .max_register = 137, + .writeable_reg = si570_regmap_is_writeable, + .volatile_reg = si570_regmap_is_volatile, +}; + +static int si570_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct clk_si570 *data; + struct clk_init_data init; + struct clk *clk; + u32 initial_fout, factory_fout, stability; + int err; + enum clk_si570_variant variant = id->driver_data; + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + init.ops = &si570_clk_ops; + init.flags = CLK_IS_ROOT; + init.num_parents = 0; + data->hw.init = &init; + data->i2c_client = client; + + if (variant == si57x) { + err = of_property_read_u32(client->dev.of_node, + "temperature-stability", &stability); + if (err) { + dev_err(&client->dev, + "'temperature-stability' property missing\n"); + return err; + } + /* adjust register offsets for 7ppm devices */ + if (stability == 7) + data->div_offset = SI570_DIV_OFFSET_7PPM; + + data->max_freq = SI570_MAX_FREQ; + } else { + data->max_freq = SI598_MAX_FREQ; + } + + if (of_property_read_string(client->dev.of_node, "clock-output-names", + &init.name)) + init.name = client->dev.of_node->name; + + err = of_property_read_u32(client->dev.of_node, "factory-fout", + &factory_fout); + if (err) { + dev_err(&client->dev, "'factory-fout' property missing\n"); + return err; + } + + data->regmap = devm_regmap_init_i2c(client, &si570_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(&client->dev, "failed to allocate register map\n"); + return PTR_ERR(data->regmap); + } + + i2c_set_clientdata(client, data); + err = si570_get_defaults(data, factory_fout); + if (err) + return err; + + clk = devm_clk_register(&client->dev, &data->hw); + if (IS_ERR(clk)) { + dev_err(&client->dev, "clock registration failed\n"); + return PTR_ERR(clk); + } + err = of_clk_add_provider(client->dev.of_node, of_clk_src_simple_get, + clk); + if (err) { + dev_err(&client->dev, "unable to add clk provider\n"); + return err; + } + + /* Read the requested initial output frequency from device tree */ + if (!of_property_read_u32(client->dev.of_node, "clock-frequency", + &initial_fout)) { + err = clk_set_rate(clk, initial_fout); + if (err) { + of_clk_del_provider(client->dev.of_node); + return err; + } + } + + /* Display a message indicating that we've successfully registered */ + dev_info(&client->dev, "registered, current frequency %llu Hz\n", + data->frequency); + + return 0; +} + +static int si570_remove(struct i2c_client *client) +{ + of_clk_del_provider(client->dev.of_node); + return 0; +} + +static const struct i2c_device_id si570_id[] = { + { "si570", si57x }, + { "si571", si57x }, + { "si598", si59x }, + { "si599", si59x }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si570_id); + +static const struct of_device_id clk_si570_of_match[] = { + { .compatible = "silabs,si570" }, + { .compatible = "silabs,si571" }, + { .compatible = "silabs,si598" }, + { .compatible = "silabs,si599" }, + { }, +}; +MODULE_DEVICE_TABLE(of, clk_si570_of_match); + +static struct i2c_driver si570_driver = { + .driver = { + .name = "si570", + .of_match_table = of_match_ptr(clk_si570_of_match), + }, + .probe = si570_probe, + .remove = si570_remove, + .id_table = si570_id, +}; +module_i2c_driver(si570_driver); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_AUTHOR("Soeren Brinkmann Date: Sat, 14 Dec 2013 01:41:55 -0800 Subject: Input: zforce - fix possible driver hang during suspend handle_level_irq masks the interrupt before handling it, and only unmasks it after the handler is finished. So when a touch event happens after threads are suspended, but before the system is fully asleep the irq handler tries to wakeup the thread which will only happen on the next resume, resulting in the wakeup event never being sent and the driver not being able to wake the system from sleep due to the masked irq. Therefore move the wakeup_event to a small non-threaded handler. Signed-off-by: Heiko Stuebner Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/zforce_ts.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 75762d6ff3ba..aa127ba392a4 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -455,7 +455,18 @@ static void zforce_complete(struct zforce_ts *ts, int cmd, int result) } } -static irqreturn_t zforce_interrupt(int irq, void *dev_id) +static irqreturn_t zforce_irq(int irq, void *dev_id) +{ + struct zforce_ts *ts = dev_id; + struct i2c_client *client = ts->client; + + if (ts->suspended && device_may_wakeup(&client->dev)) + pm_wakeup_event(&client->dev, 500); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t zforce_irq_thread(int irq, void *dev_id) { struct zforce_ts *ts = dev_id; struct i2c_client *client = ts->client; @@ -465,12 +476,10 @@ static irqreturn_t zforce_interrupt(int irq, void *dev_id) u8 *payload; /* - * When suspended, emit a wakeup signal if necessary and return. + * When still suspended, return. * Due to the level-interrupt we will get re-triggered later. */ if (ts->suspended) { - if (device_may_wakeup(&client->dev)) - pm_wakeup_event(&client->dev, 500); msleep(20); return IRQ_HANDLED; } @@ -763,8 +772,8 @@ static int zforce_probe(struct i2c_client *client, * Therefore we can trigger the interrupt anytime it is low and do * not need to limit it to the interrupt edge. */ - ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, - zforce_interrupt, + ret = devm_request_threaded_irq(&client->dev, client->irq, + zforce_irq, zforce_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, input_dev->name, ts); if (ret) { -- cgit v1.2.3 From 9222d8069d3812400b346ebd5fea47b8b88c7cbf Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 15 Dec 2013 02:25:55 -0800 Subject: Input: cyttsp - include appropriate header file in cyttsp_i2c_common.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include cyttsp4_core.h in cyttsp_i2c_common.c to ensure that implementation of cyttsp_i2c_read_block_data() and cyttsp_i2c_write_block_data() match what the rest of the driver expects. Thus, it also eliminates the following warning in cyttsp_i2c_common.c: drivers/input/touchscreen/cyttsp_i2c_common.c:34:5: warning: no previous prototype for ‘cyttsp_i2c_read_block_data’ [-Wmissing-prototypes] drivers/input/touchscreen/cyttsp_i2c_common.c:64:5: warning: no previous prototype for ‘cyttsp_i2c_write_block_data’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_i2c_common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c index 1d7b6f154168..ccefa56ca212 100644 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ b/drivers/input/touchscreen/cyttsp_i2c_common.c @@ -31,6 +31,8 @@ #include #include +#include "cyttsp4_core.h" + int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, void *values) { -- cgit v1.2.3 From 12a5a8fdfbab14427df0eb6e6c05559444ee2c73 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 15 Dec 2013 03:43:06 -0800 Subject: Input: pm8xxx-vibrator - switch to using managed resources Simplify the error paths and reduce the lines of code in this driver by using the devm_* APIs. Signed-off-by: Stephen Boyd Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pm8xxx-vibrator.c | 43 ++++++++++-------------------------- 1 file changed, 12 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index ec086f6f3cc3..50be8abb7d0c 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -186,13 +186,13 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) int error; u8 val; - vib = kzalloc(sizeof(*vib), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!vib || !input_dev) { - dev_err(&pdev->dev, "couldn't allocate memory\n"); - error = -ENOMEM; - goto err_free_mem; - } + vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) + return -ENOMEM; INIT_WORK(&vib->work, pm8xxx_work_handler); vib->dev = &pdev->dev; @@ -201,17 +201,17 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) /* operate in manual mode */ error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); if (error < 0) - goto err_free_mem; + return error; + val &= ~VIB_DRV_EN_MANUAL_MASK; error = pm8xxx_vib_write_u8(vib, val, VIB_DRV); if (error < 0) - goto err_free_mem; + return error; vib->reg_vib_drv = val; input_dev->name = "pm8xxx_vib_ffmemless"; input_dev->id.version = 1; - input_dev->dev.parent = &pdev->dev; input_dev->close = pm8xxx_vib_close; input_set_drvdata(input_dev, vib); input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE); @@ -221,35 +221,17 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) if (error) { dev_err(&pdev->dev, "couldn't register vibrator as FF device\n"); - goto err_free_mem; + return error; } error = input_register_device(input_dev); if (error) { dev_err(&pdev->dev, "couldn't register input device\n"); - goto err_destroy_memless; + return error; } platform_set_drvdata(pdev, vib); return 0; - -err_destroy_memless: - input_ff_destroy(input_dev); -err_free_mem: - input_free_device(input_dev); - kfree(vib); - - return error; -} - -static int pm8xxx_vib_remove(struct platform_device *pdev) -{ - struct pm8xxx_vib *vib = platform_get_drvdata(pdev); - - input_unregister_device(vib->vib_input_dev); - kfree(vib); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -268,7 +250,6 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); static struct platform_driver pm8xxx_vib_driver = { .probe = pm8xxx_vib_probe, - .remove = pm8xxx_vib_remove, .driver = { .name = "pm8xxx-vib", .owner = THIS_MODULE, -- cgit v1.2.3 From 21014b80257846a5561b0d0e8fed47a65edebf46 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 15 Dec 2013 03:46:21 -0800 Subject: Input: pm8xxx-vibrator - migrate to regmap APIs Use the regmap APIs for this driver instead of custom pm8xxx APIs. This breaks this driver's dependency on the pm8xxx APIs and allows us to easily port it to other bus protocols in the future. Signed-off-by: Stephen Boyd Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pm8xxx-vibrator.c | 61 +++++++++--------------------------- 1 file changed, 14 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index 50be8abb7d0c..28251560249d 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #define VIB_DRV 0x4A @@ -35,7 +35,7 @@ * struct pm8xxx_vib - structure to hold vibrator data * @vib_input_dev: input device supporting force feedback * @work: work structure to set the vibration parameters - * @dev: device supporting force feedback + * @regmap: regmap for register read/write * @speed: speed of vibration set from userland * @active: state of vibrator * @level: level of vibration to set in the chip @@ -44,49 +44,13 @@ struct pm8xxx_vib { struct input_dev *vib_input_dev; struct work_struct work; - struct device *dev; + struct regmap *regmap; int speed; int level; bool active; u8 reg_vib_drv; }; -/** - * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip - * @vib: pointer to vibrator structure - * @data: placeholder for data to be read - * @reg: register address - */ -static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib, - u8 *data, u16 reg) -{ - int rc; - - rc = pm8xxx_readb(vib->dev->parent, reg, data); - if (rc < 0) - dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n", - reg, rc); - return rc; -} - -/** - * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip - * @vib: pointer to vibrator structure - * @data: data to write - * @reg: register address - */ -static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, - u8 data, u16 reg) -{ - int rc; - - rc = pm8xxx_writeb(vib->dev->parent, reg, data); - if (rc < 0) - dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n", - reg, rc); - return rc; -} - /** * pm8xxx_vib_set - handler to start/stop vibration * @vib: pointer to vibrator structure @@ -95,14 +59,14 @@ static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) { int rc; - u8 val = vib->reg_vib_drv; + unsigned int val = vib->reg_vib_drv; if (on) val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK); else val &= ~VIB_DRV_SEL_MASK; - rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV); + rc = regmap_write(vib->regmap, VIB_DRV, val); if (rc < 0) return rc; @@ -118,9 +82,9 @@ static void pm8xxx_work_handler(struct work_struct *work) { struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); int rc; - u8 val; + unsigned int val; - rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); + rc = regmap_read(vib->regmap, VIB_DRV, &val); if (rc < 0) return; @@ -184,27 +148,30 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) struct pm8xxx_vib *vib; struct input_dev *input_dev; int error; - u8 val; + unsigned int val; vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL); if (!vib) return -ENOMEM; + vib->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!vib->regmap) + return -ENODEV; + input_dev = devm_input_allocate_device(&pdev->dev); if (!input_dev) return -ENOMEM; INIT_WORK(&vib->work, pm8xxx_work_handler); - vib->dev = &pdev->dev; vib->vib_input_dev = input_dev; /* operate in manual mode */ - error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); + error = regmap_read(vib->regmap, VIB_DRV, &val); if (error < 0) return error; val &= ~VIB_DRV_EN_MANUAL_MASK; - error = pm8xxx_vib_write_u8(vib, val, VIB_DRV); + error = regmap_write(vib->regmap, VIB_DRV, val); if (error < 0) return error; -- cgit v1.2.3 From b27f8fee4965f42405720097af045a8deebd3bcc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 15 Dec 2013 03:14:47 -0800 Subject: Input: pmic8xxx-pwrkey - pass input device directly to interrupt Instead of passing the pointer to the container structure just pass the input device here. This saves a dereference in the fast path. Signed-off-by: Stephen Boyd Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pmic8xxx-pwrkey.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index b49b738aa9c6..d618c58f8a22 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -36,22 +36,22 @@ struct pmic8xxx_pwrkey { int key_press_irq; }; -static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey) +static irqreturn_t pwrkey_press_irq(int irq, void *_pwr) { - struct pmic8xxx_pwrkey *pwrkey = _pwrkey; + struct input_dev *pwr = _pwr; - input_report_key(pwrkey->pwr, KEY_POWER, 1); - input_sync(pwrkey->pwr); + input_report_key(pwr, KEY_POWER, 1); + input_sync(pwr); return IRQ_HANDLED; } -static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey) +static irqreturn_t pwrkey_release_irq(int irq, void *_pwr) { - struct pmic8xxx_pwrkey *pwrkey = _pwrkey; + struct input_dev *pwr = _pwr; - input_report_key(pwrkey->pwr, KEY_POWER, 0); - input_sync(pwrkey->pwr); + input_report_key(pwr, KEY_POWER, 0); + input_sync(pwr); return IRQ_HANDLED; } @@ -154,7 +154,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pwrkey); err = request_irq(key_press_irq, pwrkey_press_irq, - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); + IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwr); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_press_irq, err); @@ -162,7 +162,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) } err = request_irq(key_release_irq, pwrkey_release_irq, - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); + IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwr); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_release_irq, err); @@ -194,8 +194,8 @@ static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); - free_irq(key_press_irq, pwrkey); - free_irq(key_release_irq, pwrkey); + free_irq(key_press_irq, pwrkey->pwr); + free_irq(key_release_irq, pwrkey->pwr); input_unregister_device(pwrkey->pwr); kfree(pwrkey); -- cgit v1.2.3 From 1e63bd9cc43db5400a1423a7ec8266b4e7c54bd0 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sun, 15 Dec 2013 03:24:45 -0800 Subject: Input: pmic8xxx-pwrkey - migrate to regmap APIs Use the regmap APIs for this driver instead of custom pm8xxx APIs. This breaks this driver's dependency on the pm8xxx APIs and allows us to easily port it to other bus protocols in the future. Signed-off-by: Stephen Boyd Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pmic8xxx-pwrkey.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index d618c58f8a22..ef938405a9c6 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -18,9 +18,9 @@ #include #include #include +#include #include -#include #include #define PON_CNTL_1 0x1C @@ -88,7 +88,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; - u8 pon_cntl; + unsigned int pon_cntl; + struct regmap *regmap; struct pmic8xxx_pwrkey *pwrkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -103,6 +104,12 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) return -EINVAL; } + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) { + dev_err(&pdev->dev, "failed to locate regmap for the device\n"); + return -ENODEV; + } + pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; @@ -123,7 +130,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; delay = 1 + ilog2(delay); - err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); + err = regmap_read(regmap, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); goto free_input_dev; @@ -136,7 +143,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) else pon_cntl &= ~PON_CNTL_PULL_UP; - err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); + err = regmap_write(regmap, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); goto free_input_dev; -- cgit v1.2.3 From ce027ed98fd176710fb14be9d6015697b62436f0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 15 Dec 2013 16:18:01 +0100 Subject: firewire: sbp2: bring back WRITE SAME support Commit 54b2b50c20a6 "[SCSI] Disable WRITE SAME for RAID and virtual host adapter drivers" disabled WRITE SAME support for all SBP-2 attached targets. But as described in the changelog of commit b0ea5f19d3d8 "firewire: sbp2: allow WRITE SAME and REPORT SUPPORTED OPERATION CODES", it is not required to blacklist WRITE SAME. Bring the feature back by reverting the sbp2.c hunk of commit 54b2b50c20a6. Signed-off-by: Stefan Richter Cc: stable@kernel.org --- drivers/firewire/sbp2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index b0bb056458a3..281029daf98c 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1623,7 +1623,6 @@ static struct scsi_host_template scsi_driver_template = { .cmd_per_lun = 1, .can_queue = 1, .sdev_attrs = sbp2_scsi_sysfs_attrs, - .no_write_same = 1, }; MODULE_AUTHOR("Kristian Hoegsberg "); -- cgit v1.2.3 From c00850dd6c517169734ec60eed99502c0912a7d3 Mon Sep 17 00:00:00 2001 From: Rashika Date: Sat, 14 Dec 2013 18:42:14 +0530 Subject: RDMA/cxgb4: Make _c4iw_write_mem_dma() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the function _c4iw_write_mem_dma() as static because it is not used outside this file, which fixes the warning: drivers/infiniband/hw/cxgb4/mem.c:176:5: warning: no previous prototype for ‘_c4iw_write_mem_dma’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Acked-by: Steve Wise Reviewed-by: Josh Triplett Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 4cb8eb24497c..84e45006451c 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -173,7 +173,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len, return ret; } -int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data) +static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data) { u32 remain = len; u32 dmalen; -- cgit v1.2.3 From 79db57cef949cfd0fe7f53e30666bd6945ec400a Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 14 Dec 2013 19:28:24 +0530 Subject: amd64_edac: Mark amd64_decode_bus_error as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the function amd64_decode_bus_error() as static because it is not used outside of amd64_edac.c. It also eliminates the following warning: drivers/edac/amd64_edac.c:2038:6: warning: no previous prototype for ‘amd64_decode_bus_error’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Link: http://lkml.kernel.org/r/7cddbd4c69ed493f183383e98853181aaf75b26b.1387029387.git.rashika.kheria@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index a2f1854891f3..6b2542e102e1 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2035,7 +2035,7 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, __log_bus_error(mci, &err, ecc_type); } -void amd64_decode_bus_error(int node_id, struct mce *m) +static void amd64_decode_bus_error(int node_id, struct mce *m) { __amd64_decode_bus_error(mcis[node_id], m); } -- cgit v1.2.3 From df781d0386a3e29c31f1d8eaf845b3224e65dd7f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 15 Dec 2013 17:29:44 +0100 Subject: amd64_edac: Simplify code around decode_bus_error Drop wrapper function and prefixes. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 6b2542e102e1..568e97fc1489 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2005,9 +2005,9 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err, string, ""); } -static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, - struct mce *m) +static inline void decode_bus_error(int node_id, struct mce *m) { + struct mem_ctl_info *mci = mcis[node_id]; struct amd64_pvt *pvt = mci->pvt_info; u8 ecc_type = (m->status >> 45) & 0x3; u8 xec = XEC(m->status, 0x1f); @@ -2035,11 +2035,6 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, __log_bus_error(mci, &err, ecc_type); } -static void amd64_decode_bus_error(int node_id, struct mce *m) -{ - __amd64_decode_bus_error(mcis[node_id], m); -} - /* * Use pvt->F2 which contains the F2 CPU PCI device to get the related * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. @@ -2680,7 +2675,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) if (report_gart_errors) amd_report_gart_errors(true); - amd_register_ecc_decoder(amd64_decode_bus_error); + amd_register_ecc_decoder(decode_bus_error); mcis[nid] = mci; @@ -2777,7 +2772,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev) /* unregister from EDAC MCE */ amd_report_gart_errors(false); - amd_unregister_ecc_decoder(amd64_decode_bus_error); + amd_unregister_ecc_decoder(decode_bus_error); kfree(ecc_stngs[nid]); ecc_stngs[nid] = NULL; -- cgit v1.2.3 From d1ea71cdc9801c829d97eb42204329c28a4b2f52 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 15 Dec 2013 17:54:27 +0100 Subject: amd64_edac: Remove "amd64" prefix from static functions No need for the namespace tagging there. Cleanup setup_pci_device while at it. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 118 ++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 568e97fc1489..98e14ee4833c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1,7 +1,7 @@ #include "amd64_edac.h" #include -static struct edac_pci_ctl_info *amd64_ctl_pci; +static struct edac_pci_ctl_info *pci_ctl; static int report_gart_errors; module_param(report_gart_errors, int, 0644); @@ -162,7 +162,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, * scan the scrub rate mapping table for a close or matching bandwidth value to * issue. If requested is too big, then use last maximum value found. */ -static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) +static int __set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) { u32 scrubval; int i; @@ -198,7 +198,7 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) return 0; } -static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) +static int set_scrub_rate(struct mem_ctl_info *mci, u32 bw) { struct amd64_pvt *pvt = mci->pvt_info; u32 min_scrubrate = 0x5; @@ -210,10 +210,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) if (pvt->fam == 0x15 && pvt->model < 0x10) f15h_select_dct(pvt, 0); - return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); + return __set_scrub_rate(pvt->F3, bw, min_scrubrate); } -static int amd64_get_scrub_rate(struct mem_ctl_info *mci) +static int get_scrub_rate(struct mem_ctl_info *mci) { struct amd64_pvt *pvt = mci->pvt_info; u32 scrubval = 0; @@ -240,8 +240,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) * returns true if the SysAddr given by sys_addr matches the * DRAM base/limit associated with node_id */ -static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, - u8 nid) +static bool base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, u8 nid) { u64 addr; @@ -285,7 +284,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, if (intlv_en == 0) { for (node_id = 0; node_id < DRAM_RANGES; node_id++) { - if (amd64_base_limit_match(pvt, sys_addr, node_id)) + if (base_limit_match(pvt, sys_addr, node_id)) goto found; } goto err_no_match; @@ -309,7 +308,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, } /* sanity test for sys_addr */ - if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { + if (unlikely(!base_limit_match(pvt, sys_addr, node_id))) { amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address" "range for node %d with node interleaving enabled.\n", __func__, sys_addr, node_id); @@ -660,7 +659,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs * are ECC capable. */ -static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt) +static unsigned long determine_edac_cap(struct amd64_pvt *pvt) { u8 bit; unsigned long edac_cap = EDAC_FLAG_NONE; @@ -675,9 +674,9 @@ static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt) return edac_cap; } -static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8); +static void debug_display_dimm_sizes(struct amd64_pvt *, u8); -static void amd64_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) +static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) { edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); @@ -711,7 +710,7 @@ static void dump_misc_regs(struct amd64_pvt *pvt) (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); - amd64_dump_dramcfg_low(pvt, pvt->dclr0, 0); + debug_dump_dramcfg_low(pvt, pvt->dclr0, 0); edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); @@ -722,19 +721,19 @@ static void dump_misc_regs(struct amd64_pvt *pvt) edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); - amd64_debug_display_dimm_sizes(pvt, 0); + debug_display_dimm_sizes(pvt, 0); /* everything below this point is Fam10h and above */ if (pvt->fam == 0xf) return; - amd64_debug_display_dimm_sizes(pvt, 1); + debug_display_dimm_sizes(pvt, 1); amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4")); /* Only if NOT ganged does dclr1 have valid info */ if (!dct_ganging_enabled(pvt)) - amd64_dump_dramcfg_low(pvt, pvt->dclr1, 1); + debug_dump_dramcfg_low(pvt, pvt->dclr1, 1); } /* @@ -800,7 +799,7 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) } } -static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs) +static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs) { enum mem_type type; @@ -1702,7 +1701,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, * debug routine to display the memory sizes of all logical DIMMs and its * CSROWs */ -static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) +static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) { int dimm, size0, size1; u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases; @@ -1744,7 +1743,7 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) } } -static struct amd64_family_type amd64_family_types[] = { +static struct amd64_family_type family_types[] = { [K8_CPUS] = { .ctl_name = "K8", .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, @@ -2191,7 +2190,7 @@ static void read_mc_regs(struct amd64_pvt *pvt) * encompasses * */ -static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) +static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) { u32 cs_mode, nr_pages; u32 dbam = dct ? pvt->dbam1 : pvt->dbam0; @@ -2258,19 +2257,19 @@ static int init_csrows(struct mem_ctl_info *mci) pvt->mc_node_id, i); if (row_dct0) { - nr_pages = amd64_csrow_nr_pages(pvt, 0, i); + nr_pages = get_csrow_nr_pages(pvt, 0, i); csrow->channels[0]->dimm->nr_pages = nr_pages; } /* K8 has only one DCT */ if (pvt->fam != 0xf && row_dct1) { - int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i); + int row_dct1_pages = get_csrow_nr_pages(pvt, 1, i); csrow->channels[1]->dimm->nr_pages = row_dct1_pages; nr_pages += row_dct1_pages; } - mtype = amd64_determine_memory_type(pvt, i); + mtype = determine_memory_type(pvt, i); edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); @@ -2304,7 +2303,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid) } /* check MCG_CTL on all the cpus on this node */ -static bool amd64_nb_mce_bank_enabled_on_node(u16 nid) +static bool nb_mce_bank_enabled_on_node(u16 nid) { cpumask_var_t mask; int cpu, nbe; @@ -2477,7 +2476,7 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid) ecc_en = !!(value & NBCFG_ECC_ENABLE); amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled")); - nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid); + nb_mce_en = nb_mce_bank_enabled_on_node(nid); if (!nb_mce_en) amd64_notice("NB MCE bank disabled, set MSR " "0x%08x[4] on node %d to enable.\n", @@ -2532,7 +2531,7 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci, if (pvt->nbcap & NBCAP_CHIPKILL) mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED; - mci->edac_cap = amd64_determine_edac_cap(pvt); + mci->edac_cap = determine_edac_cap(pvt); mci->mod_name = EDAC_MOD_STR; mci->mod_ver = EDAC_AMD64_VERSION; mci->ctl_name = fam->ctl_name; @@ -2540,14 +2539,14 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci, mci->ctl_page_to_phys = NULL; /* memory scrubber interface */ - mci->set_sdram_scrub_rate = amd64_set_scrub_rate; - mci->get_sdram_scrub_rate = amd64_get_scrub_rate; + mci->set_sdram_scrub_rate = set_scrub_rate; + mci->get_sdram_scrub_rate = get_scrub_rate; } /* * returns a pointer to the family descriptor on success, NULL otherwise. */ -static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) +static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) { struct amd64_family_type *fam_type = NULL; @@ -2558,29 +2557,29 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) switch (pvt->fam) { case 0xf: - fam_type = &amd64_family_types[K8_CPUS]; - pvt->ops = &amd64_family_types[K8_CPUS].ops; + fam_type = &family_types[K8_CPUS]; + pvt->ops = &family_types[K8_CPUS].ops; break; case 0x10: - fam_type = &amd64_family_types[F10_CPUS]; - pvt->ops = &amd64_family_types[F10_CPUS].ops; + fam_type = &family_types[F10_CPUS]; + pvt->ops = &family_types[F10_CPUS].ops; break; case 0x15: if (pvt->model == 0x30) { - fam_type = &amd64_family_types[F15_M30H_CPUS]; - pvt->ops = &amd64_family_types[F15_M30H_CPUS].ops; + fam_type = &family_types[F15_M30H_CPUS]; + pvt->ops = &family_types[F15_M30H_CPUS].ops; break; } - fam_type = &amd64_family_types[F15_CPUS]; - pvt->ops = &amd64_family_types[F15_CPUS].ops; + fam_type = &family_types[F15_CPUS]; + pvt->ops = &family_types[F15_CPUS].ops; break; case 0x16: - fam_type = &amd64_family_types[F16_CPUS]; - pvt->ops = &amd64_family_types[F16_CPUS].ops; + fam_type = &family_types[F16_CPUS]; + pvt->ops = &family_types[F16_CPUS].ops; break; default: @@ -2596,7 +2595,7 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) return fam_type; } -static int amd64_init_one_instance(struct pci_dev *F2) +static int init_one_instance(struct pci_dev *F2) { struct amd64_pvt *pvt = NULL; struct amd64_family_type *fam_type = NULL; @@ -2614,7 +2613,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) pvt->F2 = F2; ret = -EINVAL; - fam_type = amd64_per_family_init(pvt); + fam_type = per_family_init(pvt); if (!fam_type) goto err_free; @@ -2698,8 +2697,8 @@ err_ret: return ret; } -static int amd64_probe_one_instance(struct pci_dev *pdev, - const struct pci_device_id *mc_type) +static int probe_one_instance(struct pci_dev *pdev, + const struct pci_device_id *mc_type) { u16 nid = amd_get_node_id(pdev); struct pci_dev *F3 = node_to_amd_nb(nid)->misc; @@ -2731,7 +2730,7 @@ static int amd64_probe_one_instance(struct pci_dev *pdev, goto err_enable; } - ret = amd64_init_one_instance(pdev); + ret = init_one_instance(pdev); if (ret < 0) { amd64_err("Error probing instance: %d\n", nid); restore_ecc_error_reporting(s, nid, F3); @@ -2747,7 +2746,7 @@ err_out: return ret; } -static void amd64_remove_one_instance(struct pci_dev *pdev) +static void remove_one_instance(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct amd64_pvt *pvt; @@ -2838,8 +2837,8 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table); static struct pci_driver amd64_pci_driver = { .name = EDAC_MOD_STR, - .probe = amd64_probe_one_instance, - .remove = amd64_remove_one_instance, + .probe = probe_one_instance, + .remove = remove_one_instance, .id_table = amd64_pci_table, }; @@ -2848,23 +2847,18 @@ static void setup_pci_device(void) struct mem_ctl_info *mci; struct amd64_pvt *pvt; - if (amd64_ctl_pci) + if (pci_ctl) return; mci = mcis[0]; - if (mci) { - - pvt = mci->pvt_info; - amd64_ctl_pci = - edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); - - if (!amd64_ctl_pci) { - pr_warning("%s(): Unable to create PCI control\n", - __func__); + if (!mci) + return; - pr_warning("%s(): PCI error report via EDAC not set\n", - __func__); - } + pvt = mci->pvt_info; + pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); + if (!pci_ctl) { + pr_warn("%s(): Unable to create PCI control\n", __func__); + pr_warn("%s(): PCI error report via EDAC not set\n", __func__); } } @@ -2920,8 +2914,8 @@ err_ret: static void __exit amd64_edac_exit(void) { - if (amd64_ctl_pci) - edac_pci_release_generic_ctl(amd64_ctl_pci); + if (pci_ctl) + edac_pci_release_generic_ctl(pci_ctl); pci_unregister_driver(&amd64_pci_driver); -- cgit v1.2.3 From 95285933d086271c2e05edd3949a190551625928 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 14 Dec 2013 19:30:11 +0530 Subject: EDAC: Mark edac_create_debug_nodes as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the function edac_create_debug_nodes() as static because it is not used outside of edac_mc_sysfs.c. Thus, it also eliminates the following warning: drivers/edac/edac_mc_sysfs.c:917:5: warning: no previous prototype for ‘edac_create_debug_nodes’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Link: http://lkml.kernel.org/r/a1c863b08c0d6f67d03280cf908c771bf26a3239.1387029387.git.rashika.kheria@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 9f7e0e609516..51c0362acf5c 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -914,7 +914,7 @@ void __exit edac_debugfs_exit(void) debugfs_remove(edac_debugfs); } -int edac_create_debug_nodes(struct mem_ctl_info *mci) +static int edac_create_debug_nodes(struct mem_ctl_info *mci) { struct dentry *d, *parent; char name[80]; -- cgit v1.2.3 From 8112c0cdf7b86f5917cdffcff4ffc477eaa62ed4 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sat, 14 Dec 2013 19:32:09 +0530 Subject: sb_edac: Mark get_mci_for_node_id as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch marks the function get_mci_for_node_id() as static because it is not used outside of sb_edac.c. Thus, it also eliminates the following warning: drivers/edac/sb_edac.c:918:22: warning: no previous prototype for ‘get_mci_for_node_id’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Link: http://lkml.kernel.org/r/0441f508186fc4eeabc8e9c3e4dde013d99405d4.1387029387.git.rashika.kheria@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index b5d254bb4913..747421e03182 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -915,7 +915,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) } } -struct mem_ctl_info *get_mci_for_node_id(u8 node_id) +static struct mem_ctl_info *get_mci_for_node_id(u8 node_id) { struct sbridge_dev *sbridge_dev; -- cgit v1.2.3 From b2b98ea87a8d82d1100200324ace989970a92423 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Sun, 15 Dec 2013 18:25:26 +0100 Subject: HID: microsoft: no fallthrough in MS ergonomy 0xff05 usage For 0xff05 usage in MS ergonomy keyboard quirk, we are falling through and returning 0 instread of properly (because we've performed new mapping) returning 1. Fix that. Reported-by: Joe Perches Signed-off-by: Jiri Kosina --- drivers/hid/hid-microsoft.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 551795b7da1d..c6ef6eed3091 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -73,6 +73,7 @@ static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage, set_bit(KEY_F16, input->keybit); set_bit(KEY_F17, input->keybit); set_bit(KEY_F18, input->keybit); + break; default: return 0; } -- cgit v1.2.3 From 128d6637cce0747e21b8936e449b1c78a497b189 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Mon, 9 Dec 2013 02:17:00 +0000 Subject: iio: cm36651: Changed return value of read function A return value of callback have been changed to IIO_VAL_INT. If not IIO_VAL_INT, driver will print wrong value(*_read_int_time). A follow up patch will deal with a related bug in the new event handling code. Signed-off-by: Beomho Seo Signed-off-by: Jonathan Cameron --- drivers/iio/light/cm36651.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 21df57130018..0922e39b0ea9 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651, return -EINVAL; } - return IIO_VAL_INT_PLUS_MICRO; + return IIO_VAL_INT; } static int cm36651_write_int_time(struct cm36651_data *cm36651, -- cgit v1.2.3 From 968141d2541fea22f921bf643636b3b51177336c Mon Sep 17 00:00:00 2001 From: John Stultz Date: Sat, 14 Dec 2013 12:06:45 -0800 Subject: ion: Don't allow building ION as a module. ION doesn't export the proper symbols for it to be a module. This causes build issues when ION is configured as a module. Since Andorid kernels rarely use modules (I think recent policy requires no modules?), go ahead and set the ION config to a bool from the tristate option. If folks decide ION as a module is important, we will have to go through and export the various needed symbols. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index a342d96ee4f0..b95281eef2aa 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,5 @@ menuconfig ION - tristate "Ion Memory Manager" + bool "Ion Memory Manager" select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER ---help--- -- cgit v1.2.3 From 24b3aa09970304ece816e73c3d7174d0dd315b98 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Sat, 14 Dec 2013 12:06:46 -0800 Subject: ion: Reenable the build Now that ION builds, reenable it in the build. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 29c5ff05abe4..0a01e1914905 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -1,7 +1,6 @@ ccflags-y += -I$(src) # needed for trace events -# ION doesn't build just yet, so disable it from the build -#obj-y += ion/ +obj-y += ion/ obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ASHMEM) += ashmem.o -- cgit v1.2.3 From 6c16dedfd4c49c6a7f410f171c6da3116834a23d Mon Sep 17 00:00:00 2001 From: Chander Kashyap Date: Mon, 2 Dec 2013 07:48:23 +0900 Subject: clocksource: mct: extend mct to support 8 local interrupts for Exynos5420 Exynos5420 is octa-core SoC from Samsung. Hence extend exynos-mct clocksource driver to support 8 local interrupts. Also extend dts entries for 8 interrupts. Signed-off-by: Chander Kashyap Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420.dtsi | 9 +++++++-- drivers/clocksource/exynos_mct.c | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 6ffefd163fa0..f909d82bc453 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -135,7 +135,8 @@ interrupt-controller; #interrups-cells = <1>; interrupt-parent = <&mct_map>; - interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>; + interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>, + <8>, <9>, <10>, <11>; clocks = <&clock 1>, <&clock 315>; clock-names = "fin_pll", "mct"; @@ -150,7 +151,11 @@ <4 &gic 0 120 0>, <5 &gic 0 121 0>, <6 &gic 0 122 0>, - <7 &gic 0 123 0>; + <7 &gic 0 123 0>, + <8 &gic 0 128 0>, + <9 &gic 0 129 0>, + <10 &gic 0 130 0>, + <11 &gic 0 131 0>; }; }; diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 62b0de6a1837..48f76bc05da0 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -71,6 +71,10 @@ enum { MCT_L1_IRQ, MCT_L2_IRQ, MCT_L3_IRQ, + MCT_L4_IRQ, + MCT_L5_IRQ, + MCT_L6_IRQ, + MCT_L7_IRQ, MCT_NR_IRQS, }; -- cgit v1.2.3 From 1a84b99ccbb954ce201024691babfe4d7d9f506f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 14 Dec 2013 13:06:07 -0700 Subject: PCI: pciehp: Remove error checks when accessing PCIe Capability There's not much point in checking the return value from every config space access because the only likely errors are design-time things like unaligned accesses or invalid register numbers. The checking clutters the code significantly, so this patch removes it. No functional change. Reference: http://lkml.kernel.org/r/CA+55aFzP4xEbcNmZ+MS0SQ3LrULzSq+dBiT_X9U-bPpR-Ukgrw@mail.gmail.com Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 177 +++++++++------------------------------ 1 file changed, 41 insertions(+), 136 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 53bb5501d199..6afdd2358227 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -112,10 +112,10 @@ static int pcie_poll_cmd(struct controller *ctrl) { struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; - int err, timeout = 1000; + int timeout = 1000; - err = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); + if (slot_status & PCI_EXP_SLTSTA_CC) { pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); return 1; @@ -123,9 +123,8 @@ static int pcie_poll_cmd(struct controller *ctrl) while (timeout > 0) { msleep(10); timeout -= 10; - err = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, - &slot_status); - if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); + if (slot_status & PCI_EXP_SLTSTA_CC) { pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); return 1; @@ -157,19 +156,12 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll) static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) { struct pci_dev *pdev = ctrl_dev(ctrl); - int retval = 0; u16 slot_status; u16 slot_ctrl; mutex_lock(&ctrl->ctrl_lock); - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", - __func__); - goto out; - } - + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (slot_status & PCI_EXP_SLTSTA_CC) { if (!ctrl->no_cmd_complete) { /* @@ -193,24 +185,17 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) } } - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); - goto out; - } - + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); slot_ctrl &= ~mask; slot_ctrl |= (cmd & mask); ctrl->cmd_busy = 1; smp_mb(); - retval = pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); - if (retval) - ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); + pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); /* * Wait for command completion. */ - if (!retval && !ctrl->no_cmd_complete) { + if (!ctrl->no_cmd_complete) { int poll = 0; /* * if hotplug interrupt is not enabled or command @@ -222,20 +207,17 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) poll = 1; pcie_wait_cmd(ctrl, poll); } - out: mutex_unlock(&ctrl->ctrl_lock); - return retval; + return 0; } static bool check_link_active(struct controller *ctrl) { struct pci_dev *pdev = ctrl_dev(ctrl); - bool ret = false; u16 lnk_status; + bool ret; - if (pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status)) - return ret; - + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); if (ret) @@ -299,9 +281,8 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) int pciehp_check_link_status(struct controller *ctrl) { struct pci_dev *pdev = ctrl_dev(ctrl); + bool found; u16 lnk_status; - int retval = 0; - bool found = false; /* * Data Link Layer Link Active Reporting must be capable for @@ -318,53 +299,37 @@ int pciehp_check_link_status(struct controller *ctrl) found = pci_bus_check_dev(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); - retval = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); - if (retval) { - ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); - return retval; - } - + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); if ((lnk_status & PCI_EXP_LNKSTA_LT) || !(lnk_status & PCI_EXP_LNKSTA_NLW)) { ctrl_err(ctrl, "Link Training Error occurs \n"); - retval = -1; - return retval; + return -1; } pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); - if (!found && !retval) - retval = -1; + if (!found) + return -1; - return retval; + return 0; } static int __pciehp_link_set(struct controller *ctrl, bool enable) { struct pci_dev *pdev = ctrl_dev(ctrl); u16 lnk_ctrl; - int retval = 0; - retval = pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl); - if (retval) { - ctrl_err(ctrl, "Cannot read LNKCTRL register\n"); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl); if (enable) lnk_ctrl &= ~PCI_EXP_LNKCTL_LD; else lnk_ctrl |= PCI_EXP_LNKCTL_LD; - retval = pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl); - if (retval) { - ctrl_err(ctrl, "Cannot write LNKCTRL register\n"); - return retval; - } + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl); ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); - - return retval; + return 0; } static int pciehp_link_enable(struct controller *ctrl) @@ -383,14 +348,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status) struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; u8 atten_led_state; - int retval = 0; - - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); @@ -423,13 +382,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; u8 pwr_state; - int retval = 0; - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); @@ -447,55 +401,35 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) break; } - return retval; + return 0; } int pciehp_get_latch_status(struct slot *slot, u8 *status) { - struct controller *ctrl = slot->ctrl; - struct pci_dev *pdev = ctrl_dev(ctrl); + struct pci_dev *pdev = ctrl_dev(slot->ctrl); u16 slot_status; - int retval; - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", - __func__); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); return 0; } int pciehp_get_adapter_status(struct slot *slot, u8 *status) { - struct controller *ctrl = slot->ctrl; - struct pci_dev *pdev = ctrl_dev(ctrl); + struct pci_dev *pdev = ctrl_dev(slot->ctrl); u16 slot_status; - int retval; - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", - __func__); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); *status = !!(slot_status & PCI_EXP_SLTSTA_PDS); return 0; } int pciehp_query_power_fault(struct slot *slot) { - struct controller *ctrl = slot->ctrl; - struct pci_dev *pdev = ctrl_dev(ctrl); + struct pci_dev *pdev = ctrl_dev(slot->ctrl); u16 slot_status; - int retval; - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (retval) { - ctrl_err(ctrl, "Cannot check for power fault\n"); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); return !!(slot_status & PCI_EXP_SLTSTA_PFD); } @@ -570,25 +504,13 @@ int pciehp_power_on_slot(struct slot * slot) u16 slot_cmd; u16 cmd_mask; u16 slot_status; - int retval = 0; + int retval; /* Clear sticky power-fault bit from previous power failures */ - retval = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", - __func__); - return retval; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); slot_status &= PCI_EXP_SLTSTA_PFD; - if (slot_status) { - retval = pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, slot_status); - if (retval) { - ctrl_err(ctrl, - "%s: Cannot write to SLOTSTATUS register\n", - __func__); - return retval; - } - } + if (slot_status) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, slot_status); ctrl->power_fault_detected = 0; slot_cmd = POWER_ON; @@ -649,12 +571,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) */ intr_loc = 0; do { - if (pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, - &detected)) { - ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n", - __func__); - return IRQ_NONE; - } + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected); detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | @@ -663,13 +580,9 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) intr_loc |= detected; if (!intr_loc) return IRQ_NONE; - if (detected && - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, - intr_loc)) { - ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", - __func__); - return IRQ_NONE; - } + if (detected) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + intr_loc); } while (detected); ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); @@ -894,11 +807,7 @@ struct controller *pcie_init(struct pcie_device *dev) goto abort; } ctrl->pcie = dev; - if (pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap)) { - ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); - goto abort_ctrl; - } - + pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); ctrl->slot_cap = slot_cap; mutex_init(&ctrl->ctrl_lock); init_waitqueue_head(&ctrl->queue); @@ -914,18 +823,14 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->no_cmd_complete = 1; /* Check if Data Link Layer Link Active Reporting is implemented */ - if (pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap)) { - ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); - goto abort_ctrl; - } + pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { ctrl_dbg(ctrl, "Link Active Reporting supported\n"); ctrl->link_active_reporting = 1; } /* Clear all remaining event bits in Slot Status register */ - if (pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, 0x1f)) - goto abort_ctrl; + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, 0x1f); /* Disable software notification */ pcie_disable_notification(ctrl); -- cgit v1.2.3 From 6dae62020f0e6a2ffe424c8cea542fa49d42ec6e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 14 Dec 2013 13:06:16 -0700 Subject: PCI: pciehp: Make various functions void since they can't fail These functions: pcie_enable_notification() pciehp_power_off_slot() pciehp_get_power_status() pciehp_get_attention_status() pciehp_set_attention_status() pciehp_get_latch_status() pciehp_get_adapter_status() pcie_write_cmd() now always return success, so this patch makes them void and drops the error-checking code in their callers. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp.h | 14 +++++----- drivers/pci/hotplug/pciehp_core.c | 15 +++++++---- drivers/pci/hotplug/pciehp_ctrl.c | 52 +++++++++++++----------------------- drivers/pci/hotplug/pciehp_hpc.c | 56 +++++++++++---------------------------- drivers/pci/hotplug/pciehp_pci.c | 6 ++--- 5 files changed, 54 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 21e865ded1dc..ffe6a6b336cf 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -140,15 +140,15 @@ struct controller *pcie_init(struct pcie_device *dev); int pcie_init_notification(struct controller *ctrl); int pciehp_enable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot); -int pcie_enable_notification(struct controller *ctrl); +void pcie_enable_notification(struct controller *ctrl); int pciehp_power_on_slot(struct slot *slot); -int pciehp_power_off_slot(struct slot *slot); -int pciehp_get_power_status(struct slot *slot, u8 *status); -int pciehp_get_attention_status(struct slot *slot, u8 *status); +void pciehp_power_off_slot(struct slot *slot); +void pciehp_get_power_status(struct slot *slot, u8 *status); +void pciehp_get_attention_status(struct slot *slot, u8 *status); -int pciehp_set_attention_status(struct slot *slot, u8 status); -int pciehp_get_latch_status(struct slot *slot, u8 *status); -int pciehp_get_adapter_status(struct slot *slot, u8 *status); +void pciehp_set_attention_status(struct slot *slot, u8 status); +void pciehp_get_latch_status(struct slot *slot, u8 *status); +void pciehp_get_adapter_status(struct slot *slot, u8 *status); int pciehp_query_power_fault(struct slot *slot); void pciehp_green_led_on(struct slot *slot); void pciehp_green_led_off(struct slot *slot); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index bbd48bbe4e9b..143a389d81fa 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -160,7 +160,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - return pciehp_set_attention_status(slot, status); + pciehp_set_attention_status(slot, status); + return 0; } @@ -192,7 +193,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - return pciehp_get_power_status(slot, value); + pciehp_get_power_status(slot, value); + return 0; } static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -202,7 +204,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - return pciehp_get_attention_status(slot, value); + pciehp_get_attention_status(slot, value); + return 0; } static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -212,7 +215,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - return pciehp_get_latch_status(slot, value); + pciehp_get_latch_status(slot, value); + return 0; } static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -222,7 +226,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", __func__, slot_name(slot)); - return pciehp_get_adapter_status(slot, value); + pciehp_get_adapter_status(slot, value); + return 0; } static int reset_slot(struct hotplug_slot *hotplug_slot, int probe) diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 38f018679175..6c730b161b33 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -158,11 +158,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) { /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ if (POWER_CTRL(ctrl)) { - if (pciehp_power_off_slot(pslot)) { - ctrl_err(ctrl, - "Issue of Slot Power Off command failed\n"); - return; - } + pciehp_power_off_slot(pslot); + /* * After turning power off, we must wait for at least 1 second * before taking any action that relies on power having been @@ -174,13 +171,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (PWR_LED(ctrl)) pciehp_green_led_off(pslot); - if (ATTN_LED(ctrl)) { - if (pciehp_set_attention_status(pslot, 1)) { - ctrl_err(ctrl, - "Issue of Set Attention Led command failed\n"); - return; - } - } + if (ATTN_LED(ctrl)) + pciehp_set_attention_status(pslot, 1); } /** @@ -243,7 +235,7 @@ err_exit: */ static int remove_board(struct slot *p_slot) { - int retval = 0; + int retval; struct controller *ctrl = p_slot->ctrl; retval = pciehp_unconfigure_device(p_slot); @@ -251,13 +243,8 @@ static int remove_board(struct slot *p_slot) return retval; if (POWER_CTRL(ctrl)) { - /* power off slot */ - retval = pciehp_power_off_slot(p_slot); - if (retval) { - ctrl_err(ctrl, - "Issue of Slot Disable command failed\n"); - return retval; - } + pciehp_power_off_slot(p_slot); + /* * After turning power off, we must wait for at least 1 second * before taking any action that relies on power having been @@ -482,14 +469,14 @@ int pciehp_enable_slot(struct slot *p_slot) int rc; struct controller *ctrl = p_slot->ctrl; - rc = pciehp_get_adapter_status(p_slot, &getstatus); - if (rc || !getstatus) { + pciehp_get_adapter_status(p_slot, &getstatus); + if (!getstatus) { ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); return -ENODEV; } if (MRL_SENS(p_slot->ctrl)) { - rc = pciehp_get_latch_status(p_slot, &getstatus); - if (rc || getstatus) { + pciehp_get_latch_status(p_slot, &getstatus); + if (getstatus) { ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); return -ENODEV; @@ -497,8 +484,8 @@ int pciehp_enable_slot(struct slot *p_slot) } if (POWER_CTRL(p_slot->ctrl)) { - rc = pciehp_get_power_status(p_slot, &getstatus); - if (rc || getstatus) { + pciehp_get_power_status(p_slot, &getstatus); + if (getstatus) { ctrl_info(ctrl, "Already enabled on slot(%s)\n", slot_name(p_slot)); return -EINVAL; @@ -518,15 +505,14 @@ int pciehp_enable_slot(struct slot *p_slot) int pciehp_disable_slot(struct slot *p_slot) { u8 getstatus = 0; - int ret = 0; struct controller *ctrl = p_slot->ctrl; if (!p_slot->ctrl) return 1; if (!HP_SUPR_RM(p_slot->ctrl)) { - ret = pciehp_get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { + pciehp_get_adapter_status(p_slot, &getstatus); + if (!getstatus) { ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); return -ENODEV; @@ -534,8 +520,8 @@ int pciehp_disable_slot(struct slot *p_slot) } if (MRL_SENS(p_slot->ctrl)) { - ret = pciehp_get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { + pciehp_get_latch_status(p_slot, &getstatus); + if (getstatus) { ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot)); return -ENODEV; @@ -543,8 +529,8 @@ int pciehp_disable_slot(struct slot *p_slot) } if (POWER_CTRL(p_slot->ctrl)) { - ret = pciehp_get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { + pciehp_get_power_status(p_slot, &getstatus); + if (!getstatus) { ctrl_info(ctrl, "Already disabled on slot(%s)\n", slot_name(p_slot)); return -EINVAL; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 6afdd2358227..83df74910f9a 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -153,7 +153,7 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll) * @cmd: command value written to slot control register * @mask: bitmask of slot control register to be modified */ -static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) +static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) { struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; @@ -208,7 +208,6 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) pcie_wait_cmd(ctrl, poll); } mutex_unlock(&ctrl->ctrl_lock); - return 0; } static bool check_link_active(struct controller *ctrl) @@ -342,7 +341,7 @@ static int pciehp_link_disable(struct controller *ctrl) return __pciehp_link_set(ctrl, false); } -int pciehp_get_attention_status(struct slot *slot, u8 *status) +void pciehp_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); @@ -372,11 +371,9 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status) *status = 0xFF; break; } - - return 0; } -int pciehp_get_power_status(struct slot *slot, u8 *status) +void pciehp_get_power_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); @@ -400,28 +397,24 @@ int pciehp_get_power_status(struct slot *slot, u8 *status) *status = 0xFF; break; } - - return 0; } -int pciehp_get_latch_status(struct slot *slot, u8 *status) +void pciehp_get_latch_status(struct slot *slot, u8 *status) { struct pci_dev *pdev = ctrl_dev(slot->ctrl); u16 slot_status; pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); - return 0; } -int pciehp_get_adapter_status(struct slot *slot, u8 *status) +void pciehp_get_adapter_status(struct slot *slot, u8 *status) { struct pci_dev *pdev = ctrl_dev(slot->ctrl); u16 slot_status; pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); *status = !!(slot_status & PCI_EXP_SLTSTA_PDS); - return 0; } int pciehp_query_power_fault(struct slot *slot) @@ -433,7 +426,7 @@ int pciehp_query_power_fault(struct slot *slot) return !!(slot_status & PCI_EXP_SLTSTA_PFD); } -int pciehp_set_attention_status(struct slot *slot, u8 value) +void pciehp_set_attention_status(struct slot *slot, u8 value) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; @@ -451,11 +444,11 @@ int pciehp_set_attention_status(struct slot *slot, u8 value) slot_cmd = 0x0080; break; default: - return -EINVAL; + return; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); - return pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, slot_cmd, cmd_mask); } void pciehp_green_led_on(struct slot *slot) @@ -515,11 +508,7 @@ int pciehp_power_on_slot(struct slot * slot) slot_cmd = POWER_ON; cmd_mask = PCI_EXP_SLTCTL_PCC; - retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - if (retval) { - ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); - return retval; - } + pcie_write_cmd(ctrl, slot_cmd, cmd_mask); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); @@ -530,12 +519,11 @@ int pciehp_power_on_slot(struct slot * slot) return retval; } -int pciehp_power_off_slot(struct slot * slot) +void pciehp_power_off_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; - int retval; /* Disable the link at first */ pciehp_link_disable(ctrl); @@ -547,14 +535,9 @@ int pciehp_power_off_slot(struct slot * slot) slot_cmd = POWER_OFF; cmd_mask = PCI_EXP_SLTCTL_PCC; - retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - if (retval) { - ctrl_err(ctrl, "Write command failed!\n"); - return retval; - } + pcie_write_cmd(ctrl, slot_cmd, cmd_mask); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); - return 0; } static irqreturn_t pcie_isr(int irq, void *dev_id) @@ -617,7 +600,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) return IRQ_HANDLED; } -int pcie_enable_notification(struct controller *ctrl) +void pcie_enable_notification(struct controller *ctrl) { u16 cmd, mask; @@ -643,22 +626,18 @@ int pcie_enable_notification(struct controller *ctrl) PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); - if (pcie_write_cmd(ctrl, cmd, mask)) { - ctrl_err(ctrl, "Cannot enable software notification\n"); - return -1; - } - return 0; + pcie_write_cmd(ctrl, cmd, mask); } static void pcie_disable_notification(struct controller *ctrl) { u16 mask; + mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_DLLSCE); - if (pcie_write_cmd(ctrl, 0, mask)) - ctrl_warn(ctrl, "Cannot disable software notification\n"); + pcie_write_cmd(ctrl, 0, mask); } /* @@ -698,10 +677,7 @@ int pcie_init_notification(struct controller *ctrl) { if (pciehp_request_irq(ctrl)) return -1; - if (pcie_enable_notification(ctrl)) { - pciehp_free_irq(ctrl); - return -1; - } + pcie_enable_notification(ctrl); ctrl->notification_enabled = 1; return 0; } diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 0e0d0f7f63fd..198355112ee7 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -78,7 +78,7 @@ int pciehp_configure_device(struct slot *p_slot) int pciehp_unconfigure_device(struct slot *p_slot) { - int ret, rc = 0; + int rc = 0; u8 bctl = 0; u8 presence = 0; struct pci_dev *dev, *temp; @@ -88,9 +88,7 @@ int pciehp_unconfigure_device(struct slot *p_slot) ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n", __func__, pci_domain_nr(parent), parent->number); - ret = pciehp_get_adapter_status(p_slot, &presence); - if (ret) - presence = 0; + pciehp_get_adapter_status(p_slot, &presence); /* * Stopping an SR-IOV PF device removes all the associated VFs, -- cgit v1.2.3 From afe2478f2e3fffc45a1be24ebfc23945a66a80fd Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 14 Dec 2013 13:06:36 -0700 Subject: PCI: pciehp: Announce slot capabilities (slot #, button, LEDs, etc) We already have the vendor/device IDs from pci_setup_device(), so drop that info and print things that will be more useful for debugging: the slot number and presence of button/indicators/link active reporting/etc. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 83df74910f9a..55109d6d8a90 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -771,6 +771,8 @@ static inline void dbg_ctrl(struct controller *ctrl) ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16); } +#define FLAG(x,y) (((x) & (y)) ? '+' : '-') + struct controller *pcie_init(struct pcie_device *dev) { struct controller *ctrl; @@ -811,9 +813,16 @@ struct controller *pcie_init(struct pcie_device *dev) /* Disable software notification */ pcie_disable_notification(ctrl); - ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", - pdev->vendor, pdev->device, pdev->subsystem_vendor, - pdev->subsystem_device); + ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n", + (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, + FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), + FLAG(slot_cap, PCI_EXP_SLTCAP_AIP), + FLAG(slot_cap, PCI_EXP_SLTCAP_PIP), + FLAG(slot_cap, PCI_EXP_SLTCAP_PCP), + FLAG(slot_cap, PCI_EXP_SLTCAP_MRLSP), + FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), + FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), + FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC)); if (pcie_init_slot(ctrl)) goto abort_ctrl; -- cgit v1.2.3 From 6b59ba609bb61e4fa2ecca7827f170ac07842d64 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Thu, 21 Nov 2013 15:40:14 -0600 Subject: RDMA/iwcm: Don't touch cm_id after deref in rem_ref rem_ref() calls iwcm_deref_id(), which will wake up any blockers on cm_id_priv->destroy_comp if the refcnt hits 0. That will unblock someone in iw_destroy_cm_id() which will free the cmid. If that happens before rem_ref() calls test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags), then the test_bit() will touch freed memory. The fix is to read the bit first, then deref. We should never be in iw_destroy_cm_id() with IWCM_F_CALLBACK_DESTROY set, and there is a BUG_ON() to make sure of that. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/core/iwcm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index c47c2034ca71..0717940ec3b5 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id) static void rem_ref(struct iw_cm_id *cm_id) { struct iwcm_id_private *cm_id_priv; + int cb_destroy; + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - if (iwcm_deref_id(cm_id_priv) && - test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) { + + /* + * Test bit before deref in case the cm_id gets freed on another + * thread. + */ + cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); + if (iwcm_deref_id(cm_id_priv) && cb_destroy) { BUG_ON(!list_empty(&cm_id_priv->work_list)); free_cm_id(cm_id_priv); } -- cgit v1.2.3 From 2f2ed41cf43e22686349ecdf4ca247ea3831af55 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 14 Dec 2013 13:06:40 -0700 Subject: PCI: pciehp: Simplify "Power Fault Detected" checking/clearing It's simpler to test the PCI_EXP_SLTSTA_PFD bit directly and to write the constant back to PCI_EXP_SLTSTA. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 55109d6d8a90..cb3100af7e8c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -501,9 +501,9 @@ int pciehp_power_on_slot(struct slot * slot) /* Clear sticky power-fault bit from previous power failures */ pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - slot_status &= PCI_EXP_SLTSTA_PFD; - if (slot_status) - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, slot_status); + if (slot_status & PCI_EXP_SLTSTA_PFD) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PFD); ctrl->power_fault_detected = 0; slot_cmd = POWER_ON; -- cgit v1.2.3 From df72648c4d61d6d0ce033c0467a9fabec670fe46 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 14 Dec 2013 13:06:47 -0700 Subject: PCI: pciehp: Use symbolic constants, not hard-coded bitmask Use the PCI_EXP_SLTSTA definitions, not 0x1f, when clearing Slot Status bits. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index cb3100af7e8c..915bb35f9180 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -808,7 +808,10 @@ struct controller *pcie_init(struct pcie_device *dev) } /* Clear all remaining event bits in Slot Status register */ - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, 0x1f); + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | + PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | + PCI_EXP_SLTSTA_CC); /* Disable software notification */ pcie_disable_notification(ctrl); -- cgit v1.2.3 From e7b4f0d7841b188423b641cab71d20b1a05234e9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 14 Dec 2013 13:06:53 -0700 Subject: PCI: pciehp: Use symbolic constants for Slot Control fields Add symbolic constants for the PCIe Slot Control indicator and power control fields defined by spec and use them instead of open-coded hex constants. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_hpc.c | 86 +++++++++++++--------------------------- include/uapi/linux/pci_regs.h | 8 ++++ 2 files changed, 36 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 915bb35f9180..05d421cf935e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -46,10 +46,6 @@ static inline struct pci_dev *ctrl_dev(struct controller *ctrl) return ctrl->pcie->port; } -/* Power Control Command */ -#define POWER_ON 0 -#define POWER_OFF PCI_EXP_SLTCTL_PCC - static irqreturn_t pcie_isr(int irq, void *dev_id); static void start_int_poll_timer(struct controller *ctrl, int sec); @@ -346,25 +342,19 @@ void pciehp_get_attention_status(struct slot *slot, u8 *status) struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; - u8 atten_led_state; pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); - atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; - - switch (atten_led_state) { - case 0: - *status = 0xFF; /* Reserved */ - break; - case 1: + switch (slot_ctrl & PCI_EXP_SLTCTL_AIC) { + case PCI_EXP_SLTCTL_ATTN_IND_ON: *status = 1; /* On */ break; - case 2: + case PCI_EXP_SLTCTL_ATTN_IND_BLINK: *status = 2; /* Blink */ break; - case 3: + case PCI_EXP_SLTCTL_ATTN_IND_OFF: *status = 0; /* Off */ break; default: @@ -378,20 +368,17 @@ void pciehp_get_power_status(struct slot *slot, u8 *status) struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; - u8 pwr_state; pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); - pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; - - switch (pwr_state) { - case 0: - *status = 1; + switch (slot_ctrl & PCI_EXP_SLTCTL_PCC) { + case PCI_EXP_SLTCTL_PWR_ON: + *status = 1; /* On */ break; - case 1: - *status = 0; + case PCI_EXP_SLTCTL_PWR_OFF: + *status = 0; /* Off */ break; default: *status = 0xFF; @@ -430,72 +417,59 @@ void pciehp_set_attention_status(struct slot *slot, u8 value) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; - u16 cmd_mask; - cmd_mask = PCI_EXP_SLTCTL_AIC; switch (value) { case 0 : /* turn off */ - slot_cmd = 0x00C0; + slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF; break; case 1: /* turn on */ - slot_cmd = 0x0040; + slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_ON; break; case 2: /* turn blink */ - slot_cmd = 0x0080; + slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_BLINK; break; default: return; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC); } void pciehp_green_led_on(struct slot *slot) { struct controller *ctrl = slot->ctrl; - u16 slot_cmd; - u16 cmd_mask; - slot_cmd = 0x0100; - cmd_mask = PCI_EXP_SLTCTL_PIC; - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, - pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_PWR_IND_ON); } void pciehp_green_led_off(struct slot *slot) { struct controller *ctrl = slot->ctrl; - u16 slot_cmd; - u16 cmd_mask; - slot_cmd = 0x0300; - cmd_mask = PCI_EXP_SLTCTL_PIC; - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, - pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_PWR_IND_OFF); } void pciehp_green_led_blink(struct slot *slot) { struct controller *ctrl = slot->ctrl; - u16 slot_cmd; - u16 cmd_mask; - slot_cmd = 0x0200; - cmd_mask = PCI_EXP_SLTCTL_PIC; - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, - pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_PWR_IND_BLINK); } int pciehp_power_on_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); - u16 slot_cmd; - u16 cmd_mask; u16 slot_status; int retval; @@ -506,11 +480,10 @@ int pciehp_power_on_slot(struct slot * slot) PCI_EXP_SLTSTA_PFD); ctrl->power_fault_detected = 0; - slot_cmd = POWER_ON; - cmd_mask = PCI_EXP_SLTCTL_PCC; - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, - pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_PWR_ON); retval = pciehp_link_enable(ctrl); if (retval) @@ -522,8 +495,6 @@ int pciehp_power_on_slot(struct slot * slot) void pciehp_power_off_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; - u16 slot_cmd; - u16 cmd_mask; /* Disable the link at first */ pciehp_link_disable(ctrl); @@ -533,11 +504,10 @@ void pciehp_power_off_slot(struct slot * slot) else msleep(1000); - slot_cmd = POWER_OFF; - cmd_mask = PCI_EXP_SLTCTL_PCC; - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, - pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); + pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_PWR_OFF); } static irqreturn_t pcie_isr(int irq, void *dev_id) diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 4a98e85438a7..6d03ba42ab23 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -518,8 +518,16 @@ #define PCI_EXP_SLTCTL_CCIE 0x0010 /* Command Completed Interrupt Enable */ #define PCI_EXP_SLTCTL_HPIE 0x0020 /* Hot-Plug Interrupt Enable */ #define PCI_EXP_SLTCTL_AIC 0x00c0 /* Attention Indicator Control */ +#define PCI_EXP_SLTCTL_ATTN_IND_ON 0x0040 /* Attention Indicator on */ +#define PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */ +#define PCI_EXP_SLTCTL_ATTN_IND_OFF 0x00c0 /* Attention Indicator off */ #define PCI_EXP_SLTCTL_PIC 0x0300 /* Power Indicator Control */ +#define PCI_EXP_SLTCTL_PWR_IND_ON 0x0100 /* Power Indicator on */ +#define PCI_EXP_SLTCTL_PWR_IND_BLINK 0x0200 /* Power Indicator blinking */ +#define PCI_EXP_SLTCTL_PWR_IND_OFF 0x0300 /* Power Indicator off */ #define PCI_EXP_SLTCTL_PCC 0x0400 /* Power Controller Control */ +#define PCI_EXP_SLTCTL_PWR_ON 0x0000 /* Power On */ +#define PCI_EXP_SLTCTL_PWR_OFF 0x0400 /* Power Off */ #define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */ #define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */ #define PCI_EXP_SLTSTA 26 /* Slot Status */ -- cgit v1.2.3 From af9ab791e34147952a8b97c998fa257d8292c5d6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sun, 15 Dec 2013 17:23:54 -0700 Subject: PCI: pciehp: Move Attention & Power Indicator support tests to accessors Previously, the caller checked ATTN_LED() or PWR_LED() to see whether the slot has indicators before setting the indicator state. That clutters the caller unnecessarily, so this moves the test inside the callees. The test may not even be necessary; per spec it should be harmless to try to turn on a non-existent LED. But checking first does avoid unnecessary hotplug commands. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_ctrl.c | 42 ++++++++++++--------------------------- drivers/pci/hotplug/pciehp_hpc.c | 12 +++++++++++ 2 files changed, 25 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 6c730b161b33..50628487597d 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -168,11 +168,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) msleep(1000); } - if (PWR_LED(ctrl)) - pciehp_green_led_off(pslot); - - if (ATTN_LED(ctrl)) - pciehp_set_attention_status(pslot, 1); + pciehp_green_led_off(pslot); + pciehp_set_attention_status(pslot, 1); } /** @@ -195,8 +192,7 @@ static int board_added(struct slot *p_slot) return retval; } - if (PWR_LED(ctrl)) - pciehp_green_led_blink(p_slot); + pciehp_green_led_blink(p_slot); /* Check link training status */ retval = pciehp_check_link_status(ctrl); @@ -219,9 +215,7 @@ static int board_added(struct slot *p_slot) goto err_exit; } - if (PWR_LED(ctrl)) - pciehp_green_led_on(p_slot); - + pciehp_green_led_on(p_slot); return 0; err_exit: @@ -254,9 +248,7 @@ static int remove_board(struct slot *p_slot) } /* turn off Green LED */ - if (PWR_LED(ctrl)) - pciehp_green_led_off(p_slot); - + pciehp_green_led_off(p_slot); return 0; } @@ -292,7 +284,7 @@ static void pciehp_power_thread(struct work_struct *work) break; case POWERON_STATE: mutex_unlock(&p_slot->lock); - if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl)) + if (pciehp_enable_slot(p_slot)) pciehp_green_led_off(p_slot); mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; @@ -359,11 +351,8 @@ static void handle_button_press_event(struct slot *p_slot) "press.\n", slot_name(p_slot)); } /* blink green LED and turn off amber */ - if (PWR_LED(ctrl)) - pciehp_green_led_blink(p_slot); - if (ATTN_LED(ctrl)) - pciehp_set_attention_status(p_slot, 0); - + pciehp_green_led_blink(p_slot); + pciehp_set_attention_status(p_slot, 0); queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: @@ -376,14 +365,11 @@ static void handle_button_press_event(struct slot *p_slot) ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); cancel_delayed_work(&p_slot->work); if (p_slot->state == BLINKINGOFF_STATE) { - if (PWR_LED(ctrl)) - pciehp_green_led_on(p_slot); + pciehp_green_led_on(p_slot); } else { - if (PWR_LED(ctrl)) - pciehp_green_led_off(p_slot); + pciehp_green_led_off(p_slot); } - if (ATTN_LED(ctrl)) - pciehp_set_attention_status(p_slot, 0); + pciehp_set_attention_status(p_slot, 0); ctrl_info(ctrl, "PCI slot #%s - action canceled " "due to button press\n", slot_name(p_slot)); p_slot->state = STATIC_STATE; @@ -443,10 +429,8 @@ static void interrupt_event_handler(struct work_struct *work) case INT_POWER_FAULT: if (!POWER_CTRL(ctrl)) break; - if (ATTN_LED(ctrl)) - pciehp_set_attention_status(p_slot, 1); - if (PWR_LED(ctrl)) - pciehp_green_led_off(p_slot); + pciehp_set_attention_status(p_slot, 1); + pciehp_green_led_off(p_slot); break; case INT_PRESENCE_ON: case INT_PRESENCE_OFF: diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 05d421cf935e..14acfccb7670 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -418,6 +418,9 @@ void pciehp_set_attention_status(struct slot *slot, u8 value) struct controller *ctrl = slot->ctrl; u16 slot_cmd; + if (!ATTN_LED(ctrl)) + return; + switch (value) { case 0 : /* turn off */ slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF; @@ -440,6 +443,9 @@ void pciehp_green_led_on(struct slot *slot) { struct controller *ctrl = slot->ctrl; + if (!PWR_LED(ctrl)) + return; + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, @@ -450,6 +456,9 @@ void pciehp_green_led_off(struct slot *slot) { struct controller *ctrl = slot->ctrl; + if (!PWR_LED(ctrl)) + return; + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, @@ -460,6 +469,9 @@ void pciehp_green_led_blink(struct slot *slot) { struct controller *ctrl = slot->ctrl; + if (!PWR_LED(ctrl)) + return; + pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, -- cgit v1.2.3 From b25b4427e9dfba073cf9bc86603956ed395eb6e3 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 11 Dec 2013 22:19:01 -0500 Subject: drm/nouveau: only runtime suspend by default in optimus configuration The intent was to only enable it by default for optimus, e.g. see the runtime_idle callback. The suspend callback may be called directly, e.g. as a result of nouveau_crtc_set_config. Reported-by: Stefan Lippers-Hollmann Signed-off-by: Ilia Mirkin Tested-by: Stefan Lippers-Hollmann Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_drm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 7a3759f1c41a..98a22e6e27a1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev) if (nouveau_runtime_pm == 0) return -EINVAL; + /* are we optimus enabled? */ + if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { + DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); + return -EINVAL; + } + nv_debug_level(SILENT); drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); -- cgit v1.2.3 From b714b84e2b74de68b12847bcaf2cf409a18fb741 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 25 Nov 2013 16:07:46 +0100 Subject: dma: pl330: Alloc dma_parms for the dma device In order to be able to set a maximum segment size for the device we need to allocate a dma_parameters struct for the device first. Signed-off-by: Lars-Peter Clausen Signed-off-by: Vinod Koul --- drivers/dma/pl330.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index cdf0483b8f2d..7adaf3abffba 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -578,6 +578,9 @@ struct dma_pl330_dmac { /* DMA-Engine Device */ struct dma_device ddma; + /* Holds info about sg limitations */ + struct device_dma_parameters dma_parms; + /* Pool of descriptors available for the DMAC's channels */ struct list_head desc_pool; /* To protect desc_pool manipulation */ @@ -3023,6 +3026,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) "unable to register DMA to the generic DT DMA helpers\n"); } } + + adev->dev.dma_parms = &pdmac->dma_parms; + /* * This is the limit for transfers with a buswidth of 1, larger * buswidths will have larger limits. -- cgit v1.2.3 From cd72b8462a2ebbf9524e726c65c2770f0bf70d22 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 13 Nov 2013 22:55:24 +0800 Subject: dma: imx-sdma: Add sdma firmware version 2 support On i.MX5/6 series, SDMA is using new version firmware to support SSI dual FIFO feature and HDMI Audio (i.MX6Q/DL only). Thus add it. Signed-off-by: Nicolin Chen Acked-by: Sascha Hauer Signed-off-by: Vinod Koul --- drivers/dma/imx-sdma.c | 15 ++++++++++++++- include/linux/platform_data/dma-imx-sdma.h | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index c75679d42028..f769c7383536 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -323,6 +323,7 @@ struct sdma_engine { struct clk *clk_ipg; struct clk *clk_ahb; spinlock_t channel_0_lock; + u32 script_number; struct sdma_script_start_addrs *script_addrs; const struct sdma_driver_data *drvdata; }; @@ -1238,6 +1239,7 @@ static void sdma_issue_pending(struct dma_chan *chan) } #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34 +#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 38 static void sdma_add_scripts(struct sdma_engine *sdma, const struct sdma_script_start_addrs *addr) @@ -1246,7 +1248,7 @@ static void sdma_add_scripts(struct sdma_engine *sdma, s32 *saddr_arr = (u32 *)sdma->script_addrs; int i; - for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++) + for (i = 0; i < sdma->script_number; i++) if (addr_arr[i] > 0) saddr_arr[i] = addr_arr[i]; } @@ -1272,6 +1274,17 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) goto err_firmware; if (header->ram_code_start + header->ram_code_size > fw->size) goto err_firmware; + switch (header->version_major) { + case 1: + sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; + break; + case 2: + sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; + break; + default: + dev_err(sdma->dev, "unknown firmware version\n"); + goto err_firmware; + } addr = (void *)header + header->script_addrs_start; ram_code = (void *)header + header->ram_code_start; diff --git a/include/linux/platform_data/dma-imx-sdma.h b/include/linux/platform_data/dma-imx-sdma.h index 3a3942823c20..eabac4e2fc99 100644 --- a/include/linux/platform_data/dma-imx-sdma.h +++ b/include/linux/platform_data/dma-imx-sdma.h @@ -43,6 +43,11 @@ struct sdma_script_start_addrs { s32 dptc_dvfs_addr; s32 utra_addr; s32 ram_code_start_addr; + /* End of v1 array */ + s32 mcu_2_ssish_addr; + s32 ssish_2_mcu_addr; + s32 hdmi_dma_addr; + /* End of v2 array */ }; /** -- cgit v1.2.3 From 1a895578d4e50577bb6aa79bd194b502f09dd768 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 13 Nov 2013 22:55:25 +0800 Subject: dma: imx-sdma: Add new dma type for ssi dual fifo script This patch adds a new DMA_TYPE for SSI dual FIFO script, included in SDMA firmware version 2. This script would allow SSI use dual fifo mode to transimit/receive data without occasional hardware underrun/overrun. Signed-off-by: Nicolin Chen Acked-by: Kumar Gala Acked-by: Sascha Hauer Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt | 1 + drivers/dma/imx-sdma.c | 4 ++++ include/linux/platform_data/dma-imx.h | 1 + 3 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index 4fa814d38321..68b83ecc3850 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt @@ -42,6 +42,7 @@ The full ID of peripheral types can be found below. 19 IPU Memory 20 ASRC 21 ESAI + 22 SSI Dual FIFO (needs firmware ver >= 2) The third cell specifies the transfer priority as below. diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index f769c7383536..152247675feb 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -725,6 +725,10 @@ static void sdma_get_pc(struct sdma_channel *sdmac, per_2_emi = sdma->script_addrs->app_2_mcu_addr; emi_2_per = sdma->script_addrs->mcu_2_app_addr; break; + case IMX_DMATYPE_SSI_DUAL: + per_2_emi = sdma->script_addrs->ssish_2_mcu_addr; + emi_2_per = sdma->script_addrs->mcu_2_ssish_addr; + break; case IMX_DMATYPE_SSI_SP: case IMX_DMATYPE_MMC: case IMX_DMATYPE_SDHC: diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h index beac6b8b6a7b..bcbc6c3c14c0 100644 --- a/include/linux/platform_data/dma-imx.h +++ b/include/linux/platform_data/dma-imx.h @@ -39,6 +39,7 @@ enum sdma_peripheral_type { IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */ IMX_DMATYPE_ASRC, /* ASRC */ IMX_DMATYPE_ESAI, /* ESAI */ + IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */ }; enum imx_dma_prio { -- cgit v1.2.3 From 2b7f65b11d87f9f3925dee5df020303b362c98ee Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 17 Nov 2013 12:12:56 -0800 Subject: mmp_pdma: Style neatening Neaten code used as a template for other drivers. Make the code more consistent with kernel styles. o Convert #defines with (1< Signed-off-by: Vinod Koul --- drivers/dma/mmp_pdma.c | 204 +++++++++++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index 8869500ab92b..3f7712c4d3fa 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -5,6 +5,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + #include #include #include @@ -32,38 +33,37 @@ #define DTADR 0x0208 #define DCMD 0x020c -#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */ -#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */ -#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */ -#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ -#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ -#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */ -#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ -#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ - -#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable (R/W) */ -#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */ -#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */ -#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ -#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ -#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ -#define DCSR_EORINTR (1 << 9) /* The end of Receive */ - -#define DRCMR(n) ((((n) < 64) ? 0x0100 : 0x1100) + \ - (((n) & 0x3f) << 2)) -#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ -#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ +#define DCSR_RUN BIT(31) /* Run Bit (read / write) */ +#define DCSR_NODESC BIT(30) /* No-Descriptor Fetch (read / write) */ +#define DCSR_STOPIRQEN BIT(29) /* Stop Interrupt Enable (read / write) */ +#define DCSR_REQPEND BIT(8) /* Request Pending (read-only) */ +#define DCSR_STOPSTATE BIT(3) /* Stop State (read-only) */ +#define DCSR_ENDINTR BIT(2) /* End Interrupt (read / write) */ +#define DCSR_STARTINTR BIT(1) /* Start Interrupt (read / write) */ +#define DCSR_BUSERR BIT(0) /* Bus Error Interrupt (read / write) */ + +#define DCSR_EORIRQEN BIT(28) /* End of Receive Interrupt Enable (R/W) */ +#define DCSR_EORJMPEN BIT(27) /* Jump to next descriptor on EOR */ +#define DCSR_EORSTOPEN BIT(26) /* STOP on an EOR */ +#define DCSR_SETCMPST BIT(25) /* Set Descriptor Compare Status */ +#define DCSR_CLRCMPST BIT(24) /* Clear Descriptor Compare Status */ +#define DCSR_CMPST BIT(10) /* The Descriptor Compare Status */ +#define DCSR_EORINTR BIT(9) /* The end of Receive */ + +#define DRCMR(n) ((((n) < 64) ? 0x0100 : 0x1100) + (((n) & 0x3f) << 2)) +#define DRCMR_MAPVLD BIT(7) /* Map Valid (read / write) */ +#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ #define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */ -#define DDADR_STOP (1 << 0) /* Stop (read / write) */ - -#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */ -#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */ -#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */ -#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */ -#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */ -#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */ -#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */ +#define DDADR_STOP BIT(0) /* Stop (read / write) */ + +#define DCMD_INCSRCADDR BIT(31) /* Source Address Increment Setting. */ +#define DCMD_INCTRGADDR BIT(30) /* Target Address Increment Setting. */ +#define DCMD_FLOWSRC BIT(29) /* Flow Control by the source. */ +#define DCMD_FLOWTRG BIT(28) /* Flow Control by the target. */ +#define DCMD_STARTIRQEN BIT(22) /* Start Interrupt Enable */ +#define DCMD_ENDIRQEN BIT(21) /* End Interrupt Enable */ +#define DCMD_ENDIAN BIT(18) /* Device Endian-ness. */ #define DCMD_BURST8 (1 << 16) /* 8 byte burst */ #define DCMD_BURST16 (2 << 16) /* 16 byte burst */ #define DCMD_BURST32 (3 << 16) /* 32 byte burst */ @@ -132,10 +132,14 @@ struct mmp_pdma_device { spinlock_t phy_lock; /* protect alloc/free phy channels */ }; -#define tx_to_mmp_pdma_desc(tx) container_of(tx, struct mmp_pdma_desc_sw, async_tx) -#define to_mmp_pdma_desc(lh) container_of(lh, struct mmp_pdma_desc_sw, node) -#define to_mmp_pdma_chan(dchan) container_of(dchan, struct mmp_pdma_chan, chan) -#define to_mmp_pdma_dev(dmadev) container_of(dmadev, struct mmp_pdma_device, device) +#define tx_to_mmp_pdma_desc(tx) \ + container_of(tx, struct mmp_pdma_desc_sw, async_tx) +#define to_mmp_pdma_desc(lh) \ + container_of(lh, struct mmp_pdma_desc_sw, node) +#define to_mmp_pdma_chan(dchan) \ + container_of(dchan, struct mmp_pdma_chan, chan) +#define to_mmp_pdma_dev(dmadev) \ + container_of(dmadev, struct mmp_pdma_device, device) static void set_desc(struct mmp_pdma_phy *phy, dma_addr_t addr) { @@ -162,19 +166,18 @@ static void enable_chan(struct mmp_pdma_phy *phy) writel(dalgn, phy->base + DALGN); reg = (phy->idx << 2) + DCSR; - writel(readl(phy->base + reg) | DCSR_RUN, - phy->base + reg); + writel(readl(phy->base + reg) | DCSR_RUN, phy->base + reg); } static void disable_chan(struct mmp_pdma_phy *phy) { u32 reg; - if (phy) { - reg = (phy->idx << 2) + DCSR; - writel(readl(phy->base + reg) & ~DCSR_RUN, - phy->base + reg); - } + if (!phy) + return; + + reg = (phy->idx << 2) + DCSR; + writel(readl(phy->base + reg) & ~DCSR_RUN, phy->base + reg); } static int clear_chan_irq(struct mmp_pdma_phy *phy) @@ -183,26 +186,27 @@ static int clear_chan_irq(struct mmp_pdma_phy *phy) u32 dint = readl(phy->base + DINT); u32 reg = (phy->idx << 2) + DCSR; - if (dint & BIT(phy->idx)) { - /* clear irq */ - dcsr = readl(phy->base + reg); - writel(dcsr, phy->base + reg); - if ((dcsr & DCSR_BUSERR) && (phy->vchan)) - dev_warn(phy->vchan->dev, "DCSR_BUSERR\n"); - return 0; - } - return -EAGAIN; + if (!(dint & BIT(phy->idx))) + return -EAGAIN; + + /* clear irq */ + dcsr = readl(phy->base + reg); + writel(dcsr, phy->base + reg); + if ((dcsr & DCSR_BUSERR) && (phy->vchan)) + dev_warn(phy->vchan->dev, "DCSR_BUSERR\n"); + + return 0; } static irqreturn_t mmp_pdma_chan_handler(int irq, void *dev_id) { struct mmp_pdma_phy *phy = dev_id; - if (clear_chan_irq(phy) == 0) { - tasklet_schedule(&phy->vchan->tasklet); - return IRQ_HANDLED; - } else + if (clear_chan_irq(phy) != 0) return IRQ_NONE; + + tasklet_schedule(&phy->vchan->tasklet); + return IRQ_HANDLED; } static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id) @@ -224,8 +228,8 @@ static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id) if (irq_num) return IRQ_HANDLED; - else - return IRQ_NONE; + + return IRQ_NONE; } /* lookup free phy channel as descending priority */ @@ -245,9 +249,9 @@ static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan) */ spin_lock_irqsave(&pdev->phy_lock, flags); - for (prio = 0; prio <= (((pdev->dma_channels - 1) & 0xf) >> 2); prio++) { + for (prio = 0; prio <= ((pdev->dma_channels - 1) & 0xf) >> 2; prio++) { for (i = 0; i < pdev->dma_channels; i++) { - if (prio != ((i & 0xf) >> 2)) + if (prio != (i & 0xf) >> 2) continue; phy = &pdev->phy[i]; if (!phy->vchan) { @@ -389,14 +393,16 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) if (chan->desc_pool) return 1; - chan->desc_pool = - dma_pool_create(dev_name(&dchan->dev->device), chan->dev, - sizeof(struct mmp_pdma_desc_sw), - __alignof__(struct mmp_pdma_desc_sw), 0); + chan->desc_pool = dma_pool_create(dev_name(&dchan->dev->device), + chan->dev, + sizeof(struct mmp_pdma_desc_sw), + __alignof__(struct mmp_pdma_desc_sw), + 0); if (!chan->desc_pool) { dev_err(chan->dev, "unable to allocate descriptor pool\n"); return -ENOMEM; } + mmp_pdma_free_phy(chan); chan->idle = true; chan->dev_addr = 0; @@ -404,7 +410,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) } static void mmp_pdma_free_desc_list(struct mmp_pdma_chan *chan, - struct list_head *list) + struct list_head *list) { struct mmp_pdma_desc_sw *desc, *_desc; @@ -434,8 +440,8 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan) static struct dma_async_tx_descriptor * mmp_pdma_prep_memcpy(struct dma_chan *dchan, - dma_addr_t dma_dst, dma_addr_t dma_src, - size_t len, unsigned long flags) + dma_addr_t dma_dst, dma_addr_t dma_src, + size_t len, unsigned long flags) { struct mmp_pdma_chan *chan; struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new; @@ -515,8 +521,8 @@ fail: static struct dma_async_tx_descriptor * mmp_pdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_transfer_direction dir, - unsigned long flags, void *context) + unsigned int sg_len, enum dma_transfer_direction dir, + unsigned long flags, void *context) { struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan); struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new = NULL; @@ -591,10 +597,11 @@ fail: return NULL; } -static struct dma_async_tx_descriptor *mmp_pdma_prep_dma_cyclic( - struct dma_chan *dchan, dma_addr_t buf_addr, size_t len, - size_t period_len, enum dma_transfer_direction direction, - unsigned long flags, void *context) +static struct dma_async_tx_descriptor * +mmp_pdma_prep_dma_cyclic(struct dma_chan *dchan, + dma_addr_t buf_addr, size_t len, size_t period_len, + enum dma_transfer_direction direction, + unsigned long flags, void *context) { struct mmp_pdma_chan *chan; struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new; @@ -636,8 +643,8 @@ static struct dma_async_tx_descriptor *mmp_pdma_prep_dma_cyclic( goto fail; } - new->desc.dcmd = chan->dcmd | DCMD_ENDIRQEN | - (DCMD_LENGTH & period_len); + new->desc.dcmd = (chan->dcmd | DCMD_ENDIRQEN | + (DCMD_LENGTH & period_len)); new->desc.dsadr = dma_src; new->desc.dtadr = dma_dst; @@ -677,12 +684,11 @@ fail: } static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, - unsigned long arg) + unsigned long arg) { struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan); struct dma_slave_config *cfg = (void *)arg; unsigned long flags; - int ret = 0; u32 maxburst = 0, addr = 0; enum dma_slave_buswidth width = DMA_SLAVE_BUSWIDTH_UNDEFINED; @@ -739,11 +745,12 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, return -ENOSYS; } - return ret; + return 0; } static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan, - dma_cookie_t cookie, struct dma_tx_state *txstate) + dma_cookie_t cookie, + struct dma_tx_state *txstate) { return dma_cookie_status(dchan, cookie, txstate); } @@ -845,15 +852,14 @@ static int mmp_pdma_remove(struct platform_device *op) return 0; } -static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, - int idx, int irq) +static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq) { struct mmp_pdma_phy *phy = &pdev->phy[idx]; struct mmp_pdma_chan *chan; int ret; - chan = devm_kzalloc(pdev->dev, - sizeof(struct mmp_pdma_chan), GFP_KERNEL); + chan = devm_kzalloc(pdev->dev, sizeof(struct mmp_pdma_chan), + GFP_KERNEL); if (chan == NULL) return -ENOMEM; @@ -861,8 +867,8 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, phy->base = pdev->base; if (irq) { - ret = devm_request_irq(pdev->dev, irq, - mmp_pdma_chan_handler, 0, "pdma", phy); + ret = devm_request_irq(pdev->dev, irq, mmp_pdma_chan_handler, 0, + "pdma", phy); if (ret) { dev_err(pdev->dev, "channel request irq fail!\n"); return ret; @@ -877,8 +883,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, INIT_LIST_HEAD(&chan->chain_running); /* register virt channel to dma engine */ - list_add_tail(&chan->chan.device_node, - &pdev->device.channels); + list_add_tail(&chan->chan.device_node, &pdev->device.channels); return 0; } @@ -913,13 +918,12 @@ retry: * the lookup and the reservation */ chan = dma_get_slave_channel(candidate); - if (chan) { - struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan); - c->drcmr = dma_spec->args[0]; - return chan; - } + if (!chan) + goto retry; - goto retry; + to_mmp_pdma_chan(chan)->drcmr = dma_spec->args[0]; + + return chan; } static int mmp_pdma_probe(struct platform_device *op) @@ -934,6 +938,7 @@ static int mmp_pdma_probe(struct platform_device *op) pdev = devm_kzalloc(&op->dev, sizeof(*pdev), GFP_KERNEL); if (!pdev) return -ENOMEM; + pdev->dev = &op->dev; spin_lock_init(&pdev->phy_lock); @@ -945,8 +950,8 @@ static int mmp_pdma_probe(struct platform_device *op) of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev); if (of_id) - of_property_read_u32(pdev->dev->of_node, - "#dma-channels", &dma_channels); + of_property_read_u32(pdev->dev->of_node, "#dma-channels", + &dma_channels); else if (pdata && pdata->dma_channels) dma_channels = pdata->dma_channels; else @@ -958,8 +963,9 @@ static int mmp_pdma_probe(struct platform_device *op) irq_num++; } - pdev->phy = devm_kzalloc(pdev->dev, - dma_channels * sizeof(struct mmp_pdma_chan), GFP_KERNEL); + pdev->phy = devm_kcalloc(pdev->dev, + dma_channels, sizeof(struct mmp_pdma_chan), + GFP_KERNEL); if (pdev->phy == NULL) return -ENOMEM; @@ -968,8 +974,8 @@ static int mmp_pdma_probe(struct platform_device *op) if (irq_num != dma_channels) { /* all chan share one irq, demux inside */ irq = platform_get_irq(op, 0); - ret = devm_request_irq(pdev->dev, irq, - mmp_pdma_int_handler, 0, "pdma", pdev); + ret = devm_request_irq(pdev->dev, irq, mmp_pdma_int_handler, 0, + "pdma", pdev); if (ret) return ret; } @@ -1045,7 +1051,7 @@ bool mmp_pdma_filter_fn(struct dma_chan *chan, void *param) if (chan->device->dev->driver != &mmp_pdma_driver.driver) return false; - c->drcmr = *(unsigned int *) param; + c->drcmr = *(unsigned int *)param; return true; } @@ -1053,6 +1059,6 @@ EXPORT_SYMBOL_GPL(mmp_pdma_filter_fn); module_platform_driver(mmp_pdma_driver); -MODULE_DESCRIPTION("MARVELL MMP Periphera DMA Driver"); +MODULE_DESCRIPTION("MARVELL MMP Peripheral DMA Driver"); MODULE_AUTHOR("Marvell International Ltd."); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 9d0f1fa6e104ad80c21a1051bb875b4c33d437e0 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 28 Nov 2013 14:59:39 +0530 Subject: dmaengine: mmp_tdma: fix the 'pointer from integer' warnings the driver is using unsigned long type for storing the channel register base "reg_base", this leads to bunch of warns when we try to use this as pointer. So better use an iomem pointer type for this variable drivers/dma/mmp_tdma.c: In function 'mmp_tdma_chan_set_desc': drivers/dma/mmp_tdma.c:143: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:144: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:144: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c: In function 'mmp_tdma_enable_chan': drivers/dma/mmp_tdma.c:151: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:153: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:153: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c: In function 'mmp_tdma_disable_chan': drivers/dma/mmp_tdma.c:160: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:160: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:164: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c: In function 'mmp_tdma_resume_chan': drivers/dma/mmp_tdma.c:171: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:171: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c: In function 'mmp_tdma_pause_chan': drivers/dma/mmp_tdma.c:178: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:178: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c: In function 'mmp_tdma_config_chan': drivers/dma/mmp_tdma.c:263: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast drivers/dma/mmp_tdma.c: In function 'mmp_tdma_clear_chan_irq': drivers/dma/mmp_tdma.c:269: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast drivers/dma/mmp_tdma.c:274: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast Signed-off-by: Vinod Koul --- drivers/dma/mmp_tdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 3ddacc14a736..61b562b2602d 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -121,7 +121,7 @@ struct mmp_tdma_chan { int idx; enum mmp_tdma_type type; int irq; - unsigned long reg_base; + void __iomem *reg_base; size_t buf_len; size_t period_len; @@ -526,7 +526,7 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev, tdmac->chan.device = &tdev->device; tdmac->idx = idx; tdmac->type = type; - tdmac->reg_base = (unsigned long)tdev->base + idx * 4; + tdmac->reg_base = tdev->base + idx * 4; tdmac->status = DMA_COMPLETE; tdev->tdmac[tdmac->idx] = tdmac; tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac); -- cgit v1.2.3 From a9ebbcd986de217cf650cb9f850a2fe3f72097f1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 29 Nov 2013 10:52:52 +0530 Subject: dmaengine: mmp: fix uninitialized variable drivers/dma/mmp_tdma.c:236:8: warning: 'tdcr' may be used uninitialized in this function [-Wuninitialized] Reported-by: Dan Williams Signed-off-by: Vinod Koul --- drivers/dma/mmp_tdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 61b562b2602d..d4b730ce0369 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -182,7 +182,7 @@ static void mmp_tdma_pause_chan(struct mmp_tdma_chan *tdmac) static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac) { - unsigned int tdcr; + unsigned int tdcr = 0; mmp_tdma_disable_chan(tdmac); -- cgit v1.2.3 From c9a3d47161b29603f6b2bd428d825ef83a007c6e Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 26 Nov 2013 10:49:10 +0000 Subject: i40e: fix up some of the ethtool connection reporting Get some more reasonable information reported back out to ethtool for the different types of connections supported. Change-Id: I57b153f86b9cdd04ad7cb5bf7d1c45873c196a7a Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 32 +++++++++++++++++++------- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 ++++ 2 files changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index fd3e379de6da..eb343756b2c1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -193,32 +193,48 @@ static int i40e_get_settings(struct net_device *netdev, ecmd->supported = SUPPORTED_10000baseKR_Full; ecmd->advertising = ADVERTISED_10000baseKR_Full; break; - case I40E_PHY_TYPE_10GBASE_T: default: - ecmd->supported = SUPPORTED_10000baseT_Full; - ecmd->advertising = ADVERTISED_10000baseT_Full; + if (i40e_is_40G_device(hw->device_id)) { + ecmd->supported = SUPPORTED_40000baseSR4_Full; + ecmd->advertising = ADVERTISED_40000baseSR4_Full; + } else { + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->advertising = ADVERTISED_10000baseT_Full; + } break; } - /* for now just say autoneg all the time */ ecmd->supported |= SUPPORTED_Autoneg; + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? + AUTONEG_ENABLE : AUTONEG_DISABLE); - if (hw->phy.media_type == I40E_MEDIA_TYPE_BACKPLANE) { + switch (hw->phy.media_type) { + case I40E_MEDIA_TYPE_BACKPLANE: ecmd->supported |= SUPPORTED_Backplane; ecmd->advertising |= ADVERTISED_Backplane; ecmd->port = PORT_NONE; - } else if (hw->phy.media_type == I40E_MEDIA_TYPE_BASET) { + break; + case I40E_MEDIA_TYPE_BASET: ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; - } else if (hw->phy.media_type == I40E_MEDIA_TYPE_DA) { + break; + case I40E_MEDIA_TYPE_DA: + case I40E_MEDIA_TYPE_CX4: ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; ecmd->port = PORT_DA; - } else { + break; + case I40E_MEDIA_TYPE_FIBER: ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; ecmd->port = PORT_FIBRE; + break; + case I40E_MEDIA_TYPE_UNKNOWN: + default: + ecmd->port = PORT_OTHER; + break; } ecmd->transceiver = XCVR_EXTERNAL; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 8ae644570263..72a6028d24e0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -49,6 +49,10 @@ #define I40E_VF_DEVICE_ID 0x154C #define I40E_VF_HV_DEVICE_ID 0x1571 +#define i40e_is_40G_device(d) ((d) == I40E_QSFP_A_DEVICE_ID || \ + (d) == I40E_QSFP_B_DEVICE_ID || \ + (d) == I40E_QSFP_C_DEVICE_ID) + #define I40E_FW_API_VERSION_MAJOR 0x0001 #define I40E_FW_API_VERSION_MINOR 0x0000 -- cgit v1.2.3 From f551b4386cefaf47b116a432c64582a8355bf362 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 26 Nov 2013 10:49:12 +0000 Subject: i40e: fix pf reset after offline test When the ethtool testing starts it sets the I40E_TESTING state bit, which blocks new netdev opens so that things don't get confused, while the testing might be messing with register and other things. Unfortunately, that was keeping the PF resets after the register test from working correctly because the netdev would not get reopened. This patch reorders the tests to put the register test last as it is the only one that needs a reset, and we wait to trigger the reset until after we clear the I40E_TESTING bit. Change-Id: Ieaa18d74264250ac336b0656b490125ee8a22d2a Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index eb343756b2c1..9c380a8e95da 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -748,7 +748,6 @@ static int i40e_reg_test(struct net_device *netdev, u64 *data) netif_info(pf, hw, netdev, "register test\n"); *data = i40e_diag_reg_test(&pf->hw); - i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); return *data; } @@ -796,20 +795,18 @@ static void i40e_diag_test(struct net_device *netdev, struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; - set_bit(__I40E_TESTING, &pf->state); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ netif_info(pf, drv, netdev, "offline testing starting\n"); + set_bit(__I40E_TESTING, &pf->state); + /* Link test performed before hardware reset * so autoneg doesn't interfere with test result */ if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK])) eth_test->flags |= ETH_TEST_FL_FAILED; - if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG])) - eth_test->flags |= ETH_TEST_FL_FAILED; - if (i40e_eeprom_test(netdev, &data[I40E_ETH_TEST_EEPROM])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -819,6 +816,12 @@ static void i40e_diag_test(struct net_device *netdev, if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK])) eth_test->flags |= ETH_TEST_FL_FAILED; + /* run reg test last, a reset is required after it */ + if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + clear_bit(__I40E_TESTING, &pf->state); + i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); } else { /* Online tests */ netif_info(pf, drv, netdev, "online testing starting\n"); @@ -832,7 +835,6 @@ static void i40e_diag_test(struct net_device *netdev, data[I40E_ETH_TEST_INTR] = 0; data[I40E_ETH_TEST_LOOPBACK] = 0; } - clear_bit(__I40E_TESTING, &pf->state); netif_info(pf, drv, netdev, "testing finished\n"); } -- cgit v1.2.3 From 25946ddb117afc63c0885d5d2a13f6865d132a32 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 26 Nov 2013 10:49:14 +0000 Subject: i40e: Tell the stack about our actual number of queues Call the netif_set_real* functions in order to make sure the stack knows about how many queues we have, in order for RFS/RPS/XFS to work correctly. Change-Id: Ib7a7b2792f80c5eef210dedf42cc6607d63953d2 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index a6291e23fe5f..9dc5829a4e95 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3966,6 +3966,15 @@ static int i40e_open(struct net_device *netdev) if (err) goto err_setup_rx; + /* Notify the stack of the actual queue counts. */ + err = netif_set_real_num_tx_queues(netdev, pf->num_tx_queues); + if (err) + goto err_set_queues; + + err = netif_set_real_num_rx_queues(netdev, pf->num_rx_queues); + if (err) + goto err_set_queues; + err = i40e_up_complete(vsi); if (err) goto err_up_complete; @@ -3982,6 +3991,7 @@ static int i40e_open(struct net_device *netdev) err_up_complete: i40e_down(vsi); +err_set_queues: i40e_vsi_free_irq(vsi); err_setup_rx: i40e_vsi_free_rx_resources(vsi); -- cgit v1.2.3 From d52c20b7e40e4011c30eff987e038a0a25d3e0a7 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 26 Nov 2013 10:49:15 +0000 Subject: i40e: init flow control settings to disabled Refactor flow control set up and disable L2 flow control by default. Change-Id: I2fe257b80df6d9a1e37deb4df118da8f8467040d Signed-off-by: Jesse Brandeburg Signed-off-by: Akeem G Abodunrin Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 10 +++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 59 +++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 9c380a8e95da..fcb6def71dae 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -276,12 +276,14 @@ static void i40e_get_pauseparam(struct net_device *netdev, ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? AUTONEG_ENABLE : AUTONEG_DISABLE); - pause->rx_pause = 0; - pause->tx_pause = 0; - if (hw_link_info->an_info & I40E_AQ_LINK_PAUSE_RX) + if (hw->fc.current_mode == I40E_FC_RX_PAUSE) { pause->rx_pause = 1; - if (hw_link_info->an_info & I40E_AQ_LINK_PAUSE_TX) + } else if (hw->fc.current_mode == I40E_FC_TX_PAUSE) { pause->tx_pause = 1; + } else if (hw->fc.current_mode == I40E_FC_FULL) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } } static u32 i40e_get_msglevel(struct net_device *netdev) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9dc5829a4e95..4d3a20146cde 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6911,6 +6911,7 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) **/ static int i40e_setup_pf_switch(struct i40e_pf *pf) { + u32 rxfc, txfc, rxfc_reg; int ret; /* find out what's out there already */ @@ -6981,20 +6982,65 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf) i40e_aq_get_link_info(&pf->hw, true, NULL, NULL); i40e_link_event(pf); - /* Initialize user-specifics link properties */ + /* Initialize user-specific link properties */ pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info & I40E_AQ_AN_COMPLETED) ? true : false); - pf->hw.fc.requested_mode = I40E_FC_DEFAULT; - if (pf->hw.phy.link_info.an_info & - (I40E_AQ_LINK_PAUSE_TX | I40E_AQ_LINK_PAUSE_RX)) + /* requested_mode is set in probe or by ethtool */ + if (!pf->fc_autoneg_status) + goto no_autoneg; + + if ((pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) && + (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)) pf->hw.fc.current_mode = I40E_FC_FULL; else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) pf->hw.fc.current_mode = I40E_FC_TX_PAUSE; else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) pf->hw.fc.current_mode = I40E_FC_RX_PAUSE; else - pf->hw.fc.current_mode = I40E_FC_DEFAULT; + pf->hw.fc.current_mode = I40E_FC_NONE; + + /* sync the flow control settings with the auto-neg values */ + switch (pf->hw.fc.current_mode) { + case I40E_FC_FULL: + txfc = 1; + rxfc = 1; + break; + case I40E_FC_TX_PAUSE: + txfc = 1; + rxfc = 0; + break; + case I40E_FC_RX_PAUSE: + txfc = 0; + rxfc = 1; + break; + case I40E_FC_NONE: + case I40E_FC_DEFAULT: + txfc = 0; + rxfc = 0; + break; + case I40E_FC_PFC: + /* TBD */ + break; + /* no default case, we have to handle all possibilities here */ + } + + wr32(&pf->hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT); + + rxfc_reg = rd32(&pf->hw, I40E_PRTDCB_MFLCN) & + ~I40E_PRTDCB_MFLCN_RFCE_MASK; + rxfc_reg |= (rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT); + + wr32(&pf->hw, I40E_PRTDCB_MFLCN, rxfc_reg); + goto fc_complete; + +no_autoneg: + /* disable L2 flow control, user can turn it on if they wish */ + wr32(&pf->hw, I40E_PRTDCB_FCCFG, 0); + wr32(&pf->hw, I40E_PRTDCB_MFLCN, rd32(&pf->hw, I40E_PRTDCB_MFLCN) & + ~I40E_PRTDCB_MFLCN_RFCE_MASK); + +fc_complete: return ret; } @@ -7288,6 +7334,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_pf_reset; } + /* set up a default setting for link flow control */ + pf->hw.fc.requested_mode = I40E_FC_NONE; + err = i40e_init_adminq(hw); dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw)); if (((hw->nvm.version & I40E_NVM_VERSION_HI_MASK) -- cgit v1.2.3 From 895106a577c4ad2231c48f9cccb3cff1ae880471 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 26 Nov 2013 10:49:16 +0000 Subject: i40e: trivial fixes Prevent some compiler warnings and implement some other trivial fixes. Change-Id: I7f49d79b91b94df1ad4a8306a0410ed72238845f Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_diag.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_hmc.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c index dc6c41fade9e..98c1ef563bf0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_diag.c +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c @@ -119,7 +119,7 @@ i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw) /* read NVM control word and if NVM valid, validate EEPROM checksum*/ ret_code = i40e_read_nvm_word(hw, I40E_SR_NVM_CONTROL_WORD, ®_val); - if ((!ret_code) && + if (!ret_code && ((reg_val & I40E_SR_CONTROL_WORD_1_MASK) == (0x01 << I40E_SR_CONTROL_WORD_1_SHIFT))) { ret_code = i40e_validate_nvm_checksum(hw, NULL); diff --git a/drivers/net/ethernet/intel/i40e/i40e_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_hmc.c index 901804af8b0e..bcedf3fb1143 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_hmc.c @@ -47,10 +47,10 @@ i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw, u64 direct_mode_sz) { enum i40e_memory_type mem_type __attribute__((unused)); - i40e_status ret_code = 0; struct i40e_hmc_sd_entry *sd_entry; bool dma_mem_alloc_done = false; struct i40e_dma_mem mem; + i40e_status ret_code; u64 alloc_len; if (NULL == hmc_info->sd_table.sd_entry) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4d3a20146cde..e8bb2bba692a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6911,7 +6911,7 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) **/ static int i40e_setup_pf_switch(struct i40e_pf *pf) { - u32 rxfc, txfc, rxfc_reg; + u32 rxfc = 0, txfc = 0, rxfc_reg; int ret; /* find out what's out there already */ -- cgit v1.2.3 From bf051a3b86d68e58b0c375244699e08b40499066 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 26 Nov 2013 10:49:17 +0000 Subject: i40e: use same number of queues as CPUs The current driver default sets the number of transmit/receive queue pairs based on the current node's CPU count. A better method is to use the total number of CPUs in the system to suggest the number of queue pairs, which aligns better with the behavior of ixgbe, and also with the expectations of the kernel XPS and other subsystems in the stack. Change-Id: If3e20c7f100f13e51d69762594d948f247ffe0c8 Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e8bb2bba692a..1295adbc2198 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5401,7 +5401,7 @@ static int i40e_init_msix(struct i40e_pf *pf) /* The number of vectors we'll request will be comprised of: * - Add 1 for "other" cause for Admin Queue events, etc. * - The number of LAN queue pairs - * already adjusted for the NUMA node + * already adjusted for the number of cpus in the system * assumes symmetric Tx/Rx pairing * - The number of VMDq pairs * Once we count this up, try the request. @@ -5728,8 +5728,7 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->hw.func_caps.num_tx_qp); if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; - pf->rss_size = min_t(int, pf->rss_size_max, - nr_cpus_node(numa_node_id())); + pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus()); } else { pf->rss_size = 1; } @@ -7054,7 +7053,7 @@ static u16 i40e_set_rss_size(struct i40e_pf *pf, int queues_left) int num_tc0; num_tc0 = min_t(int, queues_left, pf->rss_size_max); - num_tc0 = min_t(int, num_tc0, nr_cpus_node(numa_node_id())); + num_tc0 = min_t(int, num_tc0, num_online_cpus()); num_tc0 = rounddown_pow_of_two(num_tc0); return num_tc0; -- cgit v1.2.3 From bc7d338fbb3fb0901fe6db4ff2a9430bdd0f15db Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 26 Nov 2013 10:49:18 +0000 Subject: i40e: reinit flow for the main VSI This patch is the first in a 3 series patchset to implement dynamically changing the queue count for the main VSI. This patch starts by adding a reinit flow. This flow is designed to be able to change just the queue count and not the number of interrupt vectors that the device originally came up with. Change-Id: I0634aaebf7dc4dd6c66af8f9dbbef89d7beac438 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 118 +++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1295adbc2198..73110cda75e0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -48,7 +48,7 @@ static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi); static void i40e_handle_reset_warning(struct i40e_pf *pf); static int i40e_add_vsi(struct i40e_vsi *vsi); static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi); -static int i40e_setup_pf_switch(struct i40e_pf *pf); +static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit); static int i40e_setup_misc_vector(struct i40e_pf *pf); static void i40e_determine_queue_usage(struct i40e_pf *pf); static int i40e_setup_pf_filter_control(struct i40e_pf *pf); @@ -354,6 +354,9 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi); int i; + if (test_bit(__I40E_DOWN, &vsi->state)) + return stats; + rcu_read_lock(); for (i = 0; i < vsi->num_queue_pairs; i++) { struct i40e_ring *tx_ring, *rx_ring; @@ -4767,8 +4770,9 @@ static int i40e_prep_for_reset(struct i40e_pf *pf) /** * i40e_reset_and_rebuild - reset and rebuid using a saved config * @pf: board private structure + * @reinit: if the Main VSI needs to re-initialized. **/ -static void i40e_reset_and_rebuild(struct i40e_pf *pf) +static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) { struct i40e_driver_version dv; struct i40e_hw *hw = &pf->hw; @@ -4816,7 +4820,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf) } /* do basic switch setup */ - ret = i40e_setup_pf_switch(pf); + ret = i40e_setup_pf_switch(pf, reinit); if (ret) goto end_core_reset; @@ -4907,7 +4911,7 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf) ret = i40e_prep_for_reset(pf); if (!ret) - i40e_reset_and_rebuild(pf); + i40e_reset_and_rebuild(pf, false); } /** @@ -5088,11 +5092,12 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi) /** * i40e_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the vsi * @type: VSI pointer + * @alloc_qvectors: a bool to specify if q_vectors need to be allocated. * * On error: returns error code (negative) * On success: returns 0 **/ -static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi) +static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors) { int size; int ret = 0; @@ -5104,12 +5109,14 @@ static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi) return -ENOMEM; vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs]; - /* allocate memory for q_vector pointers */ - size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; - vsi->q_vectors = kzalloc(size, GFP_KERNEL); - if (!vsi->q_vectors) { - ret = -ENOMEM; - goto err_vectors; + if (alloc_qvectors) { + /* allocate memory for q_vector pointers */ + size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; + vsi->q_vectors = kzalloc(size, GFP_KERNEL); + if (!vsi->q_vectors) { + ret = -ENOMEM; + goto err_vectors; + } } return ret; @@ -5179,7 +5186,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) if (ret) goto err_rings; - ret = i40e_vsi_alloc_arrays(vsi); + ret = i40e_vsi_alloc_arrays(vsi, true); if (ret) goto err_rings; @@ -5201,15 +5208,18 @@ unlock_pf: /** * i40e_vsi_free_arrays - Free queue and vector pointer arrays for the VSI * @type: VSI pointer + * @free_qvectors: a bool to specify if q_vectors need to be freed. * * On error: returns error code (negative) * On success: returns 0 **/ -static void i40e_vsi_free_arrays(struct i40e_vsi *vsi) +static void i40e_vsi_free_arrays(struct i40e_vsi *vsi, bool free_qvectors) { /* free the ring and vector containers */ - kfree(vsi->q_vectors); - vsi->q_vectors = NULL; + if (free_qvectors) { + kfree(vsi->q_vectors); + vsi->q_vectors = NULL; + } kfree(vsi->tx_rings); vsi->tx_rings = NULL; vsi->rx_rings = NULL; @@ -5251,7 +5261,7 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi) i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx); i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx); - i40e_vsi_free_arrays(vsi); + i40e_vsi_free_arrays(vsi, true); pf->vsi[vsi->idx] = NULL; if (vsi->idx < pf->next_vsi) @@ -6262,6 +6272,69 @@ vector_setup_out: return ret; } +/** + * i40e_vsi_reinit_setup - return and reallocate resources for a VSI + * @vsi: pointer to the vsi. + * + * This re-allocates a vsi's queue resources. + * + * Returns pointer to the successfully allocated and configured VSI sw struct + * on success, otherwise returns NULL on failure. + **/ +static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi) +{ + struct i40e_pf *pf = vsi->back; + u8 enabled_tc; + int ret; + + i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx); + i40e_vsi_clear_rings(vsi); + + i40e_vsi_free_arrays(vsi, false); + i40e_set_num_rings_in_vsi(vsi); + ret = i40e_vsi_alloc_arrays(vsi, false); + if (ret) + goto err_vsi; + + ret = i40e_get_lump(pf, pf->qp_pile, vsi->alloc_queue_pairs, vsi->idx); + if (ret < 0) { + dev_info(&pf->pdev->dev, "VSI %d get_lump failed %d\n", + vsi->seid, ret); + goto err_vsi; + } + vsi->base_queue = ret; + + /* Update the FW view of the VSI. Force a reset of TC and queue + * layout configurations. + */ + enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc; + pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0; + pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid; + i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc); + + /* assign it some queues */ + ret = i40e_alloc_rings(vsi); + if (ret) + goto err_rings; + + /* map all of the rings to the q_vectors */ + i40e_vsi_map_rings_to_vectors(vsi); + return vsi; + +err_rings: + i40e_vsi_free_q_vectors(vsi); + if (vsi->netdev_registered) { + vsi->netdev_registered = false; + unregister_netdev(vsi->netdev); + free_netdev(vsi->netdev); + vsi->netdev = NULL; + } + i40e_aq_delete_element(&pf->hw, vsi->seid, NULL); +err_vsi: + i40e_vsi_clear(vsi); + return NULL; +} + /** * i40e_vsi_setup - Set up a VSI by a given type * @pf: board private structure @@ -6905,10 +6978,11 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) /** * i40e_setup_pf_switch - Setup the HW switch on startup or after reset * @pf: board private structure + * @reinit: if the Main VSI needs to re-initialized. * * Returns 0 on success, negative value on failure **/ -static int i40e_setup_pf_switch(struct i40e_pf *pf) +static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) { u32 rxfc = 0, txfc = 0, rxfc_reg; int ret; @@ -6930,7 +7004,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf) i40e_fdir_setup(pf); /* first time setup */ - if (pf->lan_vsi == I40E_NO_VSI) { + if (pf->lan_vsi == I40E_NO_VSI || reinit) { struct i40e_vsi *vsi = NULL; u16 uplink_seid; @@ -6941,8 +7015,10 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf) uplink_seid = pf->veb[pf->lan_veb]->seid; else uplink_seid = pf->mac_seid; - - vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, uplink_seid, 0); + if (pf->lan_vsi == I40E_NO_VSI) + vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, uplink_seid, 0); + else if (reinit) + vsi = i40e_vsi_reinit_setup(pf->vsi[pf->lan_vsi]); if (!vsi) { dev_info(&pf->pdev->dev, "setup of MAIN VSI failed\n"); i40e_fdir_teardown(pf); @@ -7413,7 +7489,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_switch_setup; } - err = i40e_setup_pf_switch(pf); + err = i40e_setup_pf_switch(pf, false); if (err) { dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err); goto err_vsis; -- cgit v1.2.3 From f8ff14640a72dd35da0fa5fb84b0ef61610f2c3a Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 26 Nov 2013 10:49:19 +0000 Subject: i40e: function to reconfigure RSS queues and rebuild This is the second of 3 patches that allows for changing the number of queues in the driver on the fly. This patch adds a function that calls the reinit flow for the main VSI after making changes to the RSS queue count as requested by the user. Change-Id: I82dee91e9fe90eeb4e84a7369f4b8b342155dd85 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_main.c | 56 ++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 001d7cfc9129..eb1a3aa2c67c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -199,6 +199,7 @@ struct i40e_pf { u16 num_tc_qps; /* num queue pairs per TC */ u16 num_lan_qps; /* num lan queues this pf has set up */ u16 num_lan_msix; /* num queue vectors for the base pf vsi */ + int queues_left; /* queues left unclaimed */ u16 rss_size; /* num queues in the RSS array */ u16 rss_size_max; /* HW defined max RSS queues */ u16 fdir_pf_filter_count; /* num of guaranteed filters for this PF */ @@ -530,6 +531,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, int i40e_vsi_release(struct i40e_vsi *vsi); struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type, struct i40e_vsi *start_vsi); +int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count); struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc); void i40e_veb_release(struct i40e_veb *veb); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 73110cda75e0..73c9a20694a9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5411,15 +5411,18 @@ static int i40e_init_msix(struct i40e_pf *pf) /* The number of vectors we'll request will be comprised of: * - Add 1 for "other" cause for Admin Queue events, etc. * - The number of LAN queue pairs - * already adjusted for the number of cpus in the system - * assumes symmetric Tx/Rx pairing + * - Queues being used for RSS. + * We don't need as many as max_rss_size vectors. + * use rss_size instead in the calculation since that + * is governed by number of cpus in the system. + * - assumes symmetric Tx/Rx pairing * - The number of VMDq pairs * Once we count this up, try the request. * * If we can't get what we want, we'll simplify to nearly nothing * and try again. If that still fails, we punt. */ - pf->num_lan_msix = pf->num_lan_qps; + pf->num_lan_msix = pf->num_lan_qps - (pf->rss_size_max - pf->rss_size); pf->num_vmdq_msix = pf->num_vmdq_qps; v_budget = 1 + pf->num_lan_msix; v_budget += (pf->num_vmdq_vsis * pf->num_vmdq_msix); @@ -5699,6 +5702,42 @@ static int i40e_config_rss(struct i40e_pf *pf) return 0; } +/** + * i40e_reconfig_rss_queues - change number of queues for rss and rebuild + * @pf: board private structure + * @queue_count: the requested queue count for rss. + * + * returns 0 if rss is not enabled, if enabled returns the final rss queue + * count which may be different from the requested queue count. + **/ +int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count) +{ + if (!(pf->flags & I40E_FLAG_RSS_ENABLED)) + return 0; + + queue_count = min_t(int, queue_count, pf->rss_size_max); + queue_count = rounddown_pow_of_two(queue_count); + + if (queue_count != pf->rss_size) { + if (pf->queues_left < (queue_count - pf->rss_size)) { + dev_info(&pf->pdev->dev, + "Not enough queues to do RSS on %d queues: remaining queues %d\n", + queue_count, pf->queues_left); + return pf->rss_size; + } + i40e_prep_for_reset(pf); + + pf->num_lan_qps += (queue_count - pf->rss_size); + pf->queues_left -= (queue_count - pf->rss_size); + pf->rss_size = queue_count; + + i40e_reset_and_rebuild(pf, true); + i40e_config_rss(pf); + } + dev_info(&pf->pdev->dev, "RSS count: %d\n", pf->rss_size); + return pf->rss_size; +} + /** * i40e_sw_init - Initialize general software structures (struct i40e_pf) * @pf: board private structure to initialize @@ -5880,7 +5919,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) int etherdev_size; etherdev_size = sizeof(struct i40e_netdev_priv); - netdev = alloc_etherdev_mq(etherdev_size, vsi->num_queue_pairs); + netdev = alloc_etherdev_mq(etherdev_size, vsi->alloc_queue_pairs); if (!netdev) return -ENOMEM; @@ -7180,7 +7219,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) pf->rss_size = i40e_set_rss_size(pf, queues_left); queues_left -= pf->rss_size; - pf->num_lan_qps = pf->rss_size; + pf->num_lan_qps = pf->rss_size_max; } else if (pf->flags & I40E_FLAG_RSS_ENABLED && !(pf->flags & I40E_FLAG_FDIR_ENABLED) && @@ -7199,7 +7238,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) return; } - pf->num_lan_qps = pf->rss_size + accum_tc_size; + pf->num_lan_qps = pf->rss_size_max + accum_tc_size; } else if (pf->flags & I40E_FLAG_RSS_ENABLED && (pf->flags & I40E_FLAG_FDIR_ENABLED) && @@ -7215,7 +7254,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) return; } - pf->num_lan_qps = pf->rss_size; + pf->num_lan_qps = pf->rss_size_max; } else if (pf->flags & I40E_FLAG_RSS_ENABLED && (pf->flags & I40E_FLAG_FDIR_ENABLED) && @@ -7235,7 +7274,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) return; } - pf->num_lan_qps = pf->rss_size + accum_tc_size; + pf->num_lan_qps = pf->rss_size_max + accum_tc_size; } else { dev_info(&pf->pdev->dev, @@ -7257,6 +7296,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) queues_left -= (pf->num_vmdq_vsis * pf->num_vmdq_qps); } + pf->queues_left = queues_left; return; } -- cgit v1.2.3 From 4b7820ca4f039ce8173e76b14d48ad35a438685a Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 26 Nov 2013 11:59:30 +0000 Subject: i40e: Add basic support for get/set channels for RSS Implement the number of receive/transmit queue pair being changed on the fly by ethtool. Change-Id: I70df2363f1ca40b63610baa561c5b6b92b81bca7 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 90 ++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index fcb6def71dae..d6681f6bf291 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1472,6 +1472,94 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) return ret; } +/** + * i40e_max_channels - get Max number of combined channels supported + * @vsi: vsi pointer + **/ +static unsigned int i40e_max_channels(struct i40e_vsi *vsi) +{ + /* TODO: This code assumes DCB and FD is disabled for now. */ + return vsi->alloc_queue_pairs; +} + +/** + * i40e_get_channels - Get the current channels enabled and max supported etc. + * @netdev: network interface device structure + * @ch: ethtool channels structure + * + * We don't support separate tx and rx queues as channels. The other count + * represents how many queues are being used for control. max_combined counts + * how many queue pairs we can support. They may not be mapped 1 to 1 with + * q_vectors since we support a lot more queue pairs than q_vectors. + **/ +static void i40e_get_channels(struct net_device *dev, + struct ethtool_channels *ch) +{ + struct i40e_netdev_priv *np = netdev_priv(dev); + struct i40e_vsi *vsi = np->vsi; + struct i40e_pf *pf = vsi->back; + + /* report maximum channels */ + ch->max_combined = i40e_max_channels(vsi); + + /* report info for other vector */ + ch->other_count = (pf->flags & I40E_FLAG_FDIR_ENABLED) ? 1 : 0; + ch->max_other = ch->other_count; + + /* Note: This code assumes DCB is disabled for now. */ + ch->combined_count = vsi->num_queue_pairs; +} + +/** + * i40e_set_channels - Set the new channels count. + * @netdev: network interface device structure + * @ch: ethtool channels structure + * + * The new channels count may not be the same as requested by the user + * since it gets rounded down to a power of 2 value. + **/ +static int i40e_set_channels(struct net_device *dev, + struct ethtool_channels *ch) +{ + struct i40e_netdev_priv *np = netdev_priv(dev); + unsigned int count = ch->combined_count; + struct i40e_vsi *vsi = np->vsi; + struct i40e_pf *pf = vsi->back; + int new_count; + + /* We do not support setting channels for any other VSI at present */ + if (vsi->type != I40E_VSI_MAIN) + return -EINVAL; + + /* verify they are not requesting separate vectors */ + if (!count || ch->rx_count || ch->tx_count) + return -EINVAL; + + /* verify other_count has not changed */ + if (ch->other_count != ((pf->flags & I40E_FLAG_FDIR_ENABLED) ? 1 : 0)) + return -EINVAL; + + /* verify the number of channels does not exceed hardware limits */ + if (count > i40e_max_channels(vsi)) + return -EINVAL; + + /* update feature limits from largest to smallest supported values */ + /* TODO: Flow director limit, DCB etc */ + + /* cap RSS limit */ + if (count > pf->rss_size_max) + count = pf->rss_size_max; + + /* use rss_reconfig to rebuild with new queue count and update traffic + * class queue mapping + */ + new_count = i40e_reconfig_rss_queues(pf, count); + if (new_count > 1) + return 0; + else + return -EINVAL; +} + static const struct ethtool_ops i40e_ethtool_ops = { .get_settings = i40e_get_settings, .get_drvinfo = i40e_get_drvinfo, @@ -1496,6 +1584,8 @@ static const struct ethtool_ops i40e_ethtool_ops = { .get_ethtool_stats = i40e_get_ethtool_stats, .get_coalesce = i40e_get_coalesce, .set_coalesce = i40e_set_coalesce, + .get_channels = i40e_get_channels, + .set_channels = i40e_set_channels, .get_ts_info = i40e_get_ts_info, }; -- cgit v1.2.3 From f00076d2fd3fe25b2e8c83921818914dee37ffef Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Sat, 14 Dec 2013 20:38:29 -0200 Subject: drm/i915: parse backlight modulation frequency from the BIOS VBT We don't actually do anything with the information yet, but parse and log what's in the VBT. Signed-off-by: Jani Nikula Signed-off-by: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ drivers/gpu/drm/i915/intel_bios.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 67f2ca1e50e0..b0a6e767951c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1184,6 +1184,11 @@ struct intel_vbt_data { int edp_bpp; struct edp_power_seq edp_pps; + struct { + u16 pwm_freq_hz; + bool active_low_pwm; + } backlight; + /* MIPI DSI */ struct { u16 panel_id; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f88e5079a3f5..f22041973f3a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -281,6 +281,34 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, } } +static void +parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +{ + const struct bdb_lfp_backlight_data *backlight_data; + const struct bdb_lfp_backlight_data_entry *entry; + + backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); + if (!backlight_data) + return; + + if (backlight_data->entry_size != sizeof(backlight_data->data[0])) { + DRM_DEBUG_KMS("Unsupported backlight data entry size %u\n", + backlight_data->entry_size); + return; + } + + entry = &backlight_data->data[panel_type]; + + dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; + dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; + DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " + "active %s, min brightness %u, level %u\n", + dev_priv->vbt.backlight.pwm_freq_hz, + dev_priv->vbt.backlight.active_low_pwm ? "low" : "high", + entry->min_brightness, + backlight_data->level[panel_type]); +} + /* Try to find sdvo panel data */ static void parse_sdvo_panel_data(struct drm_i915_private *dev_priv, @@ -894,6 +922,7 @@ intel_parse_bios(struct drm_device *dev) parse_general_features(dev_priv, bdb); parse_general_definitions(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb); + parse_lfp_backlight(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_sdvo_device_mapping(dev_priv, bdb); parse_device_mapping(dev_priv, bdb); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 81ed58cb7b31..282de5e9f39d 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -373,6 +373,22 @@ struct bdb_lvds_lfp_data { struct bdb_lvds_lfp_data_entry data[16]; } __packed; +struct bdb_lfp_backlight_data_entry { + u8 type:2; + u8 active_low_pwm:1; + u8 obsolete1:5; + u16 pwm_freq_hz; + u8 min_brightness; + u8 obsolete2; + u8 obsolete3; +} __packed; + +struct bdb_lfp_backlight_data { + u8 entry_size; + struct bdb_lfp_backlight_data_entry data[16]; + u8 level[16]; +} __packed; + struct aimdb_header { char signature[16]; char oem_device[20]; -- cgit v1.2.3 From 233261867fc62276d6a4099519f81dcd10bd7297 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 26 Nov 2013 10:49:22 +0000 Subject: i40e: rtnl_lock in reset path fixes Any user-initiated path which eventually calls reset needs to hold the rtnl_lock, so add functionality to do that. Be careful not to use the safe reset when cleaning up from the diagnostic tests, which avoids rtnl_lock recursion from ethtool. Protect the reset_task with rtnl_lock, since it runs from a work item. Change-Id: Ib6e7a3fb2966809db2daf35fd5a123ccdf6f6f0f Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 8 ++++---- drivers/net/ethernet/intel/i40e/i40e_main.c | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index eb1a3aa2c67c..24a47ee43098 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -502,6 +502,7 @@ int i40e_up(struct i40e_vsi *vsi); void i40e_down(struct i40e_vsi *vsi); extern const char i40e_driver_name[]; extern const char i40e_driver_version_str[]; +void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags); void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags); void i40e_update_stats(struct i40e_vsi *vsi); void i40e_update_eth_stats(struct i40e_vsi *vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 9c675b5f1466..9a59dda6b5ce 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1462,19 +1462,19 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } } else if (strncmp(cmd_buf, "pfr", 3) == 0) { dev_info(&pf->pdev->dev, "forcing PFR\n"); - i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED)); + i40e_do_reset_safe(pf, (1 << __I40E_PF_RESET_REQUESTED)); } else if (strncmp(cmd_buf, "corer", 5) == 0) { dev_info(&pf->pdev->dev, "forcing CoreR\n"); - i40e_do_reset(pf, (1 << __I40E_CORE_RESET_REQUESTED)); + i40e_do_reset_safe(pf, (1 << __I40E_CORE_RESET_REQUESTED)); } else if (strncmp(cmd_buf, "globr", 5) == 0) { dev_info(&pf->pdev->dev, "forcing GlobR\n"); - i40e_do_reset(pf, (1 << __I40E_GLOBAL_RESET_REQUESTED)); + i40e_do_reset_safe(pf, (1 << __I40E_GLOBAL_RESET_REQUESTED)); } else if (strncmp(cmd_buf, "empr", 4) == 0) { dev_info(&pf->pdev->dev, "forcing EMPR\n"); - i40e_do_reset(pf, (1 << __I40E_EMP_RESET_REQUESTED)); + i40e_do_reset_safe(pf, (1 << __I40E_EMP_RESET_REQUESTED)); } else if (strncmp(cmd_buf, "read", 4) == 0) { u32 address; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 73c9a20694a9..19ad3c02a7d0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4131,6 +4131,19 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) } } +/** + * i40e_do_reset_safe - Protected reset path for userland calls. + * @pf: board private structure + * @reset_flags: which reset is requested + * + **/ +void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags) +{ + rtnl_lock(); + i40e_do_reset(pf, reset_flags); + rtnl_unlock(); +} + /** * i40e_handle_lan_overflow_event - Handler for LAN queue overflow event * @pf: board private structure @@ -4376,6 +4389,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf) { u32 reset_flags = 0; + rtnl_lock(); if (test_bit(__I40E_REINIT_REQUESTED, &pf->state)) { reset_flags |= (1 << __I40E_REINIT_REQUESTED); clear_bit(__I40E_REINIT_REQUESTED, &pf->state); @@ -4398,7 +4412,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf) */ if (test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state)) { i40e_handle_reset_warning(pf); - return; + goto unlock; } /* If we're already down or resetting, just bail */ @@ -4406,6 +4420,9 @@ static void i40e_reset_subtask(struct i40e_pf *pf) !test_bit(__I40E_DOWN, &pf->state) && !test_bit(__I40E_CONFIG_BUSY, &pf->state)) i40e_do_reset(pf, reset_flags); + +unlock: + rtnl_unlock(); } /** -- cgit v1.2.3 From 9007bccd306956280448fd16fc8e6c65ff4d5337 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 26 Nov 2013 10:49:23 +0000 Subject: i40e: support for suspend and resume Add basic support for handling suspend and resume. We'll add Wake-on-LAN support later. Change-Id: Iea5e11c81bd9289a5bdbf086de8f626911a0b5ce Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 97 ++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 24a47ee43098..40706c15cdc3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -133,6 +133,7 @@ enum i40e_state_t { __I40E_GLOBAL_RESET_REQUESTED, __I40E_EMP_RESET_REQUESTED, __I40E_FILTER_OVERFLOW_PROMISC, + __I40E_SUSPENDED, }; enum i40e_interrupt_policy { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 19ad3c02a7d0..fba0aada062a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7749,7 +7749,11 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev, dev_info(&pdev->dev, "%s: error %d\n", __func__, error); /* shutdown all operations */ - i40e_pf_quiesce_all_vsi(pf); + if (!test_bit(__I40E_SUSPENDED, &pf->state)) { + rtnl_lock(); + i40e_prep_for_reset(pf); + rtnl_unlock(); + } /* Request a slot reset */ return PCI_ERS_RESULT_NEED_RESET; @@ -7812,9 +7816,95 @@ static void i40e_pci_error_resume(struct pci_dev *pdev) struct i40e_pf *pf = pci_get_drvdata(pdev); dev_info(&pdev->dev, "%s\n", __func__); + if (test_bit(__I40E_SUSPENDED, &pf->state)) + return; + + rtnl_lock(); i40e_handle_reset_warning(pf); + rtnl_lock(); +} + +/** + * i40e_shutdown - PCI callback for shutting down + * @pdev: PCI device information struct + **/ +static void i40e_shutdown(struct pci_dev *pdev) +{ + struct i40e_pf *pf = pci_get_drvdata(pdev); + + set_bit(__I40E_SUSPENDED, &pf->state); + set_bit(__I40E_DOWN, &pf->state); + rtnl_lock(); + i40e_prep_for_reset(pf); + rtnl_unlock(); + + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, false); /* No WoL support yet */ + pci_set_power_state(pdev, PCI_D3hot); + } +} + +#ifdef CONFIG_PM +/** + * i40e_suspend - PCI callback for moving to D3 + * @pdev: PCI device information struct + **/ +static int i40e_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct i40e_pf *pf = pci_get_drvdata(pdev); + + set_bit(__I40E_SUSPENDED, &pf->state); + set_bit(__I40E_DOWN, &pf->state); + rtnl_lock(); + i40e_prep_for_reset(pf); + rtnl_unlock(); + + pci_wake_from_d3(pdev, false); /* No WoL support yet */ + pci_set_power_state(pdev, PCI_D3hot); + + return 0; } +/** + * i40e_resume - PCI callback for waking up from D3 + * @pdev: PCI device information struct + **/ +static int i40e_resume(struct pci_dev *pdev) +{ + struct i40e_pf *pf = pci_get_drvdata(pdev); + u32 err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + /* pci_restore_state() clears dev->state_saves, so + * call pci_save_state() again to restore it. + */ + pci_save_state(pdev); + + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(&pdev->dev, + "%s: Cannot enable PCI device from suspend\n", + __func__); + return err; + } + pci_set_master(pdev); + + /* no wakeup events while running */ + pci_wake_from_d3(pdev, false); + + /* handling the reset will rebuild the device state */ + if (test_and_clear_bit(__I40E_SUSPENDED, &pf->state)) { + clear_bit(__I40E_DOWN, &pf->state); + rtnl_lock(); + i40e_reset_and_rebuild(pf, false); + rtnl_unlock(); + } + + return 0; +} + +#endif static const struct pci_error_handlers i40e_err_handler = { .error_detected = i40e_pci_error_detected, .slot_reset = i40e_pci_error_slot_reset, @@ -7826,6 +7916,11 @@ static struct pci_driver i40e_driver = { .id_table = i40e_pci_tbl, .probe = i40e_probe, .remove = i40e_remove, +#ifdef CONFIG_PM + .suspend = i40e_suspend, + .resume = i40e_resume, +#endif + .shutdown = i40e_shutdown, .err_handler = &i40e_err_handler, .sriov_configure = i40e_pci_sriov_configure, }; -- cgit v1.2.3 From 6dbbbfb2e65ce7222c56b06a713fa213db8341e5 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Tue, 26 Nov 2013 10:49:24 +0000 Subject: i40e: Remove FCoE in i40e_virtchnl_pf.c code Remove FCoE code from the VF interface, as the feature will not be supported on VF interfaces. Change-Id: Ie9db04fa2e37fa14ac3e73a9c20980348d931357 Signed-off-by: Neerav Parikh Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 29 ++-------------------- 1 file changed, 2 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index e7bdd47bafcf..68e1f8eff9b2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -521,6 +521,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) f = i40e_add_filter(vsi, vf->default_lan_addr.addr, 0, true, false); } + if (!f) { dev_err(&pf->pdev->dev, "Unable to add ucast filter\n"); ret = -ENOMEM; @@ -763,6 +764,7 @@ static void i40e_free_vf_res(struct i40e_vf *vf) vf->lan_vsi_index = 0; vf->lan_vsi_id = 0; } + /* reset some of the state varibles keeping * track of the resources */ @@ -1776,30 +1778,6 @@ error_param: return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_DEL_VLAN, aq_ret); } -/** - * i40e_vc_fcoe_msg - * @vf: pointer to the vf info - * @msg: pointer to the msg buffer - * @msglen: msg length - * - * called from the vf for the fcoe msgs - **/ -static int i40e_vc_fcoe_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) -{ - i40e_status aq_ret = 0; - - if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || - !test_bit(I40E_VF_STAT_FCOEENA, &vf->vf_states)) { - aq_ret = I40E_ERR_PARAM; - goto error_param; - } - aq_ret = I40E_ERR_NOT_IMPLEMENTED; - -error_param: - /* send the response to the vf */ - return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_FCOE, aq_ret); -} - /** * i40e_vc_validate_vf_msg * @vf: pointer to the vf info @@ -1973,9 +1951,6 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode, case I40E_VIRTCHNL_OP_GET_STATS: ret = i40e_vc_get_stats_msg(vf, msg, msglen); break; - case I40E_VIRTCHNL_OP_FCOE: - ret = i40e_vc_fcoe_msg(vf, msg, msglen); - break; case I40E_VIRTCHNL_OP_UNKNOWN: default: dev_err(&pf->pdev->dev, -- cgit v1.2.3 From 376f413a7d98f02e8253cf9dd44935a7545fcb62 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 14 Dec 2013 22:44:33 -0800 Subject: pinctrl: msm: Update Kconfig for PINCTRL_MSM8X74 Add GPIOLIB and OF as dependencies for PINCTRL_MSM8X74, to fix build errors from i386-randconfig. Also add help text and make the entries tristate, while touching these entries. Cc: Stephen Boyd Signed-off-by: Bjorn Andersson [Rebased on top of pin control development branch] Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ad58e7efe1d5..5c35d0db59e2 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -204,15 +204,18 @@ config PINCTRL_IMX28 select PINCTRL_MXS config PINCTRL_MSM - bool + tristate select PINMUX select PINCONF select GENERIC_PINCONF config PINCTRL_MSM8X74 - bool "Qualcomm 8x74 pin controller driver" - depends on OF && OF_IRQ + tristate "Qualcomm 8x74 pin controller driver" + depends on GPIOLIB && OF && OF_IRQ select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8974 platform. config PINCTRL_NOMADIK bool "Nomadik pin controller driver" -- cgit v1.2.3 From 1f2b239815996a93bd54561bb1b9d8460e114ff1 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 14 Dec 2013 23:01:51 -0800 Subject: pinctrl-msm: Fix spelling misstakes and missing consts Signed-off-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-msm.c | 14 +++++++------- drivers/pinctrl/pinctrl-msm8x74.c | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c index 28b90aba708d..322bc0a26040 100644 --- a/drivers/pinctrl/pinctrl-msm.c +++ b/drivers/pinctrl/pinctrl-msm.c @@ -96,7 +96,7 @@ static int msm_get_group_pins(struct pinctrl_dev *pctldev, return 0; } -static struct pinctrl_ops msm_pinctrl_ops = { +static const struct pinctrl_ops msm_pinctrl_ops = { .get_groups_count = msm_get_groups_count, .get_group_name = msm_get_group_name, .get_group_pins = msm_get_group_pins, @@ -190,7 +190,7 @@ static void msm_pinmux_disable(struct pinctrl_dev *pctldev, spin_unlock_irqrestore(&pctrl->lock, flags); } -static struct pinmux_ops msm_pinmux_ops = { +static const struct pinmux_ops msm_pinmux_ops = { .get_functions_count = msm_get_functions_count, .get_function_name = msm_get_function_name, .get_function_groups = msm_get_function_groups, @@ -378,7 +378,7 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev, return 0; } -static struct pinconf_ops msm_pinconf_ops = { +static const struct pinconf_ops msm_pinconf_ops = { .pin_config_get = msm_config_get, .pin_config_set = msm_config_set, .pin_config_group_get = msm_config_group_get, @@ -518,7 +518,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, int pull; u32 ctl_reg; - const char *pulls[] = { + static const char * const pulls[] = { "no pull", "pull down", "keeper", @@ -545,7 +545,7 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) for (i = 0; i < chip->ngpio; i++, gpio++) { msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); - seq_printf(s, "\n"); + seq_puts(s, "\n"); } } @@ -868,7 +868,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); /* - * Each pin have it's own IRQ status register, so use + * Each pin has it's own IRQ status register, so use * enabled_irq bitmap to limit the number of reads. */ for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) { @@ -881,7 +881,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) } } - /* No interrutps where flagged */ + /* No interrupts were flagged */ if (handled == 0) handle_bad_irq(irq, desc); diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/pinctrl-msm8x74.c index 762552bc53b9..c702e775bf24 100644 --- a/drivers/pinctrl/pinctrl-msm8x74.c +++ b/drivers/pinctrl/pinctrl-msm8x74.c @@ -352,7 +352,7 @@ static const unsigned int sdc2_data_pins[] = { 151 }; MSM_MUX_##f6, \ MSM_MUX_##f7 \ }, \ - .ctl_reg = 0x1000 + 0x10 * id , \ + .ctl_reg = 0x1000 + 0x10 * id, \ .io_reg = 0x1004 + 0x10 * id, \ .intr_cfg_reg = 0x1008 + 0x10 * id, \ .intr_status_reg = 0x100c + 0x10 * id, \ @@ -602,7 +602,7 @@ static int msm8x74_pinctrl_probe(struct platform_device *pdev) return msm_pinctrl_probe(pdev, &msm8x74_pinctrl); } -static struct of_device_id msm8x74_pinctrl_of_match[] = { +static const struct of_device_id msm8x74_pinctrl_of_match[] = { { .compatible = "qcom,msm8x74-pinctrl", }, { }, }; -- cgit v1.2.3 From f393e489c79d55dcc8e72eed0fabcb061e6b0090 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 14 Dec 2013 23:01:52 -0800 Subject: pinctrl-msm: Tidy up error handling Signed-off-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-msm.c | 76 +++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c index 322bc0a26040..c1a3053ff4c7 100644 --- a/drivers/pinctrl/pinctrl-msm.c +++ b/drivers/pinctrl/pinctrl-msm.c @@ -57,7 +57,7 @@ struct msm_pinctrl { struct pinctrl_dev *pctrl; struct irq_domain *domain; struct gpio_chip chip; - unsigned irq; + int irq; spinlock_t lock; @@ -201,7 +201,7 @@ static const struct pinmux_ops msm_pinmux_ops = { static int msm_config_reg(struct msm_pinctrl *pctrl, const struct msm_pingroup *g, unsigned param, - unsigned *reg, + s16 *reg, unsigned *mask, unsigned *bit) { @@ -272,7 +272,7 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev, unsigned mask; unsigned arg; unsigned bit; - unsigned reg; + s16 reg; int ret; u32 val; @@ -322,7 +322,7 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev, unsigned mask; unsigned arg; unsigned bit; - unsigned reg; + s16 reg; int ret; u32 val; int i; @@ -350,7 +350,7 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_DRIVE_STRENGTH: /* Check for invalid values */ - if (arg > ARRAY_SIZE(msm_drive_to_regval)) + if (arg >= ARRAY_SIZE(msm_drive_to_regval)) arg = -1; else arg = msm_drive_to_regval[arg]; @@ -399,12 +399,8 @@ static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) unsigned long flags; u32 val; - if (WARN_ON(offset >= pctrl->soc->ngroups)) - return -EINVAL; - g = &pctrl->soc->groups[offset]; - - if (WARN_ON(g->oe_bit < 0)) + if (WARN_ON(g->io_reg < 0)) return -EINVAL; spin_lock_irqsave(&pctrl->lock, flags); @@ -425,12 +421,8 @@ static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, in unsigned long flags; u32 val; - if (WARN_ON(offset >= pctrl->soc->ngroups)) - return -EINVAL; - g = &pctrl->soc->groups[offset]; - - if (WARN_ON(g->oe_bit < 0)) + if (WARN_ON(g->io_reg < 0)) return -EINVAL; spin_lock_irqsave(&pctrl->lock, flags); @@ -452,10 +444,9 @@ static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); u32 val; - if (WARN_ON(offset >= pctrl->soc->ngroups)) - return -EINVAL; - g = &pctrl->soc->groups[offset]; + if (WARN_ON(g->io_reg < 0)) + return -EINVAL; val = readl(pctrl->regs + g->io_reg); return !!(val & BIT(g->in_bit)); @@ -468,10 +459,9 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) unsigned long flags; u32 val; - if (WARN_ON(offset >= pctrl->soc->ngroups)) - return; - g = &pctrl->soc->groups[offset]; + if (WARN_ON(g->io_reg < 0)) + return; spin_lock_irqsave(&pctrl->lock, flags); @@ -616,13 +606,9 @@ static void msm_gpio_irq_mask(struct irq_data *d) u32 val; pctrl = irq_data_get_irq_chip_data(d); - if (!pctrl) - return; - - if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) - return; - g = &pctrl->soc->groups[d->hwirq]; + if (WARN_ON(g->intr_cfg_reg < 0)) + return; spin_lock_irqsave(&pctrl->lock, flags); @@ -643,13 +629,9 @@ static void msm_gpio_irq_unmask(struct irq_data *d) u32 val; pctrl = irq_data_get_irq_chip_data(d); - if (!pctrl) - return; - - if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) - return; - g = &pctrl->soc->groups[d->hwirq]; + if (WARN_ON(g->intr_status_reg < 0)) + return; spin_lock_irqsave(&pctrl->lock, flags); @@ -674,13 +656,9 @@ static void msm_gpio_irq_ack(struct irq_data *d) u32 val; pctrl = irq_data_get_irq_chip_data(d); - if (!pctrl) - return; - - if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) - return; - g = &pctrl->soc->groups[d->hwirq]; + if (WARN_ON(g->intr_status_reg < 0)) + return; spin_lock_irqsave(&pctrl->lock, flags); @@ -704,13 +682,9 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) u32 val; pctrl = irq_data_get_irq_chip_data(d); - if (!pctrl) - return -EINVAL; - - if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) - return -EINVAL; - g = &pctrl->soc->groups[d->hwirq]; + if (WARN_ON(g->intr_cfg_reg < 0)) + return -EINVAL; spin_lock_irqsave(&pctrl->lock, flags); @@ -802,9 +776,6 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) unsigned ngpio; pctrl = irq_data_get_irq_chip_data(d); - if (!pctrl) - return -EINVAL; - ngpio = pctrl->chip.ngpio; spin_lock_irqsave(&pctrl->lock, flags); @@ -983,7 +954,7 @@ int msm_pinctrl_probe(struct platform_device *pdev, if (IS_ERR(pctrl->regs)) return PTR_ERR(pctrl->regs); - pctrl->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + pctrl->irq = platform_get_irq(pdev, 0); if (pctrl->irq < 0) { dev_err(&pdev->dev, "No interrupt defined for msmgpio\n"); return pctrl->irq; @@ -1017,9 +988,14 @@ int msm_pinctrl_remove(struct platform_device *pdev) struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); int ret; + ret = gpiochip_remove(&pctrl->chip); + if (ret) { + dev_err(&pdev->dev, "Failed to remove gpiochip\n"); + return ret; + } + irq_set_chained_handler(pctrl->irq, NULL); irq_domain_remove(pctrl->domain); - ret = gpiochip_remove(&pctrl->chip); pinctrl_unregister(pctrl->pctrl); return 0; -- cgit v1.2.3 From 408e3c66da700a2c30ec63e0c4078c23d28dac2f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 14 Dec 2013 23:01:53 -0800 Subject: pinctrl-msm: Remove separate allocation of bitmaps Make the bitmaps part of the msm_pinctrl allocation instead of separately allocating them. Signed-off-by: Bjorn Andersson Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-msm.c | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c index c1a3053ff4c7..011e26334077 100644 --- a/drivers/pinctrl/pinctrl-msm.c +++ b/drivers/pinctrl/pinctrl-msm.c @@ -36,6 +36,8 @@ #include "pinctrl-msm.h" #include "pinctrl-utils.h" +#define MAX_NR_GPIO 300 + /** * struct msm_pinctrl - state for a pinctrl-msm device * @dev: device handle. @@ -61,9 +63,9 @@ struct msm_pinctrl { spinlock_t lock; - unsigned long *enabled_irqs; - unsigned long *dual_edge_irqs; - unsigned long *wake_irqs; + DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO); + DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO); + DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO); const struct msm_pinctrl_soc_data *soc; void __iomem *regs; @@ -875,30 +877,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) chip->owner = THIS_MODULE; chip->of_node = pctrl->dev->of_node; - pctrl->enabled_irqs = devm_kzalloc(pctrl->dev, - sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), - GFP_KERNEL); - if (!pctrl->enabled_irqs) { - dev_err(pctrl->dev, "Failed to allocate enabled_irqs bitmap\n"); - return -ENOMEM; - } - - pctrl->dual_edge_irqs = devm_kzalloc(pctrl->dev, - sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), - GFP_KERNEL); - if (!pctrl->dual_edge_irqs) { - dev_err(pctrl->dev, "Failed to allocate dual_edge_irqs bitmap\n"); - return -ENOMEM; - } - - pctrl->wake_irqs = devm_kzalloc(pctrl->dev, - sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), - GFP_KERNEL); - if (!pctrl->wake_irqs) { - dev_err(pctrl->dev, "Failed to allocate wake_irqs bitmap\n"); - return -ENOMEM; - } - ret = gpiochip_add(&pctrl->chip); if (ret) { dev_err(pctrl->dev, "Failed register gpiochip\n"); -- cgit v1.2.3 From b31d100e9225d013b7b9b4162a2bd3c6724954bd Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 14 Dec 2013 23:01:54 -0800 Subject: pinctrl-msm: Rename compatible to be more specific Use the more specific form 8974 for the compatible to reduce the risk of future mishaps. Signed-off-by: Bjorn Andersson Signed-off-by: Linus Walleij --- .../bindings/pinctrl/qcom,msm8974-pinctrl.txt | 92 ++++++++++++++++++++++ .../bindings/pinctrl/qcom,msm8x74-pinctrl.txt | 92 ---------------------- drivers/pinctrl/pinctrl-msm8x74.c | 2 +- 3 files changed, 93 insertions(+), 93 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt delete mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt new file mode 100644 index 000000000000..4c352be5dd61 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt @@ -0,0 +1,92 @@ +Qualcomm MSM8974 TLMM block + +Required properties: +- compatible: "qcom,msm8x74-pinctrl" +- reg: Should be the base address and length of the TLMM block. +- interrupts: Should be the parent IRQ of the TLMM block. +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells: Should be two. +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells : Should be two. + The first cell is the gpio pin number and the + second cell is used for optional parameters. + +Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for +a general description of GPIO and interrupt bindings. + +Please refer to pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the meaning of the +phrase "pin configuration node". + +Qualcomm's pin configuration nodes act as a container for an abitrary number of +subnodes. Each of these subnodes represents some desired configuration for a +pin, a group, or a list of pins or groups. This configuration can include the +mux function to select on those pin(s)/group(s), and various pin configuration +parameters, such as pull-up, drive strength, etc. + +The name of each subnode is not important; all subnodes should be enumerated +and processed purely based on their content. + +Each subnode only affects those parameters that are explicitly listed. In +other words, a subnode that lists a mux function but no pin configuration +parameters implies no information about any pin configuration parameters. +Similarly, a pin subnode that describes a pullup parameter implies no +information about e.g. the mux function. + + +The following generic properties as defined in pinctrl-bindings.txt are valid +to specify in a pin configuration subnode: + pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength. + +Non-empty subnodes must specify the 'pins' property. +Note that not all properties are valid for all pins. + + +Valid values for qcom,pins are: + gpio0-gpio145 + Supports mux, bias and drive-strength + + sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, sdc2_data + Supports bias and drive-strength + +Valid values for qcom,function are: + blsp_i2c2, blsp_i2c6, blsp_i2c11, blsp_spi1, blsp_uart2, blsp_uart8, slimbus + + (Note that this is not yet the complete list of functions) + + + +Example: + + msmgpio: pinctrl@fd510000 { + compatible = "qcom,msm8974-pinctrl"; + reg = <0xfd510000 0x4000>; + + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <0 208 0>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart2_default>; + + uart2_default: uart2_default { + mux { + qcom,pins = "gpio4", "gpio5"; + qcom,function = "blsp_uart2"; + }; + + tx { + qcom,pins = "gpio4"; + drive-strength = <4>; + bias-disable; + }; + + rx { + qcom,pins = "gpio5"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt deleted file mode 100644 index 70ab78fe93c8..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt +++ /dev/null @@ -1,92 +0,0 @@ -Qualcomm MSM8x74 TLMM block - -Required properties: -- compatible: "qcom,msm8x74-pinctrl" -- reg: Should be the base address and length of the TLMM block. -- interrupts: Should be the parent IRQ of the TLMM block. -- interrupt-controller: Marks the device node as an interrupt controller. -- #interrupt-cells: Should be two. -- gpio-controller: Marks the device node as a GPIO controller. -- #gpio-cells : Should be two. - The first cell is the gpio pin number and the - second cell is used for optional parameters. - -Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for -a general description of GPIO and interrupt bindings. - -Please refer to pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices, including the meaning of the -phrase "pin configuration node". - -Qualcomm's pin configuration nodes act as a container for an abitrary number of -subnodes. Each of these subnodes represents some desired configuration for a -pin, a group, or a list of pins or groups. This configuration can include the -mux function to select on those pin(s)/group(s), and various pin configuration -parameters, such as pull-up, drive strength, etc. - -The name of each subnode is not important; all subnodes should be enumerated -and processed purely based on their content. - -Each subnode only affects those parameters that are explicitly listed. In -other words, a subnode that lists a mux function but no pin configuration -parameters implies no information about any pin configuration parameters. -Similarly, a pin subnode that describes a pullup parameter implies no -information about e.g. the mux function. - - -The following generic properties as defined in pinctrl-bindings.txt are valid -to specify in a pin configuration subnode: - pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength. - -Non-empty subnodes must specify the 'pins' property. -Note that not all properties are valid for all pins. - - -Valid values for qcom,pins are: - gpio0-gpio145 - Supports mux, bias and drive-strength - - sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, sdc2_data - Supports bias and drive-strength - -Valid values for qcom,function are: - blsp_i2c2, blsp_i2c6, blsp_i2c11, blsp_spi1, blsp_uart2, blsp_uart8, slimbus - - (Note that this is not yet the complete list of functions) - - - -Example: - - msmgpio: pinctrl@fd510000 { - compatible = "qcom,msm8x74-pinctrl"; - reg = <0xfd510000 0x4000>; - - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <0 208 0>; - - pinctrl-names = "default"; - pinctrl-0 = <&uart2_default>; - - uart2_default: uart2_default { - mux { - qcom,pins = "gpio4", "gpio5"; - qcom,function = "blsp_uart2"; - }; - - tx { - qcom,pins = "gpio4"; - drive-strength = <4>; - bias-disable; - }; - - rx { - qcom,pins = "gpio5"; - drive-strength = <2>; - bias-pull-up; - }; - }; - }; diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/pinctrl-msm8x74.c index c702e775bf24..f944bf2172ef 100644 --- a/drivers/pinctrl/pinctrl-msm8x74.c +++ b/drivers/pinctrl/pinctrl-msm8x74.c @@ -603,7 +603,7 @@ static int msm8x74_pinctrl_probe(struct platform_device *pdev) } static const struct of_device_id msm8x74_pinctrl_of_match[] = { - { .compatible = "qcom,msm8x74-pinctrl", }, + { .compatible = "qcom,msm8974-pinctrl", }, { }, }; -- cgit v1.2.3 From 8ba3f4d00078e7a49c60c0bd6298f29402c3a0a0 Mon Sep 17 00:00:00 2001 From: Sherman Yin Date: Wed, 11 Dec 2013 10:37:17 -0800 Subject: pinctrl: Adds slew-rate, input-enable/disable This commit adds slew-rate and input-enable/disable support for pinconf -generic. Signed-off-by: Sherman Yin Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt | 3 +++ drivers/pinctrl/pinconf-generic.c | 4 ++++ include/linux/pinctrl/pinconf-generic.h | 4 ++++ 3 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt index 1958ca9f9e5c..4414163e76d2 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt @@ -151,6 +151,8 @@ drive-push-pull - drive actively high and low drive-open-drain - drive with open drain drive-open-source - drive with open source drive-strength - sink or source at most X mA +input-enable - enable input on pin (no effect on output) +input-disable - disable input on pin (no effect on output) input-schmitt-enable - enable schmitt-trigger mode input-schmitt-disable - disable schmitt-trigger mode input-debounce - debounce mode with debound time X @@ -158,6 +160,7 @@ low-power-enable - enable low power mode low-power-disable - disable low power mode output-low - set the pin to output mode with low level output-high - set the pin to output mode with high level +slew-rate - set the slew rate Some of the generic properties take arguments. For those that do, the arguments are described below. diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 55a0ebe830ac..3d9a999fb699 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -48,6 +48,7 @@ static struct pin_config_item conf_items[] = { PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL), PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL), PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA"), + PCONFDUMP(PIN_CONFIG_INPUT_ENABLE, "input enabled", NULL), PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL), PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL), PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec"), @@ -160,6 +161,8 @@ static struct pinconf_generic_dt_params dt_params[] = { { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 }, { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 }, { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 }, @@ -167,6 +170,7 @@ static struct pinconf_generic_dt_params dt_params[] = { { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 }, { "output-low", PIN_CONFIG_OUTPUT, 0, }, { "output-high", PIN_CONFIG_OUTPUT, 1, }, + { "slew-rate", PIN_CONFIG_SLEW_RATE, 0}, }; /** diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index 282309d7c4dc..a15f10727eb8 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -61,6 +61,9 @@ * argument is ignored. * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current * passed as argument. The argument is in mA. + * @PIN_CONFIG_INPUT_ENABLE: enable the pin's input. Note that this does not + * affect the pin's ability to drive output. 1 enables input, 0 disables + * input. * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin. * If the argument != 0, schmitt-trigger mode is enabled. If it's 0, * schmitt-trigger mode is disabled. @@ -101,6 +104,7 @@ enum pin_config_param { PIN_CONFIG_DRIVE_OPEN_DRAIN, PIN_CONFIG_DRIVE_OPEN_SOURCE, PIN_CONFIG_DRIVE_STRENGTH, + PIN_CONFIG_INPUT_ENABLE, PIN_CONFIG_INPUT_SCHMITT_ENABLE, PIN_CONFIG_INPUT_SCHMITT, PIN_CONFIG_INPUT_DEBOUNCE, -- cgit v1.2.3 From f3c5fe979117908fb642ed130ae2cd78cb005931 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 16 Dec 2013 14:13:25 +0800 Subject: drm/i915: fix return value check of debugfs_create_file() In case of error, the function debugfs_create_file() returns NULL pointer not ERR_PTR() if debugfs is enabled. The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6badc1596ceb..242189ee3607 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2117,8 +2117,8 @@ static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor, info->dev = dev; ent = debugfs_create_file(info->name, S_IRUGO, root, info, &i915_pipe_crc_fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); + if (!ent) + return -ENOMEM; return drm_add_fake_info_node(minor, ent, info); } @@ -3133,8 +3133,8 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) S_IRUSR, root, dev, &i915_forcewake_fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); + if (!ent) + return -ENOMEM; return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops); } @@ -3151,8 +3151,8 @@ static int i915_debugfs_create(struct dentry *root, S_IRUGO | S_IWUSR, root, dev, fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); + if (!ent) + return -ENOMEM; return drm_add_fake_info_node(minor, ent, fops); } -- cgit v1.2.3 From 961794a00eab03f4344b7d5e825e8e789e55da87 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Thu, 5 Dec 2013 12:54:53 -0800 Subject: Input: wacom - add reporting of SW_MUTE_DEVICE events New Intuos series models added a hardware switch to turn touch data on/off. The state of the switch is reported periodically from the tablet. To report the state the driver will emit SW_MUTE_DEVICE events. Reviewed_by: Chris Bagwell Acked-by: Peter Hutterer Tested-by: Jason Gerecke Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 12 ++++++++++++ drivers/input/tablet/wacom_wac.c | 30 +++++++++++++++++++++++++++--- drivers/input/tablet/wacom_wac.h | 5 +++++ 3 files changed, 44 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8318826d976e..b16ebef5b911 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1197,6 +1197,8 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features.device_type = BTN_TOOL_PEN; snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); + wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; + wacom_wac1->shared->type = wacom_wac1->features.type; error = wacom_register_input(wacom1); if (error) goto fail; @@ -1218,6 +1220,10 @@ static void wacom_wireless_work(struct work_struct *work) error = wacom_register_input(wacom2); if (error) goto fail; + + if (wacom_wac1->features.type == INTUOSHT && + wacom_wac1->features.touch_max) + wacom_wac->shared->touch_input = wacom_wac2->input; } error = wacom_initialize_battery(wacom); @@ -1396,6 +1402,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail5; } } + + if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) { + if (wacom_wac->features.device_type == BTN_TOOL_FINGER) + wacom_wac->shared->touch_input = wacom_wac->input; + } + return 0; fail5: wacom_destroy_leds(wacom); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 7655088f78e0..048e5b38f167 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1219,13 +1219,23 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) static int wacom_bpt_pen(struct wacom_wac *wacom) { + struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; unsigned char *data = wacom->data; int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; - if (data[0] != WACOM_REPORT_PENABLED) + if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB) return 0; + if (data[0] == WACOM_REPORT_USB) { + if (features->type == INTUOSHT && features->touch_max) { + input_report_switch(wacom->shared->touch_input, + SW_MUTE_DEVICE, data[8] & 0x40); + input_sync(wacom->shared->touch_input); + } + return 0; + } + prox = (data[1] & 0x20) == 0x20; /* @@ -1258,8 +1268,8 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) * touching and applying pressure; do not report negative * distance. */ - if (data[8] <= wacom->features.distance_max) - d = wacom->features.distance_max - data[8]; + if (data[8] <= features->distance_max) + d = features->distance_max - data[8]; pen = data[1] & 0x01; btn1 = data[1] & 0x02; @@ -1310,6 +1320,13 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) if (connected) { int pid, battery; + if ((wacom->shared->type == INTUOSHT) && + wacom->shared->touch_max) { + input_report_switch(wacom->shared->touch_input, + SW_MUTE_DEVICE, data[5] & 0x40); + input_sync(wacom->shared->touch_input); + } + pid = get_unaligned_be16(&data[6]); battery = data[5] & 0x3f; if (wacom->pid != pid) { @@ -1779,6 +1796,13 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, break; case INTUOSHT: + if (features->touch_max && + features->device_type == BTN_TOOL_FINGER) { + input_dev->evbit[0] |= BIT_MASK(EV_SW); + __set_bit(SW_MUTE_DEVICE, input_dev->swbit); + } + /* fall through */ + case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 854cceb6d6de..3600cf705fb1 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -55,6 +55,7 @@ #define WACOM_REPORT_TPC1FGE 18 #define WACOM_REPORT_24HDT 1 #define WACOM_REPORT_WL 128 +#define WACOM_REPORT_USB 192 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -131,6 +132,10 @@ struct wacom_features { struct wacom_shared { bool stylus_in_proximity; bool touch_down; + /* for wireless device to access USB interfaces */ + unsigned touch_max; + int type; + struct input_dev *touch_input; }; struct wacom_wac { -- cgit v1.2.3 From e585c40ba19b155150f17124a308ac06e26d424a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 27 Nov 2013 20:08:33 -0800 Subject: Input: ads7846 - convert to hwmon_device_register_with_groups() Simplify the code and create mandatory 'name' attribute by using new hwmon API. Also use is_visible to determine visible attributes instead of creating several different attribute groups. Signed-off-by: Guenter Roeck Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 81 ++++++++++++------------------------- 1 file changed, 25 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 569578638233..f91592ab2f3a 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -102,7 +102,6 @@ struct ads7846 { struct regulator *reg; #if IS_ENABLED(CONFIG_HWMON) - struct attribute_group *attr_group; struct device *hwmon; #endif @@ -479,42 +478,36 @@ static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v) SHOW(in0_input, vaux, vaux_adjust) SHOW(in1_input, vbatt, vbatt_adjust) -static struct attribute *ads7846_attributes[] = { - &dev_attr_temp0.attr, - &dev_attr_temp1.attr, - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - NULL, -}; - -static struct attribute_group ads7846_attr_group = { - .attrs = ads7846_attributes, -}; +static umode_t ads7846_is_visible(struct kobject *kobj, struct attribute *attr, + int index) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct ads7846 *ts = dev_get_drvdata(dev); -static struct attribute *ads7843_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - NULL, -}; + if (ts->model == 7843 && index < 2) /* in0, in1 */ + return 0; + if (ts->model == 7845 && index != 2) /* in0 */ + return 0; -static struct attribute_group ads7843_attr_group = { - .attrs = ads7843_attributes, -}; + return attr->mode; +} -static struct attribute *ads7845_attributes[] = { - &dev_attr_in0_input.attr, +static struct attribute *ads7846_attributes[] = { + &dev_attr_temp0.attr, /* 0 */ + &dev_attr_temp1.attr, /* 1 */ + &dev_attr_in0_input.attr, /* 2 */ + &dev_attr_in1_input.attr, /* 3 */ NULL, }; -static struct attribute_group ads7845_attr_group = { - .attrs = ads7845_attributes, +static struct attribute_group ads7846_attr_group = { + .attrs = ads7846_attributes, + .is_visible = ads7846_is_visible, }; +__ATTRIBUTE_GROUPS(ads7846_attr); static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) { - struct device *hwmon; - int err; - /* hwmon sensors need a reference voltage */ switch (ts->model) { case 7846: @@ -535,43 +528,19 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) break; } - /* different chips have different sensor groups */ - switch (ts->model) { - case 7846: - ts->attr_group = &ads7846_attr_group; - break; - case 7845: - ts->attr_group = &ads7845_attr_group; - break; - case 7843: - ts->attr_group = &ads7843_attr_group; - break; - default: - dev_dbg(&spi->dev, "ADS%d not recognized\n", ts->model); - return 0; - } - - err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); - if (err) - return err; - - hwmon = hwmon_device_register(&spi->dev); - if (IS_ERR(hwmon)) { - sysfs_remove_group(&spi->dev.kobj, ts->attr_group); - return PTR_ERR(hwmon); - } + ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias, + ts, ads7846_attr_groups); + if (IS_ERR(ts->hwmon)) + return PTR_ERR(ts->hwmon); - ts->hwmon = hwmon; return 0; } static void ads784x_hwmon_unregister(struct spi_device *spi, struct ads7846 *ts) { - if (ts->hwmon) { - sysfs_remove_group(&spi->dev.kobj, ts->attr_group); + if (ts->hwmon) hwmon_device_unregister(ts->hwmon); - } } #else -- cgit v1.2.3 From 768d9aa55740754aa4efb8aca594e3841237dd88 Mon Sep 17 00:00:00 2001 From: Aleksej Makarov Date: Sat, 23 Nov 2013 10:20:36 -0800 Subject: Input: don't call input_dev_release_keys() in resume When waking up the platform by pressing a specific key, sending a release on that key makes it impossible to react on the event in user-space. This is fixed by moving the input_reset_device() call to resume instead. [dmitry.torokhov@gmail.com: make sure we still restore LED/sound state after resume, handle hibernation properly] Signed-off-by: Aleksej Makarov Signed-off-by: Oskar Andero Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 76 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index 846ccdd905b1..692435a321af 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1653,35 +1653,36 @@ static void input_dev_toggle(struct input_dev *dev, bool activate) */ void input_reset_device(struct input_dev *dev) { - mutex_lock(&dev->mutex); + unsigned long flags; - if (dev->users) { - input_dev_toggle(dev, true); + mutex_lock(&dev->mutex); + spin_lock_irqsave(&dev->event_lock, flags); - /* - * Keys that have been pressed at suspend time are unlikely - * to be still pressed when we resume. - */ - spin_lock_irq(&dev->event_lock); - input_dev_release_keys(dev); - spin_unlock_irq(&dev->event_lock); - } + input_dev_toggle(dev, true); + input_dev_release_keys(dev); + spin_unlock_irqrestore(&dev->event_lock, flags); mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_reset_device); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int input_dev_suspend(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - mutex_lock(&input_dev->mutex); + spin_lock_irq(&input_dev->event_lock); - if (input_dev->users) - input_dev_toggle(input_dev, false); + /* + * Keys that are pressed now are unlikely to be + * still pressed when we resume. + */ + input_dev_release_keys(input_dev); - mutex_unlock(&input_dev->mutex); + /* Turn off LEDs and sounds, if any are active. */ + input_dev_toggle(input_dev, false); + + spin_unlock_irq(&input_dev->event_lock); return 0; } @@ -1690,7 +1691,43 @@ static int input_dev_resume(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - input_reset_device(input_dev); + spin_lock_irq(&input_dev->event_lock); + + /* Restore state of LEDs and sounds, if any were active. */ + input_dev_toggle(input_dev, true); + + spin_unlock_irq(&input_dev->event_lock); + + return 0; +} + +static int input_dev_freeze(struct device *dev) +{ + struct input_dev *input_dev = to_input_dev(dev); + + spin_lock_irq(&input_dev->event_lock); + + /* + * Keys that are pressed now are unlikely to be + * still pressed when we resume. + */ + input_dev_release_keys(input_dev); + + spin_unlock_irq(&input_dev->event_lock); + + return 0; +} + +static int input_dev_poweroff(struct device *dev) +{ + struct input_dev *input_dev = to_input_dev(dev); + + spin_lock_irq(&input_dev->event_lock); + + /* Turn off LEDs and sounds, if any are active. */ + input_dev_toggle(input_dev, false); + + spin_unlock_irq(&input_dev->event_lock); return 0; } @@ -1698,7 +1735,8 @@ static int input_dev_resume(struct device *dev) static const struct dev_pm_ops input_dev_pm_ops = { .suspend = input_dev_suspend, .resume = input_dev_resume, - .poweroff = input_dev_suspend, + .freeze = input_dev_freeze, + .poweroff = input_dev_poweroff, .restore = input_dev_resume, }; #endif /* CONFIG_PM */ @@ -1707,7 +1745,7 @@ static struct device_type input_dev_type = { .groups = input_dev_attr_groups, .release = input_dev_release, .uevent = input_dev_uevent, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP .pm = &input_dev_pm_ops, #endif }; -- cgit v1.2.3 From 1ddbbb0c83de82599b1baf14bf6bb69a774d4fc7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 Dec 2013 22:39:17 +0100 Subject: iwlwifi: mvm: use pre-RCU-sync sta removal operation iwlmvm relies on the current mac80211 behaviour of allowing station pointers to be valid for an RCU grace period after returning from the sta_state() callback. To optimise these cases, this behaviour is going away, so make the driver use the new sta_pre_rcu_remove() method to clear the pointer in the fw_id_to_mac_id[] array. Since this may happen while the station is still present in the firmware, don't set the pointer to NULL but to -ENOENT to mark this particular case. In client mode, the station is kept even longer (until marking the MAC as unassociated) so the drain flow must take this new behavior into account. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 13 ++++++++----- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 23 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/sta.c | 11 +++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 67f6a2071653..27f140ceaac5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -98,14 +98,17 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, if (vif->type == NL80211_IFTYPE_STATION && ap_sta_id != IWL_MVM_STATION_COUNT) { struct ieee80211_sta *sta; - struct iwl_mvm_sta *mvm_sta; sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], lockdep_is_held(&mvm->mutex)); - mvm_sta = (void *)sta->drv_priv; - pos += scnprintf(buf+pos, bufsz-pos, - "ap_sta_id %d - reduced Tx power %d\n", - ap_sta_id, mvm_sta->bt_reduced_txpower); + if (!IS_ERR_OR_NULL(sta)) { + struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; + + pos += scnprintf(buf+pos, bufsz-pos, + "ap_sta_id %d - reduced Tx power %d\n", + ap_sta_id, + mvm_sta->bt_reduced_txpower); + } } rcu_read_lock(); diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index afc4419be46d..a77007cfd765 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1114,6 +1114,28 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, } } +static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; + + /* + * This is called before mac80211 does RCU synchronisation, + * so here we already invalidate our internal RCU-protected + * station pointer. The rest of the code will thus no longer + * be able to find the station this way, and we don't rely + * on further RCU synchronisation after the sta_state() + * callback deleted the station. + */ + mutex_lock(&mvm->mutex); + if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id])) + rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], + ERR_PTR(-ENOENT)); + mutex_unlock(&mvm->mutex); +} + static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1761,6 +1783,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = { .bss_info_changed = iwl_mvm_bss_info_changed, .hw_scan = iwl_mvm_mac_hw_scan, .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, + .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove, .sta_state = iwl_mvm_mac_sta_state, .sta_notify = iwl_mvm_mac_sta_notify, .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 7a5b7473eafa..026c2e06c46f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -452,8 +452,15 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], lockdep_is_held(&mvm->mutex)); - /* This station is in use */ - if (!IS_ERR(sta)) + /* + * This station is in use or RCU-removed; the latter happens in + * managed mode, where mac80211 removes the station before we + * can remove it from firmware (we can only do that after the + * MAC is marked unassociated), and possibly while the deauth + * frame to disconnect from the AP is still queued. Then, the + * station pointer is -ENOENT when the last skb is reclaimed. + */ + if (!IS_ERR(sta) || PTR_ERR(sta) == -ENOENT) continue; if (PTR_ERR(sta) == -EINVAL) { -- cgit v1.2.3 From 1b1ccee1e821e59c2a45c95b007aeb2c9dafd9be Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 Dec 2013 15:07:43 +0100 Subject: mfd: s2mps11: Fix build after regmap field rename in sec-core.c Fix building of s2mps11 regulator and clock drivers after renaming regmap field in struct sec_pmic_dev in commit: - "mfd/rtc: s5m: Fix register updating by adding regmap for RTC" Signed-off-by: Krzysztof Kozlowski Cc: Kyungmin Park Cc: Marek Szyprowski Signed-off-by: Mark Brown --- drivers/clk/clk-s2mps11.c | 6 +++--- drivers/regulator/s2mps11.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 7be41e676a64..00a3abe103a5 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -60,7 +60,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw) struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); int ret; - ret = regmap_update_bits(s2mps11->iodev->regmap, + ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL, s2mps11->mask, s2mps11->mask); if (!ret) @@ -74,7 +74,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw) struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); int ret; - ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL, + ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL, s2mps11->mask, ~s2mps11->mask); if (!ret) @@ -174,7 +174,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) s2mps11_clk->hw.init = &s2mps11_clks_init[i]; s2mps11_clk->mask = 1 << i; - ret = regmap_read(s2mps11_clk->iodev->regmap, + ret = regmap_read(s2mps11_clk->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL, &val); if (ret < 0) goto err_reg; diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 333677d68d0e..9e61922d8230 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -438,7 +438,7 @@ common_reg: platform_set_drvdata(pdev, s2mps11); config.dev = &pdev->dev; - config.regmap = iodev->regmap; + config.regmap = iodev->regmap_pmic; config.driver_data = s2mps11; for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { if (!reg_np) { -- cgit v1.2.3 From 7a5d49a33ca4b753b66c9b288dc4af60c2b787f7 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 13 Dec 2013 15:45:24 +0100 Subject: HID: remove SIS entries from hid_have_special_driver[] The entries are not needed, as hid-multitouch gets bound correctly automatically by contact ID. Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 48296c02ed01..b0de25824fb6 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1822,9 +1822,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, -- cgit v1.2.3 From 2256940010aab059dc238ab81b7b562b17942ec8 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Fri, 13 Dec 2013 13:44:16 +0100 Subject: ath10k: handle TKIP MIC error correctly We should check MIC error flag base on rx_attention, to have consistent status of MIC failure and FCS error. Signed-off-by: Janusz Dziedzic Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 1 + drivers/net/wireless/ath/ath10k/htt_rx.c | 15 +++++++++++++++ drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 7fc7919ea5f5..b93ae355bc08 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1183,6 +1183,7 @@ struct htt_rx_info { } rate; bool fcs_err; bool amsdu_more; + bool mic_err; }; struct ath10k_htt { diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index fcb534f2f28f..fe8bd1b59f0e 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -838,6 +838,20 @@ static bool ath10k_htt_rx_has_fcs_err(struct sk_buff *skb) return false; } +static bool ath10k_htt_rx_has_mic_err(struct sk_buff *skb) +{ + struct htt_rx_desc *rxd; + u32 flags; + + rxd = (void *)skb->data - sizeof(*rxd); + flags = __le32_to_cpu(rxd->attention.flags); + + if (flags & RX_ATTENTION_FLAGS_TKIP_MIC_ERR) + return true; + + return false; +} + static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) { struct htt_rx_desc *rxd; @@ -960,6 +974,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, info.skb = msdu_head; info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); + info.mic_err = ath10k_htt_rx_has_mic_err(msdu_head); info.signal = ATH10K_DEFAULT_NOISE_FLOOR; info.signal += rx->ppdu.combined_rssi; diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 22829803f087..74f45fa6f428 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -231,7 +231,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) ~IEEE80211_FCTL_PROTECTED); } - if (info->status == HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR) + if (info->mic_err) status->flag |= RX_FLAG_MMIC_ERROR; if (info->fcs_err) -- cgit v1.2.3 From 453cdb61c015f80e492dda217110353cd09eef18 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 13 Dec 2013 10:44:43 +0100 Subject: ath10k: fix band reporting for mgmt CCK frames on 5GHz Although CCK modulation isn't expected for 11a if it happened it made ath10k report wrong band (2GHz) for a mgmt frame that were actually received on 5Ghz band. Frequency would also decoded incorrectly too. In case of 5GHz-only devices this triggered mac80211 WARN_ON because there was no according sband pointer to be found. The patch should fix delivery of such frames by using different means to acquire band parameter. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 9ea333a7789c..3ec6c9a84e84 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -875,6 +875,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) struct wmi_mgmt_rx_event_v2 *ev_v2; struct wmi_mgmt_rx_hdr_v1 *ev_hdr; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_channel *ch; struct ieee80211_hdr *hdr; u32 rx_status; u32 channel; @@ -927,7 +928,25 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) if (rx_status & WMI_RX_STATUS_ERR_MIC) status->flag |= RX_FLAG_MMIC_ERROR; - status->band = phy_mode_to_band(phy_mode); + /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to + * MODE_11B. This means phy_mode is not a reliable source for the band + * of mgmt rx. */ + + ch = ar->scan_channel; + if (!ch) + ch = ar->rx_channel; + + if (ch) { + status->band = ch->band; + + if (phy_mode == MODE_11B && + status->band == IEEE80211_BAND_5GHZ) + ath10k_dbg(ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); + } else { + ath10k_warn("using (unreliable) phy_mode to extract band for mgmt rx\n"); + status->band = phy_mode_to_band(phy_mode); + } + status->freq = ieee80211_channel_to_frequency(channel, status->band); status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; status->rate_idx = get_rate_idx(rate, status->band); -- cgit v1.2.3 From 795f9953eaccf9e343cad9aecbf8956046090d76 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Sun, 15 Dec 2013 19:30:51 +0100 Subject: pinctrl: at91: fix clk_unprepare and clk_disable order clk_unprepare shall be called before clk_disable. Fix the issue by replacing the clk_unprepare and clk_disable calls by a single clk_disable_unprepare call. Signed-off-by: Boris BREZILLON Acked-by: Nicolas Ferre Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index bcfc8a2eebca..f91c72f878ad 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1365,13 +1365,11 @@ void at91_pinctrl_gpio_suspend(void) __raw_writel(backups[i], pio + PIO_IDR); __raw_writel(wakeups[i], pio + PIO_IER); - if (!wakeups[i]) { - clk_unprepare(gpio_chips[i]->clock); - clk_disable(gpio_chips[i]->clock); - } else { + if (!wakeups[i]) + clk_disable_unprepare(gpio_chips[i]->clock); + else printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]); - } } } -- cgit v1.2.3 From 37ef1d9243759ca69032be2a68d5d1a87a295fd4 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Sun, 15 Dec 2013 19:30:52 +0100 Subject: pinctrl: at91: replace clk_prepare + clk_enable by clk_prepare_enable Replace the clk_prepare and clk_enable calls by a single clk_prepare_enable call. Signed-off-by: Boris BREZILLON Acked-by: Nicolas Ferre Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-at91.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index f91c72f878ad..91dea50564dd 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1385,10 +1385,8 @@ void at91_pinctrl_gpio_resume(void) pio = gpio_chips[i]->regbase; - if (!wakeups[i]) { - if (clk_prepare(gpio_chips[i]->clock) == 0) - clk_enable(gpio_chips[i]->clock); - } + if (!wakeups[i]) + clk_prepare_enable(gpio_chips[i]->clock); __raw_writel(wakeups[i], pio + PIO_IDR); __raw_writel(backups[i], pio + PIO_IER); -- cgit v1.2.3 From 449666dd1efacaf3f0eb020cc617dd702356575c Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 26 Nov 2013 14:55:56 +0100 Subject: s390/cio: More efficient handling of CHPID availability events The CIO layer processes hardware events that indicate that a channel path has become available by performing a scan of available subchannels using the Store Subchannel (STSCH) instruction. Performing too many STSCH instructions in a tight loop can cause high Hypervisor overhead which can negatively impact the performance of the virtual machine as a whole. This patch reduces the number of STSCH instructions performed while processing a resource accessibility event and while varying a CHPID online. In both cases, Linux first performs a STSCH instruction on each unused subchannel to see if the subchannel has become available. If the STSCH instruction indicates that the subchannel is available, a full evaluation of this subchannel is scheduled. Since the full evaluation includes performing a STSCH instruction, the initial STSCH is unnecessary and can be removed. Signed-off-by: Peter Oberparleiter Reviewed-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc.c | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 13299f902676..eee70cb8730b 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -237,26 +237,6 @@ void chsc_chp_offline(struct chp_id chpid) for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); } -static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data) -{ - struct schib schib; - /* - * We don't know the device yet, but since a path - * may be available now to the device we'll have - * to do recognition again. - * Since we don't have any idea about which chpid - * that beast may be on we'll have to do a stsch - * on all devices, grr... - */ - if (stsch_err(schid, &schib)) - /* We're through */ - return -ENXIO; - - /* Put it on the slow path. */ - css_schedule_eval(schid); - return 0; -} - static int __s390_process_res_acc(struct subchannel *sch, void *data) { spin_lock_irq(sch->lock); @@ -287,8 +267,8 @@ static void s390_process_res_acc(struct chp_link *link) * The more information we have (info), the less scanning * will we have to do. */ - for_each_subchannel_staged(__s390_process_res_acc, - s390_process_res_acc_new_sch, link); + for_each_subchannel_staged(__s390_process_res_acc, NULL, link); + css_schedule_reprobe(); } static int @@ -663,19 +643,6 @@ static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data) return 0; } -static int -__s390_vary_chpid_on(struct subchannel_id schid, void *data) -{ - struct schib schib; - - if (stsch_err(schid, &schib)) - /* We're through */ - return -ENXIO; - /* Put it on the slow path. */ - css_schedule_eval(schid); - return 0; -} - /** * chsc_chp_vary - propagate channel-path vary operation to subchannels * @chpid: channl-path ID @@ -694,7 +661,8 @@ int chsc_chp_vary(struct chp_id chpid, int on) /* Try to update the channel path description. */ chp_update_desc(chp); for_each_subchannel_staged(s390_subchannel_vary_chpid_on, - __s390_vary_chpid_on, &chpid); + NULL, &chpid); + css_schedule_reprobe(); } else for_each_subchannel_staged(s390_subchannel_vary_chpid_off, NULL, &chpid); -- cgit v1.2.3 From b207f5a8f9a60fda4e995151af7d8670015e261d Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 26 Nov 2013 14:57:13 +0100 Subject: s390/cio: Relax subchannel scan loop The CIO layer scans for newly available I/O devices by performing a scan of available subchannels using the Store Subchannel (STSCH) instruction. This processing can take a significant amount of time during which no other task can run on the same CPU (unless CONFIG_PREEMPT has been enabled). As a result, scheduling latencies for other tasks are increased noticeably, especially on a single-CPU system. Fix this problem by explicitly allowing other tasks to be scheduled each time a subchannel has been processed. Signed-off-by: Peter Oberparleiter Reviewed-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/css.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8c2cb87bccc5..c1f9cc728c2d 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -553,6 +553,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) default: rc = 0; } + /* Allow scheduling here since the containing loop might + * take a while. */ + cond_resched(); } return rc; } -- cgit v1.2.3 From 175746eb06a8925274558793814d8c802dc48276 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 26 Nov 2013 14:58:08 +0100 Subject: s390/cio: Delay scan for newly available I/O devices The CIO layer scans for newly available I/O devices by performing a scan of available subchannels using the Store Subchannel (STSCH) instruction. Performing too many STSCH instructions in a tight loop can cause high Hypervisor overhead which can negatively impact the performance of the virtual machine as a whole. A subchannel scan is triggered for example during a hardware event that indicates that a channel path has become available. It is also triggered by the DASD device driver for each device that is set online. This patch reduces the number of STSCH instructions being performed by delaying the start of the actual subchannel scan by 1 second. Multiple scan requests that are scheduled during this time will be merged into a single scan loop. The trade-off consists of a short delay that is introduced between the time that the event is processed and a newly available device becoming usable. This delay should be acceptable since it only affects devices that have not been in use before. Signed-off-by: Peter Oberparleiter Reviewed-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/blacklist.c | 2 +- drivers/s390/cio/css.c | 13 +++++++------ drivers/s390/cio/css.h | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index a9fe3de2dec1..77ee4daec206 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -269,7 +269,7 @@ static int blacklist_parse_proc_parameters(char *buf) else return -EINVAL; - css_schedule_reprobe(); + css_schedule_eval_all_unreg(0); return rc; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index c1f9cc728c2d..604333ebf01e 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -575,7 +575,7 @@ static void css_slow_path_func(struct work_struct *unused) spin_unlock_irqrestore(&slow_subchannel_lock, flags); } -static DECLARE_WORK(slow_path_work, css_slow_path_func); +static DECLARE_DELAYED_WORK(slow_path_work, css_slow_path_func); struct workqueue_struct *cio_work_q; void css_schedule_eval(struct subchannel_id schid) @@ -585,7 +585,7 @@ void css_schedule_eval(struct subchannel_id schid) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_sch_add(slow_subchannel_set, schid); atomic_set(&css_eval_scheduled, 1); - queue_work(cio_work_q, &slow_path_work); + queue_delayed_work(cio_work_q, &slow_path_work, 0); spin_unlock_irqrestore(&slow_subchannel_lock, flags); } @@ -596,7 +596,7 @@ void css_schedule_eval_all(void) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_fill(slow_subchannel_set); atomic_set(&css_eval_scheduled, 1); - queue_work(cio_work_q, &slow_path_work); + queue_delayed_work(cio_work_q, &slow_path_work, 0); spin_unlock_irqrestore(&slow_subchannel_lock, flags); } @@ -609,7 +609,7 @@ static int __unset_registered(struct device *dev, void *data) return 0; } -static void css_schedule_eval_all_unreg(void) +void css_schedule_eval_all_unreg(unsigned long delay) { unsigned long flags; struct idset *unreg_set; @@ -627,7 +627,7 @@ static void css_schedule_eval_all_unreg(void) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_add_set(slow_subchannel_set, unreg_set); atomic_set(&css_eval_scheduled, 1); - queue_work(cio_work_q, &slow_path_work); + queue_delayed_work(cio_work_q, &slow_path_work, delay); spin_unlock_irqrestore(&slow_subchannel_lock, flags); idset_free(unreg_set); } @@ -640,7 +640,8 @@ void css_wait_for_slow_path(void) /* Schedule reprobing of all unregistered subchannels. */ void css_schedule_reprobe(void) { - css_schedule_eval_all_unreg(); + /* Schedule with a delay to allow merging of subsequent calls. */ + css_schedule_eval_all_unreg(1 * HZ); } EXPORT_SYMBOL_GPL(css_schedule_reprobe); diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 29351321bad6..2c9107e20251 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -133,6 +133,7 @@ extern struct channel_subsystem *channel_subsystems[]; /* Helper functions to build lists for the slow path. */ void css_schedule_eval(struct subchannel_id schid); void css_schedule_eval_all(void); +void css_schedule_eval_all_unreg(unsigned long delay); int css_complete_work(void); int sch_is_pseudo_sch(struct subchannel *); -- cgit v1.2.3 From 47d30674d6c79197fa7bfb0d09d5857f61e0277b Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 26 Nov 2013 14:59:21 +0100 Subject: s390/css: Prevent unnecessary allocation in subchannel loop Subchannel looping function for_each_subchannel_staged() allocates a subchannel-ID-bitmap to efficiently iterate over the list of known and unknown subchannels. Since this function is also used to iterate over known-subchannels only, optimize that case by not requiring the ID-bitmap allocation and falling back to simple bus_for_each_dev() looping. Signed-off-by: Peter Oberparleiter Reviewed-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/css.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 604333ebf01e..0268e5fd59b5 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -69,7 +69,8 @@ static int call_fn_known_sch(struct device *dev, void *data) struct cb_data *cb = data; int rc = 0; - idset_sch_del(cb->set, sch->schid); + if (cb->set) + idset_sch_del(cb->set, sch->schid); if (cb->fn_known_sch) rc = cb->fn_known_sch(sch, cb->data); return rc; @@ -115,6 +116,13 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), cb.fn_known_sch = fn_known; cb.fn_unknown_sch = fn_unknown; + if (fn_known && !fn_unknown) { + /* Skip idset allocation in case of known-only loop. */ + cb.set = NULL; + return bus_for_each_dev(&css_bus_type, NULL, &cb, + call_fn_known_sch); + } + cb.set = idset_sch_new(); if (!cb.set) /* fall back to brute force scanning in case of oom */ -- cgit v1.2.3 From e6b2551425d961e68e70e806e22ec40787f7ed67 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 26 Nov 2013 15:00:37 +0100 Subject: s390/blacklist: Perform subchannel scan only when needed Move scheduling of a subchannel scan to those instances where new devices may actually have become available. This reduces unnecessary scan work in case devices were added to the blacklist. Signed-off-by: Peter Oberparleiter Reviewed-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/blacklist.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 77ee4daec206..b3f791b2c1f8 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -260,16 +260,16 @@ static int blacklist_parse_proc_parameters(char *buf) parm = strsep(&buf, " "); - if (strcmp("free", parm) == 0) + if (strcmp("free", parm) == 0) { rc = blacklist_parse_parameters(buf, free, 0); - else if (strcmp("add", parm) == 0) + css_schedule_eval_all_unreg(0); + } else if (strcmp("add", parm) == 0) rc = blacklist_parse_parameters(buf, add, 0); else if (strcmp("purge", parm) == 0) return ccw_purge_blacklisted(); else return -EINVAL; - css_schedule_eval_all_unreg(0); return rc; } -- cgit v1.2.3 From 03439e7d0a7ab3d77a74523b9ba64736c0fc28de Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 4 Dec 2013 14:29:11 +0100 Subject: s390/3270: fix use after free of tty3270_screen structure The deactivation and freeing of the tty view of the 3270 device can race with a tty3270_update invocation via the update timer. To fix this move the del_timer_sync call for the update timer from tty3270_free_view to tty3270_free prior to the tty3270_free_screen call. Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tty3270.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 3f4ca4e09a4c..07cf182c18f9 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -125,10 +125,7 @@ static void tty3270_resize_work(struct work_struct *work); */ static void tty3270_set_timer(struct tty3270 *tp, int expires) { - if (expires == 0) - del_timer(&tp->timer); - else - mod_timer(&tp->timer, jiffies + expires); + mod_timer(&tp->timer, jiffies + expires); } /* @@ -744,7 +741,6 @@ tty3270_free_view(struct tty3270 *tp) { int pages; - del_timer_sync(&tp->timer); kbd_free(tp->kbd); raw3270_request_free(tp->kreset); raw3270_request_free(tp->read); @@ -877,6 +873,7 @@ tty3270_free(struct raw3270_view *view) { struct tty3270 *tp = container_of(view, struct tty3270, view); + del_timer_sync(&tp->timer); tty3270_free_screen(tp->screen, tp->view.rows); tty3270_free_view(tp); } -- cgit v1.2.3 From 333cce91f384409fb6a3e656dc11e21e872c5ea2 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 5 Dec 2013 18:46:51 +0100 Subject: s390/sclp_early: Get rid of sclp_early_read_info_sccb_valid The early sclp detect functions gather the available SCLP facility information. The sclp_early_read_info_sccb_valid indicates whether the early sclp request was valid. However, one external reference to it checks for particular sclp facility bits and this should be sufficient. Another occurance is in the sclp_get_ipl_info() function that is called later. Because all information are available at the early stage, save the ipl information when detecting the sclp facilities. Hence, no more checks for sclp_early_read_info_sccb_valid are required. Signed-off-by: Hendrik Brueckner Reviewed-by: Michael Holzheu Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp.h | 1 - drivers/s390/char/sclp_cmd.c | 2 -- drivers/s390/char/sclp_early.c | 36 ++++++++++++++++-------------------- 3 files changed, 16 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6fbe09686d18..fea76aed9eea 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -183,7 +183,6 @@ extern unsigned long sclp_console_full; extern u8 sclp_fac84; extern unsigned long long sclp_rzm; extern unsigned long long sclp_rnmax; -extern __initdata int sclp_early_read_info_sccb_valid; /* useful inlines */ diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index eaa21d542c5c..cb3c4e05a385 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -455,8 +455,6 @@ static int __init sclp_detect_standby_memory(void) if (OLDMEM_BASE) /* No standby memory in kdump mode */ return 0; - if (!sclp_early_read_info_sccb_valid) - return 0; if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) return 0; rc = -ENOMEM; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 1465e9563101..e4e5b32c52f2 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -38,8 +38,8 @@ struct read_info_sccb { static __initdata struct read_info_sccb early_read_info_sccb; static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); static unsigned long sclp_hsa_size; +static struct sclp_ipl_info sclp_ipl_info; -__initdata int sclp_early_read_info_sccb_valid; u64 sclp_facilities; u8 sclp_fac84; unsigned long long sclp_rzm; @@ -63,10 +63,9 @@ out: return rc; } -static void __init sclp_read_info_early(void) +static int __init sclp_read_info_early(void) { - int rc; - int i; + int rc, i; struct read_info_sccb *sccb; sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, SCLP_CMDW_READ_SCP_INFO}; @@ -83,21 +82,19 @@ static void __init sclp_read_info_early(void) if (rc) break; - if (sccb->header.response_code == 0x10) { - sclp_early_read_info_sccb_valid = 1; - break; - } + if (sccb->header.response_code == 0x10) + return 0; if (sccb->header.response_code != 0x1f0) break; } + return -EIO; } static void __init sclp_facilities_detect(void) { struct read_info_sccb *sccb; - sclp_read_info_early(); - if (!sclp_early_read_info_sccb_valid) + if (sclp_read_info_early()) return; sccb = &early_read_info_sccb; @@ -108,6 +105,12 @@ static void __init sclp_facilities_detect(void) sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; sclp_rzm <<= 20; + + /* Save IPL information */ + sclp_ipl_info.is_valid = 1; + if (sccb->flags & 0x2) + sclp_ipl_info.has_dump = 1; + memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN); } bool __init sclp_has_linemode(void) @@ -146,19 +149,12 @@ unsigned long long sclp_get_rzm(void) /* * This function will be called after sclp_facilities_detect(), which gets - * called from early.c code. Therefore the sccb should have valid contents. + * called from early.c code. The sclp_facilities_detect() function retrieves + * and saves the IPL information. */ void __init sclp_get_ipl_info(struct sclp_ipl_info *info) { - struct read_info_sccb *sccb; - - if (!sclp_early_read_info_sccb_valid) - return; - sccb = &early_read_info_sccb; - info->is_valid = 1; - if (sccb->flags & 0x2) - info->has_dump = 1; - memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); + *info = sclp_ipl_info; } static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) -- cgit v1.2.3 From 56e57a84a7856130f45009ce1713dc8ec8e59887 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 5 Dec 2013 19:03:50 +0100 Subject: s390/sclp_early: Replace early_read_info_sccb with sccb_early Replace early_read_info_sccb and use sccb_early instead. Also saves some memory. Signed-off-by: Hendrik Brueckner Reviewed-by: Michael Holzheu Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_early.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index e4e5b32c52f2..dc4ed04cbf50 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -35,8 +35,7 @@ struct read_info_sccb { u8 _reserved5[4096 - 112]; /* 112-4095 */ } __packed __aligned(PAGE_SIZE); -static __initdata struct read_info_sccb early_read_info_sccb; -static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); +static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; static unsigned long sclp_hsa_size; static struct sclp_ipl_info sclp_ipl_info; @@ -63,14 +62,12 @@ out: return rc; } -static int __init sclp_read_info_early(void) +static int __init sclp_read_info_early(struct read_info_sccb *sccb) { int rc, i; - struct read_info_sccb *sccb; sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, SCLP_CMDW_READ_SCP_INFO}; - sccb = &early_read_info_sccb; for (i = 0; i < ARRAY_SIZE(commands); i++) { do { memset(sccb, 0, sizeof(*sccb)); @@ -92,12 +89,11 @@ static int __init sclp_read_info_early(void) static void __init sclp_facilities_detect(void) { - struct read_info_sccb *sccb; + struct read_info_sccb *sccb = (void *) &sccb_early; - if (sclp_read_info_early()) + if (sclp_read_info_early(sccb)) return; - sccb = &early_read_info_sccb; sclp_facilities = sccb->facilities; sclp_fac84 = sccb->fac84; if (sccb->fac85 & 0x02) -- cgit v1.2.3 From 5d5de1a068efffb0dcc03235e6fa258201096f02 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 5 Dec 2013 19:13:36 +0100 Subject: s390/sclp_early: Pass sccb pointer to every *_detect() function Add a sccb pointer parameter to *_detect() functions instead of accessing the global sccb_early variable directly. Signed-off-by: Hendrik Brueckner Reviewed-by: Michael Holzheu Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_early.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index dc4ed04cbf50..1af3555c096d 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -87,10 +87,8 @@ static int __init sclp_read_info_early(struct read_info_sccb *sccb) return -EIO; } -static void __init sclp_facilities_detect(void) +static void __init sclp_facilities_detect(struct read_info_sccb *sccb) { - struct read_info_sccb *sccb = (void *) &sccb_early; - if (sclp_read_info_early(sccb)) return; @@ -181,11 +179,10 @@ static void __init sccb_init_eq_size(struct sdias_sccb *sccb) sccb->evbuf.dbs = 1; } -static int __init sclp_set_event_mask(unsigned long receive_mask, +static int __init sclp_set_event_mask(struct init_sccb *sccb, + unsigned long receive_mask, unsigned long send_mask) { - struct init_sccb *sccb = (void *) &sccb_early; - memset(sccb, 0, sizeof(*sccb)); sccb->header.length = sizeof(*sccb); sccb->mask_length = sizeof(sccb_mask_t); @@ -194,10 +191,8 @@ static int __init sclp_set_event_mask(unsigned long receive_mask, return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); } -static long __init sclp_hsa_size_init(void) +static long __init sclp_hsa_size_init(struct sdias_sccb *sccb) { - struct sdias_sccb *sccb = (void *) &sccb_early; - sccb_init_eq_size(sccb); if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) return -EIO; @@ -206,10 +201,8 @@ static long __init sclp_hsa_size_init(void) return 0; } -static long __init sclp_hsa_copy_wait(void) +static long __init sclp_hsa_copy_wait(struct sccb_header *sccb) { - struct sccb_header *sccb = (void *) &sccb_early; - memset(sccb, 0, PAGE_SIZE); sccb->length = PAGE_SIZE; if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) @@ -222,25 +215,25 @@ unsigned long sclp_get_hsa_size(void) return sclp_hsa_size; } -static void __init sclp_hsa_size_detect(void) +static void __init sclp_hsa_size_detect(void *sccb) { long size; /* First try synchronous interface (LPAR) */ - if (sclp_set_event_mask(0, 0x40000010)) + if (sclp_set_event_mask(sccb, 0, 0x40000010)) return; - size = sclp_hsa_size_init(); + size = sclp_hsa_size_init(sccb); if (size < 0) return; if (size != 0) goto out; /* Then try asynchronous interface (z/VM) */ - if (sclp_set_event_mask(0x00000010, 0x40000010)) + if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010)) return; - size = sclp_hsa_size_init(); + size = sclp_hsa_size_init(sccb); if (size < 0) return; - size = sclp_hsa_copy_wait(); + size = sclp_hsa_copy_wait(sccb); if (size < 0) return; out: @@ -249,7 +242,9 @@ out: void __init sclp_early_detect(void) { - sclp_facilities_detect(); - sclp_hsa_size_detect(); - sclp_set_event_mask(0, 0); + void *sccb = &sccb_early; + + sclp_facilities_detect(sccb); + sclp_hsa_size_detect(sccb); + sclp_set_event_mask(sccb, 0, 0); } -- cgit v1.2.3 From 52733e0152dad719ed6374b56fd1c33e784e44b3 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 5 Dec 2013 19:28:39 +0100 Subject: s390/sclp_early: Add function to detect sclp console capabilities Add SCLP console detect functions to encapsulate detection of SCLP console capabilities, for example, VT220 support. Reuse the sclp_send/receive masks that were stored by the most recent sclp_set_event_mask() call to prevent unnecessary SCLP calls. Signed-off-by: Hendrik Brueckner Reviewed-by: Michael Holzheu Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sclp.h | 4 ++-- drivers/s390/char/sclp_early.c | 46 +++++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 2f390956c7c1..220e171413f8 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -52,8 +52,8 @@ int sclp_chp_configure(struct chp_id chpid); int sclp_chp_deconfigure(struct chp_id chpid); int sclp_chp_read_info(struct sclp_chp_info *info); void sclp_get_ipl_info(struct sclp_ipl_info *info); -bool sclp_has_linemode(void); -bool sclp_has_vt220(void); +bool __init sclp_has_linemode(void); +bool __init sclp_has_vt220(void); int sclp_pci_configure(u32 fid); int sclp_pci_deconfigure(u32 fid); int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 1af3555c096d..82f2c389b4d1 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -36,6 +36,8 @@ struct read_info_sccb { } __packed __aligned(PAGE_SIZE); static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; +static unsigned int sclp_con_has_vt220 __initdata; +static unsigned int sclp_con_has_linemode __initdata; static unsigned long sclp_hsa_size; static struct sclp_ipl_info sclp_ipl_info; @@ -109,26 +111,12 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb) bool __init sclp_has_linemode(void) { - struct init_sccb *sccb = (void *) &sccb_early; - - if (sccb->header.response_code != 0x20) - return 0; - if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) - return 0; - if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) - return 0; - return 1; + return !!sclp_con_has_linemode; } bool __init sclp_has_vt220(void) { - struct init_sccb *sccb = (void *) &sccb_early; - - if (sccb->header.response_code != 0x20) - return 0; - if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) - return 1; - return 0; + return !!sclp_con_has_vt220; } unsigned long long sclp_get_rnmax(void) @@ -240,11 +228,37 @@ out: sclp_hsa_size = size; } +static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb) +{ + if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) + return 0; + if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) + return 0; + return 1; +} + +static void __init sclp_console_detect(struct init_sccb *sccb) +{ + if (sccb->header.response_code != 0x20) + return; + + if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) + sclp_con_has_vt220 = 1; + + if (sclp_con_check_linemode(sccb)) + sclp_con_has_linemode = 1; +} + void __init sclp_early_detect(void) { void *sccb = &sccb_early; sclp_facilities_detect(sccb); sclp_hsa_size_detect(sccb); + + /* Turn off SCLP event notifications. Also save remote masks in the + * sccb. These are sufficient to detect sclp console capabilities. + */ sclp_set_event_mask(sccb, 0, 0); + sclp_console_detect(sccb); } -- cgit v1.2.3 From 74bd0d859dc3536b01c892abfa9f87620e4bca2f Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 16 Dec 2013 10:51:54 +0100 Subject: s390/cio: fix unlocked access of online member Make sure that access to the online member of a ccw device is guarded by the ccwlock. Reported-by: Cornelia Huck Reviewed-by: Peter Oberparleiter Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e4a7ab2bb629..4a0734fcc83c 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -333,9 +333,9 @@ int ccw_device_set_offline(struct ccw_device *cdev) if (ret != 0) return ret; } - cdev->online = 0; spin_lock_irq(cdev->ccwlock); sch = to_subchannel(cdev->dev.parent); + cdev->online = 0; /* Wait until a final state or DISCONNECTED is reached */ while (!dev_fsm_final_state(cdev) && cdev->private->state != DEV_STATE_DISCONNECTED) { @@ -446,7 +446,10 @@ int ccw_device_set_online(struct ccw_device *cdev) ret = cdev->drv->set_online(cdev); if (ret) goto rollback; + + spin_lock_irq(cdev->ccwlock); cdev->online = 1; + spin_unlock_irq(cdev->ccwlock); return 0; rollback: @@ -1745,8 +1748,7 @@ ccw_device_probe (struct device *dev) return 0; } -static int -ccw_device_remove (struct device *dev) +static int ccw_device_remove(struct device *dev) { struct ccw_device *cdev = to_ccwdev(dev); struct ccw_driver *cdrv = cdev->drv; @@ -1754,9 +1756,10 @@ ccw_device_remove (struct device *dev) if (cdrv->remove) cdrv->remove(cdev); + + spin_lock_irq(cdev->ccwlock); if (cdev->online) { cdev->online = 0; - spin_lock_irq(cdev->ccwlock); ret = ccw_device_offline(cdev); spin_unlock_irq(cdev->ccwlock); if (ret == 0) @@ -1769,10 +1772,12 @@ ccw_device_remove (struct device *dev) cdev->private->dev_id.devno); /* Give up reference obtained in ccw_device_set_online(). */ put_device(&cdev->dev); + spin_lock_irq(cdev->ccwlock); } ccw_device_set_timeout(cdev, 0); cdev->drv = NULL; cdev->private->int_class = IRQIO_CIO; + spin_unlock_irq(cdev->ccwlock); return 0; } -- cgit v1.2.3 From 00381eeb47ef6b3b70d2a17c89a8205b6f1aa00a Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 16 Dec 2013 10:54:13 +0100 Subject: s390/cio: use device_lock to synchronize calls to the ccw driver When calling set_{on,off}line of a ccw device driver we hold the module reference of the owner. This is pretty useless - we don't want to prevent module unloading but driver unbinding. Use the driver core's device_lock instead. Reviewed-by: Peter Oberparleiter Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 4a0734fcc83c..e9d783563cbb 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -549,17 +549,12 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, if (!dev_fsm_final_state(cdev) && cdev->private->state != DEV_STATE_DISCONNECTED) { ret = -EAGAIN; - goto out_onoff; + goto out; } /* Prevent conflict between pending work and on-/offline processing.*/ if (work_pending(&cdev->private->todo_work)) { ret = -EAGAIN; - goto out_onoff; - } - - if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) { - ret = -EINVAL; - goto out_onoff; + goto out; } if (!strncmp(buf, "force\n", count)) { force = 1; @@ -571,6 +566,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, } if (ret) goto out; + + device_lock(dev); switch (i) { case 0: ret = online_store_handle_offline(cdev); @@ -581,10 +578,9 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, default: ret = -EINVAL; } + device_unlock(dev); + out: - if (cdev->drv) - module_put(cdev->drv->driver.owner); -out_onoff: atomic_set(&cdev->private->onoff, 0); return (ret < 0) ? ret : count; } -- cgit v1.2.3 From d5b877ffb9aa04a6fb6b6eae6dc19ca163d568a8 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 16 Dec 2013 10:56:46 +0100 Subject: s390/cio: use device_lock to synchronize calls to the ccwgroup driver When calling set_{on,off}line of a ccwgroup device driver we hold the module reference of the owner. This is pretty useless - we don't want to prevent module unloading but driver unbinding. Use the driver core's device_lock instead. Reviewed-by: Peter Oberparleiter Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 959135a01847..fd3367a1dc7a 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -128,14 +128,14 @@ static ssize_t ccwgroup_online_store(struct device *dev, const char *buf, size_t count) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); - struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); unsigned long value; int ret; - if (!dev->driver) - return -EINVAL; - if (!try_module_get(gdrv->driver.owner)) - return -EINVAL; + device_lock(dev); + if (!dev->driver) { + ret = -EINVAL; + goto out; + } ret = kstrtoul(buf, 0, &value); if (ret) @@ -148,7 +148,7 @@ static ssize_t ccwgroup_online_store(struct device *dev, else ret = -EINVAL; out: - module_put(gdrv->driver.owner); + device_unlock(dev); return (ret == 0) ? count : ret; } -- cgit v1.2.3 From f259509baafcf180c6146bc5bcc0ae7688e5017a Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Tue, 10 Dec 2013 16:20:39 +0100 Subject: ath10k: split the if_limits and if_comb Split the interface limits and inteface combination, to reflect the 10.X capabilites (no P2P, no STA and 8 VAP). kvalo: reverse order of ATH10K_FW_FEATURE_WMI_10X test, fix checkpath warnings Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ce9ef3499ecb..52f618740cd9 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3464,14 +3464,12 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = { }, }; -#ifdef CONFIG_ATH10K_DFS_CERTIFIED -static const struct ieee80211_iface_limit ath10k_if_dfs_limits[] = { +static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, }; -#endif static const struct ieee80211_iface_combination ath10k_if_comb[] = { { @@ -3481,19 +3479,22 @@ static const struct ieee80211_iface_combination ath10k_if_comb[] = { .num_different_channels = 1, .beacon_int_infra_match = true, }, -#ifdef CONFIG_ATH10K_DFS_CERTIFIED +}; + +static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = { { - .limits = ath10k_if_dfs_limits, - .n_limits = ARRAY_SIZE(ath10k_if_dfs_limits), + .limits = ath10k_10x_if_limits, + .n_limits = ARRAY_SIZE(ath10k_10x_if_limits), .max_interfaces = 8, .num_different_channels = 1, .beacon_int_infra_match = true, +#ifdef CONFIG_ATH10K_DFS_CERTIFIED .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | BIT(NL80211_CHAN_WIDTH_20) | BIT(NL80211_CHAN_WIDTH_40) | BIT(NL80211_CHAN_WIDTH_80), - } #endif + }, }; static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) @@ -3717,8 +3718,15 @@ int ath10k_mac_register(struct ath10k *ar) */ ar->hw->queues = 4; - ar->hw->wiphy->iface_combinations = ath10k_if_comb; - ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ath10k_if_comb); + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb; + ar->hw->wiphy->n_iface_combinations = + ARRAY_SIZE(ath10k_10x_if_comb); + } else { + ar->hw->wiphy->iface_combinations = ath10k_if_comb; + ar->hw->wiphy->n_iface_combinations = + ARRAY_SIZE(ath10k_if_comb); + } ar->hw->netdev_features = NETIF_F_HW_CSUM; -- cgit v1.2.3 From d354181f4d9a4b91ddbc90327cba6692ef3779a1 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Tue, 10 Dec 2013 16:20:40 +0100 Subject: ath10k: introduce NO_P2P fw feature flag Not each ath10k FW track supports P2P (10.X for instance does not) This new firmware feature flag allows to turn off P2P interface type. Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 3 +++ drivers/net/wireless/ath/ath10k/mac.c | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 79726e0fe2f0..035cbf6d1abe 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -306,6 +306,9 @@ enum ath10k_fw_features { /* firmware support tx frame management over WMI, otherwise it's HTT */ ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2, + /* Firmware does not support P2P */ + ATH10K_FW_FEATURE_NO_P2P = 3, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 52f618740cd9..5b45f3a8ec40 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3673,9 +3673,12 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); + BIT(NL80211_IFTYPE_AP); + + if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) + ar->hw->wiphy->interface_modes |= + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); ar->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | -- cgit v1.2.3 From 6fec88712cea016b1fc929fee53f67e3993194a6 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 16 Dec 2013 11:34:21 +0100 Subject: ahci: bail out on ICH6 before using AHCI BAR The check for "combined mode" (which disables ahci support) on ICH6 is done after the first use of AHCI BAR. But if ahci is not enabled AHCI BAR is initialized to 0x00000000. (At least it is on the ICH6-M I tested this on. If I understand the datasheet correctly it should also be on ICH6R.) This apparently makes the call of pcim_iomap_regions_request_all() return -EINVAL. And we end up with ahci: probe of 0000:00:1f.2 failed with error -22 (at warning level) in the logs. So check for "combined mode" before calling pcim_iomap_regions_request_all(). Signed-off-by: Paul Bolle Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 14f1e9506338..c0ed4f273cf2 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1238,15 +1238,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - /* AHCI controllers often implement SFF compatible interface. - * Grab all PCI BARs just in case. - */ - rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); - if (rc == -EBUSY) - pcim_pin_device(pdev); - if (rc) - return rc; - if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == 0x2652 || pdev->device == 0x2653)) { u8 map; @@ -1263,6 +1254,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } } + /* AHCI controllers often implement SFF compatible interface. + * Grab all PCI BARs just in case. + */ + rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); + if (rc == -EBUSY) + pcim_pin_device(pdev); + if (rc) + return rc; + hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); if (!hpriv) return -ENOMEM; -- cgit v1.2.3 From a57750f210ef4dcf271cd24d9b3e2ee0d267ad03 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Dec 2013 13:10:36 +0200 Subject: drm/i915: only build i915_debugfs.c when CONFIG_DEBUG_FS is enabled The whole file is wrapped around in #if defined(CONFIG_DEBUG_FS) anyway, so skip the file at the build level already. Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/Makefile | 3 ++- drivers/gpu/drm/i915/i915_debugfs.c | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 41838eaa799c..da682cbcb806 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -4,7 +4,6 @@ ccflags-y := -Iinclude/drm i915-y := i915_drv.o i915_dma.o i915_irq.o \ - i915_debugfs.o \ i915_gpu_error.o \ i915_suspend.o \ i915_gem.o \ @@ -55,6 +54,8 @@ i915-$(CONFIG_ACPI) += intel_acpi.o i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o +i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o + obj-$(CONFIG_DRM_I915) += i915.o CFLAGS_i915_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 242189ee3607..6294ffdcc0ac 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -40,8 +40,6 @@ #include #include "i915_drv.h" -#if defined(CONFIG_DEBUG_FS) - enum { ACTIVE_LIST, INACTIVE_LIST, @@ -3282,5 +3280,3 @@ void i915_debugfs_cleanup(struct drm_minor *minor) drm_debugfs_remove_files(info_list, 1, minor); } } - -#endif /* CONFIG_DEBUG_FS */ -- cgit v1.2.3 From 8a0a1af30cbf56b41220a02e34835022c4d72f41 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 16 Dec 2013 17:02:10 +0300 Subject: spi: tegra: checking for ERR_PTR instead of NULL dma_request_slave_channel() returns NULL on error and not ERR_PTRs. I've fixed this by using dma_request_slave_channel_reason() which does return ERR_PTRs. Fixes: a915d150f68d ('spi: tegra: convert to standard DMA DT bindings') Signed-off-by: Dan Carpenter Signed-off-by: Stephen Warren --- drivers/spi/spi-tegra20-slink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index dd6f26c05947..a728bb82090f 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -630,8 +630,8 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi, int ret; struct dma_slave_config dma_sconfig; - dma_chan = dma_request_slave_channel(tspi->dev, - dma_to_memory ? "rx" : "tx"); + dma_chan = dma_request_slave_channel_reason(tspi->dev, + dma_to_memory ? "rx" : "tx"); if (IS_ERR(dma_chan)) { ret = PTR_ERR(dma_chan); if (ret != -EPROBE_DEFER) -- cgit v1.2.3 From b8bd6dc36186fe99afa7b73e9e2d9a98ad5c4865 Mon Sep 17 00:00:00 2001 From: "Robin H. Johnson" Date: Mon, 16 Dec 2013 09:31:19 -0800 Subject: libata: disable a disk via libata.force params A user on StackExchange had a failing SSD that's soldered directly onto the motherboard of his system. The BIOS does not give any option to disable it at all, so he can't just hide it from the OS via the BIOS. The old IDE layer had hdX=noprobe override for situations like this, but that was never ported to the libata layer. This patch implements a disable flag for libata.force. Example use: libata.force=2.0:disable [v2 of the patch, removed the nodisable flag per Tejun Heo] Signed-off-by: Robin H. Johnson Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org Link: http://unix.stackexchange.com/questions/102648/how-to-tell-linux-kernel-3-0-to-completely-ignore-a-failing-disk Link: http://askubuntu.com/questions/352836/how-can-i-tell-linux-kernel-to-completely-ignore-a-disk-as-if-it-was-not-even-co Link: http://superuser.com/questions/599333/how-to-disable-kernel-probing-for-drive --- Documentation/kernel-parameters.txt | 2 ++ drivers/ata/libata-core.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 50680a59a2ff..b9e9bd854298 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1529,6 +1529,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. * atapi_dmadir: Enable ATAPI DMADIR bridge support + * disable: Disable this device. + If there are multiple matching configurations changing the same attribute, the last one is used. diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dae73efe5dbf..ff0158481d53 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6522,6 +6522,7 @@ static int __init ata_parse_force_one(char **cur, { "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST }, { "rstonce", .lflags = ATA_LFLAG_RST_ONCE }, { "atapi_dmadir", .horkage_on = ATA_HORKAGE_ATAPI_DMADIR }, + { "disable", .horkage_on = ATA_HORKAGE_DISABLE }, }; char *start = *cur, *p = *cur; char *id, *val, *endp; -- cgit v1.2.3 From d386735588c3e22129c2bc6eb64fc1d37a8f805c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 8 Dec 2013 23:23:57 -0800 Subject: drm/ttm: Fix accesses through vmas with only partial coverage VMAs covering a bo but that didn't start at the same address space offset as the bo they were mapping were incorrectly generating SEGFAULT errors in the fault handler. Reported-by: Joseph Dolinak Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index b249ab9b1eb2..6440eeac22d2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -169,9 +169,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + - drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff; - page_last = vma_pages(vma) + - drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff; + vma->vm_pgoff - drm_vma_node_start(&bo->vma_node); + page_last = vma_pages(vma) + vma->vm_pgoff - + drm_vma_node_start(&bo->vma_node); if (unlikely(page_offset >= bo->num_pages)) { retval = VM_FAULT_SIGBUS; -- cgit v1.2.3 From 309243ec14fde1149e1c66f19746e239e86caf39 Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Wed, 11 Dec 2013 23:01:44 +0100 Subject: IB/core: const'ify inbuf in struct ib_udata Userspace input buffer is not modified by kernel, so it can be 'const'. This is also a prerequisite to remove the implicit cast from INIT_UDATA(). Link: http://marc.info/?i=cover.1386798254.git.ydroneaud@opteya.com> Signed-off-by: Yann Droneaud Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 2 +- include/rdma/ib_verbs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index bdc842e9faef..9879568aed8c 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -49,7 +49,7 @@ #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ do { \ - (udata)->inbuf = (void __user *) (ibuf); \ + (udata)->inbuf = (const void __user *) (ibuf); \ (udata)->outbuf = (void __user *) (obuf); \ (udata)->inlen = (ilen); \ (udata)->outlen = (olen); \ diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 979874c627ee..61e1935c91b1 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -978,7 +978,7 @@ struct ib_uobject { }; struct ib_udata { - void __user *inbuf; + const void __user *inbuf; void __user *outbuf; size_t inlen; size_t outlen; -- cgit v1.2.3 From 8206937916bce22e79531f1eb2c54947ea3276a1 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 14 Oct 2013 22:48:04 +0900 Subject: [SCSI] scsi_debug: simplify creation and destruction of driver attribute files Instead of repeatedly calling driver_create_file() to create driver attribute files, This achieves the same thing by constructing an array of driver_attribute and setting it to bus_type->drv_groups. This change simplifies both creation and destruction of the attribute files, and also removes sparse warning caused by driver_attributes which are unnecessarily declared as global. Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 266 ++++++++++++++++++---------------------------- 1 file changed, 106 insertions(+), 160 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 80b8b10edf41..2decc6417518 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2873,13 +2873,13 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) return 0; } -static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) +static ssize_t delay_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); } -static ssize_t sdebug_delay_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t delay_store(struct device_driver *ddp, const char *buf, + size_t count) { int delay; char work[20]; @@ -2892,16 +2892,15 @@ static ssize_t sdebug_delay_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, - sdebug_delay_store); +static DRIVER_ATTR_RW(delay); -static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) +static ssize_t opts_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); } -static ssize_t sdebug_opts_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t opts_store(struct device_driver *ddp, const char *buf, + size_t count) { int opts; char work[20]; @@ -2921,15 +2920,14 @@ opts_done: scsi_debug_cmnd_count = 0; return count; } -DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, - sdebug_opts_store); +static DRIVER_ATTR_RW(opts); -static ssize_t sdebug_ptype_show(struct device_driver * ddp, char * buf) +static ssize_t ptype_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype); } -static ssize_t sdebug_ptype_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t ptype_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -2939,14 +2937,14 @@ static ssize_t sdebug_ptype_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store); +static DRIVER_ATTR_RW(ptype); -static ssize_t sdebug_dsense_show(struct device_driver * ddp, char * buf) +static ssize_t dsense_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense); } -static ssize_t sdebug_dsense_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t dsense_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -2956,15 +2954,14 @@ static ssize_t sdebug_dsense_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(dsense, S_IRUGO | S_IWUSR, sdebug_dsense_show, - sdebug_dsense_store); +static DRIVER_ATTR_RW(dsense); -static ssize_t sdebug_fake_rw_show(struct device_driver * ddp, char * buf) +static ssize_t fake_rw_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw); } -static ssize_t sdebug_fake_rw_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -2974,15 +2971,14 @@ static ssize_t sdebug_fake_rw_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(fake_rw, S_IRUGO | S_IWUSR, sdebug_fake_rw_show, - sdebug_fake_rw_store); +static DRIVER_ATTR_RW(fake_rw); -static ssize_t sdebug_no_lun_0_show(struct device_driver * ddp, char * buf) +static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0); } -static ssize_t sdebug_no_lun_0_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -2992,15 +2988,14 @@ static ssize_t sdebug_no_lun_0_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(no_lun_0, S_IRUGO | S_IWUSR, sdebug_no_lun_0_show, - sdebug_no_lun_0_store); +static DRIVER_ATTR_RW(no_lun_0); -static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) +static ssize_t num_tgts_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); } -static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -3011,27 +3006,26 @@ static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show, - sdebug_num_tgts_store); +static DRIVER_ATTR_RW(num_tgts); -static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) +static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); } -DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL); +static DRIVER_ATTR_RO(dev_size_mb); -static ssize_t sdebug_num_parts_show(struct device_driver * ddp, char * buf) +static ssize_t num_parts_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts); } -DRIVER_ATTR(num_parts, S_IRUGO, sdebug_num_parts_show, NULL); +static DRIVER_ATTR_RO(num_parts); -static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) +static ssize_t every_nth_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); } -static ssize_t sdebug_every_nth_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, + size_t count) { int nth; @@ -3042,15 +3036,14 @@ static ssize_t sdebug_every_nth_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show, - sdebug_every_nth_store); +static DRIVER_ATTR_RW(every_nth); -static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) +static ssize_t max_luns_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); } -static ssize_t sdebug_max_luns_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t max_luns_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -3061,15 +3054,14 @@ static ssize_t sdebug_max_luns_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show, - sdebug_max_luns_store); +static DRIVER_ATTR_RW(max_luns); -static ssize_t sdebug_max_queue_show(struct device_driver * ddp, char * buf) +static ssize_t max_queue_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue); } -static ssize_t sdebug_max_queue_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -3080,27 +3072,26 @@ static ssize_t sdebug_max_queue_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(max_queue, S_IRUGO | S_IWUSR, sdebug_max_queue_show, - sdebug_max_queue_store); +static DRIVER_ATTR_RW(max_queue); -static ssize_t sdebug_no_uld_show(struct device_driver * ddp, char * buf) +static ssize_t no_uld_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld); } -DRIVER_ATTR(no_uld, S_IRUGO, sdebug_no_uld_show, NULL); +static DRIVER_ATTR_RO(no_uld); -static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) +static ssize_t scsi_level_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); } -DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL); +static DRIVER_ATTR_RO(scsi_level); -static ssize_t sdebug_virtual_gb_show(struct device_driver * ddp, char * buf) +static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb); } -static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -3113,16 +3104,15 @@ static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(virtual_gb, S_IRUGO | S_IWUSR, sdebug_virtual_gb_show, - sdebug_virtual_gb_store); +static DRIVER_ATTR_RW(virtual_gb); -static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) +static ssize_t add_host_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); } -static ssize_t sdebug_add_host_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t add_host_store(struct device_driver *ddp, const char *buf, + size_t count) { int delta_hosts; @@ -3139,16 +3129,14 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp, } return count; } -DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, - sdebug_add_host_store); +static DRIVER_ATTR_RW(add_host); -static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp, - char * buf) +static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno); } -static ssize_t sdebug_vpd_use_hostno_store(struct device_driver * ddp, - const char * buf, size_t count) +static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -3158,40 +3146,39 @@ static ssize_t sdebug_vpd_use_hostno_store(struct device_driver * ddp, } return -EINVAL; } -DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show, - sdebug_vpd_use_hostno_store); +static DRIVER_ATTR_RW(vpd_use_hostno); -static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf) +static ssize_t sector_size_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size); } -DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL); +static DRIVER_ATTR_RO(sector_size); -static ssize_t sdebug_dix_show(struct device_driver *ddp, char *buf) +static ssize_t dix_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix); } -DRIVER_ATTR(dix, S_IRUGO, sdebug_dix_show, NULL); +static DRIVER_ATTR_RO(dix); -static ssize_t sdebug_dif_show(struct device_driver *ddp, char *buf) +static ssize_t dif_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif); } -DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL); +static DRIVER_ATTR_RO(dif); -static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf) +static ssize_t guard_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard); } -DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL); +static DRIVER_ATTR_RO(guard); -static ssize_t sdebug_ato_show(struct device_driver *ddp, char *buf) +static ssize_t ato_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato); } -DRIVER_ATTR(ato, S_IRUGO, sdebug_ato_show, NULL); +static DRIVER_ATTR_RO(ato); -static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf) +static ssize_t map_show(struct device_driver *ddp, char *buf) { ssize_t count; @@ -3206,15 +3193,14 @@ static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf) return count; } -DRIVER_ATTR(map, S_IRUGO, sdebug_map_show, NULL); +static DRIVER_ATTR_RO(map); -static ssize_t sdebug_removable_show(struct device_driver *ddp, - char *buf) +static ssize_t removable_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0); } -static ssize_t sdebug_removable_store(struct device_driver *ddp, - const char *buf, size_t count) +static ssize_t removable_store(struct device_driver *ddp, const char *buf, + size_t count) { int n; @@ -3224,74 +3210,43 @@ static ssize_t sdebug_removable_store(struct device_driver *ddp, } return -EINVAL; } -DRIVER_ATTR(removable, S_IRUGO | S_IWUSR, sdebug_removable_show, - sdebug_removable_store); +static DRIVER_ATTR_RW(removable); - -/* Note: The following function creates attribute files in the +/* Note: The following array creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters directory) is that auxiliary actions can be triggered when an attribute is changed. For example see: sdebug_add_host_store() above. */ -static int do_create_driverfs_files(void) -{ - int ret; - ret = driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_fake_rw); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_queue); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_no_lun_0); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_no_uld); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_removable); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dix); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dif); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_guard); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ato); - ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_map); - return ret; -} - -static void do_remove_driverfs_files(void) -{ - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_map); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ato); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_guard); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dif); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dix); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ptype); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_removable); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_parts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_no_uld); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_no_lun_0); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_queue); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_fake_rw); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dsense); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); -} +static struct attribute *sdebug_drv_attrs[] = { + &driver_attr_delay.attr, + &driver_attr_opts.attr, + &driver_attr_ptype.attr, + &driver_attr_dsense.attr, + &driver_attr_fake_rw.attr, + &driver_attr_no_lun_0.attr, + &driver_attr_num_tgts.attr, + &driver_attr_dev_size_mb.attr, + &driver_attr_num_parts.attr, + &driver_attr_every_nth.attr, + &driver_attr_max_luns.attr, + &driver_attr_max_queue.attr, + &driver_attr_no_uld.attr, + &driver_attr_scsi_level.attr, + &driver_attr_virtual_gb.attr, + &driver_attr_add_host.attr, + &driver_attr_vpd_use_hostno.attr, + &driver_attr_sector_size.attr, + &driver_attr_dix.attr, + &driver_attr_dif.attr, + &driver_attr_guard.attr, + &driver_attr_ato.attr, + &driver_attr_map.attr, + &driver_attr_removable.attr, + NULL, +}; +ATTRIBUTE_GROUPS(sdebug_drv); struct device *pseudo_primary; @@ -3456,12 +3411,6 @@ static int __init scsi_debug_init(void) ret); goto bus_unreg; } - ret = do_create_driverfs_files(); - if (ret < 0) { - printk(KERN_WARNING "scsi_debug: driver_create_file error: %d\n", - ret); - goto del_files; - } init_all_queued(); @@ -3482,9 +3431,6 @@ static int __init scsi_debug_init(void) } return 0; -del_files: - do_remove_driverfs_files(); - driver_unregister(&sdebug_driverfs_driver); bus_unreg: bus_unregister(&pseudo_lld_bus); dev_unreg: @@ -3506,7 +3452,6 @@ static void __exit scsi_debug_exit(void) stop_all_queued(); for (; k; k--) sdebug_remove_adapter(); - do_remove_driverfs_files(); driver_unregister(&sdebug_driverfs_driver); bus_unregister(&pseudo_lld_bus); root_device_unregister(pseudo_primary); @@ -4096,4 +4041,5 @@ static struct bus_type pseudo_lld_bus = { .match = pseudo_lld_bus_match, .probe = sdebug_driver_probe, .remove = sdebug_driver_remove, + .drv_groups = sdebug_drv_groups, }; -- cgit v1.2.3 From 3e0f65b34cc972d462c32769cd85b4eee6949139 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 18 Oct 2013 09:01:41 -0400 Subject: [SCSI] iscsi_transport: Additional parameters for network settings Added support to display and update additional network parameters through iscsiadm. Signed-off-by: Harish Zunjarrao Signed-off-by: Adheer Chandravanshi Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 340 +++++++++++++++++++++++++++++++++++- include/scsi/iscsi_if.h | 79 +++++++++ include/scsi/scsi_transport_iscsi.h | 3 + 3 files changed, 419 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 63a6ca49d4e5..9477f84c83a6 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -305,20 +305,71 @@ show_##type##_##name(struct device *dev, struct device_attribute *attr, \ iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \ static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL); -/* generic read only ipvi4 attribute */ +#define iscsi_iface_attr(type, name, param) \ + iscsi_iface_attr_show(type, name, ISCSI_IFACE_PARAM, param) \ +static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL); + +/* generic read only ipv4 attribute */ iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR); iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW); iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET); iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO); +iscsi_iface_net_attr(ipv4_iface, dhcp_dns_address_en, + ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN); +iscsi_iface_net_attr(ipv4_iface, dhcp_slp_da_info_en, + ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN); +iscsi_iface_net_attr(ipv4_iface, tos_en, ISCSI_NET_PARAM_IPV4_TOS_EN); +iscsi_iface_net_attr(ipv4_iface, tos, ISCSI_NET_PARAM_IPV4_TOS); +iscsi_iface_net_attr(ipv4_iface, grat_arp_en, + ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN); +iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id_en, + ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN); +iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id, + ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID); +iscsi_iface_net_attr(ipv4_iface, dhcp_req_vendor_id_en, + ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN); +iscsi_iface_net_attr(ipv4_iface, dhcp_use_vendor_id_en, + ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN); +iscsi_iface_net_attr(ipv4_iface, dhcp_vendor_id, + ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID); +iscsi_iface_net_attr(ipv4_iface, dhcp_learn_iqn_en, + ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN); +iscsi_iface_net_attr(ipv4_iface, fragment_disable, + ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE); +iscsi_iface_net_attr(ipv4_iface, incoming_forwarding_en, + ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN); +iscsi_iface_net_attr(ipv4_iface, ttl, ISCSI_NET_PARAM_IPV4_TTL); /* generic read only ipv6 attribute */ iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR); -iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL); +iscsi_iface_net_attr(ipv6_iface, link_local_addr, + ISCSI_NET_PARAM_IPV6_LINKLOCAL); iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER); iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg, ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG); iscsi_iface_net_attr(ipv6_iface, link_local_autocfg, ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG); +iscsi_iface_net_attr(ipv6_iface, link_local_state, + ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE); +iscsi_iface_net_attr(ipv6_iface, router_state, + ISCSI_NET_PARAM_IPV6_ROUTER_STATE); +iscsi_iface_net_attr(ipv6_iface, grat_neighbor_adv_en, + ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN); +iscsi_iface_net_attr(ipv6_iface, mld_en, ISCSI_NET_PARAM_IPV6_MLD_EN); +iscsi_iface_net_attr(ipv6_iface, flow_label, ISCSI_NET_PARAM_IPV6_FLOW_LABEL); +iscsi_iface_net_attr(ipv6_iface, traffic_class, + ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS); +iscsi_iface_net_attr(ipv6_iface, hop_limit, ISCSI_NET_PARAM_IPV6_HOP_LIMIT); +iscsi_iface_net_attr(ipv6_iface, nd_reachable_tmo, + ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO); +iscsi_iface_net_attr(ipv6_iface, nd_rexmit_time, + ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME); +iscsi_iface_net_attr(ipv6_iface, nd_stale_tmo, + ISCSI_NET_PARAM_IPV6_ND_STALE_TMO); +iscsi_iface_net_attr(ipv6_iface, dup_addr_detect_cnt, + ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT); +iscsi_iface_net_attr(ipv6_iface, router_adv_link_mtu, + ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU); /* common read only iface attribute */ iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE); @@ -327,6 +378,40 @@ iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY); iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED); iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU); iscsi_iface_net_attr(iface, port, ISCSI_NET_PARAM_PORT); +iscsi_iface_net_attr(iface, ipaddress_state, ISCSI_NET_PARAM_IPADDR_STATE); +iscsi_iface_net_attr(iface, delayed_ack_en, ISCSI_NET_PARAM_DELAYED_ACK_EN); +iscsi_iface_net_attr(iface, tcp_nagle_disable, + ISCSI_NET_PARAM_TCP_NAGLE_DISABLE); +iscsi_iface_net_attr(iface, tcp_wsf_disable, ISCSI_NET_PARAM_TCP_WSF_DISABLE); +iscsi_iface_net_attr(iface, tcp_wsf, ISCSI_NET_PARAM_TCP_WSF); +iscsi_iface_net_attr(iface, tcp_timer_scale, ISCSI_NET_PARAM_TCP_TIMER_SCALE); +iscsi_iface_net_attr(iface, tcp_timestamp_en, ISCSI_NET_PARAM_TCP_TIMESTAMP_EN); +iscsi_iface_net_attr(iface, cache_id, ISCSI_NET_PARAM_CACHE_ID); +iscsi_iface_net_attr(iface, redirect_en, ISCSI_NET_PARAM_REDIRECT_EN); + +/* common iscsi specific settings attributes */ +iscsi_iface_attr(iface, def_taskmgmt_tmo, ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO); +iscsi_iface_attr(iface, header_digest, ISCSI_IFACE_PARAM_HDRDGST_EN); +iscsi_iface_attr(iface, data_digest, ISCSI_IFACE_PARAM_DATADGST_EN); +iscsi_iface_attr(iface, immediate_data, ISCSI_IFACE_PARAM_IMM_DATA_EN); +iscsi_iface_attr(iface, initial_r2t, ISCSI_IFACE_PARAM_INITIAL_R2T_EN); +iscsi_iface_attr(iface, data_seq_in_order, + ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN); +iscsi_iface_attr(iface, data_pdu_in_order, ISCSI_IFACE_PARAM_PDU_INORDER_EN); +iscsi_iface_attr(iface, erl, ISCSI_IFACE_PARAM_ERL); +iscsi_iface_attr(iface, max_recv_dlength, ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH); +iscsi_iface_attr(iface, first_burst_len, ISCSI_IFACE_PARAM_FIRST_BURST); +iscsi_iface_attr(iface, max_outstanding_r2t, ISCSI_IFACE_PARAM_MAX_R2T); +iscsi_iface_attr(iface, max_burst_len, ISCSI_IFACE_PARAM_MAX_BURST); +iscsi_iface_attr(iface, chap_auth, ISCSI_IFACE_PARAM_CHAP_AUTH_EN); +iscsi_iface_attr(iface, bidi_chap, ISCSI_IFACE_PARAM_BIDI_CHAP_EN); +iscsi_iface_attr(iface, discovery_auth_optional, + ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL); +iscsi_iface_attr(iface, discovery_logout, + ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN); +iscsi_iface_attr(iface, strict_login_comp_en, + ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN); +iscsi_iface_attr(iface, initiator_name, ISCSI_IFACE_PARAM_INITIATOR_NAME); static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) @@ -335,6 +420,7 @@ static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj, struct iscsi_iface *iface = iscsi_dev_to_iface(dev); struct iscsi_transport *t = iface->transport; int param; + int param_type; if (attr == &dev_attr_iface_enabled.attr) param = ISCSI_NET_PARAM_IFACE_ENABLE; @@ -348,6 +434,60 @@ static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj, param = ISCSI_NET_PARAM_MTU; else if (attr == &dev_attr_iface_port.attr) param = ISCSI_NET_PARAM_PORT; + else if (attr == &dev_attr_iface_ipaddress_state.attr) + param = ISCSI_NET_PARAM_IPADDR_STATE; + else if (attr == &dev_attr_iface_delayed_ack_en.attr) + param = ISCSI_NET_PARAM_DELAYED_ACK_EN; + else if (attr == &dev_attr_iface_tcp_nagle_disable.attr) + param = ISCSI_NET_PARAM_TCP_NAGLE_DISABLE; + else if (attr == &dev_attr_iface_tcp_wsf_disable.attr) + param = ISCSI_NET_PARAM_TCP_WSF_DISABLE; + else if (attr == &dev_attr_iface_tcp_wsf.attr) + param = ISCSI_NET_PARAM_TCP_WSF; + else if (attr == &dev_attr_iface_tcp_timer_scale.attr) + param = ISCSI_NET_PARAM_TCP_TIMER_SCALE; + else if (attr == &dev_attr_iface_tcp_timestamp_en.attr) + param = ISCSI_NET_PARAM_TCP_TIMESTAMP_EN; + else if (attr == &dev_attr_iface_cache_id.attr) + param = ISCSI_NET_PARAM_CACHE_ID; + else if (attr == &dev_attr_iface_redirect_en.attr) + param = ISCSI_NET_PARAM_REDIRECT_EN; + else if (attr == &dev_attr_iface_def_taskmgmt_tmo.attr) + param = ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO; + else if (attr == &dev_attr_iface_header_digest.attr) + param = ISCSI_IFACE_PARAM_HDRDGST_EN; + else if (attr == &dev_attr_iface_data_digest.attr) + param = ISCSI_IFACE_PARAM_DATADGST_EN; + else if (attr == &dev_attr_iface_immediate_data.attr) + param = ISCSI_IFACE_PARAM_IMM_DATA_EN; + else if (attr == &dev_attr_iface_initial_r2t.attr) + param = ISCSI_IFACE_PARAM_INITIAL_R2T_EN; + else if (attr == &dev_attr_iface_data_seq_in_order.attr) + param = ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN; + else if (attr == &dev_attr_iface_data_pdu_in_order.attr) + param = ISCSI_IFACE_PARAM_PDU_INORDER_EN; + else if (attr == &dev_attr_iface_erl.attr) + param = ISCSI_IFACE_PARAM_ERL; + else if (attr == &dev_attr_iface_max_recv_dlength.attr) + param = ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH; + else if (attr == &dev_attr_iface_first_burst_len.attr) + param = ISCSI_IFACE_PARAM_FIRST_BURST; + else if (attr == &dev_attr_iface_max_outstanding_r2t.attr) + param = ISCSI_IFACE_PARAM_MAX_R2T; + else if (attr == &dev_attr_iface_max_burst_len.attr) + param = ISCSI_IFACE_PARAM_MAX_BURST; + else if (attr == &dev_attr_iface_chap_auth.attr) + param = ISCSI_IFACE_PARAM_CHAP_AUTH_EN; + else if (attr == &dev_attr_iface_bidi_chap.attr) + param = ISCSI_IFACE_PARAM_BIDI_CHAP_EN; + else if (attr == &dev_attr_iface_discovery_auth_optional.attr) + param = ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL; + else if (attr == &dev_attr_iface_discovery_logout.attr) + param = ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN; + else if (attr == &dev_attr_iface_strict_login_comp_en.attr) + param = ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN; + else if (attr == &dev_attr_iface_initiator_name.attr) + param = ISCSI_IFACE_PARAM_INITIATOR_NAME; else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { if (attr == &dev_attr_ipv4_iface_ipaddress.attr) param = ISCSI_NET_PARAM_IPV4_ADDR; @@ -357,6 +497,42 @@ static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj, param = ISCSI_NET_PARAM_IPV4_SUBNET; else if (attr == &dev_attr_ipv4_iface_bootproto.attr) param = ISCSI_NET_PARAM_IPV4_BOOTPROTO; + else if (attr == + &dev_attr_ipv4_iface_dhcp_dns_address_en.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN; + else if (attr == + &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN; + else if (attr == &dev_attr_ipv4_iface_tos_en.attr) + param = ISCSI_NET_PARAM_IPV4_TOS_EN; + else if (attr == &dev_attr_ipv4_iface_tos.attr) + param = ISCSI_NET_PARAM_IPV4_TOS; + else if (attr == &dev_attr_ipv4_iface_grat_arp_en.attr) + param = ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN; + else if (attr == + &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN; + else if (attr == &dev_attr_ipv4_iface_dhcp_alt_client_id.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID; + else if (attr == + &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN; + else if (attr == + &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN; + else if (attr == &dev_attr_ipv4_iface_dhcp_vendor_id.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID; + else if (attr == + &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr) + param = ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN; + else if (attr == + &dev_attr_ipv4_iface_fragment_disable.attr) + param = ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE; + else if (attr == + &dev_attr_ipv4_iface_incoming_forwarding_en.attr) + param = ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN; + else if (attr == &dev_attr_ipv4_iface_ttl.attr) + param = ISCSI_NET_PARAM_IPV4_TTL; else return 0; } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) { @@ -370,6 +546,31 @@ static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj, param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG; else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr) param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG; + else if (attr == &dev_attr_ipv6_iface_link_local_state.attr) + param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE; + else if (attr == &dev_attr_ipv6_iface_router_state.attr) + param = ISCSI_NET_PARAM_IPV6_ROUTER_STATE; + else if (attr == + &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr) + param = ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN; + else if (attr == &dev_attr_ipv6_iface_mld_en.attr) + param = ISCSI_NET_PARAM_IPV6_MLD_EN; + else if (attr == &dev_attr_ipv6_iface_flow_label.attr) + param = ISCSI_NET_PARAM_IPV6_FLOW_LABEL; + else if (attr == &dev_attr_ipv6_iface_traffic_class.attr) + param = ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS; + else if (attr == &dev_attr_ipv6_iface_hop_limit.attr) + param = ISCSI_NET_PARAM_IPV6_HOP_LIMIT; + else if (attr == &dev_attr_ipv6_iface_nd_reachable_tmo.attr) + param = ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO; + else if (attr == &dev_attr_ipv6_iface_nd_rexmit_time.attr) + param = ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME; + else if (attr == &dev_attr_ipv6_iface_nd_stale_tmo.attr) + param = ISCSI_NET_PARAM_IPV6_ND_STALE_TMO; + else if (attr == &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr) + param = ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT; + else if (attr == &dev_attr_ipv6_iface_router_adv_link_mtu.attr) + param = ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU; else return 0; } else { @@ -377,7 +578,32 @@ static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj, return 0; } - return t->attr_is_visible(ISCSI_NET_PARAM, param); + switch (param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + case ISCSI_IFACE_PARAM_HDRDGST_EN: + case ISCSI_IFACE_PARAM_DATADGST_EN: + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + case ISCSI_IFACE_PARAM_ERL: + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + case ISCSI_IFACE_PARAM_FIRST_BURST: + case ISCSI_IFACE_PARAM_MAX_R2T: + case ISCSI_IFACE_PARAM_MAX_BURST: + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + case ISCSI_IFACE_PARAM_INITIATOR_NAME: + param_type = ISCSI_IFACE_PARAM; + break; + default: + param_type = ISCSI_NET_PARAM; + } + + return t->attr_is_visible(param_type, param); } static struct attribute *iscsi_iface_attrs[] = { @@ -396,6 +622,59 @@ static struct attribute *iscsi_iface_attrs[] = { &dev_attr_ipv6_iface_link_local_autocfg.attr, &dev_attr_iface_mtu.attr, &dev_attr_iface_port.attr, + &dev_attr_iface_ipaddress_state.attr, + &dev_attr_iface_delayed_ack_en.attr, + &dev_attr_iface_tcp_nagle_disable.attr, + &dev_attr_iface_tcp_wsf_disable.attr, + &dev_attr_iface_tcp_wsf.attr, + &dev_attr_iface_tcp_timer_scale.attr, + &dev_attr_iface_tcp_timestamp_en.attr, + &dev_attr_iface_cache_id.attr, + &dev_attr_iface_redirect_en.attr, + &dev_attr_iface_def_taskmgmt_tmo.attr, + &dev_attr_iface_header_digest.attr, + &dev_attr_iface_data_digest.attr, + &dev_attr_iface_immediate_data.attr, + &dev_attr_iface_initial_r2t.attr, + &dev_attr_iface_data_seq_in_order.attr, + &dev_attr_iface_data_pdu_in_order.attr, + &dev_attr_iface_erl.attr, + &dev_attr_iface_max_recv_dlength.attr, + &dev_attr_iface_first_burst_len.attr, + &dev_attr_iface_max_outstanding_r2t.attr, + &dev_attr_iface_max_burst_len.attr, + &dev_attr_iface_chap_auth.attr, + &dev_attr_iface_bidi_chap.attr, + &dev_attr_iface_discovery_auth_optional.attr, + &dev_attr_iface_discovery_logout.attr, + &dev_attr_iface_strict_login_comp_en.attr, + &dev_attr_iface_initiator_name.attr, + &dev_attr_ipv4_iface_dhcp_dns_address_en.attr, + &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr, + &dev_attr_ipv4_iface_tos_en.attr, + &dev_attr_ipv4_iface_tos.attr, + &dev_attr_ipv4_iface_grat_arp_en.attr, + &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr, + &dev_attr_ipv4_iface_dhcp_alt_client_id.attr, + &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr, + &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr, + &dev_attr_ipv4_iface_dhcp_vendor_id.attr, + &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr, + &dev_attr_ipv4_iface_fragment_disable.attr, + &dev_attr_ipv4_iface_incoming_forwarding_en.attr, + &dev_attr_ipv4_iface_ttl.attr, + &dev_attr_ipv6_iface_link_local_state.attr, + &dev_attr_ipv6_iface_router_state.attr, + &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr, + &dev_attr_ipv6_iface_mld_en.attr, + &dev_attr_ipv6_iface_flow_label.attr, + &dev_attr_ipv6_iface_traffic_class.attr, + &dev_attr_ipv6_iface_hop_limit.attr, + &dev_attr_ipv6_iface_nd_reachable_tmo.attr, + &dev_attr_ipv6_iface_nd_rexmit_time.attr, + &dev_attr_ipv6_iface_nd_stale_tmo.attr, + &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr, + &dev_attr_ipv6_iface_router_adv_link_mtu.attr, NULL, }; @@ -404,6 +683,61 @@ static struct attribute_group iscsi_iface_group = { .is_visible = iscsi_iface_attr_is_visible, }; +/* convert iscsi_ipaddress_state values to ascii string name */ +static const struct { + enum iscsi_ipaddress_state value; + char *name; +} iscsi_ipaddress_state_names[] = { + {ISCSI_IPDDRESS_STATE_UNCONFIGURED, "Unconfigured" }, + {ISCSI_IPDDRESS_STATE_ACQUIRING, "Acquiring" }, + {ISCSI_IPDDRESS_STATE_TENTATIVE, "Tentative" }, + {ISCSI_IPDDRESS_STATE_VALID, "Valid" }, + {ISCSI_IPDDRESS_STATE_DISABLING, "Disabling" }, + {ISCSI_IPDDRESS_STATE_INVALID, "Invalid" }, + {ISCSI_IPDDRESS_STATE_DEPRECATED, "Deprecated" }, +}; + +char *iscsi_get_ipaddress_state_name(enum iscsi_ipaddress_state port_state) +{ + int i; + char *state = NULL; + + for (i = 0; i < ARRAY_SIZE(iscsi_ipaddress_state_names); i++) { + if (iscsi_ipaddress_state_names[i].value == port_state) { + state = iscsi_ipaddress_state_names[i].name; + break; + } + } + return state; +} +EXPORT_SYMBOL_GPL(iscsi_get_ipaddress_state_name); + +/* convert iscsi_router_state values to ascii string name */ +static const struct { + enum iscsi_router_state value; + char *name; +} iscsi_router_state_names[] = { + {ISCSI_ROUTER_STATE_UNKNOWN, "Unknown" }, + {ISCSI_ROUTER_STATE_ADVERTISED, "Advertised" }, + {ISCSI_ROUTER_STATE_MANUAL, "Manual" }, + {ISCSI_ROUTER_STATE_STALE, "Stale" }, +}; + +char *iscsi_get_router_state_name(enum iscsi_router_state router_state) +{ + int i; + char *state = NULL; + + for (i = 0; i < ARRAY_SIZE(iscsi_router_state_names); i++) { + if (iscsi_router_state_names[i].value == router_state) { + state = iscsi_router_state_names[i].name; + break; + } + } + return state; +} +EXPORT_SYMBOL_GPL(iscsi_get_router_state_name); + struct iscsi_iface * iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport, uint32_t iface_type, uint32_t iface_num, int dd_size) diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 765c982c625a..a572083c77cb 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -311,6 +311,7 @@ enum iscsi_param_type { ISCSI_NET_PARAM, /* iscsi_net_param */ ISCSI_FLASHNODE_PARAM, /* iscsi_flashnode_param */ ISCSI_CHAP_PARAM, /* iscsi_chap_param */ + ISCSI_IFACE_PARAM, /* iscsi_iface_param */ }; /* structure for minimalist usecase */ @@ -383,6 +384,10 @@ struct iscsi_path { #define ISCSI_VLAN_DISABLE 0x01 #define ISCSI_VLAN_ENABLE 0x02 +/* iscsi generic enable/disabled setting for various features */ +#define ISCSI_NET_PARAM_DISABLE 0x01 +#define ISCSI_NET_PARAM_ENABLE 0x02 + /* iSCSI network params */ enum iscsi_net_param { ISCSI_NET_PARAM_IPV4_ADDR = 1, @@ -405,6 +410,80 @@ enum iscsi_net_param { ISCSI_NET_PARAM_IFACE_NAME, ISCSI_NET_PARAM_MTU, ISCSI_NET_PARAM_PORT, + ISCSI_NET_PARAM_IPADDR_STATE, + ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE, + ISCSI_NET_PARAM_IPV6_ROUTER_STATE, + ISCSI_NET_PARAM_DELAYED_ACK_EN, + ISCSI_NET_PARAM_TCP_NAGLE_DISABLE, + ISCSI_NET_PARAM_TCP_WSF_DISABLE, + ISCSI_NET_PARAM_TCP_WSF, + ISCSI_NET_PARAM_TCP_TIMER_SCALE, + ISCSI_NET_PARAM_TCP_TIMESTAMP_EN, + ISCSI_NET_PARAM_CACHE_ID, + ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN, + ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN, + ISCSI_NET_PARAM_IPV4_TOS_EN, + ISCSI_NET_PARAM_IPV4_TOS, + ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN, + ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN, + ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID, + ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN, + ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN, + ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID, + ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN, + ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE, + ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN, + ISCSI_NET_PARAM_IPV4_TTL, + ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN, + ISCSI_NET_PARAM_IPV6_MLD_EN, + ISCSI_NET_PARAM_IPV6_FLOW_LABEL, + ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS, + ISCSI_NET_PARAM_IPV6_HOP_LIMIT, + ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO, + ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME, + ISCSI_NET_PARAM_IPV6_ND_STALE_TMO, + ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT, + ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU, + ISCSI_NET_PARAM_REDIRECT_EN, +}; + +enum iscsi_ipaddress_state { + ISCSI_IPDDRESS_STATE_UNCONFIGURED, + ISCSI_IPDDRESS_STATE_ACQUIRING, + ISCSI_IPDDRESS_STATE_TENTATIVE, + ISCSI_IPDDRESS_STATE_VALID, + ISCSI_IPDDRESS_STATE_DISABLING, + ISCSI_IPDDRESS_STATE_INVALID, + ISCSI_IPDDRESS_STATE_DEPRECATED, +}; + +enum iscsi_router_state { + ISCSI_ROUTER_STATE_UNKNOWN, + ISCSI_ROUTER_STATE_ADVERTISED, + ISCSI_ROUTER_STATE_MANUAL, + ISCSI_ROUTER_STATE_STALE, +}; + +/* iSCSI specific settings params for iface */ +enum iscsi_iface_param { + ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO, + ISCSI_IFACE_PARAM_HDRDGST_EN, + ISCSI_IFACE_PARAM_DATADGST_EN, + ISCSI_IFACE_PARAM_IMM_DATA_EN, + ISCSI_IFACE_PARAM_INITIAL_R2T_EN, + ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN, + ISCSI_IFACE_PARAM_PDU_INORDER_EN, + ISCSI_IFACE_PARAM_ERL, + ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH, + ISCSI_IFACE_PARAM_FIRST_BURST, + ISCSI_IFACE_PARAM_MAX_R2T, + ISCSI_IFACE_PARAM_MAX_BURST, + ISCSI_IFACE_PARAM_CHAP_AUTH_EN, + ISCSI_IFACE_PARAM_BIDI_CHAP_EN, + ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL, + ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN, + ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN, + ISCSI_IFACE_PARAM_INITIATOR_NAME, }; enum iscsi_conn_state { diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index fe7c8f3e93f8..2ac11feab6f3 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -478,4 +478,7 @@ iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data, extern struct device * iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess); +extern char * +iscsi_get_ipaddress_state_name(enum iscsi_ipaddress_state port_state); +extern char *iscsi_get_router_state_name(enum iscsi_router_state router_state); #endif -- cgit v1.2.3 From f8e934122424ab1f9a538fc2b7062d7d5b10fd6f Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 18 Oct 2013 09:01:42 -0400 Subject: [SCSI] qla4xxx: Add support for additional network parameters settings Added support to display and update additional network parameters through iscsiadm. Signed-off-by: Harish Zunjarrao Signed-off-by: Adheer Chandravanshi Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 32 ++ drivers/scsi/qla4xxx/ql4_fw.h | 43 +- drivers/scsi/qla4xxx/ql4_glbl.h | 1 + drivers/scsi/qla4xxx/ql4_isr.c | 32 ++ drivers/scsi/qla4xxx/ql4_mbx.c | 111 +++- drivers/scsi/qla4xxx/ql4_os.c | 1126 ++++++++++++++++++++++++++++++++++----- 6 files changed, 1212 insertions(+), 133 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 084d1fd59c9e..e2be308c0d9e 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -179,6 +179,10 @@ n &= ~v; \ } +#define OP_STATE(o, f, p) { \ + p = (o & f) ? "enable" : "disable"; \ +} + /* * Retry & Timeout Values */ @@ -476,6 +480,34 @@ struct ipaddress_config { uint16_t eth_mtu_size; uint16_t ipv4_port; uint16_t ipv6_port; + uint8_t control; + uint16_t ipv6_tcp_options; + uint8_t tcp_wsf; + uint8_t ipv6_tcp_wsf; + uint8_t ipv4_tos; + uint8_t ipv4_cache_id; + uint8_t ipv6_cache_id; + uint8_t ipv4_alt_cid_len; + uint8_t ipv4_alt_cid[11]; + uint8_t ipv4_vid_len; + uint8_t ipv4_vid[11]; + uint8_t ipv4_ttl; + uint16_t ipv6_flow_lbl; + uint8_t ipv6_traffic_class; + uint8_t ipv6_hop_limit; + uint32_t ipv6_nd_reach_time; + uint32_t ipv6_nd_rexmit_timer; + uint32_t ipv6_nd_stale_timeout; + uint8_t ipv6_dup_addr_detect_count; + uint32_t ipv6_gw_advrt_mtu; + uint16_t def_timeout; + uint8_t abort_timer; + uint16_t iscsi_options; + uint16_t iscsi_max_pdu_size; + uint16_t iscsi_first_burst_len; + uint16_t iscsi_max_outstnd_r2t; + uint16_t iscsi_max_burst_len; + uint8_t iscsi_name[224]; }; #define QL4_CHAP_MAX_NAME_LEN 256 diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 1243e5942b76..306065275707 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -551,6 +551,7 @@ struct addr_ctrl_blk { #define IFCB_VER_MIN 0x01 #define IFCB_VER_MAX 0x02 uint8_t control; /* 01 */ +#define CTRLOPT_NEW_CONN_DISABLE 0x0002 uint16_t fw_options; /* 02-03 */ #define FWOPT_HEARTBEAT_ENABLE 0x1000 @@ -582,11 +583,40 @@ struct addr_ctrl_blk { uint32_t shdwreg_addr_hi; /* 2C-2F */ uint16_t iscsi_opts; /* 30-31 */ +#define ISCSIOPTS_HEADER_DIGEST_EN 0x2000 +#define ISCSIOPTS_DATA_DIGEST_EN 0x1000 +#define ISCSIOPTS_IMMEDIATE_DATA_EN 0x0800 +#define ISCSIOPTS_INITIAL_R2T_EN 0x0400 +#define ISCSIOPTS_DATA_SEQ_INORDER_EN 0x0200 +#define ISCSIOPTS_DATA_PDU_INORDER_EN 0x0100 +#define ISCSIOPTS_CHAP_AUTH_EN 0x0080 +#define ISCSIOPTS_SNACK_EN 0x0040 +#define ISCSIOPTS_DISCOVERY_LOGOUT_EN 0x0020 +#define ISCSIOPTS_BIDI_CHAP_EN 0x0010 +#define ISCSIOPTS_DISCOVERY_AUTH_EN 0x0008 +#define ISCSIOPTS_STRICT_LOGIN_COMP_EN 0x0004 +#define ISCSIOPTS_ERL 0x0003 uint16_t ipv4_tcp_opts; /* 32-33 */ +#define TCPOPT_DELAYED_ACK_DISABLE 0x8000 #define TCPOPT_DHCP_ENABLE 0x0200 +#define TCPOPT_DNS_SERVER_IP_EN 0x0100 +#define TCPOPT_SLP_DA_INFO_EN 0x0080 +#define TCPOPT_NAGLE_ALGO_DISABLE 0x0020 +#define TCPOPT_WINDOW_SCALE_DISABLE 0x0010 +#define TCPOPT_TIMER_SCALE 0x000E +#define TCPOPT_TIMESTAMP_ENABLE 0x0001 uint16_t ipv4_ip_opts; /* 34-35 */ #define IPOPT_IPV4_PROTOCOL_ENABLE 0x8000 +#define IPOPT_IPV4_TOS_EN 0x4000 #define IPOPT_VLAN_TAGGING_ENABLE 0x2000 +#define IPOPT_GRAT_ARP_EN 0x1000 +#define IPOPT_ALT_CID_EN 0x0800 +#define IPOPT_REQ_VID_EN 0x0400 +#define IPOPT_USE_VID_EN 0x0200 +#define IPOPT_LEARN_IQN_EN 0x0100 +#define IPOPT_FRAGMENTATION_DISABLE 0x0010 +#define IPOPT_IN_FORWARD_EN 0x0008 +#define IPOPT_ARP_REDIRECT_EN 0x0004 uint16_t iscsi_max_pdu_size; /* 36-37 */ uint8_t ipv4_tos; /* 38 */ @@ -637,15 +667,24 @@ struct addr_ctrl_blk { uint32_t cookie; /* 200-203 */ uint16_t ipv6_port; /* 204-205 */ uint16_t ipv6_opts; /* 206-207 */ -#define IPV6_OPT_IPV6_PROTOCOL_ENABLE 0x8000 -#define IPV6_OPT_VLAN_TAGGING_ENABLE 0x2000 +#define IPV6_OPT_IPV6_PROTOCOL_ENABLE 0x8000 +#define IPV6_OPT_VLAN_TAGGING_ENABLE 0x2000 +#define IPV6_OPT_GRAT_NEIGHBOR_ADV_EN 0x1000 +#define IPV6_OPT_REDIRECT_EN 0x0004 uint16_t ipv6_addtl_opts; /* 208-209 */ +#define IPV6_ADDOPT_IGNORE_ICMP_ECHO_REQ 0x0040 +#define IPV6_ADDOPT_MLD_EN 0x0004 #define IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE 0x0002 /* Pri ACB Only */ #define IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR 0x0001 uint16_t ipv6_tcp_opts; /* 20A-20B */ +#define IPV6_TCPOPT_DELAYED_ACK_DISABLE 0x8000 +#define IPV6_TCPOPT_NAGLE_ALGO_DISABLE 0x0020 +#define IPV6_TCPOPT_WINDOW_SCALE_DISABLE 0x0010 +#define IPV6_TCPOPT_TIMER_SCALE 0x000E +#define IPV6_TCPOPT_TIMESTAMP_EN 0x0001 uint8_t ipv6_tcp_wsf; /* 20C */ uint16_t ipv6_flow_lbl; /* 20D-20F */ uint8_t ipv6_dflt_rtr_addr[16]; /* 210-21F */ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 5cef2527180a..b8e87b33b48e 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -276,6 +276,7 @@ int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config); int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr, uint32_t *data, uint32_t count); +uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state); extern int ql4xextended_error_logging; extern int ql4xdontresethba; diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 7dff09f09b71..66cc9c1ba53c 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -606,6 +606,36 @@ static int qla4_83xx_loopback_in_progress(struct scsi_qla_host *ha) return rval; } +static void qla4xxx_update_ipaddr_state(struct scsi_qla_host *ha, + uint32_t ipaddr_idx, + uint32_t ipaddr_fw_state) +{ + uint8_t ipaddr_state; + uint8_t ip_idx; + + ip_idx = ipaddr_idx & 0xF; + ipaddr_state = qla4xxx_set_ipaddr_state((uint8_t)ipaddr_fw_state); + + switch (ip_idx) { + case 0: + ha->ip_config.ipv4_addr_state = ipaddr_state; + break; + case 1: + ha->ip_config.ipv6_link_local_state = ipaddr_state; + break; + case 2: + ha->ip_config.ipv6_addr0_state = ipaddr_state; + break; + case 3: + ha->ip_config.ipv6_addr1_state = ipaddr_state; + break; + default: + ql4_printk(KERN_INFO, ha, "%s: Invalid IPADDR index %d\n", + __func__, ip_idx); + } +} + + /** * qla4xxx_isr_decode_mailbox - decodes mailbox status * @ha: Pointer to host adapter structure. @@ -741,6 +771,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, "mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0], mbox_sts[2], mbox_sts[3]); + qla4xxx_update_ipaddr_state(ha, mbox_sts[5], + mbox_sts[3]); /* mbox_sts[2] = Old ACB state * mbox_sts[3] = new ACB state */ if ((mbox_sts[3] == ACB_STATE_VALID) && diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 22cbd005bdf4..351793c0e18f 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -418,6 +418,38 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, return QLA_SUCCESS; } +uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state) +{ + uint8_t ipaddr_state; + + switch (fw_ipaddr_state) { + case IP_ADDRSTATE_UNCONFIGURED: + ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; + break; + case IP_ADDRSTATE_INVALID: + ipaddr_state = ISCSI_IPDDRESS_STATE_INVALID; + break; + case IP_ADDRSTATE_ACQUIRING: + ipaddr_state = ISCSI_IPDDRESS_STATE_ACQUIRING; + break; + case IP_ADDRSTATE_TENTATIVE: + ipaddr_state = ISCSI_IPDDRESS_STATE_TENTATIVE; + break; + case IP_ADDRSTATE_DEPRICATED: + ipaddr_state = ISCSI_IPDDRESS_STATE_DEPRECATED; + break; + case IP_ADDRSTATE_PREFERRED: + ipaddr_state = ISCSI_IPDDRESS_STATE_VALID; + break; + case IP_ADDRSTATE_DISABLING: + ipaddr_state = ISCSI_IPDDRESS_STATE_DISABLING; + break; + default: + ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; + } + return ipaddr_state; +} + static void qla4xxx_update_local_ip(struct scsi_qla_host *ha, struct addr_ctrl_blk *init_fw_cb) @@ -425,7 +457,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts); ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts); ha->ip_config.ipv4_addr_state = - le16_to_cpu(init_fw_cb->ipv4_addr_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv4_addr_state); ha->ip_config.eth_mtu_size = le16_to_cpu(init_fw_cb->eth_mtu_size); ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port); @@ -434,6 +466,8 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts); ha->ip_config.ipv6_addl_options = le16_to_cpu(init_fw_cb->ipv6_addtl_opts); + ha->ip_config.ipv6_tcp_options = + le16_to_cpu(init_fw_cb->ipv6_tcp_opts); } /* Save IPv4 Address Info */ @@ -448,17 +482,65 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, sizeof(init_fw_cb->ipv4_gw_addr))); ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag); + ha->ip_config.control = init_fw_cb->control; + ha->ip_config.tcp_wsf = init_fw_cb->ipv4_tcp_wsf; + ha->ip_config.ipv4_tos = init_fw_cb->ipv4_tos; + ha->ip_config.ipv4_cache_id = init_fw_cb->ipv4_cacheid; + ha->ip_config.ipv4_alt_cid_len = init_fw_cb->ipv4_dhcp_alt_cid_len; + memcpy(ha->ip_config.ipv4_alt_cid, init_fw_cb->ipv4_dhcp_alt_cid, + min(sizeof(ha->ip_config.ipv4_alt_cid), + sizeof(init_fw_cb->ipv4_dhcp_alt_cid))); + ha->ip_config.ipv4_vid_len = init_fw_cb->ipv4_dhcp_vid_len; + memcpy(ha->ip_config.ipv4_vid, init_fw_cb->ipv4_dhcp_vid, + min(sizeof(ha->ip_config.ipv4_vid), + sizeof(init_fw_cb->ipv4_dhcp_vid))); + ha->ip_config.ipv4_ttl = init_fw_cb->ipv4_ttl; + ha->ip_config.def_timeout = le16_to_cpu(init_fw_cb->def_timeout); + ha->ip_config.abort_timer = init_fw_cb->abort_timer; + ha->ip_config.iscsi_options = le16_to_cpu(init_fw_cb->iscsi_opts); + ha->ip_config.iscsi_max_pdu_size = + le16_to_cpu(init_fw_cb->iscsi_max_pdu_size); + ha->ip_config.iscsi_first_burst_len = + le16_to_cpu(init_fw_cb->iscsi_fburst_len); + ha->ip_config.iscsi_max_outstnd_r2t = + le16_to_cpu(init_fw_cb->iscsi_max_outstnd_r2t); + ha->ip_config.iscsi_max_burst_len = + le16_to_cpu(init_fw_cb->iscsi_max_burst_len); + memcpy(ha->ip_config.iscsi_name, init_fw_cb->iscsi_name, + min(sizeof(ha->ip_config.iscsi_name), + sizeof(init_fw_cb->iscsi_name))); if (is_ipv6_enabled(ha)) { /* Save IPv6 Address */ ha->ip_config.ipv6_link_local_state = - le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_lnk_lcl_addr_state); ha->ip_config.ipv6_addr0_state = - le16_to_cpu(init_fw_cb->ipv6_addr0_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr0_state); ha->ip_config.ipv6_addr1_state = - le16_to_cpu(init_fw_cb->ipv6_addr1_state); - ha->ip_config.ipv6_default_router_state = - le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr1_state); + + switch (le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state)) { + case IPV6_RTRSTATE_UNKNOWN: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_UNKNOWN; + break; + case IPV6_RTRSTATE_MANUAL: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_MANUAL; + break; + case IPV6_RTRSTATE_ADVERTISED: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_ADVERTISED; + break; + case IPV6_RTRSTATE_STALE: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_STALE; + break; + default: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_UNKNOWN; + } + ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE; ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80; @@ -479,6 +561,23 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, ha->ip_config.ipv6_vlan_tag = be16_to_cpu(init_fw_cb->ipv6_vlan_tag); ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port); + ha->ip_config.ipv6_cache_id = init_fw_cb->ipv6_cache_id; + ha->ip_config.ipv6_flow_lbl = + le16_to_cpu(init_fw_cb->ipv6_flow_lbl); + ha->ip_config.ipv6_traffic_class = + init_fw_cb->ipv6_traffic_class; + ha->ip_config.ipv6_hop_limit = init_fw_cb->ipv6_hop_limit; + ha->ip_config.ipv6_nd_reach_time = + le32_to_cpu(init_fw_cb->ipv6_nd_reach_time); + ha->ip_config.ipv6_nd_rexmit_timer = + le32_to_cpu(init_fw_cb->ipv6_nd_rexmit_timer); + ha->ip_config.ipv6_nd_stale_timeout = + le32_to_cpu(init_fw_cb->ipv6_nd_stale_timeout); + ha->ip_config.ipv6_dup_addr_detect_count = + init_fw_cb->ipv6_dup_addr_detect_count; + ha->ip_config.ipv6_gw_advrt_mtu = + le32_to_cpu(init_fw_cb->ipv6_gw_advrt_mtu); + ha->ip_config.ipv6_tcp_wsf = init_fw_cb->ipv6_tcp_wsf; } } diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index a28d5e624aab..b04afaefde84 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -440,6 +440,65 @@ static umode_t qla4_attr_is_visible(int param_type, int param) case ISCSI_NET_PARAM_VLAN_ENABLED: case ISCSI_NET_PARAM_MTU: case ISCSI_NET_PARAM_PORT: + case ISCSI_NET_PARAM_IPADDR_STATE: + case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE: + case ISCSI_NET_PARAM_IPV6_ROUTER_STATE: + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + case ISCSI_NET_PARAM_TCP_WSF: + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + case ISCSI_NET_PARAM_CACHE_ID: + case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: + case ISCSI_NET_PARAM_IPV4_TOS_EN: + case ISCSI_NET_PARAM_IPV4_TOS: + case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: + case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: + case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: + case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: + case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: + case ISCSI_NET_PARAM_REDIRECT_EN: + case ISCSI_NET_PARAM_IPV4_TTL: + case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: + case ISCSI_NET_PARAM_IPV6_MLD_EN: + case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: + case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: + case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: + case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: + case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: + case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: + case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: + case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: + return S_IRUGO; + default: + return 0; + } + case ISCSI_IFACE_PARAM: + switch (param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + case ISCSI_IFACE_PARAM_HDRDGST_EN: + case ISCSI_IFACE_PARAM_DATADGST_EN: + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + case ISCSI_IFACE_PARAM_ERL: + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + case ISCSI_IFACE_PARAM_FIRST_BURST: + case ISCSI_IFACE_PARAM_MAX_R2T: + case ISCSI_IFACE_PARAM_MAX_BURST: + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + case ISCSI_IFACE_PARAM_INITIATOR_NAME: return S_IRUGO; default: return 0; @@ -894,107 +953,437 @@ static int qla4xxx_get_iface_param(struct iscsi_iface *iface, { struct Scsi_Host *shost = iscsi_iface_to_shost(iface); struct scsi_qla_host *ha = to_qla_host(shost); + int ival; + char *pval = NULL; int len = -ENOSYS; - if (param_type != ISCSI_NET_PARAM) - return -ENOSYS; + if (param_type == ISCSI_NET_PARAM) { + switch (param) { + case ISCSI_NET_PARAM_IPV4_ADDR: + len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); + break; + case ISCSI_NET_PARAM_IPV4_SUBNET: + len = sprintf(buf, "%pI4\n", + &ha->ip_config.subnet_mask); + break; + case ISCSI_NET_PARAM_IPV4_GW: + len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway); + break; + case ISCSI_NET_PARAM_IFACE_ENABLE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_IPV4_PROTOCOL_ENABLE, pval); + } else { + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_IPV6_PROTOCOL_ENABLE, pval); + } - switch (param) { - case ISCSI_NET_PARAM_IPV4_ADDR: - len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); - break; - case ISCSI_NET_PARAM_IPV4_SUBNET: - len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask); - break; - case ISCSI_NET_PARAM_IPV4_GW: - len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway); - break; - case ISCSI_NET_PARAM_IFACE_ENABLE: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv4_options & - IPOPT_IPV4_PROTOCOL_ENABLE) ? - "enabled" : "disabled"); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_BOOTPROTO: len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_options & - IPV6_OPT_IPV6_PROTOCOL_ENABLE) ? - "enabled" : "disabled"); - break; - case ISCSI_NET_PARAM_IPV4_BOOTPROTO: - len = sprintf(buf, "%s\n", - (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ? - "dhcp" : "static"); - break; - case ISCSI_NET_PARAM_IPV6_ADDR: - if (iface->iface_num == 0) - len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0); - if (iface->iface_num == 1) - len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1); - break; - case ISCSI_NET_PARAM_IPV6_LINKLOCAL: - len = sprintf(buf, "%pI6\n", - &ha->ip_config.ipv6_link_local_addr); - break; - case ISCSI_NET_PARAM_IPV6_ROUTER: - len = sprintf(buf, "%pI6\n", - &ha->ip_config.ipv6_default_router_addr); - break; - case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_addl_options & - IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ? - "nd" : "static"); - break; - case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_addl_options & - IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ? - "auto" : "static"); - break; - case ISCSI_NET_PARAM_VLAN_ID: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + (ha->ip_config.tcp_options & + TCPOPT_DHCP_ENABLE) ? + "dhcp" : "static"); + break; + case ISCSI_NET_PARAM_IPV6_ADDR: + if (iface->iface_num == 0) + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_addr0); + if (iface->iface_num == 1) + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_addr1); + break; + case ISCSI_NET_PARAM_IPV6_LINKLOCAL: + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_link_local_addr); + break; + case ISCSI_NET_PARAM_IPV6_ROUTER: + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_default_router_addr); + break; + case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: + pval = (ha->ip_config.ipv6_addl_options & + IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ? + "nd" : "static"; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: + pval = (ha->ip_config.ipv6_addl_options & + IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ? + "auto" : "static"; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_VLAN_ID: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ival = ha->ip_config.ipv4_vlan_tag & + ISCSI_MAX_VLAN_ID; + else + ival = ha->ip_config.ipv6_vlan_tag & + ISCSI_MAX_VLAN_ID; + + len = sprintf(buf, "%d\n", ival); + break; + case ISCSI_NET_PARAM_VLAN_PRIORITY: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ival = (ha->ip_config.ipv4_vlan_tag >> 13) & + ISCSI_MAX_VLAN_PRIORITY; + else + ival = (ha->ip_config.ipv6_vlan_tag >> 13) & + ISCSI_MAX_VLAN_PRIORITY; + + len = sprintf(buf, "%d\n", ival); + break; + case ISCSI_NET_PARAM_VLAN_ENABLED: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_VLAN_TAGGING_ENABLE, pval); + } else { + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_VLAN_TAGGING_ENABLE, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_MTU: + len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size); + break; + case ISCSI_NET_PARAM_PORT: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%d\n", + ha->ip_config.ipv4_port); + else + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_port); + break; + case ISCSI_NET_PARAM_IPADDR_STATE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv4_addr_state); + } else { + if (iface->iface_num == 0) + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv6_addr0_state); + else if (iface->iface_num == 1) + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv6_addr1_state); + } + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE: + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv6_link_local_state); + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_ROUTER_STATE: + pval = iscsi_get_router_state_name( + ha->ip_config.ipv6_default_router_state); + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(~ha->ip_config.tcp_options, + TCPOPT_DELAYED_ACK_DISABLE, pval); + } else { + OP_STATE(~ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_DELAYED_ACK_DISABLE, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(~ha->ip_config.tcp_options, + TCPOPT_NAGLE_ALGO_DISABLE, pval); + } else { + OP_STATE(~ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_NAGLE_ALGO_DISABLE, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(~ha->ip_config.tcp_options, + TCPOPT_WINDOW_SCALE_DISABLE, pval); + } else { + OP_STATE(~ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_WINDOW_SCALE_DISABLE, + pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_TCP_WSF: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%d\n", + ha->ip_config.tcp_wsf); + else + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_tcp_wsf); + break; + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ival = (ha->ip_config.tcp_options & + TCPOPT_TIMER_SCALE) >> 1; + else + ival = (ha->ip_config.ipv6_tcp_options & + IPV6_TCPOPT_TIMER_SCALE) >> 1; + + len = sprintf(buf, "%d\n", ival); + break; + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.tcp_options, + TCPOPT_TIMESTAMP_ENABLE, pval); + } else { + OP_STATE(ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_TIMESTAMP_EN, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_CACHE_ID: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%d\n", + ha->ip_config.ipv4_cache_id); + else + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_cache_id); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: + OP_STATE(ha->ip_config.tcp_options, + TCPOPT_DNS_SERVER_IP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: + OP_STATE(ha->ip_config.tcp_options, + TCPOPT_SLP_DA_INFO_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_TOS_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_IPV4_TOS_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_TOS: + len = sprintf(buf, "%d\n", ha->ip_config.ipv4_tos); + break; + case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_GRAT_ARP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: + OP_STATE(ha->ip_config.ipv4_options, IPOPT_ALT_CID_EN, + pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: + pval = (ha->ip_config.ipv4_alt_cid_len) ? + (char *)ha->ip_config.ipv4_alt_cid : ""; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_REQ_VID_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_USE_VID_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: + pval = (ha->ip_config.ipv4_vid_len) ? + (char *)ha->ip_config.ipv4_vid : ""; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_LEARN_IQN_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: + OP_STATE(~ha->ip_config.ipv4_options, + IPOPT_FRAGMENTATION_DISABLE, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_IN_FORWARD_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_REDIRECT_EN: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_ARP_REDIRECT_EN, pval); + } else { + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_REDIRECT_EN, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_TTL: + len = sprintf(buf, "%d\n", ha->ip_config.ipv4_ttl); + break; + case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_GRAT_NEIGHBOR_ADV_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_MLD_EN: + OP_STATE(ha->ip_config.ipv6_addl_options, + IPV6_ADDOPT_MLD_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: + len = sprintf(buf, "%u\n", ha->ip_config.ipv6_flow_lbl); + break; + case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: len = sprintf(buf, "%d\n", - (ha->ip_config.ipv4_vlan_tag & - ISCSI_MAX_VLAN_ID)); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + ha->ip_config.ipv6_traffic_class); + break; + case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: len = sprintf(buf, "%d\n", - (ha->ip_config.ipv6_vlan_tag & - ISCSI_MAX_VLAN_ID)); - break; - case ISCSI_NET_PARAM_VLAN_PRIORITY: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ha->ip_config.ipv6_hop_limit); + break; + case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: len = sprintf(buf, "%d\n", - ((ha->ip_config.ipv4_vlan_tag >> 13) & - ISCSI_MAX_VLAN_PRIORITY)); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + ha->ip_config.ipv6_nd_reach_time); + break; + case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: len = sprintf(buf, "%d\n", - ((ha->ip_config.ipv6_vlan_tag >> 13) & - ISCSI_MAX_VLAN_PRIORITY)); - break; - case ISCSI_NET_PARAM_VLAN_ENABLED: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv4_options & - IPOPT_VLAN_TAGGING_ENABLE) ? - "enabled" : "disabled"); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_options & - IPV6_OPT_VLAN_TAGGING_ENABLE) ? - "enabled" : "disabled"); - break; - case ISCSI_NET_PARAM_MTU: - len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size); - break; - case ISCSI_NET_PARAM_PORT: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) - len = sprintf(buf, "%d\n", ha->ip_config.ipv4_port); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) - len = sprintf(buf, "%d\n", ha->ip_config.ipv6_port); - break; - default: - len = -ENOSYS; + ha->ip_config.ipv6_nd_rexmit_timer); + break; + case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_nd_stale_timeout); + break; + case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_dup_addr_detect_count); + break; + case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_gw_advrt_mtu); + break; + default: + len = -ENOSYS; + } + } else if (param_type == ISCSI_IFACE_PARAM) { + switch (param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + len = sprintf(buf, "%d\n", ha->ip_config.def_timeout); + break; + case ISCSI_IFACE_PARAM_HDRDGST_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_HEADER_DIGEST_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DATADGST_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DATA_DIGEST_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_IMMEDIATE_DATA_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_INITIAL_R2T_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DATA_SEQ_INORDER_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DATA_PDU_INORDER_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_ERL: + len = sprintf(buf, "%d\n", + (ha->ip_config.iscsi_options & + ISCSIOPTS_ERL)); + break; + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + len = sprintf(buf, "%u\n", + ha->ip_config.iscsi_max_pdu_size * + BYTE_UNITS); + break; + case ISCSI_IFACE_PARAM_FIRST_BURST: + len = sprintf(buf, "%u\n", + ha->ip_config.iscsi_first_burst_len * + BYTE_UNITS); + break; + case ISCSI_IFACE_PARAM_MAX_R2T: + len = sprintf(buf, "%d\n", + ha->ip_config.iscsi_max_outstnd_r2t); + break; + case ISCSI_IFACE_PARAM_MAX_BURST: + len = sprintf(buf, "%u\n", + ha->ip_config.iscsi_max_burst_len * + BYTE_UNITS); + break; + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_CHAP_AUTH_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_BIDI_CHAP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DISCOVERY_AUTH_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DISCOVERY_LOGOUT_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_STRICT_LOGIN_COMP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_INITIATOR_NAME: + len = sprintf(buf, "%s\n", ha->ip_config.iscsi_name); + break; + default: + len = -ENOSYS; + } } return len; @@ -1366,8 +1755,8 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, cpu_to_le16( IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE); else - ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for " - "IPv6 addr\n"); + ql4_printk(KERN_ERR, ha, + "Invalid autocfg setting for IPv6 addr\n"); break; case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: /* Autocfg applies to even interface */ @@ -1383,8 +1772,8 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, init_fw_cb->ipv6_addtl_opts &= cpu_to_le16( ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR); else - ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for " - "IPv6 linklocal addr\n"); + ql4_printk(KERN_ERR, ha, + "Invalid autocfg setting for IPv6 linklocal addr\n"); break; case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG: /* Autocfg applies to even interface */ @@ -1433,6 +1822,135 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, init_fw_cb->ipv6_port = cpu_to_le16(*(uint16_t *)iface_param->value); break; + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_DELAYED_ACK_DISABLE); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_DELAYED_ACK_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_NAGLE_ALGO_DISABLE); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_NAGLE_ALGO_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_WINDOW_SCALE_DISABLE); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_WINDOW_SCALE_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_tcp_wsf = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_TIMER_SCALE); + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16((iface_param->value[0] << 1) & + IPV6_TCPOPT_TIMER_SCALE); + break; + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_TIMESTAMP_EN); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_TIMESTAMP_EN); + break; + case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_opts |= + cpu_to_le16(IPV6_OPT_GRAT_NEIGHBOR_ADV_EN); + else + init_fw_cb->ipv6_opts &= + cpu_to_le16(~IPV6_OPT_GRAT_NEIGHBOR_ADV_EN); + break; + case ISCSI_NET_PARAM_REDIRECT_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_opts |= + cpu_to_le16(IPV6_OPT_REDIRECT_EN); + else + init_fw_cb->ipv6_opts &= + cpu_to_le16(~IPV6_OPT_REDIRECT_EN); + break; + case ISCSI_NET_PARAM_IPV6_MLD_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_addtl_opts |= + cpu_to_le16(IPV6_ADDOPT_MLD_EN); + else + init_fw_cb->ipv6_addtl_opts &= + cpu_to_le16(~IPV6_ADDOPT_MLD_EN); + break; + case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_flow_lbl = + cpu_to_le16(*(uint16_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_traffic_class = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_hop_limit = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_nd_reach_time = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_nd_rexmit_timer = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_nd_stale_timeout = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_dup_addr_detect_count = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_gw_advrt_mtu = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; default: ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n", iface_param->param); @@ -1501,6 +2019,195 @@ static void qla4xxx_set_ipv4(struct scsi_qla_host *ha, init_fw_cb->ipv4_port = cpu_to_le16(*(uint16_t *)iface_param->value); break; + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_DELAYED_ACK_DISABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_DELAYED_ACK_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_NAGLE_ALGO_DISABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_NAGLE_ALGO_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_WINDOW_SCALE_DISABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_WINDOW_SCALE_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_tcp_wsf = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_tcp_opts &= cpu_to_le16(~TCPOPT_TIMER_SCALE); + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16((iface_param->value[0] << 1) & + TCPOPT_TIMER_SCALE); + break; + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_TIMESTAMP_ENABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_TIMESTAMP_ENABLE); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_DNS_SERVER_IP_EN); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_DNS_SERVER_IP_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_SLP_DA_INFO_EN); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_SLP_DA_INFO_EN); + break; + case ISCSI_NET_PARAM_IPV4_TOS_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_IPV4_TOS_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_IPV4_TOS_EN); + break; + case ISCSI_NET_PARAM_IPV4_TOS: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_tos = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_GRAT_ARP_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_GRAT_ARP_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_ALT_CID_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_ALT_CID_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: + if (iface_param->iface_num & 0x1) + break; + memcpy(init_fw_cb->ipv4_dhcp_alt_cid, iface_param->value, + (sizeof(init_fw_cb->ipv4_dhcp_alt_cid) - 1)); + init_fw_cb->ipv4_dhcp_alt_cid_len = + strlen(init_fw_cb->ipv4_dhcp_alt_cid); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_REQ_VID_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_REQ_VID_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_USE_VID_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_USE_VID_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: + if (iface_param->iface_num & 0x1) + break; + memcpy(init_fw_cb->ipv4_dhcp_vid, iface_param->value, + (sizeof(init_fw_cb->ipv4_dhcp_vid) - 1)); + init_fw_cb->ipv4_dhcp_vid_len = + strlen(init_fw_cb->ipv4_dhcp_vid); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_LEARN_IQN_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_LEARN_IQN_EN); + break; + case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_FRAGMENTATION_DISABLE); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_FRAGMENTATION_DISABLE); + break; + case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_IN_FORWARD_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_IN_FORWARD_EN); + break; + case ISCSI_NET_PARAM_REDIRECT_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_ARP_REDIRECT_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_ARP_REDIRECT_EN); + break; + case ISCSI_NET_PARAM_IPV4_TTL: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_ttl = iface_param->value[0]; + break; default: ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n", iface_param->param); @@ -1508,6 +2215,168 @@ static void qla4xxx_set_ipv4(struct scsi_qla_host *ha, } } +static void qla4xxx_set_iscsi_param(struct scsi_qla_host *ha, + struct iscsi_iface_param_info *iface_param, + struct addr_ctrl_blk *init_fw_cb) +{ + switch (iface_param->param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->def_timeout = + cpu_to_le16(*(uint16_t *)iface_param->value); + break; + case ISCSI_IFACE_PARAM_HDRDGST_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_HEADER_DIGEST_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_HEADER_DIGEST_EN); + break; + case ISCSI_IFACE_PARAM_DATADGST_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DATA_DIGEST_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DATA_DIGEST_EN); + break; + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_IMMEDIATE_DATA_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_IMMEDIATE_DATA_EN); + break; + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_INITIAL_R2T_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_INITIAL_R2T_EN); + break; + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DATA_SEQ_INORDER_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DATA_SEQ_INORDER_EN); + break; + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DATA_PDU_INORDER_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DATA_PDU_INORDER_EN); + break; + case ISCSI_IFACE_PARAM_ERL: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_opts &= cpu_to_le16(~ISCSIOPTS_ERL); + init_fw_cb->iscsi_opts |= cpu_to_le16(iface_param->value[0] & + ISCSIOPTS_ERL); + break; + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_max_pdu_size = + cpu_to_le32(*(uint32_t *)iface_param->value) / + BYTE_UNITS; + break; + case ISCSI_IFACE_PARAM_FIRST_BURST: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_fburst_len = + cpu_to_le32(*(uint32_t *)iface_param->value) / + BYTE_UNITS; + break; + case ISCSI_IFACE_PARAM_MAX_R2T: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_max_outstnd_r2t = + cpu_to_le16(*(uint16_t *)iface_param->value); + break; + case ISCSI_IFACE_PARAM_MAX_BURST: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_max_burst_len = + cpu_to_le32(*(uint32_t *)iface_param->value) / + BYTE_UNITS; + break; + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_CHAP_AUTH_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_CHAP_AUTH_EN); + break; + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_BIDI_CHAP_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_BIDI_CHAP_EN); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DISCOVERY_AUTH_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DISCOVERY_AUTH_EN); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DISCOVERY_LOGOUT_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DISCOVERY_LOGOUT_EN); + break; + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_STRICT_LOGIN_COMP_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_STRICT_LOGIN_COMP_EN); + break; + default: + ql4_printk(KERN_ERR, ha, "Unknown iscsi param = %d\n", + iface_param->param); + break; + } +} + static void qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb) { @@ -1565,40 +2434,47 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) nla_for_each_attr(attr, data, len, rem) { iface_param = nla_data(attr); - if (iface_param->param_type != ISCSI_NET_PARAM) - continue; - - switch (iface_param->iface_type) { - case ISCSI_IFACE_TYPE_IPV4: - switch (iface_param->iface_num) { - case 0: - qla4xxx_set_ipv4(ha, iface_param, init_fw_cb); - break; - default: + if (iface_param->param_type == ISCSI_NET_PARAM) { + switch (iface_param->iface_type) { + case ISCSI_IFACE_TYPE_IPV4: + switch (iface_param->iface_num) { + case 0: + qla4xxx_set_ipv4(ha, iface_param, + init_fw_cb); + break; + default: /* Cannot have more than one IPv4 interface */ - ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface " - "number = %d\n", - iface_param->iface_num); + ql4_printk(KERN_ERR, ha, + "Invalid IPv4 iface number = %d\n", + iface_param->iface_num); + break; + } break; - } - break; - case ISCSI_IFACE_TYPE_IPV6: - switch (iface_param->iface_num) { - case 0: - case 1: - qla4xxx_set_ipv6(ha, iface_param, init_fw_cb); + case ISCSI_IFACE_TYPE_IPV6: + switch (iface_param->iface_num) { + case 0: + case 1: + qla4xxx_set_ipv6(ha, iface_param, + init_fw_cb); + break; + default: + /* Cannot have more than two IPv6 interface */ + ql4_printk(KERN_ERR, ha, + "Invalid IPv6 iface number = %d\n", + iface_param->iface_num); + break; + } break; default: - /* Cannot have more than two IPv6 interface */ - ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface " - "number = %d\n", - iface_param->iface_num); + ql4_printk(KERN_ERR, ha, + "Invalid iface type\n"); break; } - break; - default: - ql4_printk(KERN_ERR, ha, "Invalid iface type\n"); - break; + } else if (iface_param->param_type == ISCSI_IFACE_PARAM) { + qla4xxx_set_iscsi_param(ha, iface_param, + init_fw_cb); + } else { + continue; } } -- cgit v1.2.3 From 88397c279d6d113ef67be254bc145d198e733844 Mon Sep 17 00:00:00 2001 From: Adheer Chandravanshi Date: Fri, 18 Oct 2013 09:01:43 -0400 Subject: [SCSI] qla4xxx: Update driver version to 5.04.00-k2 Signed-off-by: Adheer Chandravanshi Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index f4fef72c9bcd..7427d94a311f 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.04.00-k1" +#define QLA4XXX_DRIVER_VERSION "5.04.00-k2" -- cgit v1.2.3 From 3c60cfd73966797746530768d66597d025a69804 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Nov 2013 10:48:11 +0300 Subject: [SCSI] qla4xxx: overflow in qla4xxx_set_chap_entry() We should cap the size of memcpy() because it comes from the network and can't be trusted. Fixes: 26ffd7b45fe9 ('[SCSI] qla4xxx: Add support to set CHAP entries') Signed-off-by: Dan Carpenter Acked-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index b04afaefde84..4706b8c0ec64 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -861,6 +861,7 @@ static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) int type; int rem = len; int rc = 0; + int size; memset(&chap_rec, 0, sizeof(chap_rec)); @@ -875,12 +876,14 @@ static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) chap_rec.chap_type = param_info->value[0]; break; case ISCSI_CHAP_PARAM_USERNAME: - memcpy(chap_rec.username, param_info->value, - param_info->len); + size = min_t(size_t, sizeof(chap_rec.username), + param_info->len); + memcpy(chap_rec.username, param_info->value, size); break; case ISCSI_CHAP_PARAM_PASSWORD: - memcpy(chap_rec.password, param_info->value, - param_info->len); + size = min_t(size_t, sizeof(chap_rec.password), + param_info->len); + memcpy(chap_rec.password, param_info->value, size); break; case ISCSI_CHAP_PARAM_PASSWORD_LEN: chap_rec.password_length = param_info->value[0]; -- cgit v1.2.3 From 6627b38fd902cd31c6ad52f9be12a17a38f0faef Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Mon, 28 Oct 2013 15:27:49 +0800 Subject: [SCSI] sr: use block layer runtime PM Migrate sr to make use of block layer runtime PM. Accordingly, the SCSI bus layer runtime PM callback is simplified as all SCSI drivers implementing runtime PM now use the block layer's request-based mechanism. Note that due to the device will be polled by kernel at a constant interval, if the autosuspend delay is set longer than the polling interval then the device will never suspend. Signed-off-by: Aaron Lu Acked-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_pm.c | 62 +++++++++++++------------------------------------- drivers/scsi/sr.c | 37 +++++++++++------------------- 2 files changed, 29 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index af4c050ce6e4..001e9ceda4c3 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -16,6 +16,8 @@ #include "scsi_priv.h" +#ifdef CONFIG_PM_SLEEP + static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *)) { int err; @@ -43,8 +45,6 @@ static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *)) return err; } -#ifdef CONFIG_PM_SLEEP - static int scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *)) { @@ -145,38 +145,22 @@ static int scsi_bus_restore(struct device *dev) #ifdef CONFIG_PM_RUNTIME -static int sdev_blk_runtime_suspend(struct scsi_device *sdev, - int (*cb)(struct device *)) +static int sdev_runtime_suspend(struct device *dev) { + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + struct scsi_device *sdev = to_scsi_device(dev); int err; err = blk_pre_runtime_suspend(sdev->request_queue); if (err) return err; - if (cb) - err = cb(&sdev->sdev_gendev); + if (pm && pm->runtime_suspend) + err = pm->runtime_suspend(dev); blk_post_runtime_suspend(sdev->request_queue, err); return err; } -static int sdev_runtime_suspend(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL; - struct scsi_device *sdev = to_scsi_device(dev); - int err; - - if (sdev->request_queue->dev) - return sdev_blk_runtime_suspend(sdev, cb); - - err = scsi_dev_type_suspend(dev, cb); - if (err == -EAGAIN) - pm_schedule_suspend(dev, jiffies_to_msecs( - round_jiffies_up_relative(HZ/10))); - return err; -} - static int scsi_runtime_suspend(struct device *dev) { int err = 0; @@ -190,31 +174,20 @@ static int scsi_runtime_suspend(struct device *dev) return err; } -static int sdev_blk_runtime_resume(struct scsi_device *sdev, - int (*cb)(struct device *)) +static int sdev_runtime_resume(struct device *dev) { + struct scsi_device *sdev = to_scsi_device(dev); + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; int err = 0; blk_pre_runtime_resume(sdev->request_queue); - if (cb) - err = cb(&sdev->sdev_gendev); + if (pm && pm->runtime_resume) + err = pm->runtime_resume(dev); blk_post_runtime_resume(sdev->request_queue, err); return err; } -static int sdev_runtime_resume(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL; - - if (sdev->request_queue->dev) - return sdev_blk_runtime_resume(sdev, cb); - else - return scsi_dev_type_resume(dev, cb); -} - static int scsi_runtime_resume(struct device *dev) { int err = 0; @@ -235,14 +208,11 @@ static int scsi_runtime_idle(struct device *dev) /* Insert hooks here for targets, hosts, and transport classes */ if (scsi_is_sdev_device(dev)) { - struct scsi_device *sdev = to_scsi_device(dev); - - if (sdev->request_queue->dev) { - pm_runtime_mark_last_busy(dev); - pm_runtime_autosuspend(dev); - return -EBUSY; - } + pm_runtime_mark_last_busy(dev); + pm_runtime_autosuspend(dev); + return -EBUSY; } + return 0; } diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 119d67f9c47e..40d85929aefe 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -161,14 +161,10 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) goto out; cd = scsi_cd(disk); kref_get(&cd->kref); - if (scsi_device_get(cd->device)) - goto out_put; - if (!scsi_autopm_get_device(cd->device)) - goto out; - - out_put: - kref_put(&cd->kref, sr_kref_release); - cd = NULL; + if (scsi_device_get(cd->device)) { + kref_put(&cd->kref, sr_kref_release); + cd = NULL; + } out: mutex_unlock(&sr_ref_mutex); return cd; @@ -180,7 +176,6 @@ static void scsi_cd_put(struct scsi_cd *cd) mutex_lock(&sr_ref_mutex); kref_put(&cd->kref, sr_kref_release); - scsi_autopm_put_device(sdev); scsi_device_put(sdev); mutex_unlock(&sr_ref_mutex); } @@ -558,8 +553,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, void __user *argp = (void __user *)arg; int ret; - scsi_autopm_get_device(cd->device); - mutex_lock(&sr_mutex); /* @@ -591,7 +584,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, out: mutex_unlock(&sr_mutex); - scsi_autopm_put_device(cd->device); return ret; } @@ -599,17 +591,11 @@ static unsigned int sr_block_check_events(struct gendisk *disk, unsigned int clearing) { struct scsi_cd *cd = scsi_cd(disk); - unsigned int ret; - if (atomic_read(&cd->device->disk_events_disable_depth) == 0) { - scsi_autopm_get_device(cd->device); - ret = cdrom_check_events(&cd->cdi, clearing); - scsi_autopm_put_device(cd->device); - } else { - ret = 0; - } + if (atomic_read(&cd->device->disk_events_disable_depth)) + return 0; - return ret; + return cdrom_check_events(&cd->cdi, clearing); } static int sr_block_revalidate_disk(struct gendisk *disk) @@ -617,8 +603,6 @@ static int sr_block_revalidate_disk(struct gendisk *disk) struct scsi_cd *cd = scsi_cd(disk); struct scsi_sense_hdr sshdr; - scsi_autopm_get_device(cd->device); - /* if the unit is not ready, nothing more to do */ if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) goto out; @@ -626,7 +610,6 @@ static int sr_block_revalidate_disk(struct gendisk *disk) sr_cd_check(&cd->cdi); get_sectorsize(cd); out: - scsi_autopm_put_device(cd->device); return 0; } @@ -747,6 +730,12 @@ static int sr_probe(struct device *dev) if (register_cdrom(&cd->cdi)) goto fail_put; + /* + * Initialize block layer runtime PM stuffs before the + * periodic event checking request gets started in add_disk. + */ + blk_pm_runtime_init(sdev->request_queue, dev); + dev_set_drvdata(dev, cd); disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); -- cgit v1.2.3 From 702890e3b910cd14c3d0ee3b4842d7e946e66b8d Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 23 Sep 2013 13:33:30 -0500 Subject: [SCSI] hpsa: do not attempt to flush the cache on locked up controllers There's no point in trying since it can't work, and if you do try, it will just hang the system on shutdown. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 20a5e6ecf945..c3db9bb1c235 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4942,6 +4942,15 @@ static void hpsa_flush_cache(struct ctlr_info *h) { char *flush_buf; struct CommandList *c; + unsigned long flags; + + /* Don't bother trying to flush the cache if locked up */ + spin_lock_irqsave(&h->lock, flags); + if (unlikely(h->lockup_detected)) { + spin_unlock_irqrestore(&h->lock, flags); + return; + } + spin_unlock_irqrestore(&h->lock, flags); flush_buf = kzalloc(4, GFP_KERNEL); if (!flush_buf) -- cgit v1.2.3 From 85009239477a9b0b06d068d6ead9226d5c809a82 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 23 Sep 2013 13:33:36 -0500 Subject: [SCSI] hpsa: add 5 second delay after doorbell reset The hardware guys tell us that after initiating a software reset via the doorbell register we need to wait 5 seconds before attempting to talk to the board *at all*. This means that we cannot watch the board to verify it transitions from "ready" to to "not ready" then back "ready", since this transition will most likely happen during those 5 seconds (though we can still verify the reset happens by watching the "driver version" field get cleared.) Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c3db9bb1c235..2a71ab903d96 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3785,6 +3785,13 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev, */ dev_info(&pdev->dev, "using doorbell to reset controller\n"); writel(use_doorbell, vaddr + SA5_DOORBELL); + + /* PMC hardware guys tell us we need a 5 second delay after + * doorbell reset and before any attempt to talk to the board + * at all to ensure that this actually works and doesn't fall + * over in some weird corner cases. + */ + msleep(5000); } else { /* Try to do it the PCI power state way */ /* Quoting from the Open CISS Specification: "The Power @@ -3981,15 +3988,22 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) need a little pause here */ msleep(HPSA_POST_RESET_PAUSE_MSECS); - /* Wait for board to become not ready, then ready. */ - dev_info(&pdev->dev, "Waiting for board to reset.\n"); - rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY); - if (rc) { - dev_warn(&pdev->dev, - "failed waiting for board to reset." - " Will try soft reset.\n"); - rc = -ENOTSUPP; /* Not expected, but try soft reset later */ - goto unmap_cfgtable; + if (!use_doorbell) { + /* Wait for board to become not ready, then ready. + * (if we used the doorbell, then we already waited 5 secs + * so the "not ready" state is already gone by so we + * won't catch it.) + */ + dev_info(&pdev->dev, "Waiting for board to reset.\n"); + rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY); + if (rc) { + dev_warn(&pdev->dev, + "failed waiting for board to reset." + " Will try soft reset.\n"); + /* Not expected, but try soft reset later */ + rc = -ENOTSUPP; + goto unmap_cfgtable; + } } rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY); if (rc) { -- cgit v1.2.3 From a4af4606dbe959a09b2fc61da7052d5ba9b292f9 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 23 Sep 2013 13:33:46 -0500 Subject: [SCSI] hpsa: remove unneeded include of seq_file.h Signed-off-by: Scott Teel Acked-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 2a71ab903d96..bb3ee8fd2a3d 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From e2d4a1f6b497e39d68775378960ad27be4f86250 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 23 Sep 2013 13:33:51 -0500 Subject: [SCSI] hpsa: fix memory leak in CCISS_BIG_PASSTHRU ioctl We were leaking a command buffer if a DMA mapping error was encountered in the CCISS_BIG_PASSTHRU ioctl. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index bb3ee8fd2a3d..f12f55669cb3 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3170,7 +3170,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) hpsa_pci_unmap(h->pdev, c, i, PCI_DMA_BIDIRECTIONAL); status = -ENOMEM; - goto cleanup1; + goto cleanup0; } c->SG[i].Addr.lower = temp64.val32.lower; c->SG[i].Addr.upper = temp64.val32.upper; @@ -3186,24 +3186,23 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) /* Copy the error information out */ memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info)); if (copy_to_user(argp, ioc, sizeof(*ioc))) { - cmd_special_free(h, c); status = -EFAULT; - goto cleanup1; + goto cleanup0; } if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) { /* Copy the data out of the buffer we created */ BYTE __user *ptr = ioc->buf; for (i = 0; i < sg_used; i++) { if (copy_to_user(ptr, buff[i], buff_size[i])) { - cmd_special_free(h, c); status = -EFAULT; - goto cleanup1; + goto cleanup0; } ptr += buff_size[i]; } } - cmd_special_free(h, c); status = 0; +cleanup0: + cmd_special_free(h, c); cleanup1: if (buff) { for (i = 0; i < sg_used; i++) -- cgit v1.2.3 From e06c8e5c34498d1ea0468401012be8d1c853c585 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 23 Sep 2013 13:33:56 -0500 Subject: [SCSI] hpsa: add MSA 2040 to list of external target devices Signed-off-by: Scott Teel Acked-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f12f55669cb3..6cc91f83aa69 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1782,6 +1782,7 @@ static unsigned char *ext_target_model[] = { "MSA2312", "MSA2324", "P2000 G3 SAS", + "MSA 2040 SAS", NULL, }; -- cgit v1.2.3 From a0bc3487e431eaea381c2c882a41274e9a02f028 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 16 Dec 2013 18:56:24 +0000 Subject: sfc: Fix RX drop filters for EF10 When we insert an filter, the firmware checks that the given RX queue index is in range even if it will not be used. In case we're inserting a drop filter, pass the value 0. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ef10.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index d352bdc4e53e..4dfc2296600d 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2245,7 +2245,9 @@ static void efx_ef10_filter_push_prep(struct efx_nic *efx, MC_CMD_FILTER_OP_IN_RX_DEST_HOST); MCDI_SET_DWORD(inbuf, FILTER_OP_IN_TX_DEST, MC_CMD_FILTER_OP_IN_TX_DEST_DEFAULT); - MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_QUEUE, spec->dmaq_id); + MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_QUEUE, + spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ? + 0 : spec->dmaq_id); MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_MODE, (spec->flags & EFX_FILTER_FLAG_RX_RSS) ? MC_CMD_FILTER_OP_IN_RX_MODE_RSS : -- cgit v1.2.3 From 5fc63a7c446e998d01a68b108fe007be675aced7 Mon Sep 17 00:00:00 2001 From: Antonios Motakis Date: Fri, 18 Oct 2013 16:08:29 +0100 Subject: iommu/arm-smmu: add devices attached to the SMMU to an IOMMU group IOMMU groups are expected by certain users of the IOMMU API, e.g. VFIO. Add new devices found by the SMMU driver to an IOMMU group to satisfy those users. Acked-by: Alex Williamson Signed-off-by: Antonios Motakis Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e46a88700b68..879da20617fb 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1494,6 +1494,13 @@ static int arm_smmu_add_device(struct device *dev) { struct arm_smmu_device *child, *parent, *smmu; struct arm_smmu_master *master = NULL; + struct iommu_group *group; + int ret; + + if (dev->archdata.iommu) { + dev_warn(dev, "IOMMU driver already assigned to device\n"); + return -EINVAL; + } spin_lock(&arm_smmu_devices_lock); list_for_each_entry(parent, &arm_smmu_devices, list) { @@ -1526,13 +1533,23 @@ static int arm_smmu_add_device(struct device *dev) if (!master) return -ENODEV; + group = iommu_group_alloc(); + if (IS_ERR(group)) { + dev_err(dev, "Failed to allocate IOMMU group\n"); + return PTR_ERR(group); + } + + ret = iommu_group_add_device(group, dev); + iommu_group_put(group); dev->archdata.iommu = smmu; - return 0; + + return ret; } static void arm_smmu_remove_device(struct device *dev) { dev->archdata.iommu = NULL; + iommu_group_remove_device(dev); } static struct iommu_ops arm_smmu_ops = { -- cgit v1.2.3 From 06f983dd571f564bdd3eb2ac4c33002034ea7810 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 5 Nov 2013 15:55:04 +0000 Subject: iommu/arm-smmu: use VA_BITS to determine arm64 virtual address space With the introduction of the VA_BITS definition for arm64, make use of it in the driver, allowing up to 42-bits of VA space when configured with 64k pages. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 879da20617fb..fa3371adea4f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -24,7 +24,7 @@ * - v7/v8 long-descriptor format * - Non-secure access to the SMMU * - 4k and 64k pages, with contiguous pte hints. - * - Up to 39-bit addressing + * - Up to 42-bit addressing (dependent on VA_BITS) * - Context fault reporting */ @@ -1747,7 +1747,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) * allocation (PTRS_PER_PGD). */ #ifdef CONFIG_64BIT - /* Current maximum output size of 39 bits */ smmu->s1_output_size = min(39UL, size); #else smmu->s1_output_size = min(32UL, size); @@ -1762,7 +1761,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) } else { #ifdef CONFIG_64BIT size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK; - size = min(39, arm_smmu_id_size_to_bits(size)); + size = min(VA_BITS, arm_smmu_id_size_to_bits(size)); #else size = 32; #endif -- cgit v1.2.3 From cf2d45b19ddb361241f36d8c9f3d0b234a18459b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 5 Nov 2013 16:32:00 +0000 Subject: iommu/arm-smmu: add support for IOMMU_EXEC Previously, all of our mappings were marked as executable, which isn't usually required. Now that we have the IOMMU_EXEC flag, use that to determine whether or not a mapping should be marked as executable. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fa3371adea4f..8911850c9444 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -61,12 +61,13 @@ #define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize) /* Page table bits */ -#define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) +#define ARM_SMMU_PTE_XN (((pteval_t)3) << 53) #define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52) #define ARM_SMMU_PTE_AF (((pteval_t)1) << 10) #define ARM_SMMU_PTE_SH_NS (((pteval_t)0) << 8) #define ARM_SMMU_PTE_SH_OS (((pteval_t)2) << 8) #define ARM_SMMU_PTE_SH_IS (((pteval_t)3) << 8) +#define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) #if PAGE_SIZE == SZ_4K #define ARM_SMMU_PTE_CONT_ENTRIES 16 @@ -1205,7 +1206,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, unsigned long pfn, int flags, int stage) { pte_t *pte, *start; - pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF; + pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF | ARM_SMMU_PTE_XN; if (pmd_none(*pmd)) { /* Allocate a new set of tables */ @@ -1244,7 +1245,9 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, } /* If no access, create a faulting entry to avoid TLB fills */ - if (!(flags & (IOMMU_READ | IOMMU_WRITE))) + if (flags & IOMMU_EXEC) + pteval &= ~ARM_SMMU_PTE_XN; + else if (!(flags & (IOMMU_READ | IOMMU_WRITE))) pteval &= ~ARM_SMMU_PTE_PAGE; pteval |= ARM_SMMU_PTE_SH_IS; -- cgit v1.2.3 From c0e30763f7ef9c7b7ff663204c9439bdbcac72ca Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Mon, 16 Dec 2013 10:01:07 -0800 Subject: mac80211_hwsim: Fix NULL pointer dereference mac80211_hwsim was crashing when receiving tx information from user space. Crash happens because txi->rate_driver_data[0] is pointing to a non valid memory address. This code path is only used by wmediumd and wmediumd doesn't provide multiple channel support, so we can pass the channel struct (data2->channel) directly to mac80211_hwsim_monitor_ack function. Signed-off-by: Javier Lopez Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c72438bb2faf..a1b32ee9594a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2011,7 +2011,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, (hwsim_flags & HWSIM_TX_STAT_ACK)) { if (skb->len >= 16) { hdr = (struct ieee80211_hdr *) skb->data; - mac80211_hwsim_monitor_ack(txi->rate_driver_data[0], + mac80211_hwsim_monitor_ack(data2->channel, hdr->addr2); } txi->flags |= IEEE80211_TX_STAT_ACK; -- cgit v1.2.3 From 38becbeadfc9318867d98c9d792b40997d5cb264 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Mon, 25 Nov 2013 11:56:09 -0800 Subject: target: Remove unused ua_dev_list member in struct se_ua Initialized but not used. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_ua.c | 1 - include/target/target_core_base.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index b04467e7547c..505519b10cb7 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -98,7 +98,6 @@ int core_scsi3_ua_allocate( pr_err("Unable to allocate struct se_ua\n"); return -ENOMEM; } - INIT_LIST_HEAD(&ua->ua_dev_list); INIT_LIST_HEAD(&ua->ua_nacl_list); ua->ua_nacl = nacl; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 45412a6afa69..d6f96c735309 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -504,7 +504,6 @@ struct se_ua { u8 ua_asc; u8 ua_ascq; struct se_node_acl *ua_nacl; - struct list_head ua_dev_list; struct list_head ua_nacl_list; }; -- cgit v1.2.3 From 3f0ed57b26ddd6358b4ab2b9bde652fd683fe02d Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Wed, 27 Nov 2013 14:57:56 -0800 Subject: target: Allocate more room for port default groups See target_stat_setup_port_default_groups, we need a 4 element array. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_fabric_configfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index dae2ad6a669e..fdadc4d6259a 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -906,7 +906,7 @@ static struct config_group *target_fabric_make_lun( lun_cg->default_groups[1] = NULL; port_stat_grp = &lun->port_stat_grps.stat_group; - port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, + port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, GFP_KERNEL); if (!port_stat_grp->default_groups) { pr_err("Unable to allocate port_stat_grp->default_groups\n"); -- cgit v1.2.3 From ab6dae8236767f9815bb00c29a56d045e33cd470 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Mon, 9 Dec 2013 14:27:36 -0800 Subject: target: Fix sizeof in kmalloc for some default_groups arrays Allocating an array of pointers, not the objects themselves. These two sites now match all the other sites. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 2 +- drivers/target/target_core_fabric_configfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 272755d03e5a..a1c23d10468e 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -2937,7 +2937,7 @@ static int __init target_core_init_configfs(void) * and ALUA Logical Unit Group and Target Port Group infrastructure. */ target_cg = &subsys->su_group; - target_cg->default_groups = kmalloc(sizeof(struct config_group) * 2, + target_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index fdadc4d6259a..7de9f0475d05 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -906,7 +906,7 @@ static struct config_group *target_fabric_make_lun( lun_cg->default_groups[1] = NULL; port_stat_grp = &lun->port_stat_grps.stat_group; - port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, + port_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 4, GFP_KERNEL); if (!port_stat_grp->default_groups) { pr_err("Unable to allocate port_stat_grp->default_groups\n"); -- cgit v1.2.3 From 320a382746e0ab1304476ea7e986a8d416ab99db Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Wed, 23 Oct 2013 13:07:34 -0600 Subject: NVMe: compat SG_IO ioctl For 32-bit versions of sg3-utils running on a 64-bit system. This is mostly a copy from the relevent portions of fs/compat_ioctl.c, with slight modifications for going through block_device_operations. Signed-off-by: Keith Busch Reviewed-by: Vishal Verma [fixed up CONFIG_COMPAT=n build problems] Signed-off-by: Matthew Wilcox --- drivers/block/nvme-core.c | 18 +++++- drivers/block/nvme-scsi.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/nvme.h | 1 + 3 files changed, 165 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index df3daeb6227f..e44350de8a21 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -1568,10 +1568,26 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, } } +#ifdef CONFIG_COMPAT +static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + struct nvme_ns *ns = bdev->bd_disk->private_data; + + switch (cmd) { + case SG_IO: + return nvme_sg_io32(ns, arg); + } + return nvme_ioctl(bdev, mode, cmd, arg); +} +#else +#define nvme_compat_ioctl NULL +#endif + static const struct block_device_operations nvme_fops = { .owner = THIS_MODULE, .ioctl = nvme_ioctl, - .compat_ioctl = nvme_ioctl, + .compat_ioctl = nvme_compat_ioctl, }; static void nvme_resubmit_bios(struct nvme_queue *nvmeq) diff --git a/drivers/block/nvme-scsi.c b/drivers/block/nvme-scsi.c index 4a4ff4eb8e23..4a0ceb64e269 100644 --- a/drivers/block/nvme-scsi.c +++ b/drivers/block/nvme-scsi.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -3038,6 +3039,152 @@ int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr) return retcode; } +#ifdef CONFIG_COMPAT +typedef struct sg_io_hdr32 { + compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ + compat_int_t dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short iovec_count; /* [i] 0 implies no scatter gather */ + compat_uint_t dxfer_len; /* [i] byte count of data transfer */ + compat_uint_t dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ + compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ + compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ + compat_int_t pack_id; /* [i->o] unused internally (normally) */ + compat_uptr_t usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status; /* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short host_status; /* [o] errors from host adapter */ + unsigned short driver_status; /* [o] errors from software driver */ + compat_int_t resid; /* [o] dxfer_len - actual_transferred */ + compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ + compat_uint_t info; /* [o] auxiliary information */ +} sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ + +typedef struct sg_iovec32 { + compat_uint_t iov_base; + compat_uint_t iov_len; +} sg_iovec32_t; + +static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count) +{ + sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1); + sg_iovec32_t __user *iov32 = dxferp; + int i; + + for (i = 0; i < iovec_count; i++) { + u32 base, len; + + if (get_user(base, &iov32[i].iov_base) || + get_user(len, &iov32[i].iov_len) || + put_user(compat_ptr(base), &iov[i].iov_base) || + put_user(len, &iov[i].iov_len)) + return -EFAULT; + } + + if (put_user(iov, &sgio->dxferp)) + return -EFAULT; + return 0; +} + +int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg) +{ + sg_io_hdr32_t __user *sgio32 = (sg_io_hdr32_t __user *)arg; + sg_io_hdr_t __user *sgio; + u16 iovec_count; + u32 data; + void __user *dxferp; + int err; + int interface_id; + + if (get_user(interface_id, &sgio32->interface_id)) + return -EFAULT; + if (interface_id != 'S') + return -EINVAL; + + if (get_user(iovec_count, &sgio32->iovec_count)) + return -EFAULT; + + { + void __user *top = compat_alloc_user_space(0); + void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) + + (iovec_count * sizeof(sg_iovec_t))); + if (new > top) + return -EINVAL; + + sgio = new; + } + + /* Ok, now construct. */ + if (copy_in_user(&sgio->interface_id, &sgio32->interface_id, + (2 * sizeof(int)) + + (2 * sizeof(unsigned char)) + + (1 * sizeof(unsigned short)) + + (1 * sizeof(unsigned int)))) + return -EFAULT; + + if (get_user(data, &sgio32->dxferp)) + return -EFAULT; + dxferp = compat_ptr(data); + if (iovec_count) { + if (sg_build_iovec(sgio, dxferp, iovec_count)) + return -EFAULT; + } else { + if (put_user(dxferp, &sgio->dxferp)) + return -EFAULT; + } + + { + unsigned char __user *cmdp; + unsigned char __user *sbp; + + if (get_user(data, &sgio32->cmdp)) + return -EFAULT; + cmdp = compat_ptr(data); + + if (get_user(data, &sgio32->sbp)) + return -EFAULT; + sbp = compat_ptr(data); + + if (put_user(cmdp, &sgio->cmdp) || + put_user(sbp, &sgio->sbp)) + return -EFAULT; + } + + if (copy_in_user(&sgio->timeout, &sgio32->timeout, + 3 * sizeof(int))) + return -EFAULT; + + if (get_user(data, &sgio32->usr_ptr)) + return -EFAULT; + if (put_user(compat_ptr(data), &sgio->usr_ptr)) + return -EFAULT; + + err = nvme_sg_io(ns, sgio); + if (err >= 0) { + void __user *datap; + + if (copy_in_user(&sgio32->pack_id, &sgio->pack_id, + sizeof(int)) || + get_user(datap, &sgio->usr_ptr) || + put_user((u32)(unsigned long)datap, + &sgio32->usr_ptr) || + copy_in_user(&sgio32->status, &sgio->status, + (4 * sizeof(unsigned char)) + + (2 * sizeof(unsigned short)) + + (3 * sizeof(int)))) + err = -EFAULT; + } + + return err; +} +#endif + int nvme_sg_get_version_num(int __user *ip) { return put_user(sg_version_num, ip); diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 8119a476cb29..5bc29197d90e 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -165,6 +165,7 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, struct sg_io_hdr; int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr); +int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg); int nvme_sg_get_version_num(int __user *ip); #endif /* _LINUX_NVME_H */ -- cgit v1.2.3 From d3233433356aa1965b60b08ee61465b20e50474b Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sun, 15 Dec 2013 13:36:51 +0400 Subject: regmap: irq: Allow using zero value for ack_base In some cases, clear interrupt register may be at address 0. This patch allows to use such configurations by adding additional configuration bit to indicate this. [With doc fix from Levente Kurusa -- broonie] Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 6 +++--- include/linux/regmap.h | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 763c60d3d277..82692068d3cb 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -113,7 +113,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * OR if there is masked interrupt which hasn't been Acked, * it'll be ignored in irq handler, then may introduce irq storm */ - if (d->mask_buf[i] && d->chip->ack_base) { + if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) { reg = d->chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); ret = regmap_write(map, reg, d->mask_buf[i]); @@ -271,7 +271,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) for (i = 0; i < data->chip->num_regs; i++) { data->status_buf[i] &= ~data->mask_buf[i]; - if (data->status_buf[i] && chip->ack_base) { + if (data->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * data->irq_reg_stride); ret = regmap_write(map, reg, data->status_buf[i]); @@ -448,7 +448,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, goto err_alloc; } - if (d->status_buf[i] && chip->ack_base) { + if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); ret = regmap_write(map, reg, diff --git a/include/linux/regmap.h b/include/linux/regmap.h index e55907804d39..c9e5fb197eb6 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -497,11 +497,13 @@ struct regmap_irq { * * @status_base: Base status register address. * @mask_base: Base mask register address. - * @ack_base: Base ack address. If zero then the chip is clear on read. + * @ack_base: Base ack address. If zero then the chip is clear on read. + * Using zero value is possible with @use_ack bit. * @wake_base: Base address for wake enables. If zero unsupported. * @irq_reg_stride: Stride to use for chips where registers are not contiguous. * @init_ack_masked: Ack all masked interrupts once during initalization. * @mask_invert: Inverted mask register: cleared bits are masked out. + * @use_ack: Use @ack register even if it is zero. * @wake_invert: Inverted wake register: cleared bits are wake enabled. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * @@ -520,6 +522,7 @@ struct regmap_irq_chip { unsigned int irq_reg_stride; bool init_ack_masked:1; bool mask_invert:1; + bool use_ack:1; bool wake_invert:1; bool runtime_pm:1; -- cgit v1.2.3 From 0a8d44cb33377969337fa6c1961b631605d5f453 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 15 Oct 2013 15:01:10 -0400 Subject: NVMe: Fix lockdep warnings During the initialisation path, the queue lock is taken without interrupt protection. It's perfectly safe to do so, because the interrupt handler can't run at this point, but it confuses lockdep. Signed-off-by: Matthew Wilcox --- drivers/block/nvme-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index e44350de8a21..0e9c5dcb2bd7 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -1172,9 +1172,9 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid) if (result < 0) goto release_sq; - spin_lock(&nvmeq->q_lock); + spin_lock_irq(&nvmeq->q_lock); nvme_init_queue(nvmeq, qid); - spin_unlock(&nvmeq->q_lock); + spin_unlock_irq(&nvmeq->q_lock); return result; @@ -1290,9 +1290,9 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev) if (result) return result; - spin_lock(&nvmeq->q_lock); + spin_lock_irq(&nvmeq->q_lock); nvme_init_queue(nvmeq, 0); - spin_unlock(&nvmeq->q_lock); + spin_unlock_irq(&nvmeq->q_lock); return result; } @@ -1836,9 +1836,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) for (i = dev->queue_count - 1; i > nr_io_queues; i--) { struct nvme_queue *nvmeq = dev->queues[i]; - spin_lock(&nvmeq->q_lock); + spin_lock_irq(&nvmeq->q_lock); nvme_cancel_ios(nvmeq, false); - spin_unlock(&nvmeq->q_lock); + spin_unlock_irq(&nvmeq->q_lock); nvme_free_queue(nvmeq); dev->queue_count--; -- cgit v1.2.3 From 68608c268bf265b039daeaafee6c902dfef32024 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 21 Jun 2013 14:36:34 -0400 Subject: NVMe: Cache dev->pci_dev in a local pointer Helps with line-length issues Signed-off-by: Matthew Wilcox --- drivers/block/nvme-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 0e9c5dcb2bd7..300766973d76 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -1891,6 +1891,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) */ static int nvme_dev_add(struct nvme_dev *dev) { + struct pci_dev *pdev = dev->pci_dev; int res; unsigned nn, i; struct nvme_ns *ns; @@ -1900,8 +1901,7 @@ static int nvme_dev_add(struct nvme_dev *dev) dma_addr_t dma_addr; int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12; - mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr, - GFP_KERNEL); + mem = dma_alloc_coherent(&pdev->dev, 8192, &dma_addr, GFP_KERNEL); if (!mem) return -ENOMEM; @@ -1919,8 +1919,8 @@ static int nvme_dev_add(struct nvme_dev *dev) memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); if (ctrl->mdts) dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9); - if ((dev->pci_dev->vendor == PCI_VENDOR_ID_INTEL) && - (dev->pci_dev->device == 0x0953) && ctrl->vs[3]) + if ((pdev->vendor == PCI_VENDOR_ID_INTEL) && + (pdev->device == 0x0953) && ctrl->vs[3]) dev->stripe_size = 1 << (ctrl->vs[3] + shift); id_ns = mem; -- cgit v1.2.3 From 3b58ee13da7510115b66f71c67c9e87b47e9c4aa Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 13 Dec 2013 09:14:07 -0800 Subject: regmap: Allow regmap_bulk_read() to work for "no-bus" regmaps regmap_bulk_read() should decay to performing individual reads if we're using a "no-bus" regmap. Unfortunately, it returns an error because there is no map->bus pointer. Fix it. Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 9a36ac14b0b5..02fa0e48b0f5 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1897,14 +1897,10 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, size_t val_bytes = map->format.val_bytes; bool vol = regmap_volatile_range(map, reg, val_count); - if (!map->bus) - return -EINVAL; - if (!map->format.parse_inplace) - return -EINVAL; if (reg % map->reg_stride) return -EINVAL; - if (vol || map->cache_type == REGCACHE_NONE) { + if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) { /* * Some devices does not support bulk read, for * them we have a series of single read operations. -- cgit v1.2.3 From 9a6b94584de1a0467d85b435df9c744c5c45a270 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 10 Dec 2013 13:10:36 -0700 Subject: NVMe: Device resume error handling Adds controller error handling on resume power management. If the device fails to initialize, the device is queued for a reset. If the reset fails, a thread is spawned to remove the pci device. If the device resumes as "busy", the device is responding to admin commands but will not create IO queues. In this case, we need to remove the gendisks and free the IO queues since they can't be used and may be holding bios in their lists. From testing, the dma pools require a pci device so this had to change the pci driver 'remove' to release the dma resources in line with that call instead of after all references to the device are released. Signed-off-by: Keith Busch Signed-off-by: Matthew Wilcox --- drivers/block/nvme-core.c | 108 +++++++++++++++++++++++++++++++++++++++------- include/linux/nvme.h | 1 + 2 files changed, 94 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 300766973d76..000bca43c23b 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -58,6 +58,7 @@ module_param(use_threaded_interrupts, int, 0); static DEFINE_SPINLOCK(dev_list_lock); static LIST_HEAD(dev_list); static struct task_struct *nvme_thread; +static struct workqueue_struct *nvme_workq; /* * An NVM Express queue. Each device has at least two (one for admin @@ -1968,7 +1969,6 @@ static int nvme_dev_map(struct nvme_dev *dev) dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) goto disable; - pci_set_drvdata(pdev, dev); dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); if (!dev->bar) goto disable; @@ -1995,9 +1995,9 @@ static void nvme_dev_unmap(struct nvme_dev *dev) if (dev->bar) { iounmap(dev->bar); dev->bar = NULL; + pci_release_regions(dev->pci_dev); } - pci_release_regions(dev->pci_dev); if (pci_is_enabled(dev->pci_dev)) pci_disable_device(dev->pci_dev); } @@ -2085,11 +2085,6 @@ static void nvme_release_instance(struct nvme_dev *dev) static void nvme_free_dev(struct kref *kref) { struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); - nvme_dev_remove(dev); - nvme_dev_shutdown(dev); - nvme_free_queues(dev); - nvme_release_instance(dev); - nvme_release_prp_pools(dev); kfree(dev->queues); kfree(dev->entry); kfree(dev); @@ -2161,6 +2156,70 @@ static int nvme_dev_start(struct nvme_dev *dev) return result; } +static int nvme_remove_dead_ctrl(void *arg) +{ + struct nvme_dev *dev = (struct nvme_dev *)arg; + struct pci_dev *pdev = dev->pci_dev; + + if (pci_get_drvdata(pdev)) + pci_stop_and_remove_bus_device(pdev); + kref_put(&dev->kref, nvme_free_dev); + return 0; +} + +static void nvme_remove_disks(struct work_struct *ws) +{ + int i; + struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); + + nvme_dev_remove(dev); + spin_lock(&dev_list_lock); + for (i = dev->queue_count - 1; i > 0; i--) { + BUG_ON(!dev->queues[i] || !dev->queues[i]->q_suspended); + nvme_free_queue(dev->queues[i]); + dev->queue_count--; + dev->queues[i] = NULL; + } + spin_unlock(&dev_list_lock); +} + +static int nvme_dev_resume(struct nvme_dev *dev) +{ + int ret; + + ret = nvme_dev_start(dev); + if (ret && ret != -EBUSY) + return ret; + if (ret == -EBUSY) { + spin_lock(&dev_list_lock); + INIT_WORK(&dev->reset_work, nvme_remove_disks); + queue_work(nvme_workq, &dev->reset_work); + spin_unlock(&dev_list_lock); + } + return 0; +} + +static void nvme_dev_reset(struct nvme_dev *dev) +{ + nvme_dev_shutdown(dev); + if (nvme_dev_resume(dev)) { + dev_err(&dev->pci_dev->dev, "Device failed to resume\n"); + kref_get(&dev->kref); + if (IS_ERR(kthread_run(nvme_remove_dead_ctrl, dev, "nvme%d", + dev->instance))) { + dev_err(&dev->pci_dev->dev, + "Failed to start controller remove task\n"); + kref_put(&dev->kref, nvme_free_dev); + } + } +} + +static void nvme_reset_failed_dev(struct work_struct *ws) +{ + struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); + nvme_dev_reset(dev); +} + static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int result = -ENOMEM; @@ -2180,7 +2239,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&dev->namespaces); dev->pci_dev = pdev; - + pci_set_drvdata(pdev, dev); result = nvme_set_instance(dev); if (result) goto free; @@ -2232,7 +2291,19 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void nvme_remove(struct pci_dev *pdev) { struct nvme_dev *dev = pci_get_drvdata(pdev); + + spin_lock(&dev_list_lock); + list_del_init(&dev->node); + spin_unlock(&dev_list_lock); + + pci_set_drvdata(pdev, NULL); + flush_work(&dev->reset_work); misc_deregister(&dev->miscdev); + nvme_dev_remove(dev); + nvme_dev_shutdown(dev); + nvme_free_queues(dev); + nvme_release_instance(dev); + nvme_release_prp_pools(dev); kref_put(&dev->kref, nvme_free_dev); } @@ -2256,13 +2327,12 @@ static int nvme_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct nvme_dev *ndev = pci_get_drvdata(pdev); - int ret; - ret = nvme_dev_start(ndev); - /* XXX: should remove gendisks if resume fails */ - if (ret) - nvme_free_queues(ndev); - return ret; + if (nvme_dev_resume(ndev) && !work_busy(&ndev->reset_work)) { + INIT_WORK(&ndev->reset_work, nvme_reset_failed_dev); + queue_work(nvme_workq, &ndev->reset_work); + } + return 0; } static SIMPLE_DEV_PM_OPS(nvme_dev_pm_ops, nvme_suspend, nvme_resume); @@ -2303,9 +2373,14 @@ static int __init nvme_init(void) if (IS_ERR(nvme_thread)) return PTR_ERR(nvme_thread); + result = -ENOMEM; + nvme_workq = create_singlethread_workqueue("nvme"); + if (!nvme_workq) + goto kill_kthread; + result = register_blkdev(nvme_major, "nvme"); if (result < 0) - goto kill_kthread; + goto kill_workq; else if (result > 0) nvme_major = result; @@ -2316,6 +2391,8 @@ static int __init nvme_init(void) unregister_blkdev: unregister_blkdev(nvme_major, "nvme"); + kill_workq: + destroy_workqueue(nvme_workq); kill_kthread: kthread_stop(nvme_thread); return result; @@ -2325,6 +2402,7 @@ static void __exit nvme_exit(void) { pci_unregister_driver(&nvme_driver); unregister_blkdev(nvme_major, "nvme"); + destroy_workqueue(nvme_workq); kthread_stop(nvme_thread); } diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 5bc29197d90e..eed81cc56d7e 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -87,6 +87,7 @@ struct nvme_dev { struct list_head namespaces; struct kref kref; struct miscdevice miscdev; + struct work_struct reset_work; char name[12]; char serial[20]; char model[40]; -- cgit v1.2.3 From 2af7973a37059c92330014ee5f39adc94900e7e1 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 26 Nov 2013 11:55:22 -0800 Subject: target: Refer to u32 luns as unpacked_lun It's clearer to refer to pointers to the struct se_lun as "lun" and the actual number itself as "unpacked_lun". Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 207b340498a3..4b6b787d2c62 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1112,23 +1112,23 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size) struct se_lun *core_dev_add_lun( struct se_portal_group *tpg, struct se_device *dev, - u32 lun) + u32 unpacked_lun) { - struct se_lun *lun_p; + struct se_lun *lun; int rc; - lun_p = core_tpg_pre_addlun(tpg, lun); - if (IS_ERR(lun_p)) - return lun_p; + lun = core_tpg_pre_addlun(tpg, unpacked_lun); + if (IS_ERR(lun)) + return lun; - rc = core_tpg_post_addlun(tpg, lun_p, + rc = core_tpg_post_addlun(tpg, lun, TRANSPORT_LUNFLAGS_READ_WRITE, dev); if (rc < 0) return ERR_PTR(rc); pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from" " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), - tpg->se_tpg_tfo->tpg_get_tag(tpg), lun_p->unpacked_lun, + tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, tpg->se_tpg_tfo->get_fabric_name(), dev->se_hba->hba_id); /* * Update LUN maps for dynamically added initiators when @@ -1149,7 +1149,7 @@ struct se_lun *core_dev_add_lun( spin_unlock_irq(&tpg->acl_node_lock); } - return lun_p; + return lun; } /* core_dev_del_lun(): -- cgit v1.2.3 From d344f8a15637e8b57a0d05a6d50182c11de08606 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 26 Nov 2013 12:07:54 -0800 Subject: target: Rename core_tpg_{pre,post}_addlun for clarity "pre" is really an allocation function. The only time it isn't called is for virtual_lun0, which is statically allocated. Renaming that to "alloc" lets the other function not need to be "post", and just be called core_tpg_add_lun. (nab: fix minor applying fuzz in core_tpg_setup_virtual_lun0) Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 4 ++-- drivers/target/target_core_internal.h | 4 ++-- drivers/target/target_core_tpg.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4b6b787d2c62..dbd78a176ddb 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1117,11 +1117,11 @@ struct se_lun *core_dev_add_lun( struct se_lun *lun; int rc; - lun = core_tpg_pre_addlun(tpg, unpacked_lun); + lun = core_tpg_alloc_lun(tpg, unpacked_lun); if (IS_ERR(lun)) return lun; - rc = core_tpg_post_addlun(tpg, lun, + rc = core_tpg_add_lun(tpg, lun, TRANSPORT_LUNFLAGS_READ_WRITE, dev); if (rc < 0) return ERR_PTR(rc); diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 47b63b094cdc..f67e764a42bd 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -77,8 +77,8 @@ struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tp const char *); void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *); void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); -struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32); -int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *, +struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u32); +int core_tpg_add_lun(struct se_portal_group *, struct se_lun *, u32, void *); struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index f697f8baec54..a1dbc9488183 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -662,7 +662,7 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) if (ret < 0) return ret; - ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev); + ret = core_tpg_add_lun(se_tpg, lun, lun_access, dev); if (ret < 0) { percpu_ref_cancel_init(&lun->lun_ref); return ret; @@ -789,7 +789,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) } EXPORT_SYMBOL(core_tpg_deregister); -struct se_lun *core_tpg_pre_addlun( +struct se_lun *core_tpg_alloc_lun( struct se_portal_group *tpg, u32 unpacked_lun) { @@ -819,7 +819,7 @@ struct se_lun *core_tpg_pre_addlun( return lun; } -int core_tpg_post_addlun( +int core_tpg_add_lun( struct se_portal_group *tpg, struct se_lun *lun, u32 lun_access, -- cgit v1.2.3 From 340dbf729c3395cf1317890d033aa9ac7347766c Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 12 Dec 2013 16:12:33 -0800 Subject: target: Don't use void* when passing dev in core_tpg_add_lun Especially since it's actually a device. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_internal.h | 2 +- drivers/target/target_core_tpg.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index f67e764a42bd..1e27614e6bcc 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -79,7 +79,7 @@ void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *); void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u32); int core_tpg_add_lun(struct se_portal_group *, struct se_lun *, - u32, void *); + u32, struct se_device *); struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index a1dbc9488183..d1df39a05d88 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -823,7 +823,7 @@ int core_tpg_add_lun( struct se_portal_group *tpg, struct se_lun *lun, u32 lun_access, - void *lun_ptr) + struct se_device *dev) { int ret; @@ -831,7 +831,7 @@ int core_tpg_add_lun( if (ret < 0) return ret; - ret = core_dev_export(lun_ptr, tpg, lun); + ret = core_dev_export(dev, tpg, lun); if (ret < 0) { percpu_ref_cancel_init(&lun->lun_ref); return ret; -- cgit v1.2.3 From f665c0f852316ff99e9eb7f71f34d43003f8e139 Mon Sep 17 00:00:00 2001 From: Stefan Priebe Date: Sat, 16 Nov 2013 21:26:52 +0100 Subject: bcache: kthread don't set writeback task to INTERUPTIBLE at the beginning (schedule_timout_interuptible) and others do his on their own This prevents wrong load average calculation (load of 1 per thread) Signed-off-by: Kent Overstreet --- drivers/md/bcache/writeback.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 99053b1251be..484e57d7012c 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -500,8 +500,6 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc) if (IS_ERR(dc->writeback_thread)) return PTR_ERR(dc->writeback_thread); - set_task_state(dc->writeback_thread, TASK_INTERRUPTIBLE); - INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate); schedule_delayed_work(&dc->writeback_rate_update, dc->writeback_rate_update_seconds * HZ); -- cgit v1.2.3 From ce2b3f595e1c56639085645e0130426e443008c0 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 28 Nov 2013 17:28:37 -0800 Subject: bcache: Use uninterruptible sleep in writeback We're just waiting on kthread_should_stop(), nothing else, so interruptible sleep was wrong here. Signed-off-by: Kent Overstreet --- drivers/md/bcache/writeback.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 484e57d7012c..3cd931d3f26c 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -241,7 +241,7 @@ static void read_dirty(struct cached_dev *dc) if (KEY_START(&w->key) != dc->last_read || jiffies_to_msecs(delay) > 50) while (!kthread_should_stop() && delay) - delay = schedule_timeout_interruptible(delay); + delay = schedule_timeout_uninterruptible(delay); dc->last_read = KEY_OFFSET(&w->key); @@ -438,7 +438,7 @@ static int bch_writeback_thread(void *arg) while (delay && !kthread_should_stop() && !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) - delay = schedule_timeout_interruptible(delay); + delay = schedule_timeout_uninterruptible(delay); } } -- cgit v1.2.3 From d24a6e1087030b6da286df9433add5fa2f21b83b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 10 Nov 2013 21:55:27 -0800 Subject: bcache: Fix dirty_data accounting Dirty data accounting wasn't quite right - firstly, we were adding the key we're inserting after it could have merged with another dirty key already in the btree, and secondly we could sometimes pass the wrong offset to bcache_dev_sectors_dirty_add() for dirty data we were overwriting - which is important when tracking dirty data by stripe. NOTE FOR BACKPORTERS: For 3.10 (and 3.11?) there's other accounting fixes necessary that got squashed in with other patches; the full patch against 3.10 is 408cc2f47eeac93a, available at: git://evilpiepirate.org/~kent/linux-bcache.git bcache-3.10-writeback-fixes Signed-off-by: Kent Overstreet Cc: linux-stable # >= v3.10 diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 2a46036..4a12b2f 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1817,7 +1817,8 @@ static bool fix_overlapping_extents(struct btree *b, struct bkey *insert, if (KEY_START(k) > KEY_START(insert) + sectors_found) goto check_failed; - if (KEY_PTRS(replace_key) != KEY_PTRS(k)) + if (KEY_PTRS(k) != KEY_PTRS(replace_key) || + KEY_DIRTY(k) != KEY_DIRTY(replace_key)) goto check_failed; /* skip past gen */ --- drivers/md/bcache/btree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index dc6e2be265b7..c36745e5986a 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1817,7 +1817,8 @@ static bool fix_overlapping_extents(struct btree *b, struct bkey *insert, if (KEY_START(k) > KEY_START(insert) + sectors_found) goto check_failed; - if (KEY_PTRS(replace_key) != KEY_PTRS(k)) + if (KEY_PTRS(k) != KEY_PTRS(replace_key) || + KEY_DIRTY(k) != KEY_DIRTY(replace_key)) goto check_failed; /* skip past gen */ -- cgit v1.2.3 From 9eb8ebeb2471b8cbaa078066aeb85fe5d46f5304 Mon Sep 17 00:00:00 2001 From: Nicholas Swenson Date: Tue, 22 Oct 2013 13:19:23 -0700 Subject: bcache: Fix for can_attach_cache() Signed-off-by: Nicholas Swenson Signed-off-by: Kent Overstreet --- drivers/md/bcache/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index dec15cd2d797..c57bfa071a57 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1676,7 +1676,7 @@ err: static bool can_attach_cache(struct cache *ca, struct cache_set *c) { return ca->sb.block_size == c->sb.block_size && - ca->sb.bucket_size == c->sb.block_size && + ca->sb.bucket_size == c->sb.bucket_size && ca->sb.nr_in_set == c->sb.nr_in_set; } -- cgit v1.2.3 From 97d11a660fd906dbea3dccd2638495d8497c3c81 Mon Sep 17 00:00:00 2001 From: Nicholas Swenson Date: Wed, 23 Oct 2013 17:35:26 -0700 Subject: bcache: Fix heap_peek() macro Signed-off-by: Nicholas Swenson Signed-off-by: Kent Overstreet --- drivers/md/bcache/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h index 362c4b3f8b4a..1030c6020e98 100644 --- a/drivers/md/bcache/util.h +++ b/drivers/md/bcache/util.h @@ -110,7 +110,7 @@ do { \ _r; \ }) -#define heap_peek(h) ((h)->size ? (h)->data[0] : NULL) +#define heap_peek(h) ((h)->used ? (h)->data[0] : NULL) #define heap_full(h) ((h)->used == (h)->size) -- cgit v1.2.3 From bee63f40cb5f5e8ab2abfbc85acde99cc0acd4b5 Mon Sep 17 00:00:00 2001 From: Nicholas Swenson Date: Thu, 31 Oct 2013 19:25:18 -0700 Subject: bcache: fix for gc crashing when no sectors are used Signed-off-by: Nicholas Swenson Signed-off-by: Kent Overstreet --- drivers/md/bcache/movinggc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c index 7c1275e66025..46c952379fab 100644 --- a/drivers/md/bcache/movinggc.c +++ b/drivers/md/bcache/movinggc.c @@ -184,7 +184,8 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r) static unsigned bucket_heap_top(struct cache *ca) { - return GC_SECTORS_USED(heap_peek(&ca->heap)); + struct bucket *b; + return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0; } void bch_moving_gc(struct cache_set *c) -- cgit v1.2.3 From 981aa8c091e164ea51dd1e81b71a1f3852bbcceb Mon Sep 17 00:00:00 2001 From: Nicholas Swenson Date: Thu, 7 Nov 2013 17:53:19 -0800 Subject: bcache: bugfix - moving_gc now moves only correct buckets Removed gc_move_threshold because picking buckets only by threshold could lead moving extra buckets (ei. if there are buckets at the threshold that aren't supposed to be moved do to space considerations). This is replaced by a GC_MOVE bit in the gc_mark bitmask. Now only marked buckets get moved. Signed-off-by: Nicholas Swenson Signed-off-by: Kent Overstreet --- drivers/md/bcache/alloc.c | 2 ++ drivers/md/bcache/bcache.h | 6 +++--- drivers/md/bcache/movinggc.c | 8 +++----- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index 2b46bf1d7e40..4c9852d92b0a 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -421,9 +421,11 @@ out: if (watermark <= WATERMARK_METADATA) { SET_GC_MARK(b, GC_MARK_METADATA); + SET_GC_MOVE(b, 0); b->prio = BTREE_PRIO; } else { SET_GC_MARK(b, GC_MARK_RECLAIMABLE); + SET_GC_MOVE(b, 0); b->prio = INITIAL_PRIO; } diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 4beb55a0ff30..a7b1a7631ed2 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -197,7 +197,7 @@ struct bucket { uint8_t disk_gen; uint8_t last_gc; /* Most out of date gen in the btree */ uint8_t gc_gen; - uint16_t gc_mark; + uint16_t gc_mark; /* Bitfield used by GC. See below for field */ }; /* @@ -209,7 +209,8 @@ BITMASK(GC_MARK, struct bucket, gc_mark, 0, 2); #define GC_MARK_RECLAIMABLE 0 #define GC_MARK_DIRTY 1 #define GC_MARK_METADATA 2 -BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 14); +BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13); +BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1); #include "journal.h" #include "stats.h" @@ -445,7 +446,6 @@ struct cache { * call prio_write() to keep gens from wrapping. */ uint8_t need_save_prio; - unsigned gc_move_threshold; /* * If nonzero, we know we aren't going to find any buckets to invalidate diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c index 46c952379fab..30f347d4e609 100644 --- a/drivers/md/bcache/movinggc.c +++ b/drivers/md/bcache/movinggc.c @@ -25,10 +25,9 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k) unsigned i; for (i = 0; i < KEY_PTRS(k); i++) { - struct cache *ca = PTR_CACHE(c, k, i); struct bucket *g = PTR_BUCKET(c, k, i); - if (GC_SECTORS_USED(g) < ca->gc_move_threshold) + if (GC_MOVE(g)) return true; } @@ -227,9 +226,8 @@ void bch_moving_gc(struct cache_set *c) sectors_to_move -= GC_SECTORS_USED(b); } - ca->gc_move_threshold = bucket_heap_top(ca); - - pr_debug("threshold %u", ca->gc_move_threshold); + while (heap_pop(&ca->heap, b, bucket_cmp)) + SET_GC_MOVE(b, 1); } mutex_unlock(&c->bucket_lock); -- cgit v1.2.3 From bf0a628a95dba7f983b6047cea695fb066fb2512 Mon Sep 17 00:00:00 2001 From: Nicholas Swenson Date: Tue, 26 Nov 2013 19:14:23 -0800 Subject: bcache: fix for gc and writeback race Garbage collector needs to check keys in the writeback keybuf to make sure it's not invalidating buckets to which the writeback keys point to. Signed-off-by: Nicholas Swenson Signed-off-by: Kent Overstreet --- drivers/md/bcache/btree.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index c36745e5986a..31bb53fcc67a 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1561,6 +1561,28 @@ size_t bch_btree_gc_finish(struct cache_set *c) SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i), GC_MARK_METADATA); + /* don't reclaim buckets to which writeback keys point */ + rcu_read_lock(); + for (i = 0; i < c->nr_uuids; i++) { + struct bcache_device *d = c->devices[i]; + struct cached_dev *dc; + struct keybuf_key *w, *n; + unsigned j; + + if (!d || UUID_FLASH_ONLY(&c->uuids[i])) + continue; + dc = container_of(d, struct cached_dev, disk); + + spin_lock(&dc->writeback_keys.lock); + rbtree_postorder_for_each_entry_safe(w, n, + &dc->writeback_keys.keys, node) + for (j = 0; j < KEY_PTRS(&w->key); j++) + SET_GC_MARK(PTR_BUCKET(c, &w->key, j), + GC_MARK_DIRTY); + spin_unlock(&dc->writeback_keys.lock); + } + rcu_read_unlock(); + for_each_cache(ca, c, i) { uint64_t *i; -- cgit v1.2.3 From 6d3d1a9c542b19dff1c7d7c8354d0869e4655287 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 16 Dec 2013 14:12:09 -0800 Subject: bcache: bugfix for race between moving_gc and bucket_invalidate There is a possibility for a bucket to be invalidated by the allocator while moving_gc was copying it's contents to another bucket, if the bucket only held cached data. To prevent this moving checks for a stale ptr (to an invalidated bucket), before and after reads. It it finds one, it simply ignores moving that data. This only affects bcache if the moving_gc was turned on, note that it's off by default. Signed-off-by: Nicholas Swenson Signed-off-by: Kent Overstreet --- drivers/md/bcache/movinggc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c index 30f347d4e609..f2f0998c4a91 100644 --- a/drivers/md/bcache/movinggc.c +++ b/drivers/md/bcache/movinggc.c @@ -64,11 +64,16 @@ static void write_moving_finish(struct closure *cl) static void read_moving_endio(struct bio *bio, int error) { + struct bbio *b = container_of(bio, struct bbio, bio); struct moving_io *io = container_of(bio->bi_private, struct moving_io, cl); if (error) io->op.error = error; + else if (!KEY_DIRTY(&b->key) && + ptr_stale(io->op.c, &b->key, 0)) { + io->op.error = -EINTR; + } bch_bbio_endio(io->op.c, bio, error, "reading data to move"); } @@ -140,6 +145,11 @@ static void read_moving(struct cache_set *c) if (!w) break; + if (ptr_stale(c, &w->key, 0)) { + bch_keybuf_del(&c->moving_gc_keys, w); + continue; + } + io = kzalloc(sizeof(struct moving_io) + sizeof(struct bio_vec) * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS), GFP_KERNEL); -- cgit v1.2.3 From 16749c23c00c686ed168471963e3ddb0f3fcd855 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 11 Nov 2013 13:58:34 -0800 Subject: bcache: New writeback PD controller The old writeback PD controller could get into states where it had throttled all the way down and take way too long to recover - it was too complicated to really understand what it was doing. This rewrites a good chunk of it to hopefully be simpler and make more sense, and it also pays more attention to units which should make the behaviour a bit easier to understand. Signed-off-by: Kent Overstreet --- drivers/md/bcache/bcache.h | 6 +++--- drivers/md/bcache/sysfs.c | 50 +++++++++++++++++++++++++------------------ drivers/md/bcache/util.c | 8 ++++++- drivers/md/bcache/writeback.c | 47 ++++++++++++++++++++-------------------- 4 files changed, 62 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index a7b1a7631ed2..754f43177483 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -373,14 +373,14 @@ struct cached_dev { unsigned char writeback_percent; unsigned writeback_delay; - int writeback_rate_change; - int64_t writeback_rate_derivative; uint64_t writeback_rate_target; + int64_t writeback_rate_proportional; + int64_t writeback_rate_derivative; + int64_t writeback_rate_change; unsigned writeback_rate_update_seconds; unsigned writeback_rate_d_term; unsigned writeback_rate_p_term_inverse; - unsigned writeback_rate_d_smooth; }; enum alloc_watermarks { diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c index 80d4c2bee18a..a1f85612f0b3 100644 --- a/drivers/md/bcache/sysfs.c +++ b/drivers/md/bcache/sysfs.c @@ -83,7 +83,6 @@ rw_attribute(writeback_rate); rw_attribute(writeback_rate_update_seconds); rw_attribute(writeback_rate_d_term); rw_attribute(writeback_rate_p_term_inverse); -rw_attribute(writeback_rate_d_smooth); read_attribute(writeback_rate_debug); read_attribute(stripe_size); @@ -129,31 +128,41 @@ SHOW(__bch_cached_dev) var_printf(writeback_running, "%i"); var_print(writeback_delay); var_print(writeback_percent); - sysfs_print(writeback_rate, dc->writeback_rate.rate); + sysfs_hprint(writeback_rate, dc->writeback_rate.rate << 9); var_print(writeback_rate_update_seconds); var_print(writeback_rate_d_term); var_print(writeback_rate_p_term_inverse); - var_print(writeback_rate_d_smooth); if (attr == &sysfs_writeback_rate_debug) { + char rate[20]; char dirty[20]; - char derivative[20]; char target[20]; - bch_hprint(dirty, - bcache_dev_sectors_dirty(&dc->disk) << 9); - bch_hprint(derivative, dc->writeback_rate_derivative << 9); + char proportional[20]; + char derivative[20]; + char change[20]; + s64 next_io; + + bch_hprint(rate, dc->writeback_rate.rate << 9); + bch_hprint(dirty, bcache_dev_sectors_dirty(&dc->disk) << 9); bch_hprint(target, dc->writeback_rate_target << 9); + bch_hprint(proportional,dc->writeback_rate_proportional << 9); + bch_hprint(derivative, dc->writeback_rate_derivative << 9); + bch_hprint(change, dc->writeback_rate_change << 9); + + next_io = div64_s64(dc->writeback_rate.next - local_clock(), + NSEC_PER_MSEC); return sprintf(buf, - "rate:\t\t%u\n" - "change:\t\t%i\n" + "rate:\t\t%s/sec\n" "dirty:\t\t%s\n" + "target:\t\t%s\n" + "proportional:\t%s\n" "derivative:\t%s\n" - "target:\t\t%s\n", - dc->writeback_rate.rate, - dc->writeback_rate_change, - dirty, derivative, target); + "change:\t\t%s/sec\n" + "next io:\t%llims\n", + rate, dirty, target, proportional, + derivative, change, next_io); } sysfs_hprint(dirty_data, @@ -189,6 +198,7 @@ STORE(__cached_dev) struct kobj_uevent_env *env; #define d_strtoul(var) sysfs_strtoul(var, dc->var) +#define d_strtoul_nonzero(var) sysfs_strtoul_clamp(var, dc->var, 1, INT_MAX) #define d_strtoi_h(var) sysfs_hatoi(var, dc->var) sysfs_strtoul(data_csum, dc->disk.data_csum); @@ -197,16 +207,15 @@ STORE(__cached_dev) d_strtoul(writeback_metadata); d_strtoul(writeback_running); d_strtoul(writeback_delay); - sysfs_strtoul_clamp(writeback_rate, - dc->writeback_rate.rate, 1, 1000000); + sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40); - d_strtoul(writeback_rate_update_seconds); + sysfs_strtoul_clamp(writeback_rate, + dc->writeback_rate.rate, 1, INT_MAX); + + d_strtoul_nonzero(writeback_rate_update_seconds); d_strtoul(writeback_rate_d_term); - d_strtoul(writeback_rate_p_term_inverse); - sysfs_strtoul_clamp(writeback_rate_p_term_inverse, - dc->writeback_rate_p_term_inverse, 1, INT_MAX); - d_strtoul(writeback_rate_d_smooth); + d_strtoul_nonzero(writeback_rate_p_term_inverse); d_strtoi_h(sequential_cutoff); d_strtoi_h(readahead); @@ -313,7 +322,6 @@ static struct attribute *bch_cached_dev_files[] = { &sysfs_writeback_rate_update_seconds, &sysfs_writeback_rate_d_term, &sysfs_writeback_rate_p_term_inverse, - &sysfs_writeback_rate_d_smooth, &sysfs_writeback_rate_debug, &sysfs_dirty_data, &sysfs_stripe_size, diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c index 462214eeacbe..bb37618e7664 100644 --- a/drivers/md/bcache/util.c +++ b/drivers/md/bcache/util.c @@ -209,7 +209,13 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done) { uint64_t now = local_clock(); - d->next += div_u64(done, d->rate); + d->next += div_u64(done * NSEC_PER_SEC, d->rate); + + if (time_before64(now + NSEC_PER_SEC, d->next)) + d->next = now + NSEC_PER_SEC; + + if (time_after64(now - NSEC_PER_SEC * 2, d->next)) + d->next = now - NSEC_PER_SEC * 2; return time_after64(d->next, now) ? div_u64(d->next - now, NSEC_PER_SEC / HZ) diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 3cd931d3f26c..6c44fe059c27 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -30,38 +30,40 @@ static void __update_writeback_rate(struct cached_dev *dc) /* PD controller */ - int change = 0; - int64_t error; int64_t dirty = bcache_dev_sectors_dirty(&dc->disk); int64_t derivative = dirty - dc->disk.sectors_dirty_last; + int64_t proportional = dirty - target; + int64_t change; dc->disk.sectors_dirty_last = dirty; - derivative *= dc->writeback_rate_d_term; - derivative = clamp(derivative, -dirty, dirty); + /* Scale to sectors per second */ - derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative, - dc->writeback_rate_d_smooth, 0); + proportional *= dc->writeback_rate_update_seconds; + proportional = div_s64(proportional, dc->writeback_rate_p_term_inverse); - /* Avoid divide by zero */ - if (!target) - goto out; + derivative = div_s64(derivative, dc->writeback_rate_update_seconds); - error = div64_s64((dirty + derivative - target) << 8, target); + derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative, + (dc->writeback_rate_d_term / + dc->writeback_rate_update_seconds) ?: 1, 0); + + derivative *= dc->writeback_rate_d_term; + derivative = div_s64(derivative, dc->writeback_rate_p_term_inverse); - change = div_s64((dc->writeback_rate.rate * error) >> 8, - dc->writeback_rate_p_term_inverse); + change = proportional + derivative; /* Don't increase writeback rate if the device isn't keeping up */ if (change > 0 && time_after64(local_clock(), - dc->writeback_rate.next + 10 * NSEC_PER_MSEC)) + dc->writeback_rate.next + NSEC_PER_MSEC)) change = 0; dc->writeback_rate.rate = - clamp_t(int64_t, dc->writeback_rate.rate + change, + clamp_t(int64_t, (int64_t) dc->writeback_rate.rate + change, 1, NSEC_PER_MSEC); -out: + + dc->writeback_rate_proportional = proportional; dc->writeback_rate_derivative = derivative; dc->writeback_rate_change = change; dc->writeback_rate_target = target; @@ -87,15 +89,11 @@ static void update_writeback_rate(struct work_struct *work) static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors) { - uint64_t ret; - if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) || !dc->writeback_percent) return 0; - ret = bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL); - - return min_t(uint64_t, ret, HZ); + return bch_next_delay(&dc->writeback_rate, sectors); } struct dirty_io { @@ -476,6 +474,8 @@ void bch_sectors_dirty_init(struct cached_dev *dc) bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0), sectors_dirty_init_fn, 0); + + dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk); } int bch_cached_dev_writeback_init(struct cached_dev *dc) @@ -490,10 +490,9 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc) dc->writeback_delay = 30; dc->writeback_rate.rate = 1024; - dc->writeback_rate_update_seconds = 30; - dc->writeback_rate_d_term = 16; - dc->writeback_rate_p_term_inverse = 64; - dc->writeback_rate_d_smooth = 8; + dc->writeback_rate_update_seconds = 5; + dc->writeback_rate_d_term = 30; + dc->writeback_rate_p_term_inverse = 6000; dc->writeback_thread = kthread_create(bch_writeback_thread, dc, "bcache_writeback"); -- cgit v1.2.3 From cf872776fc84128bb779ce2b83a37c884c3203ae Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 11 Dec 2013 21:11:58 -0500 Subject: tty: Fix hang at ldsem_down_read() When a controlling tty is being hung up and the hang up is waiting for a just-signalled tty reader or writer to exit, and a new tty reader/writer tries to acquire an ldisc reference concurrently with the ldisc reference release from the signalled reader/writer, the hangup can hang. The new reader/writer is sleeping in ldsem_down_read() and the hangup is sleeping in ldsem_down_write() [1]. The new reader/writer fails to wakeup the waiting hangup because the wrong lock count value is checked (the old lock count rather than the new lock count) to see if the lock is unowned. Change helper function to return the new lock count if the cmpxchg was successful; document this behavior. [1] edited dmesg log from reporter SysRq : Show Blocked State task PC stack pid father systemd D ffff88040c4f0000 0 1 0 0x00000000 ffff88040c49fbe0 0000000000000046 ffff88040c4a0000 ffff88040c49ffd8 00000000001d3980 00000000001d3980 ffff88040c4a0000 ffff88040593d840 ffff88040c49fb40 ffffffff810a4cc0 0000000000000006 0000000000000023 Call Trace: [] ? sched_clock_cpu+0x9f/0xe4 [] ? sched_clock_cpu+0x9f/0xe4 [] ? sched_clock_cpu+0x9f/0xe4 [] ? sched_clock_cpu+0x9f/0xe4 [] schedule+0x24/0x5e [] schedule_timeout+0x15b/0x1ec [] ? sched_clock_cpu+0x9f/0xe4 [] ? _raw_spin_unlock_irq+0x24/0x26 [] down_read_failed+0xe3/0x1b9 [] ldsem_down_read+0x8b/0xa5 [] ? tty_ldisc_ref_wait+0x1b/0x44 [] tty_ldisc_ref_wait+0x1b/0x44 [] tty_write+0x7d/0x28a [] redirected_tty_write+0x8d/0x98 [] ? tty_write+0x28a/0x28a [] do_loop_readv_writev+0x56/0x79 [] do_readv_writev+0x1b0/0x1ff [] ? do_vfs_ioctl+0x32a/0x489 [] ? final_putname+0x1d/0x3a [] vfs_writev+0x2e/0x49 [] SyS_writev+0x47/0xaa [] system_call_fastpath+0x16/0x1b bash D ffffffff81c104c0 0 5469 5302 0x00000082 ffff8800cf817ac0 0000000000000046 ffff8804086b22a0 ffff8800cf817fd8 00000000001d3980 00000000001d3980 ffff8804086b22a0 ffff8800cf817a48 000000000000b9a0 ffff8800cf817a78 ffffffff81004675 ffff8800cf817a44 Call Trace: [] ? dump_trace+0x165/0x29c [] ? sched_clock_cpu+0x9f/0xe4 [] ? save_stack_trace+0x26/0x41 [] schedule+0x24/0x5e [] schedule_timeout+0x15b/0x1ec [] ? sched_clock_cpu+0x9f/0xe4 [] ? down_write_failed+0xa3/0x1c9 [] ? _raw_spin_unlock_irq+0x24/0x26 [] down_write_failed+0xab/0x1c9 [] ldsem_down_write+0x79/0xb1 [] ? tty_ldisc_lock_pair_timeout+0xa5/0xd9 [] tty_ldisc_lock_pair_timeout+0xa5/0xd9 [] tty_ldisc_hangup+0xc4/0x218 [] __tty_hangup+0x2e2/0x3ed [] disassociate_ctty+0x63/0x226 [] do_exit+0x79f/0xa11 [] ? get_signal_to_deliver+0x206/0x62f [] ? lock_release_holdtime.part.8+0xf/0x16e [] do_group_exit+0x47/0xb5 [] get_signal_to_deliver+0x241/0x62f [] do_signal+0x43/0x59d [] ? __audit_syscall_exit+0x21a/0x2a8 [] ? lock_release_holdtime.part.8+0xf/0x16e [] do_notify_resume+0x54/0x6c [] int_signal+0x12/0x17 Reported-by: Sami Farin Cc: # 3.12.x Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldsem.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c index 22fad8ad5ac2..d8a55e87877f 100644 --- a/drivers/tty/tty_ldsem.c +++ b/drivers/tty/tty_ldsem.c @@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem) return atomic_long_add_return(delta, (atomic_long_t *)&sem->count); } +/* + * ldsem_cmpxchg() updates @*old with the last-known sem->count value. + * Returns 1 if count was successfully changed; @*old will have @new value. + * Returns 0 if count was not changed; @*old will have most recent sem->count + */ static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem) { - long tmp = *old; - *old = atomic_long_cmpxchg(&sem->count, *old, new); - return *old == tmp; + long tmp = atomic_long_cmpxchg(&sem->count, *old, new); + if (tmp == *old) { + *old = new; + return 1; + } else { + *old = tmp; + return 0; + } } /* -- cgit v1.2.3 From 89e47d3b8a273b0eac21e4bf6d7fdb86b654fa16 Mon Sep 17 00:00:00 2001 From: tanxiaojun Date: Fri, 13 Dec 2013 14:49:56 +0800 Subject: fddi: cleanup unsigned to unsigned int/short Use "unsigned int/short" instead of "unsigned", and change the type of iteration variable "i" to "unsigned int". Signed-off-by: Tan Xiaojun Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/fplustm.c | 24 +++++----- drivers/net/fddi/skfp/h/supern_2.h | 96 +++++++++++++++++++------------------- drivers/net/fddi/skfp/smt.c | 2 +- drivers/net/fddi/skfp/srf.c | 24 +++++----- 4 files changed, 73 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fddi/skfp/fplustm.c b/drivers/net/fddi/skfp/fplustm.c index f83993590174..d918d8a42667 100644 --- a/drivers/net/fddi/skfp/fplustm.c +++ b/drivers/net/fddi/skfp/fplustm.c @@ -55,14 +55,14 @@ static char cam_warning [] = "E_SMT_004: CAM still busy\n"; #define DUMMY_READ() smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP)) -#define CHECK_NPP() { unsigned k = 10000 ;\ +#define CHECK_NPP() { unsigned int k = 10000 ;\ while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\ if (!k) { \ SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \ } \ } -#define CHECK_CAM() { unsigned k = 10 ;\ +#define CHECK_CAM() { unsigned int k = 10 ;\ while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\ if (!k) { \ SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \ @@ -356,25 +356,25 @@ static void set_formac_addr(struct s_smc *smc) long t_requ = smc->mib.m[MAC0].fddiMACT_Req ; outpw(FM_A(FM_SAID),my_said) ; /* set short address */ - outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) + + outpw(FM_A(FM_LAIL),(unsigned short)((smc->hw.fddi_home_addr.a[4]<<8) + smc->hw.fddi_home_addr.a[5])) ; - outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) + + outpw(FM_A(FM_LAIC),(unsigned short)((smc->hw.fddi_home_addr.a[2]<<8) + smc->hw.fddi_home_addr.a[3])) ; - outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) + + outpw(FM_A(FM_LAIM),(unsigned short)((smc->hw.fddi_home_addr.a[0]<<8) + smc->hw.fddi_home_addr.a[1])) ; outpw(FM_A(FM_SAGP),my_sagp) ; /* set short group address */ - outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) + + outpw(FM_A(FM_LAGL),(unsigned short)((smc->hw.fp.group_addr.a[4]<<8) + smc->hw.fp.group_addr.a[5])) ; - outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) + + outpw(FM_A(FM_LAGC),(unsigned short)((smc->hw.fp.group_addr.a[2]<<8) + smc->hw.fp.group_addr.a[3])) ; - outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) + + outpw(FM_A(FM_LAGM),(unsigned short)((smc->hw.fp.group_addr.a[0]<<8) + smc->hw.fp.group_addr.a[1])) ; /* set r_request regs. (MSW & LSW of TRT ) */ - outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ; - outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ; + outpw(FM_A(FM_TREQ1),(unsigned short)(t_requ>>16)) ; + outpw(FM_A(FM_TREQ0),(unsigned short)t_requ) ; } static void set_int(char *p, int l) @@ -394,10 +394,10 @@ static void set_int(char *p, int l) * append 'end of chain' pointer */ static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac, - unsigned off, int len) + unsigned int off, int len) /* u_long td; transmit descriptor */ /* struct fddi_mac *mac; mac frame pointer */ -/* unsigned off; start address within buffer memory */ +/* unsigned int off; start address within buffer memory */ /* int len ; length of the frame including the FC */ { int i ; diff --git a/drivers/net/fddi/skfp/h/supern_2.h b/drivers/net/fddi/skfp/h/supern_2.h index 0b73690280f6..4ee360d2dc62 100644 --- a/drivers/net/fddi/skfp/h/supern_2.h +++ b/drivers/net/fddi/skfp/h/supern_2.h @@ -92,33 +92,33 @@ union rx_descr { struct { #ifdef LITTLE_ENDIAN - unsigned rx_length :16 ; /* frame length lower/upper byte */ - unsigned rx_erfbb :2 ; /* received frame byte boundary */ - unsigned rx_reserv2:2 ; /* reserved */ - unsigned rx_sfrmty :3 ; /* frame type bits */ - unsigned rx_sadrrg :1 ; /* DA == MA or broad-/multicast */ - unsigned rx_sfrmerr:1 ; /* received frame not valid */ - unsigned rx_seac0 :1 ; /* frame-copied C-indicator */ - unsigned rx_seac1 :1 ; /* address-match A-indicator */ - unsigned rx_seac2 :1 ; /* frame-error E-indicator */ - unsigned rx_ssrcrtg:1 ; /* == 1 SA has MSB set */ - unsigned rx_reserv1:1 ; /* reserved */ - unsigned rx_msrabt :1 ; /* memory status receive abort */ - unsigned rx_msvalid:1 ; /* memory status valid */ + unsigned int rx_length :16 ; /* frame length lower/upper byte */ + unsigned int rx_erfbb :2 ; /* received frame byte boundary */ + unsigned int rx_reserv2:2 ; /* reserved */ + unsigned int rx_sfrmty :3 ; /* frame type bits */ + unsigned int rx_sadrrg :1 ; /* DA == MA or broad-/multicast */ + unsigned int rx_sfrmerr:1 ; /* received frame not valid */ + unsigned int rx_seac0 :1 ; /* frame-copied C-indicator */ + unsigned int rx_seac1 :1 ; /* address-match A-indicator */ + unsigned int rx_seac2 :1 ; /* frame-error E-indicator */ + unsigned int rx_ssrcrtg:1 ; /* == 1 SA has MSB set */ + unsigned int rx_reserv1:1 ; /* reserved */ + unsigned int rx_msrabt :1 ; /* memory status receive abort */ + unsigned int rx_msvalid:1 ; /* memory status valid */ #else - unsigned rx_msvalid:1 ; /* memory status valid */ - unsigned rx_msrabt :1 ; /* memory status receive abort */ - unsigned rx_reserv1:1 ; /* reserved */ - unsigned rx_ssrcrtg:1 ; /* == 1 SA has MSB set */ - unsigned rx_seac2 :1 ; /* frame-error E-indicator */ - unsigned rx_seac1 :1 ; /* address-match A-indicator */ - unsigned rx_seac0 :1 ; /* frame-copied C-indicator */ - unsigned rx_sfrmerr:1 ; /* received frame not valid */ - unsigned rx_sadrrg :1 ; /* DA == MA or broad-/multicast */ - unsigned rx_sfrmty :3 ; /* frame type bits */ - unsigned rx_erfbb :2 ; /* received frame byte boundary */ - unsigned rx_reserv2:2 ; /* reserved */ - unsigned rx_length :16 ; /* frame length lower/upper byte */ + unsigned int rx_msvalid:1 ; /* memory status valid */ + unsigned int rx_msrabt :1 ; /* memory status receive abort */ + unsigned int rx_reserv1:1 ; /* reserved */ + unsigned int rx_ssrcrtg:1 ; /* == 1 SA has MSB set */ + unsigned int rx_seac2 :1 ; /* frame-error E-indicator */ + unsigned int rx_seac1 :1 ; /* address-match A-indicator */ + unsigned int rx_seac0 :1 ; /* frame-copied C-indicator */ + unsigned int rx_sfrmerr:1 ; /* received frame not valid */ + unsigned int rx_sadrrg :1 ; /* DA == MA or broad-/multicast */ + unsigned int rx_sfrmty :3 ; /* frame type bits */ + unsigned int rx_erfbb :2 ; /* received frame byte boundary */ + unsigned int rx_reserv2:2 ; /* reserved */ + unsigned int rx_length :16 ; /* frame length lower/upper byte */ #endif } r ; long i ; @@ -162,23 +162,23 @@ union rx_descr { union tx_descr { struct { #ifdef LITTLE_ENDIAN - unsigned tx_length:16 ; /* frame length lower/upper byte */ - unsigned tx_res :8 ; /* reserved (bit 16..23) */ - unsigned tx_xmtabt:1 ; /* transmit abort */ - unsigned tx_nfcs :1 ; /* no frame check sequence */ - unsigned tx_xdone :1 ; /* give up token */ - unsigned tx_rpxm :2 ; /* byte offset */ - unsigned tx_pat1 :2 ; /* must be TXP1 */ - unsigned tx_more :1 ; /* more frame in chain */ + unsigned int tx_length:16 ; /* frame length lower/upper byte */ + unsigned int tx_res :8 ; /* reserved (bit 16..23) */ + unsigned int tx_xmtabt:1 ; /* transmit abort */ + unsigned int tx_nfcs :1 ; /* no frame check sequence */ + unsigned int tx_xdone :1 ; /* give up token */ + unsigned int tx_rpxm :2 ; /* byte offset */ + unsigned int tx_pat1 :2 ; /* must be TXP1 */ + unsigned int tx_more :1 ; /* more frame in chain */ #else - unsigned tx_more :1 ; /* more frame in chain */ - unsigned tx_pat1 :2 ; /* must be TXP1 */ - unsigned tx_rpxm :2 ; /* byte offset */ - unsigned tx_xdone :1 ; /* give up token */ - unsigned tx_nfcs :1 ; /* no frame check sequence */ - unsigned tx_xmtabt:1 ; /* transmit abort */ - unsigned tx_res :8 ; /* reserved (bit 16..23) */ - unsigned tx_length:16 ; /* frame length lower/upper byte */ + unsigned int tx_more :1 ; /* more frame in chain */ + unsigned int tx_pat1 :2 ; /* must be TXP1 */ + unsigned int tx_rpxm :2 ; /* byte offset */ + unsigned int tx_xdone :1 ; /* give up token */ + unsigned int tx_nfcs :1 ; /* no frame check sequence */ + unsigned int tx_xmtabt:1 ; /* transmit abort */ + unsigned int tx_res :8 ; /* reserved (bit 16..23) */ + unsigned int tx_length:16 ; /* frame length lower/upper byte */ #endif } t ; long i ; @@ -202,13 +202,13 @@ union tx_descr { union tx_pointer { struct t { #ifdef LITTLE_ENDIAN - unsigned tp_pointer:16 ; /* pointer to tx_descr (low/high) */ - unsigned tp_res :8 ; /* reserved (bit 16..23) */ - unsigned tp_pattern:8 ; /* fixed pattern (bit 24..31) */ + unsigned int tp_pointer:16 ; /* pointer to tx_descr (low/high) */ + unsigned int tp_res :8 ; /* reserved (bit 16..23) */ + unsigned int tp_pattern:8 ; /* fixed pattern (bit 24..31) */ #else - unsigned tp_pattern:8 ; /* fixed pattern (bit 24..31) */ - unsigned tp_res :8 ; /* reserved (bit 16..23) */ - unsigned tp_pointer:16 ; /* pointer to tx_descr (low/high) */ + unsigned int tp_pattern:8 ; /* fixed pattern (bit 24..31) */ + unsigned int tp_res :8 ; /* reserved (bit 16..23) */ + unsigned int tp_pointer:16 ; /* pointer to tx_descr (low/high) */ #endif } t ; long i ; diff --git a/drivers/net/fddi/skfp/smt.c b/drivers/net/fddi/skfp/smt.c index 08d94329c12f..9edada85ed02 100644 --- a/drivers/net/fddi/skfp/smt.c +++ b/drivers/net/fddi/skfp/smt.c @@ -900,7 +900,7 @@ static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, rdf->version.v_pad2 = 0 ; /* set P13 */ - if ((unsigned) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) + + if ((unsigned int) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) + 2*sizeof(struct smt_header)) len = frame_len ; else diff --git a/drivers/net/fddi/skfp/srf.c b/drivers/net/fddi/skfp/srf.c index f6f7baf9f27a..cc27dea3414e 100644 --- a/drivers/net/fddi/skfp/srf.c +++ b/drivers/net/fddi/skfp/srf.c @@ -73,7 +73,7 @@ void smt_init_evc(struct s_smc *smc) { struct s_srf_evc *evc ; const struct evc_init *init ; - int i ; + unsigned int i ; int index ; int offset ; @@ -84,7 +84,7 @@ void smt_init_evc(struct s_smc *smc) evc = smc->evcs ; init = evc_inits ; - for (i = 0 ; (unsigned) i < MAX_INIT_EVC ; i++) { + for (i = 0 ; i < MAX_INIT_EVC ; i++) { for (index = 0 ; index < init->n ; index++) { evc->evc_code = init->code ; evc->evc_para = init->para ; @@ -98,7 +98,7 @@ void smt_init_evc(struct s_smc *smc) init++ ; } - if ((unsigned) (evc - smc->evcs) > MAX_EVCS) { + if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) { SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ; } @@ -139,7 +139,7 @@ void smt_init_evc(struct s_smc *smc) offset++ ; } #ifdef DEBUG - for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { + for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { if (SMT_IS_CONDITION(evc->evc_code)) { if (!evc->evc_cond_state) { SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ; @@ -160,10 +160,10 @@ void smt_init_evc(struct s_smc *smc) static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index) { - int i ; + unsigned int i ; struct s_srf_evc *evc ; - for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { + for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { if (evc->evc_code == code && evc->evc_index == index) return evc; } @@ -335,9 +335,9 @@ void smt_srf_event(struct s_smc *smc, int code, int index, int cond) static void clear_all_rep(struct s_smc *smc) { struct s_srf_evc *evc ; - int i ; + unsigned int i ; - for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { + for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { evc->evc_rep_required = FALSE ; if (SMT_IS_CONDITION(evc->evc_code)) *evc->evc_cond_state = FALSE ; @@ -348,10 +348,10 @@ static void clear_all_rep(struct s_smc *smc) static void clear_reported(struct s_smc *smc) { struct s_srf_evc *evc ; - int i ; + unsigned int i ; smc->srf.any_report = FALSE ; - for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { + for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { if (SMT_IS_CONDITION(evc->evc_code)) { if (*evc->evc_cond_state == FALSE) evc->evc_rep_required = FALSE ; @@ -375,7 +375,7 @@ static void smt_send_srf(struct s_smc *smc) struct s_srf_evc *evc ; SK_LOC_DECL(struct s_pcon,pcon) ; SMbuf *mb ; - int i ; + unsigned int i ; static const struct fddi_addr SMT_SRF_DA = { { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 } @@ -405,7 +405,7 @@ static void smt_send_srf(struct s_smc *smc) smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ; smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ; - for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { + for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { if (evc->evc_rep_required) { smt_add_para(smc,&pcon,evc->evc_para, (int)evc->evc_index,0) ; -- cgit v1.2.3 From 6979f8d28049879e6147767d93ba6732c8bd94f4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 10 Dec 2013 22:28:04 +0000 Subject: serial: 8250_dw: Fix LCR workaround regression Commit c49436b657d0 (serial: 8250_dw: Improve unwritable LCR workaround) caused a regression. It added a check that the LCR was written properly to detect and workaround the busy quirk, but the behaviour of bit 5 (UART_LCR_SPAR) differs between IP versions 3.00a and 3.14c per the docs. On older versions this caused the check to fail and it would repeatedly force idle and rewrite the LCR register, causing delays and preventing any input from serial being received. This is fixed by masking out UART_LCR_SPAR before making the comparison. Signed-off-by: James Hogan Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: Tim Kryger Cc: Ezequiel Garcia Cc: Matt Porter Cc: Markus Mayer Tested-by: Tim Kryger Tested-by: Ezequiel Garcia Tested-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 4658e3e0ec42..5f096c74da7e 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value) if (offset == UART_LCR) { int tries = 1000; while (tries--) { - if (value == p->serial_in(p, UART_LCR)) + unsigned int lcr = p->serial_in(p, UART_LCR); + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) return; dw8250_force_idle(p); writeb(value, p->membase + (UART_LCR << p->regshift)); @@ -132,7 +133,8 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value) if (offset == UART_LCR) { int tries = 1000; while (tries--) { - if (value == p->serial_in(p, UART_LCR)) + unsigned int lcr = p->serial_in(p, UART_LCR); + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) return; dw8250_force_idle(p); writel(value, p->membase + (UART_LCR << p->regshift)); -- cgit v1.2.3 From 0462e185caa11b38bf27f77234a8e2c3e02a35c7 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 16 Dec 2013 16:48:17 -0800 Subject: ion: remove ion_user_handle_t from ion_test.h ion_test.h should not define ion_user_handle_t, and defining it causes a warning: In file included from drivers/staging/android/ion/ion_test.c:31: drivers/staging/android/ion/../uapi/ion_test.h:23: error: redefinition of typedef 'ion_user_handle_t' drivers/staging/android/ion/../uapi/ion.h:23: note: previous declaration of 'ion_user_handle_t' was here Reported-by: Andrew Morton Cc: John Stultz Signed-off-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/ion_test.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h index 352379a02690..614d1e36f72c 100644 --- a/drivers/staging/android/uapi/ion_test.h +++ b/drivers/staging/android/uapi/ion_test.h @@ -20,8 +20,6 @@ #include #include -typedef int ion_user_handle_t; - /** * struct ion_test_rw_data - metadata passed to the kernel to read handle * @ptr: a pointer to an area at least as large as size -- cgit v1.2.3 From d4ed510a4ce84b656891f617e22d4a79a99af0c1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 17 Dec 2013 11:16:41 +0800 Subject: gpu: ion: use module_platform_driver to simplify the code module_platform_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/tegra/tegra_ion.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c index 0849600bcc00..4b3d93fbf9a5 100644 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -81,16 +81,5 @@ static struct platform_driver ion_driver = { .driver = { .name = "ion-tegra" } }; -static int __init ion_init(void) -{ - return platform_driver_register(&ion_driver); -} - -static void __exit ion_exit(void) -{ - platform_driver_unregister(&ion_driver); -} - -module_init(ion_init); -module_exit(ion_exit); +module_platform_driver(ion_driver); -- cgit v1.2.3 From 1be544cdb92954e7d73ce09f0681d9f8b6f5c3c6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 17 Dec 2013 11:20:22 +0800 Subject: gpu: ion: fix sparse non static symbol warnings Fixes the following sparse warnings: drivers/staging/android/ion/tegra/tegra_ion.c:23:19: warning: symbol 'idev' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:24:19: warning: symbol 'tegra_user_mapper' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:25:5: warning: symbol 'num_heaps' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:26:17: warning: symbol 'heaps' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:28:5: warning: symbol 'tegra_ion_probe' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:66:5: warning: symbol 'tegra_ion_remove' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/tegra/tegra_ion.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c index 4b3d93fbf9a5..3474c65f87fa 100644 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -20,12 +20,11 @@ #include "../ion.h" #include "../ion_priv.h" -struct ion_device *idev; -struct ion_mapper *tegra_user_mapper; -int num_heaps; -struct ion_heap **heaps; +static struct ion_device *idev; +static int num_heaps; +static struct ion_heap **heaps; -int tegra_ion_probe(struct platform_device *pdev) +static int tegra_ion_probe(struct platform_device *pdev) { struct ion_platform_data *pdata = pdev->dev.platform_data; int err; @@ -63,7 +62,7 @@ err: return err; } -int tegra_ion_remove(struct platform_device *pdev) +static int tegra_ion_remove(struct platform_device *pdev) { struct ion_device *idev = platform_get_drvdata(pdev); int i; -- cgit v1.2.3 From 49d45a31b71d7d9da74485922bdb63faf3dc9684 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 7 Dec 2013 13:22:42 +0100 Subject: drm/edid: add quirk for BPC in Samsung NP700G7A-S01PL notebook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug in EDID was exposed by: commit eccea7920cfb009c2fa40e9ecdce8c36f61cab66 Author: Alex Deucher Date: Mon Mar 26 15:12:54 2012 -0400 drm/radeon/kms: improve bpc handling (v2) Which resulted in kind of regression in 3.5. This fixes https://bugs.freedesktop.org/show_bug.cgi?id=70934 Signed-off-by: Rafał Miłecki Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0a1e4a5f4234..8835dcddfac3 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -68,6 +68,8 @@ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) /* Force reduced-blanking timings for detailed modes */ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) +/* Force 8bpc */ +#define EDID_QUIRK_FORCE_8BPC (1 << 8) struct detailed_mode_closure { struct drm_connector *connector; @@ -128,6 +130,9 @@ static struct edid_quirk { /* Medion MD 30217 PG */ { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, + + /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ + { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, }; /* @@ -3435,6 +3440,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) drm_add_display_info(edid, &connector->display_info); + if (quirks & EDID_QUIRK_FORCE_8BPC) + connector->display_info.bpc = 8; + return num_modes; } EXPORT_SYMBOL(drm_add_edid_modes); -- cgit v1.2.3 From 7cd0c298f6e09476f474b7ae6c1ca876c5d7f881 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 10 Dec 2013 17:00:06 -0600 Subject: usb: phy: fix driver dependencies both isp1301-omap and fsl_usb2_otg drivers depend on usb_bus_start_enum() which is only defined if CONFIG_USB != n. There is a problem, however, where both those drivers could be statically linked, while CONFIG_USB=m. Fix the problem by fixing driver dependency. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 08e2f39027ec..2b41c636a52a 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -19,8 +19,9 @@ config AB8500_USB in host mode, low speed. config FSL_USB2_OTG - bool "Freescale USB OTG Transceiver Driver" + tristate "Freescale USB OTG Transceiver Driver" depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME + depends on USB select USB_OTG select USB_PHY help @@ -29,6 +30,7 @@ config FSL_USB2_OTG config ISP1301_OMAP tristate "Philips ISP1301 with OMAP OTG" depends on I2C && ARCH_OMAP_OTG + depends on USB select USB_PHY help If you say yes here you get support for the Philips ISP1301 -- cgit v1.2.3 From f42bb70d4ff976b134fcbfb50301a87e7523f042 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 16 Dec 2013 16:34:23 -0800 Subject: drm/i915/vlv: add early DPIO init v3 Just add an early init since we may need to access DPIO regs early on. The init call in modeset_init_hw is also needed for the resume case, when we need to reset DPIO to keep things happy. v2: split reset and reg init v3: split patches (Daniel) Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a40651ef525c..9405340369d1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10871,6 +10871,8 @@ void intel_modeset_init(struct drm_device *dev) } } + intel_init_dpio(dev); + intel_cpu_pll_init(dev); intel_shared_dpll_init(dev); -- cgit v1.2.3 From 5382f5f35e73e5c7ac486824d1e26a2f44de0eec Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 16 Dec 2013 16:34:24 -0800 Subject: drm/i915/vlv: split DPIO init and reset We only need to init the reg offset for DPIO once, but we need to reset DPIO at resume time and at init time. Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9405340369d1..066fc9ddbd28 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1372,6 +1372,15 @@ static void intel_init_dpio(struct drm_device *dev) DPLL_INTEGRATED_CRI_CLK_VLV); DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; +} + +static void intel_reset_dpio(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!IS_VALLEYVIEW(dev)) + return; + /* * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - * 6. De-assert cmn_reset/side_reset. Same as VLV X0. @@ -10809,7 +10818,7 @@ void intel_modeset_init_hw(struct drm_device *dev) intel_init_clock_gating(dev); - intel_init_dpio(dev); + intel_reset_dpio(dev); mutex_lock(&dev->struct_mutex); intel_enable_gt_powersave(dev); @@ -10872,6 +10881,7 @@ void intel_modeset_init(struct drm_device *dev) } intel_init_dpio(dev); + intel_reset_dpio(dev); intel_cpu_pll_init(dev); intel_shared_dpll_init(dev); -- cgit v1.2.3 From 0e79284d138d01a794cb860af5c4d2c0eb8f6fda Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 16 Dec 2013 20:50:37 -0800 Subject: drm/i915: Reorder/respace MI instruction definition A few command were out of numerical order and had different spacing. Put them back in numerical order, with proper spacing. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f1eece4a63d5..ac87ab883ff7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -193,10 +193,13 @@ #define MI_SCENE_COUNT (1 << 3) /* just increment scene count */ #define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ #define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */ +#define MI_REPORT_HEAD MI_INSTR(0x07, 0) +#define MI_ARB_ON_OFF MI_INSTR(0x08, 0) +#define MI_ARB_ENABLE (1<<0) +#define MI_ARB_DISABLE (0<<0) #define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) #define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) #define MI_SUSPEND_FLUSH_EN (1<<0) -#define MI_REPORT_HEAD MI_INSTR(0x07, 0) #define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) #define MI_OVERLAY_CONTINUE (0x0<<21) #define MI_OVERLAY_ON (0x1<<21) @@ -212,10 +215,24 @@ #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) -#define MI_ARB_ON_OFF MI_INSTR(0x08, 0) -#define MI_ARB_ENABLE (1<<0) -#define MI_ARB_DISABLE (0<<0) - +#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */ +#define MI_SEMAPHORE_GLOBAL_GTT (1<<22) +#define MI_SEMAPHORE_UPDATE (1<<21) +#define MI_SEMAPHORE_COMPARE (1<<20) +#define MI_SEMAPHORE_REGISTER (1<<18) +#define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ +#define MI_SEMAPHORE_SYNC_VER (1<<16) /* RCS wait for VECS (RVESYNC) */ +#define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ +#define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ +#define MI_SEMAPHORE_SYNC_VEV (1<<16) /* VCS wait for VECS (VVESYNC) */ +#define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ +#define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ +#define MI_SEMAPHORE_SYNC_VEB (1<<16) /* BCS wait for VECS (BVESYNC) */ +#define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ +#define MI_SEMAPHORE_SYNC_BVE (0<<16) /* VECS wait for BCS (VEBSYNC) */ +#define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */ +#define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */ +#define MI_SEMAPHORE_SYNC_INVALID (3<<16) #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_PHYSICAL (0<<8) @@ -235,7 +252,7 @@ */ #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1) -#define MI_SRM_LRM_GLOBAL_GTT (1<<22) +#define MI_SRM_LRM_GLOBAL_GTT (1<<22) #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ #define MI_FLUSH_DW_STORE_INDEX (1<<21) #define MI_INVALIDATE_TLB (1<<18) @@ -246,30 +263,13 @@ #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) #define MI_BATCH_NON_SECURE (1) /* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */ -#define MI_BATCH_NON_SECURE_I965 (1<<8) +#define MI_BATCH_NON_SECURE_I965 (1<<8) #define MI_BATCH_PPGTT_HSW (1<<8) -#define MI_BATCH_NON_SECURE_HSW (1<<13) +#define MI_BATCH_NON_SECURE_HSW (1<<13) #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) #define MI_BATCH_GTT (2<<6) /* aliased with (1<<7) on gen4 */ #define MI_BATCH_BUFFER_START_GEN8 MI_INSTR(0x31, 1) -#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */ -#define MI_SEMAPHORE_GLOBAL_GTT (1<<22) -#define MI_SEMAPHORE_UPDATE (1<<21) -#define MI_SEMAPHORE_COMPARE (1<<20) -#define MI_SEMAPHORE_REGISTER (1<<18) -#define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ -#define MI_SEMAPHORE_SYNC_VER (1<<16) /* RCS wait for VECS (RVESYNC) */ -#define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ -#define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ -#define MI_SEMAPHORE_SYNC_VEV (1<<16) /* VCS wait for VECS (VVESYNC) */ -#define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ -#define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ -#define MI_SEMAPHORE_SYNC_VEB (1<<16) /* BCS wait for VECS (BVESYNC) */ -#define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ -#define MI_SEMAPHORE_SYNC_BVE (0<<16) /* VECS wait for BCS (VEBSYNC) */ -#define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */ -#define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */ -#define MI_SEMAPHORE_SYNC_INVALID (3<<16) + #define MI_PREDICATE_RESULT_2 (0x2214) #define LOWER_SLICE_ENABLED (1<<0) -- cgit v1.2.3 From 52ed23253b68e1cf154b03d91bed619504cf955b Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 16 Dec 2013 20:50:38 -0800 Subject: drm/i915: Don't emit mbox updates without semaphores Aside from the fact that it leaves confusing dumps on error capture, it is entirely unnecessary, and potentially harmful in cases like BDW, where the instruction has changed. In reality (seemingly), this will have no behavioral impact. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e05a0216cd9b..b106984c722a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -663,14 +663,15 @@ gen6_add_request(struct intel_ring_buffer *ring) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *useless; - int i, ret; + int i, ret, num_dwords = 4; - ret = intel_ring_begin(ring, ((I915_NUM_RINGS-1) * - MBOX_UPDATE_DWORDS) + - 4); + if (i915_semaphore_is_enabled(dev)) + num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS); +#undef MBOX_UPDATE_DWORDS + + ret = intel_ring_begin(ring, num_dwords); if (ret) return ret; -#undef MBOX_UPDATE_DWORDS for_each_ring(useless, dev_priv, i) { u32 mbox_reg = ring->signal_mbox[i]; -- cgit v1.2.3 From 2c80a4923ab9f6daf2ecab3aba36a002cf93f1b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Dec 2013 11:51:29 +0800 Subject: pwm: pca9685: depends on I2C rather than REGMAP_I2C REGMAP_I2C is not a visible config option. Thus make PWM_PCA9685 depend on I2c and then select REGMAP_I2C. Signed-off-by: Axel Lin Acked-by: Steffen Trumtrar Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 5de6fcf7f0d4..3f6642751ce5 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -112,7 +112,8 @@ config PWM_MXS config PWM_PCA9685 tristate "NXP PCA9685 PWM driver" - depends on OF && REGMAP_I2C + depends on OF && I2C + select REGMAP_I2C help Generic PWM framework driver for NXP PCA9685 LED controller. -- cgit v1.2.3 From ca7a97add4d4a7b0602b3bd1eff5c89da8636713 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 1 Dec 2013 13:04:03 -0200 Subject: backlight: pwm_bl: Remove error message upon devm_kzalloc() failure No need to have a specific OOM message, since there is generic MM out of memory message in place. Signed-off-by: Fabio Estevam Signed-off-by: Thierry Reding --- drivers/video/backlight/pwm_bl.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index fb80d68f4d33..b75201ff46f6 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -241,7 +241,6 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL); if (!pb) { - dev_err(&pdev->dev, "no memory for state\n"); ret = -ENOMEM; goto err_alloc; } -- cgit v1.2.3 From a1c31f1d057130cc63e72a09189410d169db7ecf Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 7 Dec 2013 03:10:35 +0400 Subject: can: ems_usb: fix urb leaks on failure paths There are a couple failure paths where urb leaks. Is spare code within ems_usb_start_xmit(), usb_free_urb() should be used to deallocate urb instead of usb_unanchor_urb(). In ems_usb_start() there is no usb_free_urb() if usb_submit_urb() fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Acked-by: Sebastian Haas Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/ems_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 5f9a7ad9b964..8aeec0b4601a 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -625,6 +625,7 @@ static int ems_usb_start(struct ems_usb *dev) usb_unanchor_urb(urb); usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, urb->transfer_dma); + usb_free_urb(urb); break; } @@ -798,8 +799,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne * allowed (MAX_TX_URBS). */ if (!context) { - usb_unanchor_urb(urb); usb_free_coherent(dev->udev, size, buf, urb->transfer_dma); + usb_free_urb(urb); netdev_warn(netdev, "couldn't find free context\n"); -- cgit v1.2.3 From 20fb4eb96fb0350d28fc4d7cbfd5506711079592 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 14 Dec 2013 14:36:25 +0100 Subject: can: peak_usb: fix mem leak in pcan_usb_pro_init() This patch fixes a memory leak in pcan_usb_pro_init(). In patch f14e224 net: can: peak_usb: Do not do dma on the stack the struct pcan_usb_pro_fwinfo *fi and struct pcan_usb_pro_blinfo *bi were converted from stack to dynamic allocation va kmalloc(). However the corresponding kfree() was not introduced. This patch adds the missing kfree(). Cc: linux-stable # v3.10 Reported-by: Stephane Grosjean Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 8ee9d1556e6e..263dd921edc4 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) /* set LED in default state (end of init phase) */ pcan_usb_pro_set_led(dev, 0, 1); + kfree(bi); + kfree(fi); + return 0; err_out: -- cgit v1.2.3 From 32b16d46e4154d6f9d9c1d5dd35f64cdf08b7aea Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Fri, 13 Dec 2013 14:41:49 +0800 Subject: pwm: atmel-pwm: Add Atmel PWM controller driver Add a PWM framework driver for the PWM controller found on Atmel SoCs. Signed-off-by: Bo Shen Acked-by: Alexandre Belloni Acked-by: Jean-Christophe PLAGNIOL-VILLARD [thierry.reding: coding style and other minor cleanups] Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 9 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-atmel.c | 393 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 403 insertions(+) create mode 100644 drivers/pwm/pwm-atmel.c (limited to 'drivers') diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 3f6642751ce5..6a2a1e0a4886 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -41,6 +41,15 @@ config PWM_AB8500 To compile this driver as a module, choose M here: the module will be called pwm-ab8500. +config PWM_ATMEL + tristate "Atmel PWM support" + depends on ARCH_AT91 + help + Generic PWM framework driver for Atmel SoC. + + To compile this driver as a module, choose M here: the module + will be called pwm-atmel. + config PWM_ATMEL_TCB tristate "Atmel TC Block PWM support" depends on ATMEL_TCLIB && OF diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 8b754e4dba4a..1b99cfbde527 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_PWM) += core.o obj-$(CONFIG_PWM_SYSFS) += sysfs.o obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o +obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c new file mode 100644 index 000000000000..657e90ab6e0a --- /dev/null +++ b/drivers/pwm/pwm-atmel.c @@ -0,0 +1,393 @@ +/* + * Driver for Atmel Pulse Width Modulation Controller + * + * Copyright (C) 2013 Atmel Corporation + * Bo Shen + * + * Licensed under GPLv2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The following is global registers for PWM controller */ +#define PWM_ENA 0x04 +#define PWM_DIS 0x08 +#define PWM_SR 0x0C +/* Bit field in SR */ +#define PWM_SR_ALL_CH_ON 0x0F + +/* The following register is PWM channel related registers */ +#define PWM_CH_REG_OFFSET 0x200 +#define PWM_CH_REG_SIZE 0x20 + +#define PWM_CMR 0x0 +/* Bit field in CMR */ +#define PWM_CMR_CPOL (1 << 9) +#define PWM_CMR_UPD_CDTY (1 << 10) + +/* The following registers for PWM v1 */ +#define PWMV1_CDTY 0x04 +#define PWMV1_CPRD 0x08 +#define PWMV1_CUPD 0x10 + +/* The following registers for PWM v2 */ +#define PWMV2_CDTY 0x04 +#define PWMV2_CDTYUPD 0x08 +#define PWMV2_CPRD 0x0C +#define PWMV2_CPRDUPD 0x10 + +/* + * Max value for duty and period + * + * Although the duty and period register is 32 bit, + * however only the LSB 16 bits are significant. + */ +#define PWM_MAX_DTY 0xFFFF +#define PWM_MAX_PRD 0xFFFF +#define PRD_MAX_PRES 10 + +struct atmel_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + void __iomem *base; + + void (*config)(struct pwm_chip *chip, struct pwm_device *pwm, + unsigned long dty, unsigned long prd); +}; + +static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct atmel_pwm_chip, chip); +} + +static inline u32 atmel_pwm_readl(struct atmel_pwm_chip *chip, + unsigned long offset) +{ + return readl_relaxed(chip->base + offset); +} + +static inline void atmel_pwm_writel(struct atmel_pwm_chip *chip, + unsigned long offset, unsigned long val) +{ + writel_relaxed(val, chip->base + offset); +} + +static inline u32 atmel_pwm_ch_readl(struct atmel_pwm_chip *chip, + unsigned int ch, unsigned long offset) +{ + unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE; + + return readl_relaxed(chip->base + base + offset); +} + +static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip, + unsigned int ch, unsigned long offset, + unsigned long val) +{ + unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE; + + writel_relaxed(val, chip->base + base + offset); +} + +static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + unsigned long clk_rate, prd, dty; + unsigned long long div; + unsigned int pres = 0; + int ret; + + if (test_bit(PWMF_ENABLED, &pwm->flags) && (period_ns != pwm->period)) { + dev_err(chip->dev, "cannot change PWM period while enabled\n"); + return -EBUSY; + } + + clk_rate = clk_get_rate(atmel_pwm->clk); + div = clk_rate; + + /* Calculate the period cycles */ + while (div > PWM_MAX_PRD) { + div = clk_rate / (1 << pres); + div = div * period_ns; + /* 1/Hz = 100000000 ns */ + do_div(div, 1000000000); + + if (pres++ > PRD_MAX_PRES) { + dev_err(chip->dev, "pres exceeds the maximum value\n"); + return -EINVAL; + } + } + + /* Calculate the duty cycles */ + prd = div; + div *= duty_ns; + do_div(div, period_ns); + dty = div; + + ret = clk_enable(atmel_pwm->clk); + if (ret) { + dev_err(chip->dev, "failed to enable PWM clock\n"); + return ret; + } + + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, pres); + atmel_pwm->config(chip, pwm, dty, prd); + + clk_disable(atmel_pwm->clk); + return ret; +} + +static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm, + unsigned long dty, unsigned long prd) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + unsigned int val; + + if (test_bit(PWMF_ENABLED, &pwm->flags)) { + /* + * If the PWM channel is enabled, using the update register, + * it needs to set bit 10 of CMR to 0 + */ + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty); + + val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); + val &= ~PWM_CMR_UPD_CDTY; + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); + } else { + /* + * If the PWM channel is disabled, write value to duty and + * period registers directly. + */ + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty); + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd); + } +} + +static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm, + unsigned long dty, unsigned long prd) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + + if (test_bit(PWMF_ENABLED, &pwm->flags)) { + /* + * If the PWM channel is enabled, using the duty update register + * to update the value. + */ + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTYUPD, dty); + } else { + /* + * If the PWM channel is disabled, write value to duty and + * period registers directly. + */ + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTY, dty); + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CPRD, prd); + } +} + +static int atmel_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + u32 val; + int ret; + + val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); + + if (polarity == PWM_POLARITY_NORMAL) + val &= ~PWM_CMR_CPOL; + else + val |= PWM_CMR_CPOL; + + ret = clk_enable(atmel_pwm->clk); + if (ret) { + dev_err(chip->dev, "failed to enable PWM clock\n"); + return ret; + } + + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); + + clk_disable(atmel_pwm->clk); + + return 0; +} + +static int atmel_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + int ret; + + ret = clk_enable(atmel_pwm->clk); + if (ret) { + dev_err(chip->dev, "failed to enable PWM clock\n"); + return ret; + } + + atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm); + + return 0; +} + +static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + + atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm); + + clk_disable(atmel_pwm->clk); +} + +static const struct pwm_ops atmel_pwm_ops = { + .config = atmel_pwm_config, + .set_polarity = atmel_pwm_set_polarity, + .enable = atmel_pwm_enable, + .disable = atmel_pwm_disable, + .owner = THIS_MODULE, +}; + +struct atmel_pwm_data { + void (*config)(struct pwm_chip *chip, struct pwm_device *pwm, + unsigned long dty, unsigned long prd); +}; + +static const struct atmel_pwm_data atmel_pwm_data_v1 = { + .config = atmel_pwm_config_v1, +}; + +static const struct atmel_pwm_data atmel_pwm_data_v2 = { + .config = atmel_pwm_config_v2, +}; + +static const struct platform_device_id atmel_pwm_devtypes[] = { + { + .name = "at91sam9rl-pwm", + .driver_data = (kernel_ulong_t)&atmel_pwm_data_v1, + }, { + .name = "sama5d3-pwm", + .driver_data = (kernel_ulong_t)&atmel_pwm_data_v2, + }, { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(platform, atmel_pwm_devtypes); + +static const struct of_device_id atmel_pwm_dt_ids[] = { + { + .compatible = "atmel,at91sam9rl-pwm", + .data = &atmel_pwm_data_v1, + }, { + .compatible = "atmel,sama5d3-pwm", + .data = &atmel_pwm_data_v2, + }, { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids); + +static inline const struct atmel_pwm_data * +atmel_pwm_get_driver_data(struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + + match = of_match_device(atmel_pwm_dt_ids, &pdev->dev); + if (!match) + return NULL; + + return match->data; + } else { + const struct platform_device_id *id; + + id = platform_get_device_id(pdev); + + return (struct atmel_pwm_data *)id->driver_data; + } +} + +static int atmel_pwm_probe(struct platform_device *pdev) +{ + const struct atmel_pwm_data *data; + struct atmel_pwm_chip *atmel_pwm; + struct resource *res; + int ret; + + data = atmel_pwm_get_driver_data(pdev); + if (!data) + return -ENODEV; + + atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL); + if (!atmel_pwm) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + atmel_pwm->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(atmel_pwm->base)) + return PTR_ERR(atmel_pwm->base); + + atmel_pwm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(atmel_pwm->clk)) + return PTR_ERR(atmel_pwm->clk); + + ret = clk_prepare(atmel_pwm->clk); + if (ret) { + dev_err(&pdev->dev, "failed to prepare PWM clock\n"); + return ret; + } + + atmel_pwm->chip.dev = &pdev->dev; + atmel_pwm->chip.ops = &atmel_pwm_ops; + + if (pdev->dev.of_node) { + atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags; + atmel_pwm->chip.of_pwm_n_cells = 3; + } + + atmel_pwm->chip.base = -1; + atmel_pwm->chip.npwm = 4; + atmel_pwm->config = data->config; + + ret = pwmchip_add(&atmel_pwm->chip); + if (ret < 0) { + dev_err(&pdev->dev, "failed to add PWM chip %d\n", ret); + goto unprepare_clk; + } + + platform_set_drvdata(pdev, atmel_pwm); + +unprepare_clk: + clk_unprepare(atmel_pwm->clk); + return ret; +} + +static int atmel_pwm_remove(struct platform_device *pdev) +{ + struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev); + + clk_unprepare(atmel_pwm->clk); + + return pwmchip_remove(&atmel_pwm->chip); +} + +static struct platform_driver atmel_pwm_driver = { + .driver = { + .name = "atmel-pwm", + .of_match_table = of_match_ptr(atmel_pwm_dt_ids), + }, + .id_table = atmel_pwm_devtypes, + .probe = atmel_pwm_probe, + .remove = atmel_pwm_remove, +}; +module_platform_driver(atmel_pwm_driver); + +MODULE_ALIAS("platform:atmel-pwm"); +MODULE_AUTHOR("Bo Shen "); +MODULE_DESCRIPTION("Atmel PWM driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 4ce78a838c1c5482aeb47cfba9baf9df90400a25 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 1 Nov 2013 10:36:36 +0100 Subject: can: c_can: Speed up rx_poll function This patch speeds up the rx_poll function by reducing the number of register reads. Replace the 32bit register read by a 16bit register read. Currently the 32bit register read is implemented by using 2 16bit reads. This is inefficient as we only use the lower 16bit in rx_poll. The for loop reads the pending interrupts in every iteration. This leads up to 16 reads of pending interrupts. The patch introduces a new outer loop to read the pending interrupts as long as 'quota' is above 0. This reduces the total number of reads. The third change is to replace the for-loop by a ffs loop. Tested on AM335x. I removed all 'static' and 'inline' from c_can.c to see the timings for all functions. I used the function tracer with trace_stats. 125kbit: Function Hit Time Avg s^2 -------- --- ---- --- --- c_can_do_rx_poll 63960 10168178 us 158.977 us 1493056 us With patch: c_can_do_rx_poll 63941 3764057 us 58.867 us 776162.2 us 1Mbit: Function Hit Time Avg s^2 -------- --- ---- --- --- c_can_do_rx_poll 69489 30049498 us 432.435 us 9271851 us With patch: c_can_do_rx_poll 207109 24322185 us 117.436 us 171469047 us Signed-off-by: Markus Pargmann Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 77061eebb034..951bfede8f3d 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -808,17 +808,19 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) u32 num_rx_pkts = 0; unsigned int msg_obj, msg_ctrl_save; struct c_can_priv *priv = netdev_priv(dev); - u32 val = c_can_read_reg32(priv, C_CAN_INTPND1_REG); + u16 val; + + /* + * It is faster to read only one 16bit register. This is only possible + * for a maximum number of 16 objects. + */ + BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, + "Implementation does not support more message objects than 16"); + + while (quota > 0 && (val = priv->read_reg(priv, C_CAN_INTPND1_REG))) { + while ((msg_obj = ffs(val)) && quota > 0) { + val &= ~BIT(msg_obj - 1); - for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST; - msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0; - val = c_can_read_reg32(priv, C_CAN_INTPND1_REG), - msg_obj++) { - /* - * as interrupt pending register's bit n-1 corresponds to - * message object n, we need to handle the same properly. - */ - if (val & (1 << (msg_obj - 1))) { c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL & ~IF_COMM_TXRQST); msg_ctrl_save = priv->read_reg(priv, -- cgit v1.2.3 From 05780d9808f72dc28a5c3602e11a7c53aef972ad Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 6 Dec 2013 06:28:45 -0800 Subject: can: Fix FSF address in file headers Several files refer to an old address for the Free Software Foundation in the file header comment. Resolve by replacing the address with the URL so that we do not have to keep updating the header comments anytime the address changes. CC: Wolfgang Grandegger CC: Marc Kleine-Budde Signed-off-by: Jeff Kirsher Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev.c | 3 +-- drivers/net/can/mcp251x.c | 3 +-- drivers/net/can/mscan/mpc5xxx_can.c | 3 +-- drivers/net/can/mscan/mscan.c | 3 +-- drivers/net/can/mscan/mscan.h | 3 +-- drivers/net/can/pch_can.c | 3 +-- drivers/net/can/sja1000/ems_pci.c | 3 +-- drivers/net/can/sja1000/kvaser_pci.c | 3 +-- drivers/net/can/sja1000/plx_pci.c | 3 +-- drivers/net/can/sja1000/sja1000_isa.c | 3 +-- drivers/net/can/sja1000/sja1000_of_platform.c | 3 +-- drivers/net/can/sja1000/sja1000_platform.c | 3 +-- drivers/net/can/slcan.c | 4 +--- drivers/net/can/softing/softing_cs.c | 3 +-- drivers/net/can/softing/softing_fw.c | 3 +-- drivers/net/can/softing/softing_main.c | 3 +-- 16 files changed, 16 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index bda1888cae9a..13a909822e25 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 08ac401e0214..c4970c8b949a 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -28,8 +28,7 @@ * 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 + * along with this program; if not, see . * * * diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index e59b3a392af6..035e235e3118 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index a955ec8c4b97..b9f3faabb0f3 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index e98abb97a050..ad8e08f9c496 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h @@ -14,8 +14,7 @@ * 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 + * along with this program; if not, see . */ #ifndef __MSCAN_H__ diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 5f0e9b3bfa7b..79e8699fd35a 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -12,8 +12,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index 835921388e7b..d790b874ca79 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c index 087b13bd300e..c96eb14699d5 100644 --- a/drivers/net/can/sja1000/kvaser_pci.c +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -26,8 +26,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index f9b4f81cd86a..5df7f9848823 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c @@ -16,8 +16,7 @@ * 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. + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index 06a282397fff..df136a2516c4 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -11,8 +11,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 047accd4ede5..2f6e24534231 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -13,8 +13,7 @@ * 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. + * along with this program; if not, see . */ /* This is a generic driver for SJA1000 chips on the OpenFirmware platform diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 29f9b6321187..943df645b459 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -12,8 +12,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 25377e547f9b..3fcdae266377 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -18,9 +18,7 @@ * 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. You can also get it - * at http://www.gnu.org/licenses/gpl.html + * with this program; if not, see http://www.gnu.org/licenses/gpl.html * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c index 498605f833dd..cdc0c7433a4b 100644 --- a/drivers/net/can/softing/softing_cs.c +++ b/drivers/net/can/softing/softing_cs.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c index b595d3422b9f..52fe50725d74 100644 --- a/drivers/net/can/softing/softing_fw.c +++ b/drivers/net/can/softing/softing_fw.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 6cd5c01b624d..1b8212783640 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -13,8 +13,7 @@ * 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 + * along with this program; if not, see . */ #include -- cgit v1.2.3 From 21629e1a118402566dce08f26edf19954fecef32 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sun, 15 Dec 2013 18:16:00 +0400 Subject: can: mcp251x: Convert to devm-* API Replace existing resource handling in the driver with managed device resource, this ensures more consistent error values and simplifies error paths. Signed-off-by: Alexander Shiyan Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mcp251x.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index c4970c8b949a..88d3877b6277 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -1066,15 +1066,17 @@ static int mcp251x_can_probe(struct spi_device *spi) /* Allocate non-DMA buffers */ if (!mcp251x_enable_dma) { - priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); + priv->spi_tx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, + GFP_KERNEL); if (!priv->spi_tx_buf) { ret = -ENOMEM; - goto error_tx_buf; + goto error_probe; } - priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); + priv->spi_rx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, + GFP_KERNEL); if (!priv->spi_rx_buf) { ret = -ENOMEM; - goto error_rx_buf; + goto error_probe; } } @@ -1107,12 +1109,6 @@ static int mcp251x_can_probe(struct spi_device *spi) return ret; error_probe: - if (!mcp251x_enable_dma) - kfree(priv->spi_rx_buf); -error_rx_buf: - if (!mcp251x_enable_dma) - kfree(priv->spi_tx_buf); -error_tx_buf: if (mcp251x_enable_dma) dma_free_coherent(&spi->dev, PAGE_SIZE, priv->spi_tx_buf, priv->spi_tx_dma); @@ -1135,9 +1131,6 @@ static int mcp251x_can_remove(struct spi_device *spi) if (mcp251x_enable_dma) { dma_free_coherent(&spi->dev, PAGE_SIZE, priv->spi_tx_buf, priv->spi_tx_dma); - } else { - kfree(priv->spi_tx_buf); - kfree(priv->spi_rx_buf); } mcp251x_power_enable(priv->power, 0); -- cgit v1.2.3 From f78dea064c5f7de07de4912a6e5136dbc443d614 Mon Sep 17 00:00:00 2001 From: Marc Carino Date: Mon, 16 Dec 2013 18:15:53 -0800 Subject: libata: implement ATA_HORKAGE_NO_NCQ_TRIM and apply it to Micro M500 SSDs Certain drives cannot handle queued TRIM commands properly, even though support is indicated in the IDENTIFY DEVICE buffer. This patch allows for disabling the commands for the affected drives and apply it to the Micron/Crucial M500 SSDs which exhibit incorrect protocol behavior when issued queued TRIM commands, which could lead to silent data corruption. tj: Merged two unnecessarily split patches and made minor edits including shortening horkage name. Signed-off-by: Marc Carino Signed-off-by: Tejun Heo Link: http://lkml.kernel.org/g/1387246554-7311-1-git-send-email-marc.ceeeee@gmail.com Cc: stable@vger.kernel.org # 3.12+ --- drivers/ata/libata-core.c | 15 +++++++++++++-- include/linux/libata.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ff0158481d53..1393a5890ed5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2149,9 +2149,16 @@ static int ata_dev_config_ncq(struct ata_device *dev, "failed to get NCQ Send/Recv Log Emask 0x%x\n", err_mask); } else { + u8 *cmds = dev->ncq_send_recv_cmds; + dev->flags |= ATA_DFLAG_NCQ_SEND_RECV; - memcpy(dev->ncq_send_recv_cmds, ap->sector_buf, - ATA_LOG_NCQ_SEND_RECV_SIZE); + memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE); + + if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) { + ata_dev_dbg(dev, "disabling queued TRIM support\n"); + cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &= + ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM; + } } } @@ -4205,6 +4212,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER }, { "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER }, + /* devices that don't properly handle queued TRIM commands */ + { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + /* End Marker */ { } }; diff --git a/include/linux/libata.h b/include/linux/libata.h index 0e23c26485f4..9b503376738f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -418,6 +418,7 @@ enum { ATA_HORKAGE_DUMP_ID = (1 << 16), /* dump IDENTIFY data */ ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */ ATA_HORKAGE_ATAPI_DMADIR = (1 << 18), /* device requires dmadir */ + ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ -- cgit v1.2.3 From a08acaf2f6c278f7b3c090d9d7c6cbbe4f02f003 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 17 Dec 2013 09:56:53 +0100 Subject: drm/i915: Use symbolic names for booleans in i915_semaphore_is_enabled Noticed while reviewing a patch and couldn't resist the OCD. Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aea909b2f22e..31ffe39d2b79 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -480,12 +480,12 @@ check_next: bool i915_semaphore_is_enabled(struct drm_device *dev) { if (INTEL_INFO(dev)->gen < 6) - return 0; + return false; /* Until we get further testing... */ if (IS_GEN8(dev)) { WARN_ON(!i915_preliminary_hw_support); - return 0; + return false; } if (i915_semaphores >= 0) @@ -497,7 +497,7 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) return false; #endif - return 1; + return true; } static int i915_drm_freeze(struct drm_device *dev) -- cgit v1.2.3 From 691bb717544f3c1241f5a4e5fb884a0215a2dc9e Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 12 Dec 2013 14:36:36 +0000 Subject: drm/i915: Use IS_VALLEYVIEW() to test the is_valleyview flag Signed-off-by: Damien Lespiau Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b35f65ed6c5e..7fd3e67244ec 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3582,9 +3582,11 @@ void gen6_set_rps(struct drm_device *dev, u8 val) void gen6_rps_idle(struct drm_i915_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; + mutex_lock(&dev_priv->rps.hw_lock); if (dev_priv->rps.enabled) { - if (dev_priv->info->is_valleyview) + if (IS_VALLEYVIEW(dev)) valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay); else gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); @@ -3595,9 +3597,11 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) void gen6_rps_boost(struct drm_i915_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; + mutex_lock(&dev_priv->rps.hw_lock); if (dev_priv->rps.enabled) { - if (dev_priv->info->is_valleyview) + if (IS_VALLEYVIEW(dev)) valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay); else gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay); -- cgit v1.2.3 From 243eaf381d1a851f53c9f3cbd26849731da17c48 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 17 Dec 2013 10:00:54 +0100 Subject: drm/i915: kick firmware fbs even when i915 fbdev is disabled Otherwise we don't kick out firmware framebuffers like vesafb and efifb when CONFIG_DRM_I915_FBDEV=n but CONFIG_FB=y. There's still the pesky issue with vgacon which we should somehow replace with the dummy console at least. We have a similar issue at module un/reload, since vgacon state is terminally botched after i915.ko has loaded in modeset mode. But this gets us a step further at least. v2: Use IS_ENABLED - I always get this wrong for tristates. Spotted by Jani. Reported-by: Chris Wilson Cc: Chris Wilson Cc: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index b49571df555f..1a25f9eaca59 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1405,7 +1405,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) master->driver_priv = NULL; } -#ifdef CONFIG_DRM_I915_FBDEV +#if IS_ENABLED(CONFIG_FB) static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) { struct apertures_struct *ap; -- cgit v1.2.3 From ac9545fda6ed13c3a1205de138fa25c076cf4473 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:28 +0200 Subject: drm/i915: Add IVB DDB partitioning control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On IVB the display data buffer partitioning control lives in the DISP_ARB_CTL2 register. Add the relevant defines/code for it. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 30 ++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ac87ab883ff7..e9548b185f66 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4148,6 +4148,8 @@ #define DISP_ARB_CTL 0x45000 #define DISP_TILE_SURFACE_SWIZZLING (1<<13) #define DISP_FBC_WM_DIS (1<<15) +#define DISP_ARB_CTL2 0x45004 +#define DISP_DATA_PARTITION_5_6 (1<<6) #define GEN7_MSG_CTL 0x45010 #define WAIT_FOR_PCH_RESET_ACK (1<<1) #define WAIT_FOR_PCH_FLR_ACK (1<<0) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7fd3e67244ec..be8244282742 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2864,6 +2864,7 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, static void hsw_write_wm_values(struct drm_i915_private *dev_priv, struct hsw_wm_values *results) { + struct drm_device *dev = dev_priv->dev; struct hsw_wm_values *previous = &dev_priv->wm.hw; unsigned int dirty; uint32_t val; @@ -2894,12 +2895,21 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); if (dirty & WM_DIRTY_DDB) { - val = I915_READ(WM_MISC); - if (results->partitioning == INTEL_DDB_PART_1_2) - val &= ~WM_MISC_DATA_PARTITION_5_6; - else - val |= WM_MISC_DATA_PARTITION_5_6; - I915_WRITE(WM_MISC, val); + if (IS_HASWELL(dev)) { + val = I915_READ(WM_MISC); + if (results->partitioning == INTEL_DDB_PART_1_2) + val &= ~WM_MISC_DATA_PARTITION_5_6; + else + val |= WM_MISC_DATA_PARTITION_5_6; + I915_WRITE(WM_MISC, val); + } else { + val = I915_READ(DISP_ARB_CTL2); + if (results->partitioning == INTEL_DDB_PART_1_2) + val &= ~DISP_DATA_PARTITION_5_6; + else + val |= DISP_DATA_PARTITION_5_6; + I915_WRITE(DISP_ARB_CTL2, val); + } } if (dirty & WM_DIRTY_FBC) { @@ -3210,8 +3220,12 @@ void ilk_wm_get_hw_state(struct drm_device *dev) hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB); hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); - hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? - INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; + if (IS_HASWELL(dev)) + hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? + INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; + else if (IS_IVYBRIDGE(dev)) + hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ? + INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; hw->enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); -- cgit v1.2.3 From a68d68eebc9820212186b6d02f2dce09deef0e53 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:29 +0200 Subject: drm/i915: Add ILK/SNB/IVB WM latency field support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new function ilk_wm_lp_latency() which will tell us what to write into the WM_LPx register latency field. HSW is different from erlier gens in this regard. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index be8244282742..dbd025a4f22f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2715,6 +2715,17 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm) return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable); } +/* The value we need to program into the WM_LPx latency field */ +static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_HASWELL(dev)) + return 2 * level; + else + return dev_priv->wm.pri_latency[level]; +} + static void hsw_compute_wm_results(struct drm_device *dev, const struct intel_pipe_wm *merged, enum intel_ddb_partitioning partitioning, @@ -2737,7 +2748,7 @@ static void hsw_compute_wm_results(struct drm_device *dev, break; results->wm_lp[wm_lp - 1] = WM3_LP_EN | - ((level * 2) << WM1_LP_LATENCY_SHIFT) | + (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) | (r->pri_val << WM1_LP_SR_SHIFT) | r->cur_val; -- cgit v1.2.3 From 7b39a0b791a356d09dd2517ec04b1bf9cdced4ab Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:30 +0200 Subject: drm/i915: Avoid computing invalid WM levels when sprites/scaling is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ILK/SNB only LP0/1 watermarks can be enabled when sprites are enabled, and on ILK/SNB/IVB sprite scaling is limited to LP0 only. So we can avoid computing the extra levels we're never going to use. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index dbd025a4f22f..b06076d8f386 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2643,6 +2643,14 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc, /* LP0 watermarks always use 1/2 DDB partitioning */ ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + /* ILK/SNB: LP2+ watermarks only w/o sprites */ + if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled) + max_level = 1; + + /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */ + if (params->spr.scaled) + max_level = 0; + for (level = 0; level <= max_level; level++) ilk_compute_wm_level(dev_priv, level, params, &pipe_wm->wm[level]); -- cgit v1.2.3 From 6cef2b8a5671dc6abbc0414a94be843590f93ede Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:32 +0200 Subject: drm/i915: Fix LP1 sprite watermarks for ILK/SNB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ILK/SNB don't have LP2+ watermarks for sprites. Also the LP1 sprite watermark register has its own enable bit. Take these differences into account when programming the LP1+ registers. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b06076d8f386..232d8c3b1f10 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2767,7 +2767,11 @@ static void hsw_compute_wm_results(struct drm_device *dev, results->wm_lp[wm_lp - 1] |= r->fbc_val << WM1_LP_FBC_SHIFT; - results->wm_lp_spr[wm_lp - 1] = r->spr_val; + if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) { + WARN_ON(wm_lp != 1); + results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val; + } else + results->wm_lp_spr[wm_lp - 1] = r->spr_val; } /* LP0 register values */ @@ -2899,6 +2903,10 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, 0); + if (INTEL_INFO(dev)->gen <= 6 && + dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != 0) + I915_WRITE(WM1S_LP_ILK, 0); + if (dirty & WM_DIRTY_PIPE(PIPE_A)) I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]); if (dirty & WM_DIRTY_PIPE(PIPE_B)) @@ -2940,12 +2948,17 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(DISP_ARB_CTL, val); } - if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) - I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); - if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1]) - I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]); - if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2]) - I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); + if (INTEL_INFO(dev)->gen <= 6) { + if (dirty & WM_DIRTY_LP(1) && results->wm_lp_spr[0] != 0) + I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); + } else { + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) + I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); + if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1]) + I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]); + if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2]) + I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); + } if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, results->wm_lp[0]); -- cgit v1.2.3 From facd619b8869b308e02104a200abf6f9d7cddcab Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:33 +0200 Subject: drm/i915: Fix LP1+ watermark disabling ILK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ILK disabling LP1+ watermarks must be done carefully to avoid underruns. If we just write 0 to the register in the middle of the scan cycle we often get an underrun. So instead we have to leave the actual watermark levels in the register intact, and just toggle the enable bit. Presumably the hardware takes a while to get out of low power mode, and so the watermark level need to stay valid until that time. We also have to be careful with the WM1S_LP_EN bit. It seems the hardware more or less treats it like the actual watermarks numbers, and so we must not toggle it too soon. Just leave it alone when disabling the LP1+ watermarks. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 232d8c3b1f10..c43cf138c871 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2896,16 +2896,23 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, if (!dirty) return; - if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0) - I915_WRITE(WM3_LP_ILK, 0); - if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0) - I915_WRITE(WM2_LP_ILK, 0); - if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0) - I915_WRITE(WM1_LP_ILK, 0); + if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] & WM1_LP_SR_EN) { + previous->wm_lp[2] &= ~WM1_LP_SR_EN; + I915_WRITE(WM3_LP_ILK, previous->wm_lp[2]); + } + if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] & WM1_LP_SR_EN) { + previous->wm_lp[1] &= ~WM1_LP_SR_EN; + I915_WRITE(WM2_LP_ILK, previous->wm_lp[1]); + } + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] & WM1_LP_SR_EN) { + previous->wm_lp[0] &= ~WM1_LP_SR_EN; + I915_WRITE(WM1_LP_ILK, previous->wm_lp[0]); + } - if (INTEL_INFO(dev)->gen <= 6 && - dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != 0) - I915_WRITE(WM1S_LP_ILK, 0); + /* + * Don't touch WM1S_LP_EN here. + * Doing so could cause underruns. + */ if (dirty & WM_DIRTY_PIPE(PIPE_A)) I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]); @@ -2949,7 +2956,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, } if (INTEL_INFO(dev)->gen <= 6) { - if (dirty & WM_DIRTY_LP(1) && results->wm_lp_spr[0] != 0) + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); } else { if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) @@ -2960,11 +2967,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); } - if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != results->wm_lp[0]) I915_WRITE(WM1_LP_ILK, results->wm_lp[0]); - if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0) + if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != results->wm_lp[1]) I915_WRITE(WM2_LP_ILK, results->wm_lp[1]); - if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0) + if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2]) I915_WRITE(WM3_LP_ILK, results->wm_lp[2]); dev_priv->wm.hw = *results; -- cgit v1.2.3 From 0ba22e26fe47b2a216e5438292aeeb8e015e9d64 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:34 +0200 Subject: drm/i915: Don't merge LP1+ watermarks on ILK/SNB/IVB when multiple pipes are enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multi-pipe LP1+ watermarks are a HSW+ feature, so let's not do it on earlier generations. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c43cf138c871..a65d8816c1e6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2690,11 +2690,17 @@ static void ilk_merge_wm_level(struct drm_device *dev, * Merge all low power watermarks for all active pipes. */ static void ilk_wm_merge(struct drm_device *dev, + const struct intel_wm_config *config, const struct hsw_wm_maximums *max, struct intel_pipe_wm *merged) { int level, max_level = ilk_wm_max_level(dev); + /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */ + if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) && + config->num_pipes_active > 1) + return; + merged->fbc_wm_enabled = true; /* merge each WM1+ level */ @@ -3000,13 +3006,13 @@ static void haswell_update_wm(struct drm_crtc *crtc) intel_crtc->wm.active = pipe_wm; ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max); - ilk_wm_merge(dev, &max, &lp_wm_1_2); + ilk_wm_merge(dev, &config, &max, &lp_wm_1_2); /* 5/6 split only in single pipe config on IVB+ */ if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1 && config.sprites_enabled) { ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max); - ilk_wm_merge(dev, &max, &lp_wm_5_6); + ilk_wm_merge(dev, &config, &max, &lp_wm_5_6); best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); } else { -- cgit v1.2.3 From 6c8b6c288783b05733de31fb61fc8ebfa8ae0229 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:35 +0200 Subject: drm/i915: Disable FBC WM on ILK, and disable LP2+ when FBC is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ILK has a bunch of issues with FBC. First of all, BSpec tells us that FBC WM should never be enabled. Secondly when FBC is enabled with FBC WM disabled, LP2+ watermarks must be disabled. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a65d8816c1e6..3d4daa1fc3be 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2701,7 +2701,8 @@ static void ilk_wm_merge(struct drm_device *dev, config->num_pipes_active > 1) return; - merged->fbc_wm_enabled = true; + /* ILK: FBC WM must be disabled always */ + merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6; /* merge each WM1+ level */ for (level = 1; level <= max_level; level++) { @@ -2721,6 +2722,20 @@ static void ilk_wm_merge(struct drm_device *dev, wm->fbc_val = 0; } } + + /* ILK: LP2+ must be disabled when FBC WM is disabled but FBC enabled */ + /* + * FIXME this is racy. FBC might get enabled later. + * What we should check here is whether FBC can be + * enabled sometime later. + */ + if (IS_GEN5(dev) && !merged->fbc_wm_enabled && intel_fbc_enabled(dev)) { + for (level = 2; level <= max_level; level++) { + struct intel_wm_level *wm = &merged->wm[level]; + + wm->enable = false; + } + } } static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm) -- cgit v1.2.3 From ce0e0713a6b21ec611d4a2eb5c60d18dbb4bf479 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:36 +0200 Subject: drm/i915: Linetime watermarks are a HSW feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linetime watermarks don't exist on ILK/SNB/IVB, so don't compute them except on HSW. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3d4daa1fc3be..276e98df1c0d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2655,7 +2655,8 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc, ilk_compute_wm_level(dev_priv, level, params, &pipe_wm->wm[level]); - pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc); + if (IS_HASWELL(dev)) + pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc); /* At least LP0 must be valid */ return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]); @@ -3234,7 +3235,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) }; hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]); - hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); + if (IS_HASWELL(dev)) + hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); if (intel_crtc_active(crtc)) { u32 tmp = hw->wm_pipe[pipe]; -- cgit v1.2.3 From 017636cc09e2c58bc493cc1fe74d858f50d173af Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:37 +0200 Subject: drm/i915: Disable LP1+ watermarks safely in init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ILK doesn't like if we just write the LP1+ watermarks registers with 0. We need to just disable the watermarks by clearing the enable bit. Use that method also when disabling LP1+ watermarks in init_clock_gating. It looks like disabling the sprite LP1 watermarks can cause underruns even if we just toggle the WM1S_LP_EN bit. So treat that bit like the actual watermark numbers and avoid setting it to 0 immediately. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 276e98df1c0d..e321fbc28a0b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5051,6 +5051,20 @@ static void g4x_disable_trickle_feed(struct drm_device *dev) } } +static void ilk_init_lp_watermarks(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN); + I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN); + I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); + + /* + * Don't touch WM1S_LP_EN here. + * Doing so could cause underruns. + */ +} + static void ironlake_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5084,9 +5098,8 @@ static void ironlake_init_clock_gating(struct drm_device *dev) I915_WRITE(DISP_ARB_CTL, (I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS)); - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); + + ilk_init_lp_watermarks(dev); /* * Based on the document from hardware guys the following bits @@ -5193,9 +5206,7 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE)); - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); + ilk_init_lp_watermarks(dev); I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); @@ -5369,9 +5380,7 @@ static void haswell_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); + ilk_init_lp_watermarks(dev); /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. * This implements the WaDisableRCZUnitClockGating:hsw workaround. @@ -5420,9 +5429,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; uint32_t snpcr; - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); + ilk_init_lp_watermarks(dev); I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3 From 96f90c5421aaaba35ffd931728fabeb8f6cd8471 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:38 +0200 Subject: drm/i915: Move ILK/SNB/IVB over to the HSW WM code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new HSW watermark code can now handle ILK/SNB/IVB as well, so switch them over. Kill the old code. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 656 +---------------------------------- 2 files changed, 12 insertions(+), 646 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 066fc9ddbd28..de5bbd791be5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11230,7 +11230,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, pll->on = false; } - if (IS_HASWELL(dev)) + if (HAS_PCH_SPLIT(dev)) ilk_wm_get_hw_state(dev); if (force_restore) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e321fbc28a0b..7e028341b2f5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -965,65 +965,6 @@ static const struct intel_watermark_params i830_wm_info = { I830_FIFO_LINE_SIZE }; -static const struct intel_watermark_params ironlake_display_wm_info = { - ILK_DISPLAY_FIFO, - ILK_DISPLAY_MAXWM, - ILK_DISPLAY_DFTWM, - 2, - ILK_FIFO_LINE_SIZE -}; -static const struct intel_watermark_params ironlake_cursor_wm_info = { - ILK_CURSOR_FIFO, - ILK_CURSOR_MAXWM, - ILK_CURSOR_DFTWM, - 2, - ILK_FIFO_LINE_SIZE -}; -static const struct intel_watermark_params ironlake_display_srwm_info = { - ILK_DISPLAY_SR_FIFO, - ILK_DISPLAY_MAX_SRWM, - ILK_DISPLAY_DFT_SRWM, - 2, - ILK_FIFO_LINE_SIZE -}; -static const struct intel_watermark_params ironlake_cursor_srwm_info = { - ILK_CURSOR_SR_FIFO, - ILK_CURSOR_MAX_SRWM, - ILK_CURSOR_DFT_SRWM, - 2, - ILK_FIFO_LINE_SIZE -}; - -static const struct intel_watermark_params sandybridge_display_wm_info = { - SNB_DISPLAY_FIFO, - SNB_DISPLAY_MAXWM, - SNB_DISPLAY_DFTWM, - 2, - SNB_FIFO_LINE_SIZE -}; -static const struct intel_watermark_params sandybridge_cursor_wm_info = { - SNB_CURSOR_FIFO, - SNB_CURSOR_MAXWM, - SNB_CURSOR_DFTWM, - 2, - SNB_FIFO_LINE_SIZE -}; -static const struct intel_watermark_params sandybridge_display_srwm_info = { - SNB_DISPLAY_SR_FIFO, - SNB_DISPLAY_MAX_SRWM, - SNB_DISPLAY_DFT_SRWM, - 2, - SNB_FIFO_LINE_SIZE -}; -static const struct intel_watermark_params sandybridge_cursor_srwm_info = { - SNB_CURSOR_SR_FIFO, - SNB_CURSOR_MAX_SRWM, - SNB_CURSOR_DFT_SRWM, - 2, - SNB_FIFO_LINE_SIZE -}; - - /** * intel_calculate_wm - calculate watermark level * @clock_in_khz: pixel clock @@ -1707,423 +1648,6 @@ static void i830_update_wm(struct drm_crtc *unused_crtc) I915_WRITE(FW_BLC, fwater_lo); } -/* - * Check the wm result. - * - * If any calculated watermark values is larger than the maximum value that - * can be programmed into the associated watermark register, that watermark - * must be disabled. - */ -static bool ironlake_check_srwm(struct drm_device *dev, int level, - int fbc_wm, int display_wm, int cursor_wm, - const struct intel_watermark_params *display, - const struct intel_watermark_params *cursor) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d," - " cursor %d\n", level, display_wm, fbc_wm, cursor_wm); - - if (fbc_wm > SNB_FBC_MAX_SRWM) { - DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n", - fbc_wm, SNB_FBC_MAX_SRWM, level); - - /* fbc has it's own way to disable FBC WM */ - I915_WRITE(DISP_ARB_CTL, - I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS); - return false; - } else if (INTEL_INFO(dev)->gen >= 6) { - /* enable FBC WM (except on ILK, where it must remain off) */ - I915_WRITE(DISP_ARB_CTL, - I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS); - } - - if (display_wm > display->max_wm) { - DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n", - display_wm, SNB_DISPLAY_MAX_SRWM, level); - return false; - } - - if (cursor_wm > cursor->max_wm) { - DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n", - cursor_wm, SNB_CURSOR_MAX_SRWM, level); - return false; - } - - if (!(fbc_wm || display_wm || cursor_wm)) { - DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level); - return false; - } - - return true; -} - -/* - * Compute watermark values of WM[1-3], - */ -static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, - int latency_ns, - const struct intel_watermark_params *display, - const struct intel_watermark_params *cursor, - int *fbc_wm, int *display_wm, int *cursor_wm) -{ - struct drm_crtc *crtc; - const struct drm_display_mode *adjusted_mode; - unsigned long line_time_us; - int hdisplay, htotal, pixel_size, clock; - int line_count, line_size; - int small, large; - int entries; - - if (!latency_ns) { - *fbc_wm = *display_wm = *cursor_wm = 0; - return false; - } - - crtc = intel_get_crtc_for_plane(dev, plane); - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->htotal; - hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; - pixel_size = crtc->fb->bits_per_pixel / 8; - - line_time_us = (htotal * 1000) / clock; - line_count = (latency_ns / line_time_us + 1000) / 1000; - line_size = hdisplay * pixel_size; - - /* Use the minimum of the small and large buffer method for primary */ - small = ((clock * pixel_size / 1000) * latency_ns) / 1000; - large = line_count * line_size; - - entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); - *display_wm = entries + display->guard_size; - - /* - * Spec says: - * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2 - */ - *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2; - - /* calculate the self-refresh watermark for display cursor */ - entries = line_count * pixel_size * 64; - entries = DIV_ROUND_UP(entries, cursor->cacheline_size); - *cursor_wm = entries + cursor->guard_size; - - return ironlake_check_srwm(dev, level, - *fbc_wm, *display_wm, *cursor_wm, - display, cursor); -} - -static void ironlake_update_wm(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int fbc_wm, plane_wm, cursor_wm; - unsigned int enabled; - - enabled = 0; - if (g4x_compute_wm0(dev, PIPE_A, - &ironlake_display_wm_info, - dev_priv->wm.pri_latency[0] * 100, - &ironlake_cursor_wm_info, - dev_priv->wm.cur_latency[0] * 100, - &plane_wm, &cursor_wm)) { - I915_WRITE(WM0_PIPEA_ILK, - (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); - DRM_DEBUG_KMS("FIFO watermarks For pipe A -" - " plane %d, " "cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_A; - } - - if (g4x_compute_wm0(dev, PIPE_B, - &ironlake_display_wm_info, - dev_priv->wm.pri_latency[0] * 100, - &ironlake_cursor_wm_info, - dev_priv->wm.cur_latency[0] * 100, - &plane_wm, &cursor_wm)) { - I915_WRITE(WM0_PIPEB_ILK, - (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); - DRM_DEBUG_KMS("FIFO watermarks For pipe B -" - " plane %d, cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_B; - } - - /* - * Calculate and update the self-refresh watermark only when one - * display plane is used. - */ - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); - - if (!single_plane_enabled(enabled)) - return; - enabled = ffs(enabled) - 1; - - /* WM1 */ - if (!ironlake_compute_srwm(dev, 1, enabled, - dev_priv->wm.pri_latency[1] * 500, - &ironlake_display_srwm_info, - &ironlake_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM1_LP_ILK, - WM1_LP_SR_EN | - (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - - /* WM2 */ - if (!ironlake_compute_srwm(dev, 2, enabled, - dev_priv->wm.pri_latency[2] * 500, - &ironlake_display_srwm_info, - &ironlake_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM2_LP_ILK, - WM2_LP_EN | - (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - - /* - * WM3 is unsupported on ILK, probably because we don't have latency - * data for that power state - */ -} - -static void sandybridge_update_wm(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ - u32 val; - int fbc_wm, plane_wm, cursor_wm; - unsigned int enabled; - - enabled = 0; - if (g4x_compute_wm0(dev, PIPE_A, - &sandybridge_display_wm_info, latency, - &sandybridge_cursor_wm_info, latency, - &plane_wm, &cursor_wm)) { - val = I915_READ(WM0_PIPEA_ILK); - val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); - I915_WRITE(WM0_PIPEA_ILK, val | - ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); - DRM_DEBUG_KMS("FIFO watermarks For pipe A -" - " plane %d, " "cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_A; - } - - if (g4x_compute_wm0(dev, PIPE_B, - &sandybridge_display_wm_info, latency, - &sandybridge_cursor_wm_info, latency, - &plane_wm, &cursor_wm)) { - val = I915_READ(WM0_PIPEB_ILK); - val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); - I915_WRITE(WM0_PIPEB_ILK, val | - ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); - DRM_DEBUG_KMS("FIFO watermarks For pipe B -" - " plane %d, cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_B; - } - - /* - * Calculate and update the self-refresh watermark only when one - * display plane is used. - * - * SNB support 3 levels of watermark. - * - * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, - * and disabled in the descending order - * - */ - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); - - if (!single_plane_enabled(enabled) || - dev_priv->sprite_scaling_enabled) - return; - enabled = ffs(enabled) - 1; - - /* WM1 */ - if (!ironlake_compute_srwm(dev, 1, enabled, - dev_priv->wm.pri_latency[1] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM1_LP_ILK, - WM1_LP_SR_EN | - (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - - /* WM2 */ - if (!ironlake_compute_srwm(dev, 2, enabled, - dev_priv->wm.pri_latency[2] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM2_LP_ILK, - WM2_LP_EN | - (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - - /* WM3 */ - if (!ironlake_compute_srwm(dev, 3, enabled, - dev_priv->wm.pri_latency[3] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM3_LP_ILK, - WM3_LP_EN | - (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); -} - -static void ivybridge_update_wm(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ - u32 val; - int fbc_wm, plane_wm, cursor_wm; - int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm; - unsigned int enabled; - - enabled = 0; - if (g4x_compute_wm0(dev, PIPE_A, - &sandybridge_display_wm_info, latency, - &sandybridge_cursor_wm_info, latency, - &plane_wm, &cursor_wm)) { - val = I915_READ(WM0_PIPEA_ILK); - val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); - I915_WRITE(WM0_PIPEA_ILK, val | - ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); - DRM_DEBUG_KMS("FIFO watermarks For pipe A -" - " plane %d, " "cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_A; - } - - if (g4x_compute_wm0(dev, PIPE_B, - &sandybridge_display_wm_info, latency, - &sandybridge_cursor_wm_info, latency, - &plane_wm, &cursor_wm)) { - val = I915_READ(WM0_PIPEB_ILK); - val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); - I915_WRITE(WM0_PIPEB_ILK, val | - ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); - DRM_DEBUG_KMS("FIFO watermarks For pipe B -" - " plane %d, cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_B; - } - - if (g4x_compute_wm0(dev, PIPE_C, - &sandybridge_display_wm_info, latency, - &sandybridge_cursor_wm_info, latency, - &plane_wm, &cursor_wm)) { - val = I915_READ(WM0_PIPEC_IVB); - val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); - I915_WRITE(WM0_PIPEC_IVB, val | - ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); - DRM_DEBUG_KMS("FIFO watermarks For pipe C -" - " plane %d, cursor: %d\n", - plane_wm, cursor_wm); - enabled |= 1 << PIPE_C; - } - - /* - * Calculate and update the self-refresh watermark only when one - * display plane is used. - * - * SNB support 3 levels of watermark. - * - * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, - * and disabled in the descending order - * - */ - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); - - if (!single_plane_enabled(enabled) || - dev_priv->sprite_scaling_enabled) - return; - enabled = ffs(enabled) - 1; - - /* WM1 */ - if (!ironlake_compute_srwm(dev, 1, enabled, - dev_priv->wm.pri_latency[1] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM1_LP_ILK, - WM1_LP_SR_EN | - (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - - /* WM2 */ - if (!ironlake_compute_srwm(dev, 2, enabled, - dev_priv->wm.pri_latency[2] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &fbc_wm, &plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM2_LP_ILK, - WM2_LP_EN | - (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - - /* WM3, note we have to correct the cursor latency */ - if (!ironlake_compute_srwm(dev, 3, enabled, - dev_priv->wm.pri_latency[3] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &fbc_wm, &plane_wm, &ignore_cursor_wm) || - !ironlake_compute_srwm(dev, 3, enabled, - dev_priv->wm.cur_latency[3] * 500, - &sandybridge_display_srwm_info, - &sandybridge_cursor_srwm_info, - &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm)) - return; - - I915_WRITE(WM3_LP_ILK, - WM3_LP_EN | - (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) | - (fbc_wm << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); -} - static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, struct drm_crtc *crtc) { @@ -3058,168 +2582,6 @@ static void haswell_update_sprite_wm(struct drm_plane *plane, haswell_update_wm(crtc); } -static bool -sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, - uint32_t sprite_width, int pixel_size, - const struct intel_watermark_params *display, - int display_latency_ns, int *sprite_wm) -{ - struct drm_crtc *crtc; - int clock; - int entries, tlb_miss; - - crtc = intel_get_crtc_for_plane(dev, plane); - if (!intel_crtc_active(crtc)) { - *sprite_wm = display->guard_size; - return false; - } - - clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; - - /* Use the small buffer method to calculate the sprite watermark */ - entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; - tlb_miss = display->fifo_size*display->cacheline_size - - sprite_width * 8; - if (tlb_miss > 0) - entries += tlb_miss; - entries = DIV_ROUND_UP(entries, display->cacheline_size); - *sprite_wm = entries + display->guard_size; - if (*sprite_wm > (int)display->max_wm) - *sprite_wm = display->max_wm; - - return true; -} - -static bool -sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, - uint32_t sprite_width, int pixel_size, - const struct intel_watermark_params *display, - int latency_ns, int *sprite_wm) -{ - struct drm_crtc *crtc; - unsigned long line_time_us; - int clock; - int line_count, line_size; - int small, large; - int entries; - - if (!latency_ns) { - *sprite_wm = 0; - return false; - } - - crtc = intel_get_crtc_for_plane(dev, plane); - clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; - if (!clock) { - *sprite_wm = 0; - return false; - } - - line_time_us = (sprite_width * 1000) / clock; - if (!line_time_us) { - *sprite_wm = 0; - return false; - } - - line_count = (latency_ns / line_time_us + 1000) / 1000; - line_size = sprite_width * pixel_size; - - /* Use the minimum of the small and large buffer method for primary */ - small = ((clock * pixel_size / 1000) * latency_ns) / 1000; - large = line_count * line_size; - - entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); - *sprite_wm = entries + display->guard_size; - - return *sprite_wm > 0x3ff ? false : true; -} - -static void sandybridge_update_sprite_wm(struct drm_plane *plane, - struct drm_crtc *crtc, - uint32_t sprite_width, int pixel_size, - bool enabled, bool scaled) -{ - struct drm_device *dev = plane->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe = to_intel_plane(plane)->pipe; - int latency = dev_priv->wm.spr_latency[0] * 100; /* In unit 0.1us */ - u32 val; - int sprite_wm, reg; - int ret; - - if (!enabled) - return; - - switch (pipe) { - case 0: - reg = WM0_PIPEA_ILK; - break; - case 1: - reg = WM0_PIPEB_ILK; - break; - case 2: - reg = WM0_PIPEC_IVB; - break; - default: - return; /* bad pipe */ - } - - ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size, - &sandybridge_display_wm_info, - latency, &sprite_wm); - if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n", - pipe_name(pipe)); - return; - } - - val = I915_READ(reg); - val &= ~WM0_PIPE_SPRITE_MASK; - I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); - DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm); - - - ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, - pixel_size, - &sandybridge_display_srwm_info, - dev_priv->wm.spr_latency[1] * 500, - &sprite_wm); - if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n", - pipe_name(pipe)); - return; - } - I915_WRITE(WM1S_LP_ILK, sprite_wm); - - /* Only IVB has two more LP watermarks for sprite */ - if (!IS_IVYBRIDGE(dev)) - return; - - ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, - pixel_size, - &sandybridge_display_srwm_info, - dev_priv->wm.spr_latency[2] * 500, - &sprite_wm); - if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n", - pipe_name(pipe)); - return; - } - I915_WRITE(WM2S_LP_IVB, sprite_wm); - - ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, - pixel_size, - &sandybridge_display_srwm_info, - dev_priv->wm.spr_latency[3] * 500, - &sprite_wm); - if (!ret) { - DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n", - pipe_name(pipe)); - return; - } - I915_WRITE(WM3S_LP_IVB, sprite_wm); -} - static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -6184,9 +5546,11 @@ void intel_init_pm(struct drm_device *dev) if (IS_GEN5(dev)) { if (dev_priv->wm.pri_latency[1] && dev_priv->wm.spr_latency[1] && - dev_priv->wm.cur_latency[1]) - dev_priv->display.update_wm = ironlake_update_wm; - else { + dev_priv->wm.cur_latency[1]) { + dev_priv->display.update_wm = haswell_update_wm; + dev_priv->display.update_sprite_wm = + haswell_update_sprite_wm; + } else { DRM_DEBUG_KMS("Failed to get proper latency. " "Disable CxSR\n"); dev_priv->display.update_wm = NULL; @@ -6196,8 +5560,9 @@ void intel_init_pm(struct drm_device *dev) if (dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0]) { - dev_priv->display.update_wm = sandybridge_update_wm; - dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; + dev_priv->display.update_wm = haswell_update_wm; + dev_priv->display.update_sprite_wm = + haswell_update_sprite_wm; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); @@ -6208,8 +5573,9 @@ void intel_init_pm(struct drm_device *dev) if (dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0]) { - dev_priv->display.update_wm = ivybridge_update_wm; - dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; + dev_priv->display.update_wm = haswell_update_wm; + dev_priv->display.update_sprite_wm = + haswell_update_sprite_wm; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); -- cgit v1.2.3 From 8553c18ea696827f26d3ba5652d3a2fa9ce8e874 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:39 +0200 Subject: drm/i915: Try to fix the messy IVB sprite scaling workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now have a very clear method of disabling LP1+ wartermarks, and we can actually detect if we actually did disable them, or if they were already disabled. Use that to clean up the WaCxSRDisabledForSpriteScaling:ivb handling. I was hoping to apply the workaround in a way that wouldn't require a blocking wait, but sadly IVB really does appear to require LP1+ watermarks to be off for an entire frame before enabling sprite scaling. Simply disabling LP1+ watermarks during the previous frame is not enough, no matter how early in the frame we do it :( Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 58 ++++++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_sprite.c | 27 +---------------- 3 files changed, 46 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b0a6e767951c..50da8a5a6500 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1401,7 +1401,6 @@ typedef struct drm_i915_private { /* overlay */ struct intel_overlay *overlay; - unsigned int sprite_scaling_enabled; /* backlight registers and fields in struct intel_panel */ spinlock_t backlight_lock; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7e028341b2f5..ecdb64e44e2a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2426,33 +2426,26 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, return dirty; } -/* - * The spec says we shouldn't write when we don't need, because every write - * causes WMs to be re-evaluated, expending some power. - */ -static void hsw_write_wm_values(struct drm_i915_private *dev_priv, - struct hsw_wm_values *results) +static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv, + unsigned int dirty) { - struct drm_device *dev = dev_priv->dev; struct hsw_wm_values *previous = &dev_priv->wm.hw; - unsigned int dirty; - uint32_t val; - - dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results); - if (!dirty) - return; + bool changed = false; if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] & WM1_LP_SR_EN) { previous->wm_lp[2] &= ~WM1_LP_SR_EN; I915_WRITE(WM3_LP_ILK, previous->wm_lp[2]); + changed = true; } if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] & WM1_LP_SR_EN) { previous->wm_lp[1] &= ~WM1_LP_SR_EN; I915_WRITE(WM2_LP_ILK, previous->wm_lp[1]); + changed = true; } if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] & WM1_LP_SR_EN) { previous->wm_lp[0] &= ~WM1_LP_SR_EN; I915_WRITE(WM1_LP_ILK, previous->wm_lp[0]); + changed = true; } /* @@ -2460,6 +2453,27 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, * Doing so could cause underruns. */ + return changed; +} + +/* + * The spec says we shouldn't write when we don't need, because every write + * causes WMs to be re-evaluated, expending some power. + */ +static void hsw_write_wm_values(struct drm_i915_private *dev_priv, + struct hsw_wm_values *results) +{ + struct drm_device *dev = dev_priv->dev; + struct hsw_wm_values *previous = &dev_priv->wm.hw; + unsigned int dirty; + uint32_t val; + + dirty = ilk_compute_wm_dirty(dev, previous, results); + if (!dirty) + return; + + _ilk_disable_lp_wm(dev_priv, dirty); + if (dirty & WM_DIRTY_PIPE(PIPE_A)) I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]); if (dirty & WM_DIRTY_PIPE(PIPE_B)) @@ -2523,6 +2537,13 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, dev_priv->wm.hw = *results; } +static bool ilk_disable_lp_wm(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL); +} + static void haswell_update_wm(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -2572,6 +2593,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane, uint32_t sprite_width, int pixel_size, bool enabled, bool scaled) { + struct drm_device *dev = plane->dev; struct intel_plane *intel_plane = to_intel_plane(plane); intel_plane->wm.enabled = enabled; @@ -2579,6 +2601,16 @@ static void haswell_update_sprite_wm(struct drm_plane *plane, intel_plane->wm.horiz_pixels = sprite_width; intel_plane->wm.bytes_per_pixel = pixel_size; + /* + * IVB workaround: must disable low power watermarks for at least + * one frame before enabling scaling. LP watermarks can be re-enabled + * when scaling is disabled. + * + * WaCxSRDisabledForSpriteScaling:ivb + */ + if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev)) + intel_wait_for_vblank(dev, intel_plane->pipe); + haswell_update_wm(crtc); } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 90a3f6db8288..0bba103b00ee 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -230,7 +230,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, u32 sprctl, sprscale = 0; unsigned long sprsurf_offset, linear_offset; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); - bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; sprctl = I915_READ(SPRCTL(pipe)); @@ -291,21 +290,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, crtc_w--; crtc_h--; - /* - * IVB workaround: must disable low power watermarks for at least - * one frame before enabling scaling. LP watermarks can be re-enabled - * when scaling is disabled. - */ - if (crtc_w != src_w || crtc_h != src_h) { - dev_priv->sprite_scaling_enabled |= 1 << pipe; - - if (!scaling_was_enabled) { - intel_update_watermarks(crtc); - intel_wait_for_vblank(dev, pipe); - } + if (crtc_w != src_w || crtc_h != src_h) sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; - } else - dev_priv->sprite_scaling_enabled &= ~(1 << pipe); I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); @@ -332,10 +318,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, I915_MODIFY_DISPBASE(SPRSURF(pipe), i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); POSTING_READ(SPRSURF(pipe)); - - /* potentially re-enable LP watermarks */ - if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) - intel_update_watermarks(crtc); } static void @@ -345,7 +327,6 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_plane *intel_plane = to_intel_plane(plane); int pipe = intel_plane->pipe; - bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); /* Can't leave the scaler enabled... */ @@ -355,13 +336,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) I915_MODIFY_DISPBASE(SPRSURF(pipe), 0); POSTING_READ(SPRSURF(pipe)); - dev_priv->sprite_scaling_enabled &= ~(1 << pipe); - intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); - - /* potentially re-enable LP watermarks */ - if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) - intel_update_watermarks(crtc); } static int -- cgit v1.2.3 From efb31d15dc16150a7a41947d712822e703c3e923 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:40 +0200 Subject: drm/i915: Don't disable primary when color keying is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When color keying is used, the primary may not be invisible even though the sprite fully covers it. So check for color keying before deciding to disable the primary plane. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0bba103b00ee..050ec29e3150 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -636,6 +636,15 @@ format_is_yuv(uint32_t format) } } +static bool colorkey_enabled(struct intel_plane *intel_plane) +{ + struct drm_intel_sprite_colorkey key; + + intel_plane->get_colorkey(&intel_plane->base, &key); + + return key.flags != I915_SET_COLORKEY_NONE; +} + static int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, @@ -821,7 +830,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * If the sprite is completely covering the primary plane, * we can disable the primary and save power. */ - disable_primary = drm_rect_equals(&dst, &clip); + disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane); WARN_ON(disable_primary && !visible && intel_crtc->active); mutex_lock(&dev->struct_mutex); -- cgit v1.2.3 From 1bd09ec7ad314313f15db733c7e9cb2225d95453 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:41 +0200 Subject: drm/i915: Avoid underruns when disabling sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the watermark registers aren't double bufferd, clearing the watermarks immediately after writing the sprite registers can be hazardous. Until we have something better, add a wait for vblank between the two steps to make sure the sprite no longer needs the watermark levels before we clear them. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 050ec29e3150..606c27b7ae8f 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -336,6 +336,12 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) I915_MODIFY_DISPBASE(SPRSURF(pipe), 0); POSTING_READ(SPRSURF(pipe)); + /* + * Avoid underruns when disabling the sprite. + * FIXME remove once watermark updates are done properly. + */ + intel_wait_for_vblank(dev, pipe); + intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); } @@ -503,6 +509,12 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) I915_MODIFY_DISPBASE(DVSSURF(pipe), 0); POSTING_READ(DVSSURF(pipe)); + /* + * Avoid underruns when disabling the sprite. + * FIXME remove once watermark updates are done properly. + */ + intel_wait_for_vblank(dev, pipe); + intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); } -- cgit v1.2.3 From 8368f0148fa95fb5720e0fbeb4a91d738f06a4b4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Dec 2013 15:51:31 +0200 Subject: Revert "drm/i915/sprite: Always enable the scaler on IronLake" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently always enabling the sprite scaler magically made sprites work on ILK in the past. I think the real reason for the failure was missing sprite watermark programming, and enabling the scaler effectively disabled LP1+ watermarks, which was enough to keep things going. Or it might be that the hardware more or less ignores watermarks for scaled sprites since things seem to work even if I leave sprite watermarks at 0 and disable all other planes except the sprite. In any case, we left the scaler always on but then failed to check whether we might be exceeding the scaler's source size limits. That caused the sprite to fail when a sufficiently large unscaled image was being displayed. Now that we're getting proper watermark programming for ILK, we can keep the scaler disabled unless we need to do actual scaling. This reverts commit 8aaa81a166d80ac9bf2813984e5b4c2503d0fe08. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 606c27b7ae8f..fe4de89c374c 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -469,7 +469,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, crtc_h--; dvsscale = 0; - if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h) + if (crtc_w != src_w || crtc_h != src_h) dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); -- cgit v1.2.3 From a443255c3ed5688931d89adcaa640dd10e1aeef0 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 17 Dec 2013 12:52:48 +0100 Subject: HID: debug: add labels for some new buttons Add labels for BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT and BTN_TOOL_QUADTAP. [jkosina@suse.cz: make changelog more verbose] Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 8453214ec376..53b771d5683c 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -768,6 +768,8 @@ static const char *keys[KEY_MAX + 1] = { [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", + [BTN_DPAD_UP] = "BtnDPadUp", [BTN_DPAD_DOWN] = "BtnDPadDown", + [BTN_DPAD_LEFT] = "BtnDPadLeft", [BTN_DPAD_RIGHT] = "BtnDPadRight", [BTN_0] = "Btn0", [BTN_1] = "Btn1", [BTN_2] = "Btn2", [BTN_3] = "Btn3", [BTN_4] = "Btn4", [BTN_5] = "Btn5", @@ -797,7 +799,8 @@ static const char *keys[KEY_MAX + 1] = { [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", - [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", + [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_TOOL_QUADTAP] = "ToolQuadrupleTap", + [BTN_GEAR_DOWN] = "WheelBtn", [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", -- cgit v1.2.3 From 533518a43ab9d662c864a9b63a6723050bfea488 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 12 Dec 2013 12:13:17 -0500 Subject: drm/radeon/dce6: set correct number of audio pins DCE6.0, 8.x has 6 DCE6.1 has 4 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/dce6_afmt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index de86493cbc44..ab59fd76f2d9 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -308,7 +308,9 @@ int dce6_audio_init(struct radeon_device *rdev) rdev->audio.enabled = true; if (ASIC_IS_DCE8(rdev)) - rdev->audio.num_pins = 7; + rdev->audio.num_pins = 6; + else if (ASIC_IS_DCE61(rdev)) + rdev->audio.num_pins = 4; else rdev->audio.num_pins = 6; -- cgit v1.2.3 From c745fe611ca42295c9d91d8e305d27983e9132ef Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 9 Dec 2013 17:46:59 -0500 Subject: drm/radeon/dpm: disable ss on Cayman Spread spectrum seems to cause hangs when dynamic clock switching is enabled. Disable it for now. This does not affect performance or the amount of power saved. Tracked down by Martin Andersson. bug: https://bugs.freedesktop.org/show_bug.cgi?id=69723 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/rv770_dpm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 913b025ae9b3..374499db20c7 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2328,6 +2328,12 @@ void rv770_get_engine_memory_ss(struct radeon_device *rdev) pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, ASIC_INTERNAL_MEMORY_SS, 0); + /* disable ss, causes hangs on some cayman boards */ + if (rdev->family == CHIP_CAYMAN) { + pi->sclk_ss = false; + pi->mclk_ss = false; + } + if (pi->sclk_ss || pi->mclk_ss) pi->dynamic_ss = true; else -- cgit v1.2.3 From b67ce39a30976171e7b96b30a94a0216ab89df97 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 13 Dec 2013 09:05:49 -0500 Subject: drm/radeon: check for 0 count in speaker allocation and SAD code If there is no speaker allocation block or SAD block, bail early. bug: https://bugs.freedesktop.org/show_bug.cgi?id=72283 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/dce6_afmt.c | 4 ++-- drivers/gpu/drm/radeon/evergreen_hdmi.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index ab59fd76f2d9..713a5d359901 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -174,7 +174,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) } sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); return; } @@ -235,7 +235,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) } sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read SADs: %d\n", sad_count); return; } diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index aa695c4feb3d..0c6d5cef4cf1 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -118,7 +118,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) } sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); return; } @@ -173,7 +173,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder) } sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); - if (sad_count < 0) { + if (sad_count <= 0) { DRM_ERROR("Couldn't read SADs: %d\n", sad_count); return; } -- cgit v1.2.3 From 679bcc935c4ed45e3f9c56f5d0c766b0844c93a9 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 16 Dec 2013 21:07:51 -0800 Subject: staging: ion: Add HAVE_MEMBLOCK config dependency The kbuild test robot reported a build issue w/ ION on m68k: drivers/staging/android/ion/ion.c: In function 'ion_reserve': drivers/staging/android/ion/ion.c:1526:4: error: implicit declaration of function 'memblock_alloc_base' [-Werror=implicit-function-declaration] drivers/staging/android/ion/ion.c:1528:11: error: 'MEMBLOCK_ALLOC_ANYWHERE' undeclared (first use in this function) drivers/staging/android/ion/ion.c:1528:11: note: each undeclared identifier is reported only once for each function it appears in drivers/staging/android/ion/ion.c:1537:4: error: implicit declaration of function 'memblock_reserve' [-Werror=implicit-function-declaration] cc1: some warnings being treated as errors This is caused by ION using memblock functionality which m68k doesn't support. This patch adds a HAVE_MEMBLOCK dependency to the ION config. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: kbuild test robot Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index b95281eef2aa..a9a64ea2343f 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,6 @@ menuconfig ION bool "Ion Memory Manager" + depends on HAVE_MEMBLOCK select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER ---help--- -- cgit v1.2.3 From f4ea823be2ca9e61522de002804c9a7a54c9be16 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 16 Dec 2013 21:07:52 -0800 Subject: staging: ion: Fix possible null pointer dereference The kbuild test robot reported: drivers/staging/android/ion/ion_system_heap.c:122 alloc_largest_available() error: potential null dereference 'info'. (kmalloc returns null) Where the pointer returned from kmalloc goes unchecked for failure. This patch checks the return for NULL, and reworks the logic, as suggested by Colin, so we allocate the page_info structure first. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: kbuild test robot Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 144b22727505..7f0729130d65 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -108,6 +108,10 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, struct page_info *info; int i; + info = kmalloc(sizeof(struct page_info), GFP_KERNEL); + if (!info) + return NULL; + for (i = 0; i < num_orders; i++) { if (size < order_to_size(orders[i])) continue; @@ -118,11 +122,12 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, if (!page) continue; - info = kmalloc(sizeof(struct page_info), GFP_KERNEL); info->page = page; info->order = orders[i]; return info; } + kfree(info); + return NULL; } -- cgit v1.2.3 From 068a00233969833f1ba925e7627797489efd6041 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Wed, 4 Dec 2013 16:35:12 +0100 Subject: drm: Add MIPI DSI bus support MIPI DSI bus allows to model DSI hosts and DSI peripherals using the Linux driver model. DSI hosts are registered by the DSI host drivers. During registration DSI peripherals will be created from the children of the DSI host's device tree node. Support for registration from board-setup code will be added later when needed. DSI hosts expose operations which can be used by DSI peripheral drivers to access associated devices. Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Signed-off-by: Thierry Reding --- drivers/gpu/drm/Kconfig | 4 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_mipi_dsi.c | 315 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dsi.h | 158 +++++++++++++++++++++ 4 files changed, 478 insertions(+) create mode 100644 drivers/gpu/drm/drm_mipi_dsi.c create mode 100644 include/drm/drm_mipi_dsi.h (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index f86427591167..0b8f8fdfdea9 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -20,6 +20,10 @@ menuconfig DRM details. You should also select and configure AGP (/dev/agpgart) support if it is available for your platform. +config DRM_MIPI_DSI + bool + depends on DRM + config DRM_USB tristate depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index cc08b845f965..b46239a619cf 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o CFLAGS_drm_trace_points.o := -I$(src) obj-$(CONFIG_DRM) += drm.o +obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_USB) += drm_usb.o obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_TDFX) += tdfx/ diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c new file mode 100644 index 000000000000..b155ee2ffa17 --- /dev/null +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -0,0 +1,315 @@ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Andrzej Hajda + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include